Blame linkhash.c

Packit Service def718
/*
Packit Service def718
 * $Id: linkhash.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
Packit Service def718
 *
Packit Service def718
 * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
Packit Service def718
 * Michael Clark <michael@metaparadigm.com>
Packit Service def718
 * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
Packit Service def718
 *
Packit Service def718
 * This library is free software; you can redistribute it and/or modify
Packit Service def718
 * it under the terms of the MIT license. See COPYING for details.
Packit Service def718
 *
Packit Service def718
 */
Packit Service def718
Packit Service def718
#include "config.h"
Packit Service def718
Packit Bot f5502f
#include <assert.h>
Packit Bot f5502f
#include <limits.h>
Packit Service def718
#include <stdarg.h>
Packit Service def718
#include <stddef.h>
Packit Bot f5502f
#include <stdio.h>
Packit Bot f5502f
#include <stdlib.h>
Packit Bot f5502f
#include <string.h>
Packit Service def718
Packit Service def718
#ifdef HAVE_ENDIAN_H
Packit Service def718
# include <endian.h>    /* attempt to define endianness */
Packit Service def718
#endif
Packit Service def718
Packit Service def718
#if defined(_MSC_VER) || defined(__MINGW32__)
Packit Service def718
# define WIN32_LEAN_AND_MEAN
Packit Service def718
# include <windows.h>   /* Get InterlockedCompareExchange */
Packit Service def718
#endif
Packit Service def718
Packit Service def718
#include "linkhash.h"
Packit Bot f5502f
#include "random_seed.h"
Packit Service def718
Packit Service def718
/* hash functions */
Packit Service def718
static unsigned long lh_char_hash(const void *k);
Packit Service def718
static unsigned long lh_perllike_str_hash(const void *k);
Packit Service def718
static lh_hash_fn *char_hash_fn = lh_char_hash;
Packit Service def718
Packit Service def718
int
Packit Service def718
json_global_set_string_hash(const int h)
Packit Service def718
{
Packit Service def718
	switch(h) {
Packit Service def718
	case JSON_C_STR_HASH_DFLT:
Packit Service def718
		char_hash_fn = lh_char_hash;
Packit Service def718
		break;
Packit Service def718
	case JSON_C_STR_HASH_PERLLIKE:
Packit Service def718
		char_hash_fn = lh_perllike_str_hash;
Packit Service def718
		break;
Packit Service def718
	default:
Packit Service def718
		return -1;
Packit Service def718
	}
Packit Service def718
	return 0;
Packit Service def718
}
Packit Service def718
Packit Service def718
void lh_abort(const char *msg, ...)
Packit Service def718
{
Packit Service def718
	va_list ap;
Packit Service def718
	va_start(ap, msg);
Packit Service def718
	vprintf(msg, ap);
Packit Service def718
	va_end(ap);
Packit Service def718
	exit(1);
Packit Service def718
}
Packit Service def718
Packit Service def718
static unsigned long lh_ptr_hash(const void *k)
Packit Service def718
{
Packit Service def718
	/* CAW: refactored to be 64bit nice */
Packit Service def718
	return (unsigned long)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX);
Packit Service def718
}
Packit Service def718
Packit Service def718
int lh_ptr_equal(const void *k1, const void *k2)
Packit Service def718
{
Packit Service def718
	return (k1 == k2);
Packit Service def718
}
Packit Service def718
Packit Service def718
/*
Packit Service def718
 * hashlittle from lookup3.c, by Bob Jenkins, May 2006, Public Domain.
Packit Service def718
 * http://burtleburtle.net/bob/c/lookup3.c
Packit Service def718
 * minor modifications to make functions static so no symbols are exported
Packit Service def718
 * minor mofifications to compile with -Werror
Packit Service def718
 */
