spiped 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/spiped/extconf.rb +3 -0
- data/ext/spiped/spiped-source/BUILDING +46 -0
- data/ext/spiped/spiped-source/CHANGELOG +44 -0
- data/ext/spiped/spiped-source/COPYRIGHT +33 -0
- data/ext/spiped/spiped-source/Makefile +47 -0
- data/ext/spiped/spiped-source/Makefile.POSIX +27 -0
- data/ext/spiped/spiped-source/Makefile.inc +20 -0
- data/ext/spiped/spiped-source/Makefile.prog +23 -0
- data/ext/spiped/spiped-source/POSIX/README +10 -0
- data/ext/spiped/spiped-source/POSIX/posix-cflags.sh +10 -0
- data/ext/spiped/spiped-source/POSIX/posix-clock_realtime.c +3 -0
- data/ext/spiped/spiped-source/POSIX/posix-l.c +1 -0
- data/ext/spiped/spiped-source/POSIX/posix-l.sh +14 -0
- data/ext/spiped/spiped-source/POSIX/posix-msg_nosignal.c +3 -0
- data/ext/spiped/spiped-source/README +198 -0
- data/ext/spiped/spiped-source/STYLE +151 -0
- data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.c +464 -0
- data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.h +45 -0
- data/ext/spiped/spiped-source/libcperciva/alg/sha256.c +442 -0
- data/ext/spiped/spiped-source/libcperciva/alg/sha256.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c +13 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c +8 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport.sh +37 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport.h +63 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport_x86_aesni.c +30 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.c +166 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.h +31 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.c +229 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.h +31 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.c +124 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.h +41 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.c +293 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.h +43 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.c +46 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.h +9 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.c +215 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.c +21 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.c +276 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.h +167 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/mpool.h +85 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.c +334 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.h +89 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.c +241 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.h +60 -0
- data/ext/spiped/spiped-source/libcperciva/events/events.c +203 -0
- data/ext/spiped/spiped-source/libcperciva/events/events.h +106 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_immediate.c +149 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_internal.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_network.c +347 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_network_selectstats.c +106 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_timer.c +273 -0
- data/ext/spiped/spiped-source/libcperciva/network/network.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_accept.c +103 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_connect.c +258 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_read.c +155 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_write.c +188 -0
- data/ext/spiped/spiped-source/libcperciva/util/asprintf.c +49 -0
- data/ext/spiped/spiped-source/libcperciva/util/asprintf.h +16 -0
- data/ext/spiped/spiped-source/libcperciva/util/daemonize.c +134 -0
- data/ext/spiped/spiped-source/libcperciva/util/daemonize.h +10 -0
- data/ext/spiped/spiped-source/libcperciva/util/entropy.c +76 -0
- data/ext/spiped/spiped-source/libcperciva/util/entropy.h +13 -0
- data/ext/spiped/spiped-source/libcperciva/util/imalloc.h +33 -0
- data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.c +19 -0
- data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.h +33 -0
- data/ext/spiped/spiped-source/libcperciva/util/monoclock.c +52 -0
- data/ext/spiped/spiped-source/libcperciva/util/monoclock.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/noeintr.c +54 -0
- data/ext/spiped/spiped-source/libcperciva/util/noeintr.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock.c +472 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock.h +56 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_internal.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_util.c +271 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_util.h +51 -0
- data/ext/spiped/spiped-source/libcperciva/util/sysendian.h +146 -0
- data/ext/spiped/spiped-source/libcperciva/util/warnp.c +76 -0
- data/ext/spiped/spiped-source/libcperciva/util/warnp.h +59 -0
- data/ext/spiped/spiped-source/proto/proto_conn.c +362 -0
- data/ext/spiped/spiped-source/proto/proto_conn.h +25 -0
- data/ext/spiped/spiped-source/proto/proto_crypt.c +396 -0
- data/ext/spiped/spiped-source/proto/proto_crypt.h +102 -0
- data/ext/spiped/spiped-source/proto/proto_handshake.c +330 -0
- data/ext/spiped/spiped-source/proto/proto_handshake.h +30 -0
- data/ext/spiped/spiped-source/proto/proto_pipe.c +202 -0
- data/ext/spiped/spiped-source/proto/proto_pipe.h +23 -0
- data/ext/spiped/spiped-source/spipe/Makefile +90 -0
- data/ext/spiped/spiped-source/spipe/README +24 -0
- data/ext/spiped/spiped-source/spipe/main.c +178 -0
- data/ext/spiped/spiped-source/spipe/pushbits.c +101 -0
- data/ext/spiped/spiped-source/spipe/pushbits.h +10 -0
- data/ext/spiped/spiped-source/spipe/spipe.1 +60 -0
- data/ext/spiped/spiped-source/spiped/Makefile +98 -0
- data/ext/spiped/spiped-source/spiped/README +62 -0
- data/ext/spiped/spiped-source/spiped/dispatch.c +214 -0
- data/ext/spiped/spiped-source/spiped/dispatch.h +27 -0
- data/ext/spiped/spiped-source/spiped/main.c +267 -0
- data/ext/spiped/spiped-source/spiped/spiped.1 +112 -0
- data/lib/spiped.rb +3 -0
- 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
|
+
}
|