Elektra  0.8.8
Functions
Methods for Making Tests
Key

Methods to do various tests on Keys. More...

Collaboration diagram for Methods for Making Tests:

Functions

int keyCmp (const Key *k1, const Key *k2)
int keyNeedSync (const Key *key)
int keyIsSystem (const Key *key)
int keyIsUser (const Key *key)
int keyIsBelow (const Key *key, const Key *check)
int keyIsDirectBelow (const Key *key, const Key *check)
int keyRel (const Key *key, const Key *check)
int keyIsInactive (const Key *key)
int keyIsDir (const Key *key)
int keyIsBinary (const Key *key)
int keyIsString (const Key *key)
keyswitch_t keyCompare (const Key *key1, const Key *key2)

Detailed Description

Methods to do various tests on Keys.

To use them:

#include <kdb.h>

Function Documentation

int keyCmp ( const Key *  k1,
const Key *  k2 
)

Compare the name of two keys.

Returns
a number less than, equal to or greater than zero if k1 is found, respectively, to be less than, to match, or be greater than k2.

The comparison is based on a strcmp of the keynames, and iff they match a strcmp of the owner will be used to distuingish. If even this matches the keys are found to be exactly the same and 0 is returned. These two keys can't be used in the same KeySet.

keyCmp() defines the sorting order for a KeySet.

The following 3 points are the rules for null values:

  • A null pointer will be found to be smaller than every other key. If both are null pointers, 0 is returned.
  • A null name will be found to be smaller than every other name. If both are null names, 0 is returned.

If the name is equal then:

  • No owner will be found to be smaller then every other owner. If both don't have a owner, 0 is returned.
Note
the owner will only be used if the names are equal.

Often is enough to know if the other key is less then or greater then the other one. But Sometimes you need more precise information, see keyRel().

Given any Keys k1 and k2 constructed with keyNew(), following equation hold true:

Here are some more examples:

Key *k1 = keyNew("user/a", KEY_END);
Key *k2 = keyNew("user/b", KEY_END);
// keyCmp(k1,k2) < 0
// keyCmp(k2,k1) > 0

And even more:

Key *k1 = keyNew("user/a", KEY_OWNER, "markus", KEY_END);
Key *k2 = keyNew("user/a", KEY_OWNER, "max", KEY_END);
// keyCmp(k1,k2) < 0
// keyCmp(k2,k1) > 0

Do not strcmp the keyName() yourself because the result differs from simple ascii comparison.

Parameters
k1the first key object to compare with
k2the second key object to compare with
See Also
ksAppendKey(), ksAppend() will compare keys when appending
ksLookup() will compare keys during searching
keyswitch_t keyCompare ( const Key *  key1,
const Key *  key2 
)

Compare 2 keys.

The returned flags bit array has 1s (differ) or 0s (equal) for each key meta info compared, that can be logically ORed using keyswitch_t flags. KEY_NAME , KEY_VALUE , KEY_OWNER , KEY_COMMENT , KEY_UID , KEY_GID , KEY_MODE and

