usamin 7.7.0 → 7.7.2
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 +109 -76
- data/ext/usamin/usamin.cpp +378 -212
- data/lib/usamin.rb +6 -0
- data/lib/usamin/overwrite.rb +26 -0
- data/lib/usamin/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d053f43fdfdf7a7698d45fa5707245c7ea47946c906f3c504f27aabc543f38b1
|
|
4
|
+
data.tar.gz: 0d2b48bf5962478bd7ce35c1a4cfca68589881b59b62ccff5fadd6addd59be8b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: baf083e37d53f5ebfd4ca36e39ec239d62f5f0e198c2a9d79c0efcc77060d5483962d1e1de1268a143ff566713f413f8853a29a68cacc9bc9722d5169abb6cde
|
|
7
|
+
data.tar.gz: 540f79a2a0015a39b119435b064d683687f248c6405855170dc8fa7469dfcffb4f393df2f33041f4ff1fcd6816f9d2f9808a2249f0ee68f78e685486c6d0c707
|
data/.gitignore
CHANGED
data/README.md
CHANGED
|
@@ -6,7 +6,7 @@ The name of "Usamin" is derived from [Nana Abe](https://www.project-imas.com/wik
|
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
9
|
-
Install RapidJSON beforehand.
|
|
9
|
+
Install RapidJSON beforehand. Only header files are necessary, and no need to build.
|
|
10
10
|
|
|
11
11
|
Next, add this line to your application's Gemfile:
|
|
12
12
|
|
|
@@ -37,24 +37,28 @@ require 'usamin'
|
|
|
37
37
|
### Parsing
|
|
38
38
|
|
|
39
39
|
```ruby
|
|
40
|
-
json =
|
|
41
|
-
|
|
40
|
+
json = <<JSON
|
|
41
|
+
[
|
|
42
|
+
{
|
|
43
|
+
"name": "miku maekawa",
|
|
42
44
|
"age": 15,
|
|
43
45
|
"height": 152,
|
|
44
46
|
"weight": 45,
|
|
45
47
|
"body_size": [85, 55, 81],
|
|
46
|
-
"birthday":
|
|
48
|
+
"birthday": "2/22",
|
|
47
49
|
"cv": "natsumi takamori"
|
|
48
50
|
},
|
|
49
|
-
|
|
51
|
+
{
|
|
52
|
+
"name": "nana abe",
|
|
50
53
|
"age": 17,
|
|
51
54
|
"height": 146,
|
|
52
55
|
"weight": 40,
|
|
53
56
|
"body_size": [84, 57, 84],
|
|
54
|
-
"birthday":
|
|
57
|
+
"birthday": "5/15",
|
|
55
58
|
"cv": "marie miyake"
|
|
56
59
|
}
|
|
57
|
-
|
|
60
|
+
]
|
|
61
|
+
JSON
|
|
58
62
|
|
|
59
63
|
Usamin.parse(json)
|
|
60
64
|
```
|
|
@@ -65,37 +69,37 @@ Usamin.parse(json)
|
|
|
65
69
|
data = Usamin.load(json)
|
|
66
70
|
```
|
|
67
71
|
|
|
68
|
-
Here, `data` is not a
|
|
72
|
+
Here, `data` is not a Array, but this can be handled like an Array.
|
|
69
73
|
|
|
70
74
|
```ruby
|
|
71
|
-
data.
|
|
72
|
-
#=>
|
|
75
|
+
data.size
|
|
76
|
+
#=> 2
|
|
73
77
|
|
|
74
|
-
data.map{|
|
|
75
|
-
#=>
|
|
78
|
+
data.map{|e| e['name']}
|
|
79
|
+
#=> ["miku maekawa", "nana abe"]
|
|
76
80
|
```
|
|
77
81
|
|
|
78
|
-
|
|
82
|
+
Objects also can be handled like Hash objects.
|
|
79
83
|
|
|
80
84
|
```ruby
|
|
81
|
-
data['
|
|
82
|
-
#=>
|
|
85
|
+
data.first['name']
|
|
86
|
+
#=> "miku maekawa"
|
|
83
87
|
|
|
84
|
-
data
|
|
85
|
-
#=>
|
|
88
|
+
data.first.keys
|
|
89
|
+
#=> ["name", "age", "height", "weight", "body_size", "birthday", "cv"]
|
|
86
90
|
```
|
|
87
91
|
|
|
88
|
-
The `eval` and `eval_r`
|
|
92
|
+
The methods `eval` and `eval_r` convert these data structures into Ruby data structures. `_r` means recursiveness.
|
|
89
93
|
|
|
90
94
|
```ruby
|
|
91
95
|
data.eval
|
|
92
|
-
#=>
|
|
96
|
+
#=> [#<Usamin::Hash>, #<Usamin::Hash>]
|
|
93
97
|
|
|
94
|
-
data
|
|
95
|
-
#=> {"age"=>15, "height"=>152, "weight"=>45, "body_size"=>[85, 55, 81], "birthday"=>
|
|
98
|
+
data.first.eval_r
|
|
99
|
+
#=> {"name"=>"miku maekawa", "age"=>15, "height"=>152, "weight"=>45, "body_size"=>[85, 55, 81], "birthday"=>"2/22", "cv"=>"natsumi takamori"}
|
|
96
100
|
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
# same as Usamin.parse(json)
|
|
102
|
+
Usamin.load(json).eval_r
|
|
99
103
|
```
|
|
100
104
|
|
|
101
105
|
#### Notes about lazy loading data
|
|
@@ -106,21 +110,14 @@ data.eval_r
|
|
|
106
110
|
### Generating
|
|
107
111
|
|
|
108
112
|
```ruby
|
|
109
|
-
data = {
|
|
110
|
-
"
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
"nana abe"=> {
|
|
118
|
-
"age"=>17,
|
|
119
|
-
"height"=>146,
|
|
120
|
-
"weight"=>40,
|
|
121
|
-
"body_size"=>[84, 57, 84],
|
|
122
|
-
"birthday"=>[5, 15],
|
|
123
|
-
"cv"=>"marie miyake"}}
|
|
113
|
+
data = [{"name" => "miku maekawa", "age" => 15,
|
|
114
|
+
"height" => 152, "weight" => 45,
|
|
115
|
+
"body_size" => [85, 55, 81], "birthday" => "2/22",
|
|
116
|
+
"cv" => "natsumi takamori"}, {
|
|
117
|
+
"name" => "nana abe", "age" => 17,
|
|
118
|
+
"height" => 146, "weight" => 40,
|
|
119
|
+
"body_size" => [84, 57, 84], "birthday" => "5/15",
|
|
120
|
+
"cv" => "marie miyake"}]
|
|
124
121
|
|
|
125
122
|
Usamin.generate(data)
|
|
126
123
|
|
|
@@ -132,8 +129,7 @@ Of course, UsaminValue also can be serialized.
|
|
|
132
129
|
|
|
133
130
|
```ruby
|
|
134
131
|
data = Usamin.load(json)
|
|
135
|
-
|
|
136
|
-
Usamin.generate(data['nana abe'])
|
|
132
|
+
Usamin.generate(data[1])
|
|
137
133
|
```
|
|
138
134
|
|
|
139
135
|
### Fast parsing
|
|
@@ -160,6 +156,37 @@ Usamin.parse(str)
|
|
|
160
156
|
# Usamin::ParserError: Missing a colon after a name of object member. Offset: 22
|
|
161
157
|
```
|
|
162
158
|
|
|
159
|
+
### Overwrite JSON module
|
|
160
|
+
|
|
161
|
+
You can overwrite JSON module methods by loading `usamin/overwrite`.
|
|
162
|
+
|
|
163
|
+
```ruby
|
|
164
|
+
require 'usamin/overwrite'
|
|
165
|
+
|
|
166
|
+
# These methods are based on Usamin
|
|
167
|
+
JSON.parse(json)
|
|
168
|
+
JSON.generate(data)
|
|
169
|
+
JSON.pretty_generate(data)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
The overwritten methods are as follows:
|
|
173
|
+
|
|
174
|
+
- JSON.parse -> Usamin.parse
|
|
175
|
+
- JSON.load / JSON.restore -> Usamin.parse
|
|
176
|
+
- JSON.generate -> Usamin.generate / Usamin.pretty_generate
|
|
177
|
+
- JSON.pretty_generate -> Usamin.pretty_generate
|
|
178
|
+
|
|
179
|
+
You can automatically switch packages by following technique.
|
|
180
|
+
|
|
181
|
+
```ruby
|
|
182
|
+
begin
|
|
183
|
+
require 'usamin'
|
|
184
|
+
require 'usamin/overwrite'
|
|
185
|
+
rescue LoadError
|
|
186
|
+
require 'json'
|
|
187
|
+
end
|
|
188
|
+
```
|
|
189
|
+
|
|
163
190
|
### Documentation
|
|
164
191
|
|
|
165
192
|
See: http://www.rubydoc.info/gems/usamin/
|
|
@@ -184,66 +211,72 @@ The values show the elapsed time for operating 20 times.
|
|
|
184
211
|
|
|
185
212
|
```
|
|
186
213
|
nativejson-benchmark/data/canada.json
|
|
187
|
-
json 0.
|
|
188
|
-
oj 1.
|
|
189
|
-
usamin 0.
|
|
190
|
-
usamin (fast) 0.
|
|
191
|
-
usamin (load) 0.
|
|
192
|
-
usamin (load / fast) 0.
|
|
214
|
+
json 0.755101 0.004066 0.759167 ( 0.762169)
|
|
215
|
+
oj 1.873840 0.040992 1.914832 ( 1.919647)
|
|
216
|
+
usamin 0.582432 0.011584 0.594016 ( 0.596472)
|
|
217
|
+
usamin (fast) 0.271741 0.004775 0.276516 ( 0.278315)
|
|
218
|
+
usamin (load) 0.458602 0.009857 0.468459 ( 0.471155)
|
|
219
|
+
usamin (load / fast) 0.183260 0.019372 0.202632 ( 0.204489)
|
|
193
220
|
|
|
194
221
|
nativejson-benchmark/data/citm_catalog.json
|
|
195
|
-
json 0.
|
|
196
|
-
oj 0.
|
|
197
|
-
usamin 0.
|
|
198
|
-
usamin (fast) 0.
|
|
199
|
-
usamin (load) 0.
|
|
200
|
-
usamin (load / fast) 0.
|
|
222
|
+
json 0.477735 0.006309 0.484044 ( 0.487179)
|
|
223
|
+
oj 0.374920 0.005170 0.380090 ( 0.384444)
|
|
224
|
+
usamin 0.363176 0.004812 0.367988 ( 0.370558)
|
|
225
|
+
usamin (fast) 0.352986 0.004893 0.357879 ( 0.360197)
|
|
226
|
+
usamin (load) 0.123704 0.006770 0.130474 ( 0.133101)
|
|
227
|
+
usamin (load / fast) 0.106889 0.008363 0.115252 ( 0.117514)
|
|
201
228
|
|
|
202
229
|
nativejson-benchmark/data/twitter.json
|
|
203
|
-
json 0.
|
|
204
|
-
oj 0.
|
|
205
|
-
usamin 0.
|
|
206
|
-
usamin (fast) 0.
|
|
207
|
-
usamin (load) 0.
|
|
208
|
-
usamin (load / fast) 0.
|
|
230
|
+
json 0.227502 0.001665 0.229167 ( 0.233347)
|
|
231
|
+
oj 0.148312 0.000936 0.149248 ( 0.151006)
|
|
232
|
+
usamin 0.178398 0.003571 0.181969 ( 0.183786)
|
|
233
|
+
usamin (fast) 0.170842 0.000973 0.171815 ( 0.173604)
|
|
234
|
+
usamin (load) 0.064007 0.005254 0.069261 ( 0.071036)
|
|
235
|
+
usamin (load / fast) 0.068870 0.006189 0.075059 ( 0.077111)
|
|
209
236
|
```
|
|
210
237
|
|
|
211
238
|
#### Generating
|
|
212
239
|
|
|
213
240
|
```
|
|
214
241
|
nativejson-benchmark/data/canada.json
|
|
215
|
-
json 1.
|
|
216
|
-
oj 2.
|
|
217
|
-
usamin 0.
|
|
242
|
+
json 1.994007 0.026034 2.020041 ( 2.025446)
|
|
243
|
+
oj 2.087961 0.029023 2.116984 ( 2.123429)
|
|
244
|
+
usamin 0.274208 0.022461 0.296669 ( 0.298859)
|
|
245
|
+
usamin (load) 0.273885 0.031334 0.305219 ( 0.310155)
|
|
218
246
|
|
|
219
247
|
nativejson-benchmark/data/citm_catalog.json
|
|
220
|
-
json 0.
|
|
221
|
-
oj 0.
|
|
222
|
-
usamin 0.
|
|
248
|
+
json 0.237936 0.009822 0.247758 ( 0.252693)
|
|
249
|
+
oj 0.073700 0.008512 0.082212 ( 0.084021)
|
|
250
|
+
usamin 0.064633 0.010208 0.074841 ( 0.077269)
|
|
251
|
+
usamin (load) 0.041944 0.010903 0.052847 ( 0.055097)
|
|
223
252
|
|
|
224
253
|
nativejson-benchmark/data/twitter.json
|
|
225
|
-
json 0.
|
|
226
|
-
oj 0.
|
|
227
|
-
usamin 0.
|
|
254
|
+
json 0.165987 0.005908 0.171895 ( 0.176533)
|
|
255
|
+
oj 0.042210 0.005486 0.047696 ( 0.049477)
|
|
256
|
+
usamin 0.039056 0.009091 0.048147 ( 0.050299)
|
|
257
|
+
usamin (load) 0.029979 0.009041 0.039020 ( 0.041219)
|
|
228
258
|
```
|
|
229
259
|
|
|
230
260
|
#### Pretty Generating
|
|
231
261
|
|
|
232
262
|
```
|
|
233
263
|
nativejson-benchmark/data/canada.json
|
|
234
|
-
json 2.
|
|
235
|
-
oj 1.
|
|
236
|
-
usamin 0.
|
|
264
|
+
json 2.196968 0.067552 2.264520 ( 2.270109)
|
|
265
|
+
oj 1.549510 0.019002 1.568512 ( 1.573885)
|
|
266
|
+
usamin 0.373060 0.071227 0.444287 ( 0.446266)
|
|
267
|
+
usamin (load) 0.363781 0.067480 0.431261 ( 0.433839)
|
|
237
268
|
|
|
238
269
|
nativejson-benchmark/data/citm_catalog.json
|
|
239
|
-
json 0.
|
|
240
|
-
oj 0.
|
|
241
|
-
usamin 0.
|
|
270
|
+
json 0.285428 0.022632 0.308060 ( 0.312022)
|
|
271
|
+
oj 0.064475 0.008716 0.073191 ( 0.075125)
|
|
272
|
+
usamin 0.088890 0.019419 0.108309 ( 0.110423)
|
|
273
|
+
usamin (load) 0.058728 0.018471 0.077199 ( 0.079330)
|
|
242
274
|
|
|
243
275
|
nativejson-benchmark/data/twitter.json
|
|
244
|
-
json 0.
|
|
245
|
-
oj 0.
|
|
246
|
-
usamin 0.
|
|
276
|
+
json 0.170966 0.010184 0.181150 ( 0.186188)
|
|
277
|
+
oj 0.038465 0.007323 0.045788 ( 0.047589)
|
|
278
|
+
usamin 0.046873 0.011960 0.058833 ( 0.060903)
|
|
279
|
+
usamin (load) 0.038984 0.010469 0.049453 ( 0.049652)
|
|
247
280
|
```
|
|
248
281
|
|
|
249
282
|
## Contributing
|
data/ext/usamin/usamin.cpp
CHANGED
|
@@ -211,6 +211,170 @@ static inline VALUE eval_array_r(rapidjson::Value &value) {
|
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
|
|
214
|
+
template <class Writer> static inline void write_str(Writer&, const VALUE);
|
|
215
|
+
template <class Writer> static inline void write_hash(Writer&, const VALUE);
|
|
216
|
+
template <class Writer> static inline void write_array(Writer&, const VALUE);
|
|
217
|
+
template <class Writer> static inline void write_bignum(Writer&, const VALUE);
|
|
218
|
+
template <class Writer> static inline void write_struct(Writer&, const VALUE);
|
|
219
|
+
template <class Writer> static inline void write_usamin(Writer&, const VALUE);
|
|
220
|
+
template <class Writer> static inline void write_to_s(Writer&, const VALUE);
|
|
221
|
+
|
|
222
|
+
template <class Writer> static void write(Writer &writer, const VALUE value) {
|
|
223
|
+
if (value == Qnil) {
|
|
224
|
+
writer.Null();
|
|
225
|
+
} else if (value == Qfalse) {
|
|
226
|
+
writer.Bool(false);
|
|
227
|
+
} else if (value == Qtrue) {
|
|
228
|
+
writer.Bool(true);
|
|
229
|
+
} else if (RB_FIXNUM_P(value)) {
|
|
230
|
+
writer.Int64(FIX2LONG(value));
|
|
231
|
+
} else if (RB_FLOAT_TYPE_P(value)) {
|
|
232
|
+
writer.Double(NUM2DBL(value));
|
|
233
|
+
} else if (RB_STATIC_SYM_P(value)) {
|
|
234
|
+
write_str(writer, rb_sym_to_s(value));
|
|
235
|
+
} else {
|
|
236
|
+
switch (RB_BUILTIN_TYPE(value)) {
|
|
237
|
+
case T_STRING:
|
|
238
|
+
write_str(writer, value);
|
|
239
|
+
break;
|
|
240
|
+
case T_HASH:
|
|
241
|
+
write_hash(writer, value);
|
|
242
|
+
break;
|
|
243
|
+
case T_ARRAY:
|
|
244
|
+
write_array(writer, value);
|
|
245
|
+
break;
|
|
246
|
+
case T_BIGNUM:
|
|
247
|
+
write_bignum(writer, value);
|
|
248
|
+
break;
|
|
249
|
+
case T_STRUCT:
|
|
250
|
+
write_struct(writer, value);
|
|
251
|
+
break;
|
|
252
|
+
default:
|
|
253
|
+
if (rb_obj_is_kind_of(value, rb_cUsaminValue))
|
|
254
|
+
write_usamin(writer, value);
|
|
255
|
+
else
|
|
256
|
+
write_to_s(writer, value);
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
template <class Writer> static inline void write_str(Writer &writer, const VALUE value) {
|
|
263
|
+
VALUE v = get_utf8_str(value);
|
|
264
|
+
writer.String(RSTRING_PTR(v), static_cast<unsigned int>(RSTRING_LEN(v)));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
template <class Writer> static inline void write_key_str(Writer &writer, const VALUE value) {
|
|
268
|
+
VALUE v = get_utf8_str(value);
|
|
269
|
+
writer.Key(RSTRING_PTR(v), static_cast<unsigned int>(RSTRING_LEN(v)));
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
template <class Writer> static inline void write_key_to_s(Writer &writer, const VALUE value) {
|
|
273
|
+
write_key_str(writer, rb_funcall(value, id_to_s, 0));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
template <class Writer> static inline int write_hash_each(VALUE key, VALUE value, Writer *writer) {
|
|
277
|
+
if (RB_TYPE_P(key, T_STRING))
|
|
278
|
+
write_key_str(*writer, key);
|
|
279
|
+
else if (RB_TYPE_P(key, T_SYMBOL))
|
|
280
|
+
write_key_str(*writer, rb_sym_to_s(key));
|
|
281
|
+
else
|
|
282
|
+
write_key_to_s(*writer, key);
|
|
283
|
+
write(*writer, value);
|
|
284
|
+
return ST_CONTINUE;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
template <class Writer> static inline void write_hash(Writer &writer, const VALUE hash) {
|
|
288
|
+
writer.StartObject();
|
|
289
|
+
rb_hash_foreach(hash, (int (*)(ANYARGS))write_hash_each<Writer>, reinterpret_cast<VALUE>((&writer)));
|
|
290
|
+
writer.EndObject();
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
template <class Writer> static inline void write_array(Writer &writer, const VALUE value) {
|
|
294
|
+
writer.StartArray();
|
|
295
|
+
const VALUE *ptr = rb_array_const_ptr(value);
|
|
296
|
+
for (long i = 0; i < rb_array_len(value); i++, ptr++)
|
|
297
|
+
write(writer, *ptr);
|
|
298
|
+
writer.EndArray();
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
template <class Writer> static inline void write_bignum(Writer &writer, const VALUE value) {
|
|
302
|
+
VALUE v = rb_big2str(value, 10);
|
|
303
|
+
writer.RawValue(RSTRING_PTR(v), static_cast<unsigned int>(RSTRING_LEN(v)), rapidjson::kNumberType);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
template <class Writer> static inline void write_struct(Writer &writer, const VALUE value) {
|
|
307
|
+
writer.StartObject();
|
|
308
|
+
VALUE members = rb_struct_members(value);
|
|
309
|
+
const VALUE *ptr = rb_array_const_ptr(members);
|
|
310
|
+
for (long i = 0; i < rb_array_len(members); i++, ptr++) {
|
|
311
|
+
if (RB_TYPE_P(*ptr, T_SYMBOL))
|
|
312
|
+
write_key_str(writer, rb_sym_to_s(*ptr));
|
|
313
|
+
else if (RB_TYPE_P(*ptr, T_STRING))
|
|
314
|
+
write_key_str(writer, *ptr);
|
|
315
|
+
else
|
|
316
|
+
write_key_to_s(writer, *ptr);
|
|
317
|
+
write(writer, rb_struct_aref(value, *ptr));
|
|
318
|
+
}
|
|
319
|
+
writer.EndObject();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
template <class Writer> static void write_value(Writer &writer, rapidjson::Value &value) {
|
|
323
|
+
switch (value.GetType()) {
|
|
324
|
+
case rapidjson::kObjectType:
|
|
325
|
+
writer.StartObject();
|
|
326
|
+
for (auto &m : value.GetObject()) {
|
|
327
|
+
writer.Key(m.name.GetString(), m.name.GetStringLength());
|
|
328
|
+
write_value(writer, m.value);
|
|
329
|
+
}
|
|
330
|
+
writer.EndObject();
|
|
331
|
+
break;
|
|
332
|
+
case rapidjson::kArrayType:
|
|
333
|
+
writer.StartArray();
|
|
334
|
+
for (auto &v : value.GetArray())
|
|
335
|
+
write_value(writer, v);
|
|
336
|
+
writer.EndArray();
|
|
337
|
+
break;
|
|
338
|
+
case rapidjson::kNullType:
|
|
339
|
+
writer.Null();
|
|
340
|
+
break;
|
|
341
|
+
case rapidjson::kFalseType:
|
|
342
|
+
writer.Bool(false);
|
|
343
|
+
break;
|
|
344
|
+
case rapidjson::kTrueType:
|
|
345
|
+
writer.Bool(true);
|
|
346
|
+
break;
|
|
347
|
+
case rapidjson::kNumberType:
|
|
348
|
+
if (value.IsInt())
|
|
349
|
+
writer.Int(value.GetInt());
|
|
350
|
+
else if (value.IsUint())
|
|
351
|
+
writer.Uint(value.GetUint());
|
|
352
|
+
else if (value.IsInt64())
|
|
353
|
+
writer.Int64(value.GetInt64());
|
|
354
|
+
else if (value.IsUint64())
|
|
355
|
+
writer.Uint64(value.GetUint64());
|
|
356
|
+
else
|
|
357
|
+
writer.Double(value.GetDouble());
|
|
358
|
+
break;
|
|
359
|
+
case rapidjson::kStringType:
|
|
360
|
+
writer.String(value.GetString(), value.GetStringLength());
|
|
361
|
+
break;
|
|
362
|
+
default:
|
|
363
|
+
rb_raise(rb_eUsaminError, "Unknown Value Type: %d", value.GetType());
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
template <class Writer> static inline void write_usamin(Writer &writer, const VALUE self) {
|
|
368
|
+
UsaminValue *value = get_value(self);
|
|
369
|
+
check_value(value);
|
|
370
|
+
write_value(writer, *(value->value));
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
template <class Writer> static inline void write_to_s(Writer &writer, const VALUE value) {
|
|
374
|
+
write_str(writer, rb_funcall(value, id_to_s, 0));
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
|
|
214
378
|
UsaminValue::UsaminValue(rapidjson::Value *value, bool free_flag) {
|
|
215
379
|
this->value = value;
|
|
216
380
|
this->free_flag = free_flag;
|
|
@@ -319,7 +483,8 @@ static VALUE w_value_eval(const VALUE self) {
|
|
|
319
483
|
return eval_object(*(value->value));
|
|
320
484
|
else if (value->value->IsArray())
|
|
321
485
|
return eval_array(*(value->value));
|
|
322
|
-
|
|
486
|
+
else
|
|
487
|
+
return Qnil;
|
|
323
488
|
}
|
|
324
489
|
|
|
325
490
|
/*
|
|
@@ -340,8 +505,6 @@ static VALUE w_value_isfrozen(const VALUE self) {
|
|
|
340
505
|
return Qtrue;
|
|
341
506
|
}
|
|
342
507
|
|
|
343
|
-
template <class Writer> static void write_value(Writer&, rapidjson::Value&);
|
|
344
|
-
|
|
345
508
|
/*
|
|
346
509
|
* Dumps data in JSON.
|
|
347
510
|
*
|
|
@@ -352,7 +515,7 @@ static VALUE w_value_marshal_dump(const VALUE self) {
|
|
|
352
515
|
check_value(value);
|
|
353
516
|
rapidjson::StringBuffer buf;
|
|
354
517
|
rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
|
|
355
|
-
write_value(writer, *
|
|
518
|
+
write_value(writer, *value->value);
|
|
356
519
|
return rb_str_new(buf.GetString(), buf.GetSize());
|
|
357
520
|
}
|
|
358
521
|
|
|
@@ -381,8 +544,7 @@ static VALUE w_value_marshal_load(const VALUE self, VALUE source) {
|
|
|
381
544
|
|
|
382
545
|
|
|
383
546
|
/*
|
|
384
|
-
* @
|
|
385
|
-
* @return [Object | nil]
|
|
547
|
+
* @return [Object | nil]
|
|
386
548
|
*
|
|
387
549
|
* @note This method has linear time complexity.
|
|
388
550
|
*/
|
|
@@ -397,14 +559,13 @@ static VALUE w_hash_operator_indexer(const VALUE self, VALUE key) {
|
|
|
397
559
|
}
|
|
398
560
|
|
|
399
561
|
static VALUE hash_enum_size(const VALUE self, VALUE args, VALUE eobj) {
|
|
400
|
-
|
|
401
|
-
check_object(value);
|
|
402
|
-
return UINT2NUM(value->value->MemberCount());
|
|
562
|
+
return UINT2NUM(get_value(self)->value->MemberCount());
|
|
403
563
|
}
|
|
404
564
|
|
|
405
565
|
/*
|
|
406
566
|
* @yield [key, value]
|
|
407
567
|
* @yieldparam key [String]
|
|
568
|
+
* @yieldparam value [Object]
|
|
408
569
|
* @return [Enumerator | self]
|
|
409
570
|
*/
|
|
410
571
|
static VALUE w_hash_each(const VALUE self) {
|
|
@@ -456,6 +617,28 @@ static VALUE w_hash_isempty(const VALUE self) {
|
|
|
456
617
|
return value->value->MemberCount() == 0 ? Qtrue : Qfalse;
|
|
457
618
|
}
|
|
458
619
|
|
|
620
|
+
/*
|
|
621
|
+
* @overload fetch(key, default = nil)
|
|
622
|
+
* @param [String] key
|
|
623
|
+
* @param [Object] default
|
|
624
|
+
* @return [Object]
|
|
625
|
+
*
|
|
626
|
+
* @overload fetch(key)
|
|
627
|
+
* @param [String] key
|
|
628
|
+
* @yield [key]
|
|
629
|
+
* @return [Object]
|
|
630
|
+
*/
|
|
631
|
+
static VALUE w_hash_fetch(const int argc, VALUE* argv, const VALUE self) {
|
|
632
|
+
rb_check_arity(argc, 1, 2);
|
|
633
|
+
UsaminValue *value = get_value(self);
|
|
634
|
+
check_object(value);
|
|
635
|
+
VALUE kvalue = get_utf8_str(argv[0]);
|
|
636
|
+
for (auto &m : value->value->GetObject())
|
|
637
|
+
if (str_compare(RSTRING_PTR(kvalue), RSTRING_LEN(kvalue), m.name.GetString(), m.name.GetStringLength()))
|
|
638
|
+
return eval(m.value);
|
|
639
|
+
return argc == 2 ? argv[1] : rb_block_given_p() ? rb_yield(argv[0]) : Qnil;
|
|
640
|
+
}
|
|
641
|
+
|
|
459
642
|
/*
|
|
460
643
|
* @note This method has linear time complexity.
|
|
461
644
|
*/
|
|
@@ -490,6 +673,34 @@ static VALUE w_hash_length(const VALUE self) {
|
|
|
490
673
|
return UINT2NUM(value->value->MemberCount());
|
|
491
674
|
}
|
|
492
675
|
|
|
676
|
+
/*
|
|
677
|
+
* @yield [key, value]
|
|
678
|
+
* @yieldparam key [String]
|
|
679
|
+
* @yieldparam value [Object]
|
|
680
|
+
* @return [Enumerator | ::Hash]
|
|
681
|
+
*/
|
|
682
|
+
static VALUE w_hash_select(const VALUE self) {
|
|
683
|
+
UsaminValue *value = get_value(self);
|
|
684
|
+
check_object(value);
|
|
685
|
+
RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
|
|
686
|
+
VALUE hash = rb_hash_new();
|
|
687
|
+
if (rb_proc_arity(rb_block_proc()) > 1) {
|
|
688
|
+
for (auto &m : value->value->GetObject()) {
|
|
689
|
+
VALUE args[] = { eval_str(m.name), eval(m.value) };
|
|
690
|
+
if (RTEST(rb_yield_values2(2, args)))
|
|
691
|
+
rb_hash_aset(hash, args[0], args[1]);
|
|
692
|
+
}
|
|
693
|
+
} else {
|
|
694
|
+
for (auto &m : value->value->GetObject()) {
|
|
695
|
+
VALUE key = eval_str(m.name);
|
|
696
|
+
VALUE val = eval(m.value);
|
|
697
|
+
if (RTEST(rb_yield(rb_assoc_new(key, val))))
|
|
698
|
+
rb_hash_aset(hash, key, val);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
return hash;
|
|
702
|
+
}
|
|
703
|
+
|
|
493
704
|
/*
|
|
494
705
|
* Convert to Ruby Hash. Same as {Value#eval}.
|
|
495
706
|
*
|
|
@@ -532,45 +743,57 @@ static VALUE w_array_operator_indexer(const int argc, VALUE* argv, const VALUE s
|
|
|
532
743
|
rb_check_arity(argc, 1, 2);
|
|
533
744
|
UsaminValue *value = get_value(self);
|
|
534
745
|
check_array(value);
|
|
746
|
+
rapidjson::SizeType sz = value->value->Size();
|
|
535
747
|
if (argc == 2) {
|
|
536
|
-
long beg =
|
|
537
|
-
long len =
|
|
748
|
+
long beg = FIX2LONG(argv[0]);
|
|
749
|
+
long len = FIX2LONG(argv[1]);
|
|
538
750
|
if (beg < 0)
|
|
539
|
-
beg
|
|
751
|
+
beg += sz;
|
|
540
752
|
if (beg >= 0 && len >= 0) {
|
|
541
|
-
|
|
542
|
-
if (end >
|
|
543
|
-
end =
|
|
753
|
+
rapidjson::SizeType end = static_cast<rapidjson::SizeType>(beg + len);
|
|
754
|
+
if (end > sz)
|
|
755
|
+
end = sz;
|
|
544
756
|
VALUE ret = rb_ary_new2(end - beg);
|
|
545
|
-
for (
|
|
546
|
-
rb_ary_push(ret, eval((*
|
|
757
|
+
for (rapidjson::SizeType i = static_cast<rapidjson::SizeType>(beg); i < end; i++)
|
|
758
|
+
rb_ary_push(ret, eval((*value->value)[i]));
|
|
547
759
|
return ret;
|
|
548
760
|
}
|
|
549
761
|
} else if (rb_obj_is_kind_of(argv[0], rb_cRange)) {
|
|
550
762
|
long beg, len;
|
|
551
|
-
if (rb_range_beg_len(argv[0], &beg, &len,
|
|
763
|
+
if (rb_range_beg_len(argv[0], &beg, &len, sz, 0) == Qtrue) {
|
|
552
764
|
VALUE ret = rb_ary_new2(len);
|
|
553
|
-
for (
|
|
554
|
-
rb_ary_push(ret, eval((*
|
|
765
|
+
for (rapidjson::SizeType i = static_cast<rapidjson::SizeType>(beg); i < beg + len; i++)
|
|
766
|
+
rb_ary_push(ret, eval((*value->value)[i]));
|
|
555
767
|
return ret;
|
|
556
768
|
}
|
|
557
769
|
} else {
|
|
558
|
-
long l =
|
|
770
|
+
long l = FIX2LONG(argv[0]);
|
|
559
771
|
if (l < 0)
|
|
560
|
-
l
|
|
561
|
-
if (l
|
|
562
|
-
|
|
563
|
-
if (i < value->value->Size())
|
|
564
|
-
return eval((*(value->value))[i]);
|
|
565
|
-
}
|
|
772
|
+
l += sz;
|
|
773
|
+
if (0 <= l && l < sz)
|
|
774
|
+
return eval((*value->value)[static_cast<rapidjson::SizeType>(l)]);
|
|
566
775
|
}
|
|
567
776
|
return Qnil;
|
|
568
777
|
}
|
|
569
778
|
|
|
570
|
-
|
|
779
|
+
/*
|
|
780
|
+
* @param [Integer] nth
|
|
781
|
+
* @return [Object]
|
|
782
|
+
*/
|
|
783
|
+
static VALUE w_array_at(const VALUE self, VALUE nth) {
|
|
571
784
|
UsaminValue *value = get_value(self);
|
|
572
785
|
check_array(value);
|
|
573
|
-
|
|
786
|
+
long l = FIX2LONG(nth);
|
|
787
|
+
rapidjson::SizeType sz = value->value->Size();
|
|
788
|
+
if (l < 0)
|
|
789
|
+
l += sz;
|
|
790
|
+
if (0 <= l && l < sz)
|
|
791
|
+
return eval((*value->value)[static_cast<rapidjson::SizeType>(l)]);
|
|
792
|
+
return Qnil;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
static VALUE array_enum_size(const VALUE self, VALUE args, VALUE eobj) {
|
|
796
|
+
return UINT2NUM(get_value(self)->value->Size());
|
|
574
797
|
}
|
|
575
798
|
|
|
576
799
|
/*
|
|
@@ -607,17 +830,60 @@ static VALUE w_array_isempty(const VALUE self) {
|
|
|
607
830
|
}
|
|
608
831
|
|
|
609
832
|
/*
|
|
610
|
-
* @
|
|
611
|
-
*
|
|
833
|
+
* @overload fetch(nth)
|
|
834
|
+
* @param [Integer] nth
|
|
835
|
+
* @return [Object]
|
|
836
|
+
* @raise [IndexError] if nth is out of array bounds
|
|
837
|
+
*
|
|
838
|
+
* @overload fetch(nth, ifnone)
|
|
839
|
+
* @param [Integer] nth
|
|
840
|
+
* @param [Object] ifnone
|
|
841
|
+
* @return [Object]
|
|
842
|
+
*
|
|
843
|
+
* @overload fetch(nth)
|
|
844
|
+
* @param [Integer] nth
|
|
845
|
+
* @yield [nth]
|
|
846
|
+
* @return [Object]
|
|
612
847
|
*/
|
|
613
|
-
static VALUE
|
|
848
|
+
static VALUE w_array_fetch(const int argc, VALUE* argv, const VALUE self) {
|
|
849
|
+
rb_check_arity(argc, 1, 2);
|
|
850
|
+
UsaminValue *value = get_value(self);
|
|
851
|
+
check_array(value);
|
|
852
|
+
rapidjson::SizeType sz = value->value->Size();
|
|
853
|
+
|
|
854
|
+
long l = FIX2LONG(argv[0]);
|
|
855
|
+
if (l < 0)
|
|
856
|
+
l += sz;
|
|
857
|
+
if (0 <= l && l < sz)
|
|
858
|
+
return eval((*value->value)[static_cast<rapidjson::SizeType>(l)]);
|
|
859
|
+
|
|
860
|
+
if (argc == 2)
|
|
861
|
+
return argv[1];
|
|
862
|
+
else if (rb_block_given_p())
|
|
863
|
+
return rb_yield(argv[0]);
|
|
864
|
+
else
|
|
865
|
+
rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%u", FIX2LONG(argv[0]), -static_cast<long>(sz), sz);
|
|
866
|
+
return Qnil;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/*
|
|
870
|
+
* @overload find_index(val)
|
|
871
|
+
* @param [Object] val
|
|
872
|
+
* @return [Integer | nil]
|
|
873
|
+
*
|
|
874
|
+
* @overload find_index
|
|
875
|
+
* @yield [item]
|
|
876
|
+
* @yieldparam item [Object]
|
|
877
|
+
* @return [Integer | nil]
|
|
878
|
+
*/
|
|
879
|
+
static VALUE w_array_find_index(int argc, VALUE* argv, const VALUE self) {
|
|
614
880
|
rb_check_arity(argc, 0, 1);
|
|
615
881
|
UsaminValue *value = get_value(self);
|
|
616
882
|
check_array(value);
|
|
617
883
|
|
|
618
884
|
if (argc == 1) {
|
|
619
885
|
for (rapidjson::SizeType i = 0; i < value->value->Size(); i++) {
|
|
620
|
-
if (rb_equal(argv[0], eval((*
|
|
886
|
+
if (rb_equal(argv[0], eval((*value->value)[i])) == Qtrue)
|
|
621
887
|
return UINT2NUM(i);
|
|
622
888
|
}
|
|
623
889
|
return Qnil;
|
|
@@ -625,12 +891,26 @@ static VALUE w_array_index(int argc, VALUE* argv, const VALUE self) {
|
|
|
625
891
|
|
|
626
892
|
RETURN_SIZED_ENUMERATOR(self, 0, nullptr, array_enum_size);
|
|
627
893
|
for (rapidjson::SizeType i = 0; i < value->value->Size(); i++) {
|
|
628
|
-
if (RTEST(rb_yield(eval((*
|
|
894
|
+
if (RTEST(rb_yield(eval((*value->value)[i]))))
|
|
629
895
|
return UINT2NUM(i);
|
|
630
896
|
}
|
|
631
897
|
return Qnil;
|
|
632
898
|
}
|
|
633
899
|
|
|
900
|
+
/*
|
|
901
|
+
* @overload index(val)
|
|
902
|
+
* @param [Object] val
|
|
903
|
+
* @return [Integer | nil]
|
|
904
|
+
*
|
|
905
|
+
* @overload index
|
|
906
|
+
* @yield [item]
|
|
907
|
+
* @yieldparam item [Object]
|
|
908
|
+
* @return [Integer | nil]
|
|
909
|
+
*/
|
|
910
|
+
static VALUE w_array_index(int argc, VALUE* argv, const VALUE self) {
|
|
911
|
+
return w_array_find_index(argc, argv, self);
|
|
912
|
+
}
|
|
913
|
+
|
|
634
914
|
/*
|
|
635
915
|
* @overload first
|
|
636
916
|
* @return [Object | nil]
|
|
@@ -642,24 +922,47 @@ static VALUE w_array_first(const int argc, VALUE* argv, const VALUE self) {
|
|
|
642
922
|
rb_check_arity(argc, 0, 1);
|
|
643
923
|
UsaminValue *value = get_value(self);
|
|
644
924
|
check_array(value);
|
|
925
|
+
rapidjson::SizeType sz = value->value->Size();
|
|
645
926
|
|
|
646
927
|
if (argc == 0) {
|
|
647
|
-
if (
|
|
928
|
+
if (sz == 0)
|
|
648
929
|
return Qnil;
|
|
649
|
-
return eval(
|
|
930
|
+
return eval(*value->value->Begin());
|
|
931
|
+
} else {
|
|
932
|
+
long l = FIX2LONG(argv[0]);
|
|
933
|
+
if (l > sz)
|
|
934
|
+
l = sz;
|
|
935
|
+
VALUE ret = rb_ary_new2(l);
|
|
936
|
+
for (auto v = value->value->Begin(); v < value->value->Begin() + l; v++)
|
|
937
|
+
rb_ary_push(ret, eval(*v));
|
|
938
|
+
return ret;
|
|
650
939
|
}
|
|
940
|
+
}
|
|
651
941
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
942
|
+
/*
|
|
943
|
+
* @overload last
|
|
944
|
+
* @return [Object | nil]
|
|
945
|
+
*
|
|
946
|
+
* @overload last(n)
|
|
947
|
+
* @return [::Array<Object>]
|
|
948
|
+
*/
|
|
949
|
+
static VALUE w_array_last(const int argc, VALUE* argv, const VALUE self) {
|
|
950
|
+
rb_check_arity(argc, 0, 1);
|
|
951
|
+
UsaminValue *value = get_value(self);
|
|
952
|
+
check_array(value);
|
|
953
|
+
rapidjson::SizeType sz = value->value->Size();
|
|
661
954
|
|
|
662
|
-
|
|
955
|
+
if (argc == 0) {
|
|
956
|
+
return sz > 0 ? eval(*(value->value->End() - 1)) : Qnil;
|
|
957
|
+
} else {
|
|
958
|
+
long l = FIX2LONG(argv[0]);
|
|
959
|
+
if (l > sz)
|
|
960
|
+
l = sz;
|
|
961
|
+
VALUE ret = rb_ary_new2(l);
|
|
962
|
+
for (auto v = value->value->End() - l; v < value->value->End(); v++)
|
|
963
|
+
rb_ary_push(ret, eval(*v));
|
|
964
|
+
return ret;
|
|
965
|
+
}
|
|
663
966
|
}
|
|
664
967
|
|
|
665
968
|
/*
|
|
@@ -671,6 +974,24 @@ static VALUE w_array_length(const VALUE self) {
|
|
|
671
974
|
return UINT2NUM(value->value->Size());
|
|
672
975
|
}
|
|
673
976
|
|
|
977
|
+
/*
|
|
978
|
+
* @overload slice(nth)
|
|
979
|
+
* @param [Integer] nth
|
|
980
|
+
* @return [Object | nil]
|
|
981
|
+
*
|
|
982
|
+
* @overload slice(start, length)
|
|
983
|
+
* @param [Integer] start
|
|
984
|
+
* @param [Integer] length
|
|
985
|
+
* @return [::Array<Object> | nil]
|
|
986
|
+
*
|
|
987
|
+
* @overload slice(range)
|
|
988
|
+
* @param [Range] range
|
|
989
|
+
* @return [::Array<Object> | nil]
|
|
990
|
+
*/
|
|
991
|
+
static VALUE w_array_slice(const int argc, VALUE* argv, const VALUE self) {
|
|
992
|
+
return w_array_operator_indexer(argc, argv, self);
|
|
993
|
+
}
|
|
994
|
+
|
|
674
995
|
/*
|
|
675
996
|
* Convert to Ruby data structures. Same as {Value#eval}.
|
|
676
997
|
*
|
|
@@ -683,163 +1004,6 @@ static VALUE w_array_eval(const VALUE self) {
|
|
|
683
1004
|
}
|
|
684
1005
|
|
|
685
1006
|
|
|
686
|
-
template <class Writer> static void write(Writer&, const VALUE);
|
|
687
|
-
|
|
688
|
-
template <class Writer> static inline void write_str(Writer &writer, const VALUE value) {
|
|
689
|
-
VALUE v = get_utf8_str(value);
|
|
690
|
-
writer.String(RSTRING_PTR(v), static_cast<unsigned int>(RSTRING_LEN(v)));
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
template <class Writer> static inline void write_to_s(Writer &writer, const VALUE value) {
|
|
694
|
-
write_str(writer, rb_funcall(value, id_to_s, 0));
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
template <class Writer> static inline void write_key_str(Writer &writer, const VALUE value) {
|
|
698
|
-
VALUE v = get_utf8_str(value);
|
|
699
|
-
writer.Key(RSTRING_PTR(v), static_cast<unsigned int>(RSTRING_LEN(v)));
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
template <class Writer> static inline void write_key_to_s(Writer &writer, const VALUE value) {
|
|
703
|
-
write_key_str(writer, rb_funcall(value, id_to_s, 0));
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
template <class Writer> static inline void write_bignum(Writer &writer, const VALUE value) {
|
|
707
|
-
VALUE v = rb_big2str(value, 10);
|
|
708
|
-
writer.RawValue(RSTRING_PTR(v), static_cast<unsigned int>(RSTRING_LEN(v)), rapidjson::kNumberType);
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
template <class Writer> static inline int write_hash_each(VALUE key, VALUE value, Writer *writer) {
|
|
712
|
-
if (RB_TYPE_P(key, T_STRING))
|
|
713
|
-
write_key_str(*writer, key);
|
|
714
|
-
else if (RB_TYPE_P(key, T_SYMBOL))
|
|
715
|
-
write_key_str(*writer, rb_sym_to_s(key));
|
|
716
|
-
else
|
|
717
|
-
write_key_to_s(*writer, key);
|
|
718
|
-
write(*writer, value);
|
|
719
|
-
return ST_CONTINUE;
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
template <class Writer> static inline void write_hash(Writer &writer, const VALUE hash) {
|
|
723
|
-
writer.StartObject();
|
|
724
|
-
rb_hash_foreach(hash, (int (*)(ANYARGS))write_hash_each<Writer>, reinterpret_cast<VALUE>((&writer)));
|
|
725
|
-
writer.EndObject();
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
template <class Writer> static inline void write_array(Writer &writer, const VALUE value) {
|
|
729
|
-
writer.StartArray();
|
|
730
|
-
const VALUE *ptr = rb_array_const_ptr(value);
|
|
731
|
-
for (long i = 0; i < rb_array_len(value); i++, ptr++)
|
|
732
|
-
write(writer, *ptr);
|
|
733
|
-
writer.EndArray();
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
template <class Writer> static inline void write_struct(Writer &writer, const VALUE value) {
|
|
737
|
-
writer.StartObject();
|
|
738
|
-
VALUE members = rb_struct_members(value);
|
|
739
|
-
const VALUE *ptr = rb_array_const_ptr(members);
|
|
740
|
-
for (long i = 0; i < rb_array_len(members); i++, ptr++) {
|
|
741
|
-
if (RB_TYPE_P(*ptr, T_SYMBOL))
|
|
742
|
-
write_key_str(writer, rb_sym_to_s(*ptr));
|
|
743
|
-
else if (RB_TYPE_P(*ptr, T_STRING))
|
|
744
|
-
write_key_str(writer, *ptr);
|
|
745
|
-
else
|
|
746
|
-
write_key_to_s(writer, *ptr);
|
|
747
|
-
write(writer, rb_struct_aref(value, *ptr));
|
|
748
|
-
}
|
|
749
|
-
writer.EndObject();
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
template <class Writer> static void write_value(Writer &writer, rapidjson::Value &value) {
|
|
753
|
-
switch (value.GetType()) {
|
|
754
|
-
case rapidjson::kObjectType:
|
|
755
|
-
writer.StartObject();
|
|
756
|
-
for (auto &m : value.GetObject()) {
|
|
757
|
-
writer.Key(m.name.GetString(), m.name.GetStringLength());
|
|
758
|
-
write_value(writer, m.value);
|
|
759
|
-
}
|
|
760
|
-
writer.EndObject();
|
|
761
|
-
break;
|
|
762
|
-
case rapidjson::kArrayType:
|
|
763
|
-
writer.StartArray();
|
|
764
|
-
for (auto &v : value.GetArray())
|
|
765
|
-
write_value(writer, v);
|
|
766
|
-
writer.EndArray();
|
|
767
|
-
break;
|
|
768
|
-
case rapidjson::kNullType:
|
|
769
|
-
writer.Null();
|
|
770
|
-
break;
|
|
771
|
-
case rapidjson::kFalseType:
|
|
772
|
-
writer.Bool(false);
|
|
773
|
-
break;
|
|
774
|
-
case rapidjson::kTrueType:
|
|
775
|
-
writer.Bool(true);
|
|
776
|
-
break;
|
|
777
|
-
case rapidjson::kNumberType:
|
|
778
|
-
if (value.IsInt())
|
|
779
|
-
writer.Int(value.GetInt());
|
|
780
|
-
else if (value.IsUint())
|
|
781
|
-
writer.Uint(value.GetUint());
|
|
782
|
-
else if (value.IsInt64())
|
|
783
|
-
writer.Int64(value.GetInt64());
|
|
784
|
-
else if (value.IsUint64())
|
|
785
|
-
writer.Uint64(value.GetUint64());
|
|
786
|
-
else
|
|
787
|
-
writer.Double(value.GetDouble());
|
|
788
|
-
break;
|
|
789
|
-
case rapidjson::kStringType:
|
|
790
|
-
writer.String(value.GetString(), value.GetStringLength());
|
|
791
|
-
break;
|
|
792
|
-
default:
|
|
793
|
-
rb_raise(rb_eUsaminError, "Unknown Value Type: %d", value.GetType());
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
template <class Writer> static inline void write_usamin(Writer &writer, const VALUE self) {
|
|
798
|
-
UsaminValue *value = get_value(self);
|
|
799
|
-
check_value(value);
|
|
800
|
-
write_value(writer, *(value->value));
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
template <class Writer> static void write(Writer &writer, const VALUE value) {
|
|
804
|
-
if (value == Qnil) {
|
|
805
|
-
writer.Null();
|
|
806
|
-
} else if (value == Qfalse) {
|
|
807
|
-
writer.Bool(false);
|
|
808
|
-
} else if (value == Qtrue) {
|
|
809
|
-
writer.Bool(true);
|
|
810
|
-
} else if (RB_FIXNUM_P(value)) {
|
|
811
|
-
writer.Int64(FIX2LONG(value));
|
|
812
|
-
} else if (RB_FLOAT_TYPE_P(value)) {
|
|
813
|
-
writer.Double(NUM2DBL(value));
|
|
814
|
-
} else if (RB_STATIC_SYM_P(value)) {
|
|
815
|
-
write_str(writer, rb_sym_to_s(value));
|
|
816
|
-
} else {
|
|
817
|
-
switch (RB_BUILTIN_TYPE(value)) {
|
|
818
|
-
case T_STRING:
|
|
819
|
-
write_str(writer, value);
|
|
820
|
-
break;
|
|
821
|
-
case T_HASH:
|
|
822
|
-
write_hash(writer, value);
|
|
823
|
-
break;
|
|
824
|
-
case T_ARRAY:
|
|
825
|
-
write_array(writer, value);
|
|
826
|
-
break;
|
|
827
|
-
case T_BIGNUM:
|
|
828
|
-
write_bignum(writer, value);
|
|
829
|
-
break;
|
|
830
|
-
case T_STRUCT:
|
|
831
|
-
write_struct(writer, value);
|
|
832
|
-
break;
|
|
833
|
-
default:
|
|
834
|
-
if (rb_obj_is_kind_of(value, rb_cUsaminValue))
|
|
835
|
-
write_usamin(writer, value);
|
|
836
|
-
else
|
|
837
|
-
write_to_s(writer, value);
|
|
838
|
-
break;
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
|
|
843
1007
|
/*
|
|
844
1008
|
* Generate the JSON string from Ruby data structures.
|
|
845
1009
|
*
|
|
@@ -857,10 +1021,11 @@ static VALUE w_generate(const VALUE self, VALUE value) {
|
|
|
857
1021
|
/*
|
|
858
1022
|
* Generate the prettified JSON string from Ruby data structures.
|
|
859
1023
|
*
|
|
860
|
-
* @overload
|
|
1024
|
+
* @overload pretty_generate(obj, opts = {})
|
|
861
1025
|
* @param [Object] obj an object to serialize
|
|
862
1026
|
* @param [::Hash] opts options
|
|
863
1027
|
* @option opts [String] :indent (' ') a string used to indent
|
|
1028
|
+
* @option opts [Boolean] :single_line_array (false)
|
|
864
1029
|
* @return [String]
|
|
865
1030
|
*/
|
|
866
1031
|
static VALUE w_pretty_generate(const int argc, VALUE *argv, const VALUE self) {
|
|
@@ -873,8 +1038,6 @@ static VALUE w_pretty_generate(const int argc, VALUE *argv, const VALUE self) {
|
|
|
873
1038
|
unsigned int indent_count = 2;
|
|
874
1039
|
if (argc > 1) {
|
|
875
1040
|
VALUE v_indent = rb_hash_lookup(options, sym_indent);
|
|
876
|
-
VALUE v_single_line_array = rb_hash_lookup(options, sym_single_line_array);
|
|
877
|
-
|
|
878
1041
|
if (RTEST(v_indent)) {
|
|
879
1042
|
if (RB_FIXNUM_P(v_indent)) {
|
|
880
1043
|
long l = FIX2LONG(v_indent);
|
|
@@ -887,9 +1050,6 @@ static VALUE w_pretty_generate(const int argc, VALUE *argv, const VALUE self) {
|
|
|
887
1050
|
} else {
|
|
888
1051
|
const char *indent_str = RSTRING_PTR(v);
|
|
889
1052
|
switch (indent_str[0]) {
|
|
890
|
-
case '\0':
|
|
891
|
-
indent_count = 0;
|
|
892
|
-
break;
|
|
893
1053
|
case ' ':
|
|
894
1054
|
case '\t':
|
|
895
1055
|
case '\r':
|
|
@@ -899,7 +1059,6 @@ static VALUE w_pretty_generate(const int argc, VALUE *argv, const VALUE self) {
|
|
|
899
1059
|
default:
|
|
900
1060
|
rb_raise(rb_eUsaminError, ":indent must be a repetation of \" \", \"\\t\", \"\\r\" or \"\\n\".");
|
|
901
1061
|
}
|
|
902
|
-
|
|
903
1062
|
for (long i = 1; i < vlen; i++)
|
|
904
1063
|
if (indent_str[0] != indent_str[i])
|
|
905
1064
|
rb_raise(rb_eUsaminError, ":indent must be a repetation of \" \", \"\\t\", \"\\r\" or \"\\n\".");
|
|
@@ -908,7 +1067,7 @@ static VALUE w_pretty_generate(const int argc, VALUE *argv, const VALUE self) {
|
|
|
908
1067
|
}
|
|
909
1068
|
}
|
|
910
1069
|
|
|
911
|
-
if (RTEST(
|
|
1070
|
+
if (RTEST(rb_hash_lookup(options, sym_single_line_array)))
|
|
912
1071
|
writer.SetFormatOptions(rapidjson::kFormatSingleLineArray);
|
|
913
1072
|
}
|
|
914
1073
|
writer.SetIndent(indent_char, indent_count);
|
|
@@ -950,11 +1109,13 @@ extern "C" void Init_usamin(void) {
|
|
|
950
1109
|
rb_define_alloc_func(rb_cUsaminHash, usamin_alloc);
|
|
951
1110
|
rb_undef_method(rb_cUsaminHash, "initialize");
|
|
952
1111
|
rb_define_method(rb_cUsaminHash, "[]", RUBY_METHOD_FUNC(w_hash_operator_indexer), 1);
|
|
1112
|
+
rb_define_method(rb_cUsaminHash, "assoc", RUBY_METHOD_FUNC(w_hash_operator_indexer), 1);
|
|
953
1113
|
rb_define_method(rb_cUsaminHash, "each", RUBY_METHOD_FUNC(w_hash_each), 0);
|
|
954
1114
|
rb_define_method(rb_cUsaminHash, "each_pair", RUBY_METHOD_FUNC(w_hash_each), 0);
|
|
955
1115
|
rb_define_method(rb_cUsaminHash, "each_key", RUBY_METHOD_FUNC(w_hash_each_key), 0);
|
|
956
1116
|
rb_define_method(rb_cUsaminHash, "each_value", RUBY_METHOD_FUNC(w_hash_each_value), 0);
|
|
957
1117
|
rb_define_method(rb_cUsaminHash, "empty?", RUBY_METHOD_FUNC(w_hash_isempty), 0);
|
|
1118
|
+
rb_define_method(rb_cUsaminHash, "fetch", RUBY_METHOD_FUNC(w_hash_fetch), -1);
|
|
958
1119
|
rb_define_method(rb_cUsaminHash, "has_key?", RUBY_METHOD_FUNC(w_hash_haskey), 1);
|
|
959
1120
|
rb_define_method(rb_cUsaminHash, "include?", RUBY_METHOD_FUNC(w_hash_haskey), 1);
|
|
960
1121
|
rb_define_method(rb_cUsaminHash, "key?", RUBY_METHOD_FUNC(w_hash_haskey), 1);
|
|
@@ -962,6 +1123,7 @@ extern "C" void Init_usamin(void) {
|
|
|
962
1123
|
rb_define_method(rb_cUsaminHash, "keys", RUBY_METHOD_FUNC(w_hash_keys), 0);
|
|
963
1124
|
rb_define_method(rb_cUsaminHash, "length", RUBY_METHOD_FUNC(w_hash_length), 0);
|
|
964
1125
|
rb_define_method(rb_cUsaminHash, "size", RUBY_METHOD_FUNC(w_hash_length), 0);
|
|
1126
|
+
rb_define_method(rb_cUsaminHash, "select", RUBY_METHOD_FUNC(w_hash_select), 0);
|
|
965
1127
|
rb_define_method(rb_cUsaminHash, "to_h", RUBY_METHOD_FUNC(w_hash_eval), 0);
|
|
966
1128
|
rb_define_method(rb_cUsaminHash, "to_hash", RUBY_METHOD_FUNC(w_hash_eval), 0);
|
|
967
1129
|
rb_define_method(rb_cUsaminHash, "values", RUBY_METHOD_FUNC(w_hash_values), 0);
|
|
@@ -971,14 +1133,18 @@ extern "C" void Init_usamin(void) {
|
|
|
971
1133
|
rb_define_alloc_func(rb_cUsaminArray, usamin_alloc);
|
|
972
1134
|
rb_undef_method(rb_cUsaminArray, "initialize");
|
|
973
1135
|
rb_define_method(rb_cUsaminArray, "[]", RUBY_METHOD_FUNC(w_array_operator_indexer), -1);
|
|
1136
|
+
rb_define_method(rb_cUsaminArray, "at", RUBY_METHOD_FUNC(w_array_at), 1);
|
|
974
1137
|
rb_define_method(rb_cUsaminArray, "each", RUBY_METHOD_FUNC(w_array_each), 0);
|
|
975
1138
|
rb_define_method(rb_cUsaminArray, "each_index", RUBY_METHOD_FUNC(w_array_each_index), 0);
|
|
976
1139
|
rb_define_method(rb_cUsaminArray, "empty?", RUBY_METHOD_FUNC(w_array_isempty), 0);
|
|
1140
|
+
rb_define_method(rb_cUsaminArray, "fetch", RUBY_METHOD_FUNC(w_array_fetch), -1);
|
|
1141
|
+
rb_define_method(rb_cUsaminArray, "find_index", RUBY_METHOD_FUNC(w_array_find_index), -1);
|
|
977
1142
|
rb_define_method(rb_cUsaminArray, "index", RUBY_METHOD_FUNC(w_array_index), -1);
|
|
978
|
-
rb_define_method(rb_cUsaminArray, "find_index", RUBY_METHOD_FUNC(w_array_index), -1);
|
|
979
1143
|
rb_define_method(rb_cUsaminArray, "first", RUBY_METHOD_FUNC(w_array_first), -1);
|
|
1144
|
+
rb_define_method(rb_cUsaminArray, "last", RUBY_METHOD_FUNC(w_array_last), -1);
|
|
980
1145
|
rb_define_method(rb_cUsaminArray, "length", RUBY_METHOD_FUNC(w_array_length), 0);
|
|
981
1146
|
rb_define_method(rb_cUsaminArray, "size", RUBY_METHOD_FUNC(w_array_length), 0);
|
|
1147
|
+
rb_define_method(rb_cUsaminArray, "slice", RUBY_METHOD_FUNC(w_array_slice), -1);
|
|
982
1148
|
rb_define_method(rb_cUsaminArray, "to_a", RUBY_METHOD_FUNC(w_array_eval), 0);
|
|
983
1149
|
rb_define_method(rb_cUsaminArray, "to_ary", RUBY_METHOD_FUNC(w_array_eval), 0);
|
|
984
1150
|
|
data/lib/usamin.rb
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'usamin'
|
|
2
|
+
|
|
3
|
+
module JSON
|
|
4
|
+
def self.generate(object, **options)
|
|
5
|
+
options[:indent] ? Usamin.pretty_generate(object, indent: options[:indent]) : Usamin.generate(object)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.pretty_generate(object, **options)
|
|
9
|
+
options[:indent] ? Usamin.pretty_generate(object, indent: options[:indent]) : Usamin.pretty_generate(object)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.parse(source, **options)
|
|
13
|
+
Usamin.parse(object)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.load(source, proc = nil, **options)
|
|
17
|
+
ret = Usamin.parse(object)
|
|
18
|
+
proc.call(ret) if proc
|
|
19
|
+
ret
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
alias fast_generate generate
|
|
24
|
+
alias restore load
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/usamin/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: usamin
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 7.7.
|
|
4
|
+
version: 7.7.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ishotihadus
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2018-02-
|
|
11
|
+
date: 2018-02-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -86,6 +86,7 @@ files:
|
|
|
86
86
|
- ext/usamin/extconf.rb
|
|
87
87
|
- ext/usamin/usamin.cpp
|
|
88
88
|
- lib/usamin.rb
|
|
89
|
+
- lib/usamin/overwrite.rb
|
|
89
90
|
- lib/usamin/version.rb
|
|
90
91
|
- usamin.gemspec
|
|
91
92
|
homepage: https://github.com/Ishotihadus/usamin
|