usamin 7.7.6 → 7.7.11
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/.gitignore +1 -0
- data/README.md +66 -45
- data/Rakefile +12 -10
- data/ext/usamin/default_parse_flags.hpp +6 -0
- data/ext/usamin/extconf.rb +17 -1
- data/ext/usamin/generator.cpp +226 -0
- data/ext/usamin/generator.hpp +11 -0
- data/ext/usamin/parser.cpp +101 -0
- data/ext/usamin/parser.hpp +9 -0
- data/ext/usamin/parser_helper.hpp +131 -0
- data/ext/usamin/rb270_fix.hpp +16 -0
- data/ext/usamin/rb_common.cpp +60 -0
- data/ext/usamin/rb_common.hpp +15 -0
- data/ext/usamin/rb_usamin_array.cpp +454 -0
- data/ext/usamin/rb_usamin_array.hpp +29 -0
- data/ext/usamin/rb_usamin_hash.cpp +518 -0
- data/ext/usamin/rb_usamin_hash.hpp +37 -0
- data/ext/usamin/rb_usamin_value.cpp +328 -0
- data/ext/usamin/rb_usamin_value.hpp +24 -0
- data/ext/usamin/rubynized_rapidjson.cpp +21 -0
- data/ext/usamin/rubynized_rapidjson.hpp +18 -0
- data/ext/usamin/usamin.cpp +45 -1316
- data/ext/usamin/usamin_value.cpp +14 -0
- data/ext/usamin/usamin_value.hpp +17 -0
- data/lib/usamin.rb +2 -0
- data/lib/usamin/overwrite.rb +37 -16
- data/lib/usamin/version.rb +3 -1
- data/usamin.gemspec +19 -18
- metadata +40 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5c1850442411d90d31a98e9d3286b773852a1e855ba32227b1d266ea2ae2581f
|
|
4
|
+
data.tar.gz: 4382e4499525e5aa163e023feb62f4e839bc98dd3540a11112ee6b3334d632c1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 27d1e300cb0242087202b903ef425ff25d81b1249834111f1302d060e7991e9e665f34f2674a8da5f90647bc9448417141925cd6fad06bdd5783f79fc59bea0f
|
|
7
|
+
data.tar.gz: 0133a944f187fed3deb2f295fd2e18b9386d52a1f87f3873f58ab37b530de591812f29c422558c35e180b65ebb73ff94d4ca9669dc027c6f47716018538e0004
|
data/.gitignore
CHANGED
data/README.md
CHANGED
|
@@ -69,9 +69,10 @@ Usamin.parse(json)
|
|
|
69
69
|
|
|
70
70
|
```ruby
|
|
71
71
|
data = Usamin.load(json)
|
|
72
|
+
#=> => [{...}, {...}]
|
|
72
73
|
```
|
|
73
74
|
|
|
74
|
-
Here, `data` is not
|
|
75
|
+
Here, `data` is not an Array, but this can be handled like an Array.
|
|
75
76
|
|
|
76
77
|
```ruby
|
|
77
78
|
data.size
|
|
@@ -87,6 +88,9 @@ Objects also can be handled like Hash objects.
|
|
|
87
88
|
data.first['name']
|
|
88
89
|
#=> "miku maekawa"
|
|
89
90
|
|
|
91
|
+
data.first[:name]
|
|
92
|
+
#=> "miku maekawa"
|
|
93
|
+
|
|
90
94
|
data.first.keys
|
|
91
95
|
#=> ["name", "age", "height", "weight", "body_size", "birthday", "cv"]
|
|
92
96
|
```
|
|
@@ -104,10 +108,25 @@ data.first.eval_r
|
|
|
104
108
|
Usamin.load(json).eval_r
|
|
105
109
|
```
|
|
106
110
|
|
|
111
|
+
Usamin supports pattern matching, which is introduced in Ruby 2.7.0.
|
|
112
|
+
|
|
113
|
+
Note that all keys are treated as symbols in pattern matching.
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
data = Usamin.load('{"maekawa": "miku", "osaki": ["tenka", "amana"], "hisakawa": { "hayate": "haa", "nagi": "naa" }}')
|
|
117
|
+
#=> {"maekawa"=>"miku", "osaki"=>[...], "hisakawa"=>{...}}
|
|
118
|
+
|
|
119
|
+
case data
|
|
120
|
+
in maekawa:, hisakawa: {**sisters}
|
|
121
|
+
sisters
|
|
122
|
+
end
|
|
123
|
+
#=> {:hayate=>"haa", :nagi=>"naa"}
|
|
124
|
+
```
|
|
125
|
+
|
|
107
126
|
#### Notes about lazy loading data
|
|
108
127
|
|
|
109
128
|
- Frozen. Modification is not allowed.
|
|
110
|
-
-
|
|
129
|
+
- Hash objects are based on not hash tables but arrays. An index access to an object costs O(n).
|
|
111
130
|
|
|
112
131
|
### Generating
|
|
113
132
|
|
|
@@ -207,78 +226,80 @@ Usamin and JSON load the same data from 3 big json data in nativejson-benchmark.
|
|
|
207
226
|
|
|
208
227
|
### Performance
|
|
209
228
|
|
|
210
|
-
The values show the elapsed time for operating 20 times.
|
|
229
|
+
The values show the elapsed time for operating 20 times. SSE4.2 was enabled in these tests.
|
|
230
|
+
|
|
231
|
+
Ruby 2.7.0-rc2. json 2.3.0, oj 3.10.0, usamin 7.7.10 (rapidjson 1.1.0).
|
|
211
232
|
|
|
212
233
|
#### Parsing
|
|
213
234
|
|
|
214
235
|
```
|
|
215
236
|
nativejson-benchmark/data/canada.json
|
|
216
|
-
json 0.
|
|
217
|
-
oj 1.
|
|
218
|
-
usamin 0.
|
|
219
|
-
usamin (fast) 0.
|
|
220
|
-
usamin (load) 0.
|
|
221
|
-
usamin (load / fast) 0.
|
|
237
|
+
json 0.734855 0.005684 0.740539 ( 0.743125)
|
|
238
|
+
oj 1.906612 0.022766 1.929378 ( 1.938912)
|
|
239
|
+
usamin 0.546606 0.016939 0.563545 ( 0.565339)
|
|
240
|
+
usamin (fast) 0.221778 0.013511 0.235289 ( 0.235782)
|
|
241
|
+
usamin (load) 0.467457 0.018688 0.486145 ( 0.487849)
|
|
242
|
+
usamin (load / fast) 0.166556 0.025738 0.192294 ( 0.192736)
|
|
222
243
|
|
|
223
244
|
nativejson-benchmark/data/citm_catalog.json
|
|
224
|
-
json 0.
|
|
225
|
-
oj 0.
|
|
226
|
-
usamin 0.
|
|
227
|
-
usamin (fast) 0.
|
|
228
|
-
usamin (load) 0.
|
|
229
|
-
usamin (load / fast) 0.
|
|
245
|
+
json 0.339319 0.004765 0.344084 ( 0.345174)
|
|
246
|
+
oj 0.224548 0.000997 0.225545 ( 0.225837)
|
|
247
|
+
usamin 0.278662 0.003313 0.281975 ( 0.285040)
|
|
248
|
+
usamin (fast) 0.232262 0.001691 0.233953 ( 0.234662)
|
|
249
|
+
usamin (load) 0.111687 0.006829 0.118516 ( 0.118821)
|
|
250
|
+
usamin (load / fast) 0.072404 0.007138 0.079542 ( 0.079620)
|
|
230
251
|
|
|
231
252
|
nativejson-benchmark/data/twitter.json
|
|
232
|
-
json 0.
|
|
233
|
-
oj 0.
|
|
234
|
-
usamin 0.
|
|
235
|
-
usamin (fast) 0.
|
|
236
|
-
usamin (load) 0.
|
|
237
|
-
usamin (load / fast) 0.
|
|
253
|
+
json 0.208798 0.004463 0.213261 ( 0.213952)
|
|
254
|
+
oj 0.134336 0.000970 0.135306 ( 0.135999)
|
|
255
|
+
usamin 0.174997 0.000755 0.175752 ( 0.176467)
|
|
256
|
+
usamin (fast) 0.176687 0.001193 0.177880 ( 0.179466)
|
|
257
|
+
usamin (load) 0.062983 0.004450 0.067433 ( 0.067547)
|
|
258
|
+
usamin (load / fast) 0.063495 0.006539 0.070034 ( 0.071615)
|
|
238
259
|
```
|
|
239
260
|
|
|
240
261
|
#### Generating
|
|
241
262
|
|
|
242
263
|
```
|
|
243
264
|
nativejson-benchmark/data/canada.json
|
|
244
|
-
json
|
|
245
|
-
oj 2.
|
|
246
|
-
usamin 0.
|
|
247
|
-
usamin (load) 0.
|
|
265
|
+
json 2.039965 0.015920 2.055885 ( 2.065514)
|
|
266
|
+
oj 2.008353 0.004610 2.012963 ( 2.016850)
|
|
267
|
+
usamin 0.276563 0.015915 0.292478 ( 0.294615)
|
|
268
|
+
usamin (load) 0.256360 0.010180 0.266540 ( 0.268350)
|
|
248
269
|
|
|
249
270
|
nativejson-benchmark/data/citm_catalog.json
|
|
250
|
-
json 0.
|
|
251
|
-
oj 0.
|
|
252
|
-
usamin 0.
|
|
253
|
-
usamin (load) 0.
|
|
271
|
+
json 0.068053 0.004018 0.072071 ( 0.072138)
|
|
272
|
+
oj 0.060933 0.003070 0.064003 ( 0.064161)
|
|
273
|
+
usamin 0.056743 0.008311 0.065054 ( 0.065449)
|
|
274
|
+
usamin (load) 0.037438 0.003680 0.041118 ( 0.041461)
|
|
254
275
|
|
|
255
276
|
nativejson-benchmark/data/twitter.json
|
|
256
|
-
json 0.
|
|
257
|
-
oj 0.
|
|
258
|
-
usamin 0.
|
|
259
|
-
usamin (load) 0.
|
|
277
|
+
json 0.040689 0.003881 0.044570 ( 0.044641)
|
|
278
|
+
oj 0.038957 0.003410 0.042367 ( 0.042525)
|
|
279
|
+
usamin 0.037130 0.005539 0.042669 ( 0.042951)
|
|
280
|
+
usamin (load) 0.031568 0.003316 0.034884 ( 0.035690)
|
|
260
281
|
```
|
|
261
282
|
|
|
262
283
|
#### Pretty Generating
|
|
263
284
|
|
|
264
285
|
```
|
|
265
286
|
nativejson-benchmark/data/canada.json
|
|
266
|
-
json 2.
|
|
267
|
-
oj 1.
|
|
268
|
-
usamin 0.
|
|
269
|
-
usamin (load) 0.
|
|
287
|
+
json 2.247403 0.056727 2.304130 ( 2.312832)
|
|
288
|
+
oj 1.560007 0.005153 1.565160 ( 1.569151)
|
|
289
|
+
usamin 0.353357 0.063384 0.416741 ( 0.418236)
|
|
290
|
+
usamin (load) 0.341948 0.055289 0.397237 ( 0.399525)
|
|
270
291
|
|
|
271
292
|
nativejson-benchmark/data/citm_catalog.json
|
|
272
|
-
json 0.
|
|
273
|
-
oj 0.
|
|
274
|
-
usamin 0.
|
|
275
|
-
usamin (load) 0.
|
|
293
|
+
json 0.128840 0.008824 0.137664 ( 0.139104)
|
|
294
|
+
oj 0.061869 0.004010 0.065879 ( 0.067000)
|
|
295
|
+
usamin 0.071300 0.005988 0.077288 ( 0.077439)
|
|
296
|
+
usamin (load) 0.048758 0.004353 0.053111 ( 0.053186)
|
|
276
297
|
|
|
277
298
|
nativejson-benchmark/data/twitter.json
|
|
278
|
-
json 0.
|
|
279
|
-
oj 0.
|
|
280
|
-
usamin 0.
|
|
281
|
-
usamin (load) 0.
|
|
299
|
+
json 0.060095 0.004639 0.064734 ( 0.065314)
|
|
300
|
+
oj 0.037025 0.004194 0.041219 ( 0.041495)
|
|
301
|
+
usamin 0.053145 0.011938 0.065083 ( 0.065184)
|
|
302
|
+
usamin (load) 0.034704 0.002547 0.037251 ( 0.037505)
|
|
282
303
|
```
|
|
283
304
|
|
|
284
305
|
## Contributing
|
data/Rakefile
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/gem_tasks'
|
|
4
|
+
require 'rake/testtask'
|
|
3
5
|
|
|
4
6
|
Rake::TestTask.new(:test) do |t|
|
|
5
|
-
t.libs <<
|
|
6
|
-
t.libs <<
|
|
7
|
-
t.test_files = FileList[
|
|
7
|
+
t.libs << 'test'
|
|
8
|
+
t.libs << 'lib'
|
|
9
|
+
t.test_files = FileList['test/**/*_test.rb']
|
|
8
10
|
end
|
|
9
11
|
|
|
10
|
-
require
|
|
12
|
+
require 'rake/extensiontask'
|
|
11
13
|
|
|
12
|
-
task :
|
|
14
|
+
task build: :compile
|
|
13
15
|
|
|
14
|
-
Rake::ExtensionTask.new(
|
|
15
|
-
ext.lib_dir =
|
|
16
|
+
Rake::ExtensionTask.new('usamin') do |ext|
|
|
17
|
+
ext.lib_dir = 'lib/usamin'
|
|
16
18
|
end
|
|
17
19
|
|
|
18
|
-
task :
|
|
20
|
+
task default: %i[clobber compile test]
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#define RAPIDJSON_PARSE_DEFAULT_FLAGS \
|
|
2
|
+
(rapidjson::kParseIterativeFlag | rapidjson::kParseFullPrecisionFlag | rapidjson::kParseCommentsFlag | \
|
|
3
|
+
rapidjson::kParseTrailingCommasFlag | rapidjson::kParseNanAndInfFlag)
|
|
4
|
+
#define RAPIDJSON_PARSE_FAST_FLAGS (RAPIDJSON_PARSE_DEFAULT_FLAGS & ~rapidjson::kParseFullPrecisionFlag)
|
|
5
|
+
#define RAPIDJSON_PARSE_FLAGS_FOR_MARSHAL \
|
|
6
|
+
(rapidjson::kParseIterativeFlag | rapidjson::kParseFullPrecisionFlag | rapidjson::kParseNanAndInfFlag)
|
data/ext/usamin/extconf.rb
CHANGED
|
@@ -1,11 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'mkmf'
|
|
2
4
|
|
|
3
5
|
RbConfig::MAKEFILE_CONFIG['CXX'] = ENV['CXX'] if ENV['CXX']
|
|
4
6
|
have_library('stdc++')
|
|
7
|
+
have_library('m')
|
|
5
8
|
dir_config('rapidjson')
|
|
6
9
|
append_cppflags('-O3')
|
|
7
10
|
append_cppflags('-Wall')
|
|
8
11
|
append_cppflags('-Wextra')
|
|
12
|
+
append_cppflags('-Wno-missing-field-initializers')
|
|
9
13
|
append_cppflags('-Wvla')
|
|
10
|
-
|
|
14
|
+
|
|
15
|
+
if checking_for('whether -march=native is accepted as CPPFLAGS'){try_cppflags('-march=native')}
|
|
16
|
+
if checking_for('whether -msse4.2 is accepted as CPPFLAGS'){try_cppflags('-msse4.2')}
|
|
17
|
+
$CPPFLAGS << ' -msse4.2 -march=native'
|
|
18
|
+
elsif checking_for('whether -msse2 is accepted as CPPFLAGS'){try_cppflags('-msse2')}
|
|
19
|
+
$CPPFLAGS << ' -msse2 -march=native'
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
$CPPFLAGS << ' -std=c++11'
|
|
24
|
+
|
|
25
|
+
$CPPFLAGS << ' -DRAPIDJSON_IS_HEAD' if arg_config('--rapidjson-is-head')
|
|
26
|
+
|
|
11
27
|
create_makefile('usamin/usamin')
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
#include "rb270_fix.hpp"
|
|
2
|
+
#include <rapidjson/prettywriter.h>
|
|
3
|
+
#include <rapidjson/writer.h>
|
|
4
|
+
#include <ruby.h>
|
|
5
|
+
#include <ruby/version.h>
|
|
6
|
+
#include "rb_common.hpp"
|
|
7
|
+
#include "rb_usamin_value.hpp"
|
|
8
|
+
#include "rubynized_rapidjson.hpp"
|
|
9
|
+
|
|
10
|
+
#define WRITER_CONFIGS rapidjson::UTF8<>, rapidjson::UTF8<>, RubyCrtAllocator, rapidjson::kWriteNanAndInfFlag
|
|
11
|
+
|
|
12
|
+
template <class Writer>
|
|
13
|
+
static inline void write_hash(Writer &, const VALUE);
|
|
14
|
+
template <class Writer>
|
|
15
|
+
static inline void write_array(Writer &, const VALUE);
|
|
16
|
+
template <class Writer>
|
|
17
|
+
static inline void write_struct(Writer &, const VALUE);
|
|
18
|
+
template <class Writer>
|
|
19
|
+
static inline void write_usamin(Writer &, const VALUE);
|
|
20
|
+
|
|
21
|
+
template <class Writer>
|
|
22
|
+
static inline void write_str(Writer &writer, const VALUE value) {
|
|
23
|
+
VALUE v = get_utf8_str(value);
|
|
24
|
+
writer.String(RSTRING_PTR(v), RSTRING_LENINT(v));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
template <class Writer>
|
|
28
|
+
static inline void write_to_s(Writer &writer, const VALUE value) {
|
|
29
|
+
extern ID id_to_s;
|
|
30
|
+
write_str(writer, rb_funcall(value, id_to_s, 0));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
template <class Writer>
|
|
34
|
+
static void write(Writer &writer, const VALUE value) {
|
|
35
|
+
extern VALUE rb_cUsaminValue;
|
|
36
|
+
switch (TYPE(value)) {
|
|
37
|
+
case RUBY_T_NONE:
|
|
38
|
+
case RUBY_T_NIL:
|
|
39
|
+
case RUBY_T_UNDEF:
|
|
40
|
+
writer.Null();
|
|
41
|
+
break;
|
|
42
|
+
case RUBY_T_TRUE:
|
|
43
|
+
writer.Bool(true);
|
|
44
|
+
break;
|
|
45
|
+
case RUBY_T_FALSE:
|
|
46
|
+
writer.Bool(false);
|
|
47
|
+
break;
|
|
48
|
+
case RUBY_T_FIXNUM:
|
|
49
|
+
writer.Int64(FIX2LONG(value));
|
|
50
|
+
break;
|
|
51
|
+
case RUBY_T_FLOAT:
|
|
52
|
+
case RUBY_T_RATIONAL:
|
|
53
|
+
writer.Double(NUM2DBL(value));
|
|
54
|
+
break;
|
|
55
|
+
case RUBY_T_STRING:
|
|
56
|
+
write_str(writer, value);
|
|
57
|
+
break;
|
|
58
|
+
case RUBY_T_ARRAY:
|
|
59
|
+
write_array(writer, value);
|
|
60
|
+
break;
|
|
61
|
+
case RUBY_T_HASH:
|
|
62
|
+
write_hash(writer, value);
|
|
63
|
+
break;
|
|
64
|
+
case RUBY_T_STRUCT:
|
|
65
|
+
write_struct(writer, value);
|
|
66
|
+
break;
|
|
67
|
+
case RUBY_T_BIGNUM: {
|
|
68
|
+
VALUE v = rb_big2str(value, 10);
|
|
69
|
+
writer.RawValue(RSTRING_PTR(v), RSTRING_LEN(v), rapidjson::kNumberType);
|
|
70
|
+
} break;
|
|
71
|
+
default:
|
|
72
|
+
if (rb_obj_is_kind_of(value, rb_cUsaminValue))
|
|
73
|
+
write_usamin(writer, value);
|
|
74
|
+
else
|
|
75
|
+
write_to_s(writer, value);
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
template <class Writer>
|
|
81
|
+
static inline void write_key_str(Writer &writer, const VALUE value) {
|
|
82
|
+
VALUE v = get_utf8_str(value);
|
|
83
|
+
writer.Key(RSTRING_PTR(v), RSTRING_LENINT(v));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
template <class Writer>
|
|
87
|
+
static inline void write_key_to_s(Writer &writer, const VALUE value) {
|
|
88
|
+
extern ID id_to_s;
|
|
89
|
+
write_key_str(writer, rb_funcall(value, id_to_s, 0));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
template <class Writer>
|
|
93
|
+
static inline int write_hash_each(const VALUE key, const VALUE value, VALUE writer_v) {
|
|
94
|
+
Writer *writer = reinterpret_cast<Writer *>(writer_v);
|
|
95
|
+
if (RB_TYPE_P(key, T_STRING))
|
|
96
|
+
write_key_str(*writer, key);
|
|
97
|
+
else if (RB_TYPE_P(key, T_SYMBOL))
|
|
98
|
+
write_key_str(*writer, rb_sym_to_s(key));
|
|
99
|
+
else
|
|
100
|
+
write_key_to_s(*writer, key);
|
|
101
|
+
write(*writer, value);
|
|
102
|
+
return ST_CONTINUE;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
template <class Writer>
|
|
106
|
+
static inline void write_hash(Writer &writer, const VALUE hash) {
|
|
107
|
+
writer.StartObject();
|
|
108
|
+
#if RUBY_API_VERSION_CODE < 20700
|
|
109
|
+
rb_hash_foreach(hash, (int (*)(ANYARGS))write_hash_each<Writer>, reinterpret_cast<VALUE>(&writer));
|
|
110
|
+
#else
|
|
111
|
+
rb_hash_foreach(hash, write_hash_each<Writer>, reinterpret_cast<VALUE>(&writer));
|
|
112
|
+
#endif
|
|
113
|
+
writer.EndObject();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
template <class Writer>
|
|
117
|
+
static inline void write_array(Writer &writer, const VALUE value) {
|
|
118
|
+
writer.StartArray();
|
|
119
|
+
const VALUE *ptr = rb_array_const_ptr(value);
|
|
120
|
+
for (long i = 0; i < rb_array_len(value); i++, ptr++)
|
|
121
|
+
write(writer, *ptr);
|
|
122
|
+
writer.EndArray();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
template <class Writer>
|
|
126
|
+
static inline void write_struct(Writer &writer, const VALUE value) {
|
|
127
|
+
writer.StartObject();
|
|
128
|
+
VALUE members = rb_struct_members(value);
|
|
129
|
+
const VALUE *ptr = rb_array_const_ptr(members);
|
|
130
|
+
for (long i = 0; i < rb_array_len(members); i++, ptr++) {
|
|
131
|
+
if (RB_TYPE_P(*ptr, T_SYMBOL))
|
|
132
|
+
write_key_str(writer, rb_sym_to_s(*ptr));
|
|
133
|
+
else if (RB_TYPE_P(*ptr, T_STRING))
|
|
134
|
+
write_key_str(writer, *ptr);
|
|
135
|
+
else
|
|
136
|
+
write_key_to_s(writer, *ptr);
|
|
137
|
+
write(writer, rb_struct_aref(value, *ptr));
|
|
138
|
+
}
|
|
139
|
+
writer.EndObject();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
template <class Writer>
|
|
143
|
+
static inline void write_usamin(Writer &writer, const VALUE self) {
|
|
144
|
+
UsaminValue *value = get_value(self);
|
|
145
|
+
check_value(value);
|
|
146
|
+
value->value->Accept(writer);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/*
|
|
150
|
+
* Generate the JSON string from Ruby data structures.
|
|
151
|
+
*
|
|
152
|
+
* @overload generate(obj)
|
|
153
|
+
* @param [Object] obj an object to serialize
|
|
154
|
+
* @return [String]
|
|
155
|
+
*/
|
|
156
|
+
VALUE w_generate(const VALUE, const VALUE value) {
|
|
157
|
+
rapidjson::StringBuffer buf;
|
|
158
|
+
rapidjson::Writer<rapidjson::StringBuffer, WRITER_CONFIGS> writer(buf);
|
|
159
|
+
write(writer, value);
|
|
160
|
+
return new_utf8_str(buf.GetString(), buf.GetSize());
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/*
|
|
164
|
+
* Generate the prettified JSON string from Ruby data structures.
|
|
165
|
+
*
|
|
166
|
+
* @overload pretty_generate(obj, opts = {})
|
|
167
|
+
* @param [Object] obj an object to serialize
|
|
168
|
+
* @param [::Hash] opts options
|
|
169
|
+
* @option opts [String] :indent (' ') a string used to indent
|
|
170
|
+
* @option opts [Boolean] :single_line_array (false)
|
|
171
|
+
* @return [String]
|
|
172
|
+
*/
|
|
173
|
+
VALUE w_pretty_generate(const int argc, const VALUE *argv, const VALUE) {
|
|
174
|
+
extern VALUE rb_eUsaminError;
|
|
175
|
+
extern VALUE sym_indent, sym_single_line_array;
|
|
176
|
+
|
|
177
|
+
VALUE value, options;
|
|
178
|
+
rb_scan_args(argc, argv, "1:", &value, &options);
|
|
179
|
+
rapidjson::StringBuffer buf;
|
|
180
|
+
#if RAPIDJSON_VERSION_CODE(RAPIDJSON_MAJOR_VERSION, RAPIDJSON_MINOR_VERSION, RAPIDJSON_PATCH_VERSION) > RAPIDJSON_VERSION_CODE(1, 1, 0) || defined(RAPIDJSON_IS_HEAD)
|
|
181
|
+
rapidjson::PrettyWriter<rapidjson::StringBuffer, WRITER_CONFIGS> writer(buf);
|
|
182
|
+
#else
|
|
183
|
+
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
|
|
184
|
+
#endif
|
|
185
|
+
|
|
186
|
+
char indent_char = ' ';
|
|
187
|
+
unsigned int indent_count = 2;
|
|
188
|
+
if (!NIL_P(options)) {
|
|
189
|
+
VALUE v_indent = rb_hash_lookup(options, sym_indent);
|
|
190
|
+
if (RTEST(v_indent)) {
|
|
191
|
+
if (RB_FIXNUM_P(v_indent)) {
|
|
192
|
+
int l = FIX2INT(v_indent);
|
|
193
|
+
indent_count = l > 0 ? l : 0;
|
|
194
|
+
} else {
|
|
195
|
+
int vlen = RSTRING_LENINT(v_indent);
|
|
196
|
+
if (vlen == 0) {
|
|
197
|
+
indent_count = 0;
|
|
198
|
+
} else {
|
|
199
|
+
const char *indent_str = RSTRING_PTR(v_indent);
|
|
200
|
+
switch (indent_str[0]) {
|
|
201
|
+
case ' ':
|
|
202
|
+
case '\t':
|
|
203
|
+
case '\r':
|
|
204
|
+
case '\n':
|
|
205
|
+
indent_char = indent_str[0];
|
|
206
|
+
break;
|
|
207
|
+
default:
|
|
208
|
+
rb_raise(rb_eUsaminError,
|
|
209
|
+
":indent must be a repetation of \" \", \"\\t\", \"\\r\" or \"\\n\".");
|
|
210
|
+
}
|
|
211
|
+
for (long i = 1; i < vlen; i++)
|
|
212
|
+
if (indent_str[0] != indent_str[i])
|
|
213
|
+
rb_raise(rb_eUsaminError,
|
|
214
|
+
":indent must be a repetation of \" \", \"\\t\", \"\\r\" or \"\\n\".");
|
|
215
|
+
indent_count = vlen;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (RTEST(rb_hash_lookup(options, sym_single_line_array)))
|
|
220
|
+
writer.SetFormatOptions(rapidjson::kFormatSingleLineArray);
|
|
221
|
+
}
|
|
222
|
+
writer.SetIndent(indent_char, indent_count);
|
|
223
|
+
|
|
224
|
+
write(writer, value);
|
|
225
|
+
return new_utf8_str(buf.GetString(), buf.GetSize());
|
|
226
|
+
}
|