mongory 0.7.3-x64-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mongory might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +88 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +364 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/LICENSE.txt +21 -0
- data/README.md +488 -0
- data/Rakefile +107 -0
- data/SUBMODULE_INTEGRATION.md +325 -0
- data/docs/advanced_usage.md +40 -0
- data/docs/clang_bridge.md +69 -0
- data/docs/field_names.md +30 -0
- data/docs/migration.md +30 -0
- data/docs/performance.md +61 -0
- data/examples/README.md +41 -0
- data/examples/benchmark-rails.rb +52 -0
- data/examples/benchmark.rb +184 -0
- data/ext/mongory_ext/extconf.rb +91 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core/foundations/array.h +122 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core/foundations/config.h +161 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core/foundations/error.h +79 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core/foundations/memory_pool.h +95 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core/foundations/table.h +127 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core/foundations/value.h +175 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core/matchers/matcher.h +76 -0
- data/ext/mongory_ext/mongory-core/include/mongory-core.h +12 -0
- data/ext/mongory_ext/mongory-core/src/foundations/array.c +287 -0
- data/ext/mongory_ext/mongory-core/src/foundations/array_private.h +19 -0
- data/ext/mongory_ext/mongory-core/src/foundations/config.c +270 -0
- data/ext/mongory_ext/mongory-core/src/foundations/config_private.h +48 -0
- data/ext/mongory_ext/mongory-core/src/foundations/error.c +38 -0
- data/ext/mongory_ext/mongory-core/src/foundations/memory_pool.c +298 -0
- data/ext/mongory_ext/mongory-core/src/foundations/string_buffer.c +65 -0
- data/ext/mongory_ext/mongory-core/src/foundations/string_buffer.h +49 -0
- data/ext/mongory_ext/mongory-core/src/foundations/table.c +498 -0
- data/ext/mongory_ext/mongory-core/src/foundations/utils.c +210 -0
- data/ext/mongory_ext/mongory-core/src/foundations/utils.h +70 -0
- data/ext/mongory_ext/mongory-core/src/foundations/value.c +500 -0
- data/ext/mongory_ext/mongory-core/src/matchers/array_record_matcher.c +164 -0
- data/ext/mongory_ext/mongory-core/src/matchers/array_record_matcher.h +47 -0
- data/ext/mongory_ext/mongory-core/src/matchers/base_matcher.c +122 -0
- data/ext/mongory_ext/mongory-core/src/matchers/base_matcher.h +100 -0
- data/ext/mongory_ext/mongory-core/src/matchers/compare_matcher.c +217 -0
- data/ext/mongory_ext/mongory-core/src/matchers/compare_matcher.h +83 -0
- data/ext/mongory_ext/mongory-core/src/matchers/composite_matcher.c +573 -0
- data/ext/mongory_ext/mongory-core/src/matchers/composite_matcher.h +125 -0
- data/ext/mongory_ext/mongory-core/src/matchers/existance_matcher.c +147 -0
- data/ext/mongory_ext/mongory-core/src/matchers/existance_matcher.h +48 -0
- data/ext/mongory_ext/mongory-core/src/matchers/external_matcher.c +124 -0
- data/ext/mongory_ext/mongory-core/src/matchers/external_matcher.h +46 -0
- data/ext/mongory_ext/mongory-core/src/matchers/inclusion_matcher.c +126 -0
- data/ext/mongory_ext/mongory-core/src/matchers/inclusion_matcher.h +46 -0
- data/ext/mongory_ext/mongory-core/src/matchers/literal_matcher.c +314 -0
- data/ext/mongory_ext/mongory-core/src/matchers/literal_matcher.h +97 -0
- data/ext/mongory_ext/mongory-core/src/matchers/matcher.c +252 -0
- data/ext/mongory_ext/mongory-core/src/matchers/matcher_explainable.c +79 -0
- data/ext/mongory_ext/mongory-core/src/matchers/matcher_explainable.h +23 -0
- data/ext/mongory_ext/mongory-core/src/matchers/matcher_traversable.c +60 -0
- data/ext/mongory_ext/mongory-core/src/matchers/matcher_traversable.h +23 -0
- data/ext/mongory_ext/mongory_ext.c +683 -0
- data/lib/generators/mongory/install/install_generator.rb +42 -0
- data/lib/generators/mongory/install/templates/initializer.rb.erb +83 -0
- data/lib/generators/mongory/matcher/matcher_generator.rb +56 -0
- data/lib/generators/mongory/matcher/templates/matcher.rb.erb +92 -0
- data/lib/generators/mongory/matcher/templates/matcher_spec.rb.erb +17 -0
- data/lib/mongory/c_query_builder.rb +44 -0
- data/lib/mongory/converters/abstract_converter.rb +111 -0
- data/lib/mongory/converters/condition_converter.rb +64 -0
- data/lib/mongory/converters/converted.rb +81 -0
- data/lib/mongory/converters/data_converter.rb +37 -0
- data/lib/mongory/converters/key_converter.rb +87 -0
- data/lib/mongory/converters/value_converter.rb +52 -0
- data/lib/mongory/converters.rb +8 -0
- data/lib/mongory/matchers/abstract_matcher.rb +219 -0
- data/lib/mongory/matchers/abstract_multi_matcher.rb +124 -0
- data/lib/mongory/matchers/and_matcher.rb +72 -0
- data/lib/mongory/matchers/array_record_matcher.rb +93 -0
- data/lib/mongory/matchers/elem_match_matcher.rb +55 -0
- data/lib/mongory/matchers/eq_matcher.rb +46 -0
- data/lib/mongory/matchers/every_matcher.rb +56 -0
- data/lib/mongory/matchers/exists_matcher.rb +53 -0
- data/lib/mongory/matchers/field_matcher.rb +147 -0
- data/lib/mongory/matchers/gt_matcher.rb +41 -0
- data/lib/mongory/matchers/gte_matcher.rb +41 -0
- data/lib/mongory/matchers/hash_condition_matcher.rb +62 -0
- data/lib/mongory/matchers/in_matcher.rb +68 -0
- data/lib/mongory/matchers/literal_matcher.rb +121 -0
- data/lib/mongory/matchers/lt_matcher.rb +41 -0
- data/lib/mongory/matchers/lte_matcher.rb +41 -0
- data/lib/mongory/matchers/ne_matcher.rb +38 -0
- data/lib/mongory/matchers/nin_matcher.rb +68 -0
- data/lib/mongory/matchers/not_matcher.rb +40 -0
- data/lib/mongory/matchers/or_matcher.rb +68 -0
- data/lib/mongory/matchers/present_matcher.rb +55 -0
- data/lib/mongory/matchers/regex_matcher.rb +80 -0
- data/lib/mongory/matchers/size_matcher.rb +54 -0
- data/lib/mongory/matchers.rb +176 -0
- data/lib/mongory/mongoid.rb +19 -0
- data/lib/mongory/query_builder.rb +257 -0
- data/lib/mongory/query_matcher.rb +93 -0
- data/lib/mongory/query_operator.rb +28 -0
- data/lib/mongory/rails.rb +15 -0
- data/lib/mongory/utils/context.rb +48 -0
- data/lib/mongory/utils/debugger.rb +125 -0
- data/lib/mongory/utils/rails_patch.rb +22 -0
- data/lib/mongory/utils/singleton_builder.rb +31 -0
- data/lib/mongory/utils.rb +76 -0
- data/lib/mongory/version.rb +5 -0
- data/lib/mongory.rb +123 -0
- data/lib/mongory_ext.so +0 -0
- data/mongory.gemspec +62 -0
- data/scripts/build_with_core.sh +292 -0
- data/sig/mongory.rbs +4 -0
- metadata +159 -0
@@ -0,0 +1,683 @@
|
|
1
|
+
/**
|
2
|
+
* @file mongory_ext.c
|
3
|
+
* @brief Ruby C extension wrapper for mongory-core
|
4
|
+
*
|
5
|
+
* This file provides Ruby bindings for the mongory-core C library,
|
6
|
+
* allowing Ruby applications to use high-performance C-based matching
|
7
|
+
* operations while maintaining the elegant Ruby DSL.
|
8
|
+
*/
|
9
|
+
#include "mongory-core.h"
|
10
|
+
#include <ruby.h>
|
11
|
+
#include <ruby/encoding.h>
|
12
|
+
#include <string.h>
|
13
|
+
|
14
|
+
// Ruby module and class definitions
|
15
|
+
static VALUE mMongory;
|
16
|
+
static VALUE cMongoryMatcher;
|
17
|
+
static VALUE cMongoryMatcherContext;
|
18
|
+
static VALUE mMongoryMatchers;
|
19
|
+
|
20
|
+
// Error classes
|
21
|
+
static VALUE eMongoryError;
|
22
|
+
static VALUE eMongoryTypeError;
|
23
|
+
|
24
|
+
// Converter instance
|
25
|
+
static VALUE inMongoryDataConverter;
|
26
|
+
static VALUE inMongoryConditionConverter;
|
27
|
+
|
28
|
+
// Matcher wrapper structure
|
29
|
+
typedef struct ruby_mongory_matcher_t {
|
30
|
+
mongory_matcher *matcher;
|
31
|
+
mongory_value *condition;
|
32
|
+
mongory_memory_pool *pool;
|
33
|
+
mongory_memory_pool *scratch_pool;
|
34
|
+
mongory_table *string_map;
|
35
|
+
mongory_table *symbol_map;
|
36
|
+
mongory_array *mark_list;
|
37
|
+
bool trace_enabled;
|
38
|
+
VALUE ctx;
|
39
|
+
} ruby_mongory_matcher_t;
|
40
|
+
|
41
|
+
typedef struct ruby_mongory_memory_pool_t {
|
42
|
+
mongory_memory_pool base;
|
43
|
+
ruby_mongory_matcher_t *owner;
|
44
|
+
} ruby_mongory_memory_pool_t;
|
45
|
+
|
46
|
+
typedef struct ruby_mongory_table_t {
|
47
|
+
mongory_table base;
|
48
|
+
VALUE rb_hash;
|
49
|
+
ruby_mongory_matcher_t *owner;
|
50
|
+
} ruby_mongory_table_t;
|
51
|
+
|
52
|
+
typedef struct ruby_mongory_array_t {
|
53
|
+
mongory_array base;
|
54
|
+
VALUE rb_array;
|
55
|
+
ruby_mongory_matcher_t *owner;
|
56
|
+
} ruby_mongory_array_t;
|
57
|
+
|
58
|
+
typedef struct {
|
59
|
+
mongory_table *table;
|
60
|
+
mongory_memory_pool *pool;
|
61
|
+
} hash_conv_ctx;
|
62
|
+
|
63
|
+
// Forward declarations
|
64
|
+
static void ruby_mongory_matcher_mark(void *ptr);
|
65
|
+
static void ruby_mongory_matcher_free(void *ptr);
|
66
|
+
mongory_value *ruby_to_mongory_value_deep(mongory_memory_pool *pool, VALUE rb_value);
|
67
|
+
mongory_value *ruby_to_mongory_value_shallow(mongory_memory_pool *pool, VALUE rb_value);
|
68
|
+
mongory_value *ruby_mongory_table_wrap(mongory_memory_pool *pool, VALUE rb_hash);
|
69
|
+
mongory_value *ruby_mongory_array_wrap(mongory_memory_pool *pool, VALUE rb_array);
|
70
|
+
static VALUE cache_fetch_string(ruby_mongory_matcher_t *owner, const char *key);
|
71
|
+
static VALUE cache_fetch_symbol(ruby_mongory_matcher_t *owner, const char *key);
|
72
|
+
static ruby_mongory_memory_pool_t *ruby_mongory_memory_pool_new();
|
73
|
+
static void rb_mongory_matcher_parse_argv(ruby_mongory_matcher_t *wrapper, int argc, VALUE *argv);
|
74
|
+
static bool mongory_error_handling(mongory_memory_pool *pool, char *error_message);
|
75
|
+
|
76
|
+
static const rb_data_type_t ruby_mongory_matcher_type = {
|
77
|
+
.wrap_struct_name = "mongory_matcher",
|
78
|
+
.function = {
|
79
|
+
.dmark = ruby_mongory_matcher_mark,
|
80
|
+
.dfree = ruby_mongory_matcher_free,
|
81
|
+
.dsize = NULL,
|
82
|
+
},
|
83
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
84
|
+
};
|
85
|
+
|
86
|
+
/**
|
87
|
+
* Ruby method implementations
|
88
|
+
*/
|
89
|
+
|
90
|
+
// Mongory::CMatcher.new(condition)
|
91
|
+
static VALUE ruby_mongory_matcher_new(int argc, VALUE *argv, VALUE class) {
|
92
|
+
ruby_mongory_memory_pool_t *matcher_pool = ruby_mongory_memory_pool_new();
|
93
|
+
ruby_mongory_memory_pool_t *scratch_pool = ruby_mongory_memory_pool_new();
|
94
|
+
ruby_mongory_matcher_t *wrapper = ALLOC(ruby_mongory_matcher_t);
|
95
|
+
wrapper->pool = &matcher_pool->base;
|
96
|
+
wrapper->scratch_pool = &scratch_pool->base;
|
97
|
+
wrapper->string_map = mongory_table_new(wrapper->pool);
|
98
|
+
wrapper->symbol_map = mongory_table_new(wrapper->pool);
|
99
|
+
wrapper->mark_list = mongory_array_new(wrapper->pool);
|
100
|
+
wrapper->trace_enabled = false;
|
101
|
+
matcher_pool->owner = wrapper;
|
102
|
+
scratch_pool->owner = wrapper;
|
103
|
+
rb_mongory_matcher_parse_argv(wrapper, argc, argv);
|
104
|
+
|
105
|
+
mongory_matcher *matcher = mongory_matcher_new(wrapper->pool, wrapper->condition, wrapper->ctx);
|
106
|
+
if (mongory_error_handling(wrapper->pool, "Failed to create matcher")) {
|
107
|
+
return Qnil;
|
108
|
+
}
|
109
|
+
|
110
|
+
wrapper->matcher = matcher;
|
111
|
+
return TypedData_Wrap_Struct(class, &ruby_mongory_matcher_type, wrapper);
|
112
|
+
}
|
113
|
+
|
114
|
+
static void rb_mongory_matcher_parse_argv(ruby_mongory_matcher_t *wrapper, int argc, VALUE *argv) {
|
115
|
+
VALUE condition, kw_hash;
|
116
|
+
rb_scan_args(argc, argv, "1:", &condition, &kw_hash);
|
117
|
+
const ID ctx_id[1] = { rb_intern("context") };
|
118
|
+
VALUE kw_vals[1] = { Qundef };
|
119
|
+
if (kw_hash != Qnil) {
|
120
|
+
rb_get_kwargs(kw_hash, ctx_id, 1, 0, kw_vals);
|
121
|
+
}
|
122
|
+
if (kw_vals[0] != Qundef) {
|
123
|
+
wrapper->ctx = kw_vals[0];
|
124
|
+
} else {
|
125
|
+
wrapper->ctx = rb_funcall(cMongoryMatcherContext, rb_intern("new"), 0);
|
126
|
+
}
|
127
|
+
VALUE converted_condition = rb_funcall(inMongoryConditionConverter, rb_intern("convert"), 1, condition);
|
128
|
+
wrapper->condition = ruby_to_mongory_value_deep(wrapper->pool, converted_condition);
|
129
|
+
wrapper->mark_list->push(wrapper->mark_list, wrapper->condition);
|
130
|
+
mongory_value *store_ctx = mongory_value_wrap_u(wrapper->pool, (void *)wrapper->ctx);
|
131
|
+
store_ctx->origin = (void *)wrapper->ctx;
|
132
|
+
wrapper->mark_list->push(wrapper->mark_list, store_ctx);
|
133
|
+
}
|
134
|
+
|
135
|
+
// Mongory::CMatcher#match(data)
|
136
|
+
static VALUE ruby_mongory_matcher_match(VALUE self, VALUE data) {
|
137
|
+
ruby_mongory_matcher_t *wrapper;
|
138
|
+
TypedData_Get_Struct(self, ruby_mongory_matcher_t, &ruby_mongory_matcher_type, wrapper);
|
139
|
+
mongory_value *data_value;
|
140
|
+
data_value = ruby_to_mongory_value_shallow(wrapper->scratch_pool, data);
|
141
|
+
if (mongory_error_handling(wrapper->scratch_pool, "Match failed")) {
|
142
|
+
return Qnil;
|
143
|
+
}
|
144
|
+
bool result = mongory_matcher_match(wrapper->matcher, data_value);
|
145
|
+
if (!wrapper->trace_enabled) {
|
146
|
+
wrapper->scratch_pool->reset(wrapper->scratch_pool);
|
147
|
+
}
|
148
|
+
return result ? Qtrue : Qfalse;
|
149
|
+
}
|
150
|
+
|
151
|
+
// Mongory::CMatcher#explain
|
152
|
+
static VALUE ruby_mongory_matcher_explain(VALUE self) {
|
153
|
+
ruby_mongory_matcher_t *wrapper;
|
154
|
+
TypedData_Get_Struct(self, ruby_mongory_matcher_t, &ruby_mongory_matcher_type, wrapper);
|
155
|
+
mongory_matcher_explain(wrapper->matcher, wrapper->scratch_pool);
|
156
|
+
if (mongory_error_handling(wrapper->scratch_pool, "Explain failed")) {
|
157
|
+
return Qnil;
|
158
|
+
}
|
159
|
+
wrapper->scratch_pool->reset(wrapper->scratch_pool);
|
160
|
+
return Qnil;
|
161
|
+
}
|
162
|
+
|
163
|
+
// Mongory::CMatcher#trace(data)
|
164
|
+
static VALUE ruby_mongory_matcher_trace(VALUE self, VALUE data) {
|
165
|
+
ruby_mongory_matcher_t *wrapper;
|
166
|
+
TypedData_Get_Struct(self, ruby_mongory_matcher_t, &ruby_mongory_matcher_type, wrapper);
|
167
|
+
mongory_value *data_value = ruby_to_mongory_value_shallow(wrapper->scratch_pool, data);
|
168
|
+
if (mongory_error_handling(wrapper->scratch_pool, "Trace failed")) {
|
169
|
+
return Qnil;
|
170
|
+
}
|
171
|
+
bool matched = mongory_matcher_trace(wrapper->matcher, data_value);
|
172
|
+
wrapper->scratch_pool->reset(wrapper->scratch_pool);
|
173
|
+
return matched ? Qtrue : Qfalse;
|
174
|
+
}
|
175
|
+
|
176
|
+
// Mongory::CMatcher#enable_trace
|
177
|
+
static VALUE ruby_mongory_matcher_enable_trace(VALUE self) {
|
178
|
+
ruby_mongory_matcher_t *wrapper;
|
179
|
+
TypedData_Get_Struct(self, ruby_mongory_matcher_t, &ruby_mongory_matcher_type, wrapper);
|
180
|
+
mongory_matcher_enable_trace(wrapper->matcher, wrapper->scratch_pool);
|
181
|
+
if (mongory_error_handling(wrapper->scratch_pool, "Enable trace failed")) {
|
182
|
+
return Qnil;
|
183
|
+
}
|
184
|
+
wrapper->trace_enabled = true;
|
185
|
+
return Qnil;
|
186
|
+
}
|
187
|
+
|
188
|
+
// Mongory::CMatcher#disable_trace
|
189
|
+
static VALUE ruby_mongory_matcher_disable_trace(VALUE self) {
|
190
|
+
ruby_mongory_matcher_t *wrapper;
|
191
|
+
TypedData_Get_Struct(self, ruby_mongory_matcher_t, &ruby_mongory_matcher_type, wrapper);
|
192
|
+
mongory_matcher_disable_trace(wrapper->matcher);
|
193
|
+
if (mongory_error_handling(wrapper->scratch_pool, "Disable trace failed")) {
|
194
|
+
return Qnil;
|
195
|
+
}
|
196
|
+
wrapper->scratch_pool->reset(wrapper->scratch_pool);
|
197
|
+
wrapper->trace_enabled = false;
|
198
|
+
return Qnil;
|
199
|
+
}
|
200
|
+
|
201
|
+
// Mongory::CMatcher#print_trace
|
202
|
+
static VALUE ruby_mongory_matcher_print_trace(VALUE self) {
|
203
|
+
ruby_mongory_matcher_t *wrapper;
|
204
|
+
TypedData_Get_Struct(self, ruby_mongory_matcher_t, &ruby_mongory_matcher_type, wrapper);
|
205
|
+
mongory_matcher_print_trace(wrapper->matcher);
|
206
|
+
mongory_error_handling(wrapper->scratch_pool, "Print trace failed");
|
207
|
+
return Qnil;
|
208
|
+
}
|
209
|
+
|
210
|
+
// Mongory::CMatcher#condition
|
211
|
+
static VALUE ruby_mongory_matcher_condition(VALUE self) {
|
212
|
+
ruby_mongory_matcher_t *wrapper;
|
213
|
+
TypedData_Get_Struct(self, ruby_mongory_matcher_t, &ruby_mongory_matcher_type, wrapper);
|
214
|
+
return (VALUE)wrapper->condition->origin;
|
215
|
+
}
|
216
|
+
|
217
|
+
// Mongory::CMatcher#context
|
218
|
+
static VALUE ruby_mongory_matcher_context(VALUE self) {
|
219
|
+
ruby_mongory_matcher_t *wrapper;
|
220
|
+
TypedData_Get_Struct(self, ruby_mongory_matcher_t, &ruby_mongory_matcher_type, wrapper);
|
221
|
+
return wrapper->ctx ? wrapper->ctx : Qnil;
|
222
|
+
}
|
223
|
+
|
224
|
+
// Mongory::CMatcher.trace_result_colorful=(colorful)
|
225
|
+
static VALUE ruby_mongory_matcher_trace_result_colorful(VALUE self, VALUE colorful) {
|
226
|
+
(void)self;
|
227
|
+
mongory_matcher_trace_result_colorful_set(RTEST(colorful));
|
228
|
+
return Qnil;
|
229
|
+
}
|
230
|
+
|
231
|
+
/**
|
232
|
+
* Create a new memory pool
|
233
|
+
*/
|
234
|
+
static ruby_mongory_memory_pool_t *ruby_mongory_memory_pool_new() {
|
235
|
+
ruby_mongory_memory_pool_t *pool = malloc(sizeof(ruby_mongory_memory_pool_t));
|
236
|
+
mongory_memory_pool *base = mongory_memory_pool_new();
|
237
|
+
memcpy(&pool->base, base, sizeof(mongory_memory_pool));
|
238
|
+
free(base);
|
239
|
+
|
240
|
+
return pool;
|
241
|
+
}
|
242
|
+
|
243
|
+
/**
|
244
|
+
* Ruby GC management functions
|
245
|
+
*/
|
246
|
+
static void ruby_mongory_matcher_free(void *ptr) {
|
247
|
+
ruby_mongory_matcher_t *wrapper = (ruby_mongory_matcher_t *)ptr;
|
248
|
+
mongory_memory_pool *pool = wrapper->pool;
|
249
|
+
mongory_memory_pool *scratch_pool = wrapper->scratch_pool;
|
250
|
+
pool->free(pool);
|
251
|
+
scratch_pool->free(scratch_pool);
|
252
|
+
xfree(wrapper);
|
253
|
+
}
|
254
|
+
|
255
|
+
/**
|
256
|
+
* GC marking callback for mongory_array
|
257
|
+
*/
|
258
|
+
static bool gc_mark_array_cb(mongory_value *value, void *acc) {
|
259
|
+
(void)acc;
|
260
|
+
if (value && value->origin) rb_gc_mark((VALUE)value->origin);
|
261
|
+
return true;
|
262
|
+
}
|
263
|
+
|
264
|
+
/**
|
265
|
+
* GC marking callback for mongory_matcher
|
266
|
+
*/
|
267
|
+
static void ruby_mongory_matcher_mark(void *ptr) {
|
268
|
+
ruby_mongory_matcher_t *wrapper = (ruby_mongory_matcher_t *)ptr;
|
269
|
+
if (!wrapper) return;
|
270
|
+
wrapper->mark_list->each(wrapper->mark_list, NULL, gc_mark_array_cb);
|
271
|
+
}
|
272
|
+
|
273
|
+
/**
|
274
|
+
* Helper functions for Ruby/C conversion
|
275
|
+
*/
|
276
|
+
|
277
|
+
// Helper function to convert Ruby value to C string
|
278
|
+
static char *ruby_mongory_value_to_cstr(mongory_value *value, mongory_memory_pool *pool) {
|
279
|
+
(void)pool;
|
280
|
+
VALUE rb_value = (VALUE)value->origin;
|
281
|
+
VALUE rb_str = rb_funcall(rb_value, rb_intern("inspect"), 0);
|
282
|
+
return StringValueCStr(rb_str);
|
283
|
+
}
|
284
|
+
|
285
|
+
// Helper function for primitive conversion of Ruby value to mongory_value
|
286
|
+
static mongory_value *ruby_to_mongory_value_primitive(mongory_memory_pool *pool, VALUE rb_value) {
|
287
|
+
mongory_value *mg_value = NULL;
|
288
|
+
switch (TYPE(rb_value)) {
|
289
|
+
case T_NIL:
|
290
|
+
mg_value = mongory_value_wrap_n(pool, NULL);
|
291
|
+
break;
|
292
|
+
|
293
|
+
case T_TRUE:
|
294
|
+
mg_value = mongory_value_wrap_b(pool, true);
|
295
|
+
break;
|
296
|
+
|
297
|
+
case T_FALSE:
|
298
|
+
mg_value = mongory_value_wrap_b(pool, false);
|
299
|
+
break;
|
300
|
+
|
301
|
+
case T_FIXNUM:
|
302
|
+
mg_value = mongory_value_wrap_i(pool, rb_num2long_inline(rb_value));
|
303
|
+
break;
|
304
|
+
|
305
|
+
case T_BIGNUM:
|
306
|
+
mg_value = mongory_value_wrap_i(pool, rb_num2ll_inline(rb_value));
|
307
|
+
break;
|
308
|
+
|
309
|
+
case T_FLOAT:
|
310
|
+
mg_value = mongory_value_wrap_d(pool, rb_num2dbl(rb_value));
|
311
|
+
break;
|
312
|
+
|
313
|
+
case T_STRING:
|
314
|
+
mg_value = mongory_value_wrap_s(pool, StringValueCStr(rb_value));
|
315
|
+
break;
|
316
|
+
|
317
|
+
case T_SYMBOL:
|
318
|
+
mg_value = mongory_value_wrap_s(pool, (char *)rb_id2name(rb_sym2id(rb_value)));
|
319
|
+
break;
|
320
|
+
|
321
|
+
case T_REGEXP:
|
322
|
+
mg_value = mongory_value_wrap_regex(pool, (void *)rb_value);
|
323
|
+
break;
|
324
|
+
}
|
325
|
+
return mg_value;
|
326
|
+
}
|
327
|
+
// Shallow conversion: Convert Ruby value to mongory_value (fully materialize arrays/tables)
|
328
|
+
static mongory_value *ruby_to_mongory_value_shallow_rec(mongory_memory_pool *pool, VALUE rb_value, bool converted) {
|
329
|
+
mongory_value *mg_value = ruby_to_mongory_value_primitive(pool, rb_value);
|
330
|
+
if (mg_value) {
|
331
|
+
mg_value->origin = rb_value;
|
332
|
+
return mg_value;
|
333
|
+
}
|
334
|
+
|
335
|
+
switch (TYPE(rb_value)) {
|
336
|
+
case T_ARRAY: {
|
337
|
+
mg_value = ruby_mongory_array_wrap(pool, rb_value);
|
338
|
+
break;
|
339
|
+
}
|
340
|
+
|
341
|
+
case T_HASH: {
|
342
|
+
mg_value = ruby_mongory_table_wrap(pool, rb_value);
|
343
|
+
break;
|
344
|
+
}
|
345
|
+
|
346
|
+
default:
|
347
|
+
if (converted) {
|
348
|
+
mg_value = mongory_value_wrap_u(pool, (void *)rb_value);
|
349
|
+
break;
|
350
|
+
} else {
|
351
|
+
VALUE converted_value = rb_funcall(inMongoryDataConverter, rb_intern("convert"), 1, rb_value);
|
352
|
+
return ruby_to_mongory_value_shallow_rec(pool, converted_value, true);
|
353
|
+
}
|
354
|
+
}
|
355
|
+
mg_value->origin = rb_value;
|
356
|
+
return mg_value;
|
357
|
+
}
|
358
|
+
|
359
|
+
// Shallow conversion: Convert Ruby value to mongory_value (fully materialize arrays/tables)
|
360
|
+
mongory_value *ruby_to_mongory_value_shallow(mongory_memory_pool *pool, VALUE rb_value) {
|
361
|
+
return ruby_to_mongory_value_shallow_rec(pool, rb_value, false);
|
362
|
+
}
|
363
|
+
|
364
|
+
// Helper function for deep conversion of hash values
|
365
|
+
static int hash_foreach_deep_convert_cb(VALUE key, VALUE val, VALUE ptr) {
|
366
|
+
hash_conv_ctx *ctx = (hash_conv_ctx *)ptr;
|
367
|
+
ruby_mongory_memory_pool_t *rb_pool = (ruby_mongory_memory_pool_t *)ctx->pool;
|
368
|
+
ruby_mongory_matcher_t *owner = rb_pool->owner;
|
369
|
+
mongory_table *store_map;
|
370
|
+
char *key_str;
|
371
|
+
if (SYMBOL_P(key)) {
|
372
|
+
key_str = (char *)rb_id2name(SYM2ID(key));
|
373
|
+
store_map = owner->symbol_map;
|
374
|
+
} else {
|
375
|
+
key_str = StringValueCStr(key);
|
376
|
+
store_map = owner->string_map;
|
377
|
+
}
|
378
|
+
mongory_value *store = mongory_value_wrap_u(ctx->pool, NULL);
|
379
|
+
store->origin = (void *)key;
|
380
|
+
store_map->set(store_map, key_str, store);
|
381
|
+
mongory_value *cval = ruby_to_mongory_value_deep(ctx->pool, val);
|
382
|
+
ctx->table->set(ctx->table, key_str, cval);
|
383
|
+
return ST_CONTINUE;
|
384
|
+
}
|
385
|
+
|
386
|
+
// Deep conversion: Convert Ruby value to mongory_value (fully materialize arrays/tables)
|
387
|
+
static mongory_value *ruby_to_mongory_value_deep_rec(mongory_memory_pool *pool, VALUE rb_value, bool converted) {
|
388
|
+
mongory_value *mg_value = ruby_to_mongory_value_primitive(pool, rb_value);
|
389
|
+
if (mg_value) {
|
390
|
+
mg_value->origin = rb_value;
|
391
|
+
return mg_value;
|
392
|
+
}
|
393
|
+
switch (TYPE(rb_value)) {
|
394
|
+
case T_ARRAY: {
|
395
|
+
mongory_array *array = mongory_array_new(pool);
|
396
|
+
|
397
|
+
for (long i = 0; i < RARRAY_LEN(rb_value); i++) {
|
398
|
+
array->push(array, ruby_to_mongory_value_deep(pool, RARRAY_AREF(rb_value, i)));
|
399
|
+
}
|
400
|
+
mg_value = mongory_value_wrap_a(pool, array);
|
401
|
+
break;
|
402
|
+
}
|
403
|
+
|
404
|
+
case T_HASH: {
|
405
|
+
mongory_table *table = mongory_table_new(pool);
|
406
|
+
|
407
|
+
hash_conv_ctx ctx = {table, pool};
|
408
|
+
rb_hash_foreach(rb_value, hash_foreach_deep_convert_cb, (VALUE)&ctx);
|
409
|
+
|
410
|
+
mg_value = mongory_value_wrap_t(pool, table);
|
411
|
+
break;
|
412
|
+
}
|
413
|
+
|
414
|
+
default:
|
415
|
+
if (converted) {
|
416
|
+
mg_value = mongory_value_wrap_u(pool, (void *)rb_value);
|
417
|
+
break;
|
418
|
+
} else {
|
419
|
+
VALUE converted_value = rb_funcall(inMongoryDataConverter, rb_intern("convert"), 1, rb_value);
|
420
|
+
mg_value = ruby_to_mongory_value_deep_rec(pool, converted_value, true);
|
421
|
+
break;
|
422
|
+
}
|
423
|
+
}
|
424
|
+
mg_value->origin = rb_value;
|
425
|
+
return mg_value;
|
426
|
+
}
|
427
|
+
|
428
|
+
// Deep conversion: Convert Ruby value to mongory_value (fully materialize arrays/tables)
|
429
|
+
mongory_value *ruby_to_mongory_value_deep(mongory_memory_pool *pool, VALUE rb_value) {
|
430
|
+
return ruby_to_mongory_value_deep_rec(pool, rb_value, false);
|
431
|
+
}
|
432
|
+
|
433
|
+
// Get value from Ruby hash via mongory_table
|
434
|
+
mongory_value *ruby_mongory_table_get(mongory_table *self, char *key) {
|
435
|
+
ruby_mongory_table_t *table = (ruby_mongory_table_t *)self;
|
436
|
+
VALUE rb_hash = table->rb_hash;
|
437
|
+
VALUE rb_value = Qundef;
|
438
|
+
|
439
|
+
// Use cached Ruby String key if possible
|
440
|
+
VALUE key_str = cache_fetch_string(table->owner, key);
|
441
|
+
rb_value = rb_hash_lookup2(rb_hash, key_str, Qundef);
|
442
|
+
|
443
|
+
if (rb_value == Qundef) {
|
444
|
+
// Fallback to Symbol key, using cache
|
445
|
+
VALUE key_sym = cache_fetch_symbol(table->owner, key);
|
446
|
+
rb_value = rb_hash_lookup2(rb_hash, key_sym, Qundef);
|
447
|
+
}
|
448
|
+
|
449
|
+
if (rb_value == Qundef) {
|
450
|
+
return NULL;
|
451
|
+
}
|
452
|
+
return ruby_to_mongory_value_shallow(table->base.pool, rb_value);
|
453
|
+
}
|
454
|
+
|
455
|
+
// Shallow conversion: Wrap Ruby hash as mongory_table
|
456
|
+
mongory_value *ruby_mongory_table_wrap(mongory_memory_pool *pool, VALUE rb_hash) {
|
457
|
+
ruby_mongory_table_t *table = MG_ALLOC_PTR(pool, ruby_mongory_table_t);
|
458
|
+
ruby_mongory_memory_pool_t *rb_pool = (ruby_mongory_memory_pool_t *)pool;
|
459
|
+
table->base.pool = pool;
|
460
|
+
table->base.get = ruby_mongory_table_get;
|
461
|
+
table->rb_hash = rb_hash;
|
462
|
+
table->base.count = RHASH_SIZE(rb_hash);
|
463
|
+
table->owner = rb_pool->owner;
|
464
|
+
mongory_value *mg_value = mongory_value_wrap_t(pool, &table->base);
|
465
|
+
mg_value->origin = (void *)rb_hash;
|
466
|
+
mg_value->to_str = ruby_mongory_value_to_cstr;
|
467
|
+
return mg_value;
|
468
|
+
}
|
469
|
+
|
470
|
+
// Get value from Ruby array via mongory_array
|
471
|
+
static mongory_value *ruby_mongory_array_get(mongory_array *self, size_t index) {
|
472
|
+
ruby_mongory_array_t *array = (ruby_mongory_array_t *)self;
|
473
|
+
VALUE rb_array = array->rb_array;
|
474
|
+
if (index >= (size_t)RARRAY_LEN(rb_array)) {
|
475
|
+
return NULL;
|
476
|
+
}
|
477
|
+
VALUE rb_value = rb_ary_entry(rb_array, index);
|
478
|
+
return ruby_to_mongory_value_shallow(self->pool, rb_value);
|
479
|
+
}
|
480
|
+
|
481
|
+
// Shallow conversion: Wrap Ruby array as mongory_array
|
482
|
+
mongory_value *ruby_mongory_array_wrap(mongory_memory_pool *pool, VALUE rb_array) {
|
483
|
+
ruby_mongory_array_t *array = MG_ALLOC_PTR(pool, ruby_mongory_array_t);
|
484
|
+
ruby_mongory_memory_pool_t *rb_pool = (ruby_mongory_memory_pool_t *)pool;
|
485
|
+
array->base.pool = pool;
|
486
|
+
array->base.get = ruby_mongory_array_get;
|
487
|
+
array->rb_array = rb_array;
|
488
|
+
array->base.count = RARRAY_LEN(rb_array);
|
489
|
+
array->owner = rb_pool->owner;
|
490
|
+
mongory_value *mg_value = mongory_value_wrap_a(pool, &array->base);
|
491
|
+
mg_value->origin = (void *)rb_array;
|
492
|
+
mg_value->to_str = ruby_mongory_value_to_cstr;
|
493
|
+
return mg_value;
|
494
|
+
}
|
495
|
+
|
496
|
+
// Convert mongory_value to Ruby value (returns the original Ruby value where binding in below conversion is needed)
|
497
|
+
void *mongory_value_to_ruby(mongory_memory_pool *pool, mongory_value *value) {
|
498
|
+
(void)pool;
|
499
|
+
if (!value)
|
500
|
+
return NULL;
|
501
|
+
return value->origin;
|
502
|
+
}
|
503
|
+
|
504
|
+
// ===== Cache helper implementations =====
|
505
|
+
static VALUE cache_fetch_string(ruby_mongory_matcher_t *owner, const char *key) {
|
506
|
+
if (!owner || !owner->string_map) return rb_utf8_str_new_cstr(key);
|
507
|
+
mongory_value *v = owner->string_map->get(owner->string_map, (char *)key);
|
508
|
+
if (v && v->origin) return (VALUE)v->origin;
|
509
|
+
VALUE s = rb_utf8_str_new_cstr(key);
|
510
|
+
mongory_value *store = mongory_value_wrap_u(owner->pool, NULL);
|
511
|
+
store->origin = (void *)s;
|
512
|
+
owner->string_map->set(owner->string_map, (char *)key, store);
|
513
|
+
owner->mark_list->push(owner->mark_list, store);
|
514
|
+
return s;
|
515
|
+
}
|
516
|
+
|
517
|
+
// Helper function to convert char* key to Ruby symbol
|
518
|
+
static inline VALUE char_key_to_symbol(const char *key, rb_encoding *enc) {
|
519
|
+
ID id = rb_check_id_cstr(key, (long)strlen(key), enc);
|
520
|
+
if (!id) id = rb_intern3(key, (long)strlen(key), enc);
|
521
|
+
return ID2SYM(id);
|
522
|
+
}
|
523
|
+
|
524
|
+
// Cache helper for Ruby symbol keys
|
525
|
+
static VALUE cache_fetch_symbol(ruby_mongory_matcher_t *owner, const char *key) {
|
526
|
+
rb_encoding *enc = rb_utf8_encoding();
|
527
|
+
if (!owner || !owner->symbol_map) {
|
528
|
+
return char_key_to_symbol(key, enc);
|
529
|
+
}
|
530
|
+
mongory_value *v = owner->symbol_map->get(owner->symbol_map, (char *)key);
|
531
|
+
if (v && v->origin) return (VALUE)v->origin;
|
532
|
+
VALUE sym = char_key_to_symbol(key, enc);
|
533
|
+
mongory_value *store = mongory_value_wrap_u(owner->pool, NULL);
|
534
|
+
store->origin = (void *)sym;
|
535
|
+
owner->symbol_map->set(owner->symbol_map, (char *)key, store);
|
536
|
+
owner->mark_list->push(owner->mark_list, store);
|
537
|
+
return sym;
|
538
|
+
}
|
539
|
+
|
540
|
+
// Regex adapter bridging to Ruby's Regexp
|
541
|
+
static bool ruby_regex_match_adapter(mongory_memory_pool *pool, mongory_value *pattern, mongory_value *value) {
|
542
|
+
if (!pattern || !value) {
|
543
|
+
return false;
|
544
|
+
}
|
545
|
+
if (value->type != MONGORY_TYPE_STRING) {
|
546
|
+
return false;
|
547
|
+
}
|
548
|
+
|
549
|
+
VALUE rb_str = (VALUE)value->origin;
|
550
|
+
VALUE rb_re = Qnil;
|
551
|
+
|
552
|
+
if (pattern->type == MONGORY_TYPE_REGEX && pattern->data.regex) {
|
553
|
+
rb_re = (VALUE)pattern->data.regex;
|
554
|
+
} else if (pattern->type == MONGORY_TYPE_STRING) {
|
555
|
+
rb_re = rb_funcall(rb_cRegexp, rb_intern("new"), 1, (VALUE)pattern->origin);
|
556
|
+
mongory_value *temp_value = mongory_value_wrap_regex(pool, (void *)rb_re);
|
557
|
+
memcpy(pattern, temp_value, sizeof(mongory_value));
|
558
|
+
pattern->origin = (void *)rb_re;
|
559
|
+
} else {
|
560
|
+
return false;
|
561
|
+
}
|
562
|
+
|
563
|
+
VALUE matched = rb_funcall(rb_re, rb_intern("match?"), 1, rb_str);
|
564
|
+
return RTEST(matched);
|
565
|
+
}
|
566
|
+
|
567
|
+
// Regex adapter bridging to Ruby's Regexp
|
568
|
+
static char *ruby_regex_stringify_adapter(mongory_memory_pool *pool, mongory_value *pattern) {
|
569
|
+
(void)pool;
|
570
|
+
if (pattern->type != MONGORY_TYPE_REGEX) {
|
571
|
+
return NULL;
|
572
|
+
}
|
573
|
+
VALUE rb_re = (VALUE)pattern->data.regex;
|
574
|
+
VALUE rb_str = rb_funcall(rb_re, rb_intern("inspect"), 0);
|
575
|
+
return StringValueCStr(rb_str);
|
576
|
+
}
|
577
|
+
|
578
|
+
// Custom matcher adapter bridging to Ruby's custom matcher
|
579
|
+
static mongory_matcher_custom_context *ruby_custom_matcher_build(char *key, mongory_value *condition, void *ctx) {
|
580
|
+
mongory_memory_pool *pool = condition->pool;
|
581
|
+
ruby_mongory_memory_pool_t *rb_pool = (ruby_mongory_memory_pool_t *)pool;
|
582
|
+
ruby_mongory_matcher_t *owner = rb_pool->owner;
|
583
|
+
VALUE matcher_class = rb_funcall(mMongoryMatchers, rb_intern("lookup"), 1, cache_fetch_string(owner, key));
|
584
|
+
if (matcher_class == Qnil) {
|
585
|
+
return NULL;
|
586
|
+
}
|
587
|
+
VALUE kw_hash = rb_hash_new();
|
588
|
+
rb_hash_aset(kw_hash, ID2SYM(rb_intern("context")), (VALUE)ctx);
|
589
|
+
|
590
|
+
#ifdef RB_PASS_KEYWORDS
|
591
|
+
VALUE argv_new[2] = { (VALUE)condition->origin, kw_hash };
|
592
|
+
VALUE matcher = rb_funcallv_kw(matcher_class, rb_intern("new"), 2, argv_new, RB_PASS_KEYWORDS);
|
593
|
+
#else
|
594
|
+
VALUE matcher = rb_funcall(matcher_class, rb_intern("new"), 2, (VALUE)condition->origin, kw_hash);
|
595
|
+
#endif
|
596
|
+
|
597
|
+
if (matcher == Qnil) {
|
598
|
+
return NULL;
|
599
|
+
}
|
600
|
+
mongory_value *matcher_value = mongory_value_wrap_u(pool, NULL);
|
601
|
+
matcher_value->origin = (void *)matcher;
|
602
|
+
owner->mark_list->push(owner->mark_list, matcher_value);
|
603
|
+
VALUE class_name = rb_funcall(matcher_class, rb_intern("name"), 0);
|
604
|
+
mongory_matcher_custom_context *return_ctx = MG_ALLOC_PTR(pool, mongory_matcher_custom_context);
|
605
|
+
if (return_ctx == NULL) {
|
606
|
+
return NULL;
|
607
|
+
}
|
608
|
+
return_ctx->name = StringValueCStr(class_name);
|
609
|
+
return_ctx->external_matcher = (void *)matcher;
|
610
|
+
return return_ctx;
|
611
|
+
}
|
612
|
+
|
613
|
+
// Custom matcher adapter bridging to Ruby's custom matcher
|
614
|
+
static bool ruby_custom_matcher_match(void *ruby_matcher, mongory_value *value) {
|
615
|
+
VALUE matcher = (VALUE)ruby_matcher;
|
616
|
+
VALUE match_result = rb_funcall(matcher, rb_intern("match?"), 1, value->origin);
|
617
|
+
return RTEST(match_result);
|
618
|
+
}
|
619
|
+
|
620
|
+
// Custom matcher adapter bridging to Ruby's custom matcher
|
621
|
+
static bool ruby_custom_matcher_lookup(char *key) {
|
622
|
+
VALUE matcher_class = rb_funcall(mMongoryMatchers, rb_intern("lookup"), 1, rb_str_new_cstr(key));
|
623
|
+
return RTEST(matcher_class);
|
624
|
+
}
|
625
|
+
|
626
|
+
// Error handling for mongory_memory_pool
|
627
|
+
static bool mongory_error_handling(mongory_memory_pool *pool, char *error_message) {
|
628
|
+
if (pool->error) {
|
629
|
+
rb_raise(eMongoryTypeError, "%s: %s", error_message, pool->error->message);
|
630
|
+
pool->error = NULL;
|
631
|
+
pool->reset(pool);
|
632
|
+
return true;
|
633
|
+
}
|
634
|
+
return false;
|
635
|
+
}
|
636
|
+
|
637
|
+
/**
|
638
|
+
* Extension initialization
|
639
|
+
*/
|
640
|
+
void Init_mongory_ext(void) {
|
641
|
+
// Initialize mongory core
|
642
|
+
mongory_init();
|
643
|
+
|
644
|
+
// Define modules and classes
|
645
|
+
mMongory = rb_define_module("Mongory");
|
646
|
+
cMongoryMatcher = rb_define_class_under(mMongory, "CMatcher", rb_cObject);
|
647
|
+
mMongoryMatchers = rb_define_module_under(mMongory, "Matchers");
|
648
|
+
VALUE mMongoryUtils = rb_define_module_under(mMongory, "Utils");
|
649
|
+
cMongoryMatcherContext = rb_define_class_under(mMongoryUtils, "Context", rb_cObject);
|
650
|
+
// Mongory converters
|
651
|
+
inMongoryDataConverter = rb_funcall(mMongory, rb_intern("data_converter"), 0);
|
652
|
+
inMongoryConditionConverter = rb_funcall(mMongory, rb_intern("condition_converter"), 0);
|
653
|
+
|
654
|
+
// Define error classes
|
655
|
+
eMongoryError = rb_define_class_under(mMongory, "Error", rb_eStandardError);
|
656
|
+
eMongoryTypeError = rb_define_class_under(mMongory, "TypeError", eMongoryError);
|
657
|
+
|
658
|
+
// Define Matcher methods
|
659
|
+
rb_define_singleton_method(cMongoryMatcher, "new", ruby_mongory_matcher_new, -1);
|
660
|
+
rb_define_singleton_method(cMongoryMatcher, "trace_result_colorful=", ruby_mongory_matcher_trace_result_colorful, 1);
|
661
|
+
rb_define_method(cMongoryMatcher, "match?", ruby_mongory_matcher_match, 1);
|
662
|
+
rb_define_method(cMongoryMatcher, "explain", ruby_mongory_matcher_explain, 0);
|
663
|
+
rb_define_method(cMongoryMatcher, "condition", ruby_mongory_matcher_condition, 0);
|
664
|
+
rb_define_method(cMongoryMatcher, "context", ruby_mongory_matcher_context, 0);
|
665
|
+
rb_define_method(cMongoryMatcher, "trace", ruby_mongory_matcher_trace, 1);
|
666
|
+
rb_define_method(cMongoryMatcher, "enable_trace", ruby_mongory_matcher_enable_trace, 0);
|
667
|
+
rb_define_method(cMongoryMatcher, "disable_trace", ruby_mongory_matcher_disable_trace, 0);
|
668
|
+
rb_define_method(cMongoryMatcher, "print_trace", ruby_mongory_matcher_print_trace, 0);
|
669
|
+
|
670
|
+
// Set regex adapter to use Ruby's Regexp
|
671
|
+
mongory_regex_func_set(ruby_regex_match_adapter);
|
672
|
+
mongory_regex_stringify_func_set(ruby_regex_stringify_adapter);
|
673
|
+
|
674
|
+
// Set value converter functions
|
675
|
+
mongory_value_converter_deep_convert_set(ruby_to_mongory_value_deep);
|
676
|
+
mongory_value_converter_shallow_convert_set(ruby_to_mongory_value_shallow);
|
677
|
+
mongory_value_converter_recover_set(mongory_value_to_ruby);
|
678
|
+
|
679
|
+
// Set custom matcher adapter
|
680
|
+
mongory_custom_matcher_match_func_set(ruby_custom_matcher_match);
|
681
|
+
mongory_custom_matcher_build_func_set(ruby_custom_matcher_build);
|
682
|
+
mongory_custom_matcher_lookup_func_set(ruby_custom_matcher_lookup);
|
683
|
+
}
|