Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : #include "iterator.h"
10 :
11 3744 : keyNameReverseIterator elektraKeyNameGetReverseIterator (const Key * k)
12 : {
13 : keyNameReverseIterator it;
14 3744 : it.rend = keyName (k);
15 3744 : it.rbegin = it.rend + keyGetNameSize (k);
16 3744 : it.current = it.rbegin;
17 3744 : it.size = 0;
18 3744 : return it;
19 : }
20 :
21 :
22 : /**
23 : * @brief Go to the previous element
24 : *
25 : * @param it the iterator to iterate
26 : *
27 : * @return
28 : */
29 16824 : int elektraKeyNameReverseNext (keyNameReverseIterator * it)
30 : {
31 16824 : if (it->current == it->rend) // we are at the end (move that to hasNext?)
32 : {
33 : return 0;
34 : }
35 :
36 15126 : const char * real = it->current - 1; // start at one position left
37 15126 : int endReached = 0;
38 :
39 : // skip all repeating '/' in the "beginning" of string
40 41634 : while (*real == KDB_PATH_SEPARATOR)
41 : {
42 11382 : --real;
43 : }
44 :
45 15126 : if (*real == KDB_PATH_ESCAPE)
46 : {
47 0 : ++real; // we skipped too much
48 : }
49 :
50 15126 : const char * currentEnd = real; // now we know where the string will end
51 :
52 : // now see where this basename begins
53 : // also handles escaped chars with '\'
54 107203 : while (real != it->rend && !endReached)
55 : {
56 76951 : --real;
57 76951 : if (real != it->rend && *real == KDB_PATH_SEPARATOR)
58 : {
59 : // only decrement if we have not send the end
60 13440 : --real;
61 13440 : if (*real != KDB_PATH_ESCAPE)
62 : {
63 13428 : endReached = 1;
64 13428 : real += 2; // fix for lookahead
65 : }
66 : }
67 : }
68 :
69 : // update iterator and return it
70 15126 : it->size = currentEnd - real + 1;
71 15126 : it->current = real;
72 15126 : return 1;
73 : }
74 :
75 : /**
76 : * @brief Forwards to key which is not below the next one
77 : *
78 : * Forwards at least forward one element.
79 : * ksCurrent() will point at the same key as the key which is returned.
80 : *
81 : * e.g.
82 : * user/sw/x
83 : * user/sw/x/y
84 : * user/sw/x/y/z1
85 : *
86 : * @retval last element if no other found.
87 : * @retval 0 if there is no other element afterwards (keyset will be
88 : * rewinded then)
89 : *
90 : * @param ks keyset to use
91 : *
92 : * @return key after starting position which is not below (to any latter
93 : * one)
94 : */
95 929 : Key * elektraNextNotBelow (KeySet * ks)
96 : {
97 929 : const Key * previous = ksNext (ks);
98 :
99 929 : if (!previous)
100 : {
101 72 : ksRewind (ks);
102 72 : return 0;
103 : }
104 :
105 : // uninitialized variables are ok, because do{}while guarantees initialisation
106 : cursor_t pos; // always one before current
107 : const Key * current = previous; // current is same as ksCurrent()
108 : do
109 : {
110 1006 : pos = ksGetCursor (ks); // remember candidate
111 1006 : previous = current; // and remember last key
112 1006 : current = ksNext (ks); // look forward to next key
113 1006 : } while (current && keyIsBelow (previous, current));
114 :
115 : // jump to and return candidate, because next is known to be not
116 : // below candidate
117 857 : ksSetCursor (ks, pos);
118 857 : return ksCurrent (ks);
119 : }
|