LCOV - code coverage report
Current view: top level - src/plugins/directoryvalue - directoryvalue_delegate.cpp (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 196 201 97.5 %
Date: 2019-09-12 12:28:41 Functions: 21 21 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Delegate implementation for the `directoryvalue` plugin
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  *
       8             :  */
       9             : 
      10             : #include <numeric>
      11             : 
      12             : #include <kdbassert.h>
      13             : #include <kdbease.h>
      14             : #include <kdblogger.h>
      15             : 
      16             : #include "directoryvalue_delegate.hpp"
      17             : 
      18             : using std::accumulate;
      19             : using std::ignore;
      20             : using std::make_pair;
      21             : using std::pair;
      22             : using std::range_error;
      23             : using std::string;
      24             : using std::tie;
      25             : 
      26             : // -- Functions ----------------------------------------------------------------------------------------------------------------------------
      27             : 
      28             : namespace elektra
      29             : {
      30             : using CppKey = kdb::Key;
      31             : 
      32             : /**
      33             :  * @brief This function splits the given keyset into directory leaves (marked with `DIRECTORY_POSTFIX`) and other keys.
      34             :  *
      35             :  * @param input The function searches for directory leaves in this key set.
      36             :  *
      37             :  * @return A pair of key sets, where the first key set contains all directory leaves and the second key set contains all other keys
      38             :  */
      39         276 : KeySetPair splitDirectoryLeavesOther (CppKeySet const & input)
      40             : {
      41         552 :         CppKeySet directoryLeaves;
      42         552 :         CppKeySet other;
      43             : 
      44        4011 :         for (auto key : input)
      45             :         {
      46        3183 :                 if (key.getBaseName () == DIRECTORY_POSTFIX)
      47             :                 {
      48             :                         directoryLeaves.append (key);
      49             :                 }
      50             :                 else
      51             :                 {
      52             :                         other.append (key);
      53             :                 }
      54             :         }
      55         552 :         return make_pair (directoryLeaves, other);
      56             : }
      57             : 
      58             : /**
      59             :  * @brief This function splits the given keyset into array leaves (first element of an array parent) and other keys.
      60             :  *
      61             :  * @param input The function searches for array leaves in this key set.
      62             :  *
      63             :  * @return A pair of key sets, where the first key set contains all array leaves and the second key set contains all other keys
      64             :  */
      65         276 : KeySetPair splitArrayLeavesOther (CppKeySet const & arrayParents, CppKeySet const & keys)
      66             : {
      67         276 :         bool isFirstElement = false;
      68         552 :         CppKeySet firstElements;
      69         552 :         CppKeySet others;
      70             : 
      71        2715 :         for (auto key : keys)
      72             :         {
      73        1080 :                 bool const isArrayLeaf = isFirstElement && key.isString () && key.getStringSize () > arrayValuePrefixSize &&
      74         860 :                                          strncmp (key.getString ().c_str (), ARRAY_VALUE_PREFIX, arrayValuePrefixSize) == 0;
      75        1258 :                 (isArrayLeaf ? firstElements : others).append (key);
      76        1887 :                 isFirstElement = arrayParents.lookup (key);
      77             :         }
      78             : 
      79         552 :         return make_pair (firstElements, others);
      80             : }
      81             : 
      82             : /**
      83             :  * @brief This function removes the basename (last level) from the given keys.
      84             :  *
      85             :  * @param keys This parameter contains the keys for which this function removes the basename.
      86             :  *
      87             :  * @return A copy of the input, where the last level of each key was removed
      88             :  */
      89         552 : CppKeySet removeBaseName (CppKeySet const & keys)
      90             : {
      91         552 :         CppKeySet directories;
      92             : 
      93        2148 :         for (auto key : keys)
      94             :         {
      95             :                 ELEKTRA_LOG_DEBUG ("Remove basename from “%s”: “%s”", key.getName ().c_str (),
      96             :                                    key.getBinarySize () == 0 ? "NULL" : key.isBinary () ? "binary value!" : key.getString ().c_str ());
      97         492 :                 CppKey directory = key.dup ();
      98         164 :                 directory.delBaseName ();
      99         164 :                 directories.append (directory);
     100             :         }
     101         552 :         return directories;
     102             : }
     103             : 
     104             : /**
     105             :  * @brief This function converts the given array leaves to directory keys.
     106             :  *
     107             :  * @param arrayLeaves This parameter contains array leaves (that start with `ARRAY_VALUE_PREFIX` and have the baseName = `#0`).
     108             :  *
     109             :  * @return A copy of `arrayLeaves`, where key values does not start with `ARRAY_VALUE_PREFIX` any more and the baseName of each key (`#0`)
     110             :  *         was removed
     111             :  */
     112         276 : CppKeySet convertArrayLeaves (CppKeySet const & arrayLeaves)
     113             : {
     114         276 :         CppKeySet directories = removeBaseName (arrayLeaves);
     115         975 :         for (auto key : directories)
     116             :         {
     117             :                 ELEKTRA_LOG_DEBUG ("Convert array leaf “%s”", key.getName ().c_str ());
     118          49 :                 if (key.getStringSize () == arrayValuePrefixSize + 1)
     119             :                 {
     120             :                         key.setBinary (0, 0);
     121             :                         ELEKTRA_LOG_DEBUG ("Set value of “%s” to NULL", key.getName ().c_str ());
     122             :                 }
     123             :                 else
     124             :                 {
     125         196 :                         key.setString (key.getString ().substr (arrayValuePrefixSize + 1));
     126             :                         ELEKTRA_LOG_DEBUG ("Set value of “%s” to “%s”", key.getName ().c_str (), key.getString ().c_str ());
     127             :                 }
     128             :         }
     129         276 :         return directories;
     130             : }
     131             : 
     132             : /**
     133             :  * @brief This function returns a modified copy of `child`, where child is directly below `parent`.
     134             :  *
     135             :  * For example, if `child` has the name `user/parent/level1/level2/level3` and parent has the name `user/parent`, then the function will
     136             :  * return a key with the name `user/parent/level1`.
     137             :  *
     138             :  * @pre The key `child` has to be below `parent`.
     139             :  *
     140             :  * @param parent This parameter specifies a parent key of `child`.
     141             :  * @param keys This variable stores a child key of `parent`.
     142             :  *
     143             :  * @return A copy of `child` that is directly below `parent`
     144             :  */
     145         202 : CppKey convertToDirectChild (CppKey const & parent, CppKey const & child)
     146             : {
     147         202 :         ELEKTRA_ASSERT (child.isBelow (parent), "The key `child` is not located below `parent`");
     148             : 
     149         202 :         CppKey directChild = child.dup ();
     150         420 :         while (!directChild.isDirectBelow (parent))
     151             :         {
     152         218 :                 keySetBaseName (*directChild, 0);
     153             :         }
     154         202 :         return directChild;
     155             : }
     156             : 
     157             : /**
     158             :  * @brief This function checks if `element` is an array element of `parent`.
     159             :  *
     160             :  * @pre The key `child` must be below `parent`.
     161             :  *
     162             :  * @param parent This parameter specifies a parent key.
     163             :  * @param keys This variable stores a direct or indirect child of `parent`.
     164             :  *
     165             :  * @retval true If `element` is an array element
     166             :  * @retval false Otherwise
     167             :  */
     168         233 : bool inline isArrayElementOf (CppKey const & parent, CppKey const & child)
     169             : {
     170         466 :         char const * relative = elektraKeyGetRelativeName (*child, *parent);
     171         233 :         auto offsetIndex = elektraArrayValidateBaseNameString (relative);
     172         233 :         if (offsetIndex <= 0) return false;
     173             :         // Skip `#`, underscores and digits
     174         217 :         relative += 2 * offsetIndex;
     175             :         // The next character has to be the separation char (`/`) or end of string
     176         217 :         if (relative[0] != '\0' && relative[0] != '/') return false;
     177             : 
     178         217 :         return true;
     179             : }
     180             : 
     181             : /**
     182             :  * @brief This function determines if the given key is an array parent.
     183             :  *
     184             :  * @param parent This parameter specifies a possible array parent.
     185             :  * @param keys This variable stores the key set of `parent`.
     186             :  *
     187             :  * @retval true If `parent` is the parent key of an array
     188             :  * @retval false Otherwise
     189             :  */
     190          70 : bool isArrayParent (CppKey const & parent, CppKeySet const & keys)
     191             : {
     192        1594 :         for (auto const & key : keys)
     193             :         {
     194         700 :                 if (!key.isBelow (parent)) continue;
     195         249 :                 if (!isArrayElementOf (parent, key)) return false;
     196             :         }
     197             : 
     198          54 :         return true;
     199             : }
     200             : 
     201             : /**
     202             :  * @brief Split `keys` into two key sets, one for array parents and one for all other keys.
     203             :  *
     204             :  * @param keys This parameter contains the key set this function splits.
     205             :  *
     206             :  * @return A pair of key sets, where the first key set contains all array parents and the second key set contains all other keys
     207             :  */
     208         381 : KeySetPair splitArrayParentsOther (CppKeySet const & keys)
     209             : {
     210         762 :         CppKeySet arrayParents;
     211         762 :         CppKeySet others;
     212             : 
     213         381 :         keys.rewind ();
     214         762 :         CppKey previous;
     215        9150 :         for (previous = keys.next (); keys.next (); previous = keys.current ())
     216             :         {
     217             :                 bool const previousIsArray =
     218        9017 :                         previous.hasMeta ("array") || (keys.current ().isDirectBelow (previous) &&
     219         865 :                                                        keys.current ().getBaseName ()[0] == '#' && isArrayParent (previous, keys));
     220             : 
     221        2288 :                 (previousIsArray ? arrayParents : others).append (previous);
     222             :         }
     223        1905 :         (previous.hasMeta ("array") ? arrayParents : others).append (previous);
     224             : 
     225        1143 :         ELEKTRA_ASSERT (arrayParents.size () + others.size () == keys.size (),
     226             :                         "Number of keys in split key sets: %zu ≠ number in given key set %zu", arrayParents.size () + others.size (),
     227         381 :                         keys.size ());
     228             : 
     229         762 :         return make_pair (arrayParents, others);
     230             : }
     231             : 
     232             : /**
     233             :  * @brief This function splits `keys` into two key sets, one for array parents and elements, and the other one for all other keys.
     234             :  *
     235             :  * @param arrayParents This key set contains a (copy) of all array parents of `keys`.
     236             :  * @param keys This parameter contains the key set this function splits.
     237             :  *
     238             :  * @return A pair of key sets, where the first key set contains all array parents and elements,
     239             :  *         and the second key set contains all other keys
     240             :  */
     241         377 : KeySetPair splitArrayOther (CppKeySet const & arrayParents, CppKeySet const & keys)
     242             : {
     243        1131 :         CppKeySet others = keys.dup ();
     244         754 :         CppKeySet arrays;
     245             : 
     246        1728 :         for (auto parent : arrayParents)
     247             :         {
     248         995 :                 arrays.append (others.cut (parent));
     249             :         }
     250             : 
     251         754 :         return make_pair (arrays, others);
     252             : }
     253             : 
     254             : /**
     255             :  * @brief This function splits `keys` into two key sets, one for empty array parents that do not contain a value and one for all other keys.
     256             :  *
     257             :  * @param arrayParents This key set contains array parents.
     258             :  *
     259             :  * @return A pair of key sets, where the first key set contains all array parents without values, and the second key set contains all other
     260             :  *         keys
     261             :  */
     262         101 : KeySetPair splitEmptyArrayParents (CppKeySet const & arrayParents)
     263             : {
     264         202 :         CppKeySet emptyParents;
     265         202 :         CppKeySet nonEmptyParents;
     266             : 
     267         438 :         for (auto arrayParent : arrayParents)
     268             :         {
     269         135 :                 CppKey parent = arrayParent.dup ();
     270             : 
     271          45 :                 parent.rewindMeta ();
     272          45 :                 size_t metaSize = 0;
     273          45 :                 bool isEmpty = parent.getBinarySize () == 0;
     274         108 :                 while (isEmpty && parent.nextMeta ())
     275             :                 {
     276           0 :                         if (metaSize > 2 || parent.currentMeta ().getName () != "binary" || parent.currentMeta ().getName () != "array")
     277             :                         {
     278           0 :                                 isEmpty = false;
     279             :                         }
     280           0 :                         metaSize++;
     281             :                 }
     282          90 :                 (isEmpty ? emptyParents : nonEmptyParents).append (arrayParent);
     283             :         }
     284         202 :         return make_pair (emptyParents, nonEmptyParents);
     285             : }
     286             : 
     287             : /**
     288             :  * @brief This function changes an array index of the given array element by one.
     289             :  *
     290             :  * @param parent This key set stores an array parent of `element`. The function will change the index of `element` that is directly below
     291             :  *               this key.
     292             :  * @param element This parameter stores an array element.
     293             :  * @param increment This boolean parameter specifies if the function should increase or decrease the index by one.
     294             :  *
     295             :  * @return A key containing a copy of `element`, where the index below `parent` was increased or decreased by one and the value of the
     296             :  *         updated index (e.g. `#_10`)
     297             :  */
     298         202 : pair<CppKey, string> changeArrayIndexByOne (CppKey const & parent, CppKey const & element, bool increment = true)
     299             : {
     300         404 :         CppKey elementNewIndex = convertToDirectChild (parent, element);
     301        1212 :         string postfix = elektraKeyGetRelativeName (*element, *elementNewIndex);
     302             : 
     303         404 :         if (increment ? elektraArrayIncName (*elementNewIndex) : elektraArrayDecName (*elementNewIndex))
     304             :         {
     305           0 :                 throw range_error (string ("Unable to ") + (increment ? "increment" : "decrement") + " index of key “" +
     306           0 :                                    elementNewIndex.getName () + "”");
     307             :         }
     308         404 :         string newIndex = elementNewIndex.getBaseName ();
     309         202 :         elementNewIndex.addName (postfix);
     310             : 
     311             :         ELEKTRA_LOG_DEBUG ("New name of “%s” is “%s”", element.getName ().c_str (), elementNewIndex.getName ().c_str ());
     312             : 
     313         404 :         return make_pair (elementNewIndex, newIndex);
     314             : }
     315             : 
     316             : /**
     317             :  * @brief Decrease the array index of array elements by one.
     318             :  *
     319             :  * @param parents This parameter contains the array parents for which this function decrease the index by one.
     320             :  * @param arrays This variable stores the arrays elements (and parents) this function updates.
     321             :  *
     322             :  * @return A copy of `arrays`, where all indices specified by `parents` are decreased by one
     323             :  */
     324         276 : CppKeySet decreaseArrayIndices (CppKeySet const & parents, CppKeySet const & arrays)
     325             : {
     326         552 :         CppKeySet arraysIndexDecreased = arrays.dup ();
     327         276 :         CppKeySet arrayParents = parents.dup ();
     328             : 
     329         699 :         while (CppKey parent = arrayParents.pop ())
     330             :         {
     331             :                 ELEKTRA_LOG_DEBUG ("Decrease indices for array parent “%s”", parent.getName ().c_str ());
     332             : 
     333         196 :                 parent.setMeta ("array", ""); // Set meta key for empty arrays
     334             : 
     335             :                 arraysIndexDecreased =
     336         294 :                         accumulate (arraysIndexDecreased.begin (), arraysIndexDecreased.end (), CppKeySet{},
     337         605 :                                     [&parent](CppKeySet collected, CppKey key) {
     338         369 :                                             if (key.isBelow (parent))
     339             :                                             {
     340         236 :                                                     string newIndex;
     341         236 :                                                     tie (key, newIndex) = changeArrayIndexByOne (parent, key, false);
     342         708 :                                                     parent.setMeta ("array", newIndex);
     343             :                                                     ELEKTRA_LOG_DEBUG ("New last index of “%s” is “%s”", parent.getName ().c_str (),
     344             :                                                                        parent.getMeta<string> ("array").c_str ());
     345             :                                             }
     346         369 :                                             collected.append (key);
     347         369 :                                             return collected;
     348          49 :                                     });
     349             : 
     350          49 :                 arraysIndexDecreased.append (parent); // Update meta data of parent key in `arrays`
     351             :         }
     352             : 
     353         276 :         return arraysIndexDecreased;
     354             : }
     355             : 
     356             : /**
     357             :  * @brief Increase the array index of array elements by one.
     358             :  *
     359             :  * Since it is also possible that one of the array parents is part of another array, this function also updates the indices of the given
     360             :  * array parents.
     361             :  *
     362             :  * @param parents This parameter contains the array parents for which this function increases the index by one.
     363             :  * @param arrays This variable stores the arrays elements this function updates.
     364             :  *
     365             :  * @return A pair containing a copy of `parents` and `arrays`, where all indices specified by `parents` are increased by one
     366             :  */
     367         103 : KeySetPair increaseArrayIndices (CppKeySet const & parents, CppKeySet const & arrays)
     368             : {
     369         309 :         CppKeySet arraysIncreasedIndex = arrays.dup ();
     370         309 :         CppKeySet arrayParents = parents.dup ();
     371         206 :         CppKeySet updatedParents = parents.dup ();
     372             : 
     373         290 :         while (CppKey parent = arrayParents.pop ())
     374             :         {
     375             :                 ELEKTRA_LOG_DEBUG ("Increase indices for array parent “%s”", parent.getName ().c_str ());
     376             : 
     377          56 :                 CppKeySet newArrays;
     378         852 :                 for (auto key : arraysIncreasedIndex)
     379             :                 {
     380         256 :                         if (key.isBelow (parent))
     381             :                         {
     382         168 :                                 CppKey updated;
     383         168 :                                 tie (updated, ignore) = changeArrayIndexByOne (parent, key);
     384         252 :                                 if (updatedParents.lookup (key, KDB_O_POP)) updatedParents.append (updated);
     385          84 :                                 newArrays.append (updated);
     386             :                         }
     387             :                         else
     388             :                         {
     389             :                                 newArrays.append (key);
     390             :                         }
     391             :                 }
     392          28 :                 arraysIncreasedIndex = newArrays;
     393             :         }
     394             : 
     395         206 :         return make_pair (updatedParents, arraysIncreasedIndex);
     396             : }
     397             : 
     398             : /**
     399             :  * @brief Split `keys` into two key sets, one for directories (keys without children) and one for all other keys.
     400             :  *
     401             :  * @param keys This parameter contains the key set this function splits.
     402             :  *
     403             :  * @return A pair of key sets, where the first key set contains all directories and the second key set contains all leaves
     404             :  */
     405         101 : KeySetPair splitDirectoriesLeaves (CppKeySet const & keys)
     406             : {
     407         202 :         CppKeySet leaves;
     408         202 :         CppKeySet directories;
     409             : 
     410         101 :         keys.rewind ();
     411         202 :         CppKey previous;
     412        2064 :         for (previous = keys.next (); keys.next (); previous = keys.current ())
     413             :         {
     414         972 :                 (keys.current ().isBelow (previous) ? directories : leaves).append (previous);
     415             :         }
     416         101 :         leaves.append (previous);
     417             : 
     418         202 :         return make_pair (directories, leaves);
     419             : }
     420             : 
     421             : /**
     422             :  * @brief Convert all keys in `parents` to an empty array parent and an array element with index `#0` storing the data of the old key.
     423             :  *
     424             :  * @param parents This parameter contains the set of array parent this function converts.
     425             :  *
     426             :  * @return A key set containing only empty array parents and corresponding array elements storing the values of the old array parent
     427             :  */
     428         101 : CppKeySet convertArrayParentsToLeaves (CppKeySet const & parents)
     429             : {
     430         101 :         CppKeySet converted;
     431             : 
     432         375 :         for (auto parent : parents)
     433             :         {
     434          72 :                 CppKey directory{ parent.getName (), KS_END };
     435          72 :                 CppKey leaf = parent.dup ();
     436         120 :                 leaf.delMeta ("array");
     437          96 :                 leaf.addBaseName ("#0");
     438         120 :                 leaf.setString (ARRAY_VALUE_PREFIX + (parent.isBinary () ? "" : (" " + parent.getString ())));
     439          24 :                 converted.append (directory);
     440          24 :                 converted.append (leaf);
     441             :         }
     442             : 
     443         101 :         return converted;
     444             : }
     445             : 
     446             : /**
     447             :  * @brief Convert all keys in `directories` to an empty key and a leaf key containing the data of the old key.
     448             :  *
     449             :  * @param directories This parameter contains a set of directory keys this function converts.
     450             :  *
     451             :  * @return A key set containing only empty directory keys and corresponding leaf keys storing the values of the old directory keys
     452             :  */
     453         101 : CppKeySet convertDirectoriesToLeaves (CppKeySet const & directories)
     454             : {
     455         101 :         CppKeySet directoryLeaves;
     456             : 
     457         504 :         for (auto directory : directories)
     458             :         {
     459         201 :                 CppKey emptyDirectory{ directory.getName (), KS_END };
     460         201 :                 CppKey leaf = directory.dup ();
     461         268 :                 leaf.addBaseName (DIRECTORY_POSTFIX);
     462          67 :                 directoryLeaves.append (leaf);
     463          67 :                 directoryLeaves.append (emptyDirectory);
     464             :         }
     465             : 
     466         101 :         return directoryLeaves;
     467             : }
     468             : 
     469             : // -- Class --------------------------------------------------------------------------------------------------------------------------------
     470             : 
     471             : /**
     472             :  * @brief This constructor creates a new delegate object used by the `directoryvalue` plugin
     473             :  *
     474             :  * @param config This key set contains configuration values provided by the `directoryvalue` plugin
     475             :  */
     476        1138 : DirectoryValueDelegate::DirectoryValueDelegate (CppKeySet config ELEKTRA_UNUSED)
     477             : {
     478        1138 : }
     479             : 
     480             : /**
     481             :  * @brief This method converts all leaf keys in the given key set to directory keys.
     482             :  *
     483             :  * @param keys This parameter specifies the key set this function converts.
     484             :  *
     485             :  * @retval ELEKTRA_PLUGIN_STATUS_SUCCESS If the plugin converted any value in the given key set
     486             :  * @retval ELEKTRA_PLUGIN_STATUS_NO_UPDATE If the plugin did not update `keys`
     487             :  */
     488         276 : int DirectoryValueDelegate::convertToDirectories (CppKeySet & keys)
     489             : {
     490         552 :         CppKeySet directoryLeaves;
     491         552 :         CppKeySet nonDirectoryLeaves;
     492         552 :         CppKeySet arrayParents;
     493         552 :         CppKeySet notArrayParents;
     494         552 :         CppKeySet arrays;
     495         552 :         CppKeySet arrayLeaves;
     496         552 :         CppKeySet maps;
     497             : 
     498             :         /**
     499             :          * - Split array parents
     500             :          * - Split first array child containing directory value prefix, others
     501             :          * - Convert first array child back to array parent
     502             :          * - Decrease index of arrays
     503             :          * - Merge everything back together and convert directories to leaves
     504             :          */
     505             : 
     506        1104 :         tie (arrayParents, ignore) = splitArrayParentsOther (keys);
     507        1104 :         tie (arrays, maps) = splitArrayOther (arrayParents, keys);
     508        1104 :         tie (arrayLeaves, arrays) = splitArrayLeavesOther (arrayParents, arrays);
     509             : 
     510         828 :         arrayParents = convertArrayLeaves (arrayLeaves);
     511         828 :         notArrayParents = decreaseArrayIndices (arrayParents, arrays);
     512         276 :         notArrayParents.append (maps);
     513             : 
     514        1104 :         tie (directoryLeaves, nonDirectoryLeaves) = splitDirectoryLeavesOther (notArrayParents);
     515             : 
     516             :         bool const status =
     517         472 :                 directoryLeaves.size () > 0 || arrayLeaves.size () > 0 ? ELEKTRA_PLUGIN_STATUS_SUCCESS : ELEKTRA_PLUGIN_STATUS_NO_UPDATE;
     518             : 
     519         552 :         auto directories = removeBaseName (directoryLeaves);
     520             : 
     521         276 :         keys.clear ();
     522         276 :         keys.append (nonDirectoryLeaves);
     523         276 :         keys.append (directories);
     524             : 
     525         552 :         return status;
     526             : }
     527             : 
     528             : /**
     529             :  * @brief This method converts all directory keys in the given key set to leaf keys.
     530             :  *
     531             :  * @param keys This parameter specifies the key set this function converts.
     532             :  *
     533             :  * @retval ELEKTRA_PLUGIN_STATUS_SUCCESS If the plugin converted any value in the given key set
     534             :  * @retval ELEKTRA_PLUGIN_STATUS_NO_UPDATE If the plugin did not update `keys`
     535             :  */
     536         101 : int DirectoryValueDelegate::convertToLeaves (CppKeySet & keys)
     537             : {
     538         202 :         CppKeySet notArrayParents;
     539         202 :         CppKeySet arrayParents;
     540         202 :         CppKeySet emptyArrayParents;
     541         202 :         CppKeySet arrays;
     542         202 :         CppKeySet nonArrays;
     543         202 :         CppKeySet directories;
     544         202 :         CppKeySet leaves;
     545             : 
     546         404 :         tie (arrayParents, ignore) = splitArrayParentsOther (keys);
     547         404 :         tie (arrays, nonArrays) = splitArrayOther (arrayParents, keys);
     548             : 
     549         404 :         tie (emptyArrayParents, arrayParents) = splitEmptyArrayParents (arrayParents);
     550         404 :         tie (arrayParents, arrays) = increaseArrayIndices (arrayParents, arrays);
     551             : 
     552         101 :         notArrayParents.append (arrays);
     553         101 :         notArrayParents.append (nonArrays);
     554         606 :         notArrayParents = accumulate (notArrayParents.begin (), notArrayParents.end (), CppKeySet{},
     555         750 :                                       [&arrayParents, &emptyArrayParents](CppKeySet collected, CppKey key) {
     556        2250 :                                               if (!arrayParents.lookup (key) && !emptyArrayParents.lookup (key)) collected.append (key);
     557         387 :                                               return collected;
     558         101 :                                       });
     559         303 :         arrayParents = convertArrayParentsToLeaves (arrayParents);
     560             : 
     561         404 :         tie (directories, leaves) = splitDirectoriesLeaves (notArrayParents);
     562             :         bool const status =
     563         158 :                 directories.size () > 0 || arrayParents.size () > 0 ? ELEKTRA_PLUGIN_STATUS_SUCCESS : ELEKTRA_PLUGIN_STATUS_NO_UPDATE;
     564             : 
     565         202 :         auto directoryLeaves = convertDirectoriesToLeaves (directories);
     566             : 
     567         101 :         keys.clear ();
     568         101 :         keys.append (arrays);
     569         101 :         keys.append (arrayParents);
     570         101 :         keys.append (emptyArrayParents);
     571         101 :         keys.append (directoryLeaves);
     572         101 :         keys.append (leaves);
     573             : 
     574         202 :         return status;
     575             : }
     576             : 
     577             : } // end namespace elektra

Generated by: LCOV version 1.13