oj 3.7.4 → 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 +1360 -0
- data/README.md +31 -8
- data/RELEASE_NOTES.md +61 -0
- data/ext/oj/buf.h +53 -72
- data/ext/oj/cache.c +326 -0
- data/ext/oj/cache.h +21 -0
- data/ext/oj/cache8.c +61 -64
- data/ext/oj/cache8.h +12 -39
- data/ext/oj/circarray.c +37 -43
- data/ext/oj/circarray.h +16 -17
- data/ext/oj/code.c +165 -179
- data/ext/oj/code.h +27 -29
- data/ext/oj/compat.c +174 -194
- data/ext/oj/custom.c +790 -866
- data/ext/oj/debug.c +132 -0
- data/ext/oj/dump.c +848 -863
- data/ext/oj/dump.h +81 -67
- data/ext/oj/dump_compat.c +85 -123
- data/ext/oj/dump_leaf.c +100 -188
- data/ext/oj/dump_object.c +527 -656
- data/ext/oj/dump_strict.c +315 -338
- data/ext/oj/encode.h +7 -34
- data/ext/oj/encoder.c +43 -0
- data/ext/oj/err.c +40 -29
- data/ext/oj/err.h +48 -48
- data/ext/oj/extconf.rb +17 -4
- data/ext/oj/fast.c +1073 -1088
- data/ext/oj/intern.c +298 -0
- data/ext/oj/intern.h +26 -0
- data/ext/oj/mimic_json.c +469 -436
- data/ext/oj/object.c +532 -599
- data/ext/oj/odd.c +154 -138
- data/ext/oj/odd.h +37 -38
- data/ext/oj/oj.c +1333 -986
- data/ext/oj/oj.h +336 -316
- data/ext/oj/parse.c +1002 -846
- data/ext/oj/parse.h +92 -87
- data/ext/oj/parser.c +1587 -0
- data/ext/oj/parser.h +102 -0
- data/ext/oj/rails.c +888 -878
- data/ext/oj/rails.h +11 -14
- data/ext/oj/reader.c +141 -147
- data/ext/oj/reader.h +73 -89
- data/ext/oj/resolve.c +41 -62
- data/ext/oj/resolve.h +7 -9
- data/ext/oj/rxclass.c +71 -75
- data/ext/oj/rxclass.h +18 -19
- data/ext/oj/saj.c +443 -486
- data/ext/oj/saj2.c +596 -0
- data/ext/oj/saj2.h +23 -0
- data/ext/oj/scp.c +88 -113
- data/ext/oj/sparse.c +787 -709
- data/ext/oj/stream_writer.c +133 -159
- data/ext/oj/strict.c +127 -118
- data/ext/oj/string_writer.c +230 -249
- data/ext/oj/trace.c +34 -41
- data/ext/oj/trace.h +19 -19
- data/ext/oj/usual.c +1207 -0
- data/ext/oj/usual.h +68 -0
- data/ext/oj/util.c +136 -0
- data/ext/oj/util.h +20 -0
- data/ext/oj/val_stack.c +60 -68
- data/ext/oj/val_stack.h +91 -129
- data/ext/oj/validate.c +46 -0
- data/ext/oj/wab.c +342 -353
- data/lib/oj/bag.rb +1 -0
- data/lib/oj/easy_hash.rb +5 -4
- data/lib/oj/error.rb +1 -1
- data/lib/oj/json.rb +1 -1
- data/lib/oj/mimic.rb +48 -14
- data/lib/oj/saj.rb +20 -6
- data/lib/oj/state.rb +9 -8
- data/lib/oj/version.rb +2 -2
- data/lib/oj.rb +0 -8
- data/pages/Compatibility.md +1 -1
- data/pages/JsonGem.md +15 -0
- data/pages/Modes.md +53 -46
- data/pages/Options.md +78 -11
- data/pages/Parser.md +309 -0
- data/pages/Rails.md +73 -22
- data/pages/Security.md +1 -1
- data/test/activerecord/result_test.rb +7 -2
- data/test/activesupport5/abstract_unit.rb +45 -0
- data/test/activesupport5/decoding_test.rb +68 -60
- data/test/activesupport5/encoding_test.rb +111 -96
- data/test/activesupport5/encoding_test_cases.rb +33 -25
- data/test/activesupport5/test_helper.rb +43 -21
- data/test/activesupport5/time_zone_test_helpers.rb +18 -3
- data/test/activesupport6/abstract_unit.rb +44 -0
- data/test/activesupport6/decoding_test.rb +133 -0
- data/test/activesupport6/encoding_test.rb +507 -0
- data/test/activesupport6/encoding_test_cases.rb +98 -0
- data/test/activesupport6/test_common.rb +17 -0
- data/test/activesupport6/test_helper.rb +163 -0
- data/test/activesupport6/time_zone_test_helpers.rb +39 -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 +6 -12
- data/test/baz.rb +16 -0
- data/test/bug.rb +16 -0
- data/test/foo.rb +69 -75
- data/test/helper.rb +16 -0
- data/test/json_gem/json_common_interface_test.rb +8 -3
- data/test/json_gem/json_generator_test.rb +21 -8
- data/test/json_gem/json_parser_test.rb +8 -1
- data/test/json_gem/test_helper.rb +12 -0
- data/test/mem.rb +33 -0
- data/test/perf.rb +1 -1
- data/test/perf_dump.rb +50 -0
- data/test/perf_once.rb +58 -0
- data/test/perf_parser.rb +189 -0
- data/test/perf_scp.rb +11 -10
- data/test/perf_strict.rb +17 -23
- data/test/prec.rb +23 -0
- data/test/sample_json.rb +1 -1
- data/test/test_compat.rb +46 -10
- data/test/test_custom.rb +145 -7
- data/test/test_fast.rb +62 -2
- data/test/test_file.rb +23 -7
- data/test/test_gc.rb +11 -0
- data/test/test_generate.rb +21 -0
- data/test/test_hash.rb +11 -1
- data/test/test_integer_range.rb +1 -2
- data/test/test_object.rb +43 -12
- data/test/test_parser.rb +11 -0
- data/test/test_parser_debug.rb +27 -0
- data/test/test_parser_saj.rb +335 -0
- data/test/test_parser_usual.rb +217 -0
- data/test/test_rails.rb +35 -0
- data/test/test_saj.rb +1 -1
- data/test/test_scp.rb +3 -5
- data/test/test_strict.rb +26 -1
- data/test/test_various.rb +86 -65
- data/test/test_wab.rb +2 -0
- data/test/test_writer.rb +19 -2
- data/test/tests.rb +10 -1
- data/test/tests_mimic.rb +9 -0
- data/test/tests_mimic_addition.rb +9 -0
- data/test/zoo.rb +13 -0
- metadata +63 -110
- data/ext/oj/hash.c +0 -163
- data/ext/oj/hash.h +0 -46
- data/ext/oj/hash_test.c +0 -512
data/ext/oj/string_writer.c
CHANGED
|
@@ -1,255 +1,240 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* All rights reserved.
|
|
4
|
-
*/
|
|
1
|
+
// Copyright (c) 2012, 2017 Peter Ohler. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
|
5
3
|
|
|
6
4
|
#include "dump.h"
|
|
7
5
|
#include "encode.h"
|
|
8
6
|
|
|
9
|
-
extern VALUE
|
|
7
|
+
extern VALUE Oj;
|
|
8
|
+
|
|
9
|
+
bool string_writer_optimized = false;
|
|
10
10
|
|
|
11
|
-
static void
|
|
12
|
-
|
|
13
|
-
DumpType type = sw->types[sw->depth];
|
|
11
|
+
static void key_check(StrWriter sw, const char *key) {
|
|
12
|
+
DumpType type = sw->types[sw->depth];
|
|
14
13
|
|
|
15
14
|
if (0 == key && (ObjectNew == type || ObjectType == type)) {
|
|
16
|
-
|
|
15
|
+
rb_raise(rb_eStandardError, "Can not push onto an Object without a key.");
|
|
17
16
|
}
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
static void
|
|
21
|
-
push_type(StrWriter sw, DumpType type) {
|
|
19
|
+
static void push_type(StrWriter sw, DumpType type) {
|
|
22
20
|
if (sw->types_end <= sw->types + sw->depth + 1) {
|
|
23
|
-
|
|
21
|
+
size_t size = (sw->types_end - sw->types) * 2;
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
REALLOC_N(sw->types, char, size);
|
|
24
|
+
sw->types_end = sw->types + size;
|
|
27
25
|
}
|
|
28
26
|
sw->depth++;
|
|
29
27
|
sw->types[sw->depth] = type;
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
static void
|
|
33
|
-
maybe_comma(StrWriter sw) {
|
|
30
|
+
static void maybe_comma(StrWriter sw) {
|
|
34
31
|
switch (sw->types[sw->depth]) {
|
|
35
|
-
case ObjectNew:
|
|
36
|
-
|
|
37
|
-
break;
|
|
38
|
-
case ArrayNew:
|
|
39
|
-
sw->types[sw->depth] = ArrayType;
|
|
40
|
-
break;
|
|
32
|
+
case ObjectNew: sw->types[sw->depth] = ObjectType; break;
|
|
33
|
+
case ArrayNew: sw->types[sw->depth] = ArrayType; break;
|
|
41
34
|
case ObjectType:
|
|
42
35
|
case ArrayType:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
36
|
+
// Always have a few characters available in the out.buf.
|
|
37
|
+
*sw->out.cur++ = ',';
|
|
38
|
+
break;
|
|
46
39
|
}
|
|
47
40
|
}
|
|
48
41
|
|
|
49
42
|
// Used by stream writer also.
|
|
50
|
-
void
|
|
51
|
-
|
|
52
|
-
sw->
|
|
53
|
-
sw->
|
|
54
|
-
sw->types
|
|
55
|
-
sw->
|
|
56
|
-
*sw->types = '\0';
|
|
43
|
+
void oj_str_writer_init(StrWriter sw, int buf_size) {
|
|
44
|
+
sw->opts = oj_default_options;
|
|
45
|
+
sw->depth = 0;
|
|
46
|
+
sw->types = ALLOC_N(char, 256);
|
|
47
|
+
sw->types_end = sw->types + 256;
|
|
48
|
+
*sw->types = '\0';
|
|
57
49
|
sw->keyWritten = 0;
|
|
58
50
|
|
|
59
51
|
if (0 == buf_size) {
|
|
60
|
-
|
|
52
|
+
buf_size = 4096;
|
|
61
53
|
} else if (buf_size < 1024) {
|
|
62
|
-
|
|
54
|
+
buf_size = 1024;
|
|
63
55
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
sw->out.
|
|
67
|
-
sw->out.cur
|
|
68
|
-
|
|
56
|
+
// Must be allocated. Using the out.stack_buffer results in double frees
|
|
57
|
+
// and I haven't figured out why yet.
|
|
58
|
+
sw->out.buf = ALLOC_N(char, buf_size);
|
|
59
|
+
sw->out.cur = sw->out.buf;
|
|
60
|
+
sw->out.end = sw->out.buf + buf_size - BUFFER_EXTRA;
|
|
61
|
+
sw->out.allocated = true;
|
|
62
|
+
|
|
63
|
+
*sw->out.cur = '\0';
|
|
69
64
|
sw->out.circ_cache = NULL;
|
|
70
|
-
sw->out.circ_cnt
|
|
71
|
-
sw->out.hash_cnt
|
|
72
|
-
sw->out.opts
|
|
73
|
-
sw->out.indent
|
|
74
|
-
sw->out.depth
|
|
75
|
-
sw->out.argc
|
|
76
|
-
sw->out.argv
|
|
77
|
-
sw->out.caller
|
|
78
|
-
sw->out.ropts
|
|
79
|
-
sw->out.omit_nil
|
|
65
|
+
sw->out.circ_cnt = 0;
|
|
66
|
+
sw->out.hash_cnt = 0;
|
|
67
|
+
sw->out.opts = &sw->opts;
|
|
68
|
+
sw->out.indent = sw->opts.indent;
|
|
69
|
+
sw->out.depth = 0;
|
|
70
|
+
sw->out.argc = 0;
|
|
71
|
+
sw->out.argv = NULL;
|
|
72
|
+
sw->out.caller = 0;
|
|
73
|
+
sw->out.ropts = NULL;
|
|
74
|
+
sw->out.omit_nil = oj_default_options.dump_opts.omit_nil;
|
|
80
75
|
}
|
|
81
76
|
|
|
82
|
-
void
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
long size;
|
|
77
|
+
void oj_str_writer_push_key(StrWriter sw, const char *key) {
|
|
78
|
+
DumpType type = sw->types[sw->depth];
|
|
79
|
+
long size;
|
|
86
80
|
|
|
87
81
|
if (sw->keyWritten) {
|
|
88
|
-
|
|
82
|
+
rb_raise(rb_eStandardError, "Can not push more than one key before pushing a non-key.");
|
|
89
83
|
}
|
|
90
84
|
if (ObjectNew != type && ObjectType != type) {
|
|
91
|
-
|
|
85
|
+
rb_raise(rb_eStandardError, "Can only push a key onto an Object.");
|
|
92
86
|
}
|
|
93
87
|
size = sw->depth * sw->out.indent + 3;
|
|
94
88
|
assure_size(&sw->out, size);
|
|
95
89
|
maybe_comma(sw);
|
|
96
90
|
if (0 < sw->depth) {
|
|
97
|
-
|
|
91
|
+
fill_indent(&sw->out, sw->depth);
|
|
98
92
|
}
|
|
99
93
|
oj_dump_cstr(key, strlen(key), 0, 0, &sw->out);
|
|
100
94
|
*sw->out.cur++ = ':';
|
|
101
95
|
sw->keyWritten = 1;
|
|
102
96
|
}
|
|
103
97
|
|
|
104
|
-
void
|
|
105
|
-
oj_str_writer_push_object(StrWriter sw, const char *key) {
|
|
98
|
+
void oj_str_writer_push_object(StrWriter sw, const char *key) {
|
|
106
99
|
if (sw->keyWritten) {
|
|
107
|
-
|
|
108
|
-
|
|
100
|
+
sw->keyWritten = 0;
|
|
101
|
+
assure_size(&sw->out, 1);
|
|
109
102
|
} else {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
103
|
+
long size;
|
|
104
|
+
|
|
105
|
+
key_check(sw, key);
|
|
106
|
+
size = sw->depth * sw->out.indent + 3;
|
|
107
|
+
assure_size(&sw->out, size);
|
|
108
|
+
maybe_comma(sw);
|
|
109
|
+
if (0 < sw->depth) {
|
|
110
|
+
fill_indent(&sw->out, sw->depth);
|
|
111
|
+
}
|
|
112
|
+
if (0 != key) {
|
|
113
|
+
oj_dump_cstr(key, strlen(key), 0, 0, &sw->out);
|
|
114
|
+
*sw->out.cur++ = ':';
|
|
115
|
+
}
|
|
123
116
|
}
|
|
124
117
|
*sw->out.cur++ = '{';
|
|
125
118
|
push_type(sw, ObjectNew);
|
|
126
119
|
}
|
|
127
120
|
|
|
128
|
-
void
|
|
129
|
-
oj_str_writer_push_array(StrWriter sw, const char *key) {
|
|
121
|
+
void oj_str_writer_push_array(StrWriter sw, const char *key) {
|
|
130
122
|
if (sw->keyWritten) {
|
|
131
|
-
|
|
132
|
-
|
|
123
|
+
sw->keyWritten = 0;
|
|
124
|
+
assure_size(&sw->out, 1);
|
|
133
125
|
} else {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
126
|
+
long size;
|
|
127
|
+
|
|
128
|
+
key_check(sw, key);
|
|
129
|
+
size = sw->depth * sw->out.indent + 3;
|
|
130
|
+
assure_size(&sw->out, size);
|
|
131
|
+
maybe_comma(sw);
|
|
132
|
+
if (0 < sw->depth) {
|
|
133
|
+
fill_indent(&sw->out, sw->depth);
|
|
134
|
+
}
|
|
135
|
+
if (0 != key) {
|
|
136
|
+
oj_dump_cstr(key, strlen(key), 0, 0, &sw->out);
|
|
137
|
+
*sw->out.cur++ = ':';
|
|
138
|
+
}
|
|
147
139
|
}
|
|
148
140
|
*sw->out.cur++ = '[';
|
|
149
141
|
push_type(sw, ArrayNew);
|
|
150
142
|
}
|
|
151
143
|
|
|
152
|
-
void
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
144
|
+
void oj_str_writer_push_value(StrWriter sw, VALUE val, const char *key) {
|
|
145
|
+
Out out = &sw->out;
|
|
146
|
+
|
|
156
147
|
if (sw->keyWritten) {
|
|
157
|
-
|
|
148
|
+
sw->keyWritten = 0;
|
|
158
149
|
} else {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
150
|
+
long size;
|
|
151
|
+
|
|
152
|
+
key_check(sw, key);
|
|
153
|
+
size = sw->depth * out->indent + 3;
|
|
154
|
+
assure_size(out, size);
|
|
155
|
+
maybe_comma(sw);
|
|
156
|
+
if (0 < sw->depth) {
|
|
157
|
+
fill_indent(&sw->out, sw->depth);
|
|
158
|
+
}
|
|
159
|
+
if (0 != key) {
|
|
160
|
+
oj_dump_cstr(key, strlen(key), 0, 0, out);
|
|
161
|
+
*out->cur++ = ':';
|
|
162
|
+
}
|
|
172
163
|
}
|
|
173
164
|
switch (out->opts->mode) {
|
|
174
|
-
case StrictMode:
|
|
175
|
-
case NullMode:
|
|
176
|
-
case ObjectMode:
|
|
177
|
-
case CompatMode:
|
|
178
|
-
case RailsMode:
|
|
179
|
-
case CustomMode:
|
|
180
|
-
default:
|
|
165
|
+
case StrictMode: oj_dump_strict_val(val, sw->depth, out); break;
|
|
166
|
+
case NullMode: oj_dump_null_val(val, sw->depth, out); break;
|
|
167
|
+
case ObjectMode: oj_dump_obj_val(val, sw->depth, out); break;
|
|
168
|
+
case CompatMode: oj_dump_compat_val(val, sw->depth, out, Yes == out->opts->to_json); break;
|
|
169
|
+
case RailsMode: oj_dump_rails_val(val, sw->depth, out); break;
|
|
170
|
+
case CustomMode: oj_dump_custom_val(val, sw->depth, out, true); break;
|
|
171
|
+
default: oj_dump_custom_val(val, sw->depth, out, true); break;
|
|
181
172
|
}
|
|
182
173
|
}
|
|
183
174
|
|
|
184
|
-
void
|
|
185
|
-
oj_str_writer_push_json(StrWriter sw, const char *json, const char *key) {
|
|
175
|
+
void oj_str_writer_push_json(StrWriter sw, const char *json, const char *key) {
|
|
186
176
|
if (sw->keyWritten) {
|
|
187
|
-
|
|
177
|
+
sw->keyWritten = 0;
|
|
188
178
|
} else {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
179
|
+
long size;
|
|
180
|
+
|
|
181
|
+
key_check(sw, key);
|
|
182
|
+
size = sw->depth * sw->out.indent + 3;
|
|
183
|
+
assure_size(&sw->out, size);
|
|
184
|
+
maybe_comma(sw);
|
|
185
|
+
if (0 < sw->depth) {
|
|
186
|
+
fill_indent(&sw->out, sw->depth);
|
|
187
|
+
}
|
|
188
|
+
if (0 != key) {
|
|
189
|
+
oj_dump_cstr(key, strlen(key), 0, 0, &sw->out);
|
|
190
|
+
*sw->out.cur++ = ':';
|
|
191
|
+
}
|
|
202
192
|
}
|
|
203
193
|
oj_dump_raw(json, strlen(json), &sw->out);
|
|
204
194
|
}
|
|
205
195
|
|
|
206
|
-
void
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
DumpType type = sw->types[sw->depth];
|
|
196
|
+
void oj_str_writer_pop(StrWriter sw) {
|
|
197
|
+
long size;
|
|
198
|
+
DumpType type = sw->types[sw->depth];
|
|
210
199
|
|
|
211
200
|
if (sw->keyWritten) {
|
|
212
|
-
|
|
213
|
-
|
|
201
|
+
sw->keyWritten = 0;
|
|
202
|
+
rb_raise(rb_eStandardError, "Can not pop after writing a key but no value.");
|
|
214
203
|
}
|
|
215
204
|
sw->depth--;
|
|
216
205
|
if (0 > sw->depth) {
|
|
217
|
-
|
|
206
|
+
rb_raise(rb_eStandardError, "Can not pop with no open array or object.");
|
|
218
207
|
}
|
|
219
208
|
size = sw->depth * sw->out.indent + 2;
|
|
220
209
|
assure_size(&sw->out, size);
|
|
221
210
|
fill_indent(&sw->out, sw->depth);
|
|
222
211
|
switch (type) {
|
|
223
212
|
case ObjectNew:
|
|
224
|
-
case ObjectType:
|
|
225
|
-
*sw->out.cur++ = '}';
|
|
226
|
-
break;
|
|
213
|
+
case ObjectType: *sw->out.cur++ = '}'; break;
|
|
227
214
|
case ArrayNew:
|
|
228
|
-
case ArrayType:
|
|
229
|
-
*sw->out.cur++ = ']';
|
|
230
|
-
break;
|
|
215
|
+
case ArrayType: *sw->out.cur++ = ']'; break;
|
|
231
216
|
}
|
|
232
217
|
if (0 == sw->depth && 0 <= sw->out.indent) {
|
|
233
|
-
|
|
218
|
+
*sw->out.cur++ = '\n';
|
|
234
219
|
}
|
|
235
220
|
}
|
|
236
221
|
|
|
237
|
-
void
|
|
238
|
-
oj_str_writer_pop_all(StrWriter sw) {
|
|
222
|
+
void oj_str_writer_pop_all(StrWriter sw) {
|
|
239
223
|
while (0 < sw->depth) {
|
|
240
|
-
|
|
224
|
+
oj_str_writer_pop(sw);
|
|
241
225
|
}
|
|
242
226
|
}
|
|
243
227
|
|
|
244
|
-
static void
|
|
245
|
-
|
|
246
|
-
StrWriter sw;
|
|
228
|
+
static void str_writer_free(void *ptr) {
|
|
229
|
+
StrWriter sw;
|
|
247
230
|
|
|
248
231
|
if (0 == ptr) {
|
|
249
|
-
|
|
232
|
+
return;
|
|
250
233
|
}
|
|
251
234
|
sw = (StrWriter)ptr;
|
|
252
|
-
|
|
235
|
+
|
|
236
|
+
oj_out_free(&sw->out);
|
|
237
|
+
|
|
253
238
|
xfree(sw->types);
|
|
254
239
|
xfree(ptr);
|
|
255
240
|
}
|
|
@@ -268,18 +253,17 @@ str_writer_free(void *ptr) {
|
|
|
268
253
|
* should be.
|
|
269
254
|
*
|
|
270
255
|
* - *io* [_IO_] stream to write to
|
|
271
|
-
* - *options* [_Hash_]
|
|
256
|
+
* - *options* [_Hash_] formatting options
|
|
272
257
|
*/
|
|
273
|
-
static VALUE
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
258
|
+
static VALUE str_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
259
|
+
StrWriter sw = ALLOC(struct _strWriter);
|
|
260
|
+
|
|
277
261
|
oj_str_writer_init(sw, 0);
|
|
278
262
|
if (1 == argc) {
|
|
279
|
-
|
|
263
|
+
oj_parse_options(argv[0], &sw->opts);
|
|
280
264
|
}
|
|
281
|
-
sw->out.argc
|
|
282
|
-
sw->out.argv
|
|
265
|
+
sw->out.argc = argc - 1;
|
|
266
|
+
sw->out.argv = argv + 1;
|
|
283
267
|
sw->out.indent = sw->opts.indent;
|
|
284
268
|
|
|
285
269
|
return Data_Wrap_Struct(oj_string_writer_class, 0, str_writer_free, sw);
|
|
@@ -293,9 +277,8 @@ str_writer_new(int argc, VALUE *argv, VALUE self) {
|
|
|
293
277
|
* the next push then that new key will be ignored.
|
|
294
278
|
* - *key* [_String_] the key pending for the next push
|
|
295
279
|
*/
|
|
296
|
-
static VALUE
|
|
297
|
-
|
|
298
|
-
StrWriter sw = (StrWriter)DATA_PTR(self);
|
|
280
|
+
static VALUE str_writer_push_key(VALUE self, VALUE key) {
|
|
281
|
+
StrWriter sw = (StrWriter)DATA_PTR(self);
|
|
299
282
|
|
|
300
283
|
rb_check_type(key, T_STRING);
|
|
301
284
|
oj_str_writer_push_key(sw, StringValuePtr(key));
|
|
@@ -310,29 +293,24 @@ str_writer_push_key(VALUE self, VALUE key) {
|
|
|
310
293
|
* until a pop() is called.
|
|
311
294
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
|
312
295
|
*/
|
|
313
|
-
static VALUE
|
|
314
|
-
|
|
315
|
-
StrWriter sw = (StrWriter)DATA_PTR(self);
|
|
296
|
+
static VALUE str_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
|
297
|
+
StrWriter sw = (StrWriter)DATA_PTR(self);
|
|
316
298
|
|
|
317
299
|
switch (argc) {
|
|
318
|
-
case 0:
|
|
319
|
-
oj_str_writer_push_object(sw, 0);
|
|
320
|
-
break;
|
|
300
|
+
case 0: oj_str_writer_push_object(sw, 0); break;
|
|
321
301
|
case 1:
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
default:
|
|
330
|
-
rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'.");
|
|
331
|
-
break;
|
|
302
|
+
if (Qnil == argv[0]) {
|
|
303
|
+
oj_str_writer_push_object(sw, 0);
|
|
304
|
+
} else {
|
|
305
|
+
rb_check_type(argv[0], T_STRING);
|
|
306
|
+
oj_str_writer_push_object(sw, StringValuePtr(argv[0]));
|
|
307
|
+
}
|
|
308
|
+
break;
|
|
309
|
+
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'."); break;
|
|
332
310
|
}
|
|
333
311
|
if (rb_block_given_p()) {
|
|
334
|
-
|
|
335
|
-
|
|
312
|
+
rb_yield(Qnil);
|
|
313
|
+
oj_str_writer_pop(sw);
|
|
336
314
|
}
|
|
337
315
|
return Qnil;
|
|
338
316
|
}
|
|
@@ -344,29 +322,24 @@ str_writer_push_object(int argc, VALUE *argv, VALUE self) {
|
|
|
344
322
|
* until a pop() is called.
|
|
345
323
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
|
346
324
|
*/
|
|
347
|
-
static VALUE
|
|
348
|
-
|
|
349
|
-
StrWriter sw = (StrWriter)DATA_PTR(self);
|
|
325
|
+
static VALUE str_writer_push_array(int argc, VALUE *argv, VALUE self) {
|
|
326
|
+
StrWriter sw = (StrWriter)DATA_PTR(self);
|
|
350
327
|
|
|
351
328
|
switch (argc) {
|
|
352
|
-
case 0:
|
|
353
|
-
oj_str_writer_push_array(sw, 0);
|
|
354
|
-
break;
|
|
329
|
+
case 0: oj_str_writer_push_array(sw, 0); break;
|
|
355
330
|
case 1:
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
default:
|
|
364
|
-
rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'.");
|
|
365
|
-
break;
|
|
331
|
+
if (Qnil == argv[0]) {
|
|
332
|
+
oj_str_writer_push_array(sw, 0);
|
|
333
|
+
} else {
|
|
334
|
+
rb_check_type(argv[0], T_STRING);
|
|
335
|
+
oj_str_writer_push_array(sw, StringValuePtr(argv[0]));
|
|
336
|
+
}
|
|
337
|
+
break;
|
|
338
|
+
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_object'."); break;
|
|
366
339
|
}
|
|
367
340
|
if (rb_block_given_p()) {
|
|
368
|
-
|
|
369
|
-
|
|
341
|
+
rb_yield(Qnil);
|
|
342
|
+
oj_str_writer_pop(sw);
|
|
370
343
|
}
|
|
371
344
|
return Qnil;
|
|
372
345
|
}
|
|
@@ -378,23 +351,18 @@ str_writer_push_array(int argc, VALUE *argv, VALUE self) {
|
|
|
378
351
|
* - *value* [_Object_] value to add to the JSON document
|
|
379
352
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
|
380
353
|
*/
|
|
381
|
-
static VALUE
|
|
382
|
-
str_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
|
354
|
+
static VALUE str_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
|
383
355
|
switch (argc) {
|
|
384
|
-
case 1:
|
|
385
|
-
oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
|
|
386
|
-
break;
|
|
356
|
+
case 1: oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0); break;
|
|
387
357
|
case 2:
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
default:
|
|
396
|
-
rb_raise(rb_eArgError, "Wrong number of argument to 'push_value'.");
|
|
397
|
-
break;
|
|
358
|
+
if (Qnil == argv[1]) {
|
|
359
|
+
oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, 0);
|
|
360
|
+
} else {
|
|
361
|
+
rb_check_type(argv[1], T_STRING);
|
|
362
|
+
oj_str_writer_push_value((StrWriter)DATA_PTR(self), *argv, StringValuePtr(argv[1]));
|
|
363
|
+
}
|
|
364
|
+
break;
|
|
365
|
+
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_value'."); break;
|
|
398
366
|
}
|
|
399
367
|
return Qnil;
|
|
400
368
|
}
|
|
@@ -408,24 +376,21 @@ str_writer_push_value(int argc, VALUE *argv, VALUE self) {
|
|
|
408
376
|
* - *value* [_Object_] value to add to the JSON document
|
|
409
377
|
* - *key* [_String_] the key if adding to an object in the JSON document
|
|
410
378
|
*/
|
|
411
|
-
static VALUE
|
|
412
|
-
str_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
|
379
|
+
static VALUE str_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
|
413
380
|
rb_check_type(argv[0], T_STRING);
|
|
414
381
|
switch (argc) {
|
|
415
|
-
case 1:
|
|
416
|
-
oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
|
|
417
|
-
break;
|
|
382
|
+
case 1: oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0); break;
|
|
418
383
|
case 2:
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
384
|
+
if (Qnil == argv[1]) {
|
|
385
|
+
oj_str_writer_push_json((StrWriter)DATA_PTR(self), StringValuePtr(*argv), 0);
|
|
386
|
+
} else {
|
|
387
|
+
rb_check_type(argv[1], T_STRING);
|
|
388
|
+
oj_str_writer_push_json((StrWriter)DATA_PTR(self),
|
|
389
|
+
StringValuePtr(*argv),
|
|
390
|
+
StringValuePtr(argv[1]));
|
|
391
|
+
}
|
|
392
|
+
break;
|
|
393
|
+
default: rb_raise(rb_eArgError, "Wrong number of argument to 'push_json'."); break;
|
|
429
394
|
}
|
|
430
395
|
return Qnil;
|
|
431
396
|
}
|
|
@@ -435,8 +400,7 @@ str_writer_push_json(int argc, VALUE *argv, VALUE self) {
|
|
|
435
400
|
* Pops up a level in the JSON document closing the array or object that is
|
|
436
401
|
* currently open.
|
|
437
402
|
*/
|
|
438
|
-
static VALUE
|
|
439
|
-
str_writer_pop(VALUE self) {
|
|
403
|
+
static VALUE str_writer_pop(VALUE self) {
|
|
440
404
|
oj_str_writer_pop((StrWriter)DATA_PTR(self));
|
|
441
405
|
return Qnil;
|
|
442
406
|
}
|
|
@@ -447,8 +411,7 @@ str_writer_pop(VALUE self) {
|
|
|
447
411
|
* Pops all level in the JSON document closing all the array or object that is
|
|
448
412
|
* currently open.
|
|
449
413
|
*/
|
|
450
|
-
static VALUE
|
|
451
|
-
str_writer_pop_all(VALUE self) {
|
|
414
|
+
static VALUE str_writer_pop_all(VALUE self) {
|
|
452
415
|
oj_str_writer_pop_all((StrWriter)DATA_PTR(self));
|
|
453
416
|
|
|
454
417
|
return Qnil;
|
|
@@ -459,15 +422,14 @@ str_writer_pop_all(VALUE self) {
|
|
|
459
422
|
*
|
|
460
423
|
* Reset the writer back to the empty state.
|
|
461
424
|
*/
|
|
462
|
-
static VALUE
|
|
463
|
-
|
|
464
|
-
StrWriter sw = (StrWriter)DATA_PTR(self);
|
|
425
|
+
static VALUE str_writer_reset(VALUE self) {
|
|
426
|
+
StrWriter sw = (StrWriter)DATA_PTR(self);
|
|
465
427
|
|
|
466
|
-
sw->depth
|
|
467
|
-
*sw->types
|
|
428
|
+
sw->depth = 0;
|
|
429
|
+
*sw->types = '\0';
|
|
468
430
|
sw->keyWritten = 0;
|
|
469
|
-
sw->out.cur
|
|
470
|
-
*sw->out.cur
|
|
431
|
+
sw->out.cur = sw->out.buf;
|
|
432
|
+
*sw->out.cur = '\0';
|
|
471
433
|
|
|
472
434
|
return Qnil;
|
|
473
435
|
}
|
|
@@ -479,26 +441,43 @@ str_writer_reset(VALUE self) {
|
|
|
479
441
|
*
|
|
480
442
|
* *return* [_String_]
|
|
481
443
|
*/
|
|
482
|
-
static VALUE
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
VALUE rstr = rb_str_new(sw->out.buf, sw->out.cur - sw->out.buf);
|
|
444
|
+
static VALUE str_writer_to_s(VALUE self) {
|
|
445
|
+
StrWriter sw = (StrWriter)DATA_PTR(self);
|
|
446
|
+
VALUE rstr = rb_str_new(sw->out.buf, sw->out.cur - sw->out.buf);
|
|
486
447
|
|
|
487
448
|
return oj_encode(rstr);
|
|
488
449
|
}
|
|
489
450
|
|
|
451
|
+
/* Document-method: as_json
|
|
452
|
+
* call-seq: as_json()
|
|
453
|
+
*
|
|
454
|
+
* Returns the contents of the writer as a JSON element. If called from inside
|
|
455
|
+
* an array or hash by Oj the raw buffer will be used othersize a more
|
|
456
|
+
* inefficient parse of the contents and a return of the result is
|
|
457
|
+
* completed. The parse uses the strict mode.
|
|
458
|
+
*
|
|
459
|
+
* *return* [_Hash_|_Array_|_String_|_Integer_|_Float_|_True_|_False_|_nil|)
|
|
460
|
+
*/
|
|
461
|
+
static VALUE str_writer_as_json(VALUE self) {
|
|
462
|
+
if (string_writer_optimized) {
|
|
463
|
+
return self;
|
|
464
|
+
}
|
|
465
|
+
return rb_hash_new();
|
|
466
|
+
}
|
|
467
|
+
|
|
490
468
|
/* Document-class: Oj::StringWriter
|
|
491
|
-
*
|
|
469
|
+
*
|
|
492
470
|
* Supports building a JSON document one element at a time. Build the document
|
|
493
471
|
* by pushing values into the document. Pushing an array or an object will
|
|
494
472
|
* create that element in the JSON document and subsequent pushes will add the
|
|
495
473
|
* elements to that array or object until a pop() is called. When complete
|
|
496
|
-
* calling to_s() will return the JSON document. Note
|
|
474
|
+
* calling to_s() will return the JSON document. Note that calling to_s() before
|
|
497
475
|
* construction is complete will return the document in it's current state.
|
|
498
476
|
*/
|
|
499
|
-
void
|
|
500
|
-
oj_string_writer_init() {
|
|
477
|
+
void oj_string_writer_init(void) {
|
|
501
478
|
oj_string_writer_class = rb_define_class_under(Oj, "StringWriter", rb_cObject);
|
|
479
|
+
rb_gc_register_address(&oj_string_writer_class);
|
|
480
|
+
rb_undef_alloc_func(oj_string_writer_class);
|
|
502
481
|
rb_define_module_function(oj_string_writer_class, "new", str_writer_new, -1);
|
|
503
482
|
rb_define_method(oj_string_writer_class, "push_key", str_writer_push_key, 1);
|
|
504
483
|
rb_define_method(oj_string_writer_class, "push_object", str_writer_push_object, -1);
|
|
@@ -509,4 +488,6 @@ oj_string_writer_init() {
|
|
|
509
488
|
rb_define_method(oj_string_writer_class, "pop_all", str_writer_pop_all, 0);
|
|
510
489
|
rb_define_method(oj_string_writer_class, "reset", str_writer_reset, 0);
|
|
511
490
|
rb_define_method(oj_string_writer_class, "to_s", str_writer_to_s, 0);
|
|
491
|
+
rb_define_method(oj_string_writer_class, "raw_json", str_writer_to_s, 0);
|
|
492
|
+
rb_define_method(oj_string_writer_class, "as_json", str_writer_as_json, 0);
|
|
512
493
|
}
|