5 /**A functional access to keys.
7 * Instead of writing your own loop you can write
8 * a function working with a key and pass it to
11 * The function will be executed for all keys in
14 * @param ks the keyset to work with
15 * @param func the function to execute on every key of the keyset
16 * @return the sum of all return values
17 * @return -1 if any function returned -1, the execution will stop there, but
18 * ksCurrent() will tell you where it stopped.
21 int ksForEach (KeySet *ks, int (*func) (Key *k))
27 cursor_t cursor = ksGetCursor (ks);
29 while ((current = ksNext (ks)) != 0)
32 if (rc == -1) return -1;
35 ksSetCursor(ks, cursor);
42 * filter is executed for every key in the keyset result. When it returns 0,
43 * the key will be dropped, when it returns 1 it will be ksAppendKey()ed to result,
44 * when it returns -1 the processing will be stopped. You can use ksCurrent()
45 * on input to see where the problem was. Because of this input is not const,
46 * apart from ksCurrent() the input will not be changed. The keys that have
47 * been in result before will stay untouched.
49 * @param result is the keyset where keys are added.
50 * @param input is the keyset the filter works on.
51 * @param filter is the function to execute on every key of the keyset to decide if
52 * it should be ksAppendKey()ed to the result.
53 * @return the number of keys added on success
54 * @return 0 when nothing was done
55 * @return -1 when filter returned an error (-1), ksCurrent() of input will
56 * be the problematic key.
59 int ksFilter (KeySet *result, KeySet *input, int (*filter) (Key *k))
65 cursor_t cursor = ksGetCursor (input);
67 while ((current = ksNext (input)) != 0)
69 rc = filter (current);
70 if (rc == -1) return -1;
74 ksAppendKey(result, keyDup (current));
77 ksSetCursor(input, cursor);
84 int add_string (Key *check) { return keySetString (check, "string"); }
85 int add_comment (Key *check) { return keySetComment (check, "comment"); }
86 int has_a (Key *check) { return keyName(check)[5]=='a'; }
87 int below_a (Key *check) { return keyIsBelow(global_a, check); }
88 int direct_below_a (Key *check) { return keyIsDirectBelow(global_a, check); }
90 int sum_helper (Key *check) { return atoi(keyValue(check)); }
91 int below_30 (Key *check) { return atoi(keyValue(check))<30; }
92 int find_80 (Key *check) { int n=atoi(keyValue(check)); return n>70?-1:1; }
98 KeySet *ks = ksNew (64,
99 keyNew ("user/a/1", KEY_END),
100 keyNew ("user/a/2", KEY_END),
101 keyNew ("user/a/b/1", KEY_END),
102 keyNew ("user/a/b/2", KEY_END),
103 keyNew ("user/ab/2", KEY_END),
104 keyNew ("user/b/1", KEY_END),
105 keyNew ("user/b/2", KEY_END),
108 KeySet *values_below_30 = 0;
110 global_a = keyNew ("user/a", KEY_END);
112 ksForEach (ks, add_string);
113 ksForEach (ks, add_comment);
116 ksFilter (out, ks, has_a);
120 ksFilter (out, ks, below_a);
124 ksFilter (out, ks, direct_below_a);
128 keyDel (global_a); global_a = 0;
131 keyNew ("user/a", KEY_VALUE, "40", KEY_END),
132 keyNew ("user/b", KEY_VALUE, "20", KEY_END),
133 keyNew ("user/c", KEY_VALUE, "80", KEY_END),
134 keyNew ("user/d", KEY_VALUE, "24", KEY_END),
135 keyNew ("user/e", KEY_VALUE, "32", KEY_END),
136 keyNew ("user/f", KEY_VALUE, "12", KEY_END),
137 keyNew ("user/g", KEY_VALUE, "43", KEY_END),
141 ksForEach (values, sum_helper);
143 values_below_30 = ksNew (0);
144 ksFilter (values_below_30, values, below_30);
145 ksForEach (values_below_30, sum_helper);
147 ksForEach (values, find_80);
148 found = ksCurrent (values); /* here is user/c */
149 found = ksLookupByName (values, "user/c", 0); /* should find the same */
151 ksDel (values_below_30);