oj 3.13.10 → 3.13.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/ext/oj/circarray.c +1 -1
- data/ext/oj/code.c +15 -22
- data/ext/oj/custom.c +28 -55
- data/ext/oj/dump.c +128 -161
- data/ext/oj/dump.h +12 -8
- data/ext/oj/dump_compat.c +43 -80
- data/ext/oj/dump_leaf.c +14 -58
- data/ext/oj/dump_object.c +28 -96
- data/ext/oj/dump_strict.c +12 -24
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/fast.c +9 -9
- data/ext/oj/intern.c +9 -2
- data/ext/oj/intern.h +1 -1
- data/ext/oj/mimic_json.c +25 -23
- data/ext/oj/odd.c +83 -63
- data/ext/oj/odd.h +13 -13
- data/ext/oj/oj.c +28 -16
- data/ext/oj/oj.h +20 -2
- data/ext/oj/parse.c +3 -2
- data/ext/oj/parser.c +10 -15
- data/ext/oj/rails.c +38 -57
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +2 -0
- data/ext/oj/saj.c +11 -23
- data/ext/oj/stream_writer.c +3 -1
- data/ext/oj/string_writer.c +12 -5
- data/ext/oj/wab.c +8 -8
- data/lib/oj/version.rb +1 -1
- data/test/bar.rb +1 -8
- data/test/foo.rb +67 -25
- data/test/perf_dump.rb +50 -0
- data/test/test_object.rb +12 -7
- data/test/test_saj.rb +1 -1
- data/test/test_various.rb +27 -2
- data/test/tests.rb +0 -1
- metadata +6 -3
data/ext/oj/rails.c
CHANGED
@@ -167,17 +167,14 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
|
|
167
167
|
}
|
168
168
|
fill_indent(out, d3);
|
169
169
|
*out->cur++ = '"';
|
170
|
-
|
171
|
-
out->cur += len;
|
170
|
+
APPEND_CHARS(out->cur, name, len);
|
172
171
|
*out->cur++ = '"';
|
173
172
|
if (0 < out->opts->dump_opts.before_size) {
|
174
|
-
|
175
|
-
out->cur += out->opts->dump_opts.before_size;
|
173
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
|
176
174
|
}
|
177
175
|
*out->cur++ = ':';
|
178
176
|
if (0 < out->opts->dump_opts.after_size) {
|
179
|
-
|
180
|
-
out->cur += out->opts->dump_opts.after_size;
|
177
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
|
181
178
|
}
|
182
179
|
#ifdef RSTRUCT_LEN
|
183
180
|
v = RSTRUCT_GET(obj, i);
|
@@ -330,12 +327,12 @@ static void dump_time(VALUE obj, int depth, Out out, bool as_ok) {
|
|
330
327
|
sec = (long long)ts.tv_sec;
|
331
328
|
nsec = ts.tv_nsec;
|
332
329
|
} else {
|
333
|
-
sec =
|
334
|
-
nsec =
|
330
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
331
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
335
332
|
}
|
336
333
|
#else
|
337
|
-
sec =
|
338
|
-
nsec =
|
334
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
335
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
339
336
|
#endif
|
340
337
|
dump_sec_nano(obj, sec, nsec, out);
|
341
338
|
}
|
@@ -345,9 +342,9 @@ static void dump_timewithzone(VALUE obj, int depth, Out out, bool as_ok) {
|
|
345
342
|
long long nsec = 0;
|
346
343
|
|
347
344
|
if (rb_respond_to(obj, oj_tv_nsec_id)) {
|
348
|
-
nsec =
|
345
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
349
346
|
} else if (rb_respond_to(obj, oj_tv_usec_id)) {
|
350
|
-
nsec =
|
347
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_usec_id, 0, 0)) * 1000;
|
351
348
|
}
|
352
349
|
dump_sec_nano(obj, sec, nsec, out);
|
353
350
|
}
|
@@ -405,14 +402,12 @@ static void dump_row(VALUE row, StrLen cols, int ccnt, int depth, Out out) {
|
|
405
402
|
assure_size(out, size);
|
406
403
|
if (out->opts->dump_opts.use) {
|
407
404
|
if (0 < out->opts->dump_opts.array_size) {
|
408
|
-
|
409
|
-
out->cur += out->opts->dump_opts.array_size;
|
405
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
410
406
|
}
|
411
407
|
if (0 < out->opts->dump_opts.indent_size) {
|
412
408
|
int i;
|
413
409
|
for (i = d2; 0 < i; i--) {
|
414
|
-
|
415
|
-
out->cur += out->opts->dump_opts.indent_size;
|
410
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
416
411
|
}
|
417
412
|
}
|
418
413
|
} else {
|
@@ -429,15 +424,13 @@ static void dump_row(VALUE row, StrLen cols, int ccnt, int depth, Out out) {
|
|
429
424
|
assure_size(out, size);
|
430
425
|
if (out->opts->dump_opts.use) {
|
431
426
|
if (0 < out->opts->dump_opts.array_size) {
|
432
|
-
|
433
|
-
out->cur += out->opts->dump_opts.array_size;
|
427
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
434
428
|
}
|
435
429
|
if (0 < out->opts->dump_opts.indent_size) {
|
436
430
|
int i;
|
437
431
|
|
438
432
|
for (i = depth; 0 < i; i--) {
|
439
|
-
|
440
|
-
out->cur += out->opts->dump_opts.indent_size;
|
433
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
441
434
|
}
|
442
435
|
}
|
443
436
|
} else {
|
@@ -477,14 +470,12 @@ static void dump_activerecord_result(VALUE obj, int depth, Out out, bool as_ok)
|
|
477
470
|
assure_size(out, size);
|
478
471
|
if (out->opts->dump_opts.use) {
|
479
472
|
if (0 < out->opts->dump_opts.array_size) {
|
480
|
-
|
481
|
-
out->cur += out->opts->dump_opts.array_size;
|
473
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
482
474
|
}
|
483
475
|
if (0 < out->opts->dump_opts.indent_size) {
|
484
476
|
int i;
|
485
477
|
for (i = d2; 0 < i; i--) {
|
486
|
-
|
487
|
-
out->cur += out->opts->dump_opts.indent_size;
|
478
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
488
479
|
}
|
489
480
|
}
|
490
481
|
} else {
|
@@ -500,15 +491,13 @@ static void dump_activerecord_result(VALUE obj, int depth, Out out, bool as_ok)
|
|
500
491
|
assure_size(out, size);
|
501
492
|
if (out->opts->dump_opts.use) {
|
502
493
|
if (0 < out->opts->dump_opts.array_size) {
|
503
|
-
|
504
|
-
out->cur += out->opts->dump_opts.array_size;
|
494
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
505
495
|
}
|
506
496
|
if (0 < out->opts->dump_opts.indent_size) {
|
507
497
|
int i;
|
508
498
|
|
509
499
|
for (i = depth; 0 < i; i--) {
|
510
|
-
|
511
|
-
out->cur += out->opts->dump_opts.indent_size;
|
500
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
512
501
|
}
|
513
502
|
}
|
514
503
|
} else {
|
@@ -908,7 +897,6 @@ static VALUE protect_dump(VALUE ov) {
|
|
908
897
|
}
|
909
898
|
|
910
899
|
static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *argv) {
|
911
|
-
char buf[4096];
|
912
900
|
struct _out out;
|
913
901
|
struct _options copts = *opts;
|
914
902
|
volatile VALUE rstr = Qnil;
|
@@ -925,9 +913,9 @@ static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *a
|
|
925
913
|
} else {
|
926
914
|
copts.escape_mode = RailsEsc;
|
927
915
|
}
|
928
|
-
|
929
|
-
out
|
930
|
-
|
916
|
+
|
917
|
+
oj_out_init(&out);
|
918
|
+
|
931
919
|
out.omit_nil = copts.dump_opts.omit_nil;
|
932
920
|
out.caller = 0;
|
933
921
|
out.cur = out.buf;
|
@@ -963,9 +951,9 @@ static VALUE encode(VALUE obj, ROptTable ropts, Options opts, int argc, VALUE *a
|
|
963
951
|
if (Yes == copts.circular) {
|
964
952
|
oj_cache8_delete(out.circ_cache);
|
965
953
|
}
|
966
|
-
|
967
|
-
|
968
|
-
|
954
|
+
|
955
|
+
oj_out_free(&out);
|
956
|
+
|
969
957
|
if (0 != line) {
|
970
958
|
rb_jump_tag(line);
|
971
959
|
}
|
@@ -1175,12 +1163,15 @@ oj_optimize_rails(VALUE self) {
|
|
1175
1163
|
*
|
1176
1164
|
* The Oj ActiveSupport compliant encoder.
|
1177
1165
|
*/
|
1178
|
-
void oj_mimic_rails_init() {
|
1166
|
+
void oj_mimic_rails_init(void) {
|
1179
1167
|
VALUE rails = rb_define_module_under(Oj, "Rails");
|
1180
1168
|
|
1181
1169
|
rb_define_module_function(rails, "encode", rails_encode, -1);
|
1182
1170
|
|
1183
1171
|
encoder_class = rb_define_class_under(rails, "Encoder", rb_cObject);
|
1172
|
+
rb_gc_register_address(&encoder_class);
|
1173
|
+
rb_undef_alloc_func(encoder_class);
|
1174
|
+
|
1184
1175
|
rb_define_module_function(encoder_class, "new", encoder_new, -1);
|
1185
1176
|
rb_define_module_function(rails, "optimize", rails_optimize, -1);
|
1186
1177
|
rb_define_module_function(rails, "deoptimize", rails_deoptimize, -1);
|
@@ -1263,19 +1254,17 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
1263
1254
|
} else {
|
1264
1255
|
size = d2 * out->indent + 2;
|
1265
1256
|
}
|
1257
|
+
assure_size(out, size * cnt);
|
1266
1258
|
cnt--;
|
1267
1259
|
for (i = 0; i <= cnt; i++) {
|
1268
|
-
assure_size(out, size);
|
1269
1260
|
if (out->opts->dump_opts.use) {
|
1270
1261
|
if (0 < out->opts->dump_opts.array_size) {
|
1271
|
-
|
1272
|
-
out->cur += out->opts->dump_opts.array_size;
|
1262
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
1273
1263
|
}
|
1274
1264
|
if (0 < out->opts->dump_opts.indent_size) {
|
1275
1265
|
int i;
|
1276
1266
|
for (i = d2; 0 < i; i--) {
|
1277
|
-
|
1278
|
-
out->cur += out->opts->dump_opts.indent_size;
|
1267
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
1279
1268
|
}
|
1280
1269
|
}
|
1281
1270
|
} else {
|
@@ -1290,15 +1279,13 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
1290
1279
|
assure_size(out, size);
|
1291
1280
|
if (out->opts->dump_opts.use) {
|
1292
1281
|
if (0 < out->opts->dump_opts.array_size) {
|
1293
|
-
|
1294
|
-
out->cur += out->opts->dump_opts.array_size;
|
1282
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.array_nl, out->opts->dump_opts.array_size);
|
1295
1283
|
}
|
1296
1284
|
if (0 < out->opts->dump_opts.indent_size) {
|
1297
1285
|
int i;
|
1298
1286
|
|
1299
1287
|
for (i = depth; 0 < i; i--) {
|
1300
|
-
|
1301
|
-
out->cur += out->opts->dump_opts.indent_size;
|
1288
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
1302
1289
|
}
|
1303
1290
|
}
|
1304
1291
|
} else {
|
@@ -1336,14 +1323,12 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
1336
1323
|
size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
|
1337
1324
|
assure_size(out, size);
|
1338
1325
|
if (0 < out->opts->dump_opts.hash_size) {
|
1339
|
-
|
1340
|
-
out->cur += out->opts->dump_opts.hash_size;
|
1326
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
|
1341
1327
|
}
|
1342
1328
|
if (0 < out->opts->dump_opts.indent_size) {
|
1343
1329
|
int i;
|
1344
1330
|
for (i = depth; 0 < i; i--) {
|
1345
|
-
|
1346
|
-
out->cur += out->opts->dump_opts.indent_size;
|
1331
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
1347
1332
|
}
|
1348
1333
|
}
|
1349
1334
|
if (rtype == T_STRING) {
|
@@ -1354,13 +1339,11 @@ static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
1354
1339
|
size = out->opts->dump_opts.before_size + out->opts->dump_opts.after_size + 2;
|
1355
1340
|
assure_size(out, size);
|
1356
1341
|
if (0 < out->opts->dump_opts.before_size) {
|
1357
|
-
|
1358
|
-
out->cur += out->opts->dump_opts.before_size;
|
1342
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.before_sep, out->opts->dump_opts.before_size);
|
1359
1343
|
}
|
1360
1344
|
*out->cur++ = ':';
|
1361
1345
|
if (0 < out->opts->dump_opts.after_size) {
|
1362
|
-
|
1363
|
-
out->cur += out->opts->dump_opts.after_size;
|
1346
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.after_sep, out->opts->dump_opts.after_size);
|
1364
1347
|
}
|
1365
1348
|
}
|
1366
1349
|
dump_rails_val(value, depth, out, true);
|
@@ -1403,15 +1386,13 @@ static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1403
1386
|
size = depth * out->opts->dump_opts.indent_size + out->opts->dump_opts.hash_size + 1;
|
1404
1387
|
assure_size(out, size);
|
1405
1388
|
if (0 < out->opts->dump_opts.hash_size) {
|
1406
|
-
|
1407
|
-
out->cur += out->opts->dump_opts.hash_size;
|
1389
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.hash_nl, out->opts->dump_opts.hash_size);
|
1408
1390
|
}
|
1409
1391
|
if (0 < out->opts->dump_opts.indent_size) {
|
1410
1392
|
int i;
|
1411
1393
|
|
1412
1394
|
for (i = depth; 0 < i; i--) {
|
1413
|
-
|
1414
|
-
out->cur += out->opts->dump_opts.indent_size;
|
1395
|
+
APPEND_CHARS(out->cur, out->opts->dump_opts.indent_str, out->opts->dump_opts.indent_size);
|
1415
1396
|
}
|
1416
1397
|
}
|
1417
1398
|
}
|
data/ext/oj/rails.h
CHANGED
data/ext/oj/reader.c
CHANGED
data/ext/oj/saj.c
CHANGED
@@ -210,10 +210,7 @@ static void read_hash(ParseInfo pi, const char *key) {
|
|
210
210
|
pi->s++;
|
211
211
|
} else {
|
212
212
|
if (pi->has_error) {
|
213
|
-
call_error("invalid format, expected , or } while in an object",
|
214
|
-
pi,
|
215
|
-
__FILE__,
|
216
|
-
__LINE__);
|
213
|
+
call_error("invalid format, expected , or } while in an object", pi, __FILE__, __LINE__);
|
217
214
|
}
|
218
215
|
raise_error("invalid format, expected , or } while in an object", pi->str, pi->s);
|
219
216
|
}
|
@@ -243,10 +240,7 @@ static void read_array(ParseInfo pi, const char *key) {
|
|
243
240
|
break;
|
244
241
|
} else {
|
245
242
|
if (pi->has_error) {
|
246
|
-
call_error("invalid format, expected , or ] while in an array",
|
247
|
-
pi,
|
248
|
-
__FILE__,
|
249
|
-
__LINE__);
|
243
|
+
call_error("invalid format, expected , or ] while in an array", pi, __FILE__, __LINE__);
|
250
244
|
}
|
251
245
|
raise_error("invalid format, expected , or ] while in an array", pi->str, pi->s);
|
252
246
|
}
|
@@ -276,7 +270,7 @@ static void read_str(ParseInfo pi, const char *key) {
|
|
276
270
|
#endif
|
277
271
|
|
278
272
|
static void read_num(ParseInfo pi, const char *key) {
|
279
|
-
char
|
273
|
+
char *start = pi->s;
|
280
274
|
int64_t n = 0;
|
281
275
|
long a = 0;
|
282
276
|
long div = 1;
|
@@ -351,9 +345,7 @@ static void read_num(ParseInfo pi, const char *key) {
|
|
351
345
|
|
352
346
|
*pi->s = '\0';
|
353
347
|
if (pi->has_add_value) {
|
354
|
-
call_add_value(pi->handler,
|
355
|
-
rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)),
|
356
|
-
key);
|
348
|
+
call_add_value(pi->handler, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)), key);
|
357
349
|
}
|
358
350
|
*pi->s = c;
|
359
351
|
} else {
|
@@ -371,9 +363,7 @@ static void read_num(ParseInfo pi, const char *key) {
|
|
371
363
|
|
372
364
|
*pi->s = '\0';
|
373
365
|
if (pi->has_add_value) {
|
374
|
-
call_add_value(pi->handler,
|
375
|
-
rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)),
|
376
|
-
key);
|
366
|
+
call_add_value(pi->handler, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(start)), key);
|
377
367
|
}
|
378
368
|
*pi->s = c;
|
379
369
|
} else {
|
@@ -505,9 +495,9 @@ static char *unicode_to_chars(ParseInfo pi, char *t, uint32_t code) {
|
|
505
495
|
* reached again. Do not read the character after the terminating quote.
|
506
496
|
*/
|
507
497
|
static char *read_quoted_value(ParseInfo pi) {
|
508
|
-
char
|
509
|
-
char
|
510
|
-
char
|
498
|
+
char *value = 0;
|
499
|
+
char *h = pi->s; /* head */
|
500
|
+
char *t = h; /* tail */
|
511
501
|
uint32_t code;
|
512
502
|
|
513
503
|
h++; /* skip quote character */
|
@@ -588,15 +578,13 @@ static void saj_parse(VALUE handler, char *json) {
|
|
588
578
|
pi.str = json;
|
589
579
|
pi.s = json;
|
590
580
|
#if IS_WINDOWS
|
591
|
-
pi.stack_min = (void *)((char *)&obj -
|
592
|
-
(512 * 1024)); /* assume a 1M stack and give half to ruby */
|
581
|
+
pi.stack_min = (void *)((char *)&obj - (512L * 1024L)); /* assume a 1M stack and give half to ruby */
|
593
582
|
#else
|
594
583
|
{
|
595
584
|
struct rlimit lim;
|
596
585
|
|
597
586
|
if (0 == getrlimit(RLIMIT_STACK, &lim) && RLIM_INFINITY != lim.rlim_cur) {
|
598
|
-
pi.stack_min = (void *)((char *)&obj - (lim.rlim_cur / 4 *
|
599
|
-
3)); /* let 3/4ths of the stack be used only */
|
587
|
+
pi.stack_min = (void *)((char *)&obj - (lim.rlim_cur / 4 * 3)); /* let 3/4ths of the stack be used only */
|
600
588
|
} else {
|
601
589
|
pi.stack_min = 0; /* indicates not to check stack limit */
|
602
590
|
}
|
@@ -633,7 +621,7 @@ static void saj_parse(VALUE handler, char *json) {
|
|
633
621
|
*/
|
634
622
|
VALUE
|
635
623
|
oj_saj_parse(int argc, VALUE *argv, VALUE self) {
|
636
|
-
char
|
624
|
+
char *json = 0;
|
637
625
|
size_t len = 0;
|
638
626
|
VALUE input = argv[1];
|
639
627
|
|
data/ext/oj/stream_writer.c
CHANGED
@@ -315,8 +315,10 @@ static VALUE stream_writer_flush(VALUE self) {
|
|
315
315
|
* will create that element in the JSON document and subsequent pushes will add
|
316
316
|
* the elements to that array or object until a pop() is called.
|
317
317
|
*/
|
318
|
-
void oj_stream_writer_init() {
|
318
|
+
void oj_stream_writer_init(void) {
|
319
319
|
oj_stream_writer_class = rb_define_class_under(Oj, "StreamWriter", rb_cObject);
|
320
|
+
rb_gc_register_address(&oj_stream_writer_class);
|
321
|
+
rb_undef_alloc_func(oj_stream_writer_class);
|
320
322
|
rb_define_module_function(oj_stream_writer_class, "new", stream_writer_new, -1);
|
321
323
|
rb_define_method(oj_stream_writer_class, "push_key", stream_writer_push_key, 1);
|
322
324
|
rb_define_method(oj_stream_writer_class, "push_object", stream_writer_push_object, -1);
|
data/ext/oj/string_writer.c
CHANGED
@@ -53,10 +53,13 @@ void oj_str_writer_init(StrWriter sw, int buf_size) {
|
|
53
53
|
} else if (buf_size < 1024) {
|
54
54
|
buf_size = 1024;
|
55
55
|
}
|
56
|
+
// Must be allocated. Using the out.stack_buffer results in double frees
|
57
|
+
// and I haven't figured out why yet.
|
56
58
|
sw->out.buf = ALLOC_N(char, buf_size);
|
57
|
-
sw->out.end = sw->out.buf + buf_size - 10;
|
58
|
-
sw->out.allocated = true;
|
59
59
|
sw->out.cur = sw->out.buf;
|
60
|
+
sw->out.end = sw->out.buf + buf_size - BUFFER_EXTRA;
|
61
|
+
sw->out.allocated = true;
|
62
|
+
|
60
63
|
*sw->out.cur = '\0';
|
61
64
|
sw->out.circ_cache = NULL;
|
62
65
|
sw->out.circ_cnt = 0;
|
@@ -229,7 +232,9 @@ static void str_writer_free(void *ptr) {
|
|
229
232
|
return;
|
230
233
|
}
|
231
234
|
sw = (StrWriter)ptr;
|
232
|
-
|
235
|
+
|
236
|
+
oj_out_free(&sw->out);
|
237
|
+
|
233
238
|
xfree(sw->types);
|
234
239
|
xfree(ptr);
|
235
240
|
}
|
@@ -449,7 +454,7 @@ static VALUE str_writer_to_s(VALUE self) {
|
|
449
454
|
* Returns the contents of the writer as a JSON element. If called from inside
|
450
455
|
* an array or hash by Oj the raw buffer will be used othersize a more
|
451
456
|
* inefficient parse of the contents and a return of the result is
|
452
|
-
* completed. The parse uses the
|
457
|
+
* completed. The parse uses the strict mode.
|
453
458
|
*
|
454
459
|
* *return* [_Hash_|_Array_|_String_|_Integer_|_Float_|_True_|_False_|_nil|)
|
455
460
|
*/
|
@@ -469,8 +474,10 @@ static VALUE str_writer_as_json(VALUE self) {
|
|
469
474
|
* calling to_s() will return the JSON document. Note that calling to_s() before
|
470
475
|
* construction is complete will return the document in it's current state.
|
471
476
|
*/
|
472
|
-
void oj_string_writer_init() {
|
477
|
+
void oj_string_writer_init(void) {
|
473
478
|
oj_string_writer_class = rb_define_class_under(Oj, "StringWriter", rb_cObject);
|
479
|
+
rb_gc_register_address(&oj_string_writer_class);
|
480
|
+
rb_undef_alloc_func(oj_string_writer_class);
|
474
481
|
rb_define_module_function(oj_string_writer_class, "new", str_writer_new, -1);
|
475
482
|
rb_define_method(oj_string_writer_class, "push_key", str_writer_push_key, 1);
|
476
483
|
rb_define_method(oj_string_writer_class, "push_object", str_writer_push_object, -1);
|
data/ext/oj/wab.c
CHANGED
@@ -35,7 +35,7 @@ static VALUE uri_http_clas = Qundef;
|
|
35
35
|
|
36
36
|
///// dump functions /////
|
37
37
|
|
38
|
-
static VALUE resolve_wab_uuid_class() {
|
38
|
+
static VALUE resolve_wab_uuid_class(void) {
|
39
39
|
if (Qundef == wab_uuid_clas) {
|
40
40
|
volatile VALUE wab_module;
|
41
41
|
|
@@ -50,7 +50,7 @@ static VALUE resolve_wab_uuid_class() {
|
|
50
50
|
return wab_uuid_clas;
|
51
51
|
}
|
52
52
|
|
53
|
-
static VALUE resolve_uri_class() {
|
53
|
+
static VALUE resolve_uri_class(void) {
|
54
54
|
if (Qundef == uri_clas) {
|
55
55
|
uri_clas = Qnil;
|
56
56
|
if (rb_const_defined_at(rb_cObject, rb_intern("URI"))) {
|
@@ -60,7 +60,7 @@ static VALUE resolve_uri_class() {
|
|
60
60
|
return uri_clas;
|
61
61
|
}
|
62
62
|
|
63
|
-
static VALUE resolve_uri_http_class() {
|
63
|
+
static VALUE resolve_uri_http_class(void) {
|
64
64
|
if (Qundef == uri_http_clas) {
|
65
65
|
volatile VALUE uri_module;
|
66
66
|
|
@@ -124,9 +124,9 @@ static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
|
124
124
|
*out->cur++ = ']';
|
125
125
|
} else {
|
126
126
|
size = d2 * out->indent + 2;
|
127
|
+
assure_size(out, size * cnt);
|
127
128
|
cnt--;
|
128
129
|
for (i = 0; i <= cnt; i++) {
|
129
|
-
assure_size(out, size);
|
130
130
|
fill_indent(out, d2);
|
131
131
|
oj_dump_wab_val(RARRAY_AREF(a, i), d2, out);
|
132
132
|
if (i < cnt) {
|
@@ -201,12 +201,12 @@ static void dump_time(VALUE obj, Out out) {
|
|
201
201
|
sec = ts.tv_sec;
|
202
202
|
nsec = ts.tv_nsec;
|
203
203
|
} else {
|
204
|
-
sec =
|
205
|
-
nsec =
|
204
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
205
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
206
206
|
}
|
207
207
|
#else
|
208
|
-
sec =
|
209
|
-
nsec =
|
208
|
+
sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
209
|
+
nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
210
210
|
#endif
|
211
211
|
|
212
212
|
assure_size(out, 36);
|
data/lib/oj/version.rb
CHANGED
data/test/bar.rb
CHANGED
@@ -6,11 +6,4 @@ $: << File.join(File.dirname(__FILE__), "../ext")
|
|
6
6
|
|
7
7
|
require 'oj'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
p = Oj::Parser.new(:usual)
|
12
|
-
p.cache_keys = false
|
13
|
-
p.symbol_keys = true
|
14
|
-
x = p.parse(json)
|
15
|
-
|
16
|
-
pp x
|
9
|
+
Oj.load(%|{"time":"2021-08-16 12:12:15","a":"5","b":"5"|)
|
data/test/foo.rb
CHANGED
@@ -4,32 +4,74 @@ $: << '.'
|
|
4
4
|
$: << File.join(File.dirname(__FILE__), "../lib")
|
5
5
|
$: << File.join(File.dirname(__FILE__), "../ext")
|
6
6
|
|
7
|
-
require
|
8
|
-
require
|
7
|
+
require "oj"
|
8
|
+
require "socket"
|
9
|
+
require 'io/nonblock'
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
#pid = spawn("nc -d 0.1 -l 5000", out: "/dev/null")
|
12
|
+
pid = spawn("nc -i 1 -l 7777", out: "/dev/null")
|
13
|
+
at_exit { Process.kill 9, pid }
|
14
|
+
sleep 0.2
|
15
|
+
s = Socket.tcp("localhost", 7777)
|
16
|
+
s.nonblock = false
|
17
|
+
1_000_000.times do |x|
|
18
|
+
Oj.to_stream(s, { x: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]})
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
Oj.
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
21
|
+
=begin
|
22
|
+
IO.pipe do |r, w|
|
23
|
+
if fork
|
24
|
+
r.close
|
25
|
+
#w.nonblock = false
|
26
|
+
1_000_000.times do |i|
|
27
|
+
begin
|
28
|
+
Oj.to_stream(w, { x: i})
|
29
|
+
rescue IOError => e
|
30
|
+
puts "*** #{i} raised #{e.class}: #{e}"
|
31
|
+
IO.select(nil, [w])
|
32
|
+
retry
|
33
|
+
end
|
34
|
+
w.puts
|
35
|
+
end
|
36
|
+
else
|
37
|
+
w.close
|
38
|
+
sleep(0.1)
|
39
|
+
r.each_line { |b|
|
40
|
+
#print b
|
41
|
+
}
|
42
|
+
r.close
|
43
|
+
Process.exit(0)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
=end
|
32
47
|
|
33
|
-
|
34
|
-
|
35
|
-
|
48
|
+
=begin
|
49
|
+
IO.pipe do |r, w|
|
50
|
+
if fork
|
51
|
+
r.close
|
52
|
+
#w.nonblock = false
|
53
|
+
a = []
|
54
|
+
10_000.times do |i|
|
55
|
+
a << i
|
56
|
+
end
|
57
|
+
begin
|
58
|
+
Oj.to_stream(w, a, indent: 2)
|
59
|
+
rescue IOError => e
|
60
|
+
puts "*** raised #{e.class}: #{e}"
|
61
|
+
puts "*** fileno: #{w.fileno}"
|
62
|
+
puts "*** is an IO?: #{w.kind_of?(IO)}"
|
63
|
+
IO.select(nil, [w])
|
64
|
+
retry
|
65
|
+
end
|
66
|
+
w.puts
|
67
|
+
else
|
68
|
+
w.close
|
69
|
+
sleep(0.5)
|
70
|
+
r.each_line { |b|
|
71
|
+
#print b
|
72
|
+
}
|
73
|
+
r.close
|
74
|
+
Process.exit(0)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
=end
|
data/test/perf_dump.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
$: << '.'
|
5
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
6
|
+
$: << File.join(File.dirname(__FILE__), "../ext")
|
7
|
+
|
8
|
+
require 'optparse'
|
9
|
+
require 'oj'
|
10
|
+
|
11
|
+
$verbose = false
|
12
|
+
$indent = 2
|
13
|
+
$iter = 100_000
|
14
|
+
$size = 2
|
15
|
+
|
16
|
+
opts = OptionParser.new
|
17
|
+
opts.on("-v", "verbose") { $verbose = true }
|
18
|
+
opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
|
19
|
+
opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
|
20
|
+
opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
|
21
|
+
opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
|
22
|
+
files = opts.parse(ARGV)
|
23
|
+
|
24
|
+
$obj = {
|
25
|
+
'a' => 'Alpha', # string
|
26
|
+
'b' => true, # boolean
|
27
|
+
'c' => 12345, # number
|
28
|
+
'd' => [ true, [false, [-123456789, nil], 3.9676, ['Something else.', false], nil]], # mix it up array
|
29
|
+
'e' => { 'zero' => nil, 'one' => 1, 'two' => 2, 'three' => [3], 'four' => [0, 1, 2, 3, 4] }, # hash
|
30
|
+
'f' => nil, # nil
|
31
|
+
'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
|
32
|
+
'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
|
33
|
+
}
|
34
|
+
|
35
|
+
Oj.default_options = { :indent => $indent, :mode => :strict }
|
36
|
+
|
37
|
+
if 0 < $size
|
38
|
+
o = $obj
|
39
|
+
$obj = []
|
40
|
+
(4 * $size).times do
|
41
|
+
$obj << o
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
$json = Oj.dump($obj)
|
46
|
+
GC.start
|
47
|
+
start = Time.now
|
48
|
+
$iter.times { Oj.dump($obj) }
|
49
|
+
duration = Time.now - start
|
50
|
+
puts "Dumped #{$json.length} byte JSON #{$iter} times in %0.3f seconds or %0.3f iteration/sec." % [duration, $iter / duration]
|