spiped 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/ext/spiped/extconf.rb +3 -0
  3. data/ext/spiped/spiped-source/BUILDING +46 -0
  4. data/ext/spiped/spiped-source/CHANGELOG +44 -0
  5. data/ext/spiped/spiped-source/COPYRIGHT +33 -0
  6. data/ext/spiped/spiped-source/Makefile +47 -0
  7. data/ext/spiped/spiped-source/Makefile.POSIX +27 -0
  8. data/ext/spiped/spiped-source/Makefile.inc +20 -0
  9. data/ext/spiped/spiped-source/Makefile.prog +23 -0
  10. data/ext/spiped/spiped-source/POSIX/README +10 -0
  11. data/ext/spiped/spiped-source/POSIX/posix-cflags.sh +10 -0
  12. data/ext/spiped/spiped-source/POSIX/posix-clock_realtime.c +3 -0
  13. data/ext/spiped/spiped-source/POSIX/posix-l.c +1 -0
  14. data/ext/spiped/spiped-source/POSIX/posix-l.sh +14 -0
  15. data/ext/spiped/spiped-source/POSIX/posix-msg_nosignal.c +3 -0
  16. data/ext/spiped/spiped-source/README +198 -0
  17. data/ext/spiped/spiped-source/STYLE +151 -0
  18. data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.c +464 -0
  19. data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.h +45 -0
  20. data/ext/spiped/spiped-source/libcperciva/alg/sha256.c +442 -0
  21. data/ext/spiped/spiped-source/libcperciva/alg/sha256.h +95 -0
  22. data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c +13 -0
  23. data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c +8 -0
  24. data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport.sh +37 -0
  25. data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport.h +63 -0
  26. data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport_x86_aesni.c +30 -0
  27. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.c +166 -0
  28. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.h +31 -0
  29. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.c +229 -0
  30. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.h +31 -0
  31. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.c +124 -0
  32. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.h +41 -0
  33. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.c +293 -0
  34. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.h +43 -0
  35. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.c +46 -0
  36. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.h +9 -0
  37. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.c +215 -0
  38. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.h +14 -0
  39. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.c +21 -0
  40. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.h +14 -0
  41. data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.c +276 -0
  42. data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.h +167 -0
  43. data/ext/spiped/spiped-source/libcperciva/datastruct/mpool.h +85 -0
  44. data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.c +334 -0
  45. data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.h +89 -0
  46. data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.c +241 -0
  47. data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.h +60 -0
  48. data/ext/spiped/spiped-source/libcperciva/events/events.c +203 -0
  49. data/ext/spiped/spiped-source/libcperciva/events/events.h +106 -0
  50. data/ext/spiped/spiped-source/libcperciva/events/events_immediate.c +149 -0
  51. data/ext/spiped/spiped-source/libcperciva/events/events_internal.h +95 -0
  52. data/ext/spiped/spiped-source/libcperciva/events/events_network.c +347 -0
  53. data/ext/spiped/spiped-source/libcperciva/events/events_network_selectstats.c +106 -0
  54. data/ext/spiped/spiped-source/libcperciva/events/events_timer.c +273 -0
  55. data/ext/spiped/spiped-source/libcperciva/network/network.h +95 -0
  56. data/ext/spiped/spiped-source/libcperciva/network/network_accept.c +103 -0
  57. data/ext/spiped/spiped-source/libcperciva/network/network_connect.c +258 -0
  58. data/ext/spiped/spiped-source/libcperciva/network/network_read.c +155 -0
  59. data/ext/spiped/spiped-source/libcperciva/network/network_write.c +188 -0
  60. data/ext/spiped/spiped-source/libcperciva/util/asprintf.c +49 -0
  61. data/ext/spiped/spiped-source/libcperciva/util/asprintf.h +16 -0
  62. data/ext/spiped/spiped-source/libcperciva/util/daemonize.c +134 -0
  63. data/ext/spiped/spiped-source/libcperciva/util/daemonize.h +10 -0
  64. data/ext/spiped/spiped-source/libcperciva/util/entropy.c +76 -0
  65. data/ext/spiped/spiped-source/libcperciva/util/entropy.h +13 -0
  66. data/ext/spiped/spiped-source/libcperciva/util/imalloc.h +33 -0
  67. data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.c +19 -0
  68. data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.h +33 -0
  69. data/ext/spiped/spiped-source/libcperciva/util/monoclock.c +52 -0
  70. data/ext/spiped/spiped-source/libcperciva/util/monoclock.h +14 -0
  71. data/ext/spiped/spiped-source/libcperciva/util/noeintr.c +54 -0
  72. data/ext/spiped/spiped-source/libcperciva/util/noeintr.h +14 -0
  73. data/ext/spiped/spiped-source/libcperciva/util/sock.c +472 -0
  74. data/ext/spiped/spiped-source/libcperciva/util/sock.h +56 -0
  75. data/ext/spiped/spiped-source/libcperciva/util/sock_internal.h +14 -0
  76. data/ext/spiped/spiped-source/libcperciva/util/sock_util.c +271 -0
  77. data/ext/spiped/spiped-source/libcperciva/util/sock_util.h +51 -0
  78. data/ext/spiped/spiped-source/libcperciva/util/sysendian.h +146 -0
  79. data/ext/spiped/spiped-source/libcperciva/util/warnp.c +76 -0
  80. data/ext/spiped/spiped-source/libcperciva/util/warnp.h +59 -0
  81. data/ext/spiped/spiped-source/proto/proto_conn.c +362 -0
  82. data/ext/spiped/spiped-source/proto/proto_conn.h +25 -0
  83. data/ext/spiped/spiped-source/proto/proto_crypt.c +396 -0
  84. data/ext/spiped/spiped-source/proto/proto_crypt.h +102 -0
  85. data/ext/spiped/spiped-source/proto/proto_handshake.c +330 -0
  86. data/ext/spiped/spiped-source/proto/proto_handshake.h +30 -0
  87. data/ext/spiped/spiped-source/proto/proto_pipe.c +202 -0
  88. data/ext/spiped/spiped-source/proto/proto_pipe.h +23 -0
  89. data/ext/spiped/spiped-source/spipe/Makefile +90 -0
  90. data/ext/spiped/spiped-source/spipe/README +24 -0
  91. data/ext/spiped/spiped-source/spipe/main.c +178 -0
  92. data/ext/spiped/spiped-source/spipe/pushbits.c +101 -0
  93. data/ext/spiped/spiped-source/spipe/pushbits.h +10 -0
  94. data/ext/spiped/spiped-source/spipe/spipe.1 +60 -0
  95. data/ext/spiped/spiped-source/spiped/Makefile +98 -0
  96. data/ext/spiped/spiped-source/spiped/README +62 -0
  97. data/ext/spiped/spiped-source/spiped/dispatch.c +214 -0
  98. data/ext/spiped/spiped-source/spiped/dispatch.h +27 -0
  99. data/ext/spiped/spiped-source/spiped/main.c +267 -0
  100. data/ext/spiped/spiped-source/spiped/spiped.1 +112 -0
  101. data/lib/spiped.rb +3 -0
  102. metadata +143 -0
