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 if( maug_is_locked( (v)->data_h, (v)->data_bytes ) ) { \
251 error_printf( "attempting to double-lock vector!" ); \
252 retval = MERROR_OVERFLOW; \
253 goto cleanup; \
254 } \
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 ); \
258 }
259
265#define mdata_vector_unlock( v ) \
266 if( \
267 mdata_vector_get_flag( v, MDATA_VECTOR_FLAG_REFCOUNT ) && \
268 0 < (v)->locks \
269 ) { \
270 (v)->locks--; \
271 debug_printf( MDATA_TRACE_LVL, "vector " #v " locks: " SSIZE_T_FMT, \
272 (v)->locks ); \
273 } \
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 ); \
278 }
279
280#define mdata_vector_get( v, idx, type ) \
281 ((type*)mdata_vector_get_void( v, idx ))
282
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)
287
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)
291
299#define mdata_vector_ct( v ) ((v)->ct)
300
305#define mdata_vector_sz( v ) (((v)->ct_max) * ((v)->item_sz))
306
311#define mdata_vector_fill( v, ct_new, sz ) \
312 retval = mdata_vector_alloc( v, sz, ct_new ); \
313 maug_cleanup_if_not_ok(); \
314 (v)->ct = (ct_new);
315
316#define mdata_vector_is_locked( v ) (NULL != (v)->data_bytes)
317
318/* TODO: Implement insert sorting. */
319#define mdata_vector_insert_sort( v, i, t, field )
320
321/* TODO: Implement sorting. */
322#define mdata_vector_sort( v, t, field )
323
324#define _mdata_vector_item_ptr( v, idx ) \
325 (&((v)->data_bytes[((idx) * ((v)->item_sz))]))
326
327#define mdata_vector_set_flag( v, flag ) (v)->flags |= (flag)
328
329#define mdata_vector_get_flag( v, flag ) ((flag) == ((v)->flags & (flag)))
330 /* mdata_vector */
332
333#define mdata_retval( idx ) (0 > idx ? ((idx) * -1) : MERROR_OK)
334
335#ifdef MDATA_C
336
337ssize_t mdata_strpool_find(
338 struct MDATA_STRPOOL* strpool, const char* str, size_t str_sz
339) {
340 MERROR_RETVAL retval = MERROR_OK;
341 ssize_t i = 0;
342 char* strpool_p = NULL;
343 size_t* p_str_iter_sz = NULL;
344
345 if( NULL == strpool->str_h ) {
346 error_printf( "strpool not allocated!" );
347 i = -1;
348 goto cleanup;
349 }
350
351 maug_mlock( strpool->str_h, strpool_p );
352
353 while( i < strpool->str_sz ) {
354 p_str_iter_sz = (size_t*)&(strpool_p[i]);
355 if(
356 0 == strncmp( &(strpool_p[i + sizeof( size_t )]), str, str_sz + 1 )
357 ) {
358 /* String found. Advance past the size before returning. */
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]) );
363
364 goto cleanup;
365 } else {
366 debug_printf( MDATA_TRACE_LVL,
367 "skipping strpool_idx: " SIZE_T_FMT " (" SIZE_T_FMT
368 " bytes): \"%s\"",
369 i + sizeof( size_t ), *p_str_iter_sz,
370 &(strpool_p[i + sizeof( size_t )]) );
371 }
372 i += *p_str_iter_sz;
373 }
374
375 /* String not found. */
376 i = -1;
377
378cleanup:
379
380 if( MERROR_OK != retval ) {
381 i = retval * -1;
382 }
383
384 if( NULL != strpool_p ) {
385 maug_munlock( strpool->str_h, strpool_p );
386 }
387
388 return i;
389}
390
391/* === */
392
393MAUG_MHANDLE mdata_strpool_extract( struct MDATA_STRPOOL* s, size_t i ) {
394 MERROR_RETVAL retval = MERROR_OK;
395 char* strpool = NULL;
396 MAUG_MHANDLE out_h = NULL;
397 size_t out_sz = 0;
398 char* out_tmp = NULL;
399
400 mdata_strpool_lock( s, strpool );
401
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 );
405
406 maug_mlock( out_h, out_tmp );
407 maug_cleanup_if_null_lock( char*, out_tmp );
408
409 maug_mzero( out_tmp, out_sz + 1 );
410 maug_strncpy( out_tmp, &(strpool[i]), out_sz );
411
412cleanup:
413
414 if( NULL != out_tmp ) {
415 maug_munlock( out_h, out_tmp );
416 }
417
418 if( MERROR_OK != retval && NULL != out_h ) {
419 maug_mfree( out_h );
420 }
421
422 if( NULL != strpool ) {
423 mdata_strpool_unlock( s, strpool );
424 }
425
426 return out_h;
427}
428
429/* === */
430
431ssize_t mdata_strpool_append(
432 struct MDATA_STRPOOL* strpool, const char* str, size_t str_sz
433) {
434 ssize_t idx_p_out = 0;
435 char* strpool_p = NULL;
436 MERROR_RETVAL retval = MERROR_OK;
437 size_t* p_str_sz = NULL;
438 size_t padding = 0;
439 size_t alloc_sz = 0;
440
441 if( 0 < strpool->str_sz ) {
442 /* Search the str_stable for an identical string and return that index.
443 */
444 idx_p_out = mdata_strpool_find( strpool, str, str_sz );
445 if( -1 != idx_p_out ) {
446 /* Found, or error returned. */
447 goto cleanup;
448 }
449 }
450
451 assert( 0 < str_sz );
452
453 /* Pad out allocated space so size_t is always aligned. */
454 padding = sizeof( size_t ) - ((str_sz + 1 /* NULL */) % sizeof( size_t ));
455 alloc_sz = sizeof( size_t ) + str_sz + 1 /* NULL */ + padding;
456 assert( 0 == alloc_sz % sizeof( size_t ) );
457
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 );
462
463 retval = mdata_strpool_alloc( strpool, alloc_sz );
464 maug_cleanup_if_not_ok();
465
466 maug_mlock( strpool->str_h, strpool_p );
467 maug_cleanup_if_null_alloc( char*, strpool_p );
468
469 debug_printf( MDATA_TRACE_LVL,
470 "strpool (" SIZE_T_FMT " bytes) locked to: %p",
471 strpool->str_sz, strpool_p );
472
473 /* Add this string at the end of the string table. */
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';
476
477 /* Add the size of the string to the strpool. */
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;
481
482 idx_p_out = strpool->str_sz + sizeof( size_t );
483
484 debug_printf(
485 MDATA_TRACE_LVL, "set strpool_idx: " SIZE_T_FMT ": \"%s\"",
486 strpool->str_sz, &(strpool_p[idx_p_out]) );
487
488 /* Set the string table cursor to the next available spot. */
489 strpool->str_sz += alloc_sz;
490
491cleanup:
492
493 if( MERROR_OK != retval ) {
494 idx_p_out = retval * -1;
495 }
496
497 if( NULL != strpool_p ) {
498 maug_munlock( strpool->str_h, strpool_p );
499 }
500
501 return idx_p_out;
502}
503
504/* === */
505
506MERROR_RETVAL mdata_strpool_alloc(
507 struct MDATA_STRPOOL* strpool, size_t alloc_sz
508) {
509 MERROR_RETVAL retval = MERROR_OK;
510 MAUG_MHANDLE str_h_new = (MAUG_MHANDLE)NULL;
511
512 if( (MAUG_MHANDLE)NULL == strpool->str_h ) {
513 debug_printf(
514 MDATA_TRACE_LVL, "creating string table of " SIZE_T_FMT " chars...",
515 alloc_sz );
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;
520
521 } else if( strpool->str_sz_max <= strpool->str_sz + alloc_sz ) {
522 while( strpool->str_sz_max <= strpool->str_sz + alloc_sz ) {
523 debug_printf(
524 MDATA_TRACE_LVL, "enlarging string table to " SIZE_T_FMT "...",
525 strpool->str_sz_max * 2 );
526 maug_mrealloc_test(
527 str_h_new, strpool->str_h, strpool->str_sz_max, (size_t)2 );
528 strpool->str_sz_max *= 2;
529 }
530 }
531
532cleanup:
533 return retval;
534}
535
536/* === */
537
538void mdata_strpool_free( struct MDATA_STRPOOL* strpool ) {
539 if( (MAUG_MHANDLE)NULL != strpool->str_h ) {
540 maug_mfree( strpool->str_h );
541 }
542}
543
544/* === */
545
546ssize_t mdata_vector_append(
547 struct MDATA_VECTOR* v, const void* item, size_t item_sz
548) {
549 MERROR_RETVAL retval = MERROR_OK;
550 ssize_t idx_out = -1;
551
552 if( 0 < v->item_sz && item_sz != v->item_sz ) {
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!",
555 item_sz, v->item_sz );
556 retval = MERROR_OVERFLOW;
557 goto cleanup;
558 }
559
561
562 /* Lock the vector to work in it a bit. */
564
565 idx_out = v->ct;
566
567 if( NULL != item ) {
568 /* Copy provided item. */
569 debug_printf(
570 MDATA_TRACE_LVL, "inserting into vector at index: " SIZE_T_FMT,
571 idx_out );
572
573 memcpy( _mdata_vector_item_ptr( v, idx_out ), item, item_sz );
574 }
575
576 v->ct++;
577
578cleanup:
579
580 if( MERROR_OK != retval ) {
581 error_printf( "error adding to vector: %d", retval );
582 idx_out = retval * -1;
583 assert( 0 > idx_out );
584 }
585
587
588 return idx_out;
589}
590
591/* === */
592
593MERROR_RETVAL mdata_vector_remove( struct MDATA_VECTOR* v, size_t idx ) {
594 MERROR_RETVAL retval = MERROR_OK;
595 size_t i = 0;
596
597 if( NULL != v->data_bytes ) {
598 error_printf( "vector cannot be resized while locked!" );
599 retval = MERROR_ALLOC;
600 goto cleanup;
601 }
602
603 if( v->ct <= idx ) {
604 error_printf( "index out of range!" );
605 retval = MERROR_OVERFLOW;
606 goto cleanup;
607 }
608
609 debug_printf( MDATA_TRACE_LVL, "removing vector item: " SIZE_T_FMT, idx );
610
611 assert( 0 < v->item_sz );
612
614
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...",
618 v->item_sz, i );
619 memcpy(
620 &(v->data_bytes[i * v->item_sz]),
621 &(v->data_bytes[(i + 1) * v->item_sz]),
622 v->item_sz );
623 }
624
625 v->ct--;
626
627cleanup:
628
630
631 return retval;
632}
633
634/* === */
635
636void* mdata_vector_get_void( struct MDATA_VECTOR* v, size_t idx ) {
637
638 debug_printf( MDATA_TRACE_LVL,
639 "getting vector item " SIZE_T_FMT " (of " SIZE_T_FMT ")...",
640 idx, v->ct );
641
642 assert( 0 == v->ct || NULL != v->data_bytes );
643
644 if( idx >= v->ct ) {
645 return NULL;
646 } else {
647 return _mdata_vector_item_ptr( v, idx );
648 }
649}
650
651/* === */
652
653MERROR_RETVAL mdata_vector_copy(
654 struct MDATA_VECTOR* v_dest, struct MDATA_VECTOR* v_src
655) {
656 MERROR_RETVAL retval = MERROR_OK;
657
658 if( NULL != v_src->data_bytes ) {
659 error_printf( "vector cannot be copied while locked!" );
660 retval = MERROR_ALLOC;
661 goto cleanup;
662 }
663
664 assert( 0 < v_src->item_sz );
665 assert( 0 < v_src->ct_max );
666
667 v_dest->ct_max = v_src->ct_max;
668 v_dest->ct = v_src->ct;
669 v_dest->item_sz = v_src->item_sz;
670 debug_printf(
671 MDATA_TRACE_LVL,
672 "copying " SIZE_T_FMT " vector of " SIZE_T_FMT "-byte nodes...",
673 v_src->ct_max, v_src->item_sz );
674 assert( NULL == v_dest->data_h );
675 v_dest->data_h = maug_malloc( v_src->ct_max, v_src->item_sz );
676 maug_cleanup_if_null_alloc( MAUG_MHANDLE, v_dest->data_h );
677
678 mdata_vector_lock( v_dest );
679 mdata_vector_lock( v_src );
680
681 memcpy( v_dest->data_bytes, v_src->data_bytes,
682 v_src->ct_max * v_src->item_sz );
683
684cleanup:
685
686 mdata_vector_unlock( v_src );
687 mdata_vector_unlock( v_dest );
688
689 return retval;
690}
691
692/* === */
693
695 struct MDATA_VECTOR* v, size_t item_sz, size_t item_ct_init
696) {
697 MERROR_RETVAL retval = MERROR_OK;
698 MAUG_MHANDLE data_h_new = NULL;
699 size_t new_ct = item_ct_init,
700 new_bytes_start = 0,
701 new_bytes_sz = 0;
702
703 if( NULL != v->data_bytes ) {
704 error_printf( "vector cannot be resized while locked!" );
705 retval = MERROR_ALLOC;
706 goto cleanup;
707 }
708
709 /* Make sure there are free nodes. */
710 if( (MAUG_MHANDLE)NULL == v->data_h ) {
711 assert( 0 == v->ct_max );
712
713 v->ct_max = item_ct_init;
715 debug_printf(
716 MDATA_TRACE_LVL,
717 "creating " SIZE_T_FMT " vector of " SIZE_T_FMT "-byte nodes...",
718 v->ct_max, item_sz );
719 assert( NULL == v->data_h );
720 v->data_h = maug_malloc( v->ct_max, item_sz );
721 v->item_sz = item_sz;
722 maug_cleanup_if_null_alloc( MAUG_MHANDLE, v->data_h );
723
724 /* Zero out the new space. */
728
729 } else if( v->ct_max <= v->ct + 1 || v->ct_max <= item_ct_init ) {
730 assert( item_sz == v->item_sz );
731
732 /* Use ct * 2 or ct_init... whichever is larger! */
733 if( item_ct_init < v->ct_max + v->ct_step ) {
734 assert( v->ct_max + v->ct_step > v->ct_max );
735 new_ct = v->ct_max + v->ct_step;
736 }
737
738 /* Perform the resize. */
739 debug_printf(
740 MDATA_TRACE_LVL, "enlarging vector to " SIZE_T_FMT "...",
741 new_ct );
742 maug_mrealloc_test( data_h_new, v->data_h, new_ct, item_sz );
743
744 /* Zero out the new space. */
745 new_bytes_start = v->ct_max * v->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 );
750 maug_mzero( &(v->data_bytes[new_bytes_start]), new_bytes_sz );
752
753 v->ct_max = new_ct;
754 }
755
756cleanup:
757
758 return retval;
759}
760
761/* === */
762
763void mdata_vector_free( struct MDATA_VECTOR* v ) {
764 if( (MAUG_MHANDLE)NULL != v->data_h ) {
765 maug_mfree( v->data_h );
766 }
767 v->ct = 0;
768 v->ct_max = 0;
769 v->item_sz = 0;
770}
771
772/* === */
773
774MERROR_RETVAL mdata_table_set(
775 struct MDATA_TABLE* t, const char* key, size_t key_sz,
776 void* value, size_t value_sz
777) {
778 MERROR_RETVAL retval = MERROR_OK;
779 ssize_t idx_key = -1;
780 ssize_t idx_val = -1;
781
782 /* TODO: This has all kinds of issues, obviously. At some point, turn it
783 * into a proper hashtable that can operate in tiny conditions!
784 */
785
786 assert(
787 mdata_vector_ct( &(t->data_cols[0]) ) ==
788 mdata_vector_ct( &(t->data_cols[1]) ) );
789
790 idx_key = mdata_vector_append( &(t->data_cols[0]), key, key_sz + 1 );
791 assert( 0 <= idx_key );
792
793 /* TODO: Atomicity: remove key if value fails! */
794
795 idx_val = mdata_vector_append( &(t->data_cols[1]), value, value_sz );
796 assert( 0 <= idx_val );
797
798/* cleanup: */
799
800 /* TODO: Set retval! */
801
802 return retval;
803}
804
805/* === */
806
807MERROR_RETVAL mdata_table_get_void(
808 struct MDATA_TABLE* t, const char* key, void** value_out, size_t value_sz
809) {
810 MERROR_RETVAL retval = MERROR_OK;
811 char* c = NULL;
812 size_t i = 0;
813
814 assert( NULL == *value_out );
815
816 mdata_vector_lock( &(t->data_cols[0]) );
817 mdata_vector_lock( &(t->data_cols[1]) );
818 for( i = 0 ; mdata_vector_ct( &(t->data_cols[0]) ) > i ; i++ ) {
819 /* TODO: Maybe strpool would be better for this? */
820 c = mdata_vector_get( &(t->data_cols[0]), i, char );
821 assert( NULL != c );
822 if( 0 == strncmp( key, c, t->data_cols[0].item_sz - 1 ) ) {
823 *value_out = mdata_vector_get_void( &(t->data_cols[1]), i );
824 goto cleanup;
825 }
826 }
827
828 /* Not found! */
829 retval = MERROR_OVERFLOW;
830
831cleanup:
832
833 mdata_vector_unlock( &(t->data_cols[0]) );
834 mdata_vector_unlock( &(t->data_cols[1]) );
835
836 return retval;
837}
838
839#endif /* MDATA_C */
840 /* maug_data */
842
843#endif /* MDATA_H */
844
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
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