/usr/share/doc/libelektra-dev/examples/functional.c is in libelektra-dev 0.8.7-4.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | #include <kdb.h>
// for keySetComment
#include <kdbextension.h>
#include <stdlib.h>
/**A functional access to keys.
*
* Instead of writing your own loop you can write
* a function working with a key and pass it to
* this method.
*
* The function will be executed for all keys in
* the keyset.
*
* @param ks the keyset to work with
* @param func the function to execute on every key of the keyset
* @return the sum of all return values
* @return -1 if any function returned -1, the execution will stop there, but
* ksCurrent() will tell you where it stopped.
* @see ksFilter()
*/
int ksForEach (KeySet *ks, int (*func) (Key *k))
{
int rc = 0;
int ret = 0;
Key *current;
cursor_t cursor = ksGetCursor (ks);
ksRewind (ks);
while ((current = ksNext (ks)) != 0)
{
rc = func (current);
if (rc == -1) return -1;
ret += rc;
}
ksSetCursor(ks, cursor);
return ret;
}
/**Filter a keyset.
*
* filter is executed for every key in the keyset result. When it returns 0,
* the key will be dropped, when it returns 1 it will be ksAppendKey()ed to result,
* when it returns -1 the processing will be stopped. You can use ksCurrent()
* on input to see where the problem was. Because of this input is not const,
* apart from ksCurrent() the input will not be changed. The keys that have
* been in result before will stay untouched.
*
* @param result is the keyset where keys are added.
* @param input is the keyset the filter works on.
* @param filter is the function to execute on every key of the keyset to decide if
* it should be ksAppendKey()ed to the result.
* @return the number of keys added on success
* @return 0 when nothing was done
* @return -1 when filter returned an error (-1), ksCurrent() of input will
* be the problematic key.
* @see ksForEach()
**/
int ksFilter (KeySet *result, KeySet *input, int (*filter) (Key *k))
{
int rc = 0;
int ret = 0;
Key *current;
cursor_t cursor = ksGetCursor (input);
ksRewind (input);
while ((current = ksNext (input)) != 0)
{
rc = filter (current);
if (rc == -1) return -1;
else if (rc != 0)
{
++ ret;
ksAppendKey(result, keyDup (current));
}
}
ksSetCursor(input, cursor);
return ret;
}
Key *global_a;
int add_string (Key *check) { return keySetString (check, "string"); }
int add_comment (Key *check) { return keySetComment (check, "comment"); }
int has_a (Key *check) { return keyName(check)[5]=='a'; }
int below_a (Key *check) { return keyIsBelow(global_a, check); }
int direct_below_a (Key *check) { return keyIsDirectBelow(global_a, check); }
int sum_helper (Key *check) { return atoi(keyValue(check)); }
int below_30 (Key *check) { return atoi(keyValue(check))<30; }
int find_80 (Key *check) { int n=atoi(keyValue(check)); return n>70?-1:1; }
int main()
{
KeySet *out;
KeySet *ks = ksNew (64,
keyNew ("user/a/1", KEY_END),
keyNew ("user/a/2", KEY_END),
keyNew ("user/a/b/1", KEY_END),
keyNew ("user/a/b/2", KEY_END),
keyNew ("user/ab/2", KEY_END),
keyNew ("user/b/1", KEY_END),
keyNew ("user/b/2", KEY_END),
KS_END);
KeySet *values = 0;
KeySet *values_below_30 = 0;
global_a = keyNew ("user/a", KEY_END);
ksForEach (ks, add_string);
ksForEach (ks, add_comment);
out = ksNew (0);
ksFilter (out, ks, has_a);
ksDel (out);
out = ksNew (0);
ksFilter (out, ks, below_a);
ksDel (out);
out = ksNew (0);
ksFilter (out, ks, direct_below_a);
ksDel (out);
ksDel (ks);
keyDel (global_a); global_a = 0;
values = ksNew (64,
keyNew ("user/a", KEY_VALUE, "40", KEY_END),
keyNew ("user/b", KEY_VALUE, "20", KEY_END),
keyNew ("user/c", KEY_VALUE, "80", KEY_END),
keyNew ("user/d", KEY_VALUE, "24", KEY_END),
keyNew ("user/e", KEY_VALUE, "32", KEY_END),
keyNew ("user/f", KEY_VALUE, "12", KEY_END),
keyNew ("user/g", KEY_VALUE, "43", KEY_END),
KS_END);
/* add together */
ksForEach (values, sum_helper);
values_below_30 = ksNew (0);
ksFilter (values_below_30, values, below_30);
ksForEach (values_below_30, sum_helper);
ksForEach (values, find_80);
ksCurrent (values); /* here is user/c */
ksLookupByName (values, "user/c", 0); /* should find the same */
ksDel (values);
ksDel (values_below_30);
}
|