$darkmode
Elektra 0.11.0
Public Member Functions | List of all members
kdb::KeySet Class Reference

A keyset holds together a set of keys. More...

#include <keyset.hpp>

Public Member Functions

 KeySet ()
 Creates a new empty keyset with no keys. More...
 
 KeySet (ckdb::KeySet *k)
 Take ownership of a ckdb::KeySet *. More...
 
 KeySet (const KeySet &other)
 Duplicate a keyset. More...
 
 KeySet (size_t alloc,...) ELEKTRA_SENTINEL
 Create a new keyset. More...
 
 KeySet (VaAlloc alloc, va_list ap)
 Create a new keyset. More...
 
 ~KeySet ()
 Deconstruct a keyset. More...
 
ckdb::KeySet * release ()
 If you don't want destruction of keyset at the end you can release the pointer.
 
ckdb::KeySet * getKeySet () const
 Passes out the raw keyset pointer. More...
 
KeySetoperator= (KeySet const &other)
 Duplicate a keyset. More...
 
ssize_t size () const
 The size of the keyset. More...
 
KeySet dup () const
 Duplicate a keyset. More...
 
void copy (const KeySet &other)
 Copy a keyset. More...
 
void clear ()
 Clear the keyset. More...
 
ssize_t append (const Key &toAppend)
 append a key More...
 
ssize_t append (const KeySet &toAppend)
 append a keyset More...
 
Key pop ()
 Remove and return the last Key of ks. More...
 
Key at (elektraCursor pos) const
 Lookup a key by index. More...
 
KeySet cut (const Key &k)
 Cuts out all Keys from KeySet ks that are below or at cutpoint. More...
 
KeySet cut (std::string const &name)
 Cuts out all Keys from KeySet ks that are below or at cutpoint. More...
 
Key lookup (const Key &k, const elektraLookupFlags options=KDB_O_NONE) const
 Look for a Key contained in ks that matches the name of the key. More...
 
Key lookup (std::string const &name, const elektraLookupFlags options=KDB_O_NONE) const
 Lookup a key by name. More...
 
template<typename T >
get (std::string const &name, const elektraLookupFlags options=KDB_O_NONE) const
 Generic lookup+get for keysets. More...
 
ssize_t search (const Key &toSearch) const
 Search in a key set, either yielding the actual index of the key, if the key has been found within the key set, or a negative value indicating the insertion index of the key, if the key would be inserted. More...
 
ssize_t search (std::string const &name) const
 Search in a key set, either yielding the actual index of the key, if the key has been found within the key set, or a negative value indicating the insertion index of the key, if the key would be inserted. More...
 

Detailed Description

A keyset holds together a set of keys.

Methods to manipulate KeySets. A KeySet is a set of keys.

Most important properties of a KeySet:

The most important methods of KeySet:

KeySet is the most important data structure in Elektra. It makes it possible to get and store many keys at once inside the database. In addition to that, the class can be used as high level datastructure in applications and it can be used in plugins to manipulate or check configuration.

With ksLookupByName() it is possible to fetch easily specific keys out of the list of keys.

You can easily create and iterate keys:

// create a new keyset with 3 keys
// with a hint that about 20 keys will be inside
KeySet * myConfig = ksNew (20, keyNew ("user:/name1", KEY_END), keyNew ("user:/name2", KEY_END), keyNew ("user:/name3", KEY_END), KS_END);
// append a key in the keyset
ksAppendKey (myConfig, keyNew ("user:/name4", KEY_END));
Key * current;
for (elektraCursor it = 0; it < ksGetSize (myConfig); ++it)
{
current = ksAtCursor (myConfig, it);
printf ("Key name is %s.\n", keyName (current));
}
ksDel (myConfig); // delete keyset and all keys appended
KeySet()
Creates a new empty keyset with no keys.
Definition: keyset.hpp:481
Key * keyNew(const char *name,...)
A practical way to fully create a Key object in one step.
Definition: key.c:144
@ KEY_END
Definition: kdbenum.c:95
const char * keyName(const Key *key)
Returns a pointer to the abbreviated real internal key name.
Definition: elektra/keyname.c:429
int ksDel(KeySet *ks)
A destructor for KeySet objects.
Definition: keyset.c:521
KeySet * ksNew(size_t alloc,...)
Allocate, initialize and return a new KeySet object.
Definition: keyset.c:282
ssize_t ksGetSize(const KeySet *ks)
Return the number of Keys that ks contains.
Definition: keyset.c:791
#define KS_END
End of a list of keys.
Definition: kdbenum.c:156
ssize_t ksAppendKey(KeySet *ks, Key *toAppend)
Appends a Key to the end of ks.
Definition: keyset.c:968
Key * ksAtCursor(const KeySet *ks, elektraCursor pos)
Return Key at given position pos.
Definition: keyset.c:1978
Copy-on-Write

