usamin 7.7.9 → 7.7.10

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: 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
+ }