usamin 7.7.9 → 7.7.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: db59b9c360567cf33fca6506bbd06ad9b31c1382a09b31d13cd1c81c530fbdd0
4
- data.tar.gz: c675678f1eec5cd39fae70733f36302664e020981a5d850c12536d755e9c9d7d
3
+ metadata.gz: bcf99c5b8f00f296106cfb0799a5d241dbf1cc8053e74d252b4e1d00692d760d
4
+ data.tar.gz: 48c92bfee2edd6f7e39032dbddcc94f0b9343a1fde13d561f99aa50c231bac11
5
5
  SHA512:
6
- metadata.gz: 78f82ae393b94944759de05c6e8dcc01524b9e60041f9fb13c72dbf43319265f6ad3aef8c226f23dcd8e205ee8385d0a773b7a1271a403b81bc6f093fca928ac
7
- data.tar.gz: e51369d0d04fb97f9018c0734f3f72df4c404388234baa5f9db61b8c36380f2c197626df512906d3241dbbdc75938946a8d657e086f0263d3b94dc63afa46f03
6
+ metadata.gz: 5ec0a132cc068d9cea796e407babcf04dae6323bc45a696c80f49610c78d71e0a218ae0ab20cc4e32a50eda1616a907c8f4c116dae7086eee6bf0378a5efd32d
7
+ data.tar.gz: 958dfa0b6ffe3bd031ba8ae6b9b83a5542b4a5bc69579677391788a2424c733069871a5e4f5c067eb6f99c6a770a8d15ca1476f52c5a29211cb3069231cf760d
data/README.md CHANGED
@@ -88,6 +88,9 @@ Objects also can be handled like Hash objects.
88
88
  data.first['name']
89
89
  #=> "miku maekawa"
90
90
 
91
+ data.first[:name]
92
+ #=> "miku maekawa"
93
+
91
94
  data.first.keys
92
95
  #=> ["name", "age", "height", "weight", "body_size", "birthday", "cv"]
93
96
  ```
@@ -105,6 +108,21 @@ data.first.eval_r
105
108
  Usamin.load(json).eval_r
106
109
  ```
107
110
 
111
+ Usamin supports pattern matching, which is introduced in Ruby 2.7.0.
112
+
113
+ Note that all keys are treated as symbols in pattern matching.
114
+
115
+ ```ruby
116
+ data = Usamin.load('{"maekawa": "miku", "osaki": ["tenka", "amana"], "hisakawa": { "hayate": "haa", "nagi": "naa" }}')
117
+ #=> {"maekawa"=>"miku", "osaki"=>[...], "hisakawa"=>{...}}
118
+
119
+ case data
120
+ in maekawa:, hisakawa: {**sisters}
121
+ sisters
122
+ end
123
+ #=> {:hayate=>"haa", :nagi=>"naa"}
124
+ ```
125
+
108
126
  #### Notes about lazy loading data
109
127
 
110
128
  - Frozen. Modification is not allowed.
@@ -210,76 +228,78 @@ Usamin and JSON load the same data from 3 big json data in nativejson-benchmark.
210
228
 
211
229
  The values show the elapsed time for operating 20 times. SSE4.2 was enabled in these tests.
212
230
 
231
+ Ruby 2.7.0-rc2. json 2.3.0, oj 3.10.0, usamin 7.7.10 (rapidjson 1.1.0).
232
+
213
233
  #### Parsing
214
234
 
