xref: /mOS-networking-stack/core/src/util.c (revision d88f3b1d)
176404edcSAsim Jamshed /*
276404edcSAsim Jamshed     Borrowed XXH32 and XXH64 implementation from xxHash project
376404edcSAsim Jamshed 
476404edcSAsim Jamshed     Added Copyright notice just above the function definition
576404edcSAsim Jamshed 
676404edcSAsim Jamshed     TODO 1 : We might wanna implement our version of xxh for copyright reason
776404edcSAsim Jamshed     TODO 2 : We might wanna gather all copyright notice and create a single file.
876404edcSAsim Jamshed */
976404edcSAsim Jamshed 
1076404edcSAsim Jamshed 
1176404edcSAsim Jamshed 
1276404edcSAsim Jamshed #include <stdint.h>
1376404edcSAsim Jamshed #include <netinet/in.h>
1476404edcSAsim Jamshed #include <arpa/inet.h>
1576404edcSAsim Jamshed #include <string.h>
1676404edcSAsim Jamshed #include <ctype.h>
1776404edcSAsim Jamshed #include <mtcp_util.h>
18c6a5549bSAsim Jamshed #include <limits.h>
19c6a5549bSAsim Jamshed #include <stdio.h>
20c6a5549bSAsim Jamshed #include <errno.h>
21c6a5549bSAsim Jamshed #include <stdlib.h>
2276404edcSAsim Jamshed 
2376404edcSAsim Jamshed /*-------------------------------------------------------------*/
248c9e1184SAsim Jamshed extern int
258c9e1184SAsim Jamshed FetchEndianType();
268c9e1184SAsim Jamshed /*-------------------------------------------------------------*/
2776404edcSAsim Jamshed static void
BuildKeyCache(uint32_t * cache,int cache_len)2876404edcSAsim Jamshed BuildKeyCache(uint32_t *cache, int cache_len)
2976404edcSAsim Jamshed {
3076404edcSAsim Jamshed #ifndef NBBY
3176404edcSAsim Jamshed #define NBBY 8 /* number of bits per byte */
3276404edcSAsim Jamshed #endif
3376404edcSAsim Jamshed 
34522d5c66SAsim Jamshed 	/* Both of DPDK and Netmap uses this key for hash calculation.
3576404edcSAsim Jamshed 	 * Do not change any single bit of this key. */
3676404edcSAsim Jamshed 	static const uint8_t key[] = {
3776404edcSAsim Jamshed 		 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
3876404edcSAsim Jamshed 		 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
3976404edcSAsim Jamshed 		 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
4076404edcSAsim Jamshed 		 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
4176404edcSAsim Jamshed 		 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05
4276404edcSAsim Jamshed 	};
4376404edcSAsim Jamshed 
4476404edcSAsim Jamshed 	uint32_t result = (((uint32_t)key[0]) << 24) |
4576404edcSAsim Jamshed                           (((uint32_t)key[1]) << 16) |
4676404edcSAsim Jamshed                           (((uint32_t)key[2]) << 8)  | ((uint32_t)key[3]);
4776404edcSAsim Jamshed 	uint32_t idx = 32;
4876404edcSAsim Jamshed 	int i;
4976404edcSAsim Jamshed 
5076404edcSAsim Jamshed 	for (i = 0; i < cache_len; i++, idx++) {
5176404edcSAsim Jamshed 		uint8_t shift = (idx % NBBY);
5276404edcSAsim Jamshed 		uint32_t bit;
5376404edcSAsim Jamshed 
5476404edcSAsim Jamshed 		cache[i] = result;
5576404edcSAsim Jamshed 		bit = ((key[idx/NBBY] << shift) & 0x80) ? 1 : 0;
5676404edcSAsim Jamshed 		result = ((result << 1) | bit);
5776404edcSAsim Jamshed 	}
5876404edcSAsim Jamshed 
5976404edcSAsim Jamshed }
6076404edcSAsim Jamshed /*-------------------------------------------------------------*/
6176404edcSAsim Jamshed uint32_t
GetRSSHash(in_addr_t sip,in_addr_t dip,in_port_t sp,in_port_t dp)6276404edcSAsim Jamshed GetRSSHash(in_addr_t sip, in_addr_t dip, in_port_t sp, in_port_t dp)
6376404edcSAsim Jamshed {
6476404edcSAsim Jamshed #define MSB32 0x80000000
6576404edcSAsim Jamshed #define MSB16 0x8000
6676404edcSAsim Jamshed #define KEY_CACHE_LEN 96
6776404edcSAsim Jamshed 
6876404edcSAsim Jamshed 	uint32_t res = 0;
6976404edcSAsim Jamshed 	int i;
7076404edcSAsim Jamshed 	static int first = 1;
7176404edcSAsim Jamshed 	static uint32_t key_cache[KEY_CACHE_LEN] = {0};
7276404edcSAsim Jamshed 
7376404edcSAsim Jamshed 	if (first) {
7476404edcSAsim Jamshed 		BuildKeyCache(key_cache, KEY_CACHE_LEN);
7576404edcSAsim Jamshed 		first = 0;
7676404edcSAsim Jamshed 	}
7776404edcSAsim Jamshed 
7876404edcSAsim Jamshed 	for (i = 0; i < 32; i++) {
7976404edcSAsim Jamshed 		if (sip & MSB32)
8076404edcSAsim Jamshed 			res ^= key_cache[i];
8176404edcSAsim Jamshed 		sip <<= 1;
8276404edcSAsim Jamshed 	}
8376404edcSAsim Jamshed 	for (i = 0; i < 32; i++) {
8476404edcSAsim Jamshed 		if (dip & MSB32)
8576404edcSAsim Jamshed 			res ^= key_cache[32+i];
8676404edcSAsim Jamshed 		dip <<= 1;
8776404edcSAsim Jamshed 	}
8876404edcSAsim Jamshed 	for (i = 0; i < 16; i++) {
8976404edcSAsim Jamshed 		if (sp & MSB16)
9076404edcSAsim Jamshed 			res ^= key_cache[64+i];
9176404edcSAsim Jamshed 		sp <<= 1;
9276404edcSAsim Jamshed 	}
9376404edcSAsim Jamshed 	for (i = 0; i < 16; i++) {
9476404edcSAsim Jamshed 		if (dp & MSB16)
9576404edcSAsim Jamshed 			res ^= key_cache[80+i];
9676404edcSAsim Jamshed 		dp <<= 1;
9776404edcSAsim Jamshed 	}
9876404edcSAsim Jamshed 	return res;
9976404edcSAsim Jamshed }
10076404edcSAsim Jamshed /*-------------------------------------------------------------------*/
10176404edcSAsim Jamshed /* RSS redirection table is in the little endian byte order (intel)  */
10276404edcSAsim Jamshed /*                                                                   */
10376404edcSAsim Jamshed /* idx: 0 1 2 3 | 4 5 6 7 | 8 9 10 11 | 12 13 14 15 | 16 17 18 19 ...*/
10476404edcSAsim Jamshed /* val: 3 2 1 0 | 7 6 5 4 | 11 10 9 8 | 15 14 13 12 | 19 18 17 16 ...*/
10576404edcSAsim Jamshed /* qid = val % num_queues */
10676404edcSAsim Jamshed /*-------------------------------------------------------------------*/
107*d88f3b1dSYoungGyoun /*
108*d88f3b1dSYoungGyoun  * ixgbe (e.g., X520) : (Rx queue #) = (7 LS bits of RSS hash) mod N
109*d88f3b1dSYoungGyoun  * i40e (e.g., XL710) : (Rx queue #) = (9 LS bits of RSS hash) mod N
110*d88f3b1dSYoungGyoun  */
111*d88f3b1dSYoungGyoun /*-------------------------------------------------------------------*/
112*d88f3b1dSYoungGyoun #define RSS_BIT_MASK_IXGBE 0x0000007F
113*d88f3b1dSYoungGyoun #define RSS_BIT_MASK_I40E  0x000001FF
11476404edcSAsim Jamshed int
GetRSSCPUCore(in_addr_t sip,in_addr_t dip,in_port_t sp,in_port_t dp,int num_queues)11576404edcSAsim Jamshed GetRSSCPUCore(in_addr_t sip, in_addr_t dip,
116*d88f3b1dSYoungGyoun 			  in_port_t sp, in_port_t dp, int num_queues)
11776404edcSAsim Jamshed {
118*d88f3b1dSYoungGyoun 	uint32_t masked;
1198c9e1184SAsim Jamshed 	int endian_type = FetchEndianType();
12076404edcSAsim Jamshed 
121b88bd7d2SAsim Jamshed 	if (endian_type) {
122*d88f3b1dSYoungGyoun 		masked = GetRSSHash(sip, dip, sp, dp) & RSS_BIT_MASK_I40E;
12376404edcSAsim Jamshed 		static const uint32_t off[4] = {3, 1, -1, -3};
12476404edcSAsim Jamshed 		masked += off[masked & 0x3];
125b88bd7d2SAsim Jamshed 	}
126*d88f3b1dSYoungGyoun 	else
127*d88f3b1dSYoungGyoun 		masked = GetRSSHash(sip, dip, sp, dp) & RSS_BIT_MASK_IXGBE;
128b88bd7d2SAsim Jamshed 
12976404edcSAsim Jamshed 	return (masked % num_queues);
13076404edcSAsim Jamshed 
13176404edcSAsim Jamshed }
13276404edcSAsim Jamshed /*-------------------------------------------------------------*/
13376404edcSAsim Jamshed int
mystrtol(const char * nptr,int base)134c6a5549bSAsim Jamshed mystrtol(const char *nptr, int base)
135c6a5549bSAsim Jamshed {
136c6a5549bSAsim Jamshed 	int rval;
137c6a5549bSAsim Jamshed 	char *endptr;
138c6a5549bSAsim Jamshed 
139b88bd7d2SAsim Jamshed 	errno = 0;
140c6a5549bSAsim Jamshed 	rval = strtol(nptr, &endptr, 10);
141c6a5549bSAsim Jamshed 	/* check for strtol errors */
142c6a5549bSAsim Jamshed 	if ((errno == ERANGE && (rval == LONG_MAX ||
143c6a5549bSAsim Jamshed 				 rval == LONG_MIN))
144c6a5549bSAsim Jamshed 	    || (errno != 0 && rval == 0)) {
145c6a5549bSAsim Jamshed 		perror("strtol");
146c6a5549bSAsim Jamshed 		exit(EXIT_FAILURE);
147c6a5549bSAsim Jamshed 	}
148c6a5549bSAsim Jamshed 	if (endptr == nptr) {
149c6a5549bSAsim Jamshed 		fprintf(stderr, "Parsing strtol error!\n");
150c6a5549bSAsim Jamshed 		exit(EXIT_FAILURE);
151c6a5549bSAsim Jamshed 	}
152c6a5549bSAsim Jamshed 
153c6a5549bSAsim Jamshed 	return rval;
154c6a5549bSAsim Jamshed }
155c6a5549bSAsim Jamshed /*---------------------------------------------------------------*/
156c6a5549bSAsim Jamshed int
StrToArgs(char * str,int * argc,char ** argv,int max_argc)15776404edcSAsim Jamshed StrToArgs(char *str, int *argc, char **argv, int max_argc)
15876404edcSAsim Jamshed {
15976404edcSAsim Jamshed 
16076404edcSAsim Jamshed 	uint8_t single_quotes;
16176404edcSAsim Jamshed 	uint8_t double_quotes;
16276404edcSAsim Jamshed 	uint8_t delim;
16376404edcSAsim Jamshed 
16476404edcSAsim Jamshed 	single_quotes = 0;
16576404edcSAsim Jamshed 	double_quotes = 0;
16676404edcSAsim Jamshed 	delim = 1;
16776404edcSAsim Jamshed 
16876404edcSAsim Jamshed 	*argc = 0;
16976404edcSAsim Jamshed 
17076404edcSAsim Jamshed 	int i;
17176404edcSAsim Jamshed 	int len = strlen(str);
17276404edcSAsim Jamshed 	for (i = 0; i < len; i++) {
17376404edcSAsim Jamshed 
17476404edcSAsim Jamshed 		if (str[i] == '\'') {
17576404edcSAsim Jamshed 			if (single_quotes)
17676404edcSAsim Jamshed 				str[i] = '\0';
17776404edcSAsim Jamshed 			else
17876404edcSAsim Jamshed 				i++;
17976404edcSAsim Jamshed 			single_quotes = !single_quotes;
18076404edcSAsim Jamshed 			goto __non_space;
18176404edcSAsim Jamshed 		} else if (str[i] == '\"') {
18276404edcSAsim Jamshed 			if (double_quotes)
18376404edcSAsim Jamshed 				str[i] = '\0';
18476404edcSAsim Jamshed 			else
18576404edcSAsim Jamshed 				i++;
18676404edcSAsim Jamshed 			double_quotes = !double_quotes;
18776404edcSAsim Jamshed 			goto __non_space;
18876404edcSAsim Jamshed 		}
18976404edcSAsim Jamshed 
19076404edcSAsim Jamshed 		if (single_quotes || double_quotes)
19176404edcSAsim Jamshed 			continue;
19276404edcSAsim Jamshed 
19376404edcSAsim Jamshed 		if (isspace(str[i])) {
19476404edcSAsim Jamshed 			delim = 1;
19576404edcSAsim Jamshed 			str[i] = '\0';
19676404edcSAsim Jamshed 			continue;
19776404edcSAsim Jamshed 		}
19876404edcSAsim Jamshed __non_space:
19976404edcSAsim Jamshed 		if (delim == 1) {
20076404edcSAsim Jamshed 			delim = 0;
20176404edcSAsim Jamshed 			argv[(*argc)++] = &str[i];
20276404edcSAsim Jamshed 			if (*argc > max_argc)
20376404edcSAsim Jamshed 				break;
20476404edcSAsim Jamshed 		}
20576404edcSAsim Jamshed 	}
20676404edcSAsim Jamshed 
20776404edcSAsim Jamshed 	argv[*argc] = NULL;
20876404edcSAsim Jamshed 
20976404edcSAsim Jamshed 	return 0;
21076404edcSAsim Jamshed }
21176404edcSAsim Jamshed 
21276404edcSAsim Jamshed /*
21376404edcSAsim Jamshed xxHash - Fast Hash algorithm
21476404edcSAsim Jamshed Copyright (C) 2012-2015, Yann Collet
21576404edcSAsim Jamshed 
21676404edcSAsim Jamshed BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
21776404edcSAsim Jamshed 
21876404edcSAsim Jamshed Redistribution and use in source and binary forms, with or without
21976404edcSAsim Jamshed modification, are permitted provided that the following conditions are
22076404edcSAsim Jamshed met:
22176404edcSAsim Jamshed 
22276404edcSAsim Jamshed * Redistributions of source code must retain the above copyright
22376404edcSAsim Jamshed notice, this list of conditions and the following disclaimer.
22476404edcSAsim Jamshed * Redistributions in binary form must reproduce the above
22576404edcSAsim Jamshed copyright notice, this list of conditions and the following disclaimer
22676404edcSAsim Jamshed in the documentation and/or other materials provided with the
22776404edcSAsim Jamshed distribution.
22876404edcSAsim Jamshed 
22976404edcSAsim Jamshed THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23076404edcSAsim Jamshed "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23176404edcSAsim Jamshed LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23276404edcSAsim Jamshed A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23376404edcSAsim Jamshed OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23476404edcSAsim Jamshed SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23576404edcSAsim Jamshed LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23676404edcSAsim Jamshed DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23776404edcSAsim Jamshed THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23876404edcSAsim Jamshed (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23976404edcSAsim Jamshed OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24076404edcSAsim Jamshed 
24176404edcSAsim Jamshed You can contact the author at :
24276404edcSAsim Jamshed - xxHash source repository : https://github.com/Cyan4973/xxHash
24376404edcSAsim Jamshed */
24476404edcSAsim Jamshed 
24576404edcSAsim Jamshed 
24676404edcSAsim Jamshed 
24776404edcSAsim Jamshed 
24876404edcSAsim Jamshed /**************************************
24976404edcSAsim Jamshed *  Tuning parameters
25076404edcSAsim Jamshed **************************************/
25176404edcSAsim Jamshed /* Unaligned memory access is automatically enabled for "common" CPU, such as x86.
25276404edcSAsim Jamshed  * For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected.
25376404edcSAsim Jamshed  * If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance.
25476404edcSAsim Jamshed  * You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32).
25576404edcSAsim Jamshed  */
25676404edcSAsim Jamshed #if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
25776404edcSAsim Jamshed #  define XXH_USE_UNALIGNED_ACCESS 1
25876404edcSAsim Jamshed #endif
25976404edcSAsim Jamshed 
26076404edcSAsim Jamshed /* XXH_ACCEPT_NULL_INPUT_POINTER :
26176404edcSAsim Jamshed  * If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
26276404edcSAsim Jamshed  * When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
26376404edcSAsim Jamshed  * By default, this option is disabled. To enable it, uncomment below define :
26476404edcSAsim Jamshed  */
26576404edcSAsim Jamshed /* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
26676404edcSAsim Jamshed 
26776404edcSAsim Jamshed /* XXH_FORCE_NATIVE_FORMAT :
26876404edcSAsim Jamshed  * By default, xxHash library provides endian-independant Hash values, based on little-endian convention.
26976404edcSAsim Jamshed  * Results are therefore identical for little-endian and big-endian CPU.
27076404edcSAsim Jamshed  * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
27176404edcSAsim Jamshed  * Should endian-independance be of no importance for your application, you may set the #define below to 1.
27276404edcSAsim Jamshed  * It will improve speed for Big-endian CPU.
27376404edcSAsim Jamshed  * This option has no impact on Little_Endian CPU.
27476404edcSAsim Jamshed  */
27576404edcSAsim Jamshed #define XXH_FORCE_NATIVE_FORMAT 0
27676404edcSAsim Jamshed 
27776404edcSAsim Jamshed 
27876404edcSAsim Jamshed /**************************************
27976404edcSAsim Jamshed *  Compiler Specific Options
28076404edcSAsim Jamshed ***************************************/
28176404edcSAsim Jamshed #ifdef _MSC_VER    /* Visual Studio */
28276404edcSAsim Jamshed #  pragma warning(disable : 4127)      /* disable: C4127: conditional expression is constant */
28376404edcSAsim Jamshed #  define FORCE_INLINE static __forceinline
28476404edcSAsim Jamshed #else
28576404edcSAsim Jamshed #  if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
28676404edcSAsim Jamshed #    ifdef __GNUC__
28776404edcSAsim Jamshed #      define FORCE_INLINE static inline __attribute__((always_inline))
28876404edcSAsim Jamshed #    else
28976404edcSAsim Jamshed #      define FORCE_INLINE static inline
29076404edcSAsim Jamshed #    endif
29176404edcSAsim Jamshed #  else
29276404edcSAsim Jamshed #    define FORCE_INLINE static
29376404edcSAsim Jamshed #  endif /* __STDC_VERSION__ */
29476404edcSAsim Jamshed #endif
29576404edcSAsim Jamshed 
29676404edcSAsim Jamshed 
29776404edcSAsim Jamshed /**************************************
29876404edcSAsim Jamshed *  Basic Types
29976404edcSAsim Jamshed ***************************************/
30076404edcSAsim Jamshed #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
30176404edcSAsim Jamshed # include <stdint.h>
30276404edcSAsim Jamshed   typedef uint8_t  BYTE;
30376404edcSAsim Jamshed   typedef uint16_t U16;
30476404edcSAsim Jamshed   typedef uint32_t U32;
30576404edcSAsim Jamshed   typedef  int32_t S32;
30676404edcSAsim Jamshed   typedef uint64_t U64;
30776404edcSAsim Jamshed #else
30876404edcSAsim Jamshed   typedef unsigned char      BYTE;
30976404edcSAsim Jamshed   typedef unsigned short     U16;
31076404edcSAsim Jamshed   typedef unsigned int       U32;
31176404edcSAsim Jamshed   typedef   signed int       S32;
31276404edcSAsim Jamshed   typedef unsigned long long U64;
31376404edcSAsim Jamshed #endif
31476404edcSAsim Jamshed 
XXH_read32(const void * memPtr)31576404edcSAsim Jamshed static U32 XXH_read32(const void* memPtr)
31676404edcSAsim Jamshed {
31776404edcSAsim Jamshed     U32 val32;
31876404edcSAsim Jamshed     memcpy(&val32, memPtr, 4);
31976404edcSAsim Jamshed     return val32;
32076404edcSAsim Jamshed }
32176404edcSAsim Jamshed 
XXH_read64(const void * memPtr)32276404edcSAsim Jamshed static U64 XXH_read64(const void* memPtr)
32376404edcSAsim Jamshed {
32476404edcSAsim Jamshed     U64 val64;
32576404edcSAsim Jamshed     memcpy(&val64, memPtr, 8);
32676404edcSAsim Jamshed     return val64;
32776404edcSAsim Jamshed }
32876404edcSAsim Jamshed 
32976404edcSAsim Jamshed 
33076404edcSAsim Jamshed 
33176404edcSAsim Jamshed /******************************************
33276404edcSAsim Jamshed *  Compiler-specific Functions and Macros
33376404edcSAsim Jamshed ******************************************/
33476404edcSAsim Jamshed #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
33576404edcSAsim Jamshed 
33676404edcSAsim Jamshed /* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
33776404edcSAsim Jamshed #if defined(_MSC_VER)
33876404edcSAsim Jamshed #  define XXH_rotl32(x,r) _rotl(x,r)
33976404edcSAsim Jamshed #  define XXH_rotl64(x,r) _rotl64(x,r)
34076404edcSAsim Jamshed #else
34176404edcSAsim Jamshed #  define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
34276404edcSAsim Jamshed #  define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
34376404edcSAsim Jamshed #endif
34476404edcSAsim Jamshed 
34576404edcSAsim Jamshed #if defined(_MSC_VER)     /* Visual Studio */
34676404edcSAsim Jamshed #  define XXH_swap32 _byteswap_ulong
34776404edcSAsim Jamshed #  define XXH_swap64 _byteswap_uint64
34876404edcSAsim Jamshed #elif GCC_VERSION >= 403
34976404edcSAsim Jamshed #  define XXH_swap32 __builtin_bswap32
35076404edcSAsim Jamshed #  define XXH_swap64 __builtin_bswap64
35176404edcSAsim Jamshed #else
XXH_swap32(U32 x)35276404edcSAsim Jamshed static U32 XXH_swap32 (U32 x)
35376404edcSAsim Jamshed {
35476404edcSAsim Jamshed     return  ((x << 24) & 0xff000000 ) |
35576404edcSAsim Jamshed             ((x <<  8) & 0x00ff0000 ) |
35676404edcSAsim Jamshed             ((x >>  8) & 0x0000ff00 ) |
35776404edcSAsim Jamshed             ((x >> 24) & 0x000000ff );
35876404edcSAsim Jamshed }
XXH_swap64(U64 x)35976404edcSAsim Jamshed static U64 XXH_swap64 (U64 x)
36076404edcSAsim Jamshed {
36176404edcSAsim Jamshed     return  ((x << 56) & 0xff00000000000000ULL) |
36276404edcSAsim Jamshed             ((x << 40) & 0x00ff000000000000ULL) |
36376404edcSAsim Jamshed             ((x << 24) & 0x0000ff0000000000ULL) |
36476404edcSAsim Jamshed             ((x << 8)  & 0x000000ff00000000ULL) |
36576404edcSAsim Jamshed             ((x >> 8)  & 0x00000000ff000000ULL) |
36676404edcSAsim Jamshed             ((x >> 24) & 0x0000000000ff0000ULL) |
36776404edcSAsim Jamshed             ((x >> 40) & 0x000000000000ff00ULL) |
36876404edcSAsim Jamshed             ((x >> 56) & 0x00000000000000ffULL);
36976404edcSAsim Jamshed }
37076404edcSAsim Jamshed #endif
37176404edcSAsim Jamshed 
37276404edcSAsim Jamshed 
37376404edcSAsim Jamshed /***************************************
37476404edcSAsim Jamshed *  Architecture Macros
37576404edcSAsim Jamshed ***************************************/
37676404edcSAsim Jamshed typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
37776404edcSAsim Jamshed #ifndef XXH_CPU_LITTLE_ENDIAN   /* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example using a compiler switch */
37876404edcSAsim Jamshed static const int one = 1;
37976404edcSAsim Jamshed #   define XXH_CPU_LITTLE_ENDIAN   (*(const char*)(&one))
38076404edcSAsim Jamshed #endif
38176404edcSAsim Jamshed 
38276404edcSAsim Jamshed 
38376404edcSAsim Jamshed /*****************************
38476404edcSAsim Jamshed *  Memory reads
38576404edcSAsim Jamshed *****************************/
38676404edcSAsim Jamshed typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
38776404edcSAsim Jamshed 
XXH_readLE32_align(const void * ptr,XXH_endianess endian,XXH_alignment align)38876404edcSAsim Jamshed FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
38976404edcSAsim Jamshed {
39076404edcSAsim Jamshed     if (align==XXH_unaligned)
39176404edcSAsim Jamshed         return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
39276404edcSAsim Jamshed     else
39376404edcSAsim Jamshed         return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr);
39476404edcSAsim Jamshed }
39576404edcSAsim Jamshed 
XXH_readLE64_align(const void * ptr,XXH_endianess endian,XXH_alignment align)39676404edcSAsim Jamshed FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
39776404edcSAsim Jamshed {
39876404edcSAsim Jamshed     if (align==XXH_unaligned)
39976404edcSAsim Jamshed         return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
40076404edcSAsim Jamshed     else
40176404edcSAsim Jamshed         return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr);
40276404edcSAsim Jamshed }
40376404edcSAsim Jamshed 
40476404edcSAsim Jamshed /***************************************
40576404edcSAsim Jamshed *  Macros
40676404edcSAsim Jamshed ***************************************/
40776404edcSAsim Jamshed #define XXH_STATIC_ASSERT(c)   { enum { XXH_static_assert = 1/(!!(c)) }; }    /* use only *after* variable declarations */
40876404edcSAsim Jamshed 
40976404edcSAsim Jamshed 
41076404edcSAsim Jamshed /***************************************
41176404edcSAsim Jamshed *  Constants
41276404edcSAsim Jamshed ***************************************/
41376404edcSAsim Jamshed #define PRIME32_1   2654435761U
41476404edcSAsim Jamshed #define PRIME32_2   2246822519U
41576404edcSAsim Jamshed #define PRIME32_3   3266489917U
41676404edcSAsim Jamshed #define PRIME32_4    668265263U
41776404edcSAsim Jamshed #define PRIME32_5    374761393U
41876404edcSAsim Jamshed 
41976404edcSAsim Jamshed #define PRIME64_1 11400714785074694791ULL
42076404edcSAsim Jamshed #define PRIME64_2 14029467366897019727ULL
42176404edcSAsim Jamshed #define PRIME64_3  1609587929392839161ULL
42276404edcSAsim Jamshed #define PRIME64_4  9650029242287828579ULL
42376404edcSAsim Jamshed #define PRIME64_5  2870177450012600261ULL
42476404edcSAsim Jamshed 
42576404edcSAsim Jamshed 
42676404edcSAsim Jamshed /*****************************
42776404edcSAsim Jamshed *  Simple Hash Functions
42876404edcSAsim Jamshed *****************************/
XXH32_endian_align(const void * input,size_t len,U32 seed,XXH_endianess endian,XXH_alignment align)42976404edcSAsim Jamshed FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
43076404edcSAsim Jamshed {
43176404edcSAsim Jamshed     const BYTE* p = (const BYTE*)input;
43276404edcSAsim Jamshed     const BYTE* bEnd = p + len;
43376404edcSAsim Jamshed     U32 h32;
43476404edcSAsim Jamshed #define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
43576404edcSAsim Jamshed 
43676404edcSAsim Jamshed #ifdef XXH_ACCEPT_NULL_INPUT_POINTER
43776404edcSAsim Jamshed     if (p==NULL)
43876404edcSAsim Jamshed     {
43976404edcSAsim Jamshed         len=0;
44076404edcSAsim Jamshed         bEnd=p=(const BYTE*)(size_t)16;
44176404edcSAsim Jamshed     }
44276404edcSAsim Jamshed #endif
44376404edcSAsim Jamshed 
44476404edcSAsim Jamshed     if (len>=16)
44576404edcSAsim Jamshed     {
44676404edcSAsim Jamshed         const BYTE* const limit = bEnd - 16;
44776404edcSAsim Jamshed         U32 v1 = seed + PRIME32_1 + PRIME32_2;
44876404edcSAsim Jamshed         U32 v2 = seed + PRIME32_2;
44976404edcSAsim Jamshed         U32 v3 = seed + 0;
45076404edcSAsim Jamshed         U32 v4 = seed - PRIME32_1;
45176404edcSAsim Jamshed 
45276404edcSAsim Jamshed         do
45376404edcSAsim Jamshed         {
45476404edcSAsim Jamshed             v1 += XXH_get32bits(p) * PRIME32_2;
45576404edcSAsim Jamshed             v1 = XXH_rotl32(v1, 13);
45676404edcSAsim Jamshed             v1 *= PRIME32_1;
45776404edcSAsim Jamshed             p+=4;
45876404edcSAsim Jamshed             v2 += XXH_get32bits(p) * PRIME32_2;
45976404edcSAsim Jamshed             v2 = XXH_rotl32(v2, 13);
46076404edcSAsim Jamshed             v2 *= PRIME32_1;
46176404edcSAsim Jamshed             p+=4;
46276404edcSAsim Jamshed             v3 += XXH_get32bits(p) * PRIME32_2;
46376404edcSAsim Jamshed             v3 = XXH_rotl32(v3, 13);
46476404edcSAsim Jamshed             v3 *= PRIME32_1;
46576404edcSAsim Jamshed             p+=4;
46676404edcSAsim Jamshed             v4 += XXH_get32bits(p) * PRIME32_2;
46776404edcSAsim Jamshed             v4 = XXH_rotl32(v4, 13);
46876404edcSAsim Jamshed             v4 *= PRIME32_1;
46976404edcSAsim Jamshed             p+=4;
47076404edcSAsim Jamshed         }
47176404edcSAsim Jamshed         while (p<=limit);
47276404edcSAsim Jamshed 
47376404edcSAsim Jamshed         h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
47476404edcSAsim Jamshed     }
47576404edcSAsim Jamshed     else
47676404edcSAsim Jamshed     {
47776404edcSAsim Jamshed         h32  = seed + PRIME32_5;
47876404edcSAsim Jamshed     }
47976404edcSAsim Jamshed 
48076404edcSAsim Jamshed     h32 += (U32) len;
48176404edcSAsim Jamshed 
48276404edcSAsim Jamshed     while (p+4<=bEnd)
48376404edcSAsim Jamshed     {
48476404edcSAsim Jamshed         h32 += XXH_get32bits(p) * PRIME32_3;
48576404edcSAsim Jamshed         h32  = XXH_rotl32(h32, 17) * PRIME32_4 ;
48676404edcSAsim Jamshed         p+=4;
48776404edcSAsim Jamshed     }
48876404edcSAsim Jamshed 
48976404edcSAsim Jamshed     while (p<bEnd)
49076404edcSAsim Jamshed     {
49176404edcSAsim Jamshed         h32 += (*p) * PRIME32_5;
49276404edcSAsim Jamshed         h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
49376404edcSAsim Jamshed         p++;
49476404edcSAsim Jamshed     }
49576404edcSAsim Jamshed 
49676404edcSAsim Jamshed     h32 ^= h32 >> 15;
49776404edcSAsim Jamshed     h32 *= PRIME32_2;
49876404edcSAsim Jamshed     h32 ^= h32 >> 13;
49976404edcSAsim Jamshed     h32 *= PRIME32_3;
50076404edcSAsim Jamshed     h32 ^= h32 >> 16;
50176404edcSAsim Jamshed 
50276404edcSAsim Jamshed     return h32;
50376404edcSAsim Jamshed }
50476404edcSAsim Jamshed 
50576404edcSAsim Jamshed 
XXH32(const void * input,size_t len,unsigned seed)50676404edcSAsim Jamshed unsigned XXH32 (const void* input, size_t len, unsigned seed)
50776404edcSAsim Jamshed {
50876404edcSAsim Jamshed #if 0
50976404edcSAsim Jamshed     /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
51076404edcSAsim Jamshed     XXH32_state_t state;
51176404edcSAsim Jamshed     XXH32_reset(&state, seed);
51276404edcSAsim Jamshed     XXH32_update(&state, input, len);
51376404edcSAsim Jamshed     return XXH32_digest(&state);
51476404edcSAsim Jamshed #else
51576404edcSAsim Jamshed     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
51676404edcSAsim Jamshed 
51776404edcSAsim Jamshed #  if !defined(XXH_USE_UNALIGNED_ACCESS)
51876404edcSAsim Jamshed     if ((((size_t)input) & 3) == 0)   /* Input is 4-bytes aligned, leverage the speed benefit */
51976404edcSAsim Jamshed     {
52076404edcSAsim Jamshed         if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
52176404edcSAsim Jamshed             return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
52276404edcSAsim Jamshed         else
52376404edcSAsim Jamshed             return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
52476404edcSAsim Jamshed     }
52576404edcSAsim Jamshed #  endif
52676404edcSAsim Jamshed 
52776404edcSAsim Jamshed     if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
52876404edcSAsim Jamshed         return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
52976404edcSAsim Jamshed     else
53076404edcSAsim Jamshed         return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
53176404edcSAsim Jamshed #endif
53276404edcSAsim Jamshed }
53376404edcSAsim Jamshed 
XXH64_endian_align(const void * input,size_t len,U64 seed,XXH_endianess endian,XXH_alignment align)53476404edcSAsim Jamshed FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
53576404edcSAsim Jamshed {
53676404edcSAsim Jamshed     const BYTE* p = (const BYTE*)input;
53776404edcSAsim Jamshed     const BYTE* bEnd = p + len;
53876404edcSAsim Jamshed     U64 h64;
53976404edcSAsim Jamshed #define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
54076404edcSAsim Jamshed 
54176404edcSAsim Jamshed #ifdef XXH_ACCEPT_NULL_INPUT_POINTER
54276404edcSAsim Jamshed     if (p==NULL)
54376404edcSAsim Jamshed     {
54476404edcSAsim Jamshed         len=0;
54576404edcSAsim Jamshed         bEnd=p=(const BYTE*)(size_t)32;
54676404edcSAsim Jamshed     }
54776404edcSAsim Jamshed #endif
54876404edcSAsim Jamshed 
54976404edcSAsim Jamshed     if (len>=32)
55076404edcSAsim Jamshed     {
55176404edcSAsim Jamshed         const BYTE* const limit = bEnd - 32;
55276404edcSAsim Jamshed         U64 v1 = seed + PRIME64_1 + PRIME64_2;
55376404edcSAsim Jamshed         U64 v2 = seed + PRIME64_2;
55476404edcSAsim Jamshed         U64 v3 = seed + 0;
55576404edcSAsim Jamshed         U64 v4 = seed - PRIME64_1;
55676404edcSAsim Jamshed 
55776404edcSAsim Jamshed         do
55876404edcSAsim Jamshed         {
55976404edcSAsim Jamshed             v1 += XXH_get64bits(p) * PRIME64_2;
56076404edcSAsim Jamshed             p+=8;
56176404edcSAsim Jamshed             v1 = XXH_rotl64(v1, 31);
56276404edcSAsim Jamshed             v1 *= PRIME64_1;
56376404edcSAsim Jamshed             v2 += XXH_get64bits(p) * PRIME64_2;
56476404edcSAsim Jamshed             p+=8;
56576404edcSAsim Jamshed             v2 = XXH_rotl64(v2, 31);
56676404edcSAsim Jamshed             v2 *= PRIME64_1;
56776404edcSAsim Jamshed             v3 += XXH_get64bits(p) * PRIME64_2;
56876404edcSAsim Jamshed             p+=8;
56976404edcSAsim Jamshed             v3 = XXH_rotl64(v3, 31);
57076404edcSAsim Jamshed             v3 *= PRIME64_1;
57176404edcSAsim Jamshed             v4 += XXH_get64bits(p) * PRIME64_2;
57276404edcSAsim Jamshed             p+=8;
57376404edcSAsim Jamshed             v4 = XXH_rotl64(v4, 31);
57476404edcSAsim Jamshed             v4 *= PRIME64_1;
57576404edcSAsim Jamshed         }
57676404edcSAsim Jamshed         while (p<=limit);
57776404edcSAsim Jamshed 
57876404edcSAsim Jamshed         h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
57976404edcSAsim Jamshed 
58076404edcSAsim Jamshed         v1 *= PRIME64_2;
58176404edcSAsim Jamshed         v1 = XXH_rotl64(v1, 31);
58276404edcSAsim Jamshed         v1 *= PRIME64_1;
58376404edcSAsim Jamshed         h64 ^= v1;
58476404edcSAsim Jamshed         h64 = h64 * PRIME64_1 + PRIME64_4;
58576404edcSAsim Jamshed 
58676404edcSAsim Jamshed         v2 *= PRIME64_2;
58776404edcSAsim Jamshed         v2 = XXH_rotl64(v2, 31);
58876404edcSAsim Jamshed         v2 *= PRIME64_1;
58976404edcSAsim Jamshed         h64 ^= v2;
59076404edcSAsim Jamshed         h64 = h64 * PRIME64_1 + PRIME64_4;
59176404edcSAsim Jamshed 
59276404edcSAsim Jamshed         v3 *= PRIME64_2;
59376404edcSAsim Jamshed         v3 = XXH_rotl64(v3, 31);
59476404edcSAsim Jamshed         v3 *= PRIME64_1;
59576404edcSAsim Jamshed         h64 ^= v3;
59676404edcSAsim Jamshed         h64 = h64 * PRIME64_1 + PRIME64_4;
59776404edcSAsim Jamshed 
59876404edcSAsim Jamshed         v4 *= PRIME64_2;
59976404edcSAsim Jamshed         v4 = XXH_rotl64(v4, 31);
60076404edcSAsim Jamshed         v4 *= PRIME64_1;
60176404edcSAsim Jamshed         h64 ^= v4;
60276404edcSAsim Jamshed         h64 = h64 * PRIME64_1 + PRIME64_4;
60376404edcSAsim Jamshed     }
60476404edcSAsim Jamshed     else
60576404edcSAsim Jamshed     {
60676404edcSAsim Jamshed         h64  = seed + PRIME64_5;
60776404edcSAsim Jamshed     }
60876404edcSAsim Jamshed 
60976404edcSAsim Jamshed     h64 += (U64) len;
61076404edcSAsim Jamshed 
61176404edcSAsim Jamshed     while (p+8<=bEnd)
61276404edcSAsim Jamshed     {
61376404edcSAsim Jamshed         U64 k1 = XXH_get64bits(p);
61476404edcSAsim Jamshed         k1 *= PRIME64_2;
61576404edcSAsim Jamshed         k1 = XXH_rotl64(k1,31);
61676404edcSAsim Jamshed         k1 *= PRIME64_1;
61776404edcSAsim Jamshed         h64 ^= k1;
61876404edcSAsim Jamshed         h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
61976404edcSAsim Jamshed         p+=8;
62076404edcSAsim Jamshed     }
62176404edcSAsim Jamshed 
62276404edcSAsim Jamshed     if (p+4<=bEnd)
62376404edcSAsim Jamshed     {
62476404edcSAsim Jamshed         h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
62576404edcSAsim Jamshed         h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
62676404edcSAsim Jamshed         p+=4;
62776404edcSAsim Jamshed     }
62876404edcSAsim Jamshed 
62976404edcSAsim Jamshed     while (p<bEnd)
63076404edcSAsim Jamshed     {
63176404edcSAsim Jamshed         h64 ^= (*p) * PRIME64_5;
63276404edcSAsim Jamshed         h64 = XXH_rotl64(h64, 11) * PRIME64_1;
63376404edcSAsim Jamshed         p++;
63476404edcSAsim Jamshed     }
63576404edcSAsim Jamshed 
63676404edcSAsim Jamshed     h64 ^= h64 >> 33;
63776404edcSAsim Jamshed     h64 *= PRIME64_2;
63876404edcSAsim Jamshed     h64 ^= h64 >> 29;
63976404edcSAsim Jamshed     h64 *= PRIME64_3;
64076404edcSAsim Jamshed     h64 ^= h64 >> 32;
64176404edcSAsim Jamshed 
64276404edcSAsim Jamshed     return h64;
64376404edcSAsim Jamshed }
64476404edcSAsim Jamshed 
64576404edcSAsim Jamshed 
XXH64(const void * input,size_t len,unsigned long long seed)64676404edcSAsim Jamshed unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)
64776404edcSAsim Jamshed {
64876404edcSAsim Jamshed #if 0
64976404edcSAsim Jamshed     /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
65076404edcSAsim Jamshed     XXH64_state_t state;
65176404edcSAsim Jamshed     XXH64_reset(&state, seed);
65276404edcSAsim Jamshed     XXH64_update(&state, input, len);
65376404edcSAsim Jamshed     return XXH64_digest(&state);
65476404edcSAsim Jamshed #else
65576404edcSAsim Jamshed     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
65676404edcSAsim Jamshed 
65776404edcSAsim Jamshed #  if !defined(XXH_USE_UNALIGNED_ACCESS)
65876404edcSAsim Jamshed     if ((((size_t)input) & 7)==0)   /* Input is aligned, let's leverage the speed advantage */
65976404edcSAsim Jamshed     {
66076404edcSAsim Jamshed         if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
66176404edcSAsim Jamshed             return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
66276404edcSAsim Jamshed         else
66376404edcSAsim Jamshed             return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
66476404edcSAsim Jamshed     }
66576404edcSAsim Jamshed #  endif
66676404edcSAsim Jamshed 
66776404edcSAsim Jamshed     if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
66876404edcSAsim Jamshed         return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
66976404edcSAsim Jamshed     else
67076404edcSAsim Jamshed         return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
67176404edcSAsim Jamshed #endif
67276404edcSAsim Jamshed }
67376404edcSAsim Jamshed 
674