usamin 7.7.9 → 7.7.12

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: f1416f23892e15634eafdbb8536499e785802ac5ca3ff9ac7bc8a9b6f47add00
4
+ data.tar.gz: cfdb20662dce9920a52a48f0e7c17d82943d94d7212d8ad19897b150291058cb
5
5
  SHA512:
6
- metadata.gz: 78f82ae393b94944759de05c6e8dcc01524b9e60041f9fb13c72dbf43319265f6ad3aef8c226f23dcd8e205ee8385d0a773b7a1271a403b81bc6f093fca928ac
7
- data.tar.gz: e51369d0d04fb97f9018c0734f3f72df4c404388234baa5f9db61b8c36380f2c197626df512906d3241dbbdc75938946a8d657e086f0263d3b94dc63afa46f03
6
+ metadata.gz: e7ef1f8f1eba35b68a94b28f18865c0bec6b0be3e4c145ab8fd86806fc7deace8d7ca1515c89c51bb35bec7a296db122963226583d1f0351dea38e3ec96ef9c7
7
+ data.tar.gz: 3a456c76021b846a04573bfda63c2dc2ab0935e01571ed61e4dbf05c233bb58a2bbf5af1ffb04a3328ad1696bb353e081065e745bc0f6bb2564445f4935171b7
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,18 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'mkmf'
2
4
 
3
5
  RbConfig::MAKEFILE_CONFIG['CXX'] = ENV['CXX'] if ENV['CXX']
4
6
  have_library('stdc++')
7
+ have_library('m')
5
8
  dir_config('rapidjson')
6
9
  append_cppflags('-O3')
7
10
  append_cppflags('-Wall')
11
+ append_cppflags('-Wextra')
12
+ append_cppflags('-Wno-missing-field-initializers')
13
+ append_cppflags('-Wvla')
8
14
 
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
15
+ if checking_for('whether -march=native is accepted as CPPFLAGS'){try_cppflags('-march=native')}
16
+ if checking_for('whether -msse4.2 is accepted as CPPFLAGS'){try_cppflags('-msse4.2')}
17
+ $CPPFLAGS << ' -msse4.2 -march=native'
18
+ elsif checking_for('whether -msse2 is accepted as CPPFLAGS'){try_cppflags('-msse2')}
19
+ $CPPFLAGS << ' -msse2 -march=native'
20
+ end
15
21
  end
16
22
 
17
23
  $CPPFLAGS << ' -std=c++11'
24
+
25
+ $CPPFLAGS << ' -DRAPIDJSON_IS_HEAD' if arg_config('--rapidjson-is-head')
26
+
18
27
  create_makefile('usamin/usamin')
