usamin 7.7.9 → 7.7.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,37 @@
1
+ #ifndef USAMIN_RB_USAMIN_HASH_HPP
2
+ #define USAMIN_RB_USAMIN_HASH_HPP
3
+
4
+ #include <ruby.h>
5
+
6
+ VALUE w_hash_operator_indexer(const VALUE self, const VALUE key);
7
+ VALUE w_hash_assoc(const VALUE self, const VALUE key);
8
+ VALUE w_hash_compact(const VALUE self);
9
+ VALUE w_hash_deconstruct_keys(const VALUE self, const VALUE keys);
10
+ VALUE w_hash_dig(const int argc, const VALUE *argv, const VALUE self);
11
+ VALUE w_hash_each(const VALUE self);
12
+ VALUE w_hash_each_key(const VALUE self);
13
+ VALUE w_hash_each_value(const VALUE self);
14
+ VALUE w_hash_isempty(const VALUE self);
15
+ VALUE w_hash_fetch(const int argc, const VALUE *argv, const VALUE self);
16
+ VALUE w_hash_fetch_values(const int argc, VALUE *argv, const VALUE self);
17
+ VALUE w_hash_flatten(const int argc, const VALUE *argv, const VALUE self);
18
+ VALUE w_hash_haskey(const VALUE self, const VALUE key);
19
+ VALUE w_hash_hasvalue(const VALUE self, const VALUE val);
20
+ VALUE w_hash_key(const VALUE self, const VALUE val);
21
+ VALUE w_hash_inspect(const VALUE self);
22
+ VALUE w_hash_invert(const VALUE self);
23
+ VALUE w_hash_keys(const VALUE self);
24
+ VALUE w_hash_length(const VALUE self);
25
+ VALUE w_hash_rassoc(const VALUE self, const VALUE val);
26
+ VALUE w_hash_select(const VALUE self);
27
+ VALUE w_hash_reject(const VALUE self);
28
+ VALUE w_hash_slice(const int argc, const VALUE *argv, const VALUE self);
29
+ VALUE w_hash_eval(const VALUE self);
30
+ VALUE w_hash_merge(const int argc, const VALUE *argv, const VALUE self);
31
+ VALUE w_hash_values(const VALUE self);
32
+ VALUE w_hash_to_proc(const VALUE self);
33
+ VALUE w_hash_transform_keys(const VALUE self);
34
+ VALUE w_hash_transform_values(const VALUE self);
35
+ VALUE w_hash_values_at(const int argc, const VALUE *argv, const VALUE self);
36
+
37
+ #endif
@@ -0,0 +1,327 @@
1
+ #include "default_parse_flags.hpp"
2
+ #include <rapidjson/error/en.h>
3
+ #include <rapidjson/reader.h>
4
+ #include <rapidjson/writer.h>
5
+ #include <ruby.h>
6
+ #include "generator.hpp"
7
+ #include "usamin_value.hpp"
8
+ #include "parser_helper.hpp"
9
+
10
+ static void usamin_free(void *p) {
11
+ if (!p)
12
+ return;
13
+ UsaminValue **ptr = (UsaminValue **)p;
14
+ if (*ptr)
15
+ delete *ptr;
16
+ ruby_xfree(p);
17
+ }
18
+
19
+ static void usamin_mark(void *p) {
20
+ if (!p)
21
+ return;
22
+ UsaminValue **ptr = (UsaminValue **)p;
23
+ if (*ptr && !((*ptr)->free_flag))
24
+ rb_gc_mark((*ptr)->root_document);
25
+ }
26
+
27
+ static size_t usamin_size(const void *p) {
28
+ if (!p)
29
+ return 0;
30
+ UsaminValue **ptr = (UsaminValue **)p;
31
+ size_t s = 0;
32
+ if (*ptr) {
33
+ s += sizeof(UsaminValue);
34
+ if ((*ptr)->free_flag)
35
+ s += ((RubynizedDocument *)(*ptr)->value)->GetAllocator().Capacity() +
36
+ ((RubynizedDocument *)(*ptr)->value)->GetStackCapacity();
37
+ }
38
+ return s;
39
+ }
40
+
41
+ static const rb_data_type_t rb_usamin_value_type = {
42
+ "UsaminValue", {usamin_mark, usamin_free, usamin_size}, nullptr, nullptr, RUBY_TYPED_FREE_IMMEDIATELY};
43
+
44
+ VALUE usamin_alloc(const VALUE klass) {
45
+ UsaminValue **ptr;
46
+ VALUE ret = TypedData_Make_Struct(klass, UsaminValue *, &rb_usamin_value_type, ptr);
47
+ *ptr = nullptr;
48
+ return ret;
49
+ }
50
+
51
+ UsaminValue *get_value(VALUE value) {
52
+ UsaminValue **ptr;
53
+ TypedData_Get_Struct(value, UsaminValue *, &rb_usamin_value_type, ptr);
54
+ return *ptr;
55
+ }
56
+
57
+ void set_value(VALUE value, UsaminValue *usamin) {
58
+ UsaminValue **ptr;
59
+ TypedData_Get_Struct(value, UsaminValue *, &rb_usamin_value_type, ptr);
60
+ *ptr = usamin;
61
+ }
62
+
63
+ static bool eql_array(RubynizedValue &, RubynizedValue &);
64
+ static bool eql_object(RubynizedValue &, RubynizedValue &);
65
+
66
+ static bool eql_value(RubynizedValue &self, RubynizedValue &other) {
67
+ if (self.GetType() != other.GetType())
68
+ return false;
69
+ switch (self.GetType()) {
70
+ case rapidjson::kObjectType:
71
+ return eql_object(self, other);
72
+ case rapidjson::kArrayType:
73
+ return eql_array(self, other);
74
+ case rapidjson::kStringType:
75
+ return self == other;
76
+ case rapidjson::kNumberType:
77
+ return self == other && self.IsInt() == other.IsInt() && self.IsUint() == other.IsUint() &&
78
+ self.IsInt64() == other.IsInt64() && self.IsUint64() == other.IsUint64() &&
79
+ self.IsDouble() == other.IsDouble();
80
+ default:
81
+ return true;
82
+ }
83
+ }
84
+
85
+ static bool eql_object(RubynizedValue &self, RubynizedValue &other) {
86
+ if (self.MemberCount() != other.MemberCount())
87
+ return false;
88
+ for (auto &m : self.GetObject()) {
89
+ if (!other.HasMember(m.name))
90
+ return false;
91
+ if (!eql_value(m.value, other[m.name]))
92
+ return false;
93
+ }
94
+ return true;
95
+ }
96
+
97
+ static bool eql_array(RubynizedValue &self, RubynizedValue &other) {
98
+ if (self.Size() != other.Size())
99
+ return false;
100
+ for (rapidjson::SizeType i = 0; i < self.Size(); i++) {
101
+ if (!eql_value(self[i], other[i]))
102
+ return false;
103
+ }
104
+ return true;
105
+ }
106
+
107
+ /*
108
+ * Returns whether the value is equals to the other value.
109
+ *
110
+ * @return [Boolean]
111
+ */
112
+ VALUE w_value_equal(const VALUE self, const VALUE other) {
113
+ extern VALUE rb_cUsaminValue;
114
+ if (self == other)
115
+ return Qtrue;
116
+ UsaminValue *value_self = get_value(self);
117
+ check_value(value_self);
118
+ if (rb_obj_is_kind_of(other, rb_cUsaminValue)) {
119
+ UsaminValue *value_other = get_value(other);
120
+ check_value(value_other);
121
+ return value_self->value->operator==(*value_other->value) ? Qtrue : Qfalse;
122
+ } else if (value_self->value->IsArray() && RB_TYPE_P(other, T_ARRAY)) {
123
+ if (value_self->value->Size() != RARRAY_LEN(other))
124
+ return Qfalse;
125
+ return rb_equal(other, eval_array(*value_self->value, value_self->root_document));
126
+ } else if (value_self->value->IsObject() && RB_TYPE_P(other, T_HASH)) {
127
+ if (value_self->value->MemberCount() != RHASH_SIZE(other))
128
+ return Qfalse;
129
+ return rb_equal(other, eval_object(*value_self->value, value_self->root_document, 0));
130
+ }
131
+ return Qfalse;
132
+ }
133
+
134
+ /*
135
+ * Returns whether the value is array.
136
+ */
137
+ VALUE w_value_isarray(const VALUE self) {
138
+ UsaminValue *value = get_value(self);
139
+ check_value(value);
140
+ return value->value->IsArray() ? Qtrue : Qfalse;
141
+ }
142
+
143
+ /*
144
+ * Returns whether the value is object.
145
+ */
146
+ VALUE w_value_isobject(const VALUE self) {
147
+ UsaminValue *value = get_value(self);
148
+ check_value(value);
149
+ return value->value->IsObject() ? Qtrue : Qfalse;
150
+ }
151
+
152
+ /*
153
+ * Convert to Ruby data structures.
154
+ *
155
+ * @overload eval(opts = {})
156
+ * @option opts :symbolize_names symbolize keys of all Hash objects
157
+ * @return [Object]
158
+ */
159
+ VALUE w_value_eval(const int argc, const VALUE *argv, const VALUE self) {
160
+ extern VALUE sym_symbolize_names;
161
+ VALUE options;
162
+ rb_scan_args(argc, argv, ":", &options);
163
+ UsaminValue *value = get_value(self);
164
+ check_value(value);
165
+ if (value->value->IsObject()) {
166
+ return eval_object(*(value->value), value->root_document, test_option(options, sym_symbolize_names));
167
+ } else if (value->value->IsArray()) {
168
+ return eval_array(*(value->value), value->root_document);
169
+ } else {
170
+ return Qnil;
171
+ }
172
+ }
173
+
174
+ /*
175
+ * Convert to Ruby data structures recursively.
176
+ *
177
+ * @overload eval_r(opts = {})
178
+ * @option opts :symbolize_names symbolize keys of all Hash objects
179
+ * @return [Object]
180
+ */
181
+ VALUE w_value_eval_r(const int argc, const VALUE *argv, const VALUE self) {
182
+ extern VALUE sym_symbolize_names;
183
+ VALUE options;
184
+ rb_scan_args(argc, argv, ":", &options);
185
+ UsaminValue *value = get_value(self);
186
+ check_value(value);
187
+ return eval_r(*(value->value), test_option(options, sym_symbolize_names));
188
+ }
189
+
190
+ /*
191
+ * @return [Boolean]
192
+ */
193
+ VALUE w_value_eql(const VALUE self, const VALUE other) {
194
+ extern VALUE rb_cUsaminValue;
195
+ if (self == other)
196
+ return Qtrue;
197
+ if (!rb_obj_is_kind_of(other, rb_cUsaminValue))
198
+ return Qfalse;
199
+ UsaminValue *value_self = get_value(self);
200
+ UsaminValue *value_other = get_value(other);
201
+ check_value(value_self);
202
+ check_value(value_other);
203
+ return eql_value(*value_self->value, *value_other->value) ? Qtrue : Qfalse;
204
+ }
205
+
206
+ /*
207
+ * Always true.
208
+ */
209
+ VALUE w_value_isfrozen(const VALUE) {
210
+ return Qtrue;
211
+ }
212
+
213
+ static st_index_t hash_object(RubynizedValue &value);
214
+ static st_index_t hash_array(RubynizedValue &value);
215
+
216
+ static st_index_t hash_value(RubynizedValue &value) {
217
+ auto type = value.GetType();
218
+ st_index_t h = rb_hash_start(type);
219
+ rb_hash_uint(h, reinterpret_cast<st_index_t>(hash_value));
220
+ switch (type) {
221
+ case rapidjson::kNullType:
222
+ h = rb_hash_uint(h, NUM2LONG(rb_hash(Qnil)));
223
+ break;
224
+ case rapidjson::kFalseType:
225
+ h = rb_hash_uint(h, NUM2LONG(rb_hash(Qfalse)));
226
+ break;
227
+ case rapidjson::kTrueType:
228
+ h = rb_hash_uint(h, NUM2LONG(rb_hash(Qtrue)));
229
+ break;
230
+ case rapidjson::kObjectType:
231
+ h = rb_hash_uint(h, hash_object(value));
232
+ break;
233
+ case rapidjson::kArrayType:
234
+ h = rb_hash_uint(h, hash_array(value));
235
+ break;
236
+ case rapidjson::kStringType:
237
+ h = rb_hash_uint(h, rb_str_hash(eval_str(value)));
238
+ break;
239
+ case rapidjson::kNumberType:
240
+ if (value.IsInt())
241
+ h = rb_hash_uint(h, 0x770);
242
+ if (value.IsUint())
243
+ h = rb_hash_uint(h, 0x771);
244
+ if (value.IsInt64())
245
+ h = rb_hash_uint(h, 0x772);
246
+ if (value.IsUint64())
247
+ h = rb_hash_uint(h, 0x773);
248
+ if (value.IsDouble())
249
+ h = rb_hash_uint(h, 0x774);
250
+ h = rb_hash_uint(h, NUM2LONG(rb_hash(eval_num(value))));
251
+ }
252
+ return rb_hash_end(h);
253
+ }
254
+
255
+ static st_index_t hash_object(RubynizedValue &value) {
256
+ st_index_t h = rb_hash_start(value.MemberCount());
257
+ h = rb_hash_uint(h, reinterpret_cast<st_index_t>(hash_object));
258
+ for (auto &m : value.GetObject()) {
259
+ h = rb_hash_uint(h, rb_str_hash(eval_str(m.name)));
260
+ h = rb_hash_uint(h, hash_value(m.value));
261
+ }
262
+ return rb_hash_end(h);
263
+ }
264
+
265
+ static st_index_t hash_array(RubynizedValue &value) {
266
+ st_index_t h = rb_hash_start(value.Size());
267
+ h = rb_hash_uint(h, reinterpret_cast<st_index_t>(hash_array));
268
+ for (auto &v : value.GetArray())
269
+ h = rb_hash_uint(h, hash_value(v));
270
+ return rb_hash_end(h);
271
+ }
272
+
273
+ /*
274
+ * @return [Integer]
275
+ */
276
+ VALUE w_value_hash(const VALUE self) {
277
+ UsaminValue *value = get_value(self);
278
+ check_value(value);
279
+ return ST2FIX(hash_value(*value->value));
280
+ }
281
+
282
+ /*
283
+ * Returns root object.
284
+ *
285
+ * @return [UsaminValue]
286
+ */
287
+ VALUE w_value_root(const VALUE self) {
288
+ UsaminValue *value = get_value(self);
289
+ check_value(value);
290
+ return value->root_document;
291
+ }
292
+
293
+ /*
294
+ * Dumps data in JSON.
295
+ *
296
+ * @return [String]
297
+ */
298
+ VALUE w_value_marshal_dump(const VALUE self) {
299
+ extern VALUE rb_mUsamin;
300
+ return w_generate(rb_mUsamin, self);
301
+ }
302
+
303
+ /*
304
+ * Loads marshal data.
305
+ */
306
+ VALUE w_value_marshal_load(const VALUE self, const VALUE source) {
307
+ extern VALUE rb_cUsaminHash, rb_cUsaminArray, rb_eUsaminError, rb_eParserError;
308
+ Check_Type(source, T_STRING);
309
+ RubynizedDocument *doc = new RubynizedDocument();
310
+ rapidjson::ParseResult result =
311
+ doc->Parse<RAPIDJSON_PARSE_FLAGS_FOR_MARSHAL>(RSTRING_PTR(source), RSTRING_LEN(source));
312
+ if (!result) {
313
+ delete doc;
314
+ rb_raise(rb_eParserError, "%s Offset: %lu", GetParseError_En(result.Code()), result.Offset());
315
+ }
316
+ if ((rb_obj_is_instance_of(self, rb_cUsaminHash) && doc->IsObject()) ||
317
+ (rb_obj_is_instance_of(self, rb_cUsaminArray) && doc->IsArray())) {
318
+ UsaminValue *value = new UsaminValue(doc, true);
319
+ set_value(self, value);
320
+ value->root_document = self;
321
+ } else {
322
+ auto type = doc->GetType();
323
+ delete doc;
324
+ rb_raise(rb_eUsaminError, "type mismatch in marshal load: %d", type);
325
+ }
326
+ return Qnil;
327
+ }
@@ -0,0 +1,24 @@
1
+ #ifndef USAMIN_RB_USAMIN_VALUE_HPP
2
+ #define USAMIN_RB_USAMIN_VALUE_HPP
3
+
4
+ #include <ruby.h>
5
+ #include "usamin_value.hpp"
6
+
7
+ VALUE usamin_alloc(const VALUE klass);
8
+
9
+ UsaminValue *get_value(VALUE value);
10
+ void set_value(VALUE value, UsaminValue *usamin);
11
+
12
+ VALUE w_value_equal(const VALUE self, const VALUE other);
13
+ VALUE w_value_isarray(const VALUE self);
14
+ VALUE w_value_isobject(const VALUE self);
15
+ VALUE w_value_eval(const int argc, const VALUE *argv, const VALUE self);
16
+ VALUE w_value_eval_r(const int argc, const VALUE *argv, const VALUE self);
17
+ VALUE w_value_eql(const VALUE self, const VALUE other);
18
+ VALUE w_value_isfrozen(const VALUE self);
19
+ VALUE w_value_hash(const VALUE self);
20
+ VALUE w_value_root(const VALUE self);
21
+ VALUE w_value_marshal_dump(const VALUE self);
22
+ VALUE w_value_marshal_load(const VALUE self, const VALUE source);
23
+
24
+ #endif
@@ -0,0 +1,21 @@
1
+ #include "rubynized_rapidjson.hpp"
2
+ #include <ruby.h>
3
+
4
+ void *RubyCrtAllocator::Malloc(size_t size) {
5
+ if (size)
6
+ return ruby_xmalloc(size);
7
+ else
8
+ return nullptr;
9
+ }
10
+
11
+ void *RubyCrtAllocator::Realloc(void *originalPtr, size_t, size_t newSize) {
12
+ if (newSize == 0) {
13
+ ruby_xfree(originalPtr);
14
+ return nullptr;
15
+ }
16
+ return ruby_xrealloc(originalPtr, newSize);
17
+ }
18
+
19
+ void RubyCrtAllocator::Free(void *ptr) {
20
+ ruby_xfree(ptr);
21
+ }
@@ -0,0 +1,18 @@
1
+ #ifndef USAMIN_RUBYNIZED_RAPIDJSON_HPP
2
+ #define USAMIN_RUBYNIZED_RAPIDJSON_HPP
3
+
4
+ #include <rapidjson/document.h>
5
+
6
+ class RubyCrtAllocator {
7
+ public:
8
+ static const bool kNeedFree = true;
9
+ void *Malloc(size_t size);
10
+ void *Realloc(void *originalPtr, size_t, size_t newSize);
11
+ static void Free(void *ptr);
12
+ };
13
+
14
+ typedef rapidjson::GenericValue<rapidjson::UTF8<>, rapidjson::MemoryPoolAllocator<RubyCrtAllocator> > RubynizedValue;
15
+ typedef rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::MemoryPoolAllocator<RubyCrtAllocator> >
16
+ RubynizedDocument;
17
+
18
+ #endif
@@ -1,1776 +1,35 @@
1
- #include <string.h>
2
- #include <stdint.h>
3
1
  #include <ruby.h>