@@ -0,0 +1,167 @@
1
+ #ifndef _ELASTICARRAY_H_
2
+ #define _ELASTICARRAY_H_
3
+
4
+ #include <stddef.h>
5
+
6
+ /**
7
+ * Elastic Arrays are dynamically resizing arrays which remain within a
8
+ * factor of 4 of the optimal size for the data they contain and have (within
9
+ * a constant factor) amortized optimal running time providing that all of
10
+ * the allocated space is accessed at some point. Functions return NULL or
11
+ * (int)(-1) on error and set errno; other return types indicate that failure
12
+ * is not possible. On error, the array will be unmodified.
13
+ *
14
+ * The ELASTICARRAY_DECL(type, prefix, rectype) macro can be used to create a
15
+ * more friendly interface, at the expense of restricting the array to only
16
+ * holding a single data type.
17
+ */
18
+
19
+ /* Opaque elastic array type. */
20
+ struct elasticarray;
21
+
22
+ /**
23
+ * elasticarray_init(nrec, reclen):
24
+ * Create and return an elastic array holding ${nrec} (uninitialized) records
25
+ * of length ${reclen}. Takes O(nrec * reclen) time.
26
+ */
27
+ struct elasticarray * elasticarray_init(size_t, size_t);
28
+
29
+ /**
30
+ * elasticarray_resize(EA, nrec, reclen):
31
+ * Resize the elastic array pointed to by ${EA} to hold ${nrec} records of
32
+ * length ${reclen}. If ${nrec} exceeds the number of records previously
33
+ * held by the array, the additional records will be uninitialized. Takes
34
+ * O(nrec * reclen) time.
35
+ */
36
+ int elasticarray_resize(struct elasticarray *, size_t, size_t);
37
+
38
+ /**
39
+ * elasticarray_getsize(EA, reclen):
40
+ * Return the number of length-${reclen} records in the array, rounding down
41
+ * if there is a partial record (which can only occur if elasticarray_*
42
+ * functions have been called with different values of reclen). The value
43
+ * ${reclen} must be positive.
44
+ */
45
+ size_t elasticarray_getsize(struct elasticarray *, size_t);
46
+
47
+ /**
48
+ * elasticarray_append(EA, buf, nrec, reclen):
49
+ * Append to the elastic array ${EA} the ${nrec} records of length ${reclen}
50
+ * stored in ${buf}. Takes O(nrec * reclen) amortized time.
51
+ */
52
+ int elasticarray_append(struct elasticarray *, const void *, size_t, size_t);
53
+
54
+ /**
55
+ * elasticarray_shrink(EA, nrec, reclen):
56
+ * Delete the final ${nrec} records of length ${reclen} from the elastic
57
+ * array ${EA}. If there are fewer than ${nrec} records, all records
58
+ * present will be deleted.
59
+ *
60
+ * As an exception to the normal rule, an elastic array may occupy more than
61
+ * 4 times the optimal storage immediately following an elasticarray_shrink
62
+ * call; but only if realloc(3) failed to shrink a memory allocation.
63
+ */
64
+ void elasticarray_shrink(struct elasticarray *, size_t, size_t);
65
+
66
+ /**
67
+ * elasticarray_truncate(EA):
68
+ * Release any spare space in the elastic array ${EA}.
69
+ */
70
+ int elasticarray_truncate(struct elasticarray *);
71
+
72
+ /**
73
+ * elasticarray_get(EA, pos, reclen):
74
+ * Return a pointer to record number ${pos} of length ${reclen} in the
75
+ * elastic array ${EA}. Takes O(1) time.
76
+ */
77
+ void * elasticarray_get(struct elasticarray *, size_t, size_t);
78
+
79
+ /**
80
+ * elasticarray_free(EA):
81
+ * Free the elastic array ${EA}. Takes O(1) time.
82
+ */
83
+ void elasticarray_free(struct elasticarray *);
84
+
85
+ /**
86
+ * elasticarray_export(EA, buf, nrec, reclen):
87
+ * Return the data in the elastic array ${EA} as a buffer ${buf} containing
88
+ * ${nrec} records of length ${reclen}. Free the elastic array ${EA}.
89
+ */
90
+ int elasticarray_export(struct elasticarray *, void **, size_t *, size_t);
91
+
92
+ /**
93
+ * ELASTICARRAY_DECL(type, prefix, rectype):
94
+ * Declare the type ${type} and the following functions:
95
+ * ${type} ${prefix}_init(size_t nrec);
96
+ * int ${prefix}_resize(${type} EA, size_t nrec);
97
+ * size_t ${prefix}_getsize(${type} EA);
98
+ * int ${prefix}_append(${type} EA, const void * buf, size_t nrec);
99
+ * void ${prefix}_shrink(${type} EA, size_t nrec);
100
+ * int ${prefix}_truncate(${type} EA);
101
+ * ${rectype} * ${prefix}_get(${type} EA, size_t pos);
102
+ * void ${prefix}_free(${type} EA);
103
+ */
104
+ #define ELASTICARRAY_DECL(type, prefix, rectype) \
105
+ static inline struct prefix##_struct * \
106
+ prefix##_init(size_t nrec) \
107
+ { \
108
+ struct elasticarray * EA; \
109
+ \
110
+ EA = elasticarray_init(nrec, sizeof(rectype)); \
111
+ return ((struct prefix##_struct *)EA); \
112
+ } \
113
+ static inline int \
114
+ prefix##_resize(struct prefix##_struct * EA, size_t nrec) \
115
+ { \
116
+ return (elasticarray_resize((struct elasticarray *)EA, \
117
+ nrec, sizeof(rectype))); \
118
+ } \
119
+ static inline size_t \
120
+ prefix##_getsize(struct prefix##_struct * EA) \
121
+ { \
122
+ return (elasticarray_getsize((struct elasticarray *)EA, \
123
+ sizeof(rectype))); \
124
+ } \
125
+ static inline int \
126
+ prefix##_append(struct prefix##_struct * EA, \
127
+ rectype const * buf, size_t nrec) \
128
+ { \
129
+ return (elasticarray_append((struct elasticarray *)EA, \
130
+ buf, nrec, sizeof(rectype))); \
131
+ } \
132
+ static inline void \
133
+ prefix##_shrink(struct prefix##_struct * EA, size_t nrec) \
134
+ { \
135
+ elasticarray_shrink((struct elasticarray *)EA, \
136
+ nrec, sizeof(rectype)); \
137
+ } \
138
+ static inline int \
139
+ prefix##_truncate(struct prefix##_struct * EA) \
140
+ { \
141
+ return (elasticarray_truncate( \
142
+ (struct elasticarray *)EA)); \
143
+ } \
144
+ static inline rectype * \
145
+ prefix##_get(struct prefix##_struct * EA, size_t pos) \
146
+ { \
147
+ rectype * rec; \
148
+ \
149
+ rec = elasticarray_get((struct elasticarray *)EA, \
150
+ pos, sizeof(rectype)); \
151
+ return (rec); \
152
+ } \
153
+ static inline void \
154
+ prefix##_free(struct prefix##_struct * EA) \
155
+ { \
156
+ elasticarray_free((struct elasticarray *)EA); \
157
+ } \
158
+ static inline int \
159
+ prefix##_export(struct prefix##_struct * EA, rectype ** buf, \
160
+ size_t * nrec) \
161
+ { \
162
+ return (elasticarray_export((struct elasticarray *)EA, \
163
+ (void **)buf, nrec, sizeof(rectype))); \
164
+ } \
165
+ typedef struct prefix##_struct * type
166
+
167
+ #endif /* !_ELASTICARRAY_H_ */
@@ -0,0 +1,85 @@
1
+ #ifndef _MPOOL_H_
2
+ #define _MPOOL_H_
3
+
4
+ #include <stdlib.h>
5
+
6
+ /**
7
+ * Memory allocator cache. Memory allocations can be returned to the pool
8
+ * and reused by a subsequent allocation without returning all the way to
9
+ * free/malloc. In effect, this is an optimization for the case where we
10
+ * know we will want another allocation of the same size soon, at the expense
11
+ * of allowing the memory to be reused by some other code.
12
+ */
13
+
14
+ /**
15
+ * MPOOL(name, type, size):
16
+ * Define the functions
17
+ *
18
+ * ${type} * mpool_${name}_malloc(void);
19
+ * void mpool_${name}_free(${type} *);
20
+ *
21
+ * which allocate and free structures of type ${type}. Up to ${size}
22
+ * such structures are kept cached after _free is called in order to
23
+ * allow future _malloc calls to be rapidly serviced.
24
+ *
25
+ * Cached structures will be freed at program exit time in order to aid
26
+ * in the detection of memory leaks.
27
+ */
28
+ #define MPOOL(name, type, size) \
29
+ static struct mpool_##name##_struct { \
30
+ size_t stacklen; \
31
+ void * top; \
32
+ int atexit_set; \
33
+ } mpool_##name##_rec = {0, NULL, 0}; \
34
+ \
35
+ static void \
36
+ mpool_##name##_atexit(void) \
37
+ { \
38
+ void * top; \
39
+ \
40
+ while ((top = mpool_##name##_rec.top) != NULL) { \
41
+ mpool_##name##_rec.top = *(void **)top; \
42
+ free(top); \
43
+ } \
44
+ } \
45
+ \
46
+ static inline type * \
47
+ mpool_##name##_malloc(void) \
48
+ { \
49
+ type * p; \
50
+ \
51
+ if (mpool_##name##_rec.stacklen) { \
52
+ p = mpool_##name##_rec.top; \
53
+ mpool_##name##_rec.top = *(void **)p; \
54
+ mpool_##name##_rec.stacklen -= 1; \
55
+ } else { \
56
+ if (mpool_##name##_rec.atexit_set == 0) { \
57
+ atexit(mpool_##name##_atexit); \
58
+ mpool_##name##_rec.atexit_set = 1; \
59
+ } \
60
+ p = malloc((sizeof(type) > sizeof(void *)) ? \
61
+ sizeof(type) : sizeof(void *)); \
62
+ } \
63
+ \
64
+ return (p); \
65
+ } \
66
+ \
67
+ static inline void \
68
+ mpool_##name##_free(type * p) \
69
+ { \
70
+ \
71
+ if (p == NULL) \
72
+ return; \
73
+ \
74
+ if (mpool_##name##_rec.stacklen < size) { \
75
+ *(void **)p = mpool_##name##_rec.top; \
76
+ mpool_##name##_rec.top = p; \
77
+ mpool_##name##_rec.stacklen += 1; \
78
+ } else { \
79
+ free(p); \
80
+ } \
81
+ } \
82
+ \
83
+ struct mpool_##name##_dummy
84
+
85
+ #endif /* !_MPOOL_H_ */
@@ -0,0 +1,334 @@
1
+ #include <stdlib.h>
2
+
3
+ #include "elasticarray.h"
4
+
5
+ #include "ptrheap.h"
6
+
7
+ ELASTICARRAY_DECL(PTRLIST, ptrlist, void *);
8
+
9
+ struct ptrheap {
10
+ int (* compar)(void *, const void *, const void *);
11
+ void (* setreccookie)(void *, void *, size_t);
12
+ void * cookie;
13
+ PTRLIST elems;
14
+ size_t nelems;
15
+ };
16
+
17
+ /**
18
+ * swap(elems, i, j, setreccookie, cookie):
19
+ * Swap elements ${i} and ${j} in ${elems}. If ${setreccookie} is non-NULL,
20
+ * invoke ${setreccookie}(${cookie}, elem, pos) for each of the elements and
21
+ * their new positions in the tree.
22
+ */
23
+ static void
24
+ swap(PTRLIST elems, size_t i, size_t j,
25
+ void (* setreccookie)(void *, void *, size_t), void * cookie)
26
+ {
27
+ void * tmp;
28
+
29
+ /* Swap the elements. */
30
+ tmp = *ptrlist_get(elems, i);
31
+ *ptrlist_get(elems, i) = *ptrlist_get(elems, j);
32
+ *ptrlist_get(elems, j) = tmp;
33
+
34
+ /* Notify about the moved elements. */
35
+ if (setreccookie != NULL) {
36
+ setreccookie(cookie, *ptrlist_get(elems, i), i);
37
+ setreccookie(cookie, *ptrlist_get(elems, j), j);
38
+ }
39
+ }
40
+
41
+ /**
42
+ * heapifyup(elems, i, compar, setreccookie, cookie):
43
+ * Sift up element ${i} of the elements ${elems}, using the comparison
44
+ * function ${compar} and the cookie ${cookie}. If elements move and
45
+ * ${setreccookie} is non-NULL, use it to notify about the updated position
46
+ * of elements in the heap.
47
+ */
48
+ static void
49
+ heapifyup(PTRLIST elems, size_t i,
50
+ int (* compar)(void *, const void *, const void *),
51
+ void (* setreccookie)(void *, void *, size_t), void * cookie)
52
+ {
53
+
54
+ /* Iterate up the tree. */
55
+ do {
56
+ /* If we're at the root, we have nothing to do. */
57
+ if (i == 0)
58
+ break;
59
+
60
+ /* If this is >= its parent, we're done. */
61
+ if (compar(cookie, *ptrlist_get(elems, i),
62
+ *ptrlist_get(elems, (i - 1) / 2)) >= 0)
63
+ break;
64
+
65
+ /* Swap with the parent. */
66
+ swap(elems, i, (i - 1) / 2, setreccookie, cookie);
67
+
68
+ /* Move up the tree. */
69
+ i = (i - 1) / 2;
70
+ } while (1);
71
+ }
72
+
73
+ /**
74
+ * heapify(elems, i, N, compar, setreccookie, cookie):
75
+ * Sift down element number ${i} out of ${N} of the elements ${elems}, using
76
+ * the comparison function ${compar} and the cookie ${cookie}. If elements
77
+ * move and ${setreccookie} is non-NULL, use it to notify about the updated
78
+ * position of elements in the heap.
79
+ */
80
+ static void
81
+ heapify(PTRLIST elems, size_t i, size_t N,
82
+ int (* compar)(void *, const void *, const void *),
83
+ void (* setreccookie)(void *, void *, size_t), void * cookie)
84
+ {
85
+ size_t min;
86
+
87
+ /* Iterate down the tree. */
88
+ do {
89
+ /* Look for the minimum element out of {i, 2i+1, 2i+2}. */
90
+ min = i;
91
+
92
+ /* Is this bigger than element 2i+1? */
93
+ if ((2 * i + 1 < N) &&
94
+ (compar(cookie, *ptrlist_get(elems, min),
95
+ *ptrlist_get(elems, 2 * i + 1)) > 0))
96
+ min = 2 * i + 1;
97
+
98
+ /* Is this bigger than element 2i+2? */
99
+ if ((2 * i + 2 < N) &&
100
+ (compar(cookie, *ptrlist_get(elems, min),
101
+ *ptrlist_get(elems, 2 * i + 2)) > 0))
102
+ min = 2 * i + 2;
103
+
104
+ /* If the minimum is i, we have heap-property. */
105
+ if (min == i)
106
+ break;
107
+
108
+ /* Move the minimum into position i. */
109
+ swap(elems, min, i, setreccookie, cookie);
110
+
111
+ /* Move down the tree. */
112
+ i = min;
113
+ } while (1);
114
+ }
115
+
116
+ /**
117
+ * ptrheap_init(compar, setreccookie, cookie):
118
+ * Create and return an empty heap. The function ${compar}(${cookie}, x, y)
119
+ * should return less than, equal to, or greater than 0 depending on whether
120
+ * x is less than, equal to, or greater than y; and if ${setreccookie} is
121
+ * non-zero it will be called as ${setreccookie}(${cookie}, ${ptr}, ${rc}) to
122
+ * indicate that the value ${rc} is the current record cookie for the pointer
123
+ * ${ptr}. The function ${setreccookie} may not make any ptrheap_* calls.
124
+ */
125
+ struct ptrheap *
126
+ ptrheap_init(int (* compar)(void *, const void *, const void *),
127
+ void (* setreccookie)(void *, void *, size_t), void * cookie)
128
+ {
129
+
130
+ /* Let ptrheap_create handle this. */
131
+ return (ptrheap_create(compar, setreccookie, cookie, 0, NULL));
132
+ }
133
+
134
+ /**
135
+ * ptrheap_create(compar, setreccookie, cookie, N, ptrs):
136
+ * Create and return a heap, as in ptrheap_init, but with the ${N} pointers
137
+ * in ${ptrs} as heap elements. This is faster than creating an empty heap
138
+ * and adding the elements individually.
139
+ */
140
+ struct ptrheap *
141
+ ptrheap_create(int (* compar)(void *, const void *, const void *),
142
+ void (* setreccookie)(void *, void *, size_t), void * cookie,
143
+ size_t N, void ** ptrs)
144
+ {
145
+ struct ptrheap * H;
146
+ size_t i;
147
+
148
+ /* Allocate structure. */
149
+ if ((H = malloc(sizeof(struct ptrheap))) == NULL)
150
+ goto err0;
151
+
152
+ /* Store parameters. */
153
+ H->compar = compar;
154
+ H->setreccookie = setreccookie;
155
+ H->cookie = cookie;
156
+
157
+ /* We will have N elements. */
158
+ H->nelems = N;
159
+
160
+ /* Allocate space for N heap elements. */
161
+ if ((H->elems = ptrlist_init(N)) == NULL)
162
+ goto err1;
163
+
164
+ /* Copy the heap elements in. */
165
+ for (i = 0; i < N; i++)
166
+ *ptrlist_get(H->elems, i) = ptrs[i];
167
+
168
+ /* Turn this into a heap. */
169
+ for (i = N - 1; i < N; i--)
170
+ heapify(H->elems, i, N, H->compar, NULL, H->cookie);
171
+
172
+ /* Advise the caller about the record cookies. */
173
+ if (H->setreccookie != NULL)
174
+ for (i = 0; i < N; i++)
175
+ (H->setreccookie)(H->cookie,
176
+ *ptrlist_get(H->elems, i), i);
177
+
178
+ /* Success! */
179
+ return (H);
180
+
181
+ err1:
182
+ free(H);
183
+ err0:
184
+ /* Failure! */
185
+ return (NULL);
186
+ }
187
+
188
+ /**
189
+ * ptrheap_add(H, ptr):
190
+ * Add the pointer ${ptr} to the heap ${H}.
191
+ */
192
+ int
193
+ ptrheap_add(struct ptrheap * H, void * ptr)
194
+ {
195
+
196
+ /* Add the element to the end of the heap. */
197
+ if (ptrlist_append(H->elems, &ptr, 1))
198
+ goto err0;
199
+ H->nelems += 1;
200
+
201
+ /* Advise the caller about the current location of this record. */
202
+ if (H->setreccookie != NULL)
203
+ (H->setreccookie)(H->cookie, ptr, H->nelems - 1);
204
+
205
+ /* Move the new element up in the tree if necessary. */
206
+ heapifyup(H->elems, H->nelems - 1,
207
+ H->compar, H->setreccookie, H->cookie);
208
+
209
+ /* Success! */
210
+ return (0);
211
+
212
+ err0:
213
+ /* Failure! */
214
+ return (-1);
215
+ }
216
+
217
+ /**
218
+ * ptrheap_getmin(H):
219
+ * Return the minimum pointer in the heap ${H}. If the heap is empty, NULL
220
+ * is returned.
221
+ */
222
+ void *
223
+ ptrheap_getmin(struct ptrheap * H)
224
+ {
225
+
226
+ /* If we have any elements, the minimum is in position 0. */
227
+ if (H->nelems)
228
+ return (*ptrlist_get(H->elems, 0));
229
+ else
230
+ return (NULL);
231
+ }
232
+
233
+ /**
234
+ * ptrheap_delete(H, rc):
235
+ * Delete from the heap ${H} the element ptr for which the function call
236
+ * setreccookie(cookie, ptr, ${rc}) was most recently made.
237
+ */
238
+ void
239
+ ptrheap_delete(struct ptrheap * H, size_t rc)
240
+ {
241
+
242
+ /*
243
+ * If the element we're deleting is not at the end of the heap,
244
+ * replace it with the element which is currently at the end.
245
+ */
246
+ if (rc != H->nelems - 1) {
247
+ /* Move ptr from position H->nelems - 1 into position rc. */
248
+ *ptrlist_get(H->elems, rc) =
249
+ *ptrlist_get(H->elems, H->nelems - 1);
250
+ if (H->setreccookie != NULL)
251
+ (H->setreccookie)(H->cookie,
252
+ *ptrlist_get(H->elems, rc), rc);
253
+
254
+ /* Is this too small to be in position ${rc}? */
255
+ if ((rc > 0) &&
256
+ (H->compar(H->cookie, *ptrlist_get(H->elems, rc),
257
+ *ptrlist_get(H->elems, (rc - 1) / 2)) < 0)) {
258
+ /* Swap with the parent, and keep moving up. */
259
+ swap(H->elems, rc, (rc - 1) / 2,
260
+ H->setreccookie, H->cookie);
261
+ heapifyup(H->elems, (rc - 1) / 2,
262
+ H->compar, H->setreccookie, H->cookie);
263
+ } else {
264
+ /* Maybe we need to move it down instead? */
265
+ heapify(H->elems, rc, H->nelems,
266
+ H->compar, H->setreccookie, H->cookie);
267
+ }
268
+ }
269
+
270
+ /*
271
+ * We've got everything we want to keep in positions 0 .. nelems - 2,
272
+ * and we have heap-nature, so all we need to do is strip off the
273
+ * final pointer.
274
+ */
275
+ ptrlist_shrink(H->elems, 1);
276
+ H->nelems--;
277
+ }
278
+
279
+ /**
280
+ * ptrheap_deletemin(H):
281
+ * Delete the minimum element in the heap ${H}.
282
+ */
283
+ void
284
+ ptrheap_deletemin(struct ptrheap * H)
285
+ {
286
+
287
+ /* Let ptrheap_delete handle this. */
288
+ ptrheap_delete(H, 0);
289
+ }
290
+
291
+ /**
292
+ * ptrheap_increase(H, rc):
293
+ * Adjust the heap ${H} to account for the fact that the element ptr for
294
+ * which the function call setreccookie(cookie, ptr, ${rc}) was most recently
295
+ * made has incrased.
296
+ */
297
+ void
298
+ ptrheap_increase(struct ptrheap * H, size_t rc)
299
+ {
300
+
301
+ /* Move the element down if necessary. */
302
+ heapify(H->elems, rc, H->nelems,
303
+ H->compar, H->setreccookie, H->cookie);
304
+ }
305
+
306
+ /**
307
+ * ptrheap_increasemin(H):
308
+ * Adjust the heap ${H} to account for the fact that the (formerly) minimum
309
+ * element has increased.
310
+ */
311
+ void
312
+ ptrheap_increasemin(struct ptrheap * H)
313
+ {
314
+
315
+ /* Move the element down if necessary. */
316
+ heapify(H->elems, 0, H->nelems,
317
+ H->compar, H->setreccookie, H->cookie);
318
+ }
319
+
320
+ /**
321
+ * ptrheap_free(H):
322
+ * Free the pointer heap ${H}.
323
+ */
324
+ void
325
+ ptrheap_free(struct ptrheap * H)
326
+ {
327
+
328
+ /* Be compatible with free(NULL). */
329
+ if (H == NULL)
330
+ return;
331
+
332
+ ptrlist_free(H->elems);
333
+ free(H);
334
+ }