usamin 7.7.6 → 7.7.11

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,328 @@
1
+ #include "rb270_fix.hpp"
2
+ #include "default_parse_flags.hpp"
3
+ #include <rapidjson/error/en.h>
4
+ #include <rapidjson/reader.h>
5
+ #include <rapidjson/writer.h>
6
+ #include <ruby.h>
7
+ #include "generator.hpp"
8
+ #include "usamin_value.hpp"
9
+ #include "parser_helper.hpp"
10
+
11
+ static void usamin_free(void *p) {
12
+ if (!p)
13
+ return;
14
+ UsaminValue **ptr = (UsaminValue **)p;
15
+ if (*ptr)
16
+ delete *ptr;
17
+ ruby_xfree(p);
18
+ }
19
+
20
+ static void usamin_mark(void *p) {
21
+ if (!p)
22
+ return;
23
+ UsaminValue **ptr = (UsaminValue **)p;
24
+ if (*ptr && !((*ptr)->free_flag))
25
+ rb_gc_mark((*ptr)->root_document);
26
+ }
27
+
28
+ static size_t usamin_size(const void *p) {
29
+ if (!p)
30
+ return 0;
31
+ UsaminValue **ptr = (UsaminValue **)p;
32
+ size_t s = 0;
33
+ if (*ptr) {
34
+ s += sizeof(UsaminValue);
35
+ if ((*ptr)->free_flag)
36
+ s += ((RubynizedDocument *)(*ptr)->value)->GetAllocator().Capacity() +
37
+ ((RubynizedDocument *)(*ptr)->value)->GetStackCapacity();
38
+ }
39
+ return s;
40
+ }
41
+
42
+ static const rb_data_type_t rb_usamin_value_type = {
43
+ "UsaminValue", {usamin_mark, usamin_free, usamin_size}, nullptr, nullptr, RUBY_TYPED_FREE_IMMEDIATELY};
44
+
45
+ VALUE usamin_alloc(const VALUE klass) {
46
+ UsaminValue **ptr;
47
+ VALUE ret = TypedData_Make_Struct(klass, UsaminValue *, &rb_usamin_value_type, ptr);
48
+ *ptr = nullptr;
49
+ return ret;
50
+ }
51
+
52
+ UsaminValue *get_value(VALUE value) {
53
+ UsaminValue **ptr;
54
+ TypedData_Get_Struct(value, UsaminValue *, &rb_usamin_value_type, ptr);
55
+ return *ptr;
56
+ }
57
+
58
+ void set_value(VALUE value, UsaminValue *usamin) {
59
+ UsaminValue **ptr;
60
+ TypedData_Get_Struct(value, UsaminValue *, &rb_usamin_value_type, ptr);
61
+ *ptr = usamin;
62
+ }
63
+
64
+ static bool eql_array(RubynizedValue &, RubynizedValue &);
65
+ static bool eql_object(RubynizedValue &, RubynizedValue &);
66
+
67
+ static bool eql_value(RubynizedValue &self, RubynizedValue &other) {
68
+ if (self.GetType() != other.GetType())
69
+ return false;
70
+ switch (self.GetType()) {
71
+ case rapidjson::kObjectType:
72
+ return eql_object(self, other);
73
+ case rapidjson::kArrayType:
74
+ return eql_array(self, other);
75
+ case rapidjson::kStringType:
76
+ return self == other;
77
+ case rapidjson::kNumberType:
78
+ return self == other && self.IsInt() == other.IsInt() && self.IsUint() == other.IsUint() &&
79
+ self.IsInt64() == other.IsInt64() && self.IsUint64() == other.IsUint64() &&
80
+ self.IsDouble() == other.IsDouble();
81
+ default:
82
+ return true;
83
+ }
84
+ }
85
+
86
+ static bool eql_object(RubynizedValue &self, RubynizedValue &other) {
87
+ if (self.MemberCount() != other.MemberCount())
88
+ return false;
89
+ for (auto &m : self.GetObject()) {
90
+ if (!other.HasMember(m.name))
91
+ return false;
92
+ if (!eql_value(m.value, other[m.name]))
93
+ return false;
94
+ }
95
+ return true;
96
+ }
97
+
98
+ static bool eql_array(RubynizedValue &self, RubynizedValue &other) {
99
+ if (self.Size() != other.Size())
100
+ return false;
101
+ for (rapidjson::SizeType i = 0; i < self.Size(); i++) {
102
+ if (!eql_value(self[i], other[i]))
103
+ return false;
104
+ }
105
+ return true;
106
+ }
107
+
108
+ /*
109
+ * Returns whether the value is equals to the other value.
110
+ *
111
+ * @return [Boolean]
112
+ */
113
+ VALUE w_value_equal(const VALUE self, const VALUE other) {
114
+ extern VALUE rb_cUsaminValue;
115
+ if (self == other)
116
+ return Qtrue;
117
+ UsaminValue *value_self = get_value(self);
118
+ check_value(value_self);
119
+ if (rb_obj_is_kind_of(other, rb_cUsaminValue)) {
120
+ UsaminValue *value_other = get_value(other);
121
+ check_value(value_other);
122
+ return value_self->value->operator==(*value_other->value) ? Qtrue : Qfalse;
123
+ } else if (value_self->value->IsArray() && RB_TYPE_P(other, T_ARRAY)) {
124
+ if (value_self->value->Size() != RARRAY_LEN(other))
125
+ return Qfalse;
126
+ return rb_equal(other, eval_array(*value_self->value, value_self->root_document));
127
+ } else if (value_self->value->IsObject() && RB_TYPE_P(other, T_HASH)) {
128
+ if (value_self->value->MemberCount() != RHASH_SIZE(other))
129
+ return Qfalse;
130
+ return rb_equal(other, eval_object(*value_self->value, value_self->root_document, 0));
131
+ }
132
+ return Qfalse;
133
+ }
134
+
135
+ /*
136
+ * Returns whether the value is array.
137
+ */
138
+ VALUE w_value_isarray(const VALUE self) {
139
+ UsaminValue *value = get_value(self);
140
+ check_value(value);
141
+ return value->value->IsArray() ? Qtrue : Qfalse;
142
+ }
143
+
144
+ /*
145
+ * Returns whether the value is object.
146
+ */
147
+ VALUE w_value_isobject(const VALUE self) {
148
+ UsaminValue *value = get_value(self);
149
+ check_value(value);
150
+ return value->value->IsObject() ? Qtrue : Qfalse;
151
+ }
152
+
153
+ /*
154
+ * Convert to Ruby data structures.
155
+ *
156
+ * @overload eval(opts = {})
157
+ * @option opts :symbolize_names symbolize keys of all Hash objects
158
+ * @return [Object]
159
+ */
160
+ VALUE w_value_eval(const int argc, const VALUE *argv, const VALUE self) {
161
+ extern VALUE sym_symbolize_names;
162
+ VALUE options;
163
+ rb_scan_args(argc, argv, ":", &options);
164
+ UsaminValue *value = get_value(self);
165
+ check_value(value);
166
+ if (value->value->IsObject()) {
167
+ return eval_object(*(value->value), value->root_document, test_option(options, sym_symbolize_names));
168
+ } else if (value->value->IsArray()) {
169
+ return eval_array(*(value->value), value->root_document);
170
+ } else {
171
+ return Qnil;
172
+ }
173
+ }
174
+
175
+ /*
176
+ * Convert to Ruby data structures recursively.
177
+ *
178
+ * @overload eval_r(opts = {})
179
+ * @option opts :symbolize_names symbolize keys of all Hash objects
180
+ * @return [Object]
181
+ */
182
+ VALUE w_value_eval_r(const int argc, const VALUE *argv, const VALUE self) {
183
+ extern VALUE sym_symbolize_names;
184
+ VALUE options;
185
+ rb_scan_args(argc, argv, ":", &options);
186
+ UsaminValue *value = get_value(self);
187
+ check_value(value);
188
+ return eval_r(*(value->value), test_option(options, sym_symbolize_names));
189
+ }
190
+
191
+ /*
192
+ * @return [Boolean]
193
+ */
194
+ VALUE w_value_eql(const VALUE self, const VALUE other) {
195
+ extern VALUE rb_cUsaminValue;
196
+ if (self == other)
197
+ return Qtrue;
198
+ if (!rb_obj_is_kind_of(other, rb_cUsaminValue))
199
+ return Qfalse;
200
+ UsaminValue *value_self = get_value(self);
201
+ UsaminValue *value_other = get_value(other);
202
+ check_value(value_self);
203
+ check_value(value_other);
204
+ return eql_value(*value_self->value, *value_other->value) ? Qtrue : Qfalse;
205
+ }
206
+
207
+ /*
208
+ * Always true.
209
+ */
210
+ VALUE w_value_isfrozen(const VALUE) {
211
+ return Qtrue;
212
+ }
213
+
214
+ static st_index_t hash_object(RubynizedValue &value);
215
+ static st_index_t hash_array(RubynizedValue &value);
216
+
217
+ static st_index_t hash_value(RubynizedValue &value) {
218
+ auto type = value.GetType();
219
+ st_index_t h = rb_hash_start(type);
220
+ rb_hash_uint(h, reinterpret_cast<st_index_t>(hash_value));
221
+ switch (type) {
222
+ case rapidjson::kNullType:
223
+ h = rb_hash_uint(h, NUM2LONG(rb_hash(Qnil)));
224
+ break;
225
+ case rapidjson::kFalseType:
226
+ h = rb_hash_uint(h, NUM2LONG(rb_hash(Qfalse)));
227
+ break;
228
+ case rapidjson::kTrueType:
229
+ h = rb_hash_uint(h, NUM2LONG(rb_hash(Qtrue)));
230
+ break;
231
+ case rapidjson::kObjectType:
232
+ h = rb_hash_uint(h, hash_object(value));
233
+ break;
234
+ case rapidjson::kArrayType:
235
+ h = rb_hash_uint(h, hash_array(value));
236
+ break;
237
+ case rapidjson::kStringType:
238
+ h = rb_hash_uint(h, rb_str_hash(eval_str(value)));
239
+ break;
240
+ case rapidjson::kNumberType:
241
+ if (value.IsInt())
242
+ h = rb_hash_uint(h, 0x770);
243
+ if (value.IsUint())
244
+ h = rb_hash_uint(h, 0x771);
245
+ if (value.IsInt64())
246
+ h = rb_hash_uint(h, 0x772);
247
+ if (value.IsUint64())
248
+ h = rb_hash_uint(h, 0x773);
249
+ if (value.IsDouble())
250
+ h = rb_hash_uint(h, 0x774);
251
+ h = rb_hash_uint(h, NUM2LONG(rb_hash(eval_num(value))));
252
+ }
253
+ return rb_hash_end(h);
254
+ }
255
+
256
+ static st_index_t hash_object(RubynizedValue &value) {
257
+ st_index_t h = rb_hash_start(value.MemberCount());
258
+ h = rb_hash_uint(h, reinterpret_cast<st_index_t>(hash_object));
259
+ for (auto &m : value.GetObject()) {
260
+ h = rb_hash_uint(h, rb_str_hash(eval_str(m.name)));
261
+ h = rb_hash_uint(h, hash_value(m.value));
262
+ }
263
+ return rb_hash_end(h);
264
+ }
265
+
266
+ static st_index_t hash_array(RubynizedValue &value) {
267
+ st_index_t h = rb_hash_start(value.Size());
268
+ h = rb_hash_uint(h, reinterpret_cast<st_index_t>(hash_array));
269
+ for (auto &v : value.GetArray())
270
+ h = rb_hash_uint(h, hash_value(v));
271
+ return rb_hash_end(h);
272
+ }
273
+
274
+ /*
275
+ * @return [Integer]
276
+ */
277
+ VALUE w_value_hash(const VALUE self) {
278
+ UsaminValue *value = get_value(self);
279
+ check_value(value);
280
+ return ST2FIX(hash_value(*value->value));
281
+ }
282
+
283
+ /*
284
+ * Returns root object.
285
+ *
286
+ * @return [UsaminValue]
287
+ */
288
+ VALUE w_value_root(const VALUE self) {
289
+ UsaminValue *value = get_value(self);
290
+ check_value(value);
291
+ return value->root_document;
292
+ }
293
+
294
+ /*
295
+ * Dumps data in JSON.
296
+ *
297
+ * @return [String]
298
+ */
299
+ VALUE w_value_marshal_dump(const VALUE self) {
300
+ extern VALUE rb_mUsamin;
301
+ return w_generate(rb_mUsamin, self);
302
+ }
303
+
304
+ /*
305
+ * Loads marshal data.
306
+ */
307
+ VALUE w_value_marshal_load(const VALUE self, const VALUE source) {
308
+ extern VALUE rb_cUsaminHash, rb_cUsaminArray, rb_eUsaminError, rb_eParserError;
309
+ Check_Type(source, T_STRING);
310
+ RubynizedDocument *doc = new RubynizedDocument();
311
+ rapidjson::ParseResult result =
312
+ doc->Parse<RAPIDJSON_PARSE_FLAGS_FOR_MARSHAL>(RSTRING_PTR(source), RSTRING_LEN(source));
313
+ if (!result) {
314
+ delete doc;
315
+ rb_raise(rb_eParserError, "%s Offset: %lu", GetParseError_En(result.Code()), result.Offset());
316
+ }
317
+ if ((rb_obj_is_instance_of(self, rb_cUsaminHash) && doc->IsObject()) ||
318
+ (rb_obj_is_instance_of(self, rb_cUsaminArray) && doc->IsArray())) {
319
+ UsaminValue *value = new UsaminValue(doc, true);
320
+ set_value(self, value);
321
+ value->root_document = self;
322
+ } else {
323
+ auto type = doc->GetType();
324
+ delete doc;
325
+ rb_raise(rb_eUsaminError, "type mismatch in marshal load: %d", type);
326
+ }
327
+ return Qnil;
328
+ }
@@ -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,1343 +1,54 @@
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
-
19
13
  rb_encoding *utf8;
