Configuration and TOML
MontaukOS provides a small header-only C++ API for reading and writing
TOML configuration files from userspace. Include
<montauk/config.h> for file-backed configuration and
<montauk/toml.h> for the in-memory TOML document model.
Configuration locations
System configuration is stored in 0:/config. The API accepts a
name without the .toml extension:
0:/config/desktop.toml
0:/config/network.toml
Per-user configuration is stored below the user directory:
0:/users/<username>/config/<name>.toml
Loading and saving
#include <montauk/config.h>
auto doc = montauk::config::load("desktop");
const char* theme = doc.get_string("appearance.theme", "light");
montauk::config::set_string(&doc, "appearance.theme", "dark");
int result = montauk::config::save("desktop", &doc);
doc.destroy();
load() returns an initialized empty document if the file does
not exist. save() creates the configuration directory and returns
0 on success or a negative value on error. Saving rewrites the
whole file.
System configuration API
toml::Doc config::load(const char* name);
int config::save(const char* name, toml::Doc* doc);
int config::remove(const char* name);
Per-user configuration API
toml::Doc config::load_user(const char* username, const char* name);
int config::save_user(const char* username,
const char* name,
toml::Doc* doc);
For example:
auto doc = montauk::config::load_user("alice", "desktop");
bool clock24 = doc.get_bool("display.clock_24h", false);
montauk::config::set_bool(&doc, "display.clock_24h", true);
montauk::config::save_user("alice", "desktop", &doc);
doc.destroy();
Reading values
Keys may use dotted paths corresponding to TOML tables:
[server]
host = "pool.ntp.org"
port = 123
enabled = true
const char* host = doc.get_string("server.host", "localhost");
int64_t port = doc.get_int("server.port", 80);
bool enabled = doc.get_bool("server.enabled", false);
Typed getters return their default when the key is absent or has another type. The available value types are:
toml::Type::String
toml::Type::Int
toml::Type::Bool
toml::Type::Array
toml::Type::Table
Arrays and tables are returned as toml::Value*. Their children
are available through value->array.items and
value->array.count:
auto* names = doc.get_array("server.names");
if (names) {
for (int i = 0; i < names->array.count; ++i) {
auto* item = names->array.items[i];
if (item->type == montauk::toml::Type::String)
montauk::print(item->str);
}
}
Modifying documents
void config::set_string(toml::Doc* doc,
const char* key, const char* value);
void config::set_int(toml::Doc* doc,
const char* key, int64_t value);
void config::set_bool(toml::Doc* doc,
const char* key, bool value);
bool config::unset(toml::Doc* doc, const char* key);
The setters overwrite an existing value or append a new one. The
unset() return value is true when a matching key was
removed.
Parsing and serialization
Use toml::parse() when TOML is already available in memory:
const char* text =
"[server]\n"
"port = 8080\n"
"enabled = true\n";
auto doc = montauk::toml::parse(text);
int64_t port = doc.get_int("server.port");
doc.destroy();
A document can be serialized to newly allocated TOML text:
char* text = montauk::config::serialize(&doc);
// Use text...
montauk::mfree(text);
Serialization produces normalized TOML and does not preserve comments or the original formatting.
Memory ownership
toml::Doc owns its parsed values and strings. Every document
returned by load(), load_user(), or
toml::parse() must eventually be released with
doc.destroy().
When constructing a document manually, initialize it before using the mutation helpers:
montauk::toml::Doc doc;
doc.init();
montauk::config::set_bool(&doc, "enabled", true);
montauk::config::save("example", &doc);
doc.destroy();
Supported TOML features
The userspace parser supports strings, literal and multiline strings, integers (including hexadecimal, octal, and binary forms), booleans, arrays, tables, inline tables, dotted keys, and comments.
There are no typed float or datetime accessors. Callers should also treat configuration names and usernames as safe path components, since they are used to construct filesystem paths.