iodine 0.6.5 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of iodine might be problematic. Click here for more details.

Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +4 -4
  4. data/SPEC-Websocket-Draft.md +3 -6
  5. data/bin/mustache.rb +128 -0
  6. data/examples/test_template.mustache +16 -0
  7. data/ext/iodine/fio.c +9397 -0
  8. data/ext/iodine/fio.h +4723 -0
  9. data/ext/iodine/fio_ary.h +353 -54
  10. data/ext/iodine/fio_cli.c +351 -361
  11. data/ext/iodine/fio_cli.h +84 -105
  12. data/ext/iodine/fio_hashmap.h +70 -16
  13. data/ext/iodine/fio_json_parser.h +35 -24
  14. data/ext/iodine/fio_siphash.c +104 -4
  15. data/ext/iodine/fio_siphash.h +18 -2
  16. data/ext/iodine/fio_str.h +1218 -0
  17. data/ext/iodine/fio_tmpfile.h +1 -1
  18. data/ext/iodine/fiobj.h +13 -8
  19. data/ext/iodine/fiobj4sock.h +6 -8
  20. data/ext/iodine/fiobj_ary.c +107 -17
  21. data/ext/iodine/fiobj_ary.h +36 -4
  22. data/ext/iodine/fiobj_data.c +146 -127
  23. data/ext/iodine/fiobj_data.h +25 -23
  24. data/ext/iodine/fiobj_hash.c +7 -7
  25. data/ext/iodine/fiobj_hash.h +6 -5
  26. data/ext/iodine/fiobj_json.c +20 -17
  27. data/ext/iodine/fiobj_json.h +5 -5
  28. data/ext/iodine/fiobj_mem.h +71 -0
  29. data/ext/iodine/fiobj_mustache.c +310 -0
  30. data/ext/iodine/fiobj_mustache.h +40 -0
  31. data/ext/iodine/fiobj_numbers.c +199 -94
  32. data/ext/iodine/fiobj_numbers.h +7 -7
  33. data/ext/iodine/fiobj_str.c +142 -333
  34. data/ext/iodine/fiobj_str.h +65 -55
  35. data/ext/iodine/fiobject.c +49 -11
  36. data/ext/iodine/fiobject.h +40 -39
  37. data/ext/iodine/http.c +382 -190
  38. data/ext/iodine/http.h +124 -80
  39. data/ext/iodine/http1.c +99 -127
  40. data/ext/iodine/http1.h +5 -5
  41. data/ext/iodine/http1_parser.c +3 -2
  42. data/ext/iodine/http1_parser.h +2 -2
  43. data/ext/iodine/http_internal.c +14 -12
  44. data/ext/iodine/http_internal.h +25 -19
  45. data/ext/iodine/iodine.c +37 -18
  46. data/ext/iodine/iodine.h +4 -0
  47. data/ext/iodine/iodine_caller.c +9 -2
  48. data/ext/iodine/iodine_caller.h +2 -0
  49. data/ext/iodine/iodine_connection.c +82 -117
  50. data/ext/iodine/iodine_defer.c +57 -50
  51. data/ext/iodine/iodine_defer.h +0 -1
  52. data/ext/iodine/iodine_fiobj2rb.h +4 -2
  53. data/ext/iodine/iodine_helpers.c +4 -4
  54. data/ext/iodine/iodine_http.c +25 -32
  55. data/ext/iodine/iodine_json.c +2 -1
  56. data/ext/iodine/iodine_mustache.c +423 -0
  57. data/ext/iodine/iodine_mustache.h +6 -0
  58. data/ext/iodine/iodine_pubsub.c +48 -153
  59. data/ext/iodine/iodine_pubsub.h +5 -4
  60. data/ext/iodine/iodine_rack_io.c +7 -5
  61. data/ext/iodine/iodine_store.c +16 -13
  62. data/ext/iodine/iodine_tcp.c +26 -34
  63. data/ext/iodine/mustache_parser.h +1085 -0
  64. data/ext/iodine/redis_engine.c +740 -646
  65. data/ext/iodine/redis_engine.h +13 -15
  66. data/ext/iodine/resp_parser.h +11 -5
  67. data/ext/iodine/websocket_parser.h +13 -13
  68. data/ext/iodine/websockets.c +240 -393
  69. data/ext/iodine/websockets.h +52 -113
  70. data/lib/iodine.rb +1 -1
  71. data/lib/iodine/mustache.rb +140 -0
  72. data/lib/iodine/version.rb +1 -1
  73. metadata +15 -28
  74. data/ext/iodine/defer.c +0 -566
  75. data/ext/iodine/defer.h +0 -148
  76. data/ext/iodine/evio.c +0 -26
  77. data/ext/iodine/evio.h +0 -161
  78. data/ext/iodine/evio_callbacks.c +0 -26
  79. data/ext/iodine/evio_epoll.c +0 -251
  80. data/ext/iodine/evio_kqueue.c +0 -194
  81. data/ext/iodine/facil.c +0 -2325
  82. data/ext/iodine/facil.h +0 -616
  83. data/ext/iodine/fio_base64.c +0 -277
  84. data/ext/iodine/fio_base64.h +0 -71
  85. data/ext/iodine/fio_llist.h +0 -257
  86. data/ext/iodine/fio_mem.c +0 -675
  87. data/ext/iodine/fio_mem.h +0 -143
  88. data/ext/iodine/fio_random.c +0 -248
  89. data/ext/iodine/fio_random.h +0 -45
  90. data/ext/iodine/fio_sha1.c +0 -362
  91. data/ext/iodine/fio_sha1.h +0 -107
  92. data/ext/iodine/fio_sha2.c +0 -842
  93. data/ext/iodine/fio_sha2.h +0 -169
  94. data/ext/iodine/pubsub.c +0 -867
  95. data/ext/iodine/pubsub.h +0 -221
  96. data/ext/iodine/sock.c +0 -1366
  97. data/ext/iodine/sock.h +0 -566
  98. data/ext/iodine/spnlock.inc +0 -111
