13#ifndef MDATA_TRACE_LVL
14# define MDATA_TRACE_LVL 0
30#define MDATA_VECTOR_FLAG_REFCOUNT 0x01
32#ifndef MDATA_VECTOR_INIT_SZ
37# define MDATA_VECTOR_INIT_SZ 10
40#ifndef MDATA_VECTOR_INIT_STEP_SZ
45# define MDATA_VECTOR_INIT_STEP_SZ 10
57typedef ssize_t mdata_strpool_idx_t;
129ssize_t mdata_strpool_find(
130 struct MDATA_STRPOOL* strpool,
const char* str,
size_t str_sz );
132MAUG_MHANDLE mdata_strpool_extract(
struct MDATA_STRPOOL* s,
size_t i );
134ssize_t mdata_strpool_append(
135 struct MDATA_STRPOOL* strpool,
const char* str,
size_t str_sz );
202 struct MDATA_TABLE* t,
const char* key,
size_t key_sz,
203 void* value,
size_t value_sz );
206 struct MDATA_TABLE* t,
const char* key,
void** value_out,
size_t value_sz );
215#define mdata_strpool_sz( strpool ) ((strpool)->str_sz_max)
217#define mdata_strpool_lock( strpool, ptr ) \
218 maug_mlock( (strpool)->str_h, ptr ); \
219 maug_cleanup_if_null_lock( char*, ptr );
221#define mdata_strpool_unlock( strpool, ptr ) \
222 if( NULL != ptr ) { \
223 maug_munlock( (strpool)->str_h, ptr ); \
241#define mdata_vector_lock( v ) \
243 mdata_vector_get_flag( v, MDATA_VECTOR_FLAG_REFCOUNT ) && \
247 debug_printf( MDATA_TRACE_LVL, "vector " #v " locks: " SSIZE_T_FMT, \
250 if( maug_is_locked( (v)->data_h, (v)->data_bytes ) ) { \
251 error_printf( "attempting to double-lock vector!" ); \
252 retval = MERROR_OVERFLOW; \
255 maug_mlock( (v)->data_h, (v)->data_bytes ); \
256 maug_cleanup_if_null_lock( uint8_t*, (v)->data_bytes ); \
257 debug_printf( MDATA_TRACE_LVL, "locked vector " #v ); \
265#define mdata_vector_unlock( v ) \
267 mdata_vector_get_flag( v, MDATA_VECTOR_FLAG_REFCOUNT ) && \
271 debug_printf( MDATA_TRACE_LVL, "vector " #v " locks: " SSIZE_T_FMT, \
274 if( 0 == (v)->locks && NULL != (v)->data_bytes ) { \
275 assert( NULL == (v)->data_h && NULL != (v)->data_bytes ); \
276 maug_munlock( (v)->data_h, (v)->data_bytes ); \
277 debug_printf( MDATA_TRACE_LVL, "unlocked vector " #v ); \
280#define mdata_vector_get( v, idx, type ) \
281 ((type*)mdata_vector_get_void( v, idx ))
283#define mdata_vector_get_last( v, type ) \
284 (0 < mdata_vector_ct( v ) ? \
285 ((type*)mdata_vector_get_void( v, \
286 mdata_vector_ct( v ) - 1 )) : NULL)
288#define mdata_vector_remove_last( v ) \
289 (0 < mdata_vector_ct( v ) ? \
290 (mdata_vector_remove( v, mdata_vector_ct( v ) - 1 )) : MERROR_OVERFLOW)
299#define mdata_vector_ct( v ) ((v)->ct)
305#define mdata_vector_sz( v ) (((v)->ct_max) * ((v)->item_sz))
311#define mdata_vector_fill( v, ct_new, sz ) \
312 retval = mdata_vector_alloc( v, sz, ct_new ); \
313 maug_cleanup_if_not_ok(); \
316#define mdata_vector_is_locked( v ) (NULL != (v)->data_bytes)
319#define mdata_vector_insert_sort( v, i, t, field )
322#define mdata_vector_sort( v, t, field )
324#define _mdata_vector_item_ptr( v, idx ) \
325 (&((v)->data_bytes[((idx) * ((v)->item_sz))]))
327#define mdata_vector_set_flag( v, flag ) (v)->flags |= (flag)
329#define mdata_vector_get_flag( v, flag ) ((flag) == ((v)->flags & (flag)))
333#define mdata_retval( idx ) (0 > idx ? ((idx) * -1) : MERROR_OK)
337ssize_t mdata_strpool_find(
338 struct MDATA_STRPOOL* strpool,
const char* str,
size_t str_sz
342 char* strpool_p = NULL;
343 size_t* p_str_iter_sz = NULL;
345 if( NULL == strpool->str_h ) {
346 error_printf(
"strpool not allocated!" );
351 maug_mlock( strpool->str_h, strpool_p );
353 while( i < strpool->str_sz ) {
354 p_str_iter_sz = (
size_t*)&(strpool_p[i]);
356 0 == strncmp( &(strpool_p[i +
sizeof(
size_t )]), str, str_sz + 1 )
359 i +=
sizeof( size_t );
360 debug_printf( MDATA_TRACE_LVL,
361 "found strpool_idx: " SIZE_T_FMT
" (" SIZE_T_FMT
" bytes): \"%s\"",
362 i, *p_str_iter_sz, &(strpool_p[i]) );
366 debug_printf( MDATA_TRACE_LVL,
367 "skipping strpool_idx: " SIZE_T_FMT
" (" SIZE_T_FMT
369 i +
sizeof(
size_t ), *p_str_iter_sz,
370 &(strpool_p[i +
sizeof(
size_t )]) );
380 if( MERROR_OK != retval ) {
384 if( NULL != strpool_p ) {
385 maug_munlock( strpool->str_h, strpool_p );
393MAUG_MHANDLE mdata_strpool_extract(
struct MDATA_STRPOOL* s,
size_t i ) {
395 char* strpool = NULL;
396 MAUG_MHANDLE out_h = NULL;
398 char* out_tmp = NULL;
400 mdata_strpool_lock( s, strpool );
402 out_sz = maug_strlen( &(strpool[i]) );
403 out_h = maug_malloc( out_sz + 1, 1 );
404 maug_cleanup_if_null_alloc( MAUG_MHANDLE, out_h );
406 maug_mlock( out_h, out_tmp );
407 maug_cleanup_if_null_lock(
char*, out_tmp );
410 maug_strncpy( out_tmp, &(strpool[i]), out_sz );
414 if( NULL != out_tmp ) {
415 maug_munlock( out_h, out_tmp );
418 if( MERROR_OK != retval && NULL != out_h ) {
422 if( NULL != strpool ) {
423 mdata_strpool_unlock( s, strpool );
431ssize_t mdata_strpool_append(
432 struct MDATA_STRPOOL* strpool,
const char* str,
size_t str_sz
434 ssize_t idx_p_out = 0;
435 char* strpool_p = NULL;
437 size_t* p_str_sz = NULL;
441 if( 0 < strpool->str_sz ) {
444 idx_p_out = mdata_strpool_find( strpool, str, str_sz );
445 if( -1 != idx_p_out ) {
451 assert( 0 < str_sz );
454 padding =
sizeof( size_t ) - ((str_sz + 1 ) %
sizeof(
size_t ));
455 alloc_sz =
sizeof( size_t ) + str_sz + 1 + padding;
456 assert( 0 == alloc_sz %
sizeof(
size_t ) );
458 debug_printf( MDATA_TRACE_LVL,
459 "adding size_t (" SIZE_T_FMT
" bytes) + string %s (" SIZE_T_FMT
460 " bytes) + 1 NULL + " SIZE_T_FMT
" bytes padding to strpool...",
461 sizeof(
size_t ), str, str_sz, padding );
463 retval = mdata_strpool_alloc( strpool, alloc_sz );
464 maug_cleanup_if_not_ok();
466 maug_mlock( strpool->str_h, strpool_p );
467 maug_cleanup_if_null_alloc(
char*, strpool_p );
469 debug_printf( MDATA_TRACE_LVL,
470 "strpool (" SIZE_T_FMT
" bytes) locked to: %p",
471 strpool->str_sz, strpool_p );
474 maug_strncpy( &(strpool_p[strpool->str_sz +
sizeof(
size_t )]), str, str_sz );
475 strpool_p[strpool->str_sz +
sizeof( size_t ) + str_sz] =
'\0';
478 assert( 0 == strpool->str_sz %
sizeof(
size_t ) );
479 p_str_sz = (
size_t*)&(strpool_p[strpool->str_sz]);
480 *p_str_sz = alloc_sz;
482 idx_p_out = strpool->str_sz +
sizeof( size_t );
485 MDATA_TRACE_LVL,
"set strpool_idx: " SIZE_T_FMT
": \"%s\"",
486 strpool->str_sz, &(strpool_p[idx_p_out]) );
489 strpool->str_sz += alloc_sz;
493 if( MERROR_OK != retval ) {
494 idx_p_out = retval * -1;
497 if( NULL != strpool_p ) {
498 maug_munlock( strpool->str_h, strpool_p );
510 MAUG_MHANDLE str_h_new = (MAUG_MHANDLE)NULL;
512 if( (MAUG_MHANDLE)NULL == strpool->str_h ) {
514 MDATA_TRACE_LVL,
"creating string table of " SIZE_T_FMT
" chars...",
516 assert( NULL == strpool->str_h );
517 strpool->str_h = maug_malloc( alloc_sz, 1 );
518 maug_cleanup_if_null_alloc( MAUG_MHANDLE, strpool->str_h );
519 strpool->str_sz_max = alloc_sz;
521 }
else if( strpool->str_sz_max <= strpool->str_sz + alloc_sz ) {
522 while( strpool->str_sz_max <= strpool->str_sz + alloc_sz ) {
524 MDATA_TRACE_LVL,
"enlarging string table to " SIZE_T_FMT
"...",
525 strpool->str_sz_max * 2 );
527 str_h_new, strpool->str_h, strpool->str_sz_max, (
size_t)2 );
528 strpool->str_sz_max *= 2;
539 if( (MAUG_MHANDLE)NULL != strpool->str_h ) {
540 maug_mfree( strpool->str_h );
550 ssize_t idx_out = -1;
553 error_printf(
"attempting to add item of " SIZE_T_FMT
" bytes to vector, "
554 "but vector is already sized for " SIZE_T_FMT
"-byte items!",
556 retval = MERROR_OVERFLOW;
570 MDATA_TRACE_LVL,
"inserting into vector at index: " SIZE_T_FMT,
573 memcpy( _mdata_vector_item_ptr( v, idx_out ), item,
item_sz );
580 if( MERROR_OK != retval ) {
581 error_printf(
"error adding to vector: %d", retval );
582 idx_out = retval * -1;
583 assert( 0 > idx_out );
598 error_printf(
"vector cannot be resized while locked!" );
599 retval = MERROR_ALLOC;
604 error_printf(
"index out of range!" );
605 retval = MERROR_OVERFLOW;
609 debug_printf( MDATA_TRACE_LVL,
"removing vector item: " SIZE_T_FMT, idx );
615 for( i = idx ; v->
ct > i + 1 ; i++ ) {
616 debug_printf( MDATA_TRACE_LVL,
617 "shifting " SIZE_T_FMT
"-byte vector item " SIZE_T_FMT
" up by 1...",
638 debug_printf( MDATA_TRACE_LVL,
639 "getting vector item " SIZE_T_FMT
" (of " SIZE_T_FMT
")...",
647 return _mdata_vector_item_ptr( v, idx );
659 error_printf(
"vector cannot be copied while locked!" );
660 retval = MERROR_ALLOC;
665 assert( 0 < v_src->
ct_max );
668 v_dest->
ct = v_src->
ct;
672 "copying " SIZE_T_FMT
" vector of " SIZE_T_FMT
"-byte nodes...",
674 assert( NULL == v_dest->
data_h );
676 maug_cleanup_if_null_alloc( MAUG_MHANDLE, v_dest->
data_h );
698 MAUG_MHANDLE data_h_new = NULL;
699 size_t new_ct = item_ct_init,
704 error_printf(
"vector cannot be resized while locked!" );
705 retval = MERROR_ALLOC;
710 if( (MAUG_MHANDLE)NULL == v->
data_h ) {
717 "creating " SIZE_T_FMT
" vector of " SIZE_T_FMT
"-byte nodes...",
719 assert( NULL == v->
data_h );
722 maug_cleanup_if_null_alloc( MAUG_MHANDLE, v->
data_h );
729 }
else if( v->
ct_max <= v->
ct + 1 || v->
ct_max <= item_ct_init ) {
740 MDATA_TRACE_LVL,
"enlarging vector to " SIZE_T_FMT
"...",
742 maug_mrealloc_test( data_h_new, v->
data_h, new_ct,
item_sz );
746 assert( new_bytes_start >= v->
ct_max );
747 new_bytes_sz = (new_ct * v->
item_sz) - new_bytes_start;
748 assert( new_bytes_sz >= v->
item_sz );
764 if( (MAUG_MHANDLE)NULL != v->
data_h ) {
775 struct MDATA_TABLE* t,
const char* key,
size_t key_sz,
776 void* value,
size_t value_sz
779 ssize_t idx_key = -1;
780 ssize_t idx_val = -1;
791 assert( 0 <= idx_key );
796 assert( 0 <= idx_val );
808 struct MDATA_TABLE* t,
const char* key,
void** value_out,
size_t value_sz
814 assert( NULL == *value_out );
820 c = mdata_vector_get( &(t->data_cols[0]), i,
char );
822 if( 0 == strncmp( key, c, t->data_cols[0].
item_sz - 1 ) ) {
829 retval = MERROR_OVERFLOW;
int MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition merror.h:19
#define maug_mzero(ptr, sz)
Zero the block of memory pointed to by ptr.
Definition mmem.h:65
#define mdata_vector_lock(v)
Lock the vector. This should be done when items from the vector are actively being referenced,...
Definition mdata.h:241
void * mdata_vector_get_void(struct MDATA_VECTOR *v, size_t idx)
Get a generic pointer to an item in the MDATA_VECTOR.
#define mdata_vector_unlock(v)
Unlock the vector so items may be added and removed.
Definition mdata.h:265
#define MDATA_VECTOR_INIT_SZ
Default initial value for MDATA_VECTOR::ct_max.
Definition mdata.h:37
ssize_t mdata_vector_append(struct MDATA_VECTOR *v, const void *item, size_t item_sz)
Append an item to the specified vector.
MERROR_RETVAL mdata_vector_remove(struct MDATA_VECTOR *v, size_t idx)
Remove item at the given index, shifting subsequent items up by 1.
#define mdata_vector_ct(v)
Number of items of MDATA_VECTOR::item_sz bytes actively stored in this vector.
Definition mdata.h:299
#define MDATA_VECTOR_INIT_STEP_SZ
Default initial value for MDATA_VECTOR::ct_step.
Definition mdata.h:45
MERROR_RETVAL mdata_vector_alloc(struct MDATA_VECTOR *v, size_t item_sz, size_t item_ct_init)
A pool of immutable text strings. Deduplicates strings to save memory.
Definition mdata.h:66
A vector of uniformly-sized objects, stored contiguously.
Definition mdata.h:89
size_t ct_step
Number of items added when more space is needed.
Definition mdata.h:100
MAUG_MHANDLE data_h
Handle for allocated items (unlocked).
Definition mdata.h:92
size_t item_sz
Size, in bytes, of each item.
Definition mdata.h:105
size_t ct
Maximum number of items actually used.
Definition mdata.h:98
uint8_t * data_bytes
Handle for allocated items (locked).
Definition mdata.h:94
size_t ct_max
Maximum number of items currently allocated for.
Definition mdata.h:96
ssize_t locks
Lock count, if MDATA_VECTOR_FLAG_REFCOUNT is enabled.
Definition mdata.h:107