Keysets employ copy-on-write techniques to minimize memory footprint. If you create a copy or a duplication of a keyset, the resulting keyset initially references the same data as the source keyset. Only if add or remove keys from a keyset additional memory is allocated.

Invariant
always holds an underlying elektra keyset.
Note
that the cursor is mutable, so it might be changed even in const functions as described.

Constructor & Destructor Documentation

◆ KeySet() [1/5]

kdb::KeySet::KeySet ( )
inline

Creates a new empty keyset with no keys.

Allocate, initialize and return a new KeySet object. Objects created with ksNew() must be destroyed with ksDel().

You can use an arbitrary long list of parameters to preload the KeySet with a list of Keys. Either your first and only parameter is 0 or your last parameter must be KS_END.

So, terminate with ksNew(0, KS_END) or ksNew(20, ..., KS_END)

Warning
Never use ksNew(0, keyNew(...), KS_END). If the first parameter is 0, other arguments are ignored.

The first parameter alloc defines how many Keys can be added without reallocation. If you pass any alloc size greater than 0, but less than 16, it will default to 16.

For most uses

KeySet * keys = ksNew (1, KS_END);
// enough memory for up to 16 keys, without needing reallocation
ksDel (keys);

will be fine. The alloc size will be 16 and will double whenever size reaches alloc size, so it also performs well with large KeySets.

You can defer the allocation of the internal array that holds the Keys, by passing 0 as the alloc size. This is useful if it is unclear whether your KeySet will actually hold any Keys and you want to avoid a malloc call.

