aboutsummaryrefslogtreecommitdiff
path: root/src/libsok/sok-ctx-hash.c
blob: 61689ea24a798e9d7e4dc2f251e27cc193c8fd91 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdint.h> // uint16_t
#include "sok.h"

// fnv64
// src: https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function
#define FNV_OFFSET 1099511628211
#define FNV_PRIME  0xcbf29ce484222325

static uint64_t
fnv1a(
  const uint8_t * const buf,
  const size_t len
) {
  uint64_t hash = FNV_OFFSET;

  for (size_t i = 0; i < len; i++) {
    hash ^= buf[i];
    hash *= FNV_PRIME;
  }

  return hash;
}

uint64_t
sok_ctx_hash(
  const sok_ctx_t * const ctx
) {
  uint16_t buf[512] = {ctx->home.x, ctx->home.y, 0};
  const size_t BUF_MASK = (sizeof(buf) / sizeof(uint16_t) - 1);

  for (size_t i = 0; i < ctx->level.num_boxes; i++) {
    buf[(2 * (i + 1) + 0) & BUF_MASK] = ctx->boxes[i].x;
    buf[(2 * (i + 1) + 1) & BUF_MASK] = ctx->boxes[i].y;
  }

  // calculate buffer length
  const size_t used = 2 * (ctx->level.num_boxes + 1) * sizeof(uint16_t);
  const size_t len = (used < sizeof(buf)) ? used : sizeof(buf);

  return fnv1a((uint8_t*) buf, len);
}