]> git.ozlabs.org Git - ccan/commitdiff
Merge https://github.com/dgibson/ccan
authorRusty Russell <rusty@rustcorp.com.au>
Fri, 13 Sep 2013 00:01:17 +0000 (09:31 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Fri, 13 Sep 2013 00:01:17 +0000 (09:31 +0930)
22 files changed:
Makefile-ccan
ccan/endian/_info
ccan/endian/endian.h
ccan/heap/LICENSE [new symlink]
ccan/heap/_info [new file with mode: 0644]
ccan/heap/heap.c [new file with mode: 0644]
ccan/heap/heap.h [new file with mode: 0644]
ccan/heap/test/run.c [new file with mode: 0644]
ccan/ilog/LICENSE
ccan/ilog/_info
ccan/ilog/ilog.c
ccan/ilog/ilog.h
ccan/list/list.h
ccan/list/test/run-list_prev-list_next.c [new file with mode: 0644]
ccan/short_types/_info
ccan/short_types/short_types.h
ccan/short_types/test/run-endian.c [new file with mode: 0644]
ccan/short_types/test/run.c
ccan/tal/tal.c
ccan/tal/tal.h
ccan/tal/test/run-array.c
ccan/tal/test/run-resizez.c [new file with mode: 0644]

index 2d713a6898e402e21bd45530cc586b63ca86ca4b..c4a8f455ff98683ad4721165d3eafeeef3f91b39 100644 (file)
@@ -49,6 +49,7 @@ MODS_WITH_SRC := antithread \
        foreach \
        grab_file \
        hash \
+       heap \
        htable \
        idtree \
        ilog \
index 753afa7865e37f58b79b2c6c48d7fd9a834c598a..a71b9ae7222e5abf3c921784e093bac2b7cfdaf4 100644 (file)
@@ -15,6 +15,8 @@
  * 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>
index 4dc58dd0a9bb2aaaba13134190d00a1cc2dfa057..02f5a68baf02adf94a1bcfd308c8f0a577accc48 100644 (file)
@@ -110,50 +110,66 @@ static inline uint64_t bswap_64(uint64_t val)
 #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) (native)
+#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) (native)
+#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) (native)
+#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) (le_val)
+#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) (le_val)
+#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) (le_val)
+#define LE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val))
 
 #else /* ... HAVE_BIG_ENDIAN */
-#define CPU_TO_LE64(native) BSWAP_64(native)
-#define CPU_TO_LE32(native) BSWAP_32(native)
-#define CPU_TO_LE16(native) BSWAP_16(native)
-#define LE64_TO_CPU(le_val) BSWAP_64(le_val)
-#define LE32_TO_CPU(le_val) BSWAP_32(le_val)
-#define LE16_TO_CPU(le_val) BSWAP_16(le_val)
+#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
@@ -161,45 +177,45 @@ static inline uint64_t bswap_64(uint64_t val)
  * CPU_TO_BE64 - convert a constant uint64_t value to big-endian
  * @native: constant to convert
  */
-#define CPU_TO_BE64(native) (native)
+#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) (native)
+#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) (native)
+#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) (le_val)
+#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) (le_val)
+#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) (le_val)
+#define BE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val))
 
 #else /* ... HAVE_LITTLE_ENDIAN */
-#define CPU_TO_BE64(native) BSWAP_64(native)
-#define CPU_TO_BE32(native) BSWAP_32(native)
-#define CPU_TO_BE16(native) BSWAP_16(native)
-#define BE64_TO_CPU(le_val) BSWAP_64(le_val)
-#define BE32_TO_CPU(le_val) BSWAP_32(le_val)
-#define BE16_TO_CPU(le_val) BSWAP_16(le_val)
+#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 */
 
 
@@ -207,7 +223,7 @@ static inline uint64_t bswap_64(uint64_t val)
  * cpu_to_le64 - convert a uint64_t value to little-endian
  * @native: value to convert
  */
-static inline uint64_t cpu_to_le64(uint64_t native)
+static inline leint64_t cpu_to_le64(uint64_t native)
 {
        return CPU_TO_LE64(native);
 }
@@ -216,7 +232,7 @@ static inline uint64_t cpu_to_le64(uint64_t native)
  * cpu_to_le32 - convert a uint32_t value to little-endian
  * @native: value to convert
  */
-static inline uint32_t cpu_to_le32(uint32_t native)
+static inline leint32_t cpu_to_le32(uint32_t native)
 {
        return CPU_TO_LE32(native);
 }
@@ -225,7 +241,7 @@ static inline uint32_t cpu_to_le32(uint32_t native)
  * cpu_to_le16 - convert a uint16_t value to little-endian
  * @native: value to convert
  */
-static inline uint16_t cpu_to_le16(uint16_t native)
+static inline leint16_t cpu_to_le16(uint16_t native)
 {
        return CPU_TO_LE16(native);
 }
@@ -234,7 +250,7 @@ static inline uint16_t cpu_to_le16(uint16_t 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(uint64_t le_val)
+static inline uint64_t le64_to_cpu(leint64_t le_val)
 {
        return LE64_TO_CPU(le_val);
 }
@@ -243,7 +259,7 @@ static inline uint64_t le64_to_cpu(uint64_t 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(uint32_t le_val)
+static inline uint32_t le32_to_cpu(leint32_t le_val)
 {
        return LE32_TO_CPU(le_val);
 }
@@ -252,7 +268,7 @@ static inline uint32_t le32_to_cpu(uint32_t 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(uint16_t le_val)
+static inline uint16_t le16_to_cpu(leint16_t le_val)
 {
        return LE16_TO_CPU(le_val);
 }
@@ -261,8 +277,9 @@ static inline uint16_t le16_to_cpu(uint16_t le_val)
  * cpu_to_be64 - convert a uint64_t value to big endian.
  * @native: value to convert
  */
-static inline uint64_t cpu_to_be64(uint64_t native)
+static inline beint64_t cpu_to_be64(uint64_t native)
 {
+       return ((ENDIAN_CAST beint64_t)BSWAP_64(native));
        return CPU_TO_BE64(native);
 }
 
@@ -270,7 +287,7 @@ static inline uint64_t cpu_to_be64(uint64_t native)
  * cpu_to_be32 - convert a uint32_t value to big endian.
  * @native: value to convert
  */
-static inline uint32_t cpu_to_be32(uint32_t native)
+static inline beint32_t cpu_to_be32(uint32_t native)
 {
        return CPU_TO_BE32(native);
 }
@@ -279,7 +296,7 @@ static inline uint32_t cpu_to_be32(uint32_t native)
  * cpu_to_be16 - convert a uint16_t value to big endian.
  * @native: value to convert
  */
-static inline uint16_t cpu_to_be16(uint16_t native)
+static inline beint16_t cpu_to_be16(uint16_t native)
 {
        return CPU_TO_BE16(native);
 }
@@ -288,7 +305,7 @@ static inline uint16_t cpu_to_be16(uint16_t 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(uint64_t be_val)
+static inline uint64_t be64_to_cpu(beint64_t be_val)
 {
        return BE64_TO_CPU(be_val);
 }
@@ -297,7 +314,7 @@ static inline uint64_t be64_to_cpu(uint64_t 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(uint32_t be_val)
+static inline uint32_t be32_to_cpu(beint32_t be_val)
 {
        return BE32_TO_CPU(be_val);
 }
@@ -306,9 +323,25 @@ static inline uint32_t be32_to_cpu(uint32_t 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(uint16_t be_val)
+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 */
diff --git a/ccan/heap/LICENSE b/ccan/heap/LICENSE
new file mode 120000 (symlink)
index 0000000..2354d12
--- /dev/null
@@ -0,0 +1 @@
+../../licenses/BSD-MIT
\ No newline at end of file
diff --git a/ccan/heap/_info b/ccan/heap/_info
new file mode 100644 (file)
index 0000000..552b139
--- /dev/null
@@ -0,0 +1,67 @@
+#include <string.h>
+#include "config.h"
+
+/**
+ * heap - a simple heap implementation
+ *
+ * Each heap entry is added as a void pointer. This means the implementation
+ * does _not_ assume you already have an array of entries. Instead, it keeps
+ * an internal array of pointers to those entries.
+ *
+ * Example:
+ *     #include <stdio.h>
+ *
+ *     #include <ccan/heap/heap.h>
+ *
+ *     static bool less(const int *i, const int *j)
+ *     {
+ *             return *i < *j;
+ *     }
+ *
+ *     static bool __less(const void *i, const void *j)
+ *     {
+ *             return less(i, j);
+ *     }
+ *
+ *     int main(int argc, char *argv[])
+ *     {
+ *             struct heap *h;
+ *             int arr[] = {1, 0, 2};
+ *             int i;
+ *
+ *             h = heap_init(__less);
+ *             if (h == NULL) {
+ *                     perror("heap alloc");
+ *                     exit(1);
+ *             }
+ *
+ *             for (i = 0; i < 3; i++) {
+ *                     if (heap_push(h, &arr[i])) {
+ *                             perror("heap push");
+ *                             exit(1);
+ *                     }
+ *             }
+ *             // should print 0, 1, 2
+ *             for (i = 0; i < 3; i++) {
+ *                     int *v = heap_pop(h);
+ *                     printf("%d\n", *v);
+ *             }
+ *             heap_free(h);
+ *             return 0;
+ *     }
+ *
+ * License: BSD-MIT
+ * Author: Emilio G. Cota <cota@braap.org>
+ */
+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;
+}
diff --git a/ccan/heap/heap.c b/ccan/heap/heap.c
new file mode 100644 (file)
index 0000000..aec9016
--- /dev/null
@@ -0,0 +1,119 @@
+/* Licensed under BSD-MIT - see LICENSE file for details */
+#include <ccan/heap/heap.h>
+
+/*
+ * Allocating memory in chunks greater than needed does not yield measurable
+ * speedups of the test program when linking against glibc 2.15.
+ *
+ * When the data array has to be shrunk though, limiting calls to realloc
+ * does help a little bit (~7% speedup), hence the following parameter.
+ */
+#define HEAP_MEM_HYSTERESIS    4096
+
+static inline void swap(struct heap *h, size_t i, size_t j)
+{
+       void *foo = h->data[i];
+
+       h->data[i] = h->data[j];
+       h->data[j] = foo;
+}
+
+static void __up(struct heap *h, size_t j)
+{
+       size_t i; /* parent */
+
+       while (j) {
+               i = (j - 1) / 2;
+
+               if (h->less(h->data[j], h->data[i])) {
+                       swap(h, i, j);
+                       j = i;
+               } else {
+                       break;
+               }
+       }
+}
+
+int heap_push(struct heap *h, void *data)
+{
+       if (h->len == h->cap) {
+               void *m = realloc(h->data, (h->cap + 1) * sizeof(void *));
+               if (m == NULL)
+                       return -1;
+               h->data = m;
+               h->cap++;
+       }
+       h->data[h->len++] = data;
+       __up(h, h->len - 1);
+       return 0;
+}
+
+static void __down(struct heap *h, size_t i)
+{
+       size_t l, r, j; /* left, right, min child */
+
+       while (1) {
+               l = 2 * i + 1;
+               if (l >= h->len)
+                       break;
+               r = l + 1;
+               if (r >= h->len)
+                       j = l;
+               else
+                       j = h->less(h->data[l], h->data[r]) ? l : r;
+
+               if (h->less(h->data[j], h->data[i])) {
+                       swap(h, i, j);
+                       i = j;
+               } else {
+                       break;
+               }
+       }
+}
+
+void *heap_pop(struct heap *h)
+{
+       void *ret = h->data[0];
+       void *m;
+
+       swap(h, 0, --h->len);
+       if (h->len) {
+               __down(h, 0);
+               if (h->len == h->cap - HEAP_MEM_HYSTERESIS) {
+                       m = realloc(h->data, h->len * sizeof(void *));
+                       if (m == NULL)
+                               return NULL;
+                       h->data = m;
+                       h->cap = h->len;
+               }
+       }
+
+       return ret;
+}
+
+struct heap *heap_init(heap_less_func_t less)
+{
+       struct heap *heap = calloc(1, sizeof(*heap));
+
+       if (heap == NULL)
+               return NULL;
+       heap->less = less;
+       return heap;
+}
+
+void heap_ify(struct heap *h, heap_less_func_t less)
+{
+       int i;
+
+       if (less)
+               h->less = less;
+
+       for (i = h->len / 2 - 1; i >= 0; i--)
+               __down(h, i);
+}
+
+void heap_free(struct heap *heap)
+{
+       free(heap->data);
+       free(heap);
+}
diff --git a/ccan/heap/heap.h b/ccan/heap/heap.h
new file mode 100644 (file)
index 0000000..e7694a3
--- /dev/null
@@ -0,0 +1,114 @@
+/* Licensed under BSD-MIT - see LICENSE file for details */
+#ifndef CCAN_HEAP_H
+#define CCAN_HEAP_H
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+typedef bool (*heap_less_func_t)(const void *, const void *);
+
+/**
+ * struct heap - a simple, generic heap structure
+ * @data: array of pointers to the heap's entries
+ * @less: function to compare heap entries
+ * @cap: capacity of the heap array in @data
+ * @len: number of valid elements in the heap array
+ *
+ * The @less function determines the nature of the heap. If @less is
+ * something akin to 'return a.foo < b.foo', then the heap will be
+ * a min heap. Conversely, a '>' predicate will result in a max heap.
+ *
+ * Elements in the @data array are allocated as needed, hence the need for
+ * @cap and @len.
+ */
+struct heap {
+       void **data;
+       heap_less_func_t less;
+       size_t cap;
+       size_t len;
+};
+
+/**
+ * heap_init - allocate and initialise an empty heap
+ * @less: function to be used to compare heap entries
+ *
+ * Returns a pointer to an initialised heap struct on success, NULL if
+ * the heap could not be allocated.
+ *
+ * See also: HEAP_INIT()
+ */
+struct heap *heap_init(heap_less_func_t less);
+
+/**
+ * HEAP_INIT - initialiser for an empty heap
+ * @func: comparison function to be used in the heap
+ *
+ * Explicit initialiser for a heap.
+ *
+ * See also: heap_init()
+ */
+#define HEAP_INIT(func) { NULL, func, 0, 0 }
+
+/**
+ * heap_free - free a heap allocated via heap_init()
+ * @heap: the heap to be freed
+ *
+ * Note that this only frees the heap and its internal resources, not
+ * the entries pointed to by it.
+ *
+ * See also: heap_init()
+ */
+void heap_free(struct heap *heap);
+
+/**
+ * heap_ify - enforce the heap property based on a new comparison function
+ * @h: heap to be heapified
+ * @less: new comparison function
+ *
+ * Complexity: O(n)
+ */
+void heap_ify(struct heap *h, heap_less_func_t less);
+
+/**
+ * heap_push - push a new heap entry
+ * @h: heap to receive the new entry
+ * @data: pointer to the new entry
+ *
+ * Returns 0 on success, -1 on error.
+ *
+ * Complexity: O(log n)
+ *
+ * See also: heap_pop()
+ */
+int heap_push(struct heap *h, void *data);
+
+/**
+ * heap_pop - pops the root heap entry
+ * @h: heap to pop the head from
+ *
+ * Returns the root entry of the heap after extracting it, or NULL on error.
+ *
+ * Note: Calling heap_pop() on an empty heap is a bug--don't do it.
+ *
+ * Complexity: O(log n)
+ *
+ * See also: heap_push(), heap_peek()
+ */
+void *heap_pop(struct heap *h);
+
+/**
+ * heap_peek - inspect the root entry of a heap
+ * @h: heap whose root entry is to be inspected
+ *
+ * Returns the root entry in the heap, without extracting it from @h.
+ *
+ * Note: Calling heap_peek() on an empty heap is a bug--don't do it.
+ *
+ * See also: heap_pop()
+ */
+static inline void *heap_peek(const struct heap *h)
+{
+       return h->data[0];
+}
+
+#endif /* CCAN_HEAP_H */
diff --git a/ccan/heap/test/run.c b/ccan/heap/test/run.c
new file mode 100644 (file)
index 0000000..6972a6b
--- /dev/null
@@ -0,0 +1,133 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <ccan/heap/heap.h>
+/* Include the C files directly. */
+#include <ccan/heap/heap.c>
+#include <ccan/tap/tap.h>
+
+struct item {
+       void *foobar;
+       int v;
+};
+
+static bool heap_ok(const struct heap *h, heap_less_func_t less, int i)
+{
+       int l, r;
+
+       l = 2 * i + 1;
+       r = l + 1;
+
+       if (l < h->len) {
+               if (less(h->data[l], h->data[i])) {
+                       fprintf(stderr, "heap property violation\n");
+                       return false;
+               }
+               if (!heap_ok(h, less, l))
+                       return false;
+       }
+       if (r < h->len) {
+               if (less(h->data[r], h->data[i])) {
+                       fprintf(stderr, "heap property violation\n");
+                       return false;
+               }
+               if (!heap_ok(h, less, r))
+                       return false;
+       }
+       return true;
+}
+
+static bool less(const struct item *a, const struct item *b)
+{
+       return a->v < b->v;
+}
+
+static bool __less(const void *a, const void *b)
+{
+       return less(a, b);
+}
+
+static bool more(const struct item *a, const struct item *b)
+{
+       return a->v > b->v;
+}
+
+static bool __more(const void *a, const void *b)
+{
+       return more(a, b);
+}
+
+static bool some_test(size_t n, bool is_less)
+{
+       struct item *items = calloc(n, sizeof(*items));
+       struct item *item, *prev;
+       struct heap *h;
+       int i;
+
+       if (items == NULL) {
+               perror("items");
+               exit(EXIT_FAILURE);
+       }
+
+       if (is_less)
+               h = heap_init(__less);
+       else
+               h = heap_init(__more);
+       if (h == NULL) {
+               perror("heap_init");
+               exit(EXIT_FAILURE);
+       }
+
+       for (i = 0; i < n; i++) {
+               item = &items[i];
+
+               item->v = rand();
+               printf("pushing %d\n", item->v);
+               heap_push(h, item);
+               if (!heap_ok(h, is_less ? __less : __more, 0))
+                       return false;
+       }
+       if (is_less) {
+               heap_ify(h, __more);
+               if (!heap_ok(h, __more, 0))
+                       return false;
+               heap_ify(h, __less);
+               if (!heap_ok(h, __less, 0))
+                       return false;
+       } else {
+               heap_ify(h, NULL);
+               if (!heap_ok(h, __more, 0))
+                       return false;
+       }
+
+       for (i = 0; i < n; i++) {
+               item = heap_pop(h);
+               if (!heap_ok(h, is_less ? __less : __more, 0))
+                       return false;
+               printf("popped %d\n", item->v);
+               if (i > 0) {
+                       if (is_less) {
+                               if (less(item, prev))
+                                       return false;
+                       } else {
+                               if (more(item, prev))
+                                       return false;
+                       }
+               }
+               prev = item;
+       }
+       heap_free(h);
+       free(items);
+       return true;
+}
+
+int main(void)
+{
+       plan_tests(3);
+
+       ok1(some_test(5000, true));
+       ok1(some_test(1, true));
+       ok1(some_test(33, false));
+
+       return exit_status();
+}
index dc314ecac02a0fb3117e54b1271ca135aaada572..b7951dabdc82e45d46d3cf1bd8c7ed8b3a6f7c0f 120000 (symlink)
@@ -1 +1 @@
-../../licenses/LGPL-2.1
\ No newline at end of file
+../../licenses/CC0
\ No newline at end of file
index 9a92f4e70e98f6ec87161dd18b6ccfd16df49bad..d57c05d4d25062032c390a31d5e75d1d92ced38f 100644 (file)
@@ -2,15 +2,18 @@
  * 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.
+ * 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).
+ * 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.
+ * 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.
+ * constants, so other compile-time constants can be derived from them.
  *
  * Example:
  *  #include <stdio.h>
@@ -29,7 +32,7 @@
  *    return 0;
  *  }
  *
- * License: LGPL (v2.1 or any later version)
+ * License: CC0 (Public domain)
  * Author: Timothy B. Terriberry <tterribe@xiph.org>
  */
 #include <string.h>
index 22275d2a9e02d12cf983a2b4195787349af6cea6..5f5122d5181822596c4f4d3eb185d561a7ca5076 100644 (file)
@@ -1,4 +1,4 @@
-/*(C) Timothy B. Terriberry (tterribe@xiph.org) 2001-2009 LGPL (v2 or later).
+/*(C) Timothy B. Terriberry (tterribe@xiph.org) 2001-2009 CC0 (Public domain).
  * See LICENSE file for details. */
 #include "ilog.h"
 #include <limits.h>
index e52f04233c7fe16516412f8f0feb57ffe5bc7ede..9adbb8243f6c4f67da7ccefbc8fc7735f63cda7e 100644 (file)
@@ -1,4 +1,4 @@
-/* Licensed under LGPLv2.1+ - see LICENSE file for details */
+/* CC0 (Public domain) - see LICENSE file for details */
 #if !defined(_ilog_H)
 # define _ilog_H (1)
 # include "config.h"
index ab3240871773d90ceee149c3cb30931e228326fb..03614873ef6a718aaaadec32a27356f82c6c7912 100644 (file)
@@ -399,6 +399,43 @@ static inline const void *list_tail_(const struct list_head *h, size_t off)
 #define list_for_each_safe(h, i, nxt, member)                          \
        list_for_each_safe_off(h, i, nxt, list_off_var_(i, member))
 
+/**
+ * list_next - get the next entry in a list
+ * @h: the list_head
+ * @i: a pointer to an entry in the list.
+ * @member: the list_node member of the structure
+ *
+ * If @i was the last entry in the list, returns NULL.
+ *
+ * Example:
+ *     struct child *second;
+ *     second = list_next(&parent->children, first, list);
+ *     if (!second)
+ *             printf("No second child!\n");
+ */
+#define list_next(h, i, member)                                                \
+       ((list_typeof(i))list_entry_or_null(list_debug(h),              \
+                                           (i)->member.next,           \
+                                           list_off_var_((i), member)))
+
+/**
+ * list_prev - get the previous entry in a list
+ * @h: the list_head
+ * @i: a pointer to an entry in the list.
+ * @member: the list_node member of the structure
+ *
+ * If @i was the first entry in the list, returns NULL.
+ *
+ * Example:
+ *     first = list_prev(&parent->children, second, list);
+ *     if (!first)
+ *             printf("Can't go back to first child?!\n");
+ */
+#define list_prev(h, i, member)                                                \
+       ((list_typeof(i))list_entry_or_null(list_debug(h),              \
+                                           (i)->member.prev,           \
+                                           list_off_var_((i), member)))
+
 /**
  * list_append_list - empty one list onto the end of another.
  * @to: the list to append into
@@ -560,4 +597,19 @@ static inline struct list_node *list_node_from_off_(void *ptr, size_t off)
        (container_off_var(var, member) +               \
         check_type(var->member, struct list_node))
 
+#if HAVE_TYPEOF
+#define list_typeof(var) typeof(var)
+#else
+#define list_typeof(var) void *
+#endif
+
+/* Returns member, or NULL if at end of list. */
+static inline void *list_entry_or_null(struct list_head *h,
+                                      struct list_node *n,
+                                      size_t off)
+{
+       if (n == &h->n)
+               return NULL;
+       return (char *)n - off;
+}
 #endif /* CCAN_LIST_H */
diff --git a/ccan/list/test/run-list_prev-list_next.c b/ccan/list/test/run-list_prev-list_next.c
new file mode 100644 (file)
index 0000000..85611d9
--- /dev/null
@@ -0,0 +1,50 @@
+#include <ccan/list/list.h>
+#include <ccan/tap/tap.h>
+#include <ccan/list/list.c>
+#include "helper.h"
+
+struct parent {
+       const char *name;
+       unsigned int num_children;
+       struct list_head children;
+};
+
+struct child {
+       const char *name;
+       struct list_node list;
+};
+
+int main(int argc, char *argv[])
+{
+       struct parent parent;
+       struct child c1, c2, c3;
+
+       plan_tests(12);
+       parent.num_children = 0;
+       list_head_init(&parent.children);
+
+       c1.name = "c1";
+       list_add(&parent.children, &c1.list);
+
+       ok1(list_next(&parent.children, &c1, list) == NULL);
+       ok1(list_prev(&parent.children, &c1, list) == NULL);
+
+       c2.name = "c2";
+       list_add_tail(&parent.children, &c2.list);
+
+       ok1(list_next(&parent.children, &c1, list) == &c2);
+       ok1(list_prev(&parent.children, &c1, list) == NULL);
+       ok1(list_next(&parent.children, &c2, list) == NULL);
+       ok1(list_prev(&parent.children, &c2, list) == &c1);
+
+       c3.name = "c3";
+       list_add_tail(&parent.children, &c3.list);
+
+       ok1(list_next(&parent.children, &c1, list) == &c2);
+       ok1(list_prev(&parent.children, &c1, list) == NULL);
+       ok1(list_next(&parent.children, &c2, list) == &c3);
+       ok1(list_prev(&parent.children, &c2, list) == &c1);
+       ok1(list_next(&parent.children, &c3, list) == NULL);
+       ok1(list_prev(&parent.children, &c3, list) == &c2);
+       return exit_status();
+}
index cfd439e6fccb270e943a25263478c12b6dc164a8..f324e359ac8a01f35353e753445b114fbd795d31 100644 (file)
@@ -9,8 +9,9 @@
  *     -- Linus Torvalds
  *
  * The short_types header provides for convenient abbreviations for the
- * posixly-damned uint32_t types.  It also provides be32/le32 for explicitly
- * annotating types of specific endian.
+ * posixly-damned uint32_t types.  If ccan/endian/endian.h is included,
+ * it also provides be32/le32 for explicitly annotating types of specific
+ * endian.
  *
  * Include this header, if only to stop people using these identifiers
  * for other things!
@@ -77,5 +78,10 @@ int main(int argc, char *argv[])
                return 0;
        }
 
+       if (strcmp(argv[1], "testdepends") == 0) {
+               printf("ccan/endian\n");
+               return 0;
+       }
+
        return 1;
 }
index f94ec0980fe759f26debbda91522d58366439742..175377e9bab9e6d624d08654de31ff4214169e37 100644 (file)
@@ -15,18 +15,21 @@ typedef int16_t s16;
 typedef uint8_t u8;
 typedef int8_t s8;
 
+/* Whichever they include first, they get these definitions. */
+#ifdef CCAN_ENDIAN_H
 /**
  * be64/be32/be16 - 64/32/16 bit big-endian representation.
  */
-typedef uint64_t be64;
-typedef uint32_t be32;
-typedef uint16_t be16;
+typedef beint64_t be64;
+typedef beint32_t be32;
+typedef beint16_t be16;
 
 /**
  * le64/le32/le16 - 64/32/16 bit little-endian representation.
  */
-typedef uint64_t le64;
-typedef uint32_t le32;
-typedef uint16_t le16;
+typedef leint64_t le64;
+typedef leint32_t le32;
+typedef leint16_t le16;
+#endif
 
 #endif /* CCAN_SHORT_TYPES_H */
diff --git a/ccan/short_types/test/run-endian.c b/ccan/short_types/test/run-endian.c
new file mode 100644 (file)
index 0000000..17508e1
--- /dev/null
@@ -0,0 +1,20 @@
+#include <ccan/endian/endian.h>
+#include <ccan/short_types/short_types.h>
+#include <ccan/tap/tap.h>
+#include <stdlib.h>
+#include <err.h>
+
+int main(int argc, char *argv[])
+{
+       plan_tests(6);
+
+       ok1(sizeof(be64) == 8);
+       ok1(sizeof(be32) == 4);
+       ok1(sizeof(be16) == 2);
+
+       ok1(sizeof(le64) == 8);
+       ok1(sizeof(le32) == 4);
+       ok1(sizeof(le16) == 2);
+
+       return exit_status();
+}
index 5aa80d7f5155590c69cc57b99e4847ac4eeebfac..6da3f9bc053d48c652db86f0da285a10aca5cb50 100644 (file)
@@ -5,7 +5,7 @@
 
 int main(int argc, char *argv[])
 {
-       plan_tests(22);
+       plan_tests(16);
 
        ok1(sizeof(u64) == 8);
        ok1(sizeof(s64) == 8);
@@ -16,14 +16,6 @@ int main(int argc, char *argv[])
        ok1(sizeof(u8) == 1);
        ok1(sizeof(s8) == 1);
 
-       ok1(sizeof(be64) == 8);
-       ok1(sizeof(be32) == 4);
-       ok1(sizeof(be16) == 2);
-
-       ok1(sizeof(le64) == 8);
-       ok1(sizeof(le32) == 4);
-       ok1(sizeof(le16) == 2);
-
        /* Signedness tests. */
        ok1((u64)-1 > 0);
        ok1((u32)-1 > 0);
index 1934a01318a3f09060614e144d189fff8467469b..1eaa5749476aa3abd23992c16167b031c47175f6 100644 (file)
@@ -670,13 +670,13 @@ tal_t *tal_parent(const tal_t *ctx)
         return from_tal_hdr(ignore_destroying_bit(t->parent_child)->parent);
 }
 
-bool tal_resize_(tal_t **ctxp, size_t size, size_t count)
+bool tal_resize_(tal_t **ctxp, size_t size, size_t count, bool clear)
 {
         struct tal_hdr *old_t, *t;
         struct children *child;
        struct prop_hdr **lenp;
        struct length len;
-       size_t extra = 0;
+       size_t extra = 0, elemsize = size;
 
         old_t = debug_tal(to_tal_hdr(*ctxp));
 
@@ -688,7 +688,8 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count)
                /* Copy here, in case we're shrinking! */
                len = *(struct length *)*lenp;
                extra = extra_for_length(size);
-       }
+       } else /* If we don't have an old length, we can't clear! */
+               assert(!clear);
 
         t = resizefn(old_t, sizeof(struct tal_hdr) + size + extra);
        if (!t) {
@@ -700,6 +701,12 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count)
        if (lenp) {
                struct length *new_len;
 
+               /* Clear between old end and new end. */
+               if (clear && count > len.count) {
+                       char *old_end = (char *)(t + 1) + len.count * elemsize;
+                       memset(old_end, 0, elemsize * (count - len.count));
+               }
+
                new_len = (struct length *)((char *)(t + 1) + size);
                len.count = count;
                *new_len = len;
@@ -753,7 +760,7 @@ bool tal_expand_(tal_t **ctxp, const void *src, size_t size, size_t count)
        assert(src < *ctxp
               || (char *)src >= (char *)(*ctxp) + (size * old_count));
 
-       if (!tal_resize_(ctxp, size, old_count + count))
+       if (!tal_resize_(ctxp, size, old_count + count, false))
                goto out;
 
        memcpy((char *)*ctxp + size * old_count, src, count * size);
@@ -789,7 +796,7 @@ void *tal_dup_(const tal_t *ctx, const void *p, size_t size,
        if (taken(p)) {
                if (unlikely(!p))
                        return NULL;
-               if (unlikely(!tal_resize_((void **)&p, size, n + extra)))
+               if (unlikely(!tal_resize_((void **)&p, size, n + extra, false)))
                        return tal_free(p);
                if (unlikely(!tal_steal(ctx, p)))
                        return tal_free(p);
index 86b56d35a3c26280a9915216a5443ebef78626e1..0b050759f74ed97829661de5dc2488af74264fe9 100644 (file)
@@ -110,7 +110,22 @@ void *tal_free(const tal_t *p);
  *     tal_resize(&p, 100);
  */
 #define tal_resize(p, count) \
-       tal_resize_((void **)(p), sizeof**(p), (count))
+       tal_resize_((void **)(p), sizeof**(p), (count), false)
+
+/**
+ * tal_resizez - enlarge or reduce a tal_arr[z]; zero out extra.
+ * @p: A pointer to the tal allocated array to resize.
+ * @count: the number to allocate.
+ *
+ * This returns true on success (and may move *@p), or false on failure.
+ * If @p has a length property, it is updated on success.
+ * On expand, new elements are memset to 0 bytes.
+ *
+ * Example:
+ *     tal_resizez(&p, 200);
+ */
+#define tal_resizez(p, count) \
+       tal_resize_((void **)(p), sizeof**(p), (count), true)
 
 /**
  * tal_steal - change the parent of a tal-allocated pointer.
@@ -406,7 +421,7 @@ void *tal_dup_(const tal_t *ctx, const void *p, size_t size,
 
 tal_t *tal_steal_(const tal_t *new_parent, const tal_t *t);
 
-bool tal_resize_(tal_t **ctxp, size_t size, size_t count);
+bool tal_resize_(tal_t **ctxp, size_t size, size_t count, bool clear);
 bool tal_expand_(tal_t **ctxp, const void *src, size_t size, size_t count);
 
 bool tal_add_destructor_(const tal_t *ctx, void (*destroy)(void *me));
index d3001faff84178746ff9dced2768b2f3ed296412..5cab66e9f9e4c50d46b31c1684691a6493274bf8 100644 (file)
@@ -40,6 +40,7 @@ int main(void)
        strcpy(c[0], "hello");
        tal_free(c[0]);
        ok1(tal_first(parent) == NULL);
+
        tal_free(parent);
 
        tal_cleanup();
diff --git a/ccan/tal/test/run-resizez.c b/ccan/tal/test/run-resizez.c
new file mode 100644 (file)
index 0000000..ddf6682
--- /dev/null
@@ -0,0 +1,27 @@
+#include <ccan/tal/tal.h>
+#include <ccan/tal/tal.c>
+#include <ccan/tap/tap.h>
+
+int main(void)
+{
+       char *parent, *c;
+       int i;
+
+       plan_tests(1 + 3 * 100 + 98);
+
+       parent = tal(NULL, char);
+       ok1(parent);
+
+       for (i = 0; i < 100; i++) {
+               c = tal_arr(parent, char, 1);
+               ok1(tal_resizez(&c, i));
+               ok1(tal_count(c) == i);
+               ok1(tal_parent(c) == parent);
+               if (i > 1)
+                       ok1(c[i-1] == '\0');
+       }
+       tal_free(parent);
+
+       tal_cleanup();
+       return exit_status();
+}