isomorfeus-iodine 0.7.49 → 0.7.50

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -1
  3. data/CHANGELOG.md +17 -3
  4. data/Rakefile +1 -9
  5. data/examples/etag.ru +16 -0
  6. data/ext/{iodine → iodine_ext}/extconf.rb +1 -1
  7. data/ext/{iodine → iodine_ext}/fio.c +0 -0
  8. data/ext/{iodine → iodine_ext}/fio.h +0 -0
  9. data/ext/{iodine → iodine_ext}/fio_cli.c +0 -0
  10. data/ext/{iodine → iodine_ext}/fio_cli.h +189 -189
  11. data/ext/{iodine → iodine_ext}/fio_json_parser.h +687 -687
  12. data/ext/{iodine → iodine_ext}/fio_siphash.c +157 -157
  13. data/ext/{iodine → iodine_ext}/fio_siphash.h +37 -37
  14. data/ext/{iodine → iodine_ext}/fio_tls.h +129 -129
  15. data/ext/{iodine → iodine_ext}/fio_tls_missing.c +0 -0
  16. data/ext/{iodine → iodine_ext}/fio_tls_openssl.c +0 -0
  17. data/ext/{iodine → iodine_ext}/fio_tmpfile.h +0 -0
  18. data/ext/{iodine → iodine_ext}/fiobj.h +44 -44
  19. data/ext/{iodine → iodine_ext}/fiobj4fio.h +21 -21
  20. data/ext/{iodine → iodine_ext}/fiobj_ary.c +333 -333
  21. data/ext/{iodine → iodine_ext}/fiobj_ary.h +139 -139
  22. data/ext/{iodine → iodine_ext}/fiobj_data.c +0 -0
  23. data/ext/{iodine → iodine_ext}/fiobj_data.h +0 -0
  24. data/ext/{iodine → iodine_ext}/fiobj_hash.c +0 -0
  25. data/ext/{iodine → iodine_ext}/fiobj_hash.h +176 -176
  26. data/ext/{iodine → iodine_ext}/fiobj_json.c +622 -622
  27. data/ext/{iodine → iodine_ext}/fiobj_json.h +68 -68
  28. data/ext/{iodine → iodine_ext}/fiobj_mem.h +71 -71
  29. data/ext/{iodine → iodine_ext}/fiobj_mustache.c +0 -0
  30. data/ext/{iodine → iodine_ext}/fiobj_mustache.h +62 -62
  31. data/ext/{iodine → iodine_ext}/fiobj_numbers.c +0 -0
  32. data/ext/{iodine → iodine_ext}/fiobj_numbers.h +127 -127
  33. data/ext/{iodine → iodine_ext}/fiobj_str.c +0 -0
  34. data/ext/{iodine → iodine_ext}/fiobj_str.h +172 -172
  35. data/ext/{iodine → iodine_ext}/fiobject.c +0 -0
  36. data/ext/{iodine → iodine_ext}/fiobject.h +0 -0
  37. data/ext/{iodine → iodine_ext}/hpack.h +1923 -1923
  38. data/ext/{iodine → iodine_ext}/http.c +14 -27
  39. data/ext/{iodine → iodine_ext}/http.h +1002 -1002
  40. data/ext/{iodine → iodine_ext}/http1.c +0 -0
  41. data/ext/{iodine → iodine_ext}/http1.h +29 -29
  42. data/ext/{iodine → iodine_ext}/http1_parser.h +0 -0
  43. data/ext/{iodine → iodine_ext}/http_internal.c +0 -0
  44. data/ext/{iodine → iodine_ext}/http_internal.h +0 -0
  45. data/ext/{iodine → iodine_ext}/http_mime_parser.h +350 -350
  46. data/ext/{iodine → iodine_ext}/iodine.c +1 -1
  47. data/ext/{iodine → iodine_ext}/iodine.h +0 -0
  48. data/ext/{iodine → iodine_ext}/iodine_caller.c +0 -0
  49. data/ext/{iodine → iodine_ext}/iodine_caller.h +0 -0
  50. data/ext/{iodine → iodine_ext}/iodine_connection.c +0 -0
  51. data/ext/{iodine → iodine_ext}/iodine_connection.h +55 -55
  52. data/ext/{iodine → iodine_ext}/iodine_defer.c +0 -0
  53. data/ext/{iodine → iodine_ext}/iodine_defer.h +6 -6
  54. data/ext/{iodine → iodine_ext}/iodine_fiobj2rb.h +120 -120
  55. data/ext/{iodine → iodine_ext}/iodine_helpers.c +0 -0
  56. data/ext/{iodine → iodine_ext}/iodine_helpers.h +12 -12
  57. data/ext/{iodine → iodine_ext}/iodine_http.c +0 -2
  58. data/ext/{iodine → iodine_ext}/iodine_http.h +23 -23
  59. data/ext/{iodine → iodine_ext}/iodine_json.c +302 -302
  60. data/ext/{iodine → iodine_ext}/iodine_json.h +6 -6
  61. data/ext/{iodine → iodine_ext}/iodine_mustache.c +0 -0
  62. data/ext/{iodine → iodine_ext}/iodine_mustache.h +6 -6
  63. data/ext/{iodine → iodine_ext}/iodine_pubsub.c +0 -0
  64. data/ext/{iodine → iodine_ext}/iodine_pubsub.h +26 -26
  65. data/ext/{iodine → iodine_ext}/iodine_rack_io.c +0 -0
  66. data/ext/{iodine → iodine_ext}/iodine_rack_io.h +20 -20
  67. data/ext/{iodine → iodine_ext}/iodine_store.c +0 -0
  68. data/ext/{iodine → iodine_ext}/iodine_store.h +20 -20
  69. data/ext/{iodine → iodine_ext}/iodine_tcp.c +0 -0
  70. data/ext/{iodine → iodine_ext}/iodine_tcp.h +0 -0
  71. data/ext/{iodine → iodine_ext}/iodine_tls.c +0 -0
  72. data/ext/{iodine → iodine_ext}/iodine_tls.h +13 -13
  73. data/ext/{iodine → iodine_ext}/mustache_parser.h +0 -0
  74. data/ext/{iodine → iodine_ext}/redis_engine.c +0 -0
  75. data/ext/{iodine → iodine_ext}/redis_engine.h +0 -0
  76. data/ext/{iodine → iodine_ext}/resp_parser.h +0 -0
  77. data/ext/{iodine → iodine_ext}/websocket_parser.h +505 -505
  78. data/ext/{iodine → iodine_ext}/websockets.c +0 -0
  79. data/ext/{iodine → iodine_ext}/websockets.h +185 -185
  80. data/isomorfeus-iodine.gemspec +1 -2
  81. data/lib/iodine/version.rb +1 -1
  82. data/lib/iodine.rb +1 -1
  83. metadata +79 -78
