iodine 0.7.59 → 0.8.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.
Files changed (160) hide show
  1. checksums.yaml +4 -4
  2. data/.clang-format +15 -0
  3. data/.rspec +1 -0
  4. data/.yardopts +1 -3
  5. data/CHANGELOG.md +132 -12
  6. data/Gemfile +5 -7
  7. data/LICENSE.txt +1 -1
  8. data/README.md +147 -671
  9. data/Rakefile +9 -16
  10. data/examples/chatroom.nru +9 -0
  11. data/examples/client +74 -0
  12. data/examples/config-hello.nru +9 -0
  13. data/examples/config-hello.ru +11 -0
  14. data/examples/config-hijack.ru +13 -0
  15. data/examples/config-shootout.ru +43 -0
  16. data/examples/config.nru +120 -0
  17. data/examples/config.rb +37 -0
  18. data/examples/config.ru +42 -53
  19. data/examples/fake +24 -0
  20. data/examples/hello_neorack +137 -0
  21. data/examples/routes.nru +29 -0
  22. data/examples/routes.ru +42 -0
  23. data/exe/iodine +218 -258
  24. data/ext/iodine/extconf.rb +27 -100
  25. data/ext/iodine/fio-stl.h +128336 -0
  26. data/ext/iodine/fio-stl.md +26396 -0
  27. data/ext/iodine/iodine.c +213 -1393
  28. data/ext/iodine/iodine.h +250 -55
  29. data/ext/iodine/iodine_arg_helper.h +329 -0
  30. data/ext/iodine/iodine_caller.h +234 -25
  31. data/ext/iodine/iodine_cli.h +434 -0
  32. data/ext/iodine/iodine_compression.h +312 -0
  33. data/ext/iodine/iodine_connection.h +3484 -34
  34. data/ext/iodine/iodine_core.h +363 -0
  35. data/ext/iodine/iodine_crypto.h +1441 -0
  36. data/ext/iodine/iodine_defer.h +225 -4
  37. data/ext/iodine/iodine_json.h +738 -4
  38. data/ext/iodine/iodine_listener.h +263 -0
  39. data/ext/iodine/iodine_log.h +297 -0
  40. data/ext/iodine/iodine_minimap.h +543 -0
  41. data/ext/iodine/iodine_mustache.h +461 -4
  42. data/ext/iodine/iodine_pubsub_eng.h +729 -0
  43. data/ext/iodine/iodine_pubsub_history.h +547 -0
  44. data/ext/iodine/iodine_pubsub_msg.h +228 -0
  45. data/ext/iodine/iodine_redis.h +322 -0
  46. data/ext/iodine/iodine_store.h +418 -16
  47. data/ext/iodine/iodine_threads.h +279 -0
  48. data/ext/iodine/iodine_tls.h +515 -6
  49. data/ext/iodine/iodine_utils.h +923 -0
  50. data/iodine.gemspec +37 -42
  51. data/lib/iodine/benchmark.rb +1690 -0
  52. data/lib/iodine/documentation.rb +3085 -0
  53. data/lib/iodine/version.rb +17 -1
  54. data/lib/iodine.rb +54 -255
  55. data/logo.svg +36 -0
  56. data/mustache.md +55 -0
  57. data/sig/iodine.rbs +4 -0
  58. metadata +58 -184
  59. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
  60. data/.github/workflows/ruby.yml +0 -42
  61. data/.gitignore +0 -20
  62. data/LIMITS.md +0 -41
  63. data/SPEC-PubSub-Draft.md +0 -159
  64. data/SPEC-WebSocket-Draft.md +0 -239
  65. data/bin/console +0 -22
  66. data/bin/info.md +0 -353
  67. data/bin/mustache_bench.rb +0 -100
  68. data/bin/poc/Gemfile.lock +0 -23
  69. data/bin/poc/README.md +0 -37
  70. data/bin/poc/config.ru +0 -66
  71. data/bin/poc/gemfile +0 -1
  72. data/bin/poc/www/index.html +0 -57
  73. data/examples/async_task.ru +0 -92
  74. data/examples/bates/README.md +0 -3
  75. data/examples/bates/config.ru +0 -342
  76. data/examples/bates/david+bold.pdf +0 -0
  77. data/examples/bates/public/drop-pdf.png +0 -0
  78. data/examples/bates/public/index.html +0 -600
  79. data/examples/echo.ru +0 -59
  80. data/examples/etag.ru +0 -16
  81. data/examples/hello.ru +0 -29
  82. data/examples/pubsub_engine.ru +0 -81
  83. data/examples/rack3.ru +0 -12
  84. data/examples/redis.ru +0 -70
  85. data/examples/shootout.ru +0 -73
  86. data/examples/sub-protocols.ru +0 -90
  87. data/examples/tcp_client.rb +0 -66
  88. data/examples/x-sendfile.ru +0 -14
  89. data/ext/iodine/fio.c +0 -11995
  90. data/ext/iodine/fio.h +0 -6371
  91. data/ext/iodine/fio_cli.c +0 -431
  92. data/ext/iodine/fio_cli.h +0 -189
  93. data/ext/iodine/fio_json_parser.h +0 -688
  94. data/ext/iodine/fio_siphash.c +0 -157
  95. data/ext/iodine/fio_siphash.h +0 -37
  96. data/ext/iodine/fio_tls.h +0 -129
  97. data/ext/iodine/fio_tls_missing.c +0 -649
  98. data/ext/iodine/fio_tls_openssl.c +0 -1106
  99. data/ext/iodine/fio_tmpfile.h +0 -50
  100. data/ext/iodine/fiobj.h +0 -44
  101. data/ext/iodine/fiobj4fio.h +0 -21
  102. data/ext/iodine/fiobj_ary.c +0 -333
  103. data/ext/iodine/fiobj_ary.h +0 -139
  104. data/ext/iodine/fiobj_data.c +0 -1187
  105. data/ext/iodine/fiobj_data.h +0 -167
  106. data/ext/iodine/fiobj_hash.c +0 -409
  107. data/ext/iodine/fiobj_hash.h +0 -176
  108. data/ext/iodine/fiobj_json.c +0 -622
  109. data/ext/iodine/fiobj_json.h +0 -68
  110. data/ext/iodine/fiobj_mem.h +0 -71
  111. data/ext/iodine/fiobj_mustache.c +0 -317
  112. data/ext/iodine/fiobj_mustache.h +0 -62
  113. data/ext/iodine/fiobj_numbers.c +0 -344
  114. data/ext/iodine/fiobj_numbers.h +0 -127
  115. data/ext/iodine/fiobj_str.c +0 -433
  116. data/ext/iodine/fiobj_str.h +0 -172
  117. data/ext/iodine/fiobject.c +0 -620
  118. data/ext/iodine/fiobject.h +0 -655
  119. data/ext/iodine/hpack.h +0 -1923
  120. data/ext/iodine/http.c +0 -2743
  121. data/ext/iodine/http.h +0 -1002
  122. data/ext/iodine/http1.c +0 -910
  123. data/ext/iodine/http1.h +0 -29
  124. data/ext/iodine/http1_parser.h +0 -878
  125. data/ext/iodine/http_internal.c +0 -1279
  126. data/ext/iodine/http_internal.h +0 -237
  127. data/ext/iodine/http_mime_parser.h +0 -350
  128. data/ext/iodine/iodine_caller.c +0 -230
  129. data/ext/iodine/iodine_connection.c +0 -941
  130. data/ext/iodine/iodine_defer.c +0 -420
  131. data/ext/iodine/iodine_fiobj2rb.h +0 -120
  132. data/ext/iodine/iodine_helpers.c +0 -282
  133. data/ext/iodine/iodine_helpers.h +0 -12
  134. data/ext/iodine/iodine_http.c +0 -1181
  135. data/ext/iodine/iodine_http.h +0 -23
  136. data/ext/iodine/iodine_json.c +0 -302
  137. data/ext/iodine/iodine_mustache.c +0 -567
  138. data/ext/iodine/iodine_pubsub.c +0 -580
  139. data/ext/iodine/iodine_pubsub.h +0 -26
  140. data/ext/iodine/iodine_rack_io.c +0 -273
  141. data/ext/iodine/iodine_rack_io.h +0 -20
  142. data/ext/iodine/iodine_store.c +0 -146
  143. data/ext/iodine/iodine_tcp.c +0 -346
  144. data/ext/iodine/iodine_tcp.h +0 -13
  145. data/ext/iodine/iodine_tls.c +0 -261
  146. data/ext/iodine/mustache_parser.h +0 -1546
  147. data/ext/iodine/redis_engine.c +0 -957
  148. data/ext/iodine/redis_engine.h +0 -79
  149. data/ext/iodine/resp_parser.h +0 -317
  150. data/ext/iodine/websocket_parser.h +0 -506
  151. data/ext/iodine/websockets.c +0 -743
  152. data/ext/iodine/websockets.h +0 -185
  153. data/lib/iodine/connection.rb +0 -61
  154. data/lib/iodine/json.rb +0 -42
  155. data/lib/iodine/mustache.rb +0 -113
  156. data/lib/iodine/pubsub.rb +0 -55
  157. data/lib/iodine/rack_utils.rb +0 -43
  158. data/lib/iodine/tls.rb +0 -16
  159. data/lib/rack/handler/iodine.rb +0 -33
  160. data/logo.png +0 -0
