Key construction and initialization methods. More...
Enumerations | |
enum | keyswitch_t { KEY_NAME = 1, KEY_VALUE = 1<<1, 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_END = 0 } |
Functions | |
Key * | keyNew (const char *keyName,...) |
Key * | keyDup (const Key *source) |
int | keyCopy (Key *dest, const Key *source) |
int | keyDel (Key *key) |
ssize_t | keyIncRef (Key *key) |
ssize_t | keyDecRef (Key *key) |
ssize_t | keyGetRef (const Key *key) |
Key construction and initialization methods.
To use them:
#include <kdb.h>
A Key is the essential class that encapsulates key name , value and metainfo . Key properties are:
Described here the methods to allocate and free the key.
enum keyswitch_t |
Switches to denote the various Key attributes in methods throughout this library.
This enum switch provide a flag for every metadata in a key.
In case of keyNew() they give Information what Parameter comes next.
KEY_NAME |
Flag for the key name |
KEY_VALUE |
Flag for the key data |
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 |
KEY_GID |
Flag for the key GID |
KEY_MODE |
Flag for the key permissions |
KEY_ATIME |
Flag for the key access time |
KEY_MTIME |
Flag for the key change time |
KEY_CTIME |
Flag for the key status change time |
KEY_SIZE |
Flag for maximum size to limit value |
KEY_DIR |
Flag for the key directories |
KEY_END |
Used as a parameter terminator to keyNew() |
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:
The reference counter will not change for the destination key. Affiliation to keysets are also not affected.
When you pass a NULL-pointer as source the data of dest will be cleaned completely and you get a fresh dest key.
The meta data will be duplicated for the destination key. So it will not take much additional space, even with lots of metadata.
If you want to copy all metadata, but keep the old 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 metadata from c }
dest | the key which will be written to | |
source | the key which should be copied or NULL to clean the destination key |
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.
key | the key object to work with |
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.
key | the key object to delete |
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.
source | has to be an initializised source Key |
ssize_t keyGetRef | ( | const Key * | key | ) |
Return how many references the key has.
The references will be incremented on successful calls to ksAppendKey() or ksAppend().
For your own applications you can use keyIncRef() and keyDecRef() for reference counting. Keys with zero references will be deleted when using keyDel().
key | the key object to work with |
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.
key | the key object to work with |
Key* keyNew | ( | const char * | keyName, | |
... | ||||
) |
A practical way to fully create a Key object in one step.
This function tries to mimic the C++ way for constructors.
To just get a key object, simple do:
If you want the key object to contain a name, value, comment and other meta info read on.
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. See http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html#AEN135
You can call it in many different ways depending on the attribute tags you pass as parameters. Tags are represented as the keyswitch_t values, and tell keyNew() which Key attribute comes next.
The simplest and minimum way to use it is with no tags, only a key name:
Key *nullKey,*emptyNamedKey; // Create a key that has no name, is completely empty, but is initialized nullKey=keyNew(0); keyDel (nullKey); // Is the same as above nullKey=keyNew("", KEY_END); keyDel (nullKey); // Create and initialize a key with a name and nothing else emptyNamedKey=keyNew("user/some/example",KEY_END); keyDel (emptyNamedKey);
keyNew() allocates memory for a key object and cleans everything up. After that, it processes the given argument list.
The Key attribute tags are the following:
keyswitch_t::KEY_GID
keyName
is 0.KeySet *ks=ksNew(0); ksAppendKey(ks,keyNew(0)); // an empty key ksAppendKey(ks,keyNew("user/sw", // the name of the key KEY_END)); // no more args ksAppendKey(ks,keyNew("user/tmp/ex1", KEY_VALUE,"some data", // set a string value KEY_END)); // end of args ksAppendKey(ks,keyNew("user/tmp/ex2", KEY_VALUE,"some data", // with a simple value KEY_MODE,0777, // permissions KEY_END)); // end of args ksAppendKey(ks,keyNew("user/tmp/ex4", KEY_TYPE,KEY_TYPE_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 ksAppendKey(ks,keyNew("user/tmp/ex5", KEY_TYPE, KEY_TYPE_DIR | KEY_TYPE_BINARY,// dir key with a binary value KEY_SIZE,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 ksDel(ks);
The reference counter (see keyGetRef()) 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 keyInc()) and the key can't be be deleted by a keyDel().
Key *k = keyNew(0); // ref counter 0 ksAppendKey(ks, k); // ref counter of key 1 ksDel(ks); // key will be deleted with keyset *
If you increment only by one with keyInc() the same as said above is valid:
Key *k = keyNew(0); // ref counter 0 keyIncRef(k); // ref counter of key 1 keyDel(k); // has no effect keyDecRef(k); // ref counter back to 0 keyDel(k); // key is now deleted *
If you add the key to more keySets:
Key *k = keyNew(0); // ref counter 0 ksAppendKey(ks1, k); // ref counter of key 1 ksAppendKey(ks2, k); // ref counter of key 2 ksDel(ks1); // ref counter of key 1 ksDel(ks2); // k is now deleted *
or use keyInc() 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 *
they key won't be deleted by a keyDel() as long refcounter is not 0.
The key's sync bit will always be set for any call, except:
keyName | a valid name to the key, or NULL to get a simple initialized, but really empty, object |
keyName
was passed (see keySetName()).