215
235
  ```
216
236
  nativejson-benchmark/data/canada.json
217
- json 0.743695 0.005426 0.749121 ( 0.751004)
218
- oj 1.779671 0.039642 1.819313 ( 1.824576)
219
- usamin 0.510856 0.013166 0.524022 ( 0.525174)
220
- usamin (fast) 0.258916 0.007298 0.266214 ( 0.267910)
221
- usamin (load) 0.403337 0.010124 0.413461 ( 0.414023)
222
- usamin (load / fast) 0.164099 0.020126 0.184225 ( 0.184817)
237
+ json 0.734855 0.005684 0.740539 ( 0.743125)
238
+ oj 1.906612 0.022766 1.929378 ( 1.938912)
239
+ usamin 0.546606 0.016939 0.563545 ( 0.565339)
240
+ usamin (fast) 0.221778 0.013511 0.235289 ( 0.235782)
241
+ usamin (load) 0.467457 0.018688 0.486145 ( 0.487849)
242
+ usamin (load / fast) 0.166556 0.025738 0.192294 ( 0.192736)
223
243
 
224
244
  nativejson-benchmark/data/citm_catalog.json
225
- json 0.481490 0.006217 0.487707 ( 0.490407)
226
- oj 0.337618 0.002676 0.340294 ( 0.340697)
227
- usamin 0.363082 0.005774 0.368856 ( 0.370124)
228
- usamin (fast) 0.348798 0.005620 0.354418 ( 0.355544)
229
- usamin (load) 0.114139 0.004866 0.119005 ( 0.119659)
230
- usamin (load / fast) 0.101378 0.004685 0.106063 ( 0.106161)
245
+ json 0.339319 0.004765 0.344084 ( 0.345174)
246
+ oj 0.224548 0.000997 0.225545 ( 0.225837)
247
+ usamin 0.278662 0.003313 0.281975 ( 0.285040)
248
+ usamin (fast) 0.232262 0.001691 0.233953 ( 0.234662)
249
+ usamin (load) 0.111687 0.006829 0.118516 ( 0.118821)
250
+ usamin (load / fast) 0.072404 0.007138 0.079542 ( 0.079620)
231
251
 
232
252
  nativejson-benchmark/data/twitter.json
233
- json 0.242091 0.004512 0.246603 ( 0.246985)
234
- oj 0.165441 0.000833 0.166274 ( 0.166517)
235
- usamin 0.179744 0.000353 0.180097 ( 0.180320)
236
- usamin (fast) 0.181126 0.000577 0.181703 ( 0.182080)
237
- usamin (load) 0.061376 0.000944 0.062320 ( 0.062647)
238
- usamin (load / fast) 0.064891 0.001240 0.066131 ( 0.067542)
253
+ json 0.208798 0.004463 0.213261 ( 0.213952)
254
+ oj 0.134336 0.000970 0.135306 ( 0.135999)
255
+ usamin 0.174997 0.000755 0.175752 ( 0.176467)
256
+ usamin (fast) 0.176687 0.001193 0.177880 ( 0.179466)
257
+ usamin (load) 0.062983 0.004450 0.067433 ( 0.067547)
258
+ usamin (load / fast) 0.063495 0.006539 0.070034 ( 0.071615)
239
259
  ```
240
260
 
241
261
  #### Generating
242
262
 
243
263
  ```
244
264
  nativejson-benchmark/data/canada.json
245
- json 1.964397 0.024287 1.988684 ( 1.993397)
246
- oj 2.070033 0.028986 2.099019 ( 2.107441)
247
- usamin 0.247659 0.018489 0.266148 ( 0.266663)
248
- usamin (load) 0.246872 0.027028 0.273900 ( 0.274989)
265
+ json 2.039965 0.015920 2.055885 ( 2.065514)
266
+ oj 2.008353 0.004610 2.012963 ( 2.016850)
267
+ usamin 0.276563 0.015915 0.292478 ( 0.294615)
268
+ usamin (load) 0.256360 0.010180 0.266540 ( 0.268350)
249
269
 
250
270
  nativejson-benchmark/data/citm_catalog.json
251
- json 0.244533 0.009066 0.253599 ( 0.255088)
252
- oj 0.069532 0.008088 0.077620 ( 0.077661)
253
- usamin 0.058047 0.009538 0.067585 ( 0.067694)
254
- usamin (load) 0.038105 0.009722 0.047827 ( 0.047993)
271
+ json 0.068053 0.004018 0.072071 ( 0.072138)
272
+ oj 0.060933 0.003070 0.064003 ( 0.064161)
273
+ usamin 0.056743 0.008311 0.065054 ( 0.065449)
274
+ usamin (load) 0.037438 0.003680 0.041118 ( 0.041461)
255
275
 
256
276
  nativejson-benchmark/data/twitter.json
257
- json 0.160310 0.006469 0.166779 ( 0.167137)
258
- oj 0.042114 0.004044 0.046158 ( 0.046254)
259
- usamin 0.038971 0.004943 0.043914 ( 0.044313)
260
- usamin (load) 0.029375 0.004385 0.033760 ( 0.033882)
277
+ json 0.040689 0.003881 0.044570 ( 0.044641)
278
+ oj 0.038957 0.003410 0.042367 ( 0.042525)
279
+ usamin 0.037130 0.005539 0.042669 ( 0.042951)
280
+ usamin (load) 0.031568 0.003316 0.034884 ( 0.035690)
261
281
  ```