@@ -1,620 +0,0 @@
1
- /*
2
- Copyright: Boaz Segev, 2017-2019
3
- License: MIT
4
- */
5
-
6
- /**
7
- This facil.io core library provides wrappers around complex and (or) dynamic
8
- types, abstracting some complexity and making dynamic type related tasks easier.
9
- */
10
-
11
- #include <fiobject.h>
12
-
13
- #define FIO_ARY_NAME fiobj_stack
14
- #define FIO_ARY_TYPE FIOBJ
15
- #define FIO_ARY_INVALID FIOBJ_INVALID
16
- /* don't free or compare objects, this stack shouldn't have side-effects */
17
- #include <fio.h>
18
-
19
- #include <stdarg.h>
20
- #include <stdint.h>
21
- #include <stdio.h>
22
- #include <stdlib.h>
23
- #include <string.h>
24
-
25
- /* *****************************************************************************
26
- Use the facil.io features when available, but override when missing.
27
- ***************************************************************************** */
28
- #ifndef fd_data /* defined in fio.c */
29
-
30
- #pragma weak fio_malloc
31
- void *fio_malloc(size_t size) {
32
- void *m = malloc(size);
33
- if (m)
34
- memset(m, 0, size);
35
- return m;
36
- }
37
-
38
- #pragma weak fio_calloc
39
- void *__attribute__((weak)) fio_calloc(size_t size, size_t count) {
40
- return calloc(size, count);
41
- }
42
-
43
- #pragma weak fio_free
44
- void __attribute__((weak)) fio_free(void *ptr) { free(ptr); }
45
-
46
- #pragma weak fio_realloc
47
- void *__attribute__((weak)) fio_realloc(void *ptr, size_t new_size) {
48
- return realloc(ptr, new_size);
49
- }
50
-
51
- #pragma weak fio_realloc2
52
- void *__attribute__((weak))
53
- fio_realloc2(void *ptr, size_t new_size, size_t valid_len) {
54
- return realloc(ptr, new_size);
55
- (void)valid_len;
56
- }
57
-
58
- #pragma weak fio_mmap
59
- void *__attribute__((weak)) fio_mmap(size_t size) { return fio_malloc(size); }
60
-
61
- /** The logging level */
62
- #if DEBUG
63
- #pragma weak FIO_LOG_LEVEL
64
- int __attribute__((weak)) FIO_LOG_LEVEL = FIO_LOG_LEVEL_DEBUG;
65
- #else
66
- #pragma weak FIO_LOG_LEVEL
67
- int __attribute__((weak)) FIO_LOG_LEVEL = FIO_LOG_LEVEL_INFO;
68
- #endif
69
-
70
- /**
71
- * We include this in case the parser is used outside of facil.io.
72
- */
73
- int64_t __attribute__((weak)) fio_atol(char **pstr) {
74
- return strtoll(*pstr, pstr, 0);
75
- }
76
- #pragma weak fio_atol
77
-
78
- /**
79
- * We include this in case the parser is used outside of facil.io.
80
- */
81
- double __attribute__((weak)) fio_atof(char **pstr) {
82
- return strtod(*pstr, pstr);
83
- }
84
- #pragma weak fio_atof
85
-
86
- /**
87
- * A helper function that writes a signed int64_t to a string.
88
- *
89
- * No overflow guard is provided, make sure there's at least 68 bytes
90
- * available (for base 2).
91
- *
92
- * Offers special support for base 2 (binary), base 8 (octal), base 10 and base
93
- * 16 (hex). An unsupported base will silently default to base 10. Prefixes
94
- * are automatically added (i.e., "0x" for hex and "0b" for base 2).
95
- *
96
- * Returns the number of bytes actually written (excluding the NUL
97
- * terminator).
98
- */
99
- #pragma weak fio_ltoa
100
- size_t __attribute__((weak)) fio_ltoa(char *dest, int64_t num, uint8_t base) {
101
- const char notation[] = {'0', '1', '2', '3', '4', '5', '6', '7',
102
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
103
-
104
- size_t len = 0;
105
- char buf[48] = {0}; /* we only need up to 20 for base 10, but base 3 needs 41... */
106
-
107
- if (!num)
108
- goto zero;
109
-
110
- switch (base) {
111
- case 1: /* fallthrough */
112
- case 2:
113
- /* Base 2 */
114
- {
115
- uint64_t n = num; /* avoid bit shifting inconsistencies with signed bit */
116
- uint8_t i = 0; /* counting bits */
117
- dest[len++] = '0';
118
- dest[len++] = 'b';
119
-
120
- while ((i < 64) && (n & 0x8000000000000000) == 0) {
121
- n = n << 1;
122
- i++;
123
- }
124
- /* make sure the Binary representation doesn't appear signed. */
125
- if (i) {
126
- dest[len++] = '0';
127
- }
128
- /* write to dest. */
129
- while (i < 64) {
130
- dest[len++] = ((n & 0x8000000000000000) ? '1' : '0');
131
- n = n << 1;
132
- i++;
133
- }
134
- dest[len] = 0;
135
- return len;
136
- }
137
- case 8:
138
- /* Base 8 */
139
- {
140
- uint64_t l = 0;
141
- if (num < 0) {
142
- dest[len++] = '-';
143
- num = 0 - num;
144
- }
145
- dest[len++] = '0';
146
-
147
- while (num) {
148
- buf[l++] = '0' + (num & 7);
149
- num = num >> 3;
150
- }
151
- while (l) {
152
- --l;
153
- dest[len++] = buf[l];
154
- }
155
- dest[len] = 0;
156
- return len;
157
- }
158
-
159
- case 16:
160
- /* Base 16 */
161
- {
162
- uint64_t n = num; /* avoid bit shifting inconsistencies with signed bit */
163
- uint8_t i = 0; /* counting bits */
164
- dest[len++] = '0';
165
- dest[len++] = 'x';
166
- while (i < 8 && (n & 0xFF00000000000000) == 0) {
167
- n = n << 8;
168
- i++;
169
- }
170
- /* make sure the Hex representation doesn't appear signed. */
171
- if (i && (n & 0x8000000000000000)) {
172
- dest[len++] = '0';
173
- dest[len++] = '0';
174
- }
175
- /* write the damn thing */
176
- while (i < 8) {
177
- uint8_t tmp = (n & 0xF000000000000000) >> 60;
178
- dest[len++] = notation[tmp];
179
- tmp = (n & 0x0F00000000000000) >> 56;
180
- dest[len++] = notation[tmp];
181
- i++;
182
- n = n << 8;
183
- }
184
- dest[len] = 0;
185
- return len;
186
- }
187
- case 3: /* fallthrough */
188
- case 4: /* fallthrough */
189
- case 5: /* fallthrough */
190
- case 6: /* fallthrough */
191
- case 7: /* fallthrough */
192
- case 9: /* fallthrough */
193
- /* rare bases */
194
- if (num < 0) {
195
- dest[len++] = '-';
196
- num = 0 - num;
197
- }
198
- uint64_t l = 0;
199
- while (num) {
200
- uint64_t t = num / base;
201
- buf[l++] = '0' + (num - (t * base));
202
- num = t;
203
- }
204
- while (l) {
205
- --l;
206
- dest[len++] = buf[l];
207
- }
208
- dest[len] = 0;
209
- return len;
210
-
211
- default:
212
- break;
213
- }
214
- /* Base 10, the default base */
215
-
216
- if (num < 0) {
217
- dest[len++] = '-';
218
- num = 0 - num;
219
- }
220
- uint64_t l = 0;
221
- while (num) {
222
- uint64_t t = num / 10;
223
- buf[l++] = '0' + (num - (t * 10));
224
- num = t;
225
- }
226
- while (l) {
227
- --l;
228
- dest[len++] = buf[l];
229
- }
230
- dest[len] = 0;
231
- return len;
232
-
233
- zero:
234
- switch (base) {
235
- case 1: /* fallthrough */
236
- case 2:
237
- dest[len++] = '0';
238
- dest[len++] = 'b';
239
- /* fallthrough */
240
- case 16:
241
- dest[len++] = '0';
242
- dest[len++] = 'x';
243
- dest[len++] = '0';
244
- }
245
- dest[len++] = '0';
246
- dest[len] = 0;
247
- return len;
248
- }
249
-
250
- /**
251
- * A helper function that converts between a double to a string.
252
- *
253
- * No overflow guard is provided, make sure there's at least 130 bytes
254
- * available (for base 2).
255
- *
256
- * Supports base 2, base 10 and base 16. An unsupported base will silently
257
- * default to base 10. Prefixes aren't added (i.e., no "0x" or "0b" at the
258
- * beginning of the string).
259
- *
260
- * Returns the number of bytes actually written (excluding the NUL
261
- * terminator).
262
- */
263
- #pragma weak fio_ftoa
264
- size_t __attribute__((weak)) fio_ftoa(char *dest, double num, uint8_t base) {
265
- if (base == 2 || base == 16) {
266
- /* handle the binary / Hex representation the same as if it were an
267
- * int64_t
268
- */
269
- int64_t *i = (void *)&num;
270
- return fio_ltoa(dest, *i, base);
271
- }
272
-
273
- size_t written = sprintf(dest, "%g", num);
274
- uint8_t need_zero = 1;
275
- char *start = dest;
276
- while (*start) {
277
- if (*start == ',') // locale issues?
278
- *start = '.';
279
- if (*start == '.' || *start == 'e') {
280
- need_zero = 0;
281
- break;
282
- }
283
- start++;
284
- }
285
- if (need_zero) {
286
- dest[written++] = '.';
287
- dest[written++] = '0';
288
- }
289
- return written;
290
- }
291
-
292
- #endif
293
- /* *****************************************************************************
294
- the `fiobj_each2` function
295
- ***************************************************************************** */
296
-
297
- struct task_packet_s {
298
- int (*task)(FIOBJ obj, void *arg);
299
- void *arg;
300
- fiobj_stack_s *stack;
301
- FIOBJ next;
302
- uintptr_t counter;
303
- uint8_t stop;
304
- uint8_t incomplete;
305
- };
306
-
307
- static int fiobj_task_wrapper(FIOBJ o, void *p_) {
308
- struct task_packet_s *p = p_;
309
- ++p->counter;
310
- int ret = p->task(o, p->arg);
311
- if (ret == -1) {
312
- p->stop = 1;
313
- return -1;
314
- }
315
- if (FIOBJ_IS_ALLOCATED(o) && FIOBJECT2VTBL(o)->each) {
316
- p->incomplete = 1;
317
- p->next = o;
318
- return -1;
319
- }
320
- return 0;
321
- }
322
- /**
323
- * Single layer iteration using a callback for each nested fio object.
324
- *
325
- * Accepts any `FIOBJ ` type but only collections (Arrays and Hashes) are
326
- * processed. The container itself (the Array or the Hash) is **not** processed
327
- * (unlike `fiobj_each2`).
328
- *
329
- * The callback task function must accept an object and an opaque user pointer.
330
- *
331
- * Hash objects pass along a `FIOBJ_T_COUPLET` object, containing
332
- * references for both the key and the object. Keys shouldn't be altered once
333
- * placed as a key (or the Hash will break). Collections (Arrays / Hashes) can't
334
- * be used as keeys.
335
- *
336
- * If the callback returns -1, the loop is broken. Any other value is ignored.
337
- *
338
- * Returns the "stop" position, i.e., the number of items processed + the
339
- * starting point.
340
- */
341
- size_t fiobj_each2(FIOBJ o, int (*task)(FIOBJ obj, void *arg), void *arg) {
342
- if (!o || !FIOBJ_IS_ALLOCATED(o) || (FIOBJECT2VTBL(o)->each == NULL)) {
343
- task(o, arg);
344
- return 1;
345
- }
346
- /* run task for root object */
347
- if (task(o, arg) == -1)
348
- return 1;
349
- uintptr_t pos = 0;
350
- fiobj_stack_s stack = FIO_ARY_INIT;
351
- struct task_packet_s packet = {
352
- .task = task,
353
- .arg = arg,
354
- .stack = &stack,
355
- .counter = 1,
356
- };
357
- do {
358
- if (!pos)
359
- packet.next = 0;
360
- packet.incomplete = 0;
361
- pos = FIOBJECT2VTBL(o)->each(o, pos, fiobj_task_wrapper, &packet);
362
- if (packet.stop)
363
- goto finish;
364
- if (packet.incomplete) {
365
- fiobj_stack_push(&stack, pos);
366
- fiobj_stack_push(&stack, o);
367
- }
368
-
369
- if (packet.next) {
370
- fiobj_stack_push(&stack, (FIOBJ)0);
371
- fiobj_stack_push(&stack, packet.next);
372
- }
373
- o = FIOBJ_INVALID;
374
- fiobj_stack_pop(&stack, &o);
375
- fiobj_stack_pop(&stack, &pos);
376
- } while (o);
377
- finish:
378
- fiobj_stack_free(&stack);
379
- return packet.counter;
380
- }
381
-
382
- /* *****************************************************************************
383
- Free complex objects (objects with nesting)
384
- ***************************************************************************** */
385
-
386
- static void fiobj_dealloc_task(FIOBJ o, void *stack_) {
387
- // if (!o)
388
- // fprintf(stderr, "* WARN: freeing a NULL no-object\n");
389
- // else
390
- // fprintf(stderr, "* freeing object %s\n", fiobj_obj2cstr(o).data);
391
- if (!o || !FIOBJ_IS_ALLOCATED(o))
392
- return;
393
- if (OBJREF_REM(o))
394
- return;
395
- if (!FIOBJECT2VTBL(o)->each || !FIOBJECT2VTBL(o)->count(o)) {
396
- FIOBJECT2VTBL(o)->dealloc(o, NULL, NULL);
397
- return;
398
- }
399
- fiobj_stack_s *s = stack_;
400
- fiobj_stack_push(s, o);
401
- }
402
- /**
403
- * Decreases an object's reference count, releasing memory and
404
- * resources.
405
- *
406
- * This function affects nested objects, meaning that when an Array or
407
- * a Hash object is passed along, it's children (nested objects) are
408
- * also freed.
409
- */
410
- void fiobj_free_complex_object(FIOBJ o) {
411
- fiobj_stack_s stack = FIO_ARY_INIT;
412
- do {
413
- FIOBJECT2VTBL(o)->dealloc(o, fiobj_dealloc_task, &stack);
414
- } while (!fiobj_stack_pop(&stack, &o));
415
- fiobj_stack_free(&stack);
416
- }
417
-
418
- /* *****************************************************************************
419
- Is Equal?
420
- ***************************************************************************** */
421
- #include <fiobj_hash.h>
422
-
423
- static inline int fiobj_iseq_simple(const FIOBJ o, const FIOBJ o2) {
424
- if (o == o2)
425
- return 1;
426
- if (!o || !o2)
427
- return 0; /* they should have compared equal before. */
428
- if (!FIOBJ_IS_ALLOCATED(o) || !FIOBJ_IS_ALLOCATED(o2))
429
- return 0; /* they should have compared equal before. */
430
- if (FIOBJECT2HEAD(o)->type != FIOBJECT2HEAD(o2)->type)
431
- return 0; /* non-type equality is a barriar to equality. */
432
- if (!FIOBJECT2VTBL(o)->is_eq(o, o2))
433
- return 0;
434
- return 1;
435
- }
436
-
437
- static int fiobj_iseq____internal_complex__task(FIOBJ o, void *ary_) {
438
- fiobj_stack_s *ary = ary_;
439
- fiobj_stack_push(ary, o);
440
- if (fiobj_hash_key_in_loop())
441
- fiobj_stack_push(ary, fiobj_hash_key_in_loop());
442
- return 0;
443
- }
444
-
445
- /** used internally for complext nested tests (Array / Hash types) */
446
- int fiobj_iseq____internal_complex__(FIOBJ o, FIOBJ o2) {
447
- // if (FIOBJECT2VTBL(o)->each && FIOBJECT2VTBL(o)->count(o))
448
- // return int fiobj_iseq____internal_complex__(const FIOBJ o, const FIOBJ
449
- // o2);
450
- fiobj_stack_s left = FIO_ARY_INIT, right = FIO_ARY_INIT, queue = FIO_ARY_INIT;
451
- do {
452
- fiobj_each1(o, 0, fiobj_iseq____internal_complex__task, &left);
453
- fiobj_each1(o2, 0, fiobj_iseq____internal_complex__task, &right);
454
- while (fiobj_stack_count(&left)) {
455
- o = FIOBJ_INVALID;
456
- o2 = FIOBJ_INVALID;
457
- fiobj_stack_pop(&left, &o);
458
- fiobj_stack_pop(&right, &o2);
459
- if (!fiobj_iseq_simple(o, o2))
460
- goto unequal;
461
- if (FIOBJ_IS_ALLOCATED(o) && FIOBJECT2VTBL(o)->each &&
462
- FIOBJECT2VTBL(o)->count(o)) {
463
- fiobj_stack_push(&queue, o);
464
- fiobj_stack_push(&queue, o2);
465
- }
466
- }
467
- o = FIOBJ_INVALID;
468
- o2 = FIOBJ_INVALID;
469
- fiobj_stack_pop(&queue, &o2);
470
- fiobj_stack_pop(&queue, &o);
471
- if (!fiobj_iseq_simple(o, o2))
472
- goto unequal;
473
- } while (o);
474
- fiobj_stack_free(&left);
475
- fiobj_stack_free(&right);
476
- fiobj_stack_free(&queue);
477
- return 1;
478
- unequal:
479
- fiobj_stack_free(&left);
480
- fiobj_stack_free(&right);
481
- fiobj_stack_free(&queue);
482
- return 0;
483
- }
484
-
485
- /* *****************************************************************************
486
- Defaults / NOOPs
487
- ***************************************************************************** */
488
-
489
- void fiobject___noop_dealloc(FIOBJ o, void (*task)(FIOBJ, void *), void *arg) {
490
- (void)o;
491
- (void)task;
492
- (void)arg;
493
- }
494
- void fiobject___simple_dealloc(FIOBJ o, void (*task)(FIOBJ, void *),
495
- void *arg) {
496
- fio_free(FIOBJ2PTR(o));
497
- (void)task;
498
- (void)arg;
499
- }
500
-
501
- uintptr_t fiobject___noop_count(const FIOBJ o) {
502
- (void)o;
503
- return 0;
504
- }
505
- size_t fiobject___noop_is_eq(const FIOBJ o1, const FIOBJ o2) {
506
- (void)o1;
507
- (void)o2;
508
- return 0;
509
- }
510
-
511
- fio_str_info_s fiobject___noop_to_str(const FIOBJ o) {
512
- (void)o;
513
- return (fio_str_info_s){.len = 0, .data = NULL};
514
- }
515
- intptr_t fiobject___noop_to_i(const FIOBJ o) {
516
- (void)o;
517
- return 0;
518
- }
519
- double fiobject___noop_to_f(const FIOBJ o) {
520
- (void)o;
521
- return 0;
522
- }
523
-
524
- #if DEBUG
525
-
526
- #include <fiobj_ary.h>
527
- #include <fiobj_numbers.h>
528
-
529
- static int fiobject_test_task(FIOBJ o, void *arg) {
530
- ++((uintptr_t *)arg)[0];
531
- if (!o)
532
- fprintf(stderr, "* WARN: counting a NULL no-object\n");
533
- // else
534
- // fprintf(stderr, "* counting object %s\n", fiobj_obj2cstr(o).data);
535
- return 0;
536
- (void)o;
537
- }
538
-
539
- void fiobj_test_core(void) {
540
- #define TEST_ASSERT(cond, ...) \
541
- if (!(cond)) { \
542
- fprintf(stderr, __VA_ARGS__); \
543
- fprintf(stderr, "Testing failed.\n"); \
544
- exit(-1); \
545
- }
546
- fprintf(stderr, "=== Testing Primitives\n");
547
- FIOBJ o = fiobj_null();
548
- TEST_ASSERT(o == (FIOBJ)FIOBJ_T_NULL, "fiobj_null isn't NULL!\n");
549
- TEST_ASSERT(FIOBJ_TYPE(0) == FIOBJ_T_NULL, "NULL isn't NULL!\n");
550
- TEST_ASSERT(FIOBJ_TYPE_IS(0, FIOBJ_T_NULL), "NULL isn't NULL! (2)\n");
551
- TEST_ASSERT(!FIOBJ_IS_ALLOCATED(fiobj_null()),
552
- "fiobj_null claims to be allocated!\n");
553
- TEST_ASSERT(!FIOBJ_IS_ALLOCATED(fiobj_true()),
554
- "fiobj_true claims to be allocated!\n");
555
- TEST_ASSERT(!FIOBJ_IS_ALLOCATED(fiobj_false()),
556
- "fiobj_false claims to be allocated!\n");
557
- TEST_ASSERT(FIOBJ_TYPE(fiobj_true()) == FIOBJ_T_TRUE,
558
- "fiobj_true isn't FIOBJ_T_TRUE!\n");
559
- TEST_ASSERT(FIOBJ_TYPE_IS(fiobj_true(), FIOBJ_T_TRUE),
560
- "fiobj_true isn't FIOBJ_T_TRUE! (2)\n");
561
- TEST_ASSERT(FIOBJ_TYPE(fiobj_false()) == FIOBJ_T_FALSE,
562
- "fiobj_false isn't FIOBJ_T_TRUE!\n");
563
- TEST_ASSERT(FIOBJ_TYPE_IS(fiobj_false(), FIOBJ_T_FALSE),
564
- "fiobj_false isn't FIOBJ_T_TRUE! (2)\n");
565
- fiobj_free(o); /* testing for crash*/
566
- fprintf(stderr, "* passed.\n");
567
- fprintf(stderr, "=== Testing fioj_each2\n");
568
- o = fiobj_ary_new2(4);
569
- FIOBJ tmp = fiobj_ary_new();
570
- fiobj_ary_push(o, tmp);
571
- fiobj_ary_push(o, fiobj_true());
572
- fiobj_ary_push(o, fiobj_null());
573
- fiobj_ary_push(o, fiobj_num_new(10));
574
- fiobj_ary_push(tmp, fiobj_num_new(13));
575
- fiobj_ary_push(tmp, fiobj_hash_new());
576
- FIOBJ key = fiobj_str_new("my key", 6);
577
- fiobj_hash_set(fiobj_ary_entry(tmp, -1), key, fiobj_true());
578
- fiobj_free(key);
579
- /* we have root array + 4 children (w/ array) + 2 children (w/ hash) + 1 */
580
- uintptr_t count = 0;
581
- size_t each_ret = 0;
582
- TEST_ASSERT(fiobj_each2(o, fiobject_test_task, (void *)&count) == 8,
583
- "fiobj_each1 didn't count everything... (%d != %d)", (int)count,
584
- (int)each_ret);
585
- TEST_ASSERT(count == 8, "Something went wrong with the counter task... (%d)",
586
- (int)count)
587
- fprintf(stderr, "* passed.\n");
588
- fprintf(stderr, "=== Testing fioj_iseq with nested items\n");
589
- FIOBJ o2 = fiobj_ary_new2(4);
590
- tmp = fiobj_ary_new();
591
- fiobj_ary_push(o2, tmp);
592
- fiobj_ary_push(o2, fiobj_true());
593
- fiobj_ary_push(o2, fiobj_null());
594
- fiobj_ary_push(o2, fiobj_num_new(10));
595
- fiobj_ary_push(tmp, fiobj_num_new(13));
596
- fiobj_ary_push(tmp, fiobj_hash_new());
597
- key = fiobj_str_new("my key", 6);
598
- fiobj_hash_set(fiobj_ary_entry(tmp, -1), key, fiobj_true());
599
- fiobj_free(key);
600
- TEST_ASSERT(!fiobj_iseq(o, FIOBJ_INVALID),
601
- "Array and FIOBJ_INVALID can't be equal!");
602
- TEST_ASSERT(!fiobj_iseq(o, fiobj_null()),
603
- "Array and fiobj_null can't be equal!");
604
- TEST_ASSERT(fiobj_iseq(o, o2), "Arrays aren't euqal!");
605
- fiobj_free(o);
606
- fiobj_free(o2);
607
- TEST_ASSERT(fiobj_iseq(fiobj_null(), fiobj_null()),
608
- "fiobj_null() not equal to self!");
609
- TEST_ASSERT(fiobj_iseq(fiobj_false(), fiobj_false()),
610
- "fiobj_false() not equal to self!");
611
- TEST_ASSERT(fiobj_iseq(fiobj_true(), fiobj_true()),
612
- "fiobj_true() not equal to self!");
613
- TEST_ASSERT(!fiobj_iseq(fiobj_null(), fiobj_false()),
614
- "fiobj_null eqal to fiobj_false!");
615
- TEST_ASSERT(!fiobj_iseq(fiobj_null(), fiobj_true()),
616
- "fiobj_null eqal to fiobj_true!");
617
- fprintf(stderr, "* passed.\n");
618
- }
619
-
620
- #endif