20
14
  int utf8index;
21
- ID id_to_s;
22
- VALUE rb_cUsaminValue, rb_cUsaminHash, rb_cUsaminArray, rb_eUsaminError, rb_eParserError;
23
- VALUE utf8value, sym_fast, sym_indent, sym_single_line_array;
24
-
25
- class UsaminValue {
26
- public:
27
- rapidjson::Value *value;
28
- VALUE root_document;
29
- bool free_flag;
30
-
31
- UsaminValue(rapidjson::Value *value = nullptr, const bool free_flag = false, const VALUE root_document = Qnil);
32
- ~UsaminValue();
33
- };
34
-
35
- static inline VALUE get_utf8_str(VALUE str) {
36
- Check_Type(str, T_STRING);
37
- int encoding = rb_enc_get_index(str);
38
- if (encoding == utf8index || rb_enc_compatible(str, utf8value) == utf8)
39
- return str;
40
- else
41
- return rb_str_conv_enc(str, rb_enc_from_index(encoding), utf8);
42
- }
43
-
44
- static inline VALUE new_utf8_str(const char* cstr, const long len) {
45
- VALUE ret = rb_str_new(cstr, len);
46
- rb_enc_set_index(ret, utf8index);
47
- return ret;
48
- }
49
-
50
- static inline bool str_compare(const char* str1, const long len1, const char* str2, const long len2) {
51
- if (len1 != len2 || len1 < 0)
52
- return false;
53
- return memcmp(str1, str2, len1) == 0;
54
- }
55
-
56
- static inline bool str_compare_xx(VALUE str1, const rapidjson::Value &str2) {
57
- if (RB_TYPE_P(str1, T_STRING))
58
- str1 = get_utf8_str(str1);
59
- else if (SYMBOL_P(str1))
60
- str1 = get_utf8_str(rb_sym_to_s(str1));
61
- else
62
- str1 = get_utf8_str(StringValue(str1));
63
- return str_compare(RSTRING_PTR(str1), RSTRING_LEN(str1), str2.GetString(), str2.GetStringLength());
64
- }
65
-
66
- static inline void check_value(UsaminValue *ptr) {
67
- if (!ptr || !ptr->value)
68
- rb_raise(rb_eUsaminError, "Null Reference.");
69
- }
70
-
71
- static inline void check_object(UsaminValue *ptr) {
72
- check_value(ptr);
73
- if (!ptr->value->IsObject())
74
- rb_raise(rb_eUsaminError, "Value is not an object.");
75
- }
76
-
77
- static inline void check_array(UsaminValue *ptr) {
78
- check_value(ptr);
79
- if (!ptr->value->IsArray())
80
- rb_raise(rb_eUsaminError, "Value is not an array.");
81
- }
82
-
83
-
84
- static VALUE usamin_free(UsaminValue **ptr) {
85
- if (*ptr)
86
- delete *ptr;
87
- ruby_xfree(ptr);
88
- return Qnil;
89
- }
90
-
91
- static VALUE usamin_mark(UsaminValue **ptr) {
92
- if (*ptr && (*ptr)->root_document != Qnil)
93
- rb_gc_mark((*ptr)->root_document);
94
- return Qnil;
95
- }
96
-
97
- static VALUE usamin_alloc(const VALUE klass) {
98
- UsaminValue** ptr = (UsaminValue**)ruby_xmalloc(sizeof(UsaminValue*));
99
- *ptr = nullptr;
100
- return Data_Wrap_Struct(klass, usamin_mark, usamin_free, ptr);
101
- }
102
-
103
-
104
- static inline UsaminValue* get_value(VALUE value) {
105
- UsaminValue** ptr;
106
- Data_Get_Struct(value, UsaminValue*, ptr);
107
- return *ptr;
108
- }
109
-
110
- static inline void set_value(VALUE value, UsaminValue *usamin) {
111
- UsaminValue **ptr;
112
- Data_Get_Struct(value, UsaminValue*, ptr);
113
- *ptr = usamin;
114
- }
115
-
116
- static inline VALUE make_hash(UsaminValue *value) {
117
- VALUE ret = rb_obj_alloc(rb_cUsaminHash);
118
- set_value(ret, value);
119
- return ret;
120
- }
121
-
122
- static inline VALUE make_array(UsaminValue *value) {
123
- VALUE ret = rb_obj_alloc(rb_cUsaminArray);
124
- set_value(ret, value);
125
- return ret;
126
- }
127
-
128
- static inline rapidjson::ParseResult parse(rapidjson::Document &doc, const VALUE str, bool fast = false) {
129
- volatile VALUE v = get_utf8_str(str);
130
- return fast ? doc.Parse<kParseFastFlags>(RSTRING_PTR(v), RSTRING_LEN(v)) : doc.Parse(RSTRING_PTR(v), RSTRING_LEN(v));
131
- }
132
-
133
-
134
- static inline VALUE eval_num(rapidjson::Value&);
135
- static inline VALUE eval_str(rapidjson::Value&);
136
- static inline VALUE eval_object_r(rapidjson::Value&);
137
- static inline VALUE eval_array_r(rapidjson::Value&);
138
-
139
- static VALUE eval(rapidjson::Value &value, VALUE root_document) {
140
- switch (value.GetType()) {
141
- case rapidjson::kObjectType:
142
- return make_hash(new UsaminValue(&value, false, root_document));
143
- case rapidjson::kArrayType:
144
- return make_array(new UsaminValue(&value, false, root_document));
145
- case rapidjson::kNullType:
146
- return Qnil;
147
- case rapidjson::kFalseType:
148
- return Qfalse;
149
- case rapidjson::kTrueType:
150
- return Qtrue;
151
- case rapidjson::kNumberType:
152
- return eval_num(value);
153
- case rapidjson::kStringType:
154
- return eval_str(value);
155
- default:
156
- rb_raise(rb_eUsaminError, "Unknown Value Type: %d", value.GetType());
157
- return Qnil;
158
- }
159
- }
160
-
161
- static VALUE eval_r(rapidjson::Value &value) {
162
- switch (value.GetType()) {
163
- case rapidjson::kObjectType:
164
- return eval_object_r(value);
165
- case rapidjson::kArrayType:
166
- return eval_array_r(value);
167
- case rapidjson::kNullType:
168
- return Qnil;
169
- case rapidjson::kFalseType:
170
- return Qfalse;
171
- case rapidjson::kTrueType:
172
- return Qtrue;
173
- case rapidjson::kNumberType:
174
- return eval_num(value);
175
- case rapidjson::kStringType:
176
- return eval_str(value);
177
- default:
178
- rb_raise(rb_eUsaminError, "Unknown Value Type: %d", value.GetType());
179
- return Qnil;
180
- }
181
- }
182
-
183
- static inline VALUE eval_num(rapidjson::Value &value) {
184
- if (value.IsInt())
185
- return INT2FIX(value.GetInt());
186
- else if (value.IsUint())
187
- return UINT2NUM(value.GetUint());
188
- else if (value.IsInt64())
189
- return LL2NUM(value.GetInt64());
190
- else if (value.IsUint64())
191
- return ULL2NUM(value.GetUint64());
192
- else
193
- return DBL2NUM(value.GetDouble());
194
- }
195
-
196
- static inline VALUE eval_str(rapidjson::Value &value) {
197
- return new_utf8_str(value.GetString(), value.GetStringLength());
198
- }
199
-
200
- static inline VALUE eval_object(rapidjson::Value &value, const VALUE root_document) {
201
- VALUE ret = rb_hash_new();
202
- for (auto &m : value.GetObject())
203
- rb_hash_aset(ret, eval_str(m.name), eval(m.value, root_document));
204
- return ret;
205
- }
206
-
207
- static inline VALUE eval_object_r(rapidjson::Value &value) {
208
- VALUE ret = rb_hash_new();
209
- for (auto &m : value.GetObject())
210
- rb_hash_aset(ret, eval_str(m.name), eval_r(m.value));
211
- return ret;
212
- }
213
-
214
- static inline VALUE eval_array(rapidjson::Value &value, const VALUE root_document) {
215
- VALUE ret = rb_ary_new2(value.Size());
216
- for (auto &v : value.GetArray())
217
- rb_ary_push(ret, eval(v, root_document));
218
- return ret;
219
- }
220
-
221
- static inline VALUE eval_array_r(rapidjson::Value &value) {
222
- VALUE ret = rb_ary_new2(value.Size());
223
- for (auto &v : value.GetArray())
224
- rb_ary_push(ret, eval_r(v));
225
- return ret;
226
- }
227
-
228
-
229
- template <class Writer> static inline void write_str(Writer&, const VALUE);
230
- template <class Writer> static inline void write_hash(Writer&, const VALUE);
231
- template <class Writer> static inline void write_array(Writer&, const VALUE);
232
- template <class Writer> static inline void write_struct(Writer&, const VALUE);
233
- template <class Writer> static inline void write_usamin(Writer&, const VALUE);
234
- template <class Writer> static inline void write_to_s(Writer&, const VALUE);
235
-
236
- template <class Writer> static void write(Writer &writer, const VALUE value) {
237
- switch (TYPE(value)) {
238
- case RUBY_T_NONE:
239
- case RUBY_T_NIL:
240
- case RUBY_T_UNDEF:
241
- writer.Null();
242
- break;
243
- case RUBY_T_TRUE:
244
- writer.Bool(true);
245
- break;
246
- case RUBY_T_FALSE:
247
- writer.Bool(false);
248
- break;
249
- case RUBY_T_FIXNUM:
250
- writer.Int64(FIX2LONG(value));
251
- break;
252
- case RUBY_T_FLOAT:
253
- case RUBY_T_RATIONAL:
254
- writer.Double(NUM2DBL(value));
255
- break;
256
- case RUBY_T_STRING:
257
- write_str(writer, value);
258
- break;
259
- case RUBY_T_ARRAY:
260
- write_array(writer, value);
261
- break;
262
- case RUBY_T_HASH:
263
- write_hash(writer, value);
264
- break;
265
- case RUBY_T_STRUCT:
266
- write_struct(writer, value);
267
- break;
268
- case RUBY_T_BIGNUM:
269
- {
270
- VALUE v = rb_big2str(value, 10);
271
- writer.RawValue(RSTRING_PTR(v), static_cast<unsigned int>(RSTRING_LEN(v)), rapidjson::kNumberType);
272
- }
273
- break;
274
- default:
275
- if (rb_obj_is_kind_of(value, rb_cUsaminValue))
276
- write_usamin(writer, value);
277
- else
278
- write_to_s(writer, value);
279
- break;
280
- }
281
- }
282
-
283
- template <class Writer> static inline void write_str(Writer &writer, const VALUE value) {
284
- VALUE v = get_utf8_str(value);
285
- writer.String(RSTRING_PTR(v), static_cast<unsigned int>(RSTRING_LEN(v)));
286
- }
287
-
288
- template <class Writer> static inline void write_key_str(Writer &writer, const VALUE value) {
289
- VALUE v = get_utf8_str(value);
290
- writer.Key(RSTRING_PTR(v), static_cast<unsigned int>(RSTRING_LEN(v)));
291
- }
292
-
293
- template <class Writer> static inline void write_key_to_s(Writer &writer, const VALUE value) {
294
- write_key_str(writer, rb_funcall(value, id_to_s, 0));
295
- }
296
-
297
- template <class Writer> static inline int write_hash_each(const VALUE key, const VALUE value, Writer *writer) {
298
- if (RB_TYPE_P(key, T_STRING))
299
- write_key_str(*writer, key);
300
- else if (RB_TYPE_P(key, T_SYMBOL))
301
- write_key_str(*writer, rb_sym_to_s(key));
302
- else
303
- write_key_to_s(*writer, key);
304
- write(*writer, value);
305
- return ST_CONTINUE;
306
- }
307
-
308
- template <class Writer> static inline void write_hash(Writer &writer, const VALUE hash) {
309
- writer.StartObject();
310
- rb_hash_foreach(hash, (int (*)(ANYARGS))write_hash_each<Writer>, reinterpret_cast<VALUE>((&writer)));
311
- writer.EndObject();
312
- }
313
-
314
- template <class Writer> static inline void write_array(Writer &writer, const VALUE value) {
315
- writer.StartArray();
316
- const VALUE *ptr = rb_array_const_ptr(value);
317
- for (long i = 0; i < rb_array_len(value); i++, ptr++)
318
- write(writer, *ptr);
319
- writer.EndArray();
320
- }
321
-
322
- template <class Writer> static inline void write_struct(Writer &writer, const VALUE value) {
323
- writer.StartObject();
324
- VALUE members = rb_struct_members(value);
325
- const VALUE *ptr = rb_array_const_ptr(members);
326
- for (long i = 0; i < rb_array_len(members); i++, ptr++) {
327
- if (RB_TYPE_P(*ptr, T_SYMBOL))
328
- write_key_str(writer, rb_sym_to_s(*ptr));
329
- else if (RB_TYPE_P(*ptr, T_STRING))
330
- write_key_str(writer, *ptr);
331
- else
332
- write_key_to_s(writer, *ptr);
333
- write(writer, rb_struct_aref(value, *ptr));
334
- }
335
- writer.EndObject();
336
- }
337
-
338
- template <class Writer> static void write_value(Writer &writer, rapidjson::Value &value) {
339
- switch (value.GetType()) {
340
- case rapidjson::kObjectType:
341
- writer.StartObject();
342
- for (auto &m : value.GetObject()) {
343
- writer.Key(m.name.GetString(), m.name.GetStringLength());
344
- write_value(writer, m.value);
345
- }
346
- writer.EndObject();
347
- break;
348
- case rapidjson::kArrayType:
349
- writer.StartArray();
350
- for (auto &v : value.GetArray())
351
- write_value(writer, v);
352
- writer.EndArray();
353
- break;
354
- case rapidjson::kNullType:
355
- writer.Null();
356
- break;
357
- case rapidjson::kFalseType:
358
- writer.Bool(false);
359
- break;
360
- case rapidjson::kTrueType:
361
- writer.Bool(true);
362
- break;
363
- case rapidjson::kNumberType:
364
- if (value.IsInt())
365
- writer.Int(value.GetInt());
366
- else if (value.IsUint())
367
- writer.Uint(value.GetUint());
368
- else if (value.IsInt64())
369
- writer.Int64(value.GetInt64());
370
- else if (value.IsUint64())
371
- writer.Uint64(value.GetUint64());
372
- else
373
- writer.Double(value.GetDouble());
374
- break;
375
- case rapidjson::kStringType:
376
- writer.String(value.GetString(), value.GetStringLength());
377
- break;
378
- default:
379
- rb_raise(rb_eUsaminError, "Unknown Value Type: %d", value.GetType());
380
- }
381
- }
382
-
383
- template <class Writer> static inline void write_usamin(Writer &writer, const VALUE self) {
384
- UsaminValue *value = get_value(self);
385
- check_value(value);
386
- write_value(writer, *(value->value));
387
- }
388
-
389
- template <class Writer> static inline void write_to_s(Writer &writer, const VALUE value) {
390
- write_str(writer, rb_funcall(value, id_to_s, 0));
391
- }
392
-
393
-
394
- UsaminValue::UsaminValue(rapidjson::Value *value, const bool free_flag, const VALUE root_document) {
395
- this->value = value;
396
- this->free_flag = free_flag;
397
- this->root_document = root_document;
398
- }
399
-
400
- UsaminValue::~UsaminValue() {
401
- if (value && free_flag)
402
- delete (rapidjson::Document*)value;
403
- }
404
-
405
- /*
406
- * Parse the JSON string into UsaminValue.
407
- * If the document root is not an object or an array, the same value as {#parse} will be returned.
408
- *
409
- * @overload load(source, opts = {})
410
- * @param [String] source JSON string to parse
411
- * @param [::Hash] opts options
412
- * @option opts :fast fast mode (but not precise)
413
- * @return [Object]
414
- */
415
- static VALUE w_load(const int argc, const VALUE *argv, const VALUE self) {
416
- VALUE source, options;
417
- rb_scan_args(argc, argv, "1:", &source, &options);
418
- rapidjson::Document *doc = new rapidjson::Document;
419
- auto result = parse(*doc, source, argc > 1 && RTEST(rb_hash_lookup(options, sym_fast)));
420
- if (!result) {
421
- delete doc;
422
- rb_raise(rb_eParserError, "%s Offset: %lu", GetParseError_En(result.Code()), result.Offset());
423
- }
424
-
425
- VALUE ret;
426
- switch (doc->GetType()) {
427
- case rapidjson::kObjectType:
428
- return make_hash(new UsaminValue(doc, true));
429
- case rapidjson::kArrayType:
430
- return make_array(new UsaminValue(doc, true));
431
- case rapidjson::kNullType:
432
- delete doc;
433
- return Qnil;
434
- case rapidjson::kFalseType:
435
- delete doc;
436
- return Qfalse;
437
- case rapidjson::kTrueType:
438
- delete doc;
439
- return Qtrue;
440
- case rapidjson::kNumberType:
441
- ret = eval_num(*doc);
442
- delete doc;
443
- return ret;
444
- case rapidjson::kStringType:
445
- ret = eval_str(*doc);
446
- delete doc;
447
- return ret;
448
- default:
449
- rb_raise(rb_eUsaminError, "Unknown Value Type: %d", doc->GetType());
450
- return Qnil;
451
- }
452
- }
453
-
454
- /*
455
- * Parse the JSON string into Ruby data structures.
456
- *
457
- * @overload parse(source, opts = {})
458
- * @param [String] source a JSON string to parse
459
- * @param [::Hash] opts options
460
- * @option opts :fast fast mode (but not precise)
461
- * @return [Object]
462
- */
463
- static VALUE w_parse(const int argc, const VALUE *argv, const VALUE self) {
464
- VALUE source, options;
465
- rb_scan_args(argc, argv, "1:", &source, &options);
466
- rapidjson::Document doc;
467
- auto result = parse(doc, source, argc > 1 && RTEST(rb_hash_lookup(options, sym_fast)));
468
- if (!result)
469
- rb_raise(rb_eParserError, "%s Offset: %lu", GetParseError_En(result.Code()), result.Offset());
470
- return eval_r(doc);
471
- }
472
-
473
- /*
474
- * Returns whether the value is array.
475
- */
476
- static VALUE w_value_isarray(const VALUE self) {
477
- UsaminValue *value = get_value(self);
478
- check_value(value);
479
- return value->value->IsArray() ? Qtrue : Qfalse;
480
- }
481
-
482
- /*
483
- * Returns whether the value is object.
484
- */
485
- static VALUE w_value_isobject(const VALUE self) {
486
- UsaminValue *value = get_value(self);
487
- check_value(value);
488
- return value->value->IsObject() ? Qtrue : Qfalse;
489
- }
490
-
491
- /*
492
- * Convert to Ruby data structures.
493
- *
494
- * @return [Object]
495
- */
496
- static VALUE w_value_eval(const VALUE self) {
497
- UsaminValue *value = get_value(self);
498
- check_value(value);
499
- if (value->value->IsObject())
500
- return eval_object(*(value->value), self);
501
- else if (value->value->IsArray())
502
- return eval_array(*(value->value), self);
503
- else
504
- return Qnil;
505
- }
506
-
507
- /*
508
- * Convert to Ruby data structures recursively.
509
- *
510
- * @return [Object]
511
- */
512
- static VALUE w_value_eval_r(const VALUE self) {
513
- UsaminValue *value = get_value(self);
514
- check_value(value);
515
- return eval_r(*(value->value));
516
- }
517
-
518
- /*
519
- * Always true.
520
- */
521
- static VALUE w_value_isfrozen(const VALUE self) {
522
- return Qtrue;
523
- }
524
-
525
- /*
526
- * Dumps data in JSON.
527
- *
528
- * @return [String]
529
- */
530
- static VALUE w_value_marshal_dump(const VALUE self) {
531
- UsaminValue *value = get_value(self);
532
- check_value(value);
533
- rapidjson::StringBuffer buf;
534
- rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
535
- write_value(writer, *value->value);
536
- return rb_str_new(buf.GetString(), buf.GetSize());
537
- }
538
-
539
- /*
540
- * Loads marshal data.
541
- *
542
- * @return [self]
543
- */
544
- static VALUE w_value_marshal_load(const VALUE self, const VALUE source) {
545
- Check_Type(source, T_STRING);
546
- rapidjson::Document *doc = new rapidjson::Document();
547
- rapidjson::ParseResult result = doc->Parse<rapidjson::kParseFullPrecisionFlag | rapidjson::kParseNanAndInfFlag>(RSTRING_PTR(source), RSTRING_LEN(source));
548
- if (!result) {
549
- delete doc;
550
- rb_raise(rb_eParserError, "%s Offset: %lu", GetParseError_En(result.Code()), result.Offset());
551
- }
552
- if (doc->IsObject() || doc->IsArray()) {
553
- set_value(self, new UsaminValue(doc, true));
554
- return self;
555
- }
556
- auto type = doc->GetType();
557
- delete doc;
558
- rb_raise(rb_eUsaminError, "Invalid Value Type for marshal_load: %d", type);
559
- return Qnil;
560
- }
561
-
562
-
563
- /*
564
- * @return [Object | nil]
565
- *
566
- * @note This method has linear time complexity.
567
- */
568
- static VALUE w_hash_operator_indexer(const VALUE self, const VALUE key) {
569
- UsaminValue *value = get_value(self);
570
- check_object(value);
571
- for (auto &m : value->value->GetObject())
572
- if (str_compare_xx(key, m.name))
573
- return eval(m.value, self);
574
- return Qnil;
575
- }
576
-
577
- /*
578
- * @return [::Array | nil]
579
- *
580
- * @note This method has linear time complexity.
581
- */
582
- static VALUE w_hash_assoc(const VALUE self, const VALUE key) {
583
- UsaminValue *value = get_value(self);
584
- check_object(value);
585
- for (auto &m : value->value->GetObject())
586
- if (str_compare_xx(key, m.name))
587
- return rb_assoc_new(eval_str(m.name), eval(m.value, self));
588
- return Qnil;
589
- }
590
-
591
- /*
592
- * @return [::Hash]
593
- */
594
- static VALUE w_hash_compact(const VALUE self) {
595
- UsaminValue *value = get_value(self);
596
- check_object(value);
597
- VALUE hash = rb_hash_new();
598
- for (auto &m : value->value->GetObject())
599
- if (!m.value.IsNull())
600
- rb_hash_aset(hash, eval(m.name, self), eval(m.value, self));
601
- return hash;
602
- }
603
-
604
- static VALUE hash_enum_size(const VALUE self, const VALUE args, const VALUE eobj) {
605
- return UINT2NUM(get_value(self)->value->MemberCount());
606
- }
607
-
608
- /*
609
- * @yield [key, value]
610
- * @yieldparam key [String]
611
- * @yieldparam value [Object]
612
- * @return [Enumerator | self]
613
- */
614
- static VALUE w_hash_each(const VALUE self) {
615
- UsaminValue *value = get_value(self);
616
- check_object(value);
617
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
618
- if (rb_proc_arity(rb_block_proc()) > 1) {
619
- for (auto &m : value->value->GetObject()) {
620
- VALUE args[] = { eval_str(m.name), eval(m.value, self) };
621
- rb_yield_values2(2, args);
622
- }
623
- } else {
624
- for (auto &m : value->value->GetObject())
625
- rb_yield(rb_assoc_new(eval_str(m.name), eval(m.value, self)));
626
- }
627
- return self;
628
- }
629
-
630
- /*
631
- * @yield [key]
632
- * @yieldparam key [String]
633
- * @return [Enumerator | self]
634
- */
635
- static VALUE w_hash_each_key(const VALUE self) {
636
- UsaminValue *value = get_value(self);
637
- check_object(value);
638
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
639
- for (auto &m : value->value->GetObject())
640
- rb_yield(eval_str(m.name));
641
- return self;
642
- }
643
-
644
- /*
645
- * @yield [value]
646
- * @return [Enumerator | self]
647
- */
648
- static VALUE w_hash_each_value(const VALUE self) {
649
- UsaminValue *value = get_value(self);
650
- check_object(value);
651
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
652
- for (auto &m : value->value->GetObject())
653
- rb_yield(eval(m.value, self));
654
- return self;
655
- }
656
-
657
- static VALUE w_hash_isempty(const VALUE self) {
658
- UsaminValue *value = get_value(self);
659
- check_object(value);
660
- return value->value->MemberCount() == 0 ? Qtrue : Qfalse;
661
- }
662
-
663
- /*
664
- * @overload fetch(key, default = nil)
665
- * @param [String] key
666
- * @param [Object] default
667
- * @return [Object]
668
- *
669
- * @overload fetch(key)
670
- * @param [String] key
671
- * @yield [key]
672
- * @return [Object]
673
- */
674
- static VALUE w_hash_fetch(const int argc, const VALUE *argv, const VALUE self) {
675
- rb_check_arity(argc, 1, 2);
676
- UsaminValue *value = get_value(self);
677
- check_object(value);
678
- for (auto &m : value->value->GetObject())
679
- if (str_compare_xx(argv[0], m.name))
680
- return eval(m.value, self);
681
- return argc == 2 ? argv[1] : rb_block_given_p() ? rb_yield(argv[0]) : Qnil;
682
- }
683
-
684
- /*
685
- * @param [String] key
686
- * @return [::Array<Object>]
687
- */
688
- static VALUE w_hash_fetch_values(const int argc, VALUE *argv, const VALUE self) {
689
- UsaminValue *value = get_value(self);
690
- check_object(value);
691
- VALUE ret = rb_ary_new2(argc);
692
- for (int i = 0; i < argc; i++) {
693
- bool found = false;
694
- for (auto &m : value->value->GetObject()) {
695
- if (str_compare_xx(argv[i], m.name)) {
696
- rb_ary_push(ret, eval(m.value, self));
697
- found = true;
698
- break;
699
- }
700
- }
701
- if (!found) {
702
- if (rb_block_given_p()) {
703
- rb_ary_push(ret, rb_yield(argv[i]));
704
- } else {
705
- rb_ary_free(ret);
706
- rb_raise(rb_eKeyError, "key not found: \"%s\"", StringValueCStr(argv[i]));
707
- return Qnil;
708
- }
709
- }
710
- }
711
- return ret;
712
- }
713
-
714
- /*
715
- * @note This method has linear time complexity.
716
- */
717
- static VALUE w_hash_haskey(const VALUE self, const VALUE key) {
718
- UsaminValue *value = get_value(self);
719
- check_object(value);
720
- for (auto &m : value->value->GetObject())
721
- if (str_compare_xx(key, m.name))
722
- return Qtrue;
723
- return Qfalse;
724
- }
725
-
726
- static VALUE w_hash_hasvalue(const VALUE self, const VALUE val) {
727
- UsaminValue *value = get_value(self);
728
- check_object(value);
729
- for (auto &m : value->value->GetObject())
730
- if (rb_equal(val, eval_r(m.value)))
731
- return Qtrue;
732
- return Qfalse;
733
- }
734
-
735
- /*
736
- * @return [String | nil]
737
- */
738
- static VALUE w_hash_key(const VALUE self, const VALUE val) {
739
- UsaminValue *value = get_value(self);
740
- check_object(value);
741
- for (auto &m : value->value->GetObject())
742
- if (rb_equal(val, eval_r(m.value)))
743
- return eval_str(m.name);
744
- return Qnil;
745
- }
746
-
747
- /*
748
- * @return [::Array<String>]
749
- */
750
- static VALUE w_hash_keys(const VALUE self) {
751
- UsaminValue *value = get_value(self);
752
- check_object(value);
753
- VALUE ret = rb_ary_new2(value->value->MemberCount());
754
- for (auto &m : value->value->GetObject())
755
- rb_ary_push(ret, eval_str(m.name));
756
- return ret;
757
- }
758
-
759
- /*
760
- * @return [Integer]
761
- */
762
- static VALUE w_hash_length(const VALUE self) {
763
- UsaminValue *value = get_value(self);
764
- check_object(value);
765
- return UINT2NUM(value->value->MemberCount());
766
- }
767
-
768
- /*
769
- * @return [::Array | nil]
770
- */
771
- static VALUE w_hash_rassoc(const VALUE self, const VALUE val) {
772
- UsaminValue *value = get_value(self);
773
- check_object(value);
774
- for (auto &m : value->value->GetObject())
775
- if (rb_funcall(val, rb_intern("=="), 1, eval_r(m.value)))
776
- return rb_assoc_new(eval_str(m.name), eval(m.value, self));
777
- return Qnil;
778
- }
779
-
780
- /*
781
- * @yield [key, value]
782
- * @yieldparam key [String]
783
- * @yieldparam value [Object]
784
- * @return [Enumerator | ::Hash]
785
- */
786
- static VALUE w_hash_select(const VALUE self) {
787
- UsaminValue *value = get_value(self);
788
- check_object(value);
789
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
790
- VALUE hash = rb_hash_new();
791
- if (rb_proc_arity(rb_block_proc()) > 1) {
792
- for (auto &m : value->value->GetObject()) {
793
- VALUE args[] = { eval_str(m.name), eval(m.value, self) };
794
- if (RTEST(rb_yield_values2(2, args)))
795
- rb_hash_aset(hash, args[0], args[1]);
796
- }
797
- } else {
798
- for (auto &m : value->value->GetObject()) {
799
- VALUE key = eval_str(m.name);
800
- VALUE val = eval(m.value, self);
801
- if (RTEST(rb_yield(rb_assoc_new(key, val))))
802
- rb_hash_aset(hash, key, val);
803
- }
804
- }
805
- return hash;
806
- }
807
-
808
- /*
809
- * @yield [key, value]
810
- * @yieldparam key [String]
811
- * @yieldparam value [Object]
812
- * @return [Enumerator | ::Hash]
813
- */
814
- static VALUE w_hash_reject(const VALUE self) {
815
- UsaminValue *value = get_value(self);
816
- check_object(value);
817
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
818
- VALUE hash = rb_hash_new();
819
- if (rb_proc_arity(rb_block_proc()) > 1) {
820
- for (auto &m : value->value->GetObject()) {
821
- VALUE args[] = { eval_str(m.name), eval(m.value, self) };
822
- if (!RTEST(rb_yield_values2(2, args)))
823
- rb_hash_aset(hash, args[0], args[1]);
824
- }
825
- } else {
826
- for (auto &m : value->value->GetObject()) {
827
- VALUE key = eval_str(m.name);
828
- VALUE val = eval(m.value, self);
829
- if (!RTEST(rb_yield(rb_assoc_new(key, val))))
830
- rb_hash_aset(hash, key, val);
831
- }
832
- }
833
- return hash;
834
- }
835
-
836
- /*
837
- * @yield [key, value]
838
- * @yieldparam key [String]
839
- * @yieldparam value [Object]
840
- * @return [Enumerator | ::Hash]
841
- */
842
- static VALUE w_hash_slice(const int argc, const VALUE *argv, const VALUE self) {
843
- UsaminValue *value = get_value(self);
844
- check_object(value);
845
- VALUE hash = rb_hash_new();
846
- for (int i = 0; i < argc; i++)
847
- for (auto &m : value->value->GetObject())
848
- if (str_compare_xx(argv[i], m.name))
849
- rb_hash_aset(hash, eval_str(m.name), eval(m.value, self));
850
- return hash;
851
- }
852
-
853
- /*
854
- * Convert to Ruby Hash. Same as {Value#eval}.
855
- *
856
- * @return [::Hash]
857
- */
858
- static VALUE w_hash_eval(const VALUE self) {
859
- UsaminValue *value = get_value(self);
860
- check_object(value);
861
- return eval_object(*(value->value), self);
862
- }
863
-
864
- /*
865
- * @return [::Array<Object>]
866
- */
867
- static VALUE w_hash_to_a(const VALUE self) {
868
- UsaminValue *value = get_value(self);
869
- check_object(value);
870
- VALUE ret = rb_ary_new2(value->value->MemberCount());
871
- for (auto &m : value->value->GetObject())
872
- rb_ary_push(ret, rb_assoc_new(eval_str(m.name), eval(m.value, self)));
873
- return ret;
874
- }
875
-
876
- /*
877
- * @return [::Array<Object>]
878
- */
879
- static VALUE w_hash_values(const VALUE self) {
880
- UsaminValue *value = get_value(self);
881
- check_object(value);
882
- VALUE ret = rb_ary_new2(value->value->MemberCount());
883
- for (auto &m : value->value->GetObject())
884
- rb_ary_push(ret, eval(m.value, self));
885
- return ret;
886
- }
887
-
888
- /*
889
- * @yield [key]
890
- * @yieldparam key [String]
891
- * @return [Enumerator | ::Hash]
892
- */
893
- static VALUE w_hash_transform_keys(const VALUE self) {
894
- UsaminValue *value = get_value(self);
895
- check_object(value);
896
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
897
- VALUE hash = rb_hash_new();
898
- for (auto &m : value->value->GetObject())
899
- rb_hash_aset(hash, rb_yield(eval_str(m.name)), eval(m.value, self));
900
- return hash;
901
- }
902
-
903
- /*
904
- * @yield [value]
905
- * @yieldparam value [Object]
906
- * @return [Enumerator | ::Hash]
907
- */
908
- static VALUE w_hash_transform_values(const VALUE self) {
909
- UsaminValue *value = get_value(self);
910
- check_object(value);
911
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, hash_enum_size);
912
- VALUE hash = rb_hash_new();
913
- for (auto &m : value->value->GetObject())
914
- rb_hash_aset(hash, eval_str(m.name), rb_yield(eval(m.value, self)));
915
- return hash;
916
- }
15
+ ID id_dig, id_to_s;
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;
917
18
 
