Elektra: kdb::KeySet Class Reference

Elektra 0.8.24

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)
| Takes ownership of 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...
void | setKeySet (ckdb::KeySet *k)
| Take ownership of passed keyset. More...
KeySet & | operator= (KeySet const &other)
| Duplicate a keyset. More...
ssize_t | size () const
| The size of the keyset. More...
ckdb::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 | head () const
| Return the first key in the KeySet. More...
Key | tail () const
| Return the last key in the KeySet. More...
void | rewind () const
| Rewinds the KeySet internal cursor. More...
Key | next () const
| Returns the next Key in a KeySet. More...
Key | current () const
| Return the current Key. More...
void | setCursor (cursor_t cursor) const
| Set the KeySet internal cursor. More...
cursor_t | getCursor () const
| Get the KeySet internal cursor. More...
Key | pop ()
| Remove and return the last key of `ks`. More...
Key | at (cursor_t pos) const
| Lookup a key by index. More...
KeySet | cut (Key k)
| Cuts out a keyset at the cutpoint. More...
Key | lookup (const Key &k, const option_t 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 option_t options=KDB_O_NONE) const
| Lookup a key by name. More...
template<typename T >
T | get (std::string const &name, const option_t options=KDB_O_NONE) const
| Generic lookup+get for keysets. 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:

- Allows us to iterate over all keys (in any depth)
- Iteration is always sorted
- Fast key lookup
- A Key may be shared among many KeySets.

The most important methods of KeySet:

- With ksNew() you can create a new KeySet.
- You can append keys with ksAppendKey() or with ksAppend() you can append a whole keyset.
- Using ksLookup() you can lookup (or pop with KDB_O_POP) a key.
- With ksRewind() and ksNext() you can iterate through the keyset. Be assured that you will get every key of the set in a stable order (parents before children).

Note
  Because the key is not copied, also the pointer to the current metadata keyNextMeta() will be shared.

KeySets have an internal cursor . Methods should avoid to change this cursor, unless they want to communicate something with it. The internal cursor is used:

- in ksLookup(): points to the found key
- in kdbSet(): points to the key which caused an error

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", 0), keyNew ("user/name2", 0), keyNew ("user/name3", 0), KS_END);
// append a key in the keyset
ksAppendKey (myConfig, keyNew ("user/name4", 0));
Key * current;
ksRewind (myConfig);
while ((current = ksNext (myConfig)) != 0)
{
printf ("Key name is %s.\n", keyName (current));
}
ksDel (myConfig); // delete keyset and all keys appended

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 a 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 KEY_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.

For most uses

KeySet * keys = ksNew (0, KS_END);
// work with it
ksDel (keys);

will be fine, the alloc size will be 16, defined in kdbprivate.h. The alloc size will be doubled whenever size reaches alloc size, so it also performs well with large keysets.

But if you have any clue how large your keyset may be you should read the next statements.

If you want a keyset with length 15 (because you know of your application that you only need up to 15 keys), use:

KeySet * keys = ksNew (15, keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key01", KEY_VALUE, "value01", 0),
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key02", KEY_VALUE, "value02", 0),
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key03", KEY_VALUE, "value03", 0),
// ...
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key15", KEY_VALUE, "value15", 0), 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", 0),
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key2", KEY_VALUE, "value2", 0),
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key3", KEY_VALUE, "value3", 0),
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

See also
  ksDel() to free the KeySet afterwards
  ksDup() to duplicate an existing KeySet
  ksAppendKey() to append individual keys

Parameters

  alloc | gives a hint for the size how many Keys may be stored initially

Returns
  a ready to use KeySet object

Return values

  0 | on memory error

## ◆ KeySet() [2/5]

kdb::KeySet::KeySet | ( | ckdb::KeySet * | k | ) |
| inline

Takes ownership of keyset!

Keyset will be destroyed at destructor you cant continue to use keyset afterwards!

Use KeySet::release() to avoid destruction.

Parameters

  k | the keyset to take the ownership from

See also
  release()
  setKeySet()

## ◆ 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;
orig.rewind ();
while (orig.next ())
{
deepCopy.append (orig.current ().dup ());
}
return deepCopy;
}

See also
  dup