@@ -1,277 +0,0 @@
1
- /*
2
- Copyright: Boaz Segev, 2016-2018
3
- License: MIT except for any non-public-domain algorithms (none that I'm aware
4
- of), which might be subject to their own licenses.
5
-
6
- Feel free to copy, use and enjoy in accordance with to the license(s).
7
- */
8
- #ifndef _GNU_SOURCE
9
- #define _GNU_SOURCE
10
- #endif
11
- #include "fio_base64.h"
12
-
13
- #include <stdint.h>
14
- #include <stdlib.h>
15
- /* ****************************************************************************
16
- Base64 encoding
17
- ***************************************************************************** */
18
-
19
- /** the base64 encoding array */
20
- static char base64_encodes[] =
21
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
22
-
23
- /**
24
- a base64 decoding array
25
- */
26
- static unsigned base64_decodes[] = {
27
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
28
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29
- 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60,
30
- 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
31
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0,
32
- 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
33
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
37
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
38
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40
- 0, 0, 0, 0, 0, 0, 0, 0, 0};
41
-
42
- /**
43
- This will encode a byte array (data) of a specified length (len) and
44
- place the encoded data into the target byte buffer (target). The target buffer
45
- MUST have enough room for the expected data.
46
-
47
- Base64 encoding always requires 4 bytes for each 3 bytes. Padding is added if
48
- the raw data's length isn't devisable by 3.
49
-
50
- Always assume the target buffer should have room enough for (len*4/3 + 4)
51
- bytes.
52
-
53
- Returns the number of bytes actually written to the target buffer
54
- (including the Base64 required padding and excluding a NULL terminator).
55
-
56
- A NULL terminator char is NOT written to the target buffer.
57
- */
58
- int fio_base64_encode(char *target, const char *data, int len) {
59
- /* walk backwards, allowing fo inplace decoding (target == data) */
60
- int groups = len / 3;
61
- const int mod = len - (groups * 3);
62
- const int target_size = (groups + (mod != 0)) * 4;
63
- char *writer = target + target_size - 1;
64
- const char *reader = data + len - 1;
65
- writer[1] = 0;
66
- switch (mod) {
67
- case 2: {
68
- char tmp2 = *(reader--);
69
- char tmp1 = *(reader--);
70
- *(writer--) = '=';
71
- *(writer--) = base64_encodes[((tmp2 & 15) << 2)];
72
- *(writer--) = base64_encodes[((tmp1 & 3) << 4) | ((tmp2 >> 4) & 15)];
73
- *(writer--) = base64_encodes[(tmp1 >> 2) & 63];
74
- } break;
75
- case 1: {
76
- char tmp1 = *(reader--);
77
- *(writer--) = '=';
78
- *(writer--) = '=';
79
- *(writer--) = base64_encodes[(tmp1 & 3) << 4];
80
- *(writer--) = base64_encodes[(tmp1 >> 2) & 63];
81
- } break;
82
- }
83
- while (groups) {
84
- groups--;
85
- const char tmp3 = *(reader--);
86
- const char tmp2 = *(reader--);
87
- const char tmp1 = *(reader--);
88
- *(writer--) = base64_encodes[tmp3 & 63];
89
- *(writer--) = base64_encodes[((tmp2 & 15) << 2) | ((tmp3 >> 6) & 3)];
90
- *(writer--) = base64_encodes[(((tmp1 & 3) << 4) | ((tmp2 >> 4) & 15))];
91
- *(writer--) = base64_encodes[(tmp1 >> 2) & 63];
92
- }
93
- return target_size;
94
- }
95
-
96
- /**
97
- This will decode a Base64 encoded string of a specified length (len) and
98
- place the decoded data into the target byte buffer (target).
99
-
100
- The target buffer MUST have enough room for the expected data.
101
-
102
- A NULL byte will be appended to the target buffer. The function will return
103
- the number of bytes written to the target buffer.
104
-
105
- If the target buffer is NULL, the encoded string will be destructively edited
106
- and the decoded data will be placed in the original string's buffer.
107
-
108
- Base64 encoding always requires 4 bytes for each 3 bytes. Padding is added if
109
- the raw data's length isn't devisable by 3. Hence, the target buffer should
110
- be, at least, `base64_len/4*3 + 3` long.
111
-
112
- Returns the number of bytes actually written to the target buffer (excluding
113
- the NULL terminator byte).
114
- */
115
- int fio_base64_decode(char *target, char *encoded, int base64_len) {
116
- if (!target)
117
- target = encoded;
118
- if (base64_len <= 0) {
119
- target[0] = 0;
120
- return 0;
121
- }
122
- int written = 0;
123
- char tmp1, tmp2, tmp3, tmp4;
124
- while (*encoded == '\r' || *encoded == '\n' || *encoded == ' ') {
125
- base64_len--;
126
- encoded++;
127
- }
128
- while (encoded[base64_len - 1] == '\r' || encoded[base64_len - 1] == '\n' ||
129
- encoded[base64_len - 1] == ' ' || encoded[base64_len - 1] == 0) {
130
- base64_len--;
131
- }
132
- while (base64_len >= 4) {
133
- tmp1 = *(encoded++);
134
- tmp2 = *(encoded++);
135
- tmp3 = *(encoded++);
136
- tmp4 = *(encoded++);
137
- *(target++) = (base64_decodes[(size_t)tmp1] << 2) |
138
- (base64_decodes[(size_t)tmp2] >> 4);
139
- *(target++) = (base64_decodes[(size_t)tmp2] << 4) |
140
- (base64_decodes[(size_t)tmp3] >> 2);
141
- *(target++) =
142
- (base64_decodes[(size_t)tmp3] << 6) | (base64_decodes[(size_t)tmp4]);
143
- // make sure we don't loop forever.
144
- base64_len -= 4;
145
- // count written bytes
146
- written += 3;
147
- // skip white space
148
- while (base64_len &&
149
- (*encoded == '\r' || *encoded == '\n' || *encoded == ' ')) {
150
- base64_len--;
151
- encoded++;
152
- }
153
- }
154
- // deal with the "tail" of the mis-encoded stream - this shouldn't happen
155
- tmp1 = 0;
156
- tmp2 = 0;
157
- tmp3 = 0;
158
- tmp4 = 0;
159
- switch (base64_len) {
160
- case 1:
161
- tmp1 = *(encoded++);
162
- *(target++) = base64_decodes[(size_t)tmp1];
163
- written += 1;
164
- break;
165
- case 2:
166
- tmp1 = *(encoded++);
167
- tmp2 = *(encoded++);
168
- *(target++) = (base64_decodes[(size_t)tmp1] << 2) |
169
- (base64_decodes[(size_t)tmp2] >> 6);
170
- *(target++) = (base64_decodes[(size_t)tmp2] << 4);
171
- written += 2;
172
- break;
173
- case 3:
174
- tmp1 = *(encoded++);
175
- tmp2 = *(encoded++);
176
- tmp3 = *(encoded++);
177
- *(target++) = (base64_decodes[(size_t)tmp1] << 2) |
178
- (base64_decodes[(size_t)tmp2] >> 6);
179
- *(target++) = (base64_decodes[(size_t)tmp2] << 4) |
180
- (base64_decodes[(size_t)tmp3] >> 2);
181
- *(target++) = base64_decodes[(size_t)tmp3] << 6;
182
- written += 3;
183
- break;
184
- }
185
- if (encoded[-1] == '=') {
186
- target--;
187
- written--;
188
- if (encoded[-2] == '=') {
189
- target--;
190
- written--;
191
- }
192
- }
193
- *target = 0;
194
- return written;
195
- }
196
-
197
- /* *****************************************************************************
198
- Base64 Testing
199
- ***************************************************************************** */
200
- #if defined(DEBUG) && DEBUG == 1
201
- #include <stdio.h>
202
- #include <string.h>
203
- #include <time.h>
204
-
205
- void fio_base64_test(void) {
206
- struct {
207
- char *str;
208
- char *base64;
209
- } sets[] = {
210
- // {"Man is distinguished, not only by his reason, but by this singular "
211
- // "passion from other animals, which is a lust of the mind, that by a "
212
- // "perseverance of delight in the continued and indefatigable generation
213
- // "
214
- // "of knowledge, exceeds the short vehemence of any carnal pleasure.",
215
- // "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB"
216
- // "0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG"
217
- // "x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpb"
218
- // "iB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xl"
219
- // "ZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3V"
220
- // "yZS4="},
221
- {"any carnal pleasure.", "YW55IGNhcm5hbCBwbGVhc3VyZS4="},
222
- {"any carnal pleasure", "YW55IGNhcm5hbCBwbGVhc3VyZQ=="},
223
- {"any carnal pleasur", "YW55IGNhcm5hbCBwbGVhc3Vy"},
224
- {"", ""},
225
- {"f", "Zg=="},
226
- {"fo", "Zm8="},
227
- {"foo", "Zm9v"},
228
- {"foob", "Zm9vYg=="},
229
- {"fooba", "Zm9vYmE="},
230
- {"foobar", "Zm9vYmFy"},
231
- {NULL, NULL} // Stop
232
- };
233
- int i = 0;
234
- char buffer[1024];
235
- fprintf(stderr, "+ fio");
236
- while (sets[i].str) {
237
- fio_base64_encode(buffer, sets[i].str, strlen(sets[i].str));
238
- if (strcmp(buffer, sets[i].base64)) {
239
- fprintf(stderr,
240
- ":\n--- fio Base64 Test FAILED!\nstring: %s\nlength: %lu\n "
241
- "expected: %s\ngot: %s\n\n",
242
- sets[i].str, strlen(sets[i].str), sets[i].base64, buffer);
243
- break;
244
- }
245
- i++;
246
- }
247
- if (!sets[i].str)
248
- fprintf(stderr, " Base64 encode passed.\n");
249
-
250
- i = 0;
251
- fprintf(stderr, "+ fio");
252
- while (sets[i].str) {
253
- fio_base64_decode(buffer, sets[i].base64, strlen(sets[i].base64));
254
- if (strcmp(buffer, sets[i].str)) {
255
- fprintf(stderr,
256
- ":\n--- fio Base64 Test FAILED!\nbase64: %s\nexpected: "
257
- "%s\ngot: %s\n\n",
258
- sets[i].base64, sets[i].str, buffer);
259
- return;
260
- }
261
- i++;
262
- }
263
- fprintf(stderr, " Base64 decode passed.\n");
264
- {
265
- char buff_b64[] = "any carnal pleasure.";
266
- clock_t start = clock();
267
- for (i = 0; i < 100000; i++) {
268
- size_t b64_len =
269
- fio_base64_encode(buffer, buff_b64, sizeof(buff_b64) - 1);
270
- fio_base64_decode(buff_b64, buffer, b64_len);
271
- }
272
- fprintf(stderr, "fio 100K Base64: %lf\n",
273
- (double)(clock() - start) / CLOCKS_PER_SEC);
274
- (void)buff_b64;
275
- }
276
- }
277
- #endif
@@ -1,71 +0,0 @@
1
- /*
2
- Copyright: Boaz Segev, 2016-2018
3
- License: MIT except for any non-public-domain algorithms (none that I'm aware
4
- of), which might be subject to their own licenses.
5
-
6
- Feel free to copy, use and enjoy in accordance with to the license(s).
7
- */
8
- #ifndef H_FIO_BASE64_H
9
- #define H_FIO_BASE64_H
10
- /* *****************************************************************************
11
- C++ extern
12
- */
13
- #if defined(__cplusplus)
14
- extern "C" {
15
- #endif
16
-
17
- /* ***************************************************************************
18
- Base64 encoding
19
- */
20
-
21
- /**
22
- This will encode a byte array (data) of a specified length (len) and
23
- place the encoded data into the target byte buffer (target). The target buffer
24
- MUST have enough room for the expected data.
25
-
26
- Base64 encoding always requires 4 bytes for each 3 bytes. Padding is added if
27
- the raw data's length isn't devisable by 3.
28
-
29
- Always assume the target buffer should have room enough for (len*4/3 + 4)
30
- bytes.
31
-
32
- Returns the number of bytes actually written to the target buffer
33
- (including the Base64 required padding and excluding a NULL terminator).
34
-
35
- A NULL terminator char is NOT written to the target buffer.
36
- */
37
- int fio_base64_encode(char *target, const char *data, int len);
38
-
39
- /**
40
- This will decode a Base64 encoded string of a specified length (len) and
41
- place the decoded data into the target byte buffer (target).
42
-
43
- The target buffer MUST have enough room for the expected data.
44
-
45
- A NULL byte will be appended to the target buffer. The function will return
46
- the number of bytes written to the target buffer.
47
-
48
- If the target buffer is NULL, the encoded string will be destructively edited
49
- and the decoded data will be placed in the original string's buffer.
50
-
51
- Base64 encoding always requires 4 bytes for each 3 bytes. Padding is added if
52
- the raw data's length isn't devisable by 3. Hence, the target buffer should
53
- be, at least, `base64_len/4*3 + 3` long.
54
-
55
- Returns the number of bytes actually written to the target buffer (excluding
56
- the NULL terminator byte).
57
- */
58
- int fio_base64_decode(char *target, char *encoded, int base64_len);
59
-
60
- #if defined(DEBUG) && DEBUG == 1
61
- void fio_base64_test(void);
62
- #endif
63
-
64
- /* *****************************************************************************
65
- C++ extern finish
66
- */
67
- #if defined(__cplusplus)
68
- }
69
- #endif
70
-
71
- #endif
@@ -1,257 +0,0 @@
1
- #ifndef H_FIO_SIMPLE_LIST_H
2
- /*
3
- Copyright: Boaz Segev, 2017-2018
4
- License: MIT
5
- */
6
-
7
- /* *****************************************************************************
8
- Simple Linked List - Used for existing objects (not embeddable).
9
- ***************************************************************************** */
10
-
11
- /**
12
- This header includes all the internal rescources / data and types required to
13
- create object types.
14
- */
15
- #define H_FIO_SIMPLE_LIST_H
16
-
17
- #ifndef _GNU_SOURCE
18
- #define _GNU_SOURCE
19
- #endif
20
-
21
- #ifndef FIO_FUNC
22
- #define FIO_FUNC static __attribute__((unused))
23
- #endif
24
-
25
- #include <errno.h>
26
- #include <stdio.h>
27
- #include <stdlib.h>
28
-
29
- /* *****************************************************************************
30
- Data Structure and Initialization.
31
- ***************************************************************************** */
32
-
33
- /** an embeded linked list. */
34
- typedef struct fio_ls_embd_s {
35
- struct fio_ls_embd_s *prev;
36
- struct fio_ls_embd_s *next;
37
- } fio_ls_embd_s;
38
-
39
- /** an independent linked list. */
40
- typedef struct fio_ls_s {
41
- struct fio_ls_s *prev;
42
- struct fio_ls_s *next;
43
- const void *obj;
44
- } fio_ls_s;
45
-
46
- #define FIO_LS_INIT(name) \
47
- { .next = &(name), .prev = &(name) }
48
-
49
- /* *****************************************************************************
50
- Independent List API
51
- ***************************************************************************** */
52
-
53
- /** Adds an object to the list's head. */
54
- FIO_FUNC inline void fio_ls_push(fio_ls_s *pos, const void *obj);
55
-
56
- /** Adds an object to the list's tail. */
57
- FIO_FUNC inline void fio_ls_unshift(fio_ls_s *pos, const void *obj);
58
-
59
- /** Removes an object from the list's head. */
60
- FIO_FUNC inline void *fio_ls_pop(fio_ls_s *list);
61
-
62
- /** Removes an object from the list's tail. */
63
- FIO_FUNC inline void *fio_ls_shift(fio_ls_s *list);
64
-
65
- /** Removes a node from the list, returning the contained object. */
66
- FIO_FUNC inline void *fio_ls_remove(fio_ls_s *node);
67
-
68
- /** Tests if the list is empty. */
69
- FIO_FUNC inline int fio_ls_is_empty(fio_ls_s *list);
70
-
71
- /** Tests if the list is NOT empty (contains any nodes). */
72
- FIO_FUNC inline int fio_ls_any(fio_ls_s *list);
73
-
74
- /**
75
- * Iterates through the list using a `for` loop.
76
- *
77
- * Access the data with `pos->obj` (`pos` can be named however you pleas..
78
- */
79
- #define FIO_LS_FOR(list, pos)
80
-
81
- /* *****************************************************************************
82
- Embedded List API
83
- ***************************************************************************** */
84
-
85
- /** Adds a node to the list's head. */
86
- FIO_FUNC inline void fio_ls_embd_push(fio_ls_embd_s *dest, fio_ls_embd_s *node);
87
-
88
- /** Adds a node to the list's tail. */
89
- FIO_FUNC inline void fio_ls_embd_unshift(fio_ls_embd_s *dest,
90
- fio_ls_embd_s *node);
91
-
92
- /** Removes a node from the list's head. */
93
- FIO_FUNC inline fio_ls_embd_s *fio_ls_embd_pop(fio_ls_embd_s *list);
94
-
95
- /** Removes a node from the list's tail. */
96
- FIO_FUNC inline fio_ls_embd_s *fio_ls_embd_shift(fio_ls_embd_s *list);
97
-
98
- /** Removes a node from the containing node. */
99
- FIO_FUNC inline fio_ls_embd_s *fio_ls_embd_remove(fio_ls_embd_s *node);
100
-
101
- /** Tests if the list is empty. */
102
- FIO_FUNC inline int fio_ls_embd_is_empty(fio_ls_embd_s *list);
103
-
104
- /** Tests if the list is NOT empty (contains any nodes). */
105
- FIO_FUNC inline int fio_ls_embd_any(fio_ls_embd_s *list);
106
-
107
- /**
108
- * Iterates through the list using a `for` loop.
109
- *
110
- * Access the data with `pos->obj` (`pos` can be named however you pleas..
111
- */
112
- #define FIO_LS_EMBD_FOR(list, node)
113
-
114
- /**
115
- * Takes a list pointer `plist` and returns a pointer to it's container.
116
- *
117
- * This uses pointer offset calculations and can be used to calculate any
118
- * struct's pointer (not just list containers) as an offset from a pointer of
119
- * one of it's members.
120
- *
121
- * Very useful.
122
- */
123
- #define FIO_LS_EMBD_OBJ(type, member, plist) \
124
- ((type *)((uintptr_t)(plist) - (uintptr_t)(&(((type *)0)->member))))
125
-
126
- /* *****************************************************************************
127
- Independent Implementation
128
- ***************************************************************************** */
129
-
130
- /** Adds an object to the list's head. */
131
- FIO_FUNC inline void fio_ls_push(fio_ls_s *pos, const void *obj) {
132
- /* prepare item */
133
- fio_ls_s *item = (fio_ls_s *)malloc(sizeof(*item));
134
- if (!item) {
135
- perror("ERROR: simple list couldn't allocate memory");
136
- exit(errno);
137
- }
138
- *item = (fio_ls_s){.prev = pos, .next = pos->next, .obj = obj};
139
- /* inject item */
140
- pos->next->prev = item;
141
- pos->next = item;
142
- }
143
-
144
- /** Adds an object to the list's tail. */
145
- FIO_FUNC inline void fio_ls_unshift(fio_ls_s *pos, const void *obj) {
146
- pos = pos->prev;
147
- fio_ls_push(pos, obj);
148
- }
149
-
150
- /** Removes an object from the list's head. */
151
- FIO_FUNC inline void *fio_ls_pop(fio_ls_s *list) {
152
- if (list->next == list)
153
- return NULL;
154
- fio_ls_s *item = list->next;
155
- const void *ret = item->obj;
156
- list->next = item->next;
157
- list->next->prev = list;
158
- free(item);
159
- return (void *)ret;
160
- }
161
-
162
- /** Removes an object from the list's tail. */
163
- FIO_FUNC inline void *fio_ls_shift(fio_ls_s *list) {
164
- if (list->prev == list)
165
- return NULL;
166
- fio_ls_s *item = list->prev;
167
- const void *ret = item->obj;
168
- list->prev = item->prev;
169
- list->prev->next = list;
170
- free(item);
171
- return (void *)ret;
172
- }
173
-
174
- /** Removes an object from the containing node. */
175
- FIO_FUNC inline void *fio_ls_remove(fio_ls_s *node) {
176
- const void *ret = node->obj;
177
- node->next->prev = node->prev;
178
- node->prev->next = node->next;
179
- free(node);
180
- return (void *)ret;
181
- }
182
-
183
- /** Tests if the list is empty. */
184
- FIO_FUNC inline int fio_ls_is_empty(fio_ls_s *list) {
185
- return list->next == list;
186
- }
187
-
188
- /** Tests if the list is NOT empty (contains any nodes). */
189
- FIO_FUNC inline int fio_ls_any(fio_ls_s *list) { return list->next != list; }
190
-
191
- #undef FIO_LS_FOR
192
- #define FIO_LS_FOR(list, pos) \
193
- for (fio_ls_s *pos = (list)->next; pos != (list); pos = pos->next)
194
-
195
- /* *****************************************************************************
196
- Embeded List Implementation
197
- ***************************************************************************** */
198
-
199
- /** Adds a node to the list's head. */
200
- FIO_FUNC inline void fio_ls_embd_push(fio_ls_embd_s *dest,
201
- fio_ls_embd_s *node) {
202
- node->next = dest->next;
203
- node->prev = dest->next->prev;
204
- dest->next->prev = node;
205
- dest->next = node;
206
- }
207
-
208
- /** Adds a node to the list's tail. */
209
- FIO_FUNC inline void fio_ls_embd_unshift(fio_ls_embd_s *dest,
210
- fio_ls_embd_s *node) {
211
- fio_ls_embd_push(dest->prev, node);
212
- }
213
-
214
- /** Removes a node from the list's head. */
215
- FIO_FUNC inline fio_ls_embd_s *fio_ls_embd_pop(fio_ls_embd_s *list) {
216
- if (list->next == list)
217
- return NULL;
218
- fio_ls_embd_s *item = list->next;
219
- list->next = item->next;
220
- list->next->prev = list;
221
- return item;
222
- }
223
-
224
- /** Removes a node from the list's tail. */
225
- FIO_FUNC inline fio_ls_embd_s *fio_ls_embd_shift(fio_ls_embd_s *list) {
226
- if (list->prev == list)
227
- return NULL;
228
- fio_ls_embd_s *item = list->prev;
229
- list->prev = item->prev;
230
- list->prev->next = list;
231
- return item;
232
- }
233
-
234
- /** Removes a node from the containing node. */
235
- FIO_FUNC inline fio_ls_embd_s *fio_ls_embd_remove(fio_ls_embd_s *node) {
236
- node->next->prev = node->prev;
237
- node->prev->next = node->next;
238
- return node;
239
- }
240
-
241
- /** Tests if the list is empty. */
242
- FIO_FUNC inline int fio_ls_embd_is_empty(fio_ls_embd_s *list) {
243
- return list->next == list;
244
- }
245
-
246
- /** Tests if the list is NOT empty (contains any nodes). */
247
- FIO_FUNC inline int fio_ls_embd_any(fio_ls_embd_s *list) {
248
- return list->next != list;
249
- }
250
-
251
- #undef FIO_LS_EMBD_FOR
252
- #define FIO_LS_EMBD_FOR(list, node) \
253
- for (fio_ls_embd_s *node = (list)->next; node != (list); node = node->next)
254
-
255
- #undef FIO_FUNC
256
-
257
- #endif