oj 3.13.1 → 3.13.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1270 -0
- data/README.md +2 -2
- data/RELEASE_NOTES.md +55 -0
- data/ext/oj/cache.c +246 -107
- data/ext/oj/cache.h +2 -1
- data/ext/oj/compat.c +1 -2
- data/ext/oj/custom.c +5 -8
- data/ext/oj/debug.c +2 -1
- data/ext/oj/extconf.rb +1 -0
- data/ext/oj/fast.c +1 -1
- data/ext/oj/intern.c +106 -216
- data/ext/oj/intern.h +0 -1
- data/ext/oj/mimic_json.c +2 -2
- data/ext/oj/object.c +11 -40
- data/ext/oj/oj.c +11 -8
- data/ext/oj/parse.c +1 -1
- data/ext/oj/parser.c +99 -127
- data/ext/oj/rxclass.c +1 -1
- data/ext/oj/saj.c +1 -1
- data/ext/oj/saj2.c +7 -5
- data/ext/oj/sparse.c +1 -1
- data/ext/oj/stream_writer.c +1 -1
- data/ext/oj/strict.c +2 -3
- data/ext/oj/string_writer.c +2 -2
- data/ext/oj/usual.c +53 -23
- data/ext/oj/validate.c +2 -1
- data/ext/oj/wab.c +6 -3
- data/lib/oj/error.rb +1 -1
- data/lib/oj/state.rb +8 -7
- data/lib/oj/version.rb +1 -1
- data/pages/Options.md +13 -3
- data/pages/Parser.md +3 -3
- data/pages/Rails.md +2 -2
- data/test/foo.rb +8 -8
- data/test/json_gem/json_generator_test.rb +1 -1
- data/test/mem.rb +33 -0
- data/test/perf_once.rb +58 -0
- data/test/perf_parser.rb +6 -1
- data/test/test_hash.rb +1 -1
- metadata +8 -2
data/ext/oj/rxclass.c
CHANGED
@@ -110,7 +110,7 @@ oj_rxclass_match(RxClass rc, const char *str, int len) {
|
|
110
110
|
}
|
111
111
|
} else if (len < (int)sizeof(buf)) {
|
112
112
|
#if !IS_WINDOWS
|
113
|
-
// string is not \0 terminated so copy and
|
113
|
+
// string is not \0 terminated so copy and attempt a match
|
114
114
|
memcpy(buf, str, len);
|
115
115
|
buf[len] = '\0';
|
116
116
|
if (0 == regexec(&rxc->rx, buf, 0, NULL, 0)) { // match
|
data/ext/oj/saj.c
CHANGED
@@ -628,7 +628,7 @@ static void saj_parse(VALUE handler, char *json) {
|
|
628
628
|
* @param [IO|String] io IO Object to read from
|
629
629
|
* @deprecated The sc_parse() method along with the ScHandler is the preferred
|
630
630
|
* callback parser. It is slightly faster and handles streams while the
|
631
|
-
* saj_parse()
|
631
|
+
* saj_parse() method requires a complete read before parsing.
|
632
632
|
* @see sc_parse
|
633
633
|
*/
|
634
634
|
VALUE
|
data/ext/oj/saj2.c
CHANGED
@@ -158,7 +158,7 @@ static void add_str(ojParser p) {
|
|
158
158
|
const char * str = buf_str(&p->buf);
|
159
159
|
size_t len = buf_len(&p->buf);
|
160
160
|
|
161
|
-
if (d->cache_str
|
161
|
+
if (d->cache_str < len) {
|
162
162
|
rstr = cache_intern(d->str_cache, str, len);
|
163
163
|
} else {
|
164
164
|
rstr = rb_utf8_str_new(str, len);
|
@@ -172,7 +172,7 @@ static void add_str_key(ojParser p) {
|
|
172
172
|
const char * str = buf_str(&p->buf);
|
173
173
|
size_t len = buf_len(&p->buf);
|
174
174
|
|
175
|
-
if (d->cache_str
|
175
|
+
if (d->cache_str < len) {
|
176
176
|
rstr = cache_intern(d->str_cache, str, len);
|
177
177
|
} else {
|
178
178
|
rstr = rb_utf8_str_new(str, len);
|
@@ -182,8 +182,9 @@ static void add_str_key(ojParser p) {
|
|
182
182
|
|
183
183
|
static void reset(ojParser p) {
|
184
184
|
Funcs end = p->funcs + 3;
|
185
|
+
Funcs f;
|
185
186
|
|
186
|
-
for (
|
187
|
+
for (f = p->funcs; f < end; f++) {
|
187
188
|
f->add_null = noop;
|
188
189
|
f->add_true = noop;
|
189
190
|
f->add_false = noop;
|
@@ -312,13 +313,14 @@ static void mark(ojParser p) {
|
|
312
313
|
return;
|
313
314
|
}
|
314
315
|
Delegate d = (Delegate)p->ctx;
|
316
|
+
VALUE *kp;
|
315
317
|
|
316
318
|
cache_mark(d->str_cache);
|
317
319
|
if (Qnil != d->handler) {
|
318
320
|
rb_gc_mark(d->handler);
|
319
321
|
}
|
320
322
|
if (!d->cache_keys) {
|
321
|
-
for (
|
323
|
+
for (kp = d->keys; kp < d->tail; kp++) {
|
322
324
|
rb_gc_mark(*kp);
|
323
325
|
}
|
324
326
|
}
|
@@ -334,7 +336,7 @@ void oj_set_parser_saj(ojParser p) {
|
|
334
336
|
d->klen = 256;
|
335
337
|
d->keys = ALLOC_N(VALUE, d->klen);
|
336
338
|
d->tail = d->keys;
|
337
|
-
d->str_cache = cache_create(0, form_str, true);
|
339
|
+
d->str_cache = cache_create(0, form_str, true, false);
|
338
340
|
|
339
341
|
p->ctx = (void *)d;
|
340
342
|
reset(p);
|
data/ext/oj/sparse.c
CHANGED
@@ -494,7 +494,7 @@ static void read_num(ParseInfo pi) {
|
|
494
494
|
if ('.' == c) {
|
495
495
|
c = reader_get(&pi->rd);
|
496
496
|
// A trailing . is not a valid decimal but if encountered allow it
|
497
|
-
// except when
|
497
|
+
// except when mimicking the JSON gem.
|
498
498
|
if (CompatMode == pi->options.mode) {
|
499
499
|
if (c < '0' || '9' < c) {
|
500
500
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
|
data/ext/oj/stream_writer.c
CHANGED
@@ -67,7 +67,7 @@ static VALUE buffer_size_sym = Qundef;
|
|
67
67
|
* should be and also a hint on when to flush.
|
68
68
|
*
|
69
69
|
* - *io* [_IO_] stream to write to
|
70
|
-
* - *options* [_Hash_]
|
70
|
+
* - *options* [_Hash_] formatting options
|
71
71
|
*/
|
72
72
|
static VALUE stream_writer_new(int argc, VALUE *argv, VALUE self) {
|
73
73
|
StreamWriterType type = STREAM_IO;
|
data/ext/oj/strict.c
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
VALUE oj_cstr_to_value(const char *str, size_t len, size_t cache_str) {
|
17
17
|
volatile VALUE rstr = Qnil;
|
18
18
|
|
19
|
-
if (len
|
19
|
+
if (len < cache_str) {
|
20
20
|
rstr = oj_str_intern(str, len);
|
21
21
|
} else {
|
22
22
|
rstr = rb_str_new(str, len);
|
@@ -37,8 +37,8 @@ VALUE oj_calc_hash_key(ParseInfo pi, Val parent) {
|
|
37
37
|
} else {
|
38
38
|
rkey = rb_str_new(parent->key, parent->klen);
|
39
39
|
rkey = oj_encode(rkey);
|
40
|
+
OBJ_FREEZE(rkey); // frozen when used as a Hash key anyway
|
40
41
|
}
|
41
|
-
OBJ_FREEZE(rkey);
|
42
42
|
return rkey;
|
43
43
|
}
|
44
44
|
if (Yes == pi->options.sym_key) {
|
@@ -46,7 +46,6 @@ VALUE oj_calc_hash_key(ParseInfo pi, Val parent) {
|
|
46
46
|
} else {
|
47
47
|
rkey = oj_str_intern(parent->key, parent->klen);
|
48
48
|
}
|
49
|
-
OBJ_FREEZE(rkey);
|
50
49
|
return rkey;
|
51
50
|
}
|
52
51
|
|
data/ext/oj/string_writer.c
CHANGED
@@ -248,7 +248,7 @@ static void str_writer_free(void *ptr) {
|
|
248
248
|
* should be.
|
249
249
|
*
|
250
250
|
* - *io* [_IO_] stream to write to
|
251
|
-
* - *options* [_Hash_]
|
251
|
+
* - *options* [_Hash_] formatting options
|
252
252
|
*/
|
253
253
|
static VALUE str_writer_new(int argc, VALUE *argv, VALUE self) {
|
254
254
|
StrWriter sw = ALLOC(struct _strWriter);
|
@@ -466,7 +466,7 @@ static VALUE str_writer_as_json(VALUE self) {
|
|
466
466
|
* by pushing values into the document. Pushing an array or an object will
|
467
467
|
* create that element in the JSON document and subsequent pushes will add the
|
468
468
|
* elements to that array or object until a pop() is called. When complete
|
469
|
-
* calling to_s() will return the JSON document. Note
|
469
|
+
* calling to_s() will return the JSON document. Note that calling to_s() before
|
470
470
|
* construction is complete will return the document in it's current state.
|
471
471
|
*/
|
472
472
|
void oj_string_writer_init() {
|
data/ext/oj/usual.c
CHANGED
@@ -77,6 +77,7 @@ typedef struct _delegate {
|
|
77
77
|
char * create_id;
|
78
78
|
uint8_t create_id_len;
|
79
79
|
uint8_t cache_str;
|
80
|
+
uint8_t cache_xrate;
|
80
81
|
uint8_t miss_class;
|
81
82
|
bool cache_keys;
|
82
83
|
bool ignore_json_create;
|
@@ -100,7 +101,6 @@ static VALUE form_str(const char *str, size_t len) {
|
|
100
101
|
}
|
101
102
|
|
102
103
|
static VALUE form_sym(const char *str, size_t len) {
|
103
|
-
// return ID2SYM(rb_intern3(str, len, oj_utf8_encoding));
|
104
104
|
return rb_str_intern(rb_utf8_str_new(str, len));
|
105
105
|
}
|
106
106
|
|
@@ -323,6 +323,7 @@ static void open_array_key(ojParser p) {
|
|
323
323
|
}
|
324
324
|
|
325
325
|
static void close_object(ojParser p) {
|
326
|
+
VALUE * vp;
|
326
327
|
Delegate d = (Delegate)p->ctx;
|
327
328
|
|
328
329
|
d->ctail--;
|
@@ -333,7 +334,7 @@ static void close_object(ojParser p) {
|
|
333
334
|
volatile VALUE obj = rb_hash_new();
|
334
335
|
|
335
336
|
#if HAVE_RB_HASH_BULK_INSERT
|
336
|
-
for (
|
337
|
+
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
337
338
|
*vp = d->get_key(p, kp);
|
338
339
|
if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
|
339
340
|
xfree(kp->key);
|
@@ -341,7 +342,7 @@ static void close_object(ojParser p) {
|
|
341
342
|
}
|
342
343
|
rb_hash_bulk_insert(d->vtail - head, head, obj);
|
343
344
|
#else
|
344
|
-
for (
|
345
|
+
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
345
346
|
rb_hash_aset(obj, d->get_key(p, kp), *(vp + 1));
|
346
347
|
if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
|
347
348
|
xfree(kp->key);
|
@@ -355,6 +356,7 @@ static void close_object(ojParser p) {
|
|
355
356
|
}
|
356
357
|
|
357
358
|
static void close_object_class(ojParser p) {
|
359
|
+
VALUE * vp;
|
358
360
|
Delegate d = (Delegate)p->ctx;
|
359
361
|
|
360
362
|
d->ctail--;
|
@@ -364,7 +366,7 @@ static void close_object_class(ojParser p) {
|
|
364
366
|
VALUE * head = d->vhead + c->vi + 1;
|
365
367
|
volatile VALUE obj = rb_class_new_instance(0, NULL, d->hash_class);
|
366
368
|
|
367
|
-
for (
|
369
|
+
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
368
370
|
rb_funcall(obj, hset_id, 2, d->get_key(p, kp), *(vp + 1));
|
369
371
|
if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
|
370
372
|
xfree(kp->key);
|
@@ -377,6 +379,7 @@ static void close_object_class(ojParser p) {
|
|
377
379
|
}
|
378
380
|
|
379
381
|
static void close_object_create(ojParser p) {
|
382
|
+
VALUE * vp;
|
380
383
|
Delegate d = (Delegate)p->ctx;
|
381
384
|
|
382
385
|
d->ctail--;
|
@@ -391,7 +394,7 @@ static void close_object_create(ojParser p) {
|
|
391
394
|
if (Qnil == d->hash_class) {
|
392
395
|
obj = rb_hash_new();
|
393
396
|
#if HAVE_RB_HASH_BULK_INSERT
|
394
|
-
for (
|
397
|
+
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
395
398
|
*vp = d->get_key(p, kp);
|
396
399
|
if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
|
397
400
|
xfree(kp->key);
|
@@ -399,7 +402,7 @@ static void close_object_create(ojParser p) {
|
|
399
402
|
}
|
400
403
|
rb_hash_bulk_insert(d->vtail - head, head, obj);
|
401
404
|
#else
|
402
|
-
for (
|
405
|
+
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
403
406
|
rb_hash_aset(obj, d->get_key(p, kp), *(vp + 1));
|
404
407
|
if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
|
405
408
|
xfree(kp->key);
|
@@ -408,7 +411,7 @@ static void close_object_create(ojParser p) {
|
|
408
411
|
#endif
|
409
412
|
} else {
|
410
413
|
obj = rb_class_new_instance(0, NULL, d->hash_class);
|
411
|
-
for (
|
414
|
+
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
412
415
|
rb_funcall(obj, hset_id, 2, d->get_key(p, kp), *(vp + 1));
|
413
416
|
if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
|
414
417
|
xfree(kp->key);
|
@@ -423,7 +426,7 @@ static void close_object_create(ojParser p) {
|
|
423
426
|
volatile VALUE arg = rb_hash_new();
|
424
427
|
|
425
428
|
#if HAVE_RB_HASH_BULK_INSERT
|
426
|
-
for (
|
429
|
+
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
427
430
|
*vp = d->get_key(p, kp);
|
428
431
|
if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
|
429
432
|
xfree(kp->key);
|
@@ -431,7 +434,7 @@ static void close_object_create(ojParser p) {
|
|
431
434
|
}
|
432
435
|
rb_hash_bulk_insert(d->vtail - head, head, arg);
|
433
436
|
#else
|
434
|
-
for (
|
437
|
+
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
435
438
|
rb_hash_aset(arg, d->get_key(p, kp), *(vp + 1));
|
436
439
|
if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
|
437
440
|
xfree(kp->key);
|
@@ -441,7 +444,7 @@ static void close_object_create(ojParser p) {
|
|
441
444
|
obj = rb_funcall(clas, oj_json_create_id, 1, arg);
|
442
445
|
} else {
|
443
446
|
obj = rb_class_new_instance(0, NULL, clas);
|
444
|
-
for (
|
447
|
+
for (vp = head; kp < d->ktail; kp++, vp += 2) {
|
445
448
|
rb_ivar_set(obj, get_attr_id(p, kp), *(vp + 1));
|
446
449
|
if (sizeof(kp->buf) - 1 < (size_t)kp->len) {
|
447
450
|
xfree(kp->key);
|
@@ -468,13 +471,14 @@ static void close_array(ojParser p) {
|
|
468
471
|
}
|
469
472
|
|
470
473
|
static void close_array_class(ojParser p) {
|
474
|
+
VALUE * vp;
|
471
475
|
Delegate d = (Delegate)p->ctx;
|
472
476
|
|
473
477
|
d->ctail--;
|
474
478
|
VALUE * head = d->vhead + d->ctail->vi + 1;
|
475
479
|
volatile VALUE a = rb_class_new_instance(0, NULL, d->array_class);
|
476
480
|
|
477
|
-
for (
|
481
|
+
for (vp = head; vp < d->vtail; vp++) {
|
478
482
|
rb_funcall(a, ltlt_id, 1, *vp);
|
479
483
|
}
|
480
484
|
d->vtail = head;
|
@@ -682,9 +686,10 @@ static void mark(ojParser p) {
|
|
682
686
|
return;
|
683
687
|
}
|
684
688
|
Delegate d = (Delegate)p->ctx;
|
689
|
+
VALUE * vp;
|
685
690
|
|
686
691
|
if (NULL == d) {
|
687
|
-
|
692
|
+
return;
|
688
693
|
}
|
689
694
|
cache_mark(d->str_cache);
|
690
695
|
if (NULL != d->sym_cache) {
|
@@ -693,7 +698,7 @@ static void mark(ojParser p) {
|
|
693
698
|
if (NULL != d->class_cache) {
|
694
699
|
cache_mark(d->class_cache);
|
695
700
|
}
|
696
|
-
for (
|
701
|
+
for (vp = d->vhead; vp < d->vtail; vp++) {
|
697
702
|
if (Qundef != *vp) {
|
698
703
|
rb_gc_mark(*vp);
|
699
704
|
}
|
@@ -787,6 +792,30 @@ static VALUE opt_cache_strings_set(ojParser p, VALUE value) {
|
|
787
792
|
return INT2NUM((int)d->cache_str);
|
788
793
|
}
|
789
794
|
|
795
|
+
static VALUE opt_cache_expunge(ojParser p, VALUE value) {
|
796
|
+
Delegate d = (Delegate)p->ctx;
|
797
|
+
|
798
|
+
return INT2NUM((int)d->cache_xrate);
|
799
|
+
}
|
800
|
+
|
801
|
+
static VALUE opt_cache_expunge_set(ojParser p, VALUE value) {
|
802
|
+
Delegate d = (Delegate)p->ctx;
|
803
|
+
int rate = NUM2INT(value);
|
804
|
+
|
805
|
+
if (rate < 0) {
|
806
|
+
rate = 0;
|
807
|
+
} else if (3 < rate) {
|
808
|
+
rate = 3;
|
809
|
+
}
|
810
|
+
d->cache_xrate = (uint8_t)rate;
|
811
|
+
cache_set_expunge_rate(d->str_cache, rate);
|
812
|
+
cache_set_expunge_rate(d->attr_cache, rate);
|
813
|
+
if (NULL != d->sym_cache) {
|
814
|
+
cache_set_expunge_rate(d->sym_cache, rate);
|
815
|
+
}
|
816
|
+
return INT2NUM((int)rate);
|
817
|
+
}
|
818
|
+
|
790
819
|
static VALUE opt_capacity(ojParser p, VALUE value) {
|
791
820
|
Delegate d = (Delegate)p->ctx;
|
792
821
|
|
@@ -825,11 +854,7 @@ static VALUE opt_class_cache_set(ojParser p, VALUE value) {
|
|
825
854
|
|
826
855
|
if (Qtrue == value) {
|
827
856
|
if (NULL == d->class_cache) {
|
828
|
-
|
829
|
-
d->class_cache = cache_create(0, form_class_auto, true);
|
830
|
-
} else {
|
831
|
-
d->class_cache = cache_create(0, form_class, false);
|
832
|
-
}
|
857
|
+
d->class_cache = cache_create(0, form_class_auto, MISS_AUTO == d->miss_class, false);
|
833
858
|
}
|
834
859
|
} else if (NULL != d->class_cache) {
|
835
860
|
cache_free(d->class_cache);
|
@@ -1073,7 +1098,8 @@ static VALUE opt_symbol_keys_set(ojParser p, VALUE value) {
|
|
1073
1098
|
Delegate d = (Delegate)p->ctx;
|
1074
1099
|
|
1075
1100
|
if (Qtrue == value) {
|
1076
|
-
d->sym_cache = cache_create(0, form_sym, true);
|
1101
|
+
d->sym_cache = cache_create(0, form_sym, true, false);
|
1102
|
+
cache_set_expunge_rate(d->sym_cache, d->cache_xrate);
|
1077
1103
|
d->key_cache = d->sym_cache;
|
1078
1104
|
if (!d->cache_keys) {
|
1079
1105
|
d->get_key = sym_key;
|
@@ -1091,13 +1117,16 @@ static VALUE opt_symbol_keys_set(ojParser p, VALUE value) {
|
|
1091
1117
|
}
|
1092
1118
|
|
1093
1119
|
static VALUE option(ojParser p, const char *key, VALUE value) {
|
1094
|
-
struct opt
|
1120
|
+
struct opt *op;
|
1121
|
+
struct opt opts[] = {
|
1095
1122
|
{.name = "array_class", .func = opt_array_class},
|
1096
1123
|
{.name = "array_class=", .func = opt_array_class_set},
|
1097
1124
|
{.name = "cache_keys", .func = opt_cache_keys},
|
1098
1125
|
{.name = "cache_keys=", .func = opt_cache_keys_set},
|
1099
1126
|
{.name = "cache_strings", .func = opt_cache_strings},
|
1100
1127
|
{.name = "cache_strings=", .func = opt_cache_strings_set},
|
1128
|
+
{.name = "cache_expunge", .func = opt_cache_expunge},
|
1129
|
+
{.name = "cache_expunge=", .func = opt_cache_expunge_set},
|
1101
1130
|
{.name = "capacity", .func = opt_capacity},
|
1102
1131
|
{.name = "capacity=", .func = opt_capacity_set},
|
1103
1132
|
{.name = "class_cache", .func = opt_class_cache},
|
@@ -1119,7 +1148,7 @@ static VALUE option(ojParser p, const char *key, VALUE value) {
|
|
1119
1148
|
{.name = NULL},
|
1120
1149
|
};
|
1121
1150
|
|
1122
|
-
for (
|
1151
|
+
for (op = opts; NULL != op->name; op++) {
|
1123
1152
|
if (0 == strcmp(key, op->name)) {
|
1124
1153
|
return op->func(p, value);
|
1125
1154
|
}
|
@@ -1157,6 +1186,7 @@ void oj_set_parser_usual(ojParser p) {
|
|
1157
1186
|
d->create_id = NULL;
|
1158
1187
|
d->create_id_len = 0;
|
1159
1188
|
d->miss_class = MISS_IGNORE;
|
1189
|
+
d->cache_xrate = 1;
|
1160
1190
|
|
1161
1191
|
Funcs f = &p->funcs[TOP_FUN];
|
1162
1192
|
f->add_null = add_null;
|
@@ -1197,8 +1227,8 @@ void oj_set_parser_usual(ojParser p) {
|
|
1197
1227
|
f->open_object = open_object_key;
|
1198
1228
|
f->close_object = close_object;
|
1199
1229
|
|
1200
|
-
d->str_cache = cache_create(0, form_str, true);
|
1201
|
-
d->attr_cache = cache_create(0, form_attr, false);
|
1230
|
+
d->str_cache = cache_create(0, form_str, true, false);
|
1231
|
+
d->attr_cache = cache_create(0, form_attr, false, false);
|
1202
1232
|
d->sym_cache = NULL;
|
1203
1233
|
d->class_cache = NULL;
|
1204
1234
|
d->key_cache = d->str_cache;
|
data/ext/oj/validate.c
CHANGED
@@ -28,8 +28,9 @@ mark(ojParser p) {
|
|
28
28
|
void oj_set_parser_validator(ojParser p) {
|
29
29
|
p->ctx = NULL;
|
30
30
|
Funcs end = p->funcs + 3;
|
31
|
+
Funcs f;
|
31
32
|
|
32
|
-
for (
|
33
|
+
for (f = p->funcs; f < end; f++) {
|
33
34
|
f->add_null = noop;
|
34
35
|
f->add_true = noop;
|
35
36
|
f->add_false = noop;
|
data/ext/oj/wab.c
CHANGED
@@ -305,11 +305,14 @@ static VALUE calc_hash_key(ParseInfo pi, Val parent) {
|
|
305
305
|
if (Yes == pi->options.cache_keys) {
|
306
306
|
rkey = oj_sym_intern(parent->key, parent->klen);
|
307
307
|
} else {
|
308
|
-
|
309
|
-
rkey =
|
308
|
+
#if HAVE_RB_ENC_INTERNED_STR
|
309
|
+
rkey = rb_enc_interned_str(parent->key, parent->klen, oj_utf8_encoding);
|
310
|
+
#else
|
311
|
+
rkey = rb_utf8_str_new(parent->key, parent->klen);
|
310
312
|
rkey = rb_str_intern(rkey);
|
313
|
+
OBJ_FREEZE(rkey);
|
314
|
+
#endif
|
311
315
|
}
|
312
|
-
OBJ_FREEZE(rkey);
|
313
316
|
return rkey;
|
314
317
|
}
|
315
318
|
|
data/lib/oj/error.rb
CHANGED
@@ -16,7 +16,7 @@ module Oj
|
|
16
16
|
# An Exception that is raised if a file fails to load.
|
17
17
|
LoadError = Class.new(Error)
|
18
18
|
|
19
|
-
# An Exception that is raised if there is a conflict with
|
19
|
+
# An Exception that is raised if there is a conflict with mimicking JSON
|
20
20
|
MimicError = Class.new(Error)
|
21
21
|
|
22
22
|
end # Oj
|
data/lib/oj/state.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
module JSON
|
3
3
|
module Ext
|
4
|
-
module Generator
|
4
|
+
module Generator
|
5
5
|
unless defined?(::JSON::Ext::Generator::State)
|
6
6
|
# This class exists for json gem compatibility only. While it can be
|
7
7
|
# used as the options for other than compatibility a simple Hash is
|
@@ -44,11 +44,11 @@ module JSON
|
|
44
44
|
def to_h()
|
45
45
|
return @attrs.dup
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def to_hash()
|
49
49
|
return @attrs.dup
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
def allow_nan?()
|
53
53
|
@attrs[:allow_nan]
|
54
54
|
end
|
@@ -104,7 +104,7 @@ module JSON
|
|
104
104
|
def has_key?(k)
|
105
105
|
@attrs.has_key?(key.to_sym)
|
106
106
|
end
|
107
|
-
|
107
|
+
|
108
108
|
# Handles requests for Hash values. Others cause an Exception to be raised.
|
109
109
|
# @param [Symbol|String] m method symbol
|
110
110
|
# @return [Boolean] the value of the specified instance variable.
|
@@ -116,11 +116,12 @@ module JSON
|
|
116
116
|
m = m.to_s[0..-2]
|
117
117
|
m = m.to_sym
|
118
118
|
return @attrs.store(m, args[0])
|
119
|
-
|
119
|
+
end
|
120
|
+
if @attrs.has_key?(m.to_sym)
|
120
121
|
raise ArgumentError.new("wrong number of arguments (#{args.size} for 0 with #{m}) to method #{m}") unless args.nil? or args.empty?
|
121
122
|
return @attrs[m.to_sym]
|
122
|
-
|
123
|
-
|
123
|
+
end
|
124
|
+
return @attrs.send(m, *args, &block)
|
124
125
|
end
|
125
126
|
|
126
127
|
end # State
|