hash_fnv.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2016 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Michael Maclean <mgdm@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id$ */
  19. /* Based on the public domain algorithm found at
  20. http://www.isthe.com/chongo/tech/comp/fnv/index.html */
  21. #include "php_hash.h"
  22. #include "php_hash_fnv.h"
  23. const php_hash_ops php_hash_fnv132_ops = {
  24. (php_hash_init_func_t) PHP_FNV132Init,
  25. (php_hash_update_func_t) PHP_FNV132Update,
  26. (php_hash_final_func_t) PHP_FNV132Final,
  27. (php_hash_copy_func_t) php_hash_copy,
  28. 4,
  29. 4,
  30. sizeof(PHP_FNV132_CTX)
  31. };
  32. const php_hash_ops php_hash_fnv1a32_ops = {
  33. (php_hash_init_func_t) PHP_FNV132Init,
  34. (php_hash_update_func_t) PHP_FNV1a32Update,
  35. (php_hash_final_func_t) PHP_FNV132Final,
  36. (php_hash_copy_func_t) php_hash_copy,
  37. 4,
  38. 4,
  39. sizeof(PHP_FNV132_CTX)
  40. };
  41. const php_hash_ops php_hash_fnv164_ops = {
  42. (php_hash_init_func_t) PHP_FNV164Init,
  43. (php_hash_update_func_t) PHP_FNV164Update,
  44. (php_hash_final_func_t) PHP_FNV164Final,
  45. (php_hash_copy_func_t) php_hash_copy,
  46. 8,
  47. 4,
  48. sizeof(PHP_FNV164_CTX)
  49. };
  50. const php_hash_ops php_hash_fnv1a64_ops = {
  51. (php_hash_init_func_t) PHP_FNV164Init,
  52. (php_hash_update_func_t) PHP_FNV1a64Update,
  53. (php_hash_final_func_t) PHP_FNV164Final,
  54. (php_hash_copy_func_t) php_hash_copy,
  55. 8,
  56. 4,
  57. sizeof(PHP_FNV164_CTX)
  58. };
  59. /* {{{ PHP_FNV132Init
  60. * 32-bit FNV-1 hash initialisation
  61. */
  62. PHP_HASH_API void PHP_FNV132Init(PHP_FNV132_CTX *context)
  63. {
  64. context->state = PHP_FNV1_32_INIT;
  65. }
  66. /* }}} */
  67. PHP_HASH_API void PHP_FNV132Update(PHP_FNV132_CTX *context, const unsigned char *input,
  68. unsigned int inputLen)
  69. {
  70. context->state = fnv_32_buf((void *)input, inputLen, context->state, 0);
  71. }
  72. PHP_HASH_API void PHP_FNV1a32Update(PHP_FNV132_CTX *context, const unsigned char *input,
  73. unsigned int inputLen)
  74. {
  75. context->state = fnv_32_buf((void *)input, inputLen, context->state, 1);
  76. }
  77. PHP_HASH_API void PHP_FNV132Final(unsigned char digest[4], PHP_FNV132_CTX * context)
  78. {
  79. #ifdef WORDS_BIGENDIAN
  80. memcpy(digest, &context->state, 4);
  81. #else
  82. int i = 0;
  83. unsigned char *c = (unsigned char *) &context->state;
  84. for (i = 0; i < 4; i++) {
  85. digest[i] = c[3 - i];
  86. }
  87. #endif
  88. }
  89. /* {{{ PHP_FNV164Init
  90. * 64-bit FNV-1 hash initialisation
  91. */
  92. PHP_HASH_API void PHP_FNV164Init(PHP_FNV164_CTX *context)
  93. {
  94. context->state = PHP_FNV1_64_INIT;
  95. }
  96. /* }}} */
  97. PHP_HASH_API void PHP_FNV164Update(PHP_FNV164_CTX *context, const unsigned char *input,
  98. unsigned int inputLen)
  99. {
  100. context->state = fnv_64_buf((void *)input, inputLen, context->state, 0);
  101. }
  102. PHP_HASH_API void PHP_FNV1a64Update(PHP_FNV164_CTX *context, const unsigned char *input,
  103. unsigned int inputLen)
  104. {
  105. context->state = fnv_64_buf((void *)input, inputLen, context->state, 1);
  106. }
  107. PHP_HASH_API void PHP_FNV164Final(unsigned char digest[8], PHP_FNV164_CTX * context)
  108. {
  109. #ifdef WORDS_BIGENDIAN
  110. memcpy(digest, &context->state, 8);
  111. #else
  112. int i = 0;
  113. unsigned char *c = (unsigned char *) &context->state;
  114. for (i = 0; i < 8; i++) {
  115. digest[i] = c[7 - i];
  116. }
  117. #endif
  118. }
  119. /*
  120. * fnv_32_buf - perform a 32 bit Fowler/Noll/Vo hash on a buffer
  121. *
  122. * input:
  123. * buf - start of buffer to hash
  124. * len - length of buffer in octets
  125. * hval - previous hash value or 0 if first call
  126. * alternate - if > 0 use the alternate version
  127. *
  128. * returns:
  129. * 32 bit hash as a static hash type
  130. */
  131. static php_hash_uint32
  132. fnv_32_buf(void *buf, size_t len, php_hash_uint32 hval, int alternate)
  133. {
  134. unsigned char *bp = (unsigned char *)buf; /* start of buffer */
  135. unsigned char *be = bp + len; /* beyond end of buffer */
  136. /*
  137. * FNV-1 hash each octet in the buffer
  138. */
  139. while (bp < be) {
  140. if (alternate == 0) {
  141. /* multiply by the 32 bit FNV magic prime mod 2^32 */
  142. hval *= PHP_FNV_32_PRIME;
  143. /* xor the bottom with the current octet */
  144. hval ^= (php_hash_uint32)*bp++;
  145. } else {
  146. /* xor the bottom with the current octet */
  147. hval ^= (php_hash_uint32)*bp++;
  148. /* multiply by the 32 bit FNV magic prime mod 2^32 */
  149. hval *= PHP_FNV_32_PRIME;
  150. }
  151. }
  152. /* return our new hash value */
  153. return hval;
  154. }
  155. /*
  156. * fnv_64_buf - perform a 64 bit Fowler/Noll/Vo hash on a buffer
  157. *
  158. * input:
  159. * buf - start of buffer to hash
  160. * len - length of buffer in octets
  161. * hval - previous hash value or 0 if first call
  162. * alternate - if > 0 use the alternate version
  163. *
  164. * returns:
  165. * 64 bit hash as a static hash type
  166. */
  167. static php_hash_uint64
  168. fnv_64_buf(void *buf, size_t len, php_hash_uint64 hval, int alternate)
  169. {
  170. unsigned char *bp = (unsigned char *)buf; /* start of buffer */
  171. unsigned char *be = bp + len; /* beyond end of buffer */
  172. /*
  173. * FNV-1 hash each octet of the buffer
  174. */
  175. while (bp < be) {
  176. if (alternate == 0) {
  177. /* multiply by the 64 bit FNV magic prime mod 2^64 */
  178. hval *= PHP_FNV_64_PRIME;
  179. /* xor the bottom with the current octet */
  180. hval ^= (php_hash_uint64)*bp++;
  181. } else {
  182. /* xor the bottom with the current octet */
  183. hval ^= (php_hash_uint64)*bp++;
  184. /* multiply by the 64 bit FNV magic prime mod 2^64 */
  185. hval *= PHP_FNV_64_PRIME;
  186. }
  187. }
  188. /* return our new hash value */
  189. return hval;
  190. }
  191. /*
  192. * Local variables:
  193. * tab-width: 4
  194. * c-basic-offset: 4
  195. * End:
  196. * vim600: noet sw=4 ts=4 fdm=marker
  197. * vim<600: noet sw=4 ts=4
  198. */