## ◆ KeySet() [4/5]

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

Create a new keyset.

Parameters

  alloc | minimum 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 a 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 KEY_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.

For most uses

KeySet * keys = ksNew (0, KS_END);
// work with it
ksDel (keys);

will be fine, the alloc size will be 16, defined in kdbprivate.h. The alloc size will be doubled whenever size reaches alloc size, so it also performs well with large keysets.

But if you have any clue how large your keyset may be you should read the next statements.

If you want a keyset with length 15 (because you know of your application that you only need up to 15 keys), use:

KeySet * keys = ksNew (15, keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key01", KEY_VALUE, "value01", 0),
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key02", KEY_VALUE, "value02", 0),
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key03", KEY_VALUE, "value03", 0),
// ...
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key15", KEY_VALUE, "value15", 0), 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", 0),
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key2", KEY_VALUE, "value2", 0),
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key3", KEY_VALUE, "value3", 0),
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

See also
  ksDel() to free the KeySet afterwards
  ksDup() to duplicate an existing KeySet
  ksAppendKey() to append individual keys

Parameters

  alloc | gives a hint for the size how many Keys may be stored initially

Returns
  a ready to use KeySet object

Return values

  0 | on memory error

Precondition
  caller must call va_start and va_end

va the list of arguments

Parameters

  alloc | the allocation size
  va | the list of variable arguments

## ◆ KeySet() [5/5]

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

Create a new keyset.

Parameters

  alloc | minimum number of keys to allocate
  ap | variable 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 a 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 KEY_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.

For most uses

KeySet * keys = ksNew (0, KS_END);
// work with it
ksDel (keys);

will be fine, the alloc size will be 16, defined in kdbprivate.h. The alloc size will be doubled whenever size reaches alloc size, so it also performs well with large keysets.

But if you have any clue how large your keyset may be you should read the next statements.

If you want a keyset with length 15 (because you know of your application that you only need up to 15 keys), use:

KeySet * keys = ksNew (15, keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key01", KEY_VALUE, "value01", 0),
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key02", KEY_VALUE, "value02", 0),
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key03", KEY_VALUE, "value03", 0),
// ...
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key15", KEY_VALUE, "value15", 0), 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", 0),
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key2", KEY_VALUE, "value2", 0),
keyNew ("user/sw/org/app/#0/current/fixedConfiguration/key3", KEY_VALUE, "value3", 0),
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

See also
  ksDel() to free the KeySet afterwards
  ksDup() to duplicate an existing KeySet
  ksAppendKey() to append individual keys

Parameters

  alloc | gives a hint for the size how many Keys may be stored initially

Returns
  a ready to use KeySet object

Return values

  0 | on memory error

Precondition
  caller must call va_start and va_end

va the list of arguments

Parameters

  alloc | the allocation size
  va | the list of variable arguments

## ◆ ~KeySet()

kdb::KeySet::~KeySet | ( |  | ) |
| inline

Deconstruct a keyset.

A destructor for KeySet objects. Cleans all internal dynamic attributes, decrement all reference pointers to all keys and then keyDel() all contained Keys, and elektraFree ()s the release the KeySet object memory (that was previously allocated by ksNew()).

Parameters

  ks | the keyset object to work with

Return values

  0 | when the keyset was freed
  -1 | on null pointer

See also
  ksNew()

## Member Function Documentation

## ◆ append() [1/2]

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

append a key

Parameters

  toAppend | key to append

Returns
  number of keys in the keyset

Appends a Key to the end of `ks`. Will take ownership of the key `toAppend`. That means ksDel(ks) will remove the key unless the key:

- was duplicated before inserting
- got its refcount incremented by keyIncRef() before inserting
- was also inserted into another keyset with ksAppendKey()

The reference counter of the key will be incremented to show this ownership, and thus `toAppend` is not const.

Note
  Because the key is not copied, also the pointer to the current metadata keyNextMeta() will be shared.

See also
  keyGetRef().

If the keyname already existed in the keyset, it will be replaced with the new key.

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

It is save 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);
keyIncRef (k);
ksAppendKey (ks, k);
ksDel (ks);
// now we still can work with the key k!
keyDecRef (k);
keyDel (k);

