13#ifndef MDATA_LOCK_TRACE_LVL
14# define MDATA_LOCK_TRACE_LVL 0
17#ifndef MDATA_STRPOOL_TRACE_LVL
18# define MDATA_STRPOOL_TRACE_LVL 0
21#ifndef MDATA_VECTOR_TRACE_LVL
22# define MDATA_VECTOR_TRACE_LVL 0
25#ifndef MDATA_TABLE_TRACE_LVL
26# define MDATA_TABLE_TRACE_LVL 0
29#ifndef MDATA_TABLE_KEY_SZ_MAX
30# define MDATA_TABLE_KEY_SZ_MAX 8
46#define MDATA_VECTOR_FLAG_REFCOUNT 0x01
48#define MDATA_VECTOR_FLAG_IS_LOCKED 0x02
50#ifndef MDATA_VECTOR_INIT_STEP_SZ
55# define MDATA_VECTOR_INIT_STEP_SZ 10
67#define MDATA_STRPOOL_FLAG_IS_LOCKED 0x01
69#define MDATA_STRPOOL_FLAG_DEDUPE 0x02
71#define MDATA_STRPOOL_IDX_ERROR 0
73typedef size_t mdata_strpool_idx_t;
137 char string[MDATA_TABLE_KEY_SZ_MAX + 1];
143 volatile uint16_t flags;
174mdata_strpool_idx_t mdata_strpool_find(
184mdata_strpool_idx_t mdata_strpool_append(
185 struct MDATA_STRPOOL* sp,
const char* str,
size_t str_sz, uint8_t flags );
218ssize_t mdata_vector_insert(
252uint32_t mdata_hash(
const char* token,
size_t token_sz );
261 void* cb_data,
size_t cb_data_sz,
size_t idx );
269 mdata_table_iter_t cb,
void* cb_data,
size_t cb_data_sz );
273 void* value,
size_t value_sz );
278void* mdata_table_get_void(
const struct MDATA_TABLE* t,
const char* key );
280void* mdata_table_hash_get_void(
281 struct MDATA_TABLE* t, uint32_t key_hash,
size_t key_sz );
287#if MDATA_LOCK_TRACE_LVL > 0
288# define mdata_debug_lock_printf( fmt, ... ) \
289 debug_printf( MDATA_LOCK_TRACE_LVL, fmt, __VA_ARGS__ );
291# define mdata_debug_lock_printf( fmt, ... )
302#define mdata_strpool_ct( sp ) ((sp)->str_ct)
307#define mdata_strpool_sz( sp ) ((sp)->str_sz_max)
309#define mdata_strpool_is_locked( sp ) \
310 (MDATA_STRPOOL_FLAG_IS_LOCKED == \
311 (MDATA_STRPOOL_FLAG_IS_LOCKED & (sp)->flags))
313#define mdata_strpool_lock( sp ) \
314 mdata_debug_lock_printf( "locking strpool %p...", sp ); \
315 if( NULL != (sp)->str_p ) { \
316 error_printf( "str_p not null! double lock?" ); \
317 retval = MERROR_ALLOC; \
320 maug_mlock( (sp)->str_h, (sp)->str_p ); \
321 maug_cleanup_if_null_lock( char*, (sp)->str_p ); \
322 (sp)->flags |= MDATA_STRPOOL_FLAG_IS_LOCKED;
324#define mdata_strpool_unlock( sp ) \
325 mdata_debug_lock_printf( "unlocking strpool %p...", sp ); \
326 if( NULL != (sp)->str_p ) { \
327 maug_munlock( (sp)->str_h, (sp)->str_p ); \
328 (sp)->flags &= ~MDATA_STRPOOL_FLAG_IS_LOCKED; \
334#define mdata_strpool_get( sp, idx ) \
335 ((idx >= 1 && idx < (sp)->str_sz) ? &((sp)->str_p[idx]) : NULL)
346#define mdata_strpool_get_sz( sp, idx ) \
347 ((idx >= sizeof( size_t ) && idx < (sp)->str_sz) ? \
348 (size_t)(*(&((sp)->str_p[idx - sizeof( size_t )]))) : 0)
350#define mdata_strpool_get_len( sp, idx ) \
351 ((idx >= sizeof( size_t ) && idx < (sp)->str_sz) ? \
352 (maug_strlen( &((sp)->str_p[idx]) )) : 0)
354#define mdata_strpool_padding( str_sz ) \
355 (sizeof( size_t ) - ((str_sz + 1 ) % sizeof( size_t )))
372#define mdata_vector_lock( v ) \
373 if( (MAUG_MHANDLE)NULL == (v)->data_h && NULL == (v)->data_bytes ) { \
374 mdata_debug_lock_printf( "locking empty vector..." ); \
375 (v)->flags |= MDATA_VECTOR_FLAG_IS_LOCKED; \
377 mdata_vector_get_flag( v, MDATA_VECTOR_FLAG_REFCOUNT ) && \
381 mdata_debug_lock_printf( "vector " #v " locks: " SSIZE_T_FMT, (v)->locks ); \
384 if( mdata_vector_is_locked( v ) ) { \
385 error_printf( "attempting to double-lock vector!" ); \
386 retval = MERROR_OVERFLOW; \
389 if( (MAUG_MHANDLE)NULL == (v)->data_h ) { \
390 error_printf( "invalid data handle!" ); \
391 retval = MERROR_ALLOC; \
394 maug_mlock( (v)->data_h, (v)->data_bytes ); \
395 maug_cleanup_if_null_lock( uint8_t*, (v)->data_bytes ); \
396 (v)->flags |= MDATA_VECTOR_FLAG_IS_LOCKED; \
397 mdata_debug_lock_printf( "locked vector " #v ); \
405#define mdata_vector_unlock( v ) \
406 if( (MAUG_MHANDLE)NULL == (v)->data_h && NULL == (v)->data_bytes ) { \
407 mdata_debug_lock_printf( "locking empty vector..." ); \
408 (v)->flags &= ~MDATA_VECTOR_FLAG_IS_LOCKED; \
411 mdata_vector_get_flag( v, MDATA_VECTOR_FLAG_REFCOUNT ) && \
415 mdata_debug_lock_printf( "vector " #v " locks: " SSIZE_T_FMT, \
418 if( 0 == (v)->locks && NULL != (v)->data_bytes ) { \
419 assert( mdata_vector_is_locked( v ) ); \
420 maug_munlock( (v)->data_h, (v)->data_bytes ); \
421 (v)->flags &= ~MDATA_VECTOR_FLAG_IS_LOCKED; \
422 mdata_debug_lock_printf( "unlocked vector " #v ); \
426#define mdata_vector_get( v, idx, type ) \
427 ((type*)mdata_vector_get_void( v, idx ))
429#define mdata_vector_get_last( v, type ) \
430 (0 < mdata_vector_ct( v ) ? \
431 ((type*)mdata_vector_get_void( v, \
432 mdata_vector_ct( v ) - 1 )) : NULL)
434#define mdata_vector_remove_last( v ) \
435 (0 < mdata_vector_ct( v ) ? \
436 (mdata_vector_remove( v, mdata_vector_ct( v ) - 1 )) : MERROR_OVERFLOW)
438#define mdata_vector_set_ct_step( v, step ) \
448#define mdata_vector_ct( v ) ((v)->ct)
454#define mdata_vector_sz( v ) (((v)->ct_max) * ((v)->item_sz))
460#define mdata_vector_fill( v, ct_new, sz ) \
461 retval = mdata_vector_alloc( v, sz, ct_new ); \
462 maug_cleanup_if_not_ok(); \
465#define mdata_vector_is_locked( v ) \
466 (MDATA_VECTOR_FLAG_IS_LOCKED == \
467 (MDATA_VECTOR_FLAG_IS_LOCKED & (v)->flags))
470#define mdata_vector_insert_sort( v, i, t, field )
473#define mdata_vector_sort( v, t, field )
475#define _mdata_vector_item_ptr( v, idx ) \
476 (&((v)->data_bytes[((idx) * ((v)->item_sz))]))
478#define mdata_vector_set_flag( v, flag ) (v)->flags |= (flag)
480#define mdata_vector_get_flag( v, flag ) ((flag) == ((v)->flags & (flag)))
489#define mdata_table_is_locked( t ) \
490 (mdata_vector_is_locked( &((t)->data_cols[0]) ))
492#define mdata_table_get( t, key, type ) \
493 ((type*)mdata_table_get_void( t, key ))
495#define mdata_table_hash_get( t, hash, sz, type ) \
496 ((type*)mdata_table_hash_get_void( t, hash, sz ))
498#define mdata_table_ct( t ) ((t)->data_cols[0].ct)
500#define mdata_table_sz( t ) \
501 mdata_vector_sz( &((t)->data_cols[0]) ) + \
502 mdata_vector_sz( &((t)->data_cols[1]) )
506#define mdata_retval( idx ) (0 > idx ? ((idx) * -1) : MERROR_OK)
516 size_t* p_str_iter_sz = NULL;
517 uint8_t autolock = 0;
521 error_printf(
"linear idx " SIZE_T_FMT
" exceeds " SIZE_T_FMT
" strings!",
523 retval = MERROR_OVERFLOW;
527 if( !mdata_strpool_is_locked( sp ) ) {
528 mdata_strpool_lock( sp );
535 while( i_linear < linear ) {
536 p_str_iter_sz = (
size_t*)&(sp->str_p[idx_out]);
537#if MDATA_STRPOOL_TRACE_LVL > 0
538 debug_printf( MDATA_STRPOOL_TRACE_LVL,
539 "skipping linear idx: " SIZE_T_FMT
" (" SIZE_T_FMT
" bytes): \"%s\"",
540 i_linear, *p_str_iter_sz,
541 &(strpool_p[i +
sizeof(
size_t )]) );
543 idx_out += *p_str_iter_sz;
546 error_printf(
"invalid strpool! strings counted exceed bytes!" );
547 retval = MERROR_OVERFLOW;
553 idx_out +=
sizeof( size_t );
554#if MDATA_STRPOOL_TRACE_LVL > 0
555 debug_printf( MDATA_STRPOOL_TRACE_LVL,
556 "found strpool_idx: " SIZE_T_FMT
" (" SIZE_T_FMT
" bytes): \"%s\" "
557 "to match " SIZE_T_FMT
"-byte token: %s",
558 i, *p_str_iter_sz, &(sp->str_p[i]),
565 mdata_strpool_unlock( sp );
568 if( MERROR_OK != retval ) {
569 idx_out = merror_retval_to_sz( retval );
581 mdata_strpool_idx_t i = 0;
584 if( !mdata_strpool_is_locked( sp ) ) {
585 mdata_strpool_lock( sp );
589 for( i = 0 ; sp->str_sz > i ; i += (size_t)*(&(sp->str_p[i])) ) {
599 mdata_strpool_unlock( sp );
610 uint8_t autolock = 0;
612 if( !mdata_strpool_is_locked( sp ) ) {
613 mdata_strpool_lock( sp );
618 printf(
"0x%02x ", sp->str_p[i] );
623 mdata_strpool_unlock( sp );
633mdata_strpool_idx_t mdata_strpool_find(
634 struct MDATA_STRPOOL* strpool,
const char* str,
size_t str_sz
637 mdata_strpool_idx_t i = MDATA_STRPOOL_IDX_ERROR;
638 size_t* p_str_iter_sz = NULL;
639 uint8_t autolock = 0;
641 if( (MAUG_MHANDLE)NULL == strpool->str_h ) {
642 error_printf(
"strpool not allocated!" );
643 i = MDATA_STRPOOL_IDX_ERROR;
647 if( !mdata_strpool_is_locked( strpool ) ) {
648 mdata_strpool_lock( strpool );
652 while( i < strpool->str_sz ) {
653 p_str_iter_sz = (
size_t*)&(strpool->str_p[i]);
656 &(strpool->str_p[i +
sizeof(
size_t )]), str, str_sz + 1 )
659 i +=
sizeof( size_t );
660#if MDATA_STRPOOL_TRACE_LVL > 0
661 debug_printf( MDATA_STRPOOL_TRACE_LVL,
662 "found strpool_idx: " SIZE_T_FMT
" (" SIZE_T_FMT
" bytes): \"%s\" "
663 "to match " SIZE_T_FMT
"-byte token: %s",
664 i, *p_str_iter_sz, &(strpool->str_p[i]),
669#if MDATA_STRPOOL_TRACE_LVL > 0
671 debug_printf( MDATA_STRPOOL_TRACE_LVL,
672 "skipping strpool_idx: " SIZE_T_FMT
" (" SIZE_T_FMT
674 i +
sizeof(
size_t ), *p_str_iter_sz,
675 &(strpool->str_p[i +
sizeof(
size_t )]) );
682 i = MDATA_STRPOOL_IDX_ERROR;
686 if( MERROR_OK != retval ) {
687 i = MDATA_STRPOOL_IDX_ERROR;
691 mdata_strpool_unlock( strpool );
703 MAUG_MHANDLE out_h = (MAUG_MHANDLE)NULL;
705 char* out_tmp = NULL;
707 char* str_src = NULL;
709 if( !mdata_strpool_is_locked( sp ) ) {
710 mdata_strpool_lock( sp );
715 if( NULL == str_src ) {
716 error_printf(
"invalid strpool index: " SSIZE_T_FMT, idx );
717 retval = MERROR_OVERFLOW;
721 str_sz = maug_strlen( str_src );
723 maug_malloc_test( out_h, str_sz + 1, 1 );
725 maug_mlock( out_h, out_tmp );
726 maug_cleanup_if_null_lock(
char*, out_tmp );
728 maug_mzero( out_tmp, str_sz + 1 );
732 memcpy( out_tmp, str_src, str_sz );
736 if( NULL != out_tmp ) {
737 maug_munlock( out_h, out_tmp );
740 if( MERROR_OK != retval && (MAUG_MHANDLE)NULL != out_h ) {
745 mdata_strpool_unlock( sp );
753mdata_strpool_idx_t mdata_strpool_append(
754 struct MDATA_STRPOOL* strpool,
const char* str,
size_t str_sz, uint8_t flags
756 mdata_strpool_idx_t idx_p_out = MDATA_STRPOOL_IDX_ERROR;
758 size_t* p_str_sz = NULL;
762 error_printf(
"attempted to add zero-length string!" );
763 retval = MERROR_OVERFLOW;
767 if( mdata_strpool_is_locked( strpool ) ) {
768 error_printf(
"attempted to add string to locked strpool!" );
769 retval = MERROR_ALLOC;
774 0 < strpool->str_sz &&
775 MDATA_STRPOOL_FLAG_DEDUPE == (MDATA_STRPOOL_FLAG_DEDUPE & flags)
779 idx_p_out = mdata_strpool_find( strpool, str, str_sz );
780 if( 0 < idx_p_out ) {
782#if MDATA_STRPOOL_TRACE_LVL > 0
783 debug_printf( MDATA_STRPOOL_TRACE_LVL,
784 "found duplicate string for add at index: " SSIZE_T_FMT,
792 alloc_sz =
sizeof( size_t ) + str_sz + 1 +
793 mdata_strpool_padding( str_sz );
794 assert( 0 == alloc_sz %
sizeof(
size_t ) );
796#if MDATA_STRPOOL_TRACE_LVL > 0
797 debug_printf( MDATA_STRPOOL_TRACE_LVL,
798 "adding size_t (" SIZE_T_FMT
" bytes) + string %s (" SIZE_T_FMT
799 " bytes) + 1 NULL + " SIZE_T_FMT
" bytes padding to strpool...",
800 sizeof(
size_t ), str, str_sz, mdata_strpool_padding( str_sz ) );
803 retval = mdata_strpool_alloc( strpool, alloc_sz );
804 maug_cleanup_if_not_ok();
806 mdata_strpool_lock( strpool );
808#if MDATA_LOCK_TRACE_LVL > 0
809 debug_printf( MDATA_LOCK_TRACE_LVL,
810 "strpool (" SIZE_T_FMT
" bytes) locked to: %p",
811 strpool->str_sz, strpool->str_p );
816 &(strpool->str_p[strpool->str_sz +
sizeof(
size_t )]), str, str_sz );
817 strpool->str_p[strpool->str_sz +
sizeof( size_t ) + str_sz] =
'\0';
820 assert( 0 == strpool->str_sz %
sizeof(
size_t ) );
821 p_str_sz = (
size_t*)&(strpool->str_p[strpool->str_sz]);
822 *p_str_sz = alloc_sz;
824 idx_p_out = strpool->str_sz +
sizeof( size_t );
826#if MDATA_STRPOOL_TRACE_LVL > 0
827 debug_printf( MDATA_STRPOOL_TRACE_LVL,
828 "set strpool_idx: " SIZE_T_FMT
": \"%s\"",
829 strpool->str_sz, &(strpool->str_p[idx_p_out]) );
833 strpool->str_sz += alloc_sz;
839 if( MERROR_OK != retval ) {
840 idx_p_out = MDATA_STRPOOL_IDX_ERROR;
843 if( NULL != strpool->str_p ) {
844 mdata_strpool_unlock( strpool );
856 MAUG_MHANDLE str_h_new = (MAUG_MHANDLE)NULL;
858 if( (MAUG_MHANDLE)NULL == strpool->str_h ) {
859#if MDATA_STRPOOL_TRACE_LVL > 0
861 MDATA_STRPOOL_TRACE_LVL,
862 "creating string pool of " SIZE_T_FMT
" chars...",
865 assert( (MAUG_MHANDLE)NULL == strpool->str_h );
866 maug_malloc_test( strpool->str_h, alloc_sz, 1 );
867 strpool->str_sz_max = alloc_sz;
869 }
else if( strpool->str_sz_max <= strpool->str_sz + alloc_sz ) {
870 while( strpool->str_sz_max <= strpool->str_sz + alloc_sz ) {
871#if MDATA_STRPOOL_TRACE_LVL > 0
873 MDATA_STRPOOL_TRACE_LVL,
874 "enlarging string pool to " SIZE_T_FMT
"...",
875 strpool->str_sz_max * 2 );
878 str_h_new, strpool->str_h, strpool->str_sz_max, (
size_t)2 );
879 strpool->str_sz_max *= 2;
890 if( 0 < strpool->str_sz_max && (MAUG_MHANDLE)NULL != strpool->str_h ) {
891 maug_mfree( strpool->str_h );
898 struct MDATA_VECTOR* v,
const void* item,
size_t item_sz
901 ssize_t idx_out = -1;
904 error_printf(
"attempting to add item of " SIZE_T_FMT
" bytes to vector, "
905 "but vector is already sized for " SIZE_T_FMT
"-byte items!",
907 retval = MERROR_OVERFLOW;
920#if MDATA_VECTOR_TRACE_LVL > 0
922 MDATA_VECTOR_TRACE_LVL,
"inserting into vector at index: " SIZE_T_FMT,
926 memcpy( _mdata_vector_item_ptr( v, idx_out ), item, item_sz );
933 if( MERROR_OK != retval ) {
934 error_printf(
"error adding to vector: %d", retval );
935 idx_out = retval * -1;
936 assert( 0 > idx_out );
946ssize_t mdata_vector_insert(
947 struct MDATA_VECTOR* v,
const void* item, ssize_t idx,
size_t item_sz
955 error_printf(
"attempting to add item of " SIZE_T_FMT
" bytes to vector, "
956 "but vector is already sized for " SIZE_T_FMT
"-byte items!",
958 retval = MERROR_OVERFLOW;
963 error_printf(
"attempting to insert beyond end of vector!" );
964 retval = MERROR_OVERFLOW;
973 for( i = v->
ct ; idx < i ; i-- ) {
974#if MDATA_VECTOR_TRACE_LVL > 0
975 debug_printf( MDATA_VECTOR_TRACE_LVL,
976 "copying vector item " SSIZE_T_FMT
" to " SSIZE_T_FMT
"...",
980 _mdata_vector_item_ptr( v, i ),
981 _mdata_vector_item_ptr( v, i - 1),
985#if MDATA_VECTOR_TRACE_LVL > 0
987 MDATA_VECTOR_TRACE_LVL,
988 "inserting into vector at index: " SIZE_T_FMT, idx );
992 memcpy( _mdata_vector_item_ptr( v, idx ), item, item_sz );
995 maug_mzero( _mdata_vector_item_ptr( v, idx ), item_sz );
1002 if( MERROR_OK != retval ) {
1003 error_printf(
"error adding to vector: %d", retval );
1019 if( mdata_vector_is_locked( v ) ) {
1020 error_printf(
"vector cannot be resized while locked!" );
1021 retval = MERROR_ALLOC;
1025 if( v->
ct <= idx ) {
1026 error_printf(
"index out of range!" );
1027 retval = MERROR_OVERFLOW;
1031#if MDATA_VECTOR_TRACE_LVL > 0
1032 debug_printf( MDATA_VECTOR_TRACE_LVL,
1033 "removing vector item: " SIZE_T_FMT, idx );
1040 for( i = idx ; v->
ct > i + 1 ; i++ ) {
1041#if MDATA_VECTOR_TRACE_LVL > 0
1042 debug_printf( MDATA_VECTOR_TRACE_LVL,
1043 "shifting " SIZE_T_FMT
"-byte vector item " SIZE_T_FMT
" up by 1...",
1065#if MDATA_VECTOR_TRACE_LVL > 0
1066 debug_printf( MDATA_VECTOR_TRACE_LVL,
1067 "getting vector item " SIZE_T_FMT
" (of " SIZE_T_FMT
")...",
1073 if( idx >= v->
ct ) {
1076 return _mdata_vector_item_ptr( v, idx );
1088 error_printf(
"vector cannot be copied while locked!" );
1089 retval = MERROR_ALLOC;
1094 assert( 0 < v_src->
ct_max );
1097 v_dest->
ct = v_src->
ct;
1099#if MDATA_VECTOR_TRACE_LVL > 0
1100 debug_printf( MDATA_VECTOR_TRACE_LVL,
1101 "copying " SIZE_T_FMT
" vector of " SIZE_T_FMT
"-byte nodes...",
1104 assert( (MAUG_MHANDLE)NULL == v_dest->
data_h );
1124 struct MDATA_VECTOR* v,
size_t item_sz,
size_t item_ct_init
1127 MAUG_MHANDLE data_h_new = (MAUG_MHANDLE)NULL;
1128 size_t new_ct = item_ct_init,
1129 new_bytes_start = 0,
1133 error_printf(
"vector cannot be resized while locked!" );
1134 retval = MERROR_ALLOC;
1139 if( (MAUG_MHANDLE)NULL == v->
data_h ) {
1140 assert( 0 == v->
ct_max );
1142 if( 0 < item_ct_init ) {
1143#if MDATA_VECTOR_TRACE_LVL > 0
1144 debug_printf( MDATA_VECTOR_TRACE_LVL,
"setting step sz: " SIZE_T_FMT,
1148 }
else if( 0 == v->
ct_step ) {
1149#if MDATA_VECTOR_TRACE_LVL > 0
1150 debug_printf( MDATA_VECTOR_TRACE_LVL,
"setting step sz: %d",
1156#if MDATA_VECTOR_TRACE_LVL > 0
1157 debug_printf( MDATA_VECTOR_TRACE_LVL,
1158 "creating " SIZE_T_FMT
" vector of " SIZE_T_FMT
"-byte nodes...",
1161 assert( (MAUG_MHANDLE)NULL == v->
data_h );
1170 }
else if( v->
ct_max <= v->
ct + 1 || v->
ct_max <= item_ct_init ) {
1171 assert( item_sz == v->
item_sz );
1174 if( item_ct_init < v->ct_max + v->
ct_step ) {
1180#if MDATA_VECTOR_TRACE_LVL > 0
1181 debug_printf( MDATA_VECTOR_TRACE_LVL,
1182 "enlarging vector to " SIZE_T_FMT
"...",
1185 maug_mrealloc_test( data_h_new, v->
data_h, new_ct, item_sz );
1189 assert( new_bytes_start >= v->
ct_max );
1190 new_bytes_sz = (new_ct * v->
item_sz) - new_bytes_start;
1191 assert( new_bytes_sz >= v->
item_sz );
1193 maug_mzero( &(v->
data_bytes[new_bytes_start]), new_bytes_sz );
1217uint32_t mdata_hash(
const char* token,
size_t token_sz ) {
1218 uint32_t hash_out = 2166136261u;
1222 for( i = 0 ; token_sz > i ; i++ ) {
1226 if(
'A' <= c &&
'Z' >= c ) {
1231 hash_out *= 16777619u;
1264 if( MERROR_OK != retval ) {
1265 assert( mdata_vector_is_locked( &(t->data_cols[0]) ) );
1273struct MDATA_TABLE_REPLACE_CADDY {
1280ssize_t _mdata_table_hunt_index(
1282 const char* key, uint32_t key_hash,
size_t key_sz
1287 if( 0 == mdata_table_ct( t ) ) {
1291 assert( mdata_vector_is_locked( &(t->data_cols[0]) ) );
1295 key_sz = maug_strlen( key );
1296 if( MDATA_TABLE_KEY_SZ_MAX < key_sz ) {
1297 key_sz = MDATA_TABLE_KEY_SZ_MAX;
1299 key_hash = mdata_hash( key, key_sz );
1301#if MDATA_TABLE_TRACE_LVL > 0
1302 debug_printf( MDATA_TABLE_TRACE_LVL,
1303 "searching for key: %s (%u)", key, key_hash );
1310 key_iter = mdata_vector_get(
1312 assert( NULL != key );
1314 key_iter->hash == key_hash &&
1315 key_iter->string_sz == key_sz
1317#if MDATA_TABLE_TRACE_LVL > 0
1318 debug_printf( MDATA_TABLE_TRACE_LVL,
"found value for key: %s", key );
1333 void* cb_data,
size_t cb_data_sz,
size_t idx
1336 struct MDATA_TABLE_REPLACE_CADDY* caddy =
1337 (
struct MDATA_TABLE_REPLACE_CADDY*)cb_data;
1340 key->hash == caddy->key->hash && key->string_sz == caddy->key->string_sz
1342#if MDATA_TABLE_TRACE_LVL > 0
1343 debug_printf( MDATA_TABLE_TRACE_LVL,
1344 "replacing table data for key %s (%u)...", key->string, key->hash );
1346 memcpy( data, caddy->data, data_sz );
1347 retval = MERROR_FILE;
1357 mdata_table_iter_t cb,
void* cb_data,
size_t cb_data_sz
1363 char* p_value = NULL;
1365 if( 0 == mdata_table_ct( t ) ) {
1369 if( !mdata_table_is_locked( t ) ) {
1370#if MDATA_LOCK_TRACE_LVL > 0
1371 debug_printf( MDATA_LOCK_TRACE_LVL,
"engaging table autolock..." );
1373 mdata_table_lock( t );
1378 for( i = 0 ; mdata_table_ct( t ) > i ; i++ ) {
1380 assert( NULL != p_key );
1381 assert( 0 < p_key->string_sz );
1382 assert( p_key->string_sz == maug_strlen( p_key->string ) );
1385 p_key, p_value, t->data_cols[1].
item_sz, cb_data, cb_data_sz, i );
1386 maug_cleanup_if_not_ok();
1392 mdata_table_unlock( t );
1402 void* value,
size_t value_sz
1405 ssize_t idx_key = -1;
1406 ssize_t idx_val = -1;
1408 struct MDATA_TABLE_REPLACE_CADDY caddy;
1410 assert( 0 < maug_strlen( key ) );
1412 assert( !mdata_table_is_locked( t ) );
1420 maug_strncpy( key_tmp.string, key, MDATA_TABLE_KEY_SZ_MAX );
1421 if( maug_strlen( key ) > MDATA_TABLE_KEY_SZ_MAX + 1 ) {
1423 "key %s is longer than maximum key size! truncating to: %s",
1424 key, key_tmp.string );
1426 key_tmp.string_sz = strlen( key_tmp.string );
1427 key_tmp.hash = mdata_hash( key_tmp.string, key_tmp.string_sz );
1429#if MDATA_TABLE_TRACE_LVL > 0
1430 debug_printf( MDATA_TABLE_TRACE_LVL,
1431 "attempting to set key %s (%u) to " SIZE_T_FMT
"-byte value...",
1432 key_tmp.string, key_tmp.hash, value_sz );
1435 caddy.key = &key_tmp;
1440 retval = mdata_table_iter( t, _mdata_table_replace, &caddy,
1441 sizeof(
struct MDATA_TABLE_REPLACE_CADDY ) );
1442 if( MERROR_FILE == retval ) {
1453 error_printf(
"error appending table key: %d", idx_key );
1454 retval = merror_sz_to_retval( idx_key );
1460 assert( 0 <= idx_val );
1462 error_printf(
"error appending table value: %d", idx_val );
1463 retval = merror_sz_to_retval( idx_val );
1482#if MDATA_TABLE_TRACE_LVL > 0
1483 debug_printf( MDATA_TABLE_TRACE_LVL,
"unsetting table key: %s", key );
1489 if( !mdata_table_is_locked( t ) ) {
1490#if MDATA_LOCK_TRACE_LVL > 0
1491 debug_printf( MDATA_LOCK_TRACE_LVL,
"autolocking table vectors" );
1493 assert( !mdata_vector_is_locked( &(t->data_cols[0]) ) );
1494 assert( !mdata_vector_is_locked( &(t->data_cols[1]) ) );
1495 mdata_table_lock( t );
1499 idx = _mdata_table_hunt_index( t, key, 0, 0 );
1505 mdata_table_unlock( t );
1511 if( autolock && mdata_table_is_locked( t ) ) {
1512 mdata_table_unlock( t );
1513 }
else if( !autolock && !mdata_table_is_locked( t ) ) {
1514 mdata_table_lock( t );
1522void* mdata_table_get_void(
const struct MDATA_TABLE* t,
const char* key ) {
1524 void* value_out = NULL;
1527 assert( mdata_table_is_locked( t ) );
1529 idx = _mdata_table_hunt_index( t, key, 0, 0 );
1531 retval = MERROR_OVERFLOW;
1539 if( MERROR_OK != retval ) {
1548void* mdata_table_hash_get_void(
1549 struct MDATA_TABLE* t, uint32_t key_hash,
size_t key_sz
1552 void* value_out = NULL;
1555 assert( mdata_table_is_locked( t ) );
1557#if MDATA_TABLE_TRACE_LVL > 0
1558 debug_printf( MDATA_TABLE_TRACE_LVL,
1559 "searching for hash %u (" SIZE_T_FMT
")", key_hash, key_sz );
1562 idx = _mdata_table_hunt_index( t, NULL, key_hash, key_sz );
1564 retval = MERROR_OVERFLOW;
1572 if( MERROR_OK != retval ) {
1582 mdata_vector_free( &(t->data_cols[0]) );
1583 mdata_vector_free( &(t->data_cols[1]) );
uint16_t MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition: merror.h:28
#define mdata_strpool_sz(sp)
Get the number of bytes allocated to a strpool.
Definition: mdata.h:307
#define mdata_strpool_get(sp, idx)
Get a string by the index of its first character in the strpool.
Definition: mdata.h:334
MAUG_MHANDLE mdata_strpool_extract(struct MDATA_STRPOOL *sp, mdata_strpool_idx_t idx)
Return a dynamically-allocated memory handle containing the contents of the string at the given index...
ssize_t mdata_strpool_get_idx_from_linear(struct MDATA_STRPOOL *sp, size_t linear)
Get the native strpool index, given a linear index from 0 to mdata_strpool_ct().
#define mdata_strpool_ct(sp)
Get the number of strings in a strpool.
Definition: mdata.h:302
MERROR_RETVAL mdata_strpool_check_idx(struct MDATA_STRPOOL *sp, mdata_strpool_idx_t idx)
Verify if the given mdata_strpool_idx_t is valid in the given strpool.
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.
void * mdata_vector_get_void(const struct MDATA_VECTOR *v, size_t idx)
Get a generic pointer to an item in the MDATA_VECTOR.
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:82
A vector of uniformly-sized objects, stored contiguously.
Definition: mdata.h:108
#define mdata_vector_lock(v)
Lock the vector. This should be done when items from the vector are actively being referenced,...
Definition: mdata.h:372
size_t ct_step
Number of items added when more space is needed.
Definition: mdata.h:119
#define mdata_vector_unlock(v)
Unlock the vector so items may be added and removed.
Definition: mdata.h:405
MAUG_MHANDLE data_h
Handle for allocated items (unlocked).
Definition: mdata.h:111
size_t item_sz
Size, in bytes, of each item.
Definition: mdata.h:124
size_t ct
Maximum number of items actually used.
Definition: mdata.h:117
uint8_t * data_bytes
Handle for allocated items (locked).
Definition: mdata.h:113
#define mdata_vector_ct(v)
Number of items of MDATA_VECTOR::item_sz bytes actively stored in this vector.
Definition: mdata.h:448
#define MDATA_VECTOR_INIT_STEP_SZ
Default initial value for MDATA_VECTOR::ct_step.
Definition: mdata.h:55
size_t ct_max
Maximum number of items currently allocated for.
Definition: mdata.h:115
ssize_t locks
Lock count, if MDATA_VECTOR_FLAG_REFCOUNT is enabled.
Definition: mdata.h:126