918
- /*
919
- * @param [String] keys
920
- * @return [::Array<Object>]
921
- */
922
- static VALUE w_hash_values_at(const int argc, const VALUE *argv, const VALUE self) {
923
- UsaminValue *value = get_value(self);
924
- check_object(value);
925
- VALUE ret = rb_ary_new2(argc);
926
- for (int i = 0; i < argc; i++) {
927
- VALUE data = Qnil;
928
- for (auto &m : value->value->GetObject()) {
929
- if (str_compare_xx(argv[i], m.name)) {
930
- data = eval(m.value, self);
931
- break;
932
- }
933
- }
934
- rb_ary_push(ret, data);
935
- }
936
- return ret;
937
- }
938
-
939
- /*
940
- * @overload [](nth)
941
- * @param [Integer] nth
942
- * @return [Object | nil]
943
- *
944
- * @overload [](start, length)
945
- * @param [Integer] start
946
- * @param [Integer] length
947
- * @return [::Array<Object> | nil]
948
- *
949
- * @overload [](range)
950
- * @param [Range] range
951
- * @return [::Array<Object> | nil]
952
- */
953
- static VALUE w_array_operator_indexer(const int argc, const VALUE *argv, const VALUE self) {
954
- rb_check_arity(argc, 1, 2);
955
- UsaminValue *value = get_value(self);
956
- check_array(value);
957
- rapidjson::SizeType sz = value->value->Size();
958
- if (argc == 2) {
959
- long beg = FIX2LONG(argv[0]);
960
- long len = FIX2LONG(argv[1]);
961
- if (beg < 0)
962
- beg += sz;
963
- if (beg >= 0 && len >= 0) {
964
- rapidjson::SizeType end = static_cast<rapidjson::SizeType>(beg + len);
965
- if (end > sz)
966
- end = sz;
967
- VALUE ret = rb_ary_new2(end - beg);
968
- for (rapidjson::SizeType i = static_cast<rapidjson::SizeType>(beg); i < end; i++)
969
- rb_ary_push(ret, eval((*value->value)[i], self));
970
- return ret;
971
- }
972
- } else if (rb_obj_is_kind_of(argv[0], rb_cRange)) {
973
- long beg, len;
974
- if (rb_range_beg_len(argv[0], &beg, &len, sz, 0) == Qtrue) {
975
- VALUE ret = rb_ary_new2(len);
976
- for (rapidjson::SizeType i = static_cast<rapidjson::SizeType>(beg); i < beg + len; i++)
977
- rb_ary_push(ret, eval((*value->value)[i], self));
978
- return ret;
979
- }
980
- } else {
981
- long l = FIX2LONG(argv[0]);
982
- if (l < 0)
983
- l += sz;
984
- if (0 <= l && l < sz)
985
- return eval((*value->value)[static_cast<rapidjson::SizeType>(l)], self);
986
- }
987
- return Qnil;
988
- }
989
-
990
- /*
991
- * @param [Integer] nth
992
- * @return [Object]
993
- */
994
- static VALUE w_array_at(const VALUE self, const VALUE nth) {
995
- UsaminValue *value = get_value(self);
996
- check_array(value);
997
- long l = FIX2LONG(nth);
998
- rapidjson::SizeType sz = value->value->Size();
999
- if (l < 0)
1000
- l += sz;
1001
- if (0 <= l && l < sz)
1002
- return eval((*value->value)[static_cast<rapidjson::SizeType>(l)], self);
1003
- return Qnil;
1004
- }
1005
-
1006
- /*
1007
- * @return [::Array]
1008
- */
1009
- static VALUE w_array_compact(const VALUE self, const VALUE nth) {
1010
- UsaminValue *value = get_value(self);
1011
- check_array(value);
1012
- VALUE ret = rb_ary_new2(value->value->Size());
1013
- for (auto &v : value->value->GetArray())
1014
- if (!v.IsNull())
1015
- rb_ary_push(ret, eval(v, self));
1016
- return ret;
1017
- }
1018
-
1019
- static VALUE array_enum_size(const VALUE self, const VALUE args, const VALUE eobj) {
1020
- return UINT2NUM(get_value(self)->value->Size());
1021
- }
1022
-
1023
- /*
1024
- * @yield [value]
1025
- * @return [Enumerator | self]
1026
- */
1027
- static VALUE w_array_each(const VALUE self) {
1028
- UsaminValue *value = get_value(self);
1029
- check_array(value);
1030
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, array_enum_size);
1031
- for (auto &v : value->value->GetArray())
1032
- rb_yield(eval(v, self));
1033
- return self;
1034
- }
1035
-
1036
- /*
1037
- * @yield [index]
1038
- * @yieldparam index [Integer]
1039
- * @return [Enumerator | self]
1040
- */
1041
- static VALUE w_array_each_index(const VALUE self) {
1042
- UsaminValue *value = get_value(self);
1043
- check_array(value);
1044
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, array_enum_size);
1045
- for (rapidjson::SizeType i = 0; i < value->value->Size(); i++)
1046
- rb_yield(UINT2NUM(i));
1047
- return self;
1048
- }
1049
-
1050
- static VALUE w_array_isempty(const VALUE self) {
1051
- UsaminValue *value = get_value(self);
1052
- check_array(value);
1053
- return value->value->Size() == 0 ? Qtrue : Qfalse;
1054
- }
1055
-
1056
- /*
1057
- * @overload fetch(nth)
1058
- * @param [Integer] nth
1059
- * @return [Object]
1060
- * @raise [IndexError] if nth is out of array bounds
1061
- *
1062
- * @overload fetch(nth, ifnone)
1063
- * @param [Integer] nth
1064
- * @param [Object] ifnone
1065
- * @return [Object]
1066
- *
1067
- * @overload fetch(nth)
1068
- * @param [Integer] nth
1069
- * @yield [nth]
1070
- * @return [Object]
1071
- */
1072
- static VALUE w_array_fetch(const int argc, const VALUE *argv, const VALUE self) {
1073
- rb_check_arity(argc, 1, 2);
1074
- UsaminValue *value = get_value(self);
1075
- check_array(value);
1076
- rapidjson::SizeType sz = value->value->Size();
1077
-
1078
- long l = FIX2LONG(argv[0]);
1079
- if (l < 0)
1080
- l += sz;
1081
- if (0 <= l && l < sz)
1082
- return eval((*value->value)[static_cast<rapidjson::SizeType>(l)], self);
1083
-
1084
- if (argc == 2)
1085
- return argv[1];
1086
- else if (rb_block_given_p())
1087
- return rb_yield(argv[0]);
1088
- else
1089
- rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%u", FIX2LONG(argv[0]), -static_cast<long>(sz), sz);
1090
- return Qnil;
1091
- }
1092
-
1093
- /*
1094
- * @overload find_index(val)
1095
- * @param [Object] val
1096
- * @return [Integer | nil]
1097
- *
1098
- * @overload find_index
1099
- * @yield [item]
1100
- * @yieldparam item [Object]
1101
- * @return [Integer | nil]
1102
- */
1103
- static VALUE w_array_find_index(const int argc, const VALUE *argv, const VALUE self) {
1104
- rb_check_arity(argc, 0, 1);
1105
- UsaminValue *value = get_value(self);
1106
- check_array(value);
1107
-
1108
- if (argc == 1) {
1109
- for (rapidjson::SizeType i = 0; i < value->value->Size(); i++) {
1110
- if (rb_equal(argv[0], eval_r((*value->value)[i])) == Qtrue)
1111
- return UINT2NUM(i);
1112
- }
1113
- return Qnil;
1114
- }
1115
-
1116
- RETURN_SIZED_ENUMERATOR(self, 0, nullptr, array_enum_size);
1117
- for (rapidjson::SizeType i = 0; i < value->value->Size(); i++) {
1118
- if (RTEST(rb_yield(eval((*value->value)[i], self))))
1119
- return UINT2NUM(i);
1120
- }
1121
- return Qnil;
1122
- }
1123
-
1124
- /*
1125
- * @overload index(val)
1126
- * @param [Object] val
1127
- * @return [Integer | nil]
1128
- *
1129
- * @overload index
1130
- * @yield [item]
1131
- * @yieldparam item [Object]
1132
- * @return [Integer | nil]
1133
- */
1134
- static VALUE w_array_index(const int argc, const VALUE *argv, const VALUE self) {
1135
- return w_array_find_index(argc, argv, self);
1136
- }
1137
-
1138
- /*
1139
- * @overload first
1140
- * @return [Object | nil]
1141
- *
1142
- * @overload first(n)
1143
- * @return [::Array<Object>]
1144
- */
1145
- static VALUE w_array_first(const int argc, const VALUE *argv, const VALUE self) {
1146
- rb_check_arity(argc, 0, 1);
1147
- UsaminValue *value = get_value(self);
1148
- check_array(value);
1149
- rapidjson::SizeType sz = value->value->Size();
1150
-
1151
- if (argc == 0) {
1152
- if (sz == 0)
1153
- return Qnil;
1154
- return eval(*value->value->Begin(), self);
1155
- } else {
1156
- long l = FIX2LONG(argv[0]);
1157
- if (l > sz)
1158
- l = sz;
1159
- VALUE ret = rb_ary_new2(l);
1160
- for (auto v = value->value->Begin(); v < value->value->Begin() + l; v++)
1161
- rb_ary_push(ret, eval(*v, self));
1162
- return ret;
1163
- }
1164
- }
1165
-
1166
- /*
1167
- * @return [Boolean]
1168
- */
1169
- static VALUE w_array_include(const VALUE self, const VALUE val) {
1170
- UsaminValue *value = get_value(self);
1171
- check_array(value);
1172
- for (auto &v : value->value->GetArray())
1173
- if (rb_equal(val, eval_r(v)))
1174
- return Qtrue;
1175
- return Qfalse;
1176
- }
1177
-
1178
- /*
1179
- * @overload last
1180
- * @return [Object | nil]
1181
- *
1182
- * @overload last(n)
1183
- * @return [::Array<Object>]
1184
- */
1185
- static VALUE w_array_last(const int argc, const VALUE *argv, const VALUE self) {
1186
- rb_check_arity(argc, 0, 1);
1187
- UsaminValue *value = get_value(self);
1188
- check_array(value);
1189
- rapidjson::SizeType sz = value->value->Size();
1190
-
1191
- if (argc == 0) {
1192
- return sz > 0 ? eval(*(value->value->End() - 1), self) : Qnil;
1193
- } else {
1194
- long l = FIX2LONG(argv[0]);
1195
- if (l > sz)
1196
- l = sz;
1197
- VALUE ret = rb_ary_new2(l);
1198
- for (auto v = value->value->End() - l; v < value->value->End(); v++)
1199
- rb_ary_push(ret, eval(*v, self));
1200
- return ret;
1201
- }
1202
- }
1203
-
1204
- /*
1205
- * @return [Integer]
1206
- */
1207
- static VALUE w_array_length(const VALUE self) {
1208
- UsaminValue *value = get_value(self);
1209
- check_array(value);
1210
- return UINT2NUM(value->value->Size());
1211
- }
1212
-
1213
- /*
1214
- * @overload slice(nth)
1215
- * @param [Integer] nth
1216
- * @return [Object | nil]
1217
- *
1218
- * @overload slice(start, length)
1219
- * @param [Integer] start
1220
- * @param [Integer] length
1221
- * @return [::Array<Object> | nil]
1222
- *
1223
- * @overload slice(range)
1224
- * @param [Range] range
1225
- * @return [::Array<Object> | nil]
1226
- */
1227
- static VALUE w_array_slice(const int argc, const VALUE *argv, const VALUE self) {
1228
- return w_array_operator_indexer(argc, argv, self);
1229
- }
1230
-
1231
- /*
1232
- * Convert to Ruby data structures. Same as {Value#eval}.
1233
- *
1234
- * @return [::Array<Object>]
1235
- */
1236
- static VALUE w_array_eval(const VALUE self) {
1237
- UsaminValue *value = get_value(self);
1238
- check_array(value);
1239
- return eval_array(*(value->value), self);
1240
- }
1241
-
1242
-
1243
- /*
1244
- * Generate the JSON string from Ruby data structures.
1245
- *
1246
- * @overload generate(obj)
1247
- * @param [Object] obj an object to serialize
1248
- * @return [String]
1249
- */
1250
- static VALUE w_generate(const VALUE self, const VALUE value) {
1251
- rapidjson::StringBuffer buf;
1252
- rapidjson::Writer<rapidjson::StringBuffer> writer(buf);
1253
- write(writer, value);
1254
- return new_utf8_str(buf.GetString(), buf.GetSize());
1255
- }
1256
-
1257
- /*
1258
- * Generate the prettified JSON string from Ruby data structures.
1259
- *
1260
- * @overload pretty_generate(obj, opts = {})
1261
- * @param [Object] obj an object to serialize
1262
- * @param [::Hash] opts options
1263
- * @option opts [String] :indent (' ') a string used to indent
1264
- * @option opts [Boolean] :single_line_array (false)
1265
- * @return [String]
1266
- */
1267
- static VALUE w_pretty_generate(const int argc, const VALUE *argv, const VALUE self) {
1268
- VALUE value, options;
1269
- rb_scan_args(argc, argv, "1:", &value, &options);
1270
- rapidjson::StringBuffer buf;
1271
- rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
1272
-
1273
- char indent_char = ' ';
1274
- unsigned int indent_count = 2;
1275
- if (argc > 1) {
1276
- VALUE v_indent = rb_hash_lookup(options, sym_indent);
1277
- if (RTEST(v_indent)) {
1278
- if (RB_FIXNUM_P(v_indent)) {
1279
- long l = FIX2LONG(v_indent);
1280
- indent_count = l > 0 ? static_cast<unsigned int>(l) : 0;
1281
- } else {
1282
- long vlen = RSTRING_LEN(v_indent);
1283
- if (vlen == 0) {
1284
- indent_count = 0;
1285
- } else {
1286
- const char *indent_str = RSTRING_PTR(v_indent);
1287
- switch (indent_str[0]) {
1288
- case ' ':
1289
- case '\t':
1290
- case '\r':
1291
- case '\n':
1292
- indent_char = indent_str[0];
1293
- break;
1294
- default:
1295
- rb_raise(rb_eUsaminError, ":indent must be a repetation of \" \", \"\\t\", \"\\r\" or \"\\n\".");
1296
- }
1297
- for (long i = 1; i < vlen; i++)
1298
- if (indent_str[0] != indent_str[i])
1299
- rb_raise(rb_eUsaminError, ":indent must be a repetation of \" \", \"\\t\", \"\\r\" or \"\\n\".");
1300
- indent_count = static_cast<unsigned int>(vlen);
1301
- }
1302
- }
1303
- }
1304
-
1305
- if (RTEST(rb_hash_lookup(options, sym_single_line_array)))
1306
- writer.SetFormatOptions(rapidjson::kFormatSingleLineArray);
1307
- }
1308
- writer.SetIndent(indent_char, indent_count);
1309
-
1310
- write(writer, value);
1311
- return new_utf8_str(buf.GetString(), buf.GetSize());
1312
- }
1313
-
1314
-
1315
- extern "C" void Init_usamin(void) {
19
+ extern "C" {
20
+ void Init_usamin() {
1316
21
  utf8 = rb_utf8_encoding();
1317
22
  utf8index = rb_enc_to_index(utf8);
1318
23
  utf8value = rb_enc_from_encoding(utf8);
1319
24
  sym_fast = rb_id2sym(rb_intern("fast"));
1320
25
  sym_indent = rb_id2sym(rb_intern("indent"));
26
+ sym_recursive = rb_id2sym(rb_intern("recursive"));
1321
27
  sym_single_line_array = rb_id2sym(rb_intern("single_line_array"));
28
+ sym_symbolize_names = rb_id2sym(rb_intern("symbolize_names"));
29
+ id_dig = rb_intern("dig");
1322
30
  id_to_s = rb_intern("to_s");
1323
31
 
1324
- VALUE rb_mUsamin = rb_define_module("Usamin");
32
+ rb_mUsamin = rb_define_module("Usamin");
1325
33
  rb_define_module_function(rb_mUsamin, "load", RUBY_METHOD_FUNC(w_load), -1);
1326
34
  rb_define_module_function(rb_mUsamin, "parse", RUBY_METHOD_FUNC(w_parse), -1);
1327
35
  rb_define_module_function(rb_mUsamin, "generate", RUBY_METHOD_FUNC(w_generate), 1);
1328
36
  rb_define_module_function(rb_mUsamin, "pretty_generate", RUBY_METHOD_FUNC(w_pretty_generate), -1);
1329
37
 
1330
38
  rb_cUsaminValue = rb_define_class_under(rb_mUsamin, "Value", rb_cObject);
1331
- rb_define_alloc_func(rb_cUsaminValue, usamin_alloc);
39
+ rb_undef_alloc_func(rb_cUsaminValue);
1332
40
  rb_undef_method(rb_cUsaminValue, "initialize");
41
+ rb_define_method(rb_cUsaminValue, "==", RUBY_METHOD_FUNC(w_value_equal), 1);
42
+ rb_define_method(rb_cUsaminValue, "===", RUBY_METHOD_FUNC(w_value_equal), 1);
1333
43
  rb_define_method(rb_cUsaminValue, "array?", RUBY_METHOD_FUNC(w_value_isarray), 0);
1334
44
  rb_define_method(rb_cUsaminValue, "hash?", RUBY_METHOD_FUNC(w_value_isobject), 0);
1335
45
  rb_define_method(rb_cUsaminValue, "object?", RUBY_METHOD_FUNC(w_value_isobject), 0);
1336
- rb_define_method(rb_cUsaminValue, "eval", RUBY_METHOD_FUNC(w_value_eval), 0);
1337
- 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);
48
+ rb_define_method(rb_cUsaminValue, "eql?", RUBY_METHOD_FUNC(w_value_eql), 1);
1338
49
  rb_define_method(rb_cUsaminValue, "frozen?", RUBY_METHOD_FUNC(w_value_isfrozen), 0);
1339
- rb_define_method(rb_cUsaminValue, "marshal_dump", RUBY_METHOD_FUNC(w_value_marshal_dump), 0);
1340
- rb_define_method(rb_cUsaminValue, "marshal_load", RUBY_METHOD_FUNC(w_value_marshal_load), 1);
50
+ rb_define_method(rb_cUsaminValue, "hash", RUBY_METHOD_FUNC(w_value_hash), 0);
51
+ rb_define_method(rb_cUsaminValue, "root", RUBY_METHOD_FUNC(w_value_root), 0);
1341
52
 
1342
53
  rb_cUsaminHash = rb_define_class_under(rb_mUsamin, "Hash", rb_cUsaminValue);
1343
54
  rb_include_module(rb_cUsaminHash, rb_mEnumerable);
@@ -1346,6 +57,8 @@ extern "C" void Init_usamin(void) {
1346
57
  rb_define_method(rb_cUsaminHash, "[]", RUBY_METHOD_FUNC(w_hash_operator_indexer), 1);
1347
58
  rb_define_method(rb_cUsaminHash, "assoc", RUBY_METHOD_FUNC(w_hash_assoc), 1);
1348
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);
61
+ rb_define_method(rb_cUsaminHash, "dig", RUBY_METHOD_FUNC(w_hash_dig), -1);
1349
62
  rb_define_method(rb_cUsaminHash, "each", RUBY_METHOD_FUNC(w_hash_each), 0);
1350
63
  rb_define_method(rb_cUsaminHash, "each_pair", RUBY_METHOD_FUNC(w_hash_each), 0);
1351
64
  rb_define_method(rb_cUsaminHash, "each_key", RUBY_METHOD_FUNC(w_hash_each_key), 0);
@@ -1353,6 +66,7 @@ extern "C" void Init_usamin(void) {
1353
66
  rb_define_method(rb_cUsaminHash, "empty?", RUBY_METHOD_FUNC(w_hash_isempty), 0);
1354
67
  rb_define_method(rb_cUsaminHash, "fetch", RUBY_METHOD_FUNC(w_hash_fetch), -1);
1355
68
  rb_define_method(rb_cUsaminHash, "fetch_values", RUBY_METHOD_FUNC(w_hash_fetch_values), -1);
69
+ rb_define_method(rb_cUsaminHash, "flatten", RUBY_METHOD_FUNC(w_hash_flatten), -1);
1356
70
  rb_define_method(rb_cUsaminHash, "has_key?", RUBY_METHOD_FUNC(w_hash_haskey), 1);
1357
71
  rb_define_method(rb_cUsaminHash, "include?", RUBY_METHOD_FUNC(w_hash_haskey), 1);
1358
72
  rb_define_method(rb_cUsaminHash, "key?", RUBY_METHOD_FUNC(w_hash_haskey), 1);
@@ -1361,43 +75,58 @@ extern "C" void Init_usamin(void) {
1361
75
  rb_define_method(rb_cUsaminHash, "value?", RUBY_METHOD_FUNC(w_hash_hasvalue), 1);
1362
76
  rb_define_method(rb_cUsaminHash, "key", RUBY_METHOD_FUNC(w_hash_key), 1);
1363
77
  rb_define_method(rb_cUsaminHash, "index", RUBY_METHOD_FUNC(w_hash_key), 1);
78
+ rb_define_method(rb_cUsaminHash, "inspect", RUBY_METHOD_FUNC(w_hash_inspect), 0);
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);
1364
81
  rb_define_method(rb_cUsaminHash, "keys", RUBY_METHOD_FUNC(w_hash_keys), 0);
1365
82
  rb_define_method(rb_cUsaminHash, "length", RUBY_METHOD_FUNC(w_hash_length), 0);
1366
83
  rb_define_method(rb_cUsaminHash, "size", RUBY_METHOD_FUNC(w_hash_length), 0);
84
+ rb_define_method(rb_cUsaminHash, "merge", RUBY_METHOD_FUNC(w_hash_merge), -1);
1367
85
  rb_define_method(rb_cUsaminHash, "rassoc", RUBY_METHOD_FUNC(w_hash_rassoc), 1);
1368
86
  rb_define_method(rb_cUsaminHash, "reject", RUBY_METHOD_FUNC(w_hash_reject), 0);
1369
87
  rb_define_method(rb_cUsaminHash, "select", RUBY_METHOD_FUNC(w_hash_select), 0);
1370
88
  rb_define_method(rb_cUsaminHash, "slice", RUBY_METHOD_FUNC(w_hash_slice), -1);
1371
- rb_define_method(rb_cUsaminHash, "to_a", RUBY_METHOD_FUNC(w_hash_to_a), 0);
1372
- rb_define_method(rb_cUsaminHash, "to_h", RUBY_METHOD_FUNC(w_hash_eval), 0);
1373
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);
1374
91
  rb_define_method(rb_cUsaminHash, "transform_keys", RUBY_METHOD_FUNC(w_hash_transform_keys), 0);
1375
92
  rb_define_method(rb_cUsaminHash, "transform_values", RUBY_METHOD_FUNC(w_hash_transform_values), 0);
1376
93
  rb_define_method(rb_cUsaminHash, "values", RUBY_METHOD_FUNC(w_hash_values), 0);
1377
94
  rb_define_method(rb_cUsaminHash, "values_at", RUBY_METHOD_FUNC(w_hash_values_at), -1);
95
+ rb_define_method(rb_cUsaminHash, "marshal_dump", RUBY_METHOD_FUNC(w_value_marshal_dump), 0);
96
+ rb_define_method(rb_cUsaminHash, "marshal_load", RUBY_METHOD_FUNC(w_value_marshal_load), 1);
1378
97
 
1379
98
  rb_cUsaminArray = rb_define_class_under(rb_mUsamin, "Array", rb_cUsaminValue);
1380
99
  rb_include_module(rb_cUsaminArray, rb_mEnumerable);
1381
100
  rb_define_alloc_func(rb_cUsaminArray, usamin_alloc);
1382
101
  rb_undef_method(rb_cUsaminArray, "initialize");
1383
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);
1384
104
  rb_define_method(rb_cUsaminArray, "at", RUBY_METHOD_FUNC(w_array_at), 1);
1385
105
  rb_define_method(rb_cUsaminArray, "compact", RUBY_METHOD_FUNC(w_array_compact), 0);
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);
1386
108
  rb_define_method(rb_cUsaminArray, "each", RUBY_METHOD_FUNC(w_array_each), 0);