Or if you want to avoid aliasing at all, you can duplicate the key. But then 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));
ksDel (ks);
// now we still can work with the key k!
keyDel (k);

Returns
  the size of the KeySet after insertion

Return values

  -1 | on NULL pointers
  -1 | if insertion failed, the key will be deleted then.

Parameters

  ks | KeySet that will receive the key
  toAppend | Key that will be appended to ks or deleted

See also
  ksAppend(), keyNew(), ksDel()
  keyIncRef()

## ◆ append() [2/2]

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

append a keyset

Parameters

  toAppend | keyset to append

Returns
  number of keys in the keyset

Append all `toAppend` contained keys to the end of the `ks`. `toAppend` KeySet will be left unchanged.

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

Note
  Because the key is not copied, also the pointer to the current metadata keyNextMeta() will be shared.

Postcondition
  Sorted KeySet ks with all keys it had before and additionally the keys from toAppend

Returns
  the size of the KeySet after transfer

Return values

  -1 | on NULL pointers

Parameters

  ks | the KeySet that will receive the keys
  toAppend | the KeySet that provides the keys that will be transferred

See also
  ksAppendKey()

## ◆ at()

Key kdb::KeySet::at | ( | cursor_t | pos | ) | const
| inline

Lookup a key by index.

Parameters

  pos | cursor position

Returns
  the found key

## ◆ clear()

void kdb::KeySet::clear | ( |  | ) |
| inline

Clear the keyset.

Keyset will have no keys afterwards.

## ◆ copy()

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

Copy a keyset.

Parameters

  other | other keyset to copy

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

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(). But in some situations you need to copy a keyset to a existing keyset, for that 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 the source will be added to the destination and the ksCurrent() is set properly in `dest`.

A flat copy is made, so the keys will not be duplicated, but there reference counter is updated, so both keysets need to be ksDel().

Note
  Because the key is not copied, also the pointer to the current metadata keyNextMeta() will be shared.

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)

Parameters

  source | has to be an initialized source KeySet or NULL
  dest | has to be an initialized KeySet where to write the keys

Return values

  1 | on success
  0 | if dest was cleared successfully (source is NULL)
  -1 | on NULL pointer

See also
  ksNew(), ksDel(), ksDup()
  keyCopy() for copying keys

## ◆ current()

Key kdb::KeySet::current | ( |  | ) | const
| inline

Return the current Key.

The pointer is NULL if you reached the end or after ksRewind().

Note
  You must not delete the key or change the key, use ksPop() if you want to delete it.

Parameters

  ks | the keyset object to work with

Returns
  pointer to the Key pointed by `ks's` cursor

Return values

  0 | on NULL pointer

See also
  ksNext(), ksRewind()

## ◆ cut()

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

Cuts out a keyset at the cutpoint.

