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