| 316 | #endif |
| 317 | |
| 318 | int |
| 319 | ink_code_incr_MMH_final(uint8_t *presult, MMH_CTX *ctx) |
| 320 | { |
| 321 | unsigned int len = ctx->blocks * 4 + ctx->buffer_size; |
| 322 | // pad out to 16 bytes |
| 323 | if (ctx->buffer_size) { |
| 324 | _memset(ctx->buffer + ctx->buffer_size, 0, 16 - ctx->buffer_size); |
| 325 | ctx->buffer_size = 0; |
| 326 | MMH_update(ctx, ctx->buffer); |
| 327 | } |
| 328 | // append length (before padding) |
| 329 | unsigned int *pbuffer = reinterpret_cast<unsigned int *>(ctx->buffer); |
| 330 | pbuffer[1] = pbuffer[2] = pbuffer[3] = pbuffer[0] = len; |
| 331 | MMH_update(ctx, ctx->buffer); |
| 332 | // final phase |
| 333 | uint32_t *b = reinterpret_cast<uint32_t *>(presult); |
| 334 | uint64_t d = ((static_cast<uint64_t>(1)) << 32) + 15; |
| 335 | uint32_t b0 = static_cast<uint32_t>(ctx->state[0] % d); |
| 336 | uint32_t b1 = static_cast<uint32_t>(ctx->state[1] % d); |
| 337 | uint32_t b2 = static_cast<uint32_t>(ctx->state[2] % d); |
| 338 | uint32_t b3 = static_cast<uint32_t>(ctx->state[3] % d); |
| 339 | // scramble the bits, losslessly (reversibly) |
| 340 | b[0] = b0; |
| 341 | b[1] = b1 ^ (b0 >> 24) ^ (b0 << 8); |
| 342 | b[2] = b2 ^ (b1 >> 16) ^ (b1 << 16) ^ (b0 >> 24) ^ (b0 << 8); |
| 343 | b[3] = b3 ^ (b1 >> 8) ^ (b1 << 24) ^ (b2 >> 16) ^ (b2 << 16) ^ (b0 >> 24) ^ (b0 << 8); |
| 344 | |
| 345 | b0 = b[0]; |
| 346 | b1 = b[1]; |
| 347 | b2 = b[2]; |
| 348 | b3 = b[3]; |
| 349 | |
| 350 | b[2] = b2 ^ (b3 >> 24) ^ (b3 << 8); |
| 351 | b[1] = b1 ^ (b2 >> 16) ^ (b2 << 16) ^ (b3 >> 24) ^ (b3 << 8); |
| 352 | b[0] = b0 ^ (b3 >> 8) ^ (b3 << 24) ^ (b2 >> 16) ^ (b2 << 16) ^ (b1 >> 24) ^ (b1 << 8); |
| 353 | return 0; |
| 354 | } |
| 355 | |
| 356 | MMHContext::MMHContext() |
| 357 | { |
no test coverage detected