mongory 0.7.6 → 0.7.8
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 +4 -4
- data/Rakefile +0 -14
- data/ext/mongory_ext/extconf.rb +19 -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/lib/mongory/version.rb +1 -1
- data/lib/mongory.rb +2 -2
- metadata +43 -2
@@ -0,0 +1,175 @@
|
|
1
|
+
#ifndef MONGORY_VALUE
|
2
|
+
#define MONGORY_VALUE
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @file value.h
|
6
|
+
* @brief Defines the mongory_value structure, a generic value type for the
|
7
|
+
* Mongory library.
|
8
|
+
*
|
9
|
+
* `mongory_value` is a tagged union that can represent various data types such
|
10
|
+
* as null, boolean, integer, double, string, array, table, regex, pointers,
|
11
|
+
* and an unsupported type. It includes functions for wrapping C types into
|
12
|
+
* `mongory_value` objects, comparing values, and converting them to strings.
|
13
|
+
*/
|
14
|
+
|
15
|
+
#include "mongory-core/foundations/memory_pool.h"
|
16
|
+
#include <stdbool.h>
|
17
|
+
#include <stdint.h> // For int64_t
|
18
|
+
|
19
|
+
// Forward declarations for complex types that can be stored in mongory_value.
|
20
|
+
struct mongory_array;
|
21
|
+
struct mongory_table;
|
22
|
+
|
23
|
+
// Forward declaration of mongory_value itself and its type enum.
|
24
|
+
struct mongory_value;
|
25
|
+
/**
|
26
|
+
* @brief Alias for `struct mongory_value`.
|
27
|
+
*/
|
28
|
+
typedef struct mongory_value mongory_value;
|
29
|
+
|
30
|
+
enum mongory_type;
|
31
|
+
/**
|
32
|
+
* @brief Alias for `enum mongory_type`.
|
33
|
+
*/
|
34
|
+
typedef enum mongory_type mongory_type;
|
35
|
+
|
36
|
+
/**
|
37
|
+
* @brief Function pointer type for comparing two mongory_value instances.
|
38
|
+
*
|
39
|
+
* @param a The first mongory_value.
|
40
|
+
* @param b The second mongory_value.
|
41
|
+
* @return int Returns:
|
42
|
+
* - 0 if a is equal to b.
|
43
|
+
* - A negative value if a is less than b.
|
44
|
+
* - A positive value if a is greater than b.
|
45
|
+
* - `mongory_value_compare_fail` (a specific constant) if the types
|
46
|
+
* are incompatible for comparison or an error occurs.
|
47
|
+
*/
|
48
|
+
typedef int (*mongory_value_compare_func)(mongory_value *a, mongory_value *b);
|
49
|
+
|
50
|
+
/**
|
51
|
+
* @brief Function pointer type for converting a mongory_value to a string representation.
|
52
|
+
* @param value The mongory_value to convert.
|
53
|
+
* @param pool The memory pool to allocate from.
|
54
|
+
* @return char* A string literal representing the value, or NULL if allocation
|
55
|
+
* fails. The string is a literal and should not be freed.
|
56
|
+
*/
|
57
|
+
typedef char *(*mongory_value_to_str_func)(mongory_value *value, mongory_memory_pool *pool);
|
58
|
+
|
59
|
+
/**
|
60
|
+
* @brief Converts the type of a mongory_value to its string representation.
|
61
|
+
* @param value A pointer to the mongory_value.
|
62
|
+
* @return char* A string literal representing the type (e.g., "Int", "String").
|
63
|
+
* Returns "UnknownType" if the type is not recognized. This string is a
|
64
|
+
* literal and should not be freed.
|
65
|
+
*/
|
66
|
+
char *mongory_type_to_string(mongory_value *value);
|
67
|
+
|
68
|
+
/**
|
69
|
+
* @brief Extracts a pointer to the raw data stored within a mongory_value.
|
70
|
+
* The type of the returned pointer depends on the `mongory_value`'s type.
|
71
|
+
* For example, for an MONGORY_TYPE_INT, it returns `int64_t*`.
|
72
|
+
* @param value A pointer to the mongory_value.
|
73
|
+
* @return void* A pointer to the internal data, or NULL if the type is unknown
|
74
|
+
* or has no direct data pointer (e.g. MONGORY_TYPE_NULL).
|
75
|
+
*/
|
76
|
+
void *mongory_value_extract(mongory_value *value);
|
77
|
+
|
78
|
+
/** @name Mongory Value Wrapper Functions
|
79
|
+
* Functions to create mongory_value instances from basic C types.
|
80
|
+
* These functions allocate a new mongory_value from the provided pool.
|
81
|
+
* @{
|
82
|
+
*/
|
83
|
+
mongory_value *mongory_value_wrap_n(mongory_memory_pool *pool, void *n);
|
84
|
+
mongory_value *mongory_value_wrap_b(mongory_memory_pool *pool, bool b);
|
85
|
+
mongory_value *mongory_value_wrap_i(mongory_memory_pool *pool, int64_t i);
|
86
|
+
mongory_value *mongory_value_wrap_d(mongory_memory_pool *pool, double d);
|
87
|
+
mongory_value *mongory_value_wrap_s(mongory_memory_pool *pool, char *s);
|
88
|
+
mongory_value *mongory_value_wrap_a(mongory_memory_pool *pool, struct mongory_array *a);
|
89
|
+
mongory_value *mongory_value_wrap_t(mongory_memory_pool *pool, struct mongory_table *t);
|
90
|
+
mongory_value *mongory_value_wrap_regex(mongory_memory_pool *pool, void *regex);
|
91
|
+
mongory_value *mongory_value_wrap_ptr(mongory_memory_pool *pool, void *ptr);
|
92
|
+
mongory_value *mongory_value_wrap_u(mongory_memory_pool *pool, void *u);
|
93
|
+
/** @} */
|
94
|
+
|
95
|
+
/**
|
96
|
+
* @def MONGORY_TYPE_MACRO
|
97
|
+
* @brief X-Macro for defining mongory_type enum members and associated data.
|
98
|
+
* Simplifies the definition of types, their string names, and corresponding
|
99
|
+
* union fields.
|
100
|
+
* _(ENUM_NAME, UNIQUE_NUM_SUFFIX, "STRING_NAME", UNION_FIELD_NAME)
|
101
|
+
* Note: For MONGORY_TYPE_NULL, the 'i' field (int64_t) is arbitrarily used in
|
102
|
+
* the macro as the union needs a field, but it's not meaningful for null.
|
103
|
+
*/
|
104
|
+
#define MONGORY_TYPE_MACRO(_) \
|
105
|
+
_(MONGORY_TYPE_NULL, 0, "Null", i) /* Field 'i' is arbitrary for NULL */ \
|
106
|
+
_(MONGORY_TYPE_BOOL, 10, "Bool", b) \
|
107
|
+
_(MONGORY_TYPE_INT, 11, "Int", i) \
|
108
|
+
_(MONGORY_TYPE_DOUBLE, 12, "Double", d) \
|
109
|
+
_(MONGORY_TYPE_STRING, 13, "String", s) \
|
110
|
+
_(MONGORY_TYPE_ARRAY, 14, "Array", a) \
|
111
|
+
_(MONGORY_TYPE_TABLE, 15, "Table", t) \
|
112
|
+
_(MONGORY_TYPE_REGEX, 16, "Regex", regex) /* Custom regex object pointer */ \
|
113
|
+
_(MONGORY_TYPE_POINTER, 17, "Pointer", ptr) /* Generic void pointer */ \
|
114
|
+
_(MONGORY_TYPE_UNSUPPORTED, 999, "Unsupported", u) /* External/unknown type pointer */
|
115
|
+
|
116
|
+
/**
|
117
|
+
* @def MONGORY_ENUM_MAGIC
|
118
|
+
* @brief A magic number used in generating enum values for mongory_type.
|
119
|
+
* Helps in creating somewhat unique integer values for the enums.
|
120
|
+
*/
|
121
|
+
#define MONGORY_ENUM_MAGIC 103
|
122
|
+
|
123
|
+
/**
|
124
|
+
* @enum mongory_type
|
125
|
+
* @brief Enumerates the possible data types a mongory_value can hold.
|
126
|
+
* Values are generated using MONGORY_TYPE_MACRO and MONGORY_ENUM_MAGIC.
|
127
|
+
*/
|
128
|
+
enum mongory_type {
|
129
|
+
#define DEFINE_ENUM(name, num, str, field) name = num * MONGORY_ENUM_MAGIC,
|
130
|
+
MONGORY_TYPE_MACRO(DEFINE_ENUM)
|
131
|
+
#undef DEFINE_ENUM
|
132
|
+
};
|
133
|
+
|
134
|
+
/**
|
135
|
+
* @var mongory_value_compare_fail
|
136
|
+
* @brief Special return value from compare functions indicating comparison
|
137
|
+
* failure (e.g. incompatible types).
|
138
|
+
*/
|
139
|
+
static const int mongory_value_compare_fail = 97;
|
140
|
+
|
141
|
+
/**
|
142
|
+
* @struct mongory_value
|
143
|
+
* @brief Represents a generic value in the Mongory system.
|
144
|
+
*
|
145
|
+
* It's a tagged union, where `type` indicates which field in the `data` union
|
146
|
+
* is active. Each value also carries a pointer to the `mongory_memory_pool`
|
147
|
+
* it was allocated from (or is associated with) and a `comp` function for
|
148
|
+
* comparisons. The `origin` field can be used to store a pointer to an
|
149
|
+
* original external data structure if the `mongory_value` is a bridge or
|
150
|
+
* wrapper.
|
151
|
+
*/
|
152
|
+
struct mongory_value {
|
153
|
+
mongory_memory_pool *pool; /**< Memory pool associated with this value. */
|
154
|
+
mongory_type type; /**< The type of data stored in the union. */
|
155
|
+
mongory_value_compare_func comp; /**< Function to compare this value with
|
156
|
+
another. */
|
157
|
+
mongory_value_to_str_func to_str; /**< Function to convert this value to a
|
158
|
+
string representation. */
|
159
|
+
union {
|
160
|
+
bool b; /**< Boolean data. */
|
161
|
+
int64_t i; /**< Integer data (64-bit). */
|
162
|
+
double d; /**< Double-precision floating-point data. */
|
163
|
+
char *s; /**< String data (null-terminated). String memory
|
164
|
+
is typically managed by the pool. */
|
165
|
+
struct mongory_array *a; /**< Pointer to a mongory_array. */
|
166
|
+
struct mongory_table *t; /**< Pointer to a mongory_table. */
|
167
|
+
void *regex; /**< Pointer to a custom regex object/structure. */
|
168
|
+
void *ptr; /**< Generic void pointer for other data. */
|
169
|
+
void *u; /**< Pointer for unsupported/external types. */
|
170
|
+
} data; /**< Union holding the actual data based on type. */
|
171
|
+
void *origin; /**< Optional pointer to an original external value, useful for
|
172
|
+
bridging with other data systems. */
|
173
|
+
};
|
174
|
+
|
175
|
+
#endif /* MONGORY_VALUE */
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#ifndef MONGORY_MATCHER_H
|
2
|
+
#define MONGORY_MATCHER_H
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @file matcher.h
|
6
|
+
* @brief Defines the core mongory_matcher structure and related types.
|
7
|
+
*
|
8
|
+
* This file provides the basic structure for all matchers in the Mongory
|
9
|
+
* library. A matcher is responsible for determining if a given `mongory_value`
|
10
|
+
* meets certain criteria defined by a `condition`.
|
11
|
+
*/
|
12
|
+
|
13
|
+
#include "mongory-core/foundations/array.h" // For mongory_array (used in context)
|
14
|
+
#include "mongory-core/foundations/memory_pool.h"
|
15
|
+
#include "mongory-core/foundations/value.h"
|
16
|
+
|
17
|
+
// Forward declaration for the main matcher structure.
|
18
|
+
typedef struct mongory_matcher mongory_matcher;
|
19
|
+
/**
|
20
|
+
* @brief Creates a new generic matcher instance.
|
21
|
+
*
|
22
|
+
* This function typically serves as a high-level entry point for creating
|
23
|
+
* matchers. In the current implementation, it delegates to
|
24
|
+
* `mongory_matcher_table_cond_new`, implying that conditions are often
|
25
|
+
* table-based (similar to query documents).
|
26
|
+
*
|
27
|
+
* @param pool The memory pool to use for the matcher's allocations.
|
28
|
+
* @param condition A `mongory_value` representing the condition for this
|
29
|
+
* matcher.
|
30
|
+
* @return mongory_matcher* A pointer to the newly created matcher, or NULL on
|
31
|
+
* failure.
|
32
|
+
*/
|
33
|
+
mongory_matcher *mongory_matcher_new(mongory_memory_pool *pool, mongory_value *condition, void *extern_ctx);
|
34
|
+
|
35
|
+
/**
|
36
|
+
* @brief Matches a value against a matcher.
|
37
|
+
* @param matcher The matcher to match against.
|
38
|
+
* @param value The value to match.
|
39
|
+
* @return True if the value matches the matcher, false otherwise.
|
40
|
+
*/
|
41
|
+
bool mongory_matcher_match(mongory_matcher *matcher, mongory_value *value);
|
42
|
+
|
43
|
+
/**
|
44
|
+
* @brief Explains a matcher.
|
45
|
+
* @param matcher The matcher to explain.
|
46
|
+
* @param temp_pool The temporary pool to use for the explanation.
|
47
|
+
*/
|
48
|
+
void mongory_matcher_explain(mongory_matcher *matcher, mongory_memory_pool *temp_pool);
|
49
|
+
|
50
|
+
/**
|
51
|
+
* @brief Traces a matcher.
|
52
|
+
* @param matcher The matcher to trace.
|
53
|
+
* @param value The value to trace.
|
54
|
+
*/
|
55
|
+
bool mongory_matcher_trace(mongory_matcher *matcher, mongory_value *value);
|
56
|
+
|
57
|
+
/**
|
58
|
+
* @brief Prints the trace of a matcher.
|
59
|
+
* @param matcher The matcher to print the trace of.
|
60
|
+
*/
|
61
|
+
void mongory_matcher_print_trace(mongory_matcher *matcher);
|
62
|
+
|
63
|
+
/**
|
64
|
+
* @brief Enables the trace of a matcher.
|
65
|
+
* @param matcher The matcher to enable the trace of.
|
66
|
+
* @param temp_pool The temporary pool to use for the trace.
|
67
|
+
*/
|
68
|
+
void mongory_matcher_enable_trace(mongory_matcher *matcher, mongory_memory_pool *temp_pool);
|
69
|
+
|
70
|
+
/**
|
71
|
+
* @brief Disables the trace of a matcher.
|
72
|
+
* @param matcher The matcher to disable the trace of.
|
73
|
+
*/
|
74
|
+
void mongory_matcher_disable_trace(mongory_matcher *matcher);
|
75
|
+
|
76
|
+
#endif /* MONGORY_MATCHER_H */
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#ifndef MONGORY_CORE_H
|
2
|
+
#define MONGORY_CORE_H
|
3
|
+
|
4
|
+
#include "mongory-core/foundations/array.h"
|
5
|
+
#include "mongory-core/foundations/config.h"
|
6
|
+
#include "mongory-core/foundations/error.h"
|
7
|
+
#include "mongory-core/foundations/memory_pool.h"
|
8
|
+
#include "mongory-core/foundations/table.h"
|
9
|
+
#include "mongory-core/foundations/value.h"
|
10
|
+
#include "mongory-core/matchers/matcher.h"
|
11
|
+
|
12
|
+
#endif
|
@@ -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
|