4
2
  #include <ruby/encoding.h>
5
- #define RAPIDJSON_PARSE_DEFAULT_FLAGS \
6
- rapidjson::kParseFullPrecisionFlag | rapidjson::kParseCommentsFlag | rapidjson::kParseTrailingCommasFlag | rapidjson::kParseNanAndInfFlag
7
- #define kParseFastFlags (rapidjson::kParseDefaultFlags & ~rapidjson::kParseFullPrecisionFlag)
8
- #define RAPIDJSON_WRITE_DEFAULT_FLAGS rapidjson::kWriteNanAndInfFlag
9
- #include <rapidjson/document.h>
10
- #include <rapidjson/writer.h>
11
- #include <rapidjson/prettywriter.h>
12
- #include <rapidjson/error/en.h>
3
+ #include "generator.hpp"
4
+ #include "parser.hpp"
5
+ #include "rb_usamin_value.hpp"
6
+ #include "rb_usamin_hash.hpp"
7
+ #include "rb_usamin_array.hpp"
13
8
 
14
9
  #if SIZEOF_VALUE < SIZEOF_VOIDP
15
10
  #error SIZEOF_VOIDP must not be greater than SIZEOF_VALUE.
16
11
  #endif
17
12
 
18
- class RubyCrtAllocator {
19
- public:
20
- static const bool kNeedFree = true;
21
- void* Malloc(size_t size) {
22
- if (size)
23
- return ruby_xmalloc(size);
24
- else
25
- return nullptr;
26
- }
27
- void* Realloc(void* originalPtr, size_t, size_t newSize) {
28
- if (newSize == 0) {
29
- ruby_xfree(originalPtr);
30
- return nullptr;
31
- }
32
- return ruby_xrealloc(originalPtr, newSize);
33
- }
34
- static void Free(void *ptr) { ruby_xfree(ptr); }
35
- };
36
-
37
- typedef rapidjson::GenericValue<rapidjson::UTF8<>, rapidjson::MemoryPoolAllocator<RubyCrtAllocator>> RubynizedValue;
38
- typedef rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::MemoryPoolAllocator<RubyCrtAllocator>> RubynizedDocument;
39
-
40
13
  rb_encoding *utf8;
41
14
  int utf8index;
42
15
  ID id_dig, id_to_s;
