mongory 0.7.2-x86_64-linux
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.so +0 -0
- data/mongory.gemspec +50 -0
- data/scripts/build_with_core.sh +292 -0
- data/sig/mongory.rbs +4 -0
- metadata +159 -0
@@ -0,0 +1,298 @@
|
|
1
|
+
/**
|
2
|
+
* @file memory_pool.c
|
3
|
+
* @brief Implements a memory pool for the Mongory library.
|
4
|
+
*
|
5
|
+
* This implementation uses a linked list of memory chunks. Allocations are
|
6
|
+
* made from the current chunk. If the current chunk is full, a new, larger
|
7
|
+
* chunk is allocated and added to the list. Freeing the pool deallocates all
|
8
|
+
* chunks. It also supports tracing externally allocated memory.
|
9
|
+
*/
|
10
|
+
#include <mongory-core/foundations/memory_pool.h>
|
11
|
+
#include <stdio.h> // For NULL, though stdlib.h or stddef.h is more common
|
12
|
+
#include <stdlib.h> // For calloc, free, etc.
|
13
|
+
#include <string.h> // For memset
|
14
|
+
|
15
|
+
/**
|
16
|
+
* @def MONGORY_INITIAL_CHUNK_SIZE
|
17
|
+
* @brief The initial size in bytes for the first memory chunk allocated by the
|
18
|
+
* pool.
|
19
|
+
*/
|
20
|
+
#define MONGORY_INITIAL_CHUNK_SIZE 2048
|
21
|
+
|
22
|
+
/**
|
23
|
+
* @def MONGORY_ALIGN8(size)
|
24
|
+
* @brief Macro to align a given size to an 8-byte boundary.
|
25
|
+
* This is useful for ensuring that memory allocations are suitably aligned
|
26
|
+
* for various data types.
|
27
|
+
* @param size The original size.
|
28
|
+
* @return The size aligned up to the nearest multiple of 8.
|
29
|
+
*/
|
30
|
+
#define MONGORY_ALIGN8(size) (((size) + 7) & ~((size_t)7))
|
31
|
+
|
32
|
+
/**
|
33
|
+
* @struct mongory_memory_node
|
34
|
+
* @brief Represents a node in the linked list of memory chunks within the pool.
|
35
|
+
*
|
36
|
+
* Each node holds a pointer to a block of memory (`ptr`), its total `size`,
|
37
|
+
* how much of it is `used`, and a pointer to the `next` node in the list.
|
38
|
+
* This structure is also used by the tracing mechanism to track external
|
39
|
+
* allocations.
|
40
|
+
*/
|
41
|
+
typedef struct mongory_memory_node {
|
42
|
+
void *ptr; /**< Pointer to the allocated memory block. */
|
43
|
+
size_t size; /**< Total size of the memory block. */
|
44
|
+
size_t used; /**< Bytes used in this memory block. */
|
45
|
+
struct mongory_memory_node *next; /**< Pointer to the next memory node. */
|
46
|
+
} mongory_memory_node;
|
47
|
+
|
48
|
+
/**
|
49
|
+
* @struct mongory_memory_pool_ctx
|
50
|
+
* @brief Internal context for a mongory_memory_pool.
|
51
|
+
*
|
52
|
+
* Stores the current `chunk_size` (which doubles on growth), pointers to
|
53
|
+
* the `head` and `current` memory nodes for allocations, and a list (`extra`)
|
54
|
+
* for traced external allocations.
|
55
|
+
*/
|
56
|
+
typedef struct mongory_memory_pool_ctx {
|
57
|
+
size_t chunk_size; /**< Current preferred size for new chunks. */
|
58
|
+
mongory_memory_node *head; /**< Head of the list of memory chunks. */
|
59
|
+
mongory_memory_node *current; /**< Current chunk to allocate from. */
|
60
|
+
mongory_memory_node *extra; /**< Head of list for externally traced memory. */
|
61
|
+
} mongory_memory_pool_ctx;
|
62
|
+
|
63
|
+
/**
|
64
|
+
* @brief Allocates a new memory chunk (node and its associated memory block).
|
65
|
+
*
|
66
|
+
* Uses `calloc` to ensure memory is zero-initialized.
|
67
|
+
*
|
68
|
+
* @param chunk_size The size of the memory block to allocate for this chunk.
|
69
|
+
* @return mongory_memory_node* Pointer to the new memory node, or NULL on
|
70
|
+
* failure.
|
71
|
+
*/
|
72
|
+
static inline mongory_memory_node *mongory_memory_chunk_new(size_t chunk_size) {
|
73
|
+
mongory_memory_node *node = calloc(1, sizeof(mongory_memory_node));
|
74
|
+
if (!node) {
|
75
|
+
return NULL; // Failed to allocate node structure.
|
76
|
+
}
|
77
|
+
|
78
|
+
void *mem = calloc(1, chunk_size);
|
79
|
+
if (!mem) {
|
80
|
+
free(node); // Clean up allocated node structure.
|
81
|
+
return NULL; // Failed to allocate memory block for the chunk.
|
82
|
+
}
|
83
|
+
|
84
|
+
node->ptr = mem;
|
85
|
+
node->size = chunk_size;
|
86
|
+
node->used = 0;
|
87
|
+
node->next = NULL;
|
88
|
+
|
89
|
+
return node;
|
90
|
+
}
|
91
|
+
|
92
|
+
/**
|
93
|
+
* @brief Grows the memory pool by adding a new, larger chunk.
|
94
|
+
*
|
95
|
+
* The new chunk size is at least double the previous chunk size, and large
|
96
|
+
* enough to satisfy `request_size`. The new chunk becomes the `current` chunk.
|
97
|
+
*
|
98
|
+
* @param ctx Pointer to the memory pool's context.
|
99
|
+
* @param request_size The minimum size required from the new chunk for an
|
100
|
+
* upcoming allocation.
|
101
|
+
* @return true if growth was successful, false otherwise.
|
102
|
+
*/
|
103
|
+
static inline bool mongory_memory_pool_grow(mongory_memory_pool_ctx *ctx, size_t request_size) {
|
104
|
+
if (ctx->current->next) {
|
105
|
+
ctx->current = ctx->current->next;
|
106
|
+
return true; // Already have a next chunk.
|
107
|
+
}
|
108
|
+
// Double the chunk size, ensuring it's at least as large as request_size.
|
109
|
+
ctx->chunk_size *= 2;
|
110
|
+
while (request_size > ctx->chunk_size) {
|
111
|
+
ctx->chunk_size *= 2;
|
112
|
+
}
|
113
|
+
|
114
|
+
mongory_memory_node *new_chunk = mongory_memory_chunk_new(ctx->chunk_size);
|
115
|
+
if (!new_chunk) {
|
116
|
+
return false; // Failed to create a new chunk.
|
117
|
+
}
|
118
|
+
|
119
|
+
// Link the new chunk and update the current pointer.
|
120
|
+
ctx->current->next = new_chunk;
|
121
|
+
ctx->current = new_chunk;
|
122
|
+
|
123
|
+
return true;
|
124
|
+
}
|
125
|
+
|
126
|
+
/**
|
127
|
+
* @brief Allocates memory from the pool. Implements `pool->alloc`.
|
128
|
+
*
|
129
|
+
* Allocates `size` bytes (aligned to 8 bytes) from the `current` chunk.
|
130
|
+
* If the current chunk doesn't have enough space, `mongory_memory_pool_grow`
|
131
|
+
* is called to add a new chunk.
|
132
|
+
*
|
133
|
+
* @param pool Pointer to the `mongory_memory_pool`.
|
134
|
+
* @param size The number of bytes to allocate.
|
135
|
+
* @return void* Pointer to the allocated memory, or NULL on failure.
|
136
|
+
*/
|
137
|
+
static inline void *mongory_memory_pool_alloc(mongory_memory_pool *pool, size_t size) {
|
138
|
+
mongory_memory_pool_ctx *pool_ctx = (mongory_memory_pool_ctx *)pool->ctx;
|
139
|
+
size = MONGORY_ALIGN8(size); // Ensure 8-byte alignment.
|
140
|
+
|
141
|
+
size_t balance = pool_ctx->current->size - pool_ctx->current->used;
|
142
|
+
if (size > balance) {
|
143
|
+
// Not enough space in current chunk, try to grow.
|
144
|
+
if (!mongory_memory_pool_grow(pool_ctx, size)) {
|
145
|
+
return NULL; // Growth failed.
|
146
|
+
}
|
147
|
+
// After successful growth, pool_ctx->current points to the new chunk.
|
148
|
+
}
|
149
|
+
|
150
|
+
// Allocate from the current chunk.
|
151
|
+
void *ptr = (char *)pool_ctx->current->ptr + pool_ctx->current->used;
|
152
|
+
pool_ctx->current->used += size;
|
153
|
+
|
154
|
+
return ptr;
|
155
|
+
}
|
156
|
+
|
157
|
+
static inline void mongory_memory_pool_reset(mongory_memory_pool *pool) {
|
158
|
+
mongory_memory_pool_ctx *pool_ctx = (mongory_memory_pool_ctx *)pool->ctx;
|
159
|
+
pool_ctx->current = pool_ctx->head;
|
160
|
+
mongory_memory_node *node = pool_ctx->head;
|
161
|
+
while (node) {
|
162
|
+
node->used = 0;
|
163
|
+
node = node->next;
|
164
|
+
}
|
165
|
+
}
|
166
|
+
|
167
|
+
/**
|
168
|
+
* @brief Frees a linked list of memory nodes.
|
169
|
+
*
|
170
|
+
* Iterates through the list, freeing the memory block (`node->ptr`) and then
|
171
|
+
* the node structure itself for each node. Memory blocks are zeroed out before
|
172
|
+
* freeing for security/safety.
|
173
|
+
*
|
174
|
+
* @param head Pointer to the head of the memory node list to free.
|
175
|
+
*/
|
176
|
+
static inline void mongory_memory_pool_node_list_free(mongory_memory_node *head) {
|
177
|
+
mongory_memory_node *node = head;
|
178
|
+
while (node) {
|
179
|
+
mongory_memory_node *next = node->next;
|
180
|
+
if (node->ptr) {
|
181
|
+
memset(node->ptr, 0, node->size); // Clear memory for safety.
|
182
|
+
free(node->ptr); // Free the actual memory block.
|
183
|
+
}
|
184
|
+
memset(node, 0,
|
185
|
+
sizeof(mongory_memory_node)); // Clear the node structure itself.
|
186
|
+
free(node); // Free the node structure.
|
187
|
+
node = next;
|
188
|
+
}
|
189
|
+
}
|
190
|
+
|
191
|
+
/**
|
192
|
+
* @brief Destroys the memory pool and frees all associated memory.
|
193
|
+
* Implements `pool->free`.
|
194
|
+
*
|
195
|
+
* Frees all memory chunks allocated by the pool (`ctx->head` list) and all
|
196
|
+
* externally traced memory blocks (`ctx->extra` list). Then frees the pool
|
197
|
+
* context and the pool structure itself.
|
198
|
+
*
|
199
|
+
* @param pool Pointer to the `mongory_memory_pool` to destroy.
|
200
|
+
*/
|
201
|
+
static inline void mongory_memory_pool_destroy(mongory_memory_pool *pool) {
|
202
|
+
if (!pool)
|
203
|
+
return;
|
204
|
+
mongory_memory_pool_ctx *ctx = (mongory_memory_pool_ctx *)pool->ctx;
|
205
|
+
|
206
|
+
if (ctx) {
|
207
|
+
// Free the main list of memory chunks.
|
208
|
+
mongory_memory_pool_node_list_free(ctx->head);
|
209
|
+
// Free the list of externally traced memory chunks.
|
210
|
+
mongory_memory_pool_node_list_free(ctx->extra);
|
211
|
+
|
212
|
+
memset(ctx, 0,
|
213
|
+
sizeof(mongory_memory_pool_ctx)); // Clear the context structure.
|
214
|
+
free(ctx); // Free the context structure.
|
215
|
+
}
|
216
|
+
|
217
|
+
memset(pool, 0, sizeof(mongory_memory_pool)); // Clear the pool structure.
|
218
|
+
free(pool); // Free the pool structure.
|
219
|
+
}
|
220
|
+
|
221
|
+
/**
|
222
|
+
* @brief Traces an externally allocated piece of memory. Implements
|
223
|
+
* `pool->trace`.
|
224
|
+
*
|
225
|
+
* Creates a new `mongory_memory_node` to track the external memory block and
|
226
|
+
* adds it to the `extra` list in the pool's context. This memory will be
|
227
|
+
* freed when `mongory_memory_pool_destroy` is called if this trace function
|
228
|
+
* is used.
|
229
|
+
*
|
230
|
+
* @param pool Pointer to the `mongory_memory_pool`.
|
231
|
+
* @param ptr Pointer to the externally allocated memory.
|
232
|
+
* @param size Size of the externally allocated memory.
|
233
|
+
*/
|
234
|
+
static inline void mongory_memory_pool_trace(mongory_memory_pool *pool, void *ptr, size_t size) {
|
235
|
+
mongory_memory_pool_ctx *pool_ctx = (mongory_memory_pool_ctx *)pool->ctx;
|
236
|
+
|
237
|
+
// Create a new node to trace this external allocation.
|
238
|
+
mongory_memory_node *extra_alloc_tracer = calloc(1, sizeof(mongory_memory_node));
|
239
|
+
if (!extra_alloc_tracer) {
|
240
|
+
// Allocation of tracer node failed; cannot trace.
|
241
|
+
// This might lead to a leak of 'ptr' if the caller expects the pool to
|
242
|
+
// manage it. Consider error reporting.
|
243
|
+
return;
|
244
|
+
}
|
245
|
+
extra_alloc_tracer->ptr = ptr; // This is the externally allocated memory.
|
246
|
+
extra_alloc_tracer->size = size; // Its size.
|
247
|
+
extra_alloc_tracer->used = size; // Mark as fully "used" in context of tracing.
|
248
|
+
extra_alloc_tracer->next = pool_ctx->extra; // Prepend to extra list.
|
249
|
+
pool_ctx->extra = extra_alloc_tracer;
|
250
|
+
}
|
251
|
+
|
252
|
+
/**
|
253
|
+
* @brief Creates and initializes a new memory pool.
|
254
|
+
*
|
255
|
+
* Allocates the `mongory_memory_pool` structure, its internal
|
256
|
+
* `mongory_memory_pool_ctx`, and the first memory chunk. Sets up the function
|
257
|
+
* pointers for `alloc`, `free`, and `trace`.
|
258
|
+
*
|
259
|
+
* @return mongory_memory_pool* Pointer to the new pool, or NULL on failure.
|
260
|
+
*/
|
261
|
+
mongory_memory_pool *mongory_memory_pool_new() {
|
262
|
+
// Allocate the main pool structure.
|
263
|
+
mongory_memory_pool *pool = calloc(1, sizeof(mongory_memory_pool));
|
264
|
+
if (!pool) {
|
265
|
+
return NULL;
|
266
|
+
}
|
267
|
+
|
268
|
+
// Allocate the internal context for the pool.
|
269
|
+
mongory_memory_pool_ctx *ctx = calloc(1, sizeof(mongory_memory_pool_ctx));
|
270
|
+
if (!ctx) {
|
271
|
+
free(pool); // Clean up partially allocated pool.
|
272
|
+
return NULL;
|
273
|
+
}
|
274
|
+
|
275
|
+
// Allocate the first memory chunk.
|
276
|
+
mongory_memory_node *first_chunk = mongory_memory_chunk_new(MONGORY_INITIAL_CHUNK_SIZE);
|
277
|
+
if (!first_chunk) {
|
278
|
+
free(ctx); // Clean up context.
|
279
|
+
free(pool); // Clean up pool structure.
|
280
|
+
return NULL;
|
281
|
+
}
|
282
|
+
|
283
|
+
// Initialize context fields.
|
284
|
+
ctx->chunk_size = MONGORY_INITIAL_CHUNK_SIZE;
|
285
|
+
ctx->head = first_chunk;
|
286
|
+
ctx->current = first_chunk;
|
287
|
+
ctx->extra = NULL; // No extra traced allocations initially.
|
288
|
+
|
289
|
+
// Initialize pool fields.
|
290
|
+
pool->ctx = ctx;
|
291
|
+
pool->alloc = mongory_memory_pool_alloc;
|
292
|
+
pool->reset = mongory_memory_pool_reset;
|
293
|
+
pool->free = mongory_memory_pool_destroy;
|
294
|
+
pool->trace = mongory_memory_pool_trace;
|
295
|
+
pool->error = NULL; // No error initially.
|
296
|
+
|
297
|
+
return pool;
|
298
|
+
}
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#include "string_buffer.h"
|
2
|
+
#include <mongory-core.h>
|
3
|
+
#include <stdarg.h>
|
4
|
+
#include <stdio.h>
|
5
|
+
#include <string.h>
|
6
|
+
|
7
|
+
#define MONGORY_STRING_BUFFER_INITIAL_CAPACITY 16
|
8
|
+
|
9
|
+
mongory_string_buffer *mongory_string_buffer_new(mongory_memory_pool *pool) {
|
10
|
+
mongory_string_buffer *buffer = MG_ALLOC_PTR(pool, mongory_string_buffer);
|
11
|
+
buffer->pool = pool;
|
12
|
+
buffer->buffer = (char *)MG_ALLOC(pool, MONGORY_STRING_BUFFER_INITIAL_CAPACITY);
|
13
|
+
buffer->size = 0;
|
14
|
+
buffer->capacity = MONGORY_STRING_BUFFER_INITIAL_CAPACITY;
|
15
|
+
buffer->buffer[0] = '\0';
|
16
|
+
return buffer;
|
17
|
+
}
|
18
|
+
|
19
|
+
void mongory_string_buffer_free(mongory_string_buffer *buffer) { buffer->pool->free(buffer->pool->ctx); }
|
20
|
+
|
21
|
+
static inline void mongory_string_buffer_grow(mongory_string_buffer *buffer, size_t additional_size) {
|
22
|
+
bool trigger_grow = false;
|
23
|
+
while (buffer->size + additional_size + 1 > buffer->capacity) {
|
24
|
+
buffer->capacity *= 2;
|
25
|
+
trigger_grow = true;
|
26
|
+
}
|
27
|
+
if (!trigger_grow) {
|
28
|
+
return;
|
29
|
+
}
|
30
|
+
char *previous_buffer = buffer->buffer;
|
31
|
+
buffer->buffer = (char *)MG_ALLOC(buffer->pool, buffer->capacity);
|
32
|
+
if (previous_buffer) {
|
33
|
+
strcpy(buffer->buffer, previous_buffer);
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
void mongory_string_buffer_append(mongory_string_buffer *buffer, const char *str) {
|
38
|
+
size_t len = strlen(str);
|
39
|
+
mongory_string_buffer_grow(buffer, len);
|
40
|
+
strcpy(buffer->buffer + buffer->size, str);
|
41
|
+
buffer->size += len;
|
42
|
+
buffer->buffer[buffer->size] = '\0';
|
43
|
+
}
|
44
|
+
|
45
|
+
void mongory_string_buffer_appendf(mongory_string_buffer *buffer, const char *format, ...) {
|
46
|
+
va_list args;
|
47
|
+
va_start(args, format);
|
48
|
+
int len = vsnprintf(NULL, 0, format, args);
|
49
|
+
va_end(args);
|
50
|
+
mongory_string_buffer_grow(buffer, len);
|
51
|
+
va_start(args, format);
|
52
|
+
vsnprintf(buffer->buffer + buffer->size, buffer->capacity - buffer->size, format, args);
|
53
|
+
va_end(args);
|
54
|
+
buffer->size += len;
|
55
|
+
buffer->buffer[buffer->size] = '\0';
|
56
|
+
}
|
57
|
+
|
58
|
+
char *mongory_string_buffer_cstr(mongory_string_buffer *buffer) { return buffer->buffer; }
|
59
|
+
|
60
|
+
void mongory_string_buffer_clear(mongory_string_buffer *buffer) {
|
61
|
+
buffer->buffer = (char *)MG_ALLOC(buffer->pool, MONGORY_STRING_BUFFER_INITIAL_CAPACITY);
|
62
|
+
buffer->capacity = MONGORY_STRING_BUFFER_INITIAL_CAPACITY;
|
63
|
+
buffer->size = 0;
|
64
|
+
buffer->buffer[0] = '\0';
|
65
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#include <mongory-core.h>
|
2
|
+
|
3
|
+
#ifndef MONGORY_STRING_BUFFER_H
|
4
|
+
#define MONGORY_STRING_BUFFER_H
|
5
|
+
|
6
|
+
typedef struct mongory_string_buffer {
|
7
|
+
mongory_memory_pool *pool;
|
8
|
+
char *buffer;
|
9
|
+
size_t size;
|
10
|
+
size_t capacity;
|
11
|
+
} mongory_string_buffer;
|
12
|
+
|
13
|
+
mongory_string_buffer *mongory_string_buffer_new(mongory_memory_pool *pool);
|
14
|
+
|
15
|
+
/**
|
16
|
+
* @brief Appends a string to the buffer.
|
17
|
+
* @param buffer The buffer to append to.
|
18
|
+
* @param str The string to append.
|
19
|
+
*/
|
20
|
+
void mongory_string_buffer_append(mongory_string_buffer *buffer, const char *str);
|
21
|
+
|
22
|
+
/**
|
23
|
+
* @brief Appends a formatted string to the buffer.
|
24
|
+
* @param buffer The buffer to append to.
|
25
|
+
* @param format The format string.
|
26
|
+
* @param ... The arguments to the format string.
|
27
|
+
*/
|
28
|
+
void mongory_string_buffer_appendf(mongory_string_buffer *buffer, const char *format, ...);
|
29
|
+
|
30
|
+
/**
|
31
|
+
* @brief Returns a C string representation of the buffer.
|
32
|
+
* @param buffer The buffer to get the C string from.
|
33
|
+
* @return A C string representation of the buffer.
|
34
|
+
*/
|
35
|
+
char *mongory_string_buffer_cstr(mongory_string_buffer *buffer);
|
36
|
+
|
37
|
+
/**
|
38
|
+
* @brief Clears the buffer.
|
39
|
+
* @param buffer The buffer to clear.
|
40
|
+
*/
|
41
|
+
void mongory_string_buffer_clear(mongory_string_buffer *buffer);
|
42
|
+
|
43
|
+
/**
|
44
|
+
* @brief Frees the buffer.
|
45
|
+
* @param buffer The buffer to free.
|
46
|
+
*/
|
47
|
+
void mongory_string_buffer_free(mongory_string_buffer *buffer);
|
48
|
+
|
49
|
+
#endif
|