Provided by: elektra-doc_0.7.1-1_all bug

NAME

       KeySet :: Class Methods -

       Methods to manipulate KeySets.

   Functions
       KeySet * ksNew (size_t alloc,...)
       KeySet * ksDup (const KeySet *source)
       int ksCopy (KeySet *dest, const KeySet *source)
       int ksDel (KeySet *ks)
       void ksSort (KeySet *ks)
       ssize_t ksGetSize (const KeySet *ks)
       ssize_t ksAppendKey (KeySet *ks, Key *toAppend)
       ssize_t ksAppend (KeySet *ks, const KeySet *toAppend)
       Key * ksPop (KeySet *ks)
       int ksRewind (KeySet *ks)
       Key * ksNext (KeySet *ks)
       Key * ksCurrent (const KeySet *ks)
       Key * ksHead (const KeySet *ks)
       Key * ksTail (const KeySet *ks)
       cursor_t ksGetCursor (const KeySet *ks)
       int ksSetCursor (KeySet *ks, cursor_t cursor)
       Key * ksLookup (KeySet *ks, Key *key, option_t options)
       Key * ksLookupByName (KeySet *ks, const char *name, option_t options)

Detailed Description

       Methods to manipulate KeySets.

       A KeySet is a unsorted set of keys.

       Terminate with ksNew(0) or ksNew(20, ..., KS_END) This is because there is a list of Key* required and
       KS_END has the length of (Key*).

       It can be implemented in various ways like a linked list or with a dynamically allocated array.

       With ksNew() you can create a new KeySet.

       You can add keys with ksAppendKey() in the keyset. ksGetSize() tells you the current size of the keyset.

       With ksRewind() and ksNext() you can navigate through the keyset. Don't expect any particular order, but
       it is assured that you will get every key of the set.

       KeySets have an internal cursor . This is used for ksLookup() and kdbSet().

       KeySet has a fundamental meaning inside 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. 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.0, keyName (current));
       }
       ksDel (myConfig); // delete keyset and all keys appended