262
282
 
263
283
  #### Pretty Generating
264
284
 
265
285
  ```
266
286
  nativejson-benchmark/data/canada.json
267
- json 2.224924 0.089327 2.314251 ( 2.320405)
268
- oj 1.624790 0.022204 1.646994 ( 1.650566)
269
- usamin 0.356511 0.084944 0.441455 ( 0.442372)
270
- usamin (load) 0.334884 0.076830 0.411714 ( 0.412275)
287
+ json 2.247403 0.056727 2.304130 ( 2.312832)
288
+ oj 1.560007 0.005153 1.565160 ( 1.569151)
289
+ usamin 0.353357 0.063384 0.416741 ( 0.418236)
290
+ usamin (load) 0.341948 0.055289 0.397237 ( 0.399525)
271
291
 
272
292
  nativejson-benchmark/data/citm_catalog.json
273
- json 0.302005 0.017108 0.319113 ( 0.322104)
274
- oj 0.071386 0.008597 0.079983 ( 0.080194)
275
- usamin 0.099413 0.021275 0.120688 ( 0.121417)
276
- usamin (load) 0.060486 0.021065 0.081551 ( 0.081808)
293
+ json 0.128840 0.008824 0.137664 ( 0.139104)
294
+ oj 0.061869 0.004010 0.065879 ( 0.067000)
295
+ usamin 0.071300 0.005988 0.077288 ( 0.077439)
296
+ usamin (load) 0.048758 0.004353 0.053111 ( 0.053186)
277
297
 
278
298
  nativejson-benchmark/data/twitter.json
279
- json 0.170121 0.011923 0.182044 ( 0.182585)
280
- oj 0.035700 0.006364 0.042064 ( 0.042099)
281
- usamin 0.040141 0.006321 0.046462 ( 0.046556)
282
- usamin (load) 0.036990 0.005729 0.042719 ( 0.042816)
299
+ json 0.060095 0.004639 0.064734 ( 0.065314)
300
+ oj 0.037025 0.004194 0.041219 ( 0.041495)
301
+ usamin 0.053145 0.011938 0.065083 ( 0.065184)
302
+ usamin (load) 0.034704 0.002547 0.037251 ( 0.037505)
283
303
  ```
284
304
 
285
305
  ## Contributing
data/Rakefile CHANGED
@@ -1,18 +1,20 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
3
5
 
4
6
  Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['test/**/*_test.rb']
8
10
  end
9
11
 
10
- require "rake/extensiontask"
12
+ require 'rake/extensiontask'
11
13
 
12
- task :build => :compile
14
+ task build: :compile
13
15
 
14
- Rake::ExtensionTask.new("usamin") do |ext|
15
- ext.lib_dir = "lib/usamin"
16
+ Rake::ExtensionTask.new('usamin') do |ext|
17
+ ext.lib_dir = 'lib/usamin'
16
18
  end
17
19
 
