oj 3.14.3 → 3.15.1
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 +10 -0
- data/ext/oj/code.c +3 -10
- data/ext/oj/compat.c +5 -18
- data/ext/oj/custom.c +10 -28
- data/ext/oj/dump.c +40 -10
- data/ext/oj/dump.h +1 -4
- data/ext/oj/extconf.rb +4 -2
- data/ext/oj/fast.c +3 -6
- data/ext/oj/mimic_json.c +21 -1
- data/ext/oj/object.c +7 -21
- data/ext/oj/oj.c +24 -4
- data/ext/oj/oj.h +10 -6
- data/ext/oj/parse.c +3 -5
- data/ext/oj/parse.h +16 -14
- data/ext/oj/parser.h +2 -2
- data/ext/oj/reader.c +1 -3
- data/ext/oj/saj.c +1 -1
- data/ext/oj/strict.c +9 -27
- data/ext/oj/wab.c +9 -27
- data/lib/oj/active_support_helper.rb +2 -3
- data/lib/oj/json.rb +156 -149
- data/lib/oj/mimic.rb +3 -1
- data/lib/oj/version.rb +1 -1
- data/lib/oj.rb +3 -0
- data/pages/Options.md +4 -0
- data/test/_test_active.rb +8 -8
- data/test/_test_active_mimic.rb +7 -7
- data/test/_test_mimic_rails.rb +17 -19
- data/test/files.rb +14 -14
- data/test/foo.rb +15 -10
- data/test/helper.rb +4 -4
- data/test/mem.rb +8 -7
- data/test/perf.rb +21 -26
- data/test/perf_compat.rb +30 -32
- data/test/perf_dump.rb +27 -27
- data/test/perf_fast.rb +80 -82
- data/test/perf_file.rb +27 -29
- data/test/perf_object.rb +65 -68
- data/test/perf_once.rb +8 -7
- data/test/perf_parser.rb +40 -46
- data/test/perf_saj.rb +46 -53
- data/test/perf_scp.rb +57 -69
- data/test/perf_simple.rb +40 -38
- data/test/perf_strict.rb +68 -70
- data/test/perf_wab.rb +67 -69
- data/test/prec.rb +3 -3
- data/test/sample.rb +16 -15
- data/test/sample_json.rb +8 -7
- data/test/test_compat.rb +44 -46
- data/test/test_custom.rb +56 -42
- data/test/test_debian.rb +6 -9
- data/test/test_fast.rb +78 -72
- data/test/test_file.rb +16 -21
- data/test/test_gc.rb +5 -5
- data/test/test_generate.rb +5 -5
- data/test/test_hash.rb +4 -4
- data/test/test_integer_range.rb +9 -9
- data/test/test_null.rb +18 -20
- data/test/test_object.rb +76 -86
- data/test/test_parser.rb +4 -4
- data/test/test_parser_debug.rb +4 -4
- data/test/test_parser_saj.rb +31 -31
- data/test/test_parser_usual.rb +3 -3
- data/test/test_rails.rb +2 -2
- data/test/test_saj.rb +8 -8
- data/test/test_scp.rb +29 -29
- data/test/test_strict.rb +25 -31
- data/test/test_various.rb +121 -75
- data/test/test_wab.rb +43 -42
- data/test/test_writer.rb +46 -46
- data/test/tests.rb +7 -7
- data/test/tests_mimic.rb +6 -6
- data/test/tests_mimic_addition.rb +6 -6
- metadata +3 -6
- data/test/bar.rb +0 -11
- data/test/baz.rb +0 -16
- data/test/bug.rb +0 -16
- data/test/zoo.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 257582096951b3c4db4b4979c49afd542ae855ba454bd6d51dcb1a69f68c2405
|
4
|
+
data.tar.gz: d835a958d019f7034e93d3f97ca1829fad74a4e26743f6a8b2b581c03ac9f14a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 374e55547de2db4b2199c05bebe5fa74953021883f7f609e328466c076016817b0cb8a7be03ead9c68b3fe4895eb5de0bcd60e1384ff7f1a5f7cd480824faba0
|
7
|
+
data.tar.gz: ec9cf41116602a51c49ff73ba6fc39ecbb501d51cbab0a6065bb38d2ac15a7f42332dc66f0d97df40bea6da5fafbc15209d06039180829c4c4b299b0e138676e
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 3.15.1 - 2023-07-30
|
4
|
+
|
5
|
+
- Add protection against some using `require 'oj/json`, an internal file.
|
6
|
+
|
7
|
+
- Fixed non-json errors when in compat mode.
|
8
|
+
|
9
|
+
## 3.15.0 - 2023-06-02
|
10
|
+
|
11
|
+
- Added `omit_null_byte` option when dumping.
|
12
|
+
|
3
13
|
## 3.14.3 - 2023-04-07
|
4
14
|
|
5
15
|
- Fixed compat parse with optimized Hash when parsing a JSON::GenericObject.
|
data/ext/oj/code.c
CHANGED
@@ -185,24 +185,17 @@ void oj_code_attrs(VALUE obj, Attr attrs, int depth, Out out, bool with_class) {
|
|
185
185
|
} else {
|
186
186
|
char buf[32];
|
187
187
|
char *b = buf + sizeof(buf) - 1;
|
188
|
-
|
188
|
+
bool neg = false;
|
189
189
|
long num = attrs->num;
|
190
190
|
size_t cnt = 0;
|
191
191
|
|
192
192
|
if (0 > num) {
|
193
|
-
neg =
|
193
|
+
neg = true;
|
194
194
|
num = -num;
|
195
195
|
}
|
196
196
|
*b-- = '\0';
|
197
197
|
if (0 < num) {
|
198
|
-
|
199
|
-
*b = (num % 10) + '0';
|
200
|
-
}
|
201
|
-
if (neg) {
|
202
|
-
*b = '-';
|
203
|
-
} else {
|
204
|
-
b++;
|
205
|
-
}
|
198
|
+
b = oj_longlong_to_string(num, neg, b);
|
206
199
|
} else {
|
207
200
|
*b = '0';
|
208
201
|
}
|
data/ext/oj/compat.c
CHANGED
@@ -13,32 +13,19 @@
|
|
13
13
|
#include "trace.h"
|
14
14
|
|
15
15
|
static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
|
16
|
-
const char
|
17
|
-
int
|
18
|
-
Val
|
19
|
-
volatile VALUE rkey = kval->key_val;
|
16
|
+
const char *key = kval->key;
|
17
|
+
int klen = kval->klen;
|
18
|
+
Val parent = stack_peek(&pi->stack);
|
20
19
|
|
21
|
-
if (Qundef ==
|
20
|
+
if (Qundef == kval->key_val && Yes == pi->options.create_ok && NULL != pi->options.create_id &&
|
22
21
|
*pi->options.create_id == *key && (int)pi->options.create_id_len == klen &&
|
23
22
|
0 == strncmp(pi->options.create_id, key, klen)) {
|
24
23
|
parent->classname = oj_strndup(str, len);
|
25
24
|
parent->clen = len;
|
26
25
|
} else {
|
27
26
|
volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
27
|
+
volatile VALUE rkey = oj_calc_hash_key(pi, kval);
|
28
28
|
|
29
|
-
if (Qundef == rkey) {
|
30
|
-
if (Yes != pi->options.cache_keys) {
|
31
|
-
if (Yes == pi->options.sym_key) {
|
32
|
-
rkey = ID2SYM(rb_intern3(key, klen, oj_utf8_encoding));
|
33
|
-
} else {
|
34
|
-
rkey = rb_utf8_str_new(key, klen);
|
35
|
-
}
|
36
|
-
} else if (Yes == pi->options.sym_key) {
|
37
|
-
rkey = oj_sym_intern(key, klen);
|
38
|
-
} else {
|
39
|
-
rkey = oj_str_intern(key, klen);
|
40
|
-
}
|
41
|
-
}
|
42
29
|
if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
|
43
30
|
VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
|
44
31
|
|
data/ext/oj/custom.c
CHANGED
@@ -889,12 +889,11 @@ void oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok) {
|
|
889
889
|
///// load functions /////
|
890
890
|
|
891
891
|
static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, const char *orig) {
|
892
|
-
const char
|
893
|
-
int
|
894
|
-
Val
|
895
|
-
volatile VALUE rkey = kval->key_val;
|
892
|
+
const char *key = kval->key;
|
893
|
+
int klen = kval->klen;
|
894
|
+
Val parent = stack_peek(&pi->stack);
|
896
895
|
|
897
|
-
if (Qundef ==
|
896
|
+
if (Qundef == kval->key_val && Yes == pi->options.create_ok && NULL != pi->options.create_id &&
|
898
897
|
*pi->options.create_id == *key && (int)pi->options.create_id_len == klen &&
|
899
898
|
0 == strncmp(pi->options.create_id, key, klen)) {
|
900
899
|
parent->clas = oj_name2class(pi, str, len, false, rb_eArgError);
|
@@ -907,15 +906,8 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
|
|
907
906
|
}
|
908
907
|
} else {
|
909
908
|
volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
910
|
-
|
909
|
+
volatile VALUE rkey = oj_calc_hash_key(pi, kval);
|
911
910
|
|
912
|
-
if (Qundef == rkey) {
|
913
|
-
if (Yes == pi->options.sym_key) {
|
914
|
-
rkey = ID2SYM(rb_intern3(key, klen, oj_utf8_encoding));
|
915
|
-
} else {
|
916
|
-
rkey = rb_utf8_str_new(key, klen);
|
917
|
-
}
|
918
|
-
}
|
919
911
|
if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
|
920
912
|
VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
|
921
913
|
|
@@ -937,9 +929,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c
|
|
937
929
|
break;
|
938
930
|
default: break;
|
939
931
|
}
|
940
|
-
|
941
|
-
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
|
942
|
-
}
|
932
|
+
TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rstr);
|
943
933
|
}
|
944
934
|
}
|
945
935
|
|
@@ -998,9 +988,7 @@ static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
|
|
998
988
|
break;
|
999
989
|
default: break;
|
1000
990
|
}
|
1001
|
-
|
1002
|
-
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
|
1003
|
-
}
|
991
|
+
TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rval);
|
1004
992
|
}
|
1005
993
|
|
1006
994
|
static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
@@ -1011,9 +999,7 @@ static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
|
1011
999
|
case T_HASH: rb_hash_aset(parent->val, oj_calc_hash_key(pi, kval), value); break;
|
1012
1000
|
default: break;
|
1013
1001
|
}
|
1014
|
-
|
1015
|
-
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
|
1016
|
-
}
|
1002
|
+
TRACE_PARSE_CALL(pi->options.trace, "set_value", pi, value);
|
1017
1003
|
}
|
1018
1004
|
|
1019
1005
|
static void array_append_num(ParseInfo pi, NumInfo ni) {
|
@@ -1021,9 +1007,7 @@ static void array_append_num(ParseInfo pi, NumInfo ni) {
|
|
1021
1007
|
volatile VALUE rval = oj_num_as_value(ni);
|
1022
1008
|
|
1023
1009
|
rb_ary_push(parent->val, rval);
|
1024
|
-
|
1025
|
-
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
1026
|
-
}
|
1010
|
+
TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, rval);
|
1027
1011
|
}
|
1028
1012
|
|
1029
1013
|
static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
@@ -1038,9 +1022,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
|
|
1038
1022
|
}
|
1039
1023
|
}
|
1040
1024
|
rb_ary_push(stack_peek(&pi->stack)->val, rstr);
|
1041
|
-
|
1042
|
-
oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
|
1043
|
-
}
|
1025
|
+
TRACE_PARSE_CALL(pi->options.trace, "append_string", pi, rstr);
|
1044
1026
|
}
|
1045
1027
|
|
1046
1028
|
void oj_set_custom_callbacks(ParseInfo pi) {
|
data/ext/oj/dump.c
CHANGED
@@ -857,6 +857,9 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
|
|
857
857
|
break;
|
858
858
|
case '6': // control characters
|
859
859
|
if (*(uint8_t *)str < 0x80) {
|
860
|
+
if (0 == (uint8_t)*str && out->opts->dump_opts.omit_null_byte) {
|
861
|
+
break;
|
862
|
+
}
|
860
863
|
APPEND_CHARS(out->cur, "\\u00", 4);
|
861
864
|
dump_hex((uint8_t)*str, out);
|
862
865
|
} else {
|
@@ -995,11 +998,45 @@ void oj_dump_false(VALUE obj, int depth, Out out, bool as_ok) {
|
|
995
998
|
*out->cur = '\0';
|
996
999
|
}
|
997
1000
|
|
1001
|
+
static const char digits_table[] = "\
|
1002
|
+
00010203040506070809\
|
1003
|
+
10111213141516171819\
|
1004
|
+
20212223242526272829\
|
1005
|
+
30313233343536373839\
|
1006
|
+
40414243444546474849\
|
1007
|
+
50515253545556575859\
|
1008
|
+
60616263646566676869\
|
1009
|
+
70717273747576777879\
|
1010
|
+
80818283848586878889\
|
1011
|
+
90919293949596979899";
|
1012
|
+
|
1013
|
+
char *oj_longlong_to_string(long long num, bool negative, char *buf) {
|
1014
|
+
while (100 <= num) {
|
1015
|
+
unsigned idx = num % 100 * 2;
|
1016
|
+
*buf-- = digits_table[idx + 1];
|
1017
|
+
*buf-- = digits_table[idx];
|
1018
|
+
num /= 100;
|
1019
|
+
}
|
1020
|
+
if (num < 10) {
|
1021
|
+
*buf-- = num + '0';
|
1022
|
+
} else {
|
1023
|
+
*buf-- = digits_table[num * 2 + 1];
|
1024
|
+
*buf-- = digits_table[num * 2];
|
1025
|
+
}
|
1026
|
+
|
1027
|
+
if (negative) {
|
1028
|
+
*buf = '-';
|
1029
|
+
} else {
|
1030
|
+
buf++;
|
1031
|
+
}
|
1032
|
+
return buf;
|
1033
|
+
}
|
1034
|
+
|
998
1035
|
void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
999
1036
|
char buf[32];
|
1000
1037
|
char *b = buf + sizeof(buf) - 1;
|
1001
1038
|
long long num = NUM2LL(obj);
|
1002
|
-
|
1039
|
+
bool neg = false;
|
1003
1040
|
size_t cnt = 0;
|
1004
1041
|
bool dump_as_string = false;
|
1005
1042
|
|
@@ -1008,7 +1045,7 @@ void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1008
1045
|
dump_as_string = true;
|
1009
1046
|
}
|
1010
1047
|
if (0 > num) {
|
1011
|
-
neg =
|
1048
|
+
neg = true;
|
1012
1049
|
num = -num;
|
1013
1050
|
}
|
1014
1051
|
*b-- = '\0';
|
@@ -1017,14 +1054,7 @@ void oj_dump_fixnum(VALUE obj, int depth, Out out, bool as_ok) {
|
|
1017
1054
|
*b-- = '"';
|
1018
1055
|
}
|
1019
1056
|
if (0 < num) {
|
1020
|
-
|
1021
|
-
*b = (num % 10) + '0';
|
1022
|
-
}
|
1023
|
-
if (neg) {
|
1024
|
-
*b = '-';
|
1025
|
-
} else {
|
1026
|
-
b++;
|
1027
|
-
}
|
1057
|
+
b = oj_longlong_to_string(num, neg, b);
|
1028
1058
|
} else {
|
1029
1059
|
*b = '0';
|
1030
1060
|
}
|
data/ext/oj/dump.h
CHANGED
@@ -93,10 +93,7 @@ inline static void dump_ulong(unsigned long num, Out out) {
|
|
93
93
|
|
94
94
|
*b-- = '\0';
|
95
95
|
if (0 < num) {
|
96
|
-
|
97
|
-
*b = (num % 10) + '0';
|
98
|
-
}
|
99
|
-
b++;
|
96
|
+
b = oj_longlong_to_string((long long)num, false, b);
|
100
97
|
} else {
|
101
98
|
*b = '0';
|
102
99
|
}
|
data/ext/oj/extconf.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'mkmf'
|
2
4
|
require 'rbconfig'
|
3
5
|
|
@@ -6,7 +8,7 @@ dir_config(extension_name)
|
|
6
8
|
|
7
9
|
parts = RUBY_DESCRIPTION.split(' ')
|
8
10
|
type = parts[0]
|
9
|
-
type = type[4
|
11
|
+
type = type[4..] if type.start_with?('tcs-')
|
10
12
|
is_windows = RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/
|
11
13
|
platform = RUBY_PLATFORM
|
12
14
|
version = RUBY_VERSION.split('.')
|
@@ -56,7 +58,7 @@ dflags.each do |k, v|
|
|
56
58
|
end
|
57
59
|
|
58
60
|
$CPPFLAGS += ' -Wall'
|
59
|
-
#puts "*** $CPPFLAGS: #{$CPPFLAGS}"
|
61
|
+
# puts "*** $CPPFLAGS: #{$CPPFLAGS}"
|
60
62
|
# Adding the __attribute__ flag only works with gcc compilers and even then it
|
61
63
|
# does not work to check args with varargs so just remove the check.
|
62
64
|
CONFIG['warnflags'].slice!(/ -Wsuggest-attribute=format/)
|
data/ext/oj/fast.c
CHANGED
@@ -40,7 +40,7 @@ typedef struct _doc {
|
|
40
40
|
Leaf *where; // points to current location
|
41
41
|
Leaf where_path[MAX_STACK]; // points to head of path
|
42
42
|
char *json;
|
43
|
-
unsigned long size;
|
43
|
+
unsigned long size; // number of leaves/branches in the doc
|
44
44
|
VALUE self;
|
45
45
|
Batch batches;
|
46
46
|
struct _batch batch0;
|
@@ -114,10 +114,7 @@ inline static char *ulong_fill(char *s, size_t num) {
|
|
114
114
|
char *b = buf + sizeof(buf) - 1;
|
115
115
|
|
116
116
|
*b-- = '\0';
|
117
|
-
|
118
|
-
*b = (num % 10) + '0';
|
119
|
-
}
|
120
|
-
b++;
|
117
|
+
b = oj_longlong_to_string((long long)num, false, b);
|
121
118
|
if ('\0' == *b) {
|
122
119
|
b--;
|
123
120
|
*b = '0';
|
@@ -576,7 +573,7 @@ static char *read_quoted_value(ParseInfo pi) {
|
|
576
573
|
char *h = pi->s; // head
|
577
574
|
char *t = h; // tail
|
578
575
|
|
579
|
-
h++;
|
576
|
+
h++; // skip quote character
|
580
577
|
t++;
|
581
578
|
value = h;
|
582
579
|
for (; '"' != *h; h++, t++) {
|
data/ext/oj/mimic_json.c
CHANGED
@@ -574,7 +574,6 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
574
574
|
if (T_HASH != rb_type(ropts)) {
|
575
575
|
rb_raise(rb_eArgError, "options must be a hash.");
|
576
576
|
}
|
577
|
-
|
578
577
|
rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
|
579
578
|
v = rb_hash_lookup(ropts, oj_max_nesting_sym);
|
580
579
|
if (Qtrue == v) {
|
@@ -738,6 +737,7 @@ static struct _options mimic_object_to_json_options = {0, // indent
|
|
738
737
|
0, // array_size
|
739
738
|
RaiseNan, // nan_dump
|
740
739
|
false, // omit_nil
|
740
|
+
false, // omit_null_byte
|
741
741
|
100, // max_depth
|
742
742
|
},
|
743
743
|
{
|
@@ -791,28 +791,48 @@ void oj_mimic_json_methods(VALUE json) {
|
|
791
791
|
VALUE json_error;
|
792
792
|
VALUE generator;
|
793
793
|
VALUE ext;
|
794
|
+
VALUE verbose;
|
795
|
+
|
796
|
+
// rb_undef_method doesn't work for modules or maybe sometimes
|
797
|
+
// doesn't. Anyway setting verbose should hide the warning.
|
798
|
+
verbose = rb_gv_get("$VERBOSE");
|
799
|
+
rb_gv_set("$VERBOSE", Qfalse);
|
794
800
|
|
801
|
+
rb_undef_method(json, "create_id=");
|
795
802
|
rb_define_module_function(json, "create_id=", mimic_set_create_id, 1);
|
803
|
+
rb_undef_method(json, "create_id");
|
796
804
|
rb_define_module_function(json, "create_id", mimic_create_id, 0);
|
797
805
|
|
806
|
+
rb_undef_method(json, "dump");
|
798
807
|
rb_define_module_function(json, "dump", mimic_dump, -1);
|
808
|
+
rb_undef_method(json, "load");
|
799
809
|
rb_define_module_function(json, "load", mimic_load, -1);
|
800
810
|
rb_define_module_function(json, "restore", mimic_load, -1);
|
811
|
+
rb_undef_method(json, "recurse_proc");
|
801
812
|
rb_define_module_function(json, "recurse_proc", mimic_recurse_proc, 1);
|
813
|
+
rb_undef_method(json, "[]");
|
802
814
|
rb_define_module_function(json, "[]", mimic_dump_load, -1);
|
803
815
|
|
816
|
+
rb_undef_method(json, "generate");
|
804
817
|
rb_define_module_function(json, "generate", oj_mimic_generate, -1);
|
818
|
+
rb_undef_method(json, "fast_generate");
|
805
819
|
rb_define_module_function(json, "fast_generate", oj_mimic_generate, -1);
|
820
|
+
rb_undef_method(json, "pretty_generate");
|
806
821
|
rb_define_module_function(json, "pretty_generate", oj_mimic_pretty_generate, -1);
|
807
822
|
// For older versions of JSON, the deprecated unparse methods.
|
823
|
+
rb_undef_method(json, "unparse");
|
808
824
|
rb_define_module_function(json, "unparse", oj_mimic_generate, -1);
|
809
825
|
rb_define_module_function(json, "fast_unparse", oj_mimic_generate, -1);
|
810
826
|
rb_define_module_function(json, "pretty_unparse", oj_mimic_pretty_generate, -1);
|
811
827
|
|
828
|
+
rb_undef_method(json, "parse");
|
812
829
|
rb_define_module_function(json, "parse", oj_mimic_parse, -1);
|
830
|
+
rb_undef_method(json, "parse!");
|
813
831
|
rb_define_module_function(json, "parse!", mimic_parse_bang, -1);
|
814
832
|
|
833
|
+
rb_undef_method(json, "state");
|
815
834
|
rb_define_module_function(json, "state", mimic_state, 0);
|
835
|
+
rb_gv_set("$VERBOSE", verbose);
|
816
836
|
|
817
837
|
if (rb_const_defined_at(json, rb_intern("JSONError"))) {
|
818
838
|
json_error = rb_const_get(json, rb_intern("JSONError"));
|
data/ext/oj/object.c
CHANGED
@@ -446,9 +446,7 @@ WHICH_TYPE:
|
|
446
446
|
rb_class2name(rb_obj_class(parent->val)));
|
447
447
|
return;
|
448
448
|
}
|
449
|
-
|
450
|
-
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
|
451
|
-
}
|
449
|
+
TRACE_PARSE_CALL(pi->options.trace, "set_string", pi, rval);
|
452
450
|
}
|
453
451
|
|
454
452
|
static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) {
|
@@ -517,9 +515,7 @@ WHICH_TYPE:
|
|
517
515
|
rb_class2name(rb_obj_class(parent->val)));
|
518
516
|
return;
|
519
517
|
}
|
520
|
-
|
521
|
-
oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, rval);
|
522
|
-
}
|
518
|
+
TRACE_PARSE_CALL(pi->options.trace, "add_number", pi, rval);
|
523
519
|
}
|
524
520
|
|
525
521
|
static void hash_set_value(ParseInfo pi, Val kval, VALUE value) {
|
@@ -603,9 +599,7 @@ WHICH_TYPE:
|
|
603
599
|
rb_class2name(rb_obj_class(parent->val)));
|
604
600
|
return;
|
605
601
|
}
|
606
|
-
|
607
|
-
oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, value);
|
608
|
-
}
|
602
|
+
TRACE_PARSE_CALL(pi->options.trace, "add_value", pi, value);
|
609
603
|
}
|
610
604
|
|
611
605
|
static VALUE start_hash(ParseInfo pi) {
|
@@ -651,32 +645,24 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c
|
|
651
645
|
}
|
652
646
|
rval = str_to_value(pi, str, len, orig);
|
653
647
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
654
|
-
|
655
|
-
oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rval);
|
656
|
-
}
|
648
|
+
TRACE_PARSE_CALL(pi->options.trace, "append_string", pi, rval);
|
657
649
|
}
|
658
650
|
|
659
651
|
static void array_append_num(ParseInfo pi, NumInfo ni) {
|
660
652
|
volatile VALUE rval = oj_num_as_value(ni);
|
661
653
|
|
662
654
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
663
|
-
|
664
|
-
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
665
|
-
}
|
655
|
+
TRACE_PARSE_CALL(pi->options.trace, "append_number", pi, rval);
|
666
656
|
}
|
667
657
|
|
668
658
|
static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
669
659
|
pi->stack.head->val = str_to_value(pi, str, len, orig);
|
670
|
-
|
671
|
-
oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
|
672
|
-
}
|
660
|
+
TRACE_PARSE_CALL(pi->options.trace, "add_string", pi, pi->stack.head->val);
|
673
661
|
}
|
674
662
|
|
675
663
|
static void add_num(ParseInfo pi, NumInfo ni) {
|
676
664
|
pi->stack.head->val = oj_num_as_value(ni);
|
677
|
-
|
678
|
-
oj_trace_parse_call("add_num", pi, __FILE__, __LINE__, pi->stack.head->val);
|
679
|
-
}
|
665
|
+
TRACE_PARSE_CALL(pi->options.trace, "add_num", pi, pi->stack.head->val);
|
680
666
|
}
|
681
667
|
|
682
668
|
void oj_set_object_callbacks(ParseInfo pi) {
|
data/ext/oj/oj.c
CHANGED
@@ -135,6 +135,7 @@ static VALUE newline_sym;
|
|
135
135
|
static VALUE nilnil_sym;
|
136
136
|
static VALUE null_sym;
|
137
137
|
static VALUE object_sym;
|
138
|
+
static VALUE omit_null_byte_sym;
|
138
139
|
static VALUE omit_nil_sym;
|
139
140
|
static VALUE rails_sym;
|
140
141
|
static VALUE raise_sym;
|
@@ -222,6 +223,7 @@ struct _options oj_default_options = {
|
|
222
223
|
0, // array_size
|
223
224
|
AutoNan, // nan_dump
|
224
225
|
false, // omit_nil
|
226
|
+
false, // omit_null_byte
|
225
227
|
MAX_DEPTH, // max_depth
|
226
228
|
},
|
227
229
|
{
|
@@ -230,7 +232,7 @@ struct _options oj_default_options = {
|
|
230
232
|
NULL, // tail
|
231
233
|
{'\0'}, // err
|
232
234
|
},
|
233
|
-
NULL,
|
235
|
+
NULL, // ignore
|
234
236
|
};
|
235
237
|
|
236
238
|
/* Document-method: default_options()
|
@@ -291,6 +293,7 @@ struct _options oj_default_options = {
|
|
291
293
|
*used
|
292
294
|
* - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
|
293
295
|
* - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
|
296
|
+
* - *:omit_null_byte* [_true_|_false_] if true null bytes in strings will be omitted when dumping
|
294
297
|
* - *:ignore* [_nil_|_Array_] either nil or an Array of classes to ignore when dumping
|
295
298
|
* - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when dumping in
|
296
299
|
*object or custom mode.
|
@@ -384,6 +387,7 @@ static VALUE get_def_opts(VALUE self) {
|
|
384
387
|
opts,
|
385
388
|
cache_keys_sym,
|
386
389
|
(Yes == oj_default_options.cache_keys) ? Qtrue : ((No == oj_default_options.cache_keys) ? Qfalse : Qnil));
|
390
|
+
|
387
391
|
switch (oj_default_options.mode) {
|
388
392
|
case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
|
389
393
|
case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
|
@@ -459,6 +463,7 @@ static VALUE get_def_opts(VALUE self) {
|
|
459
463
|
default: rb_hash_aset(opts, nan_sym, auto_sym); break;
|
460
464
|
}
|
461
465
|
rb_hash_aset(opts, omit_nil_sym, oj_default_options.dump_opts.omit_nil ? Qtrue : Qfalse);
|
466
|
+
rb_hash_aset(opts, omit_null_byte_sym, oj_default_options.dump_opts.omit_null_byte ? Qtrue : Qfalse);
|
462
467
|
rb_hash_aset(opts, oj_hash_class_sym, oj_default_options.hash_class);
|
463
468
|
rb_hash_aset(opts, oj_array_class_sym, oj_default_options.array_class);
|
464
469
|
|
@@ -865,6 +870,17 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
|
|
865
870
|
} else {
|
866
871
|
rb_raise(rb_eArgError, ":omit_nil must be true or false.");
|
867
872
|
}
|
873
|
+
} else if (omit_null_byte_sym == k) {
|
874
|
+
if (Qnil == v) {
|
875
|
+
return ST_CONTINUE;
|
876
|
+
}
|
877
|
+
if (Qtrue == v) {
|
878
|
+
copts->dump_opts.omit_null_byte = true;
|
879
|
+
} else if (Qfalse == v) {
|
880
|
+
copts->dump_opts.omit_null_byte = false;
|
881
|
+
} else {
|
882
|
+
rb_raise(rb_eArgError, ":omit_null_byte must be true or false.");
|
883
|
+
}
|
868
884
|
} else if (oj_ascii_only_sym == k) {
|
869
885
|
// This is here only for backwards compatibility with the original Oj.
|
870
886
|
if (Qtrue == v) {
|
@@ -1278,8 +1294,9 @@ static VALUE dump(int argc, VALUE *argv, VALUE self) {
|
|
1278
1294
|
|
1279
1295
|
oj_out_init(arg.out);
|
1280
1296
|
|
1281
|
-
arg.out->omit_nil
|
1282
|
-
arg.out->
|
1297
|
+
arg.out->omit_nil = copts.dump_opts.omit_nil;
|
1298
|
+
arg.out->omit_null_byte = copts.dump_opts.omit_null_byte;
|
1299
|
+
arg.out->caller = CALLER_DUMP;
|
1283
1300
|
|
1284
1301
|
return rb_ensure(dump_body, (VALUE)&arg, dump_ensure, (VALUE)&arg);
|
1285
1302
|
}
|
@@ -1326,7 +1343,8 @@ static VALUE to_json(int argc, VALUE *argv, VALUE self) {
|
|
1326
1343
|
|
1327
1344
|
oj_out_init(&out);
|
1328
1345
|
|
1329
|
-
out.omit_nil
|
1346
|
+
out.omit_nil = copts.dump_opts.omit_nil;
|
1347
|
+
out.omit_null_byte = copts.dump_opts.omit_null_byte;
|
1330
1348
|
// For obj.to_json or generate nan is not allowed but if called from dump
|
1331
1349
|
// it is.
|
1332
1350
|
oj_dump_obj_to_json_using_params(*argv, &copts, &out, argc - 1, argv + 1);
|
@@ -1967,6 +1985,8 @@ void Init_oj(void) {
|
|
1967
1985
|
rb_gc_register_address(&oj_quirks_mode_sym);
|
1968
1986
|
oj_safe_sym = ID2SYM(rb_intern("safe"));
|
1969
1987
|
rb_gc_register_address(&oj_safe_sym);
|
1988
|
+
omit_null_byte_sym = ID2SYM(rb_intern("omit_null_byte"));
|
1989
|
+
rb_gc_register_address(&omit_null_byte_sym);
|
1970
1990
|
oj_space_before_sym = ID2SYM(rb_intern("space_before"));
|
1971
1991
|
rb_gc_register_address(&oj_space_before_sym);
|
1972
1992
|
oj_space_sym = ID2SYM(rb_intern("space"));
|
data/ext/oj/oj.h
CHANGED
@@ -124,6 +124,7 @@ typedef struct _dumpOpts {
|
|
124
124
|
uint8_t array_size;
|
125
125
|
char nan_dump; // NanDump
|
126
126
|
bool omit_nil;
|
127
|
+
bool omit_null_byte;
|
127
128
|
int max_depth;
|
128
129
|
} *DumpOpts;
|
129
130
|
|
@@ -199,6 +200,7 @@ typedef struct _out {
|
|
199
200
|
uint32_t hash_cnt;
|
200
201
|
bool allocated;
|
201
202
|
bool omit_nil;
|
203
|
+
bool omit_null_byte;
|
202
204
|
int argc;
|
203
205
|
VALUE *argv;
|
204
206
|
DumpCaller caller; // used for the mimic json only
|
@@ -260,12 +262,13 @@ extern VALUE oj_custom_parse_cstr(int argc, VALUE *argv, char *json, size_t len)
|
|
260
262
|
extern bool oj_hash_has_key(VALUE hash, VALUE key);
|
261
263
|
extern void oj_parse_options(VALUE ropts, Options copts);
|
262
264
|
|
263
|
-
extern void
|
264
|
-
extern void
|
265
|
-
extern void
|
266
|
-
extern void
|
267
|
-
extern void
|
268
|
-
extern void
|
265
|
+
extern void oj_dump_obj_to_json(VALUE obj, Options copts, Out out);
|
266
|
+
extern void oj_dump_obj_to_json_using_params(VALUE obj, Options copts, Out out, int argc, VALUE *argv);
|
267
|
+
extern void oj_write_obj_to_file(VALUE obj, const char *path, Options copts);
|
268
|
+
extern void oj_write_obj_to_stream(VALUE obj, VALUE stream, Options copts);
|
269
|
+
extern void oj_dump_leaf_to_json(Leaf leaf, Options copts, Out out);
|
270
|
+
extern void oj_write_leaf_to_file(Leaf leaf, const char *path, Options copts);
|
271
|
+
extern char *oj_longlong_to_string(long long num, bool negative, char *buf);
|
269
272
|
|
270
273
|
extern void oj_str_writer_push_key(StrWriter sw, const char *key);
|
271
274
|
extern void oj_str_writer_push_object(StrWriter sw, const char *key);
|
@@ -323,6 +326,7 @@ extern VALUE oj_max_nesting_sym;
|
|
323
326
|
extern VALUE oj_object_class_sym;
|
324
327
|
extern VALUE oj_object_nl_sym;
|
325
328
|
extern VALUE oj_quirks_mode_sym;
|
329
|
+
extern VALUE oj_skip_null_byte_sym;
|
326
330
|
extern VALUE oj_space_before_sym;
|
327
331
|
extern VALUE oj_space_sym;
|
328
332
|
extern VALUE oj_symbolize_names_sym;
|
data/ext/oj/parse.c
CHANGED
@@ -426,6 +426,7 @@ static void read_num(ParseInfo pi) {
|
|
426
426
|
struct _numInfo ni;
|
427
427
|
Val parent = stack_peek(&pi->stack);
|
428
428
|
|
429
|
+
ni.pi = pi;
|
429
430
|
ni.str = pi->cur;
|
430
431
|
ni.i = 0;
|
431
432
|
ni.num = 0;
|
@@ -709,10 +710,7 @@ void oj_parse2(ParseInfo pi) {
|
|
709
710
|
case '[': array_start(pi); break;
|
710
711
|
case ']': array_end(pi); break;
|
711
712
|
case ',': comma(pi); break;
|
712
|
-
case '"':
|
713
|
-
read_str(pi);
|
714
|
-
break;
|
715
|
-
// case '+':
|
713
|
+
case '"': read_str(pi); break;
|
716
714
|
case '+':
|
717
715
|
if (CompatMode == pi->options.mode) {
|
718
716
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
|
@@ -877,7 +875,7 @@ oj_num_as_value(NumInfo ni) {
|
|
877
875
|
double d = strtod(ni->str, &end);
|
878
876
|
|
879
877
|
if ((long)ni->len != (long)(end - ni->str)) {
|
880
|
-
rb_raise(
|
878
|
+
rb_raise(ni->pi->err_class, "Invalid float");
|
881
879
|
}
|
882
880
|
rnum = rb_float_new(d);
|
883
881
|
}
|