oj 3.13.7 → 3.13.23
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 +75 -0
- data/README.md +11 -0
- data/ext/oj/buf.h +4 -0
- data/ext/oj/circarray.c +1 -1
- data/ext/oj/code.c +15 -22
- data/ext/oj/compat.c +10 -10
- data/ext/oj/custom.c +66 -112
- data/ext/oj/dump.c +147 -184
- data/ext/oj/dump.h +25 -8
- data/ext/oj/dump_compat.c +47 -89
- data/ext/oj/dump_leaf.c +14 -58
- data/ext/oj/dump_object.c +72 -188
- data/ext/oj/dump_strict.c +19 -31
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/extconf.rb +5 -4
- data/ext/oj/fast.c +36 -24
- data/ext/oj/intern.c +22 -12
- data/ext/oj/intern.h +1 -1
- data/ext/oj/mimic_json.c +74 -73
- data/ext/oj/object.c +54 -72
- data/ext/oj/odd.c +83 -63
- data/ext/oj/odd.h +13 -13
- data/ext/oj/oj.c +166 -175
- data/ext/oj/oj.h +25 -3
- data/ext/oj/parse.c +123 -79
- data/ext/oj/parse.h +2 -0
- data/ext/oj/parser.c +77 -21
- data/ext/oj/parser.h +12 -0
- data/ext/oj/rails.c +46 -70
- data/ext/oj/rails.h +1 -1
- data/ext/oj/reader.c +2 -0
- data/ext/oj/saj.c +11 -23
- data/ext/oj/saj2.c +333 -85
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/sparse.c +4 -0
- data/ext/oj/stream_writer.c +3 -1
- data/ext/oj/strict.c +13 -13
- data/ext/oj/string_writer.c +12 -5
- data/ext/oj/usual.c +86 -131
- data/ext/oj/usual.h +68 -0
- data/ext/oj/val_stack.c +1 -1
- data/ext/oj/validate.c +21 -26
- data/ext/oj/wab.c +22 -27
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/state.rb +1 -1
- data/lib/oj/version.rb +1 -1
- data/pages/Compatibility.md +1 -1
- data/pages/JsonGem.md +15 -0
- data/pages/Modes.md +6 -3
- data/pages/Options.md +6 -0
- data/pages/Rails.md +12 -0
- data/test/activesupport7/abstract_unit.rb +49 -0
- data/test/activesupport7/decoding_test.rb +125 -0
- data/test/activesupport7/encoding_test.rb +486 -0
- data/test/activesupport7/encoding_test_cases.rb +104 -0
- data/test/activesupport7/time_zone_test_helpers.rb +47 -0
- data/test/bar.rb +3 -8
- data/test/bug.rb +16 -0
- data/test/foo.rb +71 -7
- data/test/helper.rb +8 -2
- data/test/json_gem/json_generator_test.rb +5 -4
- data/test/json_gem/json_parser_test.rb +8 -1
- data/test/json_gem/test_helper.rb +7 -3
- data/test/perf_dump.rb +50 -0
- data/test/test_compat.rb +25 -0
- data/test/test_custom.rb +13 -2
- data/test/test_fast.rb +37 -7
- data/test/test_file.rb +23 -7
- data/test/test_gc.rb +11 -0
- data/test/test_object.rb +8 -10
- data/test/test_parser.rb +3 -19
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +92 -2
- data/test/test_saj.rb +1 -1
- data/test/test_scp.rb +2 -4
- data/test/test_strict.rb +2 -0
- data/test/test_various.rb +32 -2
- data/test/test_wab.rb +2 -0
- data/test/tests.rb +9 -1
- data/test/tests_mimic.rb +9 -0
- data/test/tests_mimic_addition.rb +9 -0
- metadata +15 -115
data/ext/oj/encoder.c
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
// Copyright (c) 2011, 2022 Peter Ohler. All rights reserved.
|
2
|
+
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
3
|
+
|
4
|
+
#include "oj.h"
|
5
|
+
|
6
|
+
typedef struct _encoder {
|
7
|
+
int indent; // indention for dump, default 2
|
8
|
+
char circular; // YesNo
|
9
|
+
char escape_mode; // Escape_Mode
|
10
|
+
char mode; // Mode
|
11
|
+
char time_format; // TimeFormat
|
12
|
+
char bigdec_as_num; // YesNo
|
13
|
+
char to_hash; // YesNo
|
14
|
+
char to_json; // YesNo
|
15
|
+
char as_json; // YesNo
|
16
|
+
char raw_json; // YesNo
|
17
|
+
char trace; // YesNo
|
18
|
+
char sec_prec_set; // boolean (0 or 1)
|
19
|
+
char ignore_under; // YesNo - ignore attrs starting with _ if true in object and custom modes
|
20
|
+
int64_t int_range_min; // dump numbers below as string
|
21
|
+
int64_t int_range_max; // dump numbers above as string
|
22
|
+
const char* create_id; // 0 or string
|
23
|
+
size_t create_id_len; // length of create_id
|
24
|
+
int sec_prec; // second precision when dumping time
|
25
|
+
char float_prec; // float precision, linked to float_fmt
|
26
|
+
char float_fmt[7]; // float format for dumping, if empty use Ruby
|
27
|
+
struct _dumpOpts dump_opts;
|
28
|
+
struct _rxClass str_rx;
|
29
|
+
VALUE* ignore; // Qnil terminated array of classes or NULL
|
30
|
+
} * Encoder;
|
31
|
+
|
32
|
+
/*
|
33
|
+
rb_define_module_function(Oj, "encode", encode, -1);
|
34
|
+
rb_define_module_function(Oj, "to_file", to_file, -1); // or maybe just write
|
35
|
+
rb_define_module_function(Oj, "to_stream", to_stream, -1);
|
36
|
+
*/
|
37
|
+
|
38
|
+
// write(to, obj)
|
39
|
+
// if to is a string then open file
|
40
|
+
// else if stream then write to stream
|
41
|
+
// handle non-blocking
|
42
|
+
|
43
|
+
// should each mode have a different encoder or use delegates like the parser?
|
data/ext/oj/extconf.rb
CHANGED
@@ -23,14 +23,10 @@ dflags = {
|
|
23
23
|
'RSTRUCT_LEN_RETURNS_INTEGER_OBJECT' => ('ruby' == type && '2' == version[0] && '4' == version[1] && '1' >= version[2]) ? 1 : 0,
|
24
24
|
}
|
25
25
|
|
26
|
-
have_func('rb_time_timespec')
|
27
|
-
have_func('rb_ivar_count')
|
28
|
-
have_func('rb_ivar_foreach')
|
29
26
|
# Support for compaction.
|
30
27
|
have_func('rb_gc_mark_movable')
|
31
28
|
have_func('stpcpy')
|
32
29
|
have_func('pthread_mutex_init')
|
33
|
-
have_func('rb_enc_associate')
|
34
30
|
have_func('rb_enc_interned_str')
|
35
31
|
have_func('rb_ext_ractor_safe', 'ruby.h')
|
36
32
|
# rb_hash_bulk_insert is deep down in a header not included in normal build and that seems to fool have_func.
|
@@ -38,6 +34,11 @@ have_func('rb_hash_bulk_insert', 'ruby.h') unless '2' == version[0] && '6' == ve
|
|
38
34
|
|
39
35
|
dflags['OJ_DEBUG'] = true unless ENV['OJ_DEBUG'].nil?
|
40
36
|
|
37
|
+
if with_config('--with-sse42')
|
38
|
+
$CPPFLAGS += ' -msse4.2'
|
39
|
+
dflags['OJ_USE_SSE4_2'] = 1
|
40
|
+
end
|
41
|
+
|
41
42
|
dflags.each do |k,v|
|
42
43
|
if v.nil?
|
43
44
|
$CPPFLAGS += " -D#{k}"
|
data/ext/oj/fast.c
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
|
14
14
|
#include "encode.h"
|
15
15
|
#include "oj.h"
|
16
|
+
#include "dump.h"
|
16
17
|
|
17
18
|
// maximum to allocate on the stack, arbitrary limit
|
18
19
|
#define SMALL_JSON 65536
|
@@ -676,21 +677,23 @@ static void free_doc_cb(void *x) {
|
|
676
677
|
}
|
677
678
|
|
678
679
|
static void mark_leaf(Leaf leaf) {
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
680
|
+
if (NULL != leaf) {
|
681
|
+
switch (leaf->value_type) {
|
682
|
+
case COL_VAL:
|
683
|
+
if (NULL != leaf->elements) {
|
684
|
+
Leaf first = leaf->elements->next;
|
685
|
+
Leaf e = first;
|
684
686
|
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
687
|
+
do {
|
688
|
+
mark_leaf(e);
|
689
|
+
e = e->next;
|
690
|
+
} while (e != first);
|
691
|
+
}
|
692
|
+
break;
|
693
|
+
case RUBY_VAL: mark(leaf->value); break;
|
692
694
|
|
693
|
-
|
695
|
+
default: break;
|
696
|
+
}
|
694
697
|
}
|
695
698
|
}
|
696
699
|
|
@@ -771,7 +774,7 @@ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) {
|
|
771
774
|
pi.doc = doc;
|
772
775
|
#if IS_WINDOWS
|
773
776
|
// assume a 1M stack and give half to ruby
|
774
|
-
pi.stack_min = (void*)((char*)&pi - (
|
777
|
+
pi.stack_min = (void *)((char *)&pi - (512L * 1024L));
|
775
778
|
#else
|
776
779
|
{
|
777
780
|
struct rlimit lim;
|
@@ -879,6 +882,10 @@ static Leaf get_leaf(Leaf *stack, Leaf *lp, const char *path) {
|
|
879
882
|
}
|
880
883
|
} else if (NULL == leaf->elements) {
|
881
884
|
leaf = NULL;
|
885
|
+
} else if (STR_VAL == leaf->value_type || RUBY_VAL == leaf->value_type) {
|
886
|
+
// We are trying to get a children of a leaf, which
|
887
|
+
// doesn't exist.
|
888
|
+
leaf = NULL;
|
882
889
|
} else if (COL_VAL == leaf->value_type) {
|
883
890
|
Leaf first = leaf->elements->next;
|
884
891
|
Leaf e = first;
|
@@ -1373,8 +1380,8 @@ static VALUE doc_fetch(int argc, VALUE *argv, VALUE self) {
|
|
1373
1380
|
* Returns true if the value at the location identified by the path exists.
|
1374
1381
|
* @param [String] path path to the location
|
1375
1382
|
* @example
|
1376
|
-
* Oj::Doc.open('[1,2]') { |doc| doc.exists('/1') } #=> true
|
1377
|
-
* Oj::Doc.open('[1,2]') { |doc| doc.exists('/3') } #=> false
|
1383
|
+
* Oj::Doc.open('[1,2]') { |doc| doc.exists?('/1') } #=> true
|
1384
|
+
* Oj::Doc.open('[1,2]') { |doc| doc.exists?('/3') } #=> false
|
1378
1385
|
*/
|
1379
1386
|
static VALUE doc_exists(VALUE self, VALUE str) {
|
1380
1387
|
Doc doc;
|
@@ -1488,6 +1495,7 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
|
|
1488
1495
|
Doc doc = self_doc(self);
|
1489
1496
|
const char *path = 0;
|
1490
1497
|
size_t wlen;
|
1498
|
+
Leaf * where_orig = doc->where;
|
1491
1499
|
|
1492
1500
|
wlen = doc->where - doc->where_path;
|
1493
1501
|
if (0 < wlen) {
|
@@ -1504,9 +1512,13 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
|
|
1504
1512
|
if (0 < wlen) {
|
1505
1513
|
memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
|
1506
1514
|
}
|
1515
|
+
doc->where = where_orig;
|
1507
1516
|
return Qnil;
|
1508
1517
|
}
|
1509
1518
|
}
|
1519
|
+
if (NULL == doc->where || NULL == *doc->where) {
|
1520
|
+
return Qnil;
|
1521
|
+
}
|
1510
1522
|
if (COL_VAL == (*doc->where)->value_type && 0 != (*doc->where)->elements) {
|
1511
1523
|
Leaf first = (*doc->where)->elements->next;
|
1512
1524
|
Leaf e = first;
|
@@ -1521,6 +1533,7 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) {
|
|
1521
1533
|
if (0 < wlen) {
|
1522
1534
|
memcpy(doc->where_path, save_path, sizeof(Leaf) * (wlen + 1));
|
1523
1535
|
}
|
1536
|
+
doc->where = where_orig;
|
1524
1537
|
}
|
1525
1538
|
return Qnil;
|
1526
1539
|
}
|
@@ -1600,18 +1613,15 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) {
|
|
1600
1613
|
volatile VALUE rjson;
|
1601
1614
|
|
1602
1615
|
if (0 == filename) {
|
1603
|
-
char buf[4096];
|
1604
1616
|
struct _out out;
|
1605
1617
|
|
1606
|
-
out
|
1607
|
-
|
1608
|
-
out.allocated = false;
|
1618
|
+
oj_out_init(&out);
|
1619
|
+
|
1609
1620
|
out.omit_nil = oj_default_options.dump_opts.omit_nil;
|
1610
1621
|
oj_dump_leaf_to_json(leaf, &oj_default_options, &out);
|
1611
1622
|
rjson = rb_str_new2(out.buf);
|
1612
|
-
|
1613
|
-
|
1614
|
-
}
|
1623
|
+
|
1624
|
+
oj_out_free(&out);
|
1615
1625
|
} else {
|
1616
1626
|
oj_write_leaf_to_file(leaf, filename, &oj_default_options);
|
1617
1627
|
rjson = Qnil;
|
@@ -1707,8 +1717,10 @@ static VALUE doc_not_implemented(VALUE self) {
|
|
1707
1717
|
* # Now try again using a path to Oj::Doc.fetch() directly and not using a
|
1708
1718
|
* block. doc = Oj::Doc.open(json) doc.fetch('/2/three') #=> 3 doc.close()
|
1709
1719
|
*/
|
1710
|
-
void oj_init_doc() {
|
1720
|
+
void oj_init_doc(void) {
|
1711
1721
|
oj_doc_class = rb_define_class_under(Oj, "Doc", rb_cObject);
|
1722
|
+
rb_gc_register_address(&oj_doc_class);
|
1723
|
+
rb_undef_alloc_func(oj_doc_class);
|
1712
1724
|
rb_define_singleton_method(oj_doc_class, "open", doc_open, 1);
|
1713
1725
|
rb_define_singleton_method(oj_doc_class, "open_file", doc_open_file, 1);
|
1714
1726
|
rb_define_singleton_method(oj_doc_class, "parse", doc_open, 1);
|
data/ext/oj/intern.c
CHANGED
@@ -37,13 +37,10 @@ typedef struct _hash {
|
|
37
37
|
struct _hash class_hash;
|
38
38
|
struct _hash attr_hash;
|
39
39
|
|
40
|
-
static struct _cache *str_cache = NULL;
|
41
40
|
static VALUE str_cache_obj;
|
42
41
|
|
43
|
-
static struct _cache *sym_cache = NULL;
|
44
42
|
static VALUE sym_cache_obj;
|
45
43
|
|
46
|
-
static struct _cache *attr_cache = NULL;
|
47
44
|
static VALUE attr_cache_obj;
|
48
45
|
|
49
46
|
static VALUE form_str(const char *str, size_t len) {
|
@@ -86,18 +83,22 @@ static VALUE form_attr(const char *str, size_t len) {
|
|
86
83
|
return (VALUE)rb_intern3(buf, len + 1, oj_utf8_encoding);
|
87
84
|
}
|
88
85
|
|
89
|
-
void oj_hash_init() {
|
86
|
+
void oj_hash_init(void) {
|
90
87
|
VALUE cache_class = rb_define_class_under(Oj, "Cache", rb_cObject);
|
88
|
+
rb_undef_alloc_func(cache_class);
|
91
89
|
|
92
|
-
|
90
|
+
rb_gc_register_address(&cache_class);
|
91
|
+
rb_undef_alloc_func(cache_class);
|
92
|
+
|
93
|
+
struct _cache *str_cache = cache_create(0, form_str, true, true);
|
93
94
|
str_cache_obj = Data_Wrap_Struct(cache_class, cache_mark, cache_free, str_cache);
|
94
95
|
rb_gc_register_address(&str_cache_obj);
|
95
96
|
|
96
|
-
sym_cache = cache_create(0, form_sym, true, true);
|
97
|
+
struct _cache *sym_cache = cache_create(0, form_sym, true, true);
|
97
98
|
sym_cache_obj = Data_Wrap_Struct(cache_class, cache_mark, cache_free, sym_cache);
|
98
99
|
rb_gc_register_address(&sym_cache_obj);
|
99
100
|
|
100
|
-
attr_cache
|
101
|
+
struct _cache *attr_cache = cache_create(0, form_attr, false, true);
|
101
102
|
attr_cache_obj = Data_Wrap_Struct(cache_class, cache_mark, cache_free, attr_cache);
|
102
103
|
rb_gc_register_address(&attr_cache_obj);
|
103
104
|
|
@@ -118,18 +119,18 @@ oj_str_intern(const char *key, size_t len) {
|
|
118
119
|
#if HAVE_RB_ENC_INTERNED_STR && 0
|
119
120
|
return rb_enc_interned_str(key, len, rb_utf8_encoding());
|
120
121
|
#else
|
121
|
-
return cache_intern(
|
122
|
+
return cache_intern(DATA_PTR(str_cache_obj), key, len);
|
122
123
|
#endif
|
123
124
|
}
|
124
125
|
|
125
126
|
VALUE
|
126
127
|
oj_sym_intern(const char *key, size_t len) {
|
127
|
-
|
128
|
+
return cache_intern(DATA_PTR(sym_cache_obj), key, len);
|
128
129
|
}
|
129
130
|
|
130
131
|
ID
|
131
132
|
oj_attr_intern(const char *key, size_t len) {
|
132
|
-
|
133
|
+
return cache_intern(DATA_PTR(attr_cache_obj), key, len);
|
133
134
|
}
|
134
135
|
|
135
136
|
static uint64_t hash_calc(const uint8_t *key, size_t len) {
|
@@ -186,6 +187,7 @@ static VALUE resolve_classpath(ParseInfo pi, const char *name, size_t len, int a
|
|
186
187
|
char * end = class_name + sizeof(class_name) - 1;
|
187
188
|
char * s;
|
188
189
|
const char *n = name;
|
190
|
+
size_t nlen = len;
|
189
191
|
|
190
192
|
clas = rb_cObject;
|
191
193
|
for (s = class_name; 0 < len; n++, len--) {
|
@@ -208,7 +210,12 @@ static VALUE resolve_classpath(ParseInfo pi, const char *name, size_t len, int a
|
|
208
210
|
}
|
209
211
|
*s = '\0';
|
210
212
|
if (Qundef == (clas = resolve_classname(clas, class_name, auto_define))) {
|
211
|
-
|
213
|
+
if (sizeof(class_name) <= nlen) {
|
214
|
+
nlen = sizeof(class_name) - 1;
|
215
|
+
}
|
216
|
+
strncpy(class_name, name, nlen);
|
217
|
+
class_name[nlen] = '\0';
|
218
|
+
oj_set_error_at(pi, error_class, __FILE__, __LINE__, "class '%s' is not defined", class_name);
|
212
219
|
if (Qnil != error_class) {
|
213
220
|
pi->err_class = error_class;
|
214
221
|
}
|
@@ -269,6 +276,7 @@ VALUE oj_class_intern(const char *key, size_t len, bool safe, ParseInfo pi, int
|
|
269
276
|
bucket->len = len;
|
270
277
|
bucket->val = resolve_classpath(pi, key, len, auto_define, error_class);
|
271
278
|
}
|
279
|
+
rb_gc_register_mark_object(bucket->val);
|
272
280
|
return bucket->val;
|
273
281
|
}
|
274
282
|
|
@@ -281,8 +289,10 @@ char *oj_strndup(const char *s, size_t len) {
|
|
281
289
|
return d;
|
282
290
|
}
|
283
291
|
|
284
|
-
|
292
|
+
/*
|
293
|
+
void intern_cleanup(void) {
|
285
294
|
cache_free(str_cache);
|
286
295
|
cache_free(sym_cache);
|
287
296
|
cache_free(attr_cache);
|
288
297
|
}
|
298
|
+
*/
|
data/ext/oj/intern.h
CHANGED
data/ext/oj/mimic_json.c
CHANGED
@@ -6,8 +6,6 @@
|
|
6
6
|
#include "oj.h"
|
7
7
|
#include "parse.h"
|
8
8
|
|
9
|
-
static VALUE symbolize_names_sym = Qundef;
|
10
|
-
|
11
9
|
extern const char oj_json_class[];
|
12
10
|
|
13
11
|
VALUE oj_array_nl_sym;
|
@@ -200,7 +198,6 @@ static int mimic_limit_arg(VALUE a) {
|
|
200
198
|
* Returns [_String_] a JSON string.
|
201
199
|
*/
|
202
200
|
static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
|
203
|
-
char buf[4096];
|
204
201
|
struct _out out;
|
205
202
|
struct _options copts = oj_default_options;
|
206
203
|
VALUE rstr;
|
@@ -208,9 +205,9 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
208
205
|
|
209
206
|
copts.str_rx.head = NULL;
|
210
207
|
copts.str_rx.tail = NULL;
|
211
|
-
|
212
|
-
out
|
213
|
-
|
208
|
+
|
209
|
+
oj_out_init(&out);
|
210
|
+
|
214
211
|
out.caller = CALLER_DUMP;
|
215
212
|
copts.escape_mode = JXEsc;
|
216
213
|
copts.mode = CompatMode;
|
@@ -259,9 +256,9 @@ static VALUE mimic_dump(int argc, VALUE *argv, VALUE self) {
|
|
259
256
|
rb_funcall2(io, oj_write_id, 1, args);
|
260
257
|
rstr = io;
|
261
258
|
}
|
262
|
-
|
263
|
-
|
264
|
-
|
259
|
+
|
260
|
+
oj_out_free(&out);
|
261
|
+
|
265
262
|
return rstr;
|
266
263
|
}
|
267
264
|
|
@@ -274,7 +271,7 @@ static int mimic_walk(VALUE key, VALUE obj, VALUE proc) {
|
|
274
271
|
size_t i;
|
275
272
|
|
276
273
|
for (i = 0; i < cnt; i++) {
|
277
|
-
mimic_walk(Qnil,
|
274
|
+
mimic_walk(Qnil, RARRAY_AREF(obj, i), proc);
|
278
275
|
}
|
279
276
|
break;
|
280
277
|
}
|
@@ -360,15 +357,16 @@ static VALUE mimic_dump_load(int argc, VALUE *argv, VALUE self) {
|
|
360
357
|
}
|
361
358
|
|
362
359
|
static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
363
|
-
char buf[4096];
|
364
360
|
struct _out out;
|
365
361
|
VALUE rstr;
|
366
362
|
|
367
|
-
|
363
|
+
if (0 == argc) {
|
364
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0))");
|
365
|
+
}
|
366
|
+
memset(out.stack_buffer, 0, sizeof(out.stack_buffer));
|
367
|
+
|
368
|
+
oj_out_init(&out);
|
368
369
|
|
369
|
-
out.buf = buf;
|
370
|
-
out.end = buf + sizeof(buf) - 10;
|
371
|
-
out.allocated = false;
|
372
370
|
out.omit_nil = copts->dump_opts.omit_nil;
|
373
371
|
out.caller = CALLER_GENERATE;
|
374
372
|
// For obj.to_json or generate nan is not allowed but if called from dump
|
@@ -390,6 +388,10 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
390
388
|
VALUE active_hack[1];
|
391
389
|
|
392
390
|
if (Qundef == state_class) {
|
391
|
+
rb_warn(
|
392
|
+
"Oj::Rails.mimic_JSON was called implicitly. "
|
393
|
+
"Call it explicitly beforehand if you want to remove this warning."
|
394
|
+
);
|
393
395
|
oj_define_mimic_json(0, NULL, Qnil);
|
394
396
|
}
|
395
397
|
active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
|
@@ -400,9 +402,9 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
400
402
|
}
|
401
403
|
rstr = rb_str_new2(out.buf);
|
402
404
|
rstr = oj_encode(rstr);
|
403
|
-
|
404
|
-
|
405
|
-
|
405
|
+
|
406
|
+
oj_out_free(&out);
|
407
|
+
|
406
408
|
return rstr;
|
407
409
|
}
|
408
410
|
|
@@ -459,9 +461,12 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
459
461
|
// a Hash. I haven't dug deep enough to find out why but using a State
|
460
462
|
// instance and not a Hash gives the desired behavior.
|
461
463
|
*rargs = *argv;
|
462
|
-
if (
|
464
|
+
if (0 == argc) {
|
465
|
+
rb_raise(rb_eArgError, "wrong number of arguments (0))");
|
466
|
+
}
|
467
|
+
if (1 == argc || Qnil == argv[1]) {
|
463
468
|
h = rb_hash_new();
|
464
|
-
} else
|
469
|
+
} else {
|
465
470
|
h = argv[1];
|
466
471
|
}
|
467
472
|
if (!oj_hash_has_key(h, oj_indent_sym)) {
|
@@ -480,6 +485,10 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
480
485
|
rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
|
481
486
|
}
|
482
487
|
if (Qundef == state_class) {
|
488
|
+
rb_warn(
|
489
|
+
"Oj::Rails.mimic_JSON was called implicitly. "
|
490
|
+
"Call it explicitly beforehand if you want to remove this warning."
|
491
|
+
);
|
483
492
|
oj_define_mimic_json(0, NULL, Qnil);
|
484
493
|
}
|
485
494
|
rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
|
@@ -501,6 +510,44 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
|
501
510
|
return mimic_generate_core(2, rargs, &copts);
|
502
511
|
}
|
503
512
|
|
513
|
+
static int parse_options_cb(VALUE k, VALUE v, VALUE info) {
|
514
|
+
struct _parseInfo *pi = (struct _parseInfo *)info;
|
515
|
+
|
516
|
+
if (oj_symbolize_names_sym == k) {
|
517
|
+
pi->options.sym_key = (Qtrue == v) ? Yes : No;
|
518
|
+
} else if (oj_quirks_mode_sym == k) {
|
519
|
+
pi->options.quirks_mode = (Qtrue == v) ? Yes : No;
|
520
|
+
} else if (oj_create_additions_sym == k) {
|
521
|
+
pi->options.create_ok = (Qtrue == v) ? Yes : No;
|
522
|
+
} else if (oj_allow_nan_sym == k) {
|
523
|
+
pi->options.allow_nan = (Qtrue == v) ? Yes : No;
|
524
|
+
} else if (oj_hash_class_sym == k) {
|
525
|
+
if (Qnil == v) {
|
526
|
+
pi->options.hash_class = Qnil;
|
527
|
+
} else {
|
528
|
+
rb_check_type(v, T_CLASS);
|
529
|
+
pi->options.hash_class = v;
|
530
|
+
}
|
531
|
+
} else if (oj_object_class_sym == k) {
|
532
|
+
if (Qnil == v) {
|
533
|
+
pi->options.hash_class = Qnil;
|
534
|
+
} else {
|
535
|
+
rb_check_type(v, T_CLASS);
|
536
|
+
pi->options.hash_class = v;
|
537
|
+
}
|
538
|
+
} else if (oj_array_class_sym == k) {
|
539
|
+
if (Qnil == v) {
|
540
|
+
pi->options.array_class = Qnil;
|
541
|
+
} else {
|
542
|
+
rb_check_type(v, T_CLASS);
|
543
|
+
pi->options.array_class = v;
|
544
|
+
}
|
545
|
+
} else if (oj_decimal_class_sym == k) {
|
546
|
+
pi->options.compat_bigdec = (oj_bigdecimal_class == v);
|
547
|
+
}
|
548
|
+
return ST_CONTINUE;
|
549
|
+
}
|
550
|
+
|
504
551
|
static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
505
552
|
struct _parseInfo pi;
|
506
553
|
VALUE ropts;
|
@@ -531,50 +578,8 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
|
|
531
578
|
if (T_HASH != rb_type(ropts)) {
|
532
579
|
rb_raise(rb_eArgError, "options must be a hash.");
|
533
580
|
}
|
534
|
-
if (Qundef == symbolize_names_sym) {
|
535
|
-
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names"));
|
536
|
-
rb_gc_register_address(&symbolize_names_sym);
|
537
|
-
}
|
538
|
-
if (Qnil != (v = rb_hash_lookup(ropts, symbolize_names_sym))) {
|
539
|
-
pi.options.sym_key = (Qtrue == v) ? Yes : No;
|
540
|
-
}
|
541
|
-
if (Qnil != (v = rb_hash_lookup(ropts, oj_quirks_mode_sym))) {
|
542
|
-
pi.options.quirks_mode = (Qtrue == v) ? Yes : No;
|
543
|
-
}
|
544
|
-
if (Qnil != (v = rb_hash_lookup(ropts, oj_create_additions_sym))) {
|
545
|
-
pi.options.create_ok = (Qtrue == v) ? Yes : No;
|
546
|
-
}
|
547
|
-
if (Qnil != (v = rb_hash_lookup(ropts, oj_allow_nan_sym))) {
|
548
|
-
pi.options.allow_nan = (Qtrue == v) ? Yes : No;
|
549
|
-
}
|
550
581
|
|
551
|
-
|
552
|
-
if (Qnil == (v = rb_hash_lookup(ropts, oj_hash_class_sym))) {
|
553
|
-
pi.options.hash_class = Qnil;
|
554
|
-
} else {
|
555
|
-
rb_check_type(v, T_CLASS);
|
556
|
-
pi.options.hash_class = v;
|
557
|
-
}
|
558
|
-
}
|
559
|
-
if (oj_hash_has_key(ropts, oj_object_class_sym)) {
|
560
|
-
if (Qnil == (v = rb_hash_lookup(ropts, oj_object_class_sym))) {
|
561
|
-
pi.options.hash_class = Qnil;
|
562
|
-
} else {
|
563
|
-
rb_check_type(v, T_CLASS);
|
564
|
-
pi.options.hash_class = v;
|
565
|
-
}
|
566
|
-
}
|
567
|
-
if (oj_hash_has_key(ropts, oj_array_class_sym)) {
|
568
|
-
if (Qnil == (v = rb_hash_lookup(ropts, oj_array_class_sym))) {
|
569
|
-
pi.options.array_class = Qnil;
|
570
|
-
} else {
|
571
|
-
rb_check_type(v, T_CLASS);
|
572
|
-
pi.options.array_class = v;
|
573
|
-
}
|
574
|
-
}
|
575
|
-
if (oj_hash_has_key(ropts, oj_decimal_class_sym)) {
|
576
|
-
pi.options.compat_bigdec = (oj_bigdecimal_class == rb_hash_lookup(ropts, oj_decimal_class_sym));
|
577
|
-
}
|
582
|
+
rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
|
578
583
|
v = rb_hash_lookup(ropts, oj_max_nesting_sym);
|
579
584
|
if (Qtrue == v) {
|
580
585
|
pi.max_depth = 100;
|
@@ -748,16 +753,15 @@ static struct _options mimic_object_to_json_options = {0, // indent
|
|
748
753
|
}};
|
749
754
|
|
750
755
|
static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
|
751
|
-
char buf[4096];
|
752
756
|
struct _out out;
|
753
757
|
VALUE rstr;
|
754
758
|
struct _options copts = oj_default_options;
|
755
759
|
|
756
760
|
copts.str_rx.head = NULL;
|
757
761
|
copts.str_rx.tail = NULL;
|
758
|
-
|
759
|
-
out
|
760
|
-
|
762
|
+
|
763
|
+
oj_out_init(&out);
|
764
|
+
|
761
765
|
out.omit_nil = copts.dump_opts.omit_nil;
|
762
766
|
copts.mode = CompatMode;
|
763
767
|
copts.to_json = No;
|
@@ -773,9 +777,9 @@ static VALUE mimic_object_to_json(int argc, VALUE *argv, VALUE self) {
|
|
773
777
|
}
|
774
778
|
rstr = rb_str_new2(out.buf);
|
775
779
|
rstr = oj_encode(rstr);
|
776
|
-
|
777
|
-
|
778
|
-
|
780
|
+
|
781
|
+
oj_out_free(&out);
|
782
|
+
|
779
783
|
return rstr;
|
780
784
|
}
|
781
785
|
|
@@ -852,9 +856,6 @@ void oj_mimic_json_methods(VALUE json) {
|
|
852
856
|
// Pull in the JSON::State mimic file.
|
853
857
|
state_class = rb_const_get_at(generator, rb_intern("State"));
|
854
858
|
rb_gc_register_mark_object(state_class);
|
855
|
-
|
856
|
-
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names"));
|
857
|
-
rb_gc_register_address(&symbolize_names_sym);
|
858
859
|
}
|
859
860
|
|
860
861
|
/* Document-module: JSON
|