1387
109
  rb_define_method(rb_cUsaminArray, "each_index", RUBY_METHOD_FUNC(w_array_each_index), 0);
1388
110
  rb_define_method(rb_cUsaminArray, "empty?", RUBY_METHOD_FUNC(w_array_isempty), 0);
1389
111
  rb_define_method(rb_cUsaminArray, "fetch", RUBY_METHOD_FUNC(w_array_fetch), -1);
1390
112
  rb_define_method(rb_cUsaminArray, "find_index", RUBY_METHOD_FUNC(w_array_find_index), -1);
1391
- 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);
1392
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);
1393
116
  rb_define_method(rb_cUsaminArray, "include?", RUBY_METHOD_FUNC(w_array_include), 1);
117
+ rb_define_method(rb_cUsaminArray, "inspect", RUBY_METHOD_FUNC(w_array_inspect), 0);
118
+ rb_define_method(rb_cUsaminArray, "to_s", RUBY_METHOD_FUNC(w_array_inspect), 0);
1394
119
  rb_define_method(rb_cUsaminArray, "last", RUBY_METHOD_FUNC(w_array_last), -1);
1395
120
  rb_define_method(rb_cUsaminArray, "length", RUBY_METHOD_FUNC(w_array_length), 0);
1396
121
  rb_define_method(rb_cUsaminArray, "size", RUBY_METHOD_FUNC(w_array_length), 0);
