iodine 0.4.14 → 0.4.15
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +61 -33
- data/README.md +7 -5
- data/ext/iodine/base64.c +12 -0
- data/ext/iodine/defer.c +211 -108
- data/ext/iodine/defer.h +7 -0
- data/ext/iodine/facil.c +5 -1
- data/ext/iodine/facil.h +1 -1
- data/ext/iodine/fio2resp.c +19 -30
- data/ext/iodine/fio2resp.h +2 -1
- data/ext/iodine/fio_cli_helper.c +2 -2
- data/ext/iodine/fiobj.h +11 -624
- data/ext/iodine/fiobj_ary.c +65 -26
- data/ext/iodine/fiobj_ary.h +106 -0
- data/ext/iodine/fiobj_hash.c +175 -115
- data/ext/iodine/fiobj_hash.h +128 -0
- data/ext/iodine/fiobj_internal.c +189 -0
- data/ext/iodine/{fiobj_types.h → fiobj_internal.h} +126 -136
- data/ext/iodine/fiobj_json.c +161 -207
- data/ext/iodine/fiobj_json.h +43 -0
- data/ext/iodine/fiobj_numbers.c +53 -35
- data/ext/iodine/fiobj_numbers.h +49 -0
- data/ext/iodine/fiobj_primitives.c +103 -70
- data/ext/iodine/fiobj_primitives.h +55 -0
- data/ext/iodine/fiobj_str.c +171 -59
- data/ext/iodine/fiobj_str.h +113 -0
- data/ext/iodine/fiobj_sym.c +46 -124
- data/ext/iodine/fiobj_sym.h +60 -0
- data/ext/iodine/fiobject.c +589 -0
- data/ext/iodine/fiobject.h +276 -0
- data/ext/iodine/pubsub.h +1 -1
- data/ext/iodine/resp.c +2 -2
- data/ext/iodine/siphash.c +11 -0
- data/ext/iodine/spnlock.inc +7 -5
- data/ext/iodine/websocket_parser.h +44 -7
- data/lib/iodine/version.rb +1 -1
- metadata +13 -8
- data/ext/iodine/fiobj_alloc.c +0 -81
- data/ext/iodine/fiobj_generic.c +0 -260
- data/ext/iodine/fiobj_io.c +0 -58
- data/ext/iodine/fiobj_misc.c +0 -213
- data/ext/iodine/fiobj_tests.c +0 -474
data/ext/iodine/fiobj_json.c
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
/*
|
2
|
-
Copyright: Boaz
|
2
|
+
Copyright: Boaz Segev, 2017
|
3
3
|
License: MIT
|
4
|
-
|
5
|
-
Feel free to copy, use and enjoy according to the license provided.
|
6
4
|
*/
|
7
|
-
#include "
|
5
|
+
#include "fiobj_json.h"
|
6
|
+
|
8
7
|
// #include "fio2resp.h"
|
9
8
|
#include <ctype.h>
|
9
|
+
#include <math.h>
|
10
|
+
#include <stdlib.h>
|
11
|
+
#include <string.h>
|
10
12
|
|
11
13
|
/* *****************************************************************************
|
12
14
|
JSON API
|
@@ -82,81 +84,88 @@ static inline int utf8_from_u32(uint8_t *dest, uint32_t u) {
|
|
82
84
|
return 4;
|
83
85
|
}
|
84
86
|
|
85
|
-
/** Writes a JSON friendly version of the src String
|
86
|
-
static void write_safe_str(fiobj_s *dest, fiobj_s *str) {
|
87
|
+
/** Writes a JSON friendly version of the src String */
|
88
|
+
static void write_safe_str(fiobj_s *dest, const fiobj_s *str) {
|
87
89
|
fio_cstr_s s = fiobj_obj2cstr(str);
|
88
|
-
|
90
|
+
fio_cstr_s t = fiobj_obj2cstr(dest);
|
91
|
+
const uint8_t *restrict src = (const uint8_t *)s.data;
|
89
92
|
size_t len = s.len;
|
90
|
-
uint64_t end =
|
93
|
+
uint64_t end = t.len;
|
91
94
|
/* make sure we have some room */
|
92
95
|
size_t added = 0;
|
93
|
-
|
94
|
-
|
96
|
+
size_t capa = fiobj_str_capa(dest);
|
97
|
+
if (capa <= end + s.len + 64) {
|
98
|
+
capa = (((capa >> 12) + 1) << 12) - 1;
|
99
|
+
fiobj_str_capa_assert(dest, capa);
|
100
|
+
fio_cstr_s tmp = fiobj_obj2cstr(dest);
|
101
|
+
t = tmp;
|
102
|
+
}
|
95
103
|
while (len) {
|
104
|
+
char *restrict writer = (char *)t.data;
|
96
105
|
while (len &&
|
97
106
|
(src[0] > 32 && src[0] != '"' && src[0] != '\\' && src[0] != '/')) {
|
98
107
|
len--;
|
99
|
-
|
108
|
+
writer[end++] = *(src++);
|
100
109
|
}
|
101
110
|
if (!len)
|
102
111
|
break;
|
103
112
|
switch (src[0]) {
|
104
113
|
case '\b':
|
105
|
-
|
106
|
-
|
114
|
+
writer[end++] = '\\';
|
115
|
+
writer[end++] = 'b';
|
107
116
|
added++;
|
108
117
|
break; /* from switch */
|
109
118
|
case '\f':
|
110
|
-
|
111
|
-
|
119
|
+
writer[end++] = '\\';
|
120
|
+
writer[end++] = 'f';
|
112
121
|
added++;
|
113
122
|
break; /* from switch */
|
114
123
|
case '\n':
|
115
|
-
|
116
|
-
|
124
|
+
writer[end++] = '\\';
|
125
|
+
writer[end++] = 'n';
|
117
126
|
added++;
|
118
127
|
break; /* from switch */
|
119
128
|
case '\r':
|
120
|
-
|
121
|
-
|
129
|
+
writer[end++] = '\\';
|
130
|
+
writer[end++] = 'r';
|
122
131
|
added++;
|
123
132
|
break; /* from switch */
|
124
133
|
case '\t':
|
125
|
-
|
126
|
-
|
134
|
+
writer[end++] = '\\';
|
135
|
+
writer[end++] = 't';
|
127
136
|
added++;
|
128
137
|
break; /* from switch */
|
129
138
|
case '"':
|
130
139
|
case '\\':
|
131
140
|
case '/':
|
132
|
-
|
133
|
-
|
141
|
+
writer[end++] = '\\';
|
142
|
+
writer[end++] = src[0];
|
134
143
|
added++;
|
135
144
|
break; /* from switch */
|
136
145
|
default:
|
137
146
|
if (src[0] <= 31) {
|
138
147
|
/* MUST escape all control values less than 32 */
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
148
|
+
writer[end++] = '\\';
|
149
|
+
writer[end++] = 'u';
|
150
|
+
writer[end++] = '0';
|
151
|
+
writer[end++] = '0';
|
152
|
+
writer[end++] = hex_chars[src[0] >> 4];
|
153
|
+
writer[end++] = hex_chars[src[0] & 15];
|
145
154
|
added += 4;
|
146
155
|
} else
|
147
|
-
|
156
|
+
writer[end++] = src[0];
|
148
157
|
break; /* from switch */
|
149
158
|
}
|
150
159
|
src++;
|
151
160
|
len--;
|
152
|
-
if (added >= 48 &&
|
153
|
-
|
154
|
-
|
161
|
+
if (added >= 48 && capa <= end + len + 64) {
|
162
|
+
capa = (((capa >> 12) + 1) << 12) - 1;
|
163
|
+
fiobj_str_capa_assert(dest, capa);
|
164
|
+
t = fiobj_obj2cstr(dest);
|
155
165
|
added = 0;
|
156
166
|
}
|
157
167
|
}
|
158
|
-
|
159
|
-
obj2str(dest)->str[end] = 0;
|
168
|
+
fiobj_str_resize(dest, end);
|
160
169
|
}
|
161
170
|
|
162
171
|
/* *****************************************************************************
|
@@ -179,7 +188,7 @@ static int fiobj_str_new_json_task(fiobj_s *obj, void *d_) {
|
|
179
188
|
/* headroom */
|
180
189
|
fiobj_str_capa_assert(
|
181
190
|
data->buffer,
|
182
|
-
((((
|
191
|
+
((((fiobj_obj2cstr(data->buffer).len + 63) >> 12) + 1) << 12) - 1);
|
183
192
|
pretty_re_rooted:
|
184
193
|
/* pretty? */
|
185
194
|
if (data->pretty) {
|
@@ -193,36 +202,32 @@ re_rooted:
|
|
193
202
|
fiobj_str_write(data->buffer, "null", 4);
|
194
203
|
goto review_nesting;
|
195
204
|
}
|
196
|
-
|
197
|
-
case FIOBJ_T_HASH:
|
205
|
+
if (obj->type == FIOBJ_T_HASH) {
|
198
206
|
fiobj_str_write(data->buffer, "{", 1);
|
199
207
|
fiobj_ary_push(data->parent, obj);
|
200
208
|
fiobj_ary_push(data->waiting, data->count);
|
201
209
|
data->count = fiobj_num_new(fiobj_hash_count(obj));
|
202
|
-
|
203
|
-
case FIOBJ_T_ARRAY:
|
210
|
+
} else if (obj->type == FIOBJ_T_ARRAY) {
|
204
211
|
fiobj_str_write(data->buffer, "[", 1);
|
205
212
|
/* push current state to stacks and update state */
|
206
213
|
fiobj_ary_push(data->parent, obj);
|
207
214
|
fiobj_ary_push(data->waiting, data->count);
|
208
215
|
data->count = fiobj_num_new(fiobj_ary_count(obj));
|
209
|
-
|
210
|
-
case FIOBJ_T_SYMBOL:
|
211
|
-
case FIOBJ_T_STRING: {
|
216
|
+
} else if (obj->type == FIOBJ_T_SYMBOL || FIOBJ_IS_STRING(obj)) {
|
212
217
|
fiobj_str_capa_assert(
|
213
218
|
data->buffer,
|
214
|
-
((((
|
219
|
+
((((fiobj_obj2cstr(data->buffer).len + 63 + fiobj_obj2cstr(obj).len) >>
|
220
|
+
12) +
|
221
|
+
1)
|
215
222
|
<< 12) -
|
216
223
|
1);
|
217
224
|
fiobj_str_write(data->buffer, "\"", 1);
|
218
225
|
write_safe_str(data->buffer, obj);
|
219
226
|
fiobj_str_write(data->buffer, "\"", 1);
|
220
|
-
|
221
|
-
}
|
222
|
-
case FIOBJ_T_COUPLET: {
|
227
|
+
} else if (obj->type == FIOBJ_T_COUPLET) {
|
223
228
|
fiobj_str_capa_assert(data->buffer,
|
224
|
-
((((
|
225
|
-
|
229
|
+
((((fiobj_obj2cstr(data->buffer).len + 31 +
|
230
|
+
fiobj_obj2cstr(fiobj_couplet2key(obj)).len) >>
|
226
231
|
12) +
|
227
232
|
1)
|
228
233
|
<< 12) -
|
@@ -235,54 +240,15 @@ re_rooted:
|
|
235
240
|
(obj->type == FIOBJ_T_ARRAY || obj->type == FIOBJ_T_HASH))
|
236
241
|
goto pretty_re_rooted;
|
237
242
|
goto re_rooted;
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
break;
|
245
|
-
case FIOBJ_T_FLOAT:
|
246
|
-
if (isnan(obj2float(obj)->f))
|
247
|
-
fiobj_str_write(data->buffer, "\"NaN\"", 5);
|
248
|
-
else if (isinf(obj2float(obj)->f)) {
|
249
|
-
if (obj2float(obj)->f > 0)
|
250
|
-
fiobj_str_write(data->buffer, "\"Infinity\"", 10);
|
251
|
-
else
|
252
|
-
fiobj_str_write(data->buffer, "\"-Infinity\"", 11);
|
253
|
-
} else {
|
254
|
-
char *start = obj2str(data->buffer)->str + obj2str(data->buffer)->len;
|
255
|
-
fiobj_str_write2(data->buffer, "%g", obj2float(obj)->f);
|
256
|
-
uint8_t need_zero = 1;
|
257
|
-
while (*start) {
|
258
|
-
if (*start == ',') // locale issues?
|
259
|
-
*start = '.';
|
260
|
-
if (*start == '.' || *start == 'e') {
|
261
|
-
need_zero = 0;
|
262
|
-
break;
|
263
|
-
}
|
264
|
-
start++;
|
265
|
-
}
|
266
|
-
if (need_zero)
|
267
|
-
fiobj_str_write(data->buffer, ".0", 2);
|
268
|
-
}
|
269
|
-
break;
|
270
|
-
// case FIOBJ_T_FLOAT:
|
271
|
-
// obj2str(data->buffer)->len +=
|
272
|
-
// fio_ftoa(obj2str(data->buffer)->str + obj2str(data->buffer)->len,
|
273
|
-
// obj2float(obj)->f, 10);
|
274
|
-
// break;
|
275
|
-
case FIOBJ_T_TRUE:
|
243
|
+
} else if (obj->type == FIOBJ_T_NUMBER || obj->type == FIOBJ_T_FLOAT) {
|
244
|
+
fio_cstr_s i2s = fiobj_obj2cstr(obj);
|
245
|
+
fiobj_str_write(data->buffer, i2s.data, i2s.len);
|
246
|
+
} else if (obj->type == FIOBJ_T_NULL) {
|
247
|
+
fiobj_str_write(data->buffer, "null", 4);
|
248
|
+
} else if (fiobj_is_true(obj)) {
|
276
249
|
fiobj_str_write(data->buffer, "true", 4);
|
277
|
-
|
278
|
-
case FIOBJ_T_FALSE:
|
250
|
+
} else
|
279
251
|
fiobj_str_write(data->buffer, "false", 5);
|
280
|
-
break;
|
281
|
-
case FIOBJ_T_IO:
|
282
|
-
case FIOBJ_T_NULL:
|
283
|
-
fiobj_str_write(data->buffer, "null", 4);
|
284
|
-
break;
|
285
|
-
}
|
286
252
|
|
287
253
|
review_nesting:
|
288
254
|
/* print clousure to String */
|
@@ -423,14 +389,14 @@ JSON UTF-8 safe string deconstruction
|
|
423
389
|
*
|
424
390
|
* Also deals with the non-standard oct ("\77") and hex ("\xFF") notations
|
425
391
|
*/
|
426
|
-
static
|
392
|
+
static uintptr_t safestr2local(fiobj_s *str) {
|
427
393
|
if (str->type != FIOBJ_T_STRING && str->type != FIOBJ_T_SYMBOL) {
|
428
394
|
fprintf(stderr,
|
429
395
|
"CRITICAL ERROR: unexpected function call `safestr2local`\n");
|
430
396
|
exit(-1);
|
431
397
|
}
|
432
398
|
fio_cstr_s s = fiobj_obj2cstr(str);
|
433
|
-
uint8_t had_changed = 0;
|
399
|
+
// uint8_t had_changed = 0;
|
434
400
|
uint8_t *end = (uint8_t *)s.bytes + s.len;
|
435
401
|
uint8_t *reader = (uint8_t *)s.bytes;
|
436
402
|
uint8_t *writer = (uint8_t *)s.bytes;
|
@@ -441,7 +407,7 @@ static void safestr2local(fiobj_s *str) {
|
|
441
407
|
if (reader[0] != '\\')
|
442
408
|
break;
|
443
409
|
|
444
|
-
had_changed = 1;
|
410
|
+
// had_changed = 1;
|
445
411
|
switch (reader[1]) {
|
446
412
|
case 'b':
|
447
413
|
*(writer++) = '\b';
|
@@ -528,15 +494,8 @@ static void safestr2local(fiobj_s *str) {
|
|
528
494
|
reader += 2;
|
529
495
|
}
|
530
496
|
}
|
531
|
-
if
|
532
|
-
|
533
|
-
obj2str(str)->str[obj2str(str)->len] = 0;
|
534
|
-
} else {
|
535
|
-
obj2sym(str)->len = (uintptr_t)writer - (uintptr_t)obj2sym(str)->str;
|
536
|
-
obj2sym(str)->str[obj2sym(str)->len] = 0;
|
537
|
-
if (had_changed)
|
538
|
-
obj2sym(str)->hash = fiobj_sym_hash(obj2sym(str)->str, obj2sym(str)->len);
|
539
|
-
}
|
497
|
+
// if(had_changed)
|
498
|
+
return ((uintptr_t)writer - (uintptr_t)s.bytes);
|
540
499
|
}
|
541
500
|
|
542
501
|
/* *****************************************************************************
|
@@ -556,6 +515,7 @@ size_t fiobj_json2obj(fiobj_s **pobj, const void *data, size_t len) {
|
|
556
515
|
return 0;
|
557
516
|
}
|
558
517
|
fiobj_s *nesting = fiobj_ary_new2(JSON_MAX_DEPTH + 2);
|
518
|
+
int64_t num;
|
559
519
|
const uint8_t *start;
|
560
520
|
fiobj_s *obj;
|
561
521
|
const uint8_t *end = (uint8_t *)data;
|
@@ -573,6 +533,57 @@ size_t fiobj_json2obj(fiobj_s **pobj, const void *data, size_t len) {
|
|
573
533
|
|
574
534
|
/* test object type. tests are ordered by precedence, if one fails, the
|
575
535
|
* other is performed. */
|
536
|
+
if (start[0] == '"') {
|
537
|
+
/* object is a string (require qoutes) */
|
538
|
+
start++;
|
539
|
+
end++;
|
540
|
+
uint8_t dirty = 0;
|
541
|
+
while (move_to_quote(&end, stop)) {
|
542
|
+
end += 2;
|
543
|
+
dirty = 1;
|
544
|
+
}
|
545
|
+
if (end >= stop) {
|
546
|
+
goto error;
|
547
|
+
}
|
548
|
+
|
549
|
+
if (fiobj_ary_index(nesting, -1) &&
|
550
|
+
fiobj_ary_index(nesting, -1)->type == FIOBJ_T_HASH) {
|
551
|
+
obj = fiobj_sym_new((char *)start, end - start);
|
552
|
+
if (dirty)
|
553
|
+
fiobj_sym_reinitialize(obj, (size_t)safestr2local(obj));
|
554
|
+
} else {
|
555
|
+
obj = fiobj_str_new((char *)start, end - start);
|
556
|
+
if (dirty)
|
557
|
+
fiobj_str_resize(obj, (size_t)safestr2local(obj));
|
558
|
+
}
|
559
|
+
end++;
|
560
|
+
|
561
|
+
goto has_obj;
|
562
|
+
}
|
563
|
+
if (end[0] >= 'a' && end[0] <= 'z') {
|
564
|
+
if (end + 3 < stop && end[0] == 't' && end[1] == 'r' && end[2] == 'u' &&
|
565
|
+
end[3] == 'e') {
|
566
|
+
/* true */
|
567
|
+
end += 4;
|
568
|
+
obj = fiobj_true();
|
569
|
+
goto has_obj;
|
570
|
+
}
|
571
|
+
if (end + 4 < stop && end[0] == 'f' && end[1] == 'a' && end[2] == 'l' &&
|
572
|
+
end[3] == 's' && end[4] == 'e') {
|
573
|
+
/* false */
|
574
|
+
end += 5;
|
575
|
+
obj = fiobj_false();
|
576
|
+
goto has_obj;
|
577
|
+
}
|
578
|
+
if (end + 3 < stop && end[0] == 'n' && end[1] == 'u' && end[2] == 'l' &&
|
579
|
+
end[3] == 'l') {
|
580
|
+
/* null */
|
581
|
+
end += 4;
|
582
|
+
obj = fiobj_null();
|
583
|
+
goto has_obj;
|
584
|
+
}
|
585
|
+
goto error;
|
586
|
+
}
|
576
587
|
if (end[0] == '{') {
|
577
588
|
/* start an object (hash) */
|
578
589
|
fiobj_ary_push(nesting, fiobj_hash_new());
|
@@ -613,25 +624,47 @@ size_t fiobj_json2obj(fiobj_s **pobj, const void *data, size_t len) {
|
|
613
624
|
}
|
614
625
|
goto has_obj;
|
615
626
|
}
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
627
|
+
|
628
|
+
if (end[0] == '-') {
|
629
|
+
if (end[0] == '-' && end[1] == 'N' && end[2] == 'a' && end[3] == 'N') {
|
630
|
+
move_to_end(&end, stop);
|
631
|
+
double fl = nan("");
|
632
|
+
fl = copysign(fl, (double)-1);
|
633
|
+
obj = fiobj_float_new(fl);
|
634
|
+
goto has_obj;
|
635
|
+
}
|
636
|
+
if (end[0] == '-' && end[1] == 'I' && end[2] == 'n' && end[3] == 'f') {
|
637
|
+
move_to_end(&end, stop);
|
638
|
+
double fl = INFINITY;
|
639
|
+
fl = copysign(fl, (double)-1);
|
640
|
+
obj = fiobj_float_new(fl);
|
641
|
+
goto has_obj;
|
642
|
+
}
|
643
|
+
goto test_for_number;
|
644
|
+
}
|
645
|
+
if (end[0] >= '0' && end[0] <= '9') {
|
646
|
+
test_for_number: /* test for a number OR float */
|
647
|
+
num = fio_atol((char **)&end);
|
648
|
+
if (end == start || *end == '.' || *end == 'e' || *end == 'E') {
|
649
|
+
end = start;
|
650
|
+
double fnum = fio_atof((char **)&end);
|
651
|
+
if (end == start)
|
652
|
+
goto error;
|
653
|
+
obj = fiobj_float_new(fnum);
|
654
|
+
goto has_obj;
|
655
|
+
}
|
656
|
+
obj = fiobj_num_new(num);
|
621
657
|
goto has_obj;
|
622
658
|
}
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
obj = fiobj_false();
|
659
|
+
|
660
|
+
if (end[0] == 'N' && end[1] == 'a' && end[2] == 'N') {
|
661
|
+
move_to_end(&end, stop);
|
662
|
+
obj = fiobj_float_new(nan(""));
|
628
663
|
goto has_obj;
|
629
664
|
}
|
630
|
-
if (end
|
631
|
-
|
632
|
-
|
633
|
-
end += 4;
|
634
|
-
obj = fiobj_null();
|
665
|
+
if (end[0] == 'I' && end[1] == 'n' && end[2] == 'f') {
|
666
|
+
move_to_end(&end, stop);
|
667
|
+
obj = fiobj_float_new(INFINITY);
|
635
668
|
goto has_obj;
|
636
669
|
}
|
637
670
|
if (end[0] == '/') {
|
@@ -655,103 +688,24 @@ size_t fiobj_json2obj(fiobj_s **pobj, const void *data, size_t len) {
|
|
655
688
|
move_to_eol(&end, stop);
|
656
689
|
continue;
|
657
690
|
}
|
658
|
-
if (start[0] == '"') {
|
659
|
-
/* object is a string (require qoutes) */
|
660
|
-
start++;
|
661
|
-
end++;
|
662
|
-
uint8_t dirty = 0;
|
663
|
-
while (move_to_quote(&end, stop)) {
|
664
|
-
end += 2;
|
665
|
-
dirty = 1;
|
666
|
-
}
|
667
|
-
if (end >= stop) {
|
668
|
-
goto error;
|
669
|
-
}
|
670
|
-
if (fiobj_ary_entry(nesting, -1) &&
|
671
|
-
fiobj_ary_entry(nesting, -1)->type == FIOBJ_T_HASH) {
|
672
|
-
obj = fiobj_sym_new((char *)start, end - start);
|
673
|
-
} else {
|
674
|
-
obj = fiobj_str_new((char *)start, end - start);
|
675
|
-
}
|
676
|
-
if (dirty)
|
677
|
-
safestr2local(obj);
|
678
|
-
end++;
|
679
|
-
|
680
|
-
goto has_obj;
|
681
|
-
}
|
682
|
-
if (end[0] == '-' || (end[0] >= '0' && end[0] <= '9')) {
|
683
|
-
/* test for a number OR float */
|
684
|
-
int64_t num = fio_atol((char **)&end);
|
685
|
-
if (end == start || *end == '.' || *end == 'e' || *end == 'E') {
|
686
|
-
end = start;
|
687
|
-
double fnum = fio_atof((char **)&end);
|
688
|
-
if (end == start)
|
689
|
-
goto error;
|
690
|
-
obj = fiobj_float_new(fnum);
|
691
|
-
goto has_obj;
|
692
|
-
}
|
693
|
-
obj = fiobj_num_new(num);
|
694
|
-
goto has_obj;
|
695
|
-
// uint8_t decimal = 0;
|
696
|
-
// while (end < stop && JSON_SEPERATOR[*end] == 0 && *end != ']' &&
|
697
|
-
// *end != '}') {
|
698
|
-
// if (*end == '.' || *end == 'e' || *end == 'E')
|
699
|
-
// decimal = 1;
|
700
|
-
// end++;
|
701
|
-
// }
|
702
|
-
// /* test against forbidden leading zeros... but allow hex and binary
|
703
|
-
// */ if (end - start > 1 && start[0] == '0' &&
|
704
|
-
// !(start[1] == '.' || start[1] == 'x' || start[1] == 'b')) {
|
705
|
-
// goto error;
|
706
|
-
// }
|
707
|
-
// /* it's a number */
|
708
|
-
// if (decimal) {
|
709
|
-
// obj = fiobj_float_new(fio_atof((char *)start));
|
710
|
-
// } else {
|
711
|
-
// obj = fiobj_num_new(fio_atol((char *)start));
|
712
|
-
// }
|
713
|
-
// goto has_obj;
|
714
|
-
}
|
715
|
-
if (end[0] == 'N' && end[1] == 'a' && end[2] == 'N') {
|
716
|
-
obj = fiobj_float_new(nan(""));
|
717
|
-
goto has_obj;
|
718
|
-
}
|
719
|
-
if (end[0] == '-' && end[1] == 'I' && end[2] == 'n' && end[3] == 'f') {
|
720
|
-
obj = fiobj_float_new(nan(""));
|
721
|
-
obj2float(obj)->f = copysign(obj2float(obj)->f, (double)-1);
|
722
|
-
goto has_obj;
|
723
|
-
}
|
724
|
-
if (end[0] == 'I' && end[1] == 'n' && end[2] == 'f') {
|
725
|
-
move_to_end(&end, stop);
|
726
|
-
obj = fiobj_float_new(INFINITY);
|
727
|
-
goto has_obj;
|
728
|
-
}
|
729
|
-
if (end[0] == '-' && end[1] == 'I' && end[2] == 'n' && end[3] == 'f') {
|
730
|
-
move_to_end(&end, stop);
|
731
|
-
obj = fiobj_float_new(INFINITY);
|
732
|
-
obj2float(obj)->f = copysign(obj2float(obj)->f, (double)-1);
|
733
|
-
goto has_obj;
|
734
|
-
}
|
735
691
|
goto error;
|
736
692
|
|
737
693
|
has_obj:
|
738
694
|
|
739
695
|
if (fiobj_ary_count(nesting) == 0)
|
740
696
|
goto finish_with_obj;
|
741
|
-
if (
|
742
|
-
fiobj_ary_push(
|
697
|
+
if (fiobj_ary_index(nesting, -1)->type == FIOBJ_T_ARRAY) {
|
698
|
+
fiobj_ary_push(fiobj_ary_index(nesting, -1), obj);
|
743
699
|
continue;
|
744
700
|
}
|
745
|
-
if (
|
746
|
-
|
747
|
-
fiobj_ary_push(nesting, fiobj_sym_new(s.buffer, s.len));
|
748
|
-
fiobj_free(obj);
|
701
|
+
if (fiobj_ary_index(nesting, -1)->type == FIOBJ_T_HASH) {
|
702
|
+
fiobj_ary_push(nesting, obj);
|
749
703
|
continue;
|
750
704
|
}
|
751
705
|
fiobj_s *sym = fiobj_ary_pop(nesting);
|
752
|
-
if (
|
706
|
+
if (fiobj_ary_index(nesting, -1)->type != FIOBJ_T_HASH)
|
753
707
|
goto error;
|
754
|
-
fiobj_hash_set(
|
708
|
+
fiobj_hash_set(fiobj_ary_index(nesting, -1), sym, obj);
|
755
709
|
fiobj_free(sym);
|
756
710
|
continue;
|
757
711
|
}
|