hash_murmur.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | https://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Author: Anatol Belski <ab@php.net> |
  14. +----------------------------------------------------------------------+
  15. */
  16. #include "php_hash.h"
  17. #include "php_hash_murmur.h"
  18. #include "murmur/PMurHash.h"
  19. #include "murmur/PMurHash128.h"
  20. const php_hash_ops php_hash_murmur3a_ops = {
  21. "murmur3a",
  22. (php_hash_init_func_t) PHP_MURMUR3AInit,
  23. (php_hash_update_func_t) PHP_MURMUR3AUpdate,
  24. (php_hash_final_func_t) PHP_MURMUR3AFinal,
  25. (php_hash_copy_func_t) PHP_MURMUR3ACopy,
  26. php_hash_serialize,
  27. php_hash_unserialize,
  28. PHP_MURMUR3A_SPEC,
  29. 4,
  30. 4,
  31. sizeof(PHP_MURMUR3A_CTX),
  32. 0
  33. };
  34. PHP_HASH_API void PHP_MURMUR3AInit(PHP_MURMUR3A_CTX *ctx, HashTable *args)
  35. {
  36. if (args) {
  37. zval *seed = zend_hash_str_find_deref(args, "seed", sizeof("seed") - 1);
  38. /* This might be a bit too restrictive, but thinking that a seed might be set
  39. once and for all, it should be done a clean way. */
  40. if (seed && IS_LONG == Z_TYPE_P(seed)) {
  41. ctx->h = (uint32_t)Z_LVAL_P(seed);
  42. } else {
  43. ctx->h = 0;
  44. }
  45. } else {
  46. ctx->h = 0;
  47. }
  48. ctx->carry = 0;
  49. ctx->len = 0;
  50. }
  51. PHP_HASH_API void PHP_MURMUR3AUpdate(PHP_MURMUR3A_CTX *ctx, const unsigned char *in, size_t len)
  52. {
  53. ctx->len += len;
  54. PMurHash32_Process(&ctx->h, &ctx->carry, in, len);
  55. }
  56. PHP_HASH_API void PHP_MURMUR3AFinal(unsigned char digest[4], PHP_MURMUR3A_CTX *ctx)
  57. {
  58. ctx->h = PMurHash32_Result(ctx->h, ctx->carry, ctx->len);
  59. digest[0] = (unsigned char)((ctx->h >> 24) & 0xff);
  60. digest[1] = (unsigned char)((ctx->h >> 16) & 0xff);
  61. digest[2] = (unsigned char)((ctx->h >> 8) & 0xff);
  62. digest[3] = (unsigned char)(ctx->h & 0xff);
  63. }
  64. PHP_HASH_API int PHP_MURMUR3ACopy(const php_hash_ops *ops, PHP_MURMUR3A_CTX *orig_context, PHP_MURMUR3A_CTX *copy_context)
  65. {
  66. copy_context->h = orig_context->h;
  67. copy_context->carry = orig_context->carry;
  68. copy_context->len = orig_context->len;
  69. return SUCCESS;
  70. }
  71. const php_hash_ops php_hash_murmur3c_ops = {
  72. "murmur3c",
  73. (php_hash_init_func_t) PHP_MURMUR3CInit,
  74. (php_hash_update_func_t) PHP_MURMUR3CUpdate,
  75. (php_hash_final_func_t) PHP_MURMUR3CFinal,
  76. (php_hash_copy_func_t) PHP_MURMUR3CCopy,
  77. php_hash_serialize,
  78. php_hash_unserialize,
  79. PHP_MURMUR3C_SPEC,
  80. 16,
  81. 4,
  82. sizeof(PHP_MURMUR3C_CTX),
  83. 0
  84. };
  85. PHP_HASH_API void PHP_MURMUR3CInit(PHP_MURMUR3C_CTX *ctx, HashTable *args)
  86. {
  87. if (args) {
  88. zval *seed = zend_hash_str_find_deref(args, "seed", sizeof("seed") - 1);
  89. /* This might be a bit too restrictive, but thinking that a seed might be set
  90. once and for all, it should be done a clean way. */
  91. if (seed && IS_LONG == Z_TYPE_P(seed)) {
  92. uint32_t _seed = (uint32_t)Z_LVAL_P(seed);
  93. ctx->h[0] = _seed;
  94. ctx->h[1] = _seed;
  95. ctx->h[2] = _seed;
  96. ctx->h[3] = _seed;
  97. } else {
  98. memset(&ctx->h, 0, sizeof ctx->h);
  99. }
  100. } else {
  101. memset(&ctx->h, 0, sizeof ctx->h);
  102. }
  103. memset(&ctx->carry, 0, sizeof ctx->carry);
  104. ctx->len = 0;
  105. }
  106. PHP_HASH_API void PHP_MURMUR3CUpdate(PHP_MURMUR3C_CTX *ctx, const unsigned char *in, size_t len)
  107. {
  108. ctx->len += len;
  109. PMurHash128x86_Process(ctx->h, ctx->carry, in, len);
  110. }
  111. PHP_HASH_API void PHP_MURMUR3CFinal(unsigned char digest[16], PHP_MURMUR3C_CTX *ctx)
  112. {
  113. uint32_t h[4] = {0, 0, 0, 0};
  114. PMurHash128x86_Result(ctx->h, ctx->carry, ctx->len, h);
  115. digest[0] = (unsigned char)((h[0] >> 24) & 0xff);
  116. digest[1] = (unsigned char)((h[0] >> 16) & 0xff);
  117. digest[2] = (unsigned char)((h[0] >> 8) & 0xff);
  118. digest[3] = (unsigned char)(h[0] & 0xff);
  119. digest[4] = (unsigned char)((h[1] >> 24) & 0xff);
  120. digest[5] = (unsigned char)((h[1] >> 16) & 0xff);
  121. digest[6] = (unsigned char)((h[1] >> 8) & 0xff);
  122. digest[7] = (unsigned char)(h[1] & 0xff);
  123. digest[8] = (unsigned char)((h[2] >> 24) & 0xff);
  124. digest[9] = (unsigned char)((h[2] >> 16) & 0xff);
  125. digest[10] = (unsigned char)((h[2] >> 8) & 0xff);
  126. digest[11] = (unsigned char)(h[2] & 0xff);
  127. digest[12] = (unsigned char)((h[3] >> 24) & 0xff);
  128. digest[13] = (unsigned char)((h[3] >> 16) & 0xff);
  129. digest[14] = (unsigned char)((h[3] >> 8) & 0xff);
  130. digest[15] = (unsigned char)(h[3] & 0xff);
  131. }
  132. PHP_HASH_API int PHP_MURMUR3CCopy(const php_hash_ops *ops, PHP_MURMUR3C_CTX *orig_context, PHP_MURMUR3C_CTX *copy_context)
  133. {
  134. memcpy(&copy_context->h, &orig_context->h, sizeof orig_context->h);
  135. memcpy(&copy_context->carry, &orig_context->carry, sizeof orig_context->carry);
  136. copy_context->len = orig_context->len;
  137. return SUCCESS;
  138. }
  139. const php_hash_ops php_hash_murmur3f_ops = {
  140. "murmur3f",
  141. (php_hash_init_func_t) PHP_MURMUR3FInit,
  142. (php_hash_update_func_t) PHP_MURMUR3FUpdate,
  143. (php_hash_final_func_t) PHP_MURMUR3FFinal,
  144. (php_hash_copy_func_t) PHP_MURMUR3FCopy,
  145. php_hash_serialize,
  146. php_hash_unserialize,
  147. PHP_MURMUR3F_SPEC,
  148. 16,
  149. 8,
  150. sizeof(PHP_MURMUR3F_CTX),
  151. 0
  152. };
  153. PHP_HASH_API void PHP_MURMUR3FInit(PHP_MURMUR3F_CTX *ctx, HashTable *args)
  154. {
  155. if (args) {
  156. zval *seed = zend_hash_str_find_deref(args, "seed", sizeof("seed") - 1);
  157. /* This might be a bit too restrictive, but thinking that a seed might be set
  158. once and for all, it should be done a clean way. */
  159. if (seed && IS_LONG == Z_TYPE_P(seed)) {
  160. uint64_t _seed = (uint64_t)Z_LVAL_P(seed);
  161. ctx->h[0] = _seed;
  162. ctx->h[1] = _seed;
  163. } else {
  164. memset(&ctx->h, 0, sizeof ctx->h);
  165. }
  166. } else {
  167. memset(&ctx->h, 0, sizeof ctx->h);
  168. }
  169. memset(&ctx->carry, 0, sizeof ctx->carry);
  170. ctx->len = 0;
  171. }
  172. PHP_HASH_API void PHP_MURMUR3FUpdate(PHP_MURMUR3F_CTX *ctx, const unsigned char *in, size_t len)
  173. {
  174. ctx->len += len;
  175. PMurHash128x64_Process(ctx->h, ctx->carry, in, len);
  176. }
  177. PHP_HASH_API void PHP_MURMUR3FFinal(unsigned char digest[16], PHP_MURMUR3F_CTX *ctx)
  178. {
  179. uint64_t h[2] = {0, 0};
  180. PMurHash128x64_Result(ctx->h, ctx->carry, ctx->len, h);
  181. digest[0] = (unsigned char)((h[0] >> 56) & 0xff);
  182. digest[1] = (unsigned char)((h[0] >> 48) & 0xff);
  183. digest[2] = (unsigned char)((h[0] >> 40) & 0xff);
  184. digest[3] = (unsigned char)((h[0] >> 32) & 0xff);
  185. digest[4] = (unsigned char)((h[0] >> 24) & 0xff);
  186. digest[5] = (unsigned char)((h[0] >> 16) & 0xff);
  187. digest[6] = (unsigned char)((h[0] >> 8) & 0xff);
  188. digest[7] = (unsigned char)(h[0] & 0xff);
  189. digest[8] = (unsigned char)((h[1] >> 56) & 0xff);
  190. digest[9] = (unsigned char)((h[1] >> 48) & 0xff);
  191. digest[10] = (unsigned char)((h[1] >> 40) & 0xff);
  192. digest[11] = (unsigned char)((h[1] >> 32) & 0xff);
  193. digest[12] = (unsigned char)((h[1] >> 24) & 0xff);
  194. digest[13] = (unsigned char)((h[1] >> 16) & 0xff);
  195. digest[14] = (unsigned char)((h[1] >> 8) & 0xff);
  196. digest[15] = (unsigned char)(h[1] & 0xff);
  197. }
  198. PHP_HASH_API int PHP_MURMUR3FCopy(const php_hash_ops *ops, PHP_MURMUR3F_CTX *orig_context, PHP_MURMUR3F_CTX *copy_context)
  199. {
  200. memcpy(&copy_context->h, &orig_context->h, sizeof orig_context->h);
  201. memcpy(&copy_context->carry, &orig_context->carry, sizeof orig_context->carry);
  202. copy_context->len = orig_context->len;
  203. return SUCCESS;
  204. }