1397
- rb_define_method(rb_cUsaminArray, "slice", RUBY_METHOD_FUNC(w_array_slice), -1);
1398
- rb_define_method(rb_cUsaminArray, "to_a", RUBY_METHOD_FUNC(w_array_eval), 0);
122
+ rb_define_method(rb_cUsaminArray, "reverse", RUBY_METHOD_FUNC(w_array_reverse), 0);
123
+ rb_define_method(rb_cUsaminArray, "rindex", RUBY_METHOD_FUNC(w_array_rindex), -1);
124
+ rb_define_method(rb_cUsaminArray, "rotate", RUBY_METHOD_FUNC(w_array_rotate), -1);
1399
125
  rb_define_method(rb_cUsaminArray, "to_ary", RUBY_METHOD_FUNC(w_array_eval), 0);
126
+ rb_define_method(rb_cUsaminArray, "marshal_dump", RUBY_METHOD_FUNC(w_value_marshal_dump), 0);
127
+ rb_define_method(rb_cUsaminArray, "marshal_load", RUBY_METHOD_FUNC(w_value_marshal_load), 1);
1400
128
 
1401
129
  rb_eUsaminError = rb_define_class_under(rb_mUsamin, "UsaminError", rb_eStandardError);
1402
130
  rb_eParserError = rb_define_class_under(rb_mUsamin, "ParserError", rb_eUsaminError);
1403
131
  }
132
+ }