Searches for the cutpoint inside the KeySet ks. If found it cuts out 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 make a 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 (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 below `system/mountpoint/interest`.

See also
  kdbGet() for explanation why you might get more keys than you requested.

Returns
  a new allocated KeySet which needs to 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

  0 | on null pointers, no key name or allocation problems

Parameters

  ks | the keyset to cut. It will be modified by removing all keys below the cutpoint. The cutpoint itself will also be removed.
  cutpoint | the point where to cut out the keyset

## ◆ dup()

ckdb::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 there reference counter is updated, so both keysets need ksDel().

Parameters

  source | has to be an initialized source KeySet

Returns
  a flat copy of source on success

Return values

  0 | on NULL pointer

See also
  ksNew(), ksDel()
  keyDup() for Key duplication

## ◆ get()

template<typename T >

T kdb::KeySet::get | ( | std::string const & | name,
|  | const option_t | options = `KDB_O_NONE`
| ) |  | const
| inline

Generic lookup+get for keysets.

Parameters

  name | the key name to get
  options | the options to be passed to lookup()

Exceptions

  KeyNotFoundException | if no key found

Note
  To specialize more complex types (which are generic themselves) you can also specialize KeySetTypeWrapper<T>.

Use

#include <keysetget.hpp>

to include specializations for std types.

Returns
  the requested type

## ◆ getCursor()

cursor_t kdb::KeySet::getCursor | ( |  | ) | const
| inline

Get the KeySet internal cursor.

Use it to get the cursor of the actual position.

Warning
  Cursors are getting invalid when the key was ksPop()ed or ksLookup() with KDB_O_POP was used.

# Read ahead

With the cursors it is possible to read ahead in a keyset:

cursor_t jump;
ksRewind (ks);
while ((key = keyNextMeta (ks))!=0)
{
// now mark this key
jump = ksGetCursor(ks);
//code..
keyNextMeta (ks); // now browse on
// use ksCurrent(ks) to check the keys
//code..
// jump back to the position marked before
ksSetCursor(ks, jump);
}

# Restoring state

It can also be used to restore the state of a keyset in a function

int f (KeySet *ks)
{
cursor_t state = ksGetCursor(ks);
// work with keyset
// now bring the keyset to the state before
ksSetCursor (ks, state);
}

It is of course possible to make the KeySet const and cast its const away to set the cursor. Another way to achieve the same is to ksDup() the keyset, but it is not as efficient.

An invalid cursor will be returned directly after ksRewind(). When you set an invalid cursor ksCurrent() is 0 and ksNext() == ksHead().

Note
  Only use a cursor for the same keyset which it was made for.

Parameters

  ks | the keyset object to work with

Returns
  a valid cursor on success
  an invalid cursor on NULL pointer or after ksRewind()

See also
  ksNext(), ksSetCursor()

## ◆ getKeySet()

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

Passes out the raw keyset pointer.

Returns
  pointer to internal ckdb KeySet

See also
  release()
  setKeySet()

## ◆ head()

Key kdb::KeySet::head | ( |  | ) | const
| inline

Return the first key in the KeySet.

Returns
  alphabetical first key

The KeySets cursor will not be affected.

If ksCurrent()==ksHead() you know you are on the first key.

Parameters

  ks | the keyset object to work with

Returns
  the first Key of a keyset

Return values

  0 | on NULL pointer or empty keyset

See also
  ksTail() for the last Key
  ksRewind(), ksCurrent() and ksNext() for iterating over the KeySet

## ◆ lookup() [1/2]

Key kdb::KeySet::lookup | ( | const Key & | key,
|  | const option_t | 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 can you load the whole configuration you can write very effective but short code for configuration:

Key * key = keyNew ("/sw/tests/myapp/#0/current/", KEY_END);
KDB * handle = kdbOpen (key);
kdbGet (handle, myConfig, key);
Key * result = ksLookupByName (myConfig, "/sw/tests/myapp/#0/current/testkey1", 0);

This is the way programs should get their configuration and search after 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, `ks` internal cursor will be positioned in the matched key (also accessible by ksCurrent()), and a pointer to the Key is returned. If not found, `ks` internal cursor will not move, and 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. ksCurrent() will not be changed, only iff ksCurrent() is the searched key, then the keyset will be ksRewind()ed.

Note
  Like in ksPop() the popped key always needs to be keyDel() afterwards, even if it is appended to another keyset.

Warning
  All cursors on the keyset will be invalid iff you use KDB_O_POP, so don't use this if you rely on a cursor, see ksGetCursor().

The invalidation of cursors does not matter if you use multiple keysets, e.g. by using ksDup(). E.g., to separate ksLookup() with KDB_O_POP and ksAppendKey():

void f (KeySet * iterator, KeySet * lookup)
{
KeySet * append = ksNew (ksGetSize (lookup), KS_END);
Key * current;
ksRewind (iterator);
while ((current = ksNext (iterator)))
{
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.
}
ksAppend (lookup, append);
// now lookup needs to be sorted only once, append never
ksDel (append);
}

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().

KDB_O_NOALL (deprecated)
  When KDB_O_NOALL is set the keyset will be only searched from ksCurrent() to ksTail(). You need to ksRewind() the keyset yourself. ksCurrent() is always set properly after searching a key, so you can go on searching another key after the found key.
  When KDB_O_NOALL is not set the cursor will stay untouched and all keys are considered. A much more efficient binary search will be used then.

KDB_O_WITHOWNER (deprecated)
  Also consider correct owner (needs KDB_O_NOALL).

KDB_O_NOCASE (deprecated)
  Lookup ignoring case (needs KDB_O_NOALL).

Parameters

  ks | where to look for
  key | the key object you are looking for
  options | of type option_t with some `KDB_O_*` option bits as explained above

Returns
  pointer to the Key found, 0 otherwise

Return values

  0 | on NULL pointers

See also
  ksLookupByName() to search by a name given by a string
  ksCurrent(), ksRewind(), ksNext() 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 option_t | options = `KDB_O_NONE`
| ) |  | const
| inline

Lookup a key by name.

Parameters

  name | the name to look for
  options | some options to pass

Returns
  the found key

See also
  lookup (const Key &Key, const option_t options)

Note
  That the internal key cursor will point to the found key

## ◆ next()

Key kdb::KeySet::next | ( |  | ) | const
| inline

Returns the next Key in a KeySet.

KeySets have an internal cursor that can be reset with ksRewind(). Every time ksNext() is called the cursor is incremented and the new current Key is returned.

You'll get a NULL pointer if the key after the end of the KeySet was reached. On subsequent calls of ksNext() it will still return the NULL pointer.

The `ks` internal cursor will be changed, so it is not const.

Note
  You must not delete or change the key, use ksPop() if you want to delete it.
  That applications must do ksLookup() with an cascading key for every single key before using it, because specifications allow to hide or override keys.

Parameters

  ks | the keyset object to work with

Returns
  the new current Key

Return values

  0 | when the end is reached
  0 | on NULL pointer

See also
  ksRewind(), ksCurrent()
  ksLookup() to honor specifications

## ◆ 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 will be decremented by one.

The KeySets 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);

