Rusty Russell
10 years ago
336 changed files with 54774 additions and 2 deletions
@ -0,0 +1,3 @@ |
|||
CCAN imported from http://ccodearchive.net. |
|||
|
|||
CCAN version: init-1956-ged95d86 |
@ -0,0 +1 @@ |
|||
../../licenses/CC0 |
@ -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; |
|||
} |
@ -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 */ |
@ -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()); |
|||
} |
@ -0,0 +1 @@ |
|||
../../licenses/CC0 |
@ -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; |
|||
} |
@ -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 */ |
@ -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); |
|||
} |
@ -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 |
|||
} |
@ -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(); |
|||
} |
@ -0,0 +1 @@ |
|||
../../licenses/LGPL-2.1 |
@ -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; |
|||
} |
@ -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 */ |
@ -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 */ |
@ -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; |
|||
} |
@ -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(); |
|||
} |
@ -0,0 +1 @@ |
|||
../../licenses/CC0 |
@ -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; |
|||
} |
@ -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 */ |
@ -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 |
|||
} |
@ -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; |
|||
} |
@ -0,0 +1,7 @@ |
|||
#include <ccan/build_assert/build_assert.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
BUILD_ASSERT(1 == 1); |
|||
return 0; |
|||
} |
@ -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(); |
|||
} |
@ -0,0 +1 @@ |
|||
../../licenses/LGPL-2.1 |
@ -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; |
|||
} |
@ -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 */ |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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; |
|||
} |
@ -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 |
@ -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 |
@ -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 |
@ -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; |
|||
} |
@ -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]; |
|||
} |
@ -0,0 +1 @@ |
|||
../../licenses/CC0 |
@ -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; |
|||
} |
@ -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 */ |
@ -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; |
|||
} |
@ -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; |
|||
} |
@ -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; |
|||
} |
@ -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(); |
|||
} |
@ -0,0 +1 @@ |
|||
../../licenses/CC0 |
@ -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; |
|||
} |
@ -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 */ |
@ -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; |
|||
} |
@ -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(); |
|||
} |
@ -0,0 +1 @@ |
|||
../../licenses/CC0 |
@ -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; |
|||
} |
@ -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 */ |
@ -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; |
|||
} |
@ -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; |
|||
} |
@ -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; |
|||
} |
@ -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(); |
|||
} |
@ -0,0 +1 @@ |
|||
../../../licenses/BSD-MIT |
@ -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; |
|||
} |
@ -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)); |
|||
} |
@ -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 */ |
@ -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(); |
|||
} |
@ -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(); |
|||
} |
@ -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(); |
|||
} |
@ -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(); |
|||
} |
@ -0,0 +1 @@ |
|||
../../../licenses/BSD-MIT |
@ -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; |
|||
} |
@ -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> |
@ -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; |
|||
} |
@ -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 */ |
@ -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(); |
|||
} |
@ -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(); |
|||
} |
@ -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(); |
|||
} |
@ -0,0 +1 @@ |
|||
../../licenses/CC0 |
@ -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; |
|||
} |
@ -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 */ |
@ -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; |
|||
} |
@ -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()); |
|||
} |
@ -0,0 +1 @@ |
|||
../../licenses/CC0 |
@ -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; |
|||
} |
@ -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 |
@ -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 */ |
@ -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(); |
|||
} |
|||
|
@ -0,0 +1 @@ |
|||
../../licenses/CC0 |
@ -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; |
|||
} |
@ -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 */ |
@ -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 */ |
@ -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(); |
|||
} |
@ -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(); |
|||
} |
@ -0,0 +1 @@ |
|||
../../licenses/CC0 |
@ -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; |
|||
} |
@ -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); |
|||
} |
|||
|
@ -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 */ |
@ -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(); |
|||
} |
@ -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(); |
|||
} |
@ -0,0 +1 @@ |
|||
../../licenses/CC0 |
@ -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; |
|||
} |
@ -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*/ |
@ -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 changed in this diff
Loading…
Reference in new issue