summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builddefs/build_test.mk1
-rw-r--r--builddefs/common_features.mk6
-rw-r--r--builddefs/testlist.mk1
-rw-r--r--lib/fnv/Makefile304
-rw-r--r--lib/fnv/README158
-rw-r--r--lib/fnv/fnv.h249
-rw-r--r--lib/fnv/fnv32.c467
-rw-r--r--lib/fnv/fnv64.c591
-rw-r--r--lib/fnv/hash_32.c156
-rw-r--r--lib/fnv/hash_32a.c144
-rw-r--r--lib/fnv/hash_64.c312
-rw-r--r--lib/fnv/hash_64a.c291
-rw-r--r--lib/fnv/have_ulong64.c58
-rw-r--r--lib/fnv/longlong.h18
-rw-r--r--lib/fnv/qmk_fnv_type_validation.c14
-rw-r--r--lib/fnv/test_fnv.c2237
-rw-r--r--quantum/wear_leveling/tests/backing_mocks.cpp154
-rw-r--r--quantum/wear_leveling/tests/backing_mocks.hpp210
-rw-r--r--quantum/wear_leveling/tests/rules.mk66
-rw-r--r--quantum/wear_leveling/tests/testlist.mk6
-rw-r--r--quantum/wear_leveling/tests/wear_leveling_2byte.cpp228
-rw-r--r--quantum/wear_leveling/tests/wear_leveling_2byte_optimized_writes.cpp295
-rw-r--r--quantum/wear_leveling/tests/wear_leveling_4byte.cpp193
-rw-r--r--quantum/wear_leveling/tests/wear_leveling_8byte.cpp178
-rw-r--r--quantum/wear_leveling/tests/wear_leveling_general.cpp204
-rw-r--r--quantum/wear_leveling/wear_leveling.c779
-rw-r--r--quantum/wear_leveling/wear_leveling.h54
-rw-r--r--quantum/wear_leveling/wear_leveling_internal.h145
28 files changed, 7519 insertions, 0 deletions
diff --git a/builddefs/build_test.mk b/builddefs/build_test.mk
index 834184f221..bd9b372c33 100644
--- a/builddefs/build_test.mk
+++ b/builddefs/build_test.mk
@@ -63,6 +63,7 @@ include $(TMK_PATH)/protocol.mk
63include $(QUANTUM_PATH)/debounce/tests/rules.mk 63include $(QUANTUM_PATH)/debounce/tests/rules.mk
64include $(QUANTUM_PATH)/encoder/tests/rules.mk 64include $(QUANTUM_PATH)/encoder/tests/rules.mk
65include $(QUANTUM_PATH)/sequencer/tests/rules.mk 65include $(QUANTUM_PATH)/sequencer/tests/rules.mk
66include $(QUANTUM_PATH)/wear_leveling/tests/rules.mk
66include $(PLATFORM_PATH)/test/rules.mk 67include $(PLATFORM_PATH)/test/rules.mk
67ifneq ($(filter $(FULL_TESTS),$(TEST)),) 68ifneq ($(filter $(FULL_TESTS),$(TEST)),)
68include $(BUILDDEFS_PATH)/build_full_test.mk 69include $(BUILDDEFS_PATH)/build_full_test.mk
diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk
index b9ee0a30a7..552171fe68 100644
--- a/builddefs/common_features.mk
+++ b/builddefs/common_features.mk
@@ -650,6 +650,12 @@ ifeq ($(strip $(CRC_ENABLE)), yes)
650 SRC += crc.c 650 SRC += crc.c
651endif 651endif
652 652
653ifeq ($(strip $(FNV_ENABLE)), yes)
654 OPT_DEFS += -DFNV_ENABLE
655 VPATH += $(LIB_PATH)/fnv
656 SRC += qmk_fnv_type_validation.c hash_32a.c hash_64a.c
657endif
658
653ifeq ($(strip $(HAPTIC_ENABLE)),yes) 659ifeq ($(strip $(HAPTIC_ENABLE)),yes)
654 COMMON_VPATH += $(DRIVER_PATH)/haptic 660 COMMON_VPATH += $(DRIVER_PATH)/haptic
655 661
diff --git a/builddefs/testlist.mk b/builddefs/testlist.mk
index b8d22bce80..8a30a44972 100644
--- a/builddefs/testlist.mk
+++ b/builddefs/testlist.mk
@@ -4,6 +4,7 @@ FULL_TESTS := $(notdir $(TEST_LIST))
4include $(QUANTUM_PATH)/debounce/tests/testlist.mk 4include $(QUANTUM_PATH)/debounce/tests/testlist.mk
5include $(QUANTUM_PATH)/encoder/tests/testlist.mk 5include $(QUANTUM_PATH)/encoder/tests/testlist.mk
6include $(QUANTUM_PATH)/sequencer/tests/testlist.mk 6include $(QUANTUM_PATH)/sequencer/tests/testlist.mk
7include $(QUANTUM_PATH)/wear_leveling/tests/testlist.mk
7include $(PLATFORM_PATH)/test/testlist.mk 8include $(PLATFORM_PATH)/test/testlist.mk
8 9
9define VALIDATE_TEST_LIST 10define VALIDATE_TEST_LIST
diff --git a/lib/fnv/Makefile b/lib/fnv/Makefile
new file mode 100644
index 0000000000..c0673ded40
--- /dev/null
+++ b/lib/fnv/Makefile
@@ -0,0 +1,304 @@
1#!/bin/make
2#
3# hash - makefile for FNV hash tools
4#
5# @(#) $Revision: 5.2 $
6# @(#) $Id: Makefile,v 5.2 2012/03/21 01:42:15 chongo Exp $
7# @(#) $Source: /usr/local/src/cmd/fnv/RCS/Makefile,v $
8#
9# See:
10# http://www.isthe.com/chongo/tech/comp/fnv/index.html
11#
12# for the most up to date copy of this code and the FNV hash home page.
13#
14# Please do not copyright this code. This code is in the public domain.
15#
16# LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
18# EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22# PERFORMANCE OF THIS SOFTWARE.
23#
24# By:
25# chongo <Landon Curt Noll> /\oo/\
26# http://www.isthe.com/chongo/
27#
28# Share and Enjoy! :-)
29
30# make tools
31#
32SHELL= /bin/sh
33CFLAGS= -O3 -g3
34#CFLAGS= -O2 -g3
35#CC= cc
36AR= ar
37TAR= tar
38EGREP= egrep
39GZIP_BIN= gzip
40INSTALL= install
41
42# If your system needs ranlib use:
43# RANLIB= ranlib
44# otherwise use:
45# RANLIB= :
46#
47#RANLIB= ranlib
48RANLIB= :
49
50# where to install things
51#
52DESTBIN= /usr/local/bin
53DESTLIB= /usr/local/lib
54DESTINC= /usr/local/include
55
56# what to build
57#
58SRC= hash_32.c hash_32a.c hash_64.c hash_64a.c \
59 fnv32.c fnv64.c \
60 have_ulong64.c test_fnv.c
61NO64BIT_SRC= no64bit_fnv64.c no64bit_hash_64.c \
62 no64bit_hash_64a.c no64bit_test_fnv.c
63HSRC= fnv.h \
64 longlong.h
65ALL= ${SRC} ${HSRC} \
66 README Makefile
67PROGS= fnv032 fnv064 fnv132 fnv164 fnv1a32 fnv1a64
68OBSOLETE_PROGS= fnv0_32 fnv0_64 fnv1_32 fnv1_64 fnv1a_32 fnv1a_64
69NO64BIT_PROGS= no64bit_fnv064 no64bit_fnv164 no64bit_fnv1a64
70LIBS= libfnv.a
71LIBOBJ= hash_32.o hash_64.o hash_32a.o hash_64a.o test_fnv.o
72NO64BIT_OBJ= no64bit_fnv64.o no64bit_hash_64.o \
73 no64bit_hash_64a.o no64bit_test_fnv.o
74OTHEROBJ= fnv32.o fnv64.o
75TARGETS= ${LIBOBJ} ${LIBS} ${PROGS}
76
77# default rule
78#
79all: ${TARGETS}
80
81# things to build
82#
83hash_32.o: hash_32.c longlong.h fnv.h
84 ${CC} ${CFLAGS} hash_32.c -c
85
86hash_64.o: hash_64.c longlong.h fnv.h
87 ${CC} ${CFLAGS} hash_64.c -c
88
89hash_32a.o: hash_32a.c longlong.h fnv.h
90 ${CC} ${CFLAGS} hash_32a.c -c
91
92hash_64a.o: hash_64a.c longlong.h fnv.h
93 ${CC} ${CFLAGS} hash_64a.c -c
94
95test_fnv.o: test_fnv.c longlong.h fnv.h
96 ${CC} ${CFLAGS} test_fnv.c -c
97
98fnv32.o: fnv32.c longlong.h fnv.h
99 ${CC} ${CFLAGS} fnv32.c -c
100
101fnv032: fnv32.o libfnv.a
102 ${CC} fnv32.o libfnv.a -o fnv032
103
104fnv64.o: fnv64.c longlong.h fnv.h
105 ${CC} ${CFLAGS} fnv64.c -c
106
107fnv064: fnv64.o libfnv.a
108 ${CC} fnv64.o libfnv.a -o fnv064
109
110libfnv.a: ${LIBOBJ}
111 rm -f $@
112 ${AR} rv $@ ${LIBOBJ}
113 ${RANLIB} $@
114
115fnv132: fnv032
116 -rm -f $@
117 -cp -f $? $@
118
119fnv1a32: fnv032
120 -rm -f $@
121 -cp -f $? $@
122
123fnv164: fnv064
124 -rm -f $@
125 -cp -f $? $@
126
127fnv1a64: fnv064
128 -rm -f $@
129 -cp -f $? $@
130
131longlong.h: have_ulong64.c Makefile
132 -@rm -f have_ulong64 have_ulong64.o ll_tmp longlong.h
133 @echo 'forming longlong.h'
134 @echo '/*' > longlong.h
135 @echo ' * DO NOT EDIT -- generated by the Makefile' >> longlong.h
136 @echo ' */' >> longlong.h
137 @echo '' >> longlong.h
138 @echo '#if !defined(__LONGLONG_H__)' >> longlong.h
139 @echo '#define __LONGLONG_H__' >> longlong.h
140 @echo '' >> longlong.h
141 @echo '/* do we have/want to use a long long type? */' >> longlong.h
142 -@rm -f have_ulong64.o have_ulong64
143 -@${CC} ${CFLAGS} have_ulong64.c -c 2>/dev/null; true
144 -@${CC} ${CFLAGS} have_ulong64.o -o have_ulong64 2>/dev/null; true
145 -@${SHELL} -c "./have_ulong64 > ll_tmp 2>/dev/null" \
146 >/dev/null 2>&1; true
147 -@if [ -s ll_tmp ]; then \
148 cat ll_tmp >> longlong.h; \
149 else \
150 echo '#undef HAVE_64BIT_LONG_LONG /* no */' >> longlong.h; \
151 fi
152 @echo '' >> longlong.h
153 @echo '/*' >> longlong.h
154 @echo ' * NO64BIT_LONG_LONG undef HAVE_64BIT_LONG_LONG' >> longlong.h
155 @echo ' */' >> longlong.h
156 @echo '#if defined(NO64BIT_LONG_LONG)' >> longlong.h
157 @echo '#undef HAVE_64BIT_LONG_LONG' >> longlong.h
158 @echo '#endif /* NO64BIT_LONG_LONG */' >> longlong.h
159 @echo '' >> longlong.h
160 @echo '#endif /* !__LONGLONG_H__ */' >> longlong.h
161 -@rm -f have_ulong64 have_ulong64.o ll_tmp
162 @echo 'longlong.h formed'
163
164# utilities
165#
166install: all
167 -@if [ -d "${DESTBIN}" ]; then \
168 echo " mkdir -p ${DESTBIN}"; \
169 mkdir -p ${DESTBIN}; \
170 fi
171 -@if [ -d "${DESTLIB}" ]; then \
172 echo " mkdir -p ${DESTLIB}"; \
173 mkdir -p ${DESTLIB}; \
174 fi
175 -@if [ -d "${DESTINC}" ]; then \
176 echo " mkdir -p ${DESTINC}"; \
177 mkdir -p ${DESTINC}; \
178 fi
179 ${INSTALL} -m 0755 ${PROGS} ${DESTBIN}
180 ${INSTALL} -m 0644 ${LIBS} ${DESTLIB}
181 ${RANLIB} ${DESTLIB}/libfnv.a
182 ${INSTALL} -m 0644 ${HSRC} ${DESTINC}
183 @# remove osolete programs
184 for i in ${OBSOLETE_PROGS}; do \
185 if [ -f "${DESTBIN}/$$i" ]; then \
186 echo "rm -f ${DESTBIN}/$$i"; \
187 rm -f "${DESTBIN}/$$i"; \
188 fi; \
189 done
190
191clean:
192 -rm -f have_ulong64 have_ulong64.o ll_tmp ll_tmp2 longlong.h
193 -rm -f ${LIBOBJ}
194 -rm -f ${OTHEROBJ}
195
196clobber: clean
197 -rm -f ${TARGETS}
198 -rm -f ${OBSOLETE_PROGS} lltmp lltmp2 ll_tmp
199 -rm -f ${NO64BIT_SRC}
200 -rm -f ${NO64BIT_OBJ}
201 -rm -f ${NO64BIT_PROGS}
202 -rm -f vector.c
203
204check: ${PROGS}
205 @echo -n "FNV-0 32 bit tests: "
206 @./fnv032 -t 1 -v
207 @echo -n "FNV-1 32 bit tests: "
208 @./fnv132 -t 1 -v
209 @echo -n "FNV-1a 32 bit tests: "
210 @./fnv1a32 -t 1 -v
211 @echo -n "FNV-0 64 bit tests: "
212 @./fnv064 -t 1 -v
213 @echo -n "FNV-1 64 bit tests: "
214 @./fnv164 -t 1 -v
215 @echo -n "FNV-1a 64 bit tests: "
216 @./fnv1a64 -t 1 -v
217
218###############################
219# generate test vector source #
220###############################
221
222no64bit_fnv64.c: fnv64.c
223 -rm -f $@
224 -cp -f $? $@
225
226no64bit_hash_64.c: hash_64.c
227 -rm -f $@
228 -cp -f $? $@
229
230no64bit_hash_64a.c: hash_64a.c
231 -rm -f $@
232 -cp -f $? $@
233
234no64bit_test_fnv.c: test_fnv.c
235 -rm -f $@
236 -cp -f $? $@
237
238no64bit_fnv64.o: no64bit_fnv64.c longlong.h fnv.h
239 ${CC} ${CFLAGS} -DNO64BIT_LONG_LONG no64bit_fnv64.c -c
240
241no64bit_hash_64.o: no64bit_hash_64.c longlong.h fnv.h
242 ${CC} ${CFLAGS} -DNO64BIT_LONG_LONG no64bit_hash_64.c -c
243
244no64bit_hash_64a.o: no64bit_hash_64a.c longlong.h fnv.h
245 ${CC} ${CFLAGS} -DNO64BIT_LONG_LONG no64bit_hash_64a.c -c
246
247no64bit_test_fnv.o: no64bit_test_fnv.c longlong.h fnv.h
248 ${CC} ${CFLAGS} -DNO64BIT_LONG_LONG no64bit_test_fnv.c -c
249
250no64bit_fnv064: no64bit_fnv64.o no64bit_hash_64.o \
251 no64bit_hash_64a.o no64bit_test_fnv.o
252 ${CC} ${CFLAGS} no64bit_fnv64.o no64bit_hash_64.o \
253 no64bit_hash_64a.o no64bit_test_fnv.o -o $@
254
255no64bit_fnv164: no64bit_fnv064
256 -rm -f $@
257 -cp -f $? $@
258
259no64bit_fnv1a64: no64bit_fnv064
260 -rm -f $@
261 -cp -f $? $@
262
263vector.c: ${PROGS} ${NO64BIT_PROGS}
264 -rm -f $@
265 echo '/* start of output generated by make $@ */' >> $@
266 echo '' >> $@
267 #@
268 echo '/* FNV-0 32 bit test vectors */' >> $@
269 ./fnv032 -t 0 >> $@
270 echo '' >> $@
271 #@
272 echo '/* FNV-1 32 bit test vectors */' >> $@
273 ./fnv132 -t 0 >> $@
274 echo '' >> $@
275 #@
276 echo '/* FNV-1a 32 bit test vectors */' >> $@
277 ./fnv1a32 -t 0 >> $@
278 echo '' >> $@
279 #@
280 echo '/* FNV-0 64 bit test vectors */' >> $@
281 echo '#if defined(HAVE_64BIT_LONG_LONG)' >> $@
282 ./fnv064 -t 0 >> $@
283 echo '#else /* HAVE_64BIT_LONG_LONG */' >> $@
284 ./no64bit_fnv064 -t 0 >> $@
285 echo '#endif /* HAVE_64BIT_LONG_LONG */' >> $@
286 echo '' >> $@
287 #@
288 echo '/* FNV-1 64 bit test vectors */' >> $@
289 echo '#if defined(HAVE_64BIT_LONG_LONG)' >> $@
290 ./fnv164 -t 0 >> $@
291 echo '#else /* HAVE_64BIT_LONG_LONG */' >> $@
292 ./no64bit_fnv164 -t 0 >> $@
293 echo '#endif /* HAVE_64BIT_LONG_LONG */' >> $@
294 echo '' >> $@
295 #@
296 echo '/* FNV-1a 64 bit test vectors */' >> $@
297 echo '#if defined(HAVE_64BIT_LONG_LONG)' >> $@
298 ./fnv1a64 -t 0 >> $@
299 echo '#else /* HAVE_64BIT_LONG_LONG */' >> $@
300 ./no64bit_fnv1a64 -t 0 >> $@
301 echo '#endif /* HAVE_64BIT_LONG_LONG */' >> $@
302 echo '' >> $@
303 #@
304 echo '/* end of output generated by make $@ */' >> $@
diff --git a/lib/fnv/README b/lib/fnv/README
new file mode 100644
index 0000000000..60aa9aaf61
--- /dev/null
+++ b/lib/fnv/README
@@ -0,0 +1,158 @@
1#=====================#
2# Fowler/Noll/Vo hash #
3#=====================#
4
5The basis of this hash algorithm was taken from an idea sent
6as reviewer comments to the IEEE POSIX P1003.2 committee by:
7
8 Phong Vo (http://www.research.att.com/info/kpv)
9 Glenn Fowler (http://www.research.att.com/~gsf/)
10
11In a subsequent ballot round:
12
13 Landon Curt Noll (http://www.isthe.com/chongo)
14
15improved on their algorithm. Some people tried this hash
16and found that it worked rather well. In an EMail message
17to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
18
19FNV hashes are designed to be fast while maintaining a low
20collision rate. The FNV speed allows one to quickly hash lots
21of data while maintaining a reasonable collision rate. See:
22
23 http://www.isthe.com/chongo/tech/comp/fnv/index.html
24
25for more details as well as other forms of the FNV hash.
26Comments, questions, bug fixes and suggestions welcome at
27the address given in the above URL.
28
29
30#==================#
31# FNV hash utility #
32#==================#
33
34Two hash utilities (32 bit and 64 bit) are provided:
35
36 fnv032 [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]
37 fnv132 [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]
38 fnv1a32 [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]
39
40 fnv064 [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]
41 fnv164 [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]
42 fnv1a64 [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]
43
44 -b bcnt mask off all but the lower bcnt bits (default: 32)
45 -m multiple hashes, one per line for each arg
46 -s hash arg as a string (ignoring terminating NUL bytes)
47 -t code 0 ==> generate test vectors, 1 ==> test FNV hash
48 -v verbose mode, print arg after hash (implies -m)
49 arg string (if -s was given) or filename (default stdin)
50
51The fnv032, fnv064 implement the historic FNV-0 hash.
52The fnv132, fnv164 implement the recommended FNV-1 hash.
53The fnv1a32, fnv1a64 implement the recommended FNV-1a hash.
54
55This is the original historic FNV algorithm with a 0 offset basis.
56It is recommended that FNV-1, with a non-0 offset basis be used instead.
57
58To test FNV hashes, try:
59
60 fnv032 -t 1 -v
61 fnv132 -t 1 -v
62 fnv1a32 -t 1 -v
63
64 fnv064 -t 1 -v
65 fnv164 -t 1 -v
66 fnv1a64 -t 1 -v
67
68If you are compiling, try:
69
70 make check
71
72
73#==================#
74# FNV hash library #
75#==================#
76
77The libfnv.a library implements both a 32 bit and a 64 bit FNV hash
78on collections of bytes, a NUL terminated strings or on an open file
79descriptor.
80
81Here is the 32 bit FNV 1 hash:
82
83 Fnv32_t fnv_32_buf(void *buf, int len, Fnv32_t hval); /* byte buf */
84 Fnv32_t fnv_32_str(char *string, Fnv32_t hval); /* string */
85
86Here is the 32 bit FNV 1a hash:
87
88 Fnv32_t fnv_32a_buf(void *buf, int len, Fnv32_t hval); /* byte buf */
89 Fnv32_t fnv_32a_str(char *string, Fnv32_t hval); /* string */
90
91Here is the 64 bit FNV 1 hash:
92
93 Fnv64_t fnv_64_buf(void *buf, int len, Fnv64_t hval); /* byte buf */
94 Fnv64_t fnv_64_str(char *string, Fnv64_t hval); /* string */
95
96Here is the 64 bit FNV 1a hash:
97
98 Fnv64_t fnv_64a_buf(void *buf, int len, Fnv64_t hval); /* byte buf */
99 Fnv64_t fnv_64a_str(char *string, Fnv64_t hval); /* string */
100
101On the first call to a hash function, one must supply the initial basis
102that is appropriate for the hash in question:
103
104 FNV-0: (not recommended)
105
106 FNV0_32_INIT /* 32 bit FNV-0 initial basis */
107 FNV0_64_INIT /* 64 bit FNV-0 initial basis */
108
109 FNV-1:
110
111 FNV1_32_INIT /* 32 bit FNV-1 initial basis */
112 FNV1_64_INIT /* 64 bit FNV-1 initial basis */
113
114 FNV-1a:
115
116 FNV1A_32_INIT /* 32 bit FNV-1a initial basis */
117 FNV1A_64_INIT /* 64 bit FNV-1a initial basis */
118
119For example to perform a 64 bit FNV-1 hash:
120
121 #include "fnv.h"
122
123 Fnv64_t hash_val;
124
125 hash_val = fnv_64_str("a string", FNV1_64_INIT);
126 hash_val = fnv_64_str("more string", hash_val);
127
128produces the same final hash value as:
129
130 hash_val = fnv_64_str("a stringmore string", FNV1_64_INIT);
131
132NOTE: If one used 'FNV0_64_INIT' instead of 'FNV1_64_INIT' one would get the
133 historic FNV-0 hash instead recommended FNV-1 hash.
134
135To perform a 32 bit FNV-1 hash:
136
137 #include "fnv.h"
138
139 Fnv32_t hash_val;
140
141 hash_val = fnv_32_buf(buf, length_of_buf, FNV1_32_INIT);
142 hash_val = fnv_32_str("more data", hash_val);
143
144To perform a 64 bit FNV-1a hash:
145
146 #include "fnv.h"
147
148 Fnv64_t hash_val;
149
150 hash_val = fnv_64a_buf(buf, length_of_buf, FNV1_64_INIT);
151 hash_val = fnv_64a_str("more data", hash_val);
152
153=-=
154
155chongo <Landon Curt Noll> /\oo/\
156http://www.isthe.com/chongo
157
158Share and Enjoy!
diff --git a/lib/fnv/fnv.h b/lib/fnv/fnv.h
new file mode 100644
index 0000000000..2083a4aa23
--- /dev/null
+++ b/lib/fnv/fnv.h
@@ -0,0 +1,249 @@
1/*
2 * fnv - Fowler/Noll/Vo- hash code
3 *
4 * @(#) $Revision: 5.4 $
5 * @(#) $Id: fnv.h,v 5.4 2009/07/30 22:49:13 chongo Exp $
6 * @(#) $Source: /usr/local/src/cmd/fnv/RCS/fnv.h,v $
7 *
8 ***
9 *
10 * Fowler/Noll/Vo- hash
11 *
12 * The basis of this hash algorithm was taken from an idea sent
13 * as reviewer comments to the IEEE POSIX P1003.2 committee by:
14 *
15 * Phong Vo (http://www.research.att.com/info/kpv/)
16 * Glenn Fowler (http://www.research.att.com/~gsf/)
17 *
18 * In a subsequent ballot round:
19 *
20 * Landon Curt Noll (http://www.isthe.com/chongo/)
21 *
22 * improved on their algorithm. Some people tried this hash
23 * and found that it worked rather well. In an EMail message
24 * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
25 *
26 * FNV hashes are designed to be fast while maintaining a low
27 * collision rate. The FNV speed allows one to quickly hash lots
28 * of data while maintaining a reasonable collision rate. See:
29 *
30 * http://www.isthe.com/chongo/tech/comp/fnv/index.html
31 *
32 * for more details as well as other forms of the FNV hash.
33 *
34 ***
35 *
36 * NOTE: The FNV-0 historic hash is not recommended. One should use
37 * the FNV-1 hash instead.
38 *
39 * To use the 32 bit FNV-0 historic hash, pass FNV0_32_INIT as the
40 * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str().
41 *
42 * To use the 64 bit FNV-0 historic hash, pass FNV0_64_INIT as the
43 * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str().
44 *
45 * To use the recommended 32 bit FNV-1 hash, pass FNV1_32_INIT as the
46 * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str().
47 *
48 * To use the recommended 64 bit FNV-1 hash, pass FNV1_64_INIT as the
49 * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str().
50 *
51 * To use the recommended 32 bit FNV-1a hash, pass FNV1_32A_INIT as the
52 * Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str().
53 *
54 * To use the recommended 64 bit FNV-1a hash, pass FNV1A_64_INIT as the
55 * Fnv64_t hashval argument to fnv_64a_buf() or fnv_64a_str().
56 *
57 ***
58 *
59 * Please do not copyright this code. This code is in the public domain.
60 *
61 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
62 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
63 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
64 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
65 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
66 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
67 * PERFORMANCE OF THIS SOFTWARE.
68 *
69 * By:
70 * chongo <Landon Curt Noll> /\oo/\
71 * http://www.isthe.com/chongo/
72 *
73 * Share and Enjoy! :-)
74 */
75
76#if !defined(__FNV_H__)
77#define __FNV_H__
78
79#include <sys/types.h>
80
81#define FNV_VERSION "5.0.2" /* @(#) FNV Version */
82
83
84/*
85 * 32 bit FNV-0 hash type
86 */
87typedef u_int32_t Fnv32_t;
88
89
90/*
91 * 32 bit FNV-0 zero initial basis
92 *
93 * This historic hash is not recommended. One should use
94 * the FNV-1 hash and initial basis instead.
95 */
96#define FNV0_32_INIT ((Fnv32_t)0)
97
98
99/*
100 * 32 bit FNV-1 and FNV-1a non-zero initial basis
101 *
102 * The FNV-1 initial basis is the FNV-0 hash of the following 32 octets:
103 *
104 * chongo <Landon Curt Noll> /\../\
105 *
106 * NOTE: The \'s above are not back-slashing escape characters.
107 * They are literal ASCII backslash 0x5c characters.
108 *
109 * NOTE: The FNV-1a initial basis is the same value as FNV-1 by definition.
110 */
111#define FNV1_32_INIT ((Fnv32_t)0x811c9dc5)
112#define FNV1_32A_INIT FNV1_32_INIT
113
114
115/*
116 * determine how 64 bit unsigned values are represented
117 */
118#include "longlong.h"
119
120
121/*
122 * 64 bit FNV-0 hash
123 */
124#if defined(HAVE_64BIT_LONG_LONG)
125typedef u_int64_t Fnv64_t;
126#else /* HAVE_64BIT_LONG_LONG */
127typedef struct {
128 u_int32_t w32[2]; /* w32[0] is low order, w32[1] is high order word */
129} Fnv64_t;
130#endif /* HAVE_64BIT_LONG_LONG */
131
132
133/*
134 * 64 bit FNV-0 zero initial basis
135 *
136 * This historic hash is not recommended. One should use
137 * the FNV-1 hash and initial basis instead.
138 */
139#if defined(HAVE_64BIT_LONG_LONG)
140#define FNV0_64_INIT ((Fnv64_t)0)
141#else /* HAVE_64BIT_LONG_LONG */
142extern const Fnv64_t fnv0_64_init;
143#define FNV0_64_INIT (fnv0_64_init)
144#endif /* HAVE_64BIT_LONG_LONG */
145
146
147/*
148 * 64 bit FNV-1 non-zero initial basis
149 *
150 * The FNV-1 initial basis is the FNV-0 hash of the following 32 octets:
151 *
152 * chongo <Landon Curt Noll> /\../\
153 *
154 * NOTE: The \'s above are not back-slashing escape characters.
155 * They are literal ASCII backslash 0x5c characters.
156 *
157 * NOTE: The FNV-1a initial basis is the same value as FNV-1 by definition.
158 */
159#if defined(HAVE_64BIT_LONG_LONG)
160#define FNV1_64_INIT ((Fnv64_t)0xcbf29ce484222325ULL)
161#define FNV1A_64_INIT FNV1_64_INIT
162#else /* HAVE_64BIT_LONG_LONG */
163extern const fnv1_64_init;
164extern const Fnv64_t fnv1a_64_init;
165#define FNV1_64_INIT (fnv1_64_init)
166#define FNV1A_64_INIT (fnv1a_64_init)
167#endif /* HAVE_64BIT_LONG_LONG */
168
169
170/*
171 * hash types
172 */
173enum fnv_type {
174 FNV_NONE = 0, /* invalid FNV hash type */
175 FNV0_32 = 1, /* FNV-0 32 bit hash */
176 FNV1_32 = 2, /* FNV-1 32 bit hash */
177 FNV1a_32 = 3, /* FNV-1a 32 bit hash */
178 FNV0_64 = 4, /* FNV-0 64 bit hash */
179 FNV1_64 = 5, /* FNV-1 64 bit hash */
180 FNV1a_64 = 6, /* FNV-1a 64 bit hash */
181};
182
183
184/*
185 * these test vectors are used as part o the FNV test suite
186 */
187struct test_vector {
188 void *buf; /* start of test vector buffer */
189 int len; /* length of test vector */
190};
191struct fnv0_32_test_vector {
192 struct test_vector *test; /* test vector buffer to hash */
193 Fnv32_t fnv0_32; /* expected FNV-0 32 bit hash value */
194};
195struct fnv1_32_test_vector {
196 struct test_vector *test; /* test vector buffer to hash */
197 Fnv32_t fnv1_32; /* expected FNV-1 32 bit hash value */
198};
199struct fnv1a_32_test_vector {
200 struct test_vector *test; /* test vector buffer to hash */
201 Fnv32_t fnv1a_32; /* expected FNV-1a 32 bit hash value */
202};
203struct fnv0_64_test_vector {
204 struct test_vector *test; /* test vector buffer to hash */
205 Fnv64_t fnv0_64; /* expected FNV-0 64 bit hash value */
206};
207struct fnv1_64_test_vector {
208 struct test_vector *test; /* test vector buffer to hash */
209 Fnv64_t fnv1_64; /* expected FNV-1 64 bit hash value */
210};
211struct fnv1a_64_test_vector {
212 struct test_vector *test; /* test vector buffer to hash */
213 Fnv64_t fnv1a_64; /* expected FNV-1a 64 bit hash value */
214};
215
216
217/*
218 * external functions
219 */
220/* hash_32.c */
221extern Fnv32_t fnv_32_buf(void *buf, size_t len, Fnv32_t hashval);
222extern Fnv32_t fnv_32_str(char *buf, Fnv32_t hashval);
223
224/* hash_32a.c */
225extern Fnv32_t fnv_32a_buf(void *buf, size_t len, Fnv32_t hashval);
226extern Fnv32_t fnv_32a_str(char *buf, Fnv32_t hashval);
227
228/* hash_64.c */
229extern Fnv64_t fnv_64_buf(void *buf, size_t len, Fnv64_t hashval);
230extern Fnv64_t fnv_64_str(char *buf, Fnv64_t hashval);
231
232/* hash_64a.c */
233extern Fnv64_t fnv_64a_buf(void *buf, size_t len, Fnv64_t hashval);
234extern Fnv64_t fnv_64a_str(char *buf, Fnv64_t hashval);
235
236/* test_fnv.c */
237extern struct test_vector fnv_test_str[];
238extern struct fnv0_32_test_vector fnv0_32_vector[];
239extern struct fnv1_32_test_vector fnv1_32_vector[];
240extern struct fnv1a_32_test_vector fnv1a_32_vector[];
241extern struct fnv0_64_test_vector fnv0_64_vector[];
242extern struct fnv1_64_test_vector fnv1_64_vector[];
243extern struct fnv1a_64_test_vector fnv1a_64_vector[];
244extern void unknown_hash_type(char *prog, enum fnv_type type, int code);
245extern void print_fnv32(Fnv32_t hval, Fnv32_t mask, int verbose, char *arg);
246extern void print_fnv64(Fnv64_t hval, Fnv64_t mask, int verbose, char *arg);
247
248
249#endif /* __FNV_H__ */
diff --git a/lib/fnv/fnv32.c b/lib/fnv/fnv32.c
new file mode 100644
index 0000000000..58c61f03fc
--- /dev/null
+++ b/lib/fnv/fnv32.c
@@ -0,0 +1,467 @@
1/*
2 * fnv32 - 32 bit Fowler/Noll/Vo hash of a buffer or string
3 *
4 * @(#) $Revision: 5.5 $
5 * @(#) $Id: fnv32.c,v 5.5 2012/03/21 01:38:12 chongo Exp $
6 * @(#) $Source: /usr/local/src/cmd/fnv/RCS/fnv32.c,v $
7 *
8 ***
9 *
10 * Fowler/Noll/Vo hash
11 *
12 * The basis of this hash algorithm was taken from an idea sent
13 * as reviewer comments to the IEEE POSIX P1003.2 committee by:
14 *
15 * Phong Vo (http://www.research.att.com/info/kpv/)
16 * Glenn Fowler (http://www.research.att.com/~gsf/)
17 *
18 * In a subsequent ballot round:
19 *
20 * Landon Curt Noll (http://www.isthe.com/chongo/)
21 *
22 * improved on their algorithm. Some people tried this hash
23 * and found that it worked rather well. In an EMail message
24 * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
25 *
26 * FNV hashes are designed to be fast while maintaining a low
27 * collision rate. The FNV speed allows one to quickly hash lots
28 * of data while maintaining a reasonable collision rate. See:
29 *
30 * http://www.isthe.com/chongo/tech/comp/fnv/index.html
31 *
32 * for more details as well as other forms of the FNV hash.
33 *
34 ***
35 *
36 * Please do not copyright this code. This code is in the public domain.
37 *
38 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
39 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
40 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
41 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
42 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
43 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
44 * PERFORMANCE OF THIS SOFTWARE.
45 *
46 * By:
47 * chongo <Landon Curt Noll> /\oo/\
48 * http://www.isthe.com/chongo/
49 *
50 * Share and Enjoy! :-)
51 */
52
53#include <stdio.h>
54#include <unistd.h>
55#include <stdlib.h>
56#include <sys/types.h>
57#include <sys/stat.h>
58#include <fcntl.h>
59#include <string.h>
60#include "longlong.h"
61#include "fnv.h"
62
63#define WIDTH 32 /* bit width of hash */
64
65#define BUF_SIZE (32*1024) /* number of bytes to hash at a time */
66
67static char *usage =
68"usage: %s [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]\n"
69"\n"
70"\t-b bcnt\tmask off all but the lower bcnt bits (default 32)\n"
71"\t-m\tmultiple hashes, one per line for each arg\n"
72"\t-s\thash arg as a string (ignoring terminating NUL bytes)\n"
73"\t-t code\t test hash code: (0 ==> generate test vectors\n"
74"\t\t\t\t 1 ==> validate against FNV test vectors)\n"
75"\t-v\tverbose mode, print arg after hash (implies -m)\n"
76"\targ\tstring (if -s was given) or filename (default stdin)\n"
77"\n"
78"\tNOTE: Programs that begin with fnv0 implement the FNV-0 hash.\n"
79"\t The FNV-0 hash is historic FNV algorithm that is now deprecated.\n"
80"\n"
81"\tSee http://www.isthe.com/chongo/tech/comp/fnv/index.html for more info.\n"
82"\n"
83"\t@(#) FNV Version: %s\n";
84static char *program; /* our name */
85
86
87/*
88 * test_fnv32 - test the FNV32 hash
89 *
90 * given:
91 * hash_type type of FNV hash to test
92 * init_hval initial hash value
93 * mask lower bit mask
94 * v_flag 1 => print test failure info on stderr
95 * code 0 ==> generate FNV test vectors
96 * 1 ==> validate against FNV test vectors
97 *
98 * returns: 0 ==> OK, else test vector failure number
99 */
100static int
101test_fnv32(enum fnv_type hash_type, Fnv32_t init_hval,
102 Fnv32_t mask, int v_flag, int code)
103{
104 struct test_vector *t; /* FNV test vestor */
105 Fnv32_t hval; /* current hash value */
106 int tstnum; /* test vector that failed, starting at 1 */
107
108 /*
109 * print preamble if generating test vectors
110 */
111 if (code == 0) {
112 switch (hash_type) {
113 case FNV0_32:
114 printf("struct fnv0_32_test_vector fnv0_32_vector[] = {\n");
115 break;
116 case FNV1_32:
117 printf("struct fnv1_32_test_vector fnv1_32_vector[] = {\n");
118 break;
119 case FNV1a_32:
120 printf("struct fnv1a_32_test_vector fnv1a_32_vector[] = {\n");
121 break;
122 default:
123 unknown_hash_type(program, hash_type, 12); /* exit(12) */
124 /*NOTREACHED*/
125 }
126 }
127
128 /*
129 * loop thru all test vectors
130 */
131 for (t = fnv_test_str, tstnum = 1; t->buf != NULL; ++t, ++tstnum) {
132
133 /*
134 * compute the FNV hash
135 */
136 hval = init_hval;
137 switch (hash_type) {
138 case FNV0_32:
139 case FNV1_32:
140 hval = fnv_32_buf(t->buf, t->len, hval);
141 break;
142 case FNV1a_32:
143 hval = fnv_32a_buf(t->buf, t->len, hval);
144 break;
145 default:
146 unknown_hash_type(program, hash_type, 13); /* exit(13) */
147 /*NOTREACHED*/
148 }
149
150 /*
151 * print the vector
152 */
153 switch (code) {
154 case 0: /* generate the test vector */
155 printf(" { &fnv_test_str[%d], (Fnv32_t) 0x%08lxUL },\n",
156 tstnum-1, hval & mask);
157 break;
158 case 1: /* validate against test vector */
159 switch (hash_type) {
160 case FNV0_32:
161 if ((hval&mask) != (fnv0_32_vector[tstnum-1].fnv0_32 & mask)) {
162 if (v_flag) {
163 fprintf(stderr, "%s: failed fnv0_32 test # %d\n",
164 program, tstnum);
165 fprintf(stderr, "%s: test # 1 is 1st test\n", program);
166 fprintf(stderr,
167 "%s: expected 0x%08lx != generated: 0x%08lx\n",
168 program, (hval&mask),
169 (fnv0_32_vector[tstnum-1].fnv0_32 & mask));
170 }
171 return tstnum;
172 }
173 break;
174 case FNV1_32:
175 if ((hval&mask) != (fnv1_32_vector[tstnum-1].fnv1_32 & mask)) {
176 if (v_flag) {
177 fprintf(stderr, "%s: failed fnv1_32 test # %d\n",
178 program, tstnum);
179 fprintf(stderr, "%s: test # 1 is 1st test\n", program);
180 fprintf(stderr,
181 "%s: expected 0x%08lx != generated: 0x%08lx\n",
182 program, (hval&mask),
183 (fnv1_32_vector[tstnum-1].fnv1_32 & mask));
184 }
185 return tstnum;
186 }
187 break;
188 case FNV1a_32:
189 if ((hval&mask) != (fnv1a_32_vector[tstnum-1].fnv1a_32 &mask)) {
190 if (v_flag) {
191 fprintf(stderr, "%s: failed fnv1a_32 test # %d\n",
192 program, tstnum);
193 fprintf(stderr, "%s: test # 1 is 1st test\n", program);
194 fprintf(stderr,
195 "%s: expected 0x%08lx != generated: 0x%08lx\n",
196 program, (hval&mask),
197 (fnv1a_32_vector[tstnum-1].fnv1a_32 & mask));
198 }
199 return tstnum;
200 }
201 break;
202 }
203 break;
204 default:
205 fprintf(stderr, "%s: -m %d not implemented yet\n", program, code);
206 exit(14);
207 }
208 }
209
210 /*
211 * print completion if generating test vectors
212 */
213 if (code == 0) {
214 printf(" { NULL, 0 }\n");
215 printf("};\n");
216 }
217
218 /*
219 * no failures, return code 0 ==> all OK
220 */
221 return 0;
222}
223
224
225/*
226 * main - the main function
227 *
228 * See the above usage for details.
229 */
230int
231main(int argc, char *argv[])
232{
233 char buf[BUF_SIZE+1]; /* read buffer */
234 int readcnt; /* number of characters written */
235 Fnv32_t hval; /* current hash value */
236 int s_flag = 0; /* 1 => -s was given, hash args as strings */
237 int m_flag = 0; /* 1 => print multiple hashes, one per arg */
238 int v_flag = 0; /* 1 => verbose hash print */
239 int b_flag = WIDTH; /* -b flag value */
240 int t_flag = -1; /* FNV test vector code (0=>print, 1=>test) */
241 enum fnv_type hash_type = FNV_NONE; /* type of FNV hash to perform */
242 Fnv32_t bmask; /* mask to apply to output */
243 extern char *optarg; /* option argument */
244 extern int optind; /* argv index of the next arg */
245 int fd; /* open file to process */
246 char *p;
247 int i;
248
249 /*
250 * parse args
251 */
252 program = argv[0];
253 while ((i = getopt(argc, argv, "b:mst:v")) != -1) {
254 switch (i) {
255 case 'b': /* bcnt bit mask count */
256 b_flag = atoi(optarg);
257 break;
258 case 'm': /* print multiple hashes, one per arg */
259 m_flag = 1;
260 break;
261 case 's': /* hash args as strings */
262 s_flag = 1;
263 break;
264 case 't': /* FNV test vector code */
265 t_flag = atoi(optarg);
266 if (t_flag < 0 || t_flag > 1) {
267 fprintf(stderr, "%s: -t code must be 0 or 1\n", program);
268 fprintf(stderr, usage, program, FNV_VERSION);
269 exit(1);
270 }
271 m_flag = 1;
272 break;
273 case 'v': /* verbose hash print */
274 m_flag = 1;
275 v_flag = 1;
276 break;
277 default:
278 fprintf(stderr, usage, program, FNV_VERSION);
279 exit(1);
280 }
281 }
282 /* -t code incompatible with -b, -m and args */
283 if (t_flag >= 0) {
284 if (b_flag != WIDTH) {
285 fprintf(stderr, "%s: -t code incompatible with -b\n", program);
286 exit(2);
287 }
288 if (s_flag != 0) {
289 fprintf(stderr, "%s: -t code incompatible with -s\n", program);
290 exit(3);
291 }
292 if (optind < argc) {
293 fprintf(stderr, "%s: -t code incompatible args\n", program);
294 exit(4);
295 }
296 }
297 /* -s requires at least 1 arg */
298 if (s_flag && optind >= argc) {
299 fprintf(stderr, usage, program, FNV_VERSION);
300 exit(5);
301 }
302 /* limit -b values */
303 if (b_flag < 0 || b_flag > WIDTH) {
304 fprintf(stderr, "%s: -b bcnt: %d must be >= 0 and < %d\n",
305 program, b_flag, WIDTH);
306 exit(6);
307 }
308 if (b_flag == WIDTH) {
309 bmask = (Fnv32_t)0xffffffff;
310 } else {
311 bmask = (Fnv32_t)((1 << b_flag) - 1);
312 }
313
314 /*
315 * start with the initial basis depending on the hash type
316 */
317 p = strrchr(program, '/');
318 if (p == NULL) {
319 p = program;
320 } else {
321 ++p;
322 }
323 if (strcmp(p, "fnv032") == 0) {
324 /* using non-recommended FNV-0 and zero initial basis */
325 hval = FNV0_32_INIT;
326 hash_type = FNV0_32;
327 } else if (strcmp(p, "fnv132") == 0) {
328 /* using FNV-1 and non-zero initial basis */
329 hval = FNV1_32_INIT;
330 hash_type = FNV1_32;
331 } else if (strcmp(p, "fnv1a32") == 0) {
332 /* start with the FNV-1a initial basis */
333 hval = FNV1_32A_INIT;
334 hash_type = FNV1a_32;
335 } else {
336 fprintf(stderr, "%s: unknown program name, unknown hash type\n",
337 program);
338 exit(7);
339 }
340
341 /*
342 * FNV test vector processing, if needed
343 */
344 if (t_flag >= 0) {
345 int code; /* test vector that failed, starting at 1 */
346
347 /*
348 * perform all tests
349 */
350 code = test_fnv32(hash_type, hval, bmask, v_flag, t_flag);
351
352 /*
353 * evaluate the tests
354 */
355 if (code == 0) {
356 if (v_flag) {
357 printf("passed\n");
358 }
359 exit(0);
360 } else {
361 printf("failed vector (1 is 1st test): %d\n", code);
362 exit(8);
363 }
364 }
365
366 /*
367 * string hashing
368 */
369 if (s_flag) {
370
371 /* hash any other strings */
372 for (i=optind; i < argc; ++i) {
373 switch (hash_type) {
374 case FNV0_32:
375 case FNV1_32:
376 hval = fnv_32_str(argv[i], hval);
377 break;
378 case FNV1a_32:
379 hval = fnv_32a_str(argv[i], hval);
380 break;
381 default:
382 unknown_hash_type(program, hash_type, 9); /* exit(9) */
383 /*NOTREACHED*/
384 }
385 if (m_flag) {
386 print_fnv32(hval, bmask, v_flag, argv[i]);
387 }
388 }
389
390
391 /*
392 * file hashing
393 */
394 } else {
395
396 /*
397 * case: process only stdin
398 */
399 if (optind >= argc) {
400
401 /* case: process only stdin */
402 while ((readcnt = read(0, buf, BUF_SIZE)) > 0) {
403 switch (hash_type) {
404 case FNV0_32:
405 case FNV1_32:
406 hval = fnv_32_buf(buf, readcnt, hval);
407 break;
408 case FNV1a_32:
409 hval = fnv_32a_buf(buf, readcnt, hval);
410 break;
411 default:
412 unknown_hash_type(program, hash_type, 10); /* exit(10) */
413 /*NOTREACHED*/
414 }
415 }
416 if (m_flag) {
417 print_fnv32(hval, bmask, v_flag, "(stdin)");
418 }
419
420 } else {
421
422 /*
423 * process any other files
424 */
425 for (i=optind; i < argc; ++i) {
426
427 /* open the file */
428 fd = open(argv[i], O_RDONLY);
429 if (fd < 0) {
430 fprintf(stderr, "%s: unable to open file: %s\n",
431 program, argv[i]);
432 exit(4);
433 }
434
435 /* hash the file */
436 while ((readcnt = read(fd, buf, BUF_SIZE)) > 0) {
437 switch (hash_type) {
438 case FNV0_32:
439 case FNV1_32:
440 hval = fnv_32_buf(buf, readcnt, hval);
441 break;
442 case FNV1a_32:
443 hval = fnv_32a_buf(buf, readcnt, hval);
444 break;
445 default:
446 unknown_hash_type(program, hash_type, 11);/* exit(11) */
447 /*NOTREACHED*/
448 }
449 }
450
451 /* finish processing the file */
452 if (m_flag) {
453 print_fnv32(hval, bmask, v_flag, argv[i]);
454 }
455 close(fd);
456 }
457 }
458 }
459
460 /*
461 * report hash and exit
462 */
463 if (!m_flag) {
464 print_fnv32(hval, bmask, v_flag, "");
465 }
466 return 0; /* exit(0); */
467}
diff --git a/lib/fnv/fnv64.c b/lib/fnv/fnv64.c
new file mode 100644
index 0000000000..0662d4d657
--- /dev/null
+++ b/lib/fnv/fnv64.c
@@ -0,0 +1,591 @@
1/*
2 * fnv_64 - 64 bit Fowler/Noll/Vo hash of a buffer or string
3 *
4 * @(#) $Revision: 5.5 $
5 * @(#) $Id: fnv64.c,v 5.5 2012/03/21 01:38:12 chongo Exp $
6 * @(#) $Source: /usr/local/src/cmd/fnv/RCS/fnv64.c,v $
7 *
8 ***
9 *
10 * Fowler/Noll/Vo hash
11 *
12 * The basis of this hash algorithm was taken from an idea sent
13 * as reviewer comments to the IEEE POSIX P1003.2 committee by:
14 *
15 * Phong Vo (http://www.research.att.com/info/kpv/)
16 * Glenn Fowler (http://www.research.att.com/~gsf/)
17 *
18 * In a subsequent ballot round:
19 *
20 * Landon Curt Noll (http://www.isthe.com/chongo/)
21 *
22 * improved on their algorithm. Some people tried this hash
23 * and found that it worked rather well. In an EMail message
24 * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
25 *
26 * FNV hashes are designed to be fast while maintaining a low
27 * collision rate. The FNV speed allows one to quickly hash lots
28 * of data while maintaining a reasonable collision rate. See:
29 *
30 * http://www.isthe.com/chongo/tech/comp/fnv/index.html
31 *
32 * for more details as well as other forms of the FNV hash.
33 *
34 ***
35 *
36 * Please do not copyright this code. This code is in the public domain.
37 *
38 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
39 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
40 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
41 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
42 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
43 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
44 * PERFORMANCE OF THIS SOFTWARE.
45 *
46 * By:
47 * chongo <Landon Curt Noll> /\oo/\
48 * http://www.isthe.com/chongo/
49 *
50 * Share and Enjoy! :-)
51 */
52
53#include <stdio.h>
54#include <unistd.h>
55#include <stdlib.h>
56#include <sys/types.h>
57#include <sys/stat.h>
58#include <fcntl.h>
59#include <string.h>
60#include "longlong.h"
61#include "fnv.h"
62
63#define WIDTH 64 /* bit width of hash */
64
65#define BUF_SIZE (32*1024) /* number of bytes to hash at a time */
66
67static char *usage =
68"usage: %s [-b bcnt] [-m] [-s arg] [-t code] [-v] [arg ...]\n"
69"\n"
70"\t-b bcnt\tmask off all but the lower bcnt bits (default 64)\n"
71"\t-m\tmultiple hashes, one per line for each arg\n"
72"\t-s\thash arg as a string (ignoring terminating NUL bytes)\n"
73"\t-t code\t test hash code: (0 ==> generate test vectors\n"
74"\t\t\t\t 1 ==> validate against FNV test vectors)\n"
75"\t-v\tverbose mode, print arg after hash (implies -m)\n"
76"\targ\tstring (if -s was given) or filename (default stdin)\n"
77"\n"
78"\tNOTE: Programs that begin with fnv0 implement the FNV-0 hash.\n"
79"\t The FNV-0 hash is historic FNV algorithm that is now deprecated.\n"
80"\n"
81"\tSee http://www.isthe.com/chongo/tech/comp/fnv/index.html for more info.\n"
82"\n"
83"\t@(#) FNV Version: %s\n";
84static char *program; /* our name */
85
86
87/*
88 * test_fnv64 - test the FNV64 hash
89 *
90 * given:
91 * hash_type type of FNV hash to test
92 * init_hval initial hash value
93 * mask lower bit mask
94 * v_flag 1 => print test failure info on stderr
95 * code 0 ==> generate FNV test vectors
96 * 1 ==> validate against FNV test vectors
97 *
98 * returns: 0 ==> OK, else test vector failure number
99 */
100static int
101test_fnv64(enum fnv_type hash_type, Fnv64_t init_hval,
102 Fnv64_t mask, int v_flag, int code)
103{
104 struct test_vector *t; /* FNV test vestor */
105 Fnv64_t hval; /* current hash value */
106 int tstnum; /* test vector that failed, starting at 1 */
107
108 /*
109 * print preamble if generating test vectors
110 */
111 if (code == 0) {
112 switch (hash_type) {
113 case FNV0_64:
114 printf("struct fnv0_64_test_vector fnv0_64_vector[] = {\n");
115 break;
116 case FNV1_64:
117 printf("struct fnv1_64_test_vector fnv1_64_vector[] = {\n");
118 break;
119 case FNV1a_64:
120 printf("struct fnv1a_64_test_vector fnv1a_64_vector[] = {\n");
121 break;
122 default:
123 unknown_hash_type(program, hash_type, 12); /* exit(12) */
124 /*NOTREACHED*/
125 }
126 }
127
128 /*
129 * loop thru all test vectors
130 */
131 for (t = fnv_test_str, tstnum = 1; t->buf != NULL; ++t, ++tstnum) {
132
133 /*
134 * compute the FNV hash
135 */
136 hval = init_hval;
137 switch (hash_type) {
138 case FNV0_64:
139 case FNV1_64:
140 hval = fnv_64_buf(t->buf, t->len, hval);
141 break;
142 case FNV1a_64:
143 hval = fnv_64a_buf(t->buf, t->len, hval);
144 break;
145 default:
146 unknown_hash_type(program, hash_type, 13); /* exit(13) */
147 /*NOTREACHED*/
148 }
149
150 /*
151 * print the vector
152 */
153#if defined(HAVE_64BIT_LONG_LONG)
154 /*
155 * HAVE_64BIT_LONG_LONG testing
156 */
157 switch (code) {
158 case 0: /* generate the test vector */
159 printf(" { &fnv_test_str[%d], (Fnv64_t) 0x%016llxULL },\n",
160 tstnum-1, hval & mask);
161 break;
162
163 case 1: /* validate against test vector */
164 switch (hash_type) {
165 case FNV0_64:
166 if ((hval&mask) != (fnv0_64_vector[tstnum-1].fnv0_64 & mask)) {
167 if (v_flag) {
168 fprintf(stderr, "%s: failed fnv0_64 test # %d\n",
169 program, tstnum);
170 fprintf(stderr, "%s: test # 1 is 1st test\n", program);
171 fprintf(stderr,
172 "%s: expected 0x%016llx != generated: 0x%016llx\n",
173 program,
174 (hval&mask),
175 (fnv0_64_vector[tstnum-1].fnv0_64 & mask));
176 }
177 return tstnum;
178 }
179 break;
180 case FNV1_64:
181 if ((hval&mask) != (fnv1_64_vector[tstnum-1].fnv1_64 & mask)) {
182 if (v_flag) {
183 fprintf(stderr, "%s: failed fnv1_64 test # %d\n",
184 program, tstnum);
185 fprintf(stderr, "%s: test # 1 is 1st test\n", program);
186 fprintf(stderr,
187 "%s: expected 0x%016llx != generated: 0x%016llx\n",
188 program,
189 (hval&mask),
190 (fnv1_64_vector[tstnum-1].fnv1_64 & mask));
191 }
192 return tstnum;
193 }
194 break;
195 case FNV1a_64:
196 if ((hval&mask) != (fnv1a_64_vector[tstnum-1].fnv1a_64 &mask)) {
197 if (v_flag) {
198 fprintf(stderr, "%s: failed fnv1a_64 test # %d\n",
199 program, tstnum);
200 fprintf(stderr, "%s: test # 1 is 1st test\n", program);
201 fprintf(stderr,
202 "%s: expected 0x%016llx != generated: 0x%016llx\n",
203 program,
204 (hval&mask),
205 (fnv1a_64_vector[tstnum-1].fnv1a_64 & mask));
206 }
207 return tstnum;
208 }
209 break;
210 }
211 break;
212
213 default:
214 fprintf(stderr, "%s: -m %d not implemented yet\n", program, code);
215 exit(14);
216 }
217#else /* HAVE_64BIT_LONG_LONG */
218 /*
219 * non HAVE_64BIT_LONG_LONG testing
220 */
221 switch (code) {
222 case 0: /* generate the test vector */
223 printf(" { &fnv_test_str[%d], "
224 "(Fnv64_t) {0x%08lxUL, 0x%08lxUL} },\n",
225 tstnum-1,
226 (hval.w32[0] & mask.w32[0]),
227 (hval.w32[1] & mask.w32[1]));
228 break;
229
230 case 1: /* validate against test vector */
231 switch (hash_type) {
232 case FNV0_64:
233 if (((hval.w32[0] & mask.w32[0]) !=
234 (fnv0_64_vector[tstnum-1].fnv0_64.w32[0] &
235 mask.w32[0])) &&
236 ((hval.w32[1] & mask.w32[1]) !=
237 (fnv0_64_vector[tstnum-1].fnv0_64.w32[1] &
238 mask.w32[1]))) {
239 if (v_flag) {
240 fprintf(stderr, "%s: failed fnv0_64 test # %d\n",
241 program, tstnum);
242 fprintf(stderr, "%s: test # 1 is 1st test\n", program);
243 fprintf(stderr,
244 "%s: expected 0x%08llx%08llx != "
245 "generated: 0x%08llx%08llx\n",
246 program,
247 (hval.w32[0] & mask.w32[0]),
248 (hval.w32[1] & mask.w32[1]),
249 ((fnv0_64_vector[tstnum-1].fnv0_64.w32[0] &
250 mask.w32[0])),
251 ((fnv0_64_vector[tstnum-1].fnv0_64.w32[1] &
252 mask.w32[1])));
253 }
254 return tstnum;
255 }
256 break;
257 case FNV1_64:
258 if (((hval.w32[0] & mask.w32[0]) !=
259 (fnv1_64_vector[tstnum-1].fnv1_64.w32[0] &
260 mask.w32[0])) &&
261 ((hval.w32[1] & mask.w32[1]) !=
262 (fnv1_64_vector[tstnum-1].fnv1_64.w32[1] &
263 mask.w32[1]))) {
264 if (v_flag) {
265 fprintf(stderr, "%s: failed fnv1_64 test # %d\n",
266 program, tstnum);
267 fprintf(stderr, "%s: test # 1 is 1st test\n", program);
268 fprintf(stderr,
269 "%s: expected 0x%08llx%08llx != "
270 "generated: 0x%08llx%08llx\n",
271 program,
272 (hval.w32[0] & mask.w32[0]),
273 (hval.w32[1] & mask.w32[1]),
274 ((fnv1_64_vector[tstnum-1].fnv1_64.w32[0] &
275 mask.w32[0])),
276 ((fnv1_64_vector[tstnum-1].fnv1_64.w32[1] &
277 mask.w32[1])));
278 }
279 return tstnum;
280 }
281 break;
282 case FNV1a_64:
283 if (((hval.w32[0] & mask.w32[0]) !=
284 (fnv1a_64_vector[tstnum-1].fnv1a_64.w32[0] &
285 mask.w32[0])) &&
286 ((hval.w32[1] & mask.w32[1]) !=
287 (fnv1a_64_vector[tstnum-1].fnv1a_64.w32[1] &
288 mask.w32[1]))) {
289 if (v_flag) {
290 fprintf(stderr, "%s: failed fnv1a_64 test # %d\n",
291 program, tstnum);
292 fprintf(stderr, "%s: test # 1 is 1st test\n", program);
293 fprintf(stderr,
294 "%s: expected 0x%08llx%08llx != "
295 "generated: 0x%08llx%08llx\n",
296 program,
297 (hval.w32[0] & mask.w32[0]),
298 (hval.w32[1] & mask.w32[1]),
299 ((fnv1a_64_vector[tstnum-1].fnv1a_64.w32[0] &
300 mask.w32[0])),
301 ((fnv1a_64_vector[tstnum-1].fnv1a_64.w32[1] &
302 mask.w32[1])));
303 }
304 return tstnum;
305 }
306 break;
307 }
308 break;
309
310 default:
311 fprintf(stderr, "%s: -m %d not implemented yet\n", program, code);
312 exit(15);
313 }
314#endif /* HAVE_64BIT_LONG_LONG */
315 }
316
317 /*
318 * print completion if generating test vectors
319 */
320 if (code == 0) {
321#if defined(HAVE_64BIT_LONG_LONG)
322 printf(" { NULL, (Fnv64_t) 0 }\n");
323#else /* HAVE_64BIT_LONG_LONG */
324 printf(" { NULL, (Fnv64_t) {0,0} }\n");
325#endif /* HAVE_64BIT_LONG_LONG */
326 printf("};\n");
327 }
328
329 /*
330 * no failures, return code 0 ==> all OK
331 */
332 return 0;
333}
334
335
336/*
337 * main - the main function
338 *
339 * See the above usage for details.
340 */
341int
342main(int argc, char *argv[])
343{
344 char buf[BUF_SIZE+1]; /* read buffer */
345 int readcnt; /* number of characters written */
346 Fnv64_t hval; /* current hash value */
347 int s_flag = 0; /* 1 => -s was given, hash args as strings */
348 int m_flag = 0; /* 1 => print multiple hashes, one per arg */
349 int v_flag = 0; /* 1 => verbose hash print */
350 int b_flag = WIDTH; /* -b flag value */
351 int t_flag = -1; /* FNV test vector code (0=>print, 1=>test) */
352 enum fnv_type hash_type = FNV_NONE; /* type of FNV hash to perform */
353 Fnv64_t bmask; /* mask to apply to output */
354 extern char *optarg; /* option argument */
355 extern int optind; /* argv index of the next arg */
356 int fd; /* open file to process */
357 char *p;
358 int i;
359
360 /*
361 * parse args
362 */
363 program = argv[0];
364 while ((i = getopt(argc, argv, "b:mst:v")) != -1) {
365 switch (i) {
366 case 'b': /* bcnt bit mask count */
367 b_flag = atoi(optarg);
368 break;
369 case 'm': /* print multiple hashes, one per arg */
370 m_flag = 1;
371 break;
372 case 's': /* hash args as strings */
373 s_flag = 1;
374 break;
375 case 't': /* FNV test vector code */
376 t_flag = atoi(optarg);
377 if (t_flag < 0 || t_flag > 1) {
378 fprintf(stderr, "%s: -t code must be 0 or 1\n", program);
379 fprintf(stderr, usage, program, FNV_VERSION);
380 exit(1);
381 }
382 m_flag = 1;
383 break;
384 case 'v': /* verbose hash print */
385 m_flag = 1;
386 v_flag = 1;
387 break;
388 default:
389 fprintf(stderr, usage, program, FNV_VERSION);
390 exit(1);
391 }
392 }
393 /* -t code incompatible with -b, -m and args */
394 if (t_flag >= 0) {
395 if (b_flag != WIDTH) {
396 fprintf(stderr, "%s: -t code incompatible with -b\n", program);
397 exit(2);
398 }
399 if (s_flag != 0) {
400 fprintf(stderr, "%s: -t code incompatible with -s\n", program);
401 exit(3);
402 }
403 if (optind < argc) {
404 fprintf(stderr, "%s: -t code incompatible args\n", program);
405 exit(4);
406 }
407 }
408 /* -s requires at least 1 arg */
409 if (s_flag && optind >= argc) {
410 fprintf(stderr, usage, program, FNV_VERSION);
411 exit(5);
412 }
413 /* limit -b values */
414 if (b_flag < 0 || b_flag > WIDTH) {
415 fprintf(stderr, "%s: -b bcnt: %d must be >= 0 and < %d\n",
416 program, b_flag, WIDTH);
417 exit(6);
418 }
419#if defined(HAVE_64BIT_LONG_LONG)
420 if (b_flag == WIDTH) {
421 bmask = (Fnv64_t)0xffffffffffffffffULL;
422 } else {
423 bmask = (Fnv64_t)((1ULL << b_flag) - 1ULL);
424 }
425#else /* HAVE_64BIT_LONG_LONG */
426 if (b_flag == WIDTH) {
427 bmask.w32[0] = 0xffffffffUL;
428 bmask.w32[1] = 0xffffffffUL;
429 } else if (b_flag >= WIDTH/2) {
430 bmask.w32[0] = 0xffffffffUL;
431 bmask.w32[1] = ((1UL << (b_flag-(WIDTH/2))) - 1UL);
432 } else {
433 bmask.w32[0] = ((1UL << b_flag) - 1UL);
434 bmask.w32[1] = 0UL;
435 }
436#endif /* HAVE_64BIT_LONG_LONG */
437
438 /*
439 * start with the initial basis depending on the hash type
440 */
441 p = strrchr(program, '/');
442 if (p == NULL) {
443 p = program;
444 } else {
445 ++p;
446 }
447 if (strcmp(p, "fnv064") == 0 || strcmp(p, "no64bit_fnv064") == 0) {
448 /* using non-recommended FNV-0 and zero initial basis */
449 hval = FNV0_64_INIT;
450 hash_type = FNV0_64;
451 } else if (strcmp(p, "fnv164") == 0 || strcmp(p, "no64bit_fnv164") == 0) {
452 /* using FNV-1 and non-zero initial basis */
453 hval = FNV1_64_INIT;
454 hash_type = FNV1_64;
455 } else if (strcmp(p, "fnv1a64") == 0 || strcmp(p, "no64bit_fnv1a64") == 0) {
456 /* start with the FNV-1a initial basis */
457 hval = FNV1A_64_INIT;
458 hash_type = FNV1a_64;
459 } else {
460 fprintf(stderr, "%s: unknown program name, unknown hash type\n",
461 program);
462 exit(7);
463 }
464
465 /*
466 * FNV test vector processing, if needed
467 */
468 if (t_flag >= 0) {
469 int code; /* test vector that failed, starting at 1 */
470
471 /*
472 * perform all tests
473 */
474 code = test_fnv64(hash_type, hval, bmask, v_flag, t_flag);
475
476 /*
477 * evaluate the tests
478 */
479 if (code == 0) {
480 if (v_flag) {
481 printf("passed\n");
482 }
483 exit(0);
484 } else {
485 printf("failed vector (1 is 1st test): %d\n", code);
486 exit(8);
487 }
488 }
489
490 /*
491 * string hashing
492 */
493 if (s_flag) {
494
495 /* hash any other strings */
496 for (i=optind; i < argc; ++i) {
497 switch (hash_type) {
498 case FNV0_64:
499 case FNV1_64:
500 hval = fnv_64_str(argv[i], hval);
501 break;
502 case FNV1a_64:
503 hval = fnv_64a_str(argv[i], hval);
504 break;
505 default:
506 unknown_hash_type(program, hash_type, 9); /* exit(9) */
507 /*NOTREACHED*/
508 }
509 if (m_flag) {
510 print_fnv64(hval, bmask, v_flag, argv[i]);
511 }
512 }
513
514
515 /*
516 * file hashing
517 */
518 } else {
519
520 /*
521 * case: process only stdin
522 */
523 if (optind >= argc) {
524
525 /* case: process only stdin */
526 while ((readcnt = read(0, buf, BUF_SIZE)) > 0) {
527 switch (hash_type) {
528 case FNV0_64:
529 case FNV1_64:
530 hval = fnv_64_buf(buf, readcnt, hval);
531 break;
532 case FNV1a_64:
533 hval = fnv_64a_buf(buf, readcnt, hval);
534 break;
535 default:
536 unknown_hash_type(program, hash_type, 10); /* exit(10) */
537 /*NOTREACHED*/
538 }
539 }
540 if (m_flag) {
541 print_fnv64(hval, bmask, v_flag, "(stdin)");
542 }
543
544 } else {
545
546 /*
547 * process any other files
548 */
549 for (i=optind; i < argc; ++i) {
550
551 /* open the file */
552 fd = open(argv[i], O_RDONLY);
553 if (fd < 0) {
554 fprintf(stderr, "%s: unable to open file: %s\n",
555 program, argv[i]);
556 exit(4);
557 }
558
559 /* hash the file */
560 while ((readcnt = read(fd, buf, BUF_SIZE)) > 0) {
561 switch (hash_type) {
562 case FNV0_64:
563 case FNV1_64:
564 hval = fnv_64_buf(buf, readcnt, hval);
565 break;
566 case FNV1a_64:
567 hval = fnv_64a_buf(buf, readcnt, hval);
568 break;
569 default:
570 unknown_hash_type(program, hash_type, 11);/* exit(11) */
571 /*NOTREACHED*/
572 }
573 }
574
575 /* finish processing the file */
576 if (m_flag) {
577 print_fnv64(hval, bmask, v_flag, argv[i]);
578 }
579 close(fd);
580 }
581 }
582 }
583
584 /*
585 * report hash and exit
586 */
587 if (!m_flag) {
588 print_fnv64(hval, bmask, v_flag, "");
589 }
590 return 0; /* exit(0); */
591}
diff --git a/lib/fnv/hash_32.c b/lib/fnv/hash_32.c
new file mode 100644
index 0000000000..077170ff6d
--- /dev/null
+++ b/lib/fnv/hash_32.c
@@ -0,0 +1,156 @@
1/*
2 * hash_32 - 32 bit Fowler/Noll/Vo hash code
3 *
4 * @(#) $Revision: 5.1 $
5 * @(#) $Id: hash_32.c,v 5.1 2009/06/30 09:13:32 chongo Exp $
6 * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_32.c,v $
7 *
8 ***
9 *
10 * Fowler/Noll/Vo hash
11 *
12 * The basis of this hash algorithm was taken from an idea sent
13 * as reviewer comments to the IEEE POSIX P1003.2 committee by:
14 *
15 * Phong Vo (http://www.research.att.com/info/kpv/)
16 * Glenn Fowler (http://www.research.att.com/~gsf/)
17 *
18 * In a subsequent ballot round:
19 *
20 * Landon Curt Noll (http://www.isthe.com/chongo/)
21 *
22 * improved on their algorithm. Some people tried this hash
23 * and found that it worked rather well. In an EMail message
24 * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
25 *
26 * FNV hashes are designed to be fast while maintaining a low
27 * collision rate. The FNV speed allows one to quickly hash lots
28 * of data while maintaining a reasonable collision rate. See:
29 *
30 * http://www.isthe.com/chongo/tech/comp/fnv/index.html
31 *
32 * for more details as well as other forms of the FNV hash.
33 ***
34 *
35 * NOTE: The FNV-0 historic hash is not recommended. One should use
36 * the FNV-1 hash instead.
37 *
38 * To use the 32 bit FNV-0 historic hash, pass FNV0_32_INIT as the
39 * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str().
40 *
41 * To use the recommended 32 bit FNV-1 hash, pass FNV1_32_INIT as the
42 * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str().
43 *
44 ***
45 *
46 * Please do not copyright this code. This code is in the public domain.
47 *
48 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
49 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
50 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
51 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
52 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
53 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
54 * PERFORMANCE OF THIS SOFTWARE.
55 *
56 * By:
57 * chongo <Landon Curt Noll> /\oo/\
58 * http://www.isthe.com/chongo/
59 *
60 * Share and Enjoy! :-)
61 */
62
63#include <stdlib.h>
64#include "fnv.h"
65
66
67/*
68 * 32 bit magic FNV-0 and FNV-1 prime
69 */
70#define FNV_32_PRIME ((Fnv32_t)0x01000193)
71
72
73/*
74 * fnv_32_buf - perform a 32 bit Fowler/Noll/Vo hash on a buffer
75 *
76 * input:
77 * buf - start of buffer to hash
78 * len - length of buffer in octets
79 * hval - previous hash value or 0 if first call
80 *
81 * returns:
82 * 32 bit hash as a static hash type
83 *
84 * NOTE: To use the 32 bit FNV-0 historic hash, use FNV0_32_INIT as the hval
85 * argument on the first call to either fnv_32_buf() or fnv_32_str().
86 *
87 * NOTE: To use the recommended 32 bit FNV-1 hash, use FNV1_32_INIT as the hval
88 * argument on the first call to either fnv_32_buf() or fnv_32_str().
89 */
90Fnv32_t
91fnv_32_buf(void *buf, size_t len, Fnv32_t hval)
92{
93 unsigned char *bp = (unsigned char *)buf; /* start of buffer */
94 unsigned char *be = bp + len; /* beyond end of buffer */
95
96 /*
97 * FNV-1 hash each octet in the buffer
98 */
99 while (bp < be) {
100
101 /* multiply by the 32 bit FNV magic prime mod 2^32 */
102#if defined(NO_FNV_GCC_OPTIMIZATION)
103 hval *= FNV_32_PRIME;
104#else
105 hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
106#endif
107
108 /* xor the bottom with the current octet */
109 hval ^= (Fnv32_t)*bp++;
110 }
111
112 /* return our new hash value */
113 return hval;
114}
115
116
117/*
118 * fnv_32_str - perform a 32 bit Fowler/Noll/Vo hash on a string
119 *
120 * input:
121 * str - string to hash
122 * hval - previous hash value or 0 if first call
123 *
124 * returns:
125 * 32 bit hash as a static hash type
126 *
127 * NOTE: To use the 32 bit FNV-0 historic hash, use FNV0_32_INIT as the hval
128 * argument on the first call to either fnv_32_buf() or fnv_32_str().
129 *
130 * NOTE: To use the recommended 32 bit FNV-1 hash, use FNV1_32_INIT as the hval
131 * argument on the first call to either fnv_32_buf() or fnv_32_str().
132 */
133Fnv32_t
134fnv_32_str(char *str, Fnv32_t hval)
135{
136 unsigned char *s = (unsigned char *)str; /* unsigned string */
137
138 /*
139 * FNV-1 hash each octet in the buffer
140 */
141 while (*s) {
142
143 /* multiply by the 32 bit FNV magic prime mod 2^32 */
144#if defined(NO_FNV_GCC_OPTIMIZATION)
145 hval *= FNV_32_PRIME;
146#else
147 hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
148#endif
149
150 /* xor the bottom with the current octet */
151 hval ^= (Fnv32_t)*s++;
152 }
153
154 /* return our new hash value */
155 return hval;
156}
diff --git a/lib/fnv/hash_32a.c b/lib/fnv/hash_32a.c
new file mode 100644
index 0000000000..8b10acf3e2
--- /dev/null
+++ b/lib/fnv/hash_32a.c
@@ -0,0 +1,144 @@
1/*
2 * hash_32 - 32 bit Fowler/Noll/Vo FNV-1a hash code
3 *
4 * @(#) $Revision: 5.1 $
5 * @(#) $Id: hash_32a.c,v 5.1 2009/06/30 09:13:32 chongo Exp $
6 * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_32a.c,v $
7 *
8 ***
9 *
10 * Fowler/Noll/Vo hash
11 *
12 * The basis of this hash algorithm was taken from an idea sent
13 * as reviewer comments to the IEEE POSIX P1003.2 committee by:
14 *
15 * Phong Vo (http://www.research.att.com/info/kpv/)
16 * Glenn Fowler (http://www.research.att.com/~gsf/)
17 *
18 * In a subsequent ballot round:
19 *
20 * Landon Curt Noll (http://www.isthe.com/chongo/)
21 *
22 * improved on their algorithm. Some people tried this hash
23 * and found that it worked rather well. In an EMail message
24 * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
25 *
26 * FNV hashes are designed to be fast while maintaining a low
27 * collision rate. The FNV speed allows one to quickly hash lots
28 * of data while maintaining a reasonable collision rate. See:
29 *
30 * http://www.isthe.com/chongo/tech/comp/fnv/index.html
31 *
32 * for more details as well as other forms of the FNV hash.
33 ***
34 *
35 * To use the recommended 32 bit FNV-1a hash, pass FNV1_32A_INIT as the
36 * Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str().
37 *
38 ***
39 *
40 * Please do not copyright this code. This code is in the public domain.
41 *
42 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
43 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
44 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
45 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
46 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
47 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
48 * PERFORMANCE OF THIS SOFTWARE.
49 *
50 * By:
51 * chongo <Landon Curt Noll> /\oo/\
52 * http://www.isthe.com/chongo/
53 *
54 * Share and Enjoy! :-)
55 */
56
57#include <stdlib.h>
58#include "fnv.h"
59
60
61/*
62 * 32 bit magic FNV-1a prime
63 */
64#define FNV_32_PRIME ((Fnv32_t)0x01000193)
65
66
67/*
68 * fnv_32a_buf - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a buffer
69 *
70 * input:
71 * buf - start of buffer to hash
72 * len - length of buffer in octets
73 * hval - previous hash value or 0 if first call
74 *
75 * returns:
76 * 32 bit hash as a static hash type
77 *
78 * NOTE: To use the recommended 32 bit FNV-1a hash, use FNV1_32A_INIT as the
79 * hval arg on the first call to either fnv_32a_buf() or fnv_32a_str().
80 */
81Fnv32_t
82fnv_32a_buf(void *buf, size_t len, Fnv32_t hval)
83{
84 unsigned char *bp = (unsigned char *)buf; /* start of buffer */
85 unsigned char *be = bp + len; /* beyond end of buffer */
86
87 /*
88 * FNV-1a hash each octet in the buffer
89 */
90 while (bp < be) {
91
92 /* xor the bottom with the current octet */
93 hval ^= (Fnv32_t)*bp++;
94
95 /* multiply by the 32 bit FNV magic prime mod 2^32 */
96#if defined(NO_FNV_GCC_OPTIMIZATION)
97 hval *= FNV_32_PRIME;
98#else
99 hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
100#endif
101 }
102
103 /* return our new hash value */
104 return hval;
105}
106
107
108/*
109 * fnv_32a_str - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a string
110 *
111 * input:
112 * str - string to hash
113 * hval - previous hash value or 0 if first call
114 *
115 * returns:
116 * 32 bit hash as a static hash type
117 *
118 * NOTE: To use the recommended 32 bit FNV-1a hash, use FNV1_32A_INIT as the
119 * hval arg on the first call to either fnv_32a_buf() or fnv_32a_str().
120 */
121Fnv32_t
122fnv_32a_str(char *str, Fnv32_t hval)
123{
124 unsigned char *s = (unsigned char *)str; /* unsigned string */
125
126 /*
127 * FNV-1a hash each octet in the buffer
128 */
129 while (*s) {
130
131 /* xor the bottom with the current octet */
132 hval ^= (Fnv32_t)*s++;
133
134 /* multiply by the 32 bit FNV magic prime mod 2^32 */
135#if defined(NO_FNV_GCC_OPTIMIZATION)
136 hval *= FNV_32_PRIME;
137#else
138 hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
139#endif
140 }
141
142 /* return our new hash value */
143 return hval;
144}
diff --git a/lib/fnv/hash_64.c b/lib/fnv/hash_64.c
new file mode 100644
index 0000000000..4338605dca
--- /dev/null
+++ b/lib/fnv/hash_64.c
@@ -0,0 +1,312 @@
1/*
2 * hash_64 - 64 bit Fowler/Noll/Vo-0 hash code
3 *
4 * @(#) $Revision: 5.1 $
5 * @(#) $Id: hash_64.c,v 5.1 2009/06/30 09:01:38 chongo Exp $
6 * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_64.c,v $
7 *
8 ***
9 *
10 * Fowler/Noll/Vo hash
11 *
12 * The basis of this hash algorithm was taken from an idea sent
13 * as reviewer comments to the IEEE POSIX P1003.2 committee by:
14 *
15 * Phong Vo (http://www.research.att.com/info/kpv/)
16 * Glenn Fowler (http://www.research.att.com/~gsf/)
17 *
18 * In a subsequent ballot round:
19 *
20 * Landon Curt Noll (http://www.isthe.com/chongo/)
21 *
22 * improved on their algorithm. Some people tried this hash
23 * and found that it worked rather well. In an EMail message
24 * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
25 *
26 * FNV hashes are designed to be fast while maintaining a low
27 * collision rate. The FNV speed allows one to quickly hash lots
28 * of data while maintaining a reasonable collision rate. See:
29 *
30 * http://www.isthe.com/chongo/tech/comp/fnv/index.html
31 *
32 * for more details as well as other forms of the FNV hash.
33 *
34 ***
35 *
36 * NOTE: The FNV-0 historic hash is not recommended. One should use
37 * the FNV-1 hash instead.
38 *
39 * To use the 64 bit FNV-0 historic hash, pass FNV0_64_INIT as the
40 * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str().
41 *
42 * To use the recommended 64 bit FNV-1 hash, pass FNV1_64_INIT as the
43 * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str().
44 *
45 ***
46 *
47 * Please do not copyright this code. This code is in the public domain.
48 *
49 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
50 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
51 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
52 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
53 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
54 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
55 * PERFORMANCE OF THIS SOFTWARE.
56 *
57 * By:
58 * chongo <Landon Curt Noll> /\oo/\
59 * http://www.isthe.com/chongo/
60 *
61 * Share and Enjoy! :-)
62 */
63
64#include <stdlib.h>
65#include "fnv.h"
66
67
68/*
69 * FNV-0 defines the initial basis to be zero
70 */
71#if !defined(HAVE_64BIT_LONG_LONG)
72const Fnv64_t fnv0_64_init = { 0UL, 0UL };
73#endif /* ! HAVE_64BIT_LONG_LONG */
74
75
76/*
77 * FNV-1 defines the initial basis to be non-zero
78 */
79#if !defined(HAVE_64BIT_LONG_LONG)
80const Fnv64_t fnv1_64_init = { 0x84222325UL, 0xcbf29ce4UL };
81#endif /* ! HAVE_64BIT_LONG_LONG */
82
83
84/*
85 * 64 bit magic FNV-0 and FNV-1 prime
86 */
87#if defined(HAVE_64BIT_LONG_LONG)
88#define FNV_64_PRIME ((Fnv64_t)0x100000001b3ULL)
89#else /* HAVE_64BIT_LONG_LONG */
90#define FNV_64_PRIME_LOW ((unsigned long)0x1b3) /* lower bits of FNV prime */
91#define FNV_64_PRIME_SHIFT (8) /* top FNV prime shift above 2^32 */
92#endif /* HAVE_64BIT_LONG_LONG */
93
94
95/*
96 * fnv_64_buf - perform a 64 bit Fowler/Noll/Vo hash on a buffer
97 *
98 * input:
99 * buf - start of buffer to hash
100 * len - length of buffer in octets
101 * hval - previous hash value or 0 if first call
102 *
103 * returns:
104 * 64 bit hash as a static hash type
105 *
106 * NOTE: To use the 64 bit FNV-0 historic hash, use FNV0_64_INIT as the hval
107 * argument on the first call to either fnv_64_buf() or fnv_64_str().
108 *
109 * NOTE: To use the recommended 64 bit FNV-1 hash, use FNV1_64_INIT as the hval
110 * argument on the first call to either fnv_64_buf() or fnv_64_str().
111 */
112Fnv64_t
113fnv_64_buf(void *buf, size_t len, Fnv64_t hval)
114{
115 unsigned char *bp = (unsigned char *)buf; /* start of buffer */
116 unsigned char *be = bp + len; /* beyond end of buffer */
117
118#if defined(HAVE_64BIT_LONG_LONG)
119
120 /*
121 * FNV-1 hash each octet of the buffer
122 */
123 while (bp < be) {
124
125 /* multiply by the 64 bit FNV magic prime mod 2^64 */
126#if defined(NO_FNV_GCC_OPTIMIZATION)
127 hval *= FNV_64_PRIME;
128#else /* NO_FNV_GCC_OPTIMIZATION */
129 hval += (hval << 1) + (hval << 4) + (hval << 5) +
130 (hval << 7) + (hval << 8) + (hval << 40);
131#endif /* NO_FNV_GCC_OPTIMIZATION */
132
133 /* xor the bottom with the current octet */
134 hval ^= (Fnv64_t)*bp++;
135 }
136
137#else /* HAVE_64BIT_LONG_LONG */
138
139 unsigned long val[4]; /* hash value in base 2^16 */
140 unsigned long tmp[4]; /* tmp 64 bit value */
141
142 /*
143 * Convert Fnv64_t hval into a base 2^16 array
144 */
145 val[0] = hval.w32[0];
146 val[1] = (val[0] >> 16);
147 val[0] &= 0xffff;
148 val[2] = hval.w32[1];
149 val[3] = (val[2] >> 16);
150 val[2] &= 0xffff;
151
152 /*
153 * FNV-1 hash each octet of the buffer
154 */
155 while (bp < be) {
156
157 /*
158 * multiply by the 64 bit FNV magic prime mod 2^64
159 *
160 * Using 0x100000001b3 we have the following digits base 2^16:
161 *
162 * 0x0 0x100 0x0 0x1b3
163 *
164 * which is the same as:
165 *
166 * 0x0 1<<FNV_64_PRIME_SHIFT 0x0 FNV_64_PRIME_LOW
167 */
168 /* multiply by the lowest order digit base 2^16 */
169 tmp[0] = val[0] * FNV_64_PRIME_LOW;
170 tmp[1] = val[1] * FNV_64_PRIME_LOW;
171 tmp[2] = val[2] * FNV_64_PRIME_LOW;
172 tmp[3] = val[3] * FNV_64_PRIME_LOW;
173 /* multiply by the other non-zero digit */
174 tmp[2] += val[0] << FNV_64_PRIME_SHIFT; /* tmp[2] += val[0] * 0x100 */
175 tmp[3] += val[1] << FNV_64_PRIME_SHIFT; /* tmp[3] += val[1] * 0x100 */
176 /* propagate carries */
177 tmp[1] += (tmp[0] >> 16);
178 val[0] = tmp[0] & 0xffff;
179 tmp[2] += (tmp[1] >> 16);
180 val[1] = tmp[1] & 0xffff;
181 val[3] = tmp[3] + (tmp[2] >> 16);
182 val[2] = tmp[2] & 0xffff;
183 /*
184 * Doing a val[3] &= 0xffff; is not really needed since it simply
185 * removes multiples of 2^64. We can discard these excess bits
186 * outside of the loop when we convert to Fnv64_t.
187 */
188
189 /* xor the bottom with the current octet */
190 val[0] ^= (unsigned long)*bp++;
191 }
192
193 /*
194 * Convert base 2^16 array back into an Fnv64_t
195 */
196 hval.w32[1] = ((val[3]<<16) | val[2]);
197 hval.w32[0] = ((val[1]<<16) | val[0]);
198
199#endif /* HAVE_64BIT_LONG_LONG */
200
201 /* return our new hash value */
202 return hval;
203}
204
205
206/*
207 * fnv_64_str - perform a 64 bit Fowler/Noll/Vo hash on a buffer
208 *
209 * input:
210 * buf - start of buffer to hash
211 * hval - previous hash value or 0 if first call
212 *
213 * returns:
214 * 64 bit hash as a static hash type
215 *
216 * NOTE: To use the 64 bit FNV-0 historic hash, use FNV0_64_INIT as the hval
217 * argument on the first call to either fnv_64_buf() or fnv_64_str().
218 *
219 * NOTE: To use the recommended 64 bit FNV-1 hash, use FNV1_64_INIT as the hval
220 * argument on the first call to either fnv_64_buf() or fnv_64_str().
221 */
222Fnv64_t
223fnv_64_str(char *str, Fnv64_t hval)
224{
225 unsigned char *s = (unsigned char *)str; /* unsigned string */
226
227#if defined(HAVE_64BIT_LONG_LONG)
228
229 /*
230 * FNV-1 hash each octet of the string
231 */
232 while (*s) {
233
234 /* multiply by the 64 bit FNV magic prime mod 2^64 */
235#if defined(NO_FNV_GCC_OPTIMIZATION)
236 hval *= FNV_64_PRIME;
237#else /* NO_FNV_GCC_OPTIMIZATION */
238 hval += (hval << 1) + (hval << 4) + (hval << 5) +
239 (hval << 7) + (hval << 8) + (hval << 40);
240#endif /* NO_FNV_GCC_OPTIMIZATION */
241
242 /* xor the bottom with the current octet */
243 hval ^= (Fnv64_t)*s++;
244 }
245
246#else /* !HAVE_64BIT_LONG_LONG */
247
248 unsigned long val[4]; /* hash value in base 2^16 */
249 unsigned long tmp[4]; /* tmp 64 bit value */
250
251 /*
252 * Convert Fnv64_t hval into a base 2^16 array
253 */
254 val[0] = hval.w32[0];
255 val[1] = (val[0] >> 16);
256 val[0] &= 0xffff;
257 val[2] = hval.w32[1];
258 val[3] = (val[2] >> 16);
259 val[2] &= 0xffff;
260
261 /*
262 * FNV-1 hash each octet of the string
263 */
264 while (*s) {
265
266 /*
267 * multiply by the 64 bit FNV magic prime mod 2^64
268 *
269 * Using 1099511628211, we have the following digits base 2^16:
270 *
271 * 0x0 0x100 0x0 0x1b3
272 *
273 * which is the same as:
274 *
275 * 0x0 1<<FNV_64_PRIME_SHIFT 0x0 FNV_64_PRIME_LOW
276 */
277 /* multiply by the lowest order digit base 2^16 */
278 tmp[0] = val[0] * FNV_64_PRIME_LOW;
279 tmp[1] = val[1] * FNV_64_PRIME_LOW;
280 tmp[2] = val[2] * FNV_64_PRIME_LOW;
281 tmp[3] = val[3] * FNV_64_PRIME_LOW;
282 /* multiply by the other non-zero digit */
283 tmp[2] += val[0] << FNV_64_PRIME_SHIFT; /* tmp[2] += val[0] * 0x100 */
284 tmp[3] += val[1] << FNV_64_PRIME_SHIFT; /* tmp[3] += val[1] * 0x100 */
285 /* propagate carries */
286 tmp[1] += (tmp[0] >> 16);
287 val[0] = tmp[0] & 0xffff;
288 tmp[2] += (tmp[1] >> 16);
289 val[1] = tmp[1] & 0xffff;
290 val[3] = tmp[3] + (tmp[2] >> 16);
291 val[2] = tmp[2] & 0xffff;
292 /*
293 * Doing a val[3] &= 0xffff; is not really needed since it simply
294 * removes multiples of 2^64. We can discard these excess bits
295 * outside of the loop when we convert to Fnv64_t.
296 */
297
298 /* xor the bottom with the current octet */
299 val[0] ^= (unsigned long)(*s++);
300 }
301
302 /*
303 * Convert base 2^16 array back into an Fnv64_t
304 */
305 hval.w32[1] = ((val[3]<<16) | val[2]);
306 hval.w32[0] = ((val[1]<<16) | val[0]);
307
308#endif /* !HAVE_64BIT_LONG_LONG */
309
310 /* return our new hash value */
311 return hval;
312}
diff --git a/lib/fnv/hash_64a.c b/lib/fnv/hash_64a.c
new file mode 100644
index 0000000000..6660f92ddf
--- /dev/null
+++ b/lib/fnv/hash_64a.c
@@ -0,0 +1,291 @@
1/*
2 * hash_64 - 64 bit Fowler/Noll/Vo-0 FNV-1a hash code
3 *
4 * @(#) $Revision: 5.1 $
5 * @(#) $Id: hash_64a.c,v 5.1 2009/06/30 09:01:38 chongo Exp $
6 * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_64a.c,v $
7 *
8 ***
9 *
10 * Fowler/Noll/Vo hash
11 *
12 * The basis of this hash algorithm was taken from an idea sent
13 * as reviewer comments to the IEEE POSIX P1003.2 committee by:
14 *
15 * Phong Vo (http://www.research.att.com/info/kpv/)
16 * Glenn Fowler (http://www.research.att.com/~gsf/)
17 *
18 * In a subsequent ballot round:
19 *
20 * Landon Curt Noll (http://www.isthe.com/chongo/)
21 *
22 * improved on their algorithm. Some people tried this hash
23 * and found that it worked rather well. In an EMail message
24 * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
25 *
26 * FNV hashes are designed to be fast while maintaining a low
27 * collision rate. The FNV speed allows one to quickly hash lots
28 * of data while maintaining a reasonable collision rate. See:
29 *
30 * http://www.isthe.com/chongo/tech/comp/fnv/index.html
31 *
32 * for more details as well as other forms of the FNV hash.
33 *
34 ***
35 *
36 * To use the recommended 64 bit FNV-1a hash, pass FNV1A_64_INIT as the
37 * Fnv64_t hashval argument to fnv_64a_buf() or fnv_64a_str().
38 *
39 ***
40 *
41 * Please do not copyright this code. This code is in the public domain.
42 *
43 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
44 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
45 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
46 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
47 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
48 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
49 * PERFORMANCE OF THIS SOFTWARE.
50 *
51 * By:
52 * chongo <Landon Curt Noll> /\oo/\
53 * http://www.isthe.com/chongo/
54 *
55 * Share and Enjoy! :-)
56 */
57
58#include <stdlib.h>
59#include "fnv.h"
60
61
62/*
63 * FNV-1a defines the initial basis to be non-zero
64 */
65#if !defined(HAVE_64BIT_LONG_LONG)
66const Fnv64_t fnv1a_64_init = { 0x84222325, 0xcbf29ce4 };
67#endif /* ! HAVE_64BIT_LONG_LONG */
68
69
70/*
71 * 64 bit magic FNV-1a prime
72 */
73#if defined(HAVE_64BIT_LONG_LONG)
74#define FNV_64_PRIME ((Fnv64_t)0x100000001b3ULL)
75#else /* HAVE_64BIT_LONG_LONG */
76#define FNV_64_PRIME_LOW ((unsigned long)0x1b3) /* lower bits of FNV prime */
77#define FNV_64_PRIME_SHIFT (8) /* top FNV prime shift above 2^32 */
78#endif /* HAVE_64BIT_LONG_LONG */
79
80
81/*
82 * fnv_64a_buf - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
83 *
84 * input:
85 * buf - start of buffer to hash
86 * len - length of buffer in octets
87 * hval - previous hash value or 0 if first call
88 *
89 * returns:
90 * 64 bit hash as a static hash type
91 *
92 * NOTE: To use the recommended 64 bit FNV-1a hash, use FNV1A_64_INIT as the
93 * hval arg on the first call to either fnv_64a_buf() or fnv_64a_str().
94 */
95Fnv64_t
96fnv_64a_buf(void *buf, size_t len, Fnv64_t hval)
97{
98 unsigned char *bp = (unsigned char *)buf; /* start of buffer */
99 unsigned char *be = bp + len; /* beyond end of buffer */
100
101#if defined(HAVE_64BIT_LONG_LONG)
102 /*
103 * FNV-1a hash each octet of the buffer
104 */
105 while (bp < be) {
106
107 /* xor the bottom with the current octet */
108 hval ^= (Fnv64_t)*bp++;
109
110 /* multiply by the 64 bit FNV magic prime mod 2^64 */
111#if defined(NO_FNV_GCC_OPTIMIZATION)
112 hval *= FNV_64_PRIME;
113#else /* NO_FNV_GCC_OPTIMIZATION */
114 hval += (hval << 1) + (hval << 4) + (hval << 5) +
115 (hval << 7) + (hval << 8) + (hval << 40);
116#endif /* NO_FNV_GCC_OPTIMIZATION */
117 }
118
119#else /* HAVE_64BIT_LONG_LONG */
120
121 unsigned long val[4]; /* hash value in base 2^16 */
122 unsigned long tmp[4]; /* tmp 64 bit value */
123
124 /*
125 * Convert Fnv64_t hval into a base 2^16 array
126 */
127 val[0] = hval.w32[0];
128 val[1] = (val[0] >> 16);
129 val[0] &= 0xffff;
130 val[2] = hval.w32[1];
131 val[3] = (val[2] >> 16);
132 val[2] &= 0xffff;
133
134 /*
135 * FNV-1a hash each octet of the buffer
136 */
137 while (bp < be) {
138
139 /* xor the bottom with the current octet */
140 val[0] ^= (unsigned long)*bp++;
141
142 /*
143 * multiply by the 64 bit FNV magic prime mod 2^64
144 *
145 * Using 0x100000001b3 we have the following digits base 2^16:
146 *
147 * 0x0 0x100 0x0 0x1b3
148 *
149 * which is the same as:
150 *
151 * 0x0 1<<FNV_64_PRIME_SHIFT 0x0 FNV_64_PRIME_LOW
152 */
153 /* multiply by the lowest order digit base 2^16 */
154 tmp[0] = val[0] * FNV_64_PRIME_LOW;
155 tmp[1] = val[1] * FNV_64_PRIME_LOW;
156 tmp[2] = val[2] * FNV_64_PRIME_LOW;
157 tmp[3] = val[3] * FNV_64_PRIME_LOW;
158 /* multiply by the other non-zero digit */
159 tmp[2] += val[0] << FNV_64_PRIME_SHIFT; /* tmp[2] += val[0] * 0x100 */
160 tmp[3] += val[1] << FNV_64_PRIME_SHIFT; /* tmp[3] += val[1] * 0x100 */
161 /* propagate carries */
162 tmp[1] += (tmp[0] >> 16);
163 val[0] = tmp[0] & 0xffff;
164 tmp[2] += (tmp[1] >> 16);
165 val[1] = tmp[1] & 0xffff;
166 val[3] = tmp[3] + (tmp[2] >> 16);
167 val[2] = tmp[2] & 0xffff;
168 /*
169 * Doing a val[3] &= 0xffff; is not really needed since it simply
170 * removes multiples of 2^64. We can discard these excess bits
171 * outside of the loop when we convert to Fnv64_t.
172 */
173 }
174
175 /*
176 * Convert base 2^16 array back into an Fnv64_t
177 */
178 hval.w32[1] = ((val[3]<<16) | val[2]);
179 hval.w32[0] = ((val[1]<<16) | val[0]);
180
181#endif /* HAVE_64BIT_LONG_LONG */
182
183 /* return our new hash value */
184 return hval;
185}
186
187
188/*
189 * fnv_64a_str - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
190 *
191 * input:
192 * buf - start of buffer to hash
193 * hval - previous hash value or 0 if first call
194 *
195 * returns:
196 * 64 bit hash as a static hash type
197 *
198 * NOTE: To use the recommended 64 bit FNV-1a hash, use FNV1A_64_INIT as the
199 * hval arg on the first call to either fnv_64a_buf() or fnv_64a_str().
200 */
201Fnv64_t
202fnv_64a_str(char *str, Fnv64_t hval)
203{
204 unsigned char *s = (unsigned char *)str; /* unsigned string */
205
206#if defined(HAVE_64BIT_LONG_LONG)
207
208 /*
209 * FNV-1a hash each octet of the string
210 */
211 while (*s) {
212
213 /* xor the bottom with the current octet */
214 hval ^= (Fnv64_t)*s++;
215
216 /* multiply by the 64 bit FNV magic prime mod 2^64 */
217#if defined(NO_FNV_GCC_OPTIMIZATION)
218 hval *= FNV_64_PRIME;
219#else /* NO_FNV_GCC_OPTIMIZATION */
220 hval += (hval << 1) + (hval << 4) + (hval << 5) +
221 (hval << 7) + (hval << 8) + (hval << 40);
222#endif /* NO_FNV_GCC_OPTIMIZATION */
223 }
224
225#else /* !HAVE_64BIT_LONG_LONG */
226
227 unsigned long val[4]; /* hash value in base 2^16 */
228 unsigned long tmp[4]; /* tmp 64 bit value */
229
230 /*
231 * Convert Fnv64_t hval into a base 2^16 array
232 */
233 val[0] = hval.w32[0];
234 val[1] = (val[0] >> 16);
235 val[0] &= 0xffff;
236 val[2] = hval.w32[1];
237 val[3] = (val[2] >> 16);
238 val[2] &= 0xffff;
239
240 /*
241 * FNV-1a hash each octet of the string
242 */
243 while (*s) {
244
245 /* xor the bottom with the current octet */
246
247 /*
248 * multiply by the 64 bit FNV magic prime mod 2^64
249 *
250 * Using 1099511628211, we have the following digits base 2^16:
251 *
252 * 0x0 0x100 0x0 0x1b3
253 *
254 * which is the same as:
255 *
256 * 0x0 1<<FNV_64_PRIME_SHIFT 0x0 FNV_64_PRIME_LOW
257 */
258 /* multiply by the lowest order digit base 2^16 */
259 tmp[0] = val[0] * FNV_64_PRIME_LOW;
260 tmp[1] = val[1] * FNV_64_PRIME_LOW;
261 tmp[2] = val[2] * FNV_64_PRIME_LOW;
262 tmp[3] = val[3] * FNV_64_PRIME_LOW;
263 /* multiply by the other non-zero digit */
264 tmp[2] += val[0] << FNV_64_PRIME_SHIFT; /* tmp[2] += val[0] * 0x100 */
265 tmp[3] += val[1] << FNV_64_PRIME_SHIFT; /* tmp[3] += val[1] * 0x100 */
266 /* propagate carries */
267 tmp[1] += (tmp[0] >> 16);
268 val[0] = tmp[0] & 0xffff;
269 tmp[2] += (tmp[1] >> 16);
270 val[1] = tmp[1] & 0xffff;
271 val[3] = tmp[3] + (tmp[2] >> 16);
272 val[2] = tmp[2] & 0xffff;
273 /*
274 * Doing a val[3] &= 0xffff; is not really needed since it simply
275 * removes multiples of 2^64. We can discard these excess bits
276 * outside of the loop when we convert to Fnv64_t.
277 */
278 val[0] ^= (unsigned long)(*s++);
279 }
280
281 /*
282 * Convert base 2^16 array back into an Fnv64_t
283 */
284 hval.w32[1] = ((val[3]<<16) | val[2]);
285 hval.w32[0] = ((val[1]<<16) | val[0]);
286
287#endif /* !HAVE_64BIT_LONG_LONG */
288
289 /* return our new hash value */
290 return hval;
291}
diff --git a/lib/fnv/have_ulong64.c b/lib/fnv/have_ulong64.c
new file mode 100644
index 0000000000..5c06262388
--- /dev/null
+++ b/lib/fnv/have_ulong64.c
@@ -0,0 +1,58 @@
1/*
2 * have_ulong64 - Determine if we have a 64 bit unsigned long long
3 *
4 * usage:
5 * have_ulong64 > longlong.h
6 *
7 * Not all systems have a 'long long type' so this may not compile on
8 * your system.
9 *
10 * This prog outputs the define:
11 *
12 * HAVE_64BIT_LONG_LONG
13 * defined ==> we have a 64 bit unsigned long long
14 * undefined ==> we must simulate a 64 bit unsigned long long
15 */
16/*
17 *
18 * Please do not copyright this code. This code is in the public domain.
19 *
20 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
21 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
22 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
23 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
24 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
25 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
26 * PERFORMANCE OF THIS SOFTWARE.
27 *
28 * By:
29 * chongo <Landon Curt Noll> /\oo/\
30 * http://www.isthe.com/chongo/
31 *
32 * Share and Enjoy! :-)
33 */
34
35/*
36 * have the compiler try its hand with unsigned and signed long longs
37 */
38#if ! defined(NO64BIT_LONG_LONG)
39unsigned long long val = 1099511628211ULL;
40#endif /* NO64BIT_LONG_LONG */
41
42int
43main(void)
44{
45 /*
46 * ensure that the length of long long val is what we expect
47 */
48#if defined(NO64BIT_LONG_LONG)
49 printf("#undef HAVE_64BIT_LONG_LONG\t/* no */\n");
50#else /* NO64BIT_LONG_LONG */
51 if (val == 1099511628211ULL && sizeof(val) == 8) {
52 printf("#define HAVE_64BIT_LONG_LONG\t/* yes */\n");
53 }
54#endif /* NO64BIT_LONG_LONG */
55
56 /* exit(0); */
57 return 0;
58}
diff --git a/lib/fnv/longlong.h b/lib/fnv/longlong.h
new file mode 100644
index 0000000000..c8cfe48f29
--- /dev/null
+++ b/lib/fnv/longlong.h
@@ -0,0 +1,18 @@
1/*
2 * DO NOT EDIT -- generated by the Makefile
3 */
4
5#if !defined(__LONGLONG_H__)
6#define __LONGLONG_H__
7
8/* do we have/want to use a long long type? */
9#define HAVE_64BIT_LONG_LONG /* yes */
10
11/*
12 * NO64BIT_LONG_LONG undef HAVE_64BIT_LONG_LONG
13 */
14#if defined(NO64BIT_LONG_LONG)
15#undef HAVE_64BIT_LONG_LONG
16#endif /* NO64BIT_LONG_LONG */
17
18#endif /* !__LONGLONG_H__ */
diff --git a/lib/fnv/qmk_fnv_type_validation.c b/lib/fnv/qmk_fnv_type_validation.c
new file mode 100644
index 0000000000..e8576617ba
--- /dev/null
+++ b/lib/fnv/qmk_fnv_type_validation.c
@@ -0,0 +1,14 @@
1// Copyright 2022 Nick Brassel (@tzarc)
2// SPDX-License-Identifier: GPL-2.0-or-later
3#include "fnv.h"
4
5// This library was originally sourced from:
6// http://www.isthe.com/chongo/tech/comp/fnv/index.html
7//
8// Version at the time of retrieval on 2022-06-26: v5.0.3
9
10_Static_assert(sizeof(long long) == 8, "long long should be 64 bits");
11_Static_assert(sizeof(unsigned long long) == 8, "unsigned long long should be 64 bits");
12
13_Static_assert(sizeof(Fnv32_t) == 4, "Fnv32_t should be 32 bits");
14_Static_assert(sizeof(Fnv64_t) == 8, "Fnv64_t should be 64 bits");
diff --git a/lib/fnv/test_fnv.c b/lib/fnv/test_fnv.c
new file mode 100644
index 0000000000..efec3dec1d
--- /dev/null
+++ b/lib/fnv/test_fnv.c
@@ -0,0 +1,2237 @@
1/*
2 * test_fnv - FNV test suite
3 *
4 * @(#) $Revision: 5.3 $
5 * @(#) $Id: test_fnv.c,v 5.3 2009/06/30 11:50:41 chongo Exp $
6 * @(#) $Source: /usr/local/src/cmd/fnv/RCS/test_fnv.c,v $
7 *
8 ***
9 *
10 * Fowler/Noll/Vo hash
11 *
12 * The basis of this hash algorithm was taken from an idea sent
13 * as reviewer comments to the IEEE POSIX P1003.2 committee by:
14 *
15 * Phong Vo (http://www.research.att.com/info/kpv/)
16 * Glenn Fowler (http://www.research.att.com/~gsf/)
17 *
18 * In a subsequent ballot round:
19 *
20 * Landon Curt Noll (http://www.isthe.com/chongo/)
21 *
22 * improved on their algorithm. Some people tried this hash
23 * and found that it worked rather well. In an EMail message
24 * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
25 *
26 * FNV hashes are designed to be fast while maintaining a low
27 * collision rate. The FNV speed allows one to quickly hash lots
28 * of data while maintaining a reasonable collision rate. See:
29 *
30 * http://www.isthe.com/chongo/tech/comp/fnv/index.html
31 *
32 * for more details as well as other forms of the FNV hash.
33 *
34 ***
35 *
36 * Please do not copyright this code. This code is in the public domain.
37 *
38 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
39 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
40 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
41 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
42 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
43 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
44 * PERFORMANCE OF THIS SOFTWARE.
45 *
46 * By:
47 * chongo <Landon Curt Noll> /\oo/\
48 * http://www.isthe.com/chongo/
49 *
50 * Share and Enjoy! :-)
51 */
52
53#include <stdio.h>
54#include "longlong.h"
55#include "fnv.h"
56
57#define LEN(x) (sizeof(x)-1)
58/* TEST macro does not include trailing NUL byte in the test vector */
59#define TEST(x) {x, LEN(x)}
60/* TEST0 macro includes the trailing NUL byte in the test vector */
61#define TEST0(x) {x, sizeof(x)}
62/* REPEAT500 - repeat a string 500 times */
63#define R500(x) R100(x)R100(x)R100(x)R100(x)R100(x)
64#define R100(x) R10(x)R10(x)R10(x)R10(x)R10(x)R10(x)R10(x)R10(x)R10(x)R10(x)
65#define R10(x) x x x x x x x x x x
66
67/*
68 * FNV test vectors
69 *
70 * NOTE: A NULL pointer marks beyond the end of the test vectors.
71 *
72 * NOTE: The order of the fnv_test_str[] test vectors is 1-to-1 with:
73 *
74 * struct fnv0_32_test_vector fnv0_32_vector[];
75 * struct fnv1_32_test_vector fnv1_32_vector[];
76 * struct fnv1a_32_test_vector fnv1a_32_vector[];
77 * struct fnv0_64_test_vector fnv0_64_vector[];
78 * struct fnv1_64_test_vector fnv1_64_vector[];
79 * struct fnv1a_64_test_vector fnv1a_64_vector[];
80 *
81 * IMPORTANT NOTE:
82 *
83 * If you change the fnv_test_str[] array, you need
84 * to also change ALL of the above fnv*_vector arrays!!!
85 *
86 * To rebuild, try:
87 *
88 * make vector.c
89 *
90 * and then fold the results into the source file.
91 * Of course, you better make sure that the vaules
92 * produced by the above command are valid, otherwise
93 * you will be testing against invalid vectors!
94 */
95struct test_vector fnv_test_str[] = {
96 TEST(""),
97 TEST("a"),
98 TEST("b"),
99 TEST("c"),
100 TEST("d"),
101 TEST("e"),
102 TEST("f"),
103 TEST("fo"),
104 TEST("foo"),
105 TEST("foob"),
106 TEST("fooba"),
107 TEST("foobar"),
108 TEST0(""),
109 TEST0("a"),
110 TEST0("b"),
111 TEST0("c"),
112 TEST0("d"),
113 TEST0("e"),
114 TEST0("f"),
115 TEST0("fo"),
116 TEST0("foo"),
117 TEST0("foob"),
118 TEST0("fooba"),
119 TEST0("foobar"),
120 TEST("ch"),
121 TEST("cho"),
122 TEST("chon"),
123 TEST("chong"),
124 TEST("chongo"),
125 TEST("chongo "),
126 TEST("chongo w"),
127 TEST("chongo wa"),
128 TEST("chongo was"),
129 TEST("chongo was "),
130 TEST("chongo was h"),
131 TEST("chongo was he"),
132 TEST("chongo was her"),
133 TEST("chongo was here"),
134 TEST("chongo was here!"),
135 TEST("chongo was here!\n"),
136 TEST0("ch"),
137 TEST0("cho"),
138 TEST0("chon"),
139 TEST0("chong"),
140 TEST0("chongo"),
141 TEST0("chongo "),
142 TEST0("chongo w"),
143 TEST0("chongo wa"),
144 TEST0("chongo was"),
145 TEST0("chongo was "),
146 TEST0("chongo was h"),
147 TEST0("chongo was he"),
148 TEST0("chongo was her"),
149 TEST0("chongo was here"),
150 TEST0("chongo was here!"),
151 TEST0("chongo was here!\n"),
152 TEST("cu"),
153 TEST("cur"),
154 TEST("curd"),
155 TEST("curds"),
156 TEST("curds "),
157 TEST("curds a"),
158 TEST("curds an"),
159 TEST("curds and"),
160 TEST("curds and "),
161 TEST("curds and w"),
162 TEST("curds and wh"),
163 TEST("curds and whe"),
164 TEST("curds and whey"),
165 TEST("curds and whey\n"),
166 TEST0("cu"),
167 TEST0("cur"),
168 TEST0("curd"),
169 TEST0("curds"),
170 TEST0("curds "),
171 TEST0("curds a"),
172 TEST0("curds an"),
173 TEST0("curds and"),
174 TEST0("curds and "),
175 TEST0("curds and w"),
176 TEST0("curds and wh"),
177 TEST0("curds and whe"),
178 TEST0("curds and whey"),
179 TEST0("curds and whey\n"),
180 TEST("hi"), TEST0("hi"),
181 TEST("hello"), TEST0("hello"),
182 TEST("\xff\x00\x00\x01"), TEST("\x01\x00\x00\xff"),
183 TEST("\xff\x00\x00\x02"), TEST("\x02\x00\x00\xff"),
184 TEST("\xff\x00\x00\x03"), TEST("\x03\x00\x00\xff"),
185 TEST("\xff\x00\x00\x04"), TEST("\x04\x00\x00\xff"),
186 TEST("\x40\x51\x4e\x44"), TEST("\x44\x4e\x51\x40"),
187 TEST("\x40\x51\x4e\x4a"), TEST("\x4a\x4e\x51\x40"),
188 TEST("\x40\x51\x4e\x54"), TEST("\x54\x4e\x51\x40"),
189 TEST("127.0.0.1"), TEST0("127.0.0.1"),
190 TEST("127.0.0.2"), TEST0("127.0.0.2"),
191 TEST("127.0.0.3"), TEST0("127.0.0.3"),
192 TEST("64.81.78.68"), TEST0("64.81.78.68"),
193 TEST("64.81.78.74"), TEST0("64.81.78.74"),
194 TEST("64.81.78.84"), TEST0("64.81.78.84"),
195 TEST("feedface"), TEST0("feedface"),
196 TEST("feedfacedaffdeed"), TEST0("feedfacedaffdeed"),
197 TEST("feedfacedeadbeef"), TEST0("feedfacedeadbeef"),
198 TEST("line 1\nline 2\nline 3"),
199 TEST("chongo <Landon Curt Noll> /\\../\\"),
200 TEST0("chongo <Landon Curt Noll> /\\../\\"),
201 TEST("chongo (Landon Curt Noll) /\\../\\"),
202 TEST0("chongo (Landon Curt Noll) /\\../\\"),
203 TEST("http://antwrp.gsfc.nasa.gov/apod/astropix.html"),
204 TEST("http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash"),
205 TEST("http://epod.usra.edu/"),
206 TEST("http://exoplanet.eu/"),
207 TEST("http://hvo.wr.usgs.gov/cam3/"),
208 TEST("http://hvo.wr.usgs.gov/cams/HMcam/"),
209 TEST("http://hvo.wr.usgs.gov/kilauea/update/deformation.html"),
210 TEST("http://hvo.wr.usgs.gov/kilauea/update/images.html"),
211 TEST("http://hvo.wr.usgs.gov/kilauea/update/maps.html"),
212 TEST("http://hvo.wr.usgs.gov/volcanowatch/current_issue.html"),
213 TEST("http://neo.jpl.nasa.gov/risk/"),
214 TEST("http://norvig.com/21-days.html"),
215 TEST("http://primes.utm.edu/curios/home.php"),
216 TEST("http://slashdot.org/"),
217 TEST("http://tux.wr.usgs.gov/Maps/155.25-19.5.html"),
218 TEST("http://volcano.wr.usgs.gov/kilaueastatus.php"),
219 TEST("http://www.avo.alaska.edu/activity/Redoubt.php"),
220 TEST("http://www.dilbert.com/fast/"),
221 TEST("http://www.fourmilab.ch/gravitation/orbits/"),
222 TEST("http://www.fpoa.net/"),
223 TEST("http://www.ioccc.org/index.html"),
224 TEST("http://www.isthe.com/cgi-bin/number.cgi"),
225 TEST("http://www.isthe.com/chongo/bio.html"),
226 TEST("http://www.isthe.com/chongo/index.html"),
227 TEST("http://www.isthe.com/chongo/src/calc/lucas-calc"),
228 TEST("http://www.isthe.com/chongo/tech/astro/venus2004.html"),
229 TEST("http://www.isthe.com/chongo/tech/astro/vita.html"),
230 TEST("http://www.isthe.com/chongo/tech/comp/c/expert.html"),
231 TEST("http://www.isthe.com/chongo/tech/comp/calc/index.html"),
232 TEST("http://www.isthe.com/chongo/tech/comp/fnv/index.html"),
233 TEST("http://www.isthe.com/chongo/tech/math/number/howhigh.html"),
234 TEST("http://www.isthe.com/chongo/tech/math/number/number.html"),
235 TEST("http://www.isthe.com/chongo/tech/math/prime/mersenne.html"),
236 TEST("http://www.isthe.com/chongo/tech/math/prime/mersenne.html#largest"),
237 TEST("http://www.lavarnd.org/cgi-bin/corpspeak.cgi"),
238 TEST("http://www.lavarnd.org/cgi-bin/haiku.cgi"),
239 TEST("http://www.lavarnd.org/cgi-bin/rand-none.cgi"),
240 TEST("http://www.lavarnd.org/cgi-bin/randdist.cgi"),
241 TEST("http://www.lavarnd.org/index.html"),
242 TEST("http://www.lavarnd.org/what/nist-test.html"),
243 TEST("http://www.macosxhints.com/"),
244 TEST("http://www.mellis.com/"),
245 TEST("http://www.nature.nps.gov/air/webcams/parks/havoso2alert/havoalert.cfm"),
246 TEST("http://www.nature.nps.gov/air/webcams/parks/havoso2alert/timelines_24.cfm"),
247 TEST("http://www.paulnoll.com/"),
248 TEST("http://www.pepysdiary.com/"),
249 TEST("http://www.sciencenews.org/index/home/activity/view"),
250 TEST("http://www.skyandtelescope.com/"),
251 TEST("http://www.sput.nl/~rob/sirius.html"),
252 TEST("http://www.systemexperts.com/"),
253 TEST("http://www.tq-international.com/phpBB3/index.php"),
254 TEST("http://www.travelquesttours.com/index.htm"),
255 TEST("http://www.wunderground.com/global/stations/89606.html"),
256 TEST(R10("21701")),
257 TEST(R10("M21701")),
258 TEST(R10("2^21701-1")),
259 TEST(R10("\x54\xc5")),
260 TEST(R10("\xc5\x54")),
261 TEST(R10("23209")),
262 TEST(R10("M23209")),
263 TEST(R10("2^23209-1")),
264 TEST(R10("\x5a\xa9")),
265 TEST(R10("\xa9\x5a")),
266 TEST(R10("391581216093")),
267 TEST(R10("391581*2^216093-1")),
268 TEST(R10("\x05\xf9\x9d\x03\x4c\x81")),
269 TEST(R10("FEDCBA9876543210")),
270 TEST(R10("\xfe\xdc\xba\x98\x76\x54\x32\x10")),
271 TEST(R10("EFCDAB8967452301")),
272 TEST(R10("\xef\xcd\xab\x89\x67\x45\x23\x01")),
273 TEST(R10("0123456789ABCDEF")),
274 TEST(R10("\x01\x23\x45\x67\x89\xab\xcd\xef")),
275 TEST(R10("1032547698BADCFE")),
276 TEST(R10("\x10\x32\x54\x76\x98\xba\xdc\xfe")),
277 TEST(R500("\x00")),
278 TEST(R500("\x07")),
279 TEST(R500("~")),
280 TEST(R500("\x7f")),
281 {NULL, 0} /* MUST BE LAST */
282};
283
284
285/*
286 * insert the contents of vector.c below
287 *
288 * make vector.c
289 * :r vector.c
290 */
291/* start of output generated by make vector.c */
292
293/* FNV-0 32 bit test vectors */
294struct fnv0_32_test_vector fnv0_32_vector[] = {
295 { &fnv_test_str[0], (Fnv32_t) 0x00000000UL },
296 { &fnv_test_str[1], (Fnv32_t) 0x00000061UL },
297 { &fnv_test_str[2], (Fnv32_t) 0x00000062UL },
298 { &fnv_test_str[3], (Fnv32_t) 0x00000063UL },
299 { &fnv_test_str[4], (Fnv32_t) 0x00000064UL },
300 { &fnv_test_str[5], (Fnv32_t) 0x00000065UL },
301 { &fnv_test_str[6], (Fnv32_t) 0x00000066UL },
302 { &fnv_test_str[7], (Fnv32_t) 0x6600a0fdUL },
303 { &fnv_test_str[8], (Fnv32_t) 0x8ffd6e28UL },
304 { &fnv_test_str[9], (Fnv32_t) 0xd3f4689aUL },
305 { &fnv_test_str[10], (Fnv32_t) 0x43c0aa0fUL },
306 { &fnv_test_str[11], (Fnv32_t) 0xb74bb5efUL },
307 { &fnv_test_str[12], (Fnv32_t) 0x00000000UL },
308 { &fnv_test_str[13], (Fnv32_t) 0x610098b3UL },
309 { &fnv_test_str[14], (Fnv32_t) 0x62009a46UL },
310 { &fnv_test_str[15], (Fnv32_t) 0x63009bd9UL },
311 { &fnv_test_str[16], (Fnv32_t) 0x64009d6cUL },
312 { &fnv_test_str[17], (Fnv32_t) 0x65009effUL },
313 { &fnv_test_str[18], (Fnv32_t) 0x6600a092UL },
314 { &fnv_test_str[19], (Fnv32_t) 0x8ffd6e47UL },
315 { &fnv_test_str[20], (Fnv32_t) 0xd3f468f8UL },
316 { &fnv_test_str[21], (Fnv32_t) 0x43c0aa6eUL },
317 { &fnv_test_str[22], (Fnv32_t) 0xb74bb59dUL },
318 { &fnv_test_str[23], (Fnv32_t) 0x7b2f673dUL },
319 { &fnv_test_str[24], (Fnv32_t) 0x63009bb1UL },
320 { &fnv_test_str[25], (Fnv32_t) 0x8af517ccUL },
321 { &fnv_test_str[26], (Fnv32_t) 0x8bd4764aUL },
322 { &fnv_test_str[27], (Fnv32_t) 0x69763619UL },
323 { &fnv_test_str[28], (Fnv32_t) 0x1e172934UL },
324 { &fnv_test_str[29], (Fnv32_t) 0x9275dcfcUL },
325 { &fnv_test_str[30], (Fnv32_t) 0x8b8ae0c3UL },
326 { &fnv_test_str[31], (Fnv32_t) 0x6e9fd298UL },
327 { &fnv_test_str[32], (Fnv32_t) 0xbd98853bUL },
328 { &fnv_test_str[33], (Fnv32_t) 0xb219bbc1UL },
329 { &fnv_test_str[34], (Fnv32_t) 0x1f8290bbUL },
330 { &fnv_test_str[35], (Fnv32_t) 0x5589d604UL },
331 { &fnv_test_str[36], (Fnv32_t) 0xabfbe83eUL },
332 { &fnv_test_str[37], (Fnv32_t) 0xfb8e99ffUL },
333 { &fnv_test_str[38], (Fnv32_t) 0x007c6c4cUL },
334 { &fnv_test_str[39], (Fnv32_t) 0x0fde7baeUL },
335 { &fnv_test_str[40], (Fnv32_t) 0x8af517a3UL },
336 { &fnv_test_str[41], (Fnv32_t) 0x8bd47624UL },
337 { &fnv_test_str[42], (Fnv32_t) 0x6976367eUL },
338 { &fnv_test_str[43], (Fnv32_t) 0x1e17295bUL },
339 { &fnv_test_str[44], (Fnv32_t) 0x9275dcdcUL },
340 { &fnv_test_str[45], (Fnv32_t) 0x8b8ae0b4UL },
341 { &fnv_test_str[46], (Fnv32_t) 0x6e9fd2f9UL },
342 { &fnv_test_str[47], (Fnv32_t) 0xbd988548UL },
343 { &fnv_test_str[48], (Fnv32_t) 0xb219bbe1UL },
344 { &fnv_test_str[49], (Fnv32_t) 0x1f8290d3UL },
345 { &fnv_test_str[50], (Fnv32_t) 0x5589d661UL },
346 { &fnv_test_str[51], (Fnv32_t) 0xabfbe84cUL },
347 { &fnv_test_str[52], (Fnv32_t) 0xfb8e999aUL },
348 { &fnv_test_str[53], (Fnv32_t) 0x007c6c6dUL },
349 { &fnv_test_str[54], (Fnv32_t) 0x0fde7ba4UL },
350 { &fnv_test_str[55], (Fnv32_t) 0xa93cb2eaUL },
351 { &fnv_test_str[56], (Fnv32_t) 0x63009bacUL },
352 { &fnv_test_str[57], (Fnv32_t) 0x85f50fb6UL },
353 { &fnv_test_str[58], (Fnv32_t) 0x96c7bbe6UL },
354 { &fnv_test_str[59], (Fnv32_t) 0x426ccb61UL },
355 { &fnv_test_str[60], (Fnv32_t) 0xf2442993UL },
356 { &fnv_test_str[61], (Fnv32_t) 0xf44d7208UL },
357 { &fnv_test_str[62], (Fnv32_t) 0x9dea82f6UL },
358 { &fnv_test_str[63], (Fnv32_t) 0x8e2c2926UL },
359 { &fnv_test_str[64], (Fnv32_t) 0xf584c6f2UL },
360 { &fnv_test_str[65], (Fnv32_t) 0x72052e81UL },
361 { &fnv_test_str[66], (Fnv32_t) 0xff28357bUL },
362 { &fnv_test_str[67], (Fnv32_t) 0x274c30c4UL },
363 { &fnv_test_str[68], (Fnv32_t) 0xa0f0c4f5UL },
364 { &fnv_test_str[69], (Fnv32_t) 0x50060da5UL },
365 { &fnv_test_str[70], (Fnv32_t) 0x85f50fc4UL },
366 { &fnv_test_str[71], (Fnv32_t) 0x96c7bb82UL },
367 { &fnv_test_str[72], (Fnv32_t) 0x426ccb12UL },
368 { &fnv_test_str[73], (Fnv32_t) 0xf24429b3UL },
369 { &fnv_test_str[74], (Fnv32_t) 0xf44d7269UL },
370 { &fnv_test_str[75], (Fnv32_t) 0x9dea8298UL },
371 { &fnv_test_str[76], (Fnv32_t) 0x8e2c2942UL },
372 { &fnv_test_str[77], (Fnv32_t) 0xf584c6d2UL },
373 { &fnv_test_str[78], (Fnv32_t) 0x72052ef6UL },
374 { &fnv_test_str[79], (Fnv32_t) 0xff283513UL },
375 { &fnv_test_str[80], (Fnv32_t) 0x274c30a1UL },
376 { &fnv_test_str[81], (Fnv32_t) 0xa0f0c48cUL },
377 { &fnv_test_str[82], (Fnv32_t) 0x50060dafUL },
378 { &fnv_test_str[83], (Fnv32_t) 0x9e877abfUL },
379 { &fnv_test_str[84], (Fnv32_t) 0x6800a3d1UL },
380 { &fnv_test_str[85], (Fnv32_t) 0x8a01e203UL },
381 { &fnv_test_str[86], (Fnv32_t) 0xec6d6be8UL },
382 { &fnv_test_str[87], (Fnv32_t) 0x1840de38UL },
383 { &fnv_test_str[88], (Fnv32_t) 0xa7cc97b4UL },
384 { &fnv_test_str[89], (Fnv32_t) 0x3ee6b3b4UL },
385 { &fnv_test_str[90], (Fnv32_t) 0xa7cc97b7UL },
386 { &fnv_test_str[91], (Fnv32_t) 0x7dcd6669UL },
387 { &fnv_test_str[92], (Fnv32_t) 0xa7cc97b6UL },
388 { &fnv_test_str[93], (Fnv32_t) 0xbcb4191eUL },
389 { &fnv_test_str[94], (Fnv32_t) 0xa7cc97b1UL },
390 { &fnv_test_str[95], (Fnv32_t) 0xfb9acdd3UL },
391 { &fnv_test_str[96], (Fnv32_t) 0x89380433UL },
392 { &fnv_test_str[97], (Fnv32_t) 0x8acd2855UL },
393 { &fnv_test_str[98], (Fnv32_t) 0x8938043dUL },
394 { &fnv_test_str[99], (Fnv32_t) 0xcaeed493UL },
395 { &fnv_test_str[100], (Fnv32_t) 0x89380423UL },
396 { &fnv_test_str[101], (Fnv32_t) 0x59382a25UL },
397 { &fnv_test_str[102], (Fnv32_t) 0x567f75d7UL },
398 { &fnv_test_str[103], (Fnv32_t) 0x01a68175UL },
399 { &fnv_test_str[104], (Fnv32_t) 0x567f75d4UL },
400 { &fnv_test_str[105], (Fnv32_t) 0xfea67cbcUL },
401 { &fnv_test_str[106], (Fnv32_t) 0x567f75d5UL },
402 { &fnv_test_str[107], (Fnv32_t) 0xffa67e4fUL },
403 { &fnv_test_str[108], (Fnv32_t) 0xd131b668UL },
404 { &fnv_test_str[109], (Fnv32_t) 0xb94225b8UL },
405 { &fnv_test_str[110], (Fnv32_t) 0xd231b7d7UL },
406 { &fnv_test_str[111], (Fnv32_t) 0xbb446775UL },
407 { &fnv_test_str[112], (Fnv32_t) 0xdf31cc6eUL },
408 { &fnv_test_str[113], (Fnv32_t) 0xc964d12aUL },
409 { &fnv_test_str[114], (Fnv32_t) 0x23af8f9fUL },
410 { &fnv_test_str[115], (Fnv32_t) 0xcc5f174dUL },
411 { &fnv_test_str[116], (Fnv32_t) 0x96b29b8cUL },
412 { &fnv_test_str[117], (Fnv32_t) 0xc72add64UL },
413 { &fnv_test_str[118], (Fnv32_t) 0x528fb7efUL },
414 { &fnv_test_str[119], (Fnv32_t) 0xe73e8d3dUL },
415 { &fnv_test_str[120], (Fnv32_t) 0x876386feUL },
416 { &fnv_test_str[121], (Fnv32_t) 0x811c9dc5UL },
417 { &fnv_test_str[122], (Fnv32_t) 0x050c5d1fUL },
418 { &fnv_test_str[123], (Fnv32_t) 0x14bf7238UL },
419 { &fnv_test_str[124], (Fnv32_t) 0xe160ce28UL },
420 { &fnv_test_str[125], (Fnv32_t) 0x89dc5a75UL },
421 { &fnv_test_str[126], (Fnv32_t) 0xd89b69a0UL },
422 { &fnv_test_str[127], (Fnv32_t) 0x94471a88UL },
423 { &fnv_test_str[128], (Fnv32_t) 0xe78db65fUL },
424 { &fnv_test_str[129], (Fnv32_t) 0x0c3009a2UL },
425 { &fnv_test_str[130], (Fnv32_t) 0x122dff03UL },
426 { &fnv_test_str[131], (Fnv32_t) 0xb4cd8875UL },
427 { &fnv_test_str[132], (Fnv32_t) 0xf4dba725UL },
428 { &fnv_test_str[133], (Fnv32_t) 0x41a16560UL },
429 { &fnv_test_str[134], (Fnv32_t) 0x9c0f941fUL },
430 { &fnv_test_str[135], (Fnv32_t) 0x451a5348UL },
431 { &fnv_test_str[136], (Fnv32_t) 0x3f1d1d89UL },
432 { &fnv_test_str[137], (Fnv32_t) 0x1b91b57aUL },
433 { &fnv_test_str[138], (Fnv32_t) 0x3e99b577UL },
434 { &fnv_test_str[139], (Fnv32_t) 0x4c9de07aUL },
435 { &fnv_test_str[140], (Fnv32_t) 0x1ddf7572UL },
436 { &fnv_test_str[141], (Fnv32_t) 0x64e81976UL },
437 { &fnv_test_str[142], (Fnv32_t) 0x1106a888UL },
438 { &fnv_test_str[143], (Fnv32_t) 0xa498d8e5UL },
439 { &fnv_test_str[144], (Fnv32_t) 0x3c03d2e3UL },
440 { &fnv_test_str[145], (Fnv32_t) 0x26568b28UL },
441 { &fnv_test_str[146], (Fnv32_t) 0x70d7fb42UL },
442 { &fnv_test_str[147], (Fnv32_t) 0xd3ae1d22UL },
443 { &fnv_test_str[148], (Fnv32_t) 0xac8ea5f4UL },
444 { &fnv_test_str[149], (Fnv32_t) 0x4d0abd60UL },
445 { &fnv_test_str[150], (Fnv32_t) 0x48f5e086UL },
446 { &fnv_test_str[151], (Fnv32_t) 0xa8f6241bUL },
447 { &fnv_test_str[152], (Fnv32_t) 0x572f864fUL },
448 { &fnv_test_str[153], (Fnv32_t) 0xa5340803UL },
449 { &fnv_test_str[154], (Fnv32_t) 0x22881aa8UL },
450 { &fnv_test_str[155], (Fnv32_t) 0xc2e2f5a2UL },
451 { &fnv_test_str[156], (Fnv32_t) 0xebf5aec7UL },
452 { &fnv_test_str[157], (Fnv32_t) 0x3cdbfb85UL },
453 { &fnv_test_str[158], (Fnv32_t) 0xbb859704UL },
454 { &fnv_test_str[159], (Fnv32_t) 0xc956fe11UL },
455 { &fnv_test_str[160], (Fnv32_t) 0x8f11a7c9UL },
456 { &fnv_test_str[161], (Fnv32_t) 0x36c48ecfUL },
457 { &fnv_test_str[162], (Fnv32_t) 0x24bfa27eUL },
458 { &fnv_test_str[163], (Fnv32_t) 0xf2596ad1UL },
459 { &fnv_test_str[164], (Fnv32_t) 0xf14a9b45UL },
460 { &fnv_test_str[165], (Fnv32_t) 0x7d45835aUL },
461 { &fnv_test_str[166], (Fnv32_t) 0x6e49334dUL },
462 { &fnv_test_str[167], (Fnv32_t) 0x71767337UL },
463 { &fnv_test_str[168], (Fnv32_t) 0x858a1a8aUL },
464 { &fnv_test_str[169], (Fnv32_t) 0x16e75ac2UL },
465 { &fnv_test_str[170], (Fnv32_t) 0x409f99dfUL },
466 { &fnv_test_str[171], (Fnv32_t) 0x6d6652ddUL },
467 { &fnv_test_str[172], (Fnv32_t) 0x2761a9ffUL },
468 { &fnv_test_str[173], (Fnv32_t) 0x41f0d616UL },
469 { &fnv_test_str[174], (Fnv32_t) 0x0e2d0d0fUL },
470 { &fnv_test_str[175], (Fnv32_t) 0x06adc8fdUL },
471 { &fnv_test_str[176], (Fnv32_t) 0x60e0d4b9UL },
472 { &fnv_test_str[177], (Fnv32_t) 0x5ddc79d3UL },
473 { &fnv_test_str[178], (Fnv32_t) 0x1e6d0b46UL },
474 { &fnv_test_str[179], (Fnv32_t) 0x1d1514d8UL },
475 { &fnv_test_str[180], (Fnv32_t) 0xb1903a4eUL },
476 { &fnv_test_str[181], (Fnv32_t) 0x8200c318UL },
477 { &fnv_test_str[182], (Fnv32_t) 0x15e22888UL },
478 { &fnv_test_str[183], (Fnv32_t) 0x57591760UL },
479 { &fnv_test_str[184], (Fnv32_t) 0x02462efcUL },
480 { &fnv_test_str[185], (Fnv32_t) 0x7651ec44UL },
481 { &fnv_test_str[186], (Fnv32_t) 0x7c24e9d4UL },
482 { &fnv_test_str[187], (Fnv32_t) 0x1952a034UL },
483 { &fnv_test_str[188], (Fnv32_t) 0xd4c46864UL },
484 { &fnv_test_str[189], (Fnv32_t) 0xcb57cde0UL },
485 { &fnv_test_str[190], (Fnv32_t) 0x71136a70UL },
486 { &fnv_test_str[191], (Fnv32_t) 0x0618fb40UL },
487 { &fnv_test_str[192], (Fnv32_t) 0x69a24fc0UL },
488 { &fnv_test_str[193], (Fnv32_t) 0x6a9be510UL },
489 { &fnv_test_str[194], (Fnv32_t) 0xe0477040UL },
490 { &fnv_test_str[195], (Fnv32_t) 0x85aa94b0UL },
491 { &fnv_test_str[196], (Fnv32_t) 0xc6d76240UL },
492 { &fnv_test_str[197], (Fnv32_t) 0xa9f09e40UL },
493 { &fnv_test_str[198], (Fnv32_t) 0xa0291540UL },
494 { &fnv_test_str[199], (Fnv32_t) 0x00000000UL },
495 { &fnv_test_str[200], (Fnv32_t) 0x2e672aa4UL },
496 { &fnv_test_str[201], (Fnv32_t) 0x84b1aa48UL },
497 { &fnv_test_str[202], (Fnv32_t) 0xfc24ba24UL },
498 { NULL, 0 }
499};
500
501/* FNV-1 32 bit test vectors */
502struct fnv1_32_test_vector fnv1_32_vector[] = {
503 { &fnv_test_str[0], (Fnv32_t) 0x811c9dc5UL },
504 { &fnv_test_str[1], (Fnv32_t) 0x050c5d7eUL },
505 { &fnv_test_str[2], (Fnv32_t) 0x050c5d7dUL },
506 { &fnv_test_str[3], (Fnv32_t) 0x050c5d7cUL },
507 { &fnv_test_str[4], (Fnv32_t) 0x050c5d7bUL },
508 { &fnv_test_str[5], (Fnv32_t) 0x050c5d7aUL },
509 { &fnv_test_str[6], (Fnv32_t) 0x050c5d79UL },
510 { &fnv_test_str[7], (Fnv32_t) 0x6b772514UL },
511 { &fnv_test_str[8], (Fnv32_t) 0x408f5e13UL },
512 { &fnv_test_str[9], (Fnv32_t) 0xb4b1178bUL },
513 { &fnv_test_str[10], (Fnv32_t) 0xfdc80fb0UL },
514 { &fnv_test_str[11], (Fnv32_t) 0x31f0b262UL },
515 { &fnv_test_str[12], (Fnv32_t) 0x050c5d1fUL },
516 { &fnv_test_str[13], (Fnv32_t) 0x70772d5aUL },
517 { &fnv_test_str[14], (Fnv32_t) 0x6f772bc7UL },
518 { &fnv_test_str[15], (Fnv32_t) 0x6e772a34UL },
519 { &fnv_test_str[16], (Fnv32_t) 0x6d7728a1UL },
520 { &fnv_test_str[17], (Fnv32_t) 0x6c77270eUL },
521 { &fnv_test_str[18], (Fnv32_t) 0x6b77257bUL },
522 { &fnv_test_str[19], (Fnv32_t) 0x408f5e7cUL },
523 { &fnv_test_str[20], (Fnv32_t) 0xb4b117e9UL },
524 { &fnv_test_str[21], (Fnv32_t) 0xfdc80fd1UL },
525 { &fnv_test_str[22], (Fnv32_t) 0x31f0b210UL },
526 { &fnv_test_str[23], (Fnv32_t) 0xffe8d046UL },
527 { &fnv_test_str[24], (Fnv32_t) 0x6e772a5cUL },
528 { &fnv_test_str[25], (Fnv32_t) 0x4197aebbUL },
529 { &fnv_test_str[26], (Fnv32_t) 0xfcc8100fUL },
530 { &fnv_test_str[27], (Fnv32_t) 0xfdf147faUL },
531 { &fnv_test_str[28], (Fnv32_t) 0xbcd44ee1UL },
532 { &fnv_test_str[29], (Fnv32_t) 0x23382c13UL },
533 { &fnv_test_str[30], (Fnv32_t) 0x846d619eUL },
534 { &fnv_test_str[31], (Fnv32_t) 0x1630abdbUL },
535 { &fnv_test_str[32], (Fnv32_t) 0xc99e89b2UL },
536 { &fnv_test_str[33], (Fnv32_t) 0x1692c316UL },
537 { &fnv_test_str[34], (Fnv32_t) 0x9f091bcaUL },
538 { &fnv_test_str[35], (Fnv32_t) 0x2556be9bUL },
539 { &fnv_test_str[36], (Fnv32_t) 0x628e0e73UL },
540 { &fnv_test_str[37], (Fnv32_t) 0x98a0bf6cUL },
541 { &fnv_test_str[38], (Fnv32_t) 0xb10d5725UL },
542 { &fnv_test_str[39], (Fnv32_t) 0xdd002f35UL },
543 { &fnv_test_str[40], (Fnv32_t) 0x4197aed4UL },
544 { &fnv_test_str[41], (Fnv32_t) 0xfcc81061UL },
545 { &fnv_test_str[42], (Fnv32_t) 0xfdf1479dUL },
546 { &fnv_test_str[43], (Fnv32_t) 0xbcd44e8eUL },
547 { &fnv_test_str[44], (Fnv32_t) 0x23382c33UL },
548 { &fnv_test_str[45], (Fnv32_t) 0x846d61e9UL },
549 { &fnv_test_str[46], (Fnv32_t) 0x1630abbaUL },
550 { &fnv_test_str[47], (Fnv32_t) 0xc99e89c1UL },
551 { &fnv_test_str[48], (Fnv32_t) 0x1692c336UL },
552 { &fnv_test_str[49], (Fnv32_t) 0x9f091ba2UL },
553 { &fnv_test_str[50], (Fnv32_t) 0x2556befeUL },
554 { &fnv_test_str[51], (Fnv32_t) 0x628e0e01UL },
555 { &fnv_test_str[52], (Fnv32_t) 0x98a0bf09UL },
556 { &fnv_test_str[53], (Fnv32_t) 0xb10d5704UL },
557 { &fnv_test_str[54], (Fnv32_t) 0xdd002f3fUL },
558 { &fnv_test_str[55], (Fnv32_t) 0x1c4a506fUL },
559 { &fnv_test_str[56], (Fnv32_t) 0x6e772a41UL },
560 { &fnv_test_str[57], (Fnv32_t) 0x26978421UL },
561 { &fnv_test_str[58], (Fnv32_t) 0xe184ff97UL },
562 { &fnv_test_str[59], (Fnv32_t) 0x9b5e5ac6UL },
563 { &fnv_test_str[60], (Fnv32_t) 0x5b88e592UL },
564 { &fnv_test_str[61], (Fnv32_t) 0xaa8164b7UL },
565 { &fnv_test_str[62], (Fnv32_t) 0x20b18c7bUL },
566 { &fnv_test_str[63], (Fnv32_t) 0xf28025c5UL },
567 { &fnv_test_str[64], (Fnv32_t) 0x84bb753fUL },
568 { &fnv_test_str[65], (Fnv32_t) 0x3219925aUL },
569 { &fnv_test_str[66], (Fnv32_t) 0x384163c6UL },
570 { &fnv_test_str[67], (Fnv32_t) 0x54f010d7UL },
571 { &fnv_test_str[68], (Fnv32_t) 0x8cea820cUL },
572 { &fnv_test_str[69], (Fnv32_t) 0xe12ab8eeUL },
573 { &fnv_test_str[70], (Fnv32_t) 0x26978453UL },
574 { &fnv_test_str[71], (Fnv32_t) 0xe184fff3UL },
575 { &fnv_test_str[72], (Fnv32_t) 0x9b5e5ab5UL },
576 { &fnv_test_str[73], (Fnv32_t) 0x5b88e5b2UL },
577 { &fnv_test_str[74], (Fnv32_t) 0xaa8164d6UL },
578 { &fnv_test_str[75], (Fnv32_t) 0x20b18c15UL },
579 { &fnv_test_str[76], (Fnv32_t) 0xf28025a1UL },
580 { &fnv_test_str[77], (Fnv32_t) 0x84bb751fUL },
581 { &fnv_test_str[78], (Fnv32_t) 0x3219922dUL },
582 { &fnv_test_str[79], (Fnv32_t) 0x384163aeUL },
583 { &fnv_test_str[80], (Fnv32_t) 0x54f010b2UL },
584 { &fnv_test_str[81], (Fnv32_t) 0x8cea8275UL },
585 { &fnv_test_str[82], (Fnv32_t) 0xe12ab8e4UL },
586 { &fnv_test_str[83], (Fnv32_t) 0x64411eaaUL },
587 { &fnv_test_str[84], (Fnv32_t) 0x6977223cUL },
588 { &fnv_test_str[85], (Fnv32_t) 0x428ae474UL },
589 { &fnv_test_str[86], (Fnv32_t) 0xb6fa7167UL },
590 { &fnv_test_str[87], (Fnv32_t) 0x73408525UL },
591 { &fnv_test_str[88], (Fnv32_t) 0xb78320a1UL },
592 { &fnv_test_str[89], (Fnv32_t) 0x0caf4135UL },
593 { &fnv_test_str[90], (Fnv32_t) 0xb78320a2UL },
594 { &fnv_test_str[91], (Fnv32_t) 0xcdc88e80UL },
595 { &fnv_test_str[92], (Fnv32_t) 0xb78320a3UL },
596 { &fnv_test_str[93], (Fnv32_t) 0x8ee1dbcbUL },
597 { &fnv_test_str[94], (Fnv32_t) 0xb78320a4UL },
598 { &fnv_test_str[95], (Fnv32_t) 0x4ffb2716UL },
599 { &fnv_test_str[96], (Fnv32_t) 0x860632aaUL },
600 { &fnv_test_str[97], (Fnv32_t) 0xcc2c5c64UL },
601 { &fnv_test_str[98], (Fnv32_t) 0x860632a4UL },
602 { &fnv_test_str[99], (Fnv32_t) 0x2a7ec4a6UL },
603 { &fnv_test_str[100], (Fnv32_t) 0x860632baUL },
604 { &fnv_test_str[101], (Fnv32_t) 0xfefe8e14UL },
605 { &fnv_test_str[102], (Fnv32_t) 0x0a3cffd8UL },
606 { &fnv_test_str[103], (Fnv32_t) 0xf606c108UL },
607 { &fnv_test_str[104], (Fnv32_t) 0x0a3cffdbUL },
608 { &fnv_test_str[105], (Fnv32_t) 0xf906c5c1UL },
609 { &fnv_test_str[106], (Fnv32_t) 0x0a3cffdaUL },
610 { &fnv_test_str[107], (Fnv32_t) 0xf806c42eUL },
611 { &fnv_test_str[108], (Fnv32_t) 0xc07167d7UL },
612 { &fnv_test_str[109], (Fnv32_t) 0xc9867775UL },
613 { &fnv_test_str[110], (Fnv32_t) 0xbf716668UL },
614 { &fnv_test_str[111], (Fnv32_t) 0xc78435b8UL },
615 { &fnv_test_str[112], (Fnv32_t) 0xc6717155UL },
616 { &fnv_test_str[113], (Fnv32_t) 0xb99568cfUL },
617 { &fnv_test_str[114], (Fnv32_t) 0x7662e0d6UL },
618 { &fnv_test_str[115], (Fnv32_t) 0x33a7f0e2UL },
619 { &fnv_test_str[116], (Fnv32_t) 0xc2732f95UL },
620 { &fnv_test_str[117], (Fnv32_t) 0xb053e78fUL },
621 { &fnv_test_str[118], (Fnv32_t) 0x3a19c02aUL },
622 { &fnv_test_str[119], (Fnv32_t) 0xa089821eUL },
623 { &fnv_test_str[120], (Fnv32_t) 0x31ae8f83UL },
624 { &fnv_test_str[121], (Fnv32_t) 0x995fa9c4UL },
625 { &fnv_test_str[122], (Fnv32_t) 0x35983f8cUL },
626 { &fnv_test_str[123], (Fnv32_t) 0x5036a251UL },
627 { &fnv_test_str[124], (Fnv32_t) 0x97018583UL },
628 { &fnv_test_str[125], (Fnv32_t) 0xb4448d60UL },
629 { &fnv_test_str[126], (Fnv32_t) 0x025dfe59UL },
630 { &fnv_test_str[127], (Fnv32_t) 0xc5eab3afUL },
631 { &fnv_test_str[128], (Fnv32_t) 0x7d21ba1eUL },
632 { &fnv_test_str[129], (Fnv32_t) 0x7704cddbUL },
633 { &fnv_test_str[130], (Fnv32_t) 0xd0071bfeUL },
634 { &fnv_test_str[131], (Fnv32_t) 0x0ff3774cUL },
635 { &fnv_test_str[132], (Fnv32_t) 0xb0fea0eaUL },
636 { &fnv_test_str[133], (Fnv32_t) 0x58177303UL },
637 { &fnv_test_str[134], (Fnv32_t) 0x4f599cdaUL },
638 { &fnv_test_str[135], (Fnv32_t) 0x3e590a47UL },
639 { &fnv_test_str[136], (Fnv32_t) 0x965595f8UL },
640 { &fnv_test_str[137], (Fnv32_t) 0xc37f178dUL },
641 { &fnv_test_str[138], (Fnv32_t) 0x9711dd26UL },
642 { &fnv_test_str[139], (Fnv32_t) 0x23c99b7fUL },
643 { &fnv_test_str[140], (Fnv32_t) 0x6e568b17UL },
644 { &fnv_test_str[141], (Fnv32_t) 0x43f0245bUL },
645 { &fnv_test_str[142], (Fnv32_t) 0xbcb7a001UL },
646 { &fnv_test_str[143], (Fnv32_t) 0x12e6dffeUL },
647 { &fnv_test_str[144], (Fnv32_t) 0x0792f2d6UL },
648 { &fnv_test_str[145], (Fnv32_t) 0xb966936bUL },
649 { &fnv_test_str[146], (Fnv32_t) 0x46439ac5UL },
650 { &fnv_test_str[147], (Fnv32_t) 0x728d49afUL },
651 { &fnv_test_str[148], (Fnv32_t) 0xd33745c9UL },
652 { &fnv_test_str[149], (Fnv32_t) 0xbc382a57UL },
653 { &fnv_test_str[150], (Fnv32_t) 0x4bda1d31UL },
654 { &fnv_test_str[151], (Fnv32_t) 0xce35ccaeUL },
655 { &fnv_test_str[152], (Fnv32_t) 0x3b6eed94UL },
656 { &fnv_test_str[153], (Fnv32_t) 0x445c9c58UL },
657 { &fnv_test_str[154], (Fnv32_t) 0x3db8bf9dUL },
658 { &fnv_test_str[155], (Fnv32_t) 0x2dee116dUL },
659 { &fnv_test_str[156], (Fnv32_t) 0xc18738daUL },
660 { &fnv_test_str[157], (Fnv32_t) 0x5b156176UL },
661 { &fnv_test_str[158], (Fnv32_t) 0x2aa7d593UL },
662 { &fnv_test_str[159], (Fnv32_t) 0xb2409658UL },
663 { &fnv_test_str[160], (Fnv32_t) 0xe1489528UL },
664 { &fnv_test_str[161], (Fnv32_t) 0xfe1ee07eUL },
665 { &fnv_test_str[162], (Fnv32_t) 0xe8842315UL },
666 { &fnv_test_str[163], (Fnv32_t) 0x3a6a63a2UL },
667 { &fnv_test_str[164], (Fnv32_t) 0x06d2c18cUL },
668 { &fnv_test_str[165], (Fnv32_t) 0xf8ef7225UL },
669 { &fnv_test_str[166], (Fnv32_t) 0x843d3300UL },
670 { &fnv_test_str[167], (Fnv32_t) 0xbb24f7aeUL },
671 { &fnv_test_str[168], (Fnv32_t) 0x878c0ec9UL },
672 { &fnv_test_str[169], (Fnv32_t) 0xb557810fUL },
673 { &fnv_test_str[170], (Fnv32_t) 0x57423246UL },
674 { &fnv_test_str[171], (Fnv32_t) 0x87f7505eUL },
675 { &fnv_test_str[172], (Fnv32_t) 0xbb809f20UL },
676 { &fnv_test_str[173], (Fnv32_t) 0x8932abb5UL },
677 { &fnv_test_str[174], (Fnv32_t) 0x0a9b3aa0UL },
678 { &fnv_test_str[175], (Fnv32_t) 0xb8682a24UL },
679 { &fnv_test_str[176], (Fnv32_t) 0xa7ac1c56UL },
680 { &fnv_test_str[177], (Fnv32_t) 0x11409252UL },
681 { &fnv_test_str[178], (Fnv32_t) 0xa987f517UL },
682 { &fnv_test_str[179], (Fnv32_t) 0xf309e7edUL },
683 { &fnv_test_str[180], (Fnv32_t) 0xc9e8f417UL },
684 { &fnv_test_str[181], (Fnv32_t) 0x7f447bddUL },
685 { &fnv_test_str[182], (Fnv32_t) 0xb929adc5UL },
686 { &fnv_test_str[183], (Fnv32_t) 0x57022879UL },
687 { &fnv_test_str[184], (Fnv32_t) 0xdcfd2c49UL },
688 { &fnv_test_str[185], (Fnv32_t) 0x6edafff5UL },
689 { &fnv_test_str[186], (Fnv32_t) 0xf04fb1f1UL },
690 { &fnv_test_str[187], (Fnv32_t) 0xfb7de8b9UL },
691 { &fnv_test_str[188], (Fnv32_t) 0xc5f1d7e9UL },
692 { &fnv_test_str[189], (Fnv32_t) 0x32c1f439UL },
693 { &fnv_test_str[190], (Fnv32_t) 0x7fd3eb7dUL },
694 { &fnv_test_str[191], (Fnv32_t) 0x81597da5UL },
695 { &fnv_test_str[192], (Fnv32_t) 0x05eb7a25UL },
696 { &fnv_test_str[193], (Fnv32_t) 0x9c0fa1b5UL },
697 { &fnv_test_str[194], (Fnv32_t) 0x53ccb1c5UL },
698 { &fnv_test_str[195], (Fnv32_t) 0xfabece15UL },
699 { &fnv_test_str[196], (Fnv32_t) 0x4ad745a5UL },
700 { &fnv_test_str[197], (Fnv32_t) 0xe5bdc495UL },
701 { &fnv_test_str[198], (Fnv32_t) 0x23b3c0a5UL },
702 { &fnv_test_str[199], (Fnv32_t) 0xfa823dd5UL },
703 { &fnv_test_str[200], (Fnv32_t) 0x0c6c58b9UL },
704 { &fnv_test_str[201], (Fnv32_t) 0xe2dbccd5UL },
705 { &fnv_test_str[202], (Fnv32_t) 0xdb7f50f9UL },
706 { NULL, 0 }
707};
708
709/* FNV-1a 32 bit test vectors */
710struct fnv1a_32_test_vector fnv1a_32_vector[] = {
711 { &fnv_test_str[0], (Fnv32_t) 0x811c9dc5UL },
712 { &fnv_test_str[1], (Fnv32_t) 0xe40c292cUL },
713 { &fnv_test_str[2], (Fnv32_t) 0xe70c2de5UL },
714 { &fnv_test_str[3], (Fnv32_t) 0xe60c2c52UL },
715 { &fnv_test_str[4], (Fnv32_t) 0xe10c2473UL },
716 { &fnv_test_str[5], (Fnv32_t) 0xe00c22e0UL },
717 { &fnv_test_str[6], (Fnv32_t) 0xe30c2799UL },
718 { &fnv_test_str[7], (Fnv32_t) 0x6222e842UL },
719 { &fnv_test_str[8], (Fnv32_t) 0xa9f37ed7UL },
720 { &fnv_test_str[9], (Fnv32_t) 0x3f5076efUL },
721 { &fnv_test_str[10], (Fnv32_t) 0x39aaa18aUL },
722 { &fnv_test_str[11], (Fnv32_t) 0xbf9cf968UL },
723 { &fnv_test_str[12], (Fnv32_t) 0x050c5d1fUL },
724 { &fnv_test_str[13], (Fnv32_t) 0x2b24d044UL },
725 { &fnv_test_str[14], (Fnv32_t) 0x9d2c3f7fUL },
726 { &fnv_test_str[15], (Fnv32_t) 0x7729c516UL },
727 { &fnv_test_str[16], (Fnv32_t) 0xb91d6109UL },
728 { &fnv_test_str[17], (Fnv32_t) 0x931ae6a0UL },
729 { &fnv_test_str[18], (Fnv32_t) 0x052255dbUL },
730 { &fnv_test_str[19], (Fnv32_t) 0xbef39fe6UL },
731 { &fnv_test_str[20], (Fnv32_t) 0x6150ac75UL },
732 { &fnv_test_str[21], (Fnv32_t) 0x9aab3a3dUL },
733 { &fnv_test_str[22], (Fnv32_t) 0x519c4c3eUL },
734 { &fnv_test_str[23], (Fnv32_t) 0x0c1c9eb8UL },
735 { &fnv_test_str[24], (Fnv32_t) 0x5f299f4eUL },
736 { &fnv_test_str[25], (Fnv32_t) 0xef8580f3UL },
737 { &fnv_test_str[26], (Fnv32_t) 0xac297727UL },
738 { &fnv_test_str[27], (Fnv32_t) 0x4546b9c0UL },
739 { &fnv_test_str[28], (Fnv32_t) 0xbd564e7dUL },
740 { &fnv_test_str[29], (Fnv32_t) 0x6bdd5c67UL },
741 { &fnv_test_str[30], (Fnv32_t) 0xdd77ed30UL },
742 { &fnv_test_str[31], (Fnv32_t) 0xf4ca9683UL },
743 { &fnv_test_str[32], (Fnv32_t) 0x4aeb9bd0UL },
744 { &fnv_test_str[33], (Fnv32_t) 0xe0e67ad0UL },
745 { &fnv_test_str[34], (Fnv32_t) 0xc2d32fa8UL },
746 { &fnv_test_str[35], (Fnv32_t) 0x7f743fb7UL },
747 { &fnv_test_str[36], (Fnv32_t) 0x6900631fUL },
748 { &fnv_test_str[37], (Fnv32_t) 0xc59c990eUL },
749 { &fnv_test_str[38], (Fnv32_t) 0x448524fdUL },
750 { &fnv_test_str[39], (Fnv32_t) 0xd49930d5UL },
751 { &fnv_test_str[40], (Fnv32_t) 0x1c85c7caUL },
752 { &fnv_test_str[41], (Fnv32_t) 0x0229fe89UL },
753 { &fnv_test_str[42], (Fnv32_t) 0x2c469265UL },
754 { &fnv_test_str[43], (Fnv32_t) 0xce566940UL },
755 { &fnv_test_str[44], (Fnv32_t) 0x8bdd8ec7UL },
756 { &fnv_test_str[45], (Fnv32_t) 0x34787625UL },
757 { &fnv_test_str[46], (Fnv32_t) 0xd3ca6290UL },
758 { &fnv_test_str[47], (Fnv32_t) 0xddeaf039UL },
759 { &fnv_test_str[48], (Fnv32_t) 0xc0e64870UL },
760 { &fnv_test_str[49], (Fnv32_t) 0xdad35570UL },
761 { &fnv_test_str[50], (Fnv32_t) 0x5a740578UL },
762 { &fnv_test_str[51], (Fnv32_t) 0x5b004d15UL },
763 { &fnv_test_str[52], (Fnv32_t) 0x6a9c09cdUL },
764 { &fnv_test_str[53], (Fnv32_t) 0x2384f10aUL },
765 { &fnv_test_str[54], (Fnv32_t) 0xda993a47UL },
766 { &fnv_test_str[55], (Fnv32_t) 0x8227df4fUL },
767 { &fnv_test_str[56], (Fnv32_t) 0x4c298165UL },
768 { &fnv_test_str[57], (Fnv32_t) 0xfc563735UL },
769 { &fnv_test_str[58], (Fnv32_t) 0x8cb91483UL },
770 { &fnv_test_str[59], (Fnv32_t) 0x775bf5d0UL },
771 { &fnv_test_str[60], (Fnv32_t) 0xd5c428d0UL },
772 { &fnv_test_str[61], (Fnv32_t) 0x34cc0ea3UL },
773 { &fnv_test_str[62], (Fnv32_t) 0xea3b4cb7UL },
774 { &fnv_test_str[63], (Fnv32_t) 0x8e59f029UL },
775 { &fnv_test_str[64], (Fnv32_t) 0x2094de2bUL },
776 { &fnv_test_str[65], (Fnv32_t) 0xa65a0ad4UL },
777 { &fnv_test_str[66], (Fnv32_t) 0x9bbee5f4UL },
778 { &fnv_test_str[67], (Fnv32_t) 0xbe836343UL },
779 { &fnv_test_str[68], (Fnv32_t) 0x22d5344eUL },
780 { &fnv_test_str[69], (Fnv32_t) 0x19a1470cUL },
781 { &fnv_test_str[70], (Fnv32_t) 0x4a56b1ffUL },
782 { &fnv_test_str[71], (Fnv32_t) 0x70b8e86fUL },
783 { &fnv_test_str[72], (Fnv32_t) 0x0a5b4a39UL },
784 { &fnv_test_str[73], (Fnv32_t) 0xb5c3f670UL },
785 { &fnv_test_str[74], (Fnv32_t) 0x53cc3f70UL },
786 { &fnv_test_str[75], (Fnv32_t) 0xc03b0a99UL },
787 { &fnv_test_str[76], (Fnv32_t) 0x7259c415UL },
788 { &fnv_test_str[77], (Fnv32_t) 0x4095108bUL },
789 { &fnv_test_str[78], (Fnv32_t) 0x7559bdb1UL },
790 { &fnv_test_str[79], (Fnv32_t) 0xb3bf0bbcUL },
791 { &fnv_test_str[80], (Fnv32_t) 0x2183ff1cUL },
792 { &fnv_test_str[81], (Fnv32_t) 0x2bd54279UL },
793 { &fnv_test_str[82], (Fnv32_t) 0x23a156caUL },
794 { &fnv_test_str[83], (Fnv32_t) 0x64e2d7e4UL },
795 { &fnv_test_str[84], (Fnv32_t) 0x683af69aUL },
796 { &fnv_test_str[85], (Fnv32_t) 0xaed2346eUL },
797 { &fnv_test_str[86], (Fnv32_t) 0x4f9f2cabUL },
798 { &fnv_test_str[87], (Fnv32_t) 0x02935131UL },
799 { &fnv_test_str[88], (Fnv32_t) 0xc48fb86dUL },
800 { &fnv_test_str[89], (Fnv32_t) 0x2269f369UL },
801 { &fnv_test_str[90], (Fnv32_t) 0xc18fb3b4UL },
802 { &fnv_test_str[91], (Fnv32_t) 0x50ef1236UL },
803 { &fnv_test_str[92], (Fnv32_t) 0xc28fb547UL },
804 { &fnv_test_str[93], (Fnv32_t) 0x96c3bf47UL },
805 { &fnv_test_str[94], (Fnv32_t) 0xbf8fb08eUL },
806 { &fnv_test_str[95], (Fnv32_t) 0xf3e4d49cUL },
807 { &fnv_test_str[96], (Fnv32_t) 0x32179058UL },
808 { &fnv_test_str[97], (Fnv32_t) 0x280bfee6UL },
809 { &fnv_test_str[98], (Fnv32_t) 0x30178d32UL },
810 { &fnv_test_str[99], (Fnv32_t) 0x21addaf8UL },
811 { &fnv_test_str[100], (Fnv32_t) 0x4217a988UL },
812 { &fnv_test_str[101], (Fnv32_t) 0x772633d6UL },
813 { &fnv_test_str[102], (Fnv32_t) 0x08a3d11eUL },
814 { &fnv_test_str[103], (Fnv32_t) 0xb7e2323aUL },
815 { &fnv_test_str[104], (Fnv32_t) 0x07a3cf8bUL },
816 { &fnv_test_str[105], (Fnv32_t) 0x91dfb7d1UL },
817 { &fnv_test_str[106], (Fnv32_t) 0x06a3cdf8UL },
818 { &fnv_test_str[107], (Fnv32_t) 0x6bdd3d68UL },
819 { &fnv_test_str[108], (Fnv32_t) 0x1d5636a7UL },
820 { &fnv_test_str[109], (Fnv32_t) 0xd5b808e5UL },
821 { &fnv_test_str[110], (Fnv32_t) 0x1353e852UL },
822 { &fnv_test_str[111], (Fnv32_t) 0xbf16b916UL },
823 { &fnv_test_str[112], (Fnv32_t) 0xa55b89edUL },
824 { &fnv_test_str[113], (Fnv32_t) 0x3c1a2017UL },
825 { &fnv_test_str[114], (Fnv32_t) 0x0588b13cUL },
826 { &fnv_test_str[115], (Fnv32_t) 0xf22f0174UL },
827 { &fnv_test_str[116], (Fnv32_t) 0xe83641e1UL },
828 { &fnv_test_str[117], (Fnv32_t) 0x6e69b533UL },
829 { &fnv_test_str[118], (Fnv32_t) 0xf1760448UL },
830 { &fnv_test_str[119], (Fnv32_t) 0x64c8bd58UL },
831 { &fnv_test_str[120], (Fnv32_t) 0x97b4ea23UL },
832 { &fnv_test_str[121], (Fnv32_t) 0x9a4e92e6UL },
833 { &fnv_test_str[122], (Fnv32_t) 0xcfb14012UL },
834 { &fnv_test_str[123], (Fnv32_t) 0xf01b2511UL },
835 { &fnv_test_str[124], (Fnv32_t) 0x0bbb59c3UL },
836 { &fnv_test_str[125], (Fnv32_t) 0xce524afaUL },
837 { &fnv_test_str[126], (Fnv32_t) 0xdd16ef45UL },
838 { &fnv_test_str[127], (Fnv32_t) 0x60648bb3UL },
839 { &fnv_test_str[128], (Fnv32_t) 0x7fa4bcfcUL },
840 { &fnv_test_str[129], (Fnv32_t) 0x5053ae17UL },
841 { &fnv_test_str[130], (Fnv32_t) 0xc9302890UL },
842 { &fnv_test_str[131], (Fnv32_t) 0x956ded32UL },
843 { &fnv_test_str[132], (Fnv32_t) 0x9136db84UL },
844 { &fnv_test_str[133], (Fnv32_t) 0xdf9d3323UL },
845 { &fnv_test_str[134], (Fnv32_t) 0x32bb6cd0UL },
846 { &fnv_test_str[135], (Fnv32_t) 0xc8f8385bUL },
847 { &fnv_test_str[136], (Fnv32_t) 0xeb08bfbaUL },
848 { &fnv_test_str[137], (Fnv32_t) 0x62cc8e3dUL },
849 { &fnv_test_str[138], (Fnv32_t) 0xc3e20f5cUL },
850 { &fnv_test_str[139], (Fnv32_t) 0x39e97f17UL },
851 { &fnv_test_str[140], (Fnv32_t) 0x7837b203UL },
852 { &fnv_test_str[141], (Fnv32_t) 0x319e877bUL },
853 { &fnv_test_str[142], (Fnv32_t) 0xd3e63f89UL },
854 { &fnv_test_str[143], (Fnv32_t) 0x29b50b38UL },
855 { &fnv_test_str[144], (Fnv32_t) 0x5ed678b8UL },
856 { &fnv_test_str[145], (Fnv32_t) 0xb0d5b793UL },
857 { &fnv_test_str[146], (Fnv32_t) 0x52450be5UL },
858 { &fnv_test_str[147], (Fnv32_t) 0xfa72d767UL },
859 { &fnv_test_str[148], (Fnv32_t) 0x95066709UL },
860 { &fnv_test_str[149], (Fnv32_t) 0x7f52e123UL },
861 { &fnv_test_str[150], (Fnv32_t) 0x76966481UL },
862 { &fnv_test_str[151], (Fnv32_t) 0x063258b0UL },
863 { &fnv_test_str[152], (Fnv32_t) 0x2ded6e8aUL },
864 { &fnv_test_str[153], (Fnv32_t) 0xb07d7c52UL },
865 { &fnv_test_str[154], (Fnv32_t) 0xd0c71b71UL },
866 { &fnv_test_str[155], (Fnv32_t) 0xf684f1bdUL },
867 { &fnv_test_str[156], (Fnv32_t) 0x868ecfa8UL },
868 { &fnv_test_str[157], (Fnv32_t) 0xf794f684UL },
869 { &fnv_test_str[158], (Fnv32_t) 0xd19701c3UL },
870 { &fnv_test_str[159], (Fnv32_t) 0x346e171eUL },
871 { &fnv_test_str[160], (Fnv32_t) 0x91f8f676UL },
872 { &fnv_test_str[161], (Fnv32_t) 0x0bf58848UL },
873 { &fnv_test_str[162], (Fnv32_t) 0x6317b6d1UL },
874 { &fnv_test_str[163], (Fnv32_t) 0xafad4c54UL },
875 { &fnv_test_str[164], (Fnv32_t) 0x0f25681eUL },
876 { &fnv_test_str[165], (Fnv32_t) 0x91b18d49UL },
877 { &fnv_test_str[166], (Fnv32_t) 0x7d61c12eUL },
878 { &fnv_test_str[167], (Fnv32_t) 0x5147d25cUL },
879 { &fnv_test_str[168], (Fnv32_t) 0x9a8b6805UL },
880 { &fnv_test_str[169], (Fnv32_t) 0x4cd2a447UL },
881 { &fnv_test_str[170], (Fnv32_t) 0x1e549b14UL },
882 { &fnv_test_str[171], (Fnv32_t) 0x2fe1b574UL },
883 { &fnv_test_str[172], (Fnv32_t) 0xcf0cd31eUL },
884 { &fnv_test_str[173], (Fnv32_t) 0x6c471669UL },
885 { &fnv_test_str[174], (Fnv32_t) 0x0e5eef1eUL },
886 { &fnv_test_str[175], (Fnv32_t) 0x2bed3602UL },
887 { &fnv_test_str[176], (Fnv32_t) 0xb26249e0UL },
888 { &fnv_test_str[177], (Fnv32_t) 0x2c9b86a4UL },
889 { &fnv_test_str[178], (Fnv32_t) 0xe415e2bbUL },
890 { &fnv_test_str[179], (Fnv32_t) 0x18a98d1dUL },
891 { &fnv_test_str[180], (Fnv32_t) 0xb7df8b7bUL },
892 { &fnv_test_str[181], (Fnv32_t) 0x241e9075UL },
893 { &fnv_test_str[182], (Fnv32_t) 0x063f70ddUL },
894 { &fnv_test_str[183], (Fnv32_t) 0x0295aed9UL },
895 { &fnv_test_str[184], (Fnv32_t) 0x56a7f781UL },
896 { &fnv_test_str[185], (Fnv32_t) 0x253bc645UL },
897 { &fnv_test_str[186], (Fnv32_t) 0x46610921UL },
898 { &fnv_test_str[187], (Fnv32_t) 0x7c1577f9UL },
899 { &fnv_test_str[188], (Fnv32_t) 0x512b2851UL },
900 { &fnv_test_str[189], (Fnv32_t) 0x76823999UL },
901 { &fnv_test_str[190], (Fnv32_t) 0xc0586935UL },
902 { &fnv_test_str[191], (Fnv32_t) 0xf3415c85UL },
903 { &fnv_test_str[192], (Fnv32_t) 0x0ae4ff65UL },
904 { &fnv_test_str[193], (Fnv32_t) 0x58b79725UL },
905 { &fnv_test_str[194], (Fnv32_t) 0xdea43aa5UL },
906 { &fnv_test_str[195], (Fnv32_t) 0x2bb3be35UL },
907 { &fnv_test_str[196], (Fnv32_t) 0xea777a45UL },
908 { &fnv_test_str[197], (Fnv32_t) 0x8f21c305UL },
909 { &fnv_test_str[198], (Fnv32_t) 0x5c9d0865UL },
910 { &fnv_test_str[199], (Fnv32_t) 0xfa823dd5UL },
911 { &fnv_test_str[200], (Fnv32_t) 0x21a27271UL },
912 { &fnv_test_str[201], (Fnv32_t) 0x83c5c6d5UL },
913 { &fnv_test_str[202], (Fnv32_t) 0x813b0881UL },
914 { NULL, 0 }
915};
916
917/* FNV-0 64 bit test vectors */
918#if defined(HAVE_64BIT_LONG_LONG)
919struct fnv0_64_test_vector fnv0_64_vector[] = {
920 { &fnv_test_str[0], (Fnv64_t) 0x0000000000000000ULL },
921 { &fnv_test_str[1], (Fnv64_t) 0x0000000000000061ULL },
922 { &fnv_test_str[2], (Fnv64_t) 0x0000000000000062ULL },
923 { &fnv_test_str[3], (Fnv64_t) 0x0000000000000063ULL },
924 { &fnv_test_str[4], (Fnv64_t) 0x0000000000000064ULL },
925 { &fnv_test_str[5], (Fnv64_t) 0x0000000000000065ULL },
926 { &fnv_test_str[6], (Fnv64_t) 0x0000000000000066ULL },
927 { &fnv_test_str[7], (Fnv64_t) 0x000066000000ad3dULL },
928 { &fnv_test_str[8], (Fnv64_t) 0x015a8f0001265ec8ULL },
929 { &fnv_test_str[9], (Fnv64_t) 0x733fc501f4330dbaULL },
930 { &fnv_test_str[10], (Fnv64_t) 0x08697c51f2c0536fULL },
931 { &fnv_test_str[11], (Fnv64_t) 0x0b91ae3f7ccdc5efULL },
932 { &fnv_test_str[12], (Fnv64_t) 0x0000000000000000ULL },
933 { &fnv_test_str[13], (Fnv64_t) 0x000061000000a4d3ULL },
934 { &fnv_test_str[14], (Fnv64_t) 0x000062000000a686ULL },
935 { &fnv_test_str[15], (Fnv64_t) 0x000063000000a839ULL },
936 { &fnv_test_str[16], (Fnv64_t) 0x000064000000a9ecULL },
937 { &fnv_test_str[17], (Fnv64_t) 0x000065000000ab9fULL },
938 { &fnv_test_str[18], (Fnv64_t) 0x000066000000ad52ULL },
939 { &fnv_test_str[19], (Fnv64_t) 0x015a8f0001265ea7ULL },
940 { &fnv_test_str[20], (Fnv64_t) 0x733fc501f4330dd8ULL },
941 { &fnv_test_str[21], (Fnv64_t) 0x08697c51f2c0530eULL },
942 { &fnv_test_str[22], (Fnv64_t) 0x0b91ae3f7ccdc59dULL },
943 { &fnv_test_str[23], (Fnv64_t) 0x765104e111a7551dULL },
944 { &fnv_test_str[24], (Fnv64_t) 0x000063000000a851ULL },
945 { &fnv_test_str[25], (Fnv64_t) 0x01508a00011e01ccULL },
946 { &fnv_test_str[26], (Fnv64_t) 0x59dc4a01e5fd0dcaULL },
947 { &fnv_test_str[27], (Fnv64_t) 0xae5f8b39ccfe6e59ULL },
948 { &fnv_test_str[28], (Fnv64_t) 0x4ac7ec3754558154ULL },
949 { &fnv_test_str[29], (Fnv64_t) 0x6737b6044d4ac19cULL },
950 { &fnv_test_str[30], (Fnv64_t) 0xae6be54f5606fc63ULL },
951 { &fnv_test_str[31], (Fnv64_t) 0x685308cf2ddedc58ULL },
952 { &fnv_test_str[32], (Fnv64_t) 0x23f4500af1b069fbULL },
953 { &fnv_test_str[33], (Fnv64_t) 0xc88dfd98aec415a1ULL },
954 { &fnv_test_str[34], (Fnv64_t) 0x8d5b8b70f730c0fbULL },
955 { &fnv_test_str[35], (Fnv64_t) 0x634eebf407d7eae4ULL },
956 { &fnv_test_str[36], (Fnv64_t) 0x9705d3a953e4211eULL },
957 { &fnv_test_str[37], (Fnv64_t) 0x8307c6b98ca4459fULL },
958 { &fnv_test_str[38], (Fnv64_t) 0x4a7c4c49fb224d0cULL },
959 { &fnv_test_str[39], (Fnv64_t) 0xb382adb5bb48eb6eULL },
960 { &fnv_test_str[40], (Fnv64_t) 0x01508a00011e01a3ULL },
961 { &fnv_test_str[41], (Fnv64_t) 0x59dc4a01e5fd0da4ULL },
962 { &fnv_test_str[42], (Fnv64_t) 0xae5f8b39ccfe6e3eULL },
963 { &fnv_test_str[43], (Fnv64_t) 0x4ac7ec375455813bULL },
964 { &fnv_test_str[44], (Fnv64_t) 0x6737b6044d4ac1bcULL },
965 { &fnv_test_str[45], (Fnv64_t) 0xae6be54f5606fc14ULL },
966 { &fnv_test_str[46], (Fnv64_t) 0x685308cf2ddedc39ULL },
967 { &fnv_test_str[47], (Fnv64_t) 0x23f4500af1b06988ULL },
968 { &fnv_test_str[48], (Fnv64_t) 0xc88dfd98aec41581ULL },
969 { &fnv_test_str[49], (Fnv64_t) 0x8d5b8b70f730c093ULL },
970 { &fnv_test_str[50], (Fnv64_t) 0x634eebf407d7ea81ULL },
971 { &fnv_test_str[51], (Fnv64_t) 0x9705d3a953e4216cULL },
972 { &fnv_test_str[52], (Fnv64_t) 0x8307c6b98ca445faULL },
973 { &fnv_test_str[53], (Fnv64_t) 0x4a7c4c49fb224d2dULL },
974 { &fnv_test_str[54], (Fnv64_t) 0xb382adb5bb48eb64ULL },
975 { &fnv_test_str[55], (Fnv64_t) 0x4ff899cd3ce80beaULL },
976 { &fnv_test_str[56], (Fnv64_t) 0x000063000000a84cULL },
977 { &fnv_test_str[57], (Fnv64_t) 0x01508500011df956ULL },
978 { &fnv_test_str[58], (Fnv64_t) 0x59cb5501e5eead46ULL },
979 { &fnv_test_str[59], (Fnv64_t) 0x832eb839b4906d81ULL },
980 { &fnv_test_str[60], (Fnv64_t) 0x78d08b0dd16a1213ULL },
981 { &fnv_test_str[61], (Fnv64_t) 0xb46e5b7ad73cb628ULL },
982 { &fnv_test_str[62], (Fnv64_t) 0xd43b99bbbc298596ULL },
983 { &fnv_test_str[63], (Fnv64_t) 0xcacbd000ba8dfd86ULL },
984 { &fnv_test_str[64], (Fnv64_t) 0x264ff73cff45ca92ULL },
985 { &fnv_test_str[65], (Fnv64_t) 0x5fabaea5c3973661ULL },
986 { &fnv_test_str[66], (Fnv64_t) 0x27f024ab59f166bbULL },
987 { &fnv_test_str[67], (Fnv64_t) 0xce750a29d5318fa4ULL },
988 { &fnv_test_str[68], (Fnv64_t) 0x026fe915433713d5ULL },
989 { &fnv_test_str[69], (Fnv64_t) 0x5b3ce4213696b2e5ULL },
990 { &fnv_test_str[70], (Fnv64_t) 0x01508500011df924ULL },
991 { &fnv_test_str[71], (Fnv64_t) 0x59cb5501e5eead22ULL },
992 { &fnv_test_str[72], (Fnv64_t) 0x832eb839b4906df2ULL },
993 { &fnv_test_str[73], (Fnv64_t) 0x78d08b0dd16a1233ULL },
994 { &fnv_test_str[74], (Fnv64_t) 0xb46e5b7ad73cb649ULL },
995 { &fnv_test_str[75], (Fnv64_t) 0xd43b99bbbc2985f8ULL },
996 { &fnv_test_str[76], (Fnv64_t) 0xcacbd000ba8dfde2ULL },
997 { &fnv_test_str[77], (Fnv64_t) 0x264ff73cff45cab2ULL },
998 { &fnv_test_str[78], (Fnv64_t) 0x5fabaea5c3973616ULL },
999 { &fnv_test_str[79], (Fnv64_t) 0x27f024ab59f166d3ULL },
1000 { &fnv_test_str[80], (Fnv64_t) 0xce750a29d5318fc1ULL },
1001 { &fnv_test_str[81], (Fnv64_t) 0x026fe915433713acULL },
1002 { &fnv_test_str[82], (Fnv64_t) 0x5b3ce4213696b2efULL },
1003 { &fnv_test_str[83], (Fnv64_t) 0x9f2a896fc211fb1fULL },
1004 { &fnv_test_str[84], (Fnv64_t) 0x000068000000b0d1ULL },
1005 { &fnv_test_str[85], (Fnv64_t) 0x01618900012c7323ULL },
1006 { &fnv_test_str[86], (Fnv64_t) 0x3fa86e63bc7d03c8ULL },
1007 { &fnv_test_str[87], (Fnv64_t) 0xa8375b79486d6cd8ULL },
1008 { &fnv_test_str[88], (Fnv64_t) 0xa0d18504e316ac54ULL },
1009 { &fnv_test_str[89], (Fnv64_t) 0x08a97b0004e7fe54ULL },
1010 { &fnv_test_str[90], (Fnv64_t) 0xa0d18504e316ac57ULL },
1011 { &fnv_test_str[91], (Fnv64_t) 0x1152f60009cffda9ULL },
1012 { &fnv_test_str[92], (Fnv64_t) 0xa0d18504e316ac56ULL },
1013 { &fnv_test_str[93], (Fnv64_t) 0x19fc71000eb7fcfeULL },
1014 { &fnv_test_str[94], (Fnv64_t) 0xa0d18504e316ac51ULL },
1015 { &fnv_test_str[95], (Fnv64_t) 0x22a5ec00139ffa53ULL },
1016 { &fnv_test_str[96], (Fnv64_t) 0x29bed00139779a33ULL },
1017 { &fnv_test_str[97], (Fnv64_t) 0x4dbc81014e3c19f5ULL },
1018 { &fnv_test_str[98], (Fnv64_t) 0x29bed00139779a3dULL },
1019 { &fnv_test_str[99], (Fnv64_t) 0x81a72b016b9f7573ULL },
1020 { &fnv_test_str[100], (Fnv64_t) 0x29bed00139779a23ULL },
1021 { &fnv_test_str[101], (Fnv64_t) 0xd85411019cbbce45ULL },
1022 { &fnv_test_str[102], (Fnv64_t) 0xf548616b8621d657ULL },
1023 { &fnv_test_str[103], (Fnv64_t) 0xebd3e0b4eb7f35d5ULL },
1024 { &fnv_test_str[104], (Fnv64_t) 0xf548616b8621d654ULL },
1025 { &fnv_test_str[105], (Fnv64_t) 0xebd3ddb4eb7f30bcULL },
1026 { &fnv_test_str[106], (Fnv64_t) 0xf548616b8621d655ULL },
1027 { &fnv_test_str[107], (Fnv64_t) 0xebd3deb4eb7f326fULL },
1028 { &fnv_test_str[108], (Fnv64_t) 0x581cb60340ab0968ULL },
1029 { &fnv_test_str[109], (Fnv64_t) 0x63d2af86e2a0fbb8ULL },
1030 { &fnv_test_str[110], (Fnv64_t) 0x581cb70340ab0b37ULL },
1031 { &fnv_test_str[111], (Fnv64_t) 0x63d63186e2a40e75ULL },
1032 { &fnv_test_str[112], (Fnv64_t) 0x581cc40340ab212eULL },
1033 { &fnv_test_str[113], (Fnv64_t) 0x64023f86e2c9612aULL },
1034 { &fnv_test_str[114], (Fnv64_t) 0xdbda6a26c33c909fULL },
1035 { &fnv_test_str[115], (Fnv64_t) 0xd0b2feddbfe9be2dULL },
1036 { &fnv_test_str[116], (Fnv64_t) 0x9c9eae3f5d037decULL },
1037 { &fnv_test_str[117], (Fnv64_t) 0x252001ab0ceef804ULL },
1038 { &fnv_test_str[118], (Fnv64_t) 0x4456a56f9e05cfefULL },
1039 { &fnv_test_str[119], (Fnv64_t) 0x250b0ba983e0531dULL },
1040 { &fnv_test_str[120], (Fnv64_t) 0x52b007213b27b33eULL },
1041 { &fnv_test_str[121], (Fnv64_t) 0xcbf29ce484222325ULL },
1042 { &fnv_test_str[122], (Fnv64_t) 0xaf63bd4c8601b7dfULL },
1043 { &fnv_test_str[123], (Fnv64_t) 0x128599ccddae09f8ULL },
1044 { &fnv_test_str[124], (Fnv64_t) 0x270e4f1caebaf068ULL },
1045 { &fnv_test_str[125], (Fnv64_t) 0x01517d497446a395ULL },
1046 { &fnv_test_str[126], (Fnv64_t) 0x9af5a29a89450b40ULL },
1047 { &fnv_test_str[127], (Fnv64_t) 0xb502f6c063ba72e8ULL },
1048 { &fnv_test_str[128], (Fnv64_t) 0xacf41561498ca7dfULL },
1049 { &fnv_test_str[129], (Fnv64_t) 0x6be8c2423a351542ULL },
1050 { &fnv_test_str[130], (Fnv64_t) 0xd04f1f6da96ce4a3ULL },
1051 { &fnv_test_str[131], (Fnv64_t) 0x69eb9a8f282c7235ULL },
1052 { &fnv_test_str[132], (Fnv64_t) 0x6a7e5a418f77cfc5ULL },
1053 { &fnv_test_str[133], (Fnv64_t) 0xbcaf568ddc2ecba0ULL },
1054 { &fnv_test_str[134], (Fnv64_t) 0xb03b5cc4c38f8b1fULL },
1055 { &fnv_test_str[135], (Fnv64_t) 0xf89a9f51432db828ULL },
1056 { &fnv_test_str[136], (Fnv64_t) 0x549e856be6103429ULL },
1057 { &fnv_test_str[137], (Fnv64_t) 0x3cf50d224d29377aULL },
1058 { &fnv_test_str[138], (Fnv64_t) 0xdb762df418c10c37ULL },
1059 { &fnv_test_str[139], (Fnv64_t) 0xfeeb4226b0e9a6baULL },
1060 { &fnv_test_str[140], (Fnv64_t) 0x7004a4cd9310c052ULL },
1061 { &fnv_test_str[141], (Fnv64_t) 0xd1c727d7f5329276ULL },
1062 { &fnv_test_str[142], (Fnv64_t) 0xbe313796596ce908ULL },
1063 { &fnv_test_str[143], (Fnv64_t) 0x768f67ede090fcc5ULL },
1064 { &fnv_test_str[144], (Fnv64_t) 0xa81563cc9db9bfc3ULL },
1065 { &fnv_test_str[145], (Fnv64_t) 0x47194043c55197a8ULL },
1066 { &fnv_test_str[146], (Fnv64_t) 0xc99d81864aebab02ULL },
1067 { &fnv_test_str[147], (Fnv64_t) 0xcc1f161b235ea4a2ULL },
1068 { &fnv_test_str[148], (Fnv64_t) 0xaadab0c420ecd434ULL },
1069 { &fnv_test_str[149], (Fnv64_t) 0x6b3c034d6f44d740ULL },
1070 { &fnv_test_str[150], (Fnv64_t) 0x73a45e850602cbc6ULL },
1071 { &fnv_test_str[151], (Fnv64_t) 0x72360f04f0cd227bULL },
1072 { &fnv_test_str[152], (Fnv64_t) 0xa9ca80be384a778fULL },
1073 { &fnv_test_str[153], (Fnv64_t) 0xd4085e66906889e3ULL },
1074 { &fnv_test_str[154], (Fnv64_t) 0x93aa8b2748efdbc8ULL },
1075 { &fnv_test_str[155], (Fnv64_t) 0x6f8cd678407436a2ULL },
1076 { &fnv_test_str[156], (Fnv64_t) 0xf39a43d4dc8be4c7ULL },
1077 { &fnv_test_str[157], (Fnv64_t) 0xd7f5cec91125d245ULL },
1078 { &fnv_test_str[158], (Fnv64_t) 0x691d7b73be18adc4ULL },
1079 { &fnv_test_str[159], (Fnv64_t) 0xf4361e01caf6b691ULL },
1080 { &fnv_test_str[160], (Fnv64_t) 0xde7d8264f64be089ULL },
1081 { &fnv_test_str[161], (Fnv64_t) 0xa34ff43e5545c06fULL },
1082 { &fnv_test_str[162], (Fnv64_t) 0x181f0b8e908a2bdeULL },
1083 { &fnv_test_str[163], (Fnv64_t) 0x28a965b78ddbc071ULL },
1084 { &fnv_test_str[164], (Fnv64_t) 0xead9cea0e3cc6ae5ULL },
1085 { &fnv_test_str[165], (Fnv64_t) 0x0b6743153b43ebbaULL },
1086 { &fnv_test_str[166], (Fnv64_t) 0xa7aa3f012c74528dULL },
1087 { &fnv_test_str[167], (Fnv64_t) 0x2d5d8ad7f9dffeb7ULL },
1088 { &fnv_test_str[168], (Fnv64_t) 0x00750fb6e19624eaULL },
1089 { &fnv_test_str[169], (Fnv64_t) 0x01c125a4e6c76c82ULL },
1090 { &fnv_test_str[170], (Fnv64_t) 0x3fde3afac0722f1fULL },
1091 { &fnv_test_str[171], (Fnv64_t) 0xd7c3eaf4abaa379dULL },
1092 { &fnv_test_str[172], (Fnv64_t) 0xd2217e1c923c9f3fULL },
1093 { &fnv_test_str[173], (Fnv64_t) 0x82d0a2e3b725caf6ULL },
1094 { &fnv_test_str[174], (Fnv64_t) 0x0a10bee8eeb72e4fULL },
1095 { &fnv_test_str[175], (Fnv64_t) 0xc530e8723e72c6fdULL },
1096 { &fnv_test_str[176], (Fnv64_t) 0xd8d34dcd2e7bad99ULL },
1097 { &fnv_test_str[177], (Fnv64_t) 0xecf77466e9a2baf3ULL },
1098 { &fnv_test_str[178], (Fnv64_t) 0xde3d2ddb043b9666ULL },
1099 { &fnv_test_str[179], (Fnv64_t) 0xd1cc824e1a8157d8ULL },
1100 { &fnv_test_str[180], (Fnv64_t) 0x7d5c68ecbc90512eULL },
1101 { &fnv_test_str[181], (Fnv64_t) 0x2f7c691b1d7c76d8ULL },
1102 { &fnv_test_str[182], (Fnv64_t) 0x5d88c2bad3a46bc8ULL },
1103 { &fnv_test_str[183], (Fnv64_t) 0xdf107320276647a0ULL },
1104 { &fnv_test_str[184], (Fnv64_t) 0x0f78f22e7e70e9bcULL },
1105 { &fnv_test_str[185], (Fnv64_t) 0x8c67be5c80f67d04ULL },
1106 { &fnv_test_str[186], (Fnv64_t) 0x07c1adfa4d019194ULL },
1107 { &fnv_test_str[187], (Fnv64_t) 0xce1312420c5b1af4ULL },
1108 { &fnv_test_str[188], (Fnv64_t) 0x043a41b2dc53ab24ULL },
1109 { &fnv_test_str[189], (Fnv64_t) 0x0b038eebf7340860ULL },
1110 { &fnv_test_str[190], (Fnv64_t) 0x1bcd837353fb69b0ULL },
1111 { &fnv_test_str[191], (Fnv64_t) 0x46f992fc59eff180ULL },
1112 { &fnv_test_str[192], (Fnv64_t) 0x497678ee29ae79c0ULL },
1113 { &fnv_test_str[193], (Fnv64_t) 0xb10a62280ddd4450ULL },
1114 { &fnv_test_str[194], (Fnv64_t) 0x35eb228db4d68140ULL },
1115 { &fnv_test_str[195], (Fnv64_t) 0x8b350e86d9470870ULL },
1116 { &fnv_test_str[196], (Fnv64_t) 0x4e1fbdb2812e9540ULL },
1117 { &fnv_test_str[197], (Fnv64_t) 0x051e080df69a0600ULL },
1118 { &fnv_test_str[198], (Fnv64_t) 0x45e1e8ae54dadb40ULL },
1119 { &fnv_test_str[199], (Fnv64_t) 0x0000000000000000ULL },
1120 { &fnv_test_str[200], (Fnv64_t) 0xcd73806290557064ULL },
1121 { &fnv_test_str[201], (Fnv64_t) 0x2613a37bbe0317c8ULL },
1122 { &fnv_test_str[202], (Fnv64_t) 0x1480e21fcf2ae5e4ULL },
1123 { NULL, (Fnv64_t) 0 }
1124};
1125#else /* HAVE_64BIT_LONG_LONG */
1126struct fnv0_64_test_vector fnv0_64_vector[] = {
1127 { &fnv_test_str[0], (Fnv64_t) {0x00000000UL, 0x00000000UL} },
1128 { &fnv_test_str[1], (Fnv64_t) {0x00000061UL, 0x00000000UL} },
1129 { &fnv_test_str[2], (Fnv64_t) {0x00000062UL, 0x00000000UL} },
1130 { &fnv_test_str[3], (Fnv64_t) {0x00000063UL, 0x00000000UL} },
1131 { &fnv_test_str[4], (Fnv64_t) {0x00000064UL, 0x00000000UL} },
1132 { &fnv_test_str[5], (Fnv64_t) {0x00000065UL, 0x00000000UL} },
1133 { &fnv_test_str[6], (Fnv64_t) {0x00000066UL, 0x00000000UL} },
1134 { &fnv_test_str[7], (Fnv64_t) {0x0000ad3dUL, 0x00006600UL} },
1135 { &fnv_test_str[8], (Fnv64_t) {0x01265ec8UL, 0x015a8f00UL} },
1136 { &fnv_test_str[9], (Fnv64_t) {0xf4330dbaUL, 0x733fc501UL} },
1137 { &fnv_test_str[10], (Fnv64_t) {0xf2c0536fUL, 0x08697c51UL} },
1138 { &fnv_test_str[11], (Fnv64_t) {0x7ccdc5efUL, 0x0b91ae3fUL} },
1139 { &fnv_test_str[12], (Fnv64_t) {0x00000000UL, 0x00000000UL} },
1140 { &fnv_test_str[13], (Fnv64_t) {0x0000a4d3UL, 0x00006100UL} },
1141 { &fnv_test_str[14], (Fnv64_t) {0x0000a686UL, 0x00006200UL} },
1142 { &fnv_test_str[15], (Fnv64_t) {0x0000a839UL, 0x00006300UL} },
1143 { &fnv_test_str[16], (Fnv64_t) {0x0000a9ecUL, 0x00006400UL} },
1144 { &fnv_test_str[17], (Fnv64_t) {0x0000ab9fUL, 0x00006500UL} },
1145 { &fnv_test_str[18], (Fnv64_t) {0x0000ad52UL, 0x00006600UL} },
1146 { &fnv_test_str[19], (Fnv64_t) {0x01265ea7UL, 0x015a8f00UL} },
1147 { &fnv_test_str[20], (Fnv64_t) {0xf4330dd8UL, 0x733fc501UL} },
1148 { &fnv_test_str[21], (Fnv64_t) {0xf2c0530eUL, 0x08697c51UL} },
1149 { &fnv_test_str[22], (Fnv64_t) {0x7ccdc59dUL, 0x0b91ae3fUL} },
1150 { &fnv_test_str[23], (Fnv64_t) {0x11a7551dUL, 0x765104e1UL} },
1151 { &fnv_test_str[24], (Fnv64_t) {0x0000a851UL, 0x00006300UL} },
1152 { &fnv_test_str[25], (Fnv64_t) {0x011e01ccUL, 0x01508a00UL} },
1153 { &fnv_test_str[26], (Fnv64_t) {0xe5fd0dcaUL, 0x59dc4a01UL} },
1154 { &fnv_test_str[27], (Fnv64_t) {0xccfe6e59UL, 0xae5f8b39UL} },
1155 { &fnv_test_str[28], (Fnv64_t) {0x54558154UL, 0x4ac7ec37UL} },
1156 { &fnv_test_str[29], (Fnv64_t) {0x4d4ac19cUL, 0x6737b604UL} },
1157 { &fnv_test_str[30], (Fnv64_t) {0x5606fc63UL, 0xae6be54fUL} },
1158 { &fnv_test_str[31], (Fnv64_t) {0x2ddedc58UL, 0x685308cfUL} },
1159 { &fnv_test_str[32], (Fnv64_t) {0xf1b069fbUL, 0x23f4500aUL} },
1160 { &fnv_test_str[33], (Fnv64_t) {0xaec415a1UL, 0xc88dfd98UL} },
1161 { &fnv_test_str[34], (Fnv64_t) {0xf730c0fbUL, 0x8d5b8b70UL} },
1162 { &fnv_test_str[35], (Fnv64_t) {0x07d7eae4UL, 0x634eebf4UL} },
1163 { &fnv_test_str[36], (Fnv64_t) {0x53e4211eUL, 0x9705d3a9UL} },
1164 { &fnv_test_str[37], (Fnv64_t) {0x8ca4459fUL, 0x8307c6b9UL} },
1165 { &fnv_test_str[38], (Fnv64_t) {0xfb224d0cUL, 0x4a7c4c49UL} },
1166 { &fnv_test_str[39], (Fnv64_t) {0xbb48eb6eUL, 0xb382adb5UL} },
1167 { &fnv_test_str[40], (Fnv64_t) {0x011e01a3UL, 0x01508a00UL} },
1168 { &fnv_test_str[41], (Fnv64_t) {0xe5fd0da4UL, 0x59dc4a01UL} },
1169 { &fnv_test_str[42], (Fnv64_t) {0xccfe6e3eUL, 0xae5f8b39UL} },
1170 { &fnv_test_str[43], (Fnv64_t) {0x5455813bUL, 0x4ac7ec37UL} },
1171 { &fnv_test_str[44], (Fnv64_t) {0x4d4ac1bcUL, 0x6737b604UL} },
1172 { &fnv_test_str[45], (Fnv64_t) {0x5606fc14UL, 0xae6be54fUL} },
1173 { &fnv_test_str[46], (Fnv64_t) {0x2ddedc39UL, 0x685308cfUL} },
1174 { &fnv_test_str[47], (Fnv64_t) {0xf1b06988UL, 0x23f4500aUL} },
1175 { &fnv_test_str[48], (Fnv64_t) {0xaec41581UL, 0xc88dfd98UL} },
1176 { &fnv_test_str[49], (Fnv64_t) {0xf730c093UL, 0x8d5b8b70UL} },
1177 { &fnv_test_str[50], (Fnv64_t) {0x07d7ea81UL, 0x634eebf4UL} },
1178 { &fnv_test_str[51], (Fnv64_t) {0x53e4216cUL, 0x9705d3a9UL} },
1179 { &fnv_test_str[52], (Fnv64_t) {0x8ca445faUL, 0x8307c6b9UL} },
1180 { &fnv_test_str[53], (Fnv64_t) {0xfb224d2dUL, 0x4a7c4c49UL} },
1181 { &fnv_test_str[54], (Fnv64_t) {0xbb48eb64UL, 0xb382adb5UL} },
1182 { &fnv_test_str[55], (Fnv64_t) {0x3ce80beaUL, 0x4ff899cdUL} },
1183 { &fnv_test_str[56], (Fnv64_t) {0x0000a84cUL, 0x00006300UL} },
1184 { &fnv_test_str[57], (Fnv64_t) {0x011df956UL, 0x01508500UL} },
1185 { &fnv_test_str[58], (Fnv64_t) {0xe5eead46UL, 0x59cb5501UL} },
1186 { &fnv_test_str[59], (Fnv64_t) {0xb4906d81UL, 0x832eb839UL} },
1187 { &fnv_test_str[60], (Fnv64_t) {0xd16a1213UL, 0x78d08b0dUL} },
1188 { &fnv_test_str[61], (Fnv64_t) {0xd73cb628UL, 0xb46e5b7aUL} },
1189 { &fnv_test_str[62], (Fnv64_t) {0xbc298596UL, 0xd43b99bbUL} },
1190 { &fnv_test_str[63], (Fnv64_t) {0xba8dfd86UL, 0xcacbd000UL} },
1191 { &fnv_test_str[64], (Fnv64_t) {0xff45ca92UL, 0x264ff73cUL} },
1192 { &fnv_test_str[65], (Fnv64_t) {0xc3973661UL, 0x5fabaea5UL} },
1193 { &fnv_test_str[66], (Fnv64_t) {0x59f166bbUL, 0x27f024abUL} },
1194 { &fnv_test_str[67], (Fnv64_t) {0xd5318fa4UL, 0xce750a29UL} },
1195 { &fnv_test_str[68], (Fnv64_t) {0x433713d5UL, 0x026fe915UL} },
1196 { &fnv_test_str[69], (Fnv64_t) {0x3696b2e5UL, 0x5b3ce421UL} },
1197 { &fnv_test_str[70], (Fnv64_t) {0x011df924UL, 0x01508500UL} },
1198 { &fnv_test_str[71], (Fnv64_t) {0xe5eead22UL, 0x59cb5501UL} },
1199 { &fnv_test_str[72], (Fnv64_t) {0xb4906df2UL, 0x832eb839UL} },
1200 { &fnv_test_str[73], (Fnv64_t) {0xd16a1233UL, 0x78d08b0dUL} },
1201 { &fnv_test_str[74], (Fnv64_t) {0xd73cb649UL, 0xb46e5b7aUL} },
1202 { &fnv_test_str[75], (Fnv64_t) {0xbc2985f8UL, 0xd43b99bbUL} },
1203 { &fnv_test_str[76], (Fnv64_t) {0xba8dfde2UL, 0xcacbd000UL} },
1204 { &fnv_test_str[77], (Fnv64_t) {0xff45cab2UL, 0x264ff73cUL} },
1205 { &fnv_test_str[78], (Fnv64_t) {0xc3973616UL, 0x5fabaea5UL} },
1206 { &fnv_test_str[79], (Fnv64_t) {0x59f166d3UL, 0x27f024abUL} },
1207 { &fnv_test_str[80], (Fnv64_t) {0xd5318fc1UL, 0xce750a29UL} },
1208 { &fnv_test_str[81], (Fnv64_t) {0x433713acUL, 0x026fe915UL} },
1209 { &fnv_test_str[82], (Fnv64_t) {0x3696b2efUL, 0x5b3ce421UL} },
1210 { &fnv_test_str[83], (Fnv64_t) {0xc211fb1fUL, 0x9f2a896fUL} },
1211 { &fnv_test_str[84], (Fnv64_t) {0x0000b0d1UL, 0x00006800UL} },
1212 { &fnv_test_str[85], (Fnv64_t) {0x012c7323UL, 0x01618900UL} },
1213 { &fnv_test_str[86], (Fnv64_t) {0xbc7d03c8UL, 0x3fa86e63UL} },
1214 { &fnv_test_str[87], (Fnv64_t) {0x486d6cd8UL, 0xa8375b79UL} },
1215 { &fnv_test_str[88], (Fnv64_t) {0xe316ac54UL, 0xa0d18504UL} },
1216 { &fnv_test_str[89], (Fnv64_t) {0x04e7fe54UL, 0x08a97b00UL} },
1217 { &fnv_test_str[90], (Fnv64_t) {0xe316ac57UL, 0xa0d18504UL} },
1218 { &fnv_test_str[91], (Fnv64_t) {0x09cffda9UL, 0x1152f600UL} },
1219 { &fnv_test_str[92], (Fnv64_t) {0xe316ac56UL, 0xa0d18504UL} },
1220 { &fnv_test_str[93], (Fnv64_t) {0x0eb7fcfeUL, 0x19fc7100UL} },
1221 { &fnv_test_str[94], (Fnv64_t) {0xe316ac51UL, 0xa0d18504UL} },
1222 { &fnv_test_str[95], (Fnv64_t) {0x139ffa53UL, 0x22a5ec00UL} },
1223 { &fnv_test_str[96], (Fnv64_t) {0x39779a33UL, 0x29bed001UL} },
1224 { &fnv_test_str[97], (Fnv64_t) {0x4e3c19f5UL, 0x4dbc8101UL} },
1225 { &fnv_test_str[98], (Fnv64_t) {0x39779a3dUL, 0x29bed001UL} },
1226 { &fnv_test_str[99], (Fnv64_t) {0x6b9f7573UL, 0x81a72b01UL} },
1227 { &fnv_test_str[100], (Fnv64_t) {0x39779a23UL, 0x29bed001UL} },
1228 { &fnv_test_str[101], (Fnv64_t) {0x9cbbce45UL, 0xd8541101UL} },
1229 { &fnv_test_str[102], (Fnv64_t) {0x8621d657UL, 0xf548616bUL} },
1230 { &fnv_test_str[103], (Fnv64_t) {0xeb7f35d5UL, 0xebd3e0b4UL} },
1231 { &fnv_test_str[104], (Fnv64_t) {0x8621d654UL, 0xf548616bUL} },
1232 { &fnv_test_str[105], (Fnv64_t) {0xeb7f30bcUL, 0xebd3ddb4UL} },
1233 { &fnv_test_str[106], (Fnv64_t) {0x8621d655UL, 0xf548616bUL} },
1234 { &fnv_test_str[107], (Fnv64_t) {0xeb7f326fUL, 0xebd3deb4UL} },
1235 { &fnv_test_str[108], (Fnv64_t) {0x40ab0968UL, 0x581cb603UL} },
1236 { &fnv_test_str[109], (Fnv64_t) {0xe2a0fbb8UL, 0x63d2af86UL} },
1237 { &fnv_test_str[110], (Fnv64_t) {0x40ab0b37UL, 0x581cb703UL} },
1238 { &fnv_test_str[111], (Fnv64_t) {0xe2a40e75UL, 0x63d63186UL} },
1239 { &fnv_test_str[112], (Fnv64_t) {0x40ab212eUL, 0x581cc403UL} },
1240 { &fnv_test_str[113], (Fnv64_t) {0xe2c9612aUL, 0x64023f86UL} },
1241 { &fnv_test_str[114], (Fnv64_t) {0xc33c909fUL, 0xdbda6a26UL} },
1242 { &fnv_test_str[115], (Fnv64_t) {0xbfe9be2dUL, 0xd0b2feddUL} },
1243 { &fnv_test_str[116], (Fnv64_t) {0x5d037decUL, 0x9c9eae3fUL} },
1244 { &fnv_test_str[117], (Fnv64_t) {0x0ceef804UL, 0x252001abUL} },
1245 { &fnv_test_str[118], (Fnv64_t) {0x9e05cfefUL, 0x4456a56fUL} },
1246 { &fnv_test_str[119], (Fnv64_t) {0x83e0531dUL, 0x250b0ba9UL} },
1247 { &fnv_test_str[120], (Fnv64_t) {0x3b27b33eUL, 0x52b00721UL} },
1248 { &fnv_test_str[121], (Fnv64_t) {0x84222325UL, 0xcbf29ce4UL} },
1249 { &fnv_test_str[122], (Fnv64_t) {0x8601b7dfUL, 0xaf63bd4cUL} },
1250 { &fnv_test_str[123], (Fnv64_t) {0xddae09f8UL, 0x128599ccUL} },
1251 { &fnv_test_str[124], (Fnv64_t) {0xaebaf068UL, 0x270e4f1cUL} },
1252 { &fnv_test_str[125], (Fnv64_t) {0x7446a395UL, 0x01517d49UL} },
1253 { &fnv_test_str[126], (Fnv64_t) {0x89450b40UL, 0x9af5a29aUL} },
1254 { &fnv_test_str[127], (Fnv64_t) {0x63ba72e8UL, 0xb502f6c0UL} },
1255 { &fnv_test_str[128], (Fnv64_t) {0x498ca7dfUL, 0xacf41561UL} },
1256 { &fnv_test_str[129], (Fnv64_t) {0x3a351542UL, 0x6be8c242UL} },
1257 { &fnv_test_str[130], (Fnv64_t) {0xa96ce4a3UL, 0xd04f1f6dUL} },
1258 { &fnv_test_str[131], (Fnv64_t) {0x282c7235UL, 0x69eb9a8fUL} },
1259 { &fnv_test_str[132], (Fnv64_t) {0x8f77cfc5UL, 0x6a7e5a41UL} },
1260 { &fnv_test_str[133], (Fnv64_t) {0xdc2ecba0UL, 0xbcaf568dUL} },
1261 { &fnv_test_str[134], (Fnv64_t) {0xc38f8b1fUL, 0xb03b5cc4UL} },
1262 { &fnv_test_str[135], (Fnv64_t) {0x432db828UL, 0xf89a9f51UL} },
1263 { &fnv_test_str[136], (Fnv64_t) {0xe6103429UL, 0x549e856bUL} },
1264 { &fnv_test_str[137], (Fnv64_t) {0x4d29377aUL, 0x3cf50d22UL} },
1265 { &fnv_test_str[138], (Fnv64_t) {0x18c10c37UL, 0xdb762df4UL} },
1266 { &fnv_test_str[139], (Fnv64_t) {0xb0e9a6baUL, 0xfeeb4226UL} },
1267 { &fnv_test_str[140], (Fnv64_t) {0x9310c052UL, 0x7004a4cdUL} },
1268 { &fnv_test_str[141], (Fnv64_t) {0xf5329276UL, 0xd1c727d7UL} },
1269 { &fnv_test_str[142], (Fnv64_t) {0x596ce908UL, 0xbe313796UL} },
1270 { &fnv_test_str[143], (Fnv64_t) {0xe090fcc5UL, 0x768f67edUL} },
1271 { &fnv_test_str[144], (Fnv64_t) {0x9db9bfc3UL, 0xa81563ccUL} },
1272 { &fnv_test_str[145], (Fnv64_t) {0xc55197a8UL, 0x47194043UL} },
1273 { &fnv_test_str[146], (Fnv64_t) {0x4aebab02UL, 0xc99d8186UL} },
1274 { &fnv_test_str[147], (Fnv64_t) {0x235ea4a2UL, 0xcc1f161bUL} },
1275 { &fnv_test_str[148], (Fnv64_t) {0x20ecd434UL, 0xaadab0c4UL} },
1276 { &fnv_test_str[149], (Fnv64_t) {0x6f44d740UL, 0x6b3c034dUL} },
1277 { &fnv_test_str[150], (Fnv64_t) {0x0602cbc6UL, 0x73a45e85UL} },
1278 { &fnv_test_str[151], (Fnv64_t) {0xf0cd227bUL, 0x72360f04UL} },
1279 { &fnv_test_str[152], (Fnv64_t) {0x384a778fUL, 0xa9ca80beUL} },
1280 { &fnv_test_str[153], (Fnv64_t) {0x906889e3UL, 0xd4085e66UL} },
1281 { &fnv_test_str[154], (Fnv64_t) {0x48efdbc8UL, 0x93aa8b27UL} },
1282 { &fnv_test_str[155], (Fnv64_t) {0x407436a2UL, 0x6f8cd678UL} },
1283 { &fnv_test_str[156], (Fnv64_t) {0xdc8be4c7UL, 0xf39a43d4UL} },
1284 { &fnv_test_str[157], (Fnv64_t) {0x1125d245UL, 0xd7f5cec9UL} },
1285 { &fnv_test_str[158], (Fnv64_t) {0xbe18adc4UL, 0x691d7b73UL} },
1286 { &fnv_test_str[159], (Fnv64_t) {0xcaf6b691UL, 0xf4361e01UL} },
1287 { &fnv_test_str[160], (Fnv64_t) {0xf64be089UL, 0xde7d8264UL} },
1288 { &fnv_test_str[161], (Fnv64_t) {0x5545c06fUL, 0xa34ff43eUL} },
1289 { &fnv_test_str[162], (Fnv64_t) {0x908a2bdeUL, 0x181f0b8eUL} },
1290 { &fnv_test_str[163], (Fnv64_t) {0x8ddbc071UL, 0x28a965b7UL} },
1291 { &fnv_test_str[164], (Fnv64_t) {0xe3cc6ae5UL, 0xead9cea0UL} },
1292 { &fnv_test_str[165], (Fnv64_t) {0x3b43ebbaUL, 0x0b674315UL} },
1293 { &fnv_test_str[166], (Fnv64_t) {0x2c74528dUL, 0xa7aa3f01UL} },
1294 { &fnv_test_str[167], (Fnv64_t) {0xf9dffeb7UL, 0x2d5d8ad7UL} },
1295 { &fnv_test_str[168], (Fnv64_t) {0xe19624eaUL, 0x00750fb6UL} },
1296 { &fnv_test_str[169], (Fnv64_t) {0xe6c76c82UL, 0x01c125a4UL} },
1297 { &fnv_test_str[170], (Fnv64_t) {0xc0722f1fUL, 0x3fde3afaUL} },
1298 { &fnv_test_str[171], (Fnv64_t) {0xabaa379dUL, 0xd7c3eaf4UL} },
1299 { &fnv_test_str[172], (Fnv64_t) {0x923c9f3fUL, 0xd2217e1cUL} },
1300 { &fnv_test_str[173], (Fnv64_t) {0xb725caf6UL, 0x82d0a2e3UL} },
1301 { &fnv_test_str[174], (Fnv64_t) {0xeeb72e4fUL, 0x0a10bee8UL} },
1302 { &fnv_test_str[175], (Fnv64_t) {0x3e72c6fdUL, 0xc530e872UL} },
1303 { &fnv_test_str[176], (Fnv64_t) {0x2e7bad99UL, 0xd8d34dcdUL} },
1304 { &fnv_test_str[177], (Fnv64_t) {0xe9a2baf3UL, 0xecf77466UL} },
1305 { &fnv_test_str[178], (Fnv64_t) {0x043b9666UL, 0xde3d2ddbUL} },
1306 { &fnv_test_str[179], (Fnv64_t) {0x1a8157d8UL, 0xd1cc824eUL} },
1307 { &fnv_test_str[180], (Fnv64_t) {0xbc90512eUL, 0x7d5c68ecUL} },
1308 { &fnv_test_str[181], (Fnv64_t) {0x1d7c76d8UL, 0x2f7c691bUL} },
1309 { &fnv_test_str[182], (Fnv64_t) {0xd3a46bc8UL, 0x5d88c2baUL} },
1310 { &fnv_test_str[183], (Fnv64_t) {0x276647a0UL, 0xdf107320UL} },
1311 { &fnv_test_str[184], (Fnv64_t) {0x7e70e9bcUL, 0x0f78f22eUL} },
1312 { &fnv_test_str[185], (Fnv64_t) {0x80f67d04UL, 0x8c67be5cUL} },
1313 { &fnv_test_str[186], (Fnv64_t) {0x4d019194UL, 0x07c1adfaUL} },
1314 { &fnv_test_str[187], (Fnv64_t) {0x0c5b1af4UL, 0xce131242UL} },
1315 { &fnv_test_str[188], (Fnv64_t) {0xdc53ab24UL, 0x043a41b2UL} },
1316 { &fnv_test_str[189], (Fnv64_t) {0xf7340860UL, 0x0b038eebUL} },
1317 { &fnv_test_str[190], (Fnv64_t) {0x53fb69b0UL, 0x1bcd8373UL} },
1318 { &fnv_test_str[191], (Fnv64_t) {0x59eff180UL, 0x46f992fcUL} },
1319 { &fnv_test_str[192], (Fnv64_t) {0x29ae79c0UL, 0x497678eeUL} },
1320 { &fnv_test_str[193], (Fnv64_t) {0x0ddd4450UL, 0xb10a6228UL} },
1321 { &fnv_test_str[194], (Fnv64_t) {0xb4d68140UL, 0x35eb228dUL} },
1322 { &fnv_test_str[195], (Fnv64_t) {0xd9470870UL, 0x8b350e86UL} },
1323 { &fnv_test_str[196], (Fnv64_t) {0x812e9540UL, 0x4e1fbdb2UL} },
1324 { &fnv_test_str[197], (Fnv64_t) {0xf69a0600UL, 0x051e080dUL} },
1325 { &fnv_test_str[198], (Fnv64_t) {0x54dadb40UL, 0x45e1e8aeUL} },
1326 { &fnv_test_str[199], (Fnv64_t) {0x00000000UL, 0x00000000UL} },
1327 { &fnv_test_str[200], (Fnv64_t) {0x90557064UL, 0xcd738062UL} },
1328 { &fnv_test_str[201], (Fnv64_t) {0xbe0317c8UL, 0x2613a37bUL} },
1329 { &fnv_test_str[202], (Fnv64_t) {0xcf2ae5e4UL, 0x1480e21fUL} },
1330 { NULL, (Fnv64_t) {0,0} }
1331};
1332#endif /* HAVE_64BIT_LONG_LONG */
1333
1334/* FNV-1 64 bit test vectors */
1335#if defined(HAVE_64BIT_LONG_LONG)
1336struct fnv1_64_test_vector fnv1_64_vector[] = {
1337 { &fnv_test_str[0], (Fnv64_t) 0xcbf29ce484222325ULL },
1338 { &fnv_test_str[1], (Fnv64_t) 0xaf63bd4c8601b7beULL },
1339 { &fnv_test_str[2], (Fnv64_t) 0xaf63bd4c8601b7bdULL },
1340 { &fnv_test_str[3], (Fnv64_t) 0xaf63bd4c8601b7bcULL },
1341 { &fnv_test_str[4], (Fnv64_t) 0xaf63bd4c8601b7bbULL },
1342 { &fnv_test_str[5], (Fnv64_t) 0xaf63bd4c8601b7baULL },
1343 { &fnv_test_str[6], (Fnv64_t) 0xaf63bd4c8601b7b9ULL },
1344 { &fnv_test_str[7], (Fnv64_t) 0x08326207b4eb2f34ULL },
1345 { &fnv_test_str[8], (Fnv64_t) 0xd8cbc7186ba13533ULL },
1346 { &fnv_test_str[9], (Fnv64_t) 0x0378817ee2ed65cbULL },
1347 { &fnv_test_str[10], (Fnv64_t) 0xd329d59b9963f790ULL },
1348 { &fnv_test_str[11], (Fnv64_t) 0x340d8765a4dda9c2ULL },
1349 { &fnv_test_str[12], (Fnv64_t) 0xaf63bd4c8601b7dfULL },
1350 { &fnv_test_str[13], (Fnv64_t) 0x08326707b4eb37daULL },
1351 { &fnv_test_str[14], (Fnv64_t) 0x08326607b4eb3627ULL },
1352 { &fnv_test_str[15], (Fnv64_t) 0x08326507b4eb3474ULL },
1353 { &fnv_test_str[16], (Fnv64_t) 0x08326407b4eb32c1ULL },
1354 { &fnv_test_str[17], (Fnv64_t) 0x08326307b4eb310eULL },
1355 { &fnv_test_str[18], (Fnv64_t) 0x08326207b4eb2f5bULL },
1356 { &fnv_test_str[19], (Fnv64_t) 0xd8cbc7186ba1355cULL },
1357 { &fnv_test_str[20], (Fnv64_t) 0x0378817ee2ed65a9ULL },
1358 { &fnv_test_str[21], (Fnv64_t) 0xd329d59b9963f7f1ULL },
1359 { &fnv_test_str[22], (Fnv64_t) 0x340d8765a4dda9b0ULL },
1360 { &fnv_test_str[23], (Fnv64_t) 0x50a6d3b724a774a6ULL },
1361 { &fnv_test_str[24], (Fnv64_t) 0x08326507b4eb341cULL },
1362 { &fnv_test_str[25], (Fnv64_t) 0xd8d5c8186ba98bfbULL },
1363 { &fnv_test_str[26], (Fnv64_t) 0x1ccefc7ef118dbefULL },
1364 { &fnv_test_str[27], (Fnv64_t) 0x0c92fab3ad3db77aULL },
1365 { &fnv_test_str[28], (Fnv64_t) 0x9b77794f5fdec421ULL },
1366 { &fnv_test_str[29], (Fnv64_t) 0x0ac742dfe7874433ULL },
1367 { &fnv_test_str[30], (Fnv64_t) 0xd7dad5766ad8e2deULL },
1368 { &fnv_test_str[31], (Fnv64_t) 0xa1bb96378e897f5bULL },
1369 { &fnv_test_str[32], (Fnv64_t) 0x5b3f9b6733a367d2ULL },
1370 { &fnv_test_str[33], (Fnv64_t) 0xb07ce25cbea969f6ULL },
1371 { &fnv_test_str[34], (Fnv64_t) 0x8d9e9997f9df0d6aULL },
1372 { &fnv_test_str[35], (Fnv64_t) 0x838c673d9603cb7bULL },
1373 { &fnv_test_str[36], (Fnv64_t) 0x8b5ee8a5e872c273ULL },
1374 { &fnv_test_str[37], (Fnv64_t) 0x4507c4e9fb00690cULL },
1375 { &fnv_test_str[38], (Fnv64_t) 0x4c9ca59581b27f45ULL },
1376 { &fnv_test_str[39], (Fnv64_t) 0xe0aca20b624e4235ULL },
1377 { &fnv_test_str[40], (Fnv64_t) 0xd8d5c8186ba98b94ULL },
1378 { &fnv_test_str[41], (Fnv64_t) 0x1ccefc7ef118db81ULL },
1379 { &fnv_test_str[42], (Fnv64_t) 0x0c92fab3ad3db71dULL },
1380 { &fnv_test_str[43], (Fnv64_t) 0x9b77794f5fdec44eULL },
1381 { &fnv_test_str[44], (Fnv64_t) 0x0ac742dfe7874413ULL },
1382 { &fnv_test_str[45], (Fnv64_t) 0xd7dad5766ad8e2a9ULL },
1383 { &fnv_test_str[46], (Fnv64_t) 0xa1bb96378e897f3aULL },
1384 { &fnv_test_str[47], (Fnv64_t) 0x5b3f9b6733a367a1ULL },
1385 { &fnv_test_str[48], (Fnv64_t) 0xb07ce25cbea969d6ULL },
1386 { &fnv_test_str[49], (Fnv64_t) 0x8d9e9997f9df0d02ULL },
1387 { &fnv_test_str[50], (Fnv64_t) 0x838c673d9603cb1eULL },
1388 { &fnv_test_str[51], (Fnv64_t) 0x8b5ee8a5e872c201ULL },
1389 { &fnv_test_str[52], (Fnv64_t) 0x4507c4e9fb006969ULL },
1390 { &fnv_test_str[53], (Fnv64_t) 0x4c9ca59581b27f64ULL },
1391 { &fnv_test_str[54], (Fnv64_t) 0xe0aca20b624e423fULL },
1392 { &fnv_test_str[55], (Fnv64_t) 0x13998e580afa800fULL },
1393 { &fnv_test_str[56], (Fnv64_t) 0x08326507b4eb3401ULL },
1394 { &fnv_test_str[57], (Fnv64_t) 0xd8d5ad186ba95dc1ULL },
1395 { &fnv_test_str[58], (Fnv64_t) 0x1c72e17ef0ca4e97ULL },
1396 { &fnv_test_str[59], (Fnv64_t) 0x2183c1b327c38ae6ULL },
1397 { &fnv_test_str[60], (Fnv64_t) 0xb66d096c914504f2ULL },
1398 { &fnv_test_str[61], (Fnv64_t) 0x404bf57ad8476757ULL },
1399 { &fnv_test_str[62], (Fnv64_t) 0x887976bd815498bbULL },
1400 { &fnv_test_str[63], (Fnv64_t) 0x3afd7f02c2bf85a5ULL },
1401 { &fnv_test_str[64], (Fnv64_t) 0xfc4476b0eb70177fULL },
1402 { &fnv_test_str[65], (Fnv64_t) 0x186d2da00f77ecbaULL },
1403 { &fnv_test_str[66], (Fnv64_t) 0xf97140fa48c74066ULL },
1404 { &fnv_test_str[67], (Fnv64_t) 0xa2b1cf49aa926d37ULL },
1405 { &fnv_test_str[68], (Fnv64_t) 0x0690712cd6cf940cULL },
1406 { &fnv_test_str[69], (Fnv64_t) 0xf7045b3102b8906eULL },
1407 { &fnv_test_str[70], (Fnv64_t) 0xd8d5ad186ba95db3ULL },
1408 { &fnv_test_str[71], (Fnv64_t) 0x1c72e17ef0ca4ef3ULL },
1409 { &fnv_test_str[72], (Fnv64_t) 0x2183c1b327c38a95ULL },
1410 { &fnv_test_str[73], (Fnv64_t) 0xb66d096c914504d2ULL },
1411 { &fnv_test_str[74], (Fnv64_t) 0x404bf57ad8476736ULL },
1412 { &fnv_test_str[75], (Fnv64_t) 0x887976bd815498d5ULL },
1413 { &fnv_test_str[76], (Fnv64_t) 0x3afd7f02c2bf85c1ULL },
1414 { &fnv_test_str[77], (Fnv64_t) 0xfc4476b0eb70175fULL },
1415 { &fnv_test_str[78], (Fnv64_t) 0x186d2da00f77eccdULL },
1416 { &fnv_test_str[79], (Fnv64_t) 0xf97140fa48c7400eULL },
1417 { &fnv_test_str[80], (Fnv64_t) 0xa2b1cf49aa926d52ULL },
1418 { &fnv_test_str[81], (Fnv64_t) 0x0690712cd6cf9475ULL },
1419 { &fnv_test_str[82], (Fnv64_t) 0xf7045b3102b89064ULL },
1420 { &fnv_test_str[83], (Fnv64_t) 0x74f762479f9d6aeaULL },
1421 { &fnv_test_str[84], (Fnv64_t) 0x08326007b4eb2b9cULL },
1422 { &fnv_test_str[85], (Fnv64_t) 0xd8c4c9186b9b1a14ULL },
1423 { &fnv_test_str[86], (Fnv64_t) 0x7b495389bdbdd4c7ULL },
1424 { &fnv_test_str[87], (Fnv64_t) 0x3b6dba0d69908e25ULL },
1425 { &fnv_test_str[88], (Fnv64_t) 0xd6b2b17bf4b71261ULL },
1426 { &fnv_test_str[89], (Fnv64_t) 0x447bfb7f98e615b5ULL },
1427 { &fnv_test_str[90], (Fnv64_t) 0xd6b2b17bf4b71262ULL },
1428 { &fnv_test_str[91], (Fnv64_t) 0x3bd2807f93fe1660ULL },
1429 { &fnv_test_str[92], (Fnv64_t) 0xd6b2b17bf4b71263ULL },
1430 { &fnv_test_str[93], (Fnv64_t) 0x3329057f8f16170bULL },
1431 { &fnv_test_str[94], (Fnv64_t) 0xd6b2b17bf4b71264ULL },
1432 { &fnv_test_str[95], (Fnv64_t) 0x2a7f8a7f8a2e19b6ULL },
1433 { &fnv_test_str[96], (Fnv64_t) 0x23d3767e64b2f98aULL },
1434 { &fnv_test_str[97], (Fnv64_t) 0xff768d7e4f9d86a4ULL },
1435 { &fnv_test_str[98], (Fnv64_t) 0x23d3767e64b2f984ULL },
1436 { &fnv_test_str[99], (Fnv64_t) 0xccd1837e334e4aa6ULL },
1437 { &fnv_test_str[100], (Fnv64_t) 0x23d3767e64b2f99aULL },
1438 { &fnv_test_str[101], (Fnv64_t) 0x7691fd7e028f6754ULL },
1439 { &fnv_test_str[102], (Fnv64_t) 0x34ad3b1041204318ULL },
1440 { &fnv_test_str[103], (Fnv64_t) 0xa29e749ea9d201c8ULL },
1441 { &fnv_test_str[104], (Fnv64_t) 0x34ad3b104120431bULL },
1442 { &fnv_test_str[105], (Fnv64_t) 0xa29e779ea9d206e1ULL },
1443 { &fnv_test_str[106], (Fnv64_t) 0x34ad3b104120431aULL },
1444 { &fnv_test_str[107], (Fnv64_t) 0xa29e769ea9d2052eULL },
1445 { &fnv_test_str[108], (Fnv64_t) 0x02a17ebca4aa3497ULL },
1446 { &fnv_test_str[109], (Fnv64_t) 0x229ef18bcd375c95ULL },
1447 { &fnv_test_str[110], (Fnv64_t) 0x02a17dbca4aa32c8ULL },
1448 { &fnv_test_str[111], (Fnv64_t) 0x229b6f8bcd3449d8ULL },
1449 { &fnv_test_str[112], (Fnv64_t) 0x02a184bca4aa3ed5ULL },
1450 { &fnv_test_str[113], (Fnv64_t) 0x22b3618bcd48c3efULL },
1451 { &fnv_test_str[114], (Fnv64_t) 0x5c2c346706186f36ULL },
1452 { &fnv_test_str[115], (Fnv64_t) 0xb78c410f5b84f8c2ULL },
1453 { &fnv_test_str[116], (Fnv64_t) 0xed9478212b267395ULL },
1454 { &fnv_test_str[117], (Fnv64_t) 0xd9bbb55c5256662fULL },
1455 { &fnv_test_str[118], (Fnv64_t) 0x8c54f0203249438aULL },
1456 { &fnv_test_str[119], (Fnv64_t) 0xbd9790b5727dc37eULL },
1457 { &fnv_test_str[120], (Fnv64_t) 0xa64e5f36c9e2b0e3ULL },
1458 { &fnv_test_str[121], (Fnv64_t) 0x8fd0680da3088a04ULL },
1459 { &fnv_test_str[122], (Fnv64_t) 0x67aad32c078284ccULL },
1460 { &fnv_test_str[123], (Fnv64_t) 0xb37d55d81c57b331ULL },
1461 { &fnv_test_str[124], (Fnv64_t) 0x55ac0f3829057c43ULL },
1462 { &fnv_test_str[125], (Fnv64_t) 0xcb27f4b8e1b6cc20ULL },
1463 { &fnv_test_str[126], (Fnv64_t) 0x26caf88bcbef2d19ULL },
1464 { &fnv_test_str[127], (Fnv64_t) 0x8e6e063b97e61b8fULL },
1465 { &fnv_test_str[128], (Fnv64_t) 0xb42750f7f3b7c37eULL },
1466 { &fnv_test_str[129], (Fnv64_t) 0xf3c6ba64cf7ca99bULL },
1467 { &fnv_test_str[130], (Fnv64_t) 0xebfb69b427ea80feULL },
1468 { &fnv_test_str[131], (Fnv64_t) 0x39b50c3ed970f46cULL },
1469 { &fnv_test_str[132], (Fnv64_t) 0x5b9b177aa3eb3e8aULL },
1470 { &fnv_test_str[133], (Fnv64_t) 0x6510063ecf4ec903ULL },
1471 { &fnv_test_str[134], (Fnv64_t) 0x2b3bbd2c00797c7aULL },
1472 { &fnv_test_str[135], (Fnv64_t) 0xf1d6204ff5cb4aa7ULL },
1473 { &fnv_test_str[136], (Fnv64_t) 0x4836e27ccf099f38ULL },
1474 { &fnv_test_str[137], (Fnv64_t) 0x82efbb0dd073b44dULL },
1475 { &fnv_test_str[138], (Fnv64_t) 0x4a80c282ffd7d4c6ULL },
1476 { &fnv_test_str[139], (Fnv64_t) 0x305d1a9c9ee43bdfULL },
1477 { &fnv_test_str[140], (Fnv64_t) 0x15c366948ffc6997ULL },
1478 { &fnv_test_str[141], (Fnv64_t) 0x80153ae218916e7bULL },
1479 { &fnv_test_str[142], (Fnv64_t) 0xfa23e2bdf9e2a9e1ULL },
1480 { &fnv_test_str[143], (Fnv64_t) 0xd47e8d8a2333c6deULL },
1481 { &fnv_test_str[144], (Fnv64_t) 0x7e128095f688b056ULL },
1482 { &fnv_test_str[145], (Fnv64_t) 0x2f5356890efcedabULL },
1483 { &fnv_test_str[146], (Fnv64_t) 0x95c2b383014f55c5ULL },
1484 { &fnv_test_str[147], (Fnv64_t) 0x4727a5339ce6070fULL },
1485 { &fnv_test_str[148], (Fnv64_t) 0xb0555ecd575108e9ULL },
1486 { &fnv_test_str[149], (Fnv64_t) 0x48d785770bb4af37ULL },
1487 { &fnv_test_str[150], (Fnv64_t) 0x09d4701c12af02b1ULL },
1488 { &fnv_test_str[151], (Fnv64_t) 0x79f031e78f3cf62eULL },
1489 { &fnv_test_str[152], (Fnv64_t) 0x52a1ee85db1b5a94ULL },
1490 { &fnv_test_str[153], (Fnv64_t) 0x6bd95b2eb37fa6b8ULL },
1491 { &fnv_test_str[154], (Fnv64_t) 0x74971b7077aef85dULL },
1492 { &fnv_test_str[155], (Fnv64_t) 0xb4e4fae2ffcc1aadULL },
1493 { &fnv_test_str[156], (Fnv64_t) 0x2bd48bd898b8f63aULL },
1494 { &fnv_test_str[157], (Fnv64_t) 0xe9966ac1556257f6ULL },
1495 { &fnv_test_str[158], (Fnv64_t) 0x92a3d1cd078ba293ULL },
1496 { &fnv_test_str[159], (Fnv64_t) 0xf81175a482e20ab8ULL },
1497 { &fnv_test_str[160], (Fnv64_t) 0x5bbb3de722e73048ULL },
1498 { &fnv_test_str[161], (Fnv64_t) 0x6b4f363492b9f2beULL },
1499 { &fnv_test_str[162], (Fnv64_t) 0xc2d559df73d59875ULL },
1500 { &fnv_test_str[163], (Fnv64_t) 0xf75f62284bc7a8c2ULL },
1501 { &fnv_test_str[164], (Fnv64_t) 0xda8dd8e116a9f1ccULL },
1502 { &fnv_test_str[165], (Fnv64_t) 0xbdc1e6ab76057885ULL },
1503 { &fnv_test_str[166], (Fnv64_t) 0xfec6a4238a1224a0ULL },
1504 { &fnv_test_str[167], (Fnv64_t) 0xc03f40f3223e290eULL },
1505 { &fnv_test_str[168], (Fnv64_t) 0x1ed21673466ffda9ULL },
1506 { &fnv_test_str[169], (Fnv64_t) 0xdf70f906bb0dd2afULL },
1507 { &fnv_test_str[170], (Fnv64_t) 0xf3dcda369f2af666ULL },
1508 { &fnv_test_str[171], (Fnv64_t) 0x9ebb11573cdcebdeULL },
1509 { &fnv_test_str[172], (Fnv64_t) 0x81c72d9077fedca0ULL },
1510 { &fnv_test_str[173], (Fnv64_t) 0x0ec074a31be5fb15ULL },
1511 { &fnv_test_str[174], (Fnv64_t) 0x2a8b3280b6c48f20ULL },
1512 { &fnv_test_str[175], (Fnv64_t) 0xfd31777513309344ULL },
1513 { &fnv_test_str[176], (Fnv64_t) 0x194534a86ad006b6ULL },
1514 { &fnv_test_str[177], (Fnv64_t) 0x3be6fdf46e0cfe12ULL },
1515 { &fnv_test_str[178], (Fnv64_t) 0x017cc137a07eb057ULL },
1516 { &fnv_test_str[179], (Fnv64_t) 0x9428fc6e7d26b54dULL },
1517 { &fnv_test_str[180], (Fnv64_t) 0x9aaa2e3603ef8ad7ULL },
1518 { &fnv_test_str[181], (Fnv64_t) 0x82c6d3f3a0ccdf7dULL },
1519 { &fnv_test_str[182], (Fnv64_t) 0xc86eeea00cf09b65ULL },
1520 { &fnv_test_str[183], (Fnv64_t) 0x705f8189dbb58299ULL },
1521 { &fnv_test_str[184], (Fnv64_t) 0x415a7f554391ca69ULL },
1522 { &fnv_test_str[185], (Fnv64_t) 0xcfe3d49fa2bdc555ULL },
1523 { &fnv_test_str[186], (Fnv64_t) 0xf0f9c56039b25191ULL },
1524 { &fnv_test_str[187], (Fnv64_t) 0x7075cb6abd1d32d9ULL },
1525 { &fnv_test_str[188], (Fnv64_t) 0x43c94e2c8b277509ULL },
1526 { &fnv_test_str[189], (Fnv64_t) 0x3cbfd4e4ea670359ULL },
1527 { &fnv_test_str[190], (Fnv64_t) 0xc05887810f4d019dULL },
1528 { &fnv_test_str[191], (Fnv64_t) 0x14468ff93ac22dc5ULL },
1529 { &fnv_test_str[192], (Fnv64_t) 0xebed699589d99c05ULL },
1530 { &fnv_test_str[193], (Fnv64_t) 0x6d99f6df321ca5d5ULL },
1531 { &fnv_test_str[194], (Fnv64_t) 0x0cd410d08c36d625ULL },
1532 { &fnv_test_str[195], (Fnv64_t) 0xef1b2a2c86831d35ULL },
1533 { &fnv_test_str[196], (Fnv64_t) 0x3b349c4d69ee5f05ULL },
1534 { &fnv_test_str[197], (Fnv64_t) 0x55248ce88f45f035ULL },
1535 { &fnv_test_str[198], (Fnv64_t) 0xaa69ca6a18a4c885ULL },
1536 { &fnv_test_str[199], (Fnv64_t) 0x1fe3fce62bd816b5ULL },
1537 { &fnv_test_str[200], (Fnv64_t) 0x0289a488a8df69d9ULL },
1538 { &fnv_test_str[201], (Fnv64_t) 0x15e96e1613df98b5ULL },
1539 { &fnv_test_str[202], (Fnv64_t) 0xe6be57375ad89b99ULL },
1540 { NULL, (Fnv64_t) 0 }
1541};
1542#else /* HAVE_64BIT_LONG_LONG */
1543struct fnv1_64_test_vector fnv1_64_vector[] = {
1544 { &fnv_test_str[0], (Fnv64_t) {0x84222325UL, 0xcbf29ce4UL} },
1545 { &fnv_test_str[1], (Fnv64_t) {0x8601b7beUL, 0xaf63bd4cUL} },
1546 { &fnv_test_str[2], (Fnv64_t) {0x8601b7bdUL, 0xaf63bd4cUL} },
1547 { &fnv_test_str[3], (Fnv64_t) {0x8601b7bcUL, 0xaf63bd4cUL} },
1548 { &fnv_test_str[4], (Fnv64_t) {0x8601b7bbUL, 0xaf63bd4cUL} },
1549 { &fnv_test_str[5], (Fnv64_t) {0x8601b7baUL, 0xaf63bd4cUL} },
1550 { &fnv_test_str[6], (Fnv64_t) {0x8601b7b9UL, 0xaf63bd4cUL} },
1551 { &fnv_test_str[7], (Fnv64_t) {0xb4eb2f34UL, 0x08326207UL} },
1552 { &fnv_test_str[8], (Fnv64_t) {0x6ba13533UL, 0xd8cbc718UL} },
1553 { &fnv_test_str[9], (Fnv64_t) {0xe2ed65cbUL, 0x0378817eUL} },
1554 { &fnv_test_str[10], (Fnv64_t) {0x9963f790UL, 0xd329d59bUL} },
1555 { &fnv_test_str[11], (Fnv64_t) {0xa4dda9c2UL, 0x340d8765UL} },
1556 { &fnv_test_str[12], (Fnv64_t) {0x8601b7dfUL, 0xaf63bd4cUL} },
1557 { &fnv_test_str[13], (Fnv64_t) {0xb4eb37daUL, 0x08326707UL} },
1558 { &fnv_test_str[14], (Fnv64_t) {0xb4eb3627UL, 0x08326607UL} },
1559 { &fnv_test_str[15], (Fnv64_t) {0xb4eb3474UL, 0x08326507UL} },
1560 { &fnv_test_str[16], (Fnv64_t) {0xb4eb32c1UL, 0x08326407UL} },
1561 { &fnv_test_str[17], (Fnv64_t) {0xb4eb310eUL, 0x08326307UL} },
1562 { &fnv_test_str[18], (Fnv64_t) {0xb4eb2f5bUL, 0x08326207UL} },
1563 { &fnv_test_str[19], (Fnv64_t) {0x6ba1355cUL, 0xd8cbc718UL} },
1564 { &fnv_test_str[20], (Fnv64_t) {0xe2ed65a9UL, 0x0378817eUL} },
1565 { &fnv_test_str[21], (Fnv64_t) {0x9963f7f1UL, 0xd329d59bUL} },
1566 { &fnv_test_str[22], (Fnv64_t) {0xa4dda9b0UL, 0x340d8765UL} },
1567 { &fnv_test_str[23], (Fnv64_t) {0x24a774a6UL, 0x50a6d3b7UL} },
1568 { &fnv_test_str[24], (Fnv64_t) {0xb4eb341cUL, 0x08326507UL} },
1569 { &fnv_test_str[25], (Fnv64_t) {0x6ba98bfbUL, 0xd8d5c818UL} },
1570 { &fnv_test_str[26], (Fnv64_t) {0xf118dbefUL, 0x1ccefc7eUL} },
1571 { &fnv_test_str[27], (Fnv64_t) {0xad3db77aUL, 0x0c92fab3UL} },
1572 { &fnv_test_str[28], (Fnv64_t) {0x5fdec421UL, 0x9b77794fUL} },
1573 { &fnv_test_str[29], (Fnv64_t) {0xe7874433UL, 0x0ac742dfUL} },
1574 { &fnv_test_str[30], (Fnv64_t) {0x6ad8e2deUL, 0xd7dad576UL} },
1575 { &fnv_test_str[31], (Fnv64_t) {0x8e897f5bUL, 0xa1bb9637UL} },
1576 { &fnv_test_str[32], (Fnv64_t) {0x33a367d2UL, 0x5b3f9b67UL} },
1577 { &fnv_test_str[33], (Fnv64_t) {0xbea969f6UL, 0xb07ce25cUL} },
1578 { &fnv_test_str[34], (Fnv64_t) {0xf9df0d6aUL, 0x8d9e9997UL} },
1579 { &fnv_test_str[35], (Fnv64_t) {0x9603cb7bUL, 0x838c673dUL} },
1580 { &fnv_test_str[36], (Fnv64_t) {0xe872c273UL, 0x8b5ee8a5UL} },
1581 { &fnv_test_str[37], (Fnv64_t) {0xfb00690cUL, 0x4507c4e9UL} },
1582 { &fnv_test_str[38], (Fnv64_t) {0x81b27f45UL, 0x4c9ca595UL} },
1583 { &fnv_test_str[39], (Fnv64_t) {0x624e4235UL, 0xe0aca20bUL} },
1584 { &fnv_test_str[40], (Fnv64_t) {0x6ba98b94UL, 0xd8d5c818UL} },
1585 { &fnv_test_str[41], (Fnv64_t) {0xf118db81UL, 0x1ccefc7eUL} },
1586 { &fnv_test_str[42], (Fnv64_t) {0xad3db71dUL, 0x0c92fab3UL} },
1587 { &fnv_test_str[43], (Fnv64_t) {0x5fdec44eUL, 0x9b77794fUL} },
1588 { &fnv_test_str[44], (Fnv64_t) {0xe7874413UL, 0x0ac742dfUL} },
1589 { &fnv_test_str[45], (Fnv64_t) {0x6ad8e2a9UL, 0xd7dad576UL} },
1590 { &fnv_test_str[46], (Fnv64_t) {0x8e897f3aUL, 0xa1bb9637UL} },
1591 { &fnv_test_str[47], (Fnv64_t) {0x33a367a1UL, 0x5b3f9b67UL} },
1592 { &fnv_test_str[48], (Fnv64_t) {0xbea969d6UL, 0xb07ce25cUL} },
1593 { &fnv_test_str[49], (Fnv64_t) {0xf9df0d02UL, 0x8d9e9997UL} },
1594 { &fnv_test_str[50], (Fnv64_t) {0x9603cb1eUL, 0x838c673dUL} },
1595 { &fnv_test_str[51], (Fnv64_t) {0xe872c201UL, 0x8b5ee8a5UL} },
1596 { &fnv_test_str[52], (Fnv64_t) {0xfb006969UL, 0x4507c4e9UL} },
1597 { &fnv_test_str[53], (Fnv64_t) {0x81b27f64UL, 0x4c9ca595UL} },
1598 { &fnv_test_str[54], (Fnv64_t) {0x624e423fUL, 0xe0aca20bUL} },
1599 { &fnv_test_str[55], (Fnv64_t) {0x0afa800fUL, 0x13998e58UL} },
1600 { &fnv_test_str[56], (Fnv64_t) {0xb4eb3401UL, 0x08326507UL} },
1601 { &fnv_test_str[57], (Fnv64_t) {0x6ba95dc1UL, 0xd8d5ad18UL} },
1602 { &fnv_test_str[58], (Fnv64_t) {0xf0ca4e97UL, 0x1c72e17eUL} },
1603 { &fnv_test_str[59], (Fnv64_t) {0x27c38ae6UL, 0x2183c1b3UL} },
1604 { &fnv_test_str[60], (Fnv64_t) {0x914504f2UL, 0xb66d096cUL} },
1605 { &fnv_test_str[61], (Fnv64_t) {0xd8476757UL, 0x404bf57aUL} },
1606 { &fnv_test_str[62], (Fnv64_t) {0x815498bbUL, 0x887976bdUL} },
1607 { &fnv_test_str[63], (Fnv64_t) {0xc2bf85a5UL, 0x3afd7f02UL} },
1608 { &fnv_test_str[64], (Fnv64_t) {0xeb70177fUL, 0xfc4476b0UL} },
1609 { &fnv_test_str[65], (Fnv64_t) {0x0f77ecbaUL, 0x186d2da0UL} },
1610 { &fnv_test_str[66], (Fnv64_t) {0x48c74066UL, 0xf97140faUL} },
1611 { &fnv_test_str[67], (Fnv64_t) {0xaa926d37UL, 0xa2b1cf49UL} },
1612 { &fnv_test_str[68], (Fnv64_t) {0xd6cf940cUL, 0x0690712cUL} },
1613 { &fnv_test_str[69], (Fnv64_t) {0x02b8906eUL, 0xf7045b31UL} },
1614 { &fnv_test_str[70], (Fnv64_t) {0x6ba95db3UL, 0xd8d5ad18UL} },
1615 { &fnv_test_str[71], (Fnv64_t) {0xf0ca4ef3UL, 0x1c72e17eUL} },
1616 { &fnv_test_str[72], (Fnv64_t) {0x27c38a95UL, 0x2183c1b3UL} },
1617 { &fnv_test_str[73], (Fnv64_t) {0x914504d2UL, 0xb66d096cUL} },
1618 { &fnv_test_str[74], (Fnv64_t) {0xd8476736UL, 0x404bf57aUL} },
1619 { &fnv_test_str[75], (Fnv64_t) {0x815498d5UL, 0x887976bdUL} },
1620 { &fnv_test_str[76], (Fnv64_t) {0xc2bf85c1UL, 0x3afd7f02UL} },
1621 { &fnv_test_str[77], (Fnv64_t) {0xeb70175fUL, 0xfc4476b0UL} },
1622 { &fnv_test_str[78], (Fnv64_t) {0x0f77eccdUL, 0x186d2da0UL} },
1623 { &fnv_test_str[79], (Fnv64_t) {0x48c7400eUL, 0xf97140faUL} },
1624 { &fnv_test_str[80], (Fnv64_t) {0xaa926d52UL, 0xa2b1cf49UL} },
1625 { &fnv_test_str[81], (Fnv64_t) {0xd6cf9475UL, 0x0690712cUL} },
1626 { &fnv_test_str[82], (Fnv64_t) {0x02b89064UL, 0xf7045b31UL} },
1627 { &fnv_test_str[83], (Fnv64_t) {0x9f9d6aeaUL, 0x74f76247UL} },
1628 { &fnv_test_str[84], (Fnv64_t) {0xb4eb2b9cUL, 0x08326007UL} },
1629 { &fnv_test_str[85], (Fnv64_t) {0x6b9b1a14UL, 0xd8c4c918UL} },
1630 { &fnv_test_str[86], (Fnv64_t) {0xbdbdd4c7UL, 0x7b495389UL} },
1631 { &fnv_test_str[87], (Fnv64_t) {0x69908e25UL, 0x3b6dba0dUL} },
1632 { &fnv_test_str[88], (Fnv64_t) {0xf4b71261UL, 0xd6b2b17bUL} },
1633 { &fnv_test_str[89], (Fnv64_t) {0x98e615b5UL, 0x447bfb7fUL} },
1634 { &fnv_test_str[90], (Fnv64_t) {0xf4b71262UL, 0xd6b2b17bUL} },
1635 { &fnv_test_str[91], (Fnv64_t) {0x93fe1660UL, 0x3bd2807fUL} },
1636 { &fnv_test_str[92], (Fnv64_t) {0xf4b71263UL, 0xd6b2b17bUL} },
1637 { &fnv_test_str[93], (Fnv64_t) {0x8f16170bUL, 0x3329057fUL} },
1638 { &fnv_test_str[94], (Fnv64_t) {0xf4b71264UL, 0xd6b2b17bUL} },
1639 { &fnv_test_str[95], (Fnv64_t) {0x8a2e19b6UL, 0x2a7f8a7fUL} },
1640 { &fnv_test_str[96], (Fnv64_t) {0x64b2f98aUL, 0x23d3767eUL} },
1641 { &fnv_test_str[97], (Fnv64_t) {0x4f9d86a4UL, 0xff768d7eUL} },
1642 { &fnv_test_str[98], (Fnv64_t) {0x64b2f984UL, 0x23d3767eUL} },
1643 { &fnv_test_str[99], (Fnv64_t) {0x334e4aa6UL, 0xccd1837eUL} },
1644 { &fnv_test_str[100], (Fnv64_t) {0x64b2f99aUL, 0x23d3767eUL} },
1645 { &fnv_test_str[101], (Fnv64_t) {0x028f6754UL, 0x7691fd7eUL} },
1646 { &fnv_test_str[102], (Fnv64_t) {0x41204318UL, 0x34ad3b10UL} },
1647 { &fnv_test_str[103], (Fnv64_t) {0xa9d201c8UL, 0xa29e749eUL} },
1648 { &fnv_test_str[104], (Fnv64_t) {0x4120431bUL, 0x34ad3b10UL} },
1649 { &fnv_test_str[105], (Fnv64_t) {0xa9d206e1UL, 0xa29e779eUL} },
1650 { &fnv_test_str[106], (Fnv64_t) {0x4120431aUL, 0x34ad3b10UL} },
1651 { &fnv_test_str[107], (Fnv64_t) {0xa9d2052eUL, 0xa29e769eUL} },
1652 { &fnv_test_str[108], (Fnv64_t) {0xa4aa3497UL, 0x02a17ebcUL} },
1653 { &fnv_test_str[109], (Fnv64_t) {0xcd375c95UL, 0x229ef18bUL} },
1654 { &fnv_test_str[110], (Fnv64_t) {0xa4aa32c8UL, 0x02a17dbcUL} },
1655 { &fnv_test_str[111], (Fnv64_t) {0xcd3449d8UL, 0x229b6f8bUL} },
1656 { &fnv_test_str[112], (Fnv64_t) {0xa4aa3ed5UL, 0x02a184bcUL} },
1657 { &fnv_test_str[113], (Fnv64_t) {0xcd48c3efUL, 0x22b3618bUL} },
1658 { &fnv_test_str[114], (Fnv64_t) {0x06186f36UL, 0x5c2c3467UL} },
1659 { &fnv_test_str[115], (Fnv64_t) {0x5b84f8c2UL, 0xb78c410fUL} },
1660 { &fnv_test_str[116], (Fnv64_t) {0x2b267395UL, 0xed947821UL} },
1661 { &fnv_test_str[117], (Fnv64_t) {0x5256662fUL, 0xd9bbb55cUL} },
1662 { &fnv_test_str[118], (Fnv64_t) {0x3249438aUL, 0x8c54f020UL} },
1663 { &fnv_test_str[119], (Fnv64_t) {0x727dc37eUL, 0xbd9790b5UL} },
1664 { &fnv_test_str[120], (Fnv64_t) {0xc9e2b0e3UL, 0xa64e5f36UL} },
1665 { &fnv_test_str[121], (Fnv64_t) {0xa3088a04UL, 0x8fd0680dUL} },
1666 { &fnv_test_str[122], (Fnv64_t) {0x078284ccUL, 0x67aad32cUL} },
1667 { &fnv_test_str[123], (Fnv64_t) {0x1c57b331UL, 0xb37d55d8UL} },
1668 { &fnv_test_str[124], (Fnv64_t) {0x29057c43UL, 0x55ac0f38UL} },
1669 { &fnv_test_str[125], (Fnv64_t) {0xe1b6cc20UL, 0xcb27f4b8UL} },
1670 { &fnv_test_str[126], (Fnv64_t) {0xcbef2d19UL, 0x26caf88bUL} },
1671 { &fnv_test_str[127], (Fnv64_t) {0x97e61b8fUL, 0x8e6e063bUL} },
1672 { &fnv_test_str[128], (Fnv64_t) {0xf3b7c37eUL, 0xb42750f7UL} },
1673 { &fnv_test_str[129], (Fnv64_t) {0xcf7ca99bUL, 0xf3c6ba64UL} },
1674 { &fnv_test_str[130], (Fnv64_t) {0x27ea80feUL, 0xebfb69b4UL} },
1675 { &fnv_test_str[131], (Fnv64_t) {0xd970f46cUL, 0x39b50c3eUL} },
1676 { &fnv_test_str[132], (Fnv64_t) {0xa3eb3e8aUL, 0x5b9b177aUL} },
1677 { &fnv_test_str[133], (Fnv64_t) {0xcf4ec903UL, 0x6510063eUL} },
1678 { &fnv_test_str[134], (Fnv64_t) {0x00797c7aUL, 0x2b3bbd2cUL} },
1679 { &fnv_test_str[135], (Fnv64_t) {0xf5cb4aa7UL, 0xf1d6204fUL} },
1680 { &fnv_test_str[136], (Fnv64_t) {0xcf099f38UL, 0x4836e27cUL} },
1681 { &fnv_test_str[137], (Fnv64_t) {0xd073b44dUL, 0x82efbb0dUL} },
1682 { &fnv_test_str[138], (Fnv64_t) {0xffd7d4c6UL, 0x4a80c282UL} },
1683 { &fnv_test_str[139], (Fnv64_t) {0x9ee43bdfUL, 0x305d1a9cUL} },
1684 { &fnv_test_str[140], (Fnv64_t) {0x8ffc6997UL, 0x15c36694UL} },
1685 { &fnv_test_str[141], (Fnv64_t) {0x18916e7bUL, 0x80153ae2UL} },
1686 { &fnv_test_str[142], (Fnv64_t) {0xf9e2a9e1UL, 0xfa23e2bdUL} },
1687 { &fnv_test_str[143], (Fnv64_t) {0x2333c6deUL, 0xd47e8d8aUL} },
1688 { &fnv_test_str[144], (Fnv64_t) {0xf688b056UL, 0x7e128095UL} },
1689 { &fnv_test_str[145], (Fnv64_t) {0x0efcedabUL, 0x2f535689UL} },
1690 { &fnv_test_str[146], (Fnv64_t) {0x014f55c5UL, 0x95c2b383UL} },
1691 { &fnv_test_str[147], (Fnv64_t) {0x9ce6070fUL, 0x4727a533UL} },
1692 { &fnv_test_str[148], (Fnv64_t) {0x575108e9UL, 0xb0555ecdUL} },
1693 { &fnv_test_str[149], (Fnv64_t) {0x0bb4af37UL, 0x48d78577UL} },
1694 { &fnv_test_str[150], (Fnv64_t) {0x12af02b1UL, 0x09d4701cUL} },
1695 { &fnv_test_str[151], (Fnv64_t) {0x8f3cf62eUL, 0x79f031e7UL} },
1696 { &fnv_test_str[152], (Fnv64_t) {0xdb1b5a94UL, 0x52a1ee85UL} },
1697 { &fnv_test_str[153], (Fnv64_t) {0xb37fa6b8UL, 0x6bd95b2eUL} },
1698 { &fnv_test_str[154], (Fnv64_t) {0x77aef85dUL, 0x74971b70UL} },
1699 { &fnv_test_str[155], (Fnv64_t) {0xffcc1aadUL, 0xb4e4fae2UL} },
1700 { &fnv_test_str[156], (Fnv64_t) {0x98b8f63aUL, 0x2bd48bd8UL} },
1701 { &fnv_test_str[157], (Fnv64_t) {0x556257f6UL, 0xe9966ac1UL} },
1702 { &fnv_test_str[158], (Fnv64_t) {0x078ba293UL, 0x92a3d1cdUL} },
1703 { &fnv_test_str[159], (Fnv64_t) {0x82e20ab8UL, 0xf81175a4UL} },
1704 { &fnv_test_str[160], (Fnv64_t) {0x22e73048UL, 0x5bbb3de7UL} },
1705 { &fnv_test_str[161], (Fnv64_t) {0x92b9f2beUL, 0x6b4f3634UL} },
1706 { &fnv_test_str[162], (Fnv64_t) {0x73d59875UL, 0xc2d559dfUL} },
1707 { &fnv_test_str[163], (Fnv64_t) {0x4bc7a8c2UL, 0xf75f6228UL} },
1708 { &fnv_test_str[164], (Fnv64_t) {0x16a9f1ccUL, 0xda8dd8e1UL} },
1709 { &fnv_test_str[165], (Fnv64_t) {0x76057885UL, 0xbdc1e6abUL} },
1710 { &fnv_test_str[166], (Fnv64_t) {0x8a1224a0UL, 0xfec6a423UL} },
1711 { &fnv_test_str[167], (Fnv64_t) {0x223e290eUL, 0xc03f40f3UL} },
1712 { &fnv_test_str[168], (Fnv64_t) {0x466ffda9UL, 0x1ed21673UL} },
1713 { &fnv_test_str[169], (Fnv64_t) {0xbb0dd2afUL, 0xdf70f906UL} },
1714 { &fnv_test_str[170], (Fnv64_t) {0x9f2af666UL, 0xf3dcda36UL} },
1715 { &fnv_test_str[171], (Fnv64_t) {0x3cdcebdeUL, 0x9ebb1157UL} },
1716 { &fnv_test_str[172], (Fnv64_t) {0x77fedca0UL, 0x81c72d90UL} },
1717 { &fnv_test_str[173], (Fnv64_t) {0x1be5fb15UL, 0x0ec074a3UL} },
1718 { &fnv_test_str[174], (Fnv64_t) {0xb6c48f20UL, 0x2a8b3280UL} },
1719 { &fnv_test_str[175], (Fnv64_t) {0x13309344UL, 0xfd317775UL} },
1720 { &fnv_test_str[176], (Fnv64_t) {0x6ad006b6UL, 0x194534a8UL} },
1721 { &fnv_test_str[177], (Fnv64_t) {0x6e0cfe12UL, 0x3be6fdf4UL} },
1722 { &fnv_test_str[178], (Fnv64_t) {0xa07eb057UL, 0x017cc137UL} },
1723 { &fnv_test_str[179], (Fnv64_t) {0x7d26b54dUL, 0x9428fc6eUL} },
1724 { &fnv_test_str[180], (Fnv64_t) {0x03ef8ad7UL, 0x9aaa2e36UL} },
1725 { &fnv_test_str[181], (Fnv64_t) {0xa0ccdf7dUL, 0x82c6d3f3UL} },
1726 { &fnv_test_str[182], (Fnv64_t) {0x0cf09b65UL, 0xc86eeea0UL} },
1727 { &fnv_test_str[183], (Fnv64_t) {0xdbb58299UL, 0x705f8189UL} },
1728 { &fnv_test_str[184], (Fnv64_t) {0x4391ca69UL, 0x415a7f55UL} },
1729 { &fnv_test_str[185], (Fnv64_t) {0xa2bdc555UL, 0xcfe3d49fUL} },
1730 { &fnv_test_str[186], (Fnv64_t) {0x39b25191UL, 0xf0f9c560UL} },
1731 { &fnv_test_str[187], (Fnv64_t) {0xbd1d32d9UL, 0x7075cb6aUL} },
1732 { &fnv_test_str[188], (Fnv64_t) {0x8b277509UL, 0x43c94e2cUL} },
1733 { &fnv_test_str[189], (Fnv64_t) {0xea670359UL, 0x3cbfd4e4UL} },
1734 { &fnv_test_str[190], (Fnv64_t) {0x0f4d019dUL, 0xc0588781UL} },
1735 { &fnv_test_str[191], (Fnv64_t) {0x3ac22dc5UL, 0x14468ff9UL} },
1736 { &fnv_test_str[192], (Fnv64_t) {0x89d99c05UL, 0xebed6995UL} },
1737 { &fnv_test_str[193], (Fnv64_t) {0x321ca5d5UL, 0x6d99f6dfUL} },
1738 { &fnv_test_str[194], (Fnv64_t) {0x8c36d625UL, 0x0cd410d0UL} },
1739 { &fnv_test_str[195], (Fnv64_t) {0x86831d35UL, 0xef1b2a2cUL} },
1740 { &fnv_test_str[196], (Fnv64_t) {0x69ee5f05UL, 0x3b349c4dUL} },
1741 { &fnv_test_str[197], (Fnv64_t) {0x8f45f035UL, 0x55248ce8UL} },
1742 { &fnv_test_str[198], (Fnv64_t) {0x18a4c885UL, 0xaa69ca6aUL} },
1743 { &fnv_test_str[199], (Fnv64_t) {0x2bd816b5UL, 0x1fe3fce6UL} },
1744 { &fnv_test_str[200], (Fnv64_t) {0xa8df69d9UL, 0x0289a488UL} },
1745 { &fnv_test_str[201], (Fnv64_t) {0x13df98b5UL, 0x15e96e16UL} },
1746 { &fnv_test_str[202], (Fnv64_t) {0x5ad89b99UL, 0xe6be5737UL} },
1747 { NULL, (Fnv64_t) {0,0} }
1748};
1749#endif /* HAVE_64BIT_LONG_LONG */
1750
1751/* FNV-1a 64 bit test vectors */
1752#if defined(HAVE_64BIT_LONG_LONG)
1753struct fnv1a_64_test_vector fnv1a_64_vector[] = {
1754 { &fnv_test_str[0], (Fnv64_t) 0xcbf29ce484222325ULL },
1755 { &fnv_test_str[1], (Fnv64_t) 0xaf63dc4c8601ec8cULL },
1756 { &fnv_test_str[2], (Fnv64_t) 0xaf63df4c8601f1a5ULL },
1757 { &fnv_test_str[3], (Fnv64_t) 0xaf63de4c8601eff2ULL },
1758 { &fnv_test_str[4], (Fnv64_t) 0xaf63d94c8601e773ULL },
1759 { &fnv_test_str[5], (Fnv64_t) 0xaf63d84c8601e5c0ULL },
1760 { &fnv_test_str[6], (Fnv64_t) 0xaf63db4c8601ead9ULL },
1761 { &fnv_test_str[7], (Fnv64_t) 0x08985907b541d342ULL },
1762 { &fnv_test_str[8], (Fnv64_t) 0xdcb27518fed9d577ULL },
1763 { &fnv_test_str[9], (Fnv64_t) 0xdd120e790c2512afULL },
1764 { &fnv_test_str[10], (Fnv64_t) 0xcac165afa2fef40aULL },
1765 { &fnv_test_str[11], (Fnv64_t) 0x85944171f73967e8ULL },
1766 { &fnv_test_str[12], (Fnv64_t) 0xaf63bd4c8601b7dfULL },
1767 { &fnv_test_str[13], (Fnv64_t) 0x089be207b544f1e4ULL },
1768 { &fnv_test_str[14], (Fnv64_t) 0x08a61407b54d9b5fULL },
1769 { &fnv_test_str[15], (Fnv64_t) 0x08a2ae07b54ab836ULL },
1770 { &fnv_test_str[16], (Fnv64_t) 0x0891b007b53c4869ULL },
1771 { &fnv_test_str[17], (Fnv64_t) 0x088e4a07b5396540ULL },
1772 { &fnv_test_str[18], (Fnv64_t) 0x08987c07b5420ebbULL },
1773 { &fnv_test_str[19], (Fnv64_t) 0xdcb28a18fed9f926ULL },
1774 { &fnv_test_str[20], (Fnv64_t) 0xdd1270790c25b935ULL },
1775 { &fnv_test_str[21], (Fnv64_t) 0xcac146afa2febf5dULL },
1776 { &fnv_test_str[22], (Fnv64_t) 0x8593d371f738acfeULL },
1777 { &fnv_test_str[23], (Fnv64_t) 0x34531ca7168b8f38ULL },
1778 { &fnv_test_str[24], (Fnv64_t) 0x08a25607b54a22aeULL },
1779 { &fnv_test_str[25], (Fnv64_t) 0xf5faf0190cf90df3ULL },
1780 { &fnv_test_str[26], (Fnv64_t) 0xf27397910b3221c7ULL },
1781 { &fnv_test_str[27], (Fnv64_t) 0x2c8c2b76062f22e0ULL },
1782 { &fnv_test_str[28], (Fnv64_t) 0xe150688c8217b8fdULL },
1783 { &fnv_test_str[29], (Fnv64_t) 0xf35a83c10e4f1f87ULL },
1784 { &fnv_test_str[30], (Fnv64_t) 0xd1edd10b507344d0ULL },
1785 { &fnv_test_str[31], (Fnv64_t) 0x2a5ee739b3ddb8c3ULL },
1786 { &fnv_test_str[32], (Fnv64_t) 0xdcfb970ca1c0d310ULL },
1787 { &fnv_test_str[33], (Fnv64_t) 0x4054da76daa6da90ULL },
1788 { &fnv_test_str[34], (Fnv64_t) 0xf70a2ff589861368ULL },
1789 { &fnv_test_str[35], (Fnv64_t) 0x4c628b38aed25f17ULL },
1790 { &fnv_test_str[36], (Fnv64_t) 0x9dd1f6510f78189fULL },
1791 { &fnv_test_str[37], (Fnv64_t) 0xa3de85bd491270ceULL },
1792 { &fnv_test_str[38], (Fnv64_t) 0x858e2fa32a55e61dULL },
1793 { &fnv_test_str[39], (Fnv64_t) 0x46810940eff5f915ULL },
1794 { &fnv_test_str[40], (Fnv64_t) 0xf5fadd190cf8edaaULL },
1795 { &fnv_test_str[41], (Fnv64_t) 0xf273ed910b32b3e9ULL },
1796 { &fnv_test_str[42], (Fnv64_t) 0x2c8c5276062f6525ULL },
1797 { &fnv_test_str[43], (Fnv64_t) 0xe150b98c821842a0ULL },
1798 { &fnv_test_str[44], (Fnv64_t) 0xf35aa3c10e4f55e7ULL },
1799 { &fnv_test_str[45], (Fnv64_t) 0xd1ed680b50729265ULL },
1800 { &fnv_test_str[46], (Fnv64_t) 0x2a5f0639b3dded70ULL },
1801 { &fnv_test_str[47], (Fnv64_t) 0xdcfbaa0ca1c0f359ULL },
1802 { &fnv_test_str[48], (Fnv64_t) 0x4054ba76daa6a430ULL },
1803 { &fnv_test_str[49], (Fnv64_t) 0xf709c7f5898562b0ULL },
1804 { &fnv_test_str[50], (Fnv64_t) 0x4c62e638aed2f9b8ULL },
1805 { &fnv_test_str[51], (Fnv64_t) 0x9dd1a8510f779415ULL },
1806 { &fnv_test_str[52], (Fnv64_t) 0xa3de2abd4911d62dULL },
1807 { &fnv_test_str[53], (Fnv64_t) 0x858e0ea32a55ae0aULL },
1808 { &fnv_test_str[54], (Fnv64_t) 0x46810f40eff60347ULL },
1809 { &fnv_test_str[55], (Fnv64_t) 0xc33bce57bef63eafULL },
1810 { &fnv_test_str[56], (Fnv64_t) 0x08a24307b54a0265ULL },
1811 { &fnv_test_str[57], (Fnv64_t) 0xf5b9fd190cc18d15ULL },
1812 { &fnv_test_str[58], (Fnv64_t) 0x4c968290ace35703ULL },
1813 { &fnv_test_str[59], (Fnv64_t) 0x07174bd5c64d9350ULL },
1814 { &fnv_test_str[60], (Fnv64_t) 0x5a294c3ff5d18750ULL },
1815 { &fnv_test_str[61], (Fnv64_t) 0x05b3c1aeb308b843ULL },
1816 { &fnv_test_str[62], (Fnv64_t) 0xb92a48da37d0f477ULL },
1817 { &fnv_test_str[63], (Fnv64_t) 0x73cdddccd80ebc49ULL },
1818 { &fnv_test_str[64], (Fnv64_t) 0xd58c4c13210a266bULL },
1819 { &fnv_test_str[65], (Fnv64_t) 0xe78b6081243ec194ULL },
1820 { &fnv_test_str[66], (Fnv64_t) 0xb096f77096a39f34ULL },
1821 { &fnv_test_str[67], (Fnv64_t) 0xb425c54ff807b6a3ULL },
1822 { &fnv_test_str[68], (Fnv64_t) 0x23e520e2751bb46eULL },
1823 { &fnv_test_str[69], (Fnv64_t) 0x1a0b44ccfe1385ecULL },
1824 { &fnv_test_str[70], (Fnv64_t) 0xf5ba4b190cc2119fULL },
1825 { &fnv_test_str[71], (Fnv64_t) 0x4c962690ace2baafULL },
1826 { &fnv_test_str[72], (Fnv64_t) 0x0716ded5c64cda19ULL },
1827 { &fnv_test_str[73], (Fnv64_t) 0x5a292c3ff5d150f0ULL },
1828 { &fnv_test_str[74], (Fnv64_t) 0x05b3e0aeb308ecf0ULL },
1829 { &fnv_test_str[75], (Fnv64_t) 0xb92a5eda37d119d9ULL },
1830 { &fnv_test_str[76], (Fnv64_t) 0x73ce41ccd80f6635ULL },
1831 { &fnv_test_str[77], (Fnv64_t) 0xd58c2c132109f00bULL },
1832 { &fnv_test_str[78], (Fnv64_t) 0xe78baf81243f47d1ULL },
1833 { &fnv_test_str[79], (Fnv64_t) 0xb0968f7096a2ee7cULL },
1834 { &fnv_test_str[80], (Fnv64_t) 0xb425a84ff807855cULL },
1835 { &fnv_test_str[81], (Fnv64_t) 0x23e4e9e2751b56f9ULL },
1836 { &fnv_test_str[82], (Fnv64_t) 0x1a0b4eccfe1396eaULL },
1837 { &fnv_test_str[83], (Fnv64_t) 0x54abd453bb2c9004ULL },
1838 { &fnv_test_str[84], (Fnv64_t) 0x08ba5f07b55ec3daULL },
1839 { &fnv_test_str[85], (Fnv64_t) 0x337354193006cb6eULL },
1840 { &fnv_test_str[86], (Fnv64_t) 0xa430d84680aabd0bULL },
1841 { &fnv_test_str[87], (Fnv64_t) 0xa9bc8acca21f39b1ULL },
1842 { &fnv_test_str[88], (Fnv64_t) 0x6961196491cc682dULL },
1843 { &fnv_test_str[89], (Fnv64_t) 0xad2bb1774799dfe9ULL },
1844 { &fnv_test_str[90], (Fnv64_t) 0x6961166491cc6314ULL },
1845 { &fnv_test_str[91], (Fnv64_t) 0x8d1bb3904a3b1236ULL },
1846 { &fnv_test_str[92], (Fnv64_t) 0x6961176491cc64c7ULL },
1847 { &fnv_test_str[93], (Fnv64_t) 0xed205d87f40434c7ULL },
1848 { &fnv_test_str[94], (Fnv64_t) 0x6961146491cc5faeULL },
1849 { &fnv_test_str[95], (Fnv64_t) 0xcd3baf5e44f8ad9cULL },
1850 { &fnv_test_str[96], (Fnv64_t) 0xe3b36596127cd6d8ULL },
1851 { &fnv_test_str[97], (Fnv64_t) 0xf77f1072c8e8a646ULL },
1852 { &fnv_test_str[98], (Fnv64_t) 0xe3b36396127cd372ULL },
1853 { &fnv_test_str[99], (Fnv64_t) 0x6067dce9932ad458ULL },
1854 { &fnv_test_str[100], (Fnv64_t) 0xe3b37596127cf208ULL },
1855 { &fnv_test_str[101], (Fnv64_t) 0x4b7b10fa9fe83936ULL },
1856 { &fnv_test_str[102], (Fnv64_t) 0xaabafe7104d914beULL },
1857 { &fnv_test_str[103], (Fnv64_t) 0xf4d3180b3cde3edaULL },
1858 { &fnv_test_str[104], (Fnv64_t) 0xaabafd7104d9130bULL },
1859 { &fnv_test_str[105], (Fnv64_t) 0xf4cfb20b3cdb5bb1ULL },
1860 { &fnv_test_str[106], (Fnv64_t) 0xaabafc7104d91158ULL },
1861 { &fnv_test_str[107], (Fnv64_t) 0xf4cc4c0b3cd87888ULL },
1862 { &fnv_test_str[108], (Fnv64_t) 0xe729bac5d2a8d3a7ULL },
1863 { &fnv_test_str[109], (Fnv64_t) 0x74bc0524f4dfa4c5ULL },
1864 { &fnv_test_str[110], (Fnv64_t) 0xe72630c5d2a5b352ULL },
1865 { &fnv_test_str[111], (Fnv64_t) 0x6b983224ef8fb456ULL },
1866 { &fnv_test_str[112], (Fnv64_t) 0xe73042c5d2ae266dULL },
1867 { &fnv_test_str[113], (Fnv64_t) 0x8527e324fdeb4b37ULL },
1868 { &fnv_test_str[114], (Fnv64_t) 0x0a83c86fee952abcULL },
1869 { &fnv_test_str[115], (Fnv64_t) 0x7318523267779d74ULL },
1870 { &fnv_test_str[116], (Fnv64_t) 0x3e66d3d56b8caca1ULL },
1871 { &fnv_test_str[117], (Fnv64_t) 0x956694a5c0095593ULL },
1872 { &fnv_test_str[118], (Fnv64_t) 0xcac54572bb1a6fc8ULL },
1873 { &fnv_test_str[119], (Fnv64_t) 0xa7a4c9f3edebf0d8ULL },
1874 { &fnv_test_str[120], (Fnv64_t) 0x7829851fac17b143ULL },
1875 { &fnv_test_str[121], (Fnv64_t) 0x2c8f4c9af81bcf06ULL },
1876 { &fnv_test_str[122], (Fnv64_t) 0xd34e31539740c732ULL },
1877 { &fnv_test_str[123], (Fnv64_t) 0x3605a2ac253d2db1ULL },
1878 { &fnv_test_str[124], (Fnv64_t) 0x08c11b8346f4a3c3ULL },
1879 { &fnv_test_str[125], (Fnv64_t) 0x6be396289ce8a6daULL },
1880 { &fnv_test_str[126], (Fnv64_t) 0xd9b957fb7fe794c5ULL },
1881 { &fnv_test_str[127], (Fnv64_t) 0x05be33da04560a93ULL },
1882 { &fnv_test_str[128], (Fnv64_t) 0x0957f1577ba9747cULL },
1883 { &fnv_test_str[129], (Fnv64_t) 0xda2cc3acc24fba57ULL },
1884 { &fnv_test_str[130], (Fnv64_t) 0x74136f185b29e7f0ULL },
1885 { &fnv_test_str[131], (Fnv64_t) 0xb2f2b4590edb93b2ULL },
1886 { &fnv_test_str[132], (Fnv64_t) 0xb3608fce8b86ae04ULL },
1887 { &fnv_test_str[133], (Fnv64_t) 0x4a3a865079359063ULL },
1888 { &fnv_test_str[134], (Fnv64_t) 0x5b3a7ef496880a50ULL },
1889 { &fnv_test_str[135], (Fnv64_t) 0x48fae3163854c23bULL },
1890 { &fnv_test_str[136], (Fnv64_t) 0x07aaa640476e0b9aULL },
1891 { &fnv_test_str[137], (Fnv64_t) 0x2f653656383a687dULL },
1892 { &fnv_test_str[138], (Fnv64_t) 0xa1031f8e7599d79cULL },
1893 { &fnv_test_str[139], (Fnv64_t) 0xa31908178ff92477ULL },
1894 { &fnv_test_str[140], (Fnv64_t) 0x097edf3c14c3fb83ULL },
1895 { &fnv_test_str[141], (Fnv64_t) 0xb51ca83feaa0971bULL },
1896 { &fnv_test_str[142], (Fnv64_t) 0xdd3c0d96d784f2e9ULL },
1897 { &fnv_test_str[143], (Fnv64_t) 0x86cd26a9ea767d78ULL },
1898 { &fnv_test_str[144], (Fnv64_t) 0xe6b215ff54a30c18ULL },
1899 { &fnv_test_str[145], (Fnv64_t) 0xec5b06a1c5531093ULL },
1900 { &fnv_test_str[146], (Fnv64_t) 0x45665a929f9ec5e5ULL },
1901 { &fnv_test_str[147], (Fnv64_t) 0x8c7609b4a9f10907ULL },
1902 { &fnv_test_str[148], (Fnv64_t) 0x89aac3a491f0d729ULL },
1903 { &fnv_test_str[149], (Fnv64_t) 0x32ce6b26e0f4a403ULL },
1904 { &fnv_test_str[150], (Fnv64_t) 0x614ab44e02b53e01ULL },
1905 { &fnv_test_str[151], (Fnv64_t) 0xfa6472eb6eef3290ULL },
1906 { &fnv_test_str[152], (Fnv64_t) 0x9e5d75eb1948eb6aULL },
1907 { &fnv_test_str[153], (Fnv64_t) 0xb6d12ad4a8671852ULL },
1908 { &fnv_test_str[154], (Fnv64_t) 0x88826f56eba07af1ULL },
1909 { &fnv_test_str[155], (Fnv64_t) 0x44535bf2645bc0fdULL },
1910 { &fnv_test_str[156], (Fnv64_t) 0x169388ffc21e3728ULL },
1911 { &fnv_test_str[157], (Fnv64_t) 0xf68aac9e396d8224ULL },
1912 { &fnv_test_str[158], (Fnv64_t) 0x8e87d7e7472b3883ULL },
1913 { &fnv_test_str[159], (Fnv64_t) 0x295c26caa8b423deULL },
1914 { &fnv_test_str[160], (Fnv64_t) 0x322c814292e72176ULL },
1915 { &fnv_test_str[161], (Fnv64_t) 0x8a06550eb8af7268ULL },
1916 { &fnv_test_str[162], (Fnv64_t) 0xef86d60e661bcf71ULL },
1917 { &fnv_test_str[163], (Fnv64_t) 0x9e5426c87f30ee54ULL },
1918 { &fnv_test_str[164], (Fnv64_t) 0xf1ea8aa826fd047eULL },
1919 { &fnv_test_str[165], (Fnv64_t) 0x0babaf9a642cb769ULL },
1920 { &fnv_test_str[166], (Fnv64_t) 0x4b3341d4068d012eULL },
1921 { &fnv_test_str[167], (Fnv64_t) 0xd15605cbc30a335cULL },
1922 { &fnv_test_str[168], (Fnv64_t) 0x5b21060aed8412e5ULL },
1923 { &fnv_test_str[169], (Fnv64_t) 0x45e2cda1ce6f4227ULL },
1924 { &fnv_test_str[170], (Fnv64_t) 0x50ae3745033ad7d4ULL },
1925 { &fnv_test_str[171], (Fnv64_t) 0xaa4588ced46bf414ULL },
1926 { &fnv_test_str[172], (Fnv64_t) 0xc1b0056c4a95467eULL },
1927 { &fnv_test_str[173], (Fnv64_t) 0x56576a71de8b4089ULL },
1928 { &fnv_test_str[174], (Fnv64_t) 0xbf20965fa6dc927eULL },
1929 { &fnv_test_str[175], (Fnv64_t) 0x569f8383c2040882ULL },
1930 { &fnv_test_str[176], (Fnv64_t) 0xe1e772fba08feca0ULL },
1931 { &fnv_test_str[177], (Fnv64_t) 0x4ced94af97138ac4ULL },
1932 { &fnv_test_str[178], (Fnv64_t) 0xc4112ffb337a82fbULL },
1933 { &fnv_test_str[179], (Fnv64_t) 0xd64a4fd41de38b7dULL },
1934 { &fnv_test_str[180], (Fnv64_t) 0x4cfc32329edebcbbULL },
1935 { &fnv_test_str[181], (Fnv64_t) 0x0803564445050395ULL },
1936 { &fnv_test_str[182], (Fnv64_t) 0xaa1574ecf4642ffdULL },
1937 { &fnv_test_str[183], (Fnv64_t) 0x694bc4e54cc315f9ULL },
1938 { &fnv_test_str[184], (Fnv64_t) 0xa3d7cb273b011721ULL },
1939 { &fnv_test_str[185], (Fnv64_t) 0x577c2f8b6115bfa5ULL },
1940 { &fnv_test_str[186], (Fnv64_t) 0xb7ec8c1a769fb4c1ULL },
1941 { &fnv_test_str[187], (Fnv64_t) 0x5d5cfce63359ab19ULL },
1942 { &fnv_test_str[188], (Fnv64_t) 0x33b96c3cd65b5f71ULL },
1943 { &fnv_test_str[189], (Fnv64_t) 0xd845097780602bb9ULL },
1944 { &fnv_test_str[190], (Fnv64_t) 0x84d47645d02da3d5ULL },
1945 { &fnv_test_str[191], (Fnv64_t) 0x83544f33b58773a5ULL },
1946 { &fnv_test_str[192], (Fnv64_t) 0x9175cbb2160836c5ULL },
1947 { &fnv_test_str[193], (Fnv64_t) 0xc71b3bc175e72bc5ULL },
1948 { &fnv_test_str[194], (Fnv64_t) 0x636806ac222ec985ULL },
1949 { &fnv_test_str[195], (Fnv64_t) 0xb6ef0e6950f52ed5ULL },
1950 { &fnv_test_str[196], (Fnv64_t) 0xead3d8a0f3dfdaa5ULL },
1951 { &fnv_test_str[197], (Fnv64_t) 0x922908fe9a861ba5ULL },
1952 { &fnv_test_str[198], (Fnv64_t) 0x6d4821de275fd5c5ULL },
1953 { &fnv_test_str[199], (Fnv64_t) 0x1fe3fce62bd816b5ULL },
1954 { &fnv_test_str[200], (Fnv64_t) 0xc23e9fccd6f70591ULL },
1955 { &fnv_test_str[201], (Fnv64_t) 0xc1af12bdfe16b5b5ULL },
1956 { &fnv_test_str[202], (Fnv64_t) 0x39e9f18f2f85e221ULL },
1957 { NULL, (Fnv64_t) 0 }
1958};
1959#else /* HAVE_64BIT_LONG_LONG */
1960struct fnv1a_64_test_vector fnv1a_64_vector[] = {
1961 { &fnv_test_str[0], (Fnv64_t) {0x84222325UL, 0xcbf29ce4UL} },
1962 { &fnv_test_str[1], (Fnv64_t) {0x8601ec8cUL, 0xaf63dc4cUL} },
1963 { &fnv_test_str[2], (Fnv64_t) {0x8601f1a5UL, 0xaf63df4cUL} },
1964 { &fnv_test_str[3], (Fnv64_t) {0x8601eff2UL, 0xaf63de4cUL} },
1965 { &fnv_test_str[4], (Fnv64_t) {0x8601e773UL, 0xaf63d94cUL} },
1966 { &fnv_test_str[5], (Fnv64_t) {0x8601e5c0UL, 0xaf63d84cUL} },
1967 { &fnv_test_str[6], (Fnv64_t) {0x8601ead9UL, 0xaf63db4cUL} },
1968 { &fnv_test_str[7], (Fnv64_t) {0xb541d342UL, 0x08985907UL} },
1969 { &fnv_test_str[8], (Fnv64_t) {0xfed9d577UL, 0xdcb27518UL} },
1970 { &fnv_test_str[9], (Fnv64_t) {0x0c2512afUL, 0xdd120e79UL} },
1971 { &fnv_test_str[10], (Fnv64_t) {0xa2fef40aUL, 0xcac165afUL} },
1972 { &fnv_test_str[11], (Fnv64_t) {0xf73967e8UL, 0x85944171UL} },
1973 { &fnv_test_str[12], (Fnv64_t) {0x8601b7dfUL, 0xaf63bd4cUL} },
1974 { &fnv_test_str[13], (Fnv64_t) {0xb544f1e4UL, 0x089be207UL} },
1975 { &fnv_test_str[14], (Fnv64_t) {0xb54d9b5fUL, 0x08a61407UL} },
1976 { &fnv_test_str[15], (Fnv64_t) {0xb54ab836UL, 0x08a2ae07UL} },
1977 { &fnv_test_str[16], (Fnv64_t) {0xb53c4869UL, 0x0891b007UL} },
1978 { &fnv_test_str[17], (Fnv64_t) {0xb5396540UL, 0x088e4a07UL} },
1979 { &fnv_test_str[18], (Fnv64_t) {0xb5420ebbUL, 0x08987c07UL} },
1980 { &fnv_test_str[19], (Fnv64_t) {0xfed9f926UL, 0xdcb28a18UL} },
1981 { &fnv_test_str[20], (Fnv64_t) {0x0c25b935UL, 0xdd127079UL} },
1982 { &fnv_test_str[21], (Fnv64_t) {0xa2febf5dUL, 0xcac146afUL} },
1983 { &fnv_test_str[22], (Fnv64_t) {0xf738acfeUL, 0x8593d371UL} },
1984 { &fnv_test_str[23], (Fnv64_t) {0x168b8f38UL, 0x34531ca7UL} },
1985 { &fnv_test_str[24], (Fnv64_t) {0xb54a22aeUL, 0x08a25607UL} },
1986 { &fnv_test_str[25], (Fnv64_t) {0x0cf90df3UL, 0xf5faf019UL} },
1987 { &fnv_test_str[26], (Fnv64_t) {0x0b3221c7UL, 0xf2739791UL} },
1988 { &fnv_test_str[27], (Fnv64_t) {0x062f22e0UL, 0x2c8c2b76UL} },
1989 { &fnv_test_str[28], (Fnv64_t) {0x8217b8fdUL, 0xe150688cUL} },
1990 { &fnv_test_str[29], (Fnv64_t) {0x0e4f1f87UL, 0xf35a83c1UL} },
1991 { &fnv_test_str[30], (Fnv64_t) {0x507344d0UL, 0xd1edd10bUL} },
1992 { &fnv_test_str[31], (Fnv64_t) {0xb3ddb8c3UL, 0x2a5ee739UL} },
1993 { &fnv_test_str[32], (Fnv64_t) {0xa1c0d310UL, 0xdcfb970cUL} },
1994 { &fnv_test_str[33], (Fnv64_t) {0xdaa6da90UL, 0x4054da76UL} },
1995 { &fnv_test_str[34], (Fnv64_t) {0x89861368UL, 0xf70a2ff5UL} },
1996 { &fnv_test_str[35], (Fnv64_t) {0xaed25f17UL, 0x4c628b38UL} },
1997 { &fnv_test_str[36], (Fnv64_t) {0x0f78189fUL, 0x9dd1f651UL} },
1998 { &fnv_test_str[37], (Fnv64_t) {0x491270ceUL, 0xa3de85bdUL} },
1999 { &fnv_test_str[38], (Fnv64_t) {0x2a55e61dUL, 0x858e2fa3UL} },
2000 { &fnv_test_str[39], (Fnv64_t) {0xeff5f915UL, 0x46810940UL} },
2001 { &fnv_test_str[40], (Fnv64_t) {0x0cf8edaaUL, 0xf5fadd19UL} },
2002 { &fnv_test_str[41], (Fnv64_t) {0x0b32b3e9UL, 0xf273ed91UL} },
2003 { &fnv_test_str[42], (Fnv64_t) {0x062f6525UL, 0x2c8c5276UL} },
2004 { &fnv_test_str[43], (Fnv64_t) {0x821842a0UL, 0xe150b98cUL} },
2005 { &fnv_test_str[44], (Fnv64_t) {0x0e4f55e7UL, 0xf35aa3c1UL} },
2006 { &fnv_test_str[45], (Fnv64_t) {0x50729265UL, 0xd1ed680bUL} },
2007 { &fnv_test_str[46], (Fnv64_t) {0xb3dded70UL, 0x2a5f0639UL} },
2008 { &fnv_test_str[47], (Fnv64_t) {0xa1c0f359UL, 0xdcfbaa0cUL} },
2009 { &fnv_test_str[48], (Fnv64_t) {0xdaa6a430UL, 0x4054ba76UL} },
2010 { &fnv_test_str[49], (Fnv64_t) {0x898562b0UL, 0xf709c7f5UL} },
2011 { &fnv_test_str[50], (Fnv64_t) {0xaed2f9b8UL, 0x4c62e638UL} },
2012 { &fnv_test_str[51], (Fnv64_t) {0x0f779415UL, 0x9dd1a851UL} },
2013 { &fnv_test_str[52], (Fnv64_t) {0x4911d62dUL, 0xa3de2abdUL} },
2014 { &fnv_test_str[53], (Fnv64_t) {0x2a55ae0aUL, 0x858e0ea3UL} },
2015 { &fnv_test_str[54], (Fnv64_t) {0xeff60347UL, 0x46810f40UL} },
2016 { &fnv_test_str[55], (Fnv64_t) {0xbef63eafUL, 0xc33bce57UL} },
2017 { &fnv_test_str[56], (Fnv64_t) {0xb54a0265UL, 0x08a24307UL} },
2018 { &fnv_test_str[57], (Fnv64_t) {0x0cc18d15UL, 0xf5b9fd19UL} },
2019 { &fnv_test_str[58], (Fnv64_t) {0xace35703UL, 0x4c968290UL} },
2020 { &fnv_test_str[59], (Fnv64_t) {0xc64d9350UL, 0x07174bd5UL} },
2021 { &fnv_test_str[60], (Fnv64_t) {0xf5d18750UL, 0x5a294c3fUL} },
2022 { &fnv_test_str[61], (Fnv64_t) {0xb308b843UL, 0x05b3c1aeUL} },
2023 { &fnv_test_str[62], (Fnv64_t) {0x37d0f477UL, 0xb92a48daUL} },
2024 { &fnv_test_str[63], (Fnv64_t) {0xd80ebc49UL, 0x73cdddccUL} },
2025 { &fnv_test_str[64], (Fnv64_t) {0x210a266bUL, 0xd58c4c13UL} },
2026 { &fnv_test_str[65], (Fnv64_t) {0x243ec194UL, 0xe78b6081UL} },
2027 { &fnv_test_str[66], (Fnv64_t) {0x96a39f34UL, 0xb096f770UL} },
2028 { &fnv_test_str[67], (Fnv64_t) {0xf807b6a3UL, 0xb425c54fUL} },
2029 { &fnv_test_str[68], (Fnv64_t) {0x751bb46eUL, 0x23e520e2UL} },
2030 { &fnv_test_str[69], (Fnv64_t) {0xfe1385ecUL, 0x1a0b44ccUL} },
2031 { &fnv_test_str[70], (Fnv64_t) {0x0cc2119fUL, 0xf5ba4b19UL} },
2032 { &fnv_test_str[71], (Fnv64_t) {0xace2baafUL, 0x4c962690UL} },
2033 { &fnv_test_str[72], (Fnv64_t) {0xc64cda19UL, 0x0716ded5UL} },
2034 { &fnv_test_str[73], (Fnv64_t) {0xf5d150f0UL, 0x5a292c3fUL} },
2035 { &fnv_test_str[74], (Fnv64_t) {0xb308ecf0UL, 0x05b3e0aeUL} },
2036 { &fnv_test_str[75], (Fnv64_t) {0x37d119d9UL, 0xb92a5edaUL} },
2037 { &fnv_test_str[76], (Fnv64_t) {0xd80f6635UL, 0x73ce41ccUL} },
2038 { &fnv_test_str[77], (Fnv64_t) {0x2109f00bUL, 0xd58c2c13UL} },
2039 { &fnv_test_str[78], (Fnv64_t) {0x243f47d1UL, 0xe78baf81UL} },
2040 { &fnv_test_str[79], (Fnv64_t) {0x96a2ee7cUL, 0xb0968f70UL} },
2041 { &fnv_test_str[80], (Fnv64_t) {0xf807855cUL, 0xb425a84fUL} },
2042 { &fnv_test_str[81], (Fnv64_t) {0x751b56f9UL, 0x23e4e9e2UL} },
2043 { &fnv_test_str[82], (Fnv64_t) {0xfe1396eaUL, 0x1a0b4eccUL} },
2044 { &fnv_test_str[83], (Fnv64_t) {0xbb2c9004UL, 0x54abd453UL} },
2045 { &fnv_test_str[84], (Fnv64_t) {0xb55ec3daUL, 0x08ba5f07UL} },
2046 { &fnv_test_str[85], (Fnv64_t) {0x3006cb6eUL, 0x33735419UL} },
2047 { &fnv_test_str[86], (Fnv64_t) {0x80aabd0bUL, 0xa430d846UL} },
2048 { &fnv_test_str[87], (Fnv64_t) {0xa21f39b1UL, 0xa9bc8accUL} },
2049 { &fnv_test_str[88], (Fnv64_t) {0x91cc682dUL, 0x69611964UL} },
2050 { &fnv_test_str[89], (Fnv64_t) {0x4799dfe9UL, 0xad2bb177UL} },
2051 { &fnv_test_str[90], (Fnv64_t) {0x91cc6314UL, 0x69611664UL} },
2052 { &fnv_test_str[91], (Fnv64_t) {0x4a3b1236UL, 0x8d1bb390UL} },
2053 { &fnv_test_str[92], (Fnv64_t) {0x91cc64c7UL, 0x69611764UL} },
2054 { &fnv_test_str[93], (Fnv64_t) {0xf40434c7UL, 0xed205d87UL} },
2055 { &fnv_test_str[94], (Fnv64_t) {0x91cc5faeUL, 0x69611464UL} },
2056 { &fnv_test_str[95], (Fnv64_t) {0x44f8ad9cUL, 0xcd3baf5eUL} },
2057 { &fnv_test_str[96], (Fnv64_t) {0x127cd6d8UL, 0xe3b36596UL} },
2058 { &fnv_test_str[97], (Fnv64_t) {0xc8e8a646UL, 0xf77f1072UL} },
2059 { &fnv_test_str[98], (Fnv64_t) {0x127cd372UL, 0xe3b36396UL} },
2060 { &fnv_test_str[99], (Fnv64_t) {0x932ad458UL, 0x6067dce9UL} },
2061 { &fnv_test_str[100], (Fnv64_t) {0x127cf208UL, 0xe3b37596UL} },
2062 { &fnv_test_str[101], (Fnv64_t) {0x9fe83936UL, 0x4b7b10faUL} },
2063 { &fnv_test_str[102], (Fnv64_t) {0x04d914beUL, 0xaabafe71UL} },
2064 { &fnv_test_str[103], (Fnv64_t) {0x3cde3edaUL, 0xf4d3180bUL} },
2065 { &fnv_test_str[104], (Fnv64_t) {0x04d9130bUL, 0xaabafd71UL} },
2066 { &fnv_test_str[105], (Fnv64_t) {0x3cdb5bb1UL, 0xf4cfb20bUL} },
2067 { &fnv_test_str[106], (Fnv64_t) {0x04d91158UL, 0xaabafc71UL} },
2068 { &fnv_test_str[107], (Fnv64_t) {0x3cd87888UL, 0xf4cc4c0bUL} },
2069 { &fnv_test_str[108], (Fnv64_t) {0xd2a8d3a7UL, 0xe729bac5UL} },
2070 { &fnv_test_str[109], (Fnv64_t) {0xf4dfa4c5UL, 0x74bc0524UL} },
2071 { &fnv_test_str[110], (Fnv64_t) {0xd2a5b352UL, 0xe72630c5UL} },
2072 { &fnv_test_str[111], (Fnv64_t) {0xef8fb456UL, 0x6b983224UL} },
2073 { &fnv_test_str[112], (Fnv64_t) {0xd2ae266dUL, 0xe73042c5UL} },
2074 { &fnv_test_str[113], (Fnv64_t) {0xfdeb4b37UL, 0x8527e324UL} },
2075 { &fnv_test_str[114], (Fnv64_t) {0xee952abcUL, 0x0a83c86fUL} },
2076 { &fnv_test_str[115], (Fnv64_t) {0x67779d74UL, 0x73185232UL} },
2077 { &fnv_test_str[116], (Fnv64_t) {0x6b8caca1UL, 0x3e66d3d5UL} },
2078 { &fnv_test_str[117], (Fnv64_t) {0xc0095593UL, 0x956694a5UL} },
2079 { &fnv_test_str[118], (Fnv64_t) {0xbb1a6fc8UL, 0xcac54572UL} },
2080 { &fnv_test_str[119], (Fnv64_t) {0xedebf0d8UL, 0xa7a4c9f3UL} },
2081 { &fnv_test_str[120], (Fnv64_t) {0xac17b143UL, 0x7829851fUL} },
2082 { &fnv_test_str[121], (Fnv64_t) {0xf81bcf06UL, 0x2c8f4c9aUL} },
2083 { &fnv_test_str[122], (Fnv64_t) {0x9740c732UL, 0xd34e3153UL} },
2084 { &fnv_test_str[123], (Fnv64_t) {0x253d2db1UL, 0x3605a2acUL} },
2085 { &fnv_test_str[124], (Fnv64_t) {0x46f4a3c3UL, 0x08c11b83UL} },
2086 { &fnv_test_str[125], (Fnv64_t) {0x9ce8a6daUL, 0x6be39628UL} },
2087 { &fnv_test_str[126], (Fnv64_t) {0x7fe794c5UL, 0xd9b957fbUL} },
2088 { &fnv_test_str[127], (Fnv64_t) {0x04560a93UL, 0x05be33daUL} },
2089 { &fnv_test_str[128], (Fnv64_t) {0x7ba9747cUL, 0x0957f157UL} },
2090 { &fnv_test_str[129], (Fnv64_t) {0xc24fba57UL, 0xda2cc3acUL} },
2091 { &fnv_test_str[130], (Fnv64_t) {0x5b29e7f0UL, 0x74136f18UL} },
2092 { &fnv_test_str[131], (Fnv64_t) {0x0edb93b2UL, 0xb2f2b459UL} },
2093 { &fnv_test_str[132], (Fnv64_t) {0x8b86ae04UL, 0xb3608fceUL} },
2094 { &fnv_test_str[133], (Fnv64_t) {0x79359063UL, 0x4a3a8650UL} },
2095 { &fnv_test_str[134], (Fnv64_t) {0x96880a50UL, 0x5b3a7ef4UL} },
2096 { &fnv_test_str[135], (Fnv64_t) {0x3854c23bUL, 0x48fae316UL} },
2097 { &fnv_test_str[136], (Fnv64_t) {0x476e0b9aUL, 0x07aaa640UL} },
2098 { &fnv_test_str[137], (Fnv64_t) {0x383a687dUL, 0x2f653656UL} },
2099 { &fnv_test_str[138], (Fnv64_t) {0x7599d79cUL, 0xa1031f8eUL} },
2100 { &fnv_test_str[139], (Fnv64_t) {0x8ff92477UL, 0xa3190817UL} },
2101 { &fnv_test_str[140], (Fnv64_t) {0x14c3fb83UL, 0x097edf3cUL} },
2102 { &fnv_test_str[141], (Fnv64_t) {0xeaa0971bUL, 0xb51ca83fUL} },
2103 { &fnv_test_str[142], (Fnv64_t) {0xd784f2e9UL, 0xdd3c0d96UL} },
2104 { &fnv_test_str[143], (Fnv64_t) {0xea767d78UL, 0x86cd26a9UL} },
2105 { &fnv_test_str[144], (Fnv64_t) {0x54a30c18UL, 0xe6b215ffUL} },
2106 { &fnv_test_str[145], (Fnv64_t) {0xc5531093UL, 0xec5b06a1UL} },
2107 { &fnv_test_str[146], (Fnv64_t) {0x9f9ec5e5UL, 0x45665a92UL} },
2108 { &fnv_test_str[147], (Fnv64_t) {0xa9f10907UL, 0x8c7609b4UL} },
2109 { &fnv_test_str[148], (Fnv64_t) {0x91f0d729UL, 0x89aac3a4UL} },
2110 { &fnv_test_str[149], (Fnv64_t) {0xe0f4a403UL, 0x32ce6b26UL} },
2111 { &fnv_test_str[150], (Fnv64_t) {0x02b53e01UL, 0x614ab44eUL} },
2112 { &fnv_test_str[151], (Fnv64_t) {0x6eef3290UL, 0xfa6472ebUL} },
2113 { &fnv_test_str[152], (Fnv64_t) {0x1948eb6aUL, 0x9e5d75ebUL} },
2114 { &fnv_test_str[153], (Fnv64_t) {0xa8671852UL, 0xb6d12ad4UL} },
2115 { &fnv_test_str[154], (Fnv64_t) {0xeba07af1UL, 0x88826f56UL} },
2116 { &fnv_test_str[155], (Fnv64_t) {0x645bc0fdUL, 0x44535bf2UL} },
2117 { &fnv_test_str[156], (Fnv64_t) {0xc21e3728UL, 0x169388ffUL} },
2118 { &fnv_test_str[157], (Fnv64_t) {0x396d8224UL, 0xf68aac9eUL} },
2119 { &fnv_test_str[158], (Fnv64_t) {0x472b3883UL, 0x8e87d7e7UL} },
2120 { &fnv_test_str[159], (Fnv64_t) {0xa8b423deUL, 0x295c26caUL} },
2121 { &fnv_test_str[160], (Fnv64_t) {0x92e72176UL, 0x322c8142UL} },
2122 { &fnv_test_str[161], (Fnv64_t) {0xb8af7268UL, 0x8a06550eUL} },
2123 { &fnv_test_str[162], (Fnv64_t) {0x661bcf71UL, 0xef86d60eUL} },
2124 { &fnv_test_str[163], (Fnv64_t) {0x7f30ee54UL, 0x9e5426c8UL} },
2125 { &fnv_test_str[164], (Fnv64_t) {0x26fd047eUL, 0xf1ea8aa8UL} },
2126 { &fnv_test_str[165], (Fnv64_t) {0x642cb769UL, 0x0babaf9aUL} },
2127 { &fnv_test_str[166], (Fnv64_t) {0x068d012eUL, 0x4b3341d4UL} },
2128 { &fnv_test_str[167], (Fnv64_t) {0xc30a335cUL, 0xd15605cbUL} },
2129 { &fnv_test_str[168], (Fnv64_t) {0xed8412e5UL, 0x5b21060aUL} },
2130 { &fnv_test_str[169], (Fnv64_t) {0xce6f4227UL, 0x45e2cda1UL} },
2131 { &fnv_test_str[170], (Fnv64_t) {0x033ad7d4UL, 0x50ae3745UL} },
2132 { &fnv_test_str[171], (Fnv64_t) {0xd46bf414UL, 0xaa4588ceUL} },
2133 { &fnv_test_str[172], (Fnv64_t) {0x4a95467eUL, 0xc1b0056cUL} },
2134 { &fnv_test_str[173], (Fnv64_t) {0xde8b4089UL, 0x56576a71UL} },
2135 { &fnv_test_str[174], (Fnv64_t) {0xa6dc927eUL, 0xbf20965fUL} },
2136 { &fnv_test_str[175], (Fnv64_t) {0xc2040882UL, 0x569f8383UL} },
2137 { &fnv_test_str[176], (Fnv64_t) {0xa08feca0UL, 0xe1e772fbUL} },
2138 { &fnv_test_str[177], (Fnv64_t) {0x97138ac4UL, 0x4ced94afUL} },
2139 { &fnv_test_str[178], (Fnv64_t) {0x337a82fbUL, 0xc4112ffbUL} },
2140 { &fnv_test_str[179], (Fnv64_t) {0x1de38b7dUL, 0xd64a4fd4UL} },
2141 { &fnv_test_str[180], (Fnv64_t) {0x9edebcbbUL, 0x4cfc3232UL} },
2142 { &fnv_test_str[181], (Fnv64_t) {0x45050395UL, 0x08035644UL} },
2143 { &fnv_test_str[182], (Fnv64_t) {0xf4642ffdUL, 0xaa1574ecUL} },
2144 { &fnv_test_str[183], (Fnv64_t) {0x4cc315f9UL, 0x694bc4e5UL} },
2145 { &fnv_test_str[184], (Fnv64_t) {0x3b011721UL, 0xa3d7cb27UL} },
2146 { &fnv_test_str[185], (Fnv64_t) {0x6115bfa5UL, 0x577c2f8bUL} },
2147 { &fnv_test_str[186], (Fnv64_t) {0x769fb4c1UL, 0xb7ec8c1aUL} },
2148 { &fnv_test_str[187], (Fnv64_t) {0x3359ab19UL, 0x5d5cfce6UL} },
2149 { &fnv_test_str[188], (Fnv64_t) {0xd65b5f71UL, 0x33b96c3cUL} },
2150 { &fnv_test_str[189], (Fnv64_t) {0x80602bb9UL, 0xd8450977UL} },
2151 { &fnv_test_str[190], (Fnv64_t) {0xd02da3d5UL, 0x84d47645UL} },
2152 { &fnv_test_str[191], (Fnv64_t) {0xb58773a5UL, 0x83544f33UL} },
2153 { &fnv_test_str[192], (Fnv64_t) {0x160836c5UL, 0x9175cbb2UL} },
2154 { &fnv_test_str[193], (Fnv64_t) {0x75e72bc5UL, 0xc71b3bc1UL} },
2155 { &fnv_test_str[194], (Fnv64_t) {0x222ec985UL, 0x636806acUL} },
2156 { &fnv_test_str[195], (Fnv64_t) {0x50f52ed5UL, 0xb6ef0e69UL} },
2157 { &fnv_test_str[196], (Fnv64_t) {0xf3dfdaa5UL, 0xead3d8a0UL} },
2158 { &fnv_test_str[197], (Fnv64_t) {0x9a861ba5UL, 0x922908feUL} },
2159 { &fnv_test_str[198], (Fnv64_t) {0x275fd5c5UL, 0x6d4821deUL} },
2160 { &fnv_test_str[199], (Fnv64_t) {0x2bd816b5UL, 0x1fe3fce6UL} },
2161 { &fnv_test_str[200], (Fnv64_t) {0xd6f70591UL, 0xc23e9fccUL} },
2162 { &fnv_test_str[201], (Fnv64_t) {0xfe16b5b5UL, 0xc1af12bdUL} },
2163 { &fnv_test_str[202], (Fnv64_t) {0x2f85e221UL, 0x39e9f18fUL} },
2164 { NULL, (Fnv64_t) {0,0} }
2165};
2166#endif /* HAVE_64BIT_LONG_LONG */
2167
2168/* end of output generated by make vector.c */
2169/*
2170 * insert the contents of vector.c above
2171 */
2172
2173
2174/*
2175 * unknown_hash_type - report an unknown hash type error
2176 *
2177 * NOTE: Does not return.
2178 */
2179void
2180unknown_hash_type(char *prog, enum fnv_type type, int code)
2181{
2182 fprintf(stderr, "%s: unknown or unexpexted hash type: %d\n", prog, type);
2183 exit(code);
2184}
2185
2186
2187/*
2188 * print_fnv32 - print an FNV hash
2189 *
2190 * given:
2191 * hval the hash value to print
2192 * mask lower bit mask
2193 * verbose 1 => print arg with hash
2194 * arg string or filename arg
2195 */
2196void
2197print_fnv32(Fnv32_t hval, Fnv32_t mask, int verbose, char *arg)
2198{
2199 if (verbose) {
2200 printf("0x%08lx %s\n", hval & mask, arg);
2201 } else {
2202 printf("0x%08lx\n", hval & mask);
2203 }
2204}
2205
2206
2207/*
2208 * print_fnv64 - print an FNV hash
2209 *
2210 * given:
2211 * hval the hash value to print
2212 * mask lower bit mask
2213 * verbose 1 => print arg with hash
2214 * arg string or filename arg
2215 */
2216void
2217print_fnv64(Fnv64_t hval, Fnv64_t mask, int verbose, char *arg)
2218{
2219#if defined(HAVE_64BIT_LONG_LONG)
2220 if (verbose) {
2221 printf("0x%016llx %s\n", hval & mask, arg);
2222 } else {
2223 printf("0x%016llx\n", hval & mask);
2224 }
2225#else
2226 if (verbose) {
2227 printf("0x%08lx%08lx %s\n",
2228 hval.w32[1] & mask.w32[1],
2229 hval.w32[0] & mask.w32[0],
2230 arg);
2231 } else {
2232 printf("0x%08lx%08lx\n",
2233 hval.w32[1] & mask.w32[1],
2234 hval.w32[0] & mask.w32[0]);
2235 }
2236#endif
2237}
diff --git a/quantum/wear_leveling/tests/backing_mocks.cpp b/quantum/wear_leveling/tests/backing_mocks.cpp
new file mode 100644
index 0000000000..1dbb26f8e7
--- /dev/null
+++ b/quantum/wear_leveling/tests/backing_mocks.cpp
@@ -0,0 +1,154 @@
1// Copyright 2022 Nick Brassel (@tzarc)
2// SPDX-License-Identifier: GPL-2.0-or-later
3#include "gtest/gtest.h"
4#include "gmock/gmock.h"
5#include "backing_mocks.hpp"
6
7////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8// Backing Store Mock implementation
9////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10
11void MockBackingStore::reset_instance() {
12 for (auto&& e : backing_storage)
13 e.reset();
14
15 locked = true;
16
17 backing_erasure_count = 0;
18 backing_max_write_count = 0;
19 backing_total_write_count = 0;
20
21 backing_init_invoke_count = 0;
22 backing_unlock_invoke_count = 0;
23 backing_erase_invoke_count = 0;
24 backing_write_invoke_count = 0;
25 backing_lock_invoke_count = 0;
26
27 init_success_callback = [](std::uint64_t) { return true; };
28 erase_success_callback = [](std::uint64_t) { return true; };
29 unlock_success_callback = [](std::uint64_t) { return true; };
30 write_success_callback = [](std::uint64_t, std::uint32_t) { return true; };
31 lock_success_callback = [](std::uint64_t) { return true; };
32
33 write_log.clear();
34}
35
36bool MockBackingStore::init(void) {
37 ++backing_init_invoke_count;
38
39 if (init_success_callback) {
40 return init_success_callback(backing_init_invoke_count);
41 }
42 return true;
43}
44
45bool MockBackingStore::unlock(void) {
46 ++backing_unlock_invoke_count;
47
48 EXPECT_TRUE(is_locked()) << "Attempted to unlock but was not locked";
49 locked = false;
50
51 if (unlock_success_callback) {
52 return unlock_success_callback(backing_unlock_invoke_count);
53 }
54 return true;
55}
56
57bool MockBackingStore::erase(void) {
58 ++backing_erase_invoke_count;
59
60 // Erase each slot
61 for (std::size_t i = 0; i < backing_storage.size(); ++i) {
62 // Drop out of erase early with failure if we need to
63 if (erase_success_callback && !erase_success_callback(backing_erase_invoke_count)) {
64 append_log(true);
65 return false;
66 }
67
68 backing_storage[i].erase();
69 }
70
71 // Keep track of the erase in the write log so that we can verify during tests
72 append_log(true);
73
74 ++backing_erasure_count;
75 return true;
76}
77
78bool MockBackingStore::write(uint32_t address, backing_store_int_t value) {
79 ++backing_write_invoke_count;
80
81 // precondition: value's buffer size already matches BACKING_STORE_WRITE_SIZE
82 EXPECT_TRUE(address % BACKING_STORE_WRITE_SIZE == 0) << "Supplied address was not aligned with the backing store integral size";
83 EXPECT_TRUE(address + BACKING_STORE_WRITE_SIZE <= WEAR_LEVELING_BACKING_SIZE) << "Address would result of out-of-bounds access";
84 EXPECT_FALSE(is_locked()) << "Write was attempted without being unlocked first";
85
86 // Drop out of write early with failure if we need to
87 if (write_success_callback && !write_success_callback(backing_write_invoke_count, address)) {
88 return false;
89 }
90
91 // Write the complement as we're simulating flash memory -- 0xFF means 0x00
92 std::size_t index = address / BACKING_STORE_WRITE_SIZE;
93 backing_storage[index].set(~value);
94
95 // Keep track of the write log so that we can verify during tests
96 append_log(address, value);
97
98 // Keep track of the total number of writes into the backing store
99 ++backing_total_write_count;
100
101 return true;
102}
103
104bool MockBackingStore::lock(void) {
105 ++backing_lock_invoke_count;
106
107 EXPECT_FALSE(is_locked()) << "Attempted to lock but was not unlocked";
108 locked = true;
109
110 if (lock_success_callback) {
111 return lock_success_callback(backing_lock_invoke_count);
112 }
113 return true;
114}
115
116bool MockBackingStore::read(uint32_t address, backing_store_int_t& value) const {
117 // precondition: value's buffer size already matches BACKING_STORE_WRITE_SIZE
118 EXPECT_TRUE(address % BACKING_STORE_WRITE_SIZE == 0) << "Supplied address was not aligned with the backing store integral size";
119 EXPECT_TRUE(address + BACKING_STORE_WRITE_SIZE <= WEAR_LEVELING_BACKING_SIZE) << "Address would result of out-of-bounds access";
120
121 // Read and take the complement as we're simulating flash memory -- 0xFF means 0x00
122 std::size_t index = address / BACKING_STORE_WRITE_SIZE;
123 value = ~backing_storage[index].get();
124
125 return true;
126}
127
128////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
129// Backing Implementation
130////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
131
132extern "C" bool backing_store_init(void) {
133 return MockBackingStore::Instance().init();
134}
135
136extern "C" bool backing_store_unlock(void) {
137 return MockBackingStore::Instance().unlock();
138}
139
140extern "C" bool backing_store_erase(void) {
141 return MockBackingStore::Instance().erase();
142}
143
144extern "C" bool backing_store_write(uint32_t address, backing_store_int_t value) {
145 return MockBackingStore::Instance().write(address, value);
146}
147
148extern "C" bool backing_store_lock(void) {
149 return MockBackingStore::Instance().lock();
150}
151
152extern "C" bool backing_store_read(uint32_t address, backing_store_int_t* value) {
153 return MockBackingStore::Instance().read(address, *value);
154}
diff --git a/quantum/wear_leveling/tests/backing_mocks.hpp b/quantum/wear_leveling/tests/backing_mocks.hpp
new file mode 100644
index 0000000000..e7af7895f3
--- /dev/null
+++ b/quantum/wear_leveling/tests/backing_mocks.hpp
@@ -0,0 +1,210 @@
1// Copyright 2022 Nick Brassel (@tzarc)
2// SPDX-License-Identifier: GPL-2.0-or-later
3#pragma once
4#include <algorithm>
5#include <array>
6#include <cstdint>
7#include <cstdlib>
8#include <functional>
9#include <type_traits>
10#include <vector>
11
12extern "C" {
13#include "fnv.h"
14#include "wear_leveling.h"
15#include "wear_leveling_internal.h"
16};
17
18// Maximum number of mock write log entries to keep
19using MOCK_WRITE_LOG_MAX_ENTRIES = std::integral_constant<std::size_t, 1024>;
20// Complement to the backing store integral, for emulating flash erases of all bytes=0xFF
21using BACKING_STORE_INTEGRAL_COMPLEMENT = std::integral_constant<backing_store_int_t, ((backing_store_int_t)(~(backing_store_int_t)0))>;
22// Total number of elements stored in the backing arrays
23using BACKING_STORE_ELEMENT_COUNT = std::integral_constant<std::size_t, (WEAR_LEVELING_BACKING_SIZE / sizeof(backing_store_int_t))>;
24
25class MockBackingStoreElement {
26 private:
27 backing_store_int_t value;
28 std::size_t writes;
29 std::size_t erases;
30
31 public:
32 MockBackingStoreElement() : value(BACKING_STORE_INTEGRAL_COMPLEMENT::value), writes(0), erases(0) {}
33 void reset() {
34 erase();
35 writes = 0;
36 erases = 0;
37 }
38 void erase() {
39 if (!is_erased()) {
40 ++erases;
41 }
42 value = BACKING_STORE_INTEGRAL_COMPLEMENT::value;
43 }
44 backing_store_int_t get() const {
45 return value;
46 }
47 void set(const backing_store_int_t& v) {
48 EXPECT_TRUE(is_erased()) << "Attempted write at index which isn't empty.";
49 value = v;
50 ++writes;
51 }
52 std::size_t num_writes() const {
53 return writes;
54 }
55 std::size_t num_erases() const {
56 return erases;
57 }
58 bool is_erased() const {
59 return value == BACKING_STORE_INTEGRAL_COMPLEMENT::value;
60 }
61};
62
63struct MockBackingStoreLogEntry {
64 MockBackingStoreLogEntry(uint32_t address, backing_store_int_t value) : address(address), value(value), erased(false) {}
65 MockBackingStoreLogEntry(bool erased) : address(0), value(0), erased(erased) {}
66 uint32_t address = 0; // The address of the operation
67 backing_store_int_t value = 0; // The value of the operation
68 bool erased = false; // Whether the entire backing store was erased
69};
70
71class MockBackingStore {
72 private:
73 MockBackingStore() {
74 reset_instance();
75 }
76
77 // Type containing each of the entries and the write counts
78 using storage_t = std::array<MockBackingStoreElement, BACKING_STORE_ELEMENT_COUNT::value>;
79
80 // Whether the backing store is locked
81 bool locked;
82 // The actual data stored in the emulated flash
83 storage_t backing_storage;
84 // The number of erase cycles that have occurred
85 std::uint64_t backing_erasure_count;
86 // The max number of writes to an element of the backing store
87 std::uint64_t backing_max_write_count;
88 // The total number of writes to all elements of the backing store
89 std::uint64_t backing_total_write_count;
90 // The write log for the backing store
91 std::vector<MockBackingStoreLogEntry> write_log;
92
93 // The number of times each API was invoked
94 std::uint64_t backing_init_invoke_count;
95 std::uint64_t backing_unlock_invoke_count;
96 std::uint64_t backing_erase_invoke_count;
97 std::uint64_t backing_write_invoke_count;
98 std::uint64_t backing_lock_invoke_count;
99
100 // Whether init should succeed
101 std::function<bool(std::uint64_t)> init_success_callback;
102 // Whether erase should succeed
103 std::function<bool(std::uint64_t)> erase_success_callback;
104 // Whether unlocks should succeed
105 std::function<bool(std::uint64_t)> unlock_success_callback;
106 // Whether writes should succeed
107 std::function<bool(std::uint64_t, std::uint32_t)> write_success_callback;
108 // Whether locks should succeed
109 std::function<bool(std::uint64_t)> lock_success_callback;
110
111 template <typename... Args>
112 void append_log(Args&&... args) {
113 if (write_log.size() < MOCK_WRITE_LOG_MAX_ENTRIES::value) {
114 write_log.emplace_back(std::forward<Args>(args)...);
115 }
116 }
117
118 public:
119 static MockBackingStore& Instance() {
120 static MockBackingStore instance;
121 return instance;
122 }
123
124 std::uint64_t erasure_count() const {
125 return backing_erasure_count;
126 }
127 std::uint64_t max_write_count() const {
128 return backing_max_write_count;
129 }
130 std::uint64_t total_write_count() const {
131 return backing_total_write_count;
132 }
133
134 // The number of times each API was invoked
135 std::uint64_t init_invoke_count() const {
136 return backing_init_invoke_count;
137 }
138 std::uint64_t unlock_invoke_count() const {
139 return backing_unlock_invoke_count;
140 }
141 std::uint64_t erase_invoke_count() const {
142 return backing_erase_invoke_count;
143 }
144 std::uint64_t write_invoke_count() const {
145 return backing_write_invoke_count;
146 }
147 std::uint64_t lock_invoke_count() const {
148 return backing_lock_invoke_count;
149 }
150
151 // Clear out the internal data for the next run
152 void reset_instance();
153
154 bool is_locked() const {
155 return locked;
156 }
157
158 // APIs for the backing store
159 bool init();
160 bool unlock();
161 bool erase();
162 bool write(std::uint32_t address, backing_store_int_t value);
163 bool lock();
164 bool read(std::uint32_t address, backing_store_int_t& value) const;
165
166 // Control over when init/writes/erases should succeed
167 void set_init_callback(std::function<bool(std::uint64_t)> callback) {
168 init_success_callback = callback;
169 }
170 void set_erase_callback(std::function<bool(std::uint64_t)> callback) {
171 erase_success_callback = callback;
172 }
173 void set_unlock_callback(std::function<bool(std::uint64_t)> callback) {
174 unlock_success_callback = callback;
175 }
176 void set_write_callback(std::function<bool(std::uint64_t, std::uint32_t)> callback) {
177 write_success_callback = callback;
178 }
179 void set_lock_callback(std::function<bool(std::uint64_t)> callback) {
180 lock_success_callback = callback;
181 }
182
183 auto storage_begin() const -> decltype(backing_storage.begin()) {
184 return backing_storage.begin();
185 }
186 auto storage_end() const -> decltype(backing_storage.end()) {
187 return backing_storage.end();
188 }
189
190 auto storage_begin() -> decltype(backing_storage.begin()) {
191 return backing_storage.begin();
192 }
193 auto storage_end() -> decltype(backing_storage.end()) {
194 return backing_storage.end();
195 }
196
197 auto log_begin() -> decltype(write_log.begin()) {
198 return write_log.begin();
199 }
200 auto log_end() -> decltype(write_log.end()) {
201 return write_log.end();
202 }
203
204 auto log_begin() const -> decltype(write_log.begin()) {
205 return write_log.begin();
206 }
207 auto log_end() const -> decltype(write_log.end()) {
208 return write_log.end();
209 }
210};
diff --git a/quantum/wear_leveling/tests/rules.mk b/quantum/wear_leveling/tests/rules.mk
new file mode 100644
index 0000000000..4d7a964049
--- /dev/null
+++ b/quantum/wear_leveling/tests/rules.mk
@@ -0,0 +1,66 @@
1wear_leveling_common_DEFS := \
2 -DWEAR_LEVELING_TESTS
3wear_leveling_common_SRC := \
4 $(LIB_PATH)/fnv/qmk_fnv_type_validation.c \
5 $(LIB_PATH)/fnv/hash_32a.c \
6 $(LIB_PATH)/fnv/hash_64a.c \
7 $(QUANTUM_PATH)/wear_leveling/wear_leveling.c \
8 $(QUANTUM_PATH)/wear_leveling/tests/backing_mocks.cpp
9wear_leveling_common_INC := \
10 $(LIB_PATH)/fnv \
11 $(QUANTUM_PATH)/wear_leveling
12
13wear_leveling_general_DEFS := \
14 $(wear_leveling_common_DEFS) \
15 -DBACKING_STORE_WRITE_SIZE=2 \
16 -DWEAR_LEVELING_BACKING_SIZE=48 \
17 -DWEAR_LEVELING_LOGICAL_SIZE=16
18wear_leveling_general_SRC := \
19 $(wear_leveling_common_SRC) \
20 $(QUANTUM_PATH)/wear_leveling/tests/wear_leveling_general.cpp
21wear_leveling_general_INC := \
22 $(wear_leveling_common_INC)
23
24wear_leveling_2byte_optimized_writes_DEFS := \
25 $(wear_leveling_common_DEFS) \
26 -DBACKING_STORE_WRITE_SIZE=2 \
27 -DWEAR_LEVELING_BACKING_SIZE=65536 \
28 -DWEAR_LEVELING_LOGICAL_SIZE=32768
29wear_leveling_2byte_optimized_writes_SRC := \
30 $(wear_leveling_common_SRC) \
31 $(QUANTUM_PATH)/wear_leveling/tests/wear_leveling_2byte_optimized_writes.cpp
32wear_leveling_2byte_optimized_writes_INC := \
33 $(wear_leveling_common_INC)
34
35wear_leveling_2byte_DEFS := \
36 $(wear_leveling_common_DEFS) \
37 -DBACKING_STORE_WRITE_SIZE=2 \
38 -DWEAR_LEVELING_BACKING_SIZE=48 \
39 -DWEAR_LEVELING_LOGICAL_SIZE=16
40wear_leveling_2byte_SRC := \
41 $(wear_leveling_common_SRC) \
42 $(QUANTUM_PATH)/wear_leveling/tests/wear_leveling_2byte.cpp
43wear_leveling_2byte_INC := \
44 $(wear_leveling_common_INC)
45
46wear_leveling_4byte_DEFS := \
47 $(wear_leveling_common_DEFS) \
48 -DBACKING_STORE_WRITE_SIZE=4 \
49 -DWEAR_LEVELING_BACKING_SIZE=48 \
50 -DWEAR_LEVELING_LOGICAL_SIZE=16
51wear_leveling_4byte_SRC := \
52 $(wear_leveling_common_SRC) \
53 $(QUANTUM_PATH)/wear_leveling/tests/wear_leveling_4byte.cpp
54wear_leveling_4byte_INC := \
55 $(wear_leveling_common_INC)
56
57wear_leveling_8byte_DEFS := \
58 $(wear_leveling_common_DEFS) \
59 -DBACKING_STORE_WRITE_SIZE=8 \
60 -DWEAR_LEVELING_BACKING_SIZE=48 \
61 -DWEAR_LEVELING_LOGICAL_SIZE=16
62wear_leveling_8byte_SRC := \
63 $(wear_leveling_common_SRC) \
64 $(QUANTUM_PATH)/wear_leveling/tests/wear_leveling_8byte.cpp
65wear_leveling_8byte_INC := \
66 $(wear_leveling_common_INC) \ No newline at end of file
diff --git a/quantum/wear_leveling/tests/testlist.mk b/quantum/wear_leveling/tests/testlist.mk
new file mode 100644
index 0000000000..32cfc178b4
--- /dev/null
+++ b/quantum/wear_leveling/tests/testlist.mk
@@ -0,0 +1,6 @@
1TEST_LIST += \
2 wear_leveling_general \
3 wear_leveling_2byte_optimized_writes \
4 wear_leveling_2byte \
5 wear_leveling_4byte \
6 wear_leveling_8byte
diff --git a/quantum/wear_leveling/tests/wear_leveling_2byte.cpp b/quantum/wear_leveling/tests/wear_leveling_2byte.cpp
new file mode 100644
index 0000000000..b749c32b04
--- /dev/null
+++ b/quantum/wear_leveling/tests/wear_leveling_2byte.cpp
@@ -0,0 +1,228 @@
1// Copyright 2022 Nick Brassel (@tzarc)
2// SPDX-License-Identifier: GPL-2.0-or-later
3#include <numeric>
4#include "gtest/gtest.h"
5#include "gmock/gmock.h"
6#include "backing_mocks.hpp"
7
8class WearLeveling2Byte : public ::testing::Test {
9 protected:
10 void SetUp() override {
11 MockBackingStore::Instance().reset_instance();
12 wear_leveling_init();
13 }
14};
15
16static std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> verify_data;
17
18static wear_leveling_status_t test_write(const uint32_t address, const void* value, size_t length) {
19 memcpy(&verify_data[address], value, length);
20 return wear_leveling_write(address, value, length);
21}
22
23/**
24 * This test verifies that the first write after initialisation occurs after the FNV1a_64 hash location.
25 */
26TEST_F(WearLeveling2Byte, FirstWriteOccursAfterHash) {
27 auto& inst = MockBackingStore::Instance();
28 uint8_t test_value = 0x15;
29 test_write(0x02, &test_value, sizeof(test_value));
30 EXPECT_EQ(inst.log_begin()->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid first write address.";
31}
32
33/**
34 * This test verifies that the first write after initialisation occurs after the FNV1a_64 hash location, after an erase has occurred.
35 */
36TEST_F(WearLeveling2Byte, FirstWriteOccursAfterHash_AfterErase) {
37 auto& inst = MockBackingStore::Instance();
38 uint8_t test_value = 0x15;
39 wear_leveling_erase();
40 test_write(0x02, &test_value, sizeof(test_value));
41 EXPECT_EQ((inst.log_begin() + 1)->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid first write address.";
42}
43
44/**
45 * This test forces consolidation by writing enough to the write log that it overflows, consolidating the data into the
46 * base logical area.
47 */
48TEST_F(WearLeveling2Byte, ConsolidationOverflow) {
49 auto& inst = MockBackingStore::Instance();
50
51 // Generate a test block of data which forces OPTIMIZED_64 writes
52 std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> testvalue;
53
54 // Write the data
55 std::iota(testvalue.begin(), testvalue.end(), 0x20);
56 EXPECT_EQ(test_write(0, testvalue.data(), testvalue.size()), WEAR_LEVELING_CONSOLIDATED) << "Write returned incorrect status";
57 uint8_t dummy = 0x40;
58 EXPECT_EQ(test_write(0x04, &dummy, sizeof(dummy)), WEAR_LEVELING_SUCCESS) << "Write returned incorrect status";
59
60 // All writes are at address<64, so each logical byte written will generate 1 write log entry, thus 1 backing store write.
61 // Expected log:
62 // [0..11]: optimised64, backing address 0x18, logical address 0x00
63 // [12]: erase
64 // [13..20]: consolidated data, backing address 0x00, logical address 0x00
65 // [21..24]: FNV1a_64 result, backing address 0x10
66 // [25]: optimised64, backing address 0x18, logical address 0x04
67 EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), 26);
68
69 // Verify the backing store writes for the write log
70 std::size_t index;
71 write_log_entry_t e;
72 for (index = 0; index < 12; ++index) {
73 auto write_iter = inst.log_begin() + index;
74 EXPECT_EQ(write_iter->address, WEAR_LEVELING_LOGICAL_SIZE + 8 + (index * BACKING_STORE_WRITE_SIZE)) << "Invalid write log address";
75 e.raw16[0] = write_iter->value;
76 EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_OPTIMIZED_64) << "Invalid write log entry type";
77 }
78
79 // Verify the backing store erase
80 {
81 index = 12;
82 auto write_iter = inst.log_begin() + index;
83 e.raw16[0] = write_iter->value;
84 EXPECT_TRUE(write_iter->erased) << "Backing store erase did not occur as required";
85 }
86
87 // Verify the backing store writes for consolidation
88 for (index = 13; index < 21; ++index) {
89 auto write_iter = inst.log_begin() + index;
90 EXPECT_EQ(write_iter->address, (index - 13) * BACKING_STORE_WRITE_SIZE) << "Invalid write log entry address";
91 }
92
93 // Verify the FNV1a_64 write
94 {
95 EXPECT_EQ((inst.log_begin() + 21)->address, WEAR_LEVELING_LOGICAL_SIZE) << "Invalid write log address";
96 e.raw16[0] = (inst.log_begin() + 21)->value;
97 e.raw16[1] = (inst.log_begin() + 22)->value;
98 e.raw16[2] = (inst.log_begin() + 23)->value;
99 e.raw16[3] = (inst.log_begin() + 24)->value;
100 EXPECT_EQ(e.raw64, fnv_64a_buf(testvalue.data(), testvalue.size(), FNV1A_64_INIT)) << "Invalid checksum"; // Note that checksum is based on testvalue, as we overwrote one byte and need to consult the consolidated data, not the current
101 }
102
103 // Verify the final write
104 EXPECT_EQ((inst.log_begin() + 25)->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid write log address";
105
106 // Verify the data is what we expected
107 std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> readback;
108 EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
109 EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback did not match";
110
111 // Re-init and re-read, verifying the reload capability
112 EXPECT_NE(wear_leveling_init(), WEAR_LEVELING_FAILED) << "Re-initialisation failed";
113 EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
114 EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback did not match";
115}
116
117/**
118 * This test verifies multibyte readback gets canceled with an out-of-bounds address.
119 */
120TEST_F(WearLeveling2Byte, PlaybackReadbackMultibyte_OOB) {
121 auto& inst = MockBackingStore::Instance();
122 auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
123
124 // Invalid FNV1a_64 hash
125 (logstart + 0)->set(0);
126 (logstart + 1)->set(0);
127 (logstart + 2)->set(0);
128 (logstart + 3)->set(0);
129
130 // Set up a 2-byte logical write of [0x11,0x12] at logical offset 0x01
131 auto entry0 = LOG_ENTRY_MAKE_MULTIBYTE(0x01, 2);
132 entry0.raw8[3] = 0x11;
133 entry0.raw8[4] = 0x12;
134 (logstart + 4)->set(~entry0.raw16[0]);
135 (logstart + 5)->set(~entry0.raw16[1]);
136 (logstart + 6)->set(~entry0.raw16[2]);
137
138 // Set up a 2-byte logical write of [0x13,0x14] at logical offset 0x1000 (out of bounds)
139 auto entry1 = LOG_ENTRY_MAKE_MULTIBYTE(0x1000, 2);
140 entry1.raw8[3] = 0x13;
141 entry1.raw8[4] = 0x14;
142 (logstart + 7)->set(~entry1.raw16[0]);
143 (logstart + 8)->set(~entry1.raw16[1]);
144 (logstart + 9)->set(~entry1.raw16[2]);
145
146 // Set up a 2-byte logical write of [0x15,0x16] at logical offset 0x01
147 auto entry2 = LOG_ENTRY_MAKE_MULTIBYTE(0x01, 2);
148 entry2.raw8[3] = 0x15;
149 entry2.raw8[4] = 0x16;
150 (logstart + 10)->set(~entry2.raw16[0]);
151 (logstart + 11)->set(~entry2.raw16[1]);
152 (logstart + 12)->set(~entry2.raw16[2]);
153
154 EXPECT_EQ(inst.erasure_count(), 0) << "Invalid initial erase count";
155 EXPECT_EQ(wear_leveling_init(), WEAR_LEVELING_CONSOLIDATED) << "Readback should have failed and triggered consolidation";
156 EXPECT_EQ(inst.erasure_count(), 1) << "Invalid final erase count";
157
158 uint8_t buf[2];
159 wear_leveling_read(0x01, buf, sizeof(buf));
160 EXPECT_EQ(buf[0], 0x11) << "Readback should have maintained the previous pre-failure value from the write log";
161 EXPECT_EQ(buf[1], 0x12) << "Readback should have maintained the previous pre-failure value from the write log";
162}
163
164/**
165 * This test verifies optimized 64 readback gets canceled with an out-of-bounds address.
166 */
167TEST_F(WearLeveling2Byte, PlaybackReadbackOptimized64_OOB) {
168 auto& inst = MockBackingStore::Instance();
169 auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
170
171 // Invalid FNV1a_64 hash
172 (logstart + 0)->set(0);
173 (logstart + 1)->set(0);
174 (logstart + 2)->set(0);
175 (logstart + 3)->set(0);
176
177 // Set up a 1-byte logical write of 0x11 at logical offset 0x01
178 auto entry0 = LOG_ENTRY_MAKE_OPTIMIZED_64(0x01, 0x11);
179 (logstart + 4)->set(~entry0.raw16[0]);
180
181 // Set up a 1-byte logical write of 0x11 at logical offset 0x30 (out of bounds)
182 auto entry1 = LOG_ENTRY_MAKE_OPTIMIZED_64(0x30, 0x11);
183 (logstart + 5)->set(~entry1.raw16[0]);
184
185 // Set up a 1-byte logical write of 0x12 at logical offset 0x01
186 auto entry2 = LOG_ENTRY_MAKE_OPTIMIZED_64(0x01, 0x12);
187 (logstart + 6)->set(~entry2.raw16[0]);
188
189 EXPECT_EQ(inst.erasure_count(), 0) << "Invalid initial erase count";
190 EXPECT_EQ(wear_leveling_init(), WEAR_LEVELING_CONSOLIDATED) << "Readback should have failed and triggered consolidation";
191 EXPECT_EQ(inst.erasure_count(), 1) << "Invalid final erase count";
192 uint8_t tmp;
193 wear_leveling_read(0x01, &tmp, sizeof(tmp));
194 EXPECT_EQ(tmp, 0x11) << "Readback should have maintained the previous pre-failure value from the write log";
195}
196
197/**
198 * This test verifies word 0/1 readback gets canceled with an out-of-bounds address.
199 */
200TEST_F(WearLeveling2Byte, PlaybackReadbackWord01_OOB) {
201 auto& inst = MockBackingStore::Instance();
202 auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
203
204 // Invalid FNV1a_64 hash
205 (logstart + 0)->set(0);
206 (logstart + 1)->set(0);
207 (logstart + 2)->set(0);
208 (logstart + 3)->set(0);
209
210 // Set up a 1-byte logical write of 1 at logical offset 0x02
211 auto entry0 = LOG_ENTRY_MAKE_WORD_01(0x02, 1);
212 (logstart + 4)->set(~entry0.raw16[0]);
213
214 // Set up a 1-byte logical write of 1 at logical offset 0x1000 (out of bounds)
215 auto entry1 = LOG_ENTRY_MAKE_WORD_01(0x1000, 1);
216 (logstart + 5)->set(~entry1.raw16[0]);
217
218 // Set up a 1-byte logical write of 0 at logical offset 0x02
219 auto entry2 = LOG_ENTRY_MAKE_WORD_01(0x02, 0);
220 (logstart + 6)->set(~entry2.raw16[0]);
221
222 EXPECT_EQ(inst.erasure_count(), 0) << "Invalid initial erase count";
223 EXPECT_EQ(wear_leveling_init(), WEAR_LEVELING_CONSOLIDATED) << "Readback should have failed and triggered consolidation";
224 EXPECT_EQ(inst.erasure_count(), 1) << "Invalid final erase count";
225 uint8_t tmp;
226 wear_leveling_read(0x02, &tmp, sizeof(tmp));
227 EXPECT_EQ(tmp, 1) << "Readback should have maintained the previous pre-failure value from the write log";
228}
diff --git a/quantum/wear_leveling/tests/wear_leveling_2byte_optimized_writes.cpp b/quantum/wear_leveling/tests/wear_leveling_2byte_optimized_writes.cpp
new file mode 100644
index 0000000000..0b03113c89
--- /dev/null
+++ b/quantum/wear_leveling/tests/wear_leveling_2byte_optimized_writes.cpp
@@ -0,0 +1,295 @@
1// Copyright 2022 Nick Brassel (@tzarc)
2// SPDX-License-Identifier: GPL-2.0-or-later
3#include <numeric>
4#include "gtest/gtest.h"
5#include "gmock/gmock.h"
6#include "backing_mocks.hpp"
7
8class WearLeveling2ByteOptimizedWrites : public ::testing::Test {
9 protected:
10 void SetUp() override {
11 MockBackingStore::Instance().reset_instance();
12 wear_leveling_init();
13 }
14};
15
16static std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> verify_data;
17
18static wear_leveling_status_t test_write(const uint32_t address, const void* value, size_t length) {
19 memcpy(&verify_data[address], value, length);
20 return wear_leveling_write(address, value, length);
21}
22
23/**
24 * This test ensures the correct number of backing store writes occurs with a multibyte write, given the input buffer size.
25 */
26TEST_F(WearLeveling2ByteOptimizedWrites, MultibyteBackingStoreWriteCounts) {
27 auto& inst = MockBackingStore::Instance();
28
29 for (std::size_t length = 1; length <= 5; ++length) {
30 // Clear things out
31 std::fill(verify_data.begin(), verify_data.end(), 0);
32 inst.reset_instance();
33 wear_leveling_init();
34
35 // Generate a test block of data
36 std::vector<std::uint8_t> testvalue(length);
37 std::iota(testvalue.begin(), testvalue.end(), 0x20);
38
39 // Write the data
40 EXPECT_EQ(test_write(2000, testvalue.data(), testvalue.size()), WEAR_LEVELING_SUCCESS) << "Write failed with incorrect status";
41
42 std::size_t expected;
43 if (length > 3) {
44 expected = 4;
45 } else if (length > 1) {
46 expected = 3;
47 } else {
48 expected = 2;
49 }
50
51 // Check that we got the expected number of write log entries
52 EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), expected);
53 }
54}
55
56/**
57 * This test runs through writing U16 values of `0` or `1` over the entire logical address range, to even addresses only.
58 * - Addresses <16384 will result in a single optimised backing write
59 * - Higher addresses will result in a multibyte write of 3 backing writes
60 */
61TEST_F(WearLeveling2ByteOptimizedWrites, WriteOneThenZeroToEvenAddresses) {
62 auto& inst = MockBackingStore::Instance();
63
64 // Only attempt writes for each address up to a limit that would NOT force a consolidated data write.
65 std::size_t writes_per_loop = (MOCK_WRITE_LOG_MAX_ENTRIES::value / 6) - 1; // Worst case is 6 writes for each pair of writes of 0/1
66 std::size_t final_address;
67 for (uint32_t address = 0; address < WEAR_LEVELING_LOGICAL_SIZE; address += (writes_per_loop * 2)) {
68 // Clear things out
69 std::fill(verify_data.begin(), verify_data.end(), 0);
70 inst.reset_instance();
71 wear_leveling_init();
72
73 // Loop through all the addresses in this range
74 std::size_t expected = 0;
75 for (uint32_t offset = 0; offset < (writes_per_loop * 2); offset += 2) {
76 // If we're about to exceed the limit of the logical store, skip the writes
77 if (address + offset + 2 > WEAR_LEVELING_LOGICAL_SIZE) {
78 break;
79 }
80
81 // The default erased value of the wear-leveling cache is zero, so we write a one first, then a zero, to ensure a backing store write occurs.
82 uint16_t val = 1;
83 EXPECT_EQ(test_write(address + offset, &val, sizeof(val)), WEAR_LEVELING_SUCCESS) << "Write failed with incorrect status";
84 val = 0;
85 EXPECT_EQ(test_write(address + offset, &val, sizeof(val)), WEAR_LEVELING_SUCCESS) << "Write failed with incorrect status";
86
87 std::size_t backing_store_writes_expected = 0;
88 if (address + offset < 16384) {
89 // A U16 value of 0/1 at an even address <16384 will result in 1 backing write each, so we need 2 backing writes for 2 logical writes
90 backing_store_writes_expected = 2;
91 } else {
92 // All other addresses result in a multibyte write (3 backing store writes) to write two local bytes of data
93 backing_store_writes_expected = 6;
94 }
95
96 // Keep track of the total number of expected writes to the backing store
97 expected += backing_store_writes_expected;
98
99 // Verify we're at the correct number of writes
100 EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), expected) << "Write log doesn't match required number of backing store writes for address " << (address + offset);
101
102 // Verify that the write log entries we expect are actually present
103 std::size_t write_index = expected - backing_store_writes_expected;
104 auto write_iter = inst.log_begin() + write_index;
105 write_log_entry_t e;
106 if (address + offset < 16384) {
107 // A U16 value of 0/1 at an even address <16384 will result in 1 backing write each, so we need 2 backing writes for 2 logical writes
108 for (std::size_t i = 0; i < 2; ++i) {
109 e.raw16[0] = write_iter->value;
110 EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_WORD_01) << "Invalid write log entry type at " << (address + offset);
111 ++write_iter;
112 }
113 } else {
114 // Multibyte write
115 e.raw16[0] = write_iter->value;
116 EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_MULTIBYTE) << "Invalid write log entry type at " << (address + offset);
117 EXPECT_EQ(LOG_ENTRY_MULTIBYTE_GET_LENGTH(e), 2) << "Invalid write log entry length at " << (address + offset);
118 ++write_iter;
119 }
120
121 // Keep track of the final address written, so we can verify the entire logical range was handled
122 final_address = address + offset;
123 }
124
125 // Verify the number of writes that occurred to the backing store
126 size_t backing_write_count = std::distance(inst.log_begin(), inst.log_end());
127 EXPECT_EQ(backing_write_count, expected) << "Invalid write count at address " << address;
128
129 // Verify the data is what we expected
130 std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> readback;
131 EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
132 EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback for address " << address << " did not match";
133
134 // Re-init and re-read, testing the reload capability
135 EXPECT_NE(wear_leveling_init(), WEAR_LEVELING_FAILED) << "Re-initialisation failed";
136 EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
137 EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback for address " << address << " did not match";
138 }
139
140 // Verify the full range of the logical area got written
141 EXPECT_EQ(final_address, WEAR_LEVELING_LOGICAL_SIZE - 2) << "Invalid final write address";
142}
143
144/**
145 * This test runs through writing U16 values of `0` or `1` over the entire logical address range, to odd addresses only.
146 * - Addresses <63 will result in 2 optimised backing writes
147 * - Address 63 results in a single optimised backing write for the first logical byte, and a multibyte write of 2 backing writes for the second logical byte
148 * - Higher addresses will result in a multibyte write of 3 backing writes
149 */
150TEST_F(WearLeveling2ByteOptimizedWrites, WriteOneThenZeroToOddAddresses) {
151 auto& inst = MockBackingStore::Instance();
152
153 // Only attempt writes for each address up to a limit that would NOT force a consolidated data write.
154 std::size_t writes_per_loop = (MOCK_WRITE_LOG_MAX_ENTRIES::value / 6) - 1; // Worst case is 6 writes for each pair of writes of 0/1
155 std::size_t final_address;
156 for (uint32_t address = 1; address < WEAR_LEVELING_LOGICAL_SIZE; address += (writes_per_loop * 2)) {
157 // Clear things out
158 std::fill(verify_data.begin(), verify_data.end(), 0);
159 inst.reset_instance();
160 wear_leveling_init();
161
162 // Loop through all the addresses in this range
163 std::size_t expected = 0;
164 for (uint32_t offset = 0; offset < (writes_per_loop * 2); offset += 2) {
165 // If we're about to exceed the limit of the logical store, skip the writes
166 if (address + offset + 2 > WEAR_LEVELING_LOGICAL_SIZE) {
167 break;
168 }
169
170 // The default erased value of the wear-leveling cache is zero, so we write a one first, then a zero, to ensure a backing store write occurs.
171 uint16_t val = 1;
172 EXPECT_EQ(test_write(address + offset, &val, sizeof(val)), WEAR_LEVELING_SUCCESS) << "Write failed with incorrect status";
173 val = 0;
174 EXPECT_EQ(test_write(address + offset, &val, sizeof(val)), WEAR_LEVELING_SUCCESS) << "Write failed with incorrect status";
175
176 std::size_t backing_store_writes_expected = 0;
177 if (address + offset < 63) {
178 // A U16 value of 0/1 at an odd address <64 will result in 2 backing writes each, so we need 4 backing writes for 2 logical writes
179 backing_store_writes_expected = 4;
180 } else if (address + offset == 63) {
181 // If we're straddling the boundary for optimised bytes (addr==64), then the first logical byte is written using the optimised write (1 backing
182 // store write), and the second logical byte uses a multibyte write (2 backing store writes)
183 backing_store_writes_expected = 2 // First logical bytes written using optimised log entries
184 + 4; // Second logical bytes written using multibyte log entries
185 } else {
186 // All other addresses result in a multibyte write (3 backing store writes) to write two local bytes of data
187 backing_store_writes_expected = 6;
188 }
189
190 // Keep track of the total number of expected writes to the backing store
191 expected += backing_store_writes_expected;
192
193 // Verify we're at the correct number of writes
194 EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), expected) << "Write log doesn't match required number of backing store writes for address " << (address + offset);
195
196 // Verify that the write log entries we expect are actually present
197 std::size_t write_index = expected - backing_store_writes_expected;
198 auto write_iter = inst.log_begin() + write_index;
199 write_log_entry_t e;
200 if (address + offset < 63) {
201 // A U16 value of 0/1 at an odd address <64 will result in 2 backing writes each, so we need 4 backing writes for 2 logical writes
202 for (std::size_t i = 0; i < 4; ++i) {
203 e.raw16[0] = write_iter->value;
204 EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_OPTIMIZED_64) << "Invalid write log entry type";
205 ++write_iter;
206 }
207 } else if (address + offset == 63) {
208 // First log entry is the 64-addr optimised one
209 e.raw16[0] = write_iter->value;
210 EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_OPTIMIZED_64) << "Invalid write log entry type";
211 ++write_iter;
212
213 // Second log entry is the multibyte entry for the second logical byte
214 e.raw16[0] = write_iter->value;
215 EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_MULTIBYTE) << "Invalid write log entry type";
216 EXPECT_EQ(LOG_ENTRY_MULTIBYTE_GET_LENGTH(e), 1) << "Invalid write log entry length";
217 ++write_iter;
218 } else {
219 // Multibyte write
220 e.raw16[0] = write_iter->value;
221 EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_MULTIBYTE) << "Invalid write log entry type";
222 EXPECT_EQ(LOG_ENTRY_MULTIBYTE_GET_LENGTH(e), 2) << "Invalid write log entry length";
223 ++write_iter;
224 }
225
226 // Keep track of the final address written, so we can verify the entire logical range was handled
227 final_address = address + offset;
228 }
229
230 // Verify the number of writes that occurred to the backing store
231 size_t backing_write_count = std::distance(inst.log_begin(), inst.log_end());
232 EXPECT_EQ(backing_write_count, expected) << "Invalid write count at address " << address;
233
234 // Verify the data is what we expected
235 std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> readback;
236 EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
237 EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback for address " << address << " did not match";
238
239 // Re-init and re-read, testing the reload capability
240 EXPECT_NE(wear_leveling_init(), WEAR_LEVELING_FAILED) << "Re-initialisation failed";
241 EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
242 EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback for address " << address << " did not match";
243 }
244
245 // Verify the full range of the logical area got written
246 EXPECT_EQ(final_address, WEAR_LEVELING_LOGICAL_SIZE - 3) << "Invalid final write address";
247}
248
249/**
250 * This test verifies readback after playback of the write log, simulating power loss and reboot.
251 */
252TEST_F(WearLeveling2ByteOptimizedWrites, PlaybackReadbackOptimized64_Success) {
253 auto& inst = MockBackingStore::Instance();
254 auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
255
256 // Invalid FNV1a_64 hash
257 (logstart + 0)->set(0);
258 (logstart + 1)->set(0);
259 (logstart + 2)->set(0);
260 (logstart + 3)->set(0);
261
262 // Set up a 1-byte logical write of 0x11 at logical offset 0x01
263 auto entry0 = LOG_ENTRY_MAKE_OPTIMIZED_64(0x01, 0x11);
264 (logstart + 4)->set(~entry0.raw16[0]); // start at offset 4 to skip FNV1a_64 result
265
266 wear_leveling_init();
267 uint8_t tmp;
268
269 wear_leveling_read(0x01, &tmp, sizeof(tmp));
270 EXPECT_EQ(tmp, 0x11) << "Failed to read back the seeded data";
271}
272
273/**
274 * This test verifies readback after playback of the write log, simulating power loss and reboot.
275 */
276TEST_F(WearLeveling2ByteOptimizedWrites, PlaybackReadbackWord01_Success) {
277 auto& inst = MockBackingStore::Instance();
278 auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
279
280 // Invalid FNV1a_64 hash
281 (logstart + 0)->set(0);
282 (logstart + 1)->set(0);
283 (logstart + 2)->set(0);
284 (logstart + 3)->set(0);
285
286 // Set up a 1-byte logical write of 1 at logical offset 0x02
287 auto entry0 = LOG_ENTRY_MAKE_WORD_01(0x02, 1);
288 (logstart + 4)->set(~entry0.raw16[0]); // start at offset 4 to skip FNV1a_64 result
289
290 wear_leveling_init();
291 uint8_t tmp;
292
293 wear_leveling_read(0x02, &tmp, sizeof(tmp));
294 EXPECT_EQ(tmp, 1) << "Failed to read back the seeded data";
295}
diff --git a/quantum/wear_leveling/tests/wear_leveling_4byte.cpp b/quantum/wear_leveling/tests/wear_leveling_4byte.cpp
new file mode 100644
index 0000000000..54482c5fe7
--- /dev/null
+++ b/quantum/wear_leveling/tests/wear_leveling_4byte.cpp
@@ -0,0 +1,193 @@
1// Copyright 2022 Nick Brassel (@tzarc)
2// SPDX-License-Identifier: GPL-2.0-or-later
3#include <numeric>
4#include "gtest/gtest.h"
5#include "gmock/gmock.h"
6#include "backing_mocks.hpp"
7
8class WearLeveling4Byte : public ::testing::Test {
9 protected:
10 void SetUp() override {
11 MockBackingStore::Instance().reset_instance();
12 wear_leveling_init();
13 }
14};
15
16static std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> verify_data;
17
18static wear_leveling_status_t test_write(const uint32_t address, const void* value, size_t length) {
19 memcpy(&verify_data[address], value, length);
20 return wear_leveling_write(address, value, length);
21}
22
23/**
24 * This test verifies that the first write after initialisation occurs after the FNV1a_64 hash location.
25 */
26TEST_F(WearLeveling4Byte, FirstWriteOccursAfterHash) {
27 auto& inst = MockBackingStore::Instance();
28 uint8_t test_value = 0x15;
29 test_write(0x02, &test_value, sizeof(test_value));
30 EXPECT_EQ(inst.log_begin()->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid first write address.";
31}
32
33/**
34 * This test verifies that the first write after initialisation occurs after the FNV1a_64 hash location, after an erase has occurred.
35 */
36TEST_F(WearLeveling4Byte, FirstWriteOccursAfterHash_AfterErase) {
37 auto& inst = MockBackingStore::Instance();
38 uint8_t test_value = 0x15;
39 wear_leveling_erase();
40 test_write(0x02, &test_value, sizeof(test_value));
41 EXPECT_EQ((inst.log_begin() + 1)->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid first write address.";
42}
43
44/**
45 * This test ensures the correct number of backing store writes occurs with a multibyte write, given the input buffer size.
46 */
47TEST_F(WearLeveling4Byte, MultibyteBackingStoreWriteCounts) {
48 auto& inst = MockBackingStore::Instance();
49
50 for (std::size_t length = 1; length <= 5; ++length) {
51 // Clear things out
52 std::fill(verify_data.begin(), verify_data.end(), 0);
53 inst.reset_instance();
54 wear_leveling_init();
55
56 // Generate a test block of data
57 std::vector<std::uint8_t> testvalue(length);
58 std::iota(testvalue.begin(), testvalue.end(), 0x20);
59
60 // Write the data
61 EXPECT_EQ(test_write(0, testvalue.data(), testvalue.size()), WEAR_LEVELING_SUCCESS) << "Write failed with incorrect status";
62
63 std::size_t expected;
64 if (length > 1) {
65 expected = 2;
66 } else {
67 expected = 1;
68 }
69
70 // Check that we got the expected number of write log entries
71 EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), expected);
72 }
73}
74
75/**
76 * This test forces consolidation by writing enough to the write log that it overflows, consolidating the data into the
77 * base logical area.
78 */
79TEST_F(WearLeveling4Byte, ConsolidationOverflow) {
80 auto& inst = MockBackingStore::Instance();
81
82 // Generate a test block of data
83 std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> testvalue;
84
85 // Write the data
86 std::iota(testvalue.begin(), testvalue.end(), 0x20);
87 EXPECT_EQ(test_write(0, testvalue.data(), testvalue.size()), WEAR_LEVELING_CONSOLIDATED) << "Write returned incorrect status";
88 uint8_t dummy = 0x40;
89 EXPECT_EQ(test_write(0x04, &dummy, sizeof(dummy)), WEAR_LEVELING_SUCCESS) << "Write returned incorrect status";
90
91 // Expected log:
92 // [0,1]: multibyte, 5 bytes, backing address 0x18, logical address 0x00
93 // [2,3]: multibyte, 5 bytes, backing address 0x20, logical address 0x05
94 // [4,5]: multibyte, 5 bytes, backing address 0x28, logical address 0x0A, triggers consolidation
95 // [6]: erase
96 // [7,8]: consolidated data, backing address 0x00, logical address 0x00
97 // [9,10]: consolidated data, backing address 0x08, logical address 0x08
98 // [11,12]: FNV1a_64 result, backing address 0x10
99 // [13]: multibyte, 1 byte, backing address 0x18, logical address 0x04
100 EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), 14);
101
102 // Verify the backing store writes for the write log
103 std::size_t index;
104 write_log_entry_t e;
105 for (index = 0; index < 6; ++index) {
106 auto write_iter = inst.log_begin() + index;
107 EXPECT_EQ(write_iter->address, WEAR_LEVELING_LOGICAL_SIZE + 8 + (index * BACKING_STORE_WRITE_SIZE)) << "Invalid write log address";
108
109 // If this is the backing store write that contains the metadata, verify it
110 if (index % 2 == 0) {
111 write_log_entry_t e;
112 e.raw64 = write_iter->value;
113 EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_MULTIBYTE) << "Invalid write log entry type";
114 }
115 }
116
117 // Verify the backing store erase
118 {
119 index = 6;
120 auto write_iter = inst.log_begin() + index;
121 e.raw64 = write_iter->value;
122 EXPECT_TRUE(write_iter->erased) << "Backing store erase did not occur as required";
123 }
124
125 // Verify the backing store writes for consolidation
126 for (index = 7; index < 11; ++index) {
127 auto write_iter = inst.log_begin() + index;
128 EXPECT_EQ(write_iter->address, (index - 7) * BACKING_STORE_WRITE_SIZE) << "Invalid write log entry address";
129 }
130
131 // Verify the FNV1a_64 write
132 {
133 EXPECT_EQ((inst.log_begin() + 11)->address, WEAR_LEVELING_LOGICAL_SIZE) << "Invalid write log address";
134 e.raw32[0] = (inst.log_begin() + 11)->value;
135 e.raw32[1] = (inst.log_begin() + 12)->value;
136 EXPECT_EQ(e.raw64, fnv_64a_buf(testvalue.data(), testvalue.size(), FNV1A_64_INIT)) << "Invalid checksum"; // Note that checksum is based on testvalue, as we overwrote one byte and need to consult the consolidated data, not the current
137 }
138
139 // Verify the final write
140 EXPECT_EQ((inst.log_begin() + 13)->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid write log address";
141
142 // Verify the data is what we expected
143 std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> readback;
144 EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
145 EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback did not match";
146
147 // Re-init and re-read, verifying the reload capability
148 EXPECT_NE(wear_leveling_init(), WEAR_LEVELING_FAILED) << "Re-initialisation failed";
149 EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
150 EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback did not match";
151}
152
153/**
154 * This test verifies multibyte readback gets canceled with an out-of-bounds address.
155 */
156TEST_F(WearLeveling4Byte, PlaybackReadbackMultibyte_OOB) {
157 auto& inst = MockBackingStore::Instance();
158 auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
159
160 // Invalid FNV1a_64 hash
161 (logstart + 0)->set(0);
162 (logstart + 1)->set(0);
163
164 // Set up a 2-byte logical write of [0x11,0x12] at logical offset 0x01
165 auto entry0 = LOG_ENTRY_MAKE_MULTIBYTE(0x01, 2);
166 entry0.raw8[3] = 0x11;
167 entry0.raw8[4] = 0x12;
168 (logstart + 2)->set(~entry0.raw32[0]);
169 (logstart + 3)->set(~entry0.raw32[1]);
170
171 // Set up a 2-byte logical write of [0x13,0x14] at logical offset 0x1000 (out of bounds)
172 auto entry1 = LOG_ENTRY_MAKE_MULTIBYTE(0x1000, 2);
173 entry1.raw8[3] = 0x13;
174 entry1.raw8[4] = 0x14;
175 (logstart + 4)->set(~entry1.raw32[0]);
176 (logstart + 5)->set(~entry1.raw32[1]);
177
178 // Set up a 2-byte logical write of [0x15,0x16] at logical offset 0x10
179 auto entry2 = LOG_ENTRY_MAKE_MULTIBYTE(0x01, 2);
180 entry2.raw8[3] = 0x15;
181 entry2.raw8[4] = 0x16;
182 (logstart + 6)->set(~entry2.raw32[0]);
183 (logstart + 7)->set(~entry2.raw32[1]);
184
185 EXPECT_EQ(inst.erasure_count(), 0) << "Invalid initial erase count";
186 EXPECT_EQ(wear_leveling_init(), WEAR_LEVELING_CONSOLIDATED) << "Readback should have failed and triggered consolidation";
187 EXPECT_EQ(inst.erasure_count(), 1) << "Invalid final erase count";
188
189 uint8_t buf[2];
190 wear_leveling_read(0x01, buf, sizeof(buf));
191 EXPECT_EQ(buf[0], 0x11) << "Readback should have maintained the previous pre-failure value from the write log";
192 EXPECT_EQ(buf[1], 0x12) << "Readback should have maintained the previous pre-failure value from the write log";
193}
diff --git a/quantum/wear_leveling/tests/wear_leveling_8byte.cpp b/quantum/wear_leveling/tests/wear_leveling_8byte.cpp
new file mode 100644
index 0000000000..c27c21d034
--- /dev/null
+++ b/quantum/wear_leveling/tests/wear_leveling_8byte.cpp
@@ -0,0 +1,178 @@
1// Copyright 2022 Nick Brassel (@tzarc)
2// SPDX-License-Identifier: GPL-2.0-or-later
3#include <numeric>
4#include "gtest/gtest.h"
5#include "gmock/gmock.h"
6#include "backing_mocks.hpp"
7
8class WearLeveling8Byte : public ::testing::Test {
9 protected:
10 void SetUp() override {
11 MockBackingStore::Instance().reset_instance();
12 wear_leveling_init();
13 }
14};
15
16static std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> verify_data;
17
18static wear_leveling_status_t test_write(const uint32_t address, const void* value, size_t length) {
19 memcpy(&verify_data[address], value, length);
20 return wear_leveling_write(address, value, length);
21}
22
23/**
24 * This test verifies that the first write after initialisation occurs after the FNV1a_64 hash location.
25 */
26TEST_F(WearLeveling8Byte, FirstWriteOccursAfterHash) {
27 auto& inst = MockBackingStore::Instance();
28 uint8_t test_value = 0x15;
29 test_write(0x02, &test_value, sizeof(test_value));
30 EXPECT_EQ(inst.log_begin()->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid first write address.";
31}
32
33/**
34 * This test verifies that the first write after initialisation occurs after the FNV1a_64 hash location, after an erase has occurred.
35 */
36TEST_F(WearLeveling8Byte, FirstWriteOccursAfterHash_AfterErase) {
37 auto& inst = MockBackingStore::Instance();
38 uint8_t test_value = 0x15;
39 wear_leveling_erase();
40 test_write(0x02, &test_value, sizeof(test_value));
41 EXPECT_EQ((inst.log_begin() + 1)->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid first write address.";
42}
43
44/**
45 * This test ensures the correct number of backing store writes occurs with a multibyte write, given the input buffer size.
46 */
47TEST_F(WearLeveling8Byte, MultibyteBackingStoreWriteCounts) {
48 auto& inst = MockBackingStore::Instance();
49
50 for (std::size_t length = 1; length <= 5; ++length) {
51 // Clear things out
52 std::fill(verify_data.begin(), verify_data.end(), 0);
53 inst.reset_instance();
54 wear_leveling_init();
55
56 // Generate a test block of data
57 std::vector<std::uint8_t> testvalue(length);
58 std::iota(testvalue.begin(), testvalue.end(), 0x20);
59
60 // Write the data
61 EXPECT_EQ(test_write(0, testvalue.data(), testvalue.size()), WEAR_LEVELING_SUCCESS) << "Write failed with incorrect status";
62
63 // Check that we got the expected number of write log entries
64 EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), 1);
65 }
66}
67
68/**
69 * This test forces consolidation by writing enough to the write log that it overflows, consolidating the data into the
70 * base logical area.
71 */
72TEST_F(WearLeveling8Byte, ConsolidationOverflow) {
73 auto& inst = MockBackingStore::Instance();
74
75 // Generate a test block of data
76 std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> testvalue;
77
78 // Write the data
79 std::iota(testvalue.begin(), testvalue.end(), 0x20);
80 EXPECT_EQ(test_write(0, testvalue.data(), testvalue.size()), WEAR_LEVELING_CONSOLIDATED) << "Write returned incorrect status";
81 uint8_t dummy = 0x40;
82 EXPECT_EQ(test_write(0x04, &dummy, sizeof(dummy)), WEAR_LEVELING_SUCCESS) << "Write returned incorrect status";
83
84 // Expected log:
85 // [0]: multibyte, 5 bytes, backing address 0x18, logical address 0x00
86 // [1]: multibyte, 5 bytes, backing address 0x20, logical address 0x05
87 // [2]: multibyte, 5 bytes, backing address 0x28, logical address 0x0A, triggers consolidation
88 // [3]: erase
89 // [4]: consolidated data, backing address 0x00, logical address 0x00
90 // [5]: consolidated data, backing address 0x08, logical address 0x08
91 // [6]: FNV1a_64 result, backing address 0x10
92 // [7]: multibyte, 1 byte, backing address 0x18, logical address 0x04
93 EXPECT_EQ(std::distance(inst.log_begin(), inst.log_end()), 8);
94
95 // Verify the backing store writes for the write log
96 std::size_t index;
97 write_log_entry_t e;
98 for (index = 0; index < 3; ++index) {
99 auto write_iter = inst.log_begin() + index;
100 EXPECT_EQ(write_iter->address, WEAR_LEVELING_LOGICAL_SIZE + 8 + (index * BACKING_STORE_WRITE_SIZE)) << "Invalid write log address";
101
102 write_log_entry_t e;
103 e.raw64 = write_iter->value;
104 EXPECT_EQ(LOG_ENTRY_GET_TYPE(e), LOG_ENTRY_TYPE_MULTIBYTE) << "Invalid write log entry type";
105 }
106
107 // Verify the backing store erase
108 {
109 index = 3;
110 auto write_iter = inst.log_begin() + index;
111 e.raw64 = write_iter->value;
112 EXPECT_TRUE(write_iter->erased) << "Backing store erase did not occur as required";
113 }
114
115 // Verify the backing store writes for consolidation
116 for (index = 4; index < 6; ++index) {
117 auto write_iter = inst.log_begin() + index;
118 EXPECT_EQ(write_iter->address, (index - 4) * BACKING_STORE_WRITE_SIZE) << "Invalid write log entry address";
119 }
120
121 // Verify the FNV1a_64 write
122 {
123 EXPECT_EQ((inst.log_begin() + 6)->address, WEAR_LEVELING_LOGICAL_SIZE) << "Invalid write log address";
124 e.raw64 = (inst.log_begin() + 6)->value;
125 EXPECT_EQ(e.raw64, fnv_64a_buf(testvalue.data(), testvalue.size(), FNV1A_64_INIT)) << "Invalid checksum"; // Note that checksum is based on testvalue, as we overwrote one byte and need to consult the consolidated data, not the current
126 }
127
128 // Verify the final write
129 EXPECT_EQ((inst.log_begin() + 7)->address, WEAR_LEVELING_LOGICAL_SIZE + 8) << "Invalid write log address";
130
131 // Verify the data is what we expected
132 std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> readback;
133 EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
134 EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback did not match";
135
136 // Re-init and re-read, verifying the reload capability
137 EXPECT_NE(wear_leveling_init(), WEAR_LEVELING_FAILED) << "Re-initialisation failed";
138 EXPECT_EQ(wear_leveling_read(0, readback.data(), WEAR_LEVELING_LOGICAL_SIZE), WEAR_LEVELING_SUCCESS) << "Failed to read back the saved data";
139 EXPECT_TRUE(memcmp(readback.data(), verify_data.data(), WEAR_LEVELING_LOGICAL_SIZE) == 0) << "Readback did not match";
140}
141
142/**
143 * This test verifies multibyte readback gets canceled with an out-of-bounds address.
144 */
145TEST_F(WearLeveling8Byte, PlaybackReadbackMultibyte_OOB) {
146 auto& inst = MockBackingStore::Instance();
147 auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
148
149 // Invalid FNV1a_64 hash
150 (logstart + 0)->set(0);
151
152 // Set up a 2-byte logical write of [0x11,0x12] at logical offset 0x01
153 auto entry0 = LOG_ENTRY_MAKE_MULTIBYTE(0x01, 2);
154 entry0.raw8[3] = 0x11;
155 entry0.raw8[4] = 0x12;
156 (logstart + 1)->set(~entry0.raw64);
157
158 // Set up a 2-byte logical write of [0x13,0x14] at logical offset 0x1000 (out of bounds)
159 auto entry1 = LOG_ENTRY_MAKE_MULTIBYTE(0x1000, 2);
160 entry1.raw8[3] = 0x13;
161 entry1.raw8[4] = 0x14;
162 (logstart + 2)->set(~entry1.raw64);
163
164 // Set up a 2-byte logical write of [0x15,0x16] at logical offset 0x10
165 auto entry2 = LOG_ENTRY_MAKE_MULTIBYTE(0x01, 2);
166 entry2.raw8[3] = 0x15;
167 entry2.raw8[4] = 0x16;
168 (logstart + 3)->set(~entry2.raw64);
169
170 EXPECT_EQ(inst.erasure_count(), 0) << "Invalid initial erase count";
171 EXPECT_EQ(wear_leveling_init(), WEAR_LEVELING_CONSOLIDATED) << "Readback should have failed and triggered consolidation";
172 EXPECT_EQ(inst.erasure_count(), 1) << "Invalid final erase count";
173
174 uint8_t buf[2];
175 wear_leveling_read(0x01, buf, sizeof(buf));
176 EXPECT_EQ(buf[0], 0x11) << "Readback should have maintained the previous pre-failure value from the write log";
177 EXPECT_EQ(buf[1], 0x12) << "Readback should have maintained the previous pre-failure value from the write log";
178}
diff --git a/quantum/wear_leveling/tests/wear_leveling_general.cpp b/quantum/wear_leveling/tests/wear_leveling_general.cpp
new file mode 100644
index 0000000000..76a4bf7bf3
--- /dev/null
+++ b/quantum/wear_leveling/tests/wear_leveling_general.cpp
@@ -0,0 +1,204 @@
1// Copyright 2022 Nick Brassel (@tzarc)
2// SPDX-License-Identifier: GPL-2.0-or-later
3#include <numeric>
4#include "gtest/gtest.h"
5#include "gmock/gmock.h"
6#include "backing_mocks.hpp"
7
8class WearLevelingGeneral : public ::testing::Test {
9 protected:
10 void SetUp() override {
11 MockBackingStore::Instance().reset_instance();
12 wear_leveling_init();
13 }
14};
15
16/**
17 * This test verifies that even if there is consolidated data present, if the checksum doesn't match then the cache is zero'd after reading the consolidated area, but before write log is played back.
18 */
19TEST_F(WearLevelingGeneral, InvalidChecksum_ConsolidatedDataIgnored) {
20 auto& inst = MockBackingStore::Instance();
21 auto logstart = inst.storage_begin() + (WEAR_LEVELING_LOGICAL_SIZE / sizeof(backing_store_int_t));
22
23 // Generate a test block of data
24 std::array<std::uint8_t, WEAR_LEVELING_LOGICAL_SIZE> testvalue;
25 std::iota(testvalue.begin(), testvalue.end(), 0x20);
26
27 // Write the data
28 EXPECT_EQ(wear_leveling_write(0, testvalue.data(), testvalue.size()), WEAR_LEVELING_CONSOLIDATED) << "Write returned incorrect status";
29
30 // Invalidate the checksum
31 (logstart + 0)->erase();
32 (logstart + 1)->erase();
33 (logstart + 2)->erase();
34 (logstart + 3)->erase();
35
36 // Set up a 1-byte logical write of [0x11] at logical offset 0x01
37 auto entry0 = LOG_ENTRY_MAKE_OPTIMIZED_64(0x01, 0x11);
38 (logstart + 4)->set(~entry0.raw16[0]);
39
40 // Re-init
41 EXPECT_EQ(wear_leveling_init(), WEAR_LEVELING_SUCCESS) << "Init returned incorrect status";
42 EXPECT_EQ(wear_leveling_read(0, testvalue.data(), testvalue.size()), WEAR_LEVELING_SUCCESS) << "Failed to read";
43 for (int i = 0; i < WEAR_LEVELING_LOGICAL_SIZE; ++i) {
44 EXPECT_EQ(testvalue[i], i == 0x01 ? 0x11 : 0x00) << "Invalid readback";
45 }
46}
47
48/**
49 * This test verifies that writing the same data multiple times does not result in subsequent writes to the backing store.
50 */
51TEST_F(WearLevelingGeneral, SameValue_SingleBackingWrite) {
52 auto& inst = MockBackingStore::Instance();
53
54 uint8_t test_val = 0x14;
55 EXPECT_EQ(wear_leveling_write(0x02, &test_val, sizeof(test_val)), WEAR_LEVELING_SUCCESS) << "First overall write operation should have succeeded";
56
57 uint64_t invoke_count = inst.unlock_invoke_count();
58 uint64_t erase_count = inst.erase_invoke_count();
59 uint64_t write_count = inst.write_invoke_count();
60 uint64_t lock_count = inst.lock_invoke_count();
61
62 for (int i = 0; i < 10; ++i) {
63 EXPECT_EQ(wear_leveling_write(0x02, &test_val, sizeof(test_val)), WEAR_LEVELING_SUCCESS) << "Subsequent overall write operation should have succeeded";
64
65 EXPECT_EQ(inst.unlock_invoke_count(), invoke_count) << "Unlock count should match";
66 EXPECT_EQ(inst.erase_invoke_count(), erase_count) << "Erase count should match";
67 EXPECT_EQ(inst.write_invoke_count(), write_count) << "Write count should match";
68 EXPECT_EQ(inst.lock_invoke_count(), lock_count) << "Lock count should match";
69 }
70}
71
72/**
73 * This test verifies that no other invocations occur if `backing_store_init()` fails.
74 */
75TEST_F(WearLevelingGeneral, InitFailure) {
76 auto& inst = MockBackingStore::Instance();
77 inst.reset_instance(); // make sure the counters are all zero
78 inst.set_init_callback([](std::uint64_t count) { return false; });
79
80 EXPECT_EQ(inst.erasure_count(), 0) << "Invalid initial erase count";
81 EXPECT_EQ(wear_leveling_init(), WEAR_LEVELING_FAILED) << "Init should have failed";
82 EXPECT_EQ(inst.erasure_count(), 0) << "Invalid final erase count";
83
84 EXPECT_EQ(inst.init_invoke_count(), 1) << "Init should have been invoked once";
85 EXPECT_EQ(inst.unlock_invoke_count(), 0) << "Unlock should not have been invoked";
86 EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
87 EXPECT_EQ(inst.write_invoke_count(), 0) << "Write should not have been invoked";
88 EXPECT_EQ(inst.lock_invoke_count(), 0) << "Lock should not have been invoked";
89}
90
91/**
92 * This test verifies that no invocations occur if the supplied address is out of range while writing.
93 */
94TEST_F(WearLevelingGeneral, WriteFailure_OOB) {
95 auto& inst = MockBackingStore::Instance();
96
97 uint8_t test_val = 0x14;
98 EXPECT_EQ(wear_leveling_write(0x21349830, &test_val, sizeof(test_val)), WEAR_LEVELING_FAILED) << "Overall write operation should have failed";
99
100 EXPECT_EQ(inst.unlock_invoke_count(), 0) << "Unlock should not have been invoked";
101 EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
102 EXPECT_EQ(inst.write_invoke_count(), 0) << "Write should not have been invoked";
103 EXPECT_EQ(inst.lock_invoke_count(), 0) << "Lock should not have been invoked";
104}
105
106/**
107 * This test verifies that a single write occurs if the supplied address and data length hits the edge of the logical area.
108 */
109TEST_F(WearLevelingGeneral, WriteSuccess_BoundaryOK) {
110 auto& inst = MockBackingStore::Instance();
111
112 uint16_t test_val = 0x14;
113 EXPECT_EQ(wear_leveling_write(WEAR_LEVELING_LOGICAL_SIZE - sizeof(test_val), &test_val, sizeof(test_val)), WEAR_LEVELING_SUCCESS) << "Overall write operation should have succeeded";
114
115 EXPECT_EQ(inst.unlock_invoke_count(), 1) << "Unlock should have been invoked once";
116 EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
117 EXPECT_EQ(inst.write_invoke_count(), 2) << "Write should have been invoked twice";
118 EXPECT_EQ(inst.lock_invoke_count(), 1) << "Lock should have been invoked once";
119}
120
121/**
122 * This test verifies that no invocations occur if the supplied address and length would generate writes outside the logical range.
123 */
124TEST_F(WearLevelingGeneral, WriteFailure_BoundaryOverflow) {
125 auto& inst = MockBackingStore::Instance();
126
127 uint16_t test_val = 0x14;
128 EXPECT_EQ(wear_leveling_write(WEAR_LEVELING_LOGICAL_SIZE - sizeof(test_val) + 1, &test_val, sizeof(test_val)), WEAR_LEVELING_FAILED) << "Overall write operation should have failed";
129
130 EXPECT_EQ(inst.unlock_invoke_count(), 0) << "Unlock should not have been invoked";
131 EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
132 EXPECT_EQ(inst.write_invoke_count(), 0) << "Write should not have been invoked";
133 EXPECT_EQ(inst.lock_invoke_count(), 0) << "Lock should not have been invoked";
134}
135
136/**
137 * This test verifies that no invocations occur if the supplied address is out of range while reading.
138 */
139TEST_F(WearLevelingGeneral, ReadFailure_OOB) {
140 auto& inst = MockBackingStore::Instance();
141
142 uint8_t test_val = 0;
143 EXPECT_EQ(wear_leveling_read(0x21349830, &test_val, sizeof(test_val)), WEAR_LEVELING_FAILED) << "Overall read operation should have failed";
144
145 EXPECT_EQ(inst.unlock_invoke_count(), 0) << "Unlock should not have been invoked";
146 EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
147 EXPECT_EQ(inst.write_invoke_count(), 0) << "Write should not have been invoked";
148 EXPECT_EQ(inst.lock_invoke_count(), 0) << "Lock should not have been invoked";
149}
150
151/**
152 * This test verifies that no write invocations occur if `backing_store_unlock()` fails.
153 */
154TEST_F(WearLevelingGeneral, UnlockFailure_NoWrite) {
155 auto& inst = MockBackingStore::Instance();
156 inst.set_unlock_callback([](std::uint64_t count) { return false; });
157
158 uint8_t test_val = 0x14;
159 EXPECT_EQ(wear_leveling_write(0x04, &test_val, sizeof(test_val)), WEAR_LEVELING_FAILED) << "Overall write operation should have failed";
160
161 EXPECT_EQ(inst.unlock_invoke_count(), 1) << "Unlock should have been invoked once";
162 EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
163 EXPECT_EQ(inst.write_invoke_count(), 0) << "Write should not have been invoked";
164 EXPECT_EQ(inst.lock_invoke_count(), 0) << "Lock should not have been invoked";
165
166 test_val = 0;
167 wear_leveling_read(0x04, &test_val, sizeof(test_val));
168 EXPECT_EQ(test_val, 0x14) << "Readback should come from cache regardless of unlock failure";
169}
170
171/**
172 * This test verifies that no erase invocations occur if `backing_store_unlock()` fails.
173 */
174TEST_F(WearLevelingGeneral, UnlockFailure_NoErase) {
175 auto& inst = MockBackingStore::Instance();
176 inst.set_unlock_callback([](std::uint64_t count) { return false; });
177
178 EXPECT_EQ(wear_leveling_erase(), WEAR_LEVELING_FAILED) << "Overall erase operation should have failed";
179
180 EXPECT_EQ(inst.unlock_invoke_count(), 1) << "Unlock should have been invoked once";
181 EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
182 EXPECT_EQ(inst.write_invoke_count(), 0) << "Write should not have been invoked";
183 EXPECT_EQ(inst.lock_invoke_count(), 0) << "Lock should not have been invoked";
184}
185
186/**
187 * This test verifies that only one write invocation occurs if `backing_store_write()` fails.
188 */
189TEST_F(WearLevelingGeneral, WriteFailure_NoSubsequentWrites) {
190 auto& inst = MockBackingStore::Instance();
191 inst.set_write_callback([](std::uint64_t count, std::uint32_t address) { return false; });
192
193 uint8_t test_val = 0x14;
194 EXPECT_EQ(wear_leveling_write(0x04, &test_val, sizeof(test_val)), WEAR_LEVELING_FAILED) << "Overall write operation should have failed";
195
196 EXPECT_EQ(inst.unlock_invoke_count(), 1) << "Unlock should have been invoked once";
197 EXPECT_EQ(inst.erase_invoke_count(), 0) << "Erase should not have been invoked";
198 EXPECT_EQ(inst.write_invoke_count(), 1) << "Write should have been invoked once";
199 EXPECT_EQ(inst.lock_invoke_count(), 1) << "Lock should have been invoked once";
200
201 test_val = 0;
202 wear_leveling_read(0x04, &test_val, sizeof(test_val));
203 EXPECT_EQ(test_val, 0x14) << "Readback should come from cache regardless of unlock failure";
204}
diff --git a/quantum/wear_leveling/wear_leveling.c b/quantum/wear_leveling/wear_leveling.c
new file mode 100644
index 0000000000..8418ae77bf
--- /dev/null
+++ b/quantum/wear_leveling/wear_leveling.c
@@ -0,0 +1,779 @@
1// Copyright 2022 Nick Brassel (@tzarc)
2// SPDX-License-Identifier: GPL-2.0-or-later
3#include <stdbool.h>
4#include "fnv.h"
5#include "wear_leveling.h"
6#include "wear_leveling_internal.h"
7
8/*
9 This wear leveling algorithm is adapted from algorithms from previous
10 implementations in QMK, namely:
11 - Artur F. (http://engsta.com/stm32-flash-memory-eeprom-emulator/)
12 - Yiancar -- QMK's base implementation for STM32F303
13 - Ilya Zhuravlev -- initial wear leveling algorithm
14 - Don Kjer -- increased flash density algorithm
15 - Nick Brassel (@tzarc) -- decoupled for use on other peripherals
16
17 At this layer, it is assumed that any reads/writes from the backing store
18 have a "reset state" after erasure of zero.
19 It is up to the backing store to perform translation of values, such as
20 taking the complement in order to deal with flash memory's reset value.
21
22 Terminology:
23
24 - Backing store: this is the storage area used by the wear leveling
25 algorithm.
26
27 - Backing size: this is the amount of storage provided by the backing
28 store for use by the wear leveling algorithm.
29
30 - Backing write size: this is the minimum number of bytes the backing
31 store can write in a single operation.
32
33 - Logical data: this is the externally-visible "emulated EEPROM" that
34 external subsystems "see" when performing reads/writes.
35
36 - Logical size: this is the amount of storage available for use
37 externally. Effectively, the "size of the EEPROM".
38
39 - Write log: this is a section of the backing store used to keep track
40 of modifications without overwriting existing data. This log is
41 "played back" on startup such that any subsequent reads are capable
42 of returning the latest data.
43
44 - Consolidated data: this is a section of the backing store reserved for
45 use for the latest copy of logical data. This is only ever written
46 when the write log is full -- the latest values for the logical data
47 are written here and the write log is cleared.
48
49 Configurables:
50
51 - BACKING_STORE_WRITE_SIZE: The number of bytes requires for a write
52 operation. This is defined by the capabilities of the backing store.
53
54 - WEAR_LEVELING_BACKING_SIZE: The number of bytes provided by the
55 backing store for use by the wear leveling algorithm. This is
56 defined by the capabilities of the backing store. This value must
57 also be at least twice the size of the logical size, as well as a
58 multiple of the logical size.
59
60 - WEAR_LEVELING_LOGICAL_SIZE: The number of bytes externally visible
61 to other subsystems performing reads/writes. This must be a multiple
62 of the write size.
63
64 General algorithm:
65
66 During initialization:
67 * The contents of the consolidated data section are read into cache.
68 * The contents of the write log are "played back" and update the
69 cache accordingly.
70
71 During reads:
72 * Logical data is served from the cache.
73
74 During writes:
75 * The cache is updated with the new data.
76 * A new write log entry is appended to the log.
77 * If the log's full, data is consolidated and the write log cleared.
78
79 Write log structure:
80
81 The first 8 bytes of the write log are a FNV1a_64 hash of the contents
82 of the consolidated data area, in an attempt to detect and guard against
83 any data corruption.
84
85 The write log follows the hash:
86
87 Given that the algorithm needs to cater for 2-, 4-, and 8-byte writes,
88 a variable-length write log entry is used such that the minimal amount
89 of storage is used based off the backing store write size.
90
91 Firstly, an empty log entry is expected to be all zeros. If the backing
92 store uses 0xFF for cleared bytes, it should return the complement, such
93 that this wear-leveling algorithm "receives" zeros.
94
95 For multi-byte writes, up to 8 bytes will be used for each log entry,
96 depending on the size of backing store writes:
97
98 ╔ Multi-byte Log Entry (2, 4-byte) ═╗
99 ║00XXXYYY║YYYYYYYY║YYYYYYYY║AAAAAAAA║
100 ║ └┬┘└┬┘║└──┬───┘║└──┬───┘║└──┬───┘║
101 ║ LenAdd║ Address║ Address║Value[0]║
102 ╚════════╩════════╩════════╩════════╝
103 ╔ Multi-byte Log Entry (2-byte) ══════════════════════╗
104 ║00XXXYYY║YYYYYYYY║YYYYYYYY║AAAAAAAA║BBBBBBBB║CCCCCCCC║
105 ║ └┬┘└┬┘║└──┬───┘║└──┬───┘║└──┬───┘║└──┬───┘║└──┬───┘║
106 ║ LenAdd║ Address║ Address║Value[0]║Value[1]║Value[2]║
107 ╚════════╩════════╩════════╩════════╩════════╩════════╝
108 ╔ Multi-byte Log Entry (2, 4, 8-byte) ══════════════════════════════════╗
109 ║00XXXYYY║YYYYYYYY║YYYYYYYY║AAAAAAAA║BBBBBBBB║CCCCCCCC║DDDDDDDD║EEEEEEEE║
110 ║ └┬┘└┬┘║└──┬───┘║└──┬───┘║└──┬───┘║└──┬───┘║└──┬───┘║└──┬───┘║└──┬───┘║
111 ║ LenAdd║ Address║ Address║Value[0]║Value[1]║Value[2]║Value[3]║Value[4]║
112 ╚════════╩════════╩════════╩════════╩════════╩════════╩════════╩════════╝
113
114 19 bits are used for the address, which allows for a max logical size of
115 512kB. Up to 5 bytes can be included in a single log entry.
116
117 For 2-byte backing store writes, the last two bytes are optional
118 depending on the length of data to be written. Accordingly, either 3
119 or 4 backing store write operations will occur.
120 For 4-byte backing store writes, either one or two write operations
121 occur, depending on the length.
122 For 8-byte backing store writes, one write operation occur.
123
124 2-byte backing store optimizations:
125
126 For single byte writes, addresses between 0...63 are encoded in a single
127 backing store write operation. 4- and 8-byte backing stores do not have
128 this optimization as it does not minimize the number of bytes written.
129
130 ╔ Byte-Entry ════╗
131 ║01XXXXXXYYYYYYYY║
132 ║ └─┬──┘└──┬───┘║
133 ║ Address Value ║
134 ╚════════════════╝
135 0 <= Address < 0x40 (64)
136
137 A second optimization takes into account uint16_t writes of 0 or 1,
138 specifically catering for KC_NO and KC_TRANSPARENT in the dynamic keymap
139 subsystem. This is valid only for the first 16kB of logical data --
140 addresses outside this range will use the multi-byte encoding above.
141
142 ╔ U16-Encoded 0 ═╗
143 ║100XXXXXXXXXXXXX║
144 ║ │└─────┬─────┘║
145 ║ │Address >> 1 ║
146 ║ └── Value: 0 ║
147 ╚════════════════╝
148 0 <= Address <= 0x3FFE (16382)
149
150 ╔ U16-Encoded 1 ═╗
151 ║101XXXXXXXXXXXXX║
152 ║ │└─────┬─────┘║
153 ║ │Address >> 1 ║
154 ║ └── Value: 1 ║
155 ╚════════════════╝
156 0 <= Address <= 0x3FFE (16382) */
157
158/**
159 * Storage area for the wear-leveling cache.
160 */
161static struct __attribute__((__aligned__(BACKING_STORE_WRITE_SIZE))) {
162 __attribute__((__aligned__(BACKING_STORE_WRITE_SIZE))) uint8_t cache[(WEAR_LEVELING_LOGICAL_SIZE)];
163 uint32_t write_address;
164 bool unlocked;
165} wear_leveling;
166
167/**
168 * Locking helper: status
169 */
170typedef enum backing_store_lock_status_t { STATUS_FAILURE = 0, STATUS_SUCCESS, STATUS_UNCHANGED } backing_store_lock_status_t;
171
172/**
173 * Locking helper: unlock
174 */
175static inline backing_store_lock_status_t wear_leveling_unlock(void) {
176 if (wear_leveling.unlocked) {
177 return STATUS_UNCHANGED;
178 }
179 if (!backing_store_unlock()) {
180 return STATUS_FAILURE;
181 }
182 wear_leveling.unlocked = true;
183 return STATUS_SUCCESS;
184}
185
186/**
187 * Locking helper: lock
188 */
189static inline backing_store_lock_status_t wear_leveling_lock(void) {
190 if (!wear_leveling.unlocked) {
191 return STATUS_UNCHANGED;
192 }
193 if (!backing_store_lock()) {
194 return STATUS_FAILURE;
195 }
196 wear_leveling.unlocked = false;
197 return STATUS_SUCCESS;
198}
199
200/**
201 * Resets the cache, ensuring the write address is correctly initialised.
202 */
203static void wear_leveling_clear_cache(void) {
204 memset(wear_leveling.cache, 0, (WEAR_LEVELING_LOGICAL_SIZE));
205 wear_leveling.write_address = (WEAR_LEVELING_LOGICAL_SIZE) + 8; // +8 is due to the FNV1a_64 of the consolidated buffer
206}
207
208/**
209 * Reads the consolidated data from the backing store into the cache.
210 * Does not consider the write log.
211 */
212static wear_leveling_status_t wear_leveling_read_consolidated(void) {
213 wl_dprintf("Reading consolidated data\n");
214
215 wear_leveling_status_t status = WEAR_LEVELING_SUCCESS;
216 for (int address = 0; address < (WEAR_LEVELING_LOGICAL_SIZE); address += (BACKING_STORE_WRITE_SIZE)) {
217 backing_store_int_t *const loc = (backing_store_int_t *)&wear_leveling.cache[address];
218 backing_store_int_t temp;
219 bool ok = backing_store_read(address, &temp);
220 if (!ok) {
221 wl_dprintf("Failed to read from backing store\n");
222 status = WEAR_LEVELING_FAILED;
223 break;
224 }
225 *loc = temp;
226 }
227
228 // Verify the FNV1a_64 result
229 if (status != WEAR_LEVELING_FAILED) {
230 uint64_t expected = fnv_64a_buf(wear_leveling.cache, (WEAR_LEVELING_LOGICAL_SIZE), FNV1A_64_INIT);
231 write_log_entry_t entry;
232#if BACKING_STORE_WRITE_SIZE == 2
233 backing_store_read((WEAR_LEVELING_LOGICAL_SIZE) + 0, &entry.raw16[0]);
234 backing_store_read((WEAR_LEVELING_LOGICAL_SIZE) + 2, &entry.raw16[1]);
235 backing_store_read((WEAR_LEVELING_LOGICAL_SIZE) + 4, &entry.raw16[2]);
236 backing_store_read((WEAR_LEVELING_LOGICAL_SIZE) + 6, &entry.raw16[3]);
237#elif BACKING_STORE_WRITE_SIZE == 4
238 backing_store_read((WEAR_LEVELING_LOGICAL_SIZE) + 0, &entry.raw32[0]);
239 backing_store_read((WEAR_LEVELING_LOGICAL_SIZE) + 4, &entry.raw32[1]);
240#elif BACKING_STORE_WRITE_SIZE == 8
241 backing_store_read((WEAR_LEVELING_LOGICAL_SIZE) + 0, &entry.raw64);
242#endif
243 // If we have a mismatch, clear the cache but do not flag a failure,
244 // which will cater for the completely clean MCU case.
245 if (entry.raw64 != expected) {
246 wear_leveling_clear_cache();
247 }
248 }
249
250 // If we failed for any reason, then clear the cache
251 if (status == WEAR_LEVELING_FAILED) {
252 wear_leveling_clear_cache();
253 }
254
255 return status;
256}
257
258/**
259 * Writes the current cache to consolidated data at the beginning of the backing store.
260 * Does not clear the write log.
261 */
262static wear_leveling_status_t wear_leveling_write_consolidated(void) {
263 wl_dprintf("Writing consolidated data\n");
264
265 wear_leveling_status_t status = WEAR_LEVELING_CONSOLIDATED;
266 backing_store_lock_status_t lock_status = wear_leveling_unlock();
267 for (int address = 0; address < (WEAR_LEVELING_LOGICAL_SIZE); address += (BACKING_STORE_WRITE_SIZE)) {
268 const backing_store_int_t value = *(backing_store_int_t *)&wear_leveling.cache[address];
269 backing_store_int_t temp;
270 bool ok = backing_store_read(address, &temp);
271 if (!ok) {
272 wl_dprintf("Failed to read from backing store\n");
273 status = WEAR_LEVELING_FAILED;
274 break;
275 }
276 if (temp != value) {
277 ok = backing_store_write(address, value);
278 if (!ok) {
279 wl_dprintf("Failed to write to backing store\n");
280 status = WEAR_LEVELING_FAILED;
281 break;
282 }
283 }
284 }
285
286 if (status != WEAR_LEVELING_FAILED) {
287 // Write out the FNV1a_64 result of the consolidated data
288 write_log_entry_t entry;
289 entry.raw64 = fnv_64a_buf(wear_leveling.cache, (WEAR_LEVELING_LOGICAL_SIZE), FNV1A_64_INIT);
290 do {
291#if BACKING_STORE_WRITE_SIZE == 2
292 if (!backing_store_write((WEAR_LEVELING_LOGICAL_SIZE) + 0, entry.raw16[0])) {
293 status = WEAR_LEVELING_FAILED;
294 break;
295 }
296 if (!backing_store_write((WEAR_LEVELING_LOGICAL_SIZE) + 2, entry.raw16[1])) {
297 status = WEAR_LEVELING_FAILED;
298 break;
299 }
300 if (!backing_store_write((WEAR_LEVELING_LOGICAL_SIZE) + 4, entry.raw16[2])) {
301 status = WEAR_LEVELING_FAILED;
302 break;
303 }
304 if (!backing_store_write((WEAR_LEVELING_LOGICAL_SIZE) + 6, entry.raw16[3])) {
305 status = WEAR_LEVELING_FAILED;
306 break;
307 }
308#elif BACKING_STORE_WRITE_SIZE == 4
309 if (!backing_store_write((WEAR_LEVELING_LOGICAL_SIZE) + 0, entry.raw32[0])) {
310 status = WEAR_LEVELING_FAILED;
311 break;
312 }
313 if (!backing_store_write((WEAR_LEVELING_LOGICAL_SIZE) + 4, entry.raw32[1])) {
314 status = WEAR_LEVELING_FAILED;
315 break;
316 }
317#elif BACKING_STORE_WRITE_SIZE == 8
318 if (!backing_store_write((WEAR_LEVELING_LOGICAL_SIZE) + 0, entry.raw64)) {
319 status = WEAR_LEVELING_FAILED;
320 break;
321 }
322#endif
323 } while (0);
324 }
325
326 if (lock_status == STATUS_SUCCESS) {
327 wear_leveling_lock();
328 }
329 return status;
330}
331
332/**
333 * Forces a write of the current cache.
334 * Erases the backing store, including the write log.
335 * During this operation, there is the potential for data loss if a power loss occurs.
336 */
337static wear_leveling_status_t wear_leveling_consolidate_force(void) {
338 wl_dprintf("Erasing backing store\n");
339
340 // Erase the backing store. Expectation is that any un-written values that are read back after this call come back as zero.
341 bool ok = backing_store_erase();
342 if (!ok) {
343 wl_dprintf("Failed to erase backing store\n");
344 return WEAR_LEVELING_FAILED;
345 }
346
347 // Write the cache to the first section of the backing store.
348 wear_leveling_status_t status = wear_leveling_write_consolidated();
349 if (status == WEAR_LEVELING_FAILED) {
350 wl_dprintf("Failed to write consolidated data\n");
351 }
352
353 // Next write of the log occurs after the consolidated values at the start of the backing store.
354 wear_leveling.write_address = (WEAR_LEVELING_LOGICAL_SIZE) + 8; // +8 due to the FNV1a_64 of the consolidated area
355
356 return status;
357}
358
359/**
360 * Potential write of the current cache to the backing store.
361 * Skipped if the current write log position is not at the end of the backing store.
362 * During this operation, there is the potential for data loss if a power loss occurs.
363 *
364 * @return true if consolidation occurred
365 */
366static wear_leveling_status_t wear_leveling_consolidate_if_needed(void) {
367 if (wear_leveling.write_address >= (WEAR_LEVELING_BACKING_SIZE)) {
368 return wear_leveling_consolidate_force();
369 }
370
371 return WEAR_LEVELING_SUCCESS;
372}
373
374/**
375 * Appends the supplied fixed-width entry to the write log, optionally consolidating if the log is full.
376 *
377 * @return true if consolidation occurred
378 */
379static wear_leveling_status_t wear_leveling_append_raw(backing_store_int_t value) {
380 bool ok = backing_store_write(wear_leveling.write_address, value);
381 if (!ok) {
382 wl_dprintf("Failed to write to backing store\n");
383 return WEAR_LEVELING_FAILED;
384 }
385 wear_leveling.write_address += (BACKING_STORE_WRITE_SIZE);
386 return wear_leveling_consolidate_if_needed();
387}
388
389/**
390 * Handles writing multi_byte-encoded data to the backing store.
391 *
392 * @return true if consolidation occurred
393 */
394static wear_leveling_status_t wear_leveling_write_raw_multibyte(uint32_t address, const void *value, size_t length) {
395 const uint8_t * p = value;
396 write_log_entry_t log = LOG_ENTRY_MAKE_MULTIBYTE(address, length);
397 for (size_t i = 0; i < length; ++i) {
398 log.raw8[3 + i] = p[i];
399 }
400
401 // Write to the backing store. See the multi-byte log format in the documentation header at the top of the file.
402 wear_leveling_status_t status;
403#if BACKING_STORE_WRITE_SIZE == 2
404 status = wear_leveling_append_raw(log.raw16[0]);
405 if (status != WEAR_LEVELING_SUCCESS) {
406 return status;
407 }
408
409 status = wear_leveling_append_raw(log.raw16[1]);
410 if (status != WEAR_LEVELING_SUCCESS) {
411 return status;
412 }
413
414 if (length > 1) {
415 status = wear_leveling_append_raw(log.raw16[2]);
416 if (status != WEAR_LEVELING_SUCCESS) {
417 return status;
418 }
419 }
420
421 if (length > 3) {
422 status = wear_leveling_append_raw(log.raw16[3]);
423 if (status != WEAR_LEVELING_SUCCESS) {
424 return status;
425 }
426 }
427#elif BACKING_STORE_WRITE_SIZE == 4
428 status = wear_leveling_append_raw(log.raw32[0]);
429 if (status != WEAR_LEVELING_SUCCESS) {
430 return status;
431 }
432
433 if (length > 1) {
434 status = wear_leveling_append_raw(log.raw32[1]);
435 if (status != WEAR_LEVELING_SUCCESS) {
436 return status;
437 }
438 }
439#elif BACKING_STORE_WRITE_SIZE == 8
440 status = wear_leveling_append_raw(log.raw64);
441 if (status != WEAR_LEVELING_SUCCESS) {
442 return status;
443 }
444#endif
445 return status;
446}
447
448/**
449 * Handles the actual writing of logical data into the write log section of the backing store.
450 */
451static wear_leveling_status_t wear_leveling_write_raw(uint32_t address, const void *value, size_t length) {
452 const uint8_t * p = value;
453 size_t remaining = length;
454 wear_leveling_status_t status = WEAR_LEVELING_SUCCESS;
455 while (remaining > 0) {
456#if BACKING_STORE_WRITE_SIZE == 2
457 // Small-write optimizations - uint16_t, 0 or 1, address is even, address <16384:
458 if (remaining >= 2 && address % 2 == 0 && address < 16384) {
459 const uint16_t v = *(const uint16_t *)p;
460 if (v == 0 || v == 1) {
461 const write_log_entry_t log = LOG_ENTRY_MAKE_WORD_01(address, v);
462 status = wear_leveling_append_raw(log.raw16[0]);
463 if (status != WEAR_LEVELING_SUCCESS) {
464 // If consolidation occurred, then the cache has already been written to the consolidated area. No need to continue.
465 // If a failure occurred, pass it on.
466 return status;
467 }
468
469 remaining -= 2;
470 address += 2;
471 p += 2;
472 continue;
473 }
474 }
475
476 // Small-write optimizations - address<64:
477 if (address < 64) {
478 const write_log_entry_t log = LOG_ENTRY_MAKE_OPTIMIZED_64(address, *p);
479 status = wear_leveling_append_raw(log.raw16[0]);
480 if (status != WEAR_LEVELING_SUCCESS) {
481 // If consolidation occurred, then the cache has already been written to the consolidated area. No need to continue.
482 // If a failure occurred, pass it on.
483 return status;
484 }
485
486 remaining--;
487 address++;
488 p++;
489 continue;
490 }
491#endif // BACKING_STORE_WRITE_SIZE == 2
492 const size_t this_length = remaining >= LOG_ENTRY_MULTIBYTE_MAX_BYTES ? LOG_ENTRY_MULTIBYTE_MAX_BYTES : remaining;
493 status = wear_leveling_write_raw_multibyte(address, p, this_length);
494 if (status != WEAR_LEVELING_SUCCESS) {
495 // If consolidation occurred, then the cache has already been written to the consolidated area. No need to continue.
496 // If a failure occurred, pass it on.
497 return status;
498 }
499 remaining -= this_length;
500 address += (uint32_t)this_length;
501 p += this_length;
502 }
503
504 return status;
505}
506
507/**
508 * "Replays" the write log from the backing store, updating the local cache with updated values.
509 */
510static wear_leveling_status_t wear_leveling_playback_log(void) {
511 wl_dprintf("Playback write log\n");
512
513 wear_leveling_status_t status = WEAR_LEVELING_SUCCESS;
514 bool cancel_playback = false;
515 uint32_t address = (WEAR_LEVELING_LOGICAL_SIZE) + 8; // +8 due to the FNV1a_64 of the consolidated area
516 while (!cancel_playback && address < (WEAR_LEVELING_BACKING_SIZE)) {
517 backing_store_int_t value;
518 bool ok = backing_store_read(address, &value);
519 if (!ok) {
520 wl_dprintf("Failed to load from backing store, skipping playback of write log\n");
521 cancel_playback = true;
522 status = WEAR_LEVELING_FAILED;
523 break;
524 }
525 if (value == 0) {
526 wl_dprintf("Found empty slot, no more log entries\n");
527 cancel_playback = true;
528 break;
529 }
530
531 // If we got a nonzero value, then we need to increment the address to ensure next write occurs at next location
532 address += (BACKING_STORE_WRITE_SIZE);
533
534 // Read from the write log
535 write_log_entry_t log;
536#if BACKING_STORE_WRITE_SIZE == 2
537 log.raw16[0] = value;
538#elif BACKING_STORE_WRITE_SIZE == 4
539 log.raw32[0] = value;
540#elif BACKING_STORE_WRITE_SIZE == 8
541 log.raw64 = value;
542#endif
543
544 switch (LOG_ENTRY_GET_TYPE(log)) {
545 case LOG_ENTRY_TYPE_MULTIBYTE: {
546#if BACKING_STORE_WRITE_SIZE == 2
547 ok = backing_store_read(address, &log.raw16[1]);
548 if (!ok) {
549 wl_dprintf("Failed to load from backing store, skipping playback of write log\n");
550 cancel_playback = true;
551 status = WEAR_LEVELING_FAILED;
552 break;
553 }
554 address += (BACKING_STORE_WRITE_SIZE);
555#endif // BACKING_STORE_WRITE_SIZE == 2
556 const uint32_t a = LOG_ENTRY_MULTIBYTE_GET_ADDRESS(log);
557 const uint8_t l = LOG_ENTRY_MULTIBYTE_GET_LENGTH(log);
558
559 if (a + l > (WEAR_LEVELING_LOGICAL_SIZE)) {
560 cancel_playback = true;
561 status = WEAR_LEVELING_FAILED;
562 break;
563 }
564
565#if BACKING_STORE_WRITE_SIZE == 2
566 if (l > 1) {
567 ok = backing_store_read(address, &log.raw16[2]);
568 if (!ok) {
569 wl_dprintf("Failed to load from backing store, skipping playback of write log\n");
570 cancel_playback = true;
571 status = WEAR_LEVELING_FAILED;
572 break;
573 }
574 address += (BACKING_STORE_WRITE_SIZE);
575 }
576 if (l > 3) {
577 ok = backing_store_read(address, &log.raw16[3]);
578 if (!ok) {
579 wl_dprintf("Failed to load from backing store, skipping playback of write log\n");
580 cancel_playback = true;
581 status = WEAR_LEVELING_FAILED;
582 break;
583 }
584 address += (BACKING_STORE_WRITE_SIZE);
585 }
586#elif BACKING_STORE_WRITE_SIZE == 4
587 if (l > 1) {
588 ok = backing_store_read(address, &log.raw32[1]);
589 if (!ok) {
590 wl_dprintf("Failed to load from backing store, skipping playback of write log\n");
591 cancel_playback = true;
592 status = WEAR_LEVELING_FAILED;
593 break;
594 }
595 address += (BACKING_STORE_WRITE_SIZE);
596 }
597#endif
598
599 memcpy(&wear_leveling.cache[a], &log.raw8[3], l);
600 } break;
601#if BACKING_STORE_WRITE_SIZE == 2
602 case LOG_ENTRY_TYPE_OPTIMIZED_64: {
603 const uint32_t a = LOG_ENTRY_OPTIMIZED_64_GET_ADDRESS(log);
604 const uint8_t v = LOG_ENTRY_OPTIMIZED_64_GET_VALUE(log);
605
606 if (a >= (WEAR_LEVELING_LOGICAL_SIZE)) {
607 cancel_playback = true;
608 status = WEAR_LEVELING_FAILED;
609 break;
610 }
611
612 wear_leveling.cache[a] = v;
613 } break;
614 case LOG_ENTRY_TYPE_WORD_01: {
615 const uint32_t a = LOG_ENTRY_WORD_01_GET_ADDRESS(log);
616 const uint8_t v = LOG_ENTRY_WORD_01_GET_VALUE(log);
617
618 if (a + 1 >= (WEAR_LEVELING_LOGICAL_SIZE)) {
619 cancel_playback = true;
620 status = WEAR_LEVELING_FAILED;
621 break;
622 }
623
624 wear_leveling.cache[a + 0] = v;
625 wear_leveling.cache[a + 1] = 0;
626 } break;
627#endif // BACKING_STORE_WRITE_SIZE == 2
628 default: {
629 cancel_playback = true;
630 status = WEAR_LEVELING_FAILED;
631 } break;
632 }
633 }
634
635 // We've reached the end of the log, so we're at the new write location
636 wear_leveling.write_address = address;
637
638 if (status == WEAR_LEVELING_FAILED) {
639 // If we had a failure during readback, assume we're corrupted -- force a consolidation with the data we already have
640 status = wear_leveling_consolidate_force();
641 } else {
642 // Consolidate the cache + write log if required
643 status = wear_leveling_consolidate_if_needed();
644 }
645
646 return status;
647}
648
649/**
650 * Wear-leveling initialization
651 */
652wear_leveling_status_t wear_leveling_init(void) {
653 wl_dprintf("Init\n");
654
655 // Reset the cache
656 wear_leveling_clear_cache();
657
658 // Initialise the backing store
659 if (!backing_store_init()) {
660 // If it failed, clear the cache and return with failure
661 wear_leveling_clear_cache();
662 return WEAR_LEVELING_FAILED;
663 }
664
665 // Read the previous consolidated values, then replay the existing write log so that the cache has the "live" values
666 wear_leveling_status_t status = wear_leveling_read_consolidated();
667 if (status == WEAR_LEVELING_FAILED) {
668 // If it failed, clear the cache and return with failure
669 wear_leveling_clear_cache();
670 return status;
671 }
672
673 status = wear_leveling_playback_log();
674 if (status == WEAR_LEVELING_FAILED) {
675 // If it failed, clear the cache and return with failure
676 wear_leveling_clear_cache();
677 return status;
678 }
679
680 return status;
681}
682
683/**
684 * Wear-leveling erase.
685 * Post-condition: any reads from the backing store directly after an erase operation must come back as zero.
686 */
687wear_leveling_status_t wear_leveling_erase(void) {
688 wl_dprintf("Erase\n");
689
690 // Unlock the backing store
691 backing_store_lock_status_t lock_status = wear_leveling_unlock();
692 if (lock_status == STATUS_FAILURE) {
693 wear_leveling_lock();
694 return WEAR_LEVELING_FAILED;
695 }
696
697 // Perform the erase
698 bool ret = backing_store_erase();
699 wear_leveling_clear_cache();
700
701 // Lock the backing store if we acquired the lock successfully
702 if (lock_status == STATUS_SUCCESS) {
703 ret &= (wear_leveling_lock() != STATUS_FAILURE);
704 }
705
706 return ret ? WEAR_LEVELING_SUCCESS : WEAR_LEVELING_FAILED;
707}
708
709/**
710 * Writes logical data into the backing store. Skips writes if there are no changes to values.
711 */
712wear_leveling_status_t wear_leveling_write(const uint32_t address, const void *value, size_t length) {
713 wl_assert(address + length <= (WEAR_LEVELING_LOGICAL_SIZE));
714 if (address + length > (WEAR_LEVELING_LOGICAL_SIZE)) {
715 return WEAR_LEVELING_FAILED;
716 }
717
718 wl_dprintf("Write ");
719 wl_dump(address, value, length);
720
721 // Skip write if there's no change compared to the current cached value
722 if (memcmp(value, &wear_leveling.cache[address], length) == 0) {
723 return true;
724 }
725
726 // Update the cache before writing to the backing store -- if we hit the end of the backing store during writes to the log then we'll force a consolidation in-line
727 memcpy(&wear_leveling.cache[address], value, length);
728
729 // Unlock the backing store
730 backing_store_lock_status_t lock_status = wear_leveling_unlock();
731 if (lock_status == STATUS_FAILURE) {
732 wear_leveling_lock();
733 return WEAR_LEVELING_FAILED;
734 }
735
736 // Perform the actual write
737 wear_leveling_status_t status = wear_leveling_write_raw(address, value, length);
738 switch (status) {
739 case WEAR_LEVELING_CONSOLIDATED:
740 case WEAR_LEVELING_FAILED:
741 // If the write triggered consolidation, or the write failed, then nothing else needs to occur.
742 break;
743
744 case WEAR_LEVELING_SUCCESS:
745 // Consolidate the cache + write log if required
746 status = wear_leveling_consolidate_if_needed();
747 break;
748
749 default:
750 // Unsure how we'd get here...
751 status = WEAR_LEVELING_FAILED;
752 break;
753 }
754
755 if (lock_status == STATUS_SUCCESS) {
756 if (wear_leveling_lock() == STATUS_FAILURE) {
757 status = WEAR_LEVELING_FAILED;
758 }
759 }
760
761 return status;
762}
763
764/**
765 * Reads logical data from the cache.
766 */
767wear_leveling_status_t wear_leveling_read(const uint32_t address, void *value, size_t length) {
768 wl_assert(address + length <= (WEAR_LEVELING_LOGICAL_SIZE));
769 if (address + length > (WEAR_LEVELING_LOGICAL_SIZE)) {
770 return WEAR_LEVELING_FAILED;
771 }
772
773 // Only need to copy from the cache
774 memcpy(value, &wear_leveling.cache[address], length);
775
776 wl_dprintf("Read ");
777 wl_dump(address, value, length);
778 return WEAR_LEVELING_SUCCESS;
779}
diff --git a/quantum/wear_leveling/wear_leveling.h b/quantum/wear_leveling/wear_leveling.h
new file mode 100644
index 0000000000..6641bc49b3
--- /dev/null
+++ b/quantum/wear_leveling/wear_leveling.h
@@ -0,0 +1,54 @@
1// Copyright 2022 Nick Brassel (@tzarc)
2// SPDX-License-Identifier: GPL-2.0-or-later
3#pragma once
4#include <stdint.h>
5#include <stdlib.h>
6
7/**
8 * @typedef Status returned from any wear-leveling API.
9 */
10typedef enum wear_leveling_status_t {
11 WEAR_LEVELING_FAILED, //< Invocation failed
12 WEAR_LEVELING_SUCCESS, //< Invocation succeeded
13 WEAR_LEVELING_CONSOLIDATED //< Invocation succeeded, consolidation occurred
14} wear_leveling_status_t;
15
16/**
17 * Wear-leveling initialization
18 *
19 * @return Status of the request
20 */
21wear_leveling_status_t wear_leveling_init(void);
22
23/**
24 * Wear-leveling erasure.
25 *
26 * Clears the wear-leveling area, with the definition that the "reset state" of all data is zero.
27 *
28 * @return Status of the request
29 */
30wear_leveling_status_t wear_leveling_erase(void);
31
32/**
33 * Writes logical data into the backing store.
34 *
35 * Skips writes if there are no changes to written values. The entire written block is considered when attempting to
36 * determine if an overwrite should occur -- if there is any data mismatch the entire block will be written to the log,
37 * not just the changed bytes.
38 *
39 * @param address[in] the logical address to write data
40 * @param value[in] pointer to the source buffer
41 * @param length[in] length of the data
42 * @return Status of the request
43 */
44wear_leveling_status_t wear_leveling_write(uint32_t address, const void* value, size_t length);
45
46/**
47 * Reads logical data from the cache.
48 *
49 * @param address[in] the logical address to read data
50 * @param value[out] pointer to the destination buffer
51 * @param length[in] length of the data
52 * @return Status of the request
53 */
54wear_leveling_status_t wear_leveling_read(uint32_t address, void* value, size_t length);
diff --git a/quantum/wear_leveling/wear_leveling_internal.h b/quantum/wear_leveling/wear_leveling_internal.h
new file mode 100644
index 0000000000..74b43932df
--- /dev/null
+++ b/quantum/wear_leveling/wear_leveling_internal.h
@@ -0,0 +1,145 @@
1// Copyright 2022 Nick Brassel (@tzarc)
2// SPDX-License-Identifier: GPL-2.0-or-later
3#pragma once
4
5#ifdef __cplusplus
6# define _Static_assert static_assert
7#endif
8
9#include <stdint.h>
10#include <string.h>
11
12#if BACKING_STORE_WRITE_SIZE == 2
13typedef uint16_t backing_store_int_t;
14#elif BACKING_STORE_WRITE_SIZE == 4
15typedef uint32_t backing_store_int_t;
16#elif BACKING_STORE_WRITE_SIZE == 8
17typedef uint64_t backing_store_int_t;
18#else
19# error Invalid BACKING_STORE_WRITE_SIZE, needs to be 2/4/8.
20#endif
21
22#ifndef WEAR_LEVELING_BACKING_SIZE
23# error WEAR_LEVELING_BACKING_SIZE was not set.
24#endif
25
26#ifndef WEAR_LEVELING_LOGICAL_SIZE
27# error WEAR_LEVELING_LOGICAL_SIZE was not set.
28#endif
29
30#ifdef WEAR_LEVELING_DEBUG_OUTPUT
31# include <stdio.h>
32# define wl_dprintf(...) printf("Wear leveling: " __VA_ARGS__)
33# define wl_dump(address, value, length) \
34 do { \
35 printf("[0x%04X]: ", (int)(address)); \
36 const uint8_t* p = (const uint8_t*)(value); \
37 for (int i = 0; i < (length); ++i) { \
38 printf(" %02X", (int)p[i]); \
39 } \
40 printf("\n"); \
41 } while (0)
42#else
43# define wl_dprintf(...) \
44 do { \
45 } while (0)
46# define wl_dump(...) \
47 do { \
48 } while (0)
49#endif // WEAR_LEVELING_DEBUG_OUTPUT
50
51#ifdef WEAR_LEVELING_ASSERTS
52# include <assert.h>
53# define wl_assert(...) assert(__VA_ARGS__)
54#else
55# define wl_assert(...) \
56 do { \
57 } while (0)
58#endif // WEAR_LEVELING_ASSERTS
59
60// Compile-time validation of configurable options
61_Static_assert(WEAR_LEVELING_BACKING_SIZE >= (WEAR_LEVELING_LOGICAL_SIZE * 2), "Total backing size must be at least twice the size of the logical size");
62_Static_assert(WEAR_LEVELING_LOGICAL_SIZE % BACKING_STORE_WRITE_SIZE == 0, "Logical size must be a multiple of write size");
63_Static_assert(WEAR_LEVELING_BACKING_SIZE % WEAR_LEVELING_LOGICAL_SIZE == 0, "Backing size must be a multiple of logical size");
64
65// Backing Store API, to be implemented elsewhere by flash driver etc.
66bool backing_store_init(void);
67bool backing_store_unlock(void);
68bool backing_store_erase(void);
69bool backing_store_write(uint32_t address, backing_store_int_t value);
70bool backing_store_lock(void);
71bool backing_store_read(uint32_t address, backing_store_int_t* value);
72
73/**
74 * Helper type used to contain a write log entry.
75 */
76typedef union write_log_entry_t {
77 uint64_t raw64;
78 uint32_t raw32[2];
79 uint16_t raw16[4];
80 uint8_t raw8[8];
81} write_log_entry_t;
82
83_Static_assert(sizeof(write_log_entry_t) == 8, "Wear leveling write log entry size was not 8");
84
85/**
86 * Log entry type discriminator.
87 */
88enum {
89 // 0x00 -- Multi-byte storage type
90 LOG_ENTRY_TYPE_MULTIBYTE,
91
92 // 0x01 -- 2-byte backing store write optimization: address < 64
93 LOG_ENTRY_TYPE_OPTIMIZED_64,
94
95 // 0x02 -- 2-byte backing store write optimization: word-encoded 0/1 values
96 LOG_ENTRY_TYPE_WORD_01,
97
98 LOG_ENTRY_TYPES
99};
100
101_Static_assert(LOG_ENTRY_TYPES <= (1 << 2), "Too many log entry types to fit into 2 bits of storage");
102
103#define BITMASK_FOR_BITCOUNT(n) ((1 << (n)) - 1)
104
105#define LOG_ENTRY_GET_TYPE(entry) (((entry).raw8[0] >> 6) & BITMASK_FOR_BITCOUNT(2))
106
107#define LOG_ENTRY_MULTIBYTE_MAX_BYTES 5
108#define LOG_ENTRY_MULTIBYTE_GET_ADDRESS(entry) (((((uint32_t)((entry).raw8[0])) & BITMASK_FOR_BITCOUNT(3)) << 16) | (((uint32_t)((entry).raw8[1])) << 8) | (entry).raw8[2])
109#define LOG_ENTRY_MULTIBYTE_GET_LENGTH(entry) ((uint8_t)(((entry).raw8[0] >> 3) & BITMASK_FOR_BITCOUNT(3)))
110#define LOG_ENTRY_MAKE_MULTIBYTE(address, length) \
111 (write_log_entry_t) { \
112 .raw8 = { \
113 [0] = (((((uint8_t)LOG_ENTRY_TYPE_MULTIBYTE) & BITMASK_FOR_BITCOUNT(2)) << 6) /* type */ \
114 | ((((uint8_t)(length)) & BITMASK_FOR_BITCOUNT(3)) << 3) /* length */ \
115 | ((((uint8_t)((address) >> 16))) & BITMASK_FOR_BITCOUNT(3)) /* address */ \
116 ), \
117 [1] = (((uint8_t)((address) >> 8)) & BITMASK_FOR_BITCOUNT(8)), /* address */ \
118 [2] = (((uint8_t)(address)) & BITMASK_FOR_BITCOUNT(8)), /* address */ \
119 } \
120 }
121
122#define LOG_ENTRY_OPTIMIZED_64_GET_ADDRESS(entry) ((uint32_t)((entry).raw8[0] & BITMASK_FOR_BITCOUNT(6)))
123#define LOG_ENTRY_OPTIMIZED_64_GET_VALUE(entry) ((entry).raw8[1])
124#define LOG_ENTRY_MAKE_OPTIMIZED_64(address, value) \
125 (write_log_entry_t) { \
126 .raw8 = { \
127 [0] = (((((uint8_t)LOG_ENTRY_TYPE_OPTIMIZED_64) & BITMASK_FOR_BITCOUNT(2)) << 6) /* type */ \
128 | ((((uint8_t)(address))) & BITMASK_FOR_BITCOUNT(6)) /* address */ \
129 ), \
130 [1] = ((uint8_t)(value)), /* value */ \
131 } \
132 }
133
134#define LOG_ENTRY_WORD_01_GET_ADDRESS(entry) ((((uint32_t)(((entry).raw8[0]) & BITMASK_FOR_BITCOUNT(5))) << 9) | (((uint32_t)((entry).raw8[1])) << 1))
135#define LOG_ENTRY_WORD_01_GET_VALUE(entry) ((uint8_t)((entry).raw8[0] >> 5) & BITMASK_FOR_BITCOUNT(1))
136#define LOG_ENTRY_MAKE_WORD_01(address, value) \
137 (write_log_entry_t) { \
138 .raw8 = { \
139 [0] = (((((uint8_t)LOG_ENTRY_TYPE_WORD_01) & BITMASK_FOR_BITCOUNT(2)) << 6) /* type */ \
140 | (((((uint8_t)((value) ? 1 : 0))) & BITMASK_FOR_BITCOUNT(1)) << 5) /* value */ \
141 | ((((uint8_t)((address) >> 9))) & BITMASK_FOR_BITCOUNT(5)) /* address */ \
142 ), \
143 [1] = (uint8_t)((address) >> 1), /* address */ \
144 } \
145 }