Problem
Projects usually do not want to use low-level APIs. KDB
and KeySet
is useful for plugins and to implement APIs but not to be directly used in applications.
Constraints
- should be extremely easy to get started with
- should be very hard to use it wrong
- all high-level APIs should work together very nicely
- same principles
- same API style
- same error handling
- can be arbitrarily intermixed
Assumptions
- Thread-safety: a handle is the accepted better solution than having to care about whether it is reentrant, thread-safe, ...
- assumes that spec is available (either by compiled-in
KeySet
or exit after elektraOpen)
- many projects do not care about some limitations (no binary, no metadata) but prefer a straightforward way to get/set config
- when people hit limitations they fall back to direct use of
KeySet
, Key
Considered Alternatives
- storing errors in the handle:
- Maintenance problem if error handling is added later
- only provide
KDB
, applications need to implement their own APIs:
- reduces consistency of how the API is used
- only provide generated API
- assume type as
string
if not given
- force
default
to be part of parameters
Decision
We provide two high-level C APIs:
- libelektra-highlevel (generic key-value getter/setter)
- code generator (specified key-value getter/setter with function names, KeySets, or strings from specifications)
Furthermore, we will:
- have as goal that no errors in specified keys with default can occur
- if you use
elektraGetType
before getting a value, no error can occur when getting it later
- enforce that every key has a type
- use
elektraError
as extra parameter (for prototyping and examples you can pass 0)
Rationale
- Very easy to get started with, to get a key needs 3 lines of codes (without error handling):
Elektra *handle =
elektraOpen (
"/sw/elektra/kdb/#0/current", 0);
printf (
"number /mykey is " ELEKTRA_LONG_F
"\n",
elektraGetLong (handle,
"/mykey"));
Elektra * elektraOpen(const char *application, KeySet *defaults, KeySet *contract, ElektraError **error)
Initializes a new Elektra instance.
Definition: elektra.c:67
void elektraClose(Elektra *elektra)
Releases all resources used by the given elektra instance.
Definition: elektra.c:484
kdb_long_t elektraGetLong(Elektra *elektra, const char *keyname)
Gets a long value.
Definition: elektra_value.c:272
- It is also easier to get started with writing new bindings.
- User can combine the different APIs.
Implications
Related Decisions
Notes
- Currently it is not possible to combine low-level and high-level API.
- Hierarchical version not implemented and probably not needed.
- #1359