Files
codebase-memory-mcp/src/foundation/dyn_array.h
T
Martin Vogel 94a9a92f83 Add C-native pipeline with blocking clang-tidy, cppcheck, clang-format linting
Complete C implementation of the indexing pipeline (src/), parallel worker
pool, graph buffer with merge support, SQLite writer, and 1893-test suite.

Linter setup: zero warnings from clang-tidy (all checks enabled, no NOLINT
suppressions), cppcheck, and clang-format. All issues fixed at source —
proper headers for external linkage, GROW_ARRAY macro restructured to
eliminate type parameter, null-deref paths guarded, named intermediates
for suspicious-argument checks.
2026-03-15 19:26:12 +01:00

106 lines
5.1 KiB
C

/*
* dyn_array.h — Type-safe growable arrays via macros (header-only).
*
* Usage:
* CBM_DYN_ARRAY(int) nums = {0}; // zero-init
* cbm_da_push(&nums, 42);
* cbm_da_push(&nums, 99);
* for (int i = 0; i < nums.count; i++)
* printf("%d\n", nums.items[i]);
* cbm_da_free(&nums);
*
* Design:
* - Items are contiguous in memory (cache-friendly)
* - Grows by 2x (amortized O(1) push)
* - Uses realloc — NOT arena-compatible (use CBMDefArray etc. for arena)
* - Header-only: no .c file needed
*/
#ifndef CBM_DYN_ARRAY_H
#define CBM_DYN_ARRAY_H
#include <stdlib.h>
#include <string.h>
/* Declare a dynamic array type for a given element type. */
#define CBM_DYN_ARRAY(T) \
struct { \
T *items; \
int count; \
int cap; \
}
/* Push an element. Grows by 2x when full. */
#define cbm_da_push(da, item) \
do { \
if ((da)->count >= (da)->cap) { \
int _new_cap = (da)->cap ? (da)->cap * 2 : 8; \
void *_new = realloc((da)->items, (size_t)_new_cap * sizeof(*(da)->items)); \
if (!_new) \
break; \
(da)->items = _new; \
(da)->cap = _new_cap; \
} \
(da)->items[(da)->count++] = (item); \
} while (0)
/* Push an element with a pointer return (for in-place init). */
#define cbm_da_push_ptr(da) \
(((da)->count >= (da)->cap \
? ((void)((da)->cap = (da)->cap ? (da)->cap * 2 : 8), \
(void)((da)->items = realloc((da)->items, (size_t)(da)->cap * sizeof(*(da)->items)))) \
: (void)0), \
&(da)->items[(da)->count++])
/* Pop last element. Returns the element. Undefined if empty. */
#define cbm_da_pop(da) ((da)->items[--(da)->count])
/* Get last element without removing. Undefined if empty. */
#define cbm_da_last(da) ((da)->items[(da)->count - 1])
/* Clear without freeing (reset count to 0). */
#define cbm_da_clear(da) ((da)->count = 0)
/* Free all memory. */
#define cbm_da_free(da) \
do { \
free((da)->items); \
(da)->items = NULL; \
(da)->count = 0; \
(da)->cap = 0; \
} while (0)
/* Reserve capacity (grow if needed, never shrink). */
#define cbm_da_reserve(da, n) \
do { \
if ((n) > (da)->cap) { \
void *_new = realloc((da)->items, (size_t)(n) * sizeof(*(da)->items)); \
if (_new) { \
(da)->items = _new; \
(da)->cap = (n); \
} \
} \
} while (0)
/* Insert at index, shifting elements right. */
#define cbm_da_insert(da, idx, item) \
do { \
cbm_da_push(da, item); /* ensure space */ \
if ((idx) < (da)->count - 1) { \
memmove(&(da)->items[(idx) + 1], &(da)->items[(idx)], \
(size_t)((da)->count - 1 - (idx)) * sizeof(*(da)->items)); \
(da)->items[(idx)] = (item); \
} \
} while (0)
/* Remove at index, shifting elements left. */
#define cbm_da_remove(da, idx) \
do { \
if ((idx) < (da)->count - 1) { \
memmove(&(da)->items[(idx)], &(da)->items[(idx) + 1], \
(size_t)((da)->count - 1 - (idx)) * sizeof(*(da)->items)); \
} \
(da)->count--; \
} while (0)
#endif /* CBM_DYN_ARRAY_H */