43
- VALUE rb_cUsaminValue, rb_cUsaminHash, rb_cUsaminArray, rb_eUsaminError, rb_eParserError;
44
- VALUE utf8value, sym_fast, sym_indent, sym_single_line_array;
45
-
46
- class UsaminValue {
47
- public:
48
- RubynizedValue *value;
49
- VALUE root_document;
50
- bool free_flag;
51
-
52
- UsaminValue(RubynizedValue *value = nullptr, const bool free_flag = false, const VALUE root_document = Qnil);
53
- ~UsaminValue();
54
- };
55
-
56
- static inline VALUE get_utf8_str(VALUE str) {
57
- Check_Type(str, T_STRING);
58
- int encoding = rb_enc_get_index(str);
59
- if (encoding == utf8index || rb_enc_compatible(str, utf8value) == utf8)
60
- return str;
61
- else
62
- return rb_str_conv_enc(str, rb_enc_from_index(encoding), utf8);
63
- }
64
-
65
- static inline VALUE new_utf8_str(const char* cstr, const long len) {
66
- VALUE ret = rb_str_new(cstr, len);
67
- rb_enc_set_index(ret, utf8index);
68
- return ret;
69
- }
70
-
71
- static inline bool str_compare(const char* str1, const long len1, const char* str2, const long len2) {
72
- if (len1 != len2 || len1 < 0)
73
- return false;
74
- return memcmp(str1, str2, len1) == 0;
75
- }
76
-
77
- static inline bool str_compare_xx(VALUE str1, const RubynizedValue &str2) {
78
- if (RB_TYPE_P(str1, T_STRING))
79
- str1 = get_utf8_str(str1);
80
- else if (SYMBOL_P(str1))
81
- str1 = get_utf8_str(rb_sym_to_s(str1));
82
- else
83
- str1 = get_utf8_str(StringValue(str1));
84
- return str_compare(RSTRING_PTR(str1), RSTRING_LEN(str1), str2.GetString(), str2.GetStringLength());
85
- }
86
-
87
- static inline void check_value(UsaminValue *ptr) {
88
- if (!ptr || !ptr->value)
89
- rb_raise(rb_eUsaminError, "Null Reference.");
90
- }
91
-
92
- static inline void check_object(UsaminValue *ptr) {
93
- check_value(ptr);
94
- if (!ptr->value->IsObject())
95
- rb_raise(rb_eUsaminError, "Value is not an object.");
96
- }
97
-
98
- static inline void check_array(UsaminValue *ptr) {
99
- check_value(ptr);
100
- if (!ptr->value->IsArray())
101
- rb_raise(rb_eUsaminError, "Value is not an array.");
102
- }
103
-
104
-
105
- static void usamin_free(void *p) {
106
- if (!p)
107
- return;
108
- UsaminValue **ptr = (UsaminValue**)p;
109
- if (*ptr)
110
- delete *ptr;
111
- ruby_xfree(p);
112
- }
113
-
114
- static void usamin_mark(void *p) {
115
- if (!p)
116
- return;
117
- UsaminValue **ptr = (UsaminValue**)p;
118
- if (*ptr && !((*ptr)->free_flag))
119
- rb_gc_mark((*ptr)->root_document);
120
- }
121
-
122
- static size_t usamin_size(const void *p) {
123
- if (!p)
124
- return 0;
125
- UsaminValue **ptr = (UsaminValue**)p;
126
- size_t s = 0;
127
- if (*ptr) {
128
- s += sizeof(UsaminValue);
129
- if ((*ptr)->free_flag)
130
- s += ((RubynizedDocument*)(*ptr)->value)->GetAllocator().Capacity() + ((RubynizedDocument*)(*ptr)->value)->GetStackCapacity();
131
- }
132
- return s;
133
- }
134
-
135
- static const rb_data_type_t rb_usamin_value_type = { "UsaminValue", { usamin_mark, usamin_free, usamin_size }, nullptr, nullptr, RUBY_TYPED_FREE_IMMEDIATELY };
136
-
137
- static VALUE usamin_alloc(const VALUE klass) {
138
- UsaminValue** ptr;
139
- VALUE ret = TypedData_Make_Struct(klass, UsaminValue*, &rb_usamin_value_type, ptr);
140
- *ptr = nullptr;
141
- return ret;
142
- }
143
-
144
-
145
- static inline UsaminValue* get_value(VALUE value) {
146
- UsaminValue **ptr;
147
- TypedData_Get_Struct(value, UsaminValue*, &rb_usamin_value_type, ptr);
148
- return *ptr;
149
- }
150
-
151
- static inline void set_value(VALUE value, UsaminValue *usamin) {
152
- UsaminValue **ptr;
153
- TypedData_Get_Struct(value, UsaminValue*, &rb_usamin_value_type, ptr);
154
- *ptr = usamin;
155
- }
156
-
157
- static inline VALUE make_hash(UsaminValue *value, bool is_root = false) {
158
- VALUE ret = rb_obj_alloc(rb_cUsaminHash);
159
- set_value(ret, value);
160
- if (is_root)
161
- value->root_document = ret;
162
- return ret;
163
- }
164
-
165
- static inline VALUE make_array(UsaminValue *value, bool is_root = false) {
166
- VALUE ret = rb_obj_alloc(rb_cUsaminArray);
167
- set_value(ret, value);
168
- if (is_root)
169
- value->root_document = ret;
170
- return ret;
171
- }
172
-
173
- static inline rapidjson::ParseResult parse(RubynizedDocument &doc, const VALUE str, bool fast = false) {
174
- volatile VALUE v = get_utf8_str(str);
175
- return fast ? doc.Parse<kParseFastFlags>(RSTRING_PTR(v), RSTRING_LEN(v)) : doc.Parse(RSTRING_PTR(v), RSTRING_LEN(v));
176
- }
177
-
178
-
179
- static inline VALUE eval_num(RubynizedValue&);
180
- static inline VALUE eval_str(RubynizedValue&);
181
- static inline VALUE eval_object_r(RubynizedValue&);
182
- static inline VALUE eval_array_r(RubynizedValue&);
183
-
184
- static VALUE eval(RubynizedValue &value, VALUE root_document) {
185
- switch (value.GetType()) {
186
- case rapidjson::kObjectType:
187
- return make_hash(new UsaminValue(&value, false, root_document));
188
- case rapidjson::kArrayType:
189
- return make_array(new UsaminValue(&value, false, root_document));
190
- case rapidjson::kNullType:
191
- return Qnil;
192
- case rapidjson::kFalseType:
193
- return Qfalse;
194
- case rapidjson::kTrueType:
195
- return Qtrue;
196
- case rapidjson::kNumberType:
197
- return eval_num(value);
198
- case rapidjson::kStringType:
199
- return eval_str(value);
200
- default:
201
- rb_raise(rb_eUsaminError, "Unknown Value Type: %d", value.GetType());
202
- return Qnil;
203
- }
204
- }
205
-
206
- static VALUE eval_r(RubynizedValue &value) {
207
- switch (value.GetType()) {
208
- case rapidjson::kObjectType:
209
- return eval_object_r(value);
210
- case rapidjson::kArrayType:
211
- return eval_array_r(value);
212
- case rapidjson::kNullType:
213
- return Qnil;
214
- case rapidjson::kFalseType:
215
- return Qfalse;
216
- case rapidjson::kTrueType:
217
- return Qtrue;
218
- case rapidjson::kNumberType:
219
- return eval_num(value);
220
- case rapidjson::kStringType:
221
- return eval_str(value);
222
- default:
223
- rb_raise(rb_eUsaminError, "Unknown Value Type: %d", value.GetType());
224
- return Qnil;
225
- }
226
- }
227
-
228
- static inline VALUE eval_num(RubynizedValue &value) {
229
- if (value.IsInt())
230
- return INT2FIX(value.GetInt());
231
- else if (value.IsUint())
232
- return UINT2NUM(value.GetUint());
233
- else if (value.IsInt64())
234
- return LL2NUM(value.GetInt64());
235
- else if (value.IsUint64())
236
- return ULL2NUM(value.GetUint64());
237
- else
238
- return DBL2NUM(value.GetDouble());
239
- }
240
-
241
- static inline VALUE eval_str(RubynizedValue &value) {
242
- return new_utf8_str(value.GetString(), value.GetStringLength());
243
- }
244
-
245
- static inline VALUE eval_object(RubynizedValue &value, const VALUE root_document) {
246
- VALUE ret = rb_hash_new();
247
- for (auto &m : value.GetObject())
248
- rb_hash_aset(ret, eval_str(m.name), eval(m.value, root_document));
249
- return ret;
250
- }
251
-
252
- static inline VALUE eval_object_r(RubynizedValue &value) {
253
- VALUE ret = rb_hash_new();
254
- for (auto &m : value.GetObject())
255
- rb_hash_aset(ret, eval_str(m.name), eval_r(m.value));
256
- return ret;
257
- }
258
-
259
- static inline VALUE eval_array(RubynizedValue &value, const VALUE root_document) {
260
- VALUE ret = rb_ary_new2(value.Size());
261
- for (auto &v : value.GetArray())
262
- rb_ary_push(ret, eval(v, root_document));
263
- return ret;
264
- }
265
-
266
- static inline VALUE eval_array_r(RubynizedValue &value) {
267
- VALUE ret = rb_ary_new2(value.Size());
268
- for (auto &v : value.GetArray())
269
- rb_ary_push(ret, eval_r(v));
270
- return ret;
271
- }
272
-
273
- static bool eql_array(RubynizedValue&, RubynizedValue&);
274
- static bool eql_object(RubynizedValue&, RubynizedValue&);
275
-
276
- static bool eql_value(RubynizedValue &self, RubynizedValue &other) {
277
- if (self.GetType() != other.GetType())
278
- return false;
279
- switch (self.GetType()) {
280
- case rapidjson::kObjectType:
281
- return eql_object(self, other);
282
- case rapidjson::kArrayType:
283
- return eql_array(self, other);
284
- case rapidjson::kStringType:
285
- return self == other;
286
- case rapidjson::kNumberType:
287
- return self == other && self.IsInt() == other.IsInt() &&
288
- self.IsUint() == other.IsUint() && self.IsInt64() == other.IsInt64() &&
289
- self.IsUint64() == other.IsUint64() && self.IsDouble() == other.IsDouble();
290
- default:
291
- return true;
292
- }
293
- }
294
-
295
- static bool eql_object(RubynizedValue &self, RubynizedValue &other) {
296
- if (self.MemberCount() != other.MemberCount())
297
- return false;
298
- for (auto &m : self.GetObject()) {
299
- if (!other.HasMember(m.name))
300
- return false;
301
- if (!eql_value(m.value, other[m.name]))
302
- return false;
303
- }
304
- return true;
305
- }
306
-
307
- static bool eql_array(RubynizedValue &self, RubynizedValue &other) {
308
- if (self.Size() != other.Size())
309
- return false;
310
- for (rapidjson::SizeType i = 0; i < self.Size(); i++) {
311
- if (!eql_value(self[i], other[i]))
312
- return false;
313
- }
314
- return true;
315
- }
316
-
317
- static st_index_t hash_object(RubynizedValue &value);
318
- static st_index_t hash_array(RubynizedValue &value);
319
-
320
- static st_index_t hash_value(RubynizedValue &value) {
321
- auto type = value.GetType();
322
- st_index_t h = rb_hash_start((st_index_t)type);
323
- rb_hash_uint(h, (st_index_t)hash_value);
324
- switch (type) {
325
- case rapidjson::kNullType:
326
- h = rb_hash_uint(h, NUM2LONG(rb_hash(Qnil)));
327
- break;
328
- case rapidjson::kFalseType:
329
- h = rb_hash_uint(h, NUM2LONG(rb_hash(Qfalse)));
330
- break;
331
- case rapidjson::kTrueType:
332
- h = rb_hash_uint(h, NUM2LONG(rb_hash(Qtrue)));
333
- break;
334
- case rapidjson::kObjectType:
335
- h = rb_hash_uint(h, hash_object(value));
336
- break;
337
- case rapidjson::kArrayType:
338
- h = rb_hash_uint(h, hash_array(value));
339
- break;
340
- case rapidjson::kStringType:
341
- h = rb_hash_uint(h, rb_str_hash(eval_str(value)));
342
- break;
343
- case rapidjson::kNumberType:
344
- if (value.IsInt())
345
- h = rb_hash_uint(h, 0x770);
346
- if (value.IsUint())
347
- h = rb_hash_uint(h, 0x771);
348
- if (value.IsInt64())
349
- h = rb_hash_uint(h, 0x772);
350
- if (value.IsUint64())
351
- h = rb_hash_uint(h, 0x773);
352
- if (value.IsDouble())
353
- h = rb_hash_uint(h, 0x774);
354
- h = rb_hash_uint(h, NUM2LONG(rb_hash(eval_num(value))));
355
- }
356
- return rb_hash_end(h);
357
- }
358
-
359
- static st_index_t hash_object(RubynizedValue &value) {
360
- st_index_t h = rb_hash_start(value.MemberCount());
361
- h = rb_hash_uint(h, (st_index_t)hash_object);
362
- for (auto &m : value.GetObject()) {
363
- h = rb_hash_uint(h, rb_str_hash(eval_str(m.name)));
364
- h = rb_hash_uint(h, hash_value(m.value));
365
- }
366
- return rb_hash_end(h);
367
- }
368
-
369
- static st_index_t hash_array(RubynizedValue &value) {
370
- st_index_t h = rb_hash_start(value.Size());
371
- h = rb_hash_uint(h, (st_index_t)hash_array);
372
- for (auto &v : value.GetArray())
373
- h = rb_hash_uint(h, hash_value(v));
374
- return rb_hash_end(h);
375
- }
376
-
377
-
378
- template <class Writer> static inline void write_str(Writer&, const VALUE);
379
- template <class Writer> static inline void write_hash(Writer&, const VALUE);
380
- template <class Writer> static inline void write_array(Writer&, const VALUE);
381
- template <class Writer> static inline void write_struct(Writer&, const VALUE);
382
- template <class Writer> static inline void write_usamin(Writer&, const VALUE);
383
- template <class Writer> static inline void write_to_s(Writer&, const VALUE);
384
-
385
- template <class Writer> static void write(Writer &writer, const VALUE value) {
386
- switch (TYPE(value)) {
387
- case RUBY_T_NONE:
388
- case RUBY_T_NIL:
389
- case RUBY_T_UNDEF:
390
- writer.Null();
391
- break;
392
- case RUBY_T_TRUE:
393
- writer.Bool(true);
394
- break;
395
- case RUBY_T_FALSE:
396
- writer.Bool(false);
397
- break;
398
- case RUBY_T_FIXNUM:
399
- writer.Int64(FIX2LONG(value));
400
- break;
401
- case RUBY_T_FLOAT:
402
- case RUBY_T_RATIONAL:
403
- writer.Double(NUM2DBL(value));
404
- break;
405
- case RUBY_T_STRING:
406
- write_str(writer, value);
407
- break;
408
- case RUBY_T_ARRAY:
409
- write_array(writer, value);
410
- break;
411
- case RUBY_T_HASH:
412
- write_hash(writer, value);
413
- break;
414
- case RUBY_T_STRUCT:
415
- write_struct(writer, value);
416
- break;
417
- case RUBY_T_BIGNUM:
418
- {
419
- VALUE v = rb_big2str(value, 10);
420
- writer.RawValue(RSTRING_PTR(v), static_cast<unsigned int>(RSTRING_LEN(v)), rapidjson::kNumberType);
421
- }
422
- break;
423
- default:
424
- if (rb_obj_is_kind_of(value, rb_cUsaminValue))
425
- write_usamin(writer, value);
426
- else
427
- write_to_s(writer, value);
428
- break;
429
- }
430
- }
431
-
432
- template <class Writer> static inline void write_str(Writer &writer, const VALUE value) {
433
- VALUE v = get_utf8_str(value);
434
- writer.String(RSTRING_PTR(v), static_cast<unsigned int>(RSTRING_LEN(v)));
435
- }
436
-
437
- template <class Writer> static inline void write_key_str(Writer &writer, const VALUE value) {
438
- VALUE v = get_utf8_str(value);
439
- writer.Key(RSTRING_PTR(v), static_cast<unsigned int>(RSTRING_LEN(v)));
440
- }
441
-
442
- template <class Writer> static inline void write_key_to_s(Writer &writer, const VALUE value) {
443
- write_key_str(writer, rb_funcall(value, id_to_s, 0));
444
- }
445
-
446
- template <class Writer> static inline int write_hash_each(const VALUE key, const VALUE value, Writer *writer) {
447
- if (RB_TYPE_P(key, T_STRING))
448
- write_key_str(*writer, key);
449
- else if (RB_TYPE_P(key, T_SYMBOL))
450
- write_key_str(*writer, rb_sym_to_s(key));
451
- else
452
- write_key_to_s(*writer, key);
453
- write(*writer, value);
454
- return ST_CONTINUE;
455
- }
456
-
457
- template <class Writer> static inline void write_hash(Writer &writer, const VALUE hash) {
458
- writer.StartObject();
459
- rb_hash_foreach(hash, (int (*)(ANYARGS))write_hash_each<Writer>, reinterpret_cast<VALUE>((&writer)));
460
- writer.EndObject();
461
- }
462
-
463
- template <class Writer> static inline void write_array(Writer &writer, const VALUE value) {
464
- writer.StartArray();
465
- const VALUE *ptr = rb_array_const_ptr(value);
466
- for (long i = 0; i < rb_array_len(value); i++, ptr++)
467
- write(writer, *ptr);
468
- writer.EndArray();
469
- }
470
-
471
- template <class Writer> static inline void write_struct(Writer &writer, const VALUE value) {
472
- writer.StartObject();
473
- VALUE members = rb_struct_members(value);
474
- const VALUE *ptr = rb_array_const_ptr(members);
475
- for (long i = 0; i < rb_array_len(members); i++, ptr++) {
476
- if (RB_TYPE_P(*ptr, T_SYMBOL))
477
- write_key_str(writer, rb_sym_to_s(*ptr));
478
- else if (RB_TYPE_P(*ptr, T_STRING))
479
- write_key_str(writer, *ptr);
480
- else
481
- write_key_to_s(writer, *ptr);
482
- write(writer, rb_struct_aref(value, *ptr));
483
- }
484
- writer.EndObject();
485
- }
486
-
487
- template <class Writer> static void write_value(Writer &writer, RubynizedValue &value) {
488
- switch (value.GetType()) {
489
- case rapidjson::kObjectType:
490
- writer.StartObject();
491
- for (auto &m : value.GetObject()) {
492
- writer.Key(m.name.GetString(), m.name.GetStringLength());
493
- write_value(writer, m.value);
494
- }
495
- writer.EndObject();
496
- break;
497
- case rapidjson::kArrayType:
498
- writer.StartArray();
499
- for (auto &v : value.GetArray())
500
- write_value(writer, v);
501
- writer.EndArray();
502
- break;
503
- case rapidjson::kNullType:
504
- writer.Null();
505
- break;
506
- case rapidjson::kFalseType:
507
- writer.Bool(false);
508
- break;
509
- case rapidjson::kTrueType:
510
- writer.Bool(true);
511
- break;
512
- case rapidjson::kNumberType:
513
- if (value.IsInt())
514
- writer.Int(value.GetInt());
515
- else if (value.IsUint())
516
- writer.Uint(value.GetUint());
517
- else if (value.IsInt64())
518
- writer.Int64(value.GetInt64());
519
- else if (value.IsUint64())
520
- writer.Uint64(value.GetUint64());
521
- else
522
- writer.Double(value.GetDouble());
523
- break;
524
- case rapidjson::kStringType:
525
- writer.String(value.GetString(), value.GetStringLength());
526
- break;
527
- default:
528
- rb_raise(rb_eUsaminError, "Unknown Value Type: %d", value.GetType());
529
- }
530
- }
531
-
532
- template <class Writer> static inline void write_usamin(Writer &writer, const VALUE self) {
533
- UsaminValue *value = get_value(self);
534
- check_value(value);
535
- write_value(writer, *(value->value));
536
- }
537
-
538
- template <class Writer> static inline void write_to_s(Writer &writer, const VALUE value) {
539
- write_str(writer, rb_funcall(value, id_to_s, 0));
540
- }
541
-
542
-
543
- UsaminValue::UsaminValue(RubynizedValue *value, const bool free_flag, const VALUE root_document) {
544
- this->value = value;
545
- this->free_flag = free_flag;
546
- this->root_document = root_document;
547
- }
548
-
549
- UsaminValue::~UsaminValue() {
550
- if (value && free_flag)
551
- delete (RubynizedDocument*)value;
552
- }
553
-
554
- /*
555
- * Parse the JSON string into UsaminValue.
556
- * If the document root is not an object or an array, the same value as {#parse} will be returned.
557
- *
558
- * @overload load(source, opts = {})
559
- * @param [String] source JSON string to parse
560
- * @param [::Hash] opts options
561
- * @option opts :fast fast mode (but not precise)
562
- * @return [Object]
563
- */
564
- static VALUE w_load(const int argc, const VALUE *argv, const VALUE self) {
565
- VALUE source, options;
566
- rb_scan_args(argc, argv, "1:", &source, &options);
567
- RubynizedDocument *doc = new RubynizedDocument;
568
- auto result = parse(*doc, source, argc > 1 && RTEST(rb_hash_lookup(options, sym_fast)));
569
- if (!result) {
570
- delete doc;
571
- rb_raise(rb_eParserError, "%s Offset: %lu", GetParseError_En(result.Code()), result.Offset());
572
- }
573
-
574
- VALUE ret;
575
- switch (doc->GetType()) {
576
- case rapidjson::kObjectType:
577
- return make_hash(new UsaminValue(doc, true), true);
578
- case rapidjson::kArrayType:
579
- return make_array(new UsaminValue(doc, true), true);
580
- case rapidjson::kNullType:
581
- delete doc;
582
- return Qnil;
583
- case rapidjson::kFalseType:
584
- delete doc;
585
- return Qfalse;
586
- case rapidjson::kTrueType:
587
- delete doc;
588
- return Qtrue;
589
- case rapidjson::kNumberType:
590
- ret = eval_num(*doc);
591
- delete doc;
592
- return ret;
593
- case rapidjson::kStringType:
594
- ret = eval_str(*doc);
595
- delete doc;
596
- return ret;
597
- default:
598
- rb_raise(rb_eUsaminError, "Unknown Value Type: %d", doc->GetType());
599
- return Qnil;
600
- }
601
- }
602
-
603
- /*
604
- * Parse the JSON string into Ruby data structures.
605
- *
606
- * @overload parse(source, opts = {})
607
- * @param [String] source a JSON string to parse
608
- * @param [::Hash] opts options
609
- * @option opts :fast fast mode (but not precise)
610
- * @return [Object]
611
- */
612
- static VALUE w_parse(const int argc, const VALUE *argv, const VALUE self) {
613
- VALUE source, options;
614
- rb_scan_args(argc, argv, "1:", &source, &options);
615
- RubynizedDocument doc;
616
- auto result = parse(doc, source, argc > 1 && RTEST(rb_hash_lookup(options, sym_fast)));
617
- if (!result)
618
- rb_raise(rb_eParserError, "%s Offset: %lu", GetParseError_En(result.Code()), result.Offset());
619
- return eval_r(doc);
620
- }
621
-
622
- /*
623
- * Returns whether the value is equals to the other value.
624
- *
625
- * @return [Boolean]
626
- */
627
- static VALUE w_value_equal(const VALUE self, const VALUE other) {
628
- if (self == other)
629
- return Qtrue;
630
- UsaminValue *value_self = get_value(self);
631
- check_value(value_self);
632
- if (rb_obj_is_kind_of(other, rb_cUsaminValue)) {
633
- UsaminValue *value_other = get_value(other);
634
- check_value(value_other);
635
- return value_self->value->operator==(*value_other->value) ? Qtrue : Qfalse;
636
- } else if (value_self->value->IsArray() && RB_TYPE_P(other, T_ARRAY)) {
637
- if (value_self->value->Size() != RARRAY_LEN(other))
638
- return Qfalse;
639
- return rb_equal(other, eval_array(*value_self->value, value_self->root_document));
640
- } else if (value_self->value->IsObject() && RB_TYPE_P(other, T_HASH)) {
641
- if (value_self->value->MemberCount() != RHASH_SIZE(other))
642
- return Qfalse;
643
- return rb_equal(other, eval_object(*value_self->value, value_self->root_document));
644
- }
645
- return Qfalse;
646
- }
647
-
648
- /*
649
- * Returns whether the value is array.
650
- */
651
- static VALUE w_value_isarray(const VALUE self) {
652
- UsaminValue *value = get_value(self);
653
- check_value(value);
654
- return value->value->IsArray() ? Qtrue : Qfalse;
655
- }
656
-
657
- /*
658
- * Returns whether the value is object.
659
- */
660
- static VALUE w_value_isobject(const VALUE self) {
661
- UsaminValue *value = get_value(self);
662
- check_value(value);
663
- return value->value->IsObject() ? Qtrue : Qfalse;
664
- }
665
-
666
- /*
667
- * Convert to Ruby data structures.
668
- *
669
- * @return [Object]
670
- */
671
- static VALUE w_value_eval(const VALUE self) {
672
- UsaminValue *value = get_value(self);
673
- check_value(value);
674
- if (value->value->IsObject())
675
- return eval_object(*(value->value), value->root_document);
676
- else if (value->value->IsArray())
677
- return eval_array(*(value->value), value->root_document);
678
- else
679
- return Qnil;
680
- }
681
-
682
- /*
683
- * Convert to Ruby data structures recursively.
684
- *
685
- * @return [Object]
686
- */
687
- static VALUE w_value_eval_r(const VALUE self) {
688
- UsaminValue *value = get_value(self);
689
- check_value(value);
690
- return eval_r(*(value->value));
691
- }
692
-
693
- /*
694
- * @return [Boolean]
695
- */
696
- static VALUE w_value_eql(const VALUE self, const VALUE other) {
697
- if (self == other)
698
- return Qtrue;
699
- if (!rb_obj_is_kind_of(other, rb_cUsaminValue))
700
- return Qfalse;
701
- UsaminValue *value_self = get_value(self);
702
- UsaminValue *value_other = get_value(other);
703
- check_value(value_self);
704
- check_value(value_other);
705
- return eql_value(*value_self->value, *value_other->value) ? Qtrue : Qfalse;
706
- }
707
-
708
- /*
709
- * Always true.
710
- */
711
- static VALUE w_value_isfrozen(const VALUE self) {
712
- return Qtrue;
713
- }
714
-
715
- /*
716
- * @return [Integer]
717
- */
718
- static VALUE w_value_hash(const VALUE self) {
719
- UsaminValue *value = get_value(self);
720
- check_value(value);
721
- return ST2FIX(hash_value(*value->value));
722
- }
723
-
724
- /*
725
- * Returns root object.
726
- *
727
- * @return [UsaminValue]
728
- */
729
- static VALUE w_value_root(const VALUE self) {
730
- UsaminValue *value = get_value(self);
731
- check_value(value);
732
- return value->root_document;
733
- }
734
-
735
- /*
736
- * Dumps data in JSON.
737
- *
738
- * @return [String]
739
- */
740
- static VALUE w_value_marshal_dump(const VALUE self) {
741
- UsaminValue *value = get_value(self);
742
- check_value(value);
743
- rapidjson::StringBuffer buf;
744
- rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
745
- write_value(writer, *value->value);
746
- return rb_str_new(buf.GetString(), buf.GetSize());
747
- }
748
-
749
- /*
750
- * Loads marshal data.
751
- */
752
- static VALUE w_value_marshal_load(const VALUE self, const VALUE source) {
753
- Check_Type(source, T_STRING);
754
- RubynizedDocument *doc = new RubynizedDocument();
755
- rapidjson::ParseResult result = doc->Parse<rapidjson::kParseFullPrecisionFlag | rapidjson::kParseNanAndInfFlag>(RSTRING_PTR(source), RSTRING_LEN(source));
756
- if (!result) {
757
- delete doc;
758
- rb_raise(rb_eParserError, "%s Offset: %lu", GetParseError_En(result.Code()), result.Offset());
759
- }
760
- if (doc->IsObject() || doc->IsArray()) {
761
- UsaminValue *value = new UsaminValue(doc, true);
762
- set_value(self, value);
763
- value->root_document = self;
764
- } else {
765
- auto type = doc->GetType();
766
- delete doc;
767
- rb_raise(rb_eUsaminError, "Invalid Value Type for marshal_load: %d", type);
768
- }
769
- return Qnil;
770
- }
771
-
772
-
773
- /*
774
- * @return [Object | nil]
775
- *
776
- * @note This method has linear time complexity.
777
- */
778
- static VALUE w_hash_operator_indexer(const VALUE self, const VALUE key) {
779
- UsaminValue *value = get_value(self);
780
- check_object(value);
781
- for (auto &m : value->value->GetObject())
782
- if (str_compare_xx(key, m.name))
783
- return eval(m.value, value->root_document);
784
- return Qnil;
785
- }
786
-
787
- /*
788
- * @return [::Array | nil]
789
- *
790
- * @note This method has linear time complexity.
791
- */
792
- static VALUE w_hash_assoc(const VALUE self, const VALUE key) {
793
- UsaminValue *value = get_value(self);
794
- check_object(value);
795
- for (auto &m : value->value->GetObject())
796
- if (str_compare_xx(key, m.name))
797
- return rb_assoc_new(eval_str(m.name), eval(m.value, value->root_document));
798
- return Qnil;
799
- }
800
-
801
- /*
802
- * @return [::Hash]
803
- */
804
- static VALUE w_hash_compact(const VALUE self) {
805
- UsaminValue *value = get_value(self);
806
- check_object(value);
807
- VALUE hash = rb_hash_new();
808
- for (auto &m : value->value->GetObject())
809
- if (!m.value.IsNull())
810
- rb_hash_aset(hash, eval(m.name, value->root_document), eval(m.value, value->root_document));
811
- return hash;
812
- }
813
-
814
- /*
815
- * @return [Object | nil]
816
- */
817
- static VALUE w_hash_dig(const int argc, const VALUE *argv, const VALUE self) {
818
- rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
819
- VALUE value = w_hash_operator_indexer(self, argv[0]);
820
- if (argc == 1)
821
- return value;
822
- else if (value == Qnil)
823
- return Qnil;
824
- else
825
- return rb_funcall3(value, id_dig, argc - 1, argv + 1);
826
- }
827
-
828
- static VALUE hash_enum_size(const VALUE self, const VALUE args, const VALUE eobj) {
829
- return UINT2NUM(get_value(self)->value->MemberCount());
830
- }
831
-
832
- /*
833
- * @yield [key, value]
834
- * @yieldparam key [String]
835
- * @yieldparam value [Object]
836
- * @return [Enumerator | self]
837
- */
838
- static VALUE w_hash_each(const VALUE self) {
839
- UsaminValue *value = get_value(self);
840
- check_object(value);
841
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
842
- if (rb_proc_arity(rb_block_proc()) > 1) {
843
- for (auto &m : value->value->GetObject()) {
844
- VALUE args[] = { eval_str(m.name), eval(m.value, value->root_document) };
845
- rb_yield_values2(2, args);
846
- }
847
- } else {
848
- for (auto &m : value->value->GetObject())
849
- rb_yield(rb_assoc_new(eval_str(m.name), eval(m.value, value->root_document)));
850
- }
851
- return self;
852
- }
853
-
854
- /*
855
- * @yield [key]
856
- * @yieldparam key [String]
857
- * @return [Enumerator | self]
858
- */
859
- static VALUE w_hash_each_key(const VALUE self) {
860
- UsaminValue *value = get_value(self);
861
- check_object(value);
862
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
863
- for (auto &m : value->value->GetObject())
864
- rb_yield(eval_str(m.name));
865
- return self;
866
- }
867
-
868
- /*
869
- * @yield [value]
870
- * @return [Enumerator | self]
871
- */
872
- static VALUE w_hash_each_value(const VALUE self) {
873
- UsaminValue *value = get_value(self);
874
- check_object(value);
875
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
876
- for (auto &m : value->value->GetObject())
877
- rb_yield(eval(m.value, value->root_document));
878
- return self;
879
- }
880
-
881
- static VALUE w_hash_isempty(const VALUE self) {
882
- UsaminValue *value = get_value(self);
883
- check_object(value);
884
- return value->value->MemberCount() == 0 ? Qtrue : Qfalse;
885
- }
886
-
887
- /*
888
- * @overload fetch(key, default = nil)
889
- * @param [String] key
890
- * @param [Object] default
891
- * @return [Object]
892
- *
893
- * @overload fetch(key)
894
- * @param [String] key
895
- * @yield [key]
896
- * @return [Object]
897
- */
898
- static VALUE w_hash_fetch(const int argc, const VALUE *argv, const VALUE self) {
899
- rb_check_arity(argc, 1, 2);
900
- UsaminValue *value = get_value(self);
901
- check_object(value);
902
- for (auto &m : value->value->GetObject())
903
- if (str_compare_xx(argv[0], m.name))
904
- return eval(m.value, value->root_document);
905
- return argc == 2 ? argv[1] : rb_block_given_p() ? rb_yield(argv[0]) : Qnil;
906
- }
907
-
908
- /*
909
- * @param [String] key
910
- * @return [::Array<Object>]
911
- */
912
- static VALUE w_hash_fetch_values(const int argc, VALUE *argv, const VALUE self) {
913
- UsaminValue *value = get_value(self);
914
- check_object(value);
915
- VALUE ret = rb_ary_new2(argc);
916
- for (int i = 0; i < argc; i++) {
917
- bool found = false;
918
- for (auto &m : value->value->GetObject()) {
919
- if (str_compare_xx(argv[i], m.name)) {
920
- rb_ary_push(ret, eval(m.value, value->root_document));
921
- found = true;
922
- break;
923
- }
924
- }
925
- if (!found) {
926
- if (rb_block_given_p()) {
927
- rb_ary_push(ret, rb_yield(argv[i]));
928
- } else {
929
- rb_ary_free(ret);
930
- rb_raise(rb_eKeyError, "key not found: \"%s\"", StringValueCStr(argv[i]));
931
- return Qnil;
932
- }
933
- }
934
- }
935
- return ret;
936
- }
937
-
938
- static void flatten_array(RubynizedValue &value, VALUE array, int level, VALUE root_document);
939
-
940
- /*
941
- * @overload flatten(level = 1)
942
- * @return [::Array<Object>]
943
- */
944
- static VALUE w_hash_flatten(const int argc, const VALUE *argv, const VALUE self) {
945
- rb_check_arity(argc, 0, 1);
946
- UsaminValue *value = get_value(self);
947
- check_object(value);
948
-
949
- int level = 1;
950
- if (argc == 1 && !NIL_P(argv[0])) {
951
- level = NUM2INT(argv[0]);
952
- if (level < 0)
953
- level = -1;
954
- }
955
-
956
- if (level == 0) {
957
- VALUE ret = rb_ary_new2(value->value->MemberCount());
958
- for (auto &m : value->value->GetObject())
959
- rb_ary_push(ret, rb_ary_new3(2, eval_str(m.name), eval(m.value, value->root_document)));
960
- return ret;
961
- }
962
-
963
- VALUE ret = rb_ary_new2(value->value->MemberCount() * 2);
964
- if (level == 1) {
965
- for (auto &m : value->value->GetObject()) {
966
- rb_ary_push(ret, eval_str(m.name));
967
- rb_ary_push(ret, eval(m.value, value->root_document));
968
- }
969
- } else {
970
- for (auto &m : value->value->GetObject()) {
971
- rb_ary_push(ret, eval_str(m.name));
972
- if (m.value.IsArray())
973
- flatten_array(m.value, ret, level > 0 ? level - 2 : level, value->root_document);
974
- else
975
- rb_ary_push(ret, eval(m.value, value->root_document));
976
- }
977
- }
978
- return ret;
979
- }
980
-
981
- /*
982
- * @note This method has linear time complexity.
983
- */
984
- static VALUE w_hash_haskey(const VALUE self, const VALUE key) {
985
- UsaminValue *value = get_value(self);
986
- check_object(value);
987
- for (auto &m : value->value->GetObject())
988
- if (str_compare_xx(key, m.name))
989
- return Qtrue;
990
- return Qfalse;
991
- }
992
-
993
- static VALUE w_hash_hasvalue(const VALUE self, const VALUE val) {
994
- UsaminValue *value = get_value(self);
995
- check_object(value);
996
- for (auto &m : value->value->GetObject())
997
- if (rb_equal(val, eval_r(m.value)))
998
- return Qtrue;
999
- return Qfalse;
1000
- }
1001
-
1002
- /*
1003
- * @return [String | nil]
1004
- */
1005
- static VALUE w_hash_key(const VALUE self, const VALUE val) {
1006
- UsaminValue *value = get_value(self);
1007
- check_object(value);
1008
- for (auto &m : value->value->GetObject())
1009
- if (rb_equal(val, eval_r(m.value)))
1010
- return eval_str(m.name);
1011
- return Qnil;
1012
- }
1013
-
1014
- /*
1015
- * @return [String]
1016
- */
1017
- static VALUE w_hash_inspect(const VALUE self) {
1018
- UsaminValue *value = get_value(self);
1019
- check_object(value);
1020
- VALUE ret = rb_str_new2("{");
1021
- bool first = true;
1022
- for (auto &m : value->value->GetObject()) {
1023
- if (!first)
1024
- ret = rb_str_cat2(ret, ", ");
1025
- ret = rb_str_append(ret, rb_inspect(eval_str(m.name)));
1026
- ret = rb_str_cat2(ret, "=>");
1027
- switch (m.value.GetType()) {
1028
- case rapidjson::kObjectType:
1029
- ret = rb_str_cat2(ret, "{...}");
1030
- break;
1031
- case rapidjson::kArrayType:
1032
- ret = rb_str_cat2(ret, "[...]");
1033
- break;
1034
- default:
1035
- ret = rb_str_append(ret, rb_inspect(eval(m.value, value->root_document)));
1036
- break;
1037
- }
1038
- first = false;
1039
- }
1040
- ret = rb_str_cat2(ret, "}");
1041
- return ret;
1042
- }
16
+ VALUE rb_mUsamin, rb_cUsaminValue, rb_cUsaminHash, rb_cUsaminArray, rb_eUsaminError, rb_eParserError;
17
+ VALUE utf8value, sym_fast, sym_indent, sym_recursive, sym_single_line_array, sym_symbolize_names;
1043
18
 
