oj 3.13.23 → 3.14.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +2 -1
- data/ext/oj/buf.h +6 -5
- data/ext/oj/cache.c +11 -10
- data/ext/oj/cache8.c +3 -2
- data/ext/oj/circarray.c +6 -5
- data/ext/oj/compat.c +12 -31
- data/ext/oj/custom.c +16 -31
- data/ext/oj/dump.c +10 -13
- data/ext/oj/dump_compat.c +9 -19
- data/ext/oj/dump_object.c +8 -13
- data/ext/oj/dump_strict.c +8 -18
- data/ext/oj/extconf.rb +10 -2
- data/ext/oj/fast.c +31 -47
- data/ext/oj/intern.c +7 -5
- data/ext/oj/mem.c +324 -0
- data/ext/oj/mem.h +53 -0
- data/ext/oj/mimic_json.c +3 -2
- data/ext/oj/object.c +9 -13
- data/ext/oj/odd.c +7 -6
- data/ext/oj/oj.c +12 -5
- data/ext/oj/oj.h +6 -0
- data/ext/oj/parse.c +18 -13
- data/ext/oj/parser.c +7 -7
- data/ext/oj/rails.c +19 -28
- data/ext/oj/reader.c +4 -3
- data/ext/oj/reader.h +3 -1
- data/ext/oj/rxclass.c +5 -4
- data/ext/oj/saj.c +6 -5
- data/ext/oj/saj2.c +10 -5
- data/ext/oj/sparse.c +5 -4
- data/ext/oj/stream_writer.c +5 -4
- data/ext/oj/strict.c +4 -12
- data/ext/oj/string_writer.c +7 -6
- data/ext/oj/trace.h +16 -0
- data/ext/oj/usual.c +28 -27
- data/ext/oj/val_stack.h +4 -3
- data/ext/oj/wab.c +9 -21
- data/lib/oj/version.rb +1 -1
- data/pages/InstallOptions.md +20 -0
- data/test/foo.rb +46 -65
- data/test/perf_parser.rb +1 -0
- data/test/test_compat.rb +9 -0
- metadata +7 -3
data/ext/oj/dump_object.c
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
// Copyright (c) 2012, 2017 Peter Ohler. All rights reserved.
|
2
2
|
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
3
3
|
|
4
|
+
#include "mem.h"
|
4
5
|
#include "dump.h"
|
5
6
|
#include "odd.h"
|
6
7
|
#include "trace.h"
|
@@ -30,7 +31,7 @@ static void dump_data(VALUE obj, int depth, Out out, bool as_ok) {
|
|
30
31
|
*out->cur = '\0';
|
31
32
|
} else {
|
32
33
|
if (oj_bigdecimal_class == clas) {
|
33
|
-
volatile VALUE rstr =
|
34
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
34
35
|
const char * str = RSTRING_PTR(rstr);
|
35
36
|
int len = (int)RSTRING_LEN(rstr);
|
36
37
|
|
@@ -59,7 +60,7 @@ static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
|
|
59
60
|
VALUE clas = rb_obj_class(obj);
|
60
61
|
|
61
62
|
if (oj_bigdecimal_class == clas) {
|
62
|
-
volatile VALUE rstr =
|
63
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
63
64
|
const char * str = RSTRING_PTR(rstr);
|
64
65
|
int len = (int)RSTRING_LEN(rstr);
|
65
66
|
|
@@ -422,7 +423,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
422
423
|
ID i;
|
423
424
|
|
424
425
|
if (sizeof(nbuf) <= nlen) {
|
425
|
-
if (NULL == (n2 =
|
426
|
+
if (NULL == (n2 = OJ_STRDUP(name))) {
|
426
427
|
rb_raise(rb_eNoMemError, "for attribute name.");
|
427
428
|
}
|
428
429
|
} else {
|
@@ -439,7 +440,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) {
|
|
439
440
|
i = rb_intern(n);
|
440
441
|
v = rb_funcall(v, i, 0);
|
441
442
|
if (nbuf != n2) {
|
442
|
-
|
443
|
+
OJ_FREE(n2);
|
443
444
|
}
|
444
445
|
}
|
445
446
|
fill_indent(out, d2);
|
@@ -682,9 +683,7 @@ static DumpFunc obj_funcs[] = {
|
|
682
683
|
void oj_dump_obj_val(VALUE obj, int depth, Out out) {
|
683
684
|
int type = rb_type(obj);
|
684
685
|
|
685
|
-
|
686
|
-
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
687
|
-
}
|
686
|
+
TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
|
688
687
|
if (MAX_DEPTH < depth) {
|
689
688
|
rb_raise(rb_eNoMemError, "Too deeply nested.\n");
|
690
689
|
}
|
@@ -693,14 +692,10 @@ void oj_dump_obj_val(VALUE obj, int depth, Out out) {
|
|
693
692
|
|
694
693
|
if (NULL != f) {
|
695
694
|
f(obj, depth, out, false);
|
696
|
-
|
697
|
-
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
|
698
|
-
}
|
695
|
+
TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
|
699
696
|
return;
|
700
697
|
}
|
701
698
|
}
|
702
699
|
oj_dump_nil(Qnil, depth, out, false);
|
703
|
-
|
704
|
-
oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
|
705
|
-
}
|
700
|
+
TRACE(out->opts->trace, "dump", Qnil, depth, TraceOut);
|
706
701
|
}
|
data/ext/oj/dump_strict.c
CHANGED
@@ -92,7 +92,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
|
92
92
|
} else if (d == (double)(long long int)d) {
|
93
93
|
cnt = snprintf(buf, sizeof(buf), "%.1f", d);
|
94
94
|
} else if (0 == out->opts->float_prec) {
|
95
|
-
volatile VALUE rstr =
|
95
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
96
96
|
|
97
97
|
cnt = (int)RSTRING_LEN(rstr);
|
98
98
|
if ((int)sizeof(buf) <= cnt) {
|
@@ -290,7 +290,7 @@ static void dump_data_strict(VALUE obj, int depth, Out out, bool as_ok) {
|
|
290
290
|
VALUE clas = rb_obj_class(obj);
|
291
291
|
|
292
292
|
if (oj_bigdecimal_class == clas) {
|
293
|
-
volatile VALUE rstr =
|
293
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
294
294
|
|
295
295
|
oj_dump_raw(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), out);
|
296
296
|
} else {
|
@@ -302,7 +302,7 @@ static void dump_data_null(VALUE obj, int depth, Out out, bool as_ok) {
|
|
302
302
|
VALUE clas = rb_obj_class(obj);
|
303
303
|
|
304
304
|
if (oj_bigdecimal_class == clas) {
|
305
|
-
volatile VALUE rstr =
|
305
|
+
volatile VALUE rstr = oj_safe_string_convert(obj);
|
306
306
|
|
307
307
|
oj_dump_raw(RSTRING_PTR(rstr), (int)RSTRING_LEN(rstr), out);
|
308
308
|
} else {
|
@@ -338,9 +338,7 @@ static DumpFunc strict_funcs[] = {
|
|
338
338
|
void oj_dump_strict_val(VALUE obj, int depth, Out out) {
|
339
339
|
int type = rb_type(obj);
|
340
340
|
|
341
|
-
|
342
|
-
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
343
|
-
}
|
341
|
+
TRACE(out->opts->trace, "dump", obj, depth, TraceIn);
|
344
342
|
if (MAX_DEPTH < depth) {
|
345
343
|
rb_raise(rb_eNoMemError, "Too deeply nested.\n");
|
346
344
|
}
|
@@ -349,9 +347,7 @@ void oj_dump_strict_val(VALUE obj, int depth, Out out) {
|
|
349
347
|
|
350
348
|
if (NULL != f) {
|
351
349
|
f(obj, depth, out, false);
|
352
|
-
|
353
|
-
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
|
354
|
-
}
|
350
|
+
TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
|
355
351
|
return;
|
356
352
|
}
|
357
353
|
}
|
@@ -386,9 +382,7 @@ static DumpFunc null_funcs[] = {
|
|
386
382
|
void oj_dump_null_val(VALUE obj, int depth, Out out) {
|
387
383
|
int type = rb_type(obj);
|
388
384
|
|
389
|
-
|
390
|
-
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
|
391
|
-
}
|
385
|
+
TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
|
392
386
|
if (MAX_DEPTH < depth) {
|
393
387
|
rb_raise(rb_eNoMemError, "Too deeply nested.\n");
|
394
388
|
}
|
@@ -397,14 +391,10 @@ void oj_dump_null_val(VALUE obj, int depth, Out out) {
|
|
397
391
|
|
398
392
|
if (NULL != f) {
|
399
393
|
f(obj, depth, out, false);
|
400
|
-
|
401
|
-
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
|
402
|
-
}
|
394
|
+
TRACE(out->opts->trace, "dump", obj, depth, TraceOut);
|
403
395
|
return;
|
404
396
|
}
|
405
397
|
}
|
406
398
|
oj_dump_nil(Qnil, depth, out, false);
|
407
|
-
|
408
|
-
oj_trace("dump", Qnil, __FILE__, __LINE__, depth, TraceOut);
|
409
|
-
}
|
399
|
+
TRACE(out->opts->trace, "dump", Qnil, depth, TraceOut);
|
410
400
|
}
|
data/ext/oj/extconf.rb
CHANGED
@@ -35,8 +35,16 @@ have_func('rb_hash_bulk_insert', 'ruby.h') unless '2' == version[0] && '6' == ve
|
|
35
35
|
dflags['OJ_DEBUG'] = true unless ENV['OJ_DEBUG'].nil?
|
36
36
|
|
37
37
|
if with_config('--with-sse42')
|
38
|
-
|
39
|
-
|
38
|
+
if try_cflags('-msse4.2')
|
39
|
+
$CPPFLAGS += ' -msse4.2'
|
40
|
+
dflags['OJ_USE_SSE4_2'] = 1
|
41
|
+
else
|
42
|
+
warn 'SSE 4.2 is not supported on this platform.'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
if enable_config('trace-log', false)
|
47
|
+
dflags['OJ_ENABLE_TRACE_LOG'] = 1
|
40
48
|
end
|
41
49
|
|
42
50
|
dflags.each do |k,v|
|
data/ext/oj/fast.c
CHANGED
@@ -11,6 +11,7 @@
|
|
11
11
|
#include <stdlib.h>
|
12
12
|
#include <string.h>
|
13
13
|
|
14
|
+
#include "mem.h"
|
14
15
|
#include "encode.h"
|
15
16
|
#include "oj.h"
|
16
17
|
#include "dump.h"
|
@@ -74,7 +75,7 @@ static char *read_quoted_value(ParseInfo pi);
|
|
74
75
|
static void skip_comment(ParseInfo pi);
|
75
76
|
|
76
77
|
static VALUE protect_open_proc(VALUE x);
|
77
|
-
static VALUE parse_json(VALUE clas, char *json, bool given
|
78
|
+
static VALUE parse_json(VALUE clas, char *json, bool given);
|
78
79
|
static void each_leaf(Doc doc, VALUE self);
|
79
80
|
static int move_step(Doc doc, const char *path, int loc);
|
80
81
|
static Leaf get_doc_leaf(Doc doc, const char *path);
|
@@ -160,7 +161,7 @@ inline static Leaf leaf_new(Doc doc, int type) {
|
|
160
161
|
Leaf leaf;
|
161
162
|
|
162
163
|
if (0 == doc->batches || BATCH_SIZE == doc->batches->next_avail) {
|
163
|
-
Batch b =
|
164
|
+
Batch b = OJ_R_ALLOC(struct _batch);
|
164
165
|
|
165
166
|
// Initializes all leaves with a NO_VAL value_type
|
166
167
|
memset(b, 0, sizeof(struct _batch));
|
@@ -648,10 +649,11 @@ static void doc_free(Doc doc) {
|
|
648
649
|
while (0 != (b = doc->batches)) {
|
649
650
|
doc->batches = doc->batches->next;
|
650
651
|
if (&doc->batch0 != b) {
|
651
|
-
|
652
|
+
OJ_R_FREE(b);
|
652
653
|
}
|
653
654
|
}
|
654
|
-
|
655
|
+
OJ_R_FREE(doc->json);
|
656
|
+
OJ_R_FREE(doc);
|
655
657
|
}
|
656
658
|
}
|
657
659
|
|
@@ -671,7 +673,6 @@ static void free_doc_cb(void *x) {
|
|
671
673
|
Doc doc = (Doc)x;
|
672
674
|
|
673
675
|
if (0 != doc) {
|
674
|
-
xfree(doc->json);
|
675
676
|
doc_free(doc);
|
676
677
|
}
|
677
678
|
}
|
@@ -749,20 +750,15 @@ static const rb_data_type_t oj_doc_type = {
|
|
749
750
|
0,
|
750
751
|
};
|
751
752
|
|
752
|
-
static VALUE parse_json(VALUE clas, char *json, bool given
|
753
|
+
static VALUE parse_json(VALUE clas, char *json, bool given) {
|
753
754
|
struct _parseInfo pi;
|
754
755
|
volatile VALUE result = Qnil;
|
755
756
|
Doc doc;
|
756
757
|
int ex = 0;
|
757
758
|
volatile VALUE self;
|
758
759
|
|
759
|
-
|
760
|
+
doc = OJ_R_ALLOC_N(struct _doc, 1);
|
760
761
|
|
761
|
-
if (given) {
|
762
|
-
doc = ALLOCA_N(struct _doc, 1);
|
763
|
-
} else {
|
764
|
-
doc = ALLOC(struct _doc);
|
765
|
-
}
|
766
762
|
// skip UTF-8 BOM if present
|
767
763
|
if (0xEF == (uint8_t)*json && 0xBB == (uint8_t)json[1] && 0xBF == (uint8_t)json[2]) {
|
768
764
|
pi.str = json + 3;
|
@@ -787,18 +783,20 @@ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
|
|
787
783
|
}
|
788
784
|
}
|
789
785
|
#endif
|
786
|
+
doc->json = json;
|
790
787
|
self = TypedData_Wrap_Struct(clas, &oj_doc_type, doc);
|
791
788
|
doc->self = self;
|
792
|
-
doc->json = json;
|
793
789
|
DATA_PTR(doc->self) = doc;
|
794
790
|
result = rb_protect(protect_open_proc, (VALUE)&pi, &ex);
|
795
791
|
if (given || 0 != ex) {
|
796
792
|
DATA_PTR(doc->self) = NULL;
|
793
|
+
// TBD is this needed?
|
794
|
+
/*
|
797
795
|
doc_free(pi.doc);
|
798
|
-
if (
|
799
|
-
|
796
|
+
if (0 != ex) { // will jump so caller will not free
|
797
|
+
OJ_R_FREE(json);
|
800
798
|
}
|
801
|
-
|
799
|
+
*/
|
802
800
|
} else {
|
803
801
|
result = doc->self;
|
804
802
|
}
|
@@ -1092,27 +1090,19 @@ static VALUE doc_open(VALUE clas, VALUE str) {
|
|
1092
1090
|
size_t len;
|
1093
1091
|
volatile VALUE obj;
|
1094
1092
|
int given = rb_block_given_p();
|
1095
|
-
int allocate;
|
1096
1093
|
|
1097
1094
|
Check_Type(str, T_STRING);
|
1098
1095
|
len = (int)RSTRING_LEN(str) + 1;
|
1099
|
-
|
1100
|
-
|
1101
|
-
json = ALLOC_N(char, len);
|
1102
|
-
} else {
|
1103
|
-
json = ALLOCA_N(char, len);
|
1104
|
-
}
|
1105
|
-
// It should not be necessaary to stop GC but if it is not stopped and a
|
1106
|
-
// large string is parsed that string is corrupted or freed during
|
1107
|
-
// parsing. I'm not sure what is going on exactly but disabling GC avoids
|
1108
|
-
// the issue.
|
1109
|
-
rb_gc_disable();
|
1096
|
+
json = OJ_R_ALLOC_N(char, len);
|
1097
|
+
|
1110
1098
|
memcpy(json, StringValuePtr(str), len);
|
1111
|
-
obj = parse_json(clas, json, given
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1099
|
+
obj = parse_json(clas, json, given);
|
1100
|
+
// TBD is this needed
|
1101
|
+
/*
|
1102
|
+
if (given) {
|
1103
|
+
OJ_R_FREE(json);
|
1115
1104
|
}
|
1105
|
+
*/
|
1116
1106
|
return obj;
|
1117
1107
|
}
|
1118
1108
|
|
@@ -1142,7 +1132,6 @@ static VALUE doc_open_file(VALUE clas, VALUE filename) {
|
|
1142
1132
|
size_t len;
|
1143
1133
|
volatile VALUE obj;
|
1144
1134
|
int given = rb_block_given_p();
|
1145
|
-
int allocate;
|
1146
1135
|
|
1147
1136
|
Check_Type(filename, T_STRING);
|
1148
1137
|
path = StringValuePtr(filename);
|
@@ -1151,12 +1140,8 @@ static VALUE doc_open_file(VALUE clas, VALUE filename) {
|
|
1151
1140
|
}
|
1152
1141
|
fseek(f, 0, SEEK_END);
|
1153
1142
|
len = ftell(f);
|
1154
|
-
|
1155
|
-
|
1156
|
-
json = ALLOC_N(char, len + 1);
|
1157
|
-
} else {
|
1158
|
-
json = ALLOCA_N(char, len + 1);
|
1159
|
-
}
|
1143
|
+
json = OJ_R_ALLOC_N(char, len + 1);
|
1144
|
+
|
1160
1145
|
fseek(f, 0, SEEK_SET);
|
1161
1146
|
if (len != fread(json, 1, len, f)) {
|
1162
1147
|
fclose(f);
|
@@ -1167,12 +1152,13 @@ static VALUE doc_open_file(VALUE clas, VALUE filename) {
|
|
1167
1152
|
}
|
1168
1153
|
fclose(f);
|
1169
1154
|
json[len] = '\0';
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
if (given
|
1174
|
-
|
1155
|
+
obj = parse_json(clas, json, given);
|
1156
|
+
// TBD is this needed
|
1157
|
+
/*
|
1158
|
+
if (given) {
|
1159
|
+
OJ_R_FREE(json);
|
1175
1160
|
}
|
1161
|
+
*/
|
1176
1162
|
return obj;
|
1177
1163
|
}
|
1178
1164
|
|
@@ -1656,11 +1642,9 @@ static VALUE doc_close(VALUE self) {
|
|
1656
1642
|
Doc doc = self_doc(self);
|
1657
1643
|
|
1658
1644
|
rb_gc_unregister_address(&doc->self);
|
1659
|
-
DATA_PTR(doc->self) =
|
1645
|
+
DATA_PTR(doc->self) = NULL;
|
1660
1646
|
if (0 != doc) {
|
1661
|
-
xfree(doc->json);
|
1662
1647
|
doc_free(doc);
|
1663
|
-
xfree(doc);
|
1664
1648
|
}
|
1665
1649
|
return Qnil;
|
1666
1650
|
}
|
data/ext/oj/intern.c
CHANGED
@@ -8,6 +8,8 @@
|
|
8
8
|
#if HAVE_PTHREAD_MUTEX_INIT
|
9
9
|
#include <pthread.h>
|
10
10
|
#endif
|
11
|
+
|
12
|
+
#include "mem.h"
|
11
13
|
#include "cache.h"
|
12
14
|
#include "parse.h"
|
13
15
|
|
@@ -55,7 +57,7 @@ static VALUE form_attr(const char *str, size_t len) {
|
|
55
57
|
char buf[256];
|
56
58
|
|
57
59
|
if (sizeof(buf) - 2 <= len) {
|
58
|
-
char *b =
|
60
|
+
char *b = OJ_R_ALLOC_N(char, len + 2);
|
59
61
|
ID id;
|
60
62
|
|
61
63
|
if ('~' == *str) {
|
@@ -68,7 +70,7 @@ static VALUE form_attr(const char *str, size_t len) {
|
|
68
70
|
b[len + 1] = '\0';
|
69
71
|
}
|
70
72
|
id = rb_intern3(buf, len + 1, oj_utf8_encoding);
|
71
|
-
|
73
|
+
OJ_R_FREE(b);
|
72
74
|
return id;
|
73
75
|
}
|
74
76
|
if ('~' == *str) {
|
@@ -246,7 +248,7 @@ VALUE oj_class_intern(const char *key, size_t len, bool safe, ParseInfo pi, int
|
|
246
248
|
}
|
247
249
|
bucket = b;
|
248
250
|
}
|
249
|
-
b =
|
251
|
+
b = OJ_R_ALLOC(struct _keyVal);
|
250
252
|
b->next = NULL;
|
251
253
|
bucket->next = b;
|
252
254
|
bucket = b;
|
@@ -267,7 +269,7 @@ VALUE oj_class_intern(const char *key, size_t len, bool safe, ParseInfo pi, int
|
|
267
269
|
}
|
268
270
|
bucket = b;
|
269
271
|
}
|
270
|
-
b =
|
272
|
+
b = OJ_R_ALLOC(struct _keyVal);
|
271
273
|
b->next = NULL;
|
272
274
|
bucket->next = b;
|
273
275
|
bucket = b;
|
@@ -281,7 +283,7 @@ VALUE oj_class_intern(const char *key, size_t len, bool safe, ParseInfo pi, int
|
|
281
283
|
}
|
282
284
|
|
283
285
|
char *oj_strndup(const char *s, size_t len) {
|
284
|
-
char *d =
|
286
|
+
char *d = OJ_R_ALLOC_N(char, len + 1);
|
285
287
|
|
286
288
|
memcpy(d, s, len);
|
287
289
|
d[len] = '\0';
|