A very simple example would be
Key *key1, *key;
uint32_t changes;
// omited key1 and key2 initialization and manipulation
changes=keyCompare(key1,key2);
if (changes == 0) printf("key1 and key2 are identicall\n");
if (changes & KEY_VALUE)
printf("key1 and key2 have different values\n");
if (changes & KEY_UID)
printf("key1 and key2 have different UID\n");
Example of very powerful specific Key lookup in a KeySet:
KDB *handle = kdbOpen();
KeySet *ks=ksNew(0, KS_END);
Key *base = keyNew ("user/sw/MyApp/something", KEY_END);
Key *current;
uint32_t match;
uint32_t interests;
kdbGetByName(handle, ks, "user/sw/MyApp", 0);
// we are interested only in key type and access permissions
interests=(KEY_TYPE | KEY_MODE);
ksRewind(ks); // put cursor in the beginning
while ((curren=ksNext(ks))) {
match=keyCompare(current,base);
if ((~match & interests) == interests)
printf("Key %s has same type and permissions of base key",keyName(current));
// continue walking in the KeySet....
}
// now we want same name and/or value
interests=(KEY_NAME | KEY_VALUE);
// we don't really need ksRewind(), since previous loop achieved end of KeySet
while ((current=ksNext(ks))) {
match=keyCompare(current,base);
if ((~match & interests) == interests) {
printf("Key %s has same name, value, and sync status
of base key",keyName(current));
}
// continue walking in the KeySet....
}
keyDel(base);
ksDel(ks);
kdbClose (handle);
Returns
a bit array pointing the differences
Parameters
key1first key
key2second key
See Also
keyswitch_t
int keyIsBelow ( const Key *  key,
const Key *  check 
)

Check if the key check is below the key key or not.

Example:

key user/sw/app
check user/sw/app/key

returns true because check is below key

Example:

key user/sw/app
check user/sw/app/folder/key

returns also true because check is indirect below key

Parameters
keythe key object to work with
checkthe key to find the relative position of
Returns
1 if check is below key
0 if it is not below or if it is the same key
See Also
keySetName(), keyGetName(), keyIsDirectBelow()
int keyIsBinary ( const Key *  key)

Check if a key is binary type.

The function checks if the key is a binary. Opposed to string values binary values can have '\0' inside the value and may not be terminated by a null character. Their disadvantage is that you need to pass their size.

Make sure to use this function and don't test the binary type another way to ensure compatibility and to write less error prone programs.

Returns
1 if it is binary
0 if it is not
-1 on NULL pointer
See Also
keyGetBinary(), keySetBinary()
Parameters
keythe key to check
int keyIsDir ( const Key *  key)

Check if the mode for the key has access privileges.

In the filesys backend a key represented through a file has the mode 664, but a key represented through a folder 775. keyIsDir() checks if all 3 executeable bits are set.

If any executable bit is set it will be recognized as a directory.

Note
keyIsDir may return true even though you can't access the directory.

To know if you can access the directory, you need to check, if your

  • user ID is equal the key's user ID and the mode & 100 is true
  • group ID is equal the key's group ID and the mode & 010 is true
  • mode & 001 is true

Accessing does not mean that you can get any value or comments below, see Modes for more information.

Note
currently mountpoints can only where keyIsDir() is true (0.7.0) but this is likely to change.
Parameters
keythe key object to work with
Returns
1 if key is a directory, 0 otherwise
-1 on NULL pointer
See Also
keySetDir(), keySetMode()
int keyIsDirectBelow ( const Key *  key,
const Key *  check 
)

Check if the key check is direct below the key key or not.

Example:
key user/sw/app
check user/sw/app/key

returns true because check is below key

Example:
key user/sw/app
check user/sw/app/folder/key

does not return true, because there is only a indirect relation
Parameters
keythe key object to work with
checkthe key to find the relative position of
Returns
1 if check is below key
0 if it is not below or if it is the same key
-1 on null pointer
See Also
keyIsBelow(), keySetName(), keyGetName()
int keyIsInactive ( const Key *  key)

Check whether a key is inactive.

In Elektra terminology a hierarchy of keys is inactive if the rootkey's basename starts with '.'. So a key is also inactive if it is below an inactive key. For example, user/key/.hidden is inactive and so is user/.hidden/below.

Inactive keys should not have any meaning to applications, they are only a convention reserved for users and administrators. To automatically remove all inactive keys for an application, consider to use the hidden plugin.

Parameters
keythe key object to work with
Return values
1if the key is inactive
0if the key is active
-1on NULL pointer or when key has no name
int keyIsString ( const Key *  key)

Check if a key is string type.

String values are null terminated and are not allowed to have any '\0' characters inside the string.

Make sure to use this function and don't test the string type another way to ensure compatibility and to write less error prone programs.

Returns
1 if it is string
0 if it is not
-1 on NULL pointer
See Also
keyGetString(), keySetString()
Parameters
keythe key to check
int keyIsSystem ( const Key *  key)

Check whether a key is under the system namespace or not

Parameters
keythe key object to work with
Returns
1 if key name begins with system, 0 otherwise
-1 on NULL pointer
See Also
keyIsUser(), keySetName(), keyName()
int keyIsUser ( const Key *  key)

Check whether a key is under the user namespace or not.

Parameters
keythe key object to work with
Returns
1 if key name begins with user, 0 otherwise
-1 on NULL pointer
See Also
keyIsSystem(), keySetName(), keyName()
int keyNeedSync ( const Key *  key)

Test if a key needs to be synced to backend storage.

If any key modification took place the key will be flagged with KEY_FLAG_SYNC so that kdbSet() knows which keys were modified and which not.

After keyNew() the flag will normally be set, but after kdbGet() and kdbSet() the flag will be removed. When you modify the key the flag will be set again.

In your application you can make use of that flag to know if you changed something in a key after a kdbGet() or kdbSet().

Note
Note that also changes in the meta data will set that flag.
See Also
keyNew()
Parameters
keythe key object to work with
Returns
1 if key was changed in memory, 0 otherwise
-1 on NULL pointer
int keyRel ( const Key *  key,
const Key *  check 
)

Information about the relation in the hierarchy between two keys.

Unlike keyCmp() the number gives information about hierarchical information.

  • If the keys are the same 0 is returned. So it is the key itself.
    user/key
    user/key
    
keySetName (key, "user/key/folder");
keySetName (check, "user/key/folder");
succeed_if (keyRel (key, check) == 0, "should be same");
*
Note
this relation can be checked with keyCmp() too.
  • If the key is direct below the other one 1 is returned. That means that, in terms of hierarchy, no other key is between them - it is a direct child.
    user/key/folder
    user/key/folder/child
    
keySetName (key, "user/key/folder");
keySetName (check, "user/key/folder/child");
succeed_if (keyRel (key, check) == 1, "should be direct below");
*
  • If the key is below the other one, but not directly 2 is returned. This is also called grand-child.
    user/key/folder
    user/key/folder/any/depth/deeper/grand-child
    
keySetName (key, "user/key/folder");
keySetName (check, "user/key/folder/any/depth/deeper/grand-child");
succeed_if (keyRel (key, check) >= 2, "should be below (but not direct)");
succeed_if (keyRel (key, check) > 0, "should be below");
succeed_if (keyRel (key, check) >= 0, "should be the same or below");
*
  • If a invalid or null ptr key is passed, -1 is returned
  • If the keys have no relations, but are not invalid, -2 is returned.
  • If the keys are in the same hierarchy, a value smaller then -2 is returned. It means that the key is not below.
    user/key/myself
    user/key/sibling
    
keySetName (key, "user/key/folder");
keySetName (check, "user/notsame/folder");
succeed_if (keyRel (key, check) < -2, "key is not below, but same namespace");

TODO Below is an idea how it could be extended: It could continue the search into the other direction if any (grand-)parents are equal.

  • If the keys are direct below a key which is next to the key, -2 is returned. This is also called nephew. (TODO not implemented)
    user/key/myself
    user/key/sibling
    
  • If the keys are direct below a key which is next to the key, -2 is returned. This is also called nephew. (TODO not implemented)
    user/key/myself
    user/key/sibling/nephew
    
  • If the keys are below a key which is next to the key, -3 is returned. This is also called grand-nephew. (TODO not implemented)
    user/key/myself
    user/key/sibling/any/depth/deeper/grand-nephew
    

The same holds true for the other direction, but with negative values. For no relation INT_MIN is returned.

Note
to check if the keys are the same, you must use keyCmp() == 0! keyRel() does not give you the information if it did not find a relation or if it is the same key.
Returns
dependend on the relation: 2.. if below 1.. if direct below 0.. if the same -1.. on null or invalid keys -2.. if none of any other relation -3.. if same hierarchy (none of those below) -4.. if sibling (in same hierarchy) -5.. if nephew (in same hierarchy)
Parameters
keythe key object to work with
checkthe second key object to check the relation with