This document describes the design of the c-\/api and gives hints for binding writers. It does not aim to plugin writers because this detail is hidden from the programmer and is Elektra specific.

Elektra follows the design principles to make it hard to use it wrong and fully aims towards an easy to use A\+P\+I for programmers reading and writing configuration. The data structures are optimized to get, set and lookup values easily and fast.

The idea is that the K\+D\+B A\+P\+I is not only implemented by Elektra. Elektra provides a full blown architecture to really support modern Linux Systems, but comes with some overhead. In this document the K\+D\+B A\+P\+I is described. But sometimes there are hints for elektra specific conventions.

\subsection*{Data Structures}

Key, Key\+Set and K\+D\+B datastructures are defined in kdbprivate.\+h to remain A\+B\+I compatible when something is added to a struct. That means it is not possible to put one of elektra's datastructures on the stack. You must use the memory management facilities mentioned in the next chapter.

\subsection*{Memory Management}

Elektra manages memory itself. No free must be required, which was not allocated by the programmer himself. This avoids that free is forgotten, makes the A\+P\+I more beginner-\/friendly. In addition to all that malloc and free must have the same libc version. malloc in a library linked against another libc, but freed by the application could lead to hard to find bugs.

Some calls have a opposite call to get the structure freed again\+: \begin{DoxyVerb}KDB * kdbOpen();
\end{DoxyVerb}
 will need the function\+: \begin{DoxyVerb}    int kdbClose(KDB *handle);
\end{DoxyVerb}
 to get rid of the resources again. It maybe also shut down connections, so it really must be called at the end of the program. \begin{DoxyVerb}    Key *keyNew(const char *keyName, ...);
    int keyDel(Key *key);

    KeySet *ksNew(int alloc, ...);
    int ksDel(KeySet *ks);
\end{DoxyVerb}


These 2 pairs just malloc what is necessary and free it again. There are more mallocs then just the K\+D\+B, Key and Key\+Set structures, but they are invisible and they happen implicit within any of these 3 classes.

Name, Value, Comment can't be handled as easy, because elektra does not provide a string library. There are 2 ways to access it, showed on the Comment example\+: \begin{DoxyVerb}    char *keyComment(const Key *key);
\end{DoxyVerb}
 just returns the comment and does not allow any change of size of the comment. \begin{DoxyVerb}    ssize_t keyGetCommentSize(const Key *key);
\end{DoxyVerb}
 to see how long the comment is for above function and how much buffer to allocate for function below. This value can be directly passed to malloc. \begin{DoxyVerb}    ssize_t keyGetComment(const Key *key, char *returnedDesc, size_t maxSize);
\end{DoxyVerb}
 will write the comment in a buffer maintained by you which is allocated with at least the size of the function above.

\subsection*{Variable Arguments}

The constructors for Key and Key\+Set take a variable list of arguments as alternative to key\+Set$\ast$ functions and to \hyperlink{group__keyset_gaa5a1d467a4d71041edce68ea7748ce45}{ks\+Append\+Key()}. With that you can generate any key or keyset in a single c-\/statement. This can be done programmatically by key\+Generate or ks\+Generate in libelektratools.

To just get a key, use \begin{DoxyVerb}    Key *k = keyNew (0);  
\end{DoxyVerb}
 and to just get a keyset, use \begin{DoxyVerb}    KeySet *k = ksNew(0, KS_END);
\end{DoxyVerb}


The macros va\+\_\+start and va\+\_\+end will not be used then. Otherwise pass a list like described in the documentation.

\subsection*{Off-\/by-\/one}

Off-\/by-\/one errors (O\+B\+O\+E) are avoided by starting all pointers with 0 as usual in C. The size returned by the $\ast$\+Get\+Size functions (key\+Get\+Value\+Size, key\+Get\+Comment\+Size and key\+Get\+Owner\+Size) is exactly the size needed to be allocated. So if you add 1 to it, too much is allocated, but no error will occur.

\subsection*{Minimal Set}

The functions listed in kdb.\+h is a minimal set to fully work with a key database. They are implemented in src/libelektra in A\+N\+S\+I C.

Functions used by backends are implemented in src/backends/helpers. They need the P\+O\+S\+I\+X interface and can optionally use iconv to make utf8 conversations.

\subsection*{Value, String or Binary}

Some confusion is about value, string or binary. Value is just a name which does not specify if it is a string or binary. String is a char array, with a terminating '\textbackslash{}0', but Binary is a void array, not terminated by '\textbackslash{}0'. Only strings may be converted to other charsets. Use the appendant Get functions, to be not depend on that internal facts. \begin{DoxyVerb}    const void *keyValue(const Key *key);
\end{DoxyVerb}
 does not specify whether it is a binary or string, it will just return the pointer to it. When Key is a string (check with {\ttfamily \hyperlink{group__keytest_gaea7670778abd07fee0fe8ac12a149190}{key\+Is\+String()}}) at least \char`\"{}\char`\"{} will be returned, see below Return Values for strings. For binary data a N\+U\+L\+L pointer is also possible to distinguish between no data and '\textbackslash{}0'. \begin{DoxyVerb}    ssize_t keyGetValueSize(const Key *key);