1044
- /*
1045
- * @return [::Array<String>]
1046
- */
1047
- static VALUE w_hash_keys(const VALUE self) {
1048
- UsaminValue *value = get_value(self);
1049
- check_object(value);
1050
- VALUE ret = rb_ary_new2(value->value->MemberCount());
1051
- for (auto &m : value->value->GetObject())
1052
- rb_ary_push(ret, eval_str(m.name));
1053
- return ret;
1054
- }
1055
-
1056
- /*
1057
- * @return [Integer]
1058
- */
1059
- static VALUE w_hash_length(const VALUE self) {
1060
- UsaminValue *value = get_value(self);
1061
- check_object(value);
1062
- return UINT2NUM(value->value->MemberCount());
1063
- }
1064
-
1065
- /*
1066
- * @return [::Array | nil]
1067
- */
1068
- static VALUE w_hash_rassoc(const VALUE self, const VALUE val) {
1069
- UsaminValue *value = get_value(self);
1070
- check_object(value);
1071
- for (auto &m : value->value->GetObject())
1072
- if (rb_funcall(val, rb_intern("=="), 1, eval_r(m.value)))
1073
- return rb_assoc_new(eval_str(m.name), eval(m.value, value->root_document));
1074
- return Qnil;
1075
- }
1076
-
1077
- /*
1078
- * @yield [key, value]
1079
- * @yieldparam key [String]
1080
- * @yieldparam value [Object]
1081
- * @return [Enumerator | ::Hash]
1082
- */
1083
- static VALUE w_hash_select(const VALUE self) {
1084
- UsaminValue *value = get_value(self);
1085
- check_object(value);
1086
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
1087
- VALUE hash = rb_hash_new();
1088
- if (rb_proc_arity(rb_block_proc()) > 1) {
1089
- for (auto &m : value->value->GetObject()) {
1090
- VALUE args[] = { eval_str(m.name), eval(m.value, value->root_document) };
1091
- if (RTEST(rb_yield_values2(2, args)))
1092
- rb_hash_aset(hash, args[0], args[1]);
1093
- }
1094
- } else {
1095
- for (auto &m : value->value->GetObject()) {
1096
- VALUE key = eval_str(m.name);
1097
- VALUE val = eval(m.value, value->root_document);
1098
- if (RTEST(rb_yield(rb_assoc_new(key, val))))
1099
- rb_hash_aset(hash, key, val);
1100
- }
1101
- }
1102
- return hash;
1103
- }
1104
-
1105
- /*
1106
- * @yield [key, value]
1107
- * @yieldparam key [String]
1108
- * @yieldparam value [Object]
1109
- * @return [Enumerator | ::Hash]
1110
- */
1111
- static VALUE w_hash_reject(const VALUE self) {
1112
- UsaminValue *value = get_value(self);
1113
- check_object(value);
1114
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
1115
- VALUE hash = rb_hash_new();
1116
- if (rb_proc_arity(rb_block_proc()) > 1) {
1117
- for (auto &m : value->value->GetObject()) {
1118
- VALUE args[] = { eval_str(m.name), eval(m.value, value->root_document) };
1119
- if (!RTEST(rb_yield_values2(2, args)))
1120
- rb_hash_aset(hash, args[0], args[1]);
1121
- }
1122
- } else {
1123
- for (auto &m : value->value->GetObject()) {
1124
- VALUE key = eval_str(m.name);
1125
- VALUE val = eval(m.value, value->root_document);
1126
- if (!RTEST(rb_yield(rb_assoc_new(key, val))))
1127
- rb_hash_aset(hash, key, val);
1128
- }
1129
- }
1130
- return hash;
1131
- }
1132
-
1133
- /*
1134
- * @yield [key, value]
1135
- * @yieldparam key [String]
1136
- * @yieldparam value [Object]
1137
- * @return [Enumerator | ::Hash]
1138
- */
1139
- static VALUE w_hash_slice(const int argc, const VALUE *argv, const VALUE self) {
1140
- UsaminValue *value = get_value(self);
1141
- check_object(value);
1142
- VALUE hash = rb_hash_new();
1143
- for (int i = 0; i < argc; i++)
1144
- for (auto &m : value->value->GetObject())
1145
- if (str_compare_xx(argv[i], m.name))
1146
- rb_hash_aset(hash, eval_str(m.name), eval(m.value, value->root_document));
1147
- return hash;
1148
- }
1149
-
1150
- /*
1151
- * Convert to Ruby Hash. Same as {Value#eval}.
1152
- *
1153
- * @return [::Hash]
1154
- */
1155
- static VALUE w_hash_eval(const VALUE self) {
1156
- UsaminValue *value = get_value(self);
1157
- check_object(value);
1158
- return eval_object(*(value->value), value->root_document);
1159
- }
1160
-
1161
- /*
1162
- * @return [::Hash]
1163
- */
1164
- static VALUE w_hash_merge(const int argc, const VALUE *argv, const VALUE self) {
1165
- static ID s = rb_intern("merge");
1166
- return rb_funcall2(w_hash_eval(self), s, argc, argv);
1167
- }
1168
-
1169
- /*
1170
- * @return [::Array<Object>]
1171
- */
1172
- static VALUE w_hash_values(const VALUE self) {
1173
- UsaminValue *value = get_value(self);
1174
- check_object(value);
1175
- VALUE ret = rb_ary_new2(value->value->MemberCount());
1176
- for (auto &m : value->value->GetObject())
1177
- rb_ary_push(ret, eval(m.value, value->root_document));
1178
- return ret;
1179
- }
1180
-
1181
- /*
1182
- * @yield [key]
1183
- * @yieldparam key [String]
1184
- * @return [Enumerator | ::Hash]
1185
- */
1186
- static VALUE w_hash_transform_keys(const VALUE self) {
1187
- UsaminValue *value = get_value(self);
1188
- check_object(value);
1189
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
1190
- VALUE hash = rb_hash_new();
1191
- for (auto &m : value->value->GetObject())
1192
- rb_hash_aset(hash, rb_yield(eval_str(m.name)), eval(m.value, value->root_document));
1193
- return hash;
1194
- }
1195
-
1196
- /*
1197
- * @yield [value]
1198
- * @yieldparam value [Object]
1199
- * @return [Enumerator | ::Hash]
1200
- */
1201
- static VALUE w_hash_transform_values(const VALUE self) {
1202
- UsaminValue *value = get_value(self);
1203
- check_object(value);
1204
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
1205
- VALUE hash = rb_hash_new();
1206
- for (auto &m : value->value->GetObject())
1207
- rb_hash_aset(hash, eval_str(m.name), rb_yield(eval(m.value, value->root_document)));
1208
- return hash;
1209
- }
1210
-
1211
- /*
1212
- * @param [String] keys
1213
- * @return [::Array<Object>]
1214
- */
1215
- static VALUE w_hash_values_at(const int argc, const VALUE *argv, const VALUE self) {
1216
- UsaminValue *value = get_value(self);
1217
- check_object(value);
1218
- VALUE ret = rb_ary_new2(argc);
1219
- for (int i = 0; i < argc; i++) {
1220
- VALUE data = Qnil;
1221
- for (auto &m : value->value->GetObject()) {
1222
- if (str_compare_xx(argv[i], m.name)) {
1223
- data = eval(m.value, value->root_document);
1224
- break;
1225
- }
1226
- }
1227
- rb_ary_push(ret, data);
1228
- }
1229
- return ret;
1230
- }
1231
-
1232
- /*
1233
- * @overload [](nth)
1234
- * @param [Integer] nth
1235
- * @return [Object | nil]
1236
- *
1237
- * @overload [](start, length)
1238
- * @param [Integer] start
1239
- * @param [Integer] length
1240
- * @return [::Array<Object> | nil]
1241
- *
1242
- * @overload [](range)
1243
- * @param [Range] range
1244
- * @return [::Array<Object> | nil]
1245
- */
1246
- static VALUE w_array_operator_indexer(const int argc, const VALUE *argv, const VALUE self) {
1247
- rb_check_arity(argc, 1, 2);
1248
- UsaminValue *value = get_value(self);
1249
- check_array(value);
1250
- rapidjson::SizeType sz = value->value->Size();
1251
- if (argc == 2) {
1252
- long beg = FIX2LONG(argv[0]);
1253
- long len = FIX2LONG(argv[1]);
1254
- if (beg < 0)
1255
- beg += sz;
1256
- if (beg >= 0 && len >= 0) {
1257
- rapidjson::SizeType end = static_cast<rapidjson::SizeType>(beg + len);
1258
- if (end > sz)
1259
- end = sz;
1260
- VALUE ret = rb_ary_new2(end - beg);
1261
- for (rapidjson::SizeType i = static_cast<rapidjson::SizeType>(beg); i < end; i++)
1262
- rb_ary_push(ret, eval((*value->value)[i], value->root_document));
1263
- return ret;
1264
- }
1265
- } else if (rb_obj_is_kind_of(argv[0], rb_cRange)) {
1266
- long beg, len;
1267
- if (rb_range_beg_len(argv[0], &beg, &len, sz, 0) == Qtrue) {
1268
- VALUE ret = rb_ary_new2(len);
1269
- for (rapidjson::SizeType i = static_cast<rapidjson::SizeType>(beg); i < beg + len; i++)
1270
- rb_ary_push(ret, eval((*value->value)[i], value->root_document));
1271
- return ret;
1272
- }
1273
- } else {
1274
- long l = FIX2LONG(argv[0]);
1275
- if (l < 0)
1276
- l += sz;
1277
- if (0 <= l && l < sz)
1278
- return eval((*value->value)[static_cast<rapidjson::SizeType>(l)], value->root_document);
1279
- }
1280
- return Qnil;
1281
- }
1282
-
1283
- /*
1284
- * @param [Integer] nth
1285
- * @return [Object]
1286
- */
1287
- static VALUE w_array_at(const VALUE self, const VALUE nth) {
1288
- UsaminValue *value = get_value(self);
1289
- check_array(value);
1290
- long l = FIX2LONG(nth);
1291
- rapidjson::SizeType sz = value->value->Size();
1292
- if (l < 0)
1293
- l += sz;
1294
- if (0 <= l && l < sz)
1295
- return eval((*value->value)[static_cast<rapidjson::SizeType>(l)], value->root_document);
1296
- return Qnil;
1297
- }
1298
-
1299
- /*
1300
- * @return [::Array]
1301
- */
1302
- static VALUE w_array_compact(const VALUE self, const VALUE nth) {
1303
- UsaminValue *value = get_value(self);
1304
- check_array(value);
1305
- VALUE ret = rb_ary_new2(value->value->Size());
1306
- for (auto &v : value->value->GetArray())
1307
- if (!v.IsNull())
1308
- rb_ary_push(ret, eval(v, value->root_document));
1309
- return ret;
1310
- }
1311
-
1312
- /*
1313
- * @return [Object | nil]
1314
- */
1315
- static VALUE w_array_dig(const int argc, const VALUE *argv, const VALUE self) {
1316
- rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
1317
- VALUE value = w_array_at(self, argv[0]);
1318
- if (argc == 1)
1319
- return value;
1320
- else if (value == Qnil)
1321
- return Qnil;
1322
- else
1323
- return rb_funcall3(value, id_dig, argc - 1, argv + 1);
1324
- }
1325
-
1326
- static VALUE array_enum_size(const VALUE self, const VALUE args, const VALUE eobj) {
1327
- return UINT2NUM(get_value(self)->value->Size());
1328
- }
1329
-
1330
- /*
1331
- * @yield [value]
1332
- * @return [Enumerator | self]
1333
- */
1334
- static VALUE w_array_each(const VALUE self) {
1335
- UsaminValue *value = get_value(self);
1336
- check_array(value);
1337
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, array_enum_size);
1338
- for (auto &v : value->value->GetArray())
1339
- rb_yield(eval(v, value->root_document));
1340
- return self;
1341
- }
1342
-
1343
- /*
1344
- * @yield [index]
1345
- * @yieldparam index [Integer]
1346
- * @return [Enumerator | self]
1347
- */
1348
- static VALUE w_array_each_index(const VALUE self) {
1349
- UsaminValue *value = get_value(self);
1350
- check_array(value);
1351
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, array_enum_size);
1352
- for (rapidjson::SizeType i = 0; i < value->value->Size(); i++)
1353
- rb_yield(UINT2NUM(i));
1354
- return self;
1355
- }
1356
-
1357
- static VALUE w_array_isempty(const VALUE self) {
1358
- UsaminValue *value = get_value(self);
1359
- check_array(value);
1360
- return value->value->Size() == 0 ? Qtrue : Qfalse;
1361
- }
1362
-
1363
- /*
1364
- * @overload fetch(nth)
1365
- * @param [Integer] nth
1366
- * @return [Object]
1367
- * @raise [IndexError] if nth is out of array bounds
1368
- *
1369
- * @overload fetch(nth, ifnone)
1370
- * @param [Integer] nth
1371
- * @param [Object] ifnone
1372
- * @return [Object]
1373
- *
1374
- * @overload fetch(nth)
1375
- * @param [Integer] nth
1376
- * @yield [nth]
1377
- * @return [Object]
1378
- */
1379
- static VALUE w_array_fetch(const int argc, const VALUE *argv, const VALUE self) {
1380
- rb_check_arity(argc, 1, 2);
1381
- UsaminValue *value = get_value(self);
1382
- check_array(value);
1383
- rapidjson::SizeType sz = value->value->Size();
1384
-
1385
- long l = FIX2LONG(argv[0]);
1386
- if (l < 0)
1387
- l += sz;
1388
- if (0 <= l && l < sz)
1389
- return eval((*value->value)[static_cast<rapidjson::SizeType>(l)], value->root_document);
1390
-
1391
- if (argc == 2)
1392
- return argv[1];
1393
- else if (rb_block_given_p())
1394
- return rb_yield(argv[0]);
1395
- else
1396
- rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%u", FIX2LONG(argv[0]), -static_cast<long>(sz), sz);
1397
- return Qnil;
1398
- }
1399
-
1400
- /*
1401
- * @overload find_index(val)
1402
- * @param [Object] val
1403
- * @return [Integer | nil]
1404
- *
1405
- * @overload find_index
1406
- * @yield [item]
1407
- * @yieldparam item [Object]
1408
- * @return [Integer | nil]
1409
- */
1410
- static VALUE w_array_find_index(const int argc, const VALUE *argv, const VALUE self) {
1411
- rb_check_arity(argc, 0, 1);
1412
- UsaminValue *value = get_value(self);
1413
- check_array(value);
1414
-
1415
- if (argc == 1) {
1416
- for (rapidjson::SizeType i = 0; i < value->value->Size(); i++) {
1417
- if (rb_equal(argv[0], eval_r((*value->value)[i])) == Qtrue)
1418
- return UINT2NUM(i);
1419
- }
1420
- return Qnil;
1421
- }
1422
-
1423
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, array_enum_size);
1424
- for (rapidjson::SizeType i = 0; i < value->value->Size(); i++) {
1425
- if (RTEST(rb_yield(eval((*value->value)[i], value->root_document))))
1426
- return UINT2NUM(i);
1427
- }
1428
- return Qnil;
1429
- }
1430
-
1431
- static void flatten_array(RubynizedValue &value, VALUE array, int level, VALUE root_document) {
1432
- if (level == 0)
1433
- for (auto &v : value.GetArray())
1434
- rb_ary_push(array, eval(v, root_document));
1435
- else
1436
- for (auto &v : value.GetArray())
1437
- if (v.IsArray())
1438
- flatten_array(v, array, level > 0 ? level - 1 : level, root_document);
1439
- else
1440
- rb_ary_push(array, eval(v, root_document));
1441
- }
1442
-
1443
- /*
1444
- * @overload flatten(lv = nil)
1445
- * @return [::Array<Object>]
1446
- */
1447
- static VALUE w_array_flatten(const int argc, const VALUE *argv, const VALUE self) {
1448
- rb_check_arity(argc, 0, 1);
1449
- UsaminValue *value = get_value(self);
1450
- check_array(value);
1451
-
1452
- int level = -1;
1453
- if (argc == 1 && !NIL_P(argv[0])) {
1454
- level = NUM2INT(argv[0]);
1455
- if (level <= 0)
1456
- return eval_array(*value->value, value->root_document);
1457
- }
1458
-
1459
- VALUE ret = rb_ary_new2(value->value->Size());
1460
- flatten_array(*value->value, ret, level, value->root_document);
1461
- return ret;
1462
- }
1463
-
1464
- /*
1465
- * @overload index(val)
1466
- * @param [Object] val
1467
- * @return [Integer | nil]
1468
- *
1469
- * @overload index
1470
- * @yield [item]
1471
- * @yieldparam item [Object]
1472
- * @return [Integer | nil]
1473
- */
1474
- static VALUE w_array_index(const int argc, const VALUE *argv, const VALUE self) {
1475
- return w_array_find_index(argc, argv, self);
1476
- }
1477
-
1478
- /*
1479
- * @overload first
1480
- * @return [Object | nil]
1481
- *
1482
- * @overload first(n)
1483
- * @return [::Array<Object>]
1484
- */
1485
- static VALUE w_array_first(const int argc, const VALUE *argv, const VALUE self) {
1486
- rb_check_arity(argc, 0, 1);
1487
- UsaminValue *value = get_value(self);
1488
- check_array(value);
1489
- rapidjson::SizeType sz = value->value->Size();
1490
-
1491
- if (argc == 0) {
1492
- if (sz == 0)
1493
- return Qnil;
1494
- return eval(*value->value->Begin(), value->root_document);
1495
- } else {
1496
- long l = FIX2LONG(argv[0]);
1497
- if (l > sz)
1498
- l = sz;
1499
- VALUE ret = rb_ary_new2(l);
1500
- for (auto v = value->value->Begin(); v < value->value->Begin() + l; v++)
1501
- rb_ary_push(ret, eval(*v, value->root_document));
1502
- return ret;
1503
- }
1504
- }
1505
-
1506
- /*
1507
- * @return [Boolean]
1508
- */
1509
- static VALUE w_array_include(const VALUE self, const VALUE val) {
1510
- UsaminValue *value = get_value(self);
1511
- check_array(value);
1512
- for (auto &v : value->value->GetArray())
1513
- if (rb_equal(val, eval_r(v)))
1514
- return Qtrue;
1515
- return Qfalse;
1516
- }
1517
-
1518
- /*
1519
- * @return [String]
1520
- */
1521
- static VALUE w_array_inspect(const VALUE self) {
1522
- UsaminValue *value = get_value(self);
1523
- check_array(value);
1524
- VALUE ret = rb_str_new2("[");
1525
- bool first = true;
1526
- for (auto &v : value->value->GetArray()) {
1527
- if (!first)
1528
- ret = rb_str_cat2(ret, ", ");
1529
- switch (v.GetType()) {
1530
- case rapidjson::kObjectType:
1531
- ret = rb_str_cat2(ret, "{...}");
1532
- break;
1533
- case rapidjson::kArrayType:
1534
- ret = rb_str_cat2(ret, "[...]");
1535
- break;
1536
- default:
1537
- ret = rb_str_append(ret, rb_inspect(eval(v, value->root_document)));
1538
- break;
1539
- }
1540
- first = false;
1541
- }
1542
- ret = rb_str_cat2(ret, "]");
1543
- return ret;
1544
- }
1545
-
1546
- /*
1547
- * @overload last
1548
- * @return [Object | nil]
1549
- *
1550
- * @overload last(n)
1551
- * @return [::Array<Object>]
1552
- */
1553
- static VALUE w_array_last(const int argc, const VALUE *argv, const VALUE self) {
1554
- rb_check_arity(argc, 0, 1);
1555
- UsaminValue *value = get_value(self);
1556
- check_array(value);
1557
- rapidjson::SizeType sz = value->value->Size();
1558
-
1559
- if (argc == 0) {
1560
- return sz > 0 ? eval(*(value->value->End() - 1), value->root_document) : Qnil;
1561
- } else {
1562
- long l = FIX2LONG(argv[0]);
1563
- if (l > sz)
1564
- l = sz;
1565
- VALUE ret = rb_ary_new2(l);
1566
- for (auto v = value->value->End() - l; v < value->value->End(); v++)
1567
- rb_ary_push(ret, eval(*v, value->root_document));
1568
- return ret;
1569
- }
1570
- }
1571
-
1572
- /*
1573
- * @return [Integer]
1574
- */
1575
- static VALUE w_array_length(const VALUE self) {
1576
- UsaminValue *value = get_value(self);
1577
- check_array(value);
1578
- return UINT2NUM(value->value->Size());
1579
- }
1580
-
1581
- /*
1582
- * @return [::Array<Object>]
1583
- */
1584
- static VALUE w_array_reverse(const VALUE self) {
1585
- UsaminValue *value = get_value(self);
1586
- check_array(value);
1587
-
1588
- VALUE ret = rb_ary_new2(value->value->Size());
1589
- for (rapidjson::SizeType i = 0, j = value->value->Size() - 1; i < value->value->Size(); i++, j--)
1590
- rb_ary_push(ret, eval((*value->value)[j], value->root_document));
1591
- return ret;
1592
- }
1593
-
1594
- /*
1595
- * @overload rindex(val)
1596
- * @param [Object] val
1597
- * @return [Integer | nil]
1598
- *
1599
- * @overload rindex
1600
- * @yield [item]
1601
- * @yieldparam item [Object]
1602
- * @return [Integer | nil]
1603
- */
1604
- static VALUE w_array_rindex(const int argc, const VALUE *argv, const VALUE self) {
1605
- rb_check_arity(argc, 0, 1);
1606
- UsaminValue *value = get_value(self);
1607
- check_array(value);
1608
-
1609
- if (argc == 1) {
1610
- for (rapidjson::SizeType i = 0, j = value->value->Size() - 1; i < value->value->Size(); i++, j--) {
1611
- if (rb_equal(argv[0], eval_r((*value->value)[j])) == Qtrue)
1612
- return UINT2NUM(j);
1613
- }
1614
- return Qnil;
1615
- }
1616
-
1617
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, array_enum_size);
1618
- for (rapidjson::SizeType i = 0, j = value->value->Size() - 1; i < value->value->Size(); i++, j--) {
1619
- if (RTEST(rb_yield(eval((*value->value)[j], value->root_document))))
1620
- return UINT2NUM(j);
1621
- }
1622
- return Qnil;
1623
- }
1624
-
1625
- /*
1626
- * @overload rotate(cnt = 1)
1627
- * @return [::Array<Object>]
1628
- */
1629
- static VALUE w_array_rotate(const int argc, const VALUE *argv, const VALUE self) {
1630
- rb_check_arity(argc, 0, 1);
1631
- UsaminValue *value = get_value(self);
1632
- check_array(value);
1633
-
1634
- switch (value->value->Size()) {
1635
- case 0:
1636
- return rb_ary_new();
1637
- case 1:
1638
- return rb_ary_new3(1, eval(value->value->operator[](0), value->root_document));
1639
- }
1640
-
1641
- int cnt = argc == 1 ? NUM2INT(argv[0]) : 1;
1642
- if (cnt >= 0) {
1643
- cnt = cnt % value->value->Size();
1644
- } else {
1645
- cnt = -cnt % value->value->Size();
1646
- if (cnt)
1647
- cnt = value->value->Size() - cnt;
1648
- }
1649
- if (cnt == 0)
1650
- return eval_array(*(value->value), value->root_document);
1651
-
1652
- rapidjson::SizeType ucnt = cnt;
1653
- VALUE ret = rb_ary_new2(value->value->Size());
1654
- for (rapidjson::SizeType i = ucnt; i < value->value->Size(); i++)
1655
- rb_ary_push(ret, eval((*value->value)[i], value->root_document));
1656
- for (rapidjson::SizeType i = 0; i < ucnt; i++)
1657
- rb_ary_push(ret, eval((*value->value)[i], value->root_document));
1658
- return ret;
1659
- }
1660
-
1661
- /*
1662
- * @overload slice(nth)
1663
- * @param [Integer] nth
1664
- * @return [Object | nil]
1665
- *
1666
- * @overload slice(start, length)
1667
- * @param [Integer] start
1668
- * @param [Integer] length
1669
- * @return [::Array<Object> | nil]
1670
- *
1671
- * @overload slice(range)
1672
- * @param [Range] range
1673
- * @return [::Array<Object> | nil]
1674
- */
1675
- static VALUE w_array_slice(const int argc, const VALUE *argv, const VALUE self) {
1676
- return w_array_operator_indexer(argc, argv, self);
1677
- }
1678
-
1679
- /*
1680
- * Convert to Ruby data structures. Same as {Value#eval}.
1681
- *
1682
- * @return [::Array<Object>]
1683
- */
1684
- static VALUE w_array_eval(const VALUE self) {
1685
- UsaminValue *value = get_value(self);
1686
- check_array(value);
1687
- return eval_array(*(value->value), value->root_document);
1688
- }
1689
-
1690
-
1691
- /*
1692
- * Generate the JSON string from Ruby data structures.
1693
- *
1694
- * @overload generate(obj)
1695
- * @param [Object] obj an object to serialize
1696
- * @return [String]
1697
- */
1698
- static VALUE w_generate(const VALUE self, const VALUE value) {
1699
- rapidjson::StringBuffer buf;
1700
- rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
1701
- write(writer, value);
1702
- return new_utf8_str(buf.GetString(), buf.GetSize());
1703
- }
1704
-
1705
- /*
1706
- * Generate the prettified JSON string from Ruby data structures.
1707
- *
1708
- * @overload pretty_generate(obj, opts = {})
1709
- * @param [Object] obj an object to serialize
1710
- * @param [::Hash] opts options
1711
- * @option opts [String] :indent (' ') a string used to indent
1712
- * @option opts [Boolean] :single_line_array (false)
1713
- * @return [String]
1714
- */
1715
- static VALUE w_pretty_generate(const int argc, const VALUE *argv, const VALUE self) {
1716
- VALUE value, options;
1717
- rb_scan_args(argc, argv, "1:", &value, &options);
1718
- rapidjson::StringBuffer buf;
1719
- rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
1720
-
1721
- char indent_char = ' ';
1722
- unsigned int indent_count = 2;
1723
- if (argc > 1) {
1724
- VALUE v_indent = rb_hash_lookup(options, sym_indent);
1725
- if (RTEST(v_indent)) {
1726
- if (RB_FIXNUM_P(v_indent)) {
1727
- long l = FIX2LONG(v_indent);
1728
- indent_count = l > 0 ? static_cast<unsigned int>(l) : 0;
1729
- } else {
1730
- long vlen = RSTRING_LEN(v_indent);
1731
- if (vlen == 0) {
1732
- indent_count = 0;
1733
- } else {
1734
- const char *indent_str = RSTRING_PTR(v_indent);
1735
- switch (indent_str[0]) {
1736
- case ' ':
1737
- case '\t':
1738
- case '\r':
1739
- case '\n':
1740
- indent_char = indent_str[0];
1741
- break;
1742
- default:
1743
- rb_raise(rb_eUsaminError, ":indent must be a repetation of \" \", \"\\t\", \"\\r\" or \"\\n\".");
1744
- }
1745
- for (long i = 1; i < vlen; i++)
1746
- if (indent_str[0] != indent_str[i])
1747
- rb_raise(rb_eUsaminError, ":indent must be a repetation of \" \", \"\\t\", \"\\r\" or \"\\n\".");
1748
- indent_count = static_cast<unsigned int>(vlen);
1749
- }
1750
- }
1751
- }
1752
-
1753
- if (RTEST(rb_hash_lookup(options, sym_single_line_array)))
1754
- writer.SetFormatOptions(rapidjson::kFormatSingleLineArray);
1755
- }
1756
- writer.SetIndent(indent_char, indent_count);
1757
-
1758
- write(writer, value);
1759
- return new_utf8_str(buf.GetString(), buf.GetSize());
1760
- }
1761
-
1762
-
1763
- extern "C" void Init_usamin(void) {
19
+ extern "C" {
20
+ void Init_usamin() {
1764
21
  utf8 = rb_utf8_encoding();
1765
22
  utf8index = rb_enc_to_index(utf8);
1766
23
  utf8value = rb_enc_from_encoding(utf8);
1767
24
  sym_fast = rb_id2sym(rb_intern("fast"));
1768
25
  sym_indent = rb_id2sym(rb_intern("indent"));
26
+ sym_recursive = rb_id2sym(rb_intern("recursive"));
1769
27
  sym_single_line_array = rb_id2sym(rb_intern("single_line_array"));
28
+ sym_symbolize_names = rb_id2sym(rb_intern("symbolize_names"));
1770
29
  id_dig = rb_intern("dig");
1771
30
  id_to_s = rb_intern("to_s");
1772
31
 
1773
- VALUE rb_mUsamin = rb_define_module("Usamin");
32
+ rb_mUsamin = rb_define_module("Usamin");
1774
33
  rb_define_module_function(rb_mUsamin, "load", RUBY_METHOD_FUNC(w_load), -1);
1775
34
  rb_define_module_function(rb_mUsamin, "parse", RUBY_METHOD_FUNC(w_parse), -1);
1776
35
  rb_define_module_function(rb_mUsamin, "generate", RUBY_METHOD_FUNC(w_generate), 1);
@@ -1784,8 +43,8 @@ extern "C" void Init_usamin(void) {
1784
43
  rb_define_method(rb_cUsaminValue, "array?", RUBY_METHOD_FUNC(w_value_isarray), 0);
1785
44
  rb_define_method(rb_cUsaminValue, "hash?", RUBY_METHOD_FUNC(w_value_isobject), 0);
1786
45
  rb_define_method(rb_cUsaminValue, "object?", RUBY_METHOD_FUNC(w_value_isobject), 0);
1787
- rb_define_method(rb_cUsaminValue, "eval", RUBY_METHOD_FUNC(w_value_eval), 0);
1788
- rb_define_method(rb_cUsaminValue, "eval_r", RUBY_METHOD_FUNC(w_value_eval_r), 0);
46
+ rb_define_method(rb_cUsaminValue, "eval", RUBY_METHOD_FUNC(w_value_eval), -1);
47
+ rb_define_method(rb_cUsaminValue, "eval_r", RUBY_METHOD_FUNC(w_value_eval_r), -1);
1789
48
  rb_define_method(rb_cUsaminValue, "eql?", RUBY_METHOD_FUNC(w_value_eql), 1);
1790
49
  rb_define_method(rb_cUsaminValue, "frozen?", RUBY_METHOD_FUNC(w_value_isfrozen), 0);
1791
50
  rb_define_method(rb_cUsaminValue, "hash", RUBY_METHOD_FUNC(w_value_hash), 0);
@@ -1798,6 +57,7 @@ extern "C" void Init_usamin(void) {
1798
57
  rb_define_method(rb_cUsaminHash, "[]", RUBY_METHOD_FUNC(w_hash_operator_indexer), 1);
1799
58
  rb_define_method(rb_cUsaminHash, "assoc", RUBY_METHOD_FUNC(w_hash_assoc), 1);
1800
59
  rb_define_method(rb_cUsaminHash, "compact", RUBY_METHOD_FUNC(w_hash_compact), 0);
60
+ rb_define_method(rb_cUsaminHash, "deconstruct_keys", RUBY_METHOD_FUNC(w_hash_deconstruct_keys), 1);
1801
61
  rb_define_method(rb_cUsaminHash, "dig", RUBY_METHOD_FUNC(w_hash_dig), -1);
1802
62
  rb_define_method(rb_cUsaminHash, "each", RUBY_METHOD_FUNC(w_hash_each), 0);
1803
63
  rb_define_method(rb_cUsaminHash, "each_pair", RUBY_METHOD_FUNC(w_hash_each), 0);
@@ -1817,6 +77,7 @@ extern "C" void Init_usamin(void) {
1817
77
  rb_define_method(rb_cUsaminHash, "index", RUBY_METHOD_FUNC(w_hash_key), 1);
1818
78
  rb_define_method(rb_cUsaminHash, "inspect", RUBY_METHOD_FUNC(w_hash_inspect), 0);
1819
79
  rb_define_method(rb_cUsaminHash, "to_s", RUBY_METHOD_FUNC(w_hash_inspect), 0);
80
+ rb_define_method(rb_cUsaminHash, "invert", RUBY_METHOD_FUNC(w_hash_invert), 0);
1820
81
  rb_define_method(rb_cUsaminHash, "keys", RUBY_METHOD_FUNC(w_hash_keys), 0);
1821
82
  rb_define_method(rb_cUsaminHash, "length", RUBY_METHOD_FUNC(w_hash_length), 0);
1822
83
  rb_define_method(rb_cUsaminHash, "size", RUBY_METHOD_FUNC(w_hash_length), 0);
@@ -1826,6 +87,7 @@ extern "C" void Init_usamin(void) {
1826
87
  rb_define_method(rb_cUsaminHash, "select", RUBY_METHOD_FUNC(w_hash_select), 0);
1827
88
  rb_define_method(rb_cUsaminHash, "slice", RUBY_METHOD_FUNC(w_hash_slice), -1);
1828
89
  rb_define_method(rb_cUsaminHash, "to_hash", RUBY_METHOD_FUNC(w_hash_eval), 0);
90
+ rb_define_method(rb_cUsaminHash, "to_proc", RUBY_METHOD_FUNC(w_hash_to_proc), 0);
1829
91
  rb_define_method(rb_cUsaminHash, "transform_keys", RUBY_METHOD_FUNC(w_hash_transform_keys), 0);
1830
92
  rb_define_method(rb_cUsaminHash, "transform_values", RUBY_METHOD_FUNC(w_hash_transform_values), 0);
1831
93
  rb_define_method(rb_cUsaminHash, "values", RUBY_METHOD_FUNC(w_hash_values), 0);
@@ -1838,27 +100,28 @@ extern "C" void Init_usamin(void) {
1838
100
  rb_define_alloc_func(rb_cUsaminArray, usamin_alloc);
1839
101
  rb_undef_method(rb_cUsaminArray, "initialize");
1840
102
  rb_define_method(rb_cUsaminArray, "[]", RUBY_METHOD_FUNC(w_array_operator_indexer), -1);
103
+ rb_define_method(rb_cUsaminArray, "slice", RUBY_METHOD_FUNC(w_array_operator_indexer), -1);
1841
104
  rb_define_method(rb_cUsaminArray, "at", RUBY_METHOD_FUNC(w_array_at), 1);
1842
105
  rb_define_method(rb_cUsaminArray, "compact", RUBY_METHOD_FUNC(w_array_compact), 0);
1843
106
  rb_define_method(rb_cUsaminArray, "dig", RUBY_METHOD_FUNC(w_array_dig), -1);
107
+ rb_define_method(rb_cUsaminArray, "deconstruct", RUBY_METHOD_FUNC(w_array_eval), 0);
1844
108
  rb_define_method(rb_cUsaminArray, "each", RUBY_METHOD_FUNC(w_array_each), 0);
1845
109
  rb_define_method(rb_cUsaminArray, "each_index", RUBY_METHOD_FUNC(w_array_each_index), 0);
1846
110
  rb_define_method(rb_cUsaminArray, "empty?", RUBY_METHOD_FUNC(w_array_isempty), 0);
1847
111
  rb_define_method(rb_cUsaminArray, "fetch", RUBY_METHOD_FUNC(w_array_fetch), -1);
1848
112
  rb_define_method(rb_cUsaminArray, "find_index", RUBY_METHOD_FUNC(w_array_find_index), -1);
1849
- rb_define_method(rb_cUsaminArray, "flatten", RUBY_METHOD_FUNC(w_array_flatten), -1);
1850
- rb_define_method(rb_cUsaminArray, "index", RUBY_METHOD_FUNC(w_array_index), -1);
113
+ rb_define_method(rb_cUsaminArray, "index", RUBY_METHOD_FUNC(w_array_find_index), -1);
1851
114
  rb_define_method(rb_cUsaminArray, "first", RUBY_METHOD_FUNC(w_array_first), -1);
115
+ rb_define_method(rb_cUsaminArray, "flatten", RUBY_METHOD_FUNC(w_array_flatten), -1);
1852
116
  rb_define_method(rb_cUsaminArray, "include?", RUBY_METHOD_FUNC(w_array_include), 1);
1853
117
  rb_define_method(rb_cUsaminArray, "inspect", RUBY_METHOD_FUNC(w_array_inspect), 0);
1854
118
  rb_define_method(rb_cUsaminArray, "to_s", RUBY_METHOD_FUNC(w_array_inspect), 0);
1855
119
  rb_define_method(rb_cUsaminArray, "last", RUBY_METHOD_FUNC(w_array_last), -1);
1856
120
  rb_define_method(rb_cUsaminArray, "length", RUBY_METHOD_FUNC(w_array_length), 0);
121
+ rb_define_method(rb_cUsaminArray, "size", RUBY_METHOD_FUNC(w_array_length), 0);
1857
122
  rb_define_method(rb_cUsaminArray, "reverse", RUBY_METHOD_FUNC(w_array_reverse), 0);
1858
123
  rb_define_method(rb_cUsaminArray, "rindex", RUBY_METHOD_FUNC(w_array_rindex), -1);
1859
124
  rb_define_method(rb_cUsaminArray, "rotate", RUBY_METHOD_FUNC(w_array_rotate), -1);
1860
- rb_define_method(rb_cUsaminArray, "size", RUBY_METHOD_FUNC(w_array_length), 0);
1861
- rb_define_method(rb_cUsaminArray, "slice", RUBY_METHOD_FUNC(w_array_slice), -1);
1862
125
  rb_define_method(rb_cUsaminArray, "to_ary", RUBY_METHOD_FUNC(w_array_eval), 0);
1863
126
  rb_define_method(rb_cUsaminArray, "marshal_dump", RUBY_METHOD_FUNC(w_value_marshal_dump), 0);
1864
127
  rb_define_method(rb_cUsaminArray, "marshal_load", RUBY_METHOD_FUNC(w_value_marshal_load), 1);
@@ -1866,3 +129,4 @@ extern "C" void Init_usamin(void) {
1866
129
  rb_eUsaminError = rb_define_class_under(rb_mUsamin, "UsaminError", rb_eStandardError);
1867
130
  rb_eParserError = rb_define_class_under(rb_mUsamin, "ParserError", rb_eUsaminError);
1868
131
  }
132
+ }