162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * xxHash - Extremely Fast Hash algorithm 362306a36Sopenharmony_ci * Copyright (C) 2012-2016, Yann Collet. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 862306a36Sopenharmony_ci * modification, are permitted provided that the following conditions are 962306a36Sopenharmony_ci * met: 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * * Redistributions of source code must retain the above copyright 1262306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 1362306a36Sopenharmony_ci * * Redistributions in binary form must reproduce the above 1462306a36Sopenharmony_ci * copyright notice, this list of conditions and the following disclaimer 1562306a36Sopenharmony_ci * in the documentation and/or other materials provided with the 1662306a36Sopenharmony_ci * distribution. 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1962306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2062306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2162306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2262306a36Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2362306a36Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2462306a36Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2562306a36Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2662306a36Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2762306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2862306a36Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or modify it under 3162306a36Sopenharmony_ci * the terms of the GNU General Public License version 2 as published by the 3262306a36Sopenharmony_ci * Free Software Foundation. This program is dual-licensed; you may select 3362306a36Sopenharmony_ci * either version 2 of the GNU General Public License ("GPL") or BSD license 3462306a36Sopenharmony_ci * ("BSD"). 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * You can contact the author at: 3762306a36Sopenharmony_ci * - xxHash homepage: https://cyan4973.github.io/xxHash/ 3862306a36Sopenharmony_ci * - xxHash source repository: https://github.com/Cyan4973/xxHash 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#include <asm/unaligned.h> 4262306a36Sopenharmony_ci#include <linux/errno.h> 4362306a36Sopenharmony_ci#include <linux/compiler.h> 4462306a36Sopenharmony_ci#include <linux/kernel.h> 4562306a36Sopenharmony_ci#include <linux/module.h> 4662306a36Sopenharmony_ci#include <linux/string.h> 4762306a36Sopenharmony_ci#include <linux/xxhash.h> 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/*-************************************* 5062306a36Sopenharmony_ci * Macros 5162306a36Sopenharmony_ci **************************************/ 5262306a36Sopenharmony_ci#define xxh_rotl32(x, r) ((x << r) | (x >> (32 - r))) 5362306a36Sopenharmony_ci#define xxh_rotl64(x, r) ((x << r) | (x >> (64 - r))) 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#ifdef __LITTLE_ENDIAN 5662306a36Sopenharmony_ci# define XXH_CPU_LITTLE_ENDIAN 1 5762306a36Sopenharmony_ci#else 5862306a36Sopenharmony_ci# define XXH_CPU_LITTLE_ENDIAN 0 5962306a36Sopenharmony_ci#endif 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/*-************************************* 6262306a36Sopenharmony_ci * Constants 6362306a36Sopenharmony_ci **************************************/ 6462306a36Sopenharmony_cistatic const uint32_t PRIME32_1 = 2654435761U; 6562306a36Sopenharmony_cistatic const uint32_t PRIME32_2 = 2246822519U; 6662306a36Sopenharmony_cistatic const uint32_t PRIME32_3 = 3266489917U; 6762306a36Sopenharmony_cistatic const uint32_t PRIME32_4 = 668265263U; 6862306a36Sopenharmony_cistatic const uint32_t PRIME32_5 = 374761393U; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic const uint64_t PRIME64_1 = 11400714785074694791ULL; 7162306a36Sopenharmony_cistatic const uint64_t PRIME64_2 = 14029467366897019727ULL; 7262306a36Sopenharmony_cistatic const uint64_t PRIME64_3 = 1609587929392839161ULL; 7362306a36Sopenharmony_cistatic const uint64_t PRIME64_4 = 9650029242287828579ULL; 7462306a36Sopenharmony_cistatic const uint64_t PRIME64_5 = 2870177450012600261ULL; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/*-************************** 7762306a36Sopenharmony_ci * Utils 7862306a36Sopenharmony_ci ***************************/ 7962306a36Sopenharmony_civoid xxh32_copy_state(struct xxh32_state *dst, const struct xxh32_state *src) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci memcpy(dst, src, sizeof(*dst)); 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ciEXPORT_SYMBOL(xxh32_copy_state); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_civoid xxh64_copy_state(struct xxh64_state *dst, const struct xxh64_state *src) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci memcpy(dst, src, sizeof(*dst)); 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ciEXPORT_SYMBOL(xxh64_copy_state); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/*-*************************** 9262306a36Sopenharmony_ci * Simple Hash Functions 9362306a36Sopenharmony_ci ****************************/ 9462306a36Sopenharmony_cistatic uint32_t xxh32_round(uint32_t seed, const uint32_t input) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci seed += input * PRIME32_2; 9762306a36Sopenharmony_ci seed = xxh_rotl32(seed, 13); 9862306a36Sopenharmony_ci seed *= PRIME32_1; 9962306a36Sopenharmony_ci return seed; 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ciuint32_t xxh32(const void *input, const size_t len, const uint32_t seed) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci const uint8_t *p = (const uint8_t *)input; 10562306a36Sopenharmony_ci const uint8_t *b_end = p + len; 10662306a36Sopenharmony_ci uint32_t h32; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci if (len >= 16) { 10962306a36Sopenharmony_ci const uint8_t *const limit = b_end - 16; 11062306a36Sopenharmony_ci uint32_t v1 = seed + PRIME32_1 + PRIME32_2; 11162306a36Sopenharmony_ci uint32_t v2 = seed + PRIME32_2; 11262306a36Sopenharmony_ci uint32_t v3 = seed + 0; 11362306a36Sopenharmony_ci uint32_t v4 = seed - PRIME32_1; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci do { 11662306a36Sopenharmony_ci v1 = xxh32_round(v1, get_unaligned_le32(p)); 11762306a36Sopenharmony_ci p += 4; 11862306a36Sopenharmony_ci v2 = xxh32_round(v2, get_unaligned_le32(p)); 11962306a36Sopenharmony_ci p += 4; 12062306a36Sopenharmony_ci v3 = xxh32_round(v3, get_unaligned_le32(p)); 12162306a36Sopenharmony_ci p += 4; 12262306a36Sopenharmony_ci v4 = xxh32_round(v4, get_unaligned_le32(p)); 12362306a36Sopenharmony_ci p += 4; 12462306a36Sopenharmony_ci } while (p <= limit); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci h32 = xxh_rotl32(v1, 1) + xxh_rotl32(v2, 7) + 12762306a36Sopenharmony_ci xxh_rotl32(v3, 12) + xxh_rotl32(v4, 18); 12862306a36Sopenharmony_ci } else { 12962306a36Sopenharmony_ci h32 = seed + PRIME32_5; 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci h32 += (uint32_t)len; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci while (p + 4 <= b_end) { 13562306a36Sopenharmony_ci h32 += get_unaligned_le32(p) * PRIME32_3; 13662306a36Sopenharmony_ci h32 = xxh_rotl32(h32, 17) * PRIME32_4; 13762306a36Sopenharmony_ci p += 4; 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci while (p < b_end) { 14162306a36Sopenharmony_ci h32 += (*p) * PRIME32_5; 14262306a36Sopenharmony_ci h32 = xxh_rotl32(h32, 11) * PRIME32_1; 14362306a36Sopenharmony_ci p++; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci h32 ^= h32 >> 15; 14762306a36Sopenharmony_ci h32 *= PRIME32_2; 14862306a36Sopenharmony_ci h32 ^= h32 >> 13; 14962306a36Sopenharmony_ci h32 *= PRIME32_3; 15062306a36Sopenharmony_ci h32 ^= h32 >> 16; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci return h32; 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ciEXPORT_SYMBOL(xxh32); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic uint64_t xxh64_round(uint64_t acc, const uint64_t input) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci acc += input * PRIME64_2; 15962306a36Sopenharmony_ci acc = xxh_rotl64(acc, 31); 16062306a36Sopenharmony_ci acc *= PRIME64_1; 16162306a36Sopenharmony_ci return acc; 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic uint64_t xxh64_merge_round(uint64_t acc, uint64_t val) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci val = xxh64_round(0, val); 16762306a36Sopenharmony_ci acc ^= val; 16862306a36Sopenharmony_ci acc = acc * PRIME64_1 + PRIME64_4; 16962306a36Sopenharmony_ci return acc; 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ciuint64_t xxh64(const void *input, const size_t len, const uint64_t seed) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci const uint8_t *p = (const uint8_t *)input; 17562306a36Sopenharmony_ci const uint8_t *const b_end = p + len; 17662306a36Sopenharmony_ci uint64_t h64; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci if (len >= 32) { 17962306a36Sopenharmony_ci const uint8_t *const limit = b_end - 32; 18062306a36Sopenharmony_ci uint64_t v1 = seed + PRIME64_1 + PRIME64_2; 18162306a36Sopenharmony_ci uint64_t v2 = seed + PRIME64_2; 18262306a36Sopenharmony_ci uint64_t v3 = seed + 0; 18362306a36Sopenharmony_ci uint64_t v4 = seed - PRIME64_1; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci do { 18662306a36Sopenharmony_ci v1 = xxh64_round(v1, get_unaligned_le64(p)); 18762306a36Sopenharmony_ci p += 8; 18862306a36Sopenharmony_ci v2 = xxh64_round(v2, get_unaligned_le64(p)); 18962306a36Sopenharmony_ci p += 8; 19062306a36Sopenharmony_ci v3 = xxh64_round(v3, get_unaligned_le64(p)); 19162306a36Sopenharmony_ci p += 8; 19262306a36Sopenharmony_ci v4 = xxh64_round(v4, get_unaligned_le64(p)); 19362306a36Sopenharmony_ci p += 8; 19462306a36Sopenharmony_ci } while (p <= limit); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci h64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) + 19762306a36Sopenharmony_ci xxh_rotl64(v3, 12) + xxh_rotl64(v4, 18); 19862306a36Sopenharmony_ci h64 = xxh64_merge_round(h64, v1); 19962306a36Sopenharmony_ci h64 = xxh64_merge_round(h64, v2); 20062306a36Sopenharmony_ci h64 = xxh64_merge_round(h64, v3); 20162306a36Sopenharmony_ci h64 = xxh64_merge_round(h64, v4); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci } else { 20462306a36Sopenharmony_ci h64 = seed + PRIME64_5; 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci h64 += (uint64_t)len; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci while (p + 8 <= b_end) { 21062306a36Sopenharmony_ci const uint64_t k1 = xxh64_round(0, get_unaligned_le64(p)); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci h64 ^= k1; 21362306a36Sopenharmony_ci h64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4; 21462306a36Sopenharmony_ci p += 8; 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci if (p + 4 <= b_end) { 21862306a36Sopenharmony_ci h64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1; 21962306a36Sopenharmony_ci h64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; 22062306a36Sopenharmony_ci p += 4; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci while (p < b_end) { 22462306a36Sopenharmony_ci h64 ^= (*p) * PRIME64_5; 22562306a36Sopenharmony_ci h64 = xxh_rotl64(h64, 11) * PRIME64_1; 22662306a36Sopenharmony_ci p++; 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci h64 ^= h64 >> 33; 23062306a36Sopenharmony_ci h64 *= PRIME64_2; 23162306a36Sopenharmony_ci h64 ^= h64 >> 29; 23262306a36Sopenharmony_ci h64 *= PRIME64_3; 23362306a36Sopenharmony_ci h64 ^= h64 >> 32; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci return h64; 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ciEXPORT_SYMBOL(xxh64); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci/*-************************************************** 24062306a36Sopenharmony_ci * Advanced Hash Functions 24162306a36Sopenharmony_ci ***************************************************/ 24262306a36Sopenharmony_civoid xxh32_reset(struct xxh32_state *statePtr, const uint32_t seed) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci /* use a local state for memcpy() to avoid strict-aliasing warnings */ 24562306a36Sopenharmony_ci struct xxh32_state state; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci memset(&state, 0, sizeof(state)); 24862306a36Sopenharmony_ci state.v1 = seed + PRIME32_1 + PRIME32_2; 24962306a36Sopenharmony_ci state.v2 = seed + PRIME32_2; 25062306a36Sopenharmony_ci state.v3 = seed + 0; 25162306a36Sopenharmony_ci state.v4 = seed - PRIME32_1; 25262306a36Sopenharmony_ci memcpy(statePtr, &state, sizeof(state)); 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ciEXPORT_SYMBOL(xxh32_reset); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_civoid xxh64_reset(struct xxh64_state *statePtr, const uint64_t seed) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci /* use a local state for memcpy() to avoid strict-aliasing warnings */ 25962306a36Sopenharmony_ci struct xxh64_state state; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci memset(&state, 0, sizeof(state)); 26262306a36Sopenharmony_ci state.v1 = seed + PRIME64_1 + PRIME64_2; 26362306a36Sopenharmony_ci state.v2 = seed + PRIME64_2; 26462306a36Sopenharmony_ci state.v3 = seed + 0; 26562306a36Sopenharmony_ci state.v4 = seed - PRIME64_1; 26662306a36Sopenharmony_ci memcpy(statePtr, &state, sizeof(state)); 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ciEXPORT_SYMBOL(xxh64_reset); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ciint xxh32_update(struct xxh32_state *state, const void *input, const size_t len) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci const uint8_t *p = (const uint8_t *)input; 27362306a36Sopenharmony_ci const uint8_t *const b_end = p + len; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci if (input == NULL) 27662306a36Sopenharmony_ci return -EINVAL; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci state->total_len_32 += (uint32_t)len; 27962306a36Sopenharmony_ci state->large_len |= (len >= 16) | (state->total_len_32 >= 16); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci if (state->memsize + len < 16) { /* fill in tmp buffer */ 28262306a36Sopenharmony_ci memcpy((uint8_t *)(state->mem32) + state->memsize, input, len); 28362306a36Sopenharmony_ci state->memsize += (uint32_t)len; 28462306a36Sopenharmony_ci return 0; 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci if (state->memsize) { /* some data left from previous update */ 28862306a36Sopenharmony_ci const uint32_t *p32 = state->mem32; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci memcpy((uint8_t *)(state->mem32) + state->memsize, input, 29162306a36Sopenharmony_ci 16 - state->memsize); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci state->v1 = xxh32_round(state->v1, get_unaligned_le32(p32)); 29462306a36Sopenharmony_ci p32++; 29562306a36Sopenharmony_ci state->v2 = xxh32_round(state->v2, get_unaligned_le32(p32)); 29662306a36Sopenharmony_ci p32++; 29762306a36Sopenharmony_ci state->v3 = xxh32_round(state->v3, get_unaligned_le32(p32)); 29862306a36Sopenharmony_ci p32++; 29962306a36Sopenharmony_ci state->v4 = xxh32_round(state->v4, get_unaligned_le32(p32)); 30062306a36Sopenharmony_ci p32++; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci p += 16-state->memsize; 30362306a36Sopenharmony_ci state->memsize = 0; 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci if (p <= b_end - 16) { 30762306a36Sopenharmony_ci const uint8_t *const limit = b_end - 16; 30862306a36Sopenharmony_ci uint32_t v1 = state->v1; 30962306a36Sopenharmony_ci uint32_t v2 = state->v2; 31062306a36Sopenharmony_ci uint32_t v3 = state->v3; 31162306a36Sopenharmony_ci uint32_t v4 = state->v4; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci do { 31462306a36Sopenharmony_ci v1 = xxh32_round(v1, get_unaligned_le32(p)); 31562306a36Sopenharmony_ci p += 4; 31662306a36Sopenharmony_ci v2 = xxh32_round(v2, get_unaligned_le32(p)); 31762306a36Sopenharmony_ci p += 4; 31862306a36Sopenharmony_ci v3 = xxh32_round(v3, get_unaligned_le32(p)); 31962306a36Sopenharmony_ci p += 4; 32062306a36Sopenharmony_ci v4 = xxh32_round(v4, get_unaligned_le32(p)); 32162306a36Sopenharmony_ci p += 4; 32262306a36Sopenharmony_ci } while (p <= limit); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci state->v1 = v1; 32562306a36Sopenharmony_ci state->v2 = v2; 32662306a36Sopenharmony_ci state->v3 = v3; 32762306a36Sopenharmony_ci state->v4 = v4; 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci if (p < b_end) { 33162306a36Sopenharmony_ci memcpy(state->mem32, p, (size_t)(b_end-p)); 33262306a36Sopenharmony_ci state->memsize = (uint32_t)(b_end-p); 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci return 0; 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ciEXPORT_SYMBOL(xxh32_update); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ciuint32_t xxh32_digest(const struct xxh32_state *state) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci const uint8_t *p = (const uint8_t *)state->mem32; 34262306a36Sopenharmony_ci const uint8_t *const b_end = (const uint8_t *)(state->mem32) + 34362306a36Sopenharmony_ci state->memsize; 34462306a36Sopenharmony_ci uint32_t h32; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci if (state->large_len) { 34762306a36Sopenharmony_ci h32 = xxh_rotl32(state->v1, 1) + xxh_rotl32(state->v2, 7) + 34862306a36Sopenharmony_ci xxh_rotl32(state->v3, 12) + xxh_rotl32(state->v4, 18); 34962306a36Sopenharmony_ci } else { 35062306a36Sopenharmony_ci h32 = state->v3 /* == seed */ + PRIME32_5; 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci h32 += state->total_len_32; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci while (p + 4 <= b_end) { 35662306a36Sopenharmony_ci h32 += get_unaligned_le32(p) * PRIME32_3; 35762306a36Sopenharmony_ci h32 = xxh_rotl32(h32, 17) * PRIME32_4; 35862306a36Sopenharmony_ci p += 4; 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci while (p < b_end) { 36262306a36Sopenharmony_ci h32 += (*p) * PRIME32_5; 36362306a36Sopenharmony_ci h32 = xxh_rotl32(h32, 11) * PRIME32_1; 36462306a36Sopenharmony_ci p++; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci h32 ^= h32 >> 15; 36862306a36Sopenharmony_ci h32 *= PRIME32_2; 36962306a36Sopenharmony_ci h32 ^= h32 >> 13; 37062306a36Sopenharmony_ci h32 *= PRIME32_3; 37162306a36Sopenharmony_ci h32 ^= h32 >> 16; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci return h32; 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ciEXPORT_SYMBOL(xxh32_digest); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ciint xxh64_update(struct xxh64_state *state, const void *input, const size_t len) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci const uint8_t *p = (const uint8_t *)input; 38062306a36Sopenharmony_ci const uint8_t *const b_end = p + len; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci if (input == NULL) 38362306a36Sopenharmony_ci return -EINVAL; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci state->total_len += len; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci if (state->memsize + len < 32) { /* fill in tmp buffer */ 38862306a36Sopenharmony_ci memcpy(((uint8_t *)state->mem64) + state->memsize, input, len); 38962306a36Sopenharmony_ci state->memsize += (uint32_t)len; 39062306a36Sopenharmony_ci return 0; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci if (state->memsize) { /* tmp buffer is full */ 39462306a36Sopenharmony_ci uint64_t *p64 = state->mem64; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci memcpy(((uint8_t *)p64) + state->memsize, input, 39762306a36Sopenharmony_ci 32 - state->memsize); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci state->v1 = xxh64_round(state->v1, get_unaligned_le64(p64)); 40062306a36Sopenharmony_ci p64++; 40162306a36Sopenharmony_ci state->v2 = xxh64_round(state->v2, get_unaligned_le64(p64)); 40262306a36Sopenharmony_ci p64++; 40362306a36Sopenharmony_ci state->v3 = xxh64_round(state->v3, get_unaligned_le64(p64)); 40462306a36Sopenharmony_ci p64++; 40562306a36Sopenharmony_ci state->v4 = xxh64_round(state->v4, get_unaligned_le64(p64)); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci p += 32 - state->memsize; 40862306a36Sopenharmony_ci state->memsize = 0; 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci if (p + 32 <= b_end) { 41262306a36Sopenharmony_ci const uint8_t *const limit = b_end - 32; 41362306a36Sopenharmony_ci uint64_t v1 = state->v1; 41462306a36Sopenharmony_ci uint64_t v2 = state->v2; 41562306a36Sopenharmony_ci uint64_t v3 = state->v3; 41662306a36Sopenharmony_ci uint64_t v4 = state->v4; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci do { 41962306a36Sopenharmony_ci v1 = xxh64_round(v1, get_unaligned_le64(p)); 42062306a36Sopenharmony_ci p += 8; 42162306a36Sopenharmony_ci v2 = xxh64_round(v2, get_unaligned_le64(p)); 42262306a36Sopenharmony_ci p += 8; 42362306a36Sopenharmony_ci v3 = xxh64_round(v3, get_unaligned_le64(p)); 42462306a36Sopenharmony_ci p += 8; 42562306a36Sopenharmony_ci v4 = xxh64_round(v4, get_unaligned_le64(p)); 42662306a36Sopenharmony_ci p += 8; 42762306a36Sopenharmony_ci } while (p <= limit); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci state->v1 = v1; 43062306a36Sopenharmony_ci state->v2 = v2; 43162306a36Sopenharmony_ci state->v3 = v3; 43262306a36Sopenharmony_ci state->v4 = v4; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci if (p < b_end) { 43662306a36Sopenharmony_ci memcpy(state->mem64, p, (size_t)(b_end-p)); 43762306a36Sopenharmony_ci state->memsize = (uint32_t)(b_end - p); 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci return 0; 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ciEXPORT_SYMBOL(xxh64_update); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ciuint64_t xxh64_digest(const struct xxh64_state *state) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci const uint8_t *p = (const uint8_t *)state->mem64; 44762306a36Sopenharmony_ci const uint8_t *const b_end = (const uint8_t *)state->mem64 + 44862306a36Sopenharmony_ci state->memsize; 44962306a36Sopenharmony_ci uint64_t h64; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci if (state->total_len >= 32) { 45262306a36Sopenharmony_ci const uint64_t v1 = state->v1; 45362306a36Sopenharmony_ci const uint64_t v2 = state->v2; 45462306a36Sopenharmony_ci const uint64_t v3 = state->v3; 45562306a36Sopenharmony_ci const uint64_t v4 = state->v4; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci h64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) + 45862306a36Sopenharmony_ci xxh_rotl64(v3, 12) + xxh_rotl64(v4, 18); 45962306a36Sopenharmony_ci h64 = xxh64_merge_round(h64, v1); 46062306a36Sopenharmony_ci h64 = xxh64_merge_round(h64, v2); 46162306a36Sopenharmony_ci h64 = xxh64_merge_round(h64, v3); 46262306a36Sopenharmony_ci h64 = xxh64_merge_round(h64, v4); 46362306a36Sopenharmony_ci } else { 46462306a36Sopenharmony_ci h64 = state->v3 + PRIME64_5; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci h64 += (uint64_t)state->total_len; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci while (p + 8 <= b_end) { 47062306a36Sopenharmony_ci const uint64_t k1 = xxh64_round(0, get_unaligned_le64(p)); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci h64 ^= k1; 47362306a36Sopenharmony_ci h64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4; 47462306a36Sopenharmony_ci p += 8; 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci if (p + 4 <= b_end) { 47862306a36Sopenharmony_ci h64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1; 47962306a36Sopenharmony_ci h64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; 48062306a36Sopenharmony_ci p += 4; 48162306a36Sopenharmony_ci } 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci while (p < b_end) { 48462306a36Sopenharmony_ci h64 ^= (*p) * PRIME64_5; 48562306a36Sopenharmony_ci h64 = xxh_rotl64(h64, 11) * PRIME64_1; 48662306a36Sopenharmony_ci p++; 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci h64 ^= h64 >> 33; 49062306a36Sopenharmony_ci h64 *= PRIME64_2; 49162306a36Sopenharmony_ci h64 ^= h64 >> 29; 49262306a36Sopenharmony_ci h64 *= PRIME64_3; 49362306a36Sopenharmony_ci h64 ^= h64 >> 32; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci return h64; 49662306a36Sopenharmony_ci} 49762306a36Sopenharmony_ciEXPORT_SYMBOL(xxh64_digest); 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 50062306a36Sopenharmony_ciMODULE_DESCRIPTION("xxHash"); 501