@@ -1,333 +1,333 @@
1
- /*
2
- Copyright: Boaz Segev, 2017-2019
3
- License: MIT
4
- */
5
- #include <fio.h>
6
- #include <fiobject.h>
7
-
8
- #define FIO_ARY_NAME fio_ary__
9
- #define FIO_ARY_TYPE FIOBJ
10
- #define FIO_ARY_TYPE_INVALID FIOBJ_INVALID
11
- #define FIO_ARY_TYPE_COMPARE(a, b) (fiobj_iseq((a), (b)))
12
- #define FIO_ARY_INVALID FIOBJ_INVALID
13
- #include <fio.h>
14
-
15
- #include <assert.h>
16
-
17
- /* *****************************************************************************
18
- Array Type
19
- ***************************************************************************** */
20
-
21
- typedef struct {
22
- fiobj_object_header_s head;
23
- fio_ary___s ary;
24
- } fiobj_ary_s;
25
-
26
- #define obj2ary(o) ((fiobj_ary_s *)(o))
27
-
28
- /* *****************************************************************************
29
- VTable
30
- ***************************************************************************** */
31
-
32
- static void fiobj_ary_dealloc(FIOBJ o, void (*task)(FIOBJ, void *), void *arg) {
33
- FIO_ARY_FOR((&obj2ary(o)->ary), i) { task(*i, arg); }
34
- fio_ary___free(&obj2ary(o)->ary);
35
- fio_free(FIOBJ2PTR(o));
36
- }
37
-
38
- static size_t fiobj_ary_each1(FIOBJ o, size_t start_at,
39
- int (*task)(FIOBJ obj, void *arg), void *arg) {
40
- return fio_ary___each(&obj2ary(o)->ary, start_at, task, arg);
41
- }
42
-
43
- static size_t fiobj_ary_is_eq(const FIOBJ self, const FIOBJ other) {
44
- fio_ary___s *a = &obj2ary(self)->ary;
45
- fio_ary___s *b = &obj2ary(other)->ary;
46
- if (fio_ary___count(a) != fio_ary___count(b))
47
- return 0;
48
- return 1;
49
- }
50
-
51
- /** Returns the number of elements in the Array. */
52
- size_t fiobj_ary_count(const FIOBJ ary) {
53
- assert(FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
54
- return fio_ary___count(&obj2ary(ary)->ary);
55
- }
56
-
57
- static size_t fiobj_ary_is_true(const FIOBJ ary) {
58
- return fiobj_ary_count(ary) > 0;
59
- }
60
-
61
- fio_str_info_s fiobject___noop_to_str(const FIOBJ o);
62
- intptr_t fiobject___noop_to_i(const FIOBJ o);
63
- double fiobject___noop_to_f(const FIOBJ o);
64
-
65
- const fiobj_object_vtable_s FIOBJECT_VTABLE_ARRAY = {
66
- .class_name = "Array",
67
- .dealloc = fiobj_ary_dealloc,
68
- .is_eq = fiobj_ary_is_eq,
69
- .is_true = fiobj_ary_is_true,
70
- .count = fiobj_ary_count,
71
- .each = fiobj_ary_each1,
72
- .to_i = fiobject___noop_to_i,
73
- .to_f = fiobject___noop_to_f,
74
- .to_str = fiobject___noop_to_str,
75
- };
76
-
77
- /* *****************************************************************************
78
- Allocation
79
- ***************************************************************************** */
80
-
81
- static inline FIOBJ fiobj_ary_alloc(size_t capa) {
82
- fiobj_ary_s *ary = fio_malloc(sizeof(*ary));
83
- if (!ary) {
84
- perror("ERROR: fiobj array couldn't allocate memory");
85
- exit(errno);
86
- }
87
- *ary = (fiobj_ary_s){
88
- .head =
89
- {
90
- .ref = 1,
91
- .type = FIOBJ_T_ARRAY,
92
- },
93
- };
94
- if (capa)
95
- fio_ary_____require_on_top(&ary->ary, capa);
96
- return (FIOBJ)ary;
97
- }
98
-
99
- /** Creates a mutable empty Array object. Use `fiobj_free` when done. */
100
- FIOBJ fiobj_ary_new(void) { return fiobj_ary_alloc(0); }
101
- /** Creates a mutable empty Array object with the requested capacity. */
102
- FIOBJ fiobj_ary_new2(size_t capa) { return fiobj_ary_alloc(capa); }
103
-
104
- /* *****************************************************************************
105
- Array direct entry access API
106
- ***************************************************************************** */
107
-
108
- /** Returns the current, temporary, array capacity (it's dynamic). */
109
- size_t fiobj_ary_capa(FIOBJ ary) {
110
- assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
111
- return fio_ary___capa(&obj2ary(ary)->ary);
112
- }
113
-
114
- /**
115
- * Returns a TEMPORARY pointer to the beginning of the array.
116
- *
117
- * This pointer can be used for sorting and other direct access operations as
118
- * long as no other actions (insertion/deletion) are performed on the array.
119
- */
120
- FIOBJ *fiobj_ary2ptr(FIOBJ ary) {
121
- assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
122
- return (FIOBJ *)(obj2ary(ary)->ary.arry + obj2ary(ary)->ary.start);
123
- }
124
-
125
- /**
126
- * Returns a temporary object owned by the Array.
127
- *
128
- * Negative values are retrieved from the end of the array. i.e., `-1`
129
- * is the last item.
130
- */
131
- FIOBJ fiobj_ary_index(FIOBJ ary, int64_t pos) {
132
- assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
133
- return fio_ary___get(&obj2ary(ary)->ary, pos);
134
- }
135
-
136
- /**
137
- * Sets an object at the requested position.
138
- */
139
- void fiobj_ary_set(FIOBJ ary, FIOBJ obj, int64_t pos) {
140
- assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
141
- FIOBJ old = FIOBJ_INVALID;
142
- fio_ary___set(&obj2ary(ary)->ary, pos, obj, &old);
143
- fiobj_free(old);
144
- }
145
-
146
- /* *****************************************************************************
147
- Array push / shift API
148
- ***************************************************************************** */
149
-
150
- /**
151
- * Pushes an object to the end of the Array.
152
- */
153
- void fiobj_ary_push(FIOBJ ary, FIOBJ obj) {
154
- assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
155
- fio_ary___push(&obj2ary(ary)->ary, obj);
156
- }
157
-
158
- /** Pops an object from the end of the Array. */
159
- FIOBJ fiobj_ary_pop(FIOBJ ary) {
160
- assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
161
- FIOBJ ret = FIOBJ_INVALID;
162
- fio_ary___pop(&obj2ary(ary)->ary, &ret);
163
- return ret;
164
- }
165
-
166
- /**
167
- * Unshifts an object to the beginning of the Array. This could be
168
- * expensive.
169
- */
170
- void fiobj_ary_unshift(FIOBJ ary, FIOBJ obj) {
171
- assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
172
- fio_ary___unshift(&obj2ary(ary)->ary, obj);
173
- }
174
-
175
- /** Shifts an object from the beginning of the Array. */
176
- FIOBJ fiobj_ary_shift(FIOBJ ary) {
177
- assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
178
- FIOBJ ret = FIOBJ_INVALID;
179
- fio_ary___shift(&obj2ary(ary)->ary, &ret);
180
- return ret;
181
- }
182
-
183
- /* *****************************************************************************
184
- Array Find / Remove / Replace
185
- ***************************************************************************** */
186
-
187
- /**
188
- * Replaces the object at a specific position, returning the old object -
189
- * remember to `fiobj_free` the old object.
190
- */
191
- FIOBJ fiobj_ary_replace(FIOBJ ary, FIOBJ obj, int64_t pos) {
192
- assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
193
- FIOBJ old = fiobj_ary_index(ary, pos);
194
- fiobj_ary_set(ary, obj, pos);
195
- return old;
196
- }
197
-
198
- /**
199
- * Finds the index of a specifide object (if any). Returns -1 if the object
200
- * isn't found.
201
- */
202
- int64_t fiobj_ary_find(FIOBJ ary, FIOBJ data) {
203
- assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
204
- return (int64_t)fio_ary___find(&obj2ary(ary)->ary, data);
205
- }
206
-
207
- /**
208
- * Removes the object at the index (if valid), changing the index of any
209
- * following objects.
210
- *
211
- * Returns 0 on success or -1 (if no object or out of bounds).
212
- */
213
- int fiobj_ary_remove(FIOBJ ary, int64_t pos) {
214
- assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
215
- FIOBJ old = FIOBJ_INVALID;
216
- if (fio_ary___remove(&obj2ary(ary)->ary, (intptr_t)pos, &old)) {
217
- return -1;
218
- }
219
- fiobj_free(old);
220
- return 0;
221
- }
222
-
223
- /**
224
- * Removes the first instance of an object from the Array (if any), changing the
225
- * index of any following objects.
226
- *
227
- * Returns 0 on success or -1 (if the object wasn't found).
228
- */
229
- int fiobj_ary_remove2(FIOBJ ary, FIOBJ data) {
230
- assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
231
- if (-1 == fio_ary___remove2(&obj2ary(ary)->ary, data, &data)) {
232
- return -1;
233
- }
234
- fiobj_free(data);
235
- return 0;
236
- }
237
-
238
- /* *****************************************************************************
239
- Array compacting (untested)
240
- ***************************************************************************** */
241
-
242
- /**
243
- * Removes any NULL *pointers* from an Array, keeping all Objects (including
244
- * explicit NULL objects) in the array.
245
- *
246
- * This action is O(n) where n in the length of the array.
247
- * It could get expensive.
248
- */
249
- void fiobj_ary_compact(FIOBJ ary) {
250
- assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
251
- fio_ary___compact(&obj2ary(ary)->ary);
252
- }
253
-
254
- /* *****************************************************************************
255
- Simple Tests
256
- ***************************************************************************** */
257
-
258
- #if DEBUG
259
- void fiobj_test_array(void) {
260
- fprintf(stderr, "=== Testing Array\n");
261
- #define TEST_ASSERT(cond, ...) \
262
- if (!(cond)) { \
263
- fprintf(stderr, "* " __VA_ARGS__); \
264
- fprintf(stderr, "Testing failed.\n"); \
265
- exit(-1); \
266
- }
267
- FIOBJ a = fiobj_ary_new2(4);
268
- TEST_ASSERT(FIOBJ_TYPE_IS(a, FIOBJ_T_ARRAY), "Array type isn't an array!\n");
269
- TEST_ASSERT(fiobj_ary_capa(a) > 4, "Array capacity ignored!\n");
270
- fiobj_ary_push(a, fiobj_null());
271
- TEST_ASSERT(fiobj_ary2ptr(a)[0] == fiobj_null(),
272
- "Array direct access failed!\n");
273
- fiobj_ary_push(a, fiobj_true());
274
- fiobj_ary_push(a, fiobj_false());
275
- TEST_ASSERT(fiobj_ary_count(a) == 3, "Array count isn't 3\n");
276
- fiobj_ary_set(a, fiobj_true(), 63);
277
- TEST_ASSERT(fiobj_ary_count(a) == 64, "Array count isn't 64 (%zu)\n",
278
- fiobj_ary_count(a));
279
- TEST_ASSERT(fiobj_ary_index(a, 0) == fiobj_null(),
280
- "Array index retrival error for fiobj_null\n");
281
- TEST_ASSERT(fiobj_ary_index(a, 1) == fiobj_true(),
282
- "Array index retrival error for fiobj_true\n");
283
- TEST_ASSERT(fiobj_ary_index(a, 2) == fiobj_false(),
284
- "Array index retrival error for fiobj_false\n");
285
- TEST_ASSERT(fiobj_ary_index(a, 3) == 0,
286
- "Array index retrival error for NULL\n");
287
- TEST_ASSERT(fiobj_ary_index(a, 63) == fiobj_true(),
288
- "Array index retrival error for index 63\n");
289
- TEST_ASSERT(fiobj_ary_index(a, -1) == fiobj_true(),
290
- "Array index retrival error for index -1\n");
291
- fiobj_ary_compact(a);
292
- TEST_ASSERT(fiobj_ary_index(a, -1) == fiobj_true(),
293
- "Array index retrival error for index -1\n");
294
- TEST_ASSERT(fiobj_ary_count(a) == 4, "Array compact error\n");
295
- fiobj_ary_unshift(a, fiobj_false());
296
- TEST_ASSERT(fiobj_ary_count(a) == 5, "Array unshift error\n");
297
- TEST_ASSERT(fiobj_ary_shift(a) == fiobj_false(), "Array shift value error\n");
298
- TEST_ASSERT(fiobj_ary_replace(a, fiobj_true(), -2) == fiobj_false(),
299
- "Array replace didn't return correct value\n");
300
-
301
- FIO_ARY_FOR(&obj2ary(a)->ary, pos) {
302
- if (*pos) {
303
- fprintf(stderr, "%lu) %s\n", pos - obj2ary(a)->ary.arry,
304
- fiobj_obj2cstr(*pos).data);
305
- }
306
- }
307
-
308
- TEST_ASSERT(fiobj_ary_index(a, -2) == fiobj_true(),
309
- "Array index retrival error for index -2 (should be true)\n");
310
- TEST_ASSERT(fiobj_ary_count(a) == 4, "Array size error\n");
311
- fiobj_ary_remove(a, -2);
312
- TEST_ASSERT(fiobj_ary_count(a) == 3, "Array remove error\n");
313
-
314
- FIO_ARY_FOR(&obj2ary(a)->ary, pos) {
315
- if (*pos) {
316
- fprintf(stderr, "%lu) %s\n", pos - obj2ary(a)->ary.arry,
317
- fiobj_obj2cstr(*pos).data);
318
- }
319
- }
320
-
321
- fiobj_ary_remove2(a, fiobj_true());
322
- TEST_ASSERT(fiobj_ary_count(a) == 2, "Array remove2 error\n");
323
- TEST_ASSERT(fiobj_ary_index(a, 0) == fiobj_null(),
324
- "Array index 0 should be null - %s\n",
325
- fiobj_obj2cstr(fiobj_ary_index(a, 0)).data);
326
- TEST_ASSERT(fiobj_ary_index(a, 1) == fiobj_true(),
327
- "Array index 0 should be true - %s\n",
328
- fiobj_obj2cstr(fiobj_ary_index(a, 0)).data);
329
-
330
- fiobj_free(a);
331
- fprintf(stderr, "* passed.\n");
332
- }
333
- #endif
1
+ /*
2
+ Copyright: Boaz Segev, 2017-2019
3
+ License: MIT
4
+ */
5
+ #include <fio.h>
6
+ #include <fiobject.h>
7
+
8
+ #define FIO_ARY_NAME fio_ary__
9
+ #define FIO_ARY_TYPE FIOBJ
10
+ #define FIO_ARY_TYPE_INVALID FIOBJ_INVALID
11
+ #define FIO_ARY_TYPE_COMPARE(a, b) (fiobj_iseq((a), (b)))
12
+ #define FIO_ARY_INVALID FIOBJ_INVALID
13
+ #include <fio.h>
14
+
15
+ #include <assert.h>
16
+
17
+ /* *****************************************************************************
18
+ Array Type
19
+ ***************************************************************************** */
20
+
21
+ typedef struct {
22
+ fiobj_object_header_s head;
23
+ fio_ary___s ary;
24
+ } fiobj_ary_s;
25
+
26
+ #define obj2ary(o) ((fiobj_ary_s *)(o))
27
+
28
+ /* *****************************************************************************
29
+ VTable
30
+ ***************************************************************************** */
31
+
32
+ static void fiobj_ary_dealloc(FIOBJ o, void (*task)(FIOBJ, void *), void *arg) {
33
+ FIO_ARY_FOR((&obj2ary(o)->ary), i) { task(*i, arg); }
34
+ fio_ary___free(&obj2ary(o)->ary);
35
+ fio_free(FIOBJ2PTR(o));
36
+ }
37
+
38
+ static size_t fiobj_ary_each1(FIOBJ o, size_t start_at,
39
+ int (*task)(FIOBJ obj, void *arg), void *arg) {
40
+ return fio_ary___each(&obj2ary(o)->ary, start_at, task, arg);
41
+ }
42
+
43
+ static size_t fiobj_ary_is_eq(const FIOBJ self, const FIOBJ other) {
44
+ fio_ary___s *a = &obj2ary(self)->ary;
45
+ fio_ary___s *b = &obj2ary(other)->ary;
46
+ if (fio_ary___count(a) != fio_ary___count(b))
47
+ return 0;
48
+ return 1;
49
+ }
50
+
51
+ /** Returns the number of elements in the Array. */
52
+ size_t fiobj_ary_count(const FIOBJ ary) {
53
+ assert(FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
54
+ return fio_ary___count(&obj2ary(ary)->ary);
55
+ }
56
+
57
+ static size_t fiobj_ary_is_true(const FIOBJ ary) {
58
+ return fiobj_ary_count(ary) > 0;
59
+ }
60
+
61
+ fio_str_info_s fiobject___noop_to_str(const FIOBJ o);
62
+ intptr_t fiobject___noop_to_i(const FIOBJ o);
63
+ double fiobject___noop_to_f(const FIOBJ o);
64
+
65
+ const fiobj_object_vtable_s FIOBJECT_VTABLE_ARRAY = {
66
+ .class_name = "Array",
67
+ .dealloc = fiobj_ary_dealloc,
68
+ .is_eq = fiobj_ary_is_eq,
69
+ .is_true = fiobj_ary_is_true,
70
+ .count = fiobj_ary_count,
71
+ .each = fiobj_ary_each1,
72
+ .to_i = fiobject___noop_to_i,
73
+ .to_f = fiobject___noop_to_f,
74
+ .to_str = fiobject___noop_to_str,
75
+ };
76
+
77
+ /* *****************************************************************************
78
+ Allocation
79
+ ***************************************************************************** */
80
+
81
+ static inline FIOBJ fiobj_ary_alloc(size_t capa) {
82
+ fiobj_ary_s *ary = fio_malloc(sizeof(*ary));
83
+ if (!ary) {
84
+ perror("ERROR: fiobj array couldn't allocate memory");
85
+ exit(errno);
86
+ }
87
+ *ary = (fiobj_ary_s){
88
+ .head =
89
+ {
90
+ .ref = 1,
91
+ .type = FIOBJ_T_ARRAY,
92
+ },
93
+ };
94
+ if (capa)
95
+ fio_ary_____require_on_top(&ary->ary, capa);
96
+ return (FIOBJ)ary;
97
+ }
98
+
99
+ /** Creates a mutable empty Array object. Use `fiobj_free` when done. */
100
+ FIOBJ fiobj_ary_new(void) { return fiobj_ary_alloc(0); }
101
+ /** Creates a mutable empty Array object with the requested capacity. */
102
+ FIOBJ fiobj_ary_new2(size_t capa) { return fiobj_ary_alloc(capa); }
103
+
104
+ /* *****************************************************************************
105
+ Array direct entry access API
106
+ ***************************************************************************** */
107
+
108
+ /** Returns the current, temporary, array capacity (it's dynamic). */
109
+ size_t fiobj_ary_capa(FIOBJ ary) {
110
+ assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
111
+ return fio_ary___capa(&obj2ary(ary)->ary);
112
+ }
113
+
114
+ /**
115
+ * Returns a TEMPORARY pointer to the beginning of the array.
116
+ *
117
+ * This pointer can be used for sorting and other direct access operations as
118
+ * long as no other actions (insertion/deletion) are performed on the array.
119
+ */
120
+ FIOBJ *fiobj_ary2ptr(FIOBJ ary) {
121
+ assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
122
+ return (FIOBJ *)(obj2ary(ary)->ary.arry + obj2ary(ary)->ary.start);
123
+ }
124
+
125
+ /**
126
+ * Returns a temporary object owned by the Array.
127
+ *
128
+ * Negative values are retrieved from the end of the array. i.e., `-1`
129
+ * is the last item.
130
+ */
131
+ FIOBJ fiobj_ary_index(FIOBJ ary, int64_t pos) {
132
+ assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
133
+ return fio_ary___get(&obj2ary(ary)->ary, pos);
134
+ }
135
+
136
+ /**
137
+ * Sets an object at the requested position.
138
+ */
139
+ void fiobj_ary_set(FIOBJ ary, FIOBJ obj, int64_t pos) {
140
+ assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
141
+ FIOBJ old = FIOBJ_INVALID;
142
+ fio_ary___set(&obj2ary(ary)->ary, pos, obj, &old);
143
+ fiobj_free(old);
144
+ }
145
+
146
+ /* *****************************************************************************
147
+ Array push / shift API
148
+ ***************************************************************************** */
149
+
150
+ /**
151
+ * Pushes an object to the end of the Array.
152
+ */
153
+ void fiobj_ary_push(FIOBJ ary, FIOBJ obj) {
154
+ assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
155
+ fio_ary___push(&obj2ary(ary)->ary, obj);
156
+ }
157
+
158
+ /** Pops an object from the end of the Array. */
159
+ FIOBJ fiobj_ary_pop(FIOBJ ary) {
160
+ assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
161
+ FIOBJ ret = FIOBJ_INVALID;
162
+ fio_ary___pop(&obj2ary(ary)->ary, &ret);
163
+ return ret;
164
+ }
165
+
166
+ /**
167
+ * Unshifts an object to the beginning of the Array. This could be
168
+ * expensive.
169
+ */
170
+ void fiobj_ary_unshift(FIOBJ ary, FIOBJ obj) {
171
+ assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
172
+ fio_ary___unshift(&obj2ary(ary)->ary, obj);
173
+ }
174
+
175
+ /** Shifts an object from the beginning of the Array. */
176
+ FIOBJ fiobj_ary_shift(FIOBJ ary) {
177
+ assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
178
+ FIOBJ ret = FIOBJ_INVALID;
179
+ fio_ary___shift(&obj2ary(ary)->ary, &ret);
180
+ return ret;
181
+ }
182
+
183
+ /* *****************************************************************************
184
+ Array Find / Remove / Replace
185
+ ***************************************************************************** */
186
+
187
+ /**
188
+ * Replaces the object at a specific position, returning the old object -
189
+ * remember to `fiobj_free` the old object.
190
+ */
191
+ FIOBJ fiobj_ary_replace(FIOBJ ary, FIOBJ obj, int64_t pos) {
192
+ assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
193
+ FIOBJ old = fiobj_ary_index(ary, pos);
194
+ fiobj_ary_set(ary, obj, pos);
195
+ return old;
196
+ }
197
+
198
+ /**
199
+ * Finds the index of a specifide object (if any). Returns -1 if the object
200
+ * isn't found.
201
+ */
202
+ int64_t fiobj_ary_find(FIOBJ ary, FIOBJ data) {
203
+ assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
204
+ return (int64_t)fio_ary___find(&obj2ary(ary)->ary, data);
205
+ }
206
+
207
+ /**
208
+ * Removes the object at the index (if valid), changing the index of any
209
+ * following objects.
210
+ *
211
+ * Returns 0 on success or -1 (if no object or out of bounds).
212
+ */
213
+ int fiobj_ary_remove(FIOBJ ary, int64_t pos) {
214
+ assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
215
+ FIOBJ old = FIOBJ_INVALID;
216
+ if (fio_ary___remove(&obj2ary(ary)->ary, (intptr_t)pos, &old)) {
217
+ return -1;
218
+ }
219
+ fiobj_free(old);
220
+ return 0;
221
+ }
222
+
223
+ /**
224
+ * Removes the first instance of an object from the Array (if any), changing the
225
+ * index of any following objects.
226
+ *
227
+ * Returns 0 on success or -1 (if the object wasn't found).
228
+ */
229
+ int fiobj_ary_remove2(FIOBJ ary, FIOBJ data) {
230
+ assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
231
+ if (-1 == fio_ary___remove2(&obj2ary(ary)->ary, data, &data)) {
232
+ return -1;
233
+ }
234
+ fiobj_free(data);
235
+ return 0;
236
+ }
237
+
238
+ /* *****************************************************************************
239
+ Array compacting (untested)
240
+ ***************************************************************************** */
241
+
242
+ /**
243
+ * Removes any NULL *pointers* from an Array, keeping all Objects (including
244
+ * explicit NULL objects) in the array.
245
+ *
246
+ * This action is O(n) where n in the length of the array.
247
+ * It could get expensive.
248
+ */
249
+ void fiobj_ary_compact(FIOBJ ary) {
250
+ assert(ary && FIOBJ_TYPE_IS(ary, FIOBJ_T_ARRAY));
251
+ fio_ary___compact(&obj2ary(ary)->ary);
252
+ }
253
+
254
+ /* *****************************************************************************
255
+ Simple Tests
256
+ ***************************************************************************** */
257
+
258
+ #if DEBUG
259
+ void fiobj_test_array(void) {
260
+ fprintf(stderr, "=== Testing Array\n");
261
+ #define TEST_ASSERT(cond, ...) \
262
+ if (!(cond)) { \
263
+ fprintf(stderr, "* " __VA_ARGS__); \
264
+ fprintf(stderr, "Testing failed.\n"); \
265
+ exit(-1); \
266
+ }
267
+ FIOBJ a = fiobj_ary_new2(4);
268
+ TEST_ASSERT(FIOBJ_TYPE_IS(a, FIOBJ_T_ARRAY), "Array type isn't an array!\n");
269
+ TEST_ASSERT(fiobj_ary_capa(a) > 4, "Array capacity ignored!\n");
270
+ fiobj_ary_push(a, fiobj_null());
271
+ TEST_ASSERT(fiobj_ary2ptr(a)[0] == fiobj_null(),
272
+ "Array direct access failed!\n");
273
+ fiobj_ary_push(a, fiobj_true());
274
+ fiobj_ary_push(a, fiobj_false());
275
+ TEST_ASSERT(fiobj_ary_count(a) == 3, "Array count isn't 3\n");
276
+ fiobj_ary_set(a, fiobj_true(), 63);
277
+ TEST_ASSERT(fiobj_ary_count(a) == 64, "Array count isn't 64 (%zu)\n",
278
+ fiobj_ary_count(a));
279
+ TEST_ASSERT(fiobj_ary_index(a, 0) == fiobj_null(),
280
+ "Array index retrival error for fiobj_null\n");
281
+ TEST_ASSERT(fiobj_ary_index(a, 1) == fiobj_true(),
282
+ "Array index retrival error for fiobj_true\n");
283
+ TEST_ASSERT(fiobj_ary_index(a, 2) == fiobj_false(),
284
+ "Array index retrival error for fiobj_false\n");
285
+ TEST_ASSERT(fiobj_ary_index(a, 3) == 0,
286
+ "Array index retrival error for NULL\n");
287
+ TEST_ASSERT(fiobj_ary_index(a, 63) == fiobj_true(),
288
+ "Array index retrival error for index 63\n");
289
+ TEST_ASSERT(fiobj_ary_index(a, -1) == fiobj_true(),
290
+ "Array index retrival error for index -1\n");
291
+ fiobj_ary_compact(a);
292
+ TEST_ASSERT(fiobj_ary_index(a, -1) == fiobj_true(),
293
+ "Array index retrival error for index -1\n");
294
+ TEST_ASSERT(fiobj_ary_count(a) == 4, "Array compact error\n");
295
+ fiobj_ary_unshift(a, fiobj_false());
296
+ TEST_ASSERT(fiobj_ary_count(a) == 5, "Array unshift error\n");
297
+ TEST_ASSERT(fiobj_ary_shift(a) == fiobj_false(), "Array shift value error\n");
298
+ TEST_ASSERT(fiobj_ary_replace(a, fiobj_true(), -2) == fiobj_false(),
299
+ "Array replace didn't return correct value\n");
300
+
301
+ FIO_ARY_FOR(&obj2ary(a)->ary, pos) {
302
+ if (*pos) {
303
+ fprintf(stderr, "%lu) %s\n", pos - obj2ary(a)->ary.arry,
304
+ fiobj_obj2cstr(*pos).data);
305
+ }
306
+ }
307
+
308
+ TEST_ASSERT(fiobj_ary_index(a, -2) == fiobj_true(),
309
+ "Array index retrival error for index -2 (should be true)\n");
310
+ TEST_ASSERT(fiobj_ary_count(a) == 4, "Array size error\n");
311
+ fiobj_ary_remove(a, -2);
312
+ TEST_ASSERT(fiobj_ary_count(a) == 3, "Array remove error\n");
313
+
314
+ FIO_ARY_FOR(&obj2ary(a)->ary, pos) {
315
+ if (*pos) {
316
+ fprintf(stderr, "%lu) %s\n", pos - obj2ary(a)->ary.arry,
317
+ fiobj_obj2cstr(*pos).data);
318
+ }
319
+ }
320
+
321
+ fiobj_ary_remove2(a, fiobj_true());
322
+ TEST_ASSERT(fiobj_ary_count(a) == 2, "Array remove2 error\n");
323
+ TEST_ASSERT(fiobj_ary_index(a, 0) == fiobj_null(),
324
+ "Array index 0 should be null - %s\n",
325
+ fiobj_obj2cstr(fiobj_ary_index(a, 0)).data);
326
+ TEST_ASSERT(fiobj_ary_index(a, 1) == fiobj_true(),
327
+ "Array index 0 should be true - %s\n",
328
+ fiobj_obj2cstr(fiobj_ary_index(a, 0)).data);
329
+
330
+ fiobj_free(a);
331
+ fprintf(stderr, "* passed.\n");
332
+ }
333
+ #endif