LCOV - code coverage report
Current view: top level - src/plugins/reference - referencegraph.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 59 82 72.0 %
Date: 2019-09-12 12:28:41 Functions: 9 10 90.0 %

          Line data    Source code
       1             : #include "referencegraph.h"
       2             : #include <kdb.h>
       3             : #include <kdbease.h>
       4             : #include <kdbhelper.h>
       5             : #include <stdlib.h>
       6             : 
       7             : struct _RefGraph
       8             : {
       9             :         KeySet * inner;
      10             :         KeySet * leaves;
      11             : };
      12             : 
      13          12 : RefGraph * rgNew (void)
      14             : {
      15          12 :         RefGraph * graph = elektraCalloc (sizeof (struct _RefGraph));
      16          12 :         graph->inner = ksNew (0, KS_END);
      17          12 :         graph->leaves = ksNew (0, KS_END);
      18          12 :         return graph;
      19             : }
      20             : 
      21           8 : RefGraph * rgDup (const RefGraph * source)
      22             : {
      23           8 :         RefGraph * graph = elektraCalloc (sizeof (struct _RefGraph));
      24           8 :         graph->inner = ksDup (source->inner);
      25           8 :         graph->leaves = ksDup (source->leaves);
      26           8 :         return graph;
      27             : }
      28             : 
      29          26 : bool rgHasLeaf (const RefGraph * graph)
      30             : {
      31          26 :         return ksGetSize (graph->leaves) > 0;
      32             : }
      33             : 
      34         116 : bool rgContains (const RefGraph * graph, const char * nodeName)
      35             : {
      36         116 :         return ksLookupByName (graph->inner, nodeName, 0) != NULL;
      37             : }
      38             : 
      39          26 : bool rgEmpty (const RefGraph * graph)
      40             : {
      41          26 :         return ksGetSize (graph->inner) == 0 && ksGetSize (graph->leaves) == 0;
      42             : }
      43             : 
      44          52 : bool rgAddEdge (RefGraph * graph, const char * fromNode, const char * toNode)
      45             : {
      46          52 :         Key * node = ksLookupByName (graph->leaves, fromNode, KDB_O_POP);
      47          52 :         if (node != NULL)
      48             :         {
      49          40 :                 keySetMeta (node, "last", "#0");
      50          40 :                 keySetMeta (node, "#0", toNode);
      51             : 
      52          40 :                 ksAppendKey (graph->inner, node);
      53          40 :                 return true;
      54             :         }
      55             : 
      56          12 :         node = ksLookupByName (graph->inner, fromNode, 0);
      57          12 :         if (node == NULL)
      58             :         {
      59             :                 return false;
      60             :         }
      61             : 
      62          12 :         Key * lastKey = keyDup (keyGetMeta (node, "last"));
      63          12 :         if (elektraArrayIncName (lastKey) < 0)
      64             :         {
      65          12 :                 keyDel (lastKey);
      66          12 :                 return false;
      67             :         }
      68             : 
      69           0 :         keySetMeta (node, "last", keyName (lastKey));
      70           0 :         keySetMeta (node, keyName (lastKey), toNode);
      71           0 :         keyDel (lastKey);
      72             : 
      73           0 :         return true;
      74             : }
      75             : 
      76         114 : void rgAddNode (RefGraph * graph, const char * nodeName)
      77             : {
      78         114 :         Key * node = keyNew (nodeName, KEY_END);
      79         114 :         ksAppendKey (graph->leaves, node);
      80         114 : }
      81             : 
      82           0 : const char * rgGetEdge (RefGraph * graph, const char * fromNode, int index)
      83             : {
      84           0 :         Key * node = ksLookupByName (graph->inner, fromNode, 0);
      85           0 :         if (node == NULL)
      86             :         {
      87             :                 return NULL;
      88             :         }
      89             : 
      90             :         char elem[ELEKTRA_MAX_ARRAY_SIZE];
      91           0 :         elektraWriteArrayNumber (elem, index);
      92             : 
      93           0 :         const Key * k = keyGetMeta (node, elem);
      94           0 :         return k == NULL ? NULL : keyString (k);
      95             : }
      96             : 
      97          16 : void rgRemoveLeaves (RefGraph * graph)
      98             : {
      99          16 :         KeySet * newLeaves = ksNew (0, KS_END);
     100          16 :         KeySet * newInner = ksNew (0, KS_END);
     101             : 
     102             :         Key * cur;
     103          62 :         while ((cur = ksPop (graph->inner)) != NULL)
     104             :         {
     105          30 :                 const char * last = keyString (keyGetMeta (cur, "last"));
     106          30 :                 last++;
     107          60 :                 while (*last == '_')
     108             :                 {
     109           0 :                         last++;
     110             :                 }
     111          30 :                 long size = strtol (last, NULL, 10);
     112             : 
     113             :                 char elem[ELEKTRA_MAX_ARRAY_SIZE];
     114          30 :                 for (int i = 0; i < size; ++i)
     115             :                 {
     116           0 :                         elektraWriteArrayNumber (elem, i);
     117           0 :                         const Key * toNode = keyGetMeta (cur, elem);
     118           0 :                         if (ksLookupByName (graph->leaves, keyString (toNode), 0) != NULL)
     119             :                         {
     120           0 :                                 keySetMeta (cur, elem, NULL);
     121             :                         }
     122             :                 }
     123             : 
     124             :                 int write = 0;
     125           0 :                 for (int read = 0; read < size; ++read, ++write)
     126             :                 {
     127           0 :                         elektraWriteArrayNumber (elem, read);
     128             : 
     129             :                         const Key * toNode;
     130           0 :                         while ((toNode = keyGetMeta (cur, elem)) == NULL && read < size)
     131             :                         {
     132           0 :                                 read++;
     133             :                         }
     134             : 
     135           0 :                         if (read >= size)
     136             :                         {
     137             :                                 break;
     138             :                         }
     139             : 
     140           0 :                         elektraWriteArrayNumber (elem, write);
     141           0 :                         keySetMeta (cur, elem, keyString (toNode));
     142             :                 }
     143          30 :                 elektraWriteArrayNumber (elem, write);
     144          30 :                 keySetMeta (cur, "last", elem);
     145             : 
     146          30 :                 if (write == 0)
     147             :                 {
     148          30 :                         ksAppendKey (newLeaves, cur);
     149             :                 }
     150             :                 else
     151             :                 {
     152           0 :                         ksAppendKey (newInner, cur);
     153             :                 }
     154             : 
     155          30 :                 keyDel (cur);
     156             :         }
     157             : 
     158          16 :         ksClear (graph->leaves);
     159          16 :         ksAppend (graph->leaves, newLeaves);
     160          16 :         ksClear (graph->inner);
     161          16 :         ksAppend (graph->inner, newInner);
     162             : 
     163          16 :         ksDel (newLeaves);
     164          16 :         ksDel (newInner);
     165          16 : }
     166             : 
     167          20 : void rgDel (RefGraph * graph)
     168             : {
     169          20 :         ksDel (graph->inner);
     170          20 :         ksDel (graph->leaves);
     171          20 :         elektraFree (graph);
     172          20 : }

Generated by: LCOV version 1.13