usamin 7.7.0 → 7.7.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 38c48b49c05c5a95289abb777b32db4b47252fd31c5553acf09b11f3c076b500
4
- data.tar.gz: 023641ec4fb9fc7277044ae4c6a1dcca134ace8ed4aaddf2b64c80a4fb7ef89e
3
+ metadata.gz: d053f43fdfdf7a7698d45fa5707245c7ea47946c906f3c504f27aabc543f38b1
4
+ data.tar.gz: 0d2b48bf5962478bd7ce35c1a4cfca68589881b59b62ccff5fadd6addd59be8b
5
5
  SHA512:
6
- metadata.gz: 493e984049b444963a1be108cc624bc6a426edbf3c951c860f4662f4f3121e309e1768be11a919a16353c36fc96fb90124daf68bb68ec8f5756a82850c4a7618
7
- data.tar.gz: 74cfe2c5148808a6be7f43a6bddf5ec1306ee3692a7833ea775392b61948fee537fc83befe55d0961d5ff3771e43a91d208294d2a8b4c41c8df20c738976cb5a
6
+ metadata.gz: baf083e37d53f5ebfd4ca36e39ec239d62f5f0e198c2a9d79c0efcc77060d5483962d1e1de1268a143ff566713f413f8853a29a68cacc9bc9722d5169abb6cde
7
+ data.tar.gz: 540f79a2a0015a39b119435b064d683687f248c6405855170dc8fa7469dfcffb4f393df2f33041f4ff1fcd6816f9d2f9808a2249f0ee68f78e685486c6d0c707
data/.gitignore CHANGED
@@ -14,3 +14,4 @@ mkmf.log
14
14
 
15
15
  .DS_Store
16
16
  /testdata/
17
+ /vendor/
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
- "miku maekawa": {
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": [2, 22],
48
+ "birthday": "2/22",
47
49
  "cv": "natsumi takamori"
48
50
  },
49
- "nana abe": {
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": [5, 15],
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 Hash, but this can be handled like a Hash.
72
+ Here, `data` is not a Array, but this can be handled like an Array.
69
73
 
70
74
  ```ruby
71
- data.keys
72
- #=> ["miku maekawa", "nana abe"]
75
+ data.size
76
+ #=> 2
73
77
 
74
- data.map{|k, v| [k, v['age']]}.to_h
75
- #=> {"miku maekawa"=>15, "nana abe"=>17}
78
+ data.map{|e| e['name']}
79
+ #=> ["miku maekawa", "nana abe"]
76
80
  ```
77
81
 
78
- Array data also can be handled like an Array object.
82
+ Objects also can be handled like Hash objects.
79
83
 
80
84
  ```ruby
81
- data['nana abe']['body_size'].size
82
- #=> 3
85
+ data.first['name']
86
+ #=> "miku maekawa"
83
87
 
84
- data['nana abe']['body_size'].inject(:+)
85
- #=> 225
88
+ data.first.keys
89
+ #=> ["name", "age", "height", "weight", "body_size", "birthday", "cv"]
86
90
  ```
87
91
 
88
- The `eval` and `eval_r` converts these data structures into the Ruby data structures. `_r` means recursiveness.
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
- #=> {"miku maekawa"=>#<Usamin::Hash>, "nana abe"=>#<Usamin::Hash>}
96
+ #=> [#<Usamin::Hash>, #<Usamin::Hash>]
93
97
 
94
- data['miku maekawa'].eval_r
95
- #=> {"age"=>15, "height"=>152, "weight"=>45, "body_size"=>[85, 55, 81], "birthday"=>[2, 22], "cv"=>"natsumi takamori"}
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
- data.eval_r
98
- #=> same as Usamin.parse(json)
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
- "miku maekawa" => {
111
- "age"=>15,
112
- "height"=>152,
113
- "weight"=>45,
114
- "body_size"=>[85, 55, 81],
115
- "birthday"=>[2, 22],
116
- "cv"=>"natsumi takamori"},
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.785524 0.007927 0.793451 ( 0.805269)
188
- oj 1.833580 0.043648 1.877228 ( 1.895704)
189
- usamin 0.595523 0.012299 0.607822 ( 0.612215)
190
- usamin (fast) 0.286458 0.008710 0.295168 ( 0.297998)
191
- usamin (load) 0.484056 0.011770 0.495826 ( 0.498110)
192
- usamin (load / fast) 0.187712 0.020202 0.207914 ( 0.210711)
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.469471 0.005208 0.474679 ( 0.478920)
196
- oj 0.327143 0.002947 0.330090 ( 0.331882)
197
- usamin 0.362764 0.005633 0.368397 ( 0.370940)
198
- usamin (fast) 0.359859 0.005884 0.365743 ( 0.371016)
199
- usamin (load) 0.117140 0.007003 0.124143 ( 0.126548)
200
- usamin (load / fast) 0.115237 0.010061 0.125298 ( 0.128470)
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.238582 0.002561 0.241143 ( 0.243726)
204
- oj 0.162212 0.001031 0.163243 ( 0.165047)
205
- usamin 0.194476 0.001523 0.195999 ( 0.197920)
206
- usamin (fast) 0.192985 0.001339 0.194324 ( 0.197404)
207
- usamin (load) 0.070360 0.005012 0.075372 ( 0.078090)
208
- usamin (load / fast) 0.067618 0.006416 0.074034 ( 0.076244)
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.988155 0.029728 2.017883 ( 2.023475)
216
- oj 2.092999 0.033136 2.126135 ( 2.135765)
217
- usamin 0.296385 0.031412 0.327797 ( 0.330314)
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.243795 0.007463 0.251258 ( 0.256621)
221
- oj 0.076474 0.009617 0.086091 ( 0.087966)
222
- usamin 0.059434 0.009616 0.069050 ( 0.071158)
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.159030 0.006730 0.165760 ( 0.170796)
226
- oj 0.052856 0.009164 0.062020 ( 0.064344)
227
- usamin 0.047707 0.010265 0.057972 ( 0.061729)
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.188493 0.066003 2.254496 ( 2.260332)
235
- oj 1.583613 0.029798 1.613411 ( 1.619652)
236
- usamin 0.399066 0.081314 0.480380 ( 0.482841)
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.300601 0.029596 0.330197 ( 0.335351)
240
- oj 0.065151 0.009553 0.074704 ( 0.077010)
241
- usamin 0.089872 0.022203 0.112075 ( 0.116063)
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.189439 0.010086 0.199525 ( 0.204491)
245
- oj 0.040982 0.008203 0.049185 ( 0.049352)
246
- usamin 0.044296 0.010095 0.054391 ( 0.056245)
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
@@ -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
- return Qnil;
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, *(value->value));
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
- * @overload [](name)
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
- UsaminValue *value = get_value(self);
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 = NUM2LONG(argv[0]);
537
- long len = NUM2LONG(argv[1]);
748
+ long beg = FIX2LONG(argv[0]);
749
+ long len = FIX2LONG(argv[1]);
538
750
  if (beg < 0)
