configtpl 0.1.1

A configuration library which uses Jinja + YAML to render the configuration values.
Documentation
#ifdef _WIN32
#include <stdlib.h>
#endif
#include <stdio.h>

#include "../../../../include/configtpl.h"

#define MAX_NAME_LENGTH 500

void printConfig(const struct configtpl_ConfigParam *cfg, char *prefix)
{
    prefix = prefix ? prefix : "";
    const struct configtpl_Array_ConfigParam *vec;
    const struct configtpl_Array_ConfigParamDictItem *map;
    switch (cfg->param_type)
    {
        case CONFIGTPL_CONFIG_PARAM_TYPE_INT:
            printf("%s=%ld\n", prefix, cfg->value.integer);
            break;
        case CONFIGTPL_CONFIG_PARAM_TYPE_STRING:
            printf("%s=%s\n", prefix, cfg->value.string);
            break;
        case CONFIGTPL_CONFIG_PARAM_TYPE_BOOLEAN:
            printf("%s=%s\n", prefix, cfg->value.boolean ? "true" : "false");
            break;
            case CONFIGTPL_CONFIG_PARAM_TYPE_FLOAT:
                printf("%s=%lf\n", prefix, cfg->value.float_num);
                break;
        case CONFIGTPL_CONFIG_PARAM_TYPE_NULL:
            printf("%s=null\n", prefix);
            break;
        case CONFIGTPL_CONFIG_PARAM_TYPE_VEC:
            vec = &cfg->value.vector;
            for (int j = 0; j < vec->len; j++)
            {
                char fullNameSub[MAX_NAME_LENGTH];
                sprintf(fullNameSub, "%s[%d]", prefix, j);
                printConfig(&vec->data[j], fullNameSub);
            }
            break;
        case CONFIGTPL_CONFIG_PARAM_TYPE_MAP:
            map = &cfg->value.map;
            for (int j = 0; j < map->len; j++)
            {
                char fullNameSub[MAX_NAME_LENGTH];
                sprintf(fullNameSub, "%s.%s", prefix, map->data[j].name);
                printConfig(map->data[j].value, fullNameSub);
            }
            break;
    }
}

int main(int argc, char** argv)
{
    if (argc < 2)
    {
        fprintf(stderr, "Usage: %s PATHS\n", argv[0]);
        return 1;
    }
    const char *paths_val[] = {
        argv[1],
    };
    struct configtpl_Array_ConstCharPtr paths = {
        .len = 1,
        .data = paths_val,
    };

    if (CONFIGTPL_SIMPLE_RESULT_ERROR == configtpl_init())
    {
        fprintf(stderr, "Failed to initialize configtpl");
        return 1;
    }

    configtpl_CfgBuilderHandle handle = configtpl_configbuilder_new();

    struct configtpl_ConfigParam context_item1 = {
        .param_type = CONFIGTPL_CONFIG_PARAM_TYPE_STRING,
        .value.string = "my_val1",
    };
    struct configtpl_ConfigParam context_item2 = {
        .param_type = CONFIGTPL_CONFIG_PARAM_TYPE_STRING,
        .value.string = "my_val2",
    };
    struct configtpl_ConfigParamDictItem context_items[2] = {
        {
            .name = "my_key1",
            .value = &context_item1,
        },
        {
            .name = "my_key2",
            .value = &context_item2,
        },
    };
    struct configtpl_ConfigParam context = {
        .param_type = CONFIGTPL_CONFIG_PARAM_TYPE_MAP,
        .value.map = {
            .data = context_items,
            .len = 2
        }
    };

    struct configtpl_ConfigParam overrides_item1 = {
        .param_type = CONFIGTPL_CONFIG_PARAM_TYPE_STRING,
        .value.string = "my_overidden_value",
    };
    struct configtpl_ConfigParamDictItem overrides_items[1] = {
        {
            .name = "my_overidden_key",
            .value = &overrides_item1,
        },
    };
    struct configtpl_ConfigParam overrides = {
        .param_type = CONFIGTPL_CONFIG_PARAM_TYPE_MAP,
        .value.map = {
            .data = overrides_items,
            .len = 1
        }
    };

    char *app_env_prefix = "MY_APP";
    struct configtpl_BuildArgs args = {
        .env_vars_prefix = app_env_prefix,
        .context = &context,
        .defaults = NULL,
        .paths = paths,
        .overrides = &overrides,
    };


    fprintf(stderr, "Before build...\n");
    const struct configtpl_BuildResult *r = configtpl_configbuilder_build(handle, args);
    fprintf(stderr, "After build...\n");
    int ret_code = -1;
    int line_nr = 0;
    char *line = NULL;
    switch (r->status)
    {
        case CONFIGTPL_BUILD_STATUS_SUCCESS:
            fprintf(stderr, "Operation succeeded. Here is the result:\n");
            printConfig(&r->output, NULL);
            ret_code = 0;
            break;
        case CONFIGTPL_BUILD_STATUS_ERROR_INVALID_HANDLE:
            fprintf(stderr, "Invalid handle: %d", handle);
            break;
        case CONFIGTPL_BUILD_STATUS_ERROR_BUILDING:
            fprintf(stderr, "Failed to render template: %s\n", r->error_msg);
            break;
        default:
            fprintf(stderr, "Unknown error occurred.");
            break;

    }

    configtpl_configbuilder_result_free(r);
    configtpl_configbuilder_free(handle);

    if (CONFIGTPL_SIMPLE_RESULT_ERROR == configtpl_cleanup())
    {
        fprintf(stderr, "Failed to deinitialize configtpl");
        ret_code = 1;
    }

    return ret_code;
}