/*
  Copyright 2016 Google LLC All rights reserved.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at:

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

/*
   american fuzzy lop - hashing function
   -------------------------------------

   The hash32() function is a variant of MurmurHash3, a good
   non-cryptosafe hashing function developed by Austin Appleby.

   For simplicity, this variant does *NOT* accept buffer lengths
   that are not divisible by 8 bytes. The 32-bit version is otherwise
   similar to the original; the 64-bit one is a custom hack with
   mostly-unproven properties.

   Austin's original code is public domain.

   Other code written and maintained by Michal Zalewski <lcamtuf@google.com>
*/

// 检查_HAVE_HASH_H宏是否已定义，如果没有，则定义它，以防止头文件被重复包含
#ifndef _HAVE_HASH_H
#define _HAVE_HASH_H

// 包含types.h头文件，可能包含一些基本类型的定义
#include "types.h"

// 如果编译目标是x86_64架构，则定义64位循环左移宏ROL64
#ifdef __x86_64__
#define ROL64(_x, _r)  ((((u64)(_x)) << (_r)) | (((u64)(_x)) >> (64 - (_r))))

// 定义一个内联函数hash32，用于计算32位哈希值（x86_64架构专用）
static inline u32 hash32(const void* key, u32 len, u32 seed) {
    // 将key转换为u64指针
    const u64* data = (u64*)key;
    // 初始化哈希值h1，种子与长度异或
    u64 h1 = seed ^ len;

    // 将长度除以8（因为u64是8字节）
    len >>= 3;

    // 循环处理每个u64数据块
    while (len--) {
        // 读取下一个u64数据
        u64 k1 = *data++;
        // 应用MurmurHash算法的步骤
        k1 *= 0x87c37b91114253d5ULL;
        k1 = ROL64(k1, 31);
        k1 *= 0x4cf5ad432745937fULL;

        // 将k1合并到h1
        h1 ^= k1;
        h1 = ROL64(h1, 27);
        h1 = h1 * 5 + 0x52dce729;
    }

    // 最后的哈希值处理步骤
    h1 ^= h1 >> 33;
    h1 *= 0xff51afd7ed558ccdULL;
    h1 ^= h1 >> 33;
    h1 *= 0xc4ceb9fe1a85ec53ULL;
    h1 ^= h1 >> 33;

    // 返回最终的哈希值
    return h1;
}

// 如果编译目标不是x86_64架构，则定义32位循环左移宏ROL32
#else 
#define ROL32(_x, _r)  ((((u32)(_x)) << (_r)) | (((u32)(_x)) >> (32 - (_r))))

// 定义一个内联函数hash32，用于计算32位哈希值（非x86_64架构专用）
static inline u32 hash32(const void* key, u32 len, u32 seed) {
    // 将key转换为u32指针
    const u32* data = (u32*)key;
    // 初始化哈希值h1，种子与长度异或
    u32 h1 = seed ^ len;

    // 将长度除以4（因为u32是4字节）
    len >>= 2;

    // 循环处理每个u32数据块
    while (len--) {
        // 读取下一个u32数据
        u32 k1 = *data++;
        // 应用MurmurHash算法的步骤
        k1 *= 0xcc9e2d51;
        k1 = ROL32(k1, 15);
        k1 *= 0x1b873593;

        // 将k1合并到h1
        h1 ^= k1;
        h1 = ROL32(h1, 13);
        h1 = h1 * 5 + 0xe6546b64;
    }

    // 最后的哈希值处理步骤
    h1 ^= h1 >> 16;
    h1 *= 0x85ebca6b;
    h1 ^= h1 >> 13;
    h1 *= 0xc2b2ae35;
    h1 ^= h1 >> 16;

    // 返回最终的哈希值
    return h1;
}

#endif /* ^__x86_64__ */

// 结束宏定义_HAVE_HASH_H
#endif /* !_HAVE_HASH_H */