\end{DoxyVerb}
 does not specify whether it is a binary or string, it will just return the size which can be passed to malloc to hold the entire value. \begin{DoxyVerb}    ssize_t keyGetString(const Key *key, char *returnedString, size_t maxSize);
\end{DoxyVerb}
 Get the string into a buffer maintained by you. \begin{DoxyVerb}    ssize_t keySetString(Key *key, const char *newString);
\end{DoxyVerb}
 Set the null terminated string. \begin{DoxyVerb}    ssize_t keyGetBinary(const Key *key, void *returnedBinary, size_t maxSize);
\end{DoxyVerb}
 Get the binary data which might contain '\textbackslash{}0'. \begin{DoxyVerb}    ssize_t keySetBinary(Key *key, const void *newBinary, size_t dataSize);
\end{DoxyVerb}
 Set the binary data which might contain '\textbackslash{}0'. The length is given by data\+Size.

\subsection*{Return Value}

There are many different types of return values. What they have in common is there error behaviour. Every function must return -\/1 on error if it returns Integers (like int, ssize\+\_\+t). If they return a pointer, 0 (N\+U\+L\+L) will show the error. This can't be used for Integers, because 0 might be a valid size or is used as \char`\"{}false\char`\"{}.

Elektra does not use any float or double, so there is no issue there.

But Elektra uses integers for c-\/string length, reference counting, keyset length and internal keyset allocations.

The interface always accept size\+\_\+t and uses internal size\+\_\+t which can hold larger numbers then ssize\+\_\+t. But to indicate an error it must be always possible to return -\/1. This is only possible with int or ssize\+\_\+t. These two are used for tests and to return a size.

So the real size of c-\/strings and buffers is limited to S\+S\+I\+Z\+E\+\_\+\+M\+A\+X which must be checked in every function. When it exceeds that limit -\/1 (see above Return Value) or N\+U\+L\+L pointer must be returned.

There are some functions which return an internal string\+: \begin{DoxyVerb}    const char *keyName(const Key *key);  
    const char *keyBaseName(const Key *key);  
    const char *keyOwner(const Key *key);  
    const char *keyComment(const Key *key);  
\end{DoxyVerb}


and in the case that ({\ttfamily key\+Is\+Binary(key)==1}) also\+: \begin{DoxyVerb}    const void *keyValue(const Key *key);  
\end{DoxyVerb}


A Null pointer will lead in all that cases that you get back a Null pointer.

When there is no string you will get back \char`\"{}\char`\"{}, that is a pointer to '\textbackslash{}0'. It marks that there is no string. The function to determine the size will return 1 in that case. That means that 1 is for empty strings (Nothing except the N\+U\+L\+L terminator).

This is not true for key\+Value in the case of binary data, because '\textbackslash{}0' in the first byte is a perfect legal binary data. \hyperlink{group__keyvalue_gae326672fffb7474abfe9baf53b73217e}{key\+Get\+Value\+Size()} may also return 0 for that reason.

\subsection*{Error Handling}

Error handling will not be implemented with 0.\+7.\+0. So it won't be possible for an application to determine what exactly went wrong.

Elektra does not set errno. If a function you call sets errno, make sure to set it back to the old value again.

\subsection*{Naming}

All Function Names begin with their class name, e.\+g. kdb, ks or key. The words are written together with large letters for separation. This leads to short names, but might be not as good to read. {\itshape Get} and {\itshape Set} are used for getters/and setters, {\itshape Is} to ask about a flag or state, {\itshape Needs} to ask about state related to database and e.\+g. key\+Remove to set a flag or state. For allocation/deallocation the names are c++ stylish, like the $\ast$\+New functions $\ast$\+Del.

Macros and Enums are written in capital letters. Options start with K\+D\+B\+\_\+\+O, errors K\+D\+B\+\_\+\+E\+R\+R, namespaces K\+E\+Y\+\_\+\+N\+S and key types with K\+E\+Y\+\_\+\+T\+Y\+P\+E.

The data structures start with a capital letter for every part of the word\+: \begin{DoxyVerb}    KDB ... Key Data Base Handle  
    KeySet ... Key Set  
    Key ... Key  
\end{DoxyVerb}


\hyperlink{group__meta_gacaa5060e67b03f50ae49a3620c54bc46}{key\+Get\+U\+I\+D()} and \hyperlink{group__meta_ga46a95e81d7d7f4e3eb59e60e5f3738c0}{key\+Get\+G\+I\+D()} have upper case letters because I\+D is commonly written in upper case letters.

Only singular is used for all names.

Function Names not belonging to one of the three classes are Elektra specific. Those have the prefix elektra$\ast$. They will always be Elektra specific and won't be implemented by other K\+D\+B implementations.

\subsection*{const}

Where possible the functions should use const for parameters. Where Key or Key\+Set is not modified, const is used. For return values no const is used, its more disturbing then have any positive effect. The only exceptions are\+:

In special\+: \begin{DoxyVerb}    const char *keyName(const Key *key);  
    const char *keyBaseName(const Key *key);  
    const char *keyComment(const Key *key);  
    const void *keyValue(const Key *key);  
    const char *keyString(const Key *key);  
    const Key  *keyGetMeta(const Key *key, const char* metaName)  
\end{DoxyVerb}


These functions are really thought to get something and not to change anything! Elektra will lose the knowledge if these keys are synchronized or not. So they are marked const, and you must not cast that away. 