AxlConfig – Configuration
Unified configuration framework. Declare options once in a descriptor
table, populate from command-line args or programmatic set calls, and
retrieve with typed getters. Supports auto-apply via offsetof,
callbacks for custom logic, and parent inheritance for cascading defaults.
Header: <axl/axl-config.h>
Overview
AxlConfig replaces ad-hoc key-value parsing with a declarative system. You define a table of option descriptors (name, type, default value), then set values from any source. Type validation happens automatically.
Defining Options
#include <axl.h>
typedef struct {
size_t port;
bool verbose;
size_t max_connections;
} ServerConfig;
static const AxlConfigDesc opts[] = {
{ "port", AXL_CFG_UINT, "8080", 0, "Listen port",
offsetof(ServerConfig, port), sizeof(size_t) },
{ "verbose", AXL_CFG_BOOL, "false", 0, "Verbose output",
offsetof(ServerConfig, verbose), sizeof(bool) },
{ "max.conn", AXL_CFG_UINT, "16", 0, "Max connections",
offsetof(ServerConfig, max_connections), sizeof(size_t) },
{ 0 }
};
Creating and Querying
ServerConfig sc;
AXL_AUTOPTR(AxlConfig) cfg = axl_config_new(opts);
// Set the auto-apply target -- values are written directly
// into the struct fields via offsetof
axl_config_set_target(cfg, &sc);
// Set values (type-validated)
axl_config_set(cfg, "port", "9090"); // sc.port = 9090
axl_config_set(cfg, "verbose", "true"); // sc.verbose = true
// Query values
size_t port = axl_config_get_uint(cfg, "port");
const char *port_str = axl_config_get(cfg, "port"); // "9090"
Command-Line Integration
Parse -p 8080 --verbose directly into the config:
static const AxlOpt cli_opts[] = {
{ 'p', "--port", AXL_OPT_VALUE, "PORT", "Listen port" },
{ 'v', "--verbose", AXL_OPT_FLAG, NULL, "Verbose" },
{ 0 }
};
// axl_config_parse_args maps short/long flags to config keys
axl_config_parse_args(cfg, argc, argv, cli_opts);
Multi-Value Options
For options that can be specified multiple times (e.g., -H "Name: Value"):
size_t count = axl_config_get_multi_count(cfg, "headers");
for (size_t i = 0; i < count; i++) {
const char *hdr = axl_config_get_multi(cfg, "headers", i);
axl_printf(" header: %s\n", hdr);
}
Parent Inheritance
Create a child config that inherits defaults from a parent:
AxlConfig *defaults = axl_config_new(opts);
axl_config_set(defaults, "port", "8080");
AxlConfig *override = axl_config_new_with_parent(opts, defaults);
// override inherits "port"="8080" until explicitly set
API Reference
Defines
-
AXL_CFG_BOOL
“true”/”false”/”1”/”0”
-
AXL_CFG_INT
signed integer
-
AXL_CFG_UINT
unsigned integer
-
AXL_CFG_STRING
arbitrary string
-
AXL_CFG_MULTI
repeatable string (array)
Typedefs
-
typedef int (*AxlConfigApplyFunc)(void *target, const char *key, const char *value)
Callback invoked when an option is set.
Called BEFORE descriptor lookup — handles dynamic keys (e.g. “header.*”) that aren’t in the descriptor table.
Return values:
0: accepted, proceed with descriptor lookup + auto-apply
1: handled by callback (value stored, auto-apply skipped)
-1: rejected (set returns -1)
Functions
-
AxlConfig *axl_config_new(const AxlConfigDesc *descs, AxlConfigApplyFunc apply_fn, void *target)
Create a config object from descriptors.
Defaults from descriptors are applied immediately. If
targetis non-NULL and descriptors have offset/field_size, defaults are written into the target struct.- Parameters:
descs – descriptor table (borrowed, not copied)
apply_fn – change callback (NULL for auto-only)
target – opaque pointer for apply_fn + auto-apply
- Returns:
new config, or NULL on allocation failure.
-
void axl_config_free(AxlConfig *cfg)
Free a config object. NULL-safe.
- Parameters:
cfg – config to free
-
int axl_config_set(AxlConfig *cfg, const char *key, const char *value)
Set a config option.
Validates type, calls apply_fn (if set), then auto-applies via offsetof (if descriptor has offset). Stores the string value internally for later retrieval.
- Parameters:
cfg – config
key – option key
value – value as string
- Returns:
0 on success, -1 on unknown key, type mismatch, or callback rejection.
-
int axl_config_setv(AxlConfig *cfg, ...)
Set multiple options in one call.
Accepts key/value string pairs terminated by NULL. Stops at the first failure and returns -1.
axl_config_setv(cfg, "port", "8080", "verbose", "true", NULL);
- Parameters:
cfg – config
- Param :
key, value pairs terminated by NULL
- Returns:
0 on success, -1 on first error.
-
const char *axl_config_get(AxlConfig *cfg, const char *key)
Get an option value as string.
- Parameters:
cfg – config
key – option key
- Returns:
stored value, default, or NULL if unknown key.
-
bool axl_config_get_bool(AxlConfig *cfg, const char *key)
Get a boolean option.
Accepts “true”/”1”/”yes” as true, everything else as false.
- Parameters:
cfg – config
key – option key
-
int64_t axl_config_get_int(AxlConfig *cfg, const char *key)
Get a signed integer option.
- Parameters:
cfg – config
key – option key
- Returns:
parsed value, or 0 if unset or not a number.
-
uint64_t axl_config_get_uint(AxlConfig *cfg, const char *key)
Get an unsigned integer option.
- Parameters:
cfg – config
key – option key
- Returns:
parsed value, or 0 if unset or not a number.
-
size_t axl_config_get_multi_count(AxlConfig *cfg, const char *key)
Get the count of values for a MULTI option.
- Parameters:
cfg – config
key – option key
-
const char *axl_config_get_multi(AxlConfig *cfg, const char *key, size_t index)
Get a value from a MULTI option by index.
- Parameters:
cfg – config
key – option key
index – 0-based index
- Returns:
value string, or NULL if index out of range.
-
int axl_config_parse_args(AxlConfig *cfg, int argc, char **argv)
Parse command-line arguments into config.
Maps short flags and long options (key names) to config values. Flags without values are treated as boolean “true”. Supports
-k,--key,--key=value, and--to stop parsing. Unrecognized args are collected as positional arguments.- Parameters:
cfg – config
argc – argument count
argv – argument vector (argv[0] is program name)
- Returns:
0 on success, -1 on error (unknown flag).
-
const char *axl_config_pos(AxlConfig *cfg, int index)
Get positional argument by index.
- Parameters:
cfg – config
index – 0-based index
- Returns:
argument string, or NULL if index out of range.
-
int axl_config_pos_count(AxlConfig *cfg)
Get count of positional arguments.
- Parameters:
cfg – config
-
void axl_config_usage(AxlConfig *cfg, const char *program, const char *synopsis)
Print usage from descriptors.
Outputs formatted help to stdout: “Usage: PROGRAM SYNOPSIS” followed by option descriptions from the descriptor table.
- Parameters:
cfg – config (for descriptors)
program – program name
synopsis – usage synopsis (e.g. “[options] FILE”)
-
void axl_config_set_parent(AxlConfig *cfg, AxlConfig *parent)
Set a parent config for cascading defaults.
When axl_config_get finds no value for a key, it falls through to the parent. Useful for per-connection configs that inherit server-level defaults.
- Parameters:
cfg – child config
parent – parent config (borrowed, not owned)
-
struct AxlConfigDesc
- #include <axl-config.h>
Option descriptor. Define a static array terminated by {0}.
Public Members
-
const char *key
dotted name (e.g. “timeout.ms”)
-
int type
AXL_CFG_BOOL, _INT, _UINT, _STRING, _MULTI.
-
const char *default_value
default as string (NULL = no default)
-
char short_flag
single-char CLI flag (0 = none)
-
const char *description
help text
-
size_t offset
offsetof into target struct
-
size_t field_size
sizeof the target field (0 = no auto-apply)
-
const char *key