@@ -0,0 +1,226 @@
1
+ #include "rb270_fix.hpp"
2
+ #include <rapidjson/prettywriter.h>
3
+ #include <rapidjson/writer.h>
4
+ #include <ruby.h>
5
+ #include <ruby/version.h>
6
+ #include "rb_common.hpp"
7
+ #include "rb_usamin_value.hpp"
8
+ #include "rubynized_rapidjson.hpp"
9
+
10
+ #define WRITER_CONFIGS rapidjson::UTF8<>, rapidjson::UTF8<>, RubyCrtAllocator, rapidjson::kWriteNanAndInfFlag
11
+
12
+ template <class Writer>
13
+ static inline void write_hash(Writer &, const VALUE);
14
+ template <class Writer>
15
+ static inline void write_array(Writer &, const VALUE);
16
+ template <class Writer>
17
+ static inline void write_struct(Writer &, const VALUE);
18
+ template <class Writer>
19
+ static inline void write_usamin(Writer &, const VALUE);
20
+
21
+ template <class Writer>
22
+ static inline void write_str(Writer &writer, const VALUE value) {
23
+ VALUE v = get_utf8_str(value);
24
+ writer.String(RSTRING_PTR(v), RSTRING_LENINT(v));
25
+ }
26
+
27
+ template <class Writer>
28
+ static inline void write_to_s(Writer &writer, const VALUE value) {
29
+ extern ID id_to_s;
30
+ write_str(writer, rb_funcall(value, id_to_s, 0));
31
+ }
32
+
33
+ template <class Writer>
34
+ static void write(Writer &writer, const VALUE value) {
35
+ extern VALUE rb_cUsaminValue;
36
+ switch (TYPE(value)) {
37
+ case RUBY_T_NONE:
38
+ case RUBY_T_NIL:
39
+ case RUBY_T_UNDEF:
40
+ writer.Null();
41
+ break;
42
+ case RUBY_T_TRUE:
43
+ writer.Bool(true);
44
+ break;
45
+ case RUBY_T_FALSE:
46
+ writer.Bool(false);
47
+ break;
48
+ case RUBY_T_FIXNUM:
49
+ writer.Int64(FIX2LONG(value));
50
+ break;
51
+ case RUBY_T_FLOAT:
52
+ case RUBY_T_RATIONAL:
53
+ writer.Double(NUM2DBL(value));
54
+ break;
55
+ case RUBY_T_STRING:
56
+ write_str(writer, value);
57
+ break;
58
+ case RUBY_T_ARRAY:
59
+ write_array(writer, value);
60
+ break;
61
+ case RUBY_T_HASH:
62
+ write_hash(writer, value);
63
+ break;
64
+ case RUBY_T_STRUCT:
65
+ write_struct(writer, value);
66
+ break;
67
+ case RUBY_T_BIGNUM: {
68
+ VALUE v = rb_big2str(value, 10);
69
+ writer.RawValue(RSTRING_PTR(v), RSTRING_LEN(v), rapidjson::kNumberType);
70
+ } break;
71
+ default:
72
+ if (rb_obj_is_kind_of(value, rb_cUsaminValue))
73
+ write_usamin(writer, value);
74
+ else
75
+ write_to_s(writer, value);
76
+ break;
77
+ }
78
+ }
79
+
80
+ template <class Writer>
81
+ static inline void write_key_str(Writer &writer, const VALUE value) {
82
+ VALUE v = get_utf8_str(value);
83
+ writer.Key(RSTRING_PTR(v), RSTRING_LENINT(v));
84
+ }
85
+
86
+ template <class Writer>
87
+ static inline void write_key_to_s(Writer &writer, const VALUE value) {
88
+ extern ID id_to_s;
89
+ write_key_str(writer, rb_funcall(value, id_to_s, 0));
90
+ }
91
+
92
+ template <class Writer>
93
+ static inline int write_hash_each(const VALUE key, const VALUE value, VALUE writer_v) {
94
+ Writer *writer = reinterpret_cast<Writer *>(writer_v);
95
+ if (RB_TYPE_P(key, T_STRING))
96
+ write_key_str(*writer, key);
97
+ else if (RB_TYPE_P(key, T_SYMBOL))
98
+ write_key_str(*writer, rb_sym_to_s(key));
99
+ else
100
+ write_key_to_s(*writer, key);
101
+ write(*writer, value);
102
+ return ST_CONTINUE;
103
+ }
104
+
105
+ template <class Writer>
106
+ static inline void write_hash(Writer &writer, const VALUE hash) {
107
+ writer.StartObject();
108
+ #if RUBY_API_VERSION_CODE < 20700
109
+ rb_hash_foreach(hash, (int (*)(ANYARGS))write_hash_each<Writer>, reinterpret_cast<VALUE>(&writer));
110
+ #else
111
+ rb_hash_foreach(hash, write_hash_each<Writer>, reinterpret_cast<VALUE>(&writer));
112
+ #endif
113
+ writer.EndObject();
114
+ }
115
+
116
+ template <class Writer>
117
+ static inline void write_array(Writer &writer, const VALUE value) {
118
+ writer.StartArray();
119
+ const VALUE *ptr = rb_array_const_ptr(value);
120
+ for (long i = 0; i < rb_array_len(value); i++, ptr++)
121
+ write(writer, *ptr);
122
+ writer.EndArray();
123
+ }
124
+
125
+ template <class Writer>
126
+ static inline void write_struct(Writer &writer, const VALUE value) {
127
+ writer.StartObject();
128
+ VALUE members = rb_struct_members(value);
129
+ const VALUE *ptr = rb_array_const_ptr(members);
130
+ for (long i = 0; i < rb_array_len(members); i++, ptr++) {
131
+ if (RB_TYPE_P(*ptr, T_SYMBOL))
132
+ write_key_str(writer, rb_sym_to_s(*ptr));
133
+ else if (RB_TYPE_P(*ptr, T_STRING))
134
+ write_key_str(writer, *ptr);
135
+ else
136
+ write_key_to_s(writer, *ptr);
137
+ write(writer, rb_struct_aref(value, *ptr));
138
+ }
139
+ writer.EndObject();
140
+ }
141
+
142
+ template <class Writer>
143
+ static inline void write_usamin(Writer &writer, const VALUE self) {
144
+ UsaminValue *value = get_value(self);
145
+ check_value(value);
146
+ value->value->Accept(writer);
147
+ }
148
+
149
+ /*
150
+ * Generate the JSON string from Ruby data structures.
151
+ *
152
+ * @overload generate(obj)
153
+ * @param [Object] obj an object to serialize
154
+ * @return [String]
155
+ */
156
+ VALUE w_generate(const VALUE, const VALUE value) {
157
+ rapidjson::StringBuffer buf;
158
+ rapidjson::Writer<rapidjson::StringBuffer, WRITER_CONFIGS> writer(buf);
159
+ write(writer, value);
160
+ return new_utf8_str(buf.GetString(), buf.GetSize());
161
+ }
162
+
163
+ /*
164
+ * Generate the prettified JSON string from Ruby data structures.
165
+ *
166
+ * @overload pretty_generate(obj, opts = {})
167
+ * @param [Object] obj an object to serialize
168
+ * @param [::Hash] opts options
169
+ * @option opts [String] :indent (' ') a string used to indent
170
+ * @option opts [Boolean] :single_line_array (false)
171
+ * @return [String]
172
+ */
173
+ VALUE w_pretty_generate(const int argc, const VALUE *argv, const VALUE) {
174
+ extern VALUE rb_eUsaminError;
175
+ extern VALUE sym_indent, sym_single_line_array;
176
+
177
+ VALUE value, options;
178
+ rb_scan_args(argc, argv, "1:", &value, &options);
179
+ rapidjson::StringBuffer buf;
180
+ #if RAPIDJSON_VERSION_CODE(RAPIDJSON_MAJOR_VERSION, RAPIDJSON_MINOR_VERSION, RAPIDJSON_PATCH_VERSION) > RAPIDJSON_VERSION_CODE(1, 1, 0) || defined(RAPIDJSON_IS_HEAD)
181
+ rapidjson::PrettyWriter<rapidjson::StringBuffer, WRITER_CONFIGS> writer(buf);
182
+ #else
183
+ rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
184
+ #endif
185
+
186
+ char indent_char = ' ';
187
+ unsigned int indent_count = 2;
188
+ if (!NIL_P(options)) {
189
+ VALUE v_indent = rb_hash_lookup(options, sym_indent);
190
+ if (RTEST(v_indent)) {
191
+ if (RB_FIXNUM_P(v_indent)) {
192
+ int l = FIX2INT(v_indent);
193
+ indent_count = l > 0 ? l : 0;
194
+ } else {
195
+ int vlen = RSTRING_LENINT(v_indent);
196
+ if (vlen == 0) {
197
+ indent_count = 0;
198
+ } else {
199
+ const char *indent_str = RSTRING_PTR(v_indent);
200
+ switch (indent_str[0]) {
201
+ case ' ':
202
+ case '\t':
203
+ case '\r':
204
+ case '\n':
205
+ indent_char = indent_str[0];
206
+ break;
207
+ default:
208
+ rb_raise(rb_eUsaminError,
209
+ ":indent must be a repetation of \" \", \"\\t\", \"\\r\" or \"\\n\".");
210
+ }
211
+ for (long i = 1; i < vlen; i++)
212
+ if (indent_str[0] != indent_str[i])
213
+ rb_raise(rb_eUsaminError,
214
+ ":indent must be a repetation of \" \", \"\\t\", \"\\r\" or \"\\n\".");
215
+ indent_count = vlen;
216
+ }
217
+ }
218
+ }
219
+ if (RTEST(rb_hash_lookup(options, sym_single_line_array)))
220
+ writer.SetFormatOptions(rapidjson::kFormatSingleLineArray);
221
+ }
222
+ writer.SetIndent(indent_char, indent_count);
223
+
224
+ write(writer, value);
225
+ return new_utf8_str(buf.GetString(), buf.GetSize());
226
+ }
@@ -0,0 +1,11 @@
1
+ #ifndef USAMIN_GENERATOR_HPP
2
+ #define USAMIN_GENERATOR_HPP
3
+
4
+ #include <rapidjson/writer.h>
5
+ #include <ruby.h>
6
+ #include "rubynized_rapidjson.hpp"
7
+
8
+ VALUE w_generate(const VALUE self, const VALUE value);
9
+ VALUE w_pretty_generate(const int argc, const VALUE *argv, const VALUE self);
10
+
11
+ #endif
@@ -0,0 +1,101 @@
1
+ #include "rb270_fix.hpp"
2
+ #include "default_parse_flags.hpp"
3
+ #include <rapidjson/reader.h>
4
+ #include <rapidjson/error/en.h>
5
+ #include "parser.hpp"
6
+ #include <ruby.h>
7
+ #include "rb_common.hpp"
8
+ #include "rubynized_rapidjson.hpp"
9
+ #include "usamin_value.hpp"
10
+ #include "parser_helper.hpp"
11
+
12
+ static inline rapidjson::ParseResult parse(RubynizedDocument &doc, const VALUE str, bool fast = false,
13
+ bool recursive = false) {
14
+ volatile VALUE v = get_utf8_str(str);
15
+ #define PARSE_WITH_FLAGS(flags) return doc.Parse<flags>(RSTRING_PTR(v), RSTRING_LEN(v))
16
+ if (recursive)
17
+ if (fast)
18
+ PARSE_WITH_FLAGS(RAPIDJSON_PARSE_FAST_FLAGS & ~rapidjson::kParseIterativeFlag);
19
+ else
20
+ PARSE_WITH_FLAGS(RAPIDJSON_PARSE_DEFAULT_FLAGS & ~rapidjson::kParseIterativeFlag);
21
+ else if (fast)
22
+ PARSE_WITH_FLAGS(RAPIDJSON_PARSE_FAST_FLAGS);
23
+ else
24
+ PARSE_WITH_FLAGS(RAPIDJSON_PARSE_DEFAULT_FLAGS);
25
+ #undef PARSE_WITH_FLAGS
26
+ }
27
+
28
+ /*
29
+ * Parse the JSON string into UsaminValue.
30
+ * If the document root is not an object or an array, the same value as {#parse} will be returned.
31
+ *
32
+ * @overload load(source, opts = {})
33
+ * @param [String] source JSON string to parse
34
+ * @param [::Hash] opts options
35
+ * @option opts :fast fast mode (but not precise)
36
+ * @option opts :recursive non-iterative (recursive) mode (fast but not safe, can cause SystemStackError and illegal hardware instruction)
37
+ * @return [Object]
38
+ */
39
+ VALUE w_load(const int argc, const VALUE *argv, const VALUE) {
40
+ extern VALUE rb_eUsaminError, rb_eParserError, sym_fast, sym_recursive;
41
+
42
+ VALUE source, options;
43
+ rb_scan_args(argc, argv, "1:", &source, &options);
44
+ RubynizedDocument *doc = new RubynizedDocument;
45
+ auto result = parse(*doc, source, test_option(options, sym_fast), test_option(options, sym_recursive));
46
+ if (!result) {
47
+ delete doc;
48
+ rb_raise(rb_eParserError, "%s Offset: %lu", GetParseError_En(result.Code()), result.Offset());
49
+ }
50
+
51
+ VALUE ret;
52
+ switch (doc->GetType()) {
53
+ case rapidjson::kNullType:
54
+ delete doc;
55
+ return Qnil;
56
+ case rapidjson::kFalseType:
57
+ delete doc;
58
+ return Qfalse;
59
+ case rapidjson::kTrueType:
60
+ delete doc;
61
+ return Qtrue;
62
+ case rapidjson::kObjectType:
63
+ return make_hash(new UsaminValue(doc, true), true);
64
+ case rapidjson::kArrayType:
65
+ return make_array(new UsaminValue(doc, true), true);
66
+ case rapidjson::kStringType:
67
+ ret = eval_str(*doc);
68
+ delete doc;
69
+ return ret;
70
+ case rapidjson::kNumberType:
71
+ ret = eval_num(*doc);
72
+ delete doc;
73
+ return ret;
74
+ default:
75
+ rb_raise(rb_eUsaminError, "unknown value type: %d", doc->GetType());
76
+ return Qnil;
77
+ }
78
+ }
79
+
80
+ /*
81
+ * Parse the JSON string into Ruby data structures.
82
+ *
83
+ * @overload parse(source, opts = {})
84
+ * @param [String] source a JSON string to parse
85
+ * @param [::Hash] opts options
86
+ * @option opts :fast fast mode (but not precise)
87
+ * @option opts :recursive non-iterative (recursive) mode (fast but not safe, can cause SystemStackError and illegal hardware instruction)
88
+ * @option opts :symbolize_names symbolize keys of all Hash objects
89
+ * @return [Object]
90
+ */
91
+ VALUE w_parse(const int argc, const VALUE *argv, const VALUE) {
92
+ extern VALUE rb_eParserError, sym_fast, sym_recursive, sym_symbolize_names;
93
+
94
+ VALUE source, options;
95
+ rb_scan_args(argc, argv, "1:", &source, &options);
96
+ RubynizedDocument doc;
97
+ auto result = parse(doc, source, test_option(options, sym_fast), test_option(options, sym_recursive));
98
+ if (!result)
99
+ rb_raise(rb_eParserError, "%s Offset: %lu", GetParseError_En(result.Code()), result.Offset());
100
+ return eval_r(doc, test_option(options, sym_symbolize_names));
101
+ }
@@ -0,0 +1,9 @@
1
+ #ifndef USAMIN_PARSER_HPP
2
+ #define USAMIN_PARSER_HPP
3
+
4
+ #include <ruby.h>
5
+
6
+ VALUE w_load(const int argc, const VALUE *argv, const VALUE self);
7
+ VALUE w_parse(const int argc, const VALUE *argv, const VALUE self);
8
+
9
+ #endif