Function Documentation

   ssize_t ksAppend (KeySet *ks, const KeySet *toAppend) Append all toAppend contained keys to the end of the
       ks.
       toAppend KeySet will be left unchanged.

       Makes the keyset dirty, see ksSort().

       Returns:
           the size of the KeySet after transfer

           -1 on NULL pointers

       Parameters:
           ks the KeySet that will receive the keys
           toAppend the KeySet that provides the keys that will be transfered

       See also:
           ksAppendKey(), ksInsert(), ksInsertKeys()

   ssize_t ksAppendKey (KeySet *ks, Key *toAppend) Appends a Key to the end of ks.
       A pointer to the key will be stored, and not a private copy. So a future ksDel() on ks may keyDel() the
       toAppend object, see keyGetRef().

       The reference counter of the key will be incremented, and thus toAppend is not const.

       The KeySet internal cursor is not moved.

       Makes the keyset dirty, see ksSort().

       Returns:
           the size of the KeySet after insertion

           -1 on NULL pointers

       Parameters:
           ks KeySet that will receive the key
           toAppend Key that will be appended to ks

       See also:
           ksInsert(), ksInsertKeys(), ksAppend(), keyNew(), ksDel()

           keyIncRef()

   int ksCopy (KeySet *dest, const KeySet *source) 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)

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

       Returns:
           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

   Key* ksCurrent (const KeySet *ks) 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

           0 on NULL pointer

       See also:
           ksNext(), ksRewind()

           kdbMonitorKeys() for a usage example

   int ksDel (KeySet *ks) 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()).

       Parameters:
           ks the keyset object to work with

       Returns:
           0 when the keyset was freed

           -1 on null pointer

       See also:
           ksNew()

   KeySet* ksDup (const KeySet *source) 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 initializised source KeySet

       Returns:
           a flat copy of source on success

           0 on NULL pointer

       See also:
           ksNew(), ksDel()

           keyDup() for Key :: Basic Methods duplication

   cursor_t ksGetCursor (const KeySet *ks) 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 = keyNext (ks))!=0)
       {
               // now mark this key
               jump = ksGetCursor(ks);

               //code..
               keyNext (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()

   ssize_t ksGetSize (const KeySet *ks) Return the number of keys that ks contains.
       Parameters:
           ks the keyset object to work with

       Returns:
           the number of keys that ks contains.

           -1 on NULL pointer

       See also:
           ksNew(0), ksDel()

   Key* ksHead (const KeySet *ks) 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.

       Parameters:
           ks the keyset object to work with

       Returns:
           the first Key of a keyset

           0 on NULL pointer or empty keyset

       See also:
           ksTail() for the last Key :: Basic Methods

           ksRewind(), ksCurrent() and ksNext() for iterating over the KeySet :: Class Methods

   Key* ksLookup (KeySet *ks, Key *key, option_toptions) Look for a Key contained in ks that matches the name of
       the key.

Introduction

       ksLookup() is designed to let you work with entirely pre-loaded KeySets, so instead of kdbGetKey(), key
       by key, the idea is to fully kdbGet() for your application root key and process it all at once with
       ksLookup().

       This function is very efficient by using binary search. Together with kdbGet() which can you load the
       whole configuration with only some communication to backends you can write very effective but short code
       for configuration.

Usage

       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 is done if the first character is a /. This leads to ignoring the prefix like system/ and
       user/.

               if (kdbGet(handle, 'user/myapp', myConfig, 0 ) == -1)
                       ErrorHandler ('Could not get Keys');

               if (kdbGet(handle, 'system/myapp', myConfig, 0 ) == -1)
                       ErrorHandler ('Could not get Keys');

               if ((myKey = ksLookup(myConfig, key, 0)) == NULL)
                       ErrorHandler ('Could not Lookup Key');

       This is the way multi user Programs should get there 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.

   KDB_O_NOALL
       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.

       So if you change keys, e.g. rename (keySetName()) or remove (keyRemove()) them make sure to sort the
       keyset with ksSort(). When the keyset is dirty, see ksNeedSort() it will be sorted automatically when
       needed.

   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:
           Note that keyRemove() keys won't be found after the first time the keyset is resorted. Lookup
           automatically sorts the keyset, if needed, but it can't find it out when only keys are changed, not
           the keyset.

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

       Note:
           Never use ksLookup() with KDB_O_POP and ksAppendKey() or ksAppend() together in a loop. Otherwise
           ksLookup() will need to resort the keyset every iteration and spend 99.96% of the time in ksSort()
           (benchmarked with above 500k iterations).

       You can solve this problem by using KDB_O_NOALL, risking you have to iterate n^2 instead of n.

       The more elegant way is to separate the keyset you use for ksLookup() and ksAppendKey():

       int f(KeySet *iterator, KeySet *lookup)
       {
               KeySet *append = ksNew (ksGetSize(lookup), KS_END);
               Key *key;
               Key *current;

               ksRewind(iterator);
               while (current=ksNext(iterator))
               {
                       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);
       }

       Parameters:
           ks where to look for
           key the key object you are looking for
           options some KDB_O_* option bits:

           • KDB_O_NOCASE
              Lookup ignoring case.

           • KDB_O_WITHOWNER
              Also consider correct owner.

           • KDB_O_NOALL
              Only search from ksCurrent() to end of keyset, see above text.

           • KDB_O_POP
              Pop the key which was found.

           • KDB_O_SORT
              Force sorting before searching, see ksSort(). Together with KDB_O_NOALL the search will start from
             beginning.

       Returns:
           pointer to the Key found, 0 otherwise

           0 on NULL pointers

       See also:
           ksLookupByName() to search by a name given by a string

           ksCurrent(), ksRewind(), ksNext() for iterating over a KeySet :: Class Methods

           ksSort() to understand how KeySet :: Class Methods sort themself

   Key*  ksLookupByName  (KeySet  *ks,  const  char  *name, option_toptions) Look for a Key contained in ks that
       matches name.
       ksLookupByName() is designed to let you work with entirely pre-loaded KeySets, so instead of kdbGetKey(),
       key by key, the idea is to fully kdbGetByName() for your application root key and process it all at  once
       with ksLookupByName().

       This  function  is very efficient by using binary search. Together with kdbGetByName() which can you load
       the whole configuration with only some communication to backends you can write very effective  but  short
       code for configuration.

       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

       Cascading  is  done  if  the  first  character is a /. This leads to ignoring the prefix like system/ and
       user/.

               if (kdbGetByName(handle, '/sw/myapp/current', myConfig, 0 ) == -1)
                       ErrorHandler ('Could not get Keys');

               if ((myKey = ksLookupByName (myConfig, '/myapp/current/key', 0)) == NULL)
                       ErrorHandler ('Could not Lookup Key');

       This is the way multi user Programs should get there 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.

Full Search

       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.

       Parameters:
           ks where to look for
           name key name you are looking for
           options some KDB_O_* option bits:

           • KDB_O_NOCASE
              Lookup ignoring case.

           • KDB_O_WITHOWNER
              Also consider correct owner.

           • KDB_O_NOALL
              Only search from ksCurrent() to end of keyset, see above text.

           • KDB_O_POP
              Pop the key which was found.

           • KDB_O_SORT
              Force sorting before searching, see ksSort(). Together with KDB_O_NOALL the search will start from
             beginning.

       Currently no options supported.

       Returns:
           pointer to the Key found, 0 otherwise

           0 on NULL pointers

       See also:
           keyCompare() for very powerful Key lookups in KeySets

           ksCurrent(), ksRewind(), ksNext()

   KeySet* ksNew (size_talloc, ...) 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.

       For most uses

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

        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 14 keys), use:

       KeySet * keys = ksNew (15, 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.

       Due to ABI compatibility, the KeySet structure is only declared in kdb.h, and not  defined.  So  you  can
       only declare pointers to KeySets in your program. See http://tldp.org/HOWTO/Program-Library-HOWTO/shared-
       libraries.html#AEN135

       See also:
           ksDel() to free the KeySet :: Class Methods afterwards

           ksDup() to duplicate an existing KeySet :: Class Methods

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

       Returns:
           a ready to use KeySet object

           0 on memory error

   Key* ksNext (KeySet *ks) 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. It will set the  cursor  to
       the beginning of the KeySet and the next time the first key is returned.

       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.

       Parameters:
           ks the keyset object to work with

       Returns:
           the new current Key

           0 when the end is reached

           0 on NULL pointer

       See also:
           ksRewind(), ksCurrent()

   Key* ksPop (KeySet *ks) 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.

       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);
       ks2=ksNew(0);

       k1=keyNew(0); // 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

           NULL if ks is empty or on NULL pointer

       Parameters:
           ks KeySet to work with

       See also:
           ksAppendKey(), ksAppend()

           commandList() for an example

   int ksRewind (KeySet *ks) 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 = keyNext (ks))!=0) {}

       Parameters:
           ks the keyset object to work with

       Returns:
           0 on success

           -1 on NULL pointer

       See also:
           ksNext(), ksCurrent()

   int ksSetCursor (KeySet *ks, cursor_tcursor) 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 = keyNext (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

       Returns:
           0 when the keyset is ksRewind()ed

           1 otherwise

           -1 on NULL pointer

       See also:
           ksNext(), ksGetCursor()

   void ksSort (KeySet *ks) Sorts a KeySet alphabetically by Key name.
       You need ksSort() only in few cases directly.

Don't need to sort before using ksLookup

       You don't need it if you just just kdbGet() and subsequent ksLookup().

       KeySet *ks = ksNew(0);
       kdbGet(h, ks, k, 0);
       // ksPop(), ksAppend() and ksAppendKey() allowed here
       ksLookup(ks, s, 0); // you don't need to sort ks

       This is because the KeySet tracks if it needs to be sorted and ksLookup() will sort when needed.

Sort when iterating

       Before you iterate over a keyset you have to sort it, if you need it in a sorted way.

       To achieve that you can pass option_t::KDB_O_SORT to kdbGet() and  kdbSet().  Then  you  will  receive  a
       already sorted keyset over which you can iterate.

       KeySet *ks = ksNew(0);
       kdbGet(h, ks, k, KDB_O_SORT);
       // no changes to keyset allowed
       ksRewind(ks);
       // now you can iterate over a sorted keyset

       Its of course also possible to use ksLookup() once, because it will sort the keyset too.

Sort when changing key

       Warning:
           You  should  not  use  keySetName() or keyRemove() when a key belongs to a keyset. When you are doing
           this, you always need to manually sort  all  keysets  where  the  key  was  before  using  ksLookup()
           (otherwise ksLookup() won't find that keys), kdbGet() or kdbSet() methods.

       When you change a key's name or its remove status the order which was previously correctly is then wrong.
       The keyset does not recognize this, so the programmer has to take care that ksSort() is called before any
       operation  which  needs  a  sorted  keyset  (which  are  all  ksLookup(),  all  kdbGet() and all kdbSet()
       functions).

       Note:
           You can remember that easily that all functions which get options require one of the following:

           • that you did not manipulate a keys name or a remove status

           • that you pass KDB_O_SORT when you know that you manipulated at least one key

           • that you ksSort() yourself after manipulating keys

Dirty KeySet

       When you use ksAppend(), ksAppendKey(), ksPop() the keyset is dirty afterwards, which means that it needs
       to be sorted. This is done automatically using a ksLookup() method and in ksGet() or ksSet() (All methods
       which accept options).

       It won't be done if you just iterate over the keyset, so you might use a ksLookup()  or  ksSort()  first.
       ksLookup()  will  be  more  efficient  in  that  case,  because it will only sort when needed. Don't pass
       KDB_O_NOALL (it will deactivate the sorting feature), see ksLookup() for more information.

       Parameters:
           ks KeySet to be sorted

       See also:
           kdbGet(), kdbSet(), ksLookup() for some functions which may need sorting before they are called. (All
           functions which take options as arguments)

           keySetName(), keySetBaseName(), keyAddBaseName() and keyRemove() for all  methods  which  change  the
           sorting state where the KeySet :: Class Methods can't track the change.

           ksAppend(), ksAppendKey(), ksPop() for all methods which make a KeySet :: Class Methods dirty.

   Key* ksTail (const KeySet *ks) 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.

       Parameters:
           ks the keyset object to work with

       Returns:
           the last Key of a keyset

           0 on NULL pointer or empty keyset

       See also:
           ksHead() for the first Key :: Basic Methods

           ksRewind(), ksCurrent() and ksNext() for iterating over the KeySet :: Class Methods

Author

       Generated automatically by Doxygen for Elektra Projekt from the source code.

Elektra Projekt                                  Tue Sep 13 2011                      KeySet :: Class Methods(3)