usamin 7.7.9 → 7.7.10
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/README.md +62 -42
- data/Rakefile +12 -10
- data/ext/usamin/default_parse_flags.hpp +6 -0
- data/ext/usamin/extconf.rb +11 -6
- data/ext/usamin/generator.cpp +219 -0
- data/ext/usamin/generator.hpp +11 -0
- data/ext/usamin/parser.cpp +100 -0
- data/ext/usamin/parser.hpp +9 -0
- data/ext/usamin/parser_helper.hpp +131 -0
- data/ext/usamin/rb_common.cpp +60 -0
- data/ext/usamin/rb_common.hpp +15 -0
- data/ext/usamin/rb_usamin_array.cpp +453 -0
- data/ext/usamin/rb_usamin_array.hpp +29 -0
- data/ext/usamin/rb_usamin_hash.cpp +517 -0
- data/ext/usamin/rb_usamin_hash.hpp +37 -0
- data/ext/usamin/rb_usamin_value.cpp +327 -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 +23 -1759
- 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 +35 -28
- data/lib/usamin/version.rb +3 -1
- data/usamin.gemspec +19 -18
- metadata +24 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bcf99c5b8f00f296106cfb0799a5d241dbf1cc8053e74d252b4e1d00692d760d
|
|
4
|
+
data.tar.gz: 48c92bfee2edd6f7e39032dbddcc94f0b9343a1fde13d561f99aa50c231bac11
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5ec0a132cc068d9cea796e407babcf04dae6323bc45a696c80f49610c78d71e0a218ae0ab20cc4e32a50eda1616a907c8f4c116dae7086eee6bf0378a5efd32d
|
|
7
|
+
data.tar.gz: 958dfa0b6ffe3bd031ba8ae6b9b83a5542b4a5bc69579677391788a2424c733069871a5e4f5c067eb6f99c6a770a8d15ca1476f52c5a29211cb3069231cf760d
|
data/README.md
CHANGED
|
@@ -88,6 +88,9 @@ Objects also can be handled like Hash objects.
|
|
|
88
88
|
data.first['name']
|
|
89
89
|
#=> "miku maekawa"
|
|
90
90
|
|
|
91
|
+
data.first[:name]
|
|
92
|
+
#=> "miku maekawa"
|
|
93
|
+
|
|
91
94
|
data.first.keys
|
|
92
95
|
#=> ["name", "age", "height", "weight", "body_size", "birthday", "cv"]
|
|
93
96
|
```
|
|
@@ -105,6 +108,21 @@ data.first.eval_r
|
|
|
105
108
|
Usamin.load(json).eval_r
|
|
106
109
|
```
|
|
107
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
|
+
|
|
108
126
|
#### Notes about lazy loading data
|
|
109
127
|
|
|
110
128
|
- Frozen. Modification is not allowed.
|
|
@@ -210,76 +228,78 @@ Usamin and JSON load the same data from 3 big json data in nativejson-benchmark.
|
|
|
210
228
|
|
|
211
229
|
The values show the elapsed time for operating 20 times. SSE4.2 was enabled in these tests.
|
|
212
230
|
|
|
231
|
+
Ruby 2.7.0-rc2. json 2.3.0, oj 3.10.0, usamin 7.7.10 (rapidjson 1.1.0).
|
|
232
|
+
|
|
213
233
|
#### Parsing
|
|
214
234
|
|
|
215
235
|
```
|
|
216
236
|
nativejson-benchmark/data/canada.json
|
|
217
|
-
json 0.
|
|
218
|
-
oj 1.
|
|
219
|
-
usamin 0.
|
|
220
|
-
usamin (fast) 0.
|
|
221
|
-
usamin (load) 0.
|
|
222
|
-
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)
|
|
223
243
|
|
|
224
244
|
nativejson-benchmark/data/citm_catalog.json
|
|
225
|
-
json 0.
|
|
226
|
-
oj 0.
|
|
227
|
-
usamin 0.
|
|
228
|
-
usamin (fast) 0.
|
|
229
|
-
usamin (load) 0.
|
|
230
|
-
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)
|
|
231
251
|
|
|
232
252
|
nativejson-benchmark/data/twitter.json
|
|
233
|
-
json 0.
|
|
234
|
-
oj 0.
|
|
235
|
-
usamin 0.
|
|
236
|
-
usamin (fast) 0.
|
|
237
|
-
usamin (load) 0.
|
|
238
|
-
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)
|
|
239
259
|
```
|
|
240
260
|
|
|
241
261
|
#### Generating
|
|
242
262
|
|
|
243
263
|
```
|
|
244
264
|
nativejson-benchmark/data/canada.json
|
|
245
|
-
json
|
|
246
|
-
oj 2.
|
|
247
|
-
usamin 0.
|
|
248
|
-
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)
|
|
249
269
|
|
|
250
270
|
nativejson-benchmark/data/citm_catalog.json
|
|
251
|
-
json 0.
|
|
252
|
-
oj 0.
|
|
253
|
-
usamin 0.
|
|
254
|
-
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)
|
|
255
275
|
|
|
256
276
|
nativejson-benchmark/data/twitter.json
|
|
257
|
-
json 0.
|
|
258
|
-
oj 0.
|
|
259
|
-
usamin 0.
|
|
260
|
-
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)
|
|
261
281
|
```
|
|
262
282
|
|
|
263
283
|
#### Pretty Generating
|
|
264
284
|
|
|
265
285
|
```
|
|
266
286
|
nativejson-benchmark/data/canada.json
|
|
267
|
-
json 2.
|
|
268
|
-
oj 1.
|
|
269
|
-
usamin 0.
|
|
270
|
-
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)
|
|
271
291
|
|
|
272
292
|
nativejson-benchmark/data/citm_catalog.json
|
|
273
|
-
json 0.
|
|
274
|
-
oj 0.
|
|
275
|
-
usamin 0.
|
|
276
|
-
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)
|
|
277
297
|
|
|
278
298
|
nativejson-benchmark/data/twitter.json
|
|
279
|
-
json 0.
|
|
280
|
-
oj 0.
|
|
281
|
-
usamin 0.
|
|
282
|
-
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)
|
|
283
303
|
```
|
|
284
304
|
|
|
285
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,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'mkmf'
|
|
2
4
|
|
|
3
5
|
RbConfig::MAKEFILE_CONFIG['CXX'] = ENV['CXX'] if ENV['CXX']
|
|
@@ -5,13 +7,16 @@ have_library('stdc++')
|
|
|
5
7
|
dir_config('rapidjson')
|
|
6
8
|
append_cppflags('-O3')
|
|
7
9
|
append_cppflags('-Wall')
|
|
10
|
+
append_cppflags('-Wextra')
|
|
11
|
+
append_cppflags('-Wno-missing-field-initializers')
|
|
12
|
+
append_cppflags('-Wvla')
|
|
8
13
|
|
|
9
|
-
if checking_for(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
if checking_for('whether -march=native is accepted as CPPFLAGS'){try_cppflags('-march=native')}
|
|
15
|
+
if checking_for('whether -msse4.2 is accepted as CPPFLAGS'){try_cppflags('-msse4.2')}
|
|
16
|
+
$CPPFLAGS << ' -msse4.2 -march=native'
|
|
17
|
+
elsif checking_for('whether -msse2 is accepted as CPPFLAGS'){try_cppflags('-msse2')}
|
|
18
|
+
$CPPFLAGS << ' -msse2 -march=native'
|
|
19
|
+
end
|
|
15
20
|
end
|
|
16
21
|
|
|
17
22
|
$CPPFLAGS << ' -std=c++11'
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
#include <rapidjson/prettywriter.h>
|
|
2
|
+
#include <rapidjson/writer.h>
|
|
3
|
+
#include <ruby.h>
|
|
4
|
+
#include <ruby/version.h>
|
|
5
|
+
#include "rb_common.hpp"
|
|
6
|
+
#include "rb_usamin_value.hpp"
|
|
7
|
+
#include "rubynized_rapidjson.hpp"
|
|
8
|
+
|
|
9
|
+
template <class Writer>
|
|
10
|
+
static inline void write_hash(Writer &, const VALUE);
|
|
11
|
+
template <class Writer>
|
|
12
|
+
static inline void write_array(Writer &, const VALUE);
|
|
13
|
+
template <class Writer>
|
|
14
|
+
static inline void write_struct(Writer &, const VALUE);
|
|
15
|
+
template <class Writer>
|
|
16
|
+
static inline void write_usamin(Writer &, const VALUE);
|
|
17
|
+
|
|
18
|
+
template <class Writer>
|
|
19
|
+
static inline void write_str(Writer &writer, const VALUE value) {
|
|
20
|
+
VALUE v = get_utf8_str(value);
|
|
21
|
+
writer.String(RSTRING_PTR(v), RSTRING_LENINT(v));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
template <class Writer>
|
|
25
|
+
static inline void write_to_s(Writer &writer, const VALUE value) {
|
|
26
|
+
extern ID id_to_s;
|
|
27
|
+
write_str(writer, rb_funcall(value, id_to_s, 0));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
template <class Writer>
|
|
31
|
+
static void write(Writer &writer, const VALUE value) {
|
|
32
|
+
extern VALUE rb_cUsaminValue;
|
|
33
|
+
switch (TYPE(value)) {
|
|
34
|
+
case RUBY_T_NONE:
|
|
35
|
+
case RUBY_T_NIL:
|
|
36
|
+
case RUBY_T_UNDEF:
|
|
37
|
+
writer.Null();
|
|
38
|
+
break;
|
|
39
|
+
case RUBY_T_TRUE:
|
|
40
|
+
writer.Bool(true);
|
|
41
|
+
break;
|
|
42
|
+
case RUBY_T_FALSE:
|
|
43
|
+
writer.Bool(false);
|
|
44
|
+
break;
|
|
45
|
+
case RUBY_T_FIXNUM:
|
|
46
|
+
writer.Int64(FIX2LONG(value));
|
|
47
|
+
break;
|
|
48
|
+
case RUBY_T_FLOAT:
|
|
49
|
+
case RUBY_T_RATIONAL:
|
|
50
|
+
writer.Double(NUM2DBL(value));
|
|
51
|
+
break;
|
|
52
|
+
case RUBY_T_STRING:
|
|
53
|
+
write_str(writer, value);
|
|
54
|
+
break;
|
|
55
|
+
case RUBY_T_ARRAY:
|
|
56
|
+
write_array(writer, value);
|
|
57
|
+
break;
|
|
58
|
+
case RUBY_T_HASH:
|
|
59
|
+
write_hash(writer, value);
|
|
60
|
+
break;
|
|
61
|
+
case RUBY_T_STRUCT:
|
|
62
|
+
write_struct(writer, value);
|
|
63
|
+
break;
|
|
64
|
+
case RUBY_T_BIGNUM: {
|
|
65
|
+
VALUE v = rb_big2str(value, 10);
|
|
66
|
+
writer.RawValue(RSTRING_PTR(v), RSTRING_LEN(v), rapidjson::kNumberType);
|
|
67
|
+
} break;
|
|
68
|
+
default:
|
|
69
|
+
if (rb_obj_is_kind_of(value, rb_cUsaminValue))
|
|
70
|
+
write_usamin(writer, value);
|
|
71
|
+
else
|
|
72
|
+
write_to_s(writer, value);
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
template <class Writer>
|
|
78
|
+
static inline void write_key_str(Writer &writer, const VALUE value) {
|
|
79
|
+
VALUE v = get_utf8_str(value);
|
|
80
|
+
writer.Key(RSTRING_PTR(v), RSTRING_LENINT(v));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
template <class Writer>
|
|
84
|
+
static inline void write_key_to_s(Writer &writer, const VALUE value) {
|
|
85
|
+
extern ID id_to_s;
|
|
86
|
+
write_key_str(writer, rb_funcall(value, id_to_s, 0));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
template <class Writer>
|
|
90
|
+
static inline int write_hash_each(const VALUE key, const VALUE value, VALUE writer_v) {
|
|
91
|
+
Writer *writer = reinterpret_cast<Writer *>(writer_v);
|
|
92
|
+
if (RB_TYPE_P(key, T_STRING))
|
|
93
|
+
write_key_str(*writer, key);
|
|
94
|
+
else if (RB_TYPE_P(key, T_SYMBOL))
|
|
95
|
+
write_key_str(*writer, rb_sym_to_s(key));
|
|
96
|
+
else
|
|
97
|
+
write_key_to_s(*writer, key);
|
|
98
|
+
write(*writer, value);
|
|
99
|
+
return ST_CONTINUE;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
template <class Writer>
|
|
103
|
+
static inline void write_hash(Writer &writer, const VALUE hash) {
|
|
104
|
+
writer.StartObject();
|
|
105
|
+
#if RUBY_API_VERSION_CODE < 20700
|
|
106
|
+
rb_hash_foreach(hash, (int (*)(ANYARGS))write_hash_each<Writer>, reinterpret_cast<VALUE>(&writer));
|
|
107
|
+
#else
|
|
108
|
+
rb_hash_foreach(hash, write_hash_each<Writer>, reinterpret_cast<VALUE>(&writer));
|
|
109
|
+
#endif
|
|
110
|
+
writer.EndObject();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
template <class Writer>
|
|
114
|
+
static inline void write_array(Writer &writer, const VALUE value) {
|
|
115
|
+
writer.StartArray();
|
|
116
|
+
const VALUE *ptr = rb_array_const_ptr(value);
|
|
117
|
+
for (long i = 0; i < rb_array_len(value); i++, ptr++)
|
|
118
|
+
write(writer, *ptr);
|
|
119
|
+
writer.EndArray();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
template <class Writer>
|
|
123
|
+
static inline void write_struct(Writer &writer, const VALUE value) {
|
|
124
|
+
writer.StartObject();
|
|
125
|
+
VALUE members = rb_struct_members(value);
|
|
126
|
+
const VALUE *ptr = rb_array_const_ptr(members);
|
|
127
|
+
for (long i = 0; i < rb_array_len(members); i++, ptr++) {
|
|
128
|
+
if (RB_TYPE_P(*ptr, T_SYMBOL))
|
|
129
|
+
write_key_str(writer, rb_sym_to_s(*ptr));
|
|
130
|
+
else if (RB_TYPE_P(*ptr, T_STRING))
|
|
131
|
+
write_key_str(writer, *ptr);
|
|
132
|
+
else
|
|
133
|
+
write_key_to_s(writer, *ptr);
|
|
134
|
+
write(writer, rb_struct_aref(value, *ptr));
|
|
135
|
+
}
|
|
136
|
+
writer.EndObject();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
template <class Writer>
|
|
140
|
+
static inline void write_usamin(Writer &writer, const VALUE self) {
|
|
141
|
+
UsaminValue *value = get_value(self);
|
|
142
|
+
check_value(value);
|
|
143
|
+
value->value->Accept(writer);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/*
|
|
147
|
+
* Generate the JSON string from Ruby data structures.
|
|
148
|
+
*
|
|
149
|
+
* @overload generate(obj)
|
|
150
|
+
* @param [Object] obj an object to serialize
|
|
151
|
+
* @return [String]
|
|
152
|
+
*/
|
|
153
|
+
VALUE w_generate(const VALUE, const VALUE value) {
|
|
154
|
+
rapidjson::StringBuffer buf;
|
|
155
|
+
rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
|
|
156
|
+
write(writer, value);
|
|
157
|
+
return new_utf8_str(buf.GetString(), buf.GetSize());
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/*
|
|
161
|
+
* Generate the prettified JSON string from Ruby data structures.
|
|
162
|
+
*
|
|
163
|
+
* @overload pretty_generate(obj, opts = {})
|
|
164
|
+
* @param [Object] obj an object to serialize
|
|
165
|
+
* @param [::Hash] opts options
|
|
166
|
+
* @option opts [String] :indent (' ') a string used to indent
|
|
167
|
+
* @option opts [Boolean] :single_line_array (false)
|
|
168
|
+
* @return [String]
|
|
169
|
+
*/
|
|
170
|
+
VALUE w_pretty_generate(const int argc, const VALUE *argv, const VALUE) {
|
|
171
|
+
extern VALUE rb_eUsaminError;
|
|
172
|
+
extern VALUE sym_indent, sym_single_line_array;
|
|
173
|
+
|
|
174
|
+
VALUE value, options;
|
|
175
|
+
rb_scan_args(argc, argv, "1:", &value, &options);
|
|
176
|
+
rapidjson::StringBuffer buf;
|
|
177
|
+
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
|
|
178
|
+
|
|
179
|
+
char indent_char = ' ';
|
|
180
|
+
unsigned int indent_count = 2;
|
|
181
|
+
if (!NIL_P(options)) {
|
|
182
|
+
VALUE v_indent = rb_hash_lookup(options, sym_indent);
|
|
183
|
+
if (RTEST(v_indent)) {
|
|
184
|
+
if (RB_FIXNUM_P(v_indent)) {
|
|
185
|
+
int l = FIX2INT(v_indent);
|
|
186
|
+
indent_count = l > 0 ? l : 0;
|
|
187
|
+
} else {
|
|
188
|
+
int vlen = RSTRING_LENINT(v_indent);
|
|
189
|
+
if (vlen == 0) {
|
|
190
|
+
indent_count = 0;
|
|
191
|
+
} else {
|
|
192
|
+
const char *indent_str = RSTRING_PTR(v_indent);
|
|
193
|
+
switch (indent_str[0]) {
|
|
194
|
+
case ' ':
|
|
195
|
+
case '\t':
|
|
196
|
+
case '\r':
|
|
197
|
+
case '\n':
|
|
198
|
+
indent_char = indent_str[0];
|
|
199
|
+
break;
|
|
200
|
+
default:
|
|
201
|
+
rb_raise(rb_eUsaminError,
|
|
202
|
+
":indent must be a repetation of \" \", \"\\t\", \"\\r\" or \"\\n\".");
|
|
203
|
+
}
|
|
204
|
+
for (long i = 1; i < vlen; i++)
|
|
205
|
+
if (indent_str[0] != indent_str[i])
|
|
206
|
+
rb_raise(rb_eUsaminError,
|
|
207
|
+
":indent must be a repetation of \" \", \"\\t\", \"\\r\" or \"\\n\".");
|
|
208
|
+
indent_count = vlen;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (RTEST(rb_hash_lookup(options, sym_single_line_array)))
|
|
213
|
+
writer.SetFormatOptions(rapidjson::kFormatSingleLineArray);
|
|
214
|
+
}
|
|
215
|
+
writer.SetIndent(indent_char, indent_count);
|
|
216
|
+
|
|
217
|
+
write(writer, value);
|
|
218
|
+
return new_utf8_str(buf.GetString(), buf.GetSize());
|
|
219
|
+
}
|