maug
Quick and dirty C mini-augmentation library.
Loading...
Searching...
No Matches
mdata.h
Go to the documentation of this file.
1
2#ifndef MDATA_H
3#define MDATA_H
4
12
13#ifndef MDATA_TRACE_LVL
14# define MDATA_TRACE_LVL 0
15#endif /* !MDATA_TRACE_LVL */
16
21
30#define MDATA_VECTOR_FLAG_REFCOUNT 0x01
31
32#ifndef MDATA_VECTOR_INIT_SZ
37# define MDATA_VECTOR_INIT_SZ 10
38#endif /* !MDATA_TRACE_LVL */
39
40#ifndef MDATA_VECTOR_INIT_STEP_SZ
45# define MDATA_VECTOR_INIT_STEP_SZ 10
46#endif /* !MDATA_VECTOR_INIT_STEP_SZ */
47
49
56
57typedef ssize_t mdata_strpool_idx_t;
58
67 MAUG_MHANDLE str_h;
68 size_t str_sz;
69 size_t str_sz_max;
70};
71 /* mdata_strpool */
73
79
90 uint8_t flags;
92 MAUG_MHANDLE data_h;
94 uint8_t* data_bytes;
96 size_t ct_max;
98 size_t ct;
100 size_t ct_step;
105 size_t item_sz;
107 ssize_t locks;
108};
109 /* mdata_vector */
111
116
118 struct MDATA_VECTOR data_cols[2];
119 size_t key_sz;
120};
121
123
128
129ssize_t mdata_strpool_find(
130 struct MDATA_STRPOOL* strpool, const char* str, size_t str_sz );
131
132MAUG_MHANDLE mdata_strpool_extract( struct MDATA_STRPOOL* s, size_t i );
133
134ssize_t mdata_strpool_append(
135 struct MDATA_STRPOOL* strpool, const char* str, size_t str_sz );
136
137MERROR_RETVAL mdata_strpool_alloc(
138 struct MDATA_STRPOOL* strpool, size_t alloc_sz );
139
140void mdata_strpool_free( struct MDATA_STRPOOL* strpool );
141
143
148
163 struct MDATA_VECTOR* v, const void* item, size_t item_sz );
164
171
180void* mdata_vector_get_void( struct MDATA_VECTOR* v, size_t idx );
181
182MERROR_RETVAL mdata_vector_copy(
183 struct MDATA_VECTOR* v_dest, struct MDATA_VECTOR* v_src );
184
190 struct MDATA_VECTOR* v, size_t item_sz, size_t item_ct_init );
191
192void mdata_vector_free( struct MDATA_VECTOR* v );
193 /* mdata_vector */
195
200
201MERROR_RETVAL mdata_table_set(
202 struct MDATA_TABLE* t, const char* key, size_t key_sz,
203 void* value, size_t value_sz );
204
205MERROR_RETVAL mdata_table_get_void(
206 struct MDATA_TABLE* t, const char* key, void** value_out, size_t value_sz );
207
209
214
215#define mdata_strpool_sz( strpool ) ((strpool)->str_sz_max)
216
217#define mdata_strpool_lock( strpool, ptr ) \
218 maug_mlock( (strpool)->str_h, ptr ); \
219 maug_cleanup_if_null_lock( char*, ptr );
220
221#define mdata_strpool_unlock( strpool, ptr ) \
222 if( NULL != ptr ) { \
223 maug_munlock( (strpool)->str_h, ptr ); \
224 }
225 /* mdata_strpool */
227
232
241#define mdata_vector_lock( v ) \
242 if( \
243 mdata_vector_get_flag( v, MDATA_VECTOR_FLAG_REFCOUNT ) && \
244 0 < (v)->locks \
245 ) { \
246 (v)->locks++; \
247 debug_printf( MDATA_TRACE_LVL, "vector " #v " locks: " SSIZE_T_FMT, \
248 (v)->locks ); \
249 } else { \
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 ); \
254 }
255
261#define mdata_vector_unlock( v ) \
262 if( \
263 mdata_vector_get_flag( v, MDATA_VECTOR_FLAG_REFCOUNT ) && \
264 0 < (v)->locks \
265 ) { \
266 (v)->locks--; \
267 debug_printf( MDATA_TRACE_LVL, "vector " #v " locks: " SSIZE_T_FMT, \
268 (v)->locks ); \
269 } \
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 ); \
274 }
275
276#define mdata_vector_get( v, idx, type ) \
277 ((type*)mdata_vector_get_void( v, idx ))
278
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)
283
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)
287
295#define mdata_vector_ct( v ) ((v)->ct)
296
301#define mdata_vector_sz( v ) (((v)->ct_max) * ((v)->item_sz))
302
307#define mdata_vector_fill( v, ct_new, sz ) \
308 retval = mdata_vector_alloc( v, sz, ct_new ); \
309 maug_cleanup_if_not_ok(); \
310 (v)->ct = (ct_new);
311
312#define mdata_vector_is_locked( v ) (NULL != (v)->data_bytes)
313
314/* TODO: Implement insert sorting. */
315#define mdata_vector_insert_sort( v, i, t, field )
316
317/* TODO: Implement sorting. */
318#define mdata_vector_sort( v, t, field )
319
320#define _mdata_vector_item_ptr( v, idx ) \
321 (&((v)->data_bytes[((idx) * ((v)->item_sz))]))
322
323#define mdata_vector_set_flag( v, flag ) (v)->flags |= (flag)
324
325#define mdata_vector_get_flag( v, flag ) ((flag) == ((v)->flags & (flag)))
326 /* mdata_vector */
328
329#define mdata_retval( idx ) (0 > idx ? ((idx) * -1) : MERROR_OK)
330
331#ifdef MDATA_C
332
333ssize_t mdata_strpool_find(
334 struct MDATA_STRPOOL* strpool, const char* str, size_t str_sz
335) {
336 MERROR_RETVAL retval = MERROR_OK;
337 ssize_t i = 0;
338 char* strpool_p = NULL;
339 size_t* p_str_iter_sz = NULL;
340
341 if( NULL == strpool->str_h ) {
342 error_printf( "strpool not allocated!" );
343 i = -1;
344 goto cleanup;
345 }
346
347 maug_mlock( strpool->str_h, strpool_p );
348
349 while( i < strpool->str_sz ) {
350 p_str_iter_sz = (size_t*)&(strpool_p[i]);
351 if(
352 0 == strncmp( &(strpool_p[i + sizeof( size_t )]), str, str_sz + 1 )
353 ) {
354 /* String found. Advance past the size before returning. */
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]) );
359
360 goto cleanup;
361 } else {
362 debug_printf( MDATA_TRACE_LVL,
363 "skipping strpool_idx: " SIZE_T_FMT " (" SIZE_T_FMT
364 " bytes): \"%s\"",
365 i + sizeof( size_t ), *p_str_iter_sz,
366 &(strpool_p[i + sizeof( size_t )]) );
367 }
368 i += *p_str_iter_sz;
369 }
370
371 /* String not found. */
372 i = -1;
373
374cleanup:
375
376 if( MERROR_OK != retval ) {
377 i = retval * -1;
378 }
379
380 if( NULL != strpool_p ) {
381 maug_munlock( strpool->str_h, strpool_p );
382 }
383
384 return i;
385}
386
387/* === */
388
389MAUG_MHANDLE mdata_strpool_extract( struct MDATA_STRPOOL* s, size_t i ) {
390 MERROR_RETVAL retval = MERROR_OK;
391 char* strpool = NULL;
392 MAUG_MHANDLE out_h = NULL;
393 size_t out_sz = 0;
394 char* out_tmp = NULL;
395
396 mdata_strpool_lock( s, strpool );
397
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 );
401
402 maug_mlock( out_h, out_tmp );
403 maug_cleanup_if_null_lock( char*, out_tmp );
404
405 maug_mzero( out_tmp, out_sz + 1 );
406 maug_strncpy( out_tmp, &(strpool[i]), out_sz );
407
408cleanup:
409
410 if( NULL != out_tmp ) {
411 maug_munlock( out_h, out_tmp );
412 }
413
414 if( MERROR_OK != retval && NULL != out_h ) {
415 maug_mfree( out_h );
416 }
417
418 if( NULL != strpool ) {
419 mdata_strpool_unlock( s, strpool );
420 }
421
422 return out_h;
423}
424
425/* === */
426
427ssize_t mdata_strpool_append(
428 struct MDATA_STRPOOL* strpool, const char* str, size_t str_sz
429) {
430 ssize_t idx_p_out = 0;
431 char* strpool_p = NULL;
432 MERROR_RETVAL retval = MERROR_OK;
433 size_t* p_str_sz = NULL;
434 size_t padding = 0;
435 size_t alloc_sz = 0;
436
437 if( 0 < strpool->str_sz ) {
438 /* Search the str_stable for an identical string and return that index.
439 */
440 idx_p_out = mdata_strpool_find( strpool, str, str_sz );
441 if( -1 != idx_p_out ) {
442 /* Found, or error returned. */
443 goto cleanup;
444 }
445 }
446
447 assert( 0 < str_sz );
448
449 /* Pad out allocated space so size_t is always aligned. */
450 padding = sizeof( size_t ) - ((str_sz + 1 /* NULL */) % sizeof( size_t ));
451 alloc_sz = sizeof( size_t ) + str_sz + 1 /* NULL */ + padding;
452 assert( 0 == alloc_sz % sizeof( size_t ) );
453
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 );
458
459 retval = mdata_strpool_alloc( strpool, alloc_sz );
460 maug_cleanup_if_not_ok();
461
462 maug_mlock( strpool->str_h, strpool_p );
463 maug_cleanup_if_null_alloc( char*, strpool_p );
464
465 debug_printf( MDATA_TRACE_LVL,
466 "strpool (" SIZE_T_FMT " bytes) locked to: %p",
467 strpool->str_sz, strpool_p );
468
469 /* Add this string at the end of the string table. */
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';
472
473 /* Add the size of the string to the strpool. */
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;
477
478 idx_p_out = strpool->str_sz + sizeof( size_t );
479
480 debug_printf(
481 MDATA_TRACE_LVL, "set strpool_idx: " SIZE_T_FMT ": \"%s\"",
482 strpool->str_sz, &(strpool_p[idx_p_out]) );
483
484 /* Set the string table cursor to the next available spot. */
485 strpool->str_sz += alloc_sz;
486
487cleanup:
488
489 if( MERROR_OK != retval ) {
490 idx_p_out = retval * -1;
491 }
492
493 if( NULL != strpool_p ) {
494 maug_munlock( strpool->str_h, strpool_p );
495 }
496
497 return idx_p_out;
498}
499
500/* === */
501
502MERROR_RETVAL mdata_strpool_alloc(
503 struct MDATA_STRPOOL* strpool, size_t alloc_sz
504) {
505 MERROR_RETVAL retval = MERROR_OK;
506 MAUG_MHANDLE str_h_new = (MAUG_MHANDLE)NULL;
507
508 if( (MAUG_MHANDLE)NULL == strpool->str_h ) {
509 debug_printf(
510 MDATA_TRACE_LVL, "creating string table of " SIZE_T_FMT " chars...",
511 alloc_sz );
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;
516
517 } else if( strpool->str_sz_max <= strpool->str_sz + alloc_sz ) {
518 while( strpool->str_sz_max <= strpool->str_sz + alloc_sz ) {
519 debug_printf(
520 MDATA_TRACE_LVL, "enlarging string table to " SIZE_T_FMT "...",
521 strpool->str_sz_max * 2 );
522 maug_mrealloc_test(
523 str_h_new, strpool->str_h, strpool->str_sz_max, (size_t)2 );
524 strpool->str_sz_max *= 2;
525 }
526 }
527
528cleanup:
529 return retval;
530}
531
532/* === */
533
534void mdata_strpool_free( struct MDATA_STRPOOL* strpool ) {
535 if( (MAUG_MHANDLE)NULL != strpool->str_h ) {
536 maug_mfree( strpool->str_h );
537 }
538}
539
540/* === */
541
542ssize_t mdata_vector_append(
543 struct MDATA_VECTOR* v, const void* item, size_t item_sz
544) {
545 MERROR_RETVAL retval = MERROR_OK;
546 ssize_t idx_out = -1;
547
548 if( 0 < v->item_sz && item_sz != v->item_sz ) {
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!",
551 item_sz, v->item_sz );
552 retval = MERROR_OVERFLOW;
553 goto cleanup;
554 }
555
557
558 /* Lock the vector to work in it a bit. */
560
561 idx_out = v->ct;
562
563 if( NULL != item ) {
564 /* Copy provided item. */
565 debug_printf(
566 MDATA_TRACE_LVL, "inserting into vector at index: " SIZE_T_FMT,
567 idx_out );
568
569 memcpy( _mdata_vector_item_ptr( v, idx_out ), item, item_sz );
570 }
571
572 v->ct++;
573
574cleanup:
575
576 if( MERROR_OK != retval ) {
577 error_printf( "error adding to vector: %d", retval );
578 idx_out = retval * -1;
579 assert( 0 > idx_out );
580 }
581
583
584 return idx_out;
585}
586
587/* === */
588
589MERROR_RETVAL mdata_vector_remove( struct MDATA_VECTOR* v, size_t idx ) {
590 MERROR_RETVAL retval = MERROR_OK;
591 size_t i = 0;
592
593 if( NULL != v->data_bytes ) {
594 error_printf( "vector cannot be resized while locked!" );
595 retval = MERROR_ALLOC;
596 goto cleanup;
597 }
598
599 if( v->ct <= idx ) {
600 error_printf( "index out of range!" );
601 retval = MERROR_OVERFLOW;
602 goto cleanup;
603 }
604
605 debug_printf( MDATA_TRACE_LVL, "removing vector item: " SIZE_T_FMT, idx );
606
607 assert( 0 < v->item_sz );
608
610
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...",
614 v->item_sz, i );
615 memcpy(
616 &(v->data_bytes[i * v->item_sz]),
617 &(v->data_bytes[(i + 1) * v->item_sz]),
618 v->item_sz );
619 }
620
621 v->ct--;
622
623cleanup:
624
626
627 return retval;
628}
629
630/* === */
631
632void* mdata_vector_get_void( struct MDATA_VECTOR* v, size_t idx ) {
633
634 debug_printf( MDATA_TRACE_LVL,
635 "getting vector item " SIZE_T_FMT " (of " SIZE_T_FMT ")...",
636 idx, v->ct );
637
638 assert( 0 == v->ct || NULL != v->data_bytes );
639
640 if( idx >= v->ct ) {
641 return NULL;
642 } else {
643 return _mdata_vector_item_ptr( v, idx );
644 }
645}
646
647/* === */
648
649MERROR_RETVAL mdata_vector_copy(
650 struct MDATA_VECTOR* v_dest, struct MDATA_VECTOR* v_src
651) {
652 MERROR_RETVAL retval = MERROR_OK;
653
654 if( NULL != v_src->data_bytes ) {
655 error_printf( "vector cannot be copied while locked!" );
656 retval = MERROR_ALLOC;
657 goto cleanup;
658 }
659
660 assert( 0 < v_src->item_sz );
661 assert( 0 < v_src->ct_max );
662
663 v_dest->ct_max = v_src->ct_max;
664 v_dest->ct = v_src->ct;
665 v_dest->item_sz = v_src->item_sz;
666 debug_printf(
667 MDATA_TRACE_LVL,
668 "copying " SIZE_T_FMT " vector of " SIZE_T_FMT "-byte nodes...",
669 v_src->ct_max, v_src->item_sz );
670 assert( NULL == v_dest->data_h );
671 v_dest->data_h = maug_malloc( v_src->ct_max, v_src->item_sz );
672 maug_cleanup_if_null_alloc( MAUG_MHANDLE, v_dest->data_h );
673
674 mdata_vector_lock( v_dest );
675 mdata_vector_lock( v_src );
676
677 memcpy( v_dest->data_bytes, v_src->data_bytes,
678 v_src->ct_max * v_src->item_sz );
679
680cleanup:
681
682 mdata_vector_unlock( v_src );
683 mdata_vector_unlock( v_dest );
684
685 return retval;
686}
687
688/* === */
689
691 struct MDATA_VECTOR* v, size_t item_sz, size_t item_ct_init
692) {
693 MERROR_RETVAL retval = MERROR_OK;
694 MAUG_MHANDLE data_h_new = NULL;
695 size_t new_ct = item_ct_init,
696 new_bytes_start = 0,
697 new_bytes_sz = 0;
698
699 if( NULL != v->data_bytes ) {
700 error_printf( "vector cannot be resized while locked!" );
701 retval = MERROR_ALLOC;
702 goto cleanup;
703 }
704
705 /* Make sure there are free nodes. */
706 if( (MAUG_MHANDLE)NULL == v->data_h ) {
707 assert( 0 == v->ct_max );
708
709 v->ct_max = item_ct_init;
711 debug_printf(
712 MDATA_TRACE_LVL,
713 "creating " SIZE_T_FMT " vector of " SIZE_T_FMT "-byte nodes...",
714 v->ct_max, item_sz );
715 assert( NULL == v->data_h );
716 v->data_h = maug_malloc( v->ct_max, item_sz );
717 v->item_sz = item_sz;
718 maug_cleanup_if_null_alloc( MAUG_MHANDLE, v->data_h );
719
720 /* Zero out the new space. */
724
725 } else if( v->ct_max <= v->ct + 1 || v->ct_max <= item_ct_init ) {
726 assert( item_sz == v->item_sz );
727
728 /* Use ct * 2 or ct_init... whichever is larger! */
729 if( item_ct_init < v->ct_max + v->ct_step ) {
730 assert( v->ct_max + v->ct_step > v->ct_max );
731 new_ct = v->ct_max + v->ct_step;
732 }
733
734 /* Perform the resize. */
735 debug_printf(
736 MDATA_TRACE_LVL, "enlarging vector to " SIZE_T_FMT "...",
737 new_ct );
738 maug_mrealloc_test( data_h_new, v->data_h, new_ct, item_sz );
739
740 /* Zero out the new space. */
741 new_bytes_start = v->ct_max * v->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 );
746 maug_mzero( &(v->data_bytes[new_bytes_start]), new_bytes_sz );
748
749 v->ct_max = new_ct;
750 }
751
752cleanup:
753
754 return retval;
755}
756
757/* === */
758
759void mdata_vector_free( struct MDATA_VECTOR* v ) {
760 if( (MAUG_MHANDLE)NULL != v->data_h ) {
761 maug_mfree( v->data_h );
762 }
763 v->ct = 0;
764 v->ct_max = 0;
765 v->item_sz = 0;
766}
767
768/* === */
769
770MERROR_RETVAL mdata_table_set(
771 struct MDATA_TABLE* t, const char* key, size_t key_sz,
772 void* value, size_t value_sz
773) {
774 MERROR_RETVAL retval = MERROR_OK;
775 ssize_t idx_key = -1;
776 ssize_t idx_val = -1;
777
778 /* TODO: This has all kinds of issues, obviously. At some point, turn it
779 * into a proper hashtable that can operate in tiny conditions!
780 */
781
782 assert(
783 mdata_vector_ct( &(t->data_cols[0]) ) ==
784 mdata_vector_ct( &(t->data_cols[1]) ) );
785
786 idx_key = mdata_vector_append( &(t->data_cols[0]), key, key_sz + 1 );
787 assert( 0 <= idx_key );
788
789 /* TODO: Atomicity: remove key if value fails! */
790
791 idx_val = mdata_vector_append( &(t->data_cols[1]), value, value_sz );
792 assert( 0 <= idx_val );
793
794/* cleanup: */
795
796 /* TODO: Set retval! */
797
798 return retval;
799}
800
801/* === */
802
803MERROR_RETVAL mdata_table_get_void(
804 struct MDATA_TABLE* t, const char* key, void** value_out, size_t value_sz
805) {
806 MERROR_RETVAL retval = MERROR_OK;
807 char* c = NULL;
808 size_t i = 0;
809
810 assert( NULL == *value_out );
811
812 mdata_vector_lock( &(t->data_cols[0]) );
813 mdata_vector_lock( &(t->data_cols[1]) );
814 for( i = 0 ; mdata_vector_ct( &(t->data_cols[0]) ) > i ; i++ ) {
815 /* TODO: Maybe strpool would be better for this? */
816 c = mdata_vector_get( &(t->data_cols[0]), i, char );
817 assert( NULL != c );
818 if( 0 == strncmp( key, c, t->data_cols[0].item_sz - 1 ) ) {
819 *value_out = mdata_vector_get_void( &(t->data_cols[1]), i );
820 goto cleanup;
821 }
822 }
823
824 /* Not found! */
825 retval = MERROR_OVERFLOW;
826
827cleanup:
828
829 mdata_vector_unlock( &(t->data_cols[0]) );
830 mdata_vector_unlock( &(t->data_cols[1]) );
831
832 return retval;
833}
834
835#endif /* MDATA_C */
836 /* maug_data */
838
839#endif /* MDATA_H */
840
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
Definition mdata.h:117
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