Packit Service def718
Packit Service def718
/*
Packit Service def718
-------------------------------------------------------------------------------
Packit Service def718
lookup3.c, by Bob Jenkins, May 2006, Public Domain.
Packit Service def718
Packit Service def718
These are functions for producing 32-bit hashes for hash table lookup.
Packit Service def718
hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
Packit Service def718
are externally useful functions.  Routines to test the hash are included
Packit Service def718
if SELF_TEST is defined.  You can use this free for any purpose.  It's in
Packit Service def718
the public domain.  It has no warranty.
Packit Service def718
Packit Service def718
You probably want to use hashlittle().  hashlittle() and hashbig()
Packit Service def718
hash byte arrays.  hashlittle() is is faster than hashbig() on
Packit Service def718
little-endian machines.  Intel and AMD are little-endian machines.
Packit Service def718
On second thought, you probably want hashlittle2(), which is identical to
Packit Service def718
hashlittle() except it returns two 32-bit hashes for the price of one.
Packit Service def718
You could implement hashbig2() if you wanted but I haven't bothered here.
Packit Service def718
Packit Service def718
If you want to find a hash of, say, exactly 7 integers, do
Packit Service def718
  a = i1;  b = i2;  c = i3;
Packit Service def718
  mix(a,b,c);
Packit Service def718
  a += i4; b += i5; c += i6;
Packit Service def718
  mix(a,b,c);
Packit Service def718
  a += i7;
Packit Service def718
  final(a,b,c);
Packit Service def718
then use c as the hash value.  If you have a variable length array of
Packit Service def718
4-byte integers to hash, use hashword().  If you have a byte array (like
Packit Service def718
a character string), use hashlittle().  If you have several byte arrays, or
Packit Service def718
a mix of things, see the comments above hashlittle().
Packit Service def718
Packit Service def718
Why is this so big?  I read 12 bytes at a time into 3 4-byte integers,
Packit Service def718
then mix those integers.  This is fast (you can do a lot more thorough
Packit Service def718
mixing with 12*3 instructions on 3 integers than you can with 3 instructions
Packit Service def718
on 1 byte), but shoehorning those bytes into integers efficiently is messy.
Packit Service def718
-------------------------------------------------------------------------------
Packit Service def718
*/
Packit Service def718
Packit Service def718
/*
Packit Service def718
 * My best guess at if you are big-endian or little-endian.  This may
Packit Service def718
 * need adjustment.
Packit Service def718
 */
Packit Service def718
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
Packit Service def718
     __BYTE_ORDER == __LITTLE_ENDIAN) || \
Packit Service def718
    (defined(i386) || defined(__i386__) || defined(__i486__) || \
Packit Service def718
     defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
Packit Service def718
# define HASH_LITTLE_ENDIAN 1
Packit Service def718
# define HASH_BIG_ENDIAN 0
Packit Service def718
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
Packit Service def718
       __BYTE_ORDER == __BIG_ENDIAN) || \
