Elektra: Key

Elektra 0.8.24

Modules | Enumerations | Functions
Key

Key is an essential class that encapsulates key name , value and metainfo . More...

## Modules
| Meta Info Manipulation Methods
| Methods to do various operations on Key metadata.
| Methods for Making Tests
| Methods to do various tests on Keys.
| Name Manipulation Methods
| Methods to do various operations on Key names.
| Value Manipulation Methods
| Methods to do various operations on Key values.

## Enumerations
enum | keyswitch_t { KEY_NAME =1, KEY_VALUE =1<<1, KEY_FLAGS =3, KEY_OWNER =1<<2, KEY_COMMENT =1<<3, KEY_BINARY =1<<4, KEY_UID =1<<5, KEY_GID =1<<6, KEY_MODE =1<<7, KEY_ATIME =1<<8, KEY_MTIME =1<<9, KEY_CTIME =1<<10, KEY_SIZE =1<<11, KEY_DIR =1<<14, KEY_META =1<<15, KEY_NULL =1<<16, KEY_CASCADING_NAME =1<<20, KEY_META_NAME =1<<21, KEY_END =0 }
| Allows keyNew() to determine which information comes next. More...
enum | elektraNamespace { KEY_NS_NONE =0, KEY_NS_EMPTY =1, KEY_NS_META =2, KEY_NS_CASCADING =3, KEY_NS_FIRST =4, KEY_NS_SPEC =4, KEY_NS_PROC =5, KEY_NS_DIR =6, KEY_NS_USER =7, KEY_NS_SYSTEM =8, KEY_NS_LAST =8 }
| Elektra currently supported Key namespaces. More...

## Functions
Key * | keyNew (const char *name,...)
| A practical way to fully create a Key object in one step. More...
Key * | keyDup (const Key *source)
| Return a duplicate of a key. More...
int | keyCopy (Key *dest, const Key *source)
| Copy or Clear a key. More...
int | keyDel (Key *key)
| A destructor for Key objects. More...
int | keyClear (Key *key)
| Key Object Cleaner. More...
ssize_t | keyIncRef (Key *key)
| Increment the viability of a key object. More...
ssize_t | keyDecRef (Key *key)
| Decrement the viability of a key object. More...
ssize_t | keyGetRef (const Key *key)
| Return how many references the key has. More...

## Detailed Description

Key is an essential class that encapsulates key name , value and metainfo .

To use it include:

#include <kdb.h>

Key properties are:

- Key name
- Key value
- Key metadata , including but not limited to:
  - Key comment
  - Key owner
  - UID, GID and filesystem-like mode permissions
  - Mode, change and modification times

ABI
  Due to ABI compatibility, the `Key` structure is not defined in kdb.h, only declared. So you can only declare `pointers` to `Keys` in your program, and allocate and free memory for them with keyNew() and keyDel() respectively.

Reference Counting
  Every key has its reference counter (see keyGetRef() for longer explanation) that will be initialized with 0, that means a subsequent call of keyDel() will delete the key. If you append the key to a keyset the reference counter will be incremented by one (see keyIncRef()) and the key can't be deleted by a keyDel().

  As you can imagine this refcounting allows you to put the Key in your own data structures. It can be a very powerful feature, e.g. if you need your own-defined ordering or different Models of your configuration.

## Enumeration Type Documentation

## ◆ elektraNamespace

enum elektraNamespace

Elektra currently supported Key namespaces.

See also
  kdbGet(), keyGetNamespace()

Enumerator
KEY_NS_NONE | no key given as parameter to keyGetNamespace()
KEY_NS_EMPTY | key name was empty, e.g. invalid key name
KEY_NS_META | metakey, i.e. any key name not under other categories
KEY_NS_CASCADING | cascading key, starts with /, abstract name for any of the namespaces below
KEY_NS_FIRST | For iteration over namespaces (first element, inclusive)
KEY_NS_SPEC | spec contains the specification of the other namespaces
KEY_NS_PROC | proc contains process-specific configuration
KEY_NS_DIR | dir contains configuration from a specific directory
KEY_NS_USER | user key in the home directory of the current user
KEY_NS_SYSTEM | system key is shared for a computer system
KEY_NS_LAST | For iteration over namespaces (last element, inclusive)

## ◆ keyswitch_t

enum keyswitch_t

Allows keyNew() to determine which information comes next.

See also
  keyNew()

