13#ifndef MDATA_TRACE_LVL
14# define MDATA_TRACE_LVL 0
30#define MDATA_VECTOR_FLAG_REFCOUNT 0x01
32#define MDATA_VECTOR_FLAG_IS_LOCKED 0x02
34#ifndef MDATA_VECTOR_INIT_STEP_SZ
39# define MDATA_VECTOR_INIT_STEP_SZ 10
51typedef ssize_t mdata_strpool_idx_t;
127ssize_t mdata_strpool_find(
128 struct MDATA_STRPOOL* strpool,
const char* str,
size_t str_sz );
130MAUG_MHANDLE mdata_strpool_extract(
struct MDATA_STRPOOL* s,
size_t i );
132ssize_t mdata_strpool_append(
133 struct MDATA_STRPOOL* strpool,
const char* str,
size_t str_sz );
200 struct MDATA_TABLE* t,
const char* key,
size_t key_sz,
201 void* value,
size_t value_sz );
204 struct MDATA_TABLE* t,
const char* key,
void** value_out,
size_t value_sz );
213#define mdata_strpool_sz( strpool ) ((strpool)->str_sz_max)
215#define mdata_strpool_lock( strpool, ptr ) \
216 maug_mlock( (strpool)->str_h, ptr ); \
217 maug_cleanup_if_null_lock( char*, ptr );
219#define mdata_strpool_unlock( strpool, ptr ) \
220 if( NULL != ptr ) { \
221 maug_munlock( (strpool)->str_h, ptr ); \
239#define mdata_vector_lock( v ) \
241 mdata_vector_get_flag( v, MDATA_VECTOR_FLAG_REFCOUNT ) && \
245 debug_printf( MDATA_TRACE_LVL, "vector " #v " locks: " SSIZE_T_FMT, \
248 assert( !mdata_vector_is_locked( v ) ); \
249 if( mdata_vector_is_locked( v ) ) { \
250 error_printf( "attempting to double-lock vector!" ); \
251 retval = MERROR_OVERFLOW; \
254 maug_mlock( (v)->data_h, (v)->data_bytes ); \
255 maug_cleanup_if_null_lock( uint8_t*, (v)->data_bytes ); \
256 (v)->flags |= MDATA_VECTOR_FLAG_IS_LOCKED; \
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( mdata_vector_is_locked( v ) ); \
276 maug_munlock( (v)->data_h, (v)->data_bytes ); \
277 (v)->flags &= ~MDATA_VECTOR_FLAG_IS_LOCKED; \
278 debug_printf( MDATA_TRACE_LVL, "unlocked vector " #v ); \
281#define mdata_vector_get( v, idx, type ) \
282 ((type*)mdata_vector_get_void( v, idx ))
284#define mdata_vector_get_last( v, type ) \
285 (0 < mdata_vector_ct( v ) ? \
286 ((type*)mdata_vector_get_void( v, \
287 mdata_vector_ct( v ) - 1 )) : NULL)
289#define mdata_vector_remove_last( v ) \
290 (0 < mdata_vector_ct( v ) ? \
291 (mdata_vector_remove( v, mdata_vector_ct( v ) - 1 )) : MERROR_OVERFLOW)
293#define mdata_vector_set_ct_step( v, step ) \
303#define mdata_vector_ct( v ) ((v)->ct)
309#define mdata_vector_sz( v ) (((v)->ct_max) * ((v)->item_sz))
315#define mdata_vector_fill( v, ct_new, sz ) \
316 retval = mdata_vector_alloc( v, sz, ct_new ); \
317 maug_cleanup_if_not_ok(); \
320#define mdata_vector_is_locked( v ) \
321 (MDATA_VECTOR_FLAG_IS_LOCKED == \
322 (MDATA_VECTOR_FLAG_IS_LOCKED & (v)->flags))
325#define mdata_vector_insert_sort( v, i, t, field )
328#define mdata_vector_sort( v, t, field )
330#define _mdata_vector_item_ptr( v, idx ) \
331 (&((v)->data_bytes[((idx) * ((v)->item_sz))]))
333#define mdata_vector_set_flag( v, flag ) (v)->flags |= (flag)
335#define mdata_vector_get_flag( v, flag ) ((flag) == ((v)->flags & (flag)))
339#define mdata_retval( idx ) (0 > idx ? ((idx) * -1) : MERROR_OK)
343ssize_t mdata_strpool_find(
344 struct MDATA_STRPOOL* strpool,
const char* str,
size_t str_sz
348 char* strpool_p = NULL;
349 size_t* p_str_iter_sz = NULL;
351 if( (MAUG_MHANDLE)NULL == strpool->str_h ) {
352 error_printf(
"strpool not allocated!" );
357 maug_mlock( strpool->str_h, strpool_p );
359 while( i < strpool->str_sz ) {
360 p_str_iter_sz = (
size_t*)&(strpool_p[i]);
362 0 == strncmp( &(strpool_p[i +
sizeof(
size_t )]), str, str_sz + 1 )
365 i +=
sizeof( size_t );
366 debug_printf( MDATA_TRACE_LVL,
367 "found strpool_idx: " SIZE_T_FMT
" (" SIZE_T_FMT
" bytes): \"%s\"",
368 i, *p_str_iter_sz, &(strpool_p[i]) );
372 debug_printf( MDATA_TRACE_LVL,
373 "skipping strpool_idx: " SIZE_T_FMT
" (" SIZE_T_FMT
375 i +
sizeof(
size_t ), *p_str_iter_sz,
376 &(strpool_p[i +
sizeof(
size_t )]) );
386 if( MERROR_OK != retval ) {
390 if( NULL != strpool_p ) {
391 maug_munlock( strpool->str_h, strpool_p );
399MAUG_MHANDLE mdata_strpool_extract(
struct MDATA_STRPOOL* s,
size_t i ) {
401 char* strpool = NULL;
402 MAUG_MHANDLE out_h = (MAUG_MHANDLE)NULL;
404 char* out_tmp = NULL;
406 mdata_strpool_lock( s, strpool );
408 out_sz = maug_strlen( &(strpool[i]) );
409 out_h = maug_malloc( out_sz + 1, 1 );
410 maug_cleanup_if_null_alloc( MAUG_MHANDLE, out_h );
412 maug_mlock( out_h, out_tmp );
413 maug_cleanup_if_null_lock(
char*, out_tmp );
415 maug_mzero( out_tmp, out_sz + 1 );
416 maug_strncpy( out_tmp, &(strpool[i]), out_sz );
420 if( NULL != out_tmp ) {
421 maug_munlock( out_h, out_tmp );
424 if( MERROR_OK != retval && (MAUG_MHANDLE)NULL != out_h ) {
428 if( NULL != strpool ) {
429 mdata_strpool_unlock( s, strpool );
437ssize_t mdata_strpool_append(
438 struct MDATA_STRPOOL* strpool,
const char* str,
size_t str_sz
440 ssize_t idx_p_out = 0;
441 char* strpool_p = NULL;
443 size_t* p_str_sz = NULL;
447 if( 0 < strpool->str_sz ) {
450 idx_p_out = mdata_strpool_find( strpool, str, str_sz );
451 if( -1 != idx_p_out ) {
457 assert( 0 < str_sz );
460 padding =
sizeof( size_t ) - ((str_sz + 1 ) %
sizeof(
size_t ));
461 alloc_sz =
sizeof( size_t ) + str_sz + 1 + padding;
462 assert( 0 == alloc_sz %
sizeof(
size_t ) );
464 debug_printf( MDATA_TRACE_LVL,
465 "adding size_t (" SIZE_T_FMT
" bytes) + string %s (" SIZE_T_FMT
466 " bytes) + 1 NULL + " SIZE_T_FMT
" bytes padding to strpool...",
467 sizeof(
size_t ), str, str_sz, padding );
469 retval = mdata_strpool_alloc( strpool, alloc_sz );
470 maug_cleanup_if_not_ok();
472 maug_mlock( strpool->str_h, strpool_p );
473 maug_cleanup_if_null_alloc(
char*, strpool_p );
475 debug_printf( MDATA_TRACE_LVL,
476 "strpool (" SIZE_T_FMT
" bytes) locked to: %p",
477 strpool->str_sz, strpool_p );
480 maug_strncpy( &(strpool_p[strpool->str_sz +
sizeof(
size_t )]), str, str_sz );
481 strpool_p[strpool->str_sz +
sizeof( size_t ) + str_sz] =
'\0';
484 assert( 0 == strpool->str_sz %
sizeof(
size_t ) );
485 p_str_sz = (
size_t*)&(strpool_p[strpool->str_sz]);
486 *p_str_sz = alloc_sz;
488 idx_p_out = strpool->str_sz +
sizeof( size_t );
491 MDATA_TRACE_LVL,
"set strpool_idx: " SIZE_T_FMT
": \"%s\"",
492 strpool->str_sz, &(strpool_p[idx_p_out]) );
495 strpool->str_sz += alloc_sz;
499 if( MERROR_OK != retval ) {
500 idx_p_out = retval * -1;
503 if( NULL != strpool_p ) {
504 maug_munlock( strpool->str_h, strpool_p );
516 MAUG_MHANDLE str_h_new = (MAUG_MHANDLE)NULL;
518 if( (MAUG_MHANDLE)NULL == strpool->str_h ) {
520 MDATA_TRACE_LVL,
"creating string table of " SIZE_T_FMT
" chars...",
522 assert( (MAUG_MHANDLE)NULL == strpool->str_h );
523 strpool->str_h = maug_malloc( alloc_sz, 1 );
524 maug_cleanup_if_null_alloc( MAUG_MHANDLE, strpool->str_h );
525 strpool->str_sz_max = alloc_sz;
528 }
else if( strpool->str_sz_max <= strpool->str_sz + alloc_sz ) {
529 while( strpool->str_sz_max <= strpool->str_sz + alloc_sz ) {
531 MDATA_TRACE_LVL,
"enlarging string table to " SIZE_T_FMT
"...",
532 strpool->str_sz_max * 2 );
534 str_h_new, strpool->str_h, strpool->str_sz_max, (
size_t)2 );
535 strpool->str_sz_max *= 2;
546 if( (MAUG_MHANDLE)NULL != strpool->str_h ) {
547 maug_mfree( strpool->str_h );
553ssize_t mdata_vector_append(
554 struct MDATA_VECTOR* v,
const void* item,
size_t item_sz
557 ssize_t idx_out = -1;
560 error_printf(
"attempting to add item of " SIZE_T_FMT
" bytes to vector, "
561 "but vector is already sized for " SIZE_T_FMT
"-byte items!",
563 retval = MERROR_OVERFLOW;
570 mdata_vector_lock( v );
577 MDATA_TRACE_LVL,
"inserting into vector at index: " SIZE_T_FMT,
580 memcpy( _mdata_vector_item_ptr( v, idx_out ), item, item_sz );
587 if( MERROR_OK != retval ) {
588 error_printf(
"error adding to vector: %d", retval );
589 idx_out = retval * -1;
590 assert( 0 > idx_out );
593 mdata_vector_unlock( v );
605 error_printf(
"vector cannot be resized while locked!" );
606 retval = MERROR_ALLOC;
611 error_printf(
"index out of range!" );
612 retval = MERROR_OVERFLOW;
616 debug_printf( MDATA_TRACE_LVL,
"removing vector item: " SIZE_T_FMT, idx );
620 mdata_vector_lock( v );
622 for( i = idx ; v->
ct > i + 1 ; i++ ) {
623 debug_printf( MDATA_TRACE_LVL,
624 "shifting " SIZE_T_FMT
"-byte vector item " SIZE_T_FMT
" up by 1...",
636 mdata_vector_unlock( v );
643void* mdata_vector_get_void(
struct MDATA_VECTOR* v,
size_t idx ) {
645 debug_printf( MDATA_TRACE_LVL,
646 "getting vector item " SIZE_T_FMT
" (of " SIZE_T_FMT
")...",
654 return _mdata_vector_item_ptr( v, idx );
666 error_printf(
"vector cannot be copied while locked!" );
667 retval = MERROR_ALLOC;
672 assert( 0 < v_src->
ct_max );
675 v_dest->
ct = v_src->
ct;
679 "copying " SIZE_T_FMT
" vector of " SIZE_T_FMT
"-byte nodes...",
681 assert( (MAUG_MHANDLE)NULL == v_dest->
data_h );
683 maug_cleanup_if_null_alloc( MAUG_MHANDLE, v_dest->
data_h );
685 mdata_vector_lock( v_dest );
686 mdata_vector_lock( v_src );
693 mdata_vector_unlock( v_src );
694 mdata_vector_unlock( v_dest );
702 struct MDATA_VECTOR* v,
size_t item_sz,
size_t item_ct_init
705 MAUG_MHANDLE data_h_new = (MAUG_MHANDLE)NULL;
706 size_t new_ct = item_ct_init,
711 error_printf(
"vector cannot be resized while locked!" );
712 retval = MERROR_ALLOC;
717 if( (MAUG_MHANDLE)NULL == v->
data_h ) {
720 if( 0 < item_ct_init ) {
721 debug_printf( MDATA_TRACE_LVL,
"setting step sz: " SIZE_T_FMT,
725 debug_printf( MDATA_TRACE_LVL,
"setting step sz: %d",
726 MDATA_VECTOR_INIT_STEP_SZ );
727 v->
ct_step = MDATA_VECTOR_INIT_STEP_SZ;
732 "creating " SIZE_T_FMT
" vector of " SIZE_T_FMT
"-byte nodes...",
734 assert( (MAUG_MHANDLE)NULL == v->
data_h );
737 maug_cleanup_if_null_alloc( MAUG_MHANDLE, v->
data_h );
740 mdata_vector_lock( v );
742 mdata_vector_unlock( v );
746 }
else if( v->
ct_max <= v->
ct + 1 || v->
ct_max <= item_ct_init ) {
757 MDATA_TRACE_LVL,
"enlarging vector to " SIZE_T_FMT
"...",
759 maug_mrealloc_test( data_h_new, v->
data_h, new_ct,
item_sz );
763 assert( new_bytes_start >= v->
ct_max );
764 new_bytes_sz = (new_ct * v->
item_sz) - new_bytes_start;
765 assert( new_bytes_sz >= v->
item_sz );
767 maug_mzero( &(v->
data_bytes[new_bytes_start]), new_bytes_sz );
792 struct MDATA_TABLE* t,
const char* key,
size_t key_sz,
793 void* value,
size_t value_sz
796 ssize_t idx_key = -1;
797 ssize_t idx_val = -1;
808 assert( 0 <= idx_key );
813 assert( 0 <= idx_val );
825 struct MDATA_TABLE* t,
const char* key,
void** value_out,
size_t value_sz
831 assert( NULL == *value_out );
837 c = mdata_vector_get( &(t->data_cols[0]), i,
char );
839 if( 0 == strncmp( key, c, t->data_cols[0].
item_sz - 1 ) ) {
846 retval = MERROR_OVERFLOW;
int MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition merror.h:19
#define mdata_vector_lock(v)
Lock the vector. This should be done when items from the vector are actively being referenced,...
Definition mdata.h:239
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
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:303
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:60
size_t sz
Size of this struct (useful for serializing).
Definition mdata.h:62
A vector of uniformly-sized objects, stored contiguously.
Definition mdata.h:85
size_t ct_step
Number of items added when more space is needed.
Definition mdata.h:98
MAUG_MHANDLE data_h
Handle for allocated items (unlocked).
Definition mdata.h:90
size_t item_sz
Size, in bytes, of each item.
Definition mdata.h:103
size_t sz
Size of this struct (useful for serializing).
Definition mdata.h:87
size_t ct
Maximum number of items actually used.
Definition mdata.h:96
uint8_t * data_bytes
Handle for allocated items (locked).
Definition mdata.h:92
size_t ct_max
Maximum number of items currently allocated for.
Definition mdata.h:94
ssize_t locks
Lock count, if MDATA_VECTOR_FLAG_REFCOUNT is enabled.
Definition mdata.h:105