Packit Service def718
      (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
Packit Service def718
# define HASH_LITTLE_ENDIAN 0
Packit Service def718
# define HASH_BIG_ENDIAN 1
Packit Service def718
#else
Packit Service def718
# define HASH_LITTLE_ENDIAN 0
Packit Service def718
# define HASH_BIG_ENDIAN 0
Packit Service def718
#endif
Packit Service def718
Packit Service def718
#define hashsize(n) ((uint32_t)1<<(n))
Packit Service def718
#define hashmask(n) (hashsize(n)-1)
Packit Service def718
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
Packit Service def718
Packit Service def718
/*
Packit Service def718
-------------------------------------------------------------------------------
Packit Service def718
mix -- mix 3 32-bit values reversibly.
Packit Service def718
Packit Service def718
This is reversible, so any information in (a,b,c) before mix() is
Packit Service def718
still in (a,b,c) after mix().
Packit Service def718
Packit Service def718
If four pairs of (a,b,c) inputs are run through mix(), or through
Packit Service def718
mix() in reverse, there are at least 32 bits of the output that
Packit Service def718
are sometimes the same for one pair and different for another pair.
Packit Service def718
This was tested for:
Packit Service def718
* pairs that differed by one bit, by two bits, in any combination
Packit Service def718
  of top bits of (a,b,c), or in any combination of bottom bits of
Packit Service def718
  (a,b,c).
Packit Service def718
* "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed
Packit Service def718
  the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
Packit Service def718
  is commonly produced by subtraction) look like a single 1-bit
Packit Service def718
  difference.
Packit Service def718
* the base values were pseudorandom, all zero but one bit set, or
Packit Service def718
  all zero plus a counter that starts at zero.
Packit Service def718
Packit Service def718
Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
Packit Service def718
satisfy this are
Packit Service def718
    4  6  8 16 19  4
Packit Service def718
    9 15  3 18 27 15
Packit Service def718
   14  9  3  7 17  3
Packit Service def718
Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
Packit Service def718
for "differ" defined as + with a one-bit base and a two-bit delta.  I
Packit Service def718
used http://burtleburtle.net/bob/hash/avalanche.html to choose
Packit Service def718
the operations, constants, and arrangements of the variables.
Packit Service def718
Packit Service def718
This does not achieve avalanche.  There are input bits of (a,b,c)
Packit Service def718
that fail to affect some output bits of (a,b,c), especially of a.  The
Packit Service def718
most thoroughly mixed value is c, but it doesn't really even achieve
Packit Service def718
avalanche in c.
Packit Service def718
Packit Service def718
This allows some parallelism.  Read-after-writes are good at doubling
Packit Service def718
the number of bits affected, so the goal of mixing pulls in the opposite
Packit Service def718
direction as the goal of parallelism.  I did what I could.  Rotates
Packit Service def718
seem to cost as much as shifts on every machine I could lay my hands
Packit Service def718
on, and rotates are much kinder to the top and bottom bits, so I used
Packit Service def718
rotates.
Packit Service def718
-------------------------------------------------------------------------------
Packit Service def718
*/
Packit Service def718
#define mix(a,b,c) \
Packit Service def718
{ \
Packit Service def718
  a -= c;  a ^= rot(c, 4);  c += b; \
Packit Service def718
  b -= a;  b ^= rot(a, 6);  a += c; \
Packit Service def718
  c -= b;  c ^= rot(b, 8);  b += a; \
Packit Service def718
  a -= c;  a ^= rot(c,16);  c += b; \
Packit Service def718
  b -= a;  b ^= rot(a,19);  a += c; \
Packit Service def718
  c -= b;  c ^= rot(b, 4);  b += a; \
Packit Service def718
}
Packit Service def718
Packit Service def718
/*
Packit Service def718
-------------------------------------------------------------------------------
Packit Service def718
final -- final mixing of 3 32-bit values (a,b,c) into c
Packit Service def718
Packit Service def718
Pairs of (a,b,c) values differing in only a few bits will usually
Packit Service def718
produce values of c that look totally different.  This was tested for
Packit Service def718
* pairs that differed by one bit, by two bits, in any combination
Packit Service def718
  of top bits of (a,b,c), or in any combination of bottom bits of
Packit Service def718
  (a,b,c).
Packit Service def718
* "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed
Packit Service def718
  the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
Packit Service def718
  is commonly produced by subtraction) look like a single 1-bit
Packit Service def718
  difference.
Packit Service def718
* the base values were pseudorandom, all zero but one bit set, or
Packit Service def718
  all zero plus a counter that starts at zero.
Packit Service def718
Packit Service def718
These constants passed:
Packit Service def718
 14 11 25 16 4 14 24
Packit Service def718
 12 14 25 16 4 14 24
Packit Service def718
and these came close:
Packit Service def718
  4  8 15 26 3 22 24
Packit Service def718
 10  8 15 26 3 22 24
Packit Service def718
 11  8 15 26 3 22 24
Packit Service def718
-------------------------------------------------------------------------------
Packit Service def718
*/
Packit Service def718
#define final(a,b,c) \
Packit Service def718
{ \
Packit Service def718
  c ^= b; c -= rot(b,14); \
Packit Service def718
  a ^= c; a -= rot(c,11); \
Packit Service def718
  b ^= a; b -= rot(a,25); \
Packit Service def718
  c ^= b; c -= rot(b,16); \
Packit Service def718
  a ^= c; a -= rot(c,4);  \
Packit Service def718
  b ^= a; b -= rot(a,14); \
Packit Service def718
  c ^= b; c -= rot(b,24); \
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
/*
Packit Service def718
-------------------------------------------------------------------------------
Packit Service def718
hashlittle() -- hash a variable-length key into a 32-bit value
Packit Service def718
  k       : the key (the unaligned variable-length array of bytes)
Packit Service def718
  length  : the length of the key, counting by bytes
Packit Service def718
  initval : can be any 4-byte value
Packit Service def718
Returns a 32-bit value.  Every bit of the key affects every bit of
Packit Service def718
the return value.  Two keys differing by one or two bits will have
Packit Service def718
totally different hash values.
Packit Service def718
Packit Service def718
The best hash table sizes are powers of 2.  There is no need to do
Packit Service def718
mod a prime (mod is sooo slow!).  If you need less than 32 bits,
Packit Service def718
use a bitmask.  For example, if you need only 10 bits, do
Packit Service def718
  h = (h & hashmask(10));
Packit Service def718
In which case, the hash table should have hashsize(10) elements.
Packit Service def718
Packit Service def718
If you are hashing n strings (uint8_t **)k, do it like this:
Packit Service def718
  for (i=0, h=0; i
Packit Service def718
Packit Service def718
By Bob Jenkins, 2006.  bob_jenkins@burtleburtle.net.  You may use this
Packit Service def718
code any way you wish, private, educational, or commercial.  It's free.
Packit Service def718
Packit Service def718
Use for hash table lookup, or anything where one collision in 2^^32 is
Packit Service def718
acceptable.  Do NOT use for cryptographic purposes.
Packit Service def718
-------------------------------------------------------------------------------
Packit Service def718
*/
Packit Service def718
Packit Service def718
static uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
Packit Service def718
{
Packit Service def718
  uint32_t a,b,c;                                          /* internal state */
Packit Service def718
  union { const void *ptr; size_t i; } u;     /* needed for Mac Powerbook G4 */
Packit Service def718
Packit Service def718
  /* Set up the internal state */
Packit Service def718
  a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
Packit Service def718
Packit Service def718
  u.ptr = key;
Packit Service def718
  if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
Packit Service def718
    const uint32_t *k = (const uint32_t *)key;         /* read 32-bit chunks */
Packit Service def718
Packit Service def718
    /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
Packit Service def718
    while (length > 12)
Packit Service def718
    {
Packit Service def718
      a += k[0];
Packit Service def718
      b += k[1];
Packit Service def718
      c += k[2];
Packit Service def718
      mix(a,b,c);
Packit Service def718
      length -= 12;
Packit Service def718
      k += 3;
Packit Service def718
    }
Packit Service def718
Packit Service def718
    /*----------------------------- handle the last (probably partial) block */
Packit Service def718
    /*
Packit Service def718
     * "k[2]&0xffffff" actually reads beyond the end of the string, but
Packit Service def718
     * then masks off the part it's not allowed to read.  Because the
Packit Service def718
     * string is aligned, the masked-off tail is in the same word as the
Packit Service def718
     * rest of the string.  Every machine with memory protection I've seen
Packit Service def718
     * does it on word boundaries, so is OK with this.  But VALGRIND will
Packit Service def718
     * still catch it and complain.  The masking trick does make the hash
Packit Service def718
     * noticably faster for short strings (like English words).
Packit Service def718
     * AddressSanitizer is similarly picky about overrunning
Packit Service def718
	 * the buffer. (http://clang.llvm.org/docs/AddressSanitizer.html
Packit Service def718
     */
Packit Service def718
#ifdef VALGRIND
Packit Service def718
#    define PRECISE_MEMORY_ACCESS 1
Packit Service def718
#elif defined(__SANITIZE_ADDRESS__) /* GCC's ASAN */
Packit Service def718
#    define PRECISE_MEMORY_ACCESS 1
Packit Service def718
#elif defined(__has_feature)
Packit Service def718
#  if __has_feature(address_sanitizer) /* Clang's ASAN */
Packit Service def718
#    define PRECISE_MEMORY_ACCESS 1
Packit Service def718
#  endif
Packit Service def718
#endif
Packit Service def718
#ifndef PRECISE_MEMORY_ACCESS
Packit Service def718
Packit Service def718
    switch(length)
Packit Service def718
    {
Packit Service def718
    case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
Packit Service def718
    case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
Packit Service def718
    case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
Packit Service def718
    case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
Packit Service def718
    case 8 : b+=k[1]; a+=k[0]; break;
Packit Service def718
    case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
Packit Service def718
    case 6 : b+=k[1]&0xffff; a+=k[0]; break;
Packit Service def718
    case 5 : b+=k[1]&0xff; a+=k[0]; break;
Packit Service def718
    case 4 : a+=k[0]; break;
Packit Service def718
    case 3 : a+=k[0]&0xffffff; break;
Packit Service def718
    case 2 : a+=k[0]&0xffff; break;
Packit Service def718
    case 1 : a+=k[0]&0xff; break;
Packit Service def718
    case 0 : return c;              /* zero length strings require no mixing */
Packit Service def718
    }
Packit Service def718
Packit Service def718
#else /* make valgrind happy */
Packit Service def718
Packit Service def718
    const uint8_t  *k8 = (const uint8_t *)k;
Packit Service def718
    switch(length)
Packit Service def718
    {
Packit Service def718
    case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
Packit Service def718
    case 11: c+=((uint32_t)k8[10])<<16;  /* fall through */
Packit Service def718
    case 10: c+=((uint32_t)k8[9])<<8;    /* fall through */
Packit Service def718
    case 9 : c+=k8[8];                   /* fall through */
Packit Service def718
    case 8 : b+=k[1]; a+=k[0]; break;
Packit Service def718
    case 7 : b+=((uint32_t)k8[6])<<16;   /* fall through */
Packit Service def718
    case 6 : b+=((uint32_t)k8[5])<<8;    /* fall through */
Packit Service def718
    case 5 : b+=k8[4];                   /* fall through */
Packit Service def718
    case 4 : a+=k[0]; break;
Packit Service def718
    case 3 : a+=((uint32_t)k8[2])<<16;   /* fall through */
Packit Service def718
    case 2 : a+=((uint32_t)k8[1])<<8;    /* fall through */
Packit Service def718
    case 1 : a+=k8[0]; break;
Packit Service def718
    case 0 : return c;
Packit Service def718
    }
Packit Service def718
Packit Service def718
#endif /* !valgrind */
Packit Service def718
Packit Service def718
  } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
Packit Service def718
    const uint16_t *k = (const uint16_t *)key;         /* read 16-bit chunks */
Packit Service def718
    const uint8_t  *k8;
Packit Service def718
Packit Service def718
    /*--------------- all but last block: aligned reads and different mixing */
Packit Service def718
    while (length > 12)
Packit Service def718
    {
Packit Service def718
      a += k[0] + (((uint32_t)k[1])<<16);
Packit Service def718
      b += k[2] + (((uint32_t)k[3])<<16);
Packit Service def718
      c += k[4] + (((uint32_t)k[5])<<16);
Packit Service def718
      mix(a,b,c);
Packit Service def718
      length -= 12;
Packit Service def718
      k += 6;
Packit Service def718
    }
Packit Service def718
Packit Service def718
    /*----------------------------- handle the last (probably partial) block */
Packit Service def718
    k8 = (const uint8_t *)k;
Packit Service def718
    switch(length)
Packit Service def718
    {
Packit Service def718
    case 12: c+=k[4]+(((uint32_t)k[5])<<16);
Packit Service def718
             b+=k[2]+(((uint32_t)k[3])<<16);
Packit Service def718
             a+=k[0]+(((uint32_t)k[1])<<16);
Packit Service def718
             break;
Packit Service def718
    case 11: c+=((uint32_t)k8[10])<<16;     /* fall through */
Packit Service def718
    case 10: c+=k[4];
Packit Service def718
             b+=k[2]+(((uint32_t)k[3])<<16);
Packit Service def718
             a+=k[0]+(((uint32_t)k[1])<<16);
Packit Service def718
             break;
Packit Service def718
    case 9 : c+=k8[8];                      /* fall through */
Packit Service def718
    case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
Packit Service def718
             a+=k[0]+(((uint32_t)k[1])<<16);
Packit Service def718
             break;
Packit Service def718
    case 7 : b+=((uint32_t)k8[6])<<16;      /* fall through */
Packit Service def718
    case 6 : b+=k[2];
Packit Service def718
             a+=k[0]+(((uint32_t)k[1])<<16);
Packit Service def718
             break;
Packit Service def718
    case 5 : b+=k8[4];                      /* fall through */
Packit Service def718
    case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
Packit Service def718
             break;
Packit Service def718
    case 3 : a+=((uint32_t)k8[2])<<16;      /* fall through */
Packit Service def718
    case 2 : a+=k[0];
Packit Service def718
             break;
Packit Service def718
    case 1 : a+=k8[0];
Packit Service def718
             break;
Packit Service def718
    case 0 : return c;                     /* zero length requires no mixing */
Packit Service def718
    }
Packit Service def718
Packit Service def718
  } else {                        /* need to read the key one byte at a time */
Packit Service def718
    const uint8_t *k = (const uint8_t *)key;
Packit Service def718
Packit Service def718
    /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
Packit Service def718
    while (length > 12)
Packit Service def718
    {
Packit Service def718
      a += k[0];
Packit Service def718
      a += ((uint32_t)k[1])<<8;
Packit Service def718
      a += ((uint32_t)k[2])<<16;
Packit Service def718
      a += ((uint32_t)k[3])<<24;
Packit Service def718
      b += k[4];
Packit Service def718
      b += ((uint32_t)k[5])<<8;
Packit Service def718
      b += ((uint32_t)k[6])<<16;
Packit Service def718
      b += ((uint32_t)k[7])<<24;
Packit Service def718
      c += k[8];
Packit Service def718
      c += ((uint32_t)k[9])<<8;
Packit Service def718
      c += ((uint32_t)k[10])<<16;
Packit Service def718
      c += ((uint32_t)k[11])<<24;
Packit Service def718
      mix(a,b,c);
Packit Service def718
      length -= 12;
Packit Service def718
      k += 12;
Packit Service def718
    }
Packit Service def718
Packit Service def718
    /*-------------------------------- last block: affect all 32 bits of (c) */
Packit Service def718
    switch(length)                   /* all the case statements fall through */
Packit Service def718
    {
Packit Service def718
    case 12: c+=((uint32_t)k[11])<<24; /* FALLTHRU */
Packit Service def718
    case 11: c+=((uint32_t)k[10])<<16; /* FALLTHRU */
Packit Service def718
    case 10: c+=((uint32_t)k[9])<<8; /* FALLTHRU */
Packit Service def718
    case 9 : c+=k[8]; /* FALLTHRU */
Packit Service def718
    case 8 : b+=((uint32_t)k[7])<<24; /* FALLTHRU */
Packit Service def718
    case 7 : b+=((uint32_t)k[6])<<16; /* FALLTHRU */
Packit Service def718
    case 6 : b+=((uint32_t)k[5])<<8; /* FALLTHRU */
Packit Service def718
    case 5 : b+=k[4]; /* FALLTHRU */
Packit Service def718
    case 4 : a+=((uint32_t)k[3])<<24; /* FALLTHRU */
Packit Service def718
    case 3 : a+=((uint32_t)k[2])<<16; /* FALLTHRU */
Packit Service def718
    case 2 : a+=((uint32_t)k[1])<<8; /* FALLTHRU */
Packit Service def718
    case 1 : a+=k[0];
Packit Service def718
             break;
Packit Service def718
    case 0 : return c;
Packit Service def718
    }
Packit Service def718
  }
Packit Service def718
Packit Service def718
  final(a,b,c);
Packit Service def718
  return c;
Packit Service def718
}
Packit Service def718
Packit Service def718
/* a simple hash function similiar to what perl does for strings.
Packit Service def718
 * for good results, the string should not be excessivly large.
Packit Service def718
 */
