@ -15,7 +15,9 @@ __attribute_cold__
static void array_extend ( array * const a ) {
a - > size + = 16 ;
a - > data = realloc ( a - > data , sizeof ( * a - > data ) * a - > size ) ;
a - > sorted = realloc ( a - > sorted , sizeof ( * a - > sorted ) * a - > size ) ;
force_assert ( a - > data ) ;
force_assert ( a - > sorted ) ;
memset ( a - > data + a - > used , 0 , ( a - > size - a - > used ) * sizeof ( * a - > data ) ) ;
}
@ -30,6 +32,7 @@ array *array_init(void) {
}
void array_free_data ( array * const a ) {
if ( a - > sorted ) free ( a - > sorted ) ;
data_unset * * const data = a - > data ;
const uint32_t sz = a - > size ;
for ( uint32_t i = 0 ; i < sz ; + + i ) {
@ -47,6 +50,9 @@ void array_copy_array(array * const dst, const array * const src) {
dst - > data = calloc ( src - > size , sizeof ( * src - > data ) ) ;
force_assert ( NULL ! = dst - > data ) ;
dst - > sorted = malloc ( sizeof ( * src - > sorted ) * src - > size ) ;
force_assert ( NULL ! = dst - > sorted ) ;
memcpy ( dst - > sorted , src - > sorted , sizeof ( * src - > sorted ) * src - > used ) ;
for ( uint32_t i = 0 ; i < src - > used ; + + i ) {
dst - > data [ i ] = src - > data [ i ] - > fn - > copy ( src - > data [ i ] ) ;
}
@ -82,6 +88,7 @@ data_unset *array_pop(array * const a) {
a - > used - - ;
du = a - > data [ a - > used ] ;
force_assert ( a - > sorted [ a - > used ] = = a - > used ) ; /* only works on "simple" lists */
a - > data [ a - > used ] = NULL ;
return du ;
@ -110,9 +117,9 @@ static int array_keycmp(const char * const a, const size_t alen, const char * co
return alen < blen ? - 1 : alen > blen ? 1 : array_caseless_compare ( a , b , blen ) ;
}
/* If key is found, returns pos (pos >= 0) into a->data[]
* If key is not found , returns - pos - 1 if that is the position - 1 in a - > data [ ]
* where the key would be inserted ( - 1 to avoid - 0 )
/* returns pos into a->sorted[] which contains index to data in a->data[]
* if pos > = 0 , or returns - pos - 1 if that is the position - 1 in a - > sorted [ ]
* where the key needs to be inserted ( - 1 to avoid - 0 )
*/
__attribute_hot__
__attribute_pure__
@ -123,7 +130,7 @@ static int32_t array_get_index(const array * const a, const char * const k, cons
uint32_t lower = 0 , upper = a - > used ;
while ( lower ! = upper ) {
uint32_t probe = ( lower + upper ) / 2 ;
const buffer * const b = & a - > data [ probe ] - > key ;
const buffer * const b = & a - > data [ a - > sorted [ probe ] ] - > key ;
/* key is non-empty (0==b->used), though possibly blank (1==b->used),
* if inserted into key - value array */
/*force_assert(b && b->used);*/
@ -143,26 +150,42 @@ static int32_t array_get_index(const array * const a, const char * const k, cons
__attribute_hot__
data_unset * array_get_element_klen ( const array * const a , const char * key , const size_t klen ) {
const int32_t ipos = array_get_index ( a , key , klen ) ;
return ipos > = 0 ? a - > data [ ipos ] : NULL ;
return ipos > = 0 ? a - > data [ a - > sorted [ ipos ] ] : NULL ;
}
/* non-const (data_config *) for configparser.y (not array_get_element_klen())*/
data_unset * array_get_data_unset ( const array * const a , const char * key , const size_t klen ) {
const int32_t ipos = array_get_index ( a , key , klen ) ;
return ipos > = 0 ? a - > data [ ipos ] : NULL ;
return ipos > = 0 ? a - > data [ a - > sorted [ ipos ] ] : NULL ;
}
data_unset * array_extract_element_klen ( array * const a , const char * key , const size_t klen ) {
const int32_t ipos = array_get_index ( a , key , klen ) ;
if ( ipos < 0 ) return NULL ;
/* remove entry from a->data: move everything after pos one step left */
data_unset * const entry = a - > data [ ipos ] ;
const uint32_t last_ndx = - - a - > used ;
if ( last_ndx ! = ( uint32_t ) ipos ) {
data_unset * * const d = a - > data + ipos ;
memmove ( d , d + 1 , ( last_ndx - ( uint32_t ) ipos ) * sizeof ( * d ) ) ;
}
const uint32_t ndx = a - > sorted [ ipos ] , pos = ( uint32_t ) ipos ;
data_unset * const entry = a - > data [ ndx ] ;
/* now we need to swap it with the last element (if it isn't already the last element) */
if ( ndx ! = last_ndx ) {
/* to swap we also need to modify the index in a->sorted - find pos of last_elem there */
int32_t last_elem_pos = array_get_index ( a , CONST_BUF_LEN ( & a - > data [ last_ndx ] - > key ) ) ;
/* last element must be present at the expected position */
force_assert ( last_ndx = = a - > sorted [ last_elem_pos ] ) ;
/* move entry from last_ndx to ndx */
a - > data [ ndx ] = a - > data [ last_ndx ] ;
/* fix index entry for moved entry */
a - > sorted [ last_elem_pos ] = ndx ;
}
/* remove entry in a->sorted: move everything after pos one step to the left */
if ( pos ! = last_ndx ) {
memmove ( a - > sorted + pos , a - > sorted + pos + 1 , ( last_ndx - pos ) * sizeof ( * a - > sorted ) ) ;
}
a - > data [ last_ndx ] = NULL ;
return entry ;
}
@ -206,12 +229,13 @@ static void array_insert_data_at_pos(array * const a, data_unset * const entry,
const uint32_t ndx = a - > used + + ;
data_unset * const prev = a - > data [ ndx ] ;
a - > data [ ndx ] = entry ;
/* move everything one step to the right */
if ( pos ! = ndx ) {
memmove ( a - > data + ( pos + 1 ) , a - > data + ( pos ) , ( ndx - pos ) * sizeof ( * a - > data ) ) ;
memmove ( a - > sorted + ( pos + 1 ) , a - > sorted + ( pos ) , ( ndx - pos ) * sizeof ( * a - > sorted ) ) ;
}
a - > data [ pos ] = entry ;
a - > sorted [ pos ] = ndx ;
if ( prev ) prev - > fn - > free ( prev ) ; /* free prior data, if any, from slot */
}
@ -236,7 +260,7 @@ static data_string * array_insert_string_at_pos(array * const a, const uint32_t
int * array_get_int_ptr ( array * const a , const char * const k , const size_t klen ) {
int32_t ipos = array_get_index ( a , k , klen ) ;
if ( ipos > = 0 ) return & ( ( data_integer * ) a - > data [ ipos ] ) - > value ;
if ( ipos > = 0 ) return & ( ( data_integer * ) a - > data [ a - > sorted [ ipos ] ] ) - > value ;
data_integer * const di = array_insert_integer_at_pos ( a , ( uint32_t ) ( - ipos - 1 ) ) ;
buffer_copy_string_len ( & di - > key , k , klen ) ;
@ -246,7 +270,7 @@ int * array_get_int_ptr(array * const a, const char * const k, const size_t klen
buffer * array_get_buf_ptr ( array * const a , const char * const k , const size_t klen ) {
int32_t ipos = array_get_index ( a , k , klen ) ;
if ( ipos > = 0 ) return & ( ( data_string * ) a - > data [ ipos ] ) - > value ;
if ( ipos > = 0 ) return & ( ( data_string * ) a - > data [ a - > sorted [ ipos ] ] ) - > value ;
data_string * const ds = array_insert_string_at_pos ( a , ( uint32_t ) ( - ipos - 1 ) ) ;
buffer_copy_string_len ( & ds - > key , k , klen ) ;
@ -273,7 +297,7 @@ static data_unset **array_find_or_insert(array * const a, data_unset * const ent
/* try to find the entry */
const int32_t ipos = array_get_index ( a , CONST_BUF_LEN ( & entry - > key ) ) ;
if ( ipos > = 0 ) return & a - > data [ ipos ] ;
if ( ipos > = 0 ) return & a - > data [ a - > sorted [ ipos ] ] ;
array_insert_data_at_pos ( a , entry , ( uint32_t ) ( - ipos - 1 ) ) ;
return NULL ;