Add config module: INI loader with schema-driven defaults
Config_Def schema tables declare section/key/type/default per module. Typed getters: config_get_str, _u16, _u32, _flags. FLAGS type parses space/comma-separated tokens via a Config_Flag_Def table. config_defaults() gives schema defaults without a file. config_dump() prints effective values for diagnostics. config_cli: load a file or --defaults and dump effective config. dev/example.cfg: sample config covering node, discovery, transport. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
76
include/config.h
Normal file
76
include/config.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "error.h"
|
||||
|
||||
/*
|
||||
* INI-style config file loader with schema-driven defaults and validation.
|
||||
*
|
||||
* File format:
|
||||
* [section]
|
||||
* key = value ; inline comments with ; or #
|
||||
* key = value # same
|
||||
*
|
||||
* Whitespace around keys and values is stripped.
|
||||
* Commas in values are treated as whitespace (useful for flag lists).
|
||||
*/
|
||||
|
||||
typedef enum Config_Type {
|
||||
CONFIG_STRING, /* arbitrary string value */
|
||||
CONFIG_UINT16, /* decimal integer, fits u16 */
|
||||
CONFIG_UINT32, /* decimal integer, fits u32 */
|
||||
CONFIG_FLAGS, /* space/comma-separated tokens mapped via a flag table */
|
||||
} Config_Type;
|
||||
|
||||
/*
|
||||
* One entry in a flags table — maps a token string to a bitmask value.
|
||||
* The table must be terminated by an entry with token = NULL.
|
||||
*/
|
||||
struct Config_Flag_Def {
|
||||
const char *token;
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
/*
|
||||
* One entry in a config schema.
|
||||
* Provide a table of these terminated by an entry with section = NULL.
|
||||
*/
|
||||
struct Config_Def {
|
||||
const char *section;
|
||||
const char *key;
|
||||
Config_Type type;
|
||||
const char *default_val; /* string form of the default */
|
||||
const struct Config_Flag_Def *flags; /* required when type = CONFIG_FLAGS */
|
||||
};
|
||||
|
||||
struct Config;
|
||||
|
||||
/*
|
||||
* Load a config file and validate it against the schema.
|
||||
* Keys present in the file but absent from the schema are ignored.
|
||||
* Keys absent from the file are filled with their schema default.
|
||||
*/
|
||||
struct App_Error config_load(struct Config **out,
|
||||
const char *path,
|
||||
const struct Config_Def *schema);
|
||||
|
||||
/*
|
||||
* Load defaults only (no file). Useful when no config file is present
|
||||
* but you still want schema-driven defaults.
|
||||
*/
|
||||
struct App_Error config_defaults(struct Config **out,
|
||||
const struct Config_Def *schema);
|
||||
|
||||
void config_free(struct Config *cfg);
|
||||
|
||||
/*
|
||||
* Typed getters. Return the effective value (file value or default).
|
||||
* Caller must not free the returned string — it is owned by the Config.
|
||||
*/
|
||||
const char *config_get_str (struct Config *cfg, const char *section, const char *key);
|
||||
uint16_t config_get_u16 (struct Config *cfg, const char *section, const char *key);
|
||||
uint32_t config_get_u32 (struct Config *cfg, const char *section, const char *key);
|
||||
uint32_t config_get_flags(struct Config *cfg, const char *section, const char *key);
|
||||
|
||||
/* Print all effective key/value pairs to stdout — useful for diagnostics. */
|
||||
void config_dump(struct Config *cfg);
|
||||
Reference in New Issue
Block a user