// Create KeySet without allocating memory for keys
KeySet * keys = ksNew (0, KS_END);
// The first allocation will happen in ksAppendKey
ksAppendKey(keys, keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key02", KEY_VALUE, "value02", KEY_END));
// work with the KeySet
ksDel (keys);
@ KEY_VALUE
Definition: kdbenum.c:88

If the size of the KeySet is known in advance, use the alloc parameter to hint the size of the KeySet.

If your application only needs up to 15 Keys you can request a KeySet of size 15:

KeySet * keys = ksNew (15, keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key01", KEY_VALUE, "value01", KEY_END),
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key02", KEY_VALUE, "value02", KEY_END),
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key03", KEY_VALUE, "value03", KEY_END),
// ...
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key15", KEY_VALUE, "value15", KEY_END), KS_END);
// work with it
ksDel (keys);

If you start having 3 Keys, and your application needs approximately 200 up to 500 Keys, you can use:

KeySet * config = ksNew (500, keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key1", KEY_VALUE, "value1", KEY_END),
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key2", KEY_VALUE, "value2", KEY_END),
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key3", KEY_VALUE, "value3", KEY_END),
KS_END); // don't forget the KS_END at the end!
// work with it
ksDel (config);

Alloc size is 500, the size of the KeySet will be 3 after ksNew. This means the KeySet will reallocate when appending more than 497 keys.

The main benefit of taking a list of variant length parameters is to be able to have one C-Statement for any possible KeySet. If you prefer, you can always create an empty KeySet and use ksAppendKey().

Postcondition
the KeySet is rewinded properly
Parameters
allocgives a hint for how many Keys may be stored initially
Returns
a ready to use KeySet object
Return values
0on memory error
Since
1.0.0
See also
ksDel() to free the KeySet afterwards
ksDup() to duplicate an existing KeySet
ksAppendKey() to append individual Keys to a KeySet

◆ KeySet() [2/5]

kdb::KeySet::KeySet ( ckdb::KeySet *  keyset)
inline

Take ownership of a ckdb::KeySet *.

// TODO: use ksIncRef/ksDecRef

Parameters
keysetthe KeySet * to take the ownership of
See also
release()

◆ KeySet() [3/5]

kdb::KeySet::KeySet ( const KeySet other)
inline

Duplicate a keyset.

This keyset will be a duplicate of the other afterwards.

Note
that they still reference to the same Keys, so if you change key values also the keys in the original keyset will be changed.

So it is shallow copy, to create a deep copy you have to dup() every key (it still won't copy metadata, but they are COW):

kdb::KeySet ksDeepCopy (kdb::KeySet orig)
{
kdb::KeySet deepCopy;
for (ssize_t it = 0; it < orig.size (); ++it)
{
deepCopy.append (orig.at (it).dup ());
}
return deepCopy;
}
A keyset holds together a set of keys.
Definition: keyset.hpp:54
ssize_t append(const Key &toAppend)
append a key
Definition: keyset.hpp:665
Key at(elektraCursor pos) const
Lookup a key by index.
Definition: keyset.hpp:701
ssize_t size() const
The size of the keyset.
Definition: keyset.hpp:610
Key dup(elektraCopyFlags flags=KEY_CP_ALL) const
Definition: key.hpp:845
See also
dup

◆ KeySet() [4/5]

kdb::KeySet::KeySet ( size_t  alloc,
  ... 
)
inlineexplicit

Create a new keyset.

Parameters
allocminimum number of keys to allocate
...variable argument list

Allocate, initialize and return a new KeySet object. Objects created with ksNew() must be destroyed with ksDel().

You can use an arbitrary long list of parameters to preload the KeySet with a list of Keys. Either your first and only parameter is 0 or your last parameter must be KS_END.

So, terminate with ksNew(0, KS_END) or ksNew(20, ..., KS_END)

Warning
Never use ksNew(0, keyNew(...), KS_END). If the first parameter is 0, other arguments are ignored.

The first parameter alloc defines how many Keys can be added without reallocation. If you pass any alloc size greater than 0, but less than 16, it will default to 16.

For most uses

KeySet * keys = ksNew (1, KS_END);
// enough memory for up to 16 keys, without needing reallocation
ksDel (keys);

will be fine. The alloc size will be 16 and will double whenever size reaches alloc size, so it also performs well with large KeySets.

You can defer the allocation of the internal array that holds the Keys, by passing 0 as the alloc size. This is useful if it is unclear whether your KeySet will actually hold any Keys and you want to avoid a malloc call.

// Create KeySet without allocating memory for keys
KeySet * keys = ksNew (0, KS_END);
// The first allocation will happen in ksAppendKey
ksAppendKey(keys, keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key02", KEY_VALUE, "value02", KEY_END));
// work with the KeySet
ksDel (keys);

If the size of the KeySet is known in advance, use the alloc parameter to hint the size of the KeySet.

If your application only needs up to 15 Keys you can request a KeySet of size 15:

KeySet * keys = ksNew (15, keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key01", KEY_VALUE, "value01", KEY_END),
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key02", KEY_VALUE, "value02", KEY_END),
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key03", KEY_VALUE, "value03", KEY_END),
// ...
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key15", KEY_VALUE, "value15", KEY_END), KS_END);
// work with it
ksDel (keys);

If you start having 3 Keys, and your application needs approximately 200 up to 500 Keys, you can use:

KeySet * config = ksNew (500, keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key1", KEY_VALUE, "value1", KEY_END),
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key2", KEY_VALUE, "value2", KEY_END),
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key3", KEY_VALUE, "value3", KEY_END),
KS_END); // don't forget the KS_END at the end!
// work with it
ksDel (config);

Alloc size is 500, the size of the KeySet will be 3 after ksNew. This means the KeySet will reallocate when appending more than 497 keys.

The main benefit of taking a list of variant length parameters is to be able to have one C-Statement for any possible KeySet. If you prefer, you can always create an empty KeySet and use ksAppendKey().

Postcondition
the KeySet is rewinded properly
Parameters
allocgives a hint for how many Keys may be stored initially
Returns
a ready to use KeySet object
Return values
0on memory error
Since
1.0.0
See also
ksDel() to free the KeySet afterwards
ksDup() to duplicate an existing KeySet
ksAppendKey() to append individual Keys to a KeySet
Precondition
caller must call va_start and va_end
va the list of arguments
Parameters
allocthe allocation size
vathe list of variable arguments

◆ KeySet() [5/5]

kdb::KeySet::KeySet ( VaAlloc  alloc,
va_list  av 
)
inlineexplicit

Create a new keyset.

Parameters
allocminimum number of keys to allocate
apvariable arguments list

Use va as first argument to use this constructor, e.g.:

KeySet ks(va, 23, ...);

Allocate, initialize and return a new KeySet object. Objects created with ksNew() must be destroyed with ksDel().

You can use an arbitrary long list of parameters to preload the KeySet with a list of Keys. Either your first and only parameter is 0 or your last parameter must be KS_END.

So, terminate with ksNew(0, KS_END) or ksNew(20, ..., KS_END)

Warning
Never use ksNew(0, keyNew(...), KS_END). If the first parameter is 0, other arguments are ignored.

The first parameter alloc defines how many Keys can be added without reallocation. If you pass any alloc size greater than 0, but less than 16, it will default to 16.

For most uses

KeySet * keys = ksNew (1, KS_END);
// enough memory for up to 16 keys, without needing reallocation
ksDel (keys);

will be fine. The alloc size will be 16 and will double whenever size reaches alloc size, so it also performs well with large KeySets.

You can defer the allocation of the internal array that holds the Keys, by passing 0 as the alloc size. This is useful if it is unclear whether your KeySet will actually hold any Keys and you want to avoid a malloc call.

// Create KeySet without allocating memory for keys
KeySet * keys = ksNew (0, KS_END);
// The first allocation will happen in ksAppendKey
ksAppendKey(keys, keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key02", KEY_VALUE, "value02", KEY_END));
// work with the KeySet
ksDel (keys);

If the size of the KeySet is known in advance, use the alloc parameter to hint the size of the KeySet.

If your application only needs up to 15 Keys you can request a KeySet of size 15:

KeySet * keys = ksNew (15, keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key01", KEY_VALUE, "value01", KEY_END),
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key02", KEY_VALUE, "value02", KEY_END),
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key03", KEY_VALUE, "value03", KEY_END),
// ...
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key15", KEY_VALUE, "value15", KEY_END), KS_END);
// work with it
ksDel (keys);

If you start having 3 Keys, and your application needs approximately 200 up to 500 Keys, you can use:

KeySet * config = ksNew (500, keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key1", KEY_VALUE, "value1", KEY_END),
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key2", KEY_VALUE, "value2", KEY_END),
keyNew ("user:/sw/org/app/#0/current/fixedConfiguration/key3", KEY_VALUE, "value3", KEY_END),
KS_END); // don't forget the KS_END at the end!
// work with it
ksDel (config);

Alloc size is 500, the size of the KeySet will be 3 after ksNew. This means the KeySet will reallocate when appending more than 497 keys.

The main benefit of taking a list of variant length parameters is to be able to have one C-Statement for any possible KeySet. If you prefer, you can always create an empty KeySet and use ksAppendKey().

Postcondition
the KeySet is rewinded properly
Parameters
allocgives a hint for how many Keys may be stored initially
Returns
a ready to use KeySet object
Return values
0on memory error
Since
1.0.0
See also
ksDel() to free the KeySet afterwards
ksDup() to duplicate an existing KeySet
ksAppendKey() to append individual Keys to a KeySet
Precondition
caller must call va_start and va_end
va the list of arguments
Parameters
allocthe allocation size
vathe list of variable arguments

◆ ~KeySet()

kdb::KeySet::~KeySet ( )
inline

Deconstruct a keyset.

A destructor for KeySet objects. Every KeySet created by ksNew() must be deleted with ksDel().

When the reference counter of ks is non-zero, this function will do nothing and simply return the current value of the reference counter.

It is therefore safe to call ksDel (ks) on any KeySet * ks.

Parameters
ksthe KeySet object to delete
Return values
0when the KeySet was freed
-1on NULL pointers
Returns
the value of the reference counter, if it was non-zero
Since
1.0.0
See also
ksNew() for creating a new KeySet
ksIncRef() for more information about the reference counter

Member Function Documentation

◆ append() [1/2]

ssize_t kdb::KeySet::append ( const Key toAppend)
inline

append a key

Parameters
toAppendkey to append
Returns
number of keys in the keyset

Appends a Key to the end of ks. Hands the ownership of the Key toAppend to the KeySet ks. ksDel(ks) uses keyDel(k) to delete every Key unless it got its reference counter incremented by keyIncRef(), e.g. by another KeySet that contains this Key.

The reference counter of the Key will be incremented to indicate this ownership, and thus toAppend is not const.

See also
keyGetRef()

If the Key's name already exists in the KeySet, it will be replaced with the new Key.

ksAppendKey() will also lock the Key's name from toAppend. This is necessary so that the order of the KeySet cannot be destroyed via calls to keySetName().

The KeySet internal cursor will be set to the new Key.

It is safe to directly append newly created Keys:

KeySet * ks = ksNew (1, KS_END);
ksAppendKey (ks, keyNew ("user:/my/new/key", KEY_END));
ksDel (ks);
// key deleted, too!

If you want the key to outlive the KeySet, make sure to do proper ref counting:

KeySet * ks = ksNew (1, KS_END);
Key * k = keyNew ("user:/ref/key", KEY_END);
ksAppendKey (ks, k);
ksDel (ks);
// now we still can work with the key k!
keyDel (k);
uint16_t keyIncRef(Key *key)
Increment the reference counter of a Key object.
Definition: key.c:581
uint16_t keyDecRef(Key *key)
Decrement the reference counter of a Key object.
Definition: key.c:620
int keyDel(Key *key)
A destructor for Key objects.
Definition: key.c:459

You can duplicate the Key to avoid aliasing, but then the Key in the KeySet has another identity:

KeySet * ks = ksNew (1, KS_END);
Key * k = keyNew ("user:/ref/key", KEY_END);
ksAppendKey (ks, keyDup (k, KEY_CP_ALL));
ksDel (ks);
// now we still can work with the key k!
keyDel (k);
@ KEY_CP_ALL
Definition: kdbenum.c:110
Parameters
ksKeySet where toAppend should be append
toAppendKey that will be appended to ks or deleted
Returns
the size of the KeySet after appending
Return values
-1on NULL pointers
-1if appending failed (only on memory problems). The Key will be deleted then.
Since
1.0.0
See also
ksAppend() for appending a KeySet to another KeySet
keyIncRef() for manually increasing a Key's reference counter

◆ append() [2/2]

ssize_t kdb::KeySet::append ( const KeySet toAppend)
inline

append a keyset

Parameters
toAppendkeyset to append
Returns
number of keys in the keyset

Append all Keys in toAppend to the end of the KeySet ks. toAppend KeySet will be left unchanged.

If a Key is both in toAppend and ks, the Key in ks will be overwritten.

Postcondition
Sorted KeySet ks with all Keys it had before and additionally the Keys from toAppend
Parameters
ksthe KeySet that will receive the Keys
toAppendthe KeySet that provides the Keys that will be transferred
Returns
the size of the KeySet ks after transfer
Return values
-1on NULL pointers
Since
1.0.0
See also
ksAppendKey()

◆ at()

Key kdb::KeySet::at ( elektraCursor  pos) const
inline

Lookup a key by index.

Parameters
poscursor position
Returns
the found key

◆ clear()

void kdb::KeySet::clear ( )
inline

Clear the keyset.

Keyset will be empty afterwards.

◆ copy()

void kdb::KeySet::copy ( const KeySet other)
inline

Copy a keyset.

Replaces all keys in this with the ones from other. This is only a shallow copy. For a deep copy you need to manually Key::dup every key.

Parameters
otherother keyset to copy

Replace the content of a KeySet with another one. Most often you may want a duplicate of a KeySet, see ksDup() or append keys, see ksAppend(). In some situations you need to copy Keys from a KeySet to another KeySet, for which this function exists.

Note
You can also use it to clear a KeySet when you pass a NULL pointer as source.
Implementation:
First all Keys in dest will be deleted. Afterwards the content of source will be added to the destination.

A flat copy is made, so Keys will not be duplicated, but their reference counter is updated, so both KeySets need to be deleted via ksDel().

int f (KeySet *ks)
{
KeySet *c = ksNew (20, ..., KS_END);
// c receives keys
ksCopy (ks, c); // pass the KeySet to the caller
ksDel (c);
} // caller needs to ksDel (ks)
int ksCopy(KeySet *dest, const KeySet *source)
Replace the content of a KeySet with another one.
Definition: keyset.c:476
Parameters
sourcean initialized KeySet or NULL
destan initialized KeySet, where the Keys from source get copied to
Return values
1on success
0if dest was cleared successfully (source is NULL)
-1when dest is a NULL pointer
Since
1.0.0
See also
ksNew() for creating a new KeySet
ksDel() for deleting an existing KeySet
ksDup() for duplicating an existing KeySet
keyCopy() for copying Keys

◆ cut() [1/2]

KeySet kdb::KeySet::cut ( const Key k)
inline

Cuts out all Keys from KeySet ks that are below or at cutpoint.

Searches for the cutpoint inside the KeySet ks. If found, it cuts out this Key and everything which is below (see keyIsBelow()) this Key. These Keys will be missing in the keyset ks. Instead, they will be moved to the returned KeySet. If cutpoint is not found an empty KeySet is returned and ks is not changed.

The cursor will stay at the same Key as it was before. If the cursor was inside the region of cut (moved) Keys, the cursor will be set to the Key before the cutpoint.

If you use ksCut() on a KeySet you got from kdbGet() and plan to use kdbSet() later, make sure that you keep all Keys that should not be removed permanently. You have to keep the KeySet that was returned and the KeySet ks.

Example:

You have the keyset ks:

  • system:/mountpoint/interest
  • system:/mountpoint/interest/folder
  • system:/mountpoint/interest/folder/key1
  • system:/mountpoint/interest/folder/key2
  • system:/mountpoint/other/key1

When you use

Key * parentKey = keyNew ("system:/mountpoint/interest", KEY_END);
KDB * kdb = kdbOpen (NULL, parentKey);
KeySet * ks = ksNew (0, KS_END);
kdbGet (kdb, ks, parentKey);
KeySet * returned = ksCut (ks, parentKey);
kdbSet (kdb, ks, parentKey); // all keys below cutpoint are now removed
kdbClose (kdb, parentKey);
int kdbSet(KDB *handle, KeySet *ks, Key *parentKey)
Set Keys to the Key database in an atomic and universal way.
Definition: kdb.c:2343
int kdbGet(KDB *handle, KeySet *ks, Key *parentKey)
Retrieve Keys from the Key database in an atomic and universal way.
Definition: kdb.c:1734
KDB * kdbOpen(const KeySet *contract, Key *errorKey)
Opens the session with the Key database.
Definition: kdb.c:967
int kdbClose(KDB *handle, Key *errorKey)
Closes the session with the Key database.
Definition: kdb.c:1105
KeySet * ksCut(KeySet *ks, const Key *cutpoint)
Cuts out all Keys from KeySet ks that are below or at cutpoint.
Definition: keyset.c:1608
This is the main namespace for the C++ binding and libraries.
Definition: backend.hpp:31

Then in returned are:

  • system:/mountpoint/interest
  • system:/mountpoint/interest/folder
  • system:/mountpoint/interest/folder/key1
  • system:/mountpoint/interest/folder/key2

And in ks are:

  • system:/mountpoint/other/key1

So kdbSet() permanently removes all keys at or below system:/mountpoint/interest.

Parameters
ksthe Keyset to cut. It will be modified by removing all Keys at or below the cutpoint.
cutpointthe point where to cut out the Keyset
Returns
a new allocated KeySet which needs to be deleted with ksDel(). The KeySet consists of all Keys (of the original KeySet ks) below the cutpoint. If the Key cutpoint exists, it will also be appended.
Return values
0on NULL pointers, no Key name or allocation problems
Since
1.0.0
See also
kdbGet() for an explanation on why you might get more Keys than you requested.

◆ cut() [2/2]

KeySet kdb::KeySet::cut ( std::string const &  name)
inline

Cuts out all Keys from KeySet ks that are below or at cutpoint.

Searches for the cutpoint inside the KeySet ks. If found, it cuts out this Key and everything which is below (see keyIsBelow()) this Key. These Keys will be missing in the keyset ks. Instead, they will be moved to the returned KeySet. If cutpoint is not found an empty KeySet is returned and ks is not changed.

The cursor will stay at the same Key as it was before. If the cursor was inside the region of cut (moved) Keys, the cursor will be set to the Key before the cutpoint.

If you use ksCut() on a KeySet you got from kdbGet() and plan to use kdbSet() later, make sure that you keep all Keys that should not be removed permanently. You have to keep the KeySet that was returned and the KeySet ks.

Example:

You have the keyset ks:

  • system:/mountpoint/interest
  • system:/mountpoint/interest/folder
  • system:/mountpoint/interest/folder/key1
  • system:/mountpoint/interest/folder/key2
  • system:/mountpoint/other/key1

When you use

Key * parentKey = keyNew ("system:/mountpoint/interest", KEY_END);
KDB * kdb = kdbOpen (NULL, parentKey);
KeySet * ks = ksNew (0, KS_END);
kdbGet (kdb, ks, parentKey);
KeySet * returned = ksCut (ks, parentKey);
kdbSet (kdb, ks, parentKey); // all keys below cutpoint are now removed
kdbClose (kdb, parentKey);

Then in returned are:

  • system:/mountpoint/interest
  • system:/mountpoint/interest/folder
  • system:/mountpoint/interest/folder/key1
  • system:/mountpoint/interest/folder/key2

And in ks are:

  • system:/mountpoint/other/key1

So kdbSet() permanently removes all keys at or below system:/mountpoint/interest.

Parameters
ksthe Keyset to cut. It will be modified by removing all Keys at or below the cutpoint.
cutpointthe point where to cut out the Keyset
Returns
a new allocated KeySet which needs to be deleted with ksDel(). The KeySet consists of all Keys (of the original KeySet ks) below the cutpoint. If the Key cutpoint exists, it will also be appended.
Return values
0on NULL pointers, no Key name or allocation problems
Since
1.0.0
See also
kdbGet() for an explanation on why you might get more Keys than you requested.

◆ dup()

KeySet kdb::KeySet::dup ( ) const
inline

Duplicate a keyset.

Returns
a copy of the keys

This is only a shallow copy. For a deep copy you need to dup every key.

Return a duplicate of a KeySet. Objects created with ksDup() must be destroyed with ksDel().

Memory will be allocated as needed for dynamic properties, so you need to ksDel() the returned pointer.

A flat copy is made, so the Keys will not be duplicated, but their reference counter is updated, so both KeySets need to be deleted via ksDel().

Parameters
sourcehas to be an initialized KeySet
Returns
a flat copy of source on success
Return values
0on NULL pointer
Since
1.0.0
See also
ksNew() for creating a new KeySet
ksDel() for deleting a KeySet
keyDup() for Key duplication

◆ get()

template<typename T >
T kdb::KeySet::get ( std::string const &  name,
const elektraLookupFlags  options = KDB_O_NONE 
) const
inline

Generic lookup+get for keysets.

Parameters
namethe key name to get
optionsthe options to be passed to lookup()
Exceptions
KeyNotFoundExceptionif no key found
Note
To specialize more complex types (which are generic themselves) you can also specialize KeySetTypeWrapper<T>.

Use

to include specializations for std types.

Returns
the requested type

◆ getKeySet()

ckdb::KeySet * kdb::KeySet::getKeySet ( ) const
inline

Passes out the raw keyset pointer.

This function exists so that pure C functions that do not have a C++ binding can be called.

Returns
pointer to internal ckdb KeySet

◆ lookup() [1/2]

Key kdb::KeySet::lookup ( const Key key,
const elektraLookupFlags  options = KDB_O_NONE 
) const
inline

Look for a Key contained in ks that matches the name of the key.

Note
Applications should only use ksLookup() with cascading Keys (Key name starting with /). Furthermore, a lookup should be done for every Key (also when iterating over Keys) so that the specifications are honored correctly. Keys of all namespaces need to be present so that ksLookup() can work correctly, so make sure to also use kdbGet() with a cascading Key.

ksLookup() is designed to let you work with a KeySet containing all Keys of the application. The idea is to fully kdbGet() the whole configuration of your application and process it all at once with many ksLookup().

This function is efficient (at least using binary search). Together with kdbGet(), which you can use to load the whole configuration, you can write very effective and short code for configuration:

Key * key = keyNew ("/sw/tests/myapp/#0/current/", KEY_END);
KDB * handle = kdbOpen (NULL, key);
kdbGet (handle, myConfig, key);
Key * result = ksLookupByName (myConfig, "/sw/tests/myapp/#0/current/testkey1", 0);
Key * ksLookupByName(KeySet *ks, const char *name, elektraLookupFlags options)
Convenience method to look for a Key contained in ks with name name.
Definition: keyset.c:2778

This is the way programs should get their configuration and search for the values. It is guaranteed, that more namespaces can be added easily and that all values can be set by admin and user. Furthermore, using the kdb-tool, it is possible to introspect which values an application will get (by doing the same cascading lookup).

If found, a pointer to the Key is returned. If not found a NULL pointer is returned.

Cascading lookups will by default search in all namespaces (proc:/, dir:/, user:/ and system:/), but will also correctly consider the specification (=metadata) in spec:/:

  • override/# will make sure that another Key is considered before
  • namespace/# will change the number and/or order in which the namespaces are searched
  • fallback/# will search for other Keys when the other possibilities up to now were not successful
  • default to return the given value when not even fallback Keys were found.
Note
override and fallback work recursively, while default does not.

This process is very flexible, but it would be boring to manually follow all this links to find out which Key will be taken in the end. Use kdb get -v to trace the Keys.

KDB_O_POP
When KDB_O_POP is set the Key which was found will be ksPop()ed.
Note
Like in ksPop() the popped Key always needs to be keyDel() afterwards, even if it is appended to another KeySet.
void f (KeySet * iterator, KeySet * lookup)
{
ssize_t ksSize = ksGetSize (iterator);
for (elektraCursor it = 0; it < ksSize; ++it)
{
Key * current = ksAtCursor (iterator, it);
Key * key = ksLookup (lookup, current, KDB_O_POP);
// do something...
ksAppendKey (append, key); // now append it to append, not lookup!
keyDel (key); // make sure to ALWAYS delete poped keys.
}
// now lookup needs to be sorted only once, append never
}
Key lookup(const Key &k, const elektraLookupFlags options=KDB_O_NONE) const
Look for a Key contained in ks that matches the name of the key.
Definition: keyset.hpp:729
ssize_t ksAppend(KeySet *ks, const KeySet *toAppend)
Append all Keys in toAppend to the end of the KeySet ks.
Definition: keyset.c:1081
Key * ksLookup(KeySet *ks, Key *key, elektraLookupFlags options)
Look for a Key contained in ks that matches the name of the key.
Definition: keyset.c:2714
@ KDB_O_POP
Pop Parent out of keyset key in ksLookup().
Definition: kdbenum.c:186

This is also a nice example how a complete application with ksLookup() can look like.

KDB_O_DEL
Passing KDB_O_DEL will cause the deletion of the parameter key using keyDel().
Hybrid search
When Elektra is compiled with ENABLE_OPTIMIZATIONS=ON a hybrid search decides dynamically between the binary search and the OPMPHM. The hybrid search can be overruled by passing KDB_O_OPMPHM or KDB_O_BINSEARCH in the options to ksLookup().
Parameters
ksthe KeySet that should be searched
keythe Key object you are looking for
optionsof type elektraLookupFlags with some KDB_O_* option bits - as explained above
Returns
pointer to the Key found
Return values
0if no Key has been found
0on NULL pointers
Since
1.0.0
See also
ksLookupByName() to search by a name given by a string
ksGetSize(), ksAtCursor() for iterating over a KeySet
Note
That the internal key cursor will point to the found key

◆ lookup() [2/2]

Key kdb::KeySet::lookup ( std::string const &  name,
const elektraLookupFlags  options = KDB_O_NONE 
) const
inline

Lookup a key by name.

Parameters
namethe name to look for
optionssome options to pass
Returns
the found key
See also
lookup (const Key &Key, const elektraLookupFlags options)
Note
That the internal key cursor will point to the found key

◆ operator=()

KeySet & kdb::KeySet::operator= ( KeySet const &  other)
inline

Duplicate a keyset.

This keyset will be a duplicate of the other afterwards.

Note
that they still reference to the same Keys, so if you change key values also the keys in the original keyset will be changed.

◆ pop()

Key kdb::KeySet::pop ( )
inline

Remove and return the last Key of ks.

The reference counter of the Key will be decremented by one.

The KeySet's cursor will not be affected if it did not point to the popped Key.

Note
You need to keyDel() the Key afterwards, if you don't append it to another KeySet. It has the same semantics like a Key allocated with keyNew() or keyDup().
ks1=ksNew(0, KS_END);
ks2=ksNew(0, KS_END);
k1=keyNew("user:/name", KEY_END); // ref counter 0
ksAppendKey(ks1, k1); // ref counter 1
ksAppendKey(ks2, k1); // ref counter 2
k1=ksPop (ks1); // ref counter 1
k1=ksPop (ks2); // ref counter 0, like after keyNew()
ksAppendKey(ks1, k1); // ref counter 1
ksDel (ks1); // key is deleted too
ksDel (ks2);
Key * ksPop(KeySet *ks)
Remove and return the last Key of ks.
Definition: keyset.c:1740
Parameters
ksKeySet to pop a Key from
Returns
the last Key of ks
Return values
NULLif ks is empty or a NULL pointer
Since
1.0.0
See also
ksLookup() to pop Keys by name
ksCopy() to pop all Keys

◆ search() [1/2]

ssize_t kdb::KeySet::search ( const Key toSearch) const
inline

Search in a key set, either yielding the actual index of the key, if the key has been found within the key set, or a negative value indicating the insertion index of the key, if the key would be inserted.

ssize_t result = ksSearch(ks, key);
if (result >= 0)
{
ssize_t position = result;
// The key already exist in key set.
} else {
ssize_t insertpos = -result-1;
// The key was not found in key set.
}
ssize_t ksSearch(const KeySet *ks, const Key *key)
Search in a key set, either yielding the actual index of the key, if the key has been found within th...
Definition: keyset.c:916
Parameters
ksthe keyset to work with
keythe key to check
Returns
position where the key is (>=0) if the key was found
-insertpos -1 (< 0) if the key was not found so to get the insertpos simple do: -insertpos -1
See also
ksLookup() for retrieving the found Key

◆ search() [2/2]

ssize_t kdb::KeySet::search ( std::string const &  name) const
inline

Search in a key set, either yielding the actual index of the key, if the key has been found within the key set, or a negative value indicating the insertion index of the key, if the key would be inserted.

ssize_t result = ksSearch(ks, key);
if (result >= 0)
{
ssize_t position = result;
// The key already exist in key set.
} else {
ssize_t insertpos = -result-1;
// The key was not found in key set.
}
Parameters
ksthe keyset to work with
keythe key to check
Returns
position where the key is (>=0) if the key was found
-insertpos -1 (< 0) if the key was not found so to get the insertpos simple do: -insertpos -1
See also
ksLookup() for retrieving the found Key
Note
Accepts a keyname as string instead of a Key object.

◆ size()

ssize_t kdb::KeySet::size ( ) const
inline

The size of the keyset.

Returns
the number of keys in the keyset

The documentation for this class was generated from the following file: