hash_fnv.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 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. /* Based on the public domain algorithm found at
  19. http://www.isthe.com/chongo/tech/comp/fnv/index.html */
  20. #include "php_hash.h"
  21. #include "php_hash_fnv.h"
  22. const php_hash_ops php_hash_fnv132_ops = {
  23. (php_hash_init_func_t) PHP_FNV132Init,
  24. (php_hash_update_func_t) PHP_FNV132Update,
  25. (php_hash_final_func_t) PHP_FNV132Final,
  26. (php_hash_copy_func_t) php_hash_copy,
  27. 4,
  28. 4,
  29. sizeof(PHP_FNV132_CTX),
  30. 0
  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. 0
  41. };
  42. const php_hash_ops php_hash_fnv164_ops = {
  43. (php_hash_init_func_t) PHP_FNV164Init,
  44. (php_hash_update_func_t) PHP_FNV164Update,
  45. (php_hash_final_func_t) PHP_FNV164Final,
  46. (php_hash_copy_func_t) php_hash_copy,
  47. 8,
  48. 4,
  49. sizeof(PHP_FNV164_CTX),
  50. 0
  51. };
  52. const php_hash_ops php_hash_fnv1a64_ops = {
  53. (php_hash_init_func_t) PHP_FNV164Init,
  54. (php_hash_update_func_t) PHP_FNV1a64Update,
  55. (php_hash_final_func_t) PHP_FNV164Final,
  56. (php_hash_copy_func_t) php_hash_copy,
  57. 8,
  58. 4,
  59. sizeof(PHP_FNV164_CTX),
  60. 0
  61. };
  62. /* {{{ PHP_FNV132Init
  63. * 32-bit FNV-1 hash initialisation
  64. */
  65. PHP_HASH_API void PHP_FNV132Init(PHP_FNV132_CTX *context)
  66. {
  67. context->state = PHP_FNV1_32_INIT;
  68. }
  69. /* }}} */
  70. PHP_HASH_API void PHP_FNV132Update(PHP_FNV132_CTX *context, const unsigned char *input,
  71. unsigned int inputLen)
  72. {
  73. context->state = fnv_32_buf((void *)input, inputLen, context->state, 0);
  74. }
  75. PHP_HASH_API void PHP_FNV1a32Update(PHP_FNV132_CTX *context, const unsigned char *input,
  76. unsigned int inputLen)
  77. {
  78. context->state = fnv_32_buf((void *)input, inputLen, context->state, 1);
  79. }
  80. PHP_HASH_API void PHP_FNV132Final(unsigned char digest[4], PHP_FNV132_CTX * context)
  81. {
  82. #ifdef WORDS_BIGENDIAN
  83. memcpy(digest, &context->state, 4);
  84. #else
  85. int i = 0;
  86. unsigned char *c = (unsigned char *) &context->state;
  87. for (i = 0; i < 4; i++) {
  88. digest[i] = c[3 - i];
  89. }
  90. #endif
  91. }
  92. /* {{{ PHP_FNV164Init
  93. * 64-bit FNV-1 hash initialisation
  94. */
  95. PHP_HASH_API void PHP_FNV164Init(PHP_FNV164_CTX *context)
  96. {
  97. context->state = PHP_FNV1_64_INIT;
  98. }
  99. /* }}} */
  100. PHP_HASH_API void PHP_FNV164Update(PHP_FNV164_CTX *context, const unsigned char *input,
  101. unsigned int inputLen)
  102. {
  103. context->state = fnv_64_buf((void *)input, inputLen, context->state, 0);
  104. }
  105. PHP_HASH_API void PHP_FNV1a64Update(PHP_FNV164_CTX *context, const unsigned char *input,
  106. unsigned int inputLen)
  107. {
  108. context->state = fnv_64_buf((void *)input, inputLen, context->state, 1);
  109. }
  110. PHP_HASH_API void PHP_FNV164Final(unsigned char digest[8], PHP_FNV164_CTX * context)
  111. {
  112. #ifdef WORDS_BIGENDIAN
  113. memcpy(digest, &context->state, 8);
  114. #else
  115. int i = 0;
  116. unsigned char *c = (unsigned char *) &context->state;
  117. for (i = 0; i < 8; i++) {
  118. digest[i] = c[7 - i];
  119. }
  120. #endif
  121. }
  122. /*
  123. * fnv_32_buf - perform a 32 bit Fowler/Noll/Vo hash on a buffer
  124. *
  125. * input:
  126. * buf - start of buffer to hash
  127. * len - length of buffer in octets
  128. * hval - previous hash value or 0 if first call
  129. * alternate - if > 0 use the alternate version
  130. *
  131. * returns:
  132. * 32 bit hash as a static hash type
  133. */
  134. static uint32_t
  135. fnv_32_buf(void *buf, size_t len, uint32_t hval, int alternate)
  136. {
  137. unsigned char *bp = (unsigned char *)buf; /* start of buffer */
  138. unsigned char *be = bp + len; /* beyond end of buffer */
  139. /*
  140. * FNV-1 hash each octet in the buffer
  141. */
  142. if (alternate == 0) {
  143. while (bp < be) {
  144. /* multiply by the 32 bit FNV magic prime mod 2^32 */
  145. hval *= PHP_FNV_32_PRIME;
  146. /* xor the bottom with the current octet */
  147. hval ^= (uint32_t)*bp++;
  148. }
  149. } else {
  150. while (bp < be) {
  151. /* xor the bottom with the current octet */
  152. hval ^= (uint32_t)*bp++;
  153. /* multiply by the 32 bit FNV magic prime mod 2^32 */
  154. hval *= PHP_FNV_32_PRIME;
  155. }
  156. }
  157. /* return our new hash value */
  158. return hval;
  159. }
  160. /*
  161. * fnv_64_buf - perform a 64 bit Fowler/Noll/Vo hash on a buffer
  162. *
  163. * input:
  164. * buf - start of buffer to hash
  165. * len - length of buffer in octets
  166. * hval - previous hash value or 0 if first call
  167. * alternate - if > 0 use the alternate version
  168. *
  169. * returns:
  170. * 64 bit hash as a static hash type
  171. */
  172. static uint64_t
  173. fnv_64_buf(void *buf, size_t len, uint64_t hval, int alternate)
  174. {
  175. unsigned char *bp = (unsigned char *)buf; /* start of buffer */
  176. unsigned char *be = bp + len; /* beyond end of buffer */
  177. /*
  178. * FNV-1 hash each octet of the buffer
  179. */
  180. if (alternate == 0) {
  181. while (bp < be) {
  182. /* multiply by the 64 bit FNV magic prime mod 2^64 */
  183. hval *= PHP_FNV_64_PRIME;
  184. /* xor the bottom with the current octet */
  185. hval ^= (uint64_t)*bp++;
  186. }
  187. } else {
  188. while (bp < be) {
  189. /* xor the bottom with the current octet */
  190. hval ^= (uint64_t)*bp++;
  191. /* multiply by the 64 bit FNV magic prime mod 2^64 */
  192. hval *= PHP_FNV_64_PRIME;
  193. }
  194. }
  195. /* return our new hash value */
  196. return hval;
  197. }
  198. /*
  199. * Local variables:
  200. * tab-width: 4
  201. * c-basic-offset: 4
  202. * End:
  203. * vim600: noet sw=4 ts=4 fdm=marker
  204. * vim<600: noet sw=4 ts=4
  205. */