--- /dev/null
+/*
+ SipHash reference C implementation
+
+ Copyright (c) 2012-2021 Jean-Philippe Aumasson
+ <jeanphilippe.aumasson@gmail.com>
+ Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
+ Slightly tweaked by the git author.
+
+ To the extent possible under law, the author(s) have dedicated all copyright
+ and related and neighboring rights to this software to the public domain
+ worldwide. This software is distributed without any warranty.
+
+ You should have received a copy of the CC0 Public Domain Dedication along
+ with
+ this software. If not, see
+ <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* default: SipHash-2-4 */
+#ifndef cROUNDS
+#define cROUNDS 1
+#endif
+#ifndef dROUNDS
+#define dROUNDS 3
+#endif
+
+#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
+
+#define U32TO8_LE(p, v) \
+ (p)[0] = (uint8_t)((v)); \
+ (p)[1] = (uint8_t)((v) >> 8); \
+ (p)[2] = (uint8_t)((v) >> 16); \
+ (p)[3] = (uint8_t)((v) >> 24);
+
+#define U8TO64_LE(p) \
+ (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \
+ ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \
+ ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \
+ ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
+
+#define SIPROUND \
+ do { \
+ v0 += v1; \
+ v1 = ROTL(v1, 13); \
+ v1 ^= v0; \
+ v0 = ROTL(v0, 32); \
+ v2 += v3; \
+ v3 = ROTL(v3, 16); \
+ v3 ^= v2; \
+ v0 += v3; \
+ v3 = ROTL(v3, 21); \
+ v3 ^= v0; \
+ v2 += v1; \
+ v1 = ROTL(v1, 17); \
+ v1 ^= v2; \
+ v2 = ROTL(v2, 32); \
+ } while (0)
+
+#ifdef DEBUG
+#include <stdio.h>
+#define TRACE \
+ do { \
+ printf("(%3zu) v0 %016" PRIx64 "\n", inlen, v0); \
+ printf("(%3zu) v1 %016" PRIx64 "\n", inlen, v1); \
+ printf("(%3zu) v2 %016" PRIx64 "\n", inlen, v2); \
+ printf("(%3zu) v3 %016" PRIx64 "\n", inlen, v3); \
+ } while (0)
+#else
+#define TRACE
+#endif
+
+__attribute__((always_inline))
+static inline uint64_t siphash(const void *in, const size_t inlen, const uint8_t k[16]) {
+ const unsigned char *ni = (const unsigned char *)in;
+ const unsigned char *kk = (const unsigned char *)k;
+
+ uint64_t v0 = UINT64_C(0x736f6d6570736575);
+ uint64_t v1 = UINT64_C(0x646f72616e646f6d);
+ uint64_t v2 = UINT64_C(0x6c7967656e657261);
+ uint64_t v3 = UINT64_C(0x7465646279746573);
+ uint64_t k0 = U8TO64_LE(kk);
+ uint64_t k1 = U8TO64_LE(kk + 8);
+ uint64_t m;
+ int i;
+ const unsigned char *end = ni + inlen - (inlen % sizeof(uint64_t));
+ const int left = inlen & 7;
+ uint64_t b = ((uint64_t)inlen) << 56;
+ v3 ^= k1;
+ v2 ^= k0;
+ v1 ^= k1;
+ v0 ^= k0;
+
+ for (; ni != end; ni += 8) {
+ m = U8TO64_LE(ni);
+ v3 ^= m;
+
+ TRACE;
+ for (i = 0; i < cROUNDS; ++i)
+ SIPROUND;
+
+ v0 ^= m;
+ }
+
+ switch (left) {
+ case 7:
+ b |= ((uint64_t)ni[6]) << 48;
+ case 6:
+ b |= ((uint64_t)ni[5]) << 40;
+ case 5:
+ b |= ((uint64_t)ni[4]) << 32;
+ case 4:
+ b |= ((uint64_t)ni[3]) << 24;
+ case 3:
+ b |= ((uint64_t)ni[2]) << 16;
+ case 2:
+ b |= ((uint64_t)ni[1]) << 8;
+ case 1:
+ b |= ((uint64_t)ni[0]);
+ break;
+ case 0:
+ break;
+ }
+
+ v3 ^= b;
+
+ TRACE;
+ for (i = 0; i < cROUNDS; ++i)
+ SIPROUND;
+
+ v0 ^= b;
+ v2 ^= 0xff;
+
+ TRACE;
+ for (i = 0; i < dROUNDS; ++i)
+ SIPROUND;
+
+ b = v0 ^ v1 ^ v2 ^ v3;
+ return b;
+}