liblcfg - lightweight configuration file library

About liblcfg

liblcfg is a lightweight configuration file library written in C99. The file format supports arbitrarily nested simple assignments, lists and maps (aka dictionaries).

Example input file

The following file is a simple example configuration file readable by liblcfg.

// simple assignment
string-value = "foo"

// list value assignment
list_value = [ "a", "b", "c" ]

// map value assignment
map-value = {
    foo = "bar"
    bar = "foo"
}

binary_string = "\0\xff\r\n\0\0\x4a"

/* deep nesting */
nested-list = [[[["deep nesting"]]]]

a = {
    d = ["d", ["e","r"], "my index is 2"]
}

Download & Source

The current download version of liblcfg is 0.2.2; git access and online browsing is also available.

Installing liblcfg

There are two ways to use liblcfg in your program. You can either link it as a shared object against your program or generate a pair of static source files to be included at compile-time.

Installing liblcfg on your system

By installing liblcfg on your system you can link your program against liblcfg dynamically. The standard autoconf steps are required for installation:

./configure
make
make install # as root

The installation includes the lcfg binary, which is a simple command line tool to query configuration files. Altough this is certainly the preferred installation method, it is probably unlikely that you want to install liblcfg system-wide and have it added as a dependency to your program. See next section for a static approach.

Compiling liblcfg into your program

By compiling liblcfg statically into your program you avoid any external dependency. The liblcfg distribution package contains a small shellscript named mksinglefile.sh which will create two files: lcfg_static.h and lcfg_static.c. After adding these files to your project and including the header you'll be able to use all liblcfg features.

Usage example

The following code shows some basic usage of liblcfg by printing all values of the specified configuration file to stdout. This file is also available in the liblcfg distribution package.

#include <stdio.h>
#include <ctype.h>

#include <lcfg/lcfg.h>

enum lcfg_status example_visitor(const char *key, void *data, size_t len, void *user_data) {
    int i;
    char c;

    printf("%s = \"", key);
    for( i = 0; i < len; i++ ) {
        c = *((const char *)(data + i));
        printf("%c", isprint(c) ? c : '.');
    }
    puts("\"");

    return lcfg_status_ok;
}


int main(int argc, char **argv) {
    if( argc != 2 ) {
        printf("usage: %s FILE\n", argv[0]);
        return -1;
    }

    struct lcfg *c = lcfg_new(argv[1]);
    
    if( lcfg_parse(c) != lcfg_status_ok ) {
        printf("lcfg error: %s\n", lcfg_error_get(c));
    } else {
        lcfg_accept(c, example_visitor, 0);
    }

    lcfg_delete(c); 
    
    return 0;
}

Interface description

The liblcfg interface consists of a very small set of functions and types. All elements of lcfg.h are described here.

struct lcfg
This structure represents a configuration file context. The storage size and elements are purposely unknown to the library user and may change between versions.
enum lcfg_status
The lcfg_status enumeration contains several return codes used by various functions within liblcfg. Currently only lcfg_status_ok and lcfg_status_error are implemented.
enum lcfg_status (*lcfg_visitor_function)(const char *key, void *data, size_t size, void *user_data)
The lcfg_visitor_function function-pointer typedef. This function is called for every configuration element identified by key with a value of length size pointed to by data. The user_data argument is set by the user upon the visit invocation. If this function does not return lcfg_status_ok the iteration is stopped prematurely and no further calls are made.
struct lcfg *lcfg_new(const char *filename)
Creates a new configuration file context and returns a pointer to the newly created context.
enum lcfg_status lcfg_parse(struct lcfg *c)
Parse the configuration file specified in the context pointed to by c. If any error is encountered the function returns lcfg_status_error and the error message is set accordingly. Otherwise lcfg_status_ok is returned.
enum lcfg_status lcfg_accept(struct lcfg *c, lcfg_visitor_function fn, void *user_data)
Start iterating through all configuration key/value-pairs of c using the visitor function fn. The user_data value can be of any type and is passed along with every visitor call.
enum lcfg_status lcfg_value_get(struct lcfg *c, const char *key, void **data, size_t *len)
Return the string-value located at path key by setting data and len of the value. Returns lcfg_status_error if the key was not found, lcfg_status_ok otherwise. Note that this function does only return string-values, if the value pointed to by key is not a string-value lcfg_status_error is returned.
const char *lcfg_error_get(struct lcfg *c)
Return the last error message within context c.
void lcfg_error_set(struct lcfg *c, const char *fmt, ...)
Set the error message for context c. A library user should not need this function.
void lcfg_delete(struct lcfg *c)
Free the configuration context pointed to by c.

Tree Interface

By design, liblcfg does not store an explicit abstract syntax tree after parsing the file. Nonetheless you can still access the file through a tree structure by using lcfgx/lcfgx_tree.h which acts as a seperate layer on top of the regular interface. Please refer to this file for documentation (one struct and two functions only!).

The lcfg utility

The liblcfg package also includes a simple CLI tool lcfg to query a configuration file by keys. It is useful for processing configuration files properly in shell scripts etc.

License and author

liblcfg is licensed under the BSD license. liblcfg is © 2007–2012 Paul Baecher. I can be reached at Get a graphical browser..