Due to ABI compatibility, the Key structure is not defined in kdb.h, only declared. So you can only declare pointers to Keys in your program, and allocate and free memory for them with keyNew() and keyDel() respectively.
Reference Counting
Every key has its reference counter (see keyGetRef() for longer explanation) that will be initialized with 0, that means a subsequent call of keyDel() will delete the key. If you append the key to a keyset the reference counter will be incremented by one (see keyIncRef()) and the key can't be deleted by a keyDel().
As you can imagine this refcounting allows you to put the Key in your own data structures. It can be a very powerful feature, e.g. if you need your own-defined ordering or different Models of your configuration.
Copy-On-Write
Keys employ copy-on-write techniques to minimize memory footprint. If keys are copied or duplicated, they will point at the same name and value as the source key. Only if this data is changed, additional memory is allocated.
This class is an wrapper for an optional, refcounted ckdb::Key. It is like an shared_ptr<ckdb::Key>, but the shared_ptr functionality is already within the Key and exposed with this wrapper.
optional
A key can be constructed with an null pointer, by using Key (static_cast<ckdb::Key*>(0)); or made empty afterwards by using release() or assign a null key. To check if there is an associated managed object the user can use isNull().
references
Copies of keys are cheap because they are only flat. If you really need a deep copy, you can use copy() or dup(). If you release() an object, the reference counter will stay All other operations operate on references.
documentation
Note that the documentation is typically copied from the underlying function which is wrapped and sometimes extended with C++ specific details. So you might find C examples within the C++ documentation.
Invariant
Key either has a working underlying Elektra Key object or a null pointer. The Key, however, might be invalid (see isValid()) or null (see isNull()).
Note
that the reference counting in the keys is mutable, so that const keys can be passed around by value.
keyNew() allocates memory for a key object and keyDel() cleans everything up.
If you want the key object to contain a name, value, comment and other meta info read on.
Note
When you already have a key with similar properties its easier to keyDup() the key.
You can call keyNew() in many different ways depending on the attribute tags you pass as parameters. Tags are represented as elektraKeyFlags values, and tell keyNew() which Key attribute comes next. The Key attribute tags are the following:
KEY_VALUE
Next parameter is a pointer to the value that will be used. If no KEY_BINARY was used before, a string is assumed.
// Create and initialize a key with a name and nothing else
KEY_END
Must be the last parameter passed to keyNew(). It is always required, unless the keyName is 0.
KEY_FLAGS
Bitwise disjunction of flags, which don't require one or more values. recommended way to set multiple flags. overrides previously defined flags.
KEY_BINARY
Allows one to change the key to a binary key. Make sure that you also pass KEY_SIZE before you set the value. Otherwise it will be cut off with first \0 in the string. So this flag toggle from keySetString() to keySetBinary(). If no value (nor size) is given, it will be a NULL key.
// Create and initialize a key with a name and nothing else
keyNew() allocates memory for a key object and keyDel() cleans everything up.
If you want the key object to contain a name, value, comment and other meta info read on.
Note
When you already have a key with similar properties its easier to keyDup() the key.
You can call keyNew() in many different ways depending on the attribute tags you pass as parameters. Tags are represented as elektraKeyFlags values, and tell keyNew() which Key attribute comes next. The Key attribute tags are the following:
KEY_VALUE
Next parameter is a pointer to the value that will be used. If no KEY_BINARY was used before, a string is assumed.
// Create and initialize a key with a name and nothing else
KEY_END
Must be the last parameter passed to keyNew(). It is always required, unless the keyName is 0.
KEY_FLAGS
Bitwise disjunction of flags, which don't require one or more values. recommended way to set multiple flags. overrides previously defined flags.
KEY_BINARY
Allows one to change the key to a binary key. Make sure that you also pass KEY_SIZE before you set the value. Otherwise it will be cut off with first \0 in the string. So this flag toggle from keySetString() to keySetBinary(). If no value (nor size) is given, it will be a NULL key.
// Create and initialize a key with a name and nothing else
keyNew() allocates memory for a key object and keyDel() cleans everything up.
If you want the key object to contain a name, value, comment and other meta info read on.
Note
When you already have a key with similar properties its easier to keyDup() the key.
You can call keyNew() in many different ways depending on the attribute tags you pass as parameters. Tags are represented as elektraKeyFlags values, and tell keyNew() which Key attribute comes next. The Key attribute tags are the following:
KEY_VALUE
Next parameter is a pointer to the value that will be used. If no KEY_BINARY was used before, a string is assumed.
// Create and initialize a key with a name and nothing else
KEY_END
Must be the last parameter passed to keyNew(). It is always required, unless the keyName is 0.
KEY_FLAGS
Bitwise disjunction of flags, which don't require one or more values. recommended way to set multiple flags. overrides previously defined flags.
KEY_BINARY
Allows one to change the key to a binary key. Make sure that you also pass KEY_SIZE before you set the value. Otherwise it will be cut off with first \0 in the string. So this flag toggle from keySetString() to keySetBinary(). If no value (nor size) is given, it will be a NULL key.
// Create and initialize a key with a name and nothing else
Adds baseName to the name of key. baseName will be escaped before adding it to the name of key. No other part of the Key's name will be affected.
Assumes that key is a directory and will append baseName to it. The function adds the path separator for concatenating.
If key has the name "system:/dir1/dir2" and this method is called with baseName"mykey", the resulting key will have the name "system:/dir1/dir2/mykey".
When baseName is 0, nothing will happen and the size of the name is returned.
Depending on the chosen flagskeyCopy() only copies certain parts of source into dest.
If KEY_CP_NAME is set, the key name will be copied from source to dest.
If KEY_CP_META is set, the meta keys will be copied from source to dest.
If KEY_CP_VALUE is set, the key value will be copied from source to dest. Additionally, if source is a binary key (keyIsBinary()), dest will also be marked as binary. This means that even if KEY_CP_META is not set, the binary meta key will be copied with KEY_CP_VALUE.
If KEY_CP_STRING is set, the key value will be copied from source to dest, but only, if source is not a binary key (keyIsBinary()). If source is binary, keyCopy() fails. If dest is binary, it will still be marked as binary after the copy. This cannot be used together with KEY_CP_VALUE. The main purpose of KEY_CP_STRING is for copying into known string keys. It ensure that you don't accidentally convert string keys into binary keys.
There is also the shorthand KEY_CP_ALL. It is equivalent to KEY_CP_NAME | KEY_CP_VALUE | KEY_CP_META, i.e. all key data supported by keyCopy() will be copied from source to dest.
Use this function when you need to copy into an existing key, e.g. because it was passed by a pointer in a function you can do so:
The reference counter will not be changed for both keys. Affiliation to keysets are also not affected.
Since metadata uses copy-on-write semantics there is only a constant memory cost to copying metadata.
When you pass a NULL-pointer as source the pieces of dest specified by flags will be cleared.
Calling keyCopy (dest, NULL, KEY_CP_ALL) is different from calling keyClear(). The key will not be fully reset, the reference counter and internal flags will remain unchanged. Additionally, keyCopy() respects keyLock() state, while keyClear() always works.
the key which should be copied or NULL to clear the data of dest
flags
specifies which parts of the key should be copied
Returns
dest
Return values
NULL
on memory allocation problems
NULL
when a part of dest that should be modified (e.g. name, value) was marked read-only, e.g. the name of dest will be read-only if dest is part of a KeySet
Do a shallow copy of all metadata from source to dest.
The key dest will additionally have all metadata the source had. Metadata not present in source will not be changed. Metadata which was present in source and dest will be overwritten. If the destKey is read-only it will not be changed.
For example the metadata type is copied into the Key k:
The main purpose of this function is for plugins or applications which want to add the same metadata to n keys. When you do that with keySetMeta() it will take n times the memory for the key. This can be considerable amount of memory for many keys with some metadata for each.
Do a shallow copy of metadata with name metaName from source to dest.
Afterwards source and dest will have the same metadata referred with metaName. If the Key with name metaName doesn't exist in source - it gets deleted in dest.
For example the metadata type is copied into the Key k.
The main purpose of this function is for plugins or applications, which want to add the same metadata to n keys. When you do that keySetMeta() will take n times the memory for the key. This can be a considerable amount of memory for many keys with some metadata for each.
Returns a pointer to the unescaped Key's name where the basename starts.
This is a much more efficient version of keyGetBaseName() and you should use it if you are responsible enough to not mess up things. The name might change or even point to a wrong place after a keySetName(). So make sure to copy the memory before the name changes.
keyBaseName() returns "" when the Key has no basename. The reason is
Calculates number of bytes needed to store basename of key (including NULL terminator).
Key names consisting of only root names (e.g. "system:/" or "user:/" or "user:domain" ) do not have basenames. In this case the function will return 1, because only a NULL terminator is needed for storage.
Returns the number of bytes needed to store the key value, including the NULL terminator.
It returns the correct size, independent of the Key Type. If the value is binary there might be '\0' values in it.
For an empty string you need one byte to store the ending NULL. For that reason 1 is returned. This is not true for binary data, so 0 will be returned.
A binary key has no '\0' termination. String types are null-terminated, and the terminator will be considered for the length.
No exception will be thrown if a const Key or char* is requested, but don't forget the const: getMeta<const Key>, otherwise you will get an compiler error.
Returns a pointer to the abbreviated real internal key name.
This is a much more efficient version of keyGetName() and can use it if you are responsible enough to not mess up things. You are not allowed to change anything in the returned array. The content of that string may change after keySetName() and similar functions. If you need a copy of the name, consider using keyGetName().
proc:/something for in-memory keys, e.g. commandline.
dir:/something for dir keys in current working directory
system:/something for system keys in /etc or /
user:/something for user keys in home directory
user:username/something for other users (deprecated: kdbGet() + kdbSet() currently unsupported)
/something for cascading keys (actually refers to one of the above, see also ksLookup())
Note
Note that the Key structure keeps its own size field that is calculated by library internal calls, so to avoid inconsistencies, you must never use the pointer returned by keyName() method to set a new value. Use keySetName() instead.
Returns the number of bytes needed to store the key value, including the NULL terminator.
It returns the correct size, independent of the Key Type. If the value is binary there might be '\0' values in it.
For an empty string you need one byte to store the ending NULL. For that reason 1 is returned. This is not true for binary data, so 0 will be returned.
A binary key has no '\0' termination. String types are null-terminated, and the terminator will be considered for the length.
This is a much more efficient version of keyGetString()keyGetBinary(). You should use it if you are responsible enough to not mess up things. You are not allowed to modify anything in the returned string. If you need a copy of the Value, consider to use keyGetString() or keyGetBinary() instead.
String Handling
If key is string (keyIsString()), you may cast the returned as a "char *" because you'll get a NULL terminated regular string.
keyValue() returns "" in string mode when there is no value. The reason is
Note that the Key structure keeps its own size field that is calculated by library internal calls, so to avoid inconsistencies, you must never use the pointer returned by keyValue() method to set a new value. Use keySetString() or keySetBinary() instead.
Warning
Binary keys will return a NULL pointer when there is no data in contrast to keyName(), keyBaseName() and keyComment(). For string value the behaviour is the same.
The function checks if the value of key is binary. Contrary to string values binary values can have '\0' inside the value and may not be terminated by a null character. Their disadvantage is that you need to pass their size.
Make sure to use this function and don't test the binary type another way to ensure compatibility and to write less error prone programs.
The comparison is based on a memcmp of the Key's names. If the names match, the Keys are found to be exactly the same and 0 is returned. These two keys can't be used in the same KeySet.
As long as the reference counter is non-zero, keyDel() operations on key will be a no-op and return an error code.
Elektra's system for reference counting is not based on a concept of shared ownership. It is more similar to a shared lock, where the counter is used to keep track of how many clients hold the lock.
Initially, the reference counter will be 0. This is can be interpreted as the lock being unlocked. When you increment the reference counter, the lock becomes locked and keyDel() is blocked and fails. Only when the reference counter is fully decremented back down to 0 again, will keyDel() work again.
Note
The reference counter can never exceed UINT16_MAX - 1. UINT16_MAX is reserved as an error code.
Postcondition
key's reference counter is > 0
key's reference counter is <= UINT16_MAX - 1
Parameters
key
the Key object whose reference counter should be increased
Returns
the updated value of the reference counter
Return values
UINT16_MAX
on NULL pointer
UINT16_MAX
when the reference counter already was the maximum value UINT16_MAX - 1, the reference counter will not be modified in this case
Since
1.0.0
See also
keyGetRef() to retrieve the current reference count
As long as the reference counter is non-zero, keyDel() operations on key will be a no-op and return an error code.
Elektra's system for reference counting is not based on a concept of shared ownership. It is more similar to a shared lock, where the counter is used to keep track of how many clients hold the lock.
Initially, the reference counter will be 0. This is can be interpreted as the lock being unlocked. When you increment the reference counter, the lock becomes locked and keyDel() is blocked and fails. Only when the reference counter is fully decremented back down to 0 again, will keyDel() work again.
Note
The reference counter can never exceed UINT16_MAX - 1. UINT16_MAX is reserved as an error code.
Postcondition
key's reference counter is > 0
key's reference counter is <= UINT16_MAX - 1
Parameters
key
the Key object whose reference counter should be increased
Returns
the updated value of the reference counter
Return values
UINT16_MAX
on NULL pointer
UINT16_MAX
when the reference counter already was the maximum value UINT16_MAX - 1, the reference counter will not be modified in this case
Since
1.0.0
See also
keyGetRef() to retrieve the current reference count
The comparison is based on a memcmp of the Key's names. If the names match, the Keys are found to be exactly the same and 0 is returned. These two keys can't be used in the same KeySet.
The comparison is based on a memcmp of the Key's names. If the names match, the Keys are found to be exactly the same and 0 is returned. These two keys can't be used in the same KeySet.
The comparison is based on a memcmp of the Key's names. If the names match, the Keys are found to be exactly the same and 0 is returned. These two keys can't be used in the same KeySet.
The comparison is based on a memcmp of the Key's names. If the names match, the Keys are found to be exactly the same and 0 is returned. These two keys can't be used in the same KeySet.
The comparison is based on a memcmp of the Key's names. If the names match, the Keys are found to be exactly the same and 0 is returned. These two keys can't be used in the same KeySet.
Set the value for key as newStringValue. The function will allocate and save a private copy of newStringValue, so the parameter can be freed after the call.
String values will be saved in backend storage in UTF-8 universal encoding, regardless of the program's current encoding (if the iconv plugin is available).
Precondition
newStringValue is a NULL terminated string
Postcondition
Value of the Key is set to the UTF-8 encoded value of newStringValue
All text after the last '/' in the Key's name is erased and baseName is appended. If baseName is 0 (NULL), then the last part of the Key's name is removed without replacement. The root name of the Key will not be removed though.
Let us suppose key has name "system:/dir1/dir2/key1". If baseName is "key2", the resulting key name will be "system:/dir1/dir2/key2". If baseName is 0 (NULL), the resulting key name will be "system:/dir1/dir2". If baseName is empty, the resulting key name will be "system:/dir1/dir2/%", where "%" denotes an empty base name, as also shown in the following code:
keySetBaseName() does proper escaping on the supplied name argument.
You can use character sequences as baseName (e.g. "." (dot), ".." (dot-dot), "%" (empty basename)). They will be properly escaped and will not have their usual meaning.
If you want to add to the basename instead of changing it, use keyAddBaseName(). If you do not want any escaping, use keyAddName().
Set the value of a Key to the binary value newBinary.
A private copy of newBinary will be allocated and saved inside key, so the parameter can be deallocated after the call.
Binary values might be encoded in another way than string values depending on the plugin. Typically character encodings should not take place on binary data. Consider using a string Key instead, if encoding should occur.
When newBinary is a NULL pointer the value will be freed and 0 will be returned.
Read-only keys will stay unchanged after calling this function.
Note
The metadata "binary" will be set to mark that the key is binary from now on. When the Key is already binary the metadata won't be changed. This will only happen in the successful case, but not when -1 is returned.
unlike the C Interface, it is not possible to remove metadata with this method. k.setMeta("something", NULL) will lead to set the number 0 or to something different (may depend on compiler definition of NULL). See discussion in Issue https://github.com/ElektraInitiative/libelektra/issues/8
The last form has explicitly set the owner, to let the library know in which user folder to save the Key. A owner is a user name. If it is not defined (the second form), current user is used.
You should always follow the guidelines for Key tree structure creation.
A private copy of the Key name will be stored, and the newName parameter can be freed after this call.
.., . and / will be handled as in filesystem paths. A valid name will be build out of the (valid) name what you pass, e.g. user:///sw/../sw//././MyApp -> user:/sw/MyApp
Trailing slashes will be stripped.
On invalid names, the name stays unchanged.
Returns
size of the new Key name in bytes, including NULL terminator
Return values
-1
if key or keyName is NULL or keyName is empty or invalid
The function will allocate and save a private copy of newStringValue, so the parameter can be freed after the call.
String values will be saved in backend storage in UTF-8 universal encoding, regardless of the program's current encoding (if the iconv plugin is available).
Precondition
newStringValue is a NULL terminated string
Postcondition
Value of the Key is set to the UTF-8 encoded value of newStringValue