Enumerator
KEY_NAME | Flag for the key name
KEY_VALUE | Flag for the key data
KEY_FLAGS | Allows to define multiple flags at once.
KEY_OWNER | Flag for the key user domain
KEY_COMMENT | Flag for the key comment
KEY_BINARY | Flag if the key is binary
KEY_UID | Flag for the key UID Deprecated: do not use
KEY_GID | Flag for the key GID Deprecated: do not use
KEY_MODE | Flag for the key permissions Deprecated: do not use
KEY_ATIME | Flag for the key access time Deprecated: do not use
KEY_MTIME | Flag for the key change time Deprecated: do not use
KEY_CTIME | Flag for the key status change time Deprecated: do not use
KEY_SIZE | Flag for maximum size to limit value
KEY_DIR | Flag for the key directories Deprecated: do not use
KEY_META | Flag for metadata
KEY_NULL | Is not a flag, only as return value Deprecated: do not use
KEY_CASCADING_NAME | Is default, no need to use it Deprecated: do not use
KEY_META_NAME | Allow any key names (not only with known namespaces+cascading
KEY_END | Used as a parameter terminator to keyNew()

## Function Documentation

## ◆ keyClear()

int keyClear | ( | Key * | key | ) |

Key Object Cleaner.

Will reset all internal data.

After this call you will receive a fresh key.

The reference counter will stay unmodified.

Note
  that you might also clear() all aliases with this operation.

int f (Key *k)
{
keyClear (k);
// you have a fresh key k here
keySetString (k, "value");
// the caller will get an empty key k with an value
}

Return values

  returns | 0 on success
  -1 | on null pointer

Parameters

  key | the key object to work with

## ◆ keyCopy()

int keyCopy | ( | Key * | dest,
|  | const Key * | source
| ) |  |

Copy or Clear a key.

Most often you may prefer keyDup() which allocates a new key and returns a duplication of another key.

But when you need to copy into an existing key, e.g. because it was passed by a pointer in a function you can do so:

void h (Key * k)
{
// receive key c
keyCopy (k, c);
// the caller will see the changed key k
}

The reference counter will not be changed for both keys. Affiliation to keysets are also not affected.

The metadata will be duplicated for the destination key. So it will not take much additional space, even with lots of metadata.

When you pass a NULL-pointer as source the data of dest will be cleaned completely (except reference counter, see keyClear()) and you get a fresh dest key:

void g (Key * k)
{
keyCopy (k, 0);
// k is now an empty and fresh key
}

If you want to copy everything, except e.g. the value you can use keyCopy() too:

void j (Key * k)
{
size_t size = keyGetValueSize (k);
char * value = malloc (size);
int bstring = keyIsString (k);
// receive key c
memcpy (value, keyValue (k), size);
keyCopy (k, c);
if (bstring)
keySetString (k, value);
else
keySetBinary (k, value, size);
free (value);
// the caller will see the changed key k
// with the name and metadata from c (except
// metadata "binary", which stayed the same)
}

Restrain from coping everything yourself, because it will lead to wrong metadata and is not able to copy empty or cascading names:

void i (Key * k)
{
keySetName (k, keyName (c));
keySetString (k, keyString (c));
keyCopyAllMeta (k, c);
// k is not a copy of c even if everything was successfully,
// because it still contains metadata from k
}

Parameters

  dest | the key which will be written to
  source | the key which should be copied or NULL to clean the destination key

Return values

  -1 | on failure when a NULL pointer was passed for dest or a dynamic property could not be written. The content will be unmodified then.
  0 | when dest was cleaned
  1 | when source was successfully copied

See also
  keyDup() to get a duplication of a Key

## ◆ keyDecRef()

ssize_t keyDecRef | ( | Key * | key | ) |

Decrement the viability of a key object.

The references will be decremented for ksPop() or successful calls of ksLookup() with the option KDB_O_POP. It will also be decremented with an following keyDel() in the case that an old key is replaced with another key with the same name.

The reference counter can't be decremented once it reached 0. In that situation nothing will happen and 0 will be returned.

Note
  keyDup() will reset the references for dupped key.

Returns
  the value of the new reference counter

Return values

  -1 | on null pointer
  0 | when the key is ready to be freed

Parameters

  key | the key object to work with

See also
  keyGetRef() for longer explanation, keyDel(), keyIncRef()

## ◆ keyDel()

int keyDel | ( | Key * | key | ) |

A destructor for Key objects.

Every key created by keyNew() must be deleted with keyDel().

It is save to delete keys which are in a keyset, the number of references will be returned then.

It is save to delete a nullpointer, -1 will be returned then.

It is also save to delete a multiple referenced key, nothing will happen then and the reference counter will be returned.

Parameters

  key | the key object to delete

See also
  keyNew(), keyIncRef(), keyGetRef()

Returns
  the value of the reference counter if the key is within keyset(s)

Return values

  0 | when the key was freed
  -1 | on null pointers

## ◆ keyDup()

Key* keyDup | ( | const Key * | source | ) |

Return a duplicate of a key.

Memory will be allocated as needed for dynamic properties.

The new key will not be member of any KeySet and will start with a new reference counter at 0. A subsequent keyDel() will delete the key.

int f (const Key * source)
{
Key * dup = keyDup (source);
// work with duplicate
keyDel (dup);
// everything related to dup is freed
// and source is unchanged
}

Like for a new key after keyNew() a subsequent ksAppend() makes a KeySet to take care of the lifecycle of the key.

int g (const Key * source, KeySet * ks)
{
Key * dup = keyDup (source);
// work with duplicate
ksAppendKey (ks, dup);
// ksDel(ks) will also free the duplicate
// source remains unchanged.
}

Duplication of keys should be preferred to keyNew(), because data like owner can be filled with a copy of the key instead of asking the environment. It can also be optimized in the checks, because the keyname is known to be valid.

Parameters

  source | has to be an initialized source Key

Return values

  0 | failure or on NULL pointer

Returns
  a fully copy of source on success

See also
  ksAppend(), keyDel(), keyNew()

## ◆ keyGetRef()

ssize_t keyGetRef | ( | const Key * | key | ) |

Return how many references the key has.

The reference counting is the essential property of keys to make sure that they can be put safely into data structures. E.g. if you put a Key into a KeySet:

Key *k = keyNew("user/proper_name", KEY_END); // ref counter = 0
KeySet *ks = ksNew (1, k, KS_END);
keyDel(k); // key will not be deleted, because its in the keyset
ksDel(ks); // now the key will be deleted

You can even add the key to more KeySets:

Key *k = keyNew("user/proper_name", KEY_END); // ref counter 0
KeySet *ks1 = ksNew(1, k, KS_END); // ref counter of k 1
KeySet *ks2 = ksNew(1, k, KS_END); // ref counter of k 2
ksDel(ks1); // ref counter of k 1
ksDel(ks2); // k is now deleted

If you increment only by one with keyIncRef() the same as said above is valid:

Key *k = keyNew(0); // ref counter = 0
keyIncRef(k); // ref counter = 1
keyDel(k); // key will not be deleted
keyDecRef(k);
keyDel(k);

or use keyIncRef() more than once:

Key *k = keyNew(0); // ref counter 0
keyIncRef(k); // ref counter of key 1
keyDel (k); // has no effect
keyIncRef(k); // ref counter of key 2
keyDel (k); // has no effect
keyDecRef(k); // ref counter of key 1
keyDel (k); // has no effect
keyDecRef(k); // ref counter is now 0
keyDel (k); // k is now deleted

The key won't be deleted by a keyDel() as long refcounter is not 0.

The references will be incremented on successful calls to ksAppendKey() or ksAppend().

Note
  keyDup() will reset the references for dupped key.

For your own applications you can use keyIncRef() and keyDecRef() for reference counting, too.

Parameters

  key | the key object to work with

Returns
  the number of references

Return values

  -1 | on null pointer

See also
  keyIncRef() and keyDecRef()

## ◆ keyIncRef()

ssize_t keyIncRef | ( | Key * | key | ) |

Increment the viability of a key object.

This function is intended for applications using their own reference counter for key objects. With it you can increment the reference and thus avoid destruction of the object in a subsequent keyDel().

The reference counter can't be incremented once it reached SSIZE_MAX. In that situation nothing will happen and SSIZE_MAX will be returned.

Note
  keyDup() will reset the references for dupped key.

Returns
  the value of the new reference counter

Return values

  -1 | on null pointer
  SSIZE_MAX | when maximum exceeded

Parameters

  key | the key object to work with

See also
  keyGetRef() for longer explanation, keyDecRef(), keyDel()

## ◆ keyNew()

Key* keyNew | ( | const char * | name,
|  |  | ...
| ) |  |

A practical way to fully create a Key object in one step.

To just get a key object, simple do:

Key *k = keyNew(0);
// work with it
keyDel (k);

If you want the key object to contain a name, value, comment and other meta info read on.

Note
  When you already have a key with similar properties its easier to keyDup() the key.

You can call it in many different ways depending on the attribute tags you pass as parameters. Tags are represented as keyswitch_t values, and tell keyNew() which Key attribute comes next.

We can also give an empty key name and a KEY_END tag with the same effect as before:

Key *k =keyNew("", KEY_END); // Has the same effect as above
// work with it
keyDel (k);

But we can also give the key a proper name right from the start:

// Create and initialize a key with a name and nothing else
Key *k=keyNew("user/some/example", KEY_END);
// work with it
keyDel (k);

So, keyNew() allocates memory for a key object and keyDel() cleans everything up.

keyNew() processes the given argument list even further. The Key attribute tags are the following:

- KEY_VALUE
  Next parameter is a pointer to the value that will be used. If no KEY_BINARY was used before, a string is assumed.
  // Create and initialize a key with a name and nothing else
  Key *k=keyNew("user/tmp/ex0",
  KEY_VALUE, "some data", // set a string value
  KEY_END); // end of args
- KEY_SIZE
  Define a maximum length of the value. This is only used when setting a binary key.
  // Create and initialize a key with a name and nothing else
  Key *k=keyNew("user/tmp/ex1",
  KEY_SIZE, 4, // has no effect on strings
  KEY_VALUE, "some data", // set a string value
  KEY_END); // end of args
- KEY_META
  Next two parameter is a metaname and a metavalue. See keySetMeta().
  Key *k=keyNew("user/tmp/ex3",
  KEY_META, "comment", "a comment", // with a comment
  KEY_META, "owner", "root", // and an owner
  KEY_META, "special", "yes", // and any other metadata
  KEY_END); // end of args
- KEY_END
  Must be the last parameter passed to keyNew(). It is always required, unless the `keyName` is 0.
- KEY_FLAGS
  Bitwise disjunction of flags, which don't require one or more values. recommended way to set multiple flags. overrides previously defined flags.
  Key *k=keyNew("user/tmp/ex3",
  KEY_FLAGS, KEY_BINARY | KEY_CASCADING_NAME, // flags
  KEY_SIZE, 7, // assume binary length 7
  KEY_VALUE, "some data", // value that will be truncated in 7 bytes
  KEY_END); // end of args
- KEY_BINARY
  Allows one to change the key to a binary key. Make sure that you also pass KEY_SIZE before you set the value. Otherwise it will be cut off with first \0 in the string. So this flag toggle from keySetString() to keySetBinary(). If no value (nor size) is given, it will be a NULL key.
  // Create and initialize a key with a name and nothing else
  Key *k=keyNew("user/tmp/ex2",
  KEY_BINARY,
  KEY_SIZE, 4, // now the size is important
  KEY_VALUE, "some data", // sets the binary value ("some")
  KEY_END); // end of args
- KEY_CASCADING_NAME allow the name to start with / useful for ksLookup() and kdbGet() parent/lookup keys
- KEY_META_NAME allow the name to start with arbitrary namespaces useful to compare with metakeys

Deprecated:
  The flags below are deprecated and KEY_META should be preferred. They remain some time, however, for compatibility:
  - KEY_DIR
    Define that the key is a directory rather than a ordinary key. This means its executable bits in its mode are set. But even without this option the key can have subkeys. See keySetDir().
  - KEY_OWNER
    Next parameter is the owner. See keySetOwner().
  - KEY_UID, KEY_GID
    Next parameter is taken as the UID (uid_t) or GID (gid_t) that will be defined on the key. See keySetUID() and keySetGID().
  - KEY_MODE
    Next parameter is taken as mode permissions (int) to the key. See keySetMode().
    Key *k=keyNew("user/tmp/ex3",
    KEY_VALUE, "some data", // with a simple value
    KEY_MODE, 0777, // permissions
    KEY_END); // end of args
  - KEY_COMMENT
    Next parameter is a comment. See keySetComment().
    Key *k=keyNew("user/tmp/ex4",
    KEY_BINARY, // key type
    KEY_SIZE, 7, // assume binary length 7
    KEY_VALUE, "some data", // value that will be truncated in 7 bytes
    KEY_COMMENT, "value is truncated",
    KEY_OWNER, "root", // owner (not uid) is root
    KEY_UID, 0, // root uid
    KEY_END); // end of args

Parameters

  name | a valid name to the key, or NULL to get a simple initialized, but really empty, object

See also
  keyDel()

Returns
  a pointer to a new allocated and initialized Key object.

Return values

  NULL | on allocation error or if an invalid `name` was passed (see keySetName()).