18
- task :default => [:clobber, :compile, :test]
20
+ task default: %i[clobber compile test]
@@ -0,0 +1,6 @@
1
+ #define RAPIDJSON_PARSE_DEFAULT_FLAGS \
2
+ (rapidjson::kParseIterativeFlag | rapidjson::kParseFullPrecisionFlag | rapidjson::kParseCommentsFlag | \
3
+ rapidjson::kParseTrailingCommasFlag | rapidjson::kParseNanAndInfFlag)
4
+ #define RAPIDJSON_PARSE_FAST_FLAGS (RAPIDJSON_PARSE_DEFAULT_FLAGS & ~rapidjson::kParseFullPrecisionFlag)
5
+ #define RAPIDJSON_PARSE_FLAGS_FOR_MARSHAL \
6
+ (rapidjson::kParseIterativeFlag | rapidjson::kParseFullPrecisionFlag | rapidjson::kParseNanAndInfFlag)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'mkmf'
2
4
 
3
5
  RbConfig::MAKEFILE_CONFIG['CXX'] = ENV['CXX'] if ENV['CXX']
@@ -5,13 +7,16 @@ have_library('stdc++')
5
7
  dir_config('rapidjson')
6
8
  append_cppflags('-O3')
7
9
  append_cppflags('-Wall')
10
+ append_cppflags('-Wextra')
11
+ append_cppflags('-Wno-missing-field-initializers')
12
+ append_cppflags('-Wvla')
8
13
 
9
- if checking_for("whether -march=native is accepted as CPPFLAGS"){try_cppflags('-march=native')}
10
- if checking_for("whether -msse4.2 is accepted as CPPFLAGS"){try_cppflags('-msse4.2')}
11
- $CPPFLAGS << ' -msse4.2 -march=native'
12
- elsif checking_for("whether -msse2 is accepted as CPPFLAGS"){try_cppflags('-msse2')}
13
- $CPPFLAGS << ' -msse2 -march=native'
14
- end
14
+ if checking_for('whether -march=native is accepted as CPPFLAGS'){try_cppflags('-march=native')}
15
+ if checking_for('whether -msse4.2 is accepted as CPPFLAGS'){try_cppflags('-msse4.2')}
16
+ $CPPFLAGS << ' -msse4.2 -march=native'
17
+ elsif checking_for('whether -msse2 is accepted as CPPFLAGS'){try_cppflags('-msse2')}
18
+ $CPPFLAGS << ' -msse2 -march=native'
19
+ end
15
20
  end
16
21
 
17
22
  $CPPFLAGS << ' -std=c++11'
