TOML module, originally intended for HAZE, but usable elsewhere. Forked from
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Nabla ecc32538ea 1.2.5 - Formatting accessor 7 months ago
assets Project layout changes 7 months ago
demo Declare dependency 7 months ago
deprecated_tests Update lib version 7 months ago
src 1.2.5 - Formatting accessor 7 months ago
.editorconfig Add editorconfig file 1 year ago
.gitignore Completed meson support 7 months ago
LICENSE Project layout changes 7 months ago move building and installing 7 months ago Completed meson support 7 months ago


TOML in c99; v1.0 compliant, with Meson subproject support.

Building and installing

Follow standard procedure with Meson. Example:

git clone libhztoml
cd libhztoml

meson builddir
cd builddir
meson configure -Dc_args="-O2 -march=core2 -mtune=generic -g"
meson compile
meson install


Please see the toml.h file for details. What follows is a simple example that parses this config file:

	host = ""
	port = 80

The steps for getting values from our file is usually :

  1. Parse the whole TOML file.
  2. Get a single table from the file.
  3. Find a value from the table.
  4. Then, free up that memory if needed.

Below is an example of parsing the values from the example table.

  1. Parse the whole TOML file.
FILE* fp;
toml_table_t* conf;
char errbuf[200];

/* Open the file and parse content */
if (0 == (fp = fopen("path/to/file.toml", "r"))) {
	return handle_error();
conf = toml_parse_file(fp, errbuf, sizeof(errbuf));
if (0 == conf) {
	return handle_error();

/* Alternatively, use `toml_parse` which takes a string rather than a file. */
conf = toml_parse("A null terminated string that is TOML\0", errbuf, sizeof(errbuf));
  1. Get a single table from the file.
toml_table_t* server;

/* Locate the [server] table. */
if (0 == (server = toml_table_in(conf, "server"))) {
	return handle_error();
  1. Find a value from the table.
/* Extract 'host' config value. */
toml_datum_t host = toml_string_in(server, "host");
if (!host.ok) {
	return handle_error();

toml_datum_t port = toml_int_in(server, "port");
if (!port.ok) {
	return handle_error();

printf("host %s\n", host.u.s);
printf("port %d\n", port.u.i);

  1. Then, free up that memory if needed.
/* Use `toml_free` on the table returned from `toml_parse[_file]`.
 * NOTE: you only need to `toml_free` the root table returned by `toml_parse[_file]`;
 * internal tables do not need to be freed.

/* Free any string values returned from access functions. */

Accessing Table Content

TOML tables are dictionaries where lookups are done using string keys. In general, all access methods on tables are named toml_*_in(...).

Keys in tables can be interrogated using an integer index:

toml_table_t* tab = toml_parse_file(...);
for (int i = 0; ; i++) {
    const char* key = toml_key_in(tab, i);
    if (!key) break;
    printf("key %d: %s\n", i, key);

Once you know a key and its content type, retrievals can be done with one of these methods:

toml_string_in(tab, key);
toml_bool_in(tab, key);
toml_int_in(tab, key);
toml_double_in(tab, key);
toml_timestamp_in(tab, key);
toml_table_in(tab, key);
toml_array_in(tab, key);

Accessing Array Content

TOML arrays can be deref-ed using integer values. In general, all access methods on arrays are named toml_*_at().

To obtain the size of an array:

int size = toml_array_nelem(arr);

To obtain the content of an array, use a valid index and call one of these functions:

toml_string_at(arr, idx);
toml_bool_at(arr, idx);
toml_int_at(arr, idx);
toml_double_at(arr, idx);
toml_timestamp_at(arr, idx);
toml_table_at(arr, idx);
toml_array_at(arr, idx);


Some toml_*_at and toml_*_in functions return a toml_datum_t structure. The ok flag in the structure indicates if the function call was successful. If so, you may proceed to read the value corresponding to the type of the content.

For example:

toml_datum_t host = toml_string_in(tab, "host");
if (host.ok) {
	printf("host: %s\n", host.u.s);
	free(host.u.s);   /* FREE applies to string and timestamp types only */

** IMPORTANT: if the accessed value is a string or a timestamp, you must call free(datum.u.s) or free(datum.u.ts) respectively after usage. **