clibconfig

Dynamically enumerate keys in libconfig


in libconfig - is it possible to dymanically enumerate keys?

As an example, in this example config file from their repo - if someone invented more days in the hours section, could the code dynamically enumerate them and print them out?

Looking at the docs, I see lots of code to get a specific string, or list out an array, but I can't find an example where it enumerates the keys of a config section.

Edit

Received some downvotes, so thought I'd have another crack at being more specific.

I'd like to use libconfig to track some state in my application, read in the last known state when the app starts, and write it out again when it exits. My app stores things in a tree (of depth 2) - so this could be niceley represented as an associative array in a libconfig compatible file as below. The point is that the list of Ids (1234/4567) can change. I could track them in another array, but if I could just enumerate the 'keys' in the ids array below - that would be neater.

so

ids = {
    "1234" = [1,2,3]
    "4567" = [9,10,11,23]

}

e.g (psuedocode)

foreach $key(config_get_keys_under(&configroot)){
    config_get_String($key)
}

I can't see anything obvious in the header file.


Solution

  • You can use config_setting_get_elem function to get n-th element of the group, array or list, and then (if it's group) use config_setting_name to get it's name. But AFAIK you can't use digits in key names. So consider following config structure:

    ids = (
        {
             key = "1234";
             value = [1, 2, 3];
        },
        {
             key = "4567";
             value = [9, 10, 11, 23];
        }
    );
    

    Then you can easily enumerate through all members of the ids getting the values you want using the following code:

    #include <stdio.h>
    #include <libconfig.h>
    
    int main(int argc, char **argv) {
        struct config_t cfg;
        char *file = "config.cfg";
    
        config_init(&cfg);
    
        /* Load the file */
        printf("loading [%s]...\n", file);
        if (!config_read_file(&cfg, file)) {
            printf("failed\n");
            return 1;
        }
        config_setting_t *setting, *member, *array;
        setting = config_lookup(&cfg, "ids");
        if (setting == NULL) {
            printf("no ids\n");
            return 2;
        }
        int n = 0, k, v;
        char const *str;
        while (1) {
            member = config_setting_get_elem(setting, n);
            if (member == NULL) {
                break;
            }
            printf("element %d\n", n);
            if (config_setting_lookup_string(member, "key", &str)) {
                printf("  key = %s\n", str);
            }
            array = config_setting_get_member(member, "value");
            k = 0;
            if (array) {
                printf("  values = [ ");
                while (1) {
                    if (config_setting_get_elem(array, k) == NULL) {
                        break;
                    }
                    v = config_setting_get_int_elem(array, k);
                    printf("%s%d", k == 0 ? "" : ", ", v);
                    ++k;
                }
                printf(" ]\n");
            }
    
            ++n;
        }
        printf("done\n");
        /* Free the configuration */
        config_destroy(&cfg);
    
        return 0;
    }