Returns
  the last key of `ks`

Return values

  NULL | if `ks` is empty or on NULL pointer

Parameters

  ks | KeySet to work with

See also
  ksLookup() to pop keys by name
  ksCopy() to pop all keys
  commandList() for an example

## ◆ rewind()

void kdb::KeySet::rewind | ( |  | ) | const
| inline

Rewinds the KeySet internal cursor.

Use it to set the cursor to the beginning of the KeySet. ksCurrent() will then always return NULL afterwards. So you want to ksNext() first.

ksRewind (ks);
while ((key = ksNext (ks))!=0) {}

Parameters

  ks | the keyset object to work with

Return values

  0 | on success
  -1 | on NULL pointer

See also
  ksNext(), ksCurrent()

## ◆ setCursor()

void kdb::KeySet::setCursor | ( | cursor_t | cursor | ) | const
| inline

Set the KeySet internal cursor.

Use it to set the cursor to a stored position. ksCurrent() will then be the position which you got with.

Warning
  Cursors may get invalid when the key was ksPop()ed or ksLookup() was used together with KDB_O_POP.

cursor_t cursor;
..
// key now in any position here
cursor = ksGetCursor (ks);
while ((key = keyNextMeta (ks))!=0) {}
ksSetCursor (ks, cursor); // reset state
ksCurrent(ks); // in same position as before

An invalid cursor will set the keyset to its beginning like ksRewind(). When you set an invalid cursor ksCurrent() is 0 and ksNext() == ksHead().

Parameters

  cursor | the cursor to use
  ks | the keyset object to work with

Return values

  0 | when the keyset is ksRewind()ed
  1 | otherwise
  -1 | on NULL pointer

See also
  ksNext(), ksGetCursor()

## ◆ setKeySet()

void kdb::KeySet::setKeySet | ( | ckdb::KeySet * | k | ) |
| inline

Take ownership of passed keyset.

Parameters

  k | the keyset to take ownership from

See also
  release()
  getKeySet()

## ◆ size()

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

The size of the keyset.

Returns
  the number of keys in the keyset

## ◆ tail()

Key kdb::KeySet::tail | ( |  | ) | const
| inline

Return the last key in the KeySet.

Returns
  alphabetical last key

The KeySets cursor will not be affected.

If ksCurrent()==ksTail() you know you are on the last key. ksNext() will return a NULL pointer afterwards.

Parameters

  ks | the keyset object to work with

Returns
  the last Key of a keyset

Return values

  0 | on NULL pointer or empty keyset

See also
  ksHead() for the first Key
  ksRewind(), ksCurrent() and ksNext() for iterating over the KeySet

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

- keyset.hpp