| Elektra 0.11.0

High-level API

# 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

1. should be extremely easy to get started with
2. should be very hard to use it wrong
3. 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:

1. libelektra-highlevel (generic key-value getter/setter)
2. 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

1. 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"));
   elektraClose (handle);
   elektraOpen
   Elektra * elektraOpen(const char *application, KeySet *defaults, KeySet *contract, ElektraError **error)
   Initializes a new Elektra instance.
   Definition elektra.c:67
   elektraClose
   void elektraClose(Elektra *elektra)
   Releases all resources used by the given elektra instance.
   Definition elektra.c:484
   elektraGetLong
   kdb_long_t elektraGetLong(Elektra *elektra, const char *keyname)
   Gets a long value.
   Definition elektra_value.c:272
2. It is also easier to get started with writing new bindings.
3. 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