mongory 0.7.2-arm64-darwin-23
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.
- 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.bundle +0 -0
- data/mongory.gemspec +50 -0
- data/scripts/build_with_core.sh +292 -0
- data/sig/mongory.rbs +4 -0
- metadata +164 -0
@@ -0,0 +1,287 @@
|
|
1
|
+
/**
|
2
|
+
* @file array.c
|
3
|
+
* @brief Implements the mongory_array dynamic array.
|
4
|
+
*
|
5
|
+
* This file contains the internal implementation details for the mongory_array,
|
6
|
+
* including memory management, resizing, and the core array operations.
|
7
|
+
* It uses a private structure `mongory_array_private` which extends
|
8
|
+
* `mongory_array` with capacity information and the actual item storage.
|
9
|
+
*/
|
10
|
+
|
11
|
+
#include <string.h>
|
12
|
+
#include "array_private.h"
|
13
|
+
#include <mongory-core/foundations/array.h>
|
14
|
+
#include <mongory-core/foundations/memory_pool.h>
|
15
|
+
#include <stdarg.h>
|
16
|
+
#include <mongory-core/foundations/value.h>
|
17
|
+
|
18
|
+
/**
|
19
|
+
* @def MONGORY_ARRAY_INIT_SIZE
|
20
|
+
* @brief Initial capacity of a newly created mongory_array.
|
21
|
+
*/
|
22
|
+
#define MONGORY_ARRAY_INIT_SIZE 4
|
23
|
+
|
24
|
+
/**
|
25
|
+
* @brief Resizes the internal storage of the array.
|
26
|
+
*
|
27
|
+
* Allocates a new block of memory for items and copies existing items to it.
|
28
|
+
* The old item storage is not explicitly freed here as it's managed by the
|
29
|
+
* memory pool; this function assumes the new allocation replaces the old one
|
30
|
+
* in terms of where `internal->items` points.
|
31
|
+
*
|
32
|
+
* @param self Pointer to the mongory_array instance.
|
33
|
+
* @param size The new capacity (number of elements) for the array.
|
34
|
+
* @return true if resizing was successful, false otherwise (e.g., memory
|
35
|
+
* allocation failure).
|
36
|
+
*/
|
37
|
+
bool mongory_array_resize(mongory_array *self, size_t size) {
|
38
|
+
mongory_array_private *internal = (mongory_array_private *)self;
|
39
|
+
|
40
|
+
// Allocate a new, larger block of memory for the items.
|
41
|
+
mongory_value **new_items = MG_ALLOC_ARY(self->pool, mongory_value*, size);
|
42
|
+
if (!new_items) {
|
43
|
+
self->pool->error = &MONGORY_ALLOC_ERROR;
|
44
|
+
return false;
|
45
|
+
}
|
46
|
+
|
47
|
+
// Copy existing item pointers to the new memory block.
|
48
|
+
memcpy(new_items, internal->items, sizeof(mongory_value *) * self->count);
|
49
|
+
|
50
|
+
internal->items = new_items;
|
51
|
+
internal->capacity = size;
|
52
|
+
return true;
|
53
|
+
}
|
54
|
+
|
55
|
+
/**
|
56
|
+
* @brief Ensures the array has enough capacity for a given size, growing it if
|
57
|
+
* necessary.
|
58
|
+
*
|
59
|
+
* If the required size is smaller than the current capacity, this function does
|
60
|
+
* nothing. Otherwise, it calculates a new capacity (typically double the
|
61
|
+
* current, or more if needed to fit `size`) and calls mongory_array_resize.
|
62
|
+
*
|
63
|
+
* @param self Pointer to the mongory_array instance.
|
64
|
+
* @param size The minimum number of elements the array needs to accommodate.
|
65
|
+
* @return true if the array has sufficient capacity (or was successfully
|
66
|
+
* grown), false otherwise.
|
67
|
+
*/
|
68
|
+
// ============================================================================
|
69
|
+
// Static Helper Functions
|
70
|
+
// ============================================================================
|
71
|
+
static inline bool mongory_array_grow_if_needed(mongory_array *self, size_t size) {
|
72
|
+
mongory_array_private *internal = (mongory_array_private *)self;
|
73
|
+
if (size < internal->capacity) {
|
74
|
+
return true;
|
75
|
+
}
|
76
|
+
|
77
|
+
// Calculate new capacity, typically doubling, until it's sufficient.
|
78
|
+
size_t new_capacity = internal->capacity * 2;
|
79
|
+
while (new_capacity <= size) {
|
80
|
+
new_capacity *= 2;
|
81
|
+
}
|
82
|
+
|
83
|
+
return mongory_array_resize(self, new_capacity);
|
84
|
+
}
|
85
|
+
|
86
|
+
/**
|
87
|
+
* @brief Internal implementation for iterating over array elements.
|
88
|
+
* @param self Pointer to the mongory_array instance.
|
89
|
+
* @param acc Accumulator/context passed to the callback.
|
90
|
+
* @param func Callback function executed for each item.
|
91
|
+
* @return true if iteration completed, false if callback stopped it.
|
92
|
+
*/
|
93
|
+
static inline bool mongory_array_each(mongory_array *self, void *acc, mongory_array_callback_func func) {
|
94
|
+
mongory_array_private *internal = (mongory_array_private *)self;
|
95
|
+
for (size_t i = 0; i < self->count; i++) {
|
96
|
+
mongory_value *item = internal->items[i];
|
97
|
+
if (!func(item, acc)) {
|
98
|
+
return false; // Callback requested to stop iteration.
|
99
|
+
}
|
100
|
+
}
|
101
|
+
return true;
|
102
|
+
}
|
103
|
+
|
104
|
+
/**
|
105
|
+
* @brief Internal implementation for adding an element to the end of the array.
|
106
|
+
* Grows the array if necessary.
|
107
|
+
* @param self Pointer to the mongory_array instance.
|
108
|
+
* @param value The mongory_value to add.
|
109
|
+
* @return true if successful, false on failure (e.g., memory allocation).
|
110
|
+
*/
|
111
|
+
static inline bool mongory_array_push(mongory_array *self, mongory_value *value) {
|
112
|
+
mongory_array_private *internal = (mongory_array_private *)self;
|
113
|
+
// Ensure there's space for one more element (current count).
|
114
|
+
if (!mongory_array_grow_if_needed(self, self->count)) {
|
115
|
+
return false;
|
116
|
+
}
|
117
|
+
|
118
|
+
internal->items[self->count++] = value;
|
119
|
+
return true;
|
120
|
+
}
|
121
|
+
|
122
|
+
/**
|
123
|
+
* @brief Internal implementation for retrieving an element by index.
|
124
|
+
* @param self Pointer to the mongory_array instance.
|
125
|
+
* @param index The index of the element.
|
126
|
+
* @return Pointer to the mongory_value, or NULL if index is out of bounds.
|
127
|
+
*/
|
128
|
+
static inline mongory_value *mongory_array_get(mongory_array *self, size_t index) {
|
129
|
+
mongory_array_private *internal = (mongory_array_private *)self;
|
130
|
+
if (index >= self->count) {
|
131
|
+
return NULL; // Index out of bounds.
|
132
|
+
}
|
133
|
+
return internal->items[index];
|
134
|
+
}
|
135
|
+
|
136
|
+
/**
|
137
|
+
* @brief Internal implementation for setting an element at a specific index.
|
138
|
+
*
|
139
|
+
* Grows the array if necessary. If the index is beyond the current count,
|
140
|
+
* intermediate elements are set to NULL, and the array's count is updated.
|
141
|
+
*
|
142
|
+
* @param self Pointer to the mongory_array instance.
|
143
|
+
* @param index The index at which to set the value.
|
144
|
+
* @param value The mongory_value to set.
|
145
|
+
* @return true if successful, false on failure (e.g., memory allocation).
|
146
|
+
*/
|
147
|
+
static inline bool mongory_array_set(mongory_array *self, size_t index, mongory_value *value) {
|
148
|
+
mongory_array_private *internal = (mongory_array_private *)self;
|
149
|
+
// Ensure capacity for the given index (index + 1 elements).
|
150
|
+
if (!mongory_array_grow_if_needed(self, index + 1)) {
|
151
|
+
return false;
|
152
|
+
}
|
153
|
+
|
154
|
+
// If setting beyond the current count, fill intermediate spots with NULL.
|
155
|
+
if (index >= self->count) {
|
156
|
+
for (size_t i = self->count; i < index; i++) {
|
157
|
+
internal->items[i] = NULL;
|
158
|
+
}
|
159
|
+
self->count = index + 1; // Update count to include the new element.
|
160
|
+
}
|
161
|
+
|
162
|
+
internal->items[index] = value;
|
163
|
+
return true;
|
164
|
+
}
|
165
|
+
|
166
|
+
/**
|
167
|
+
* @brief Creates and initializes a new mongory_array.
|
168
|
+
*
|
169
|
+
* Allocates memory for the array structure itself and its initial item storage
|
170
|
+
* using the provided memory pool. Assigns function pointers for array
|
171
|
+
* operations.
|
172
|
+
*
|
173
|
+
* @param pool The memory pool to use for allocations.
|
174
|
+
* @return Pointer to the new mongory_array, or NULL on allocation failure.
|
175
|
+
*/
|
176
|
+
mongory_array *mongory_array_new(mongory_memory_pool *pool) {
|
177
|
+
// First, allocate the private structure that holds all array metadata.
|
178
|
+
mongory_array_private *internal = MG_ALLOC_PTR(pool, mongory_array_private);
|
179
|
+
if (!internal) {
|
180
|
+
pool->error = &MONGORY_ALLOC_ERROR;
|
181
|
+
return NULL;
|
182
|
+
}
|
183
|
+
|
184
|
+
// Then, allocate the initial block of memory for the array items.
|
185
|
+
mongory_value **items = MG_ALLOC_ARY(pool, mongory_value*, MONGORY_ARRAY_INIT_SIZE);
|
186
|
+
if (!items) {
|
187
|
+
// If this fails, the 'internal' struct allocated above will be cleaned up
|
188
|
+
// by the pool, assuming it's a tracing pool.
|
189
|
+
pool->error = &MONGORY_ALLOC_ERROR;
|
190
|
+
return NULL;
|
191
|
+
}
|
192
|
+
|
193
|
+
// Initialize the public part of the array structure.
|
194
|
+
internal->base.pool = pool;
|
195
|
+
internal->base.count = 0;
|
196
|
+
internal->base.each = mongory_array_each;
|
197
|
+
internal->base.get = mongory_array_get;
|
198
|
+
internal->base.push = mongory_array_push;
|
199
|
+
internal->base.set = mongory_array_set;
|
200
|
+
|
201
|
+
// Initialize the private part of the array structure.
|
202
|
+
internal->items = items;
|
203
|
+
internal->capacity = MONGORY_ARRAY_INIT_SIZE;
|
204
|
+
|
205
|
+
return &internal->base; // Return pointer to the public structure.
|
206
|
+
}
|
207
|
+
|
208
|
+
/**
|
209
|
+
* @brief Creates a new mongory_array instance with a nested array.
|
210
|
+
*
|
211
|
+
* This function is used to create a new mongory_array instance with a nested
|
212
|
+
* array. The nested array is created with the given memory pool and the given
|
213
|
+
* values. The nested array is returned as a pointer to the mongory_array structure.
|
214
|
+
*
|
215
|
+
* @param pool A pointer to the mongory_memory_pool to be used for allocations.
|
216
|
+
* @param argc The number of values to be set.
|
217
|
+
* @param ... The values to be set.
|
218
|
+
* @return mongory_array* A pointer to the newly created mongory_array, or NULL
|
219
|
+
* if creation fails (e.g., memory allocation failure).
|
220
|
+
*/
|
221
|
+
mongory_array *mongory_array_nested_wrap(mongory_memory_pool *pool, int argc, ...) {
|
222
|
+
mongory_array *array = mongory_array_new(pool);
|
223
|
+
if (!array) {
|
224
|
+
return NULL;
|
225
|
+
}
|
226
|
+
va_list args;
|
227
|
+
va_start(args, argc);
|
228
|
+
for (int i = 0; i < argc; i++) {
|
229
|
+
mongory_value *value = va_arg(args, mongory_value *);
|
230
|
+
array->push(array, value);
|
231
|
+
}
|
232
|
+
va_end(args);
|
233
|
+
return array;
|
234
|
+
}
|
235
|
+
|
236
|
+
typedef size_t(*mongory_array_sort_cb)(mongory_value *value, void *ctx);
|
237
|
+
|
238
|
+
static mongory_value** mongory_array_merge_sort_finalize(mongory_memory_pool *pool, mongory_value **left, mongory_value **right, size_t count, void *ctx, mongory_array_sort_cb callback) {
|
239
|
+
mongory_value **result = MG_ALLOC_ARY(pool, mongory_value*, count);
|
240
|
+
size_t i = 0, j = 0, k = 0;
|
241
|
+
while (i < count / 2 && j < count - count / 2) {
|
242
|
+
if (callback(left[i], ctx) < callback(right[j], ctx)) {
|
243
|
+
result[k++] = left[i++];
|
244
|
+
} else {
|
245
|
+
result[k++] = right[j++];
|
246
|
+
}
|
247
|
+
}
|
248
|
+
while (i < count / 2) {
|
249
|
+
result[k++] = left[i++];
|
250
|
+
}
|
251
|
+
while (j < count - count / 2) {
|
252
|
+
result[k++] = right[j++];
|
253
|
+
}
|
254
|
+
return result;
|
255
|
+
}
|
256
|
+
|
257
|
+
static mongory_value** mongory_array_merge_sort(mongory_memory_pool *pool, mongory_value **origin_items, size_t count, void *ctx, mongory_array_sort_cb callback) {
|
258
|
+
if (count <= 1) {
|
259
|
+
return origin_items;
|
260
|
+
}
|
261
|
+
size_t mid = count / 2;
|
262
|
+
mongory_value **left = mongory_array_merge_sort(pool, origin_items, mid, ctx, callback);
|
263
|
+
mongory_value **right = mongory_array_merge_sort(pool, origin_items + mid, count - mid, ctx, callback);
|
264
|
+
return mongory_array_merge_sort_finalize(pool, left, right, count, ctx, callback);
|
265
|
+
}
|
266
|
+
|
267
|
+
mongory_array *mongory_array_sort_by(mongory_array *self, mongory_memory_pool *temp_pool, void *ctx, mongory_array_sort_cb callback) {
|
268
|
+
mongory_array_private *internal = (mongory_array_private *)self;
|
269
|
+
|
270
|
+
mongory_value **new_items = mongory_array_merge_sort(temp_pool, internal->items, self->count, ctx, callback);
|
271
|
+
mongory_array_private *new_array = (mongory_array_private *)mongory_array_new(self->pool);
|
272
|
+
new_array->capacity = internal->capacity;
|
273
|
+
new_array->base.count = self->count;
|
274
|
+
new_array->items = MG_ALLOC_ARY(self->pool, mongory_value*, new_array->capacity);
|
275
|
+
memcpy(new_array->items, new_items, sizeof(mongory_value *) * self->count);
|
276
|
+
return &new_array->base;
|
277
|
+
}
|
278
|
+
|
279
|
+
bool mongory_array_includes(mongory_array *self, mongory_value *value) {
|
280
|
+
for (size_t i = 0; i < self->count; i++) {
|
281
|
+
mongory_value *item = self->get(self, i);
|
282
|
+
if (item->comp(item, value) == 0) {
|
283
|
+
return true;
|
284
|
+
}
|
285
|
+
}
|
286
|
+
return false;
|
287
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#ifndef MONGORY_ARRAY_PRIVATE_H
|
2
|
+
#define MONGORY_ARRAY_PRIVATE_H
|
3
|
+
#include "mongory-core/foundations/array.h"
|
4
|
+
#include "mongory-core/foundations/memory_pool.h"
|
5
|
+
#include "mongory-core/foundations/value.h"
|
6
|
+
#include <stdbool.h>
|
7
|
+
|
8
|
+
bool mongory_array_resize(mongory_array *self, size_t size); // resize array
|
9
|
+
|
10
|
+
typedef struct mongory_array_private {
|
11
|
+
mongory_array base; // public array
|
12
|
+
mongory_value **items; // items pointer
|
13
|
+
size_t capacity; // capacity
|
14
|
+
} mongory_array_private;
|
15
|
+
|
16
|
+
mongory_array *mongory_array_sort_by(mongory_array *self, mongory_memory_pool *temp_pool, void *ctx, size_t(*callback)(mongory_value *value, void *ctx));
|
17
|
+
bool mongory_array_includes(mongory_array *self, mongory_value *value);
|
18
|
+
|
19
|
+
#endif // MONGORY_ARRAY_PRIVATE_H
|
@@ -0,0 +1,270 @@
|
|
1
|
+
/**
|
2
|
+
* @file config.c
|
3
|
+
* @brief Implements global configuration and initialization for the Mongory
|
4
|
+
* library.
|
5
|
+
*
|
6
|
+
* This file manages the lifecycle of global resources such as the internal
|
7
|
+
* memory pool, regex adapter, matcher registration table, and value converters.
|
8
|
+
* It provides the `mongory_init` and `mongory_cleanup` functions, as well as
|
9
|
+
* setters for customizable components and a string copy utility.
|
10
|
+
*/
|
11
|
+
#include "mongory-core/foundations/config.h"
|
12
|
+
#include "../matchers/base_matcher.h" // For mongory_matcher_build_func
|
13
|
+
#include "../matchers/compare_matcher.h" // For specific matcher constructors
|
14
|
+
#include "../matchers/composite_matcher.h" // For specific matcher constructors
|
15
|
+
#include "../matchers/existance_matcher.h" // For specific matcher constructors
|
16
|
+
#include "../matchers/inclusion_matcher.h" // For specific matcher constructors
|
17
|
+
#include "../matchers/literal_matcher.h" // For specific matcher constructors
|
18
|
+
#include "../matchers/external_matcher.h" // For specific matcher constructors
|
19
|
+
#include "config_private.h" // For mongory_regex_adapter, mongory_value_converter, etc.
|
20
|
+
#include "mongory-core/foundations/memory_pool.h"
|
21
|
+
#include "mongory-core/foundations/table.h"
|
22
|
+
#include "mongory-core/foundations/value.h"
|
23
|
+
|
24
|
+
static bool mongory_regex_default_func(mongory_memory_pool *pool, mongory_value *pattern, mongory_value *value);
|
25
|
+
static char *mongory_regex_default_stringify_func(mongory_memory_pool *pool, mongory_value *pattern);
|
26
|
+
|
27
|
+
// Global internal memory pool for the library.
|
28
|
+
mongory_memory_pool *mongory_internal_pool = NULL;
|
29
|
+
// Global adapter for regex operations.
|
30
|
+
mongory_regex_adapter mongory_internal_regex_adapter = {
|
31
|
+
.match_func = mongory_regex_default_func,
|
32
|
+
.stringify_func = mongory_regex_default_stringify_func,
|
33
|
+
};
|
34
|
+
// Global table mapping matcher names (e.g., "$eq") to their build functions.
|
35
|
+
mongory_table *mongory_matcher_mapping = NULL;
|
36
|
+
// Global converter for handling external data types.
|
37
|
+
mongory_value_converter mongory_internal_value_converter = {
|
38
|
+
.deep_convert = NULL,
|
39
|
+
.shallow_convert = NULL,
|
40
|
+
.recover = NULL,
|
41
|
+
};
|
42
|
+
// Global adapter for custom matchers.
|
43
|
+
mongory_matcher_custom_adapter mongory_custom_matcher_adapter = {
|
44
|
+
.build = NULL,
|
45
|
+
.lookup = NULL,
|
46
|
+
.match = NULL,
|
47
|
+
};
|
48
|
+
|
49
|
+
bool mongory_matcher_trace_result_colorful = true;
|
50
|
+
|
51
|
+
/**
|
52
|
+
* @brief Initializes the internal memory pool if it hasn't been already.
|
53
|
+
* This pool is used for allocations by various library components.
|
54
|
+
*/
|
55
|
+
static inline void mongory_internal_pool_init() {
|
56
|
+
if (mongory_internal_pool != NULL) {
|
57
|
+
return; // Already initialized.
|
58
|
+
}
|
59
|
+
mongory_internal_pool = mongory_memory_pool_new();
|
60
|
+
// TODO: Add error handling if mongory_memory_pool_new returns NULL.
|
61
|
+
}
|
62
|
+
|
63
|
+
/**
|
64
|
+
* @brief Default regex function that always returns false.
|
65
|
+
* Used if no custom regex function is set via mongory_regex_func_set.
|
66
|
+
* @param pool Unused.
|
67
|
+
* @param pattern Unused.
|
68
|
+
* @param value Unused.
|
69
|
+
* @return Always false.
|
70
|
+
*/
|
71
|
+
static bool mongory_regex_default_func(mongory_memory_pool *pool, mongory_value *pattern, mongory_value *value) {
|
72
|
+
(void)pool; // Mark as unused to prevent compiler warnings.
|
73
|
+
(void)pattern; // Mark as unused.
|
74
|
+
(void)value; // Mark as unused.
|
75
|
+
return false; // Default behavior is no match.
|
76
|
+
}
|
77
|
+
|
78
|
+
static char *mongory_regex_default_stringify_func(mongory_memory_pool *pool, mongory_value *pattern) {
|
79
|
+
(void)pool; // Mark as unused to prevent compiler warnings.
|
80
|
+
(void)pattern; // Mark as unused.
|
81
|
+
return "//"; // Default behavior is no stringification.
|
82
|
+
}
|
83
|
+
|
84
|
+
/**
|
85
|
+
* @brief Sets the global regex matching function.
|
86
|
+
* Initializes the regex adapter if it's not already.
|
87
|
+
* @param func The custom regex function to use.
|
88
|
+
*/
|
89
|
+
void mongory_regex_func_set(mongory_regex_func func) {
|
90
|
+
mongory_internal_regex_adapter.match_func = func;
|
91
|
+
}
|
92
|
+
|
93
|
+
/**
|
94
|
+
* @brief Sets the global regex stringify function.
|
95
|
+
* Initializes the regex adapter if it's not already.
|
96
|
+
* @param func The custom regex stringify function to use.
|
97
|
+
*/
|
98
|
+
void mongory_regex_stringify_func_set(mongory_regex_stringify_func func) {
|
99
|
+
mongory_internal_regex_adapter.stringify_func = func;
|
100
|
+
}
|
101
|
+
/**
|
102
|
+
* @brief Initializes the matcher mapping table if it hasn't been already.
|
103
|
+
* This table stores registrations of matcher names to their constructor
|
104
|
+
* functions.
|
105
|
+
*/
|
106
|
+
static inline void mongory_matcher_mapping_init() {
|
107
|
+
if (mongory_matcher_mapping != NULL) {
|
108
|
+
return; // Already initialized.
|
109
|
+
}
|
110
|
+
|
111
|
+
// Ensure the internal pool is initialized first.
|
112
|
+
mongory_internal_pool_init();
|
113
|
+
if (mongory_internal_pool == NULL) {
|
114
|
+
return; // Cannot proceed if pool initialization failed.
|
115
|
+
}
|
116
|
+
|
117
|
+
mongory_matcher_mapping = mongory_table_new(mongory_internal_pool);
|
118
|
+
if (mongory_matcher_mapping == NULL) {
|
119
|
+
// TODO: Set error state.
|
120
|
+
return;
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
/**
|
125
|
+
* @brief Registers a matcher build function with a given name.
|
126
|
+
* The build function is stored in the global matcher mapping table.
|
127
|
+
* @param name The name of the matcher (e.g., "$eq", "$in").
|
128
|
+
* @param build_func A function pointer to the matcher's constructor.
|
129
|
+
*/
|
130
|
+
void mongory_matcher_register(char *name, mongory_matcher_build_func build_func) {
|
131
|
+
// Ensure mapping is initialized.
|
132
|
+
if (mongory_matcher_mapping == NULL) {
|
133
|
+
mongory_matcher_mapping_init();
|
134
|
+
if (mongory_matcher_mapping == NULL) {
|
135
|
+
// TODO: Set error: Cannot register if mapping init failed.
|
136
|
+
return;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
// Wrap the function pointer in a mongory_value to store in the table.
|
141
|
+
mongory_value *value = mongory_value_wrap_ptr(mongory_internal_pool, build_func);
|
142
|
+
if (value == NULL) {
|
143
|
+
// TODO: Set error: Failed to wrap pointer.
|
144
|
+
return;
|
145
|
+
}
|
146
|
+
|
147
|
+
mongory_matcher_mapping->set(mongory_matcher_mapping, name, value);
|
148
|
+
// TODO: Check return value of set?
|
149
|
+
}
|
150
|
+
|
151
|
+
/**
|
152
|
+
* @brief Retrieves a matcher build function by its name from the global
|
153
|
+
* mapping.
|
154
|
+
* @param name The name of the matcher to retrieve.
|
155
|
+
* @return mongory_matcher_build_func A function pointer to the matcher's
|
156
|
+
* constructor, or NULL if not found.
|
157
|
+
*/
|
158
|
+
mongory_matcher_build_func mongory_matcher_build_func_get(char *name) {
|
159
|
+
if (mongory_matcher_mapping == NULL) {
|
160
|
+
return NULL; // Mapping not initialized or init failed.
|
161
|
+
}
|
162
|
+
|
163
|
+
mongory_value *value = mongory_matcher_mapping->get(mongory_matcher_mapping, name);
|
164
|
+
if (value == NULL || value->type != MONGORY_TYPE_POINTER) {
|
165
|
+
return NULL; // Not found or not a pointer type as expected.
|
166
|
+
}
|
167
|
+
|
168
|
+
return (mongory_matcher_build_func)value->data.ptr;
|
169
|
+
}
|
170
|
+
|
171
|
+
/**
|
172
|
+
* @brief Sets the function for deep conversion of external values.
|
173
|
+
* Initializes the value converter if necessary.
|
174
|
+
* @param deep_convert The deep conversion function.
|
175
|
+
*/
|
176
|
+
void mongory_value_converter_deep_convert_set(mongory_deep_convert_func deep_convert) {
|
177
|
+
mongory_internal_value_converter.deep_convert = deep_convert;
|
178
|
+
}
|
179
|
+
|
180
|
+
/**
|
181
|
+
* @brief Sets the function for shallow conversion of external values.
|
182
|
+
* Initializes the value converter if necessary.
|
183
|
+
* @param shallow_convert The shallow conversion function.
|
184
|
+
*/
|
185
|
+
void mongory_value_converter_shallow_convert_set(mongory_shallow_convert_func shallow_convert) {
|
186
|
+
mongory_internal_value_converter.shallow_convert = shallow_convert;
|
187
|
+
}
|
188
|
+
|
189
|
+
/**
|
190
|
+
* @brief Sets the function for recovering external values from mongory_value.
|
191
|
+
* Initializes the value converter if necessary.
|
192
|
+
* @param recover The recovery function.
|
193
|
+
*/
|
194
|
+
void mongory_value_converter_recover_set(mongory_recover_func recover) {
|
195
|
+
mongory_internal_value_converter.recover = recover;
|
196
|
+
}
|
197
|
+
|
198
|
+
|
199
|
+
void mongory_custom_matcher_match_func_set(bool (*match)(void *external_matcher, mongory_value *value)) {
|
200
|
+
mongory_custom_matcher_adapter.match = match;
|
201
|
+
}
|
202
|
+
|
203
|
+
void mongory_custom_matcher_build_func_set(mongory_matcher_custom_context *(*build)(char *key, mongory_value *condition, void *extern_ctx)) {
|
204
|
+
mongory_custom_matcher_adapter.build = build;
|
205
|
+
}
|
206
|
+
|
207
|
+
void mongory_custom_matcher_lookup_func_set(bool (*lookup)(char *key)) {
|
208
|
+
mongory_custom_matcher_adapter.lookup = lookup;
|
209
|
+
}
|
210
|
+
|
211
|
+
void mongory_matcher_trace_result_colorful_set(bool colorful) {
|
212
|
+
mongory_matcher_trace_result_colorful = colorful;
|
213
|
+
}
|
214
|
+
|
215
|
+
/**
|
216
|
+
* @brief Initializes all core Mongory library components.
|
217
|
+
* This includes the internal memory pool, regex adapter, matcher mapping table,
|
218
|
+
* and value converter. It then registers all standard matcher types.
|
219
|
+
* This function MUST be called before using most other library features.
|
220
|
+
*/
|
221
|
+
void mongory_init() {
|
222
|
+
// Initialize all global components. Order can be important if one init
|
223
|
+
// depends on another (e.g., most depend on the pool).
|
224
|
+
mongory_internal_pool_init();
|
225
|
+
mongory_matcher_mapping_init();
|
226
|
+
|
227
|
+
// Register all standard matchers.
|
228
|
+
// Note: These registrations rely on mongory_internal_pool and
|
229
|
+
// mongory_matcher_mapping being successfully initialized.
|
230
|
+
// TODO: Add checks to ensure initializations were successful before
|
231
|
+
// proceeding.
|
232
|
+
mongory_matcher_register("$in", mongory_matcher_in_new);
|
233
|
+
mongory_matcher_register("$nin", mongory_matcher_not_in_new);
|
234
|
+
mongory_matcher_register("$eq", mongory_matcher_equal_new);
|
235
|
+
mongory_matcher_register("$ne", mongory_matcher_not_equal_new);
|
236
|
+
mongory_matcher_register("$gt", mongory_matcher_greater_than_new);
|
237
|
+
mongory_matcher_register("$gte", mongory_matcher_greater_than_or_equal_new);
|
238
|
+
mongory_matcher_register("$lt", mongory_matcher_less_than_new);
|
239
|
+
mongory_matcher_register("$lte", mongory_matcher_less_than_or_equal_new);
|
240
|
+
mongory_matcher_register("$exists", mongory_matcher_exists_new);
|
241
|
+
mongory_matcher_register("$present", mongory_matcher_present_new);
|
242
|
+
mongory_matcher_register("$regex", mongory_matcher_regex_new);
|
243
|
+
mongory_matcher_register("$and", mongory_matcher_and_new);
|
244
|
+
mongory_matcher_register("$or", mongory_matcher_or_new);
|
245
|
+
mongory_matcher_register("$elemMatch", mongory_matcher_elem_match_new);
|
246
|
+
mongory_matcher_register("$every", mongory_matcher_every_new);
|
247
|
+
mongory_matcher_register("$not", mongory_matcher_not_new);
|
248
|
+
mongory_matcher_register("$size", mongory_matcher_size_new);
|
249
|
+
}
|
250
|
+
|
251
|
+
/**
|
252
|
+
* @brief Cleans up all resources allocated by the Mongory library.
|
253
|
+
* This primarily involves freeing the internal memory pool, which should, in
|
254
|
+
* turn, release all memory allocated from it. It also resets global pointers
|
255
|
+
* to NULL. This should be called when the library is no longer needed to
|
256
|
+
* prevent memory leaks.
|
257
|
+
*/
|
258
|
+
void mongory_cleanup() {
|
259
|
+
if (mongory_internal_pool != NULL) {
|
260
|
+
// Freeing the pool should handle all allocations made from it,
|
261
|
+
// including the regex_adapter, matcher_mapping table (and its contents if
|
262
|
+
// they were allocated from this pool), and value_converter.
|
263
|
+
mongory_internal_pool->free(mongory_internal_pool);
|
264
|
+
mongory_internal_pool = NULL;
|
265
|
+
}
|
266
|
+
|
267
|
+
// Set other global pointers to NULL to indicate they are no longer valid.
|
268
|
+
// The memory they pointed to should have been managed by the internal pool.
|
269
|
+
mongory_matcher_mapping = NULL; // The table itself and its nodes.
|
270
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#ifndef MONGORY_FOUNDATIONS_CONFIG_PRIVATE_H
|
2
|
+
#define MONGORY_FOUNDATIONS_CONFIG_PRIVATE_H
|
3
|
+
#include "../matchers/base_matcher.h"
|
4
|
+
#include "mongory-core/foundations/config.h"
|
5
|
+
#include "mongory-core/foundations/table.h"
|
6
|
+
#include "mongory-core/matchers/matcher.h"
|
7
|
+
|
8
|
+
typedef struct mongory_regex_adapter {
|
9
|
+
mongory_regex_func match_func;
|
10
|
+
mongory_regex_stringify_func stringify_func;
|
11
|
+
} mongory_regex_adapter;
|
12
|
+
|
13
|
+
typedef struct mongory_value_converter {
|
14
|
+
mongory_deep_convert_func deep_convert;
|
15
|
+
mongory_shallow_convert_func shallow_convert;
|
16
|
+
mongory_recover_func recover;
|
17
|
+
} mongory_value_converter;
|
18
|
+
|
19
|
+
/**
|
20
|
+
* @brief Function pointer type for matching a value against an external matcher.
|
21
|
+
*
|
22
|
+
* This function is called when a value needs to be matched against an external
|
23
|
+
* matcher.
|
24
|
+
*
|
25
|
+
* @param external_matcher The external reference to the matcher.
|
26
|
+
* @param value The value to match against.
|
27
|
+
* @return bool True if the value matches the matcher, false otherwise.
|
28
|
+
*/
|
29
|
+
typedef struct mongory_matcher_custom_adapter {
|
30
|
+
bool (*match)(void *external_matcher, mongory_value *value); // Match a value against an external matcher.
|
31
|
+
mongory_matcher_custom_context *(*build)(char *key, mongory_value *condition, void *extern_ctx); // Build an external matcher reference.
|
32
|
+
bool (*lookup)(char *key); // Lookup a matcher reference by key.
|
33
|
+
} mongory_matcher_custom_adapter;
|
34
|
+
|
35
|
+
extern mongory_memory_pool *mongory_internal_pool;
|
36
|
+
extern mongory_regex_adapter mongory_internal_regex_adapter;
|
37
|
+
extern mongory_table *mongory_matcher_mapping;
|
38
|
+
extern mongory_value_converter mongory_internal_value_converter;
|
39
|
+
extern mongory_matcher_custom_adapter mongory_custom_matcher_adapter;
|
40
|
+
extern bool mongory_matcher_trace_result_colorful;
|
41
|
+
|
42
|
+
typedef mongory_matcher *(*mongory_matcher_build_func)(mongory_memory_pool *pool,
|
43
|
+
mongory_value *condition,
|
44
|
+
void *extern_ctx); // build function
|
45
|
+
void mongory_matcher_register(char *name, mongory_matcher_build_func build_func);
|
46
|
+
mongory_matcher_build_func mongory_matcher_build_func_get(char *name);
|
47
|
+
|
48
|
+
#endif
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#ifndef MONGORY_ERROR_C
|
2
|
+
#define MONGORY_ERROR_C
|
3
|
+
/**
|
4
|
+
* @file error.c
|
5
|
+
* @brief Implements error type to string conversion for the Mongory library.
|
6
|
+
*/
|
7
|
+
#include <mongory-core/foundations/error.h>
|
8
|
+
|
9
|
+
/**
|
10
|
+
* @brief Converts a mongory_error_type enum to its human-readable string
|
11
|
+
* representation.
|
12
|
+
*
|
13
|
+
* This function uses the MONGORY_ERROR_TYPE_MACRO to generate a switch
|
14
|
+
* statement that maps each error enum to its corresponding string.
|
15
|
+
*
|
16
|
+
* @param type The mongory_error_type enum value to convert.
|
17
|
+
* @return const char* A string literal representing the error type. If the
|
18
|
+
* type is not recognized, it returns "Unknown Error Type".
|
19
|
+
*/
|
20
|
+
const char *mongory_error_type_to_string(enum mongory_error_type type) {
|
21
|
+
switch (type) {
|
22
|
+
// Use the X-Macro to generate case statements for each error type.
|
23
|
+
#define DEFINE_ERROR_STRING(name, num, str) \
|
24
|
+
case name: \
|
25
|
+
return str;
|
26
|
+
MONGORY_ERROR_TYPE_MACRO(DEFINE_ERROR_STRING)
|
27
|
+
#undef DEFINE_ERROR_STRING // Undefine the macro after use.
|
28
|
+
default:
|
29
|
+
// Fallback for any undefined or unknown error types.
|
30
|
+
return "Unknown Error Type";
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
mongory_error MONGORY_ALLOC_ERROR = {
|
35
|
+
.type = MONGORY_ERROR_MEMORY,
|
36
|
+
.message = "Memory Allocation Failed",
|
37
|
+
};
|
38
|
+
#endif
|