void test_countLevel (void) { Key * k = keyNew ("user///", KEY_END); succeed_if (elektraKeyCountLevel (k) == 1, "count level wrong"); keySetName (k, "user/x"); succeed_if (elektraKeyCountLevel (k) == 2, "count level wrong"); keySetName (k, "user/x/z/f"); succeed_if (elektraKeyCountLevel (k) == 4, "count level wrong"); keySetName (k, "user/x/z\\/f"); succeed_if (elektraKeyCountLevel (k) == 3, "count level wrong"); Key * k2 = keyNew ("user/x/z", KEY_END); succeed_if (elektraKeyCountEqualLevel (k, k2) == 2, "equal level wrong"); keySetName (k, "user/x/z\\/f"); keySetName (k2, "user/x/z\\/f"); succeed_if (elektraKeyCountEqualLevel (k, k2) == 3, "equal level wrong"); keySetName (k, "user/x/v/ffkkk"); keySetName (k2, "user/x/v/ff"); succeed_if (elektraKeyCountEqualLevel (k, k2) == 3, "equal level wrong"); keySetName (k, "user/x/v/ff"); keySetName (k2, "user/x/v/ff"); succeed_if (elektraKeyCountEqualLevel (k, k2) == 4, "equal level wrong"); keySetName (k, "user/x\\abc/v/ff"); keySetName (k2, "user/x\\abc/v/ff"); succeed_if (elektraKeyCountEqualLevel (k, k2) == 4, "equal level wrong"); keyDel (k); keyDel (k2); }
/** * @brief Close all levels in cur not needed in next * * Closing is much simpler then opening because no names need to be * yield. * * @pre keys are not allowed to be below, * except: last run where everything below root/parent key is * closed * * Then all levels are reverse iterated until the level before the equal * level. * @see elektraGenCloseIterate * * In the level before the equal level there is some special handling in * regards to the next level. * @see elektraGenCloseFirst * * @example * * cur: user/sw/org/deeper * next: user/sw/org/other/deeper/below * -> nothing will be done ("deeper" is value) * [eq: 3, cur: 4, next: 6, gen: 0] * * cur: user/sw/org/other/deeper/below * next: user/no * -> "deeper", "other", "org" and "sw" maps will be closed ("below" is value) * [eq: 1, cur: 6, next: 2, gen: 4] * * cur: user/no * next: user/oops/it/is/below * -> nothing will be done ("no" is value) * [eq: 1, cur: 2, next: 5, gen: 0] * * cur: user/oops/it/is/below * next: user/x/t/s/x * -> close "is", "it", "oops" * [eq: 1, cur: 5, next: 5, gen: 3] * * last iteration (e.g. close down to root) * cur: user/x/t/s/x * next: user * -> close "s", "t" and "x" maps * [eq: 1, cur: 5, next: 1, gen: 3] * * cur: user/#0/1/1/1 * next: user/#1/1/1/1 * -> close "1", "1", "1", but not array * [eq: 1, cur: 5, next: 5, gen: 3] * * @param g * @param cur * @param next */ void elektraGenClose (yajl_gen g, const Key * cur, const Key * next) { int curLevels = elektraKeyCountLevel (cur); #ifdef ELEKTRA_YAJL_VERBOSE int nextLevels = elektraKeyCountLevel (next); #endif int equalLevels = elektraKeyCountEqualLevel (cur, next); // 1 for last level not to iterate, 1 before 1 after equal int levels = curLevels - equalLevels - 2; const char * pcur = keyName (cur); size_t csize = 0; const char * pnext = keyName (next); size_t nsize = 0; for (int i = 0; i < equalLevels + 1; ++i) { pcur = keyNameGetOneLevel (pcur + csize, &csize); pnext = keyNameGetOneLevel (pnext + nsize, &nsize); } #ifdef ELEKTRA_YAJL_VERBOSE printf ("elektraGenClose, eq: %d, cur: %s %d, next: %s %d, " "levels: %d\n", equalLevels, pcur, curLevels, pnext, nextLevels, levels); #endif if (levels > 0) { elektraGenCloseLast (g, cur); } elektraGenCloseIterate (g, cur, levels); elektraGenCloseFirst (g, pcur, csize, pnext, levels); }
/** * @brief Close the last element * * Needs less special handling because cur is fully below next. * * Will fully iterate over all elements. * * @param g handle to yield close events * @param cur current key * @param next the last key (the parentKey) */ void elektraGenCloseFinally(yajl_gen g, const Key *cur, const Key *next) { int curLevels = elektraKeyCountLevel(cur); #ifdef ELEKTRA_YAJL_VERBOSE int nextLevels = elektraKeyCountLevel(next); #endif int equalLevels = elektraKeyCountEqualLevel(cur, next); // 1 for last level not to iterate, 1 after equal int levels = curLevels - equalLevels - 1; const char *pcur = keyName(cur); size_t csize = 0; const char *pnext = keyName(next); size_t nsize = 0; for (int i=0; i < equalLevels+1; ++i) { pcur=keyNameGetOneLevel(pcur+csize,&csize); pnext=keyNameGetOneLevel(pnext+nsize, &nsize); } #ifdef ELEKTRA_YAJL_VERBOSE printf ("elektraGenFinally, eq: %d, cur: %s %d, next: %s %d, " "levels: %d\n", equalLevels, pcur, curLevels, pnext, nextLevels, levels); #endif // fixes elektraGenCloseIterate for the special handling of // arrays finally elektraGenCloseLast(g, cur); // now we iterate over the middle part elektraGenCloseIterate(g, cur, levels); // now we look at the first unequal element // this is the very last element we are about to close if (pcur && *pcur == '#') { #ifdef ELEKTRA_YAJL_VERBOSE printf ("array close FINAL\n"); #endif } else { #ifdef ELEKTRA_YAJL_VERBOSE printf ("GEN map close FINAL\n"); #endif yajl_gen_map_close(g); } }