libk  kconf.md at [926d05a4ce]

File kconf/kconf.md artifact b260f2842a part of check-in 926d05a4ce


# kconf

while there are a number of existing configuration parser libraries out there, they all have their problems, and all depend on libc. since configuration string parsing is a fairly core functionality that would force many programs to either write their own code or drag libc back into their dependencies, supplying a basic parser with libk makes sense.

## basic principles

kconf is intended to be fast, lightweight, transparent, and low-overhead.

to initialize a kconf structure, we begin by supplying a list of *atoms.* like in Xlib, an atom is a performant way to reference a known string of text from a compiled program. we can do this in two different ways, either by generating the values ourselves at compile time with an enum, or by generating them at runtime using the appropriate kconf interface. note that if you supply your own with an enum, because zero is used for in-band error signalling, the first atom should always be an error token. alternately, it may be explicitly set to a non-zero number and a return value of zero can be checked for implicitly or against a literal 0.

note that, in a recurring libk pattern, if an element count of zero (or `null`) is passed to a function that takes an array of nullables, that function will treat its array argument as a null-terminated array to be counted at runtime.

kconf is initialized by filling out the struct `kconf` with the parameters of operations and then passing it to the appropriate function.

    enum atoms { parse_error, user, pw, email, atomct };
    kconf kc = {
    	.decl = { atomct, {
    		{ user,  {4, "user"    } },
    		{ pw,    {8, "password"} },
    		{ email, {5, "email"   } }
    	}}
    };

	/* with runtime counts:
     * enum atoms { parse_error, user, pw, email };
     * kconf kc = {
     * 	.decl = { null, {
     * 		{ user,  {0, "user"    } },
     * 		{ pw,    {0, "password"} },
     * 		{ email, {0, "email"   } },
	 *		{ null }
     * 	}}
     * }; */

	/* with macros:
     * enum atoms { parse_error, user, password, email };
     * kconf kc = {
     * 	.decl = {Kmpsa(kconf_decl, {
	 * 		Kconf_atom(user),
	 * 		Kconf_atom(password),
	 * 		Kconf_atom(email)
	 * 	})};
	 * }; */

## types

### struct kconf
	* `union { kconf_decl decl; kconf_gen gen; };`

### struct kconf_atom

 * `sz key`
 * `ksraw string`

### struct kconf_pair

 * `kconf_atom atom`
 * `ksraw* dest`


## macros

 * `Kconf_atom(atom)` - a convenience macro for definining an pre-defined atom structure (`kconf_atom`), under the assumption that the C enumerator name is the same as the string used to name the field in the configuration file. inserts the text `{atom, {sizeof(#atom), #atom}}`
 * `Kconf_atom_pfx(pfx,atom)` - a convenience macro for definining an pre-defined atom structure (`kconf_atom`), under the assumption that the C enumerator name is the string used to name the field in the configuration file with a prefix attached. inserts the text `{pfx##atom, {sizeof(#atom), #atom}}`