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 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