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 assert( NULL != (v)->data_h && NULL == (v)->data_bytes ); \
251 maug_mlock( (v)->data_h, (v)->data_bytes ); \
252 maug_cleanup_if_null_lock( uint8_t*, (v)->data_bytes ); \
253 debug_printf( MDATA_TRACE_LVL, "locked vector " #v ); \
261#define mdata_vector_unlock( v ) \
263 mdata_vector_get_flag( v, MDATA_VECTOR_FLAG_REFCOUNT ) && \
267 debug_printf( MDATA_TRACE_LVL, "vector " #v " locks: " SSIZE_T_FMT, \
270 if( 0 == (v)->locks && NULL != (v)->data_bytes ) { \
271 assert( NULL == (v)->data_h && NULL != (v)->data_bytes ); \
272 maug_munlock( (v)->data_h, (v)->data_bytes ); \
273 debug_printf( MDATA_TRACE_LVL, "unlocked vector " #v ); \
276#define mdata_vector_get( v, idx, type ) \
277 ((type*)mdata_vector_get_void( v, idx ))
279#define mdata_vector_get_last( v, type ) \
280 (0 < mdata_vector_ct( v ) ? \
281 ((type*)mdata_vector_get_void( v, \
282 mdata_vector_ct( v ) - 1 )) : NULL)
284#define mdata_vector_remove_last( v ) \
285 (0 < mdata_vector_ct( v ) ? \
286 (mdata_vector_remove( v, mdata_vector_ct( v ) - 1 )) : MERROR_OVERFLOW)
295#define mdata_vector_ct( v ) ((v)->ct)
301#define mdata_vector_sz( v ) (((v)->ct_max) * ((v)->item_sz))
307#define mdata_vector_fill( v, ct_new, sz ) \
308 retval = mdata_vector_alloc( v, sz, ct_new ); \
309 maug_cleanup_if_not_ok(); \
312#define mdata_vector_is_locked( v ) (NULL != (v)->data_bytes)
315#define mdata_vector_insert_sort( v, i, t, field )
318#define mdata_vector_sort( v, t, field )
320#define _mdata_vector_item_ptr( v, idx ) \
321 (&((v)->data_bytes[((idx) * ((v)->item_sz))]))
323#define mdata_vector_set_flag( v, flag ) (v)->flags |= (flag)
325#define mdata_vector_get_flag( v, flag ) ((flag) == ((v)->flags & (flag)))
329#define mdata_retval( idx ) (0 > idx ? ((idx) * -1) : MERROR_OK)
333ssize_t mdata_strpool_find(
334 struct MDATA_STRPOOL* strpool,
const char* str,
size_t str_sz
338 char* strpool_p = NULL;
339 size_t* p_str_iter_sz = NULL;
341 if( NULL == strpool->str_h ) {
342 error_printf(
"strpool not allocated!" );
347 maug_mlock( strpool->str_h, strpool_p );
349 while( i < strpool->str_sz ) {
350 p_str_iter_sz = (
size_t*)&(strpool_p[i]);
352 0 == strncmp( &(strpool_p[i +
sizeof(
size_t )]), str, str_sz + 1 )
355 i +=
sizeof( size_t );
356 debug_printf( MDATA_TRACE_LVL,
357 "found strpool_idx: " SIZE_T_FMT
" (" SIZE_T_FMT
" bytes): \"%s\"",
358 i, *p_str_iter_sz, &(strpool_p[i]) );
362 debug_printf( MDATA_TRACE_LVL,
363 "skipping strpool_idx: " SIZE_T_FMT
" (" SIZE_T_FMT
365 i +
sizeof(
size_t ), *p_str_iter_sz,
366 &(strpool_p[i +
sizeof(
size_t )]) );
376 if( MERROR_OK != retval ) {
380 if( NULL != strpool_p ) {
381 maug_munlock( strpool->str_h, strpool_p );
389MAUG_MHANDLE mdata_strpool_extract(
struct MDATA_STRPOOL* s,
size_t i ) {
391 char* strpool = NULL;
392 MAUG_MHANDLE out_h = NULL;
394 char* out_tmp = NULL;
396 mdata_strpool_lock( s, strpool );
398 out_sz = maug_strlen( &(strpool[i]) );
399 out_h = maug_malloc( out_sz + 1, 1 );
400 maug_cleanup_if_null_alloc( MAUG_MHANDLE, out_h );
402 maug_mlock( out_h, out_tmp );
403 maug_cleanup_if_null_lock(
char*, out_tmp );
406 maug_strncpy( out_tmp, &(strpool[i]), out_sz );
410 if( NULL != out_tmp ) {
411 maug_munlock( out_h, out_tmp );
414 if( MERROR_OK != retval && NULL != out_h ) {
418 if( NULL != strpool ) {
419 mdata_strpool_unlock( s, strpool );
427ssize_t mdata_strpool_append(
428 struct MDATA_STRPOOL* strpool,
const char* str,
size_t str_sz
430 ssize_t idx_p_out = 0;
431 char* strpool_p = NULL;
433 size_t* p_str_sz = NULL;
437 if( 0 < strpool->str_sz ) {
440 idx_p_out = mdata_strpool_find( strpool, str, str_sz );
441 if( -1 != idx_p_out ) {
447 assert( 0 < str_sz );
450 padding =
sizeof( size_t ) - ((str_sz + 1 ) %
sizeof(
size_t ));
451 alloc_sz =
sizeof( size_t ) + str_sz + 1 + padding;
452 assert( 0 == alloc_sz %
sizeof(
size_t ) );
454 debug_printf( MDATA_TRACE_LVL,
455 "adding size_t (" SIZE_T_FMT
" bytes) + string %s (" SIZE_T_FMT
456 " bytes) + 1 NULL + " SIZE_T_FMT
" bytes padding to strpool...",
457 sizeof(
size_t ), str, str_sz, padding );
459 retval = mdata_strpool_alloc( strpool, alloc_sz );
460 maug_cleanup_if_not_ok();
462 maug_mlock( strpool->str_h, strpool_p );
463 maug_cleanup_if_null_alloc(
char*, strpool_p );
465 debug_printf( MDATA_TRACE_LVL,
466 "strpool (" SIZE_T_FMT
" bytes) locked to: %p",
467 strpool->str_sz, strpool_p );
470 maug_strncpy( &(strpool_p[strpool->str_sz +
sizeof(
size_t )]), str, str_sz );
471 strpool_p[strpool->str_sz +
sizeof( size_t ) + str_sz] =
'\0';
474 assert( 0 == strpool->str_sz %
sizeof(
size_t ) );
475 p_str_sz = (
size_t*)&(strpool_p[strpool->str_sz]);
476 *p_str_sz = alloc_sz;
478 idx_p_out = strpool->str_sz +
sizeof( size_t );
481 MDATA_TRACE_LVL,
"set strpool_idx: " SIZE_T_FMT
": \"%s\"",
482 strpool->str_sz, &(strpool_p[idx_p_out]) );
485 strpool->str_sz += alloc_sz;
489 if( MERROR_OK != retval ) {
490 idx_p_out = retval * -1;
493 if( NULL != strpool_p ) {
494 maug_munlock( strpool->str_h, strpool_p );
506 MAUG_MHANDLE str_h_new = (MAUG_MHANDLE)NULL;
508 if( (MAUG_MHANDLE)NULL == strpool->str_h ) {
510 MDATA_TRACE_LVL,
"creating string table of " SIZE_T_FMT
" chars...",
512 assert( NULL == strpool->str_h );
513 strpool->str_h = maug_malloc( alloc_sz, 1 );
514 maug_cleanup_if_null_alloc( MAUG_MHANDLE, strpool->str_h );
515 strpool->str_sz_max = alloc_sz;
517 }
else if( strpool->str_sz_max <= strpool->str_sz + alloc_sz ) {
518 while( strpool->str_sz_max <= strpool->str_sz + alloc_sz ) {
520 MDATA_TRACE_LVL,
"enlarging string table to " SIZE_T_FMT
"...",
521 strpool->str_sz_max * 2 );
523 str_h_new, strpool->str_h, strpool->str_sz_max, (
size_t)2 );
524 strpool->str_sz_max *= 2;
535 if( (MAUG_MHANDLE)NULL != strpool->str_h ) {
536 maug_mfree( strpool->str_h );
546 ssize_t idx_out = -1;
549 error_printf(
"attempting to add item of " SIZE_T_FMT
" bytes to vector, "
550 "but vector is already sized for " SIZE_T_FMT
"-byte items!",
552 retval = MERROR_OVERFLOW;
566 MDATA_TRACE_LVL,
"inserting into vector at index: " SIZE_T_FMT,
569 memcpy( _mdata_vector_item_ptr( v, idx_out ), item,
item_sz );
576 if( MERROR_OK != retval ) {
577 error_printf(
"error adding to vector: %d", retval );
578 idx_out = retval * -1;
579 assert( 0 > idx_out );
594 error_printf(
"vector cannot be resized while locked!" );
595 retval = MERROR_ALLOC;
600 error_printf(
"index out of range!" );
601 retval = MERROR_OVERFLOW;
605 debug_printf( MDATA_TRACE_LVL,
"removing vector item: " SIZE_T_FMT, idx );
611 for( i = idx ; v->
ct > i + 1 ; i++ ) {
612 debug_printf( MDATA_TRACE_LVL,
613 "shifting " SIZE_T_FMT
"-byte vector item " SIZE_T_FMT
" up by 1...",
634 debug_printf( MDATA_TRACE_LVL,
635 "getting vector item " SIZE_T_FMT
" (of " SIZE_T_FMT
")...",
643 return _mdata_vector_item_ptr( v, idx );
655 error_printf(
"vector cannot be copied while locked!" );
656 retval = MERROR_ALLOC;
661 assert( 0 < v_src->
ct_max );
664 v_dest->
ct = v_src->
ct;
668 "copying " SIZE_T_FMT
" vector of " SIZE_T_FMT
"-byte nodes...",
670 assert( NULL == v_dest->
data_h );
672 maug_cleanup_if_null_alloc( MAUG_MHANDLE, v_dest->
data_h );
694 MAUG_MHANDLE data_h_new = NULL;
695 size_t new_ct = item_ct_init,
700 error_printf(
"vector cannot be resized while locked!" );
701 retval = MERROR_ALLOC;
706 if( (MAUG_MHANDLE)NULL == v->
data_h ) {
713 "creating " SIZE_T_FMT
" vector of " SIZE_T_FMT
"-byte nodes...",
715 assert( NULL == v->
data_h );
718 maug_cleanup_if_null_alloc( MAUG_MHANDLE, v->
data_h );
725 }
else if( v->
ct_max <= v->
ct + 1 || v->
ct_max <= item_ct_init ) {
736 MDATA_TRACE_LVL,
"enlarging vector to " SIZE_T_FMT
"...",
738 maug_mrealloc_test( data_h_new, v->
data_h, new_ct,
item_sz );
742 assert( new_bytes_start >= v->
ct_max );
743 new_bytes_sz = (new_ct * v->
item_sz) - new_bytes_start;
744 assert( new_bytes_sz >= v->
item_sz );
760 if( (MAUG_MHANDLE)NULL != v->
data_h ) {
771 struct MDATA_TABLE* t,
const char* key,
size_t key_sz,
772 void* value,
size_t value_sz
775 ssize_t idx_key = -1;
776 ssize_t idx_val = -1;
787 assert( 0 <= idx_key );
792 assert( 0 <= idx_val );
804 struct MDATA_TABLE* t,
const char* key,
void** value_out,
size_t value_sz
810 assert( NULL == *value_out );
816 c = mdata_vector_get( &(t->data_cols[0]), i,
char );
818 if( 0 == strncmp( key, c, t->data_cols[0].
item_sz - 1 ) ) {
825 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:62
#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:261
#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:295
#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