Elektra
0.8.12
|
A keyset holds together a set of keys. More...
#include <keyset.hpp>
Public Member Functions | |
KeySet () | |
Creates a new empty keyset with no keys. | |
KeySet (ckdb::KeySet *k) | |
Takes ownership of keyset! | |
KeySet (const KeySet &other) | |
Duplicate a keyset. | |
KeySet (size_t alloc,...) | |
Create a new keyset. | |
KeySet (Va va, size_t alloc, va_list ap) | |
Create a new keyset. | |
~KeySet () | |
Deconstruct a keyset. | |
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. | |
void | setKeySet (ckdb::KeySet *k) |
Take ownership of passed keyset. | |
KeySet & | operator= (KeySet const &other) |
Duplicate a keyset. | |
ssize_t | size () const |
The size of the keyset. | |
ckdb::KeySet * | dup () const |
Duplicate a keyset. | |
void | copy (const KeySet &other) |
Copy a keyset. | |
void | clear () |
Clear the keyset. | |
ssize_t | append (const Key &toAppend) |
append a key | |
ssize_t | append (const KeySet &toAppend) |
append a keyset | |
Key | head () const |
Key | tail () const |
void | rewind () const |
Key | next () const |
Key | current () const |
void | setCursor (cursor_t cursor) const |
cursor_t | getCursor () const |
Key | pop () |
KeySet | cut (Key k) |
Key | lookup (const Key &k, const option_t options=KDB_O_NONE) const |
Key | lookup (std::string const &name, const option_t options=KDB_O_NONE) const |
Lookup a key by name. | |
Key | at (cursor_t pos) const |
Lookup a key by index. |
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:
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).
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:
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:
#include <kdb.h> // 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
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 various 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)
For most uses
goes ok, 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 out 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 normally need about 12 up to 15 keys), use:
KeySet * keys = ksNew (15, keyNew ("user/sw/app/fixedConfiguration/key01", KEY_SWITCH_VALUE, "value01", 0), keyNew ("user/sw/app/fixedConfiguration/key02", KEY_SWITCH_VALUE, "value02", 0), keyNew ("user/sw/app/fixedConfiguration/key03", KEY_SWITCH_VALUE, "value03", 0), // ... keyNew ("user/sw/app/fixedConfiguration/key15", KEY_SWITCH_VALUE, "value15", 0), KS_END); // work with it ksDel (keys);
If you start having 3 keys, and your application needs approximately 200-500 keys, you can use:
KeySet * config = ksNew (500, keyNew ("user/sw/app/fixedConfiguration/key1", KEY_SWITCH_VALUE, "value1", 0), keyNew ("user/sw/app/fixedConfiguration/key2", KEY_SWITCH_VALUE, "value2", 0), keyNew ("user/sw/app/fixedConfiguration/key3", KEY_SWITCH_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.
alloc | gives a hint for the size how many Keys may be stored initially |
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.
k | the keyset to take the ownership from |
kdb::KeySet::KeySet | ( | const KeySet & | other | ) | [inline] |
Duplicate a keyset.
This keyset will be a duplicate of the other afterwards.
So it is shallow copy, to create a deep copy you have to dup() every key (it still won't copy meta data, 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; }
kdb::KeySet::KeySet | ( | size_t | alloc, |
... | |||
) | [inline, explicit] |
Create a new keyset.
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 various 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)
For most uses
goes ok, 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 out 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 normally need about 12 up to 15 keys), use:
KeySet * keys = ksNew (15, keyNew ("user/sw/app/fixedConfiguration/key01", KEY_SWITCH_VALUE, "value01", 0), keyNew ("user/sw/app/fixedConfiguration/key02", KEY_SWITCH_VALUE, "value02", 0), keyNew ("user/sw/app/fixedConfiguration/key03", KEY_SWITCH_VALUE, "value03", 0), // ... keyNew ("user/sw/app/fixedConfiguration/key15", KEY_SWITCH_VALUE, "value15", 0), KS_END); // work with it ksDel (keys);
If you start having 3 keys, and your application needs approximately 200-500 keys, you can use:
KeySet * config = ksNew (500, keyNew ("user/sw/app/fixedConfiguration/key1", KEY_SWITCH_VALUE, "value1", 0), keyNew ("user/sw/app/fixedConfiguration/key2", KEY_SWITCH_VALUE, "value2", 0), keyNew ("user/sw/app/fixedConfiguration/key3", KEY_SWITCH_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.
alloc | gives a hint for the size how many Keys may be stored initially |
alloc | the allocation size |
va | the list of variable arguments |
kdb::KeySet::KeySet | ( | Va | va, |
size_t | alloc, | ||
va_list | av | ||
) | [inline, explicit] |
Create a new keyset.
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 various 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)
For most uses
goes ok, 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 out 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 normally need about 12 up to 15 keys), use:
KeySet * keys = ksNew (15, keyNew ("user/sw/app/fixedConfiguration/key01", KEY_SWITCH_VALUE, "value01", 0), keyNew ("user/sw/app/fixedConfiguration/key02", KEY_SWITCH_VALUE, "value02", 0), keyNew ("user/sw/app/fixedConfiguration/key03", KEY_SWITCH_VALUE, "value03", 0), // ... keyNew ("user/sw/app/fixedConfiguration/key15", KEY_SWITCH_VALUE, "value15", 0), KS_END); // work with it ksDel (keys);
If you start having 3 keys, and your application needs approximately 200-500 keys, you can use:
KeySet * config = ksNew (500, keyNew ("user/sw/app/fixedConfiguration/key1", KEY_SWITCH_VALUE, "value1", 0), keyNew ("user/sw/app/fixedConfiguration/key2", KEY_SWITCH_VALUE, "value2", 0), keyNew ("user/sw/app/fixedConfiguration/key3", KEY_SWITCH_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.
alloc | gives a hint for the size how many Keys may be stored initially |
alloc | the allocation size |
va | the list of variable arguments |
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 free()s the release the KeySet object memory (that was previously allocated by ksNew()).
ks | the keyset object to work with |
ssize_t kdb::KeySet::append | ( | const Key & | toAppend | ) | [inline] |
append a key
toAppend | key to append |
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:
The reference counter of the key will be incremented to show this ownership, and thus toAppend
is not const.
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);
ssize_t kdb::KeySet::append | ( | const KeySet & | toAppend | ) | [inline] |
append a keyset
toAppend | keyset to append |
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.
ks | the KeySet that will receive the keys |
toAppend | the KeySet that provides the keys that will be transferred |
Key kdb::KeySet::at | ( | cursor_t | pos | ) | const [inline] |
Lookup a key by index.
pos | cursor position |
void kdb::KeySet::clear | ( | ) | [inline] |
Clear the keyset.
Keyset will have no keys afterwards.
void kdb::KeySet::copy | ( | const KeySet & | other | ) | [inline] |
Copy a keyset.
other | other keyset to copy |
This is only a shallow copy. For a deep copy you need to dup every key.
Copy a keyset.
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.
You can also use it to clear a keyset when you pass a NULL pointer as source
.
Note that 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().
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)
source | has to be an initialized source KeySet or NULL |
dest | has to be an initialized KeySet where to write the keys |
Key kdb::KeySet::current | ( | ) | const [inline] |
Return the current Key.
The pointer is NULL if you reached the end or after ksRewind().
ks | the keyset object to work with |
ks's
cursor 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
.
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
.
0 | on null pointers, no key name or allocation problems |
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 |
ckdb::KeySet * kdb::KeySet::dup | ( | ) | const [inline] |
Duplicate a keyset.
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().
source | has to be an initialized source KeySet |
cursor_t kdb::KeySet::getCursor | ( | ) | const [inline] |
Get the KeySet internal cursor.
Use it to get the cursor of the actual position.
ckdb::KeySet * kdb::KeySet::getKeySet | ( | ) | const [inline] |
Passes out the raw keyset pointer.
Key kdb::KeySet::head | ( | ) | const [inline] |
Return the first key in the KeySet.
The KeySets cursor will not be effected.
If ksCurrent()==ksHead() you know you are on the first key.
ks | the keyset object to work with |
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
.
Key kdb::KeySet::lookup | ( | std::string const & | name, |
const option_t | options = KDB_O_NONE |
||
) | const [inline] |
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.
ks | the keyset object to work with |
Duplicate a keyset.
This keyset will be a duplicate of the other afterwards.
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 effected if it did not point to the popped key.
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); *
ks
ks
is empty or on NULL pointer ks | KeySet to work with |
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.
ks | the keyset object to work with |
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.
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().
cursor | the cursor to use |
ks | the keyset object to work with |
void kdb::KeySet::setKeySet | ( | ckdb::KeySet * | k | ) | [inline] |
Take ownership of passed keyset.
k | the keyset to take ownership from |
ssize_t kdb::KeySet::size | ( | ) | const [inline] |
The size of the keyset.
Key kdb::KeySet::tail | ( | ) | const [inline] |
Return the last key in the KeySet.
The KeySets cursor will not be effected.
If ksCurrent()==ksTail() you know you are on the last key. ksNext() will return a NULL pointer afterwards.
ks | the keyset object to work with |