@@ -0,0 +1,219 @@
1
+ #include <rapidjson/prettywriter.h>
2
+ #include <rapidjson/writer.h>
3
+ #include <ruby.h>
4
+ #include <ruby/version.h>
5
+ #include "rb_common.hpp"
6
+ #include "rb_usamin_value.hpp"
7
+ #include "rubynized_rapidjson.hpp"
8
+
9
+ template <class Writer>
10
+ static inline void write_hash(Writer &, const VALUE);
11
+ template <class Writer>
12
+ static inline void write_array(Writer &, const VALUE);
13
+ template <class Writer>
14
+ static inline void write_struct(Writer &, const VALUE);
15
+ template <class Writer>
16
+ static inline void write_usamin(Writer &, const VALUE);
17
+
18
+ template <class Writer>
19
+ static inline void write_str(Writer &writer, const VALUE value) {
20
+ VALUE v = get_utf8_str(value);
21
+ writer.String(RSTRING_PTR(v), RSTRING_LENINT(v));
22
+ }
23
+
24
+ template <class Writer>
25
+ static inline void write_to_s(Writer &writer, const VALUE value) {
26
+ extern ID id_to_s;
27
+ write_str(writer, rb_funcall(value, id_to_s, 0));
28
+ }
29
+
30
+ template <class Writer>
31
+ static void write(Writer &writer, const VALUE value) {
32
+ extern VALUE rb_cUsaminValue;
33
+ switch (TYPE(value)) {
34
+ case RUBY_T_NONE:
35
+ case RUBY_T_NIL:
36
+ case RUBY_T_UNDEF:
37
+ writer.Null();
38
+ break;
39
+ case RUBY_T_TRUE:
40
+ writer.Bool(true);
41
+ break;
42
+ case RUBY_T_FALSE:
43
+ writer.Bool(false);
44
+ break;
45
+ case RUBY_T_FIXNUM:
46
+ writer.Int64(FIX2LONG(value));
47
+ break;
48
+ case RUBY_T_FLOAT:
49
+ case RUBY_T_RATIONAL:
50
+ writer.Double(NUM2DBL(value));
51
+ break;
52
+ case RUBY_T_STRING:
53
+ write_str(writer, value);
54
+ break;
55
+ case RUBY_T_ARRAY:
56
+ write_array(writer, value);
57
+ break;
58
+ case RUBY_T_HASH:
59
+ write_hash(writer, value);
60
+ break;
61
+ case RUBY_T_STRUCT:
62
+ write_struct(writer, value);
63
+ break;
64
+ case RUBY_T_BIGNUM: {
65
+ VALUE v = rb_big2str(value, 10);
66
+ writer.RawValue(RSTRING_PTR(v), RSTRING_LEN(v), rapidjson::kNumberType);
67
+ } break;
68
+ default:
69
+ if (rb_obj_is_kind_of(value, rb_cUsaminValue))
70
+ write_usamin(writer, value);
71
+ else
72
+ write_to_s(writer, value);
73
+ break;
74
+ }
75
+ }
76
+
77
+ template <class Writer>
78
+ static inline void write_key_str(Writer &writer, const VALUE value) {
79
+ VALUE v = get_utf8_str(value);
80
+ writer.Key(RSTRING_PTR(v), RSTRING_LENINT(v));
81
+ }
82
+
83
+ template <class Writer>
84
+ static inline void write_key_to_s(Writer &writer, const VALUE value) {
85
+ extern ID id_to_s;
86
+ write_key_str(writer, rb_funcall(value, id_to_s, 0));
87
+ }
88
+
89
+ template <class Writer>
90
+ static inline int write_hash_each(const VALUE key, const VALUE value, VALUE writer_v) {
91
+ Writer *writer = reinterpret_cast<Writer *>(writer_v);
92
+ if (RB_TYPE_P(key, T_STRING))
93
+ write_key_str(*writer, key);
94
+ else if (RB_TYPE_P(key, T_SYMBOL))
95
+ write_key_str(*writer, rb_sym_to_s(key));
96
+ else
97
+ write_key_to_s(*writer, key);
98
+ write(*writer, value);
99
+ return ST_CONTINUE;
100
+ }
101
+
102
+ template <class Writer>
103
+ static inline void write_hash(Writer &writer, const VALUE hash) {
104
+ writer.StartObject();
105
+ #if RUBY_API_VERSION_CODE < 20700
106
+ rb_hash_foreach(hash, (int (*)(ANYARGS))write_hash_each<Writer>, reinterpret_cast<VALUE>(&writer));
107
+ #else
108
+ rb_hash_foreach(hash, write_hash_each<Writer>, reinterpret_cast<VALUE>(&writer));
109
+ #endif
110
+ writer.EndObject();
111
+ }
112
+
113
+ template <class Writer>
114
+ static inline void write_array(Writer &writer, const VALUE value) {
115
+ writer.StartArray();
116
+ const VALUE *ptr = rb_array_const_ptr(value);
117
+ for (long i = 0; i < rb_array_len(value); i++, ptr++)
118
+ write(writer, *ptr);
119
+ writer.EndArray();
120
+ }
121
+
122
+ template <class Writer>
123
+ static inline void write_struct(Writer &writer, const VALUE value) {
124
+ writer.StartObject();
125
+ VALUE members = rb_struct_members(value);
126
+ const VALUE *ptr = rb_array_const_ptr(members);
127
+ for (long i = 0; i < rb_array_len(members); i++, ptr++) {
128
+ if (RB_TYPE_P(*ptr, T_SYMBOL))
129
+ write_key_str(writer, rb_sym_to_s(*ptr));
130
+ else if (RB_TYPE_P(*ptr, T_STRING))
131
+ write_key_str(writer, *ptr);
132
+ else
133
+ write_key_to_s(writer, *ptr);
134
+ write(writer, rb_struct_aref(value, *ptr));
135
+ }
136
+ writer.EndObject();
137
+ }
138
+
139
+ template <class Writer>
140
+ static inline void write_usamin(Writer &writer, const VALUE self) {
141
+ UsaminValue *value = get_value(self);
142
+ check_value(value);
143
+ value->value->Accept(writer);
144
+ }
145
+
146
+ /*
147
+ * Generate the JSON string from Ruby data structures.
148
+ *
149
+ * @overload generate(obj)
150
+ * @param [Object] obj an object to serialize
151
+ * @return [String]
152
+ */
153
+ VALUE w_generate(const VALUE, const VALUE value) {
154
+ rapidjson::StringBuffer buf;
155
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
156
+ write(writer, value);
157
+ return new_utf8_str(buf.GetString(), buf.GetSize());
158
+ }
159
+
160
+ /*
161
+ * Generate the prettified JSON string from Ruby data structures.
162
+ *
163
+ * @overload pretty_generate(obj, opts = {})
164
+ * @param [Object] obj an object to serialize
165
+ * @param [::Hash] opts options
166
+ * @option opts [String] :indent (' ') a string used to indent
167
+ * @option opts [Boolean] :single_line_array (false)
168
+ * @return [String]
169
+ */
170
+ VALUE w_pretty_generate(const int argc, const VALUE *argv, const VALUE) {
171
+ extern VALUE rb_eUsaminError;
172
+ extern VALUE sym_indent, sym_single_line_array;
173
+
174
+ VALUE value, options;
175
+ rb_scan_args(argc, argv, "1:", &value, &options);
176
+ rapidjson::StringBuffer buf;
177
+ rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
178
+
179
+ char indent_char = ' ';
180
+ unsigned int indent_count = 2;
181
+ if (!NIL_P(options)) {
182
+ VALUE v_indent = rb_hash_lookup(options, sym_indent);
183
+ if (RTEST(v_indent)) {
184
+ if (RB_FIXNUM_P(v_indent)) {
185
+ int l = FIX2INT(v_indent);
186
+ indent_count = l > 0 ? l : 0;
187
+ } else {
188
+ int vlen = RSTRING_LENINT(v_indent);
189
+ if (vlen == 0) {
190
+ indent_count = 0;
191
+ } else {
192
+ const char *indent_str = RSTRING_PTR(v_indent);
193
+ switch (indent_str[0]) {
194
+ case ' ':
195
+ case '\t':
196
+ case '\r':
197
+ case '\n':
198
+ indent_char = indent_str[0];
199
+ break;
200
+ default:
201
+ rb_raise(rb_eUsaminError,
202
+ ":indent must be a repetation of \" \", \"\\t\", \"\\r\" or \"\\n\".");
203
+ }
204
+ for (long i = 1; i < vlen; i++)
205
+ if (indent_str[0] != indent_str[i])
206
+ rb_raise(rb_eUsaminError,
207
+ ":indent must be a repetation of \" \", \"\\t\", \"\\r\" or \"\\n\".");
208
+ indent_count = vlen;
209
+ }
210
+ }
211
+ }
212
+ if (RTEST(rb_hash_lookup(options, sym_single_line_array)))
213
+ writer.SetFormatOptions(rapidjson::kFormatSingleLineArray);
214
+ }
215
+ writer.SetIndent(indent_char, indent_count);
216
+
217
+ write(writer, value);
218
+ return new_utf8_str(buf.GetString(), buf.GetSize());
219
+ }