oj 1.0.6 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of oj might be problematic. Click here for more details.
- data/README.md +8 -2
- data/ext/oj/dump.c +166 -26
- data/ext/oj/fast.c +153 -37
- data/ext/oj/load.c +49 -1
- data/ext/oj/oj.c +361 -49
- data/ext/oj/oj.h +20 -0
- data/lib/oj/version.rb +1 -1
- data/test/perf.rb +1 -0
- data/test/perf_fast.rb +19 -0
- data/test/perf_strict.rb +28 -14
- data/test/test_fast.rb +54 -0
- data/test/test_mimic.rb +164 -0
- data/test/tests.rb +54 -1
- metadata +3 -2
data/ext/oj/load.c
CHANGED
@@ -75,6 +75,7 @@ static VALUE read_false(ParseInfo pi);
|
|
75
75
|
static VALUE read_nil(ParseInfo pi);
|
76
76
|
static void next_non_white(ParseInfo pi);
|
77
77
|
static char* read_quoted_value(ParseInfo pi);
|
78
|
+
static void skip_comment(ParseInfo pi);
|
78
79
|
|
79
80
|
|
80
81
|
/* This XML parser is a single pass, destructive, callback parser. It is a
|
@@ -100,6 +101,9 @@ next_non_white(ParseInfo pi) {
|
|
100
101
|
case '\n':
|
101
102
|
case '\r':
|
102
103
|
break;
|
104
|
+
case '/':
|
105
|
+
skip_comment(pi);
|
106
|
+
break;
|
103
107
|
default:
|
104
108
|
return;
|
105
109
|
}
|
@@ -275,6 +279,36 @@ circ_array_get(CircArray ca, unsigned long id) {
|
|
275
279
|
return obj;
|
276
280
|
}
|
277
281
|
|
282
|
+
static void
|
283
|
+
skip_comment(ParseInfo pi) {
|
284
|
+
pi->s++; // skip first /
|
285
|
+
if ('*' == *pi->s) {
|
286
|
+
pi->s++;
|
287
|
+
for (; '\0' != *pi->s; pi->s++) {
|
288
|
+
if ('*' == *pi->s && '/' == *(pi->s + 1)) {
|
289
|
+
pi->s++;
|
290
|
+
return;
|
291
|
+
} else if ('\0' == *pi->s) {
|
292
|
+
raise_error("comment not terminated", pi->str, pi->s);
|
293
|
+
}
|
294
|
+
}
|
295
|
+
} else if ('/' == *pi->s) {
|
296
|
+
for (; 1; pi->s++) {
|
297
|
+
switch (*pi->s) {
|
298
|
+
case '\n':
|
299
|
+
case '\r':
|
300
|
+
case '\f':
|
301
|
+
case '\0':
|
302
|
+
return;
|
303
|
+
default:
|
304
|
+
break;
|
305
|
+
}
|
306
|
+
}
|
307
|
+
} else {
|
308
|
+
raise_error("invalid comment", pi->str, pi->s);
|
309
|
+
}
|
310
|
+
}
|
311
|
+
|
278
312
|
static VALUE
|
279
313
|
read_next(ParseInfo pi, int hint) {
|
280
314
|
VALUE obj;
|
@@ -307,7 +341,10 @@ read_next(ParseInfo pi, int hint) {
|
|
307
341
|
} else {
|
308
342
|
obj = read_num(pi);
|
309
343
|
}
|
310
|
-
|
344
|
+
break;
|
345
|
+
case 'I':
|
346
|
+
obj = read_num(pi);
|
347
|
+
break;
|
311
348
|
case 't':
|
312
349
|
obj = read_true(pi);
|
313
350
|
break;
|
@@ -641,6 +678,17 @@ read_num(ParseInfo pi) {
|
|
641
678
|
} else if ('+' == *pi->s) {
|
642
679
|
pi->s++;
|
643
680
|
}
|
681
|
+
if ('I' == *pi->s) {
|
682
|
+
if (0 != strncmp("Infinity", pi->s, 8)) {
|
683
|
+
raise_error("number or other value", pi->str, pi->s);
|
684
|
+
}
|
685
|
+
pi->s += 8;
|
686
|
+
if (neg) {
|
687
|
+
return rb_float_new(-INFINITY);
|
688
|
+
} else {
|
689
|
+
return rb_float_new(INFINITY);
|
690
|
+
}
|
691
|
+
}
|
644
692
|
for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
|
645
693
|
n = n * 10 + (*pi->s - '0');
|
646
694
|
if (NUM_MAX <= n) {
|
data/ext/oj/oj.c
CHANGED
@@ -33,9 +33,15 @@
|
|
33
33
|
#include <errno.h>
|
34
34
|
#include <stdio.h>
|
35
35
|
#include <string.h>
|
36
|
+
#include <sys/types.h>
|
37
|
+
#include <sys/uio.h>
|
38
|
+
#include <unistd.h>
|
36
39
|
|
37
40
|
#include "oj.h"
|
38
41
|
|
42
|
+
// maximum to allocate on the stack, arbitrary limit
|
43
|
+
#define SMALL_XML 65536
|
44
|
+
|
39
45
|
typedef struct _YesNoOpt {
|
40
46
|
VALUE sym;
|
41
47
|
char *attr;
|
@@ -47,6 +53,7 @@ VALUE Oj = Qnil;
|
|
47
53
|
|
48
54
|
ID oj_as_json_id;
|
49
55
|
ID oj_at_id;
|
56
|
+
ID oj_fileno_id;
|
50
57
|
ID oj_instance_variables_id;
|
51
58
|
ID oj_json_create_id;
|
52
59
|
ID oj_read_id;
|
@@ -57,6 +64,7 @@ ID oj_to_sym_id;
|
|
57
64
|
ID oj_tv_nsec_id;
|
58
65
|
ID oj_tv_sec_id;
|
59
66
|
ID oj_tv_usec_id;
|
67
|
+
ID oj_write_id;
|
60
68
|
|
61
69
|
VALUE oj_bag_class;
|
62
70
|
VALUE oj_date_class;
|
@@ -78,19 +86,33 @@ static VALUE object_sym;
|
|
78
86
|
static VALUE strict_sym;
|
79
87
|
static VALUE symbol_keys_sym;
|
80
88
|
|
89
|
+
static VALUE array_nl_sym;
|
90
|
+
static VALUE create_additions_sym;
|
91
|
+
static VALUE object_nl_sym;
|
92
|
+
static VALUE space_before_sym;
|
93
|
+
static VALUE space_sym;
|
94
|
+
static VALUE symbolize_names_sym;
|
95
|
+
|
96
|
+
static VALUE mimic = Qnil;
|
97
|
+
static VALUE keep = Qnil;
|
98
|
+
|
81
99
|
Cache oj_class_cache = 0;
|
82
100
|
Cache oj_attr_cache = 0;
|
83
101
|
|
84
102
|
struct _Options oj_default_options = {
|
85
|
-
{ '\0' }, // encoding
|
103
|
+
// { '\0' }, // encoding
|
104
|
+
"UTF-8", // encoding
|
86
105
|
0, // indent
|
87
106
|
No, // circular
|
88
107
|
Yes, // auto_define
|
89
108
|
No, // sym_key
|
90
109
|
No, // ascii_only
|
91
110
|
ObjectMode, // mode
|
111
|
+
0, // dump_opts
|
92
112
|
};
|
93
113
|
|
114
|
+
static VALUE define_mimic_json(VALUE self);
|
115
|
+
|
94
116
|
/* call-seq: default_options() => Hash
|
95
117
|
*
|
96
118
|
* Returns the default load and dump options as a Hash. The options are
|
@@ -257,42 +279,20 @@ parse_options(VALUE ropts, Options copts) {
|
|
257
279
|
}
|
258
280
|
|
259
281
|
static VALUE
|
260
|
-
|
261
|
-
VALUE obj;
|
262
|
-
struct _Options options = oj_default_options;
|
263
|
-
|
264
|
-
if (1 == argc) {
|
265
|
-
parse_options(*argv, &options);
|
266
|
-
}
|
267
|
-
obj = oj_parse(json, &options);
|
268
|
-
//free(json);
|
269
|
-
|
270
|
-
return obj;
|
271
|
-
}
|
272
|
-
|
273
|
-
/* call-seq: load(json, options) => Hash, Array, String, Fixnum, Float, true, false, or nil
|
274
|
-
*
|
275
|
-
* Parses a JSON document String into a Hash, Array, String, Fixnum, Float,
|
276
|
-
* true, false, or nil. Raises an exception if the JSON is malformed or the
|
277
|
-
* classes specified are not valid.
|
278
|
-
* @param [String] json JSON String
|
279
|
-
* @param [Hash] options load options (same as default_options)
|
280
|
-
*/
|
281
|
-
static VALUE
|
282
|
-
load_str(int argc, VALUE *argv, VALUE self) {
|
282
|
+
load_with_opts(VALUE input, Options copts) {
|
283
283
|
char *json;
|
284
284
|
size_t len;
|
285
|
-
VALUE
|
286
|
-
|
287
|
-
if (1 > argc) {
|
288
|
-
rb_raise(rb_eArgError, "Wrong number of arguments to load().\n");
|
289
|
-
}
|
290
|
-
input = *argv;
|
285
|
+
VALUE obj;
|
286
|
+
|
291
287
|
if (rb_type(input) == T_STRING) {
|
292
288
|
// the json string gets modified so make a copy of it
|
293
|
-
len = RSTRING_LEN(
|
294
|
-
|
295
|
-
|
289
|
+
len = RSTRING_LEN(input) + 1;
|
290
|
+
if (SMALL_XML < len) {
|
291
|
+
json = ALLOC_N(char, len);
|
292
|
+
} else {
|
293
|
+
json = ALLOCA_N(char, len);
|
294
|
+
}
|
295
|
+
strcpy(json, StringValuePtr(input));
|
296
296
|
} else {
|
297
297
|
VALUE clas = rb_obj_class(input);
|
298
298
|
VALUE s;
|
@@ -300,21 +300,66 @@ load_str(int argc, VALUE *argv, VALUE self) {
|
|
300
300
|
if (oj_stringio_class == clas) {
|
301
301
|
s = rb_funcall2(input, oj_string_id, 0, 0);
|
302
302
|
len = RSTRING_LEN(s) + 1;
|
303
|
-
|
303
|
+
if (SMALL_XML < len) {
|
304
|
+
json = ALLOC_N(char, len);
|
305
|
+
} else {
|
306
|
+
json = ALLOCA_N(char, len);
|
307
|
+
}
|
304
308
|
strcpy(json, StringValuePtr(s));
|
305
|
-
|
306
|
-
|
307
|
-
|
309
|
+
} else if (rb_respond_to(input, oj_fileno_id) && Qnil != (s = rb_funcall(input, oj_fileno_id, 0))) {
|
310
|
+
int fd = FIX2INT(s);
|
311
|
+
ssize_t cnt;
|
312
|
+
|
313
|
+
len = lseek(fd, 0, SEEK_END);
|
314
|
+
lseek(fd, 0, SEEK_SET);
|
315
|
+
if (SMALL_XML < len) {
|
316
|
+
json = ALLOC_N(char, len + 1);
|
317
|
+
} else {
|
318
|
+
json = ALLOCA_N(char, len + 1);
|
319
|
+
}
|
320
|
+
if (0 >= (cnt = read(fd, json, len)) || cnt != (ssize_t)len) {
|
321
|
+
rb_raise(rb_eIOError, "failed to read from IO Object.\n");
|
322
|
+
}
|
323
|
+
json[len] = '\0';
|
308
324
|
} else if (rb_respond_to(input, oj_read_id)) {
|
309
325
|
s = rb_funcall2(input, oj_read_id, 0, 0);
|
310
326
|
len = RSTRING_LEN(s) + 1;
|
311
|
-
|
327
|
+
if (SMALL_XML < len) {
|
328
|
+
json = ALLOC_N(char, len);
|
329
|
+
} else {
|
330
|
+
json = ALLOCA_N(char, len);
|
331
|
+
}
|
312
332
|
strcpy(json, StringValuePtr(s));
|
313
333
|
} else {
|
314
334
|
rb_raise(rb_eArgError, "load() expected a String or IO Object.\n");
|
315
335
|
}
|
316
336
|
}
|
317
|
-
|
337
|
+
obj = oj_parse(json, copts);
|
338
|
+
if (SMALL_XML < len) {
|
339
|
+
xfree(json);
|
340
|
+
}
|
341
|
+
return obj;
|
342
|
+
}
|
343
|
+
|
344
|
+
/* call-seq: load(json, options) => Hash, Array, String, Fixnum, Float, true, false, or nil
|
345
|
+
*
|
346
|
+
* Parses a JSON document String into a Hash, Array, String, Fixnum, Float,
|
347
|
+
* true, false, or nil. Raises an exception if the JSON is malformed or the
|
348
|
+
* classes specified are not valid.
|
349
|
+
* @param [String] json JSON String
|
350
|
+
* @param [Hash] options load options (same as default_options)
|
351
|
+
*/
|
352
|
+
static VALUE
|
353
|
+
load(int argc, VALUE *argv, VALUE self) {
|
354
|
+
struct _Options options = oj_default_options;
|
355
|
+
|
356
|
+
if (1 > argc) {
|
357
|
+
rb_raise(rb_eArgError, "Wrong number of arguments to load().\n");
|
358
|
+
}
|
359
|
+
if (2 <= argc) {
|
360
|
+
parse_options(argv[1], &options);
|
361
|
+
}
|
362
|
+
return load_with_opts(*argv, &options);
|
318
363
|
}
|
319
364
|
|
320
365
|
static VALUE
|
@@ -323,7 +368,9 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
323
368
|
char *json;
|
324
369
|
FILE *f;
|
325
370
|
unsigned long len;
|
326
|
-
|
371
|
+
VALUE obj;
|
372
|
+
struct _Options options = oj_default_options;
|
373
|
+
|
327
374
|
Check_Type(*argv, T_STRING);
|
328
375
|
path = StringValuePtr(*argv);
|
329
376
|
if (0 == (f = fopen(path, "r"))) {
|
@@ -331,9 +378,10 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
331
378
|
}
|
332
379
|
fseek(f, 0, SEEK_END);
|
333
380
|
len = ftell(f);
|
334
|
-
if (
|
335
|
-
|
336
|
-
|
381
|
+
if (SMALL_XML < len) {
|
382
|
+
json = ALLOC_N(char, len + 1);
|
383
|
+
} else {
|
384
|
+
json = ALLOCA_N(char, len + 1);
|
337
385
|
}
|
338
386
|
fseek(f, 0, SEEK_SET);
|
339
387
|
if (len != fread(json, 1, len, f)) {
|
@@ -342,8 +390,14 @@ load_file(int argc, VALUE *argv, VALUE self) {
|
|
342
390
|
}
|
343
391
|
fclose(f);
|
344
392
|
json[len] = '\0';
|
345
|
-
|
346
|
-
|
393
|
+
if (2 <= argc) {
|
394
|
+
parse_options(argv[1], &options);
|
395
|
+
}
|
396
|
+
obj = oj_parse(json, &options);
|
397
|
+
if (SMALL_XML < len) {
|
398
|
+
xfree(json);
|
399
|
+
}
|
400
|
+
return obj;
|
347
401
|
}
|
348
402
|
|
349
403
|
/* call-seq: dump(obj, options) => json-string
|
@@ -365,7 +419,7 @@ dump(int argc, VALUE *argv, VALUE self) {
|
|
365
419
|
rb_raise(rb_eNoMemError, "Not enough memory.\n");
|
366
420
|
}
|
367
421
|
rstr = rb_str_new2(json);
|
368
|
-
#ifdef
|
422
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
369
423
|
if ('\0' != *copts.encoding) {
|
370
424
|
rb_enc_associate(rstr, rb_enc_find(copts.encoding));
|
371
425
|
}
|
@@ -398,9 +452,264 @@ to_file(int argc, VALUE *argv, VALUE self) {
|
|
398
452
|
return Qnil;
|
399
453
|
}
|
400
454
|
|
401
|
-
|
402
|
-
|
455
|
+
// Mimic JSON section
|
456
|
+
|
457
|
+
static VALUE
|
458
|
+
mimic_dump(int argc, VALUE *argv, VALUE self) {
|
459
|
+
char *json;
|
460
|
+
struct _Options copts = oj_default_options;
|
461
|
+
VALUE rstr;
|
462
|
+
|
463
|
+
if (0 == (json = oj_write_obj_to_str(*argv, &copts))) {
|
464
|
+
rb_raise(rb_eNoMemError, "Not enough memory.\n");
|
465
|
+
}
|
466
|
+
rstr = rb_str_new2(json);
|
467
|
+
#ifdef ENCODING_INLINE_MAX
|
468
|
+
if ('\0' != *copts.encoding) {
|
469
|
+
rb_enc_associate(rstr, rb_enc_find(copts.encoding));
|
470
|
+
}
|
471
|
+
#endif
|
472
|
+
if (2 <= argc && Qnil != argv[1]) {
|
473
|
+
VALUE io = argv[1];
|
474
|
+
VALUE args[1];
|
475
|
+
|
476
|
+
*args = rstr;
|
477
|
+
rb_funcall2(io, oj_write_id, 1, args);
|
478
|
+
rstr = io;
|
479
|
+
}
|
480
|
+
xfree(json);
|
481
|
+
|
482
|
+
return rstr;
|
483
|
+
}
|
484
|
+
|
485
|
+
// This is the signature for the hash_foreach callback also.
|
486
|
+
static int
|
487
|
+
mimic_walk(VALUE key, VALUE obj, VALUE proc) {
|
488
|
+
VALUE args[1];
|
489
|
+
|
490
|
+
switch (rb_type(obj)) {
|
491
|
+
case T_HASH:
|
492
|
+
rb_hash_foreach(obj, mimic_walk, proc);
|
493
|
+
break;
|
494
|
+
case T_ARRAY:
|
495
|
+
{
|
496
|
+
VALUE *np = RARRAY_PTR(obj);
|
497
|
+
size_t cnt = RARRAY_LEN(obj);
|
498
|
+
|
499
|
+
for (; 0 < cnt; cnt--, np++) {
|
500
|
+
mimic_walk(Qnil, *np, proc);
|
501
|
+
}
|
502
|
+
break;
|
503
|
+
}
|
504
|
+
default:
|
505
|
+
break;
|
506
|
+
}
|
507
|
+
*args = obj;
|
508
|
+
if (Qnil == proc) {
|
509
|
+
rb_yield_values2(1, args);
|
510
|
+
} else {
|
511
|
+
rb_proc_call_with_block(proc, 1, args, Qnil);
|
512
|
+
}
|
513
|
+
return ST_CONTINUE;
|
514
|
+
}
|
515
|
+
|
516
|
+
static VALUE
|
517
|
+
mimic_load(int argc, VALUE *argv, VALUE self) {
|
518
|
+
VALUE obj = load(1, argv, self);
|
519
|
+
|
520
|
+
if (2 <= argc && Qnil != argv[1]) {
|
521
|
+
mimic_walk(Qnil, obj, argv[1]);
|
522
|
+
}
|
523
|
+
return obj;
|
524
|
+
}
|
525
|
+
|
526
|
+
static VALUE
|
527
|
+
mimic_dump_load(int argc, VALUE *argv, VALUE self) {
|
528
|
+
if (1 > argc) {
|
529
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)\n");
|
530
|
+
} else if (T_STRING == rb_type(*argv)) {
|
531
|
+
return mimic_load(argc, argv, self);
|
532
|
+
} else {
|
533
|
+
return mimic_dump(argc, argv, self);
|
534
|
+
}
|
535
|
+
}
|
403
536
|
|
537
|
+
static VALUE
|
538
|
+
mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
539
|
+
char *json;
|
540
|
+
VALUE rstr;
|
541
|
+
|
542
|
+
if (2 == argc && Qnil != argv[1]) {
|
543
|
+
struct _DumpOpts dump_opts;
|
544
|
+
VALUE ropts = argv[1];
|
545
|
+
VALUE v;
|
546
|
+
|
547
|
+
memset(&dump_opts, 0, sizeof(dump_opts)); // may not be needed
|
548
|
+
if (T_HASH != rb_type(ropts)) {
|
549
|
+
rb_raise(rb_eArgError, "options must be a hash.\n");
|
550
|
+
}
|
551
|
+
if (Qnil != (v = rb_hash_lookup(ropts, indent_sym))) {
|
552
|
+
rb_check_type(v, T_STRING);
|
553
|
+
if (0 == copts->dump_opts) {
|
554
|
+
copts->dump_opts = &dump_opts;
|
555
|
+
}
|
556
|
+
copts->dump_opts->indent = StringValuePtr(v);
|
557
|
+
copts->dump_opts->indent_size = (uint8_t)strlen(copts->dump_opts->indent);
|
558
|
+
}
|
559
|
+
if (Qnil != (v = rb_hash_lookup(ropts, space_sym))) {
|
560
|
+
rb_check_type(v, T_STRING);
|
561
|
+
if (0 == copts->dump_opts) {
|
562
|
+
copts->dump_opts = &dump_opts;
|
563
|
+
}
|
564
|
+
copts->dump_opts->after_sep = StringValuePtr(v);
|
565
|
+
copts->dump_opts->after_size = (uint8_t)strlen(copts->dump_opts->after_sep);
|
566
|
+
}
|
567
|
+
if (Qnil != (v = rb_hash_lookup(ropts, space_before_sym))) {
|
568
|
+
rb_check_type(v, T_STRING);
|
569
|
+
if (0 == copts->dump_opts) {
|
570
|
+
copts->dump_opts = &dump_opts;
|
571
|
+
}
|
572
|
+
copts->dump_opts->before_sep = StringValuePtr(v);
|
573
|
+
copts->dump_opts->before_size = (uint8_t)strlen(copts->dump_opts->before_sep);
|
574
|
+
}
|
575
|
+
if (Qnil != (v = rb_hash_lookup(ropts, object_nl_sym))) {
|
576
|
+
rb_check_type(v, T_STRING);
|
577
|
+
if (0 == copts->dump_opts) {
|
578
|
+
copts->dump_opts = &dump_opts;
|
579
|
+
}
|
580
|
+
copts->dump_opts->hash_nl = StringValuePtr(v);
|
581
|
+
copts->dump_opts->hash_size = (uint8_t)strlen(copts->dump_opts->hash_nl);
|
582
|
+
}
|
583
|
+
if (Qnil != (v = rb_hash_lookup(ropts, array_nl_sym))) {
|
584
|
+
rb_check_type(v, T_STRING);
|
585
|
+
if (0 == copts->dump_opts) {
|
586
|
+
copts->dump_opts = &dump_opts;
|
587
|
+
}
|
588
|
+
copts->dump_opts->array_nl = StringValuePtr(v);
|
589
|
+
copts->dump_opts->array_size = (uint8_t)strlen(copts->dump_opts->array_nl);
|
590
|
+
}
|
591
|
+
// :allow_nan is not supported as Oj always allows_nan
|
592
|
+
// :max_nesting is always set to 100
|
593
|
+
}
|
594
|
+
if (0 == (json = oj_write_obj_to_str(*argv, copts))) {
|
595
|
+
rb_raise(rb_eNoMemError, "Not enough memory.\n");
|
596
|
+
}
|
597
|
+
rstr = rb_str_new2(json);
|
598
|
+
#ifdef ENCODING_INLINE_MAX
|
599
|
+
if ('\0' != *copts->encoding) {
|
600
|
+
rb_enc_associate(rstr, rb_enc_find(copts->encoding));
|
601
|
+
}
|
602
|
+
#endif
|
603
|
+
xfree(json);
|
604
|
+
|
605
|
+
return rstr;
|
606
|
+
}
|
607
|
+
|
608
|
+
static VALUE
|
609
|
+
mimic_generate(int argc, VALUE *argv, VALUE self) {
|
610
|
+
struct _Options copts = oj_default_options;
|
611
|
+
|
612
|
+
return mimic_generate_core(argc, argv, &copts);
|
613
|
+
}
|
614
|
+
|
615
|
+
static VALUE
|
616
|
+
mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
617
|
+
struct _Options copts = oj_default_options;
|
618
|
+
struct _DumpOpts dump_opts;
|
619
|
+
|
620
|
+
dump_opts.indent = " ";
|
621
|
+
dump_opts.indent_size = (uint8_t)strlen(dump_opts.indent);
|
622
|
+
dump_opts.before_sep = " ";
|
623
|
+
dump_opts.before_size = (uint8_t)strlen(dump_opts.before_sep);
|
624
|
+
dump_opts.after_sep = " ";
|
625
|
+
dump_opts.after_size = (uint8_t)strlen(dump_opts.after_sep);
|
626
|
+
dump_opts.hash_nl = "\n";
|
627
|
+
dump_opts.hash_size = (uint8_t)strlen(dump_opts.hash_nl);
|
628
|
+
dump_opts.array_nl = "\n";
|
629
|
+
dump_opts.array_size = (uint8_t)strlen(dump_opts.array_nl);
|
630
|
+
copts.dump_opts = &dump_opts;
|
631
|
+
|
632
|
+
return mimic_generate_core(argc, argv, &copts);
|
633
|
+
}
|
634
|
+
|
635
|
+
static VALUE
|
636
|
+
mimic_parse(int argc, VALUE *argv, VALUE self) {
|
637
|
+
struct _Options options = oj_default_options;
|
638
|
+
|
639
|
+
if (1 > argc) {
|
640
|
+
rb_raise(rb_eArgError, "Wrong number of arguments to load().\n");
|
641
|
+
}
|
642
|
+
if (2 <= argc && Qnil != argv[1]) {
|
643
|
+
VALUE ropts = argv[1];
|
644
|
+
VALUE v;
|
645
|
+
|
646
|
+
if (T_HASH != rb_type(ropts)) {
|
647
|
+
rb_raise(rb_eArgError, "options must be a hash.\n");
|
648
|
+
}
|
649
|
+
if (Qnil != (v = rb_hash_lookup(ropts, symbolize_names_sym))) {
|
650
|
+
options.sym_key = (Qtrue == v) ? Yes : No;
|
651
|
+
}
|
652
|
+
if (Qnil != (v = rb_hash_lookup(ropts, create_additions_sym))) {
|
653
|
+
options.mode = (Qtrue == v) ? CompatMode : StrictMode;
|
654
|
+
}
|
655
|
+
// :allow_nan is not supported as Oj always allows_nan
|
656
|
+
// :max_nesting is always set to 100
|
657
|
+
// :object_class is always Hash
|
658
|
+
// :array_class is always Array
|
659
|
+
}
|
660
|
+
return load_with_opts(*argv, &options);
|
661
|
+
}
|
662
|
+
|
663
|
+
static VALUE
|
664
|
+
mimic_recurse_proc(VALUE self, VALUE obj) {
|
665
|
+
rb_need_block();
|
666
|
+
mimic_walk(Qnil, obj, Qnil);
|
667
|
+
|
668
|
+
return Qnil;
|
669
|
+
}
|
670
|
+
|
671
|
+
static VALUE
|
672
|
+
no_op1(VALUE self, VALUE obj) {
|
673
|
+
return Qnil;
|
674
|
+
}
|
675
|
+
|
676
|
+
static VALUE
|
677
|
+
define_mimic_json(VALUE self) {
|
678
|
+
if (Qnil == mimic) {
|
679
|
+
VALUE ext;
|
680
|
+
|
681
|
+
mimic = rb_define_module("JSON");
|
682
|
+
ext = rb_define_module_under(mimic, "Ext");
|
683
|
+
rb_define_class_under(ext, "Parser", rb_cObject);
|
684
|
+
rb_define_class_under(ext, "Generator", rb_cObject);
|
685
|
+
|
686
|
+
rb_define_module_function(mimic, "parser=", no_op1, 1);
|
687
|
+
rb_define_module_function(mimic, "generator=", no_op1, 1);
|
688
|
+
|
689
|
+
rb_define_module_function(mimic, "dump", mimic_dump, -1);
|
690
|
+
rb_define_module_function(mimic, "load", mimic_load, -1);
|
691
|
+
rb_define_module_function(mimic, "restore", mimic_load, -1);
|
692
|
+
rb_define_module_function(mimic, "recurse_proc", mimic_recurse_proc, 1);
|
693
|
+
rb_define_module_function(mimic, "[]", mimic_dump_load, -1);
|
694
|
+
rb_define_module_function(mimic, "generate", mimic_generate, -1);
|
695
|
+
rb_define_module_function(mimic, "fast_generate", mimic_generate, -1);
|
696
|
+
rb_define_module_function(mimic, "pretty_generate", mimic_pretty_generate, -1);
|
697
|
+
rb_define_module_function(mimic, "parse", mimic_parse, -1);
|
698
|
+
rb_define_module_function(mimic, "parse!", mimic_parse, -1);
|
699
|
+
|
700
|
+
array_nl_sym = ID2SYM(rb_intern("array_nl")); rb_ary_push(keep, array_nl_sym);
|
701
|
+
create_additions_sym = ID2SYM(rb_intern("create_additions")); rb_ary_push(keep, create_additions_sym);
|
702
|
+
object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_ary_push(keep, object_nl_sym);
|
703
|
+
space_before_sym = ID2SYM(rb_intern("space_before")); rb_ary_push(keep, space_before_sym);
|
704
|
+
space_sym = ID2SYM(rb_intern("space")); rb_ary_push(keep, space_sym);
|
705
|
+
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names")); rb_ary_push(keep, symbolize_names_sym);
|
706
|
+
|
707
|
+
oj_default_options.mode = CompatMode;
|
708
|
+
}
|
709
|
+
return mimic;
|
710
|
+
}
|
711
|
+
|
712
|
+
void Init_oj() {
|
404
713
|
Oj = rb_define_module("Oj");
|
405
714
|
keep = rb_cv_get(Oj, "@@keep"); // needed to stop GC from deleting and reusing VALUEs
|
406
715
|
|
@@ -411,13 +720,15 @@ void Init_oj() {
|
|
411
720
|
rb_define_module_function(Oj, "default_options", get_def_opts, 0);
|
412
721
|
rb_define_module_function(Oj, "default_options=", set_def_opts, 1);
|
413
722
|
|
414
|
-
rb_define_module_function(Oj, "
|
723
|
+
rb_define_module_function(Oj, "mimic_JSON", define_mimic_json, 0);
|
724
|
+
rb_define_module_function(Oj, "load", load, -1);
|
415
725
|
rb_define_module_function(Oj, "load_file", load_file, -1);
|
416
726
|
rb_define_module_function(Oj, "dump", dump, -1);
|
417
727
|
rb_define_module_function(Oj, "to_file", to_file, -1);
|
418
728
|
|
419
729
|
oj_as_json_id = rb_intern("as_json");
|
420
730
|
oj_at_id = rb_intern("at");
|
731
|
+
oj_fileno_id = rb_intern("fileno");
|
421
732
|
oj_instance_variables_id = rb_intern("instance_variables");
|
422
733
|
oj_json_create_id = rb_intern("json_create");
|
423
734
|
oj_read_id = rb_intern("read");
|
@@ -428,6 +739,7 @@ void Init_oj() {
|
|
428
739
|
oj_tv_nsec_id = rb_intern("tv_nsec");
|
429
740
|
oj_tv_sec_id = rb_intern("tv_sec");
|
430
741
|
oj_tv_usec_id = rb_intern("tv_usec");
|
742
|
+
oj_write_id = rb_intern("write");
|
431
743
|
|
432
744
|
oj_bag_class = rb_const_get_at(Oj, rb_intern("Bag"));
|
433
745
|
oj_struct_class = rb_const_get(rb_cObject, rb_intern("Struct"));
|