539
- beg = beg + value->value->Size();
751
+ beg += sz;
540
752
  if (beg >= 0 && len >= 0) {
541
- long end = beg + len;
542
- if (end > value->value->Size())
543
- end = value->value->Size();
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 (long i = beg; i < end; i++)
546
- rb_ary_push(ret, eval((*(value->value))[static_cast<unsigned int>(i)]));
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, value->value->Size(), 0) == Qtrue) {
763
+ if (rb_range_beg_len(argv[0], &beg, &len, sz, 0) == Qtrue) {
552
764
  VALUE ret = rb_ary_new2(len);
553
- for (long i = beg; i < beg + len; i++)
554
- rb_ary_push(ret, eval((*(value->value))[static_cast<unsigned int>(i)]));
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 = NUM2LONG(argv[0]);
770
+ long l = FIX2LONG(argv[0]);
559
771
  if (l < 0)
560
- l = l + value->value->Size();
561
- if (l >= 0) {
562
- unsigned int i = static_cast<unsigned int>(l);
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
- static VALUE array_enum_size(const VALUE self, VALUE args, VALUE eobj) {
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
- return UINT2NUM(value->value->Size());
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
- * @yield [value]
611
- * @return [Integer]
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 w_array_index(int argc, VALUE* argv, const VALUE self) {
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((*(value->value))[i])) == Qtrue)
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((*(value->value))[i]))))
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 (value->value->Size() == 0)
928
+ if (sz == 0)
648
929
  return Qnil;
649
- return eval((*(value->value))[0]);
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
- long l = NUM2LONG(argv[0]);
653
- if (l < 0)
654
- l = 0;
655
- else if (l > value->value->Size())
656
- l = value->value->Size();
657
- unsigned int li = static_cast<unsigned int>(l);
658
- VALUE ret = rb_ary_new2(li);
659
- for (unsigned int i = 0; i < li; i++)
660
- rb_ary_push(ret, eval((*(value->value))[i]));
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
- return ret;
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 generate(obj, opts = {})
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(v_single_line_array))
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
 
@@ -1,2 +1,8 @@
1
1
  require 'usamin/version'
2
2
  require 'usamin/usamin'
3
+
4
+ # When I was a child, I loved fairy tales.
5
+ # I wished for wonderland every time my mother read the tales to me.
6
+ # And now, I feel like I'm in the dream.
7
+ module Usamin
8
+ end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Usamin
2
- VERSION = "7.7.0"
2
+ VERSION = "7.7.2"
3
3
  end
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.0
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-24 00:00:00.000000000 Z
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