Packit Service def718
static unsigned long lh_perllike_str_hash(const void *k) 
Packit Service def718
{
Packit Service def718
    const char *rkey = (const char *)k;
Packit Service def718
    unsigned hashval = 1;
Packit Service def718
Packit Service def718
    while (*rkey)
Packit Service def718
        hashval = hashval * 33 + *rkey++;
Packit Service def718
Packit Service def718
    return hashval;
Packit Service def718
}
Packit Service def718
Packit Service def718
static unsigned long lh_char_hash(const void *k)
Packit Service def718
{
Packit Service def718
#if defined _MSC_VER || defined __MINGW32__
Packit Service def718
#define RANDOM_SEED_TYPE LONG
Packit Service def718
#else
Packit Service def718
#define RANDOM_SEED_TYPE int
Packit Service def718
#endif
Packit Service def718
	static volatile RANDOM_SEED_TYPE random_seed = -1;
Packit Service def718
Packit Service def718
	if (random_seed == -1) {
Packit Service def718
		RANDOM_SEED_TYPE seed;
Packit Service def718
		/* we can't use -1 as it is the unitialized sentinel */
Packit Service def718
		while ((seed = json_c_get_random_seed()) == -1);
Packit Service def718
#if SIZEOF_INT == 8 && defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
Packit Service def718
#define USE_SYNC_COMPARE_AND_SWAP 1
Packit Service def718
#endif
Packit Service def718
#if SIZEOF_INT == 4 && defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
Packit Service def718
#define USE_SYNC_COMPARE_AND_SWAP 1
Packit Service def718
#endif
Packit Service def718
#if SIZEOF_INT == 2 && defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
Packit Service def718
#define USE_SYNC_COMPARE_AND_SWAP 1
Packit Service def718
#endif
Packit Service def718
#if defined USE_SYNC_COMPARE_AND_SWAP
Packit Service def718
		(void)__sync_val_compare_and_swap(&random_seed, -1, seed);
Packit Service def718
#elif defined _MSC_VER || defined __MINGW32__
Packit Service def718
		InterlockedCompareExchange(&random_seed, seed, -1);
Packit Service def718
#else
Packit Service def718
//#warning "racy random seed initializtion if used by multiple threads"
Packit Service def718
		random_seed = seed; /* potentially racy */
Packit Service def718
#endif
Packit Service def718
	}
Packit Service def718
Packit Service def718
	return hashlittle((const char*)k, strlen((const char*)k), random_seed);
Packit Service def718
}
Packit Service def718
Packit Service def718
int lh_char_equal(const void *k1, const void *k2)
Packit Service def718
{
Packit Service def718
	return (strcmp((const char*)k1, (const char*)k2) == 0);
Packit Service def718
}
Packit Service def718
Packit Service def718
struct lh_table* lh_table_new(int size,
Packit Service def718
			      lh_entry_free_fn *free_fn,
Packit Service def718
			      lh_hash_fn *hash_fn,
Packit Service def718
			      lh_equal_fn *equal_fn)
Packit Service def718
{
Packit Service def718
	int i;
Packit Service def718
	struct lh_table *t;
Packit Service def718
Packit Bot f5502f
	/* Allocate space for elements to avoid divisions by zero. */
Packit Bot f5502f
	assert(size > 0);
Packit Bot f5502f
	t = (struct lh_table *)calloc(1, sizeof(struct lh_table));
Packit Service def718
	if (!t)
Packit Service def718
		return NULL;
Packit Service def718
Packit Service def718
	t->count = 0;
Packit Service def718
	t->size = size;
Packit Service def718
	t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry));
Packit Service def718
	if (!t->table)
Packit Service def718
	{
Packit Service def718
		free(t);
Packit Service def718
		return NULL;
Packit Service def718
	}
Packit Service def718
	t->free_fn = free_fn;
Packit Service def718
	t->hash_fn = hash_fn;
Packit Service def718
	t->equal_fn = equal_fn;
Packit Service def718
	for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY;
Packit Service def718
	return t;
Packit Service def718
}
Packit Service def718
Packit Service def718
struct lh_table* lh_kchar_table_new(int size,
Packit Service def718
				    lh_entry_free_fn *free_fn)
Packit Service def718
{
Packit Service def718
	return lh_table_new(size, free_fn, char_hash_fn, lh_char_equal);
Packit Service def718
}
Packit Service def718
Packit Service def718
struct lh_table* lh_kptr_table_new(int size,
Packit Service def718
				   lh_entry_free_fn *free_fn)
Packit Service def718
{
Packit Service def718
	return lh_table_new(size, free_fn, lh_ptr_hash, lh_ptr_equal);
Packit Service def718
}
Packit Service def718
Packit Service def718
int lh_table_resize(struct lh_table *t, int new_size)
Packit Service def718
{
Packit Service def718
	struct lh_table *new_t;
Packit Service def718
	struct lh_entry *ent;
Packit Service def718
Packit Service def718
	new_t = lh_table_new(new_size, NULL, t->hash_fn, t->equal_fn);
Packit Service def718
	if (new_t == NULL)
Packit Service def718
		return -1;
Packit Service def718
Packit Service def718
	for (ent = t->head; ent != NULL; ent = ent->next)
Packit Service def718
	{
Packit Service def718
		unsigned long h = lh_get_hash(new_t, ent->k);
Packit Service def718
		unsigned int opts = 0;
Packit Service def718
		if (ent->k_is_constant)
Packit Service def718
			opts = JSON_C_OBJECT_KEY_IS_CONSTANT;
Packit Service def718
		if (lh_table_insert_w_hash(new_t, ent->k, ent->v, h, opts) != 0)
Packit Service def718
		{
Packit Service def718
			lh_table_free(new_t);
Packit Service def718
			return -1;
Packit Service def718
		}
Packit Service def718
	}
Packit Service def718
	free(t->table);
Packit Service def718
	t->table = new_t->table;
Packit Service def718
	t->size = new_size;
Packit Service def718
	t->head = new_t->head;
Packit Service def718
	t->tail = new_t->tail;
Packit Service def718
	free(new_t);
Packit Service def718
Packit Service def718
	return 0;
Packit Service def718
}
Packit Service def718
Packit Service def718
void lh_table_free(struct lh_table *t)
Packit Service def718
{
Packit Service def718
	struct lh_entry *c;
Packit Service def718
	if(t->free_fn) {
Packit Service def718
		for(c = t->head; c != NULL; c = c->next)
Packit Service def718
			t->free_fn(c);
Packit Service def718
	}
Packit Service def718
	free(t->table);
Packit Service def718
	free(t);
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, const unsigned long h, const unsigned opts)
Packit Service def718
{
Packit Service def718
	unsigned long n;
Packit Service def718
Packit Service def718
	if (t->count >= t->size * LH_LOAD_FACTOR)
Packit Bot f5502f
	{
Packit Bot f5502f
		/* Avoid signed integer overflow with large tables. */
Packit Bot f5502f
		int new_size = (t->size > INT_MAX / 2) ? INT_MAX : (t->size * 2);
Packit Bot f5502f
		if (t->size == INT_MAX || lh_table_resize(t, new_size) != 0)
Packit Service def718
			return -1;
Packit Bot f5502f
	}
Packit Service def718
Packit Service def718
	n = h % t->size;
Packit Service def718
Packit Service def718
	while( 1 ) {
Packit Service def718
		if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break;
Packit Service def718
		if ((int)++n == t->size) n = 0;
Packit Service def718
	}
Packit Service def718
Packit Service def718
	t->table[n].k = k;
Packit Service def718
	t->table[n].k_is_constant = (opts & JSON_C_OBJECT_KEY_IS_CONSTANT);
Packit Service def718
	t->table[n].v = v;
Packit Service def718
	t->count++;
Packit Service def718
Packit Service def718
	if(t->head == NULL) {
Packit Service def718
		t->head = t->tail = &t->table[n];
Packit Service def718
		t->table[n].next = t->table[n].prev = NULL;
Packit Service def718
	} else {
Packit Service def718
		t->tail->next = &t->table[n];
Packit Service def718
		t->table[n].prev = t->tail;
Packit Service def718
		t->table[n].next = NULL;
Packit Service def718
		t->tail = &t->table[n];
Packit Service def718
	}
Packit Service def718
Packit Service def718
	return 0;
Packit Service def718
}
Packit Service def718
int lh_table_insert(struct lh_table *t, const void *k, const void *v)
Packit Service def718
{
Packit Service def718
	return lh_table_insert_w_hash(t, k, v, lh_get_hash(t, k), 0);
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
struct lh_entry* lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k, const unsigned long h)
Packit Service def718
{
Packit Service def718
	unsigned long n = h % t->size;
Packit Service def718
	int count = 0;
Packit Service def718
Packit Service def718
	while( count < t->size ) {
Packit Service def718
		if(t->table[n].k == LH_EMPTY) return NULL;
Packit Service def718
		if(t->table[n].k != LH_FREED &&
Packit Service def718
		   t->equal_fn(t->table[n].k, k)) return &t->table[n];
Packit Service def718
		if ((int)++n == t->size) n = 0;
Packit Service def718
		count++;
Packit Service def718
	}
Packit Service def718
	return NULL;
Packit Service def718
}
Packit Service def718
Packit Service def718
struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k)
Packit Service def718
{
Packit Service def718
	return lh_table_lookup_entry_w_hash(t, k, lh_get_hash(t, k));
Packit Service def718
}
Packit Service def718
Packit Service def718
const void* lh_table_lookup(struct lh_table *t, const void *k)
Packit Service def718
{
Packit Service def718
	void *result;
Packit Service def718
	lh_table_lookup_ex(t, k, &result);
Packit Service def718
	return result;
Packit Service def718
}
Packit Service def718
Packit Service def718
json_bool lh_table_lookup_ex(struct lh_table* t, const void* k, void **v)
Packit Service def718
{
Packit Service def718
	struct lh_entry *e = lh_table_lookup_entry(t, k);
Packit Service def718
	if (e != NULL) {
Packit Service def718
		if (v != NULL) *v = lh_entry_v(e);
Packit Service def718
		return TRUE; /* key found */
Packit Service def718
	}
Packit Service def718
	if (v != NULL) *v = NULL;
Packit Service def718
		return FALSE; /* key not found */
Packit Service def718
}
Packit Service def718
Packit Service def718
int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
Packit Service def718
{
Packit Service def718
	ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */
Packit Service def718
Packit Service def718
	/* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */
Packit Service def718
	if(n < 0) { return -2; }
Packit Service def718
Packit Service def718
	if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1;
Packit Service def718
	t->count--;
Packit Service def718
	if(t->free_fn) t->free_fn(e);
Packit Service def718
	t->table[n].v = NULL;
Packit Service def718
	t->table[n].k = LH_FREED;
Packit Service def718
	if(t->tail == &t->table[n] && t->head == &t->table[n]) {
Packit Service def718
		t->head = t->tail = NULL;
Packit Service def718
	} else if (t->head == &t->table[n]) {
Packit Service def718
		t->head->next->prev = NULL;
Packit Service def718
		t->head = t->head->next;
Packit Service def718
	} else if (t->tail == &t->table[n]) {
Packit Service def718
		t->tail->prev->next = NULL;
Packit Service def718
		t->tail = t->tail->prev;
Packit Service def718
	} else {
Packit Service def718
		t->table[n].prev->next = t->table[n].next;
Packit Service def718
		t->table[n].next->prev = t->table[n].prev;
Packit Service def718
	}
Packit Service def718
	t->table[n].next = t->table[n].prev = NULL;
Packit Service def718
	return 0;
Packit Service def718
}
Packit Service def718
Packit Service def718
Packit Service def718
int lh_table_delete(struct lh_table *t, const void *k)
Packit Service def718
{
Packit Service def718
	struct lh_entry *e = lh_table_lookup_entry(t, k);
Packit Service def718
	if(!e) return -1;
Packit Service def718
	return lh_table_delete_entry(t, e);
Packit Service def718
}
Packit Service def718
Packit Service def718
int lh_table_length(struct lh_table *t)
Packit Service def718
{
Packit Service def718
	return t->count;
Packit Service def718
}