mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
ccan: add local copy.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
92ec2f874b
commit
c91d2b5206
9
Makefile
9
Makefile
@ -13,7 +13,7 @@ CCAN_OBJS := ccan-crypto-sha256.o ccan-crypto-shachain.o ccan-err.o ccan-tal.o c
|
||||
|
||||
HEADERS := $(wildcard *.h)
|
||||
|
||||
CCANDIR := ../ccan/
|
||||
CCANDIR := ccan/
|
||||
CFLAGS := -g -Wall -I $(CCANDIR)
|
||||
LDLIBS := -lcrypto -lprotobuf-c
|
||||
$(PROGRAMS): CFLAGS+=-I.
|
||||
@ -30,8 +30,13 @@ lightning.pb-c.c lightning.pb-c.h: lightning.proto
|
||||
$(PROGRAMS): % : %.o $(HELPER_OBJS) $(BITCOIN_OBJS) $(CCAN_OBJS)
|
||||
$(PROGRAMS:=.o) $(HELPER_OBJS): $(HEADERS)
|
||||
|
||||
$(CCAN_OBJS) $(HELPER_OBJS) $(PROGRAM_OBJS) $(BITCOIN_OBJS): ccan/config.h
|
||||
|
||||
ccan/config.h: ccan/tools/configurator/configurator
|
||||
$< > $@
|
||||
|
||||
distclean: clean
|
||||
$(RM) lightning.pb-c.c lightning.pb-c.h
|
||||
$(RM) lightning.pb-c.c lightning.pb-c.h ccan/config.h
|
||||
|
||||
clean:
|
||||
$(RM) $(PROGRAMS)
|
||||
|
3
ccan/README
Normal file
3
ccan/README
Normal file
@ -0,0 +1,3 @@
|
||||
CCAN imported from http://ccodearchive.net.
|
||||
|
||||
CCAN version: init-1956-ged95d86
|
1
ccan/ccan/alignof/LICENSE
Symbolic link
1
ccan/ccan/alignof/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../licenses/CC0
|
51
ccan/ccan/alignof/_info
Normal file
51
ccan/ccan/alignof/_info
Normal file
@ -0,0 +1,51 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* alignof - ALIGNOF() macro to determine alignment of a type.
|
||||
*
|
||||
* Many platforms have requirements that certain types must be aligned
|
||||
* to certain address boundaries, such as ints needing to be on 4-byte
|
||||
* boundaries. Attempting to access variables with incorrect
|
||||
* alignment may cause performance loss or even program failure (eg. a
|
||||
* bus signal).
|
||||
*
|
||||
* There are times which it's useful to be able to programatically
|
||||
* access these requirements, such as for dynamic allocators.
|
||||
*
|
||||
* Example:
|
||||
* #include <stdio.h>
|
||||
* #include <stdlib.h>
|
||||
* #include <ccan/alignof/alignof.h>
|
||||
*
|
||||
* // Output contains "ALIGNOF(char) == 1"
|
||||
* // Will also print out whether an onstack char array can hold a long.
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* char arr[sizeof(int)];
|
||||
*
|
||||
* printf("ALIGNOF(char) == %zu\n", ALIGNOF(char));
|
||||
* if ((unsigned long)arr % ALIGNOF(int)) {
|
||||
* printf("arr %p CANNOT hold an int\n", arr);
|
||||
* exit(1);
|
||||
* } else {
|
||||
* printf("arr %p CAN hold an int\n", arr);
|
||||
* exit(0);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* License: CC0 (Public domain)
|
||||
* Author: Rusty Russell <rusty@rustcorp.com.au>
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
20
ccan/ccan/alignof/alignof.h
Normal file
20
ccan/ccan/alignof/alignof.h
Normal file
@ -0,0 +1,20 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#ifndef CCAN_ALIGNOF_H
|
||||
#define CCAN_ALIGNOF_H
|
||||
#include "config.h"
|
||||
|
||||
/**
|
||||
* ALIGNOF - get the alignment of a type
|
||||
* @t: the type to test
|
||||
*
|
||||
* This returns a safe alignment for the given type.
|
||||
*/
|
||||
#if HAVE_ALIGNOF
|
||||
/* A GCC extension. */
|
||||
#define ALIGNOF(t) __alignof__(t)
|
||||
#else
|
||||
/* Alignment by measuring structure padding. */
|
||||
#define ALIGNOF(t) ((char *)(&((struct { char c; t _h; } *)0)->_h) - (char *)0)
|
||||
#endif
|
||||
|
||||
#endif /* CCAN_ALIGNOF_H */
|
61
ccan/ccan/alignof/test/run.c
Normal file
61
ccan/ccan/alignof/test/run.c
Normal file
@ -0,0 +1,61 @@
|
||||
#include <ccan/alignof/alignof.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
/* Alignment is remarkably difficult to test. The rules may be more
|
||||
* complex than ALIGNOF() can know: eg. on i386 __alignof__(double) == 8, but
|
||||
* __alignof__(struct containing double) == 4.
|
||||
*
|
||||
* Technically, we can only test that we give *at least* the alignment which
|
||||
* naturally occurs, and that accesses work.
|
||||
*
|
||||
* For the moment, we work around double. */
|
||||
struct lots_of_types
|
||||
{
|
||||
char c;
|
||||
short s;
|
||||
char c2;
|
||||
int i;
|
||||
char c3;
|
||||
float f;
|
||||
char c4;
|
||||
double d;
|
||||
char c5;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct lots_of_types lots_of_types, *lp = malloc(sizeof(*lp));
|
||||
char c;
|
||||
short s;
|
||||
char c2;
|
||||
int i;
|
||||
char c3;
|
||||
float f;
|
||||
char c4;
|
||||
double d;
|
||||
|
||||
/* Make sure we use all the variables. */
|
||||
c = c2 = c3 = c4 = 0;
|
||||
|
||||
plan_tests(15);
|
||||
ok1((unsigned long)&c % ALIGNOF(char) == 0);
|
||||
ok1((unsigned long)&s % ALIGNOF(short) == 0);
|
||||
ok1((unsigned long)&i % ALIGNOF(int) == 0);
|
||||
ok1((unsigned long)&f % ALIGNOF(float) == 0);
|
||||
ok1((unsigned long)&d % ALIGNOF(double) == 0);
|
||||
|
||||
ok1((unsigned long)&lots_of_types.c % ALIGNOF(char) == 0);
|
||||
ok1((unsigned long)&lots_of_types.s % ALIGNOF(short) == 0);
|
||||
ok1((unsigned long)&lots_of_types.i % ALIGNOF(int) == 0);
|
||||
ok1((unsigned long)&lots_of_types.f % ALIGNOF(float) == 0);
|
||||
ok1(offsetof(struct lots_of_types, d) % ALIGNOF(double) == 0);
|
||||
|
||||
ok1((unsigned long)&lp->c % ALIGNOF(char) == 0);
|
||||
ok1((unsigned long)&lp->s % ALIGNOF(short) == 0);
|
||||
ok1((unsigned long)&lp->i % ALIGNOF(int) == 0);
|
||||
ok1((unsigned long)&lp->f % ALIGNOF(float) == 0);
|
||||
ok1((unsigned long)&lp->d % ALIGNOF(double) == 0);
|
||||
exit(exit_status());
|
||||
}
|
1
ccan/ccan/array_size/LICENSE
Symbolic link
1
ccan/ccan/array_size/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../licenses/CC0
|
46
ccan/ccan/array_size/_info
Normal file
46
ccan/ccan/array_size/_info
Normal file
@ -0,0 +1,46 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* array_size - routine for safely deriving the size of a visible array.
|
||||
*
|
||||
* This provides a simple ARRAY_SIZE() macro, which (given a good compiler)
|
||||
* will also break compile if you try to use it on a pointer.
|
||||
*
|
||||
* This can ensure your code is robust to changes, without needing a gratuitous
|
||||
* macro or constant.
|
||||
*
|
||||
* Example:
|
||||
* // Outputs "Initialized 32 values"
|
||||
* #include <ccan/array_size/array_size.h>
|
||||
* #include <stdlib.h>
|
||||
* #include <stdio.h>
|
||||
*
|
||||
* // We currently use 32 random values.
|
||||
* static unsigned int vals[32];
|
||||
*
|
||||
* int main(void)
|
||||
* {
|
||||
* unsigned int i;
|
||||
* for (i = 0; i < ARRAY_SIZE(vals); i++)
|
||||
* vals[i] = random();
|
||||
* printf("Initialized %u values\n", i);
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* License: CC0 (Public domain)
|
||||
* Author: Rusty Russell <rusty@rustcorp.com.au>
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
printf("ccan/build_assert\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
26
ccan/ccan/array_size/array_size.h
Normal file
26
ccan/ccan/array_size/array_size.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#ifndef CCAN_ARRAY_SIZE_H
|
||||
#define CCAN_ARRAY_SIZE_H
|
||||
#include "config.h"
|
||||
#include <ccan/build_assert/build_assert.h>
|
||||
|
||||
/**
|
||||
* ARRAY_SIZE - get the number of elements in a visible array
|
||||
* @arr: the array whose size you want.
|
||||
*
|
||||
* This does not work on pointers, or arrays declared as [], or
|
||||
* function parameters. With correct compiler support, such usage
|
||||
* will cause a build error (see build_assert).
|
||||
*/
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + _array_size_chk(arr))
|
||||
|
||||
#if HAVE_BUILTIN_TYPES_COMPATIBLE_P && HAVE_TYPEOF
|
||||
/* Two gcc extensions.
|
||||
* &a[0] degrades to a pointer: a different type from an array */
|
||||
#define _array_size_chk(arr) \
|
||||
BUILD_ASSERT_OR_ZERO(!__builtin_types_compatible_p(typeof(arr), \
|
||||
typeof(&(arr)[0])))
|
||||
#else
|
||||
#define _array_size_chk(arr) 0
|
||||
#endif
|
||||
#endif /* CCAN_ALIGNOF_H */
|
24
ccan/ccan/array_size/test/compile_fail-function-param.c
Normal file
24
ccan/ccan/array_size/test/compile_fail-function-param.c
Normal file
@ -0,0 +1,24 @@
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct foo {
|
||||
unsigned int a, b;
|
||||
};
|
||||
|
||||
int check_parameter(const struct foo array[4]);
|
||||
int check_parameter(const struct foo array[4])
|
||||
{
|
||||
#ifdef FAIL
|
||||
return (ARRAY_SIZE(array) == 4);
|
||||
#if !HAVE_TYPEOF || !HAVE_BUILTIN_TYPES_COMPATIBLE_P
|
||||
#error "Unfortunately we don't fail if _array_size_chk is a noop."
|
||||
#endif
|
||||
#else
|
||||
return sizeof(array) == 4 * sizeof(struct foo);
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
return check_parameter(NULL);
|
||||
}
|
14
ccan/ccan/array_size/test/compile_fail.c
Normal file
14
ccan/ccan/array_size/test/compile_fail.c
Normal file
@ -0,0 +1,14 @@
|
||||
#include <ccan/array_size/array_size.h>
|
||||
|
||||
int main(int argc, char *argv[8])
|
||||
{
|
||||
char array[100];
|
||||
#ifdef FAIL
|
||||
return ARRAY_SIZE(argv) + ARRAY_SIZE(array);
|
||||
#if !HAVE_TYPEOF || !HAVE_BUILTIN_TYPES_COMPATIBLE_P
|
||||
#error "Unfortunately we don't fail if _array_size_chk is a noop."
|
||||
#endif
|
||||
#else
|
||||
return ARRAY_SIZE(array);
|
||||
#endif
|
||||
}
|
33
ccan/ccan/array_size/test/run.c
Normal file
33
ccan/ccan/array_size/test/run.c
Normal file
@ -0,0 +1,33 @@
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
static char array1[1];
|
||||
static int array2[2];
|
||||
static unsigned long array3[3][5];
|
||||
struct foo {
|
||||
unsigned int a, b;
|
||||
char string[100];
|
||||
};
|
||||
static struct foo array4[4];
|
||||
|
||||
/* Make sure they can be used in initializers. */
|
||||
static int array1_size = ARRAY_SIZE(array1);
|
||||
static int array2_size = ARRAY_SIZE(array2);
|
||||
static int array3_size = ARRAY_SIZE(array3);
|
||||
static int array4_size = ARRAY_SIZE(array4);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
plan_tests(8);
|
||||
ok1(array1_size == 1);
|
||||
ok1(array2_size == 2);
|
||||
ok1(array3_size == 3);
|
||||
ok1(array4_size == 4);
|
||||
|
||||
ok1(ARRAY_SIZE(array1) == 1);
|
||||
ok1(ARRAY_SIZE(array2) == 2);
|
||||
ok1(ARRAY_SIZE(array3) == 3);
|
||||
ok1(ARRAY_SIZE(array4) == 4);
|
||||
|
||||
return exit_status();
|
||||
}
|
1
ccan/ccan/asort/LICENSE
Symbolic link
1
ccan/ccan/asort/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../licenses/LGPL-2.1
|
70
ccan/ccan/asort/_info
Normal file
70
ccan/ccan/asort/_info
Normal file
@ -0,0 +1,70 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* asort - typesafe array sort (qsort)
|
||||
*
|
||||
* qsort() is the standard routine for sorting an array of objects.
|
||||
* Unfortunately, it has two problems:
|
||||
* 1) It isn't typesafe,
|
||||
* 2) The comparison function doesn't take a context pointer.
|
||||
*
|
||||
* asort does both.
|
||||
*
|
||||
* License: LGPL (v2.1 or any later version)
|
||||
* Author: Rusty Russell <rusty@rustcorp.com.au>
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/asort/asort.h>
|
||||
* #include <stdio.h>
|
||||
* #include <string.h>
|
||||
*
|
||||
* static int cmp(char *const *a, char *const *n, bool *casefold)
|
||||
* {
|
||||
* if (*casefold)
|
||||
* return strcasecmp(*a, *n);
|
||||
* else
|
||||
* return strcmp(*a, *n);
|
||||
* }
|
||||
*
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* bool casefold = false;
|
||||
* unsigned int i;
|
||||
*
|
||||
* if (argc < 2) {
|
||||
* fprintf(stderr, "Usage: %s [-i] <list>...\n"
|
||||
* "Sort arguments (-i = ignore case)\n",
|
||||
* argv[0]);
|
||||
* exit(1);
|
||||
* }
|
||||
*
|
||||
* if (strcmp(argv[1], "-i") == 0) {
|
||||
* casefold = true;
|
||||
* argc--;
|
||||
* argv++;
|
||||
* }
|
||||
* asort(&argv[1], argc-1, cmp, &casefold);
|
||||
* for (i = 1; i < argc; i++)
|
||||
* printf("%s ", argv[i]);
|
||||
* printf("\n");
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
printf("ccan/typesafe_cb\n");
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(argv[1], "testdepends") == 0) {
|
||||
printf("ccan/array_size\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
259
ccan/ccan/asort/asort.c
Normal file
259
ccan/ccan/asort/asort.c
Normal file
@ -0,0 +1,259 @@
|
||||
#include <ccan/asort/asort.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !HAVE_QSORT_R_PRIVATE_LAST
|
||||
|
||||
/* Steal glibc's code. */
|
||||
|
||||
/* Copyright (C) 1991,1992,1996,1997,1999,2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* If you consider tuning this algorithm, you should consult first:
|
||||
Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
|
||||
Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Byte-wise swap two items of size SIZE. */
|
||||
#define SWAP(a, b, size) \
|
||||
do \
|
||||
{ \
|
||||
register size_t __size = (size); \
|
||||
register char *__a = (a), *__b = (b); \
|
||||
do \
|
||||
{ \
|
||||
char __tmp = *__a; \
|
||||
*__a++ = *__b; \
|
||||
*__b++ = __tmp; \
|
||||
} while (--__size > 0); \
|
||||
} while (0)
|
||||
|
||||
/* Discontinue quicksort algorithm when partition gets below this size.
|
||||
This particular magic number was chosen to work best on a Sun 4/260. */
|
||||
#define MAX_THRESH 4
|
||||
|
||||
/* Stack node declarations used to store unfulfilled partition obligations. */
|
||||
typedef struct
|
||||
{
|
||||
char *lo;
|
||||
char *hi;
|
||||
} stack_node;
|
||||
|
||||
/* The next 4 #defines implement a very fast in-line stack abstraction. */
|
||||
/* The stack needs log (total_elements) entries (we could even subtract
|
||||
log(MAX_THRESH)). Since total_elements has type size_t, we get as
|
||||
upper bound for log (total_elements):
|
||||
bits per byte (CHAR_BIT) * sizeof(size_t). */
|
||||
#define STACK_SIZE (CHAR_BIT * sizeof(size_t))
|
||||
#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
|
||||
#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
|
||||
#define STACK_NOT_EMPTY (stack < top)
|
||||
|
||||
|
||||
/* Order size using quicksort. This implementation incorporates
|
||||
four optimizations discussed in Sedgewick:
|
||||
|
||||
1. Non-recursive, using an explicit stack of pointer that store the
|
||||
next array partition to sort. To save time, this maximum amount
|
||||
of space required to store an array of SIZE_MAX is allocated on the
|
||||
stack. Assuming a 32-bit (64 bit) integer for size_t, this needs
|
||||
only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).
|
||||
Pretty cheap, actually.
|
||||
|
||||
2. Chose the pivot element using a median-of-three decision tree.
|
||||
This reduces the probability of selecting a bad pivot value and
|
||||
eliminates certain extraneous comparisons.
|
||||
|
||||
3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
|
||||
insertion sort to order the MAX_THRESH items within each partition.
|
||||
This is a big win, since insertion sort is faster for small, mostly
|
||||
sorted array segments.
|
||||
|
||||
4. The larger of the two sub-partitions is always pushed onto the
|
||||
stack first, with the algorithm then concentrating on the
|
||||
smaller partition. This *guarantees* no more than log (total_elems)
|
||||
stack size is needed (actually O(1) in this case)! */
|
||||
|
||||
void
|
||||
_asort (void *const pbase, size_t total_elems, size_t size,
|
||||
int(*cmp)(const void *, const void *, void *arg),
|
||||
void *arg)
|
||||
{
|
||||
register char *base_ptr = (char *) pbase;
|
||||
|
||||
const size_t max_thresh = MAX_THRESH * size;
|
||||
|
||||
if (total_elems == 0)
|
||||
/* Avoid lossage with unsigned arithmetic below. */
|
||||
return;
|
||||
|
||||
if (total_elems > MAX_THRESH)
|
||||
{
|
||||
char *lo = base_ptr;
|
||||
char *hi = &lo[size * (total_elems - 1)];
|
||||
stack_node stack[STACK_SIZE];
|
||||
stack_node *top = stack;
|
||||
|
||||
PUSH (NULL, NULL);
|
||||
|
||||
while (STACK_NOT_EMPTY)
|
||||
{
|
||||
char *left_ptr;
|
||||
char *right_ptr;
|
||||
|
||||
/* Select median value from among LO, MID, and HI. Rearrange
|
||||
LO and HI so the three values are sorted. This lowers the
|
||||
probability of picking a pathological pivot value and
|
||||
skips a comparison for both the LEFT_PTR and RIGHT_PTR in
|
||||
the while loops. */
|
||||
|
||||
char *mid = lo + size * ((hi - lo) / size >> 1);
|
||||
|
||||
if ((*cmp) ((void *) mid, (void *) lo, arg) < 0)
|
||||
SWAP (mid, lo, size);
|
||||
if ((*cmp) ((void *) hi, (void *) mid, arg) < 0)
|
||||
SWAP (mid, hi, size);
|
||||
else
|
||||
goto jump_over;
|
||||
if ((*cmp) ((void *) mid, (void *) lo, arg) < 0)
|
||||
SWAP (mid, lo, size);
|
||||
jump_over:;
|
||||
|
||||
left_ptr = lo + size;
|
||||
right_ptr = hi - size;
|
||||
|
||||
/* Here's the famous ``collapse the walls'' section of quicksort.
|
||||
Gotta like those tight inner loops! They are the main reason
|
||||
that this algorithm runs much faster than others. */
|
||||
do
|
||||
{
|
||||
while ((*cmp) ((void *) left_ptr, (void *) mid, arg) < 0)
|
||||
left_ptr += size;
|
||||
|
||||
while ((*cmp) ((void *) mid, (void *) right_ptr, arg) < 0)
|
||||
right_ptr -= size;
|
||||
|
||||
if (left_ptr < right_ptr)
|
||||
{
|
||||
SWAP (left_ptr, right_ptr, size);
|
||||
if (mid == left_ptr)
|
||||
mid = right_ptr;
|
||||
else if (mid == right_ptr)
|
||||
mid = left_ptr;
|
||||
left_ptr += size;
|
||||
right_ptr -= size;
|
||||
}
|
||||
else if (left_ptr == right_ptr)
|
||||
{
|
||||
left_ptr += size;
|
||||
right_ptr -= size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (left_ptr <= right_ptr);
|
||||
|
||||
/* Set up pointers for next iteration. First determine whether
|
||||
left and right partitions are below the threshold size. If so,
|
||||
ignore one or both. Otherwise, push the larger partition's
|
||||
bounds on the stack and continue sorting the smaller one. */
|
||||
|
||||
if ((size_t) (right_ptr - lo) <= max_thresh)
|
||||
{
|
||||
if ((size_t) (hi - left_ptr) <= max_thresh)
|
||||
/* Ignore both small partitions. */
|
||||
POP (lo, hi);
|
||||
else
|
||||
/* Ignore small left partition. */
|
||||
lo = left_ptr;
|
||||
}
|
||||
else if ((size_t) (hi - left_ptr) <= max_thresh)
|
||||
/* Ignore small right partition. */
|
||||
hi = right_ptr;
|
||||
else if ((right_ptr - lo) > (hi - left_ptr))
|
||||
{
|
||||
/* Push larger left partition indices. */
|
||||
PUSH (lo, right_ptr);
|
||||
lo = left_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Push larger right partition indices. */
|
||||
PUSH (left_ptr, hi);
|
||||
hi = right_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Once the BASE_PTR array is partially sorted by quicksort the rest
|
||||
is completely sorted using insertion sort, since this is efficient
|
||||
for partitions below MAX_THRESH size. BASE_PTR points to the beginning
|
||||
of the array to sort, and END_PTR points at the very last element in
|
||||
the array (*not* one beyond it!). */
|
||||
|
||||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
{
|
||||
char *const end_ptr = &base_ptr[size * (total_elems - 1)];
|
||||
char *tmp_ptr = base_ptr;
|
||||
char *thresh = min(end_ptr, base_ptr + max_thresh);
|
||||
register char *run_ptr;
|
||||
|
||||
/* Find smallest element in first threshold and place it at the
|
||||
array's beginning. This is the smallest array element,
|
||||
and the operation speeds up insertion sort's inner loop. */
|
||||
|
||||
for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
|
||||
if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0)
|
||||
tmp_ptr = run_ptr;
|
||||
|
||||
if (tmp_ptr != base_ptr)
|
||||
SWAP (tmp_ptr, base_ptr, size);
|
||||
|
||||
/* Insertion sort, running from left-hand-side up to right-hand-side. */
|
||||
|
||||
run_ptr = base_ptr + size;
|
||||
while ((run_ptr += size) <= end_ptr)
|
||||
{
|
||||
tmp_ptr = run_ptr - size;
|
||||
while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0)
|
||||
tmp_ptr -= size;
|
||||
|
||||
tmp_ptr += size;
|
||||
if (tmp_ptr != run_ptr)
|
||||
{
|
||||
char *trav;
|
||||
|
||||
trav = run_ptr + size;
|
||||
while (--trav >= run_ptr)
|
||||
{
|
||||
char c = *trav;
|
||||
char *hi, *lo;
|
||||
|
||||
for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
|
||||
*hi = *lo;
|
||||
*hi = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !HAVE_QSORT_R_PRIVATE_LAST */
|
38
ccan/ccan/asort/asort.h
Normal file
38
ccan/ccan/asort/asort.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* Licensed under LGPLv2.1+ - see LICENSE file for details */
|
||||
#ifndef CCAN_ASORT_H
|
||||
#define CCAN_ASORT_H
|
||||
#include "config.h"
|
||||
#include <ccan/typesafe_cb/typesafe_cb.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* asort - sort an array of elements
|
||||
* @base: pointer to data to sort
|
||||
* @num: number of elements
|
||||
* @cmp: pointer to comparison function
|
||||
* @ctx: a context pointer for the cmp function
|
||||
*
|
||||
* This function does a sort on the given array. The resulting array
|
||||
* will be in ascending sorted order by the provided comparison function.
|
||||
*
|
||||
* The @cmp function should exactly match the type of the @base and
|
||||
* @ctx arguments. Otherwise it can take three const void *.
|
||||
*/
|
||||
#define asort(base, num, cmp, ctx) \
|
||||
_asort((base), (num), sizeof(*(base)), \
|
||||
typesafe_cb_cast(int (*)(const void *, const void *, void *), \
|
||||
int (*)(const __typeof__(*(base)) *, \
|
||||
const __typeof__(*(base)) *, \
|
||||
__typeof__(ctx)), \
|
||||
(cmp)), \
|
||||
(ctx))
|
||||
|
||||
#if HAVE_QSORT_R_PRIVATE_LAST
|
||||
#define _asort(b, n, s, cmp, ctx) qsort_r(b, n, s, cmp, ctx)
|
||||
#else
|
||||
void _asort(void *base, size_t nmemb, size_t size,
|
||||
int(*compar)(const void *, const void *, void *),
|
||||
void *ctx);
|
||||
#endif
|
||||
|
||||
#endif /* CCAN_ASORT_H */
|
22
ccan/ccan/asort/test/compile_fail-context-type.c
Normal file
22
ccan/ccan/asort/test/compile_fail-context-type.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <ccan/asort/asort.h>
|
||||
#include <ccan/asort/asort.c>
|
||||
|
||||
static int cmp(char *const *a, char *const *b, int *flag)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#ifdef FAIL
|
||||
#if HAVE_TYPEOF && HAVE_BUILTIN_CHOOSE_EXPR && HAVE_BUILTIN_TYPES_COMPATIBLE_P
|
||||
char flag;
|
||||
#else
|
||||
#error "Unfortunately we don't fail if no typecheck_cb support."
|
||||
#endif
|
||||
#else
|
||||
int flag;
|
||||
#endif
|
||||
asort(argv+1, argc-1, cmp, &flag);
|
||||
return 0;
|
||||
}
|
68
ccan/ccan/asort/test/run.c
Normal file
68
ccan/ccan/asort/test/run.c
Normal file
@ -0,0 +1,68 @@
|
||||
#include <ccan/asort/asort.h>
|
||||
#include <ccan/asort/asort.c>
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/tap/tap.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static int test_cmp(const int *key, const int *elt, int *flag)
|
||||
{
|
||||
if (*key < *elt)
|
||||
return -1 * *flag;
|
||||
else if (*key > *elt)
|
||||
return 1 * *flag;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_sorted(const int arr[], unsigned int size)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 1; i < size; i++)
|
||||
if (arr[i] < arr[i-1])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_reverse_sorted(const int arr[], unsigned int size)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 1; i < size; i++)
|
||||
if (arr[i] > arr[i-1])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void psuedo_random_array(int arr[], unsigned int size)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
arr[i] = i * (INT_MAX / 4 - 7);
|
||||
}
|
||||
|
||||
#define TEST_SIZE 100
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int tmparr[TEST_SIZE];
|
||||
int multiplier = 1;
|
||||
|
||||
plan_tests(4);
|
||||
|
||||
psuedo_random_array(tmparr, TEST_SIZE);
|
||||
ok1(!is_sorted(tmparr, TEST_SIZE));
|
||||
ok1(!is_reverse_sorted(tmparr, TEST_SIZE));
|
||||
|
||||
asort(tmparr, TEST_SIZE, test_cmp, &multiplier);
|
||||
ok1(is_sorted(tmparr, TEST_SIZE));
|
||||
|
||||
psuedo_random_array(tmparr, TEST_SIZE);
|
||||
multiplier = -1;
|
||||
asort(tmparr, TEST_SIZE, test_cmp, &multiplier);
|
||||
ok1(is_reverse_sorted(tmparr, TEST_SIZE));
|
||||
|
||||
return exit_status();
|
||||
}
|
1
ccan/ccan/build_assert/LICENSE
Symbolic link
1
ccan/ccan/build_assert/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../licenses/CC0
|
49
ccan/ccan/build_assert/_info
Normal file
49
ccan/ccan/build_assert/_info
Normal file
@ -0,0 +1,49 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* build_assert - routines for build-time assertions
|
||||
*
|
||||
* This code provides routines which will cause compilation to fail should some
|
||||
* assertion be untrue: such failures are preferable to run-time assertions,
|
||||
* but much more limited since they can only depends on compile-time constants.
|
||||
*
|
||||
* These assertions are most useful when two parts of the code must be kept in
|
||||
* sync: it is better to avoid such cases if possible, but seconds best is to
|
||||
* detect invalid changes at build time.
|
||||
*
|
||||
* For example, a tricky piece of code might rely on a certain element being at
|
||||
* the start of the structure. To ensure that future changes don't break it,
|
||||
* you would catch such changes in your code like so:
|
||||
*
|
||||
* Example:
|
||||
* #include <stddef.h>
|
||||
* #include <ccan/build_assert/build_assert.h>
|
||||
*
|
||||
* struct foo {
|
||||
* char string[5];
|
||||
* int x;
|
||||
* };
|
||||
*
|
||||
* static char *foo_string(struct foo *foo)
|
||||
* {
|
||||
* // This trick requires that the string be first in the structure
|
||||
* BUILD_ASSERT(offsetof(struct foo, string) == 0);
|
||||
* return (char *)foo;
|
||||
* }
|
||||
*
|
||||
* License: CC0 (Public domain)
|
||||
* Author: Rusty Russell <rusty@rustcorp.com.au>
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0)
|
||||
/* Nothing. */
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
40
ccan/ccan/build_assert/build_assert.h
Normal file
40
ccan/ccan/build_assert/build_assert.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#ifndef CCAN_BUILD_ASSERT_H
|
||||
#define CCAN_BUILD_ASSERT_H
|
||||
|
||||
/**
|
||||
* BUILD_ASSERT - assert a build-time dependency.
|
||||
* @cond: the compile-time condition which must be true.
|
||||
*
|
||||
* Your compile will fail if the condition isn't true, or can't be evaluated
|
||||
* by the compiler. This can only be used within a function.
|
||||
*
|
||||
* Example:
|
||||
* #include <stddef.h>
|
||||
* ...
|
||||
* static char *foo_to_char(struct foo *foo)
|
||||
* {
|
||||
* // This code needs string to be at start of foo.
|
||||
* BUILD_ASSERT(offsetof(struct foo, string) == 0);
|
||||
* return (char *)foo;
|
||||
* }
|
||||
*/
|
||||
#define BUILD_ASSERT(cond) \
|
||||
do { (void) sizeof(char [1 - 2*!(cond)]); } while(0)
|
||||
|
||||
/**
|
||||
* BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression.
|
||||
* @cond: the compile-time condition which must be true.
|
||||
*
|
||||
* Your compile will fail if the condition isn't true, or can't be evaluated
|
||||
* by the compiler. This can be used in an expression: its value is "0".
|
||||
*
|
||||
* Example:
|
||||
* #define foo_to_char(foo) \
|
||||
* ((char *)(foo) \
|
||||
* + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0))
|
||||
*/
|
||||
#define BUILD_ASSERT_OR_ZERO(cond) \
|
||||
(sizeof(char [1 - 2*!(cond)]) - 1)
|
||||
|
||||
#endif /* CCAN_BUILD_ASSERT_H */
|
10
ccan/ccan/build_assert/test/compile_fail-expr.c
Normal file
10
ccan/ccan/build_assert/test/compile_fail-expr.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include <ccan/build_assert/build_assert.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef FAIL
|
||||
return BUILD_ASSERT_OR_ZERO(1 == 0);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
9
ccan/ccan/build_assert/test/compile_fail.c
Normal file
9
ccan/ccan/build_assert/test/compile_fail.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include <ccan/build_assert/build_assert.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef FAIL
|
||||
BUILD_ASSERT(1 == 0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
7
ccan/ccan/build_assert/test/compile_ok.c
Normal file
7
ccan/ccan/build_assert/test/compile_ok.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include <ccan/build_assert/build_assert.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
BUILD_ASSERT(1 == 1);
|
||||
return 0;
|
||||
}
|
9
ccan/ccan/build_assert/test/run-BUILD_ASSERT_OR_ZERO.c
Normal file
9
ccan/ccan/build_assert/test/run-BUILD_ASSERT_OR_ZERO.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include <ccan/build_assert/build_assert.h>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
plan_tests(1);
|
||||
ok1(BUILD_ASSERT_OR_ZERO(1 == 1) == 0);
|
||||
return exit_status();
|
||||
}
|
1
ccan/ccan/cast/LICENSE
Symbolic link
1
ccan/ccan/cast/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../licenses/LGPL-2.1
|
85
ccan/ccan/cast/_info
Normal file
85
ccan/ccan/cast/_info
Normal file
@ -0,0 +1,85 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* cast - routines for safer casting.
|
||||
*
|
||||
* Often you want to cast in a limited way, such as removing a const or
|
||||
* switching between integer types. However, normal casts will work on
|
||||
* almost any type, making them dangerous when the code changes.
|
||||
*
|
||||
* These C++-inspired macros serve two purposes: they make it clear the
|
||||
* exact reason for the cast, and they also (with some compilers) cause
|
||||
* errors when misused.
|
||||
*
|
||||
* Based on Jan Engelhardt's libHX macros: http://libhx.sourceforge.net/
|
||||
*
|
||||
* Author: Jan Engelhardt
|
||||
* Maintainer: Rusty Russell <rusty@rustcorp.com.au>
|
||||
* License: LGPL (v2.1 or any later version)
|
||||
*
|
||||
* Example:
|
||||
* // Given "test" contains "3 t's in 'test string'
|
||||
* #include <ccan/cast/cast.h>
|
||||
* #include <stdint.h>
|
||||
* #include <stdio.h>
|
||||
*
|
||||
* // Find char @orig in @str, if @repl, replace them. Return number.
|
||||
* static size_t find_chars(char *str, char orig, char repl)
|
||||
* {
|
||||
* size_t i, count = 0;
|
||||
* for (i = 0; str[i]; i++) {
|
||||
* if (str[i] == orig) {
|
||||
* count++;
|
||||
* if (repl)
|
||||
* str[i] = repl;
|
||||
* }
|
||||
* }
|
||||
* return count;
|
||||
* }
|
||||
*
|
||||
* // Terrible hash function.
|
||||
* static uint64_t hash_string(const unsigned char *str)
|
||||
* {
|
||||
* size_t i;
|
||||
* uint64_t hash = 0;
|
||||
* for (i = 0; str[i]; i++)
|
||||
* hash += str[i];
|
||||
* return hash;
|
||||
* }
|
||||
*
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* uint64_t hash;
|
||||
*
|
||||
* // find_chars wants a non-const string, but doesn't
|
||||
* // need it if repl == 0.
|
||||
* printf("%zu %c's in 'test string'\n",
|
||||
* find_chars(cast_const(char *, "test string"),
|
||||
* argv[1][0], 0),
|
||||
* argv[1][0]);
|
||||
*
|
||||
* // hash_string wants an unsigned char.
|
||||
* hash = hash_string(cast_signed(unsigned char *, argv[1]));
|
||||
*
|
||||
* // Need a long long to hand to printf.
|
||||
* printf("Hash of '%s' = %llu\n", argv[1],
|
||||
* cast_static(unsigned long long, hash));
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* Expect exactly one argument */
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
printf("ccan/build_assert\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
134
ccan/ccan/cast/cast.h
Normal file
134
ccan/ccan/cast/cast.h
Normal file
@ -0,0 +1,134 @@
|
||||
/* Licensed under LGPLv2.1+ - see LICENSE file for details */
|
||||
#ifndef CCAN_CAST_H
|
||||
#define CCAN_CAST_H
|
||||
#include "config.h"
|
||||
#include <stdint.h>
|
||||
#include <ccan/build_assert/build_assert.h>
|
||||
|
||||
/**
|
||||
* cast_signed - cast a (const) char * to/from (const) signed/unsigned char *.
|
||||
* @type: some char * variant.
|
||||
* @expr: expression (of some char * variant) to cast.
|
||||
*
|
||||
* Some libraries insist on an unsigned char in various places; cast_signed
|
||||
* makes sure (with suitable compiler) that the expression you are casting
|
||||
* only differs in signed/unsigned, not in type or const-ness.
|
||||
*/
|
||||
#define cast_signed(type, expr) \
|
||||
(0 ? BUILD_ASSERT_OR_ZERO(cast_sign_compatible(type, (expr))) : \
|
||||
(type)(expr))
|
||||
|
||||
/**
|
||||
* cast_const - remove a const qualifier from a pointer.
|
||||
* @type: some pointer type.
|
||||
* @expr: expression to cast.
|
||||
*
|
||||
* This ensures that you are only removing the const qualifier from an
|
||||
* expression. The expression must otherwise match @type.
|
||||
*
|
||||
* We cast via intptr_t to suppress gcc's -Wcast-qual (which SAMBA
|
||||
* uses), and via the ? : so Sun CC doesn't complain about the result
|
||||
* not being constant.
|
||||
*
|
||||
* If @type is a pointer to a pointer, you must use cast_const2 (etc).
|
||||
*
|
||||
* Example:
|
||||
* // Dumb open-coded strstr variant.
|
||||
* static char *find_needle(const char *haystack)
|
||||
* {
|
||||
* size_t i;
|
||||
* for (i = 0; i < strlen(haystack); i++)
|
||||
* if (memcmp("needle", haystack+i, strlen("needle")) == 0)
|
||||
* return cast_const(char *, haystack+i);
|
||||
* return NULL;
|
||||
* }
|
||||
*/
|
||||
#define cast_const(type, expr) \
|
||||
(0 ? BUILD_ASSERT_OR_ZERO(cast_const_compat1((expr), type)) : \
|
||||
(type)(intptr_t)(expr))
|
||||
|
||||
/**
|
||||
* cast_const2 - remove a const qualifier from a pointer to a pointer.
|
||||
* @type: some pointer to pointer type.
|
||||
* @expr: expression to cast.
|
||||
*
|
||||
* This ensures that you are only removing the const qualifier from an
|
||||
* expression. The expression must otherwise match @type.
|
||||
*/
|
||||
#define cast_const2(type, expr) \
|
||||
(0 ? BUILD_ASSERT_OR_ZERO(cast_const_compat2((expr), type)) : \
|
||||
(type)(intptr_t)(expr))
|
||||
|
||||
/**
|
||||
* cast_const3 - remove a const from a pointer to a pointer to a pointer..
|
||||
* @type: some pointer to pointer to pointer type.
|
||||
* @expr: expression to cast.
|
||||
*
|
||||
* This ensures that you are only removing the const qualifier from an
|
||||
* expression. The expression must otherwise match @type.
|
||||
*/
|
||||
#define cast_const3(type, expr) \
|
||||
(0 ? BUILD_ASSERT_OR_ZERO(cast_const_compat3((expr), type)) : \
|
||||
(type)(intptr_t)(expr))
|
||||
|
||||
|
||||
/**
|
||||
* cast_static - explicit mimic of implicit cast.
|
||||
* @type: some type.
|
||||
* @expr: expression to cast.
|
||||
*
|
||||
* This ensures that the cast is not to or from a pointer: it can only be
|
||||
* an implicit cast, such as a pointer to a similar const pointer, or between
|
||||
* integral types.
|
||||
*/
|
||||
#if HAVE_COMPOUND_LITERALS
|
||||
#define cast_static(type, expr) \
|
||||
((struct { type x; }){(expr)}.x)
|
||||
#else
|
||||
#define cast_static(type, expr) \
|
||||
((type)(expr))
|
||||
#endif
|
||||
|
||||
/* Herein lies the gcc magic to evoke compile errors. */
|
||||
#if HAVE_BUILTIN_CHOOSE_EXPR && HAVE_BUILTIN_TYPES_COMPATIBLE_P && HAVE_TYPEOF
|
||||
#define cast_sign_compatible(t, e) \
|
||||
__builtin_choose_expr( \
|
||||
__builtin_types_compatible_p(__typeof__(t), char *) || \
|
||||
__builtin_types_compatible_p(__typeof__(t), signed char *) || \
|
||||
__builtin_types_compatible_p(__typeof__(t), unsigned char *), \
|
||||
/* if type is not const qualified */ \
|
||||
__builtin_types_compatible_p(__typeof__(e), char *) || \
|
||||
__builtin_types_compatible_p(__typeof__(e), signed char *) || \
|
||||
__builtin_types_compatible_p(__typeof__(e), unsigned char *), \
|
||||
/* and if it is... */ \
|
||||
__builtin_types_compatible_p(__typeof__(e), const char *) || \
|
||||
__builtin_types_compatible_p(__typeof__(e), const signed char *) || \
|
||||
__builtin_types_compatible_p(__typeof__(e), const unsigned char *) ||\
|
||||
__builtin_types_compatible_p(__typeof__(e), char *) || \
|
||||
__builtin_types_compatible_p(__typeof__(e), signed char *) || \
|
||||
__builtin_types_compatible_p(__typeof__(e), unsigned char *) \
|
||||
)
|
||||
|
||||
#define cast_const_strip1(expr) \
|
||||
__typeof__(*(union { int z; __typeof__(expr) x; }){0}.x)
|
||||
#define cast_const_strip2(expr) \
|
||||
__typeof__(**(union { int z; __typeof__(expr) x; }){0}.x)
|
||||
#define cast_const_strip3(expr) \
|
||||
__typeof__(***(union { int z; __typeof__(expr) x; }){0}.x)
|
||||
#define cast_const_compat1(expr, type) \
|
||||
__builtin_types_compatible_p(cast_const_strip1(expr), \
|
||||
cast_const_strip1(type))
|
||||
#define cast_const_compat2(expr, type) \
|
||||
__builtin_types_compatible_p(cast_const_strip2(expr), \
|
||||
cast_const_strip2(type))
|
||||
#define cast_const_compat3(expr, type) \
|
||||
__builtin_types_compatible_p(cast_const_strip3(expr), \
|
||||
cast_const_strip3(type))
|
||||
#else
|
||||
#define cast_sign_compatible(type, expr) \
|
||||
(sizeof(*(type)0) == 1 && sizeof(*(expr)) == 1)
|
||||
#define cast_const_compat1(expr, type) (1)
|
||||
#define cast_const_compat2(expr, type) (1)
|
||||
#define cast_const_compat3(expr, type) (1)
|
||||
#endif
|
||||
#endif /* CCAN_CAST_H */
|
29
ccan/ccan/cast/test/compile_fail-cast_const.c
Normal file
29
ccan/ccan/cast/test/compile_fail-cast_const.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include <ccan/cast/cast.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Note: this *isn't* sizeof(char) on all platforms. */
|
||||
struct char_struct {
|
||||
char c;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *uc;
|
||||
const
|
||||
#ifdef FAIL
|
||||
struct char_struct
|
||||
#else
|
||||
char
|
||||
#endif
|
||||
*p = NULL;
|
||||
|
||||
uc = cast_const(char *, p);
|
||||
(void) uc; /* Suppress unused-but-set-variable warning. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef FAIL
|
||||
#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P
|
||||
#error "Unfortunately we don't fail if cast_const can only use size"
|
||||
#endif
|
||||
#endif
|
29
ccan/ccan/cast/test/compile_fail-cast_const2.c
Normal file
29
ccan/ccan/cast/test/compile_fail-cast_const2.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include <ccan/cast/cast.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Note: this *isn't* sizeof(char) on all platforms. */
|
||||
struct char_struct {
|
||||
char c;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char **uc;
|
||||
const
|
||||
#ifdef FAIL
|
||||
struct char_struct
|
||||
#else
|
||||
char
|
||||
#endif
|
||||
**p = NULL;
|
||||
|
||||
uc = cast_const2(char **, p);
|
||||
(void) uc; /* Suppress unused-but-set-variable warning. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef FAIL
|
||||
#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P
|
||||
#error "Unfortunately we don't fail if cast_const can only use size"
|
||||
#endif
|
||||
#endif
|
29
ccan/ccan/cast/test/compile_fail-cast_const3.c
Normal file
29
ccan/ccan/cast/test/compile_fail-cast_const3.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include <ccan/cast/cast.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Note: this *isn't* sizeof(char) on all platforms. */
|
||||
struct char_struct {
|
||||
char c;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char ***uc;
|
||||
const
|
||||
#ifdef FAIL
|
||||
struct char_struct
|
||||
#else
|
||||
char
|
||||
#endif
|
||||
***p = NULL;
|
||||
|
||||
uc = cast_const3(char ***, p);
|
||||
(void) uc; /* Suppress unused-but-set-variable warning. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef FAIL
|
||||
#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P
|
||||
#error "Unfortunately we don't fail if cast_const can only use size"
|
||||
#endif
|
||||
#endif
|
22
ccan/ccan/cast/test/compile_fail-cast_signed-const.c
Normal file
22
ccan/ccan/cast/test/compile_fail-cast_signed-const.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <ccan/cast/cast.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned char *uc;
|
||||
#ifdef FAIL
|
||||
const
|
||||
#endif
|
||||
char
|
||||
*p = NULL;
|
||||
|
||||
uc = cast_signed(unsigned char *, p);
|
||||
(void) uc; /* Suppress unused-but-set-variable warning. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef FAIL
|
||||
#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P
|
||||
#error "Unfortunately we don't fail if cast_const can only use size"
|
||||
#endif
|
||||
#endif
|
29
ccan/ccan/cast/test/compile_fail-cast_signed-sizesame.c
Normal file
29
ccan/ccan/cast/test/compile_fail-cast_signed-sizesame.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include <ccan/cast/cast.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Note: this *isn't* sizeof(char) on all platforms. */
|
||||
struct char_struct {
|
||||
char c;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned char *uc;
|
||||
#ifdef FAIL
|
||||
struct char_struct
|
||||
#else
|
||||
char
|
||||
#endif
|
||||
*p = NULL;
|
||||
|
||||
uc = cast_signed(unsigned char *, p);
|
||||
|
||||
(void) uc; /* Suppress unused-but-set-variable warning. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef FAIL
|
||||
#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P
|
||||
#error "Unfortunately we don't fail if cast_signed can only use size"
|
||||
#endif
|
||||
#endif
|
17
ccan/ccan/cast/test/compile_fail-cast_signed.c
Normal file
17
ccan/ccan/cast/test/compile_fail-cast_signed.c
Normal file
@ -0,0 +1,17 @@
|
||||
#include <ccan/cast/cast.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned char *uc;
|
||||
#ifdef FAIL
|
||||
int
|
||||
#else
|
||||
char
|
||||
#endif
|
||||
*p = NULL;
|
||||
|
||||
uc = cast_signed(unsigned char *, p);
|
||||
(void) uc; /* Suppress unused-but-set-variable warning. */
|
||||
return 0;
|
||||
}
|
23
ccan/ccan/cast/test/compile_fail-cast_static-2.c
Normal file
23
ccan/ccan/cast/test/compile_fail-cast_static-2.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include <ccan/cast/cast.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *c;
|
||||
#ifdef FAIL
|
||||
long
|
||||
#else
|
||||
char
|
||||
#endif
|
||||
*p = 0;
|
||||
|
||||
c = cast_static(char *, p);
|
||||
(void) c; /* Suppress unused-but-set-variable warning. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef FAIL
|
||||
#if !HAVE_COMPOUND_LITERALS
|
||||
#error "Unfortunately we don't fail if cast_static is a noop"
|
||||
#endif
|
||||
#endif
|
21
ccan/ccan/cast/test/compile_fail-cast_static-3.c
Normal file
21
ccan/ccan/cast/test/compile_fail-cast_static-3.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include <ccan/cast/cast.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *c;
|
||||
#ifdef FAIL
|
||||
const
|
||||
#endif
|
||||
char *p = 0;
|
||||
|
||||
c = cast_static(char *, p);
|
||||
(void) c; /* Suppress unused-but-set-variable warning. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef FAIL
|
||||
#if !HAVE_COMPOUND_LITERALS
|
||||
#error "Unfortunately we don't fail if cast_static is a noop"
|
||||
#endif
|
||||
#endif
|
23
ccan/ccan/cast/test/compile_fail-cast_static.c
Normal file
23
ccan/ccan/cast/test/compile_fail-cast_static.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include <ccan/cast/cast.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
long c;
|
||||
#ifdef FAIL
|
||||
char *
|
||||
#else
|
||||
char
|
||||
#endif
|
||||
x = 0;
|
||||
|
||||
c = cast_static(long, x);
|
||||
(void) c; /* Suppress unused-but-set-variable warning. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef FAIL
|
||||
#if !HAVE_COMPOUND_LITERALS
|
||||
#error "Unfortunately we don't fail if cast_static without compound literals"
|
||||
#endif
|
||||
#endif
|
12
ccan/ccan/cast/test/compile_ok-cast_void.c
Normal file
12
ccan/ccan/cast/test/compile_ok-cast_void.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include <ccan/cast/cast.h>
|
||||
|
||||
static void *remove_void(const void *p)
|
||||
{
|
||||
return cast_const(void *, p);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
void *p = remove_void("foo");
|
||||
return !p;
|
||||
}
|
10
ccan/ccan/cast/test/compile_ok-static.c
Normal file
10
ccan/ccan/cast/test/compile_ok-static.c
Normal file
@ -0,0 +1,10 @@
|
||||
/* OpenIndiana's CC (aka suncc) has issues with constants: make sure
|
||||
* we are one! */
|
||||
#include <ccan/cast/cast.h>
|
||||
|
||||
static char *p = cast_const(char *, (const char *)"hello");
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
return p[0] == argv[0][0];
|
||||
}
|
1
ccan/ccan/check_type/LICENSE
Symbolic link
1
ccan/ccan/check_type/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../licenses/CC0
|
33
ccan/ccan/check_type/_info
Normal file
33
ccan/ccan/check_type/_info
Normal file
@ -0,0 +1,33 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* check_type - routines for compile time type checking
|
||||
*
|
||||
* C has fairly weak typing: ints get automatically converted to longs, signed
|
||||
* to unsigned, etc. There are some cases where this is best avoided, and
|
||||
* these macros provide methods for evoking warnings (or build errors) when
|
||||
* a precise type isn't used.
|
||||
*
|
||||
* On compilers which don't support typeof() these routines are less effective,
|
||||
* since they have to use sizeof() which can only distiguish between types of
|
||||
* different size.
|
||||
*
|
||||
* License: CC0 (Public domain)
|
||||
* Author: Rusty Russell <rusty@rustcorp.com.au>
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
#if !HAVE_TYPEOF
|
||||
printf("ccan/build_assert\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
64
ccan/ccan/check_type/check_type.h
Normal file
64
ccan/ccan/check_type/check_type.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#ifndef CCAN_CHECK_TYPE_H
|
||||
#define CCAN_CHECK_TYPE_H
|
||||
#include "config.h"
|
||||
|
||||
/**
|
||||
* check_type - issue a warning or build failure if type is not correct.
|
||||
* @expr: the expression whose type we should check (not evaluated).
|
||||
* @type: the exact type we expect the expression to be.
|
||||
*
|
||||
* This macro is usually used within other macros to try to ensure that a macro
|
||||
* argument is of the expected type. No type promotion of the expression is
|
||||
* done: an unsigned int is not the same as an int!
|
||||
*
|
||||
* check_type() always evaluates to 0.
|
||||
*
|
||||
* If your compiler does not support typeof, then the best we can do is fail
|
||||
* to compile if the sizes of the types are unequal (a less complete check).
|
||||
*
|
||||
* Example:
|
||||
* // They should always pass a 64-bit value to _set_some_value!
|
||||
* #define set_some_value(expr) \
|
||||
* _set_some_value((check_type((expr), uint64_t), (expr)))
|
||||
*/
|
||||
|
||||
/**
|
||||
* check_types_match - issue a warning or build failure if types are not same.
|
||||
* @expr1: the first expression (not evaluated).
|
||||
* @expr2: the second expression (not evaluated).
|
||||
*
|
||||
* This macro is usually used within other macros to try to ensure that
|
||||
* arguments are of identical types. No type promotion of the expressions is
|
||||
* done: an unsigned int is not the same as an int!
|
||||
*
|
||||
* check_types_match() always evaluates to 0.
|
||||
*
|
||||
* If your compiler does not support typeof, then the best we can do is fail
|
||||
* to compile if the sizes of the types are unequal (a less complete check).
|
||||
*
|
||||
* Example:
|
||||
* // Do subtraction to get to enclosing type, but make sure that
|
||||
* // pointer is of correct type for that member.
|
||||
* #define container_of(mbr_ptr, encl_type, mbr) \
|
||||
* (check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \
|
||||
* ((encl_type *) \
|
||||
* ((char *)(mbr_ptr) - offsetof(enclosing_type, mbr))))
|
||||
*/
|
||||
#if HAVE_TYPEOF
|
||||
#define check_type(expr, type) \
|
||||
((typeof(expr) *)0 != (type *)0)
|
||||
|
||||
#define check_types_match(expr1, expr2) \
|
||||
((typeof(expr1) *)0 != (typeof(expr2) *)0)
|
||||
#else
|
||||
#include <ccan/build_assert/build_assert.h>
|
||||
/* Without typeof, we can only test the sizes. */
|
||||
#define check_type(expr, type) \
|
||||
BUILD_ASSERT_OR_ZERO(sizeof(expr) == sizeof(type))
|
||||
|
||||
#define check_types_match(expr1, expr2) \
|
||||
BUILD_ASSERT_OR_ZERO(sizeof(expr1) == sizeof(expr2))
|
||||
#endif /* HAVE_TYPEOF */
|
||||
|
||||
#endif /* CCAN_CHECK_TYPE_H */
|
9
ccan/ccan/check_type/test/compile_fail-check_type.c
Normal file
9
ccan/ccan/check_type/test/compile_fail-check_type.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include <ccan/check_type/check_type.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef FAIL
|
||||
check_type(argc, char);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
14
ccan/ccan/check_type/test/compile_fail-check_type_unsigned.c
Normal file
14
ccan/ccan/check_type/test/compile_fail-check_type_unsigned.c
Normal file
@ -0,0 +1,14 @@
|
||||
#include <ccan/check_type/check_type.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef FAIL
|
||||
#if HAVE_TYPEOF
|
||||
check_type(argc, unsigned int);
|
||||
#else
|
||||
/* This doesn't work without typeof, so just fail */
|
||||
#error "Fail without typeof"
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
10
ccan/ccan/check_type/test/compile_fail-check_types_match.c
Normal file
10
ccan/ccan/check_type/test/compile_fail-check_types_match.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include <ccan/check_type/check_type.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned char x = argc;
|
||||
#ifdef FAIL
|
||||
check_types_match(argc, x);
|
||||
#endif
|
||||
return x;
|
||||
}
|
22
ccan/ccan/check_type/test/run.c
Normal file
22
ccan/ccan/check_type/test/run.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <ccan/check_type/check_type.h>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int x = 0, y = 0;
|
||||
|
||||
plan_tests(9);
|
||||
|
||||
ok1(check_type(argc, int) == 0);
|
||||
ok1(check_type(&argc, int *) == 0);
|
||||
ok1(check_types_match(argc, argc) == 0);
|
||||
ok1(check_types_match(argc, x) == 0);
|
||||
ok1(check_types_match(&argc, &x) == 0);
|
||||
|
||||
ok1(check_type(x++, int) == 0);
|
||||
ok(x == 0, "check_type does not evaluate expression");
|
||||
ok1(check_types_match(x++, y++) == 0);
|
||||
ok(x == 0 && y == 0, "check_types_match does not evaluate expressions");
|
||||
|
||||
return exit_status();
|
||||
}
|
1
ccan/ccan/compiler/LICENSE
Symbolic link
1
ccan/ccan/compiler/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../licenses/CC0
|
64
ccan/ccan/compiler/_info
Normal file
64
ccan/ccan/compiler/_info
Normal file
@ -0,0 +1,64 @@
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* compiler - macros for common compiler extensions
|
||||
*
|
||||
* Abstracts away some compiler hints. Currently these include:
|
||||
* - COLD
|
||||
* For functions not called in fast paths (aka. cold functions)
|
||||
* - PRINTF_FMT
|
||||
* For functions which take printf-style parameters.
|
||||
* - CONST_FUNCTION
|
||||
* For functions which return the same value for same parameters.
|
||||
* - NEEDED
|
||||
* For functions and variables which must be emitted even if unused.
|
||||
* - UNNEEDED
|
||||
* For functions and variables which need not be emitted if unused.
|
||||
* - UNUSED
|
||||
* For parameters which are not used.
|
||||
* - IS_COMPILE_CONSTANT()
|
||||
* For using different tradeoffs for compiletime vs runtime evaluation.
|
||||
*
|
||||
* License: CC0 (Public domain)
|
||||
* Author: Rusty Russell <rusty@rustcorp.com.au>
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/compiler/compiler.h>
|
||||
* #include <stdio.h>
|
||||
* #include <stdarg.h>
|
||||
*
|
||||
* // Example of a (slow-path) logging function.
|
||||
* static int log_threshold = 2;
|
||||
* static void COLD PRINTF_FMT(2,3)
|
||||
* logger(int level, const char *fmt, ...)
|
||||
* {
|
||||
* va_list ap;
|
||||
* va_start(ap, fmt);
|
||||
* if (level >= log_threshold)
|
||||
* vfprintf(stderr, fmt, ap);
|
||||
* va_end(ap);
|
||||
* }
|
||||
*
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* if (argc != 1) {
|
||||
* logger(3, "Don't want %i arguments!\n", argc-1);
|
||||
* return 1;
|
||||
* }
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* Expect exactly one argument */
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
231
ccan/ccan/compiler/compiler.h
Normal file
231
ccan/ccan/compiler/compiler.h
Normal file
@ -0,0 +1,231 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#ifndef CCAN_COMPILER_H
|
||||
#define CCAN_COMPILER_H
|
||||
#include "config.h"
|
||||
|
||||
#ifndef COLD
|
||||
#if HAVE_ATTRIBUTE_COLD
|
||||
/**
|
||||
* COLD - a function is unlikely to be called.
|
||||
*
|
||||
* Used to mark an unlikely code path and optimize appropriately.
|
||||
* It is usually used on logging or error routines.
|
||||
*
|
||||
* Example:
|
||||
* static void COLD moan(const char *reason)
|
||||
* {
|
||||
* fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno));
|
||||
* }
|
||||
*/
|
||||
#define COLD __attribute__((__cold__))
|
||||
#else
|
||||
#define COLD
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NORETURN
|
||||
#if HAVE_ATTRIBUTE_NORETURN
|
||||
/**
|
||||
* NORETURN - a function does not return
|
||||
*
|
||||
* Used to mark a function which exits; useful for suppressing warnings.
|
||||
*
|
||||
* Example:
|
||||
* static void NORETURN fail(const char *reason)
|
||||
* {
|
||||
* fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno));
|
||||
* exit(1);
|
||||
* }
|
||||
*/
|
||||
#define NORETURN __attribute__((__noreturn__))
|
||||
#else
|
||||
#define NORETURN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PRINTF_FMT
|
||||
#if HAVE_ATTRIBUTE_PRINTF
|
||||
/**
|
||||
* PRINTF_FMT - a function takes printf-style arguments
|
||||
* @nfmt: the 1-based number of the function's format argument.
|
||||
* @narg: the 1-based number of the function's first variable argument.
|
||||
*
|
||||
* This allows the compiler to check your parameters as it does for printf().
|
||||
*
|
||||
* Example:
|
||||
* void PRINTF_FMT(2,3) my_printf(const char *prefix, const char *fmt, ...);
|
||||
*/
|
||||
#define PRINTF_FMT(nfmt, narg) \
|
||||
__attribute__((format(__printf__, nfmt, narg)))
|
||||
#else
|
||||
#define PRINTF_FMT(nfmt, narg)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CONST_FUNCTION
|
||||
#if HAVE_ATTRIBUTE_CONST
|
||||
/**
|
||||
* CONST_FUNCTION - a function's return depends only on its argument
|
||||
*
|
||||
* This allows the compiler to assume that the function will return the exact
|
||||
* same value for the exact same arguments. This implies that the function
|
||||
* must not use global variables, or dereference pointer arguments.
|
||||
*/
|
||||
#define CONST_FUNCTION __attribute__((__const__))
|
||||
#else
|
||||
#define CONST_FUNCTION
|
||||
#endif
|
||||
|
||||
#ifndef PURE_FUNCTION
|
||||
#if HAVE_ATTRIBUTE_PURE
|
||||
/**
|
||||
* PURE_FUNCTION - a function is pure
|
||||
*
|
||||
* A pure function is one that has no side effects other than it's return value
|
||||
* and uses no inputs other than it's arguments and global variables.
|
||||
*/
|
||||
#define PURE_FUNCTION __attribute__((__pure__))
|
||||
#else
|
||||
#define PURE_FUNCTION
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAVE_ATTRIBUTE_UNUSED
|
||||
#ifndef UNNEEDED
|
||||
/**
|
||||
* UNNEEDED - a variable/function may not be needed
|
||||
*
|
||||
* This suppresses warnings about unused variables or functions, but tells
|
||||
* the compiler that if it is unused it need not emit it into the source code.
|
||||
*
|
||||
* Example:
|
||||
* // With some preprocessor options, this is unnecessary.
|
||||
* static UNNEEDED int counter;
|
||||
*
|
||||
* // With some preprocessor options, this is unnecessary.
|
||||
* static UNNEEDED void add_to_counter(int add)
|
||||
* {
|
||||
* counter += add;
|
||||
* }
|
||||
*/
|
||||
#define UNNEEDED __attribute__((__unused__))
|
||||
#endif
|
||||
|
||||
#ifndef NEEDED
|
||||
#if HAVE_ATTRIBUTE_USED
|
||||
/**
|
||||
* NEEDED - a variable/function is needed
|
||||
*
|
||||
* This suppresses warnings about unused variables or functions, but tells
|
||||
* the compiler that it must exist even if it (seems) unused.
|
||||
*
|
||||
* Example:
|
||||
* // Even if this is unused, these are vital for debugging.
|
||||
* static NEEDED int counter;
|
||||
* static NEEDED void dump_counter(void)
|
||||
* {
|
||||
* printf("Counter is %i\n", counter);
|
||||
* }
|
||||
*/
|
||||
#define NEEDED __attribute__((__used__))
|
||||
#else
|
||||
/* Before used, unused functions and vars were always emitted. */
|
||||
#define NEEDED __attribute__((__unused__))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UNUSED
|
||||
/**
|
||||
* UNUSED - a parameter is unused
|
||||
*
|
||||
* Some compilers (eg. gcc with -W or -Wunused) warn about unused
|
||||
* function parameters. This suppresses such warnings and indicates
|
||||
* to the reader that it's deliberate.
|
||||
*
|
||||
* Example:
|
||||
* // This is used as a callback, so needs to have this prototype.
|
||||
* static int some_callback(void *unused UNUSED)
|
||||
* {
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
#define UNUSED __attribute__((__unused__))
|
||||
#endif
|
||||
#else
|
||||
#ifndef UNNEEDED
|
||||
#define UNNEEDED
|
||||
#endif
|
||||
#ifndef NEEDED
|
||||
#define NEEDED
|
||||
#endif
|
||||
#ifndef UNUSED
|
||||
#define UNUSED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef IS_COMPILE_CONSTANT
|
||||
#if HAVE_BUILTIN_CONSTANT_P
|
||||
/**
|
||||
* IS_COMPILE_CONSTANT - does the compiler know the value of this expression?
|
||||
* @expr: the expression to evaluate
|
||||
*
|
||||
* When an expression manipulation is complicated, it is usually better to
|
||||
* implement it in a function. However, if the expression being manipulated is
|
||||
* known at compile time, it is better to have the compiler see the entire
|
||||
* expression so it can simply substitute the result.
|
||||
*
|
||||
* This can be done using the IS_COMPILE_CONSTANT() macro.
|
||||
*
|
||||
* Example:
|
||||
* enum greek { ALPHA, BETA, GAMMA, DELTA, EPSILON };
|
||||
*
|
||||
* // Out-of-line version.
|
||||
* const char *greek_name(enum greek greek);
|
||||
*
|
||||
* // Inline version.
|
||||
* static inline const char *_greek_name(enum greek greek)
|
||||
* {
|
||||
* switch (greek) {
|
||||
* case ALPHA: return "alpha";
|
||||
* case BETA: return "beta";
|
||||
* case GAMMA: return "gamma";
|
||||
* case DELTA: return "delta";
|
||||
* case EPSILON: return "epsilon";
|
||||
* default: return "**INVALID**";
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // Use inline if compiler knows answer. Otherwise call function
|
||||
* // to avoid copies of the same code everywhere.
|
||||
* #define greek_name(g) \
|
||||
* (IS_COMPILE_CONSTANT(greek) ? _greek_name(g) : greek_name(g))
|
||||
*/
|
||||
#define IS_COMPILE_CONSTANT(expr) __builtin_constant_p(expr)
|
||||
#else
|
||||
/* If we don't know, assume it's not. */
|
||||
#define IS_COMPILE_CONSTANT(expr) 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef WARN_UNUSED_RESULT
|
||||
#if HAVE_WARN_UNUSED_RESULT
|
||||
/**
|
||||
* WARN_UNUSED_RESULT - warn if a function return value is unused.
|
||||
*
|
||||
* Used to mark a function where it is extremely unlikely that the caller
|
||||
* can ignore the result, eg realloc().
|
||||
*
|
||||
* Example:
|
||||
* // buf param may be freed by this; need return value!
|
||||
* static char *WARN_UNUSED_RESULT enlarge(char *buf, unsigned *size)
|
||||
* {
|
||||
* return realloc(buf, (*size) *= 2);
|
||||
* }
|
||||
*/
|
||||
#define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
|
||||
#else
|
||||
#define WARN_UNUSED_RESULT
|
||||
#endif
|
||||
#endif
|
||||
#endif /* CCAN_COMPILER_H */
|
22
ccan/ccan/compiler/test/compile_fail-printf.c
Normal file
22
ccan/ccan/compiler/test/compile_fail-printf.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <ccan/compiler/compiler.h>
|
||||
|
||||
static void PRINTF_FMT(2,3) my_printf(int x, const char *fmt, ...)
|
||||
{
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
my_printf(1, "Not a pointer "
|
||||
#ifdef FAIL
|
||||
"%p",
|
||||
#if !HAVE_ATTRIBUTE_PRINTF
|
||||
#error "Unfortunately we don't fail if !HAVE_ATTRIBUTE_PRINTF."
|
||||
#endif
|
||||
#else
|
||||
"%i",
|
||||
#endif
|
||||
i);
|
||||
return 0;
|
||||
}
|
15
ccan/ccan/compiler/test/run-is_compile_constant.c
Normal file
15
ccan/ccan/compiler/test/run-is_compile_constant.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <ccan/compiler/compiler.h>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
plan_tests(2);
|
||||
|
||||
ok1(!IS_COMPILE_CONSTANT(argc));
|
||||
#if HAVE_BUILTIN_CONSTANT_P
|
||||
ok1(IS_COMPILE_CONSTANT(7));
|
||||
#else
|
||||
pass("If !HAVE_BUILTIN_CONSTANT_P, IS_COMPILE_CONSTANT always false");
|
||||
#endif
|
||||
return exit_status();
|
||||
}
|
1
ccan/ccan/container_of/LICENSE
Symbolic link
1
ccan/ccan/container_of/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../licenses/CC0
|
63
ccan/ccan/container_of/_info
Normal file
63
ccan/ccan/container_of/_info
Normal file
@ -0,0 +1,63 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* container_of - routine for upcasting
|
||||
*
|
||||
* It is often convenient to create code where the caller registers a pointer
|
||||
* to a generic structure and a callback. The callback might know that the
|
||||
* pointer points to within a larger structure, and container_of gives a
|
||||
* convenient and fairly type-safe way of returning to the enclosing structure.
|
||||
*
|
||||
* This idiom is an alternative to providing a void * pointer for every
|
||||
* callback.
|
||||
*
|
||||
* Example:
|
||||
* #include <stdio.h>
|
||||
* #include <ccan/container_of/container_of.h>
|
||||
*
|
||||
* struct timer {
|
||||
* void *members;
|
||||
* };
|
||||
*
|
||||
* struct info {
|
||||
* int my_stuff;
|
||||
* struct timer timer;
|
||||
* };
|
||||
*
|
||||
* static void register_timer(struct timer *timer)
|
||||
* {
|
||||
* //...
|
||||
* }
|
||||
*
|
||||
* static void my_timer_callback(struct timer *timer)
|
||||
* {
|
||||
* struct info *info = container_of(timer, struct info, timer);
|
||||
* printf("my_stuff is %u\n", info->my_stuff);
|
||||
* }
|
||||
*
|
||||
* int main(void)
|
||||
* {
|
||||
* struct info info = { .my_stuff = 1 };
|
||||
*
|
||||
* register_timer(&info.timer);
|
||||
* // ...
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* License: CC0 (Public domain)
|
||||
* Author: Rusty Russell <rusty@rustcorp.com.au>
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
printf("ccan/check_type\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
145
ccan/ccan/container_of/container_of.h
Normal file
145
ccan/ccan/container_of/container_of.h
Normal file
@ -0,0 +1,145 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#ifndef CCAN_CONTAINER_OF_H
|
||||
#define CCAN_CONTAINER_OF_H
|
||||
#include <stddef.h>
|
||||
|
||||
#include "config.h"
|
||||
#include <ccan/check_type/check_type.h>
|
||||
|
||||
/**
|
||||
* container_of - get pointer to enclosing structure
|
||||
* @member_ptr: pointer to the structure member
|
||||
* @containing_type: the type this member is within
|
||||
* @member: the name of this member within the structure.
|
||||
*
|
||||
* Given a pointer to a member of a structure, this macro does pointer
|
||||
* subtraction to return the pointer to the enclosing type.
|
||||
*
|
||||
* Example:
|
||||
* struct foo {
|
||||
* int fielda, fieldb;
|
||||
* // ...
|
||||
* };
|
||||
* struct info {
|
||||
* int some_other_field;
|
||||
* struct foo my_foo;
|
||||
* };
|
||||
*
|
||||
* static struct info *foo_to_info(struct foo *foo)
|
||||
* {
|
||||
* return container_of(foo, struct info, my_foo);
|
||||
* }
|
||||
*/
|
||||
#define container_of(member_ptr, containing_type, member) \
|
||||
((containing_type *) \
|
||||
((char *)(member_ptr) \
|
||||
- container_off(containing_type, member)) \
|
||||
+ check_types_match(*(member_ptr), ((containing_type *)0)->member))
|
||||
|
||||
|
||||
/**
|
||||
* container_of_or_null - get pointer to enclosing structure, or NULL
|
||||
* @member_ptr: pointer to the structure member
|
||||
* @containing_type: the type this member is within
|
||||
* @member: the name of this member within the structure.
|
||||
*
|
||||
* Given a pointer to a member of a structure, this macro does pointer
|
||||
* subtraction to return the pointer to the enclosing type, unless it
|
||||
* is given NULL, in which case it also returns NULL.
|
||||
*
|
||||
* Example:
|
||||
* struct foo {
|
||||
* int fielda, fieldb;
|
||||
* // ...
|
||||
* };
|
||||
* struct info {
|
||||
* int some_other_field;
|
||||
* struct foo my_foo;
|
||||
* };
|
||||
*
|
||||
* static struct info *foo_to_info_allowing_null(struct foo *foo)
|
||||
* {
|
||||
* return container_of_or_null(foo, struct info, my_foo);
|
||||
* }
|
||||
*/
|
||||
static inline char *container_of_or_null_(void *member_ptr, size_t offset)
|
||||
{
|
||||
return member_ptr ? (char *)member_ptr - offset : NULL;
|
||||
}
|
||||
#define container_of_or_null(member_ptr, containing_type, member) \
|
||||
((containing_type *) \
|
||||
container_of_or_null_(member_ptr, \
|
||||
container_off(containing_type, member)) \
|
||||
+ check_types_match(*(member_ptr), ((containing_type *)0)->member))
|
||||
|
||||
/**
|
||||
* container_off - get offset to enclosing structure
|
||||
* @containing_type: the type this member is within
|
||||
* @member: the name of this member within the structure.
|
||||
*
|
||||
* Given a pointer to a member of a structure, this macro does
|
||||
* typechecking and figures out the offset to the enclosing type.
|
||||
*
|
||||
* Example:
|
||||
* struct foo {
|
||||
* int fielda, fieldb;
|
||||
* // ...
|
||||
* };
|
||||
* struct info {
|
||||
* int some_other_field;
|
||||
* struct foo my_foo;
|
||||
* };
|
||||
*
|
||||
* static struct info *foo_to_info(struct foo *foo)
|
||||
* {
|
||||
* size_t off = container_off(struct info, my_foo);
|
||||
* return (void *)((char *)foo - off);
|
||||
* }
|
||||
*/
|
||||
#define container_off(containing_type, member) \
|
||||
offsetof(containing_type, member)
|
||||
|
||||
/**
|
||||
* container_of_var - get pointer to enclosing structure using a variable
|
||||
* @member_ptr: pointer to the structure member
|
||||
* @container_var: a pointer of same type as this member's container
|
||||
* @member: the name of this member within the structure.
|
||||
*
|
||||
* Given a pointer to a member of a structure, this macro does pointer
|
||||
* subtraction to return the pointer to the enclosing type.
|
||||
*
|
||||
* Example:
|
||||
* static struct info *foo_to_i(struct foo *foo)
|
||||
* {
|
||||
* struct info *i = container_of_var(foo, i, my_foo);
|
||||
* return i;
|
||||
* }
|
||||
*/
|
||||
#if HAVE_TYPEOF
|
||||
#define container_of_var(member_ptr, container_var, member) \
|
||||
container_of(member_ptr, typeof(*container_var), member)
|
||||
#else
|
||||
#define container_of_var(member_ptr, container_var, member) \
|
||||
((void *)((char *)(member_ptr) - \
|
||||
container_off_var(container_var, member)))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* container_off_var - get offset of a field in enclosing structure
|
||||
* @container_var: a pointer to a container structure
|
||||
* @member: the name of a member within the structure.
|
||||
*
|
||||
* Given (any) pointer to a structure and a its member name, this
|
||||
* macro does pointer subtraction to return offset of member in a
|
||||
* structure memory layout.
|
||||
*
|
||||
*/
|
||||
#if HAVE_TYPEOF
|
||||
#define container_off_var(var, member) \
|
||||
container_off(typeof(*var), member)
|
||||
#else
|
||||
#define container_off_var(var, member) \
|
||||
((const char *)&(var)->member - (const char *)(var))
|
||||
#endif
|
||||
|
||||
#endif /* CCAN_CONTAINER_OF_H */
|
22
ccan/ccan/container_of/test/compile_fail-bad-type.c
Normal file
22
ccan/ccan/container_of/test/compile_fail-bad-type.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <ccan/container_of/container_of.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct foo {
|
||||
int a;
|
||||
char b;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct foo foo = { .a = 1, .b = 2 };
|
||||
int *intp = &foo.a;
|
||||
char *p;
|
||||
|
||||
#ifdef FAIL
|
||||
/* p is a char *, but this gives a struct foo * */
|
||||
p = container_of(intp, struct foo, a);
|
||||
#else
|
||||
p = (char *)intp;
|
||||
#endif
|
||||
return p == NULL;
|
||||
}
|
22
ccan/ccan/container_of/test/compile_fail-types.c
Normal file
22
ccan/ccan/container_of/test/compile_fail-types.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <ccan/container_of/container_of.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct foo {
|
||||
int a;
|
||||
char b;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct foo foo = { .a = 1, .b = 2 }, *foop;
|
||||
int *intp = &foo.a;
|
||||
|
||||
#ifdef FAIL
|
||||
/* b is a char, but intp is an int * */
|
||||
foop = container_of(intp, struct foo, b);
|
||||
#else
|
||||
foop = NULL;
|
||||
#endif
|
||||
(void) foop; /* Suppress unused-but-set-variable warning. */
|
||||
return intp == NULL;
|
||||
}
|
25
ccan/ccan/container_of/test/compile_fail-var-types.c
Normal file
25
ccan/ccan/container_of/test/compile_fail-var-types.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include <ccan/container_of/container_of.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct foo {
|
||||
int a;
|
||||
char b;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct foo foo = { .a = 1, .b = 2 }, *foop;
|
||||
int *intp = &foo.a;
|
||||
|
||||
#ifdef FAIL
|
||||
/* b is a char, but intp is an int * */
|
||||
foop = container_of_var(intp, foop, b);
|
||||
#if !HAVE_TYPEOF
|
||||
#error "Unfortunately we don't fail if we don't have typeof."
|
||||
#endif
|
||||
#else
|
||||
foop = NULL;
|
||||
#endif
|
||||
(void) foop; /* Suppress unused-but-set-variable warning. */
|
||||
return intp == NULL;
|
||||
}
|
30
ccan/ccan/container_of/test/run.c
Normal file
30
ccan/ccan/container_of/test/run.c
Normal file
@ -0,0 +1,30 @@
|
||||
#include <ccan/container_of/container_of.h>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
struct foo {
|
||||
int a;
|
||||
char b;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct foo foo = { .a = 1, .b = 2 };
|
||||
int *intp = &foo.a;
|
||||
char *charp = &foo.b;
|
||||
|
||||
plan_tests(12);
|
||||
ok1(container_of(intp, struct foo, a) == &foo);
|
||||
ok1(container_of(charp, struct foo, b) == &foo);
|
||||
ok1(container_of_or_null(intp, struct foo, a) == &foo);
|
||||
ok1(container_of_or_null(charp, struct foo, b) == &foo);
|
||||
ok1(container_of_or_null((int *)NULL, struct foo, a) == NULL);
|
||||
ok1(container_of_or_null((char *)NULL, struct foo, b) == NULL);
|
||||
ok1(container_of_var(intp, &foo, a) == &foo);
|
||||
ok1(container_of_var(charp, &foo, b) == &foo);
|
||||
|
||||
ok1(container_off(struct foo, a) == 0);
|
||||
ok1(container_off(struct foo, b) == offsetof(struct foo, b));
|
||||
ok1(container_off_var(&foo, a) == 0);
|
||||
ok1(container_off_var(&foo, b) == offsetof(struct foo, b));
|
||||
return exit_status();
|
||||
}
|
1
ccan/ccan/crypto/sha256/LICENSE
Symbolic link
1
ccan/ccan/crypto/sha256/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../../licenses/BSD-MIT
|
55
ccan/ccan/crypto/sha256/_info
Normal file
55
ccan/ccan/crypto/sha256/_info
Normal file
@ -0,0 +1,55 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* crypto/sha256 - implementation of SHA-2 with 256 bit digest.
|
||||
*
|
||||
* This code is either a wrapper for openssl (if CCAN_CRYPTO_SHA256_USE_OPENSSL
|
||||
* is defined) or an open-coded implementation based on Bitcoin's.
|
||||
*
|
||||
* License: BSD-MIT
|
||||
* Maintainer: Rusty Russell <rusty@rustcorp.com.au>
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/crypto/sha256/sha256.h>
|
||||
* #include <err.h>
|
||||
* #include <stdio.h>
|
||||
* #include <string.h>
|
||||
*
|
||||
* // Simple demonstration: idential strings will have the same hash, but
|
||||
* // two different strings will not.
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* struct sha256 hash1, hash2;
|
||||
*
|
||||
* if (argc != 3)
|
||||
* errx(1, "Usage: %s <string1> <string2>", argv[0]);
|
||||
*
|
||||
* sha256(&hash1, argv[1], strlen(argv[1]));
|
||||
* sha256(&hash2, argv[2], strlen(argv[2]));
|
||||
* printf("Hash is %s\n", memcmp(&hash1, &hash2, sizeof(hash1))
|
||||
* ? "different" : "same");
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* Expect exactly one argument */
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
printf("ccan/endian\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "libs") == 0) {
|
||||
#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL
|
||||
printf("crypto\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
307
ccan/ccan/crypto/sha256/sha256.c
Normal file
307
ccan/ccan/crypto/sha256/sha256.c
Normal file
@ -0,0 +1,307 @@
|
||||
/* MIT (BSD) license - see LICENSE file for details */
|
||||
/* SHA256 core code translated from the Bitcoin project's C++:
|
||||
*
|
||||
* src/crypto/sha256.cpp commit 417532c8acb93c36c2b6fd052b7c11b6a2906aa2
|
||||
* Copyright (c) 2014 The Bitcoin Core developers
|
||||
* Distributed under the MIT software license, see the accompanying
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
*/
|
||||
#include <ccan/crypto/sha256/sha256.h>
|
||||
#include <ccan/endian/endian.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
static void invalidate_sha256(struct sha256_ctx *ctx)
|
||||
{
|
||||
#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL
|
||||
ctx->c.md_len = 0;
|
||||
#else
|
||||
ctx->bytes = -1ULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void check_sha256(struct sha256_ctx *ctx)
|
||||
{
|
||||
#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL
|
||||
assert(ctx->c.md_len != 0);
|
||||
#else
|
||||
assert(ctx->bytes != -1ULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL
|
||||
void sha256_init(struct sha256_ctx *ctx)
|
||||
{
|
||||
SHA256_Init(&ctx->c);
|
||||
}
|
||||
|
||||
void sha256_update_bytes(struct sha256_ctx *ctx, const void *p, size_t size)
|
||||
{
|
||||
check_sha256(ctx);
|
||||
SHA256_Update(&ctx->c, p, size);
|
||||
}
|
||||
|
||||
void sha256_done(struct sha256_ctx *ctx, struct sha256 *res)
|
||||
{
|
||||
SHA256_Final(res->u.u8, &ctx->c);
|
||||
invalidate_sha256(ctx);
|
||||
}
|
||||
#else
|
||||
static uint32_t Ch(uint32_t x, uint32_t y, uint32_t z)
|
||||
{
|
||||
return z ^ (x & (y ^ z));
|
||||
}
|
||||
static uint32_t Maj(uint32_t x, uint32_t y, uint32_t z)
|
||||
{
|
||||
return (x & y) | (z & (x | y));
|
||||
}
|
||||
static uint32_t Sigma0(uint32_t x)
|
||||
{
|
||||
return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10);
|
||||
}
|
||||
static uint32_t Sigma1(uint32_t x)
|
||||
{
|
||||
return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7);
|
||||
}
|
||||
static uint32_t sigma0(uint32_t x)
|
||||
{
|
||||
return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3);
|
||||
}
|
||||
static uint32_t sigma1(uint32_t x)
|
||||
{
|
||||
return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10);
|
||||
}
|
||||
|
||||
/** One round of SHA-256. */
|
||||
static void Round(uint32_t a, uint32_t b, uint32_t c, uint32_t *d, uint32_t e, uint32_t f, uint32_t g, uint32_t *h, uint32_t k, uint32_t w)
|
||||
{
|
||||
uint32_t t1 = *h + Sigma1(e) + Ch(e, f, g) + k + w;
|
||||
uint32_t t2 = Sigma0(a) + Maj(a, b, c);
|
||||
*d += t1;
|
||||
*h = t1 + t2;
|
||||
}
|
||||
|
||||
/** Perform one SHA-256 transformation, processing a 64-byte chunk. */
|
||||
static void Transform(uint32_t *s, const uint32_t *chunk)
|
||||
{
|
||||
uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7];
|
||||
uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
|
||||
|
||||
Round(a, b, c, &d, e, f, g, &h, 0x428a2f98, w0 = be32_to_cpu(chunk[0]));
|
||||
Round(h, a, b, &c, d, e, f, &g, 0x71374491, w1 = be32_to_cpu(chunk[1]));
|
||||
Round(g, h, a, &b, c, d, e, &f, 0xb5c0fbcf, w2 = be32_to_cpu(chunk[2]));
|
||||
Round(f, g, h, &a, b, c, d, &e, 0xe9b5dba5, w3 = be32_to_cpu(chunk[3]));
|
||||
Round(e, f, g, &h, a, b, c, &d, 0x3956c25b, w4 = be32_to_cpu(chunk[4]));
|
||||
Round(d, e, f, &g, h, a, b, &c, 0x59f111f1, w5 = be32_to_cpu(chunk[5]));
|
||||
Round(c, d, e, &f, g, h, a, &b, 0x923f82a4, w6 = be32_to_cpu(chunk[6]));
|
||||
Round(b, c, d, &e, f, g, h, &a, 0xab1c5ed5, w7 = be32_to_cpu(chunk[7]));
|
||||
Round(a, b, c, &d, e, f, g, &h, 0xd807aa98, w8 = be32_to_cpu(chunk[8]));
|
||||
Round(h, a, b, &c, d, e, f, &g, 0x12835b01, w9 = be32_to_cpu(chunk[9]));
|
||||
Round(g, h, a, &b, c, d, e, &f, 0x243185be, w10 = be32_to_cpu(chunk[10]));
|
||||
Round(f, g, h, &a, b, c, d, &e, 0x550c7dc3, w11 = be32_to_cpu(chunk[11]));
|
||||
Round(e, f, g, &h, a, b, c, &d, 0x72be5d74, w12 = be32_to_cpu(chunk[12]));
|
||||
Round(d, e, f, &g, h, a, b, &c, 0x80deb1fe, w13 = be32_to_cpu(chunk[13]));
|
||||
Round(c, d, e, &f, g, h, a, &b, 0x9bdc06a7, w14 = be32_to_cpu(chunk[14]));
|
||||
Round(b, c, d, &e, f, g, h, &a, 0xc19bf174, w15 = be32_to_cpu(chunk[15]));
|
||||
|
||||
Round(a, b, c, &d, e, f, g, &h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
|
||||
Round(h, a, b, &c, d, e, f, &g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
|
||||
Round(g, h, a, &b, c, d, e, &f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3));
|
||||
Round(f, g, h, &a, b, c, d, &e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4));
|
||||
Round(e, f, g, &h, a, b, c, &d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5));
|
||||
Round(d, e, f, &g, h, a, b, &c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6));
|
||||
Round(c, d, e, &f, g, h, a, &b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7));
|
||||
Round(b, c, d, &e, f, g, h, &a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8));
|
||||
Round(a, b, c, &d, e, f, g, &h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9));
|
||||
Round(h, a, b, &c, d, e, f, &g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10));
|
||||
Round(g, h, a, &b, c, d, e, &f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11));
|
||||
Round(f, g, h, &a, b, c, d, &e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12));
|
||||
Round(e, f, g, &h, a, b, c, &d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13));
|
||||
Round(d, e, f, &g, h, a, b, &c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14));
|
||||
Round(c, d, e, &f, g, h, a, &b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15));
|
||||
Round(b, c, d, &e, f, g, h, &a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0));
|
||||
|
||||
Round(a, b, c, &d, e, f, g, &h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1));
|
||||
Round(h, a, b, &c, d, e, f, &g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2));
|
||||
Round(g, h, a, &b, c, d, e, &f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3));
|
||||
Round(f, g, h, &a, b, c, d, &e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4));
|
||||
Round(e, f, g, &h, a, b, c, &d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5));
|
||||
Round(d, e, f, &g, h, a, b, &c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6));
|
||||
Round(c, d, e, &f, g, h, a, &b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7));
|
||||
Round(b, c, d, &e, f, g, h, &a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8));
|
||||
Round(a, b, c, &d, e, f, g, &h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9));
|
||||
Round(h, a, b, &c, d, e, f, &g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10));
|
||||
Round(g, h, a, &b, c, d, e, &f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11));
|
||||
Round(f, g, h, &a, b, c, d, &e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12));
|
||||
Round(e, f, g, &h, a, b, c, &d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13));
|
||||
Round(d, e, f, &g, h, a, b, &c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14));
|
||||
Round(c, d, e, &f, g, h, a, &b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15));
|
||||
Round(b, c, d, &e, f, g, h, &a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0));
|
||||
|
||||
Round(a, b, c, &d, e, f, g, &h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1));
|
||||
Round(h, a, b, &c, d, e, f, &g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2));
|
||||
Round(g, h, a, &b, c, d, e, &f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3));
|
||||
Round(f, g, h, &a, b, c, d, &e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4));
|
||||
Round(e, f, g, &h, a, b, c, &d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5));
|
||||
Round(d, e, f, &g, h, a, b, &c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6));
|
||||
Round(c, d, e, &f, g, h, a, &b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7));
|
||||
Round(b, c, d, &e, f, g, h, &a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8));
|
||||
Round(a, b, c, &d, e, f, g, &h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9));
|
||||
Round(h, a, b, &c, d, e, f, &g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10));
|
||||
Round(g, h, a, &b, c, d, e, &f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11));
|
||||
Round(f, g, h, &a, b, c, d, &e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12));
|
||||
Round(e, f, g, &h, a, b, c, &d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13));
|
||||
Round(d, e, f, &g, h, a, b, &c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14));
|
||||
Round(c, d, e, &f, g, h, a, &b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15));
|
||||
Round(b, c, d, &e, f, g, h, &a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0));
|
||||
|
||||
s[0] += a;
|
||||
s[1] += b;
|
||||
s[2] += c;
|
||||
s[3] += d;
|
||||
s[4] += e;
|
||||
s[5] += f;
|
||||
s[6] += g;
|
||||
s[7] += h;
|
||||
}
|
||||
|
||||
static bool alignment_ok(const void *p, size_t n)
|
||||
{
|
||||
#if HAVE_UNALIGNED_ACCESS
|
||||
return true;
|
||||
#else
|
||||
return ((size_t)p % n == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void add(struct sha256_ctx *ctx, const void *p, size_t len)
|
||||
{
|
||||
const unsigned char *data = p;
|
||||
size_t bufsize = ctx->bytes % 64;
|
||||
|
||||
if (bufsize + len >= 64) {
|
||||
// Fill the buffer, and process it.
|
||||
memcpy(ctx->buf.u8 + bufsize, data, 64 - bufsize);
|
||||
ctx->bytes += 64 - bufsize;
|
||||
data += 64 - bufsize;
|
||||
len -= 64 - bufsize;
|
||||
Transform(ctx->s, ctx->buf.u32);
|
||||
bufsize = 0;
|
||||
}
|
||||
|
||||
while (len >= 64) {
|
||||
// Process full chunks directly from the source.
|
||||
if (alignment_ok(data, sizeof(uint32_t)))
|
||||
Transform(ctx->s, (const uint32_t *)data);
|
||||
else {
|
||||
memcpy(ctx->buf.u8, data, sizeof(ctx->buf));
|
||||
Transform(ctx->s, ctx->buf.u32);
|
||||
}
|
||||
ctx->bytes += 64;
|
||||
data += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
// Fill the buffer with what remains.
|
||||
memcpy(ctx->buf.u8 + bufsize, data, len);
|
||||
ctx->bytes += len;
|
||||
}
|
||||
}
|
||||
|
||||
void sha256_init(struct sha256_ctx *ctx)
|
||||
{
|
||||
struct sha256_ctx init = SHA256_INIT;
|
||||
*ctx = init;
|
||||
}
|
||||
|
||||
void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size)
|
||||
{
|
||||
check_sha256(ctx);
|
||||
add(ctx, p, size);
|
||||
}
|
||||
|
||||
void sha256_done(struct sha256_ctx *ctx, struct sha256 *res)
|
||||
{
|
||||
static const unsigned char pad[64] = {0x80};
|
||||
uint64_t sizedesc;
|
||||
size_t i;
|
||||
|
||||
sizedesc = cpu_to_be64(ctx->bytes << 3);
|
||||
/* Add '1' bit to terminate, then all 0 bits, up to next block - 8. */
|
||||
add(ctx, pad, 1 + ((119 - (ctx->bytes % 64)) % 64));
|
||||
/* Add number of bits of data (big endian) */
|
||||
add(ctx, &sizedesc, 8);
|
||||
for (i = 0; i < sizeof(ctx->s) / sizeof(ctx->s[0]); i++)
|
||||
res->u.u32[i] = cpu_to_be32(ctx->s[i]);
|
||||
invalidate_sha256(ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
void sha256(struct sha256 *sha, const void *p, size_t size)
|
||||
{
|
||||
struct sha256_ctx ctx;
|
||||
|
||||
sha256_init(&ctx);
|
||||
sha256_update(&ctx, p, size);
|
||||
sha256_done(&ctx, sha);
|
||||
}
|
||||
|
||||
void sha256_u8(struct sha256_ctx *ctx, uint8_t v)
|
||||
{
|
||||
sha256_update(ctx, &v, sizeof(v));
|
||||
}
|
||||
|
||||
void sha256_u16(struct sha256_ctx *ctx, uint16_t v)
|
||||
{
|
||||
sha256_update(ctx, &v, sizeof(v));
|
||||
}
|
||||
|
||||
void sha256_u32(struct sha256_ctx *ctx, uint32_t v)
|
||||
{
|
||||
sha256_update(ctx, &v, sizeof(v));
|
||||
}
|
||||
|
||||
void sha256_u64(struct sha256_ctx *ctx, uint64_t v)
|
||||
{
|
||||
sha256_update(ctx, &v, sizeof(v));
|
||||
}
|
||||
|
||||
/* Add as little-endian */
|
||||
void sha256_le16(struct sha256_ctx *ctx, uint16_t v)
|
||||
{
|
||||
leint16_t lev = cpu_to_le16(v);
|
||||
sha256_update(ctx, &lev, sizeof(lev));
|
||||
}
|
||||
|
||||
void sha256_le32(struct sha256_ctx *ctx, uint32_t v)
|
||||
{
|
||||
leint32_t lev = cpu_to_le32(v);
|
||||
sha256_update(ctx, &lev, sizeof(lev));
|
||||
}
|
||||
|
||||
void sha256_le64(struct sha256_ctx *ctx, uint64_t v)
|
||||
{
|
||||
leint64_t lev = cpu_to_le64(v);
|
||||
sha256_update(ctx, &lev, sizeof(lev));
|
||||
}
|
||||
|
||||
/* Add as big-endian */
|
||||
void sha256_be16(struct sha256_ctx *ctx, uint16_t v)
|
||||
{
|
||||
beint16_t bev = cpu_to_be16(v);
|
||||
sha256_update(ctx, &bev, sizeof(bev));
|
||||
}
|
||||
|
||||
void sha256_be32(struct sha256_ctx *ctx, uint32_t v)
|
||||
{
|
||||
beint32_t bev = cpu_to_be32(v);
|
||||
sha256_update(ctx, &bev, sizeof(bev));
|
||||
}
|
||||
|
||||
void sha256_be64(struct sha256_ctx *ctx, uint64_t v)
|
||||
{
|
||||
beint64_t bev = cpu_to_be64(v);
|
||||
sha256_update(ctx, &bev, sizeof(bev));
|
||||
}
|
148
ccan/ccan/crypto/sha256/sha256.h
Normal file
148
ccan/ccan/crypto/sha256/sha256.h
Normal file
@ -0,0 +1,148 @@
|
||||
#ifndef CCAN_CRYPTO_SHA256_H
|
||||
#define CCAN_CRYPTO_SHA256_H
|
||||
/* BSD-MIT - see LICENSE file for details */
|
||||
#include "config.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Uncomment this to use openssl's SHA256 routines (and link with -lcrypto) */
|
||||
//#define CCAN_CRYPTO_SHA256_USE_OPENSSL 1
|
||||
|
||||
#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL
|
||||
#include <openssl/sha.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct sha256 - structure representing a completed SHA256.
|
||||
* @u.u8: an unsigned char array.
|
||||
* @u.u32: a 32-bit integer array.
|
||||
*
|
||||
* Other fields may be added to the union in future.
|
||||
*/
|
||||
struct sha256 {
|
||||
union {
|
||||
/* Array of chars */
|
||||
unsigned char u8[32];
|
||||
/* Array of uint32_t */
|
||||
uint32_t u32[8];
|
||||
} u;
|
||||
};
|
||||
|
||||
/**
|
||||
* sha256 - return sha256 of an object.
|
||||
* @sha256: the sha256 to fill in
|
||||
* @p: pointer to memory,
|
||||
* @size: the number of bytes pointed to by @p
|
||||
*
|
||||
* The bytes pointed to by @p is SHA256 hashed into @sha256. This is
|
||||
* equivalent to sha256_init(), sha256_update() then sha256_done().
|
||||
*/
|
||||
void sha256(struct sha256 *sha, const void *p, size_t size);
|
||||
|
||||
/**
|
||||
* struct sha256_ctx - structure to store running context for sha256
|
||||
*/
|
||||
struct sha256_ctx {
|
||||
#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL
|
||||
SHA256_CTX c;
|
||||
#else
|
||||
uint32_t s[8];
|
||||
uint64_t bytes;
|
||||
union {
|
||||
uint32_t u32[8];
|
||||
unsigned char u8[64];
|
||||
} buf;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* sha256_init - initialize an SHA256 context.
|
||||
* @ctx: the sha256_ctx to initialize
|
||||
*
|
||||
* This must be called before sha256_update or sha256_done, or
|
||||
* alternately you can assign SHA256_INIT.
|
||||
*
|
||||
* If it was already initialized, this forgets anything which was
|
||||
* hashed before.
|
||||
*
|
||||
* Example:
|
||||
* static void hash_all(const char **arr, struct sha256 *hash)
|
||||
* {
|
||||
* size_t i;
|
||||
* struct sha256_ctx ctx;
|
||||
*
|
||||
* sha256_init(&ctx);
|
||||
* for (i = 0; arr[i]; i++)
|
||||
* sha256_update(&ctx, arr[i], strlen(arr[i]));
|
||||
* sha256_done(&ctx, hash);
|
||||
* }
|
||||
*/
|
||||
void sha256_init(struct sha256_ctx *ctx);
|
||||
|
||||
/**
|
||||
* SHA256_INIT - initializer for an SHA256 context.
|
||||
*
|
||||
* This can be used to staticly initialize an SHA256 context (instead
|
||||
* of sha256_init()).
|
||||
*
|
||||
* Example:
|
||||
* static void hash_all(const char **arr, struct sha256 *hash)
|
||||
* {
|
||||
* size_t i;
|
||||
* struct sha256_ctx ctx = SHA256_INIT;
|
||||
*
|
||||
* for (i = 0; arr[i]; i++)
|
||||
* sha256_update(&ctx, arr[i], strlen(arr[i]));
|
||||
* sha256_done(&ctx, hash);
|
||||
* }
|
||||
*/
|
||||
#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL
|
||||
#define SHA256_INIT \
|
||||
{ { { 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, \
|
||||
0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul }, \
|
||||
0x0, 0x0, \
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \
|
||||
0x0, 0x20 } }
|
||||
#else
|
||||
#define SHA256_INIT \
|
||||
{ { 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, \
|
||||
0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul }, 0 }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* sha256_update - include some memory in the hash.
|
||||
* @ctx: the sha256_ctx to use
|
||||
* @p: pointer to memory,
|
||||
* @size: the number of bytes pointed to by @p
|
||||
*
|
||||
* You can call this multiple times to hash more data, before calling
|
||||
* sha256_done().
|
||||
*/
|
||||
void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size);
|
||||
|
||||
/**
|
||||
* sha256_done - finish SHA256 and return the hash
|
||||
* @ctx: the sha256_ctx to complete
|
||||
* @res: the hash to return.
|
||||
*
|
||||
* Note that @ctx is *destroyed* by this, and must be reinitialized.
|
||||
* To avoid that, pass a copy instead.
|
||||
*/
|
||||
void sha256_done(struct sha256_ctx *sha256, struct sha256 *res);
|
||||
|
||||
/* Add various types to an SHA256 hash */
|
||||
void sha256_u8(struct sha256_ctx *ctx, uint8_t v);
|
||||
void sha256_u16(struct sha256_ctx *ctx, uint16_t v);
|
||||
void sha256_u32(struct sha256_ctx *ctx, uint32_t v);
|
||||
void sha256_u64(struct sha256_ctx *ctx, uint64_t v);
|
||||
|
||||
/* Add as little-endian */
|
||||
void sha256_le16(struct sha256_ctx *ctx, uint16_t v);
|
||||
void sha256_le32(struct sha256_ctx *ctx, uint32_t v);
|
||||
void sha256_le64(struct sha256_ctx *ctx, uint64_t v);
|
||||
|
||||
/* Add as big-endian */
|
||||
void sha256_be16(struct sha256_ctx *ctx, uint16_t v);
|
||||
void sha256_be32(struct sha256_ctx *ctx, uint32_t v);
|
||||
void sha256_be64(struct sha256_ctx *ctx, uint64_t v);
|
||||
#endif /* CCAN_CRYPTO_SHA256_H */
|
54
ccan/ccan/crypto/sha256/test/run-33-bit-test.c
Normal file
54
ccan/ccan/crypto/sha256/test/run-33-bit-test.c
Normal file
@ -0,0 +1,54 @@
|
||||
#include <ccan/crypto/sha256/sha256.h>
|
||||
/* Include the C files directly. */
|
||||
#include <ccan/crypto/sha256/sha256.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* This is the test introduced for SHA-3, which checks for 33-bit overflow:
|
||||
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"
|
||||
16777216 times.
|
||||
*/
|
||||
static uint32_t expected[] = {
|
||||
CPU_TO_BE32(0x50e72a0e), CPU_TO_BE32(0x26442fe2),
|
||||
CPU_TO_BE32(0x552dc393), CPU_TO_BE32(0x8ac58658),
|
||||
CPU_TO_BE32(0x228c0cbf), CPU_TO_BE32(0xb1d2ca87),
|
||||
CPU_TO_BE32(0x2ae43526), CPU_TO_BE32(0x6fcd055e)
|
||||
};
|
||||
|
||||
/* Produced by actually running the code on x86. */
|
||||
static const struct sha256_ctx after_16M_by_64 = {
|
||||
#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL
|
||||
{ { LE32_TO_CPU(0x515e3215), LE32_TO_CPU(0x592f4ae0),
|
||||
LE32_TO_CPU(0xd407a8fc), LE32_TO_CPU(0x1fad409b),
|
||||
LE32_TO_CPU(0x51fa46cc), LE32_TO_CPU(0xea528ae5),
|
||||
LE32_TO_CPU(0x5fa58ebb), LE32_TO_CPU(0x8be97931) },
|
||||
0x0, 0x2,
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
0x0, 0x20 }
|
||||
#else
|
||||
{ LE32_TO_CPU(0x515e3215), LE32_TO_CPU(0x592f4ae0),
|
||||
LE32_TO_CPU(0xd407a8fc), LE32_TO_CPU(0x1fad409b),
|
||||
LE32_TO_CPU(0x51fa46cc), LE32_TO_CPU(0xea528ae5),
|
||||
LE32_TO_CPU(0x5fa58ebb), LE32_TO_CPU(0x8be97931) },
|
||||
1073741824,
|
||||
{ .u32 = { 0x64636261, 0x68676665, 0x65646362, 0x69686766,
|
||||
0x66656463, 0x6a696867, 0x67666564, 0x6b6a6968 } }
|
||||
#endif
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct sha256 h;
|
||||
struct sha256_ctx ctx;
|
||||
|
||||
/* This is how many tests you plan to run */
|
||||
plan_tests(1);
|
||||
|
||||
ctx = after_16M_by_64;
|
||||
sha256_done(&ctx, &h);
|
||||
|
||||
ok1(memcmp(&h.u, expected, sizeof(expected)) == 0);
|
||||
|
||||
/* This exits depending on whether all tests passed */
|
||||
return exit_status();
|
||||
}
|
23
ccan/ccan/crypto/sha256/test/run-lotsa-data.c
Normal file
23
ccan/ccan/crypto/sha256/test/run-lotsa-data.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include <ccan/crypto/sha256/sha256.h>
|
||||
/* Include the C files directly. */
|
||||
#include <ccan/crypto/sha256/sha256.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct sha256 h, expected;
|
||||
static const char zeroes[1000];
|
||||
size_t i;
|
||||
|
||||
plan_tests(63);
|
||||
|
||||
/* Test different alignments. */
|
||||
sha256(&expected, zeroes, sizeof(zeroes) - 64);
|
||||
for (i = 1; i < 64; i++) {
|
||||
sha256(&h, zeroes + i, sizeof(zeroes) - 64);
|
||||
ok1(memcmp(&h, &expected, sizeof(h)) == 0);
|
||||
}
|
||||
|
||||
/* This exits depending on whether all tests passed */
|
||||
return exit_status();
|
||||
}
|
83
ccan/ccan/crypto/sha256/test/run-test-vectors.c
Normal file
83
ccan/ccan/crypto/sha256/test/run-test-vectors.c
Normal file
@ -0,0 +1,83 @@
|
||||
#include <ccan/crypto/sha256/sha256.h>
|
||||
/* Include the C files directly. */
|
||||
#include <ccan/crypto/sha256/sha256.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
/* Test vectors. */
|
||||
struct test {
|
||||
const char *test;
|
||||
size_t repetitions;
|
||||
beint32_t result[8];
|
||||
};
|
||||
|
||||
static struct test tests[] = {
|
||||
{ "", 1,
|
||||
{ CPU_TO_BE32(0xe3b0c442), CPU_TO_BE32(0x98fc1c14),
|
||||
CPU_TO_BE32(0x9afbf4c8), CPU_TO_BE32(0x996fb924),
|
||||
CPU_TO_BE32(0x27ae41e4), CPU_TO_BE32(0x649b934c),
|
||||
CPU_TO_BE32(0xa495991b), CPU_TO_BE32(0x7852b855) } },
|
||||
{ "abc", 1,
|
||||
{ CPU_TO_BE32(0xba7816bf), CPU_TO_BE32(0x8f01cfea),
|
||||
CPU_TO_BE32(0x414140de), CPU_TO_BE32(0x5dae2223),
|
||||
CPU_TO_BE32(0xb00361a3), CPU_TO_BE32(0x96177a9c),
|
||||
CPU_TO_BE32(0xb410ff61), CPU_TO_BE32(0xf20015ad) } },
|
||||
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1,
|
||||
{ CPU_TO_BE32(0x248d6a61), CPU_TO_BE32(0xd20638b8),
|
||||
CPU_TO_BE32(0xe5c02693), CPU_TO_BE32(0x0c3e6039),
|
||||
CPU_TO_BE32(0xa33ce459), CPU_TO_BE32(0x64ff2167),
|
||||
CPU_TO_BE32(0xf6ecedd4), CPU_TO_BE32(0x19db06c1) } },
|
||||
{ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 1,
|
||||
{ CPU_TO_BE32(0xcf5b16a7), CPU_TO_BE32(0x78af8380),
|
||||
CPU_TO_BE32(0x036ce59e), CPU_TO_BE32(0x7b049237),
|
||||
CPU_TO_BE32(0x0b249b11), CPU_TO_BE32(0xe8f07a51),
|
||||
CPU_TO_BE32(0xafac4503), CPU_TO_BE32(0x7afee9d1) } },
|
||||
{ "a", 1000000,
|
||||
{ CPU_TO_BE32(0xcdc76e5c), CPU_TO_BE32(0x9914fb92),
|
||||
CPU_TO_BE32(0x81a1c7e2), CPU_TO_BE32(0x84d73e67),
|
||||
CPU_TO_BE32(0xf1809a48), CPU_TO_BE32(0xa497200e),
|
||||
CPU_TO_BE32(0x046d39cc), CPU_TO_BE32(0xc7112cd0) } }
|
||||
#if 0 /* Good test, but takes ages! */
|
||||
, { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno", 16777216,
|
||||
{ CPU_TO_BE32(0x50e72a0e), CPU_TO_BE32(0x26442fe2),
|
||||
CPU_TO_BE32(0x552dc393), CPU_TO_BE32(0x8ac58658),
|
||||
CPU_TO_BE32(0x228c0cbf), CPU_TO_BE32(0xb1d2ca87),
|
||||
CPU_TO_BE32(0x2ae43526), CPU_TO_BE32(0x6fcd055e) } }
|
||||
#endif
|
||||
};
|
||||
|
||||
static bool do_test(const struct test *t, bool single)
|
||||
{
|
||||
struct sha256 h;
|
||||
|
||||
if (single) {
|
||||
if (t->repetitions != 1)
|
||||
return true;
|
||||
sha256(&h, t->test, strlen(t->test));
|
||||
} else {
|
||||
struct sha256_ctx ctx = SHA256_INIT;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < t->repetitions; i++)
|
||||
sha256_update(&ctx, t->test, strlen(t->test));
|
||||
sha256_done(&ctx, &h);
|
||||
}
|
||||
|
||||
return memcmp(&h.u, t->result, sizeof(t->result)) == 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* This is how many tests you plan to run */
|
||||
plan_tests(sizeof(tests) / sizeof(struct test) * 2);
|
||||
|
||||
for (i = 0; i < sizeof(tests) / sizeof(struct test); i++)
|
||||
ok1(do_test(&tests[i], false));
|
||||
|
||||
for (i = 0; i < sizeof(tests) / sizeof(struct test); i++)
|
||||
ok1(do_test(&tests[i], true));
|
||||
|
||||
/* This exits depending on whether all tests passed */
|
||||
return exit_status();
|
||||
}
|
63
ccan/ccan/crypto/sha256/test/run-types.c
Normal file
63
ccan/ccan/crypto/sha256/test/run-types.c
Normal file
@ -0,0 +1,63 @@
|
||||
#include <ccan/crypto/sha256/sha256.h>
|
||||
/* Include the C files directly. */
|
||||
#include <ccan/crypto/sha256/sha256.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
static unsigned char arr[] = {
|
||||
0x12,
|
||||
#if HAVE_BIG_ENDIAN
|
||||
/* u16 */
|
||||
0x12, 0x34,
|
||||
/* u32 */
|
||||
0x12, 0x34, 0x56, 0x78,
|
||||
/* u64 */
|
||||
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
|
||||
#else
|
||||
/* u16 */
|
||||
0x34, 0x12,
|
||||
/* u32 */
|
||||
0x78, 0x56, 0x34, 0x12,
|
||||
/* u64 */
|
||||
0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
|
||||
#endif
|
||||
/* le16 */
|
||||
0x34, 0x12,
|
||||
/* le32 */
|
||||
0x78, 0x56, 0x34, 0x12,
|
||||
/* le64 */
|
||||
0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
|
||||
/* be16 */
|
||||
0x12, 0x34,
|
||||
/* be32 */
|
||||
0x12, 0x34, 0x56, 0x78,
|
||||
/* be64 */
|
||||
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct sha256 h, expected;
|
||||
struct sha256_ctx ctx;
|
||||
|
||||
/* This is how many tests you plan to run */
|
||||
plan_tests(1);
|
||||
|
||||
sha256_init(&ctx);
|
||||
sha256_u8(&ctx, 0x12);
|
||||
sha256_u16(&ctx, 0x1234);
|
||||
sha256_u32(&ctx, 0x12345678);
|
||||
sha256_u64(&ctx, 0x123456789abcdef0ULL);
|
||||
sha256_le16(&ctx, 0x1234);
|
||||
sha256_le32(&ctx, 0x12345678);
|
||||
sha256_le64(&ctx, 0x123456789abcdef0ULL);
|
||||
sha256_be16(&ctx, 0x1234);
|
||||
sha256_be32(&ctx, 0x12345678);
|
||||
sha256_be64(&ctx, 0x123456789abcdef0ULL);
|
||||
sha256_done(&ctx, &h);
|
||||
|
||||
sha256(&expected, arr, sizeof(arr));
|
||||
ok1(memcmp(&h, &expected, sizeof(h)) == 0);
|
||||
|
||||
/* This exits depending on whether all tests passed */
|
||||
return exit_status();
|
||||
}
|
1
ccan/ccan/crypto/shachain/LICENSE
Symbolic link
1
ccan/ccan/crypto/shachain/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../../licenses/BSD-MIT
|
59
ccan/ccan/crypto/shachain/_info
Normal file
59
ccan/ccan/crypto/shachain/_info
Normal file
@ -0,0 +1,59 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* crypto/shachain - compactly-representable chain of 256-bit numbers.
|
||||
*
|
||||
* This code produces a practically infinite (2^64) chain of 256-bit numbers
|
||||
* from a single number, such that you can't derive element N from any element
|
||||
* less than N, but can efficiently derive element N from a limited number
|
||||
* of elements >= N.
|
||||
*
|
||||
* License: BSD-MIT
|
||||
* Author: Rusty Russell <rusty@rustcorp.com.au>
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* #include <ccan/crypto/shachain/shachain.h>
|
||||
* #include <ccan/err/err.h>
|
||||
* #include <stdio.h>
|
||||
* #include <stdlib.h>
|
||||
* #include <string.h>
|
||||
*
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* size_t i, j, limit = 10;
|
||||
* struct sha256 seed;
|
||||
*
|
||||
* if (argc < 2)
|
||||
* errx(1, "Usage: %s <passphrase> [<num-to-generate>]", argv[0]);
|
||||
* sha256(&seed, argv[1], strlen(argv[1]));
|
||||
* if (argv[2])
|
||||
* limit = atol(argv[2]);
|
||||
*
|
||||
* for (i = 0; i < limit; i++) {
|
||||
* struct sha256 v;
|
||||
* shachain_from_seed(&seed, i, &v);
|
||||
* printf("%zu: ", i);
|
||||
* for (j = 0; j < sizeof(v.u.u8); j++)
|
||||
* printf("%02x", v.u.u8[j]);
|
||||
* printf("\n");
|
||||
* }
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* Expect exactly one argument */
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
printf("ccan/ilog\n");
|
||||
printf("ccan/crypto/sha256\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
114
ccan/ccan/crypto/shachain/design.txt
Normal file
114
ccan/ccan/crypto/shachain/design.txt
Normal file
@ -0,0 +1,114 @@
|
||||
Efficient Chains Of Unpredictable Numbers
|
||||
=========================================
|
||||
|
||||
The Problem
|
||||
-----------
|
||||
|
||||
The Lightning Network wants a chain of (say 1 million) unguessable 256
|
||||
bit values; we generate them and send them one at a time to a remote
|
||||
node. We don't want the remote node to have to store all the values,
|
||||
so it's better if they can derive them once they see them.
|
||||
|
||||
A Simple Solution
|
||||
-----------------
|
||||
|
||||
A simple system is a hash chain: we select a random seed value, the
|
||||
hash it 1,000,000 times. This gives the first "random" number.
|
||||
Hashed 999,999 times gives the second number, etc. ie:
|
||||
|
||||
R(1,000,000) = seed
|
||||
R(N-1) = SHA256(R(N))
|
||||
|
||||
This way the remote node needs only to remember the last R(N) it was
|
||||
given, and it can calculate any R for N-1 or below.
|
||||
|
||||
However, this means we need to generate 1 million hashes up front, and
|
||||
then do almost as many hashes to derive the next number. That's slow.
|
||||
|
||||
A More Complex Solution
|
||||
-----------------------
|
||||
|
||||
Instead of a one-dimensional chain, we can use two dimensions: 1000
|
||||
chains of 1000 values each. Indeed, we can set generate the "top" of
|
||||
each chain much like we generated a single chain:
|
||||
|
||||
Chain 1000 Chain 999 Chain 998 ...........Chain 1
|
||||
seed SHA256(C1000) SHA256(C999) ....... SHA256(C2)
|
||||
|
||||
Now, deriving chain 1000 from seed doesn't quite work, because it'll
|
||||
look like this chain, so we flip the lower bit to generate the chain:
|
||||
|
||||
Chain 1000 Chain 999 Chain 998 ...........Chain 1
|
||||
1000 seed^1 SHA256(C1000)^1 SHA256(C999)^1...... SHA256(C2)^1
|
||||
999 SHA256(above) SHA256(above) SHA256(above) ..... SHA256(above)
|
||||
998 SHA256(above) SHA256(above) SHA256(above) ..... SHA256(above)
|
||||
...
|
||||
|
||||
Now, we can get the first value to give out (chain 1, position 1) with
|
||||
999 hashes to get to chain 1, and 999 hashes to get to the end of the
|
||||
chain. 2000 hashes is much better than the 999,999 hashes it would
|
||||
have taken previously.
|
||||
|
||||
Why Stop at 2 Dimensions?
|
||||
-------------------------
|
||||
|
||||
Indeed, the implementation uses 64 dimensions rather than 2, and a
|
||||
chain length of 2 rather than 1000, giving a worst-case of 63 hashes
|
||||
to derive any of 2^64 values. Each dimension flips a different bit of
|
||||
the hash, to ensure the chains are distinct.
|
||||
|
||||
For simplicity, I'll explain what this looks like using 8 dimensions,
|
||||
ie. 8 bits. The seed value always sits the maximum possible index, in
|
||||
this case index 0xFF (b11111111).
|
||||
|
||||
To generate the hash for 0xFE (b11111110), we need to move down
|
||||
dimension 0, so we flip bit 0 of the seed value, then hash it. To
|
||||
generate the hash for 0xFD (b11111101) we need to move down dimension
|
||||
1, so we flip bit 1 of the seed value, then hash it.
|
||||
|
||||
To reach 0xFC (b11111100) we need to move down dimension 1 then
|
||||
dimension 0, in that order.
|
||||
|
||||
Spotting the pattern, it becomes easy to derive how to reach any value:
|
||||
|
||||
hash = seed
|
||||
for bit in 7 6 5 4 3 2 1 0:
|
||||
if bit not set in index:
|
||||
flip(bit) in hash
|
||||
hash = SHA256(hash)
|
||||
|
||||
Handling Partial Knowledge
|
||||
--------------------------
|
||||
|
||||
How does the remote node, which doesn't know the seed value, derive
|
||||
subvalues?
|
||||
|
||||
Once it knows the value for index 1, it can derive the value for index
|
||||
0 by flipping bit 0 of the value and hashing it. In effect, it can
|
||||
always derive a value for any index where it only needs to clear bits.
|
||||
|
||||
So, index 1 gives index 0, but index 2 doesn't yield index 1. When
|
||||
index 3 comes along, it yields 2, 1, and 0.
|
||||
|
||||
How many hash values will we have to remember at once? The answer is
|
||||
equal to the number of dimensions. It turns out that the worst case
|
||||
for 8 dimensions is 254 (0b11111110), for which we will have to
|
||||
remember the following indices:
|
||||
|
||||
127 0b01111111
|
||||
191 0b10111111
|
||||
223 0b11011111
|
||||
239 0b11101111
|
||||
247 0b11110111
|
||||
251 0b11111011
|
||||
253 0b11111101
|
||||
254 0b11111110
|
||||
|
||||
127 lets us derive any hash value for index <= 127. Similarly, 191
|
||||
lets us derive anything > 127 but <= 191. 254 lets us derive only
|
||||
itself.
|
||||
|
||||
When we get index 255 this collapses, and we only need to remember
|
||||
that one index to derive everything.
|
||||
|
||||
Rusty Russell <rusty@rustcorp.com.au>
|
102
ccan/ccan/crypto/shachain/shachain.c
Normal file
102
ccan/ccan/crypto/shachain/shachain.c
Normal file
@ -0,0 +1,102 @@
|
||||
/* MIT (BSD) license - see LICENSE file for details */
|
||||
#include <ccan/crypto/shachain/shachain.h>
|
||||
#include <ccan/ilog/ilog.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
static void change_bit(unsigned char *arr, size_t index)
|
||||
{
|
||||
arr[index / CHAR_BIT] ^= (1 << (index % CHAR_BIT));
|
||||
}
|
||||
|
||||
/* We can only ever *unset* bits, so to must only have bits in from. */
|
||||
static bool can_derive(shachain_index_t from, shachain_index_t to)
|
||||
{
|
||||
return (~from & to) == 0;
|
||||
}
|
||||
|
||||
static void derive(shachain_index_t from, shachain_index_t to,
|
||||
const struct sha256 *from_hash,
|
||||
struct sha256 *hash)
|
||||
{
|
||||
shachain_index_t branches;
|
||||
int i;
|
||||
|
||||
assert(can_derive(from, to));
|
||||
|
||||
/* We start with the first hash. */
|
||||
*hash = *from_hash;
|
||||
|
||||
/* This represents the bits set in from, and not to. */
|
||||
branches = from ^ to;
|
||||
for (i = ilog64(branches) - 1; i >= 0; i--) {
|
||||
if (((branches >> i) & 1)) {
|
||||
change_bit(hash->u.u8, i);
|
||||
sha256(hash, hash, sizeof(*hash));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void shachain_from_seed(const struct sha256 *seed, shachain_index_t index,
|
||||
struct sha256 *hash)
|
||||
{
|
||||
derive((shachain_index_t)-1ULL, index, seed, hash);
|
||||
}
|
||||
|
||||
void shachain_init(struct shachain *chain)
|
||||
{
|
||||
chain->num_valid = 0;
|
||||
chain->max_index = 0;
|
||||
}
|
||||
|
||||
bool shachain_add_hash(struct shachain *chain,
|
||||
shachain_index_t index, const struct sha256 *hash)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* You have to insert them in order! */
|
||||
assert(index == chain->max_index + 1 ||
|
||||
(index == 0 && chain->num_valid == 0));
|
||||
|
||||
for (i = 0; i < chain->num_valid; i++) {
|
||||
/* If we could derive this value, we don't need it,
|
||||
* not any others (since they're in order). */
|
||||
if (can_derive(index, chain->known[i].index)) {
|
||||
struct sha256 expect;
|
||||
|
||||
/* Make sure the others derive as expected! */
|
||||
derive(index, chain->known[i].index, hash, &expect);
|
||||
if (memcmp(&expect, &chain->known[i].hash,
|
||||
sizeof(expect)) != 0)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* This can happen if you skip indices! */
|
||||
assert(i < sizeof(chain->known) / sizeof(chain->known[0]));
|
||||
chain->known[i].index = index;
|
||||
chain->known[i].hash = *hash;
|
||||
chain->num_valid = i+1;
|
||||
chain->max_index = index;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool shachain_get_hash(const struct shachain *chain,
|
||||
shachain_index_t index, struct sha256 *hash)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < chain->num_valid; i++) {
|
||||
/* If we can get from key to index only by resetting bits,
|
||||
* we can derive from it => index has no bits key doesn't. */
|
||||
if (!can_derive(chain->known[i].index, index))
|
||||
continue;
|
||||
|
||||
derive(chain->known[i].index, index, &chain->known[i].hash,
|
||||
hash);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
128
ccan/ccan/crypto/shachain/shachain.h
Normal file
128
ccan/ccan/crypto/shachain/shachain.h
Normal file
@ -0,0 +1,128 @@
|
||||
/* MIT (BSD) license - see LICENSE file for details */
|
||||
#ifndef CCAN_CRYPTO_SHACHAIN_H
|
||||
#define CCAN_CRYPTO_SHACHAIN_H
|
||||
#include "config.h"
|
||||
#include <ccan/crypto/sha256/sha256.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Useful for testing. */
|
||||
#ifndef shachain_index_t
|
||||
#define shachain_index_t uint64_t
|
||||
#endif
|
||||
|
||||
/**
|
||||
* shachain_from_seed - Generate an unpredictable SHA from a seed value.
|
||||
* @seed: (secret) seed value to use
|
||||
* @index: index of value to generate.
|
||||
* @hash: value generated
|
||||
*
|
||||
* There will be no way to derive the result from that generated for
|
||||
* any *lesser* index.
|
||||
*
|
||||
* Example:
|
||||
* #include <time.h>
|
||||
*
|
||||
* static void next_hash(struct sha256 *hash)
|
||||
* {
|
||||
* static uint64_t index = 0;
|
||||
* static struct sha256 seed;
|
||||
*
|
||||
* // First time, initialize seed.
|
||||
* if (index == 0) {
|
||||
* // DO NOT DO THIS! Very predictable!
|
||||
* time_t now = time(NULL);
|
||||
* memcpy(&seed, &now, sizeof(now));
|
||||
* }
|
||||
*
|
||||
* shachain_from_seed(&seed, index++, hash);
|
||||
* }
|
||||
*/
|
||||
void shachain_from_seed(const struct sha256 *seed, shachain_index_t index,
|
||||
struct sha256 *hash);
|
||||
|
||||
/**
|
||||
* shachain - structure for recording/deriving incrementing chain members
|
||||
* @max_index: maximum index value successfully shachain_add_hash()ed.
|
||||
* @num_valid: number of known[] array valid. If non-zero, @max_index valid.
|
||||
* @known: known values to allow us to derive those <= @max_index.
|
||||
*
|
||||
* This is sufficient storage to derive any shachain hash value previously
|
||||
* added.
|
||||
*/
|
||||
struct shachain {
|
||||
shachain_index_t max_index;
|
||||
unsigned int num_valid;
|
||||
struct {
|
||||
shachain_index_t index;
|
||||
struct sha256 hash;
|
||||
} known[sizeof(shachain_index_t) * 8];
|
||||
};
|
||||
|
||||
/**
|
||||
* shachain_init - initialize an shachain
|
||||
* @chain: the chain to initialize
|
||||
*
|
||||
* Alternately, ensure that it's all zero.
|
||||
*/
|
||||
void shachain_init(struct shachain *chain);
|
||||
|
||||
/**
|
||||
* shachain_add_hash - record the hash for the next index.
|
||||
* @chain: the chain to add to
|
||||
* @index: the index of the hash
|
||||
* @hash: the hash value.
|
||||
*
|
||||
* You can only add index 0 (for a freshly initialized chain), or one more
|
||||
* than the previously successfully added value.
|
||||
*
|
||||
* This can fail (return false without altering @chain) if the hash
|
||||
* for this index isn't consistent with previous hashes (ie. wasn't
|
||||
* generated from the same seed), though it can't always detect that.
|
||||
* If the hash is inconsistent yet undetected, the next addition will
|
||||
* fail.
|
||||
*
|
||||
* Example:
|
||||
* static void next_hash(const struct sha256 *hash)
|
||||
* {
|
||||
* static uint64_t index = 0;
|
||||
* static struct shachain chain;
|
||||
*
|
||||
* if (!shachain_add_hash(&chain, index++, hash))
|
||||
* errx(1, "Corrupted hash value?");
|
||||
* }
|
||||
*/
|
||||
bool shachain_add_hash(struct shachain *chain,
|
||||
shachain_index_t index, const struct sha256 *hash);
|
||||
|
||||
/**
|
||||
* shachain_get_hash - get the hash for a given index.
|
||||
* @chain: the chain query
|
||||
* @index: the index of the hash to get
|
||||
* @hash: the hash value.
|
||||
*
|
||||
* This will return true and set @hash to that given in the successful
|
||||
* shachain_get_hash() call for that index. If there was no
|
||||
* successful shachain_get_hash() for that index, it will return
|
||||
* false.
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/structeq/structeq.h>
|
||||
*
|
||||
* static void next_hash(const struct sha256 *hash)
|
||||
* {
|
||||
* static uint64_t index = 0;
|
||||
* static struct shachain chain;
|
||||
*
|
||||
* if (!shachain_add_hash(&chain, index++, hash))
|
||||
* errx(1, "Corrupted hash value?");
|
||||
* else {
|
||||
* struct sha256 check;
|
||||
* assert(shachain_get_hash(&chain, index-1, &check));
|
||||
* assert(structeq(&check, hash));
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
bool shachain_get_hash(const struct shachain *chain,
|
||||
shachain_index_t index, struct sha256 *hash);
|
||||
#endif /* CCAN_CRYPTO_SHACHAIN_H */
|
52
ccan/ccan/crypto/shachain/test/run-8bit.c
Normal file
52
ccan/ccan/crypto/shachain/test/run-8bit.c
Normal file
@ -0,0 +1,52 @@
|
||||
#define shachain_index_t uint8_t
|
||||
|
||||
#include <ccan/crypto/shachain/shachain.h>
|
||||
/* Include the C files directly. */
|
||||
#include <ccan/crypto/shachain/shachain.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define NUM_TESTS 255
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct sha256 seed;
|
||||
struct shachain chain;
|
||||
struct sha256 expect[NUM_TESTS];
|
||||
size_t i, j;
|
||||
|
||||
/* This is how many tests you plan to run */
|
||||
plan_tests(NUM_TESTS * 3 + NUM_TESTS * (NUM_TESTS + 1));
|
||||
|
||||
memset(&seed, 0, sizeof(seed));
|
||||
/* Generate a whole heap. */
|
||||
for (i = 0; i < NUM_TESTS; i++) {
|
||||
shachain_from_seed(&seed, i, &expect[i]);
|
||||
if (i == 0)
|
||||
ok1(memcmp(&expect[i], &seed, sizeof(expect[i])));
|
||||
else
|
||||
ok1(memcmp(&expect[i], &expect[i-1], sizeof(expect[i])));
|
||||
}
|
||||
|
||||
shachain_init(&chain);
|
||||
|
||||
for (i = 0; i < NUM_TESTS; i++) {
|
||||
struct sha256 hash;
|
||||
|
||||
ok1(shachain_add_hash(&chain, i, &expect[i]));
|
||||
for (j = 0; j <= i; j++) {
|
||||
ok1(shachain_get_hash(&chain, j, &hash));
|
||||
ok1(memcmp(&hash, &expect[j], sizeof(hash)) == 0);
|
||||
}
|
||||
ok1(!shachain_get_hash(&chain, i+1, &hash));
|
||||
if (chain.num_valid == 8) {
|
||||
printf("%zu: num_valid %u\n", i, chain.num_valid);
|
||||
for (j = 0; j < 8; j++)
|
||||
printf("chain.known[%zu] = 0x%02x\n",
|
||||
j, chain.known[j].index);
|
||||
}
|
||||
}
|
||||
|
||||
return exit_status();
|
||||
}
|
38
ccan/ccan/crypto/shachain/test/run-badhash.c
Normal file
38
ccan/ccan/crypto/shachain/test/run-badhash.c
Normal file
@ -0,0 +1,38 @@
|
||||
#include <ccan/crypto/shachain/shachain.h>
|
||||
/* Include the C files directly. */
|
||||
#include <ccan/crypto/shachain/shachain.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
#define NUM_TESTS 1000
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct sha256 seed;
|
||||
struct shachain chain;
|
||||
size_t i;
|
||||
|
||||
plan_tests(NUM_TESTS);
|
||||
|
||||
memset(&seed, 0xFF, sizeof(seed));
|
||||
shachain_init(&chain);
|
||||
|
||||
for (i = 0; i < NUM_TESTS; i++) {
|
||||
struct sha256 expect;
|
||||
unsigned int num_known = chain.num_valid;
|
||||
|
||||
shachain_from_seed(&seed, i, &expect);
|
||||
/* Screw it up. */
|
||||
expect.u.u8[0]++;
|
||||
|
||||
/* Either it should fail, or it couldn't derive any others. */
|
||||
if (shachain_add_hash(&chain, i, &expect)) {
|
||||
ok1(chain.num_valid == num_known + 1);
|
||||
/* Fix it up in-place */
|
||||
chain.known[num_known].hash.u.u8[0]--;
|
||||
} else {
|
||||
expect.u.u8[0]--;
|
||||
ok1(shachain_add_hash(&chain, i, &expect));
|
||||
}
|
||||
}
|
||||
return exit_status();
|
||||
}
|
42
ccan/ccan/crypto/shachain/test/run.c
Normal file
42
ccan/ccan/crypto/shachain/test/run.c
Normal file
@ -0,0 +1,42 @@
|
||||
#include <ccan/crypto/shachain/shachain.h>
|
||||
/* Include the C files directly. */
|
||||
#include <ccan/crypto/shachain/shachain.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
#define NUM_TESTS 50
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct sha256 seed;
|
||||
struct shachain chain;
|
||||
struct sha256 expect[NUM_TESTS];
|
||||
size_t i, j;
|
||||
|
||||
/* This is how many tests you plan to run */
|
||||
plan_tests(NUM_TESTS * 3 + NUM_TESTS * (NUM_TESTS + 1));
|
||||
|
||||
memset(&seed, 0, sizeof(seed));
|
||||
/* Generate a whole heap. */
|
||||
for (i = 0; i < NUM_TESTS; i++) {
|
||||
shachain_from_seed(&seed, i, &expect[i]);
|
||||
if (i == 0)
|
||||
ok1(memcmp(&expect[i], &seed, sizeof(expect[i])));
|
||||
else
|
||||
ok1(memcmp(&expect[i], &expect[i-1], sizeof(expect[i])));
|
||||
}
|
||||
|
||||
shachain_init(&chain);
|
||||
|
||||
for (i = 0; i < NUM_TESTS; i++) {
|
||||
struct sha256 hash;
|
||||
|
||||
ok1(shachain_add_hash(&chain, i, &expect[i]));
|
||||
for (j = 0; j <= i; j++) {
|
||||
ok1(shachain_get_hash(&chain, j, &hash));
|
||||
ok1(memcmp(&hash, &expect[j], sizeof(hash)) == 0);
|
||||
}
|
||||
ok1(!shachain_get_hash(&chain, i+1, &hash));
|
||||
}
|
||||
|
||||
return exit_status();
|
||||
}
|
1
ccan/ccan/endian/LICENSE
Symbolic link
1
ccan/ccan/endian/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../licenses/CC0
|
55
ccan/ccan/endian/_info
Normal file
55
ccan/ccan/endian/_info
Normal file
@ -0,0 +1,55 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* endian - endian conversion macros for simple types
|
||||
*
|
||||
* Portable protocols (such as on-disk formats, or network protocols)
|
||||
* are often defined to be a particular endian: little-endian (least
|
||||
* significant bytes first) or big-endian (most significant bytes
|
||||
* first).
|
||||
*
|
||||
* Similarly, some CPUs lay out values in memory in little-endian
|
||||
* order (most commonly, Intel's 8086 and derivatives), or big-endian
|
||||
* order (almost everyone else).
|
||||
*
|
||||
* This module provides conversion routines, inspired by the linux kernel.
|
||||
* It also provides leint32_t, beint32_t etc typedefs, which are annotated for
|
||||
* the sparse checker.
|
||||
*
|
||||
* Example:
|
||||
* #include <stdio.h>
|
||||
* #include <err.h>
|
||||
* #include <ccan/endian/endian.h>
|
||||
*
|
||||
* //
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* uint32_t value;
|
||||
*
|
||||
* if (argc != 2)
|
||||
* errx(1, "Usage: %s <value>", argv[0]);
|
||||
*
|
||||
* value = atoi(argv[1]);
|
||||
* printf("native: %08x\n", value);
|
||||
* printf("little-endian: %08x\n", cpu_to_le32(value));
|
||||
* printf("big-endian: %08x\n", cpu_to_be32(value));
|
||||
* printf("byte-reversed: %08x\n", bswap_32(value));
|
||||
* exit(0);
|
||||
* }
|
||||
*
|
||||
* License: License: CC0 (Public domain)
|
||||
* Author: Rusty Russell <rusty@rustcorp.com.au>
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0)
|
||||
/* Nothing */
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
346
ccan/ccan/endian/endian.h
Normal file
346
ccan/ccan/endian/endian.h
Normal file
@ -0,0 +1,346 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#ifndef CCAN_ENDIAN_H
|
||||
#define CCAN_ENDIAN_H
|
||||
#include <stdint.h>
|
||||
#include "config.h"
|
||||
|
||||
/**
|
||||
* BSWAP_16 - reverse bytes in a constant uint16_t value.
|
||||
* @val: constant value whose bytes to swap.
|
||||
*
|
||||
* Designed to be usable in constant-requiring initializers.
|
||||
*
|
||||
* Example:
|
||||
* struct mystruct {
|
||||
* char buf[BSWAP_16(0x1234)];
|
||||
* };
|
||||
*/
|
||||
#define BSWAP_16(val) \
|
||||
((((uint16_t)(val) & 0x00ff) << 8) \
|
||||
| (((uint16_t)(val) & 0xff00) >> 8))
|
||||
|
||||
/**
|
||||
* BSWAP_32 - reverse bytes in a constant uint32_t value.
|
||||
* @val: constant value whose bytes to swap.
|
||||
*
|
||||
* Designed to be usable in constant-requiring initializers.
|
||||
*
|
||||
* Example:
|
||||
* struct mystruct {
|
||||
* char buf[BSWAP_32(0xff000000)];
|
||||
* };
|
||||
*/
|
||||
#define BSWAP_32(val) \
|
||||
((((uint32_t)(val) & 0x000000ff) << 24) \
|
||||
| (((uint32_t)(val) & 0x0000ff00) << 8) \
|
||||
| (((uint32_t)(val) & 0x00ff0000) >> 8) \
|
||||
| (((uint32_t)(val) & 0xff000000) >> 24))
|
||||
|
||||
/**
|
||||
* BSWAP_64 - reverse bytes in a constant uint64_t value.
|
||||
* @val: constantvalue whose bytes to swap.
|
||||
*
|
||||
* Designed to be usable in constant-requiring initializers.
|
||||
*
|
||||
* Example:
|
||||
* struct mystruct {
|
||||
* char buf[BSWAP_64(0xff00000000000000ULL)];
|
||||
* };
|
||||
*/
|
||||
#define BSWAP_64(val) \
|
||||
((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \
|
||||
| (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \
|
||||
| (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \
|
||||
| (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \
|
||||
| (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \
|
||||
| (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \
|
||||
| (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \
|
||||
| (((uint64_t)(val) & 0xff00000000000000ULL) >> 56))
|
||||
|
||||
#if HAVE_BYTESWAP_H
|
||||
#include <byteswap.h>
|
||||
#else
|
||||
/**
|
||||
* bswap_16 - reverse bytes in a uint16_t value.
|
||||
* @val: value whose bytes to swap.
|
||||
*
|
||||
* Example:
|
||||
* // Output contains "1024 is 4 as two bytes reversed"
|
||||
* printf("1024 is %u as two bytes reversed\n", bswap_16(1024));
|
||||
*/
|
||||
static inline uint16_t bswap_16(uint16_t val)
|
||||
{
|
||||
return BSWAP_16(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* bswap_32 - reverse bytes in a uint32_t value.
|
||||
* @val: value whose bytes to swap.
|
||||
*
|
||||
* Example:
|
||||
* // Output contains "1024 is 262144 as four bytes reversed"
|
||||
* printf("1024 is %u as four bytes reversed\n", bswap_32(1024));
|
||||
*/
|
||||
static inline uint32_t bswap_32(uint32_t val)
|
||||
{
|
||||
return BSWAP_32(val);
|
||||
}
|
||||
#endif /* !HAVE_BYTESWAP_H */
|
||||
|
||||
#if !HAVE_BSWAP_64
|
||||
/**
|
||||
* bswap_64 - reverse bytes in a uint64_t value.
|
||||
* @val: value whose bytes to swap.
|
||||
*
|
||||
* Example:
|
||||
* // Output contains "1024 is 1125899906842624 as eight bytes reversed"
|
||||
* printf("1024 is %llu as eight bytes reversed\n",
|
||||
* (unsigned long long)bswap_64(1024));
|
||||
*/
|
||||
static inline uint64_t bswap_64(uint64_t val)
|
||||
{
|
||||
return BSWAP_64(val);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Sanity check the defines. We don't handle weird endianness. */
|
||||
#if !HAVE_LITTLE_ENDIAN && !HAVE_BIG_ENDIAN
|
||||
#error "Unknown endian"
|
||||
#elif HAVE_LITTLE_ENDIAN && HAVE_BIG_ENDIAN
|
||||
#error "Can't compile for both big and little endian."
|
||||
#endif
|
||||
|
||||
#ifdef __CHECKER__
|
||||
/* sparse needs forcing to remove bitwise attribute from ccan/short_types */
|
||||
#define ENDIAN_CAST __attribute__((force))
|
||||
#define ENDIAN_TYPE __attribute__((bitwise))
|
||||
#else
|
||||
#define ENDIAN_CAST
|
||||
#define ENDIAN_TYPE
|
||||
#endif
|
||||
|
||||
typedef uint64_t ENDIAN_TYPE leint64_t;
|
||||
typedef uint64_t ENDIAN_TYPE beint64_t;
|
||||
typedef uint32_t ENDIAN_TYPE leint32_t;
|
||||
typedef uint32_t ENDIAN_TYPE beint32_t;
|
||||
typedef uint16_t ENDIAN_TYPE leint16_t;
|
||||
typedef uint16_t ENDIAN_TYPE beint16_t;
|
||||
|
||||
#if HAVE_LITTLE_ENDIAN
|
||||
/**
|
||||
* CPU_TO_LE64 - convert a constant uint64_t value to little-endian
|
||||
* @native: constant to convert
|
||||
*/
|
||||
#define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)(native))
|
||||
|
||||
/**
|
||||
* CPU_TO_LE32 - convert a constant uint32_t value to little-endian
|
||||
* @native: constant to convert
|
||||
*/
|
||||
#define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)(native))
|
||||
|
||||
/**
|
||||
* CPU_TO_LE16 - convert a constant uint16_t value to little-endian
|
||||
* @native: constant to convert
|
||||
*/
|
||||
#define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)(native))
|
||||
|
||||
/**
|
||||
* LE64_TO_CPU - convert a little-endian uint64_t constant
|
||||
* @le_val: little-endian constant to convert
|
||||
*/
|
||||
#define LE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val))
|
||||
|
||||
/**
|
||||
* LE32_TO_CPU - convert a little-endian uint32_t constant
|
||||
* @le_val: little-endian constant to convert
|
||||
*/
|
||||
#define LE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val))
|
||||
|
||||
/**
|
||||
* LE16_TO_CPU - convert a little-endian uint16_t constant
|
||||
* @le_val: little-endian constant to convert
|
||||
*/
|
||||
#define LE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val))
|
||||
|
||||
#else /* ... HAVE_BIG_ENDIAN */
|
||||
#define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)BSWAP_64(native))
|
||||
#define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)BSWAP_32(native))
|
||||
#define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)BSWAP_16(native))
|
||||
#define LE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val)
|
||||
#define LE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val)
|
||||
#define LE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val)
|
||||
#endif /* HAVE_BIG_ENDIAN */
|
||||
|
||||
#if HAVE_BIG_ENDIAN
|
||||
/**
|
||||
* CPU_TO_BE64 - convert a constant uint64_t value to big-endian
|
||||
* @native: constant to convert
|
||||
*/
|
||||
#define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)(native))
|
||||
|
||||
/**
|
||||
* CPU_TO_BE32 - convert a constant uint32_t value to big-endian
|
||||
* @native: constant to convert
|
||||
*/
|
||||
#define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)(native))
|
||||
|
||||
/**
|
||||
* CPU_TO_BE16 - convert a constant uint16_t value to big-endian
|
||||
* @native: constant to convert
|
||||
*/
|
||||
#define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)(native))
|
||||
|
||||
/**
|
||||
* BE64_TO_CPU - convert a big-endian uint64_t constant
|
||||
* @le_val: big-endian constant to convert
|
||||
*/
|
||||
#define BE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val))
|
||||
|
||||
/**
|
||||
* BE32_TO_CPU - convert a big-endian uint32_t constant
|
||||
* @le_val: big-endian constant to convert
|
||||
*/
|
||||
#define BE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val))
|
||||
|
||||
/**
|
||||
* BE16_TO_CPU - convert a big-endian uint16_t constant
|
||||
* @le_val: big-endian constant to convert
|
||||
*/
|
||||
#define BE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val))
|
||||
|
||||
#else /* ... HAVE_LITTLE_ENDIAN */
|
||||
#define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)BSWAP_64(native))
|
||||
#define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)BSWAP_32(native))
|
||||
#define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)BSWAP_16(native))
|
||||
#define BE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val)
|
||||
#define BE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val)
|
||||
#define BE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val)
|
||||
#endif /* HAVE_LITTE_ENDIAN */
|
||||
|
||||
|
||||
/**
|
||||
* cpu_to_le64 - convert a uint64_t value to little-endian
|
||||
* @native: value to convert
|
||||
*/
|
||||
static inline leint64_t cpu_to_le64(uint64_t native)
|
||||
{
|
||||
return CPU_TO_LE64(native);
|
||||
}
|
||||
|
||||
/**
|
||||
* cpu_to_le32 - convert a uint32_t value to little-endian
|
||||
* @native: value to convert
|
||||
*/
|
||||
static inline leint32_t cpu_to_le32(uint32_t native)
|
||||
{
|
||||
return CPU_TO_LE32(native);
|
||||
}
|
||||
|
||||
/**
|
||||
* cpu_to_le16 - convert a uint16_t value to little-endian
|
||||
* @native: value to convert
|
||||
*/
|
||||
static inline leint16_t cpu_to_le16(uint16_t native)
|
||||
{
|
||||
return CPU_TO_LE16(native);
|
||||
}
|
||||
|
||||
/**
|
||||
* le64_to_cpu - convert a little-endian uint64_t value
|
||||
* @le_val: little-endian value to convert
|
||||
*/
|
||||
static inline uint64_t le64_to_cpu(leint64_t le_val)
|
||||
{
|
||||
return LE64_TO_CPU(le_val);
|
||||
}
|
||||
|
||||
/**
|
||||
* le32_to_cpu - convert a little-endian uint32_t value
|
||||
* @le_val: little-endian value to convert
|
||||
*/
|
||||
static inline uint32_t le32_to_cpu(leint32_t le_val)
|
||||
{
|
||||
return LE32_TO_CPU(le_val);
|
||||
}
|
||||
|
||||
/**
|
||||
* le16_to_cpu - convert a little-endian uint16_t value
|
||||
* @le_val: little-endian value to convert
|
||||
*/
|
||||
static inline uint16_t le16_to_cpu(leint16_t le_val)
|
||||
{
|
||||
return LE16_TO_CPU(le_val);
|
||||
}
|
||||
|
||||
/**
|
||||
* cpu_to_be64 - convert a uint64_t value to big endian.
|
||||
* @native: value to convert
|
||||
*/
|
||||
static inline beint64_t cpu_to_be64(uint64_t native)
|
||||
{
|
||||
return CPU_TO_BE64(native);
|
||||
}
|
||||
|
||||
/**
|
||||
* cpu_to_be32 - convert a uint32_t value to big endian.
|
||||
* @native: value to convert
|
||||
*/
|
||||
static inline beint32_t cpu_to_be32(uint32_t native)
|
||||
{
|
||||
return CPU_TO_BE32(native);
|
||||
}
|
||||
|
||||
/**
|
||||
* cpu_to_be16 - convert a uint16_t value to big endian.
|
||||
* @native: value to convert
|
||||
*/
|
||||
static inline beint16_t cpu_to_be16(uint16_t native)
|
||||
{
|
||||
return CPU_TO_BE16(native);
|
||||
}
|
||||
|
||||
/**
|
||||
* be64_to_cpu - convert a big-endian uint64_t value
|
||||
* @be_val: big-endian value to convert
|
||||
*/
|
||||
static inline uint64_t be64_to_cpu(beint64_t be_val)
|
||||
{
|
||||
return BE64_TO_CPU(be_val);
|
||||
}
|
||||
|
||||
/**
|
||||
* be32_to_cpu - convert a big-endian uint32_t value
|
||||
* @be_val: big-endian value to convert
|
||||
*/
|
||||
static inline uint32_t be32_to_cpu(beint32_t be_val)
|
||||
{
|
||||
return BE32_TO_CPU(be_val);
|
||||
}
|
||||
|
||||
/**
|
||||
* be16_to_cpu - convert a big-endian uint16_t value
|
||||
* @be_val: big-endian value to convert
|
||||
*/
|
||||
static inline uint16_t be16_to_cpu(beint16_t be_val)
|
||||
{
|
||||
return BE16_TO_CPU(be_val);
|
||||
}
|
||||
|
||||
/* Whichever they include first, they get these definitions. */
|
||||
#ifdef CCAN_SHORT_TYPES_H
|
||||
/**
|
||||
* be64/be32/be16 - 64/32/16 bit big-endian representation.
|
||||
*/
|
||||
typedef beint64_t be64;
|
||||
typedef beint32_t be32;
|
||||
typedef beint16_t be16;
|
||||
|
||||
/**
|
||||
* le64/le32/le16 - 64/32/16 bit little-endian representation.
|
||||
*/
|
||||
typedef leint64_t le64;
|
||||
typedef leint32_t le32;
|
||||
typedef leint16_t le16;
|
||||
#endif
|
||||
#endif /* CCAN_ENDIAN_H */
|
12
ccan/ccan/endian/test/compile_ok-constant.c
Normal file
12
ccan/ccan/endian/test/compile_ok-constant.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include <ccan/endian/endian.h>
|
||||
|
||||
struct foo {
|
||||
char one[BSWAP_16(0xFF00)];
|
||||
char two[BSWAP_32(0xFF000000)];
|
||||
char three[BSWAP_64(0xFF00000000000000ULL)];
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
106
ccan/ccan/endian/test/run.c
Normal file
106
ccan/ccan/endian/test/run.c
Normal file
@ -0,0 +1,106 @@
|
||||
#include <ccan/endian/endian.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
union {
|
||||
uint64_t u64;
|
||||
unsigned char u64_bytes[8];
|
||||
} u64;
|
||||
union {
|
||||
uint32_t u32;
|
||||
unsigned char u32_bytes[4];
|
||||
} u32;
|
||||
union {
|
||||
uint16_t u16;
|
||||
unsigned char u16_bytes[2];
|
||||
} u16;
|
||||
|
||||
plan_tests(48);
|
||||
|
||||
/* Straight swap tests. */
|
||||
u64.u64_bytes[0] = 0x00;
|
||||
u64.u64_bytes[1] = 0x11;
|
||||
u64.u64_bytes[2] = 0x22;
|
||||
u64.u64_bytes[3] = 0x33;
|
||||
u64.u64_bytes[4] = 0x44;
|
||||
u64.u64_bytes[5] = 0x55;
|
||||
u64.u64_bytes[6] = 0x66;
|
||||
u64.u64_bytes[7] = 0x77;
|
||||
u64.u64 = bswap_64(u64.u64);
|
||||
ok1(u64.u64_bytes[7] == 0x00);
|
||||
ok1(u64.u64_bytes[6] == 0x11);
|
||||
ok1(u64.u64_bytes[5] == 0x22);
|
||||
ok1(u64.u64_bytes[4] == 0x33);
|
||||
ok1(u64.u64_bytes[3] == 0x44);
|
||||
ok1(u64.u64_bytes[2] == 0x55);
|
||||
ok1(u64.u64_bytes[1] == 0x66);
|
||||
ok1(u64.u64_bytes[0] == 0x77);
|
||||
|
||||
u32.u32_bytes[0] = 0x00;
|
||||
u32.u32_bytes[1] = 0x11;
|
||||
u32.u32_bytes[2] = 0x22;
|
||||
u32.u32_bytes[3] = 0x33;
|
||||
u32.u32 = bswap_32(u32.u32);
|
||||
ok1(u32.u32_bytes[3] == 0x00);
|
||||
ok1(u32.u32_bytes[2] == 0x11);
|
||||
ok1(u32.u32_bytes[1] == 0x22);
|
||||
ok1(u32.u32_bytes[0] == 0x33);
|
||||
|
||||
u16.u16_bytes[0] = 0x00;
|
||||
u16.u16_bytes[1] = 0x11;
|
||||
u16.u16 = bswap_16(u16.u16);
|
||||
ok1(u16.u16_bytes[1] == 0x00);
|
||||
ok1(u16.u16_bytes[0] == 0x11);
|
||||
|
||||
/* Endian tests. */
|
||||
u64.u64 = cpu_to_le64(0x0011223344556677ULL);
|
||||
ok1(u64.u64_bytes[0] == 0x77);
|
||||
ok1(u64.u64_bytes[1] == 0x66);
|
||||
ok1(u64.u64_bytes[2] == 0x55);
|
||||
ok1(u64.u64_bytes[3] == 0x44);
|
||||
ok1(u64.u64_bytes[4] == 0x33);
|
||||
ok1(u64.u64_bytes[5] == 0x22);
|
||||
ok1(u64.u64_bytes[6] == 0x11);
|
||||
ok1(u64.u64_bytes[7] == 0x00);
|
||||
ok1(le64_to_cpu(u64.u64) == 0x0011223344556677ULL);
|
||||
|
||||
u64.u64 = cpu_to_be64(0x0011223344556677ULL);
|
||||
ok1(u64.u64_bytes[7] == 0x77);
|
||||
ok1(u64.u64_bytes[6] == 0x66);
|
||||
ok1(u64.u64_bytes[5] == 0x55);
|
||||
ok1(u64.u64_bytes[4] == 0x44);
|
||||
ok1(u64.u64_bytes[3] == 0x33);
|
||||
ok1(u64.u64_bytes[2] == 0x22);
|
||||
ok1(u64.u64_bytes[1] == 0x11);
|
||||
ok1(u64.u64_bytes[0] == 0x00);
|
||||
ok1(be64_to_cpu(u64.u64) == 0x0011223344556677ULL);
|
||||
|
||||
u32.u32 = cpu_to_le32(0x00112233);
|
||||
ok1(u32.u32_bytes[0] == 0x33);
|
||||
ok1(u32.u32_bytes[1] == 0x22);
|
||||
ok1(u32.u32_bytes[2] == 0x11);
|
||||
ok1(u32.u32_bytes[3] == 0x00);
|
||||
ok1(le32_to_cpu(u32.u32) == 0x00112233);
|
||||
|
||||
u32.u32 = cpu_to_be32(0x00112233);
|
||||
ok1(u32.u32_bytes[3] == 0x33);
|
||||
ok1(u32.u32_bytes[2] == 0x22);
|
||||
ok1(u32.u32_bytes[1] == 0x11);
|
||||
ok1(u32.u32_bytes[0] == 0x00);
|
||||
ok1(be32_to_cpu(u32.u32) == 0x00112233);
|
||||
|
||||
u16.u16 = cpu_to_le16(0x0011);
|
||||
ok1(u16.u16_bytes[0] == 0x11);
|
||||
ok1(u16.u16_bytes[1] == 0x00);
|
||||
ok1(le16_to_cpu(u16.u16) == 0x0011);
|
||||
|
||||
u16.u16 = cpu_to_be16(0x0011);
|
||||
ok1(u16.u16_bytes[1] == 0x11);
|
||||
ok1(u16.u16_bytes[0] == 0x00);
|
||||
ok1(be16_to_cpu(u16.u16) == 0x0011);
|
||||
|
||||
exit(exit_status());
|
||||
}
|
1
ccan/ccan/err/LICENSE
Symbolic link
1
ccan/ccan/err/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../licenses/CC0
|
41
ccan/ccan/err/_info
Normal file
41
ccan/ccan/err/_info
Normal file
@ -0,0 +1,41 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* err - err(), errx(), warn() and warnx(), as per BSD's err.h.
|
||||
*
|
||||
* A few platforms don't provide err.h; for those, this provides replacements.
|
||||
* For most, it simple includes the system err.h.
|
||||
*
|
||||
* Unfortunately, you have to call err_set_progname() to tell the replacements
|
||||
* your program name, otherwise it prints "unknown program".
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/err/err.h>
|
||||
*
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* err_set_progname(argv[0]);
|
||||
* if (argc != 1)
|
||||
* errx(1, "Expect no arguments");
|
||||
* exit(0);
|
||||
* }
|
||||
*
|
||||
* License: CC0 (Public domain)
|
||||
* Author: Rusty Russell <rusty@rustcorp.com.au>
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
#if !HAVE_ERR_H
|
||||
printf("ccan/compiler\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
65
ccan/ccan/err/err.c
Normal file
65
ccan/ccan/err/err.c
Normal file
@ -0,0 +1,65 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#include "err.h"
|
||||
|
||||
#if !HAVE_ERR_H
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static const char *progname = "unknown program";
|
||||
|
||||
void err_set_progname(const char *name)
|
||||
{
|
||||
progname = name;
|
||||
}
|
||||
|
||||
void NORETURN err(int eval, const char *fmt, ...)
|
||||
{
|
||||
int err_errno = errno;
|
||||
va_list ap;
|
||||
|
||||
fprintf(stderr, "%s: ", progname);
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, ": %s\n", strerror(err_errno));
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
void NORETURN errx(int eval, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fprintf(stderr, "%s: ", progname);
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
void warn(const char *fmt, ...)
|
||||
{
|
||||
int err_errno = errno;
|
||||
va_list ap;
|
||||
|
||||
fprintf(stderr, "%s: ", progname);
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, ": %s\n", strerror(err_errno));
|
||||
}
|
||||
|
||||
void warnx(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fprintf(stderr, "%s: ", progname);
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
88
ccan/ccan/err/err.h
Normal file
88
ccan/ccan/err/err.h
Normal file
@ -0,0 +1,88 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#ifndef CCAN_ERR_H
|
||||
#define CCAN_ERR_H
|
||||
#include "config.h"
|
||||
|
||||
#if HAVE_ERR_H
|
||||
#include <err.h>
|
||||
|
||||
/* This is unnecessary with a real err.h. See below */
|
||||
#define err_set_progname(name) ((void)name)
|
||||
|
||||
#else
|
||||
#include <ccan/compiler/compiler.h>
|
||||
|
||||
/**
|
||||
* err_set_progname - set the program name
|
||||
* @name: the name to use for err, errx, warn and warnx
|
||||
*
|
||||
* The BSD err.h calls know the program name, unfortunately there's no
|
||||
* portable way for the CCAN replacements to do that on other systems.
|
||||
*
|
||||
* If you don't call this with argv[0], it will be "unknown program".
|
||||
*
|
||||
* Example:
|
||||
* err_set_progname(argv[0]);
|
||||
*/
|
||||
void err_set_progname(const char *name);
|
||||
|
||||
/**
|
||||
* err - exit(eval) with message based on format and errno.
|
||||
* @eval: the exit code
|
||||
* @fmt: the printf-style format string
|
||||
*
|
||||
* The format string is printed to stderr like so:
|
||||
* <executable name>: <format>: <strerror(errno)>\n
|
||||
*
|
||||
* Example:
|
||||
* char *p = strdup("hello");
|
||||
* if (!p)
|
||||
* err(1, "Failed to strdup 'hello'");
|
||||
*/
|
||||
void NORETURN err(int eval, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* errx - exit(eval) with message based on format.
|
||||
* @eval: the exit code
|
||||
* @fmt: the printf-style format string
|
||||
*
|
||||
* The format string is printed to stderr like so:
|
||||
* <executable name>: <format>\n
|
||||
*
|
||||
* Example:
|
||||
* if (argc != 1)
|
||||
* errx(1, "I don't expect any arguments");
|
||||
*/
|
||||
void NORETURN errx(int eval, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* warn - print a message to stderr based on format and errno.
|
||||
* @eval: the exit code
|
||||
* @fmt: the printf-style format string
|
||||
*
|
||||
* The format string is printed to stderr like so:
|
||||
* <executable name>: <format>: <strerror(errno)>\n
|
||||
*
|
||||
* Example:
|
||||
* char *p = strdup("hello");
|
||||
* if (!p)
|
||||
* warn("Failed to strdup 'hello'");
|
||||
*/
|
||||
void warn(const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* warnx - print a message to stderr based on format.
|
||||
* @eval: the exit code
|
||||
* @fmt: the printf-style format string
|
||||
*
|
||||
* The format string is printed to stderr like so:
|
||||
* <executable name>: <format>\n
|
||||
*
|
||||
* Example:
|
||||
* if (argc != 1)
|
||||
* warnx("I don't expect any arguments (ignoring)");
|
||||
*/
|
||||
void warnx(const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
#endif /* CCAN_ERR_H */
|
153
ccan/ccan/err/test/run.c
Normal file
153
ccan/ccan/err/test/run.c
Normal file
@ -0,0 +1,153 @@
|
||||
#include <ccan/err/err.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#define BUFFER_MAX 1024
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int pfd[2];
|
||||
const char *base;
|
||||
|
||||
plan_tests(24);
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
/* In case it only prints out the basename of argv[0]. */
|
||||
base = strrchr(argv[0], '/');
|
||||
if (base)
|
||||
base++;
|
||||
else
|
||||
base = argv[0];
|
||||
|
||||
/* Test err() in child */
|
||||
pipe(pfd);
|
||||
fflush(stdout);
|
||||
if (fork()) {
|
||||
char buffer[BUFFER_MAX+1];
|
||||
unsigned int i;
|
||||
int status;
|
||||
|
||||
/* We are parent. */
|
||||
close(pfd[1]);
|
||||
for (i = 0; i < BUFFER_MAX; i++) {
|
||||
if (read(pfd[0], buffer + i, 1) == 0) {
|
||||
buffer[i] = '\0';
|
||||
ok1(strstr(buffer, "running err:"));
|
||||
ok1(strstr(buffer, strerror(ENOENT)));
|
||||
ok1(strstr(buffer, base));
|
||||
ok1(buffer[i-1] == '\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(pfd[0]);
|
||||
ok1(wait(&status) != -1);
|
||||
ok1(WIFEXITED(status));
|
||||
ok1(WEXITSTATUS(status) == 17);
|
||||
} else {
|
||||
close(pfd[0]);
|
||||
dup2(pfd[1], STDERR_FILENO);
|
||||
errno = ENOENT;
|
||||
err(17, "running %s", "err");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Test errx() in child */
|
||||
pipe(pfd);
|
||||
fflush(stdout);
|
||||
if (fork()) {
|
||||
char buffer[BUFFER_MAX+1];
|
||||
unsigned int i;
|
||||
int status;
|
||||
|
||||
/* We are parent. */
|
||||
close(pfd[1]);
|
||||
for (i = 0; i < BUFFER_MAX; i++) {
|
||||
if (read(pfd[0], buffer + i, 1) == 0) {
|
||||
buffer[i] = '\0';
|
||||
ok1(strstr(buffer, "running errx\n"));
|
||||
ok1(strstr(buffer, base));
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(pfd[0]);
|
||||
ok1(wait(&status) != -1);
|
||||
ok1(WIFEXITED(status));
|
||||
ok1(WEXITSTATUS(status) == 17);
|
||||
} else {
|
||||
close(pfd[0]);
|
||||
dup2(pfd[1], STDERR_FILENO);
|
||||
errx(17, "running %s", "errx");
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
/* Test warn() in child */
|
||||
pipe(pfd);
|
||||
fflush(stdout);
|
||||
if (fork()) {
|
||||
char buffer[BUFFER_MAX+1];
|
||||
unsigned int i;
|
||||
int status;
|
||||
|
||||
/* We are parent. */
|
||||
close(pfd[1]);
|
||||
for (i = 0; i < BUFFER_MAX; i++) {
|
||||
if (read(pfd[0], buffer + i, 1) == 0) {
|
||||
buffer[i] = '\0';
|
||||
ok1(strstr(buffer, "running warn:"));
|
||||
ok1(strstr(buffer, strerror(ENOENT)));
|
||||
ok1(strstr(buffer, base));
|
||||
ok1(buffer[i-1] == '\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(pfd[0]);
|
||||
ok1(wait(&status) != -1);
|
||||
ok1(WIFEXITED(status));
|
||||
ok1(WEXITSTATUS(status) == 17);
|
||||
} else {
|
||||
close(pfd[0]);
|
||||
dup2(pfd[1], STDERR_FILENO);
|
||||
errno = ENOENT;
|
||||
warn("running %s", "warn");
|
||||
exit(17);
|
||||
}
|
||||
|
||||
/* Test warnx() in child */
|
||||
pipe(pfd);
|
||||
fflush(stdout);
|
||||
if (fork()) {
|
||||
char buffer[BUFFER_MAX+1];
|
||||
unsigned int i;
|
||||
int status;
|
||||
|
||||
/* We are parent. */
|
||||
close(pfd[1]);
|
||||
for (i = 0; i < BUFFER_MAX; i++) {
|
||||
if (read(pfd[0], buffer + i, 1) == 0) {
|
||||
buffer[i] = '\0';
|
||||
ok1(strstr(buffer, "running warnx\n"));
|
||||
ok1(strstr(buffer, base));
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(pfd[0]);
|
||||
ok1(wait(&status) != -1);
|
||||
ok1(WIFEXITED(status));
|
||||
ok1(WEXITSTATUS(status) == 17);
|
||||
} else {
|
||||
close(pfd[0]);
|
||||
dup2(pfd[1], STDERR_FILENO);
|
||||
warnx("running %s", "warnx");
|
||||
exit(17);
|
||||
}
|
||||
return exit_status();
|
||||
}
|
||||
|
1
ccan/ccan/hash/LICENSE
Symbolic link
1
ccan/ccan/hash/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../licenses/CC0
|
32
ccan/ccan/hash/_info
Normal file
32
ccan/ccan/hash/_info
Normal file
@ -0,0 +1,32 @@
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* hash - routines for hashing bytes
|
||||
*
|
||||
* When creating a hash table it's important to have a hash function
|
||||
* which mixes well and is fast. This package supplies such functions.
|
||||
*
|
||||
* The hash functions come in two flavors: the normal ones and the
|
||||
* stable ones. The normal ones can vary from machine-to-machine and
|
||||
* may change if we find better or faster hash algorithms in future.
|
||||
* The stable ones will always give the same results on any computer,
|
||||
* and on any version of this package.
|
||||
*
|
||||
* License: CC0 (Public domain)
|
||||
* Maintainer: Rusty Russell <rusty@rustcorp.com.au>
|
||||
* Author: Bob Jenkins <bob_jenkins@burtleburtle.net>
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
printf("ccan/build_assert\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
926
ccan/ccan/hash/hash.c
Normal file
926
ccan/ccan/hash/hash.c
Normal file
@ -0,0 +1,926 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
lookup3.c, by Bob Jenkins, May 2006, Public Domain.
|
||||
|
||||
These are functions for producing 32-bit hashes for hash table lookup.
|
||||
hash_word(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
|
||||
are externally useful functions. Routines to test the hash are included
|
||||
if SELF_TEST is defined. You can use this free for any purpose. It's in
|
||||
the public domain. It has no warranty.
|
||||
|
||||
You probably want to use hashlittle(). hashlittle() and hashbig()
|
||||
hash byte arrays. hashlittle() is is faster than hashbig() on
|
||||
little-endian machines. Intel and AMD are little-endian machines.
|
||||
On second thought, you probably want hashlittle2(), which is identical to
|
||||
hashlittle() except it returns two 32-bit hashes for the price of one.
|
||||
You could implement hashbig2() if you wanted but I haven't bothered here.
|
||||
|
||||
If you want to find a hash of, say, exactly 7 integers, do
|
||||
a = i1; b = i2; c = i3;
|
||||
mix(a,b,c);
|
||||
a += i4; b += i5; c += i6;
|
||||
mix(a,b,c);
|
||||
a += i7;
|
||||
final(a,b,c);
|
||||
then use c as the hash value. If you have a variable length array of
|
||||
4-byte integers to hash, use hash_word(). If you have a byte array (like
|
||||
a character string), use hashlittle(). If you have several byte arrays, or
|
||||
a mix of things, see the comments above hashlittle().
|
||||
|
||||
Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
|
||||
then mix those integers. This is fast (you can do a lot more thorough
|
||||
mixing with 12*3 instructions on 3 integers than you can with 3 instructions
|
||||
on 1 byte), but shoehorning those bytes into integers efficiently is messy.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
//#define SELF_TEST 1
|
||||
|
||||
#if 0
|
||||
#include <stdio.h> /* defines printf for tests */
|
||||
#include <time.h> /* defines time_t for timings in the test */
|
||||
#include <stdint.h> /* defines uint32_t etc */
|
||||
#include <sys/param.h> /* attempt to define endianness */
|
||||
|
||||
#ifdef linux
|
||||
# include <endian.h> /* attempt to define endianness */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* My best guess at if you are big-endian or little-endian. This may
|
||||
* need adjustment.
|
||||
*/
|
||||
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
|
||||
__BYTE_ORDER == __LITTLE_ENDIAN) || \
|
||||
(defined(i386) || defined(__i386__) || defined(__i486__) || \
|
||||
defined(__i586__) || defined(__i686__) || defined(__x86_64) || \
|
||||
defined(vax) || defined(MIPSEL))
|
||||
# define HASH_LITTLE_ENDIAN 1
|
||||
# define HASH_BIG_ENDIAN 0
|
||||
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
|
||||
__BYTE_ORDER == __BIG_ENDIAN) || \
|
||||
(defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
|
||||
# define HASH_LITTLE_ENDIAN 0
|
||||
# define HASH_BIG_ENDIAN 1
|
||||
#else
|
||||
# error Unknown endian
|
||||
#endif
|
||||
#endif /* old hash.c headers. */
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
#if HAVE_LITTLE_ENDIAN
|
||||
#define HASH_LITTLE_ENDIAN 1
|
||||
#define HASH_BIG_ENDIAN 0
|
||||
#elif HAVE_BIG_ENDIAN
|
||||
#define HASH_LITTLE_ENDIAN 0
|
||||
#define HASH_BIG_ENDIAN 1
|
||||
#else
|
||||
#error Unknown endian
|
||||
#endif
|
||||
|
||||
#define hashsize(n) ((uint32_t)1<<(n))
|
||||
#define hashmask(n) (hashsize(n)-1)
|
||||
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
mix -- mix 3 32-bit values reversibly.
|
||||
|
||||
This is reversible, so any information in (a,b,c) before mix() is
|
||||
still in (a,b,c) after mix().
|
||||
|
||||
If four pairs of (a,b,c) inputs are run through mix(), or through
|
||||
mix() in reverse, there are at least 32 bits of the output that
|
||||
are sometimes the same for one pair and different for another pair.
|
||||
This was tested for:
|
||||
* pairs that differed by one bit, by two bits, in any combination
|
||||
of top bits of (a,b,c), or in any combination of bottom bits of
|
||||
(a,b,c).
|
||||
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
|
||||
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
|
||||
is commonly produced by subtraction) look like a single 1-bit
|
||||
difference.
|
||||
* the base values were pseudorandom, all zero but one bit set, or
|
||||
all zero plus a counter that starts at zero.
|
||||
|
||||
Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
|
||||
satisfy this are
|
||||
4 6 8 16 19 4
|
||||
9 15 3 18 27 15
|
||||
14 9 3 7 17 3
|
||||
Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
|
||||
for "differ" defined as + with a one-bit base and a two-bit delta. I
|
||||
used http://burtleburtle.net/bob/hash/avalanche.html to choose
|
||||
the operations, constants, and arrangements of the variables.
|
||||
|
||||
This does not achieve avalanche. There are input bits of (a,b,c)
|
||||
that fail to affect some output bits of (a,b,c), especially of a. The
|
||||
most thoroughly mixed value is c, but it doesn't really even achieve
|
||||
avalanche in c.
|
||||
|
||||
This allows some parallelism. Read-after-writes are good at doubling
|
||||
the number of bits affected, so the goal of mixing pulls in the opposite
|
||||
direction as the goal of parallelism. I did what I could. Rotates
|
||||
seem to cost as much as shifts on every machine I could lay my hands
|
||||
on, and rotates are much kinder to the top and bottom bits, so I used
|
||||
rotates.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#define mix(a,b,c) \
|
||||
{ \
|
||||
a -= c; a ^= rot(c, 4); c += b; \
|
||||
b -= a; b ^= rot(a, 6); a += c; \
|
||||
c -= b; c ^= rot(b, 8); b += a; \
|
||||
a -= c; a ^= rot(c,16); c += b; \
|
||||
b -= a; b ^= rot(a,19); a += c; \
|
||||
c -= b; c ^= rot(b, 4); b += a; \
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
final -- final mixing of 3 32-bit values (a,b,c) into c
|
||||
|
||||
Pairs of (a,b,c) values differing in only a few bits will usually
|
||||
produce values of c that look totally different. This was tested for
|
||||
* pairs that differed by one bit, by two bits, in any combination
|
||||
of top bits of (a,b,c), or in any combination of bottom bits of
|
||||
(a,b,c).
|
||||
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
|
||||
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
|
||||
is commonly produced by subtraction) look like a single 1-bit
|
||||
difference.
|
||||
* the base values were pseudorandom, all zero but one bit set, or
|
||||
all zero plus a counter that starts at zero.
|
||||
|
||||
These constants passed:
|
||||
14 11 25 16 4 14 24
|
||||
12 14 25 16 4 14 24
|
||||
and these came close:
|
||||
4 8 15 26 3 22 24
|
||||
10 8 15 26 3 22 24
|
||||
11 8 15 26 3 22 24
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#define final(a,b,c) \
|
||||
{ \
|
||||
c ^= b; c -= rot(b,14); \
|
||||
a ^= c; a -= rot(c,11); \
|
||||
b ^= a; b -= rot(a,25); \
|
||||
c ^= b; c -= rot(b,16); \
|
||||
a ^= c; a -= rot(c,4); \
|
||||
b ^= a; b -= rot(a,14); \
|
||||
c ^= b; c -= rot(b,24); \
|
||||
}
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------
|
||||
This works on all machines. To be useful, it requires
|
||||
-- that the key be an array of uint32_t's, and
|
||||
-- that the length be the number of uint32_t's in the key
|
||||
|
||||
The function hash_word() is identical to hashlittle() on little-endian
|
||||
machines, and identical to hashbig() on big-endian machines,
|
||||
except that the length has to be measured in uint32_ts rather than in
|
||||
bytes. hashlittle() is more complicated than hash_word() only because
|
||||
hashlittle() has to dance around fitting the key bytes into registers.
|
||||
--------------------------------------------------------------------
|
||||
*/
|
||||
uint32_t hash_u32(
|
||||
const uint32_t *k, /* the key, an array of uint32_t values */
|
||||
size_t length, /* the length of the key, in uint32_ts */
|
||||
uint32_t initval) /* the previous hash, or an arbitrary value */
|
||||
{
|
||||
uint32_t a,b,c;
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = 0xdeadbeef + (((uint32_t)length)<<2) + initval;
|
||||
|
||||
/*------------------------------------------------- handle most of the key */
|
||||
while (length > 3)
|
||||
{
|
||||
a += k[0];
|
||||
b += k[1];
|
||||
c += k[2];
|
||||
mix(a,b,c);
|
||||
length -= 3;
|
||||
k += 3;
|
||||
}
|
||||
|
||||
/*------------------------------------------- handle the last 3 uint32_t's */
|
||||
switch(length) /* all the case statements fall through */
|
||||
{
|
||||
case 3 : c+=k[2];
|
||||
case 2 : b+=k[1];
|
||||
case 1 : a+=k[0];
|
||||
final(a,b,c);
|
||||
case 0: /* case 0: nothing left to add */
|
||||
break;
|
||||
}
|
||||
/*------------------------------------------------------ report the result */
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
hashlittle() -- hash a variable-length key into a 32-bit value
|
||||
k : the key (the unaligned variable-length array of bytes)
|
||||
length : the length of the key, counting by bytes
|
||||
val2 : IN: can be any 4-byte value OUT: second 32 bit hash.
|
||||
Returns a 32-bit value. Every bit of the key affects every bit of
|
||||
the return value. Two keys differing by one or two bits will have
|
||||
totally different hash values. Note that the return value is better
|
||||
mixed than val2, so use that first.
|
||||
|
||||
The best hash table sizes are powers of 2. There is no need to do
|
||||
mod a prime (mod is sooo slow!). If you need less than 32 bits,
|
||||
use a bitmask. For example, if you need only 10 bits, do
|
||||
h = (h & hashmask(10));
|
||||
In which case, the hash table should have hashsize(10) elements.
|
||||
|
||||
If you are hashing n strings (uint8_t **)k, do it like this:
|
||||
for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h);
|
||||
|
||||
By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this
|
||||
code any way you wish, private, educational, or commercial. It's free.
|
||||
|
||||
Use for hash table lookup, or anything where one collision in 2^^32 is
|
||||
acceptable. Do NOT use for cryptographic purposes.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static uint32_t hashlittle( const void *key, size_t length, uint32_t *val2 )
|
||||
{
|
||||
uint32_t a,b,c; /* internal state */
|
||||
union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = 0xdeadbeef + ((uint32_t)length) + *val2;
|
||||
|
||||
u.ptr = key;
|
||||
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
|
||||
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
|
||||
const uint8_t *k8;
|
||||
|
||||
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
|
||||
while (length > 12)
|
||||
{
|
||||
a += k[0];
|
||||
b += k[1];
|
||||
c += k[2];
|
||||
mix(a,b,c);
|
||||
length -= 12;
|
||||
k += 3;
|
||||
}
|
||||
|
||||
/*----------------------------- handle the last (probably partial) block */
|
||||
/*
|
||||
* "k[2]&0xffffff" actually reads beyond the end of the string, but
|
||||
* then masks off the part it's not allowed to read. Because the
|
||||
* string is aligned, the masked-off tail is in the same word as the
|
||||
* rest of the string. Every machine with memory protection I've seen
|
||||
* does it on word boundaries, so is OK with this. But VALGRIND will
|
||||
* still catch it and complain. The masking trick does make the hash
|
||||
* noticably faster for short strings (like English words).
|
||||
*
|
||||
* Not on my testing with gcc 4.5 on an intel i5 CPU, at least --RR.
|
||||
*/
|
||||
#if 0
|
||||
switch(length)
|
||||
{
|
||||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
|
||||
case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
|
||||
case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
|
||||
case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
|
||||
case 8 : b+=k[1]; a+=k[0]; break;
|
||||
case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
|
||||
case 6 : b+=k[1]&0xffff; a+=k[0]; break;
|
||||
case 5 : b+=k[1]&0xff; a+=k[0]; break;
|
||||
case 4 : a+=k[0]; break;
|
||||
case 3 : a+=k[0]&0xffffff; break;
|
||||
case 2 : a+=k[0]&0xffff; break;
|
||||
case 1 : a+=k[0]&0xff; break;
|
||||
case 0 : return c; /* zero length strings require no mixing */
|
||||
}
|
||||
|
||||
#else /* make valgrind happy */
|
||||
|
||||
k8 = (const uint8_t *)k;
|
||||
switch(length)
|
||||
{
|
||||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
|
||||
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
|
||||
case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
|
||||
case 9 : c+=k8[8]; /* fall through */
|
||||
case 8 : b+=k[1]; a+=k[0]; break;
|
||||
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
|
||||
case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
|
||||
case 5 : b+=k8[4]; /* fall through */
|
||||
case 4 : a+=k[0]; break;
|
||||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
|
||||
case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
|
||||
case 1 : a+=k8[0]; break;
|
||||
case 0 : return c;
|
||||
}
|
||||
|
||||
#endif /* !valgrind */
|
||||
|
||||
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
|
||||
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
|
||||
const uint8_t *k8;
|
||||
|
||||
/*--------------- all but last block: aligned reads and different mixing */
|
||||
while (length > 12)
|
||||
{
|
||||
a += k[0] + (((uint32_t)k[1])<<16);
|
||||
b += k[2] + (((uint32_t)k[3])<<16);
|
||||
c += k[4] + (((uint32_t)k[5])<<16);
|
||||
mix(a,b,c);
|
||||
length -= 12;
|
||||
k += 6;
|
||||
}
|
||||
|
||||
/*----------------------------- handle the last (probably partial) block */
|
||||
k8 = (const uint8_t *)k;
|
||||
switch(length)
|
||||
{
|
||||
case 12: c+=k[4]+(((uint32_t)k[5])<<16);
|
||||
b+=k[2]+(((uint32_t)k[3])<<16);
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
|
||||
case 10: c+=k[4];
|
||||
b+=k[2]+(((uint32_t)k[3])<<16);
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 9 : c+=k8[8]; /* fall through */
|
||||
case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
|
||||
case 6 : b+=k[2];
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 5 : b+=k8[4]; /* fall through */
|
||||
case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
|
||||
case 2 : a+=k[0];
|
||||
break;
|
||||
case 1 : a+=k8[0];
|
||||
break;
|
||||
case 0 : return c; /* zero length requires no mixing */
|
||||
}
|
||||
|
||||
} else { /* need to read the key one byte at a time */
|
||||
const uint8_t *k = (const uint8_t *)key;
|
||||
|
||||
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */
|
||||
while (length > 12)
|
||||
{
|
||||
a += k[0];
|
||||
a += ((uint32_t)k[1])<<8;
|
||||
a += ((uint32_t)k[2])<<16;
|
||||
a += ((uint32_t)k[3])<<24;
|
||||
b += k[4];
|
||||
b += ((uint32_t)k[5])<<8;
|
||||
b += ((uint32_t)k[6])<<16;
|
||||
b += ((uint32_t)k[7])<<24;
|
||||
c += k[8];
|
||||
c += ((uint32_t)k[9])<<8;
|
||||
c += ((uint32_t)k[10])<<16;
|
||||
c += ((uint32_t)k[11])<<24;
|
||||
mix(a,b,c);
|
||||
length -= 12;
|
||||
k += 12;
|
||||
}
|
||||
|
||||
/*-------------------------------- last block: affect all 32 bits of (c) */
|
||||
switch(length) /* all the case statements fall through */
|
||||
{
|
||||
case 12: c+=((uint32_t)k[11])<<24;
|
||||
case 11: c+=((uint32_t)k[10])<<16;
|
||||
case 10: c+=((uint32_t)k[9])<<8;
|
||||
case 9 : c+=k[8];
|
||||
case 8 : b+=((uint32_t)k[7])<<24;
|
||||
case 7 : b+=((uint32_t)k[6])<<16;
|
||||
case 6 : b+=((uint32_t)k[5])<<8;
|
||||
case 5 : b+=k[4];
|
||||
case 4 : a+=((uint32_t)k[3])<<24;
|
||||
case 3 : a+=((uint32_t)k[2])<<16;
|
||||
case 2 : a+=((uint32_t)k[1])<<8;
|
||||
case 1 : a+=k[0];
|
||||
break;
|
||||
case 0 : return c;
|
||||
}
|
||||
}
|
||||
|
||||
final(a,b,c);
|
||||
*val2 = b;
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* hashbig():
|
||||
* This is the same as hash_word() on big-endian machines. It is different
|
||||
* from hashlittle() on all machines. hashbig() takes advantage of
|
||||
* big-endian byte ordering.
|
||||
*/
|
||||
static uint32_t hashbig( const void *key, size_t length, uint32_t *val2)
|
||||
{
|
||||
uint32_t a,b,c;
|
||||
union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = 0xdeadbeef + ((uint32_t)length) + *val2;
|
||||
|
||||
u.ptr = key;
|
||||
if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) {
|
||||
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
|
||||
const uint8_t *k8;
|
||||
|
||||
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
|
||||
while (length > 12)
|
||||
{
|
||||
a += k[0];
|
||||
b += k[1];
|
||||
c += k[2];
|
||||
mix(a,b,c);
|
||||
length -= 12;
|
||||
k += 3;
|
||||
}
|
||||
|
||||
/*----------------------------- handle the last (probably partial) block */
|
||||
/*
|
||||
* "k[2]<<8" actually reads beyond the end of the string, but
|
||||
* then shifts out the part it's not allowed to read. Because the
|
||||
* string is aligned, the illegal read is in the same word as the
|
||||
* rest of the string. Every machine with memory protection I've seen
|
||||
* does it on word boundaries, so is OK with this. But VALGRIND will
|
||||
* still catch it and complain. The masking trick does make the hash
|
||||
* noticably faster for short strings (like English words).
|
||||
*
|
||||
* Not on my testing with gcc 4.5 on an intel i5 CPU, at least --RR.
|
||||
*/
|
||||
#if 0
|
||||
switch(length)
|
||||
{
|
||||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
|
||||
case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break;
|
||||
case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break;
|
||||
case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break;
|
||||
case 8 : b+=k[1]; a+=k[0]; break;
|
||||
case 7 : b+=k[1]&0xffffff00; a+=k[0]; break;
|
||||
case 6 : b+=k[1]&0xffff0000; a+=k[0]; break;
|
||||
case 5 : b+=k[1]&0xff000000; a+=k[0]; break;
|
||||
case 4 : a+=k[0]; break;
|
||||
case 3 : a+=k[0]&0xffffff00; break;
|
||||
case 2 : a+=k[0]&0xffff0000; break;
|
||||
case 1 : a+=k[0]&0xff000000; break;
|
||||
case 0 : return c; /* zero length strings require no mixing */
|
||||
}
|
||||
|
||||
#else /* make valgrind happy */
|
||||
|
||||
k8 = (const uint8_t *)k;
|
||||
switch(length) /* all the case statements fall through */
|
||||
{
|
||||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
|
||||
case 11: c+=((uint32_t)k8[10])<<8; /* fall through */
|
||||
case 10: c+=((uint32_t)k8[9])<<16; /* fall through */
|
||||
case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */
|
||||
case 8 : b+=k[1]; a+=k[0]; break;
|
||||
case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */
|
||||
case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */
|
||||
case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */
|
||||
case 4 : a+=k[0]; break;
|
||||
case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */
|
||||
case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */
|
||||
case 1 : a+=((uint32_t)k8[0])<<24; break;
|
||||
case 0 : return c;
|
||||
}
|
||||
|
||||
#endif /* !VALGRIND */
|
||||
|
||||
} else { /* need to read the key one byte at a time */
|
||||
const uint8_t *k = (const uint8_t *)key;
|
||||
|
||||
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */
|
||||
while (length > 12)
|
||||
{
|
||||
a += ((uint32_t)k[0])<<24;
|
||||
a += ((uint32_t)k[1])<<16;
|
||||
a += ((uint32_t)k[2])<<8;
|
||||
a += ((uint32_t)k[3]);
|
||||
b += ((uint32_t)k[4])<<24;
|
||||
b += ((uint32_t)k[5])<<16;
|
||||
b += ((uint32_t)k[6])<<8;
|
||||
b += ((uint32_t)k[7]);
|
||||
c += ((uint32_t)k[8])<<24;
|
||||
c += ((uint32_t)k[9])<<16;
|
||||
c += ((uint32_t)k[10])<<8;
|
||||
c += ((uint32_t)k[11]);
|
||||
mix(a,b,c);
|
||||
length -= 12;
|
||||
k += 12;
|
||||
}
|
||||
|
||||
/*-------------------------------- last block: affect all 32 bits of (c) */
|
||||
switch(length) /* all the case statements fall through */
|
||||
{
|
||||
case 12: c+=k[11];
|
||||
case 11: c+=((uint32_t)k[10])<<8;
|
||||
case 10: c+=((uint32_t)k[9])<<16;
|
||||
case 9 : c+=((uint32_t)k[8])<<24;
|
||||
case 8 : b+=k[7];
|
||||
case 7 : b+=((uint32_t)k[6])<<8;
|
||||
case 6 : b+=((uint32_t)k[5])<<16;
|
||||
case 5 : b+=((uint32_t)k[4])<<24;
|
||||
case 4 : a+=k[3];
|
||||
case 3 : a+=((uint32_t)k[2])<<8;
|
||||
case 2 : a+=((uint32_t)k[1])<<16;
|
||||
case 1 : a+=((uint32_t)k[0])<<24;
|
||||
break;
|
||||
case 0 : return c;
|
||||
}
|
||||
}
|
||||
|
||||
final(a,b,c);
|
||||
*val2 = b;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* I basically use hashlittle here, but use native endian within each
|
||||
* element. This delivers least-surprise: hash such as "int arr[] = {
|
||||
* 1, 2 }; hash_stable(arr, 2, 0);" will be the same on big and little
|
||||
* endian machines, even though a bytewise hash wouldn't be. */
|
||||
uint64_t hash64_stable_64(const void *key, size_t n, uint64_t base)
|
||||
{
|
||||
const uint64_t *k = key;
|
||||
uint32_t a,b,c;
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = 0xdeadbeef + ((uint32_t)n*8) + (base >> 32) + base;
|
||||
|
||||
while (n > 3) {
|
||||
a += (uint32_t)k[0];
|
||||
b += (uint32_t)(k[0] >> 32);
|
||||
c += (uint32_t)k[1];
|
||||
mix(a,b,c);
|
||||
a += (uint32_t)(k[1] >> 32);
|
||||
b += (uint32_t)k[2];
|
||||
c += (uint32_t)(k[2] >> 32);
|
||||
mix(a,b,c);
|
||||
n -= 3;
|
||||
k += 3;
|
||||
}
|
||||
switch (n) {
|
||||
case 2:
|
||||
a += (uint32_t)k[0];
|
||||
b += (uint32_t)(k[0] >> 32);
|
||||
c += (uint32_t)k[1];
|
||||
mix(a,b,c);
|
||||
a += (uint32_t)(k[1] >> 32);
|
||||
break;
|
||||
case 1:
|
||||
a += (uint32_t)k[0];
|
||||
b += (uint32_t)(k[0] >> 32);
|
||||
break;
|
||||
case 0:
|
||||
return c;
|
||||
}
|
||||
final(a,b,c);
|
||||
return ((uint64_t)b << 32) | c;
|
||||
}
|
||||
|
||||
uint64_t hash64_stable_32(const void *key, size_t n, uint64_t base)
|
||||
{
|
||||
const uint32_t *k = key;
|
||||
uint32_t a,b,c;
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = 0xdeadbeef + ((uint32_t)n*4) + (base >> 32) + base;
|
||||
|
||||
while (n > 3) {
|
||||
a += k[0];
|
||||
b += k[1];
|
||||
c += k[2];
|
||||
mix(a,b,c);
|
||||
|
||||
n -= 3;
|
||||
k += 3;
|
||||
}
|
||||
switch (n) {
|
||||
case 2:
|
||||
b += (uint32_t)k[1];
|
||||
case 1:
|
||||
a += (uint32_t)k[0];
|
||||
break;
|
||||
case 0:
|
||||
return c;
|
||||
}
|
||||
final(a,b,c);
|
||||
return ((uint64_t)b << 32) | c;
|
||||
}
|
||||
|
||||
uint64_t hash64_stable_16(const void *key, size_t n, uint64_t base)
|
||||
{
|
||||
const uint16_t *k = key;
|
||||
uint32_t a,b,c;
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = 0xdeadbeef + ((uint32_t)n*2) + (base >> 32) + base;
|
||||
|
||||
while (n > 6) {
|
||||
a += (uint32_t)k[0] + ((uint32_t)k[1] << 16);
|
||||
b += (uint32_t)k[2] + ((uint32_t)k[3] << 16);
|
||||
c += (uint32_t)k[4] + ((uint32_t)k[5] << 16);
|
||||
mix(a,b,c);
|
||||
|
||||
n -= 6;
|
||||
k += 6;
|
||||
}
|
||||
|
||||
switch (n) {
|
||||
case 5:
|
||||
c += (uint32_t)k[4];
|
||||
case 4:
|
||||
b += ((uint32_t)k[3] << 16);
|
||||
case 3:
|
||||
b += (uint32_t)k[2];
|
||||
case 2:
|
||||
a += ((uint32_t)k[1] << 16);
|
||||
case 1:
|
||||
a += (uint32_t)k[0];
|
||||
break;
|
||||
case 0:
|
||||
return c;
|
||||
}
|
||||
final(a,b,c);
|
||||
return ((uint64_t)b << 32) | c;
|
||||
}
|
||||
|
||||
uint64_t hash64_stable_8(const void *key, size_t n, uint64_t base)
|
||||
{
|
||||
uint32_t b32 = base + (base >> 32);
|
||||
uint32_t lower = hashlittle(key, n, &b32);
|
||||
|
||||
return ((uint64_t)b32 << 32) | lower;
|
||||
}
|
||||
|
||||
uint32_t hash_any(const void *key, size_t length, uint32_t base)
|
||||
{
|
||||
if (HASH_BIG_ENDIAN)
|
||||
return hashbig(key, length, &base);
|
||||
else
|
||||
return hashlittle(key, length, &base);
|
||||
}
|
||||
|
||||
uint32_t hash_stable_64(const void *key, size_t n, uint32_t base)
|
||||
{
|
||||
return hash64_stable_64(key, n, base);
|
||||
}
|
||||
|
||||
uint32_t hash_stable_32(const void *key, size_t n, uint32_t base)
|
||||
{
|
||||
return hash64_stable_32(key, n, base);
|
||||
}
|
||||
|
||||
uint32_t hash_stable_16(const void *key, size_t n, uint32_t base)
|
||||
{
|
||||
return hash64_stable_16(key, n, base);
|
||||
}
|
||||
|
||||
uint32_t hash_stable_8(const void *key, size_t n, uint32_t base)
|
||||
{
|
||||
return hashlittle(key, n, &base);
|
||||
}
|
||||
|
||||
/* Jenkins' lookup8 is a 64 bit hash, but he says it's obsolete. Use
|
||||
* the plain one and recombine into 64 bits. */
|
||||
uint64_t hash64_any(const void *key, size_t length, uint64_t base)
|
||||
{
|
||||
uint32_t b32 = base + (base >> 32);
|
||||
uint32_t lower;
|
||||
|
||||
if (HASH_BIG_ENDIAN)
|
||||
lower = hashbig(key, length, &b32);
|
||||
else
|
||||
lower = hashlittle(key, length, &b32);
|
||||
|
||||
return ((uint64_t)b32 << 32) | lower;
|
||||
}
|
||||
|
||||
#ifdef SELF_TEST
|
||||
|
||||
/* used for timings */
|
||||
void driver1()
|
||||
{
|
||||
uint8_t buf[256];
|
||||
uint32_t i;
|
||||
uint32_t h=0;
|
||||
time_t a,z;
|
||||
|
||||
time(&a);
|
||||
for (i=0; i<256; ++i) buf[i] = 'x';
|
||||
for (i=0; i<1; ++i)
|
||||
{
|
||||
h = hashlittle(&buf[0],1,h);
|
||||
}
|
||||
time(&z);
|
||||
if (z-a > 0) printf("time %d %.8x\n", z-a, h);
|
||||
}
|
||||
|
||||
/* check that every input bit changes every output bit half the time */
|
||||
#define HASHSTATE 1
|
||||
#define HASHLEN 1
|
||||
#define MAXPAIR 60
|
||||
#define MAXLEN 70
|
||||
void driver2()
|
||||
{
|
||||
uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1];
|
||||
uint32_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z;
|
||||
uint32_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE];
|
||||
uint32_t x[HASHSTATE],y[HASHSTATE];
|
||||
uint32_t hlen;
|
||||
|
||||
printf("No more than %d trials should ever be needed \n",MAXPAIR/2);
|
||||
for (hlen=0; hlen < MAXLEN; ++hlen)
|
||||
{
|
||||
z=0;
|
||||
for (i=0; i<hlen; ++i) /*----------------------- for each input byte, */
|
||||
{
|
||||
for (j=0; j<8; ++j) /*------------------------ for each input bit, */
|
||||
{
|
||||
for (m=1; m<8; ++m) /*------------ for several possible initvals, */
|
||||
{
|
||||
for (l=0; l<HASHSTATE; ++l)
|
||||
e[l]=f[l]=g[l]=h[l]=x[l]=y[l]=~((uint32_t)0);
|
||||
|
||||
/*---- check that every output bit is affected by that input bit */
|
||||
for (k=0; k<MAXPAIR; k+=2)
|
||||
{
|
||||
uint32_t finished=1;
|
||||
/* keys have one bit different */
|
||||
for (l=0; l<hlen+1; ++l) {a[l] = b[l] = (uint8_t)0;}
|
||||
/* have a and b be two keys differing in only one bit */
|
||||
a[i] ^= (k<<j);
|
||||
a[i] ^= (k>>(8-j));
|
||||
c[0] = hashlittle(a, hlen, m);
|
||||
b[i] ^= ((k+1)<<j);
|
||||
b[i] ^= ((k+1)>>(8-j));
|
||||
d[0] = hashlittle(b, hlen, m);
|
||||
/* check every bit is 1, 0, set, and not set at least once */
|
||||
for (l=0; l<HASHSTATE; ++l)
|
||||
{
|
||||
e[l] &= (c[l]^d[l]);
|
||||
f[l] &= ~(c[l]^d[l]);
|
||||
g[l] &= c[l];
|
||||
h[l] &= ~c[l];
|
||||
x[l] &= d[l];
|
||||
y[l] &= ~d[l];
|
||||
if (e[l]|f[l]|g[l]|h[l]|x[l]|y[l]) finished=0;
|
||||
}
|
||||
if (finished) break;
|
||||
}
|
||||
if (k>z) z=k;
|
||||
if (k==MAXPAIR)
|
||||
{
|
||||
printf("Some bit didn't change: ");
|
||||
printf("%.8x %.8x %.8x %.8x %.8x %.8x ",
|
||||
e[0],f[0],g[0],h[0],x[0],y[0]);
|
||||
printf("i %d j %d m %d len %d\n", i, j, m, hlen);
|
||||
}
|
||||
if (z==MAXPAIR) goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
if (z < MAXPAIR)
|
||||
{
|
||||
printf("Mix success %2d bytes %2d initvals ",i,m);
|
||||
printf("required %d trials\n", z/2);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Check for reading beyond the end of the buffer and alignment problems */
|
||||
void driver3()
|
||||
{
|
||||
uint8_t buf[MAXLEN+20], *b;
|
||||
uint32_t len;
|
||||
uint8_t q[] = "This is the time for all good men to come to the aid of their country...";
|
||||
uint32_t h;
|
||||
uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country...";
|
||||
uint32_t i;
|
||||
uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country...";
|
||||
uint32_t j;
|
||||
uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country...";
|
||||
uint32_t ref,x,y;
|
||||
uint8_t *p;
|
||||
|
||||
printf("Endianness. These lines should all be the same (for values filled in):\n");
|
||||
printf("%.8x %.8x %.8x\n",
|
||||
hash_word((const uint32_t *)q, (sizeof(q)-1)/4, 13),
|
||||
hash_word((const uint32_t *)q, (sizeof(q)-5)/4, 13),
|
||||
hash_word((const uint32_t *)q, (sizeof(q)-9)/4, 13));
|
||||
p = q;
|
||||
printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
|
||||
hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
|
||||
hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
|
||||
hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
|
||||
hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
|
||||
hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
|
||||
hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
|
||||
p = &qq[1];
|
||||
printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
|
||||
hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
|
||||
hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
|
||||
hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
|
||||
hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
|
||||
hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
|
||||
hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
|
||||
p = &qqq[2];
|
||||
printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
|
||||
hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
|
||||
hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
|
||||
hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
|
||||
hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
|
||||
hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
|
||||
hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
|
||||
p = &qqqq[3];
|
||||
printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n",
|
||||
hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13),
|
||||
hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13),
|
||||
hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13),
|
||||
hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13),
|
||||
hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13),
|
||||
hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13));
|
||||
printf("\n");
|
||||
|
||||
/* check that hashlittle2 and hashlittle produce the same results */
|
||||
i=47; j=0;
|
||||
hashlittle2(q, sizeof(q), &i, &j);
|
||||
if (hashlittle(q, sizeof(q), 47) != i)
|
||||
printf("hashlittle2 and hashlittle mismatch\n");
|
||||
|
||||
/* check that hash_word2 and hash_word produce the same results */
|
||||
len = 0xdeadbeef;
|
||||
i=47, j=0;
|
||||
hash_word2(&len, 1, &i, &j);
|
||||
if (hash_word(&len, 1, 47) != i)
|
||||
printf("hash_word2 and hash_word mismatch %x %x\n",
|
||||
i, hash_word(&len, 1, 47));
|
||||
|
||||
/* check hashlittle doesn't read before or after the ends of the string */
|
||||
for (h=0, b=buf+1; h<8; ++h, ++b)
|
||||
{
|
||||
for (i=0; i<MAXLEN; ++i)
|
||||
{
|
||||
len = i;
|
||||
for (j=0; j<i; ++j) *(b+j)=0;
|
||||
|
||||
/* these should all be equal */
|
||||
ref = hashlittle(b, len, (uint32_t)1);
|
||||
*(b+i)=(uint8_t)~0;
|
||||
*(b-1)=(uint8_t)~0;
|
||||
x = hashlittle(b, len, (uint32_t)1);
|
||||
y = hashlittle(b, len, (uint32_t)1);
|
||||
if ((ref != x) || (ref != y))
|
||||
{
|
||||
printf("alignment error: %.8x %.8x %.8x %d %d\n",ref,x,y,
|
||||
h, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for problems with nulls */
|
||||
void driver4()
|
||||
{
|
||||
uint8_t buf[1];
|
||||
uint32_t h,i,state[HASHSTATE];
|
||||
|
||||
|
||||
buf[0] = ~0;
|
||||
for (i=0; i<HASHSTATE; ++i) state[i] = 1;
|
||||
printf("These should all be different\n");
|
||||
for (i=0, h=0; i<8; ++i)
|
||||
{
|
||||
h = hashlittle(buf, 0, h);
|
||||
printf("%2ld 0-byte strings, hash is %.8x\n", i, h);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
driver1(); /* test that the key is hashed: used for timings */
|
||||
driver2(); /* test that whole key is hashed thoroughly */
|
||||
driver3(); /* test that nothing but the key is hashed */
|
||||
driver4(); /* test hashing multiple buffers (all buffers are null) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* SELF_TEST */
|
313
ccan/ccan/hash/hash.h
Normal file
313
ccan/ccan/hash/hash.h
Normal file
@ -0,0 +1,313 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#ifndef CCAN_HASH_H
|
||||
#define CCAN_HASH_H
|
||||
#include "config.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <ccan/build_assert/build_assert.h>
|
||||
|
||||
/* Stolen mostly from: lookup3.c, by Bob Jenkins, May 2006, Public Domain.
|
||||
*
|
||||
* http://burtleburtle.net/bob/c/lookup3.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* hash - fast hash of an array for internal use
|
||||
* @p: the array or pointer to first element
|
||||
* @num: the number of elements to hash
|
||||
* @base: the base number to roll into the hash (usually 0)
|
||||
*
|
||||
* The memory region pointed to by p is combined with the base to form
|
||||
* a 32-bit hash.
|
||||
*
|
||||
* This hash will have different results on different machines, so is
|
||||
* only useful for internal hashes (ie. not hashes sent across the
|
||||
* network or saved to disk).
|
||||
*
|
||||
* It may also change with future versions: it could even detect at runtime
|
||||
* what the fastest hash to use is.
|
||||
*
|
||||
* See also: hash64, hash_stable.
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/hash/hash.h>
|
||||
* #include <err.h>
|
||||
* #include <stdio.h>
|
||||
* #include <string.h>
|
||||
*
|
||||
* // Simple demonstration: idential strings will have the same hash, but
|
||||
* // two different strings will probably not.
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* uint32_t hash1, hash2;
|
||||
*
|
||||
* if (argc != 3)
|
||||
* err(1, "Usage: %s <string1> <string2>", argv[0]);
|
||||
*
|
||||
* hash1 = hash(argv[1], strlen(argv[1]), 0);
|
||||
* hash2 = hash(argv[2], strlen(argv[2]), 0);
|
||||
* printf("Hash is %s\n", hash1 == hash2 ? "same" : "different");
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
#define hash(p, num, base) hash_any((p), (num)*sizeof(*(p)), (base))
|
||||
|
||||
/**
|
||||
* hash_stable - hash of an array for external use
|
||||
* @p: the array or pointer to first element
|
||||
* @num: the number of elements to hash
|
||||
* @base: the base number to roll into the hash (usually 0)
|
||||
*
|
||||
* The array of simple integer types pointed to by p is combined with
|
||||
* the base to form a 32-bit hash.
|
||||
*
|
||||
* This hash will have the same results on different machines, so can
|
||||
* be used for external hashes (ie. hashes sent across the network or
|
||||
* saved to disk). The results will not change in future versions of
|
||||
* this module.
|
||||
*
|
||||
* Note that it is only legal to hand an array of simple integer types
|
||||
* to this hash (ie. char, uint16_t, int64_t, etc). In these cases,
|
||||
* the same values will have the same hash result, even though the
|
||||
* memory representations of integers depend on the machine
|
||||
* endianness.
|
||||
*
|
||||
* See also:
|
||||
* hash64_stable
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/hash/hash.h>
|
||||
* #include <err.h>
|
||||
* #include <stdio.h>
|
||||
* #include <string.h>
|
||||
*
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* if (argc != 2)
|
||||
* err(1, "Usage: %s <string-to-hash>", argv[0]);
|
||||
*
|
||||
* printf("Hash stable result is %u\n",
|
||||
* hash_stable(argv[1], strlen(argv[1]), 0));
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
#define hash_stable(p, num, base) \
|
||||
(BUILD_ASSERT_OR_ZERO(sizeof(*(p)) == 8 || sizeof(*(p)) == 4 \
|
||||
|| sizeof(*(p)) == 2 || sizeof(*(p)) == 1) + \
|
||||
sizeof(*(p)) == 8 ? hash_stable_64((p), (num), (base)) \
|
||||
: sizeof(*(p)) == 4 ? hash_stable_32((p), (num), (base)) \
|
||||
: sizeof(*(p)) == 2 ? hash_stable_16((p), (num), (base)) \
|
||||
: hash_stable_8((p), (num), (base)))
|
||||
|
||||
/**
|
||||
* hash_u32 - fast hash an array of 32-bit values for internal use
|
||||
* @key: the array of uint32_t
|
||||
* @num: the number of elements to hash
|
||||
* @base: the base number to roll into the hash (usually 0)
|
||||
*
|
||||
* The array of uint32_t pointed to by @key is combined with the base
|
||||
* to form a 32-bit hash. This is 2-3 times faster than hash() on small
|
||||
* arrays, but the advantage vanishes over large hashes.
|
||||
*
|
||||
* This hash will have different results on different machines, so is
|
||||
* only useful for internal hashes (ie. not hashes sent across the
|
||||
* network or saved to disk).
|
||||
*/
|
||||
uint32_t hash_u32(const uint32_t *key, size_t num, uint32_t base);
|
||||
|
||||
/**
|
||||
* hash_string - very fast hash of an ascii string
|
||||
* @str: the nul-terminated string
|
||||
*
|
||||
* The string is hashed, using a hash function optimized for ASCII and
|
||||
* similar strings. It's weaker than the other hash functions.
|
||||
*
|
||||
* This hash may have different results on different machines, so is
|
||||
* only useful for internal hashes (ie. not hashes sent across the
|
||||
* network or saved to disk). The results will be different from the
|
||||
* other hash functions in this module, too.
|
||||
*/
|
||||
static inline uint32_t hash_string(const char *string)
|
||||
{
|
||||
/* This is Karl Nelson <kenelson@ece.ucdavis.edu>'s X31 hash.
|
||||
* It's a little faster than the (much better) lookup3 hash(): 56ns vs
|
||||
* 84ns on my 2GHz Intel Core Duo 2 laptop for a 10 char string. */
|
||||
uint32_t ret;
|
||||
|
||||
for (ret = 0; *string; string++)
|
||||
ret = (ret << 5) - ret + *string;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* hash64 - fast 64-bit hash of an array for internal use
|
||||
* @p: the array or pointer to first element
|
||||
* @num: the number of elements to hash
|
||||
* @base: the 64-bit base number to roll into the hash (usually 0)
|
||||
*
|
||||
* The memory region pointed to by p is combined with the base to form
|
||||
* a 64-bit hash.
|
||||
*
|
||||
* This hash will have different results on different machines, so is
|
||||
* only useful for internal hashes (ie. not hashes sent across the
|
||||
* network or saved to disk).
|
||||
*
|
||||
* It may also change with future versions: it could even detect at runtime
|
||||
* what the fastest hash to use is.
|
||||
*
|
||||
* See also: hash.
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/hash/hash.h>
|
||||
* #include <err.h>
|
||||
* #include <stdio.h>
|
||||
* #include <string.h>
|
||||
*
|
||||
* // Simple demonstration: idential strings will have the same hash, but
|
||||
* // two different strings will probably not.
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* uint64_t hash1, hash2;
|
||||
*
|
||||
* if (argc != 3)
|
||||
* err(1, "Usage: %s <string1> <string2>", argv[0]);
|
||||
*
|
||||
* hash1 = hash64(argv[1], strlen(argv[1]), 0);
|
||||
* hash2 = hash64(argv[2], strlen(argv[2]), 0);
|
||||
* printf("Hash is %s\n", hash1 == hash2 ? "same" : "different");
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
#define hash64(p, num, base) hash64_any((p), (num)*sizeof(*(p)), (base))
|
||||
|
||||
/**
|
||||
* hash64_stable - 64 bit hash of an array for external use
|
||||
* @p: the array or pointer to first element
|
||||
* @num: the number of elements to hash
|
||||
* @base: the base number to roll into the hash (usually 0)
|
||||
*
|
||||
* The array of simple integer types pointed to by p is combined with
|
||||
* the base to form a 64-bit hash.
|
||||
*
|
||||
* This hash will have the same results on different machines, so can
|
||||
* be used for external hashes (ie. hashes sent across the network or
|
||||
* saved to disk). The results will not change in future versions of
|
||||
* this module.
|
||||
*
|
||||
* Note that it is only legal to hand an array of simple integer types
|
||||
* to this hash (ie. char, uint16_t, int64_t, etc). In these cases,
|
||||
* the same values will have the same hash result, even though the
|
||||
* memory representations of integers depend on the machine
|
||||
* endianness.
|
||||
*
|
||||
* See also:
|
||||
* hash_stable
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/hash/hash.h>
|
||||
* #include <err.h>
|
||||
* #include <stdio.h>
|
||||
* #include <string.h>
|
||||
*
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* if (argc != 2)
|
||||
* err(1, "Usage: %s <string-to-hash>", argv[0]);
|
||||
*
|
||||
* printf("Hash stable result is %llu\n",
|
||||
* (long long)hash64_stable(argv[1], strlen(argv[1]), 0));
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
#define hash64_stable(p, num, base) \
|
||||
(BUILD_ASSERT_OR_ZERO(sizeof(*(p)) == 8 || sizeof(*(p)) == 4 \
|
||||
|| sizeof(*(p)) == 2 || sizeof(*(p)) == 1) + \
|
||||
sizeof(*(p)) == 8 ? hash64_stable_64((p), (num), (base)) \
|
||||
: sizeof(*(p)) == 4 ? hash64_stable_32((p), (num), (base)) \
|
||||
: sizeof(*(p)) == 2 ? hash64_stable_16((p), (num), (base)) \
|
||||
: hash64_stable_8((p), (num), (base)))
|
||||
|
||||
|
||||
/**
|
||||
* hashl - fast 32/64-bit hash of an array for internal use
|
||||
* @p: the array or pointer to first element
|
||||
* @num: the number of elements to hash
|
||||
* @base: the base number to roll into the hash (usually 0)
|
||||
*
|
||||
* This is either hash() or hash64(), on 32/64 bit long machines.
|
||||
*/
|
||||
#define hashl(p, num, base) \
|
||||
(BUILD_ASSERT_OR_ZERO(sizeof(long) == sizeof(uint32_t) \
|
||||
|| sizeof(long) == sizeof(uint64_t)) + \
|
||||
(sizeof(long) == sizeof(uint64_t) \
|
||||
? hash64((p), (num), (base)) : hash((p), (num), (base))))
|
||||
|
||||
/* Our underlying operations. */
|
||||
uint32_t hash_any(const void *key, size_t length, uint32_t base);
|
||||
uint32_t hash_stable_64(const void *key, size_t n, uint32_t base);
|
||||
uint32_t hash_stable_32(const void *key, size_t n, uint32_t base);
|
||||
uint32_t hash_stable_16(const void *key, size_t n, uint32_t base);
|
||||
uint32_t hash_stable_8(const void *key, size_t n, uint32_t base);
|
||||
uint64_t hash64_any(const void *key, size_t length, uint64_t base);
|
||||
uint64_t hash64_stable_64(const void *key, size_t n, uint64_t base);
|
||||
uint64_t hash64_stable_32(const void *key, size_t n, uint64_t base);
|
||||
uint64_t hash64_stable_16(const void *key, size_t n, uint64_t base);
|
||||
uint64_t hash64_stable_8(const void *key, size_t n, uint64_t base);
|
||||
|
||||
/**
|
||||
* hash_pointer - hash a pointer for internal use
|
||||
* @p: the pointer value to hash
|
||||
* @base: the base number to roll into the hash (usually 0)
|
||||
*
|
||||
* The pointer p (not what p points to!) is combined with the base to form
|
||||
* a 32-bit hash.
|
||||
*
|
||||
* This hash will have different results on different machines, so is
|
||||
* only useful for internal hashes (ie. not hashes sent across the
|
||||
* network or saved to disk).
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/hash/hash.h>
|
||||
*
|
||||
* // Code to keep track of memory regions.
|
||||
* struct region {
|
||||
* struct region *chain;
|
||||
* void *start;
|
||||
* unsigned int size;
|
||||
* };
|
||||
* // We keep a simple hash table.
|
||||
* static struct region *region_hash[128];
|
||||
*
|
||||
* static void add_region(struct region *r)
|
||||
* {
|
||||
* unsigned int h = hash_pointer(r->start, 0);
|
||||
*
|
||||
* r->chain = region_hash[h];
|
||||
* region_hash[h] = r->chain;
|
||||
* }
|
||||
*
|
||||
* static struct region *find_region(const void *start)
|
||||
* {
|
||||
* struct region *r;
|
||||
*
|
||||
* for (r = region_hash[hash_pointer(start, 0)]; r; r = r->chain)
|
||||
* if (r->start == start)
|
||||
* return r;
|
||||
* return NULL;
|
||||
* }
|
||||
*/
|
||||
static inline uint32_t hash_pointer(const void *p, uint32_t base)
|
||||
{
|
||||
if (sizeof(p) % sizeof(uint32_t) == 0) {
|
||||
/* This convoluted union is the right way of aliasing. */
|
||||
union {
|
||||
uint32_t a[sizeof(p) / sizeof(uint32_t)];
|
||||
const void *p;
|
||||
} u;
|
||||
u.p = p;
|
||||
return hash_u32(u.a, sizeof(p) / sizeof(uint32_t), base);
|
||||
} else
|
||||
return hash(&p, 1, base);
|
||||
}
|
||||
#endif /* HASH_H */
|
300
ccan/ccan/hash/test/api-hash_stable.c
Normal file
300
ccan/ccan/hash/test/api-hash_stable.c
Normal file
@ -0,0 +1,300 @@
|
||||
#include <ccan/hash/hash.h>
|
||||
#include <ccan/tap/tap.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ARRAY_WORDS 5
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int i;
|
||||
uint8_t u8array[ARRAY_WORDS];
|
||||
uint16_t u16array[ARRAY_WORDS];
|
||||
uint32_t u32array[ARRAY_WORDS];
|
||||
uint64_t u64array[ARRAY_WORDS];
|
||||
|
||||
/* Initialize arrays. */
|
||||
for (i = 0; i < ARRAY_WORDS; i++) {
|
||||
u8array[i] = i;
|
||||
u16array[i] = i;
|
||||
u32array[i] = i;
|
||||
u64array[i] = i;
|
||||
}
|
||||
|
||||
plan_tests(264);
|
||||
|
||||
/* hash_stable is API-guaranteed. */
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 0) == 0x1d4833cc);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 1) == 0x37125e2 );
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 2) == 0x330a007a);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 4) == 0x7b0df29b);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 8) == 0xe7e5d741);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 16) == 0xaae57471);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 32) == 0xc55399e5);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 64) == 0x67f21f7 );
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 128) == 0x1d795b71);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 256) == 0xeb961671);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 512) == 0xc2597247);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 1024) == 0x3f5c4d75);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 2048) == 0xe65cf4f9);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 4096) == 0xf2cd06cb);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 8192) == 0x443041e1);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 16384) == 0xdfc618f5);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 32768) == 0x5e3d5b97);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 65536) == 0xd5f64730);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 131072) == 0x372bbecc);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 262144) == 0x7c194c8d);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 524288) == 0x16cbb416);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 1048576) == 0x53e99222);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 2097152) == 0x6394554a);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 4194304) == 0xd83a506d);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 8388608) == 0x7619d9a4);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 16777216) == 0xfe98e5f6);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 33554432) == 0x6c262927);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 67108864) == 0x3f0106fd);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 134217728) == 0xc91e3a28);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 268435456) == 0x14229579);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 536870912) == 0x9dbefa76);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 1073741824) == 0xb05c0c78);
|
||||
ok1(hash_stable(u8array, ARRAY_WORDS, 2147483648U) == 0x88f24d81);
|
||||
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 0) == 0xecb5f507);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 1) == 0xadd666e6);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 2) == 0xea0f214c);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 4) == 0xae4051ba);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 8) == 0x6ed28026);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 16) == 0xa3917a19);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 32) == 0xf370f32b);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 64) == 0x807af460);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 128) == 0xb4c8cd83);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 256) == 0xa10cb5b0);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 512) == 0x8b7d7387);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 1024) == 0x9e49d1c );
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 2048) == 0x288830d1);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 4096) == 0xbe078a43);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 8192) == 0xa16d5d88);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 16384) == 0x46839fcd);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 32768) == 0x9db9bd4f);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 65536) == 0xedff58f8);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 131072) == 0x95ecef18);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 262144) == 0x23c31b7d);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 524288) == 0x1d85c7d0);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 1048576) == 0x25218842);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 2097152) == 0x711d985c);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 4194304) == 0x85470eca);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 8388608) == 0x99ed4ceb);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 16777216) == 0x67b3710c);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 33554432) == 0x77f1ab35);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 67108864) == 0x81f688aa);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 134217728) == 0x27b56ca5);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 268435456) == 0xf21ba203);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 536870912) == 0xd48d1d1 );
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 1073741824) == 0xa542b62d);
|
||||
ok1(hash_stable(u16array, ARRAY_WORDS, 2147483648U) == 0xa04c7058);
|
||||
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 0) == 0x13305f8c);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 1) == 0x171abf74);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 2) == 0x7646fcc7);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 4) == 0xa758ed5);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 8) == 0x2dedc2e4);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 16) == 0x28e2076b);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 32) == 0xb73091c5);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 64) == 0x87daf5db);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 128) == 0xa16dfe20);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 256) == 0x300c63c3);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 512) == 0x255c91fc);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 1024) == 0x6357b26);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 2048) == 0x4bc5f339);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 4096) == 0x1301617c);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 8192) == 0x506792c9);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 16384) == 0xcd596705);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 32768) == 0xa8713cac);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 65536) == 0x94d9794);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 131072) == 0xac753e8);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 262144) == 0xcd8bdd20);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 524288) == 0xd44faf80);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 1048576) == 0x2547ccbe);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 2097152) == 0xbab06dbc);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 4194304) == 0xaac0e882);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 8388608) == 0x443f48d0);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 16777216) == 0xdff49fcc);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 33554432) == 0x9ce0fd65);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 67108864) == 0x9ddb1def);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 134217728) == 0x86096f25);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 268435456) == 0xe713b7b5);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 536870912) == 0x5baeffc5);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 1073741824) == 0xde874f52);
|
||||
ok1(hash_stable(u32array, ARRAY_WORDS, 2147483648U) == 0xeca13b4e);
|
||||
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 0) == 0x12ef6302);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 1) == 0xe9aeb406);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 2) == 0xc4218ceb);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 4) == 0xb3d11412);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 8) == 0xdafbd654);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 16) == 0x9c336cba);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 32) == 0x65059721);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 64) == 0x95b5bbe6);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 128) == 0xe7596b84);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 256) == 0x503622a2);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 512) == 0xecdcc5ca);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 1024) == 0xc40d0513);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 2048) == 0xaab25e4d);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 4096) == 0xcc353fb9);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 8192) == 0x18e2319f);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 16384) == 0xfddaae8d);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 32768) == 0xef7976f2);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 65536) == 0x86359fc9);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 131072) == 0x8b5af385);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 262144) == 0x80d4ee31);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 524288) == 0x42f5f85b);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 1048576) == 0x9a6920e1);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 2097152) == 0x7b7c9850);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 4194304) == 0x69573e09);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 8388608) == 0xc942bc0e);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 16777216) == 0x7a89f0f1);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 33554432) == 0x2dd641ca);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 67108864) == 0x89bbd391);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 134217728) == 0xbcf88e31);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 268435456) == 0xfa7a3460);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 536870912) == 0x49a37be0);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 1073741824) == 0x1b346394);
|
||||
ok1(hash_stable(u64array, ARRAY_WORDS, 2147483648U) == 0x6c3a1592);
|
||||
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 0) == 16887282882572727244ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 1) == 12032777473133454818ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 2) == 18183407363221487738ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 4) == 17860764172704150171ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 8) == 18076051600675559233ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 16) == 9909361918431556721ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 32) == 12937969888744675813ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 64) == 5245669057381736951ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 128) == 4376874646406519665ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 256) == 14219974419871569521ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 512) == 2263415354134458951ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 1024) == 4953859694526221685ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 2048) == 3432228642067641593ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 4096) == 1219647244417697483ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 8192) == 7629939424585859553ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 16384) == 10041660531376789749ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 32768) == 13859885793922603927ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 65536) == 15069060338344675120ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 131072) == 818163430835601100ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 262144) == 14914314323019517069ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 524288) == 17518437749769352214ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 1048576) == 14920048004901212706ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 2097152) == 8758567366332536138ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 4194304) == 6226655736088907885ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 8388608) == 13716650013685832100ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 16777216) == 305325651636315638ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 33554432) == 16784147606583781671ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 67108864) == 16509467555140798205ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 134217728) == 8717281234694060584ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 268435456) == 8098476701725660537ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 536870912) == 16345871539461094006ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 1073741824) == 3755557000429964408ULL);
|
||||
ok1(hash64_stable(u8array, ARRAY_WORDS, 2147483648U) == 15017348801959710081ULL);
|
||||
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 0) == 1038028831307724039ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 1) == 10155473272642627302ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 2) == 5714751190106841420ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 4) == 3923885607767527866ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 8) == 3931017318293995558ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 16) == 1469696588339313177ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 32) == 11522218526952715051ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 64) == 6953517591561958496ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 128) == 7406689491740052867ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 256) == 10101844489704093104ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 512) == 12511348870707245959ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 1024) == 1614019938016861468ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 2048) == 5294796182374592721ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 4096) == 16089570706643716675ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 8192) == 1689302638424579464ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 16384) == 1446340172370386893ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 32768) == 16535503506744393039ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 65536) == 3496794142527150328ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 131072) == 6568245367474548504ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 262144) == 9487676460765485949ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 524288) == 4519762130966530000ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 1048576) == 15623412069215340610ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 2097152) == 544013388676438108ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 4194304) == 5594904760290840266ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 8388608) == 18098755780041592043ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 16777216) == 6389168672387330316ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 33554432) == 896986127732419381ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 67108864) == 13232626471143901354ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 134217728) == 53378562890493093ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 268435456) == 10072361400297824771ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 536870912) == 14511948118285144529ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 1073741824) == 6981033484844447277ULL);
|
||||
ok1(hash64_stable(u16array, ARRAY_WORDS, 2147483648U) == 5619339091684126808ULL);
|
||||
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 0) == 3037571077312110476ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 1) == 14732398743825071988ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 2) == 14949132158206672071ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 4) == 1291370080511561429ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 8) == 10792665964172133092ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 16) == 14250138032054339435ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 32) == 17136741522078732741ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 64) == 3260193403318236635ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 128) == 10526616652205653536ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 256) == 9019690373358576579ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 512) == 6997491436599677436ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 1024) == 18302783371416533798ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 2048) == 10149320644446516025ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 4096) == 7073759949410623868ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 8192) == 17442399482223760073ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 16384) == 2983906194216281861ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 32768) == 4975845419129060524ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 65536) == 594019910205413268ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 131072) == 11903010186073691112ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 262144) == 7339636527154847008ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 524288) == 15243305400579108736ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 1048576) == 16737926245392043198ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 2097152) == 15725083267699862972ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 4194304) == 12527834265678833794ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 8388608) == 13908436455987824848ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 16777216) == 9672773345173872588ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 33554432) == 2305314279896710501ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 67108864) == 1866733780381408751ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 134217728) == 11906263969465724709ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 268435456) == 5501594918093830069ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 536870912) == 15823785789276225477ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 1073741824) == 17353000723889475410ULL);
|
||||
ok1(hash64_stable(u32array, ARRAY_WORDS, 2147483648U) == 7494736910655503182ULL);
|
||||
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 0) == 9765419389786481410ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 1) == 11182806172127114246ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 2) == 2559155171395472619ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 4) == 3311692033324815378ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 8) == 1297175419505333844ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 16) == 617896928653569210ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 32) == 1517398559958603553ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 64) == 4504821917445110758ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 128) == 1971743331114904452ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 256) == 6177667912354374306ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 512) == 15570521289777792458ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 1024) == 9204559632415917331ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 2048) == 9008982669760028237ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 4096) == 14803537660281700281ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 8192) == 2873966517448487327ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 16384) == 5859277625928363661ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 32768) == 15520461285618185970ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 65536) == 16746489793331175369ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 131072) == 514952025484227461ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 262144) == 10867212269810675249ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 524288) == 9822204377278314587ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 1048576) == 3295088921987850465ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 2097152) == 7559197431498053712ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 4194304) == 1667267269116771849ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 8388608) == 2916804068951374862ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 16777216) == 14422558383125688561ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 33554432) == 10083112683694342602ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 67108864) == 7222777647078298513ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 134217728) == 18424513674048212529ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 268435456) == 14913668581101810784ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 536870912) == 14377721174297902048ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 1073741824) == 6031715005667500948ULL);
|
||||
ok1(hash64_stable(u64array, ARRAY_WORDS, 2147483648U) == 4827100319722378642ULL);
|
||||
|
||||
return exit_status();
|
||||
}
|
149
ccan/ccan/hash/test/run.c
Normal file
149
ccan/ccan/hash/test/run.c
Normal file
@ -0,0 +1,149 @@
|
||||
#include <ccan/hash/hash.h>
|
||||
#include <ccan/tap/tap.h>
|
||||
#include <ccan/hash/hash.c>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ARRAY_WORDS 5
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int i, j, k;
|
||||
uint32_t array[ARRAY_WORDS], val;
|
||||
char array2[sizeof(array) + sizeof(uint32_t)];
|
||||
uint32_t results[256];
|
||||
|
||||
/* Initialize array. */
|
||||
for (i = 0; i < ARRAY_WORDS; i++)
|
||||
array[i] = i;
|
||||
|
||||
plan_tests(39);
|
||||
/* Hash should be the same, indep of memory alignment. */
|
||||
val = hash(array, ARRAY_WORDS, 0);
|
||||
for (i = 0; i < sizeof(uint32_t); i++) {
|
||||
memcpy(array2 + i, array, sizeof(array));
|
||||
ok(hash(array2 + i, ARRAY_WORDS, 0) != val,
|
||||
"hash matched at offset %i", i);
|
||||
}
|
||||
|
||||
/* Hash of random values should have random distribution:
|
||||
* check one byte at a time. */
|
||||
for (i = 0; i < sizeof(uint32_t); i++) {
|
||||
unsigned int lowest = -1U, highest = 0;
|
||||
|
||||
memset(results, 0, sizeof(results));
|
||||
|
||||
for (j = 0; j < 256000; j++) {
|
||||
for (k = 0; k < ARRAY_WORDS; k++)
|
||||
array[k] = random();
|
||||
results[(hash(array, ARRAY_WORDS, 0) >> i*8)&0xFF]++;
|
||||
}
|
||||
|
||||
for (j = 0; j < 256; j++) {
|
||||
if (results[j] < lowest)
|
||||
lowest = results[j];
|
||||
if (results[j] > highest)
|
||||
highest = results[j];
|
||||
}
|
||||
/* Expect within 20% */
|
||||
ok(lowest > 800, "Byte %i lowest %i", i, lowest);
|
||||
ok(highest < 1200, "Byte %i highest %i", i, highest);
|
||||
diag("Byte %i, range %u-%u", i, lowest, highest);
|
||||
}
|
||||
|
||||
/* Hash of random values should have random distribution:
|
||||
* check one byte at a time. */
|
||||
for (i = 0; i < sizeof(uint64_t); i++) {
|
||||
unsigned int lowest = -1U, highest = 0;
|
||||
|
||||
memset(results, 0, sizeof(results));
|
||||
|
||||
for (j = 0; j < 256000; j++) {
|
||||
for (k = 0; k < ARRAY_WORDS; k++)
|
||||
array[k] = random();
|
||||
results[(hash64(array, sizeof(array)/sizeof(uint64_t),
|
||||
0) >> i*8)&0xFF]++;
|
||||
}
|
||||
|
||||
for (j = 0; j < 256; j++) {
|
||||
if (results[j] < lowest)
|
||||
lowest = results[j];
|
||||
if (results[j] > highest)
|
||||
highest = results[j];
|
||||
}
|
||||
/* Expect within 20% */
|
||||
ok(lowest > 800, "Byte %i lowest %i", i, lowest);
|
||||
ok(highest < 1200, "Byte %i highest %i", i, highest);
|
||||
diag("Byte %i, range %u-%u", i, lowest, highest);
|
||||
}
|
||||
|
||||
/* Hash of pointer values should also have random distribution. */
|
||||
for (i = 0; i < sizeof(uint32_t); i++) {
|
||||
unsigned int lowest = -1U, highest = 0;
|
||||
char *p = malloc(256000);
|
||||
|
||||
memset(results, 0, sizeof(results));
|
||||
|
||||
for (j = 0; j < 256000; j++)
|
||||
results[(hash_pointer(p + j, 0) >> i*8)&0xFF]++;
|
||||
free(p);
|
||||
|
||||
for (j = 0; j < 256; j++) {
|
||||
if (results[j] < lowest)
|
||||
lowest = results[j];
|
||||
if (results[j] > highest)
|
||||
highest = results[j];
|
||||
}
|
||||
/* Expect within 20% */
|
||||
ok(lowest > 800, "hash_pointer byte %i lowest %i", i, lowest);
|
||||
ok(highest < 1200, "hash_pointer byte %i highest %i",
|
||||
i, highest);
|
||||
diag("hash_pointer byte %i, range %u-%u", i, lowest, highest);
|
||||
}
|
||||
|
||||
if (sizeof(long) == sizeof(uint32_t))
|
||||
ok1(hashl(array, ARRAY_WORDS, 0)
|
||||
== hash(array, ARRAY_WORDS, 0));
|
||||
else
|
||||
ok1(hashl(array, ARRAY_WORDS, 0)
|
||||
== hash64(array, ARRAY_WORDS, 0));
|
||||
|
||||
/* String hash: weak, so only test bottom byte */
|
||||
for (i = 0; i < 1; i++) {
|
||||
unsigned int num = 0, cursor, lowest = -1U, highest = 0;
|
||||
char p[5];
|
||||
|
||||
memset(results, 0, sizeof(results));
|
||||
|
||||
memset(p, 'A', sizeof(p));
|
||||
p[sizeof(p)-1] = '\0';
|
||||
|
||||
for (;;) {
|
||||
for (cursor = 0; cursor < sizeof(p)-1; cursor++) {
|
||||
p[cursor]++;
|
||||
if (p[cursor] <= 'z')
|
||||
break;
|
||||
p[cursor] = 'A';
|
||||
}
|
||||
if (cursor == sizeof(p)-1)
|
||||
break;
|
||||
|
||||
results[(hash_string(p) >> i*8)&0xFF]++;
|
||||
num++;
|
||||
}
|
||||
|
||||
for (j = 0; j < 256; j++) {
|
||||
if (results[j] < lowest)
|
||||
lowest = results[j];
|
||||
if (results[j] > highest)
|
||||
highest = results[j];
|
||||
}
|
||||
/* Expect within 20% */
|
||||
ok(lowest > 35000, "hash_pointer byte %i lowest %i", i, lowest);
|
||||
ok(highest < 53000, "hash_pointer byte %i highest %i",
|
||||
i, highest);
|
||||
diag("hash_pointer byte %i, range %u-%u", i, lowest, highest);
|
||||
}
|
||||
|
||||
return exit_status();
|
||||
}
|
1
ccan/ccan/ilog/LICENSE
Symbolic link
1
ccan/ccan/ilog/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../licenses/CC0
|
50
ccan/ccan/ilog/_info
Normal file
50
ccan/ccan/ilog/_info
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* ilog - Integer logarithm.
|
||||
*
|
||||
* ilog_32() and ilog_64() compute the minimum number of bits required to store
|
||||
* an unsigned 32-bit or 64-bit value without any leading zero bits.
|
||||
*
|
||||
* This can also be thought of as the location of the highest set bit, with
|
||||
* counting starting from one (so that 0 returns 0, 1 returns 1, and 2**31
|
||||
* returns 32).
|
||||
*
|
||||
* When the value is known to be non-zero ilog32_nz() and ilog64_nz() can
|
||||
* compile into as few as two instructions, one of which may get optimized out
|
||||
* later.
|
||||
*
|
||||
* STATIC_ILOG_32 and STATIC_ILOG_64 allow computation on compile-time
|
||||
* constants, so other compile-time constants can be derived from them.
|
||||
*
|
||||
* Example:
|
||||
* #include <stdio.h>
|
||||
* #include <limits.h>
|
||||
* #include <ccan/ilog/ilog.h>
|
||||
*
|
||||
* int main(void){
|
||||
* int i;
|
||||
* printf("ilog32(0x%08X)=%i\n",0,ilog32(0));
|
||||
* for(i=1;i<=STATIC_ILOG_32(USHRT_MAX);i++){
|
||||
* uint32_t v;
|
||||
* v=(uint32_t)1U<<(i-1);
|
||||
* //Here we know v is non-zero, so we can use ilog32_nz().
|
||||
* printf("ilog32(0x%08X)=%i\n",v,ilog32_nz(v));
|
||||
* }
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* License: CC0 (Public domain)
|
||||
* Author: Timothy B. Terriberry <tterribe@xiph.org>
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int _argc,const char *_argv[]){
|
||||
/*Expect exactly one argument.*/
|
||||
if(_argc!=2)return 1;
|
||||
if(strcmp(_argv[1],"depends")==0){
|
||||
printf("ccan/compiler\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
141
ccan/ccan/ilog/ilog.c
Normal file
141
ccan/ccan/ilog/ilog.c
Normal file
@ -0,0 +1,141 @@
|
||||
/*(C) Timothy B. Terriberry (tterribe@xiph.org) 2001-2009 CC0 (Public domain).
|
||||
* See LICENSE file for details. */
|
||||
#include "ilog.h"
|
||||
#include <limits.h>
|
||||
|
||||
/*The fastest fallback strategy for platforms with fast multiplication appears
|
||||
to be based on de Bruijn sequences~\cite{LP98}.
|
||||
Tests confirmed this to be true even on an ARM11, where it is actually faster
|
||||
than using the native clz instruction.
|
||||
Define ILOG_NODEBRUIJN to use a simpler fallback on platforms where
|
||||
multiplication or table lookups are too expensive.
|
||||
|
||||
@UNPUBLISHED{LP98,
|
||||
author="Charles E. Leiserson and Harald Prokop",
|
||||
title="Using de {Bruijn} Sequences to Index a 1 in a Computer Word",
|
||||
month=Jun,
|
||||
year=1998,
|
||||
note="\url{http://supertech.csail.mit.edu/papers/debruijn.pdf}"
|
||||
}*/
|
||||
static UNNEEDED const unsigned char DEBRUIJN_IDX32[32]={
|
||||
0, 1,28, 2,29,14,24, 3,30,22,20,15,25,17, 4, 8,
|
||||
31,27,13,23,21,19,16, 7,26,12,18, 6,11, 5,10, 9
|
||||
};
|
||||
|
||||
/* We always compile these in, in case someone takes address of function. */
|
||||
#undef ilog32_nz
|
||||
#undef ilog32
|
||||
#undef ilog64_nz
|
||||
#undef ilog64
|
||||
|
||||
int ilog32(uint32_t _v){
|
||||
/*On a Pentium M, this branchless version tested as the fastest version without
|
||||
multiplications on 1,000,000,000 random 32-bit integers, edging out a
|
||||
similar version with branches, and a 256-entry LUT version.*/
|
||||
# if defined(ILOG_NODEBRUIJN)
|
||||
int ret;
|
||||
int m;
|
||||
ret=_v>0;
|
||||
m=(_v>0xFFFFU)<<4;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
m=(_v>0xFFU)<<3;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
m=(_v>0xFU)<<2;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
m=(_v>3)<<1;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
ret+=_v>1;
|
||||
return ret;
|
||||
/*This de Bruijn sequence version is faster if you have a fast multiplier.*/
|
||||
# else
|
||||
int ret;
|
||||
ret=_v>0;
|
||||
_v|=_v>>1;
|
||||
_v|=_v>>2;
|
||||
_v|=_v>>4;
|
||||
_v|=_v>>8;
|
||||
_v|=_v>>16;
|
||||
_v=(_v>>1)+1;
|
||||
ret+=DEBRUIJN_IDX32[_v*0x77CB531U>>27&0x1F];
|
||||
return ret;
|
||||
# endif
|
||||
}
|
||||
|
||||
int ilog32_nz(uint32_t _v)
|
||||
{
|
||||
return ilog32(_v);
|
||||
}
|
||||
|
||||
int ilog64(uint64_t _v){
|
||||
# if defined(ILOG_NODEBRUIJN)
|
||||
uint32_t v;
|
||||
int ret;
|
||||
int m;
|
||||
ret=_v>0;
|
||||
m=(_v>0xFFFFFFFFU)<<5;
|
||||
v=(uint32_t)(_v>>m);
|
||||
ret|=m;
|
||||
m=(v>0xFFFFU)<<4;
|
||||
v>>=m;
|
||||
ret|=m;
|
||||
m=(v>0xFFU)<<3;
|
||||
v>>=m;
|
||||
ret|=m;
|
||||
m=(v>0xFU)<<2;
|
||||
v>>=m;
|
||||
ret|=m;
|
||||
m=(v>3)<<1;
|
||||
v>>=m;
|
||||
ret|=m;
|
||||
ret+=v>1;
|
||||
return ret;
|
||||
# else
|
||||
/*If we don't have a 64-bit word, split it into two 32-bit halves.*/
|
||||
# if LONG_MAX<9223372036854775807LL
|
||||
uint32_t v;
|
||||
int ret;
|
||||
int m;
|
||||
ret=_v>0;
|
||||
m=(_v>0xFFFFFFFFU)<<5;
|
||||
v=(uint32_t)(_v>>m);
|
||||
ret|=m;
|
||||
v|=v>>1;
|
||||
v|=v>>2;
|
||||
v|=v>>4;
|
||||
v|=v>>8;
|
||||
v|=v>>16;
|
||||
v=(v>>1)+1;
|
||||
ret+=DEBRUIJN_IDX32[v*0x77CB531U>>27&0x1F];
|
||||
return ret;
|
||||
/*Otherwise do it in one 64-bit operation.*/
|
||||
# else
|
||||
static const unsigned char DEBRUIJN_IDX64[64]={
|
||||
0, 1, 2, 7, 3,13, 8,19, 4,25,14,28, 9,34,20,40,
|
||||
5,17,26,38,15,46,29,48,10,31,35,54,21,50,41,57,
|
||||
63, 6,12,18,24,27,33,39,16,37,45,47,30,53,49,56,
|
||||
62,11,23,32,36,44,52,55,61,22,43,51,60,42,59,58
|
||||
};
|
||||
int ret;
|
||||
ret=_v>0;
|
||||
_v|=_v>>1;
|
||||
_v|=_v>>2;
|
||||
_v|=_v>>4;
|
||||
_v|=_v>>8;
|
||||
_v|=_v>>16;
|
||||
_v|=_v>>32;
|
||||
_v=(_v>>1)+1;
|
||||
ret+=DEBRUIJN_IDX64[_v*0x218A392CD3D5DBF>>58&0x3F];
|
||||
return ret;
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
|
||||
int ilog64_nz(uint64_t _v)
|
||||
{
|
||||
return ilog64(_v);
|
||||
}
|
||||
|
151
ccan/ccan/ilog/ilog.h
Normal file
151
ccan/ccan/ilog/ilog.h
Normal file
@ -0,0 +1,151 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#if !defined(_ilog_H)
|
||||
# define _ilog_H (1)
|
||||
# include "config.h"
|
||||
# include <stdint.h>
|
||||
# include <limits.h>
|
||||
# include <ccan/compiler/compiler.h>
|
||||
|
||||
/**
|
||||
* ilog32 - Integer binary logarithm of a 32-bit value.
|
||||
* @_v: A 32-bit value.
|
||||
* Returns floor(log2(_v))+1, or 0 if _v==0.
|
||||
* This is the number of bits that would be required to represent _v in two's
|
||||
* complement notation with all of the leading zeros stripped.
|
||||
* Note that many uses will resolve to the fast macro version instead.
|
||||
*
|
||||
* See Also:
|
||||
* ilog32_nz(), ilog64()
|
||||
*
|
||||
* Example:
|
||||
* // Rounds up to next power of 2 (if not a power of 2).
|
||||
* static uint32_t round_up32(uint32_t i)
|
||||
* {
|
||||
* assert(i != 0);
|
||||
* return 1U << ilog32(i-1);
|
||||
* }
|
||||
*/
|
||||
int ilog32(uint32_t _v) CONST_FUNCTION;
|
||||
|
||||
/**
|
||||
* ilog32_nz - Integer binary logarithm of a non-zero 32-bit value.
|
||||
* @_v: A 32-bit value.
|
||||
* Returns floor(log2(_v))+1, or undefined if _v==0.
|
||||
* This is the number of bits that would be required to represent _v in two's
|
||||
* complement notation with all of the leading zeros stripped.
|
||||
* Note that many uses will resolve to the fast macro version instead.
|
||||
* See Also:
|
||||
* ilog32(), ilog64_nz()
|
||||
* Example:
|
||||
* // Find Last Set (ie. highest bit set, 0 to 31).
|
||||
* static uint32_t fls32(uint32_t i)
|
||||
* {
|
||||
* assert(i != 0);
|
||||
* return ilog32_nz(i) - 1;
|
||||
* }
|
||||
*/
|
||||
int ilog32_nz(uint32_t _v) CONST_FUNCTION;
|
||||
|
||||
/**
|
||||
* ilog64 - Integer binary logarithm of a 64-bit value.
|
||||
* @_v: A 64-bit value.
|
||||
* Returns floor(log2(_v))+1, or 0 if _v==0.
|
||||
* This is the number of bits that would be required to represent _v in two's
|
||||
* complement notation with all of the leading zeros stripped.
|
||||
* Note that many uses will resolve to the fast macro version instead.
|
||||
* See Also:
|
||||
* ilog64_nz(), ilog32()
|
||||
*/
|
||||
int ilog64(uint64_t _v) CONST_FUNCTION;
|
||||
|
||||
/**
|
||||
* ilog64_nz - Integer binary logarithm of a non-zero 64-bit value.
|
||||
* @_v: A 64-bit value.
|
||||
* Returns floor(log2(_v))+1, or undefined if _v==0.
|
||||
* This is the number of bits that would be required to represent _v in two's
|
||||
* complement notation with all of the leading zeros stripped.
|
||||
* Note that many uses will resolve to the fast macro version instead.
|
||||
* See Also:
|
||||
* ilog64(), ilog32_nz()
|
||||
*/
|
||||
int ilog64_nz(uint64_t _v) CONST_FUNCTION;
|
||||
|
||||
/**
|
||||
* STATIC_ILOG_32 - The integer logarithm of an (unsigned, 32-bit) constant.
|
||||
* @_v: A non-negative 32-bit constant.
|
||||
* Returns floor(log2(_v))+1, or 0 if _v==0.
|
||||
* This is the number of bits that would be required to represent _v in two's
|
||||
* complement notation with all of the leading zeros stripped.
|
||||
* This macro should only be used when you need a compile-time constant,
|
||||
* otherwise ilog32 or ilog32_nz are just as fast and more flexible.
|
||||
*
|
||||
* Example:
|
||||
* #define MY_PAGE_SIZE 4096
|
||||
* #define MY_PAGE_BITS (STATIC_ILOG_32(PAGE_SIZE) - 1)
|
||||
*/
|
||||
#define STATIC_ILOG_32(_v) (STATIC_ILOG5((uint32_t)(_v)))
|
||||
|
||||
/**
|
||||
* STATIC_ILOG_64 - The integer logarithm of an (unsigned, 64-bit) constant.
|
||||
* @_v: A non-negative 64-bit constant.
|
||||
* Returns floor(log2(_v))+1, or 0 if _v==0.
|
||||
* This is the number of bits that would be required to represent _v in two's
|
||||
* complement notation with all of the leading zeros stripped.
|
||||
* This macro should only be used when you need a compile-time constant,
|
||||
* otherwise ilog64 or ilog64_nz are just as fast and more flexible.
|
||||
*/
|
||||
#define STATIC_ILOG_64(_v) (STATIC_ILOG6((uint64_t)(_v)))
|
||||
|
||||
/* Private implementation details */
|
||||
|
||||
/*Note the casts to (int) below: this prevents "upgrading"
|
||||
the type of an entire expression to an (unsigned) size_t.*/
|
||||
#if INT_MAX>=2147483647 && HAVE_BUILTIN_CLZ
|
||||
#define builtin_ilog32_nz(v) \
|
||||
(((int)sizeof(unsigned)*CHAR_BIT) - __builtin_clz(v))
|
||||
#elif LONG_MAX>=2147483647L && HAVE_BUILTIN_CLZL
|
||||
#define builtin_ilog32_nz(v) \
|
||||
(((int)sizeof(unsigned)*CHAR_BIT) - __builtin_clzl(v))
|
||||
#endif
|
||||
|
||||
#if INT_MAX>=9223372036854775807LL && HAVE_BUILTIN_CLZ
|
||||
#define builtin_ilog64_nz(v) \
|
||||
(((int)sizeof(unsigned)*CHAR_BIT) - __builtin_clz(v))
|
||||
#elif LONG_MAX>=9223372036854775807LL && HAVE_BUILTIN_CLZL
|
||||
#define builtin_ilog64_nz(v) \
|
||||
(((int)sizeof(unsigned long)*CHAR_BIT) - __builtin_clzl(v))
|
||||
#elif HAVE_BUILTIN_CLZLL
|
||||
#define builtin_ilog64_nz(v) \
|
||||
(((int)sizeof(unsigned long long)*CHAR_BIT) - __builtin_clzll(v))
|
||||
#endif
|
||||
|
||||
#ifdef builtin_ilog32_nz
|
||||
#define ilog32(_v) (builtin_ilog32_nz(_v)&-!!(_v))
|
||||
#define ilog32_nz(_v) builtin_ilog32_nz(_v)
|
||||
#else
|
||||
#define ilog32_nz(_v) ilog32(_v)
|
||||
#define ilog32(_v) (IS_COMPILE_CONSTANT(_v) ? STATIC_ILOG_32(_v) : ilog32(_v))
|
||||
#endif /* builtin_ilog32_nz */
|
||||
|
||||
#ifdef builtin_ilog64_nz
|
||||
#define ilog64(_v) (builtin_ilog64_nz(_v)&-!!(_v))
|
||||
#define ilog64_nz(_v) builtin_ilog64_nz(_v)
|
||||
#else
|
||||
#define ilog64_nz(_v) ilog64(_v)
|
||||
#define ilog64(_v) (IS_COMPILE_CONSTANT(_v) ? STATIC_ILOG_64(_v) : ilog64(_v))
|
||||
#endif /* builtin_ilog64_nz */
|
||||
|
||||
/* Macros for evaluating compile-time constant ilog. */
|
||||
# define STATIC_ILOG0(_v) (!!(_v))
|
||||
# define STATIC_ILOG1(_v) (((_v)&0x2)?2:STATIC_ILOG0(_v))
|
||||
# define STATIC_ILOG2(_v) (((_v)&0xC)?2+STATIC_ILOG1((_v)>>2):STATIC_ILOG1(_v))
|
||||
# define STATIC_ILOG3(_v) \
|
||||
(((_v)&0xF0)?4+STATIC_ILOG2((_v)>>4):STATIC_ILOG2(_v))
|
||||
# define STATIC_ILOG4(_v) \
|
||||
(((_v)&0xFF00)?8+STATIC_ILOG3((_v)>>8):STATIC_ILOG3(_v))
|
||||
# define STATIC_ILOG5(_v) \
|
||||
(((_v)&0xFFFF0000)?16+STATIC_ILOG4((_v)>>16):STATIC_ILOG4(_v))
|
||||
# define STATIC_ILOG6(_v) \
|
||||
(((_v)&0xFFFFFFFF00000000ULL)?32+STATIC_ILOG5((_v)>>32):STATIC_ILOG5(_v))
|
||||
|
||||
#endif /* _ilog_H */
|
65
ccan/ccan/ilog/test/run-out-of-line.c
Normal file
65
ccan/ccan/ilog/test/run-out-of-line.c
Normal file
@ -0,0 +1,65 @@
|
||||
#include <ccan/ilog/ilog.h>
|
||||
#include <ccan/ilog/ilog.c>
|
||||
#include <stdio.h>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
/*Dead simple (but slow) versions to compare against.*/
|
||||
|
||||
static int test_ilog32(uint32_t _v){
|
||||
int ret;
|
||||
for(ret=0;_v;ret++)_v>>=1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_ilog64(uint64_t _v){
|
||||
int ret;
|
||||
for(ret=0;_v;ret++)_v>>=1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define NTRIALS (64)
|
||||
|
||||
int main(int _argc,const char *_argv[]){
|
||||
int i;
|
||||
int j;
|
||||
int (*il32)(uint32_t) = ilog32;
|
||||
int (*il64)(uint64_t) = ilog64;
|
||||
int (*il32_nz)(uint32_t) = ilog32_nz;
|
||||
int (*il64_nz)(uint64_t) = ilog64_nz;
|
||||
|
||||
/*This is how many tests you plan to run.*/
|
||||
plan_tests(33 * NTRIALS * 3 + 65 * NTRIALS * 3);
|
||||
for(i=0;i<=32;i++){
|
||||
uint32_t v;
|
||||
/*Test each bit in turn (and 0).*/
|
||||
v=i?(uint32_t)1U<<(i-1):0;
|
||||
for(j=0;j<NTRIALS;j++){
|
||||
int l;
|
||||
l=test_ilog32(v);
|
||||
ok1(STATIC_ILOG_32(v)==l);
|
||||
ok1(il32(v)==l);
|
||||
ok1(il32_nz(v) == l || v == 0);
|
||||
/*Also try a few more pseudo-random values with at most the same number
|
||||
of bits.*/
|
||||
v=(1103515245U*v+12345U)&0xFFFFFFFFU>>((33-i)>>1)>>((32-i)>>1);
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<=64;i++){
|
||||
uint64_t v;
|
||||
/*Test each bit in turn (and 0).*/
|
||||
v=i?(uint64_t)1U<<(i-1):0;
|
||||
for(j=0;j<NTRIALS;j++){
|
||||
int l;
|
||||
l=test_ilog64(v);
|
||||
ok1(STATIC_ILOG_64(v)==l);
|
||||
ok1(il64(v)==l);
|
||||
ok1(il64_nz(v) == l || v == 0);
|
||||
/*Also try a few more pseudo-random values with at most the same number
|
||||
of bits.*/
|
||||
v=(uint64_t)((2862933555777941757ULL*v+3037000493ULL)
|
||||
&0xFFFFFFFFFFFFFFFFULL>>((65-i)>>1)>>((64-i)>>1));
|
||||
}
|
||||
}
|
||||
return exit_status();
|
||||
}
|
60
ccan/ccan/ilog/test/run.c
Normal file
60
ccan/ccan/ilog/test/run.c
Normal file
@ -0,0 +1,60 @@
|
||||
#include <ccan/ilog/ilog.h>
|
||||
#include <ccan/ilog/ilog.c>
|
||||
#include <stdio.h>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
/*Dead simple (but slow) versions to compare against.*/
|
||||
|
||||
static int test_ilog32(uint32_t _v){
|
||||
int ret;
|
||||
for(ret=0;_v;ret++)_v>>=1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_ilog64(uint64_t _v){
|
||||
int ret;
|
||||
for(ret=0;_v;ret++)_v>>=1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define NTRIALS (64)
|
||||
|
||||
int main(int _argc,const char *_argv[]){
|
||||
int i;
|
||||
int j;
|
||||
/*This is how many tests you plan to run.*/
|
||||
plan_tests(33 * NTRIALS * 3 + 65 * NTRIALS * 3);
|
||||
for(i=0;i<=32;i++){
|
||||
uint32_t v;
|
||||
/*Test each bit in turn (and 0).*/
|
||||
v=i?(uint32_t)1U<<(i-1):0;
|
||||
for(j=0;j<NTRIALS;j++){
|
||||
int l;
|
||||
l=test_ilog32(v);
|
||||
ok1(STATIC_ILOG_32(v)==l);
|
||||
ok1(ilog32(v)==l);
|
||||
ok1(ilog32_nz(v) == l || v == 0);
|
||||
/*Also try a few more pseudo-random values with at most the same number
|
||||
of bits.*/
|
||||
v=(1103515245U*v+12345U)&0xFFFFFFFFU>>((33-i)>>1)>>((32-i)>>1);
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<=64;i++){
|
||||
uint64_t v;
|
||||
/*Test each bit in turn (and 0).*/
|
||||
v=i?(uint64_t)1U<<(i-1):0;
|
||||
for(j=0;j<NTRIALS;j++){
|
||||
int l;
|
||||
l=test_ilog64(v);
|
||||
ok1(STATIC_ILOG_64(v)==l);
|
||||
ok1(ilog64(v)==l);
|
||||
ok1(ilog64_nz(v) == l || v == 0);
|
||||
/*Also try a few more pseudo-random values with at most the same number
|
||||
of bits.*/
|
||||
v=(uint64_t)((2862933555777941757ULL*v+3037000493ULL)
|
||||
&0xFFFFFFFFFFFFFFFFULL>>((65-i)>>1)>>((64-i)>>1));
|
||||
}
|
||||
}
|
||||
return exit_status();
|
||||
}
|
1
ccan/ccan/likely/LICENSE
Symbolic link
1
ccan/ccan/likely/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../licenses/CC0
|
57
ccan/ccan/likely/_info
Normal file
57
ccan/ccan/likely/_info
Normal file
@ -0,0 +1,57 @@
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* likely - macros for annotating likely/unlikely branches in the code
|
||||
*
|
||||
* Inspired by Andi Kleen's macros for the Linux Kernel, these macros
|
||||
* help you annotate rare paths in your code for the convenience of the
|
||||
* compiler and the reader.
|
||||
*
|
||||
* With CCAN_LIKELY_DEBUG defined, it provides statistics for each
|
||||
* likely()/unlikely() call (but note that this requires LGPL dependencies).
|
||||
*
|
||||
* License: CC0 (Public domain)
|
||||
* Author: Rusty Russell <rusty@rustcorp.com.au>
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/likely/likely.h>
|
||||
* #include <stdio.h>
|
||||
*
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* // This example is silly: the compiler knows exit() is unlikely.
|
||||
* if (unlikely(argc == 1)) {
|
||||
* fprintf(stderr, "Usage: %s <args>...\n", argv[0]);
|
||||
* return 1;
|
||||
* }
|
||||
* for (argc++; argv[argc]; argc++)
|
||||
* printf("%s\n", argv[argc]);
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* Expect exactly one argument */
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
#ifdef CCAN_LIKELY_DEBUG
|
||||
printf("ccan/str\n");
|
||||
printf("ccan/htable\n");
|
||||
printf("ccan/hash\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(argv[1], "testdepends") == 0) {
|
||||
#ifndef CCAN_LIKELY_DEBUG
|
||||
printf("ccan/str\n");
|
||||
printf("ccan/htable\n");
|
||||
printf("ccan/hash\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
136
ccan/ccan/likely/likely.c
Normal file
136
ccan/ccan/likely/likely.c
Normal file
@ -0,0 +1,136 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details. */
|
||||
#ifdef CCAN_LIKELY_DEBUG
|
||||
#include <ccan/likely/likely.h>
|
||||
#include <ccan/hash/hash.h>
|
||||
#include <ccan/htable/htable_type.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
struct trace {
|
||||
const char *condstr;
|
||||
const char *file;
|
||||
unsigned int line;
|
||||
bool expect;
|
||||
unsigned long count, right;
|
||||
};
|
||||
|
||||
static size_t hash_trace(const struct trace *trace)
|
||||
{
|
||||
return hash(trace->condstr, strlen(trace->condstr),
|
||||
hash(trace->file, strlen(trace->file),
|
||||
trace->line + trace->expect));
|
||||
}
|
||||
|
||||
static bool trace_eq(const struct trace *t1, const struct trace *t2)
|
||||
{
|
||||
return t1->condstr == t2->condstr
|
||||
&& t1->file == t2->file
|
||||
&& t1->line == t2->line
|
||||
&& t1->expect == t2->expect;
|
||||
}
|
||||
|
||||
/* struct thash */
|
||||
HTABLE_DEFINE_TYPE(struct trace, (const struct trace *), hash_trace, trace_eq,
|
||||
thash);
|
||||
|
||||
static struct thash htable
|
||||
= { HTABLE_INITIALIZER(htable.raw, thash_hash, NULL) };
|
||||
|
||||
static void init_trace(struct trace *trace,
|
||||
const char *condstr, const char *file, unsigned int line,
|
||||
bool expect)
|
||||
{
|
||||
trace->condstr = condstr;
|
||||
trace->file = file;
|
||||
trace->line = line;
|
||||
trace->expect = expect;
|
||||
trace->count = trace->right = 0;
|
||||
}
|
||||
|
||||
static struct trace *add_trace(const struct trace *t)
|
||||
{
|
||||
struct trace *trace = malloc(sizeof(*trace));
|
||||
*trace = *t;
|
||||
thash_add(&htable, trace);
|
||||
return trace;
|
||||
}
|
||||
|
||||
long _likely_trace(bool cond, bool expect,
|
||||
const char *condstr,
|
||||
const char *file, unsigned int line)
|
||||
{
|
||||
struct trace *p, trace;
|
||||
|
||||
init_trace(&trace, condstr, file, line, expect);
|
||||
p = thash_get(&htable, &trace);
|
||||
if (!p)
|
||||
p = add_trace(&trace);
|
||||
|
||||
p->count++;
|
||||
if (cond == expect)
|
||||
p->right++;
|
||||
|
||||
return cond;
|
||||
}
|
||||
|
||||
static double right_ratio(const struct trace *t)
|
||||
{
|
||||
return (double)t->right / t->count;
|
||||
}
|
||||
|
||||
char *likely_stats(unsigned int min_hits, unsigned int percent)
|
||||
{
|
||||
struct trace *worst;
|
||||
double worst_ratio;
|
||||
struct thash_iter i;
|
||||
char *ret;
|
||||
struct trace *t;
|
||||
|
||||
worst = NULL;
|
||||
worst_ratio = 2;
|
||||
|
||||
/* This is O(n), but it's not likely called that often. */
|
||||
for (t = thash_first(&htable, &i); t; t = thash_next(&htable, &i)) {
|
||||
if (t->count >= min_hits) {
|
||||
if (right_ratio(t) < worst_ratio) {
|
||||
worst = t;
|
||||
worst_ratio = right_ratio(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (worst_ratio * 100 > percent)
|
||||
return NULL;
|
||||
|
||||
ret = malloc(strlen(worst->condstr) +
|
||||
strlen(worst->file) +
|
||||
sizeof(long int) * 8 +
|
||||
sizeof("%s:%u:%slikely(%s) correct %u%% (%lu/%lu)"));
|
||||
sprintf(ret, "%s:%u:%slikely(%s) correct %u%% (%lu/%lu)",
|
||||
worst->file, worst->line,
|
||||
worst->expect ? "" : "un", worst->condstr,
|
||||
(unsigned)(worst_ratio * 100),
|
||||
worst->right, worst->count);
|
||||
|
||||
thash_del(&htable, worst);
|
||||
free(worst);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void likely_stats_reset(void)
|
||||
{
|
||||
struct thash_iter i;
|
||||
struct trace *t;
|
||||
|
||||
/* This is a bit better than O(n^2), but we have to loop since
|
||||
* first/next during delete is unreliable. */
|
||||
while ((t = thash_first(&htable, &i)) != NULL) {
|
||||
for (; t; t = thash_next(&htable, &i)) {
|
||||
thash_del(&htable, t);
|
||||
free(t);
|
||||
}
|
||||
}
|
||||
|
||||
thash_clear(&htable);
|
||||
}
|
||||
#endif /*CCAN_LIKELY_DEBUG*/
|
111
ccan/ccan/likely/likely.h
Normal file
111
ccan/ccan/likely/likely.h
Normal file
@ -0,0 +1,111 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#ifndef CCAN_LIKELY_H
|
||||
#define CCAN_LIKELY_H
|
||||
#include "config.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef CCAN_LIKELY_DEBUG
|
||||
#if HAVE_BUILTIN_EXPECT
|
||||
/**
|
||||
* likely - indicate that a condition is likely to be true.
|
||||
* @cond: the condition
|
||||
*
|
||||
* This uses a compiler extension where available to indicate a likely
|
||||
* code path and optimize appropriately; it's also useful for readers
|
||||
* to quickly identify exceptional paths through functions. The
|
||||
* threshold for "likely" is usually considered to be between 90 and
|
||||
* 99%; marginal cases should not be marked either way.
|
||||
*
|
||||
* See Also:
|
||||
* unlikely(), likely_stats()
|
||||
*
|
||||
* Example:
|
||||
* // Returns false if we overflow.
|
||||
* static inline bool inc_int(unsigned int *val)
|
||||
* {
|
||||
* (*val)++;
|
||||
* if (likely(*val))
|
||||
* return true;
|
||||
* return false;
|
||||
* }
|
||||
*/
|
||||
#define likely(cond) __builtin_expect(!!(cond), 1)
|
||||
|
||||
/**
|
||||
* unlikely - indicate that a condition is unlikely to be true.
|
||||
* @cond: the condition
|
||||
*
|
||||
* This uses a compiler extension where available to indicate an unlikely
|
||||
* code path and optimize appropriately; see likely() above.
|
||||
*
|
||||
* See Also:
|
||||
* likely(), likely_stats(), COLD (compiler.h)
|
||||
*
|
||||
* Example:
|
||||
* // Prints a warning if we overflow.
|
||||
* static inline void inc_int(unsigned int *val)
|
||||
* {
|
||||
* (*val)++;
|
||||
* if (unlikely(*val == 0))
|
||||
* fprintf(stderr, "Overflow!");
|
||||
* }
|
||||
*/
|
||||
#define unlikely(cond) __builtin_expect(!!(cond), 0)
|
||||
#else
|
||||
#define likely(cond) (!!(cond))
|
||||
#define unlikely(cond) (!!(cond))
|
||||
#endif
|
||||
#else /* CCAN_LIKELY_DEBUG versions */
|
||||
#include <ccan/str/str.h>
|
||||
|
||||
#define likely(cond) \
|
||||
(_likely_trace(!!(cond), 1, stringify(cond), __FILE__, __LINE__))
|
||||
#define unlikely(cond) \
|
||||
(_likely_trace(!!(cond), 0, stringify(cond), __FILE__, __LINE__))
|
||||
|
||||
long _likely_trace(bool cond, bool expect,
|
||||
const char *condstr,
|
||||
const char *file, unsigned int line);
|
||||
/**
|
||||
* likely_stats - return description of abused likely()/unlikely()
|
||||
* @min_hits: minimum number of hits
|
||||
* @percent: maximum percentage correct
|
||||
*
|
||||
* When CCAN_LIKELY_DEBUG is defined, likely() and unlikely() trace their
|
||||
* results: this causes a significant slowdown, but allows analysis of
|
||||
* whether the branches are labelled correctly.
|
||||
*
|
||||
* This function returns a malloc'ed description of the least-correct
|
||||
* usage of likely() or unlikely(). It ignores places which have been
|
||||
* called less than @min_hits times, and those which were predicted
|
||||
* correctly more than @percent of the time. It returns NULL when
|
||||
* nothing meets those criteria.
|
||||
*
|
||||
* Note that this call is destructive; the returned offender is
|
||||
* removed from the trace so that the next call to likely_stats() will
|
||||
* return the next-worst likely()/unlikely() usage.
|
||||
*
|
||||
* Example:
|
||||
* // Print every place hit more than twice which was wrong > 5%.
|
||||
* static void report_stats(void)
|
||||
* {
|
||||
* #ifdef CCAN_LIKELY_DEBUG
|
||||
* const char *bad;
|
||||
*
|
||||
* while ((bad = likely_stats(2, 95)) != NULL) {
|
||||
* printf("Suspicious likely: %s", bad);
|
||||
* free(bad);
|
||||
* }
|
||||
* #endif
|
||||
* }
|
||||
*/
|
||||
char *likely_stats(unsigned int min_hits, unsigned int percent);
|
||||
|
||||
/**
|
||||
* likely_stats_reset - free up memory of likely()/unlikely() branches.
|
||||
*
|
||||
* This can also plug memory leaks.
|
||||
*/
|
||||
void likely_stats_reset(void);
|
||||
#endif /* CCAN_LIKELY_DEBUG */
|
||||
#endif /* CCAN_LIKELY_H */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user