src/core/config/parser.c
/**
 * This is an array context aware array split. It splits the inner values
 * of an array keeping in mind that there might be nested arrays. Instead of
 * splitting on each ',' (which would happen if we used string_split) we keep
 * track of our position on the array (and nested arrays) and only return the
 * top level items.
 *
 * Firstly we build a list of top level value items. This allows us to figure
 * out the number of value items dynamically. Then we do a single allocation
 * for the returned array and destroy the intermediate list.
 *
 * The provided char array is populated with the result, and the provided
 * length pointer is populated with the number of value items we found
 */
This is an array context aware array split. It splits the inner values
of an array keeping in mind that there might be nested arrays. Instead of
splitting on each ',' (which would happen if we used string_split) we keep
track of our position on the array (and nested arrays) and only return the
top level items.

Firstly we build a list of top level value items. This allows us to figure
out the number of value items dynamically. Then we do a single allocation
for the returned array and destroy the intermediate list.

The provided char array is populated with the result, and the provided
length pointer is populated with the number of value items we found
This is an array context aware array split . It splits the inner values of an array keeping in mind that there might be nested arrays . Instead of splitting on each ' ' ( which would happen if we used string_split ) we keep track of our position on the array ( and nested arrays ) and only return the top level items . Firstly we build a list of top level value items . This allows us to figure out the number of value items dynamically . Then we do a single allocation for the returned array and destroy the intermediate list . The provided char array is populated with the result and the provided length pointer is populated with the number of value items we found
static enum natwm_error array_split_value_items_string(const char *string, char ***result,
                                                       size_t *length)
{
        struct list *list = list_create();
        if (list == NULL) {
                return MEMORY_ALLOCATION_ERROR;
        }
        size_t current_index = 0;
        for (;;) {
                char *item = NULL;
                size_t end_pos = 0;
                enum natwm_error err = array_context_get_delimiter(
                        string + current_index, ',', &item, &end_pos, false);
                if (err == NOT_FOUND_ERROR) {
                        char *last_item = string_init(string + current_index);
                        if (last_item == NULL) {
                                goto free_and_error;
                        }
                        list_insert(list, last_item);
                        break;
                }
                if (err != NO_ERROR) {
                        goto free_and_error;
                }
                list_insert(list, item);
                string += (end_pos + 1);
        }
        char **array_items = malloc(sizeof(char *) * list->size);
        if (array_items == NULL) {
                goto free_and_error;
        }
        size_t array_item_index = (list->size - 1);
        LIST_FOR_EACH(list, item)
        {
                char *list_item = (char *)item->data;
                array_items[array_item_index] = list_item;
                --array_item_index;
        }
        *result = array_items;
        *length = list->size;
        list_destroy(list);
        return NO_ERROR;
free_and_error:
        LIST_FOR_EACH(list, item)
        {
                if (item && item->data) {
                        free((char *)item->data);
                }
        }
        list_destroy(list);
        return GENERIC_ERROR;
}
static enum natwm_error array_split_value_items_string ( const char * string , char * * * result , size_t * length ) { struct list * list = list_create ( ) ; if ( list == NULL ) { return MEMORY_ALLOCATION_ERROR ; } size_t current_index = 0 ; for ( ; ; ) { char * item = NULL ; size_t end_pos = 0 ; enum natwm_error err = array_context_get_delimiter ( string + current_index , ' ' , & item , & end_pos , false ) ; if ( err == NOT_FOUND_ERROR ) { char * last_item = string_init ( string + current_index ) ; if ( last_item == NULL ) { goto free_and_error ; } list_insert ( list , last_item ) ; break ; } if ( err != NO_ERROR ) { goto free_and_error ; } list_insert ( list , item ) ; string += ( end_pos + 1 ) ; } char * * array_items = malloc ( sizeof ( char * ) * list -> size ) ; if ( array_items == NULL ) { goto free_and_error ; } size_t array_item_index = ( list -> size - 1 ) ; LIST_FOR_EACH ( list , item ) { char * list_item = ( char * ) item -> data ; array_items [ array_item_index ] = list_item ; -- array_item_index ; } * result = array_items ; * length = list -> size ; list_destroy ( list ) ; return NO_ERROR ; free_and_error : LIST_FOR_EACH ( list , item ) { if ( item && item -> data ) { free ( ( char * ) item -> data ) ; } } list_destroy ( list ) ; return GENERIC_ERROR ; }
This is an array context aware array split.
This is an array context aware array split .
// Walk the list backwards to insert in the correct position