LCOV - code coverage report
Current view: top level - benchmarks - benchmarks.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 0 264 0.0 %
Date: 2019-09-12 12:28:41 Functions: 0 18 0.0 %

          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             : #define _GNU_SOURCE
      10             : #include <benchmarks.h>
      11             : #ifdef HAVE_HSEARCHR
      12             : #include <search.h>
      13             : #endif
      14             : #include <sys/time.h>
      15             : 
      16             : struct timeval start;
      17             : int num_dir = NUM_DIR;
      18             : int num_key = NUM_KEY;
      19             : KeySet * large;
      20             : 
      21           0 : void timeInit (void)
      22             : {
      23           0 :         gettimeofday (&start, 0);
      24           0 : }
      25             : 
      26           0 : void timePrint (char * msg)
      27             : {
      28             :         struct timeval measure;
      29             :         time_t diff;
      30             : 
      31           0 :         gettimeofday (&measure, 0);
      32             : 
      33           0 :         diff = (measure.tv_sec - start.tv_sec) * 1000000 + (measure.tv_usec - start.tv_usec);
      34           0 :         fprintf (stdout, "%20s: %20d Microseconds\n", msg, (int) diff);
      35             : 
      36           0 :         gettimeofday (&start, 0);
      37           0 : }
      38             : 
      39           0 : int timeGetDiffMicroseconds (void)
      40             : {
      41             :         struct timeval measure;
      42             :         time_t diff;
      43             : 
      44           0 :         gettimeofday (&measure, 0);
      45           0 :         diff = (measure.tv_sec - start.tv_sec) * 1000000 + (measure.tv_usec - start.tv_usec);
      46           0 :         gettimeofday (&start, 0);
      47             : 
      48           0 :         return (int) diff;
      49             : }
      50             : 
      51           0 : void benchmarkCreate (void)
      52             : {
      53           0 :         large = ksNew (num_key * num_dir, KS_END);
      54           0 : }
      55             : 
      56           0 : void benchmarkFillup (void)
      57             : {
      58             :         int i, j;
      59             :         char name[KEY_NAME_LENGTH + 1];
      60           0 :         char value[] = "data";
      61             : 
      62           0 :         for (i = 0; i < num_dir; i++)
      63             :         {
      64           0 :                 snprintf (name, KEY_NAME_LENGTH, "%s/%s%d", KEY_ROOT, "dir", i);
      65           0 :                 ksAppendKey (large, keyNew (name, KEY_VALUE, value, KEY_END));
      66           0 :                 for (j = 0; j < num_key; j++)
      67             :                 {
      68           0 :                         snprintf (name, KEY_NAME_LENGTH, "%s/%s%d/%s%d", KEY_ROOT, "dir", i, "key", j);
      69           0 :                         ksAppendKey (large, keyNew (name, KEY_VALUE, value, KEY_END));
      70             :                 }
      71             :         }
      72           0 : }
      73             : 
      74             : 
      75             : /**
      76             :  * Arbitrary Key Set Generator
      77             :  */
      78             : 
      79             : 
      80             : /**
      81             :  * Internal representation of the KsTree
      82             :  */
      83             : typedef struct _KsTreeVertex KsTreeVertex;
      84             : struct _KsTreeVertex
      85             : {
      86             :         char * name;                      /*!< name of the vertex, root has no name */
      87             :         uint8_t isKey;                    /*!< when true the path from root to vertex is a Key in the resulting KeySet */
      88             :         uint8_t isLink;                   /*!< determines if vertex is link, used at recFreeKsTree (...) */
      89             :         struct _KsTreeVertex ** children; /*!< stores the children */
      90             : #ifdef HAVE_HSEARCHR
      91             :         struct hsearch_data * htab; /*!< stores the Hash Map, containing the children names */
      92             : #endif
      93             :         size_t numberofChildren; /*!< number of the stored children */
      94             :         size_t mallocSize;       /*!< size malloced for the children */
      95             : };
      96             : 
      97             : /**
      98             :  * Declares the label storage and some config
      99             :  */
     100             : const uint8_t maxNameGenerationTries = 99;
     101             : #define NUMBER_OF_LABELS 10
     102             : static KsTreeVertex * labels[NUMBER_OF_LABELS];
     103             : 
     104             : static void * shapeDefaultInit (void);
     105             : static void shapeDefaultDel (void * data);
     106             : static void shapefDefault (const size_t initSize, size_t size, size_t level, int32_t * seed, KsShapeFunctionReturn * ret, void * data);
     107             : 
     108             : const char * const alphabetnumbers = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789";
     109             : const char * const alphabetspecial = "^!\"$`%&/{([)]=} %?\\+*~#';,:§.-_|<>¸¬½¼³²¹ł€¶øæßð𳽫»¢“”nµ─·";
     110             : 
     111             : 
     112             : #ifdef HAVE_HSEARCHR
     113             : /**
     114             :  * @brief Creates the Hash Map for a given vertex.
     115             :  *
     116             :  * vertex->mallocSize must be set.
     117             :  *
     118             :  * @param vertex the vertex
     119             :  */
     120           0 : static void createHashMap (KsTreeVertex * vertex)
     121             : {
     122           0 :         vertex->htab = elektraCalloc (sizeof (struct hsearch_data));
     123           0 :         if (!vertex->htab || !hcreate_r (vertex->mallocSize, vertex->htab))
     124             :         {
     125           0 :                 printExit ("recGenerateKsTree: can not create Hash Map");
     126             :         }
     127           0 : }
     128             : 
     129             : /**
     130             :  * @brief Deletes the Hash Map for a given vertex.
     131             :  *
     132             :  * @param vertex the vertex
     133             :  */
     134             : static void deleteHashMap (KsTreeVertex * vertex)
     135             : {
     136           0 :         hdestroy_r (vertex->htab);
     137           0 :         elektraFree (vertex->htab);
     138             : }
     139             : /**
     140             :  * @brief Searches in the Hash Map of vertex for the name.
     141             :  *
     142             :  * If not in vertex insert it.
     143             :  *
     144             :  * @param vertex the vertex
     145             :  * @param name the name to search
     146             :  *
     147             :  * @retval 1 if not in vertex, unique
     148             :  * @retval 0 if in vertex, not unique
     149             :  */
     150           0 : static int searchHashMap (KsTreeVertex * vertex, char * name)
     151             : {
     152             :         ENTRY e;
     153             :         ENTRY * ep;
     154           0 :         e.key = name;
     155           0 :         e.data = NULL;
     156           0 :         if (!hsearch_r (e, FIND, &ep, vertex->htab))
     157             :         {
     158             :                 // not in Hash Map, insert
     159           0 :                 if (!hsearch_r (e, ENTER, &ep, vertex->htab))
     160             :                 {
     161           0 :                         printExit ("recGenerateKsTree: can not insert in Hash Map");
     162             :                 }
     163             :                 return 1;
     164             :         }
     165             :         else
     166             :         {
     167             :                 return 0;
     168             :         }
     169             : }
     170             : #else
     171             : // no hsearch use dummys and linear search
     172             : static void createHashMap (KsTreeVertex * vertex ELEKTRA_UNUSED)
     173             : {
     174             : }
     175             : static void deleteHashMap (KsTreeVertex * vertex ELEKTRA_UNUSED)
     176             : {
     177             : }
     178             : static int searchHashMap (KsTreeVertex * vertex, char * name)
     179             : {
     180             :         for (size_t i = 0; i < vertex->numberofChildren; ++i)
     181             :         {
     182             :                 if (!strcmp (vertex->children[i]->name, name))
     183             :                 {
     184             :                         return 0;
     185             :                 }
     186             :         }
     187             :         return 1;
     188             : }
     189             : #endif
     190             : 
     191             : /**
     192             :  * @brief Fills a string up with random chars and null terminates it.
     193             :  *
     194             :  * @param name the string
     195             :  * @param length the length of the string (excluding the '\0')
     196             :  * @param seed to generate random data
     197             :  * @param shape the shape of the KeySet
     198             :  */
     199           0 : static void fillUpWithRandomChars (char * name, size_t length, int32_t * seed, KeySetShape * shape)
     200             : {
     201             :         // throw the dice and use 8 bit of each byte from seed for one char, determination if special or not and which
     202           0 :         elektraRand (seed);
     203           0 :         size_t i = 0;
     204           0 :         size_t s = i;
     205           0 :         char * c = name;
     206           0 :         bool done = false;
     207           0 :         while (!done)
     208             :         {
     209           0 :                 uint8_t ds = (*seed >> (8 * s * 2)) & 0xFF;
     210           0 :                 uint8_t dc = (*seed >> (8 * (s * 2 + 1))) & 0xFF;
     211             :                 // special or not
     212           0 :                 bool special = shape->special && (ds % shape->special) == 0;
     213             :                 // choose
     214           0 :                 if (special)
     215             :                 {
     216           0 :                         *c = alphabetspecial[dc % strlen (alphabetspecial)];
     217             :                 }
     218             :                 else
     219             :                 {
     220           0 :                         *c = alphabetnumbers[dc % strlen (alphabetnumbers)];
     221             :                 }
     222           0 :                 ++c;
     223           0 :                 ++i;
     224           0 :                 ++s;
     225           0 :                 if (i == length)
     226             :                 {
     227             :                         done = true;
     228             :                 }
     229           0 :                 else if (s == 2)
     230             :                 {
     231           0 :                         elektraRand (seed);
     232           0 :                         s = 0;
     233             :                 }
     234             :         }
     235           0 :         *c = '\0';
     236           0 : }
     237             : 
     238             : /**
     239             :  * @brief Recursively calculate the number of vertices with isKey set to 1 starting from vertex.
     240             :  *
     241             :  * @param vertex the staring
     242             :  */
     243           0 : static size_t getSizeOfVertex (KsTreeVertex * vertex)
     244             : {
     245           0 :         size_t size = 0;
     246           0 :         if (vertex->isKey)
     247             :         {
     248           0 :                 ++size;
     249             :         }
     250           0 :         for (size_t i = 0; i < vertex->numberofChildren; ++i)
     251             :         {
     252           0 :                 size += getSizeOfVertex (vertex->children[i]);
     253             :         }
     254           0 :         return size;
     255             : }
     256             : 
     257             : /**
     258             :  * @brief Generate a name for a vertex.
     259             :  *
     260             :  * Generates a name and looks in the parent if the name is unique, if not try until maxNameGenerationTries * (maxLength - length + 1)
     261             :  * is exceeded. The length is extended every maxNameGenerationTries by one until maxWordLength is reached.
     262             :  *
     263             :  * @param parent the parent vertex
     264             :  * @param seed the seed for random actions, already randomized
     265             :  * @param shape the KeySetShape
     266             :  *
     267             :  * @retval char * the generated name
     268             :  */
     269           0 : static char * generateName (KsTreeVertex * parent, int32_t * seed, KeySetShape * shape)
     270             : {
     271           0 :         char * out = elektraMalloc ((shape->maxWordLength + 1) * sizeof (char));
     272           0 :         if (!out)
     273             :         {
     274           0 :                 printExit ("recGenerateKsTree: malloc vertex->name");
     275             :         }
     276           0 :         int32_t dl = *seed & 0xFFFFFF;
     277           0 :         size_t length = (dl % (shape->maxWordLength - shape->minWordLength + 1)) + shape->minWordLength;
     278             :         uint8_t uniqueName;
     279           0 :         uint8_t nameGenerationTries = 0;
     280             :         do
     281             :         {
     282             :                 // generate name and see if name is unique
     283           0 :                 fillUpWithRandomChars (out, length, seed, shape);
     284           0 :                 uniqueName = searchHashMap (parent, out);
     285           0 :                 ++nameGenerationTries;
     286           0 :                 if (nameGenerationTries > maxNameGenerationTries && !uniqueName)
     287             :                 {
     288             :                         // make word longer if possible
     289           0 :                         if (length < shape->maxWordLength)
     290             :                         {
     291             : 
     292           0 :                                 ++length;
     293             :                                 // start new
     294           0 :                                 nameGenerationTries = 0;
     295             :                         }
     296             :                         else
     297             :                         {
     298           0 :                                 printExit ("recGenerateKsTree: max name generation tries exceeded");
     299             :                         }
     300             :                 }
     301           0 :         } while (!uniqueName);
     302           0 :         return out;
     303             : }
     304             : 
     305             : /**
     306             :  * @brief Recursively generates a KsTree.
     307             :  *
     308             :  * Every invocation generates a vertex. First the name and after the KeySetShape->shapef invocation the children by recursion.
     309             :  *
     310             :  * @param parent the parent vertex
     311             :  * @param size the target number of vertices where isKey is 1
     312             :  * @param actualSize the number of vertices where isKey is 1 so far
     313             :  * @param level the actual level
     314             :  * @param seed the seed for random actions
     315             :  * @param shape the KeySetShape
     316             :  * @param data the data passed to the KeySetShape->shapef function
     317             :  *
     318             :  * @retval KsTreeVertex * the generated vertex
     319             :  */
     320           0 : static KsTreeVertex * recGenerateKsTree (KsTreeVertex * parent, const size_t size, size_t * actualSize, size_t level, int32_t * seed,
     321             :                                          KeySetShape * shape, void * data)
     322             : {
     323             :         // create actual vertex
     324           0 :         KsTreeVertex * vertex = elektraMalloc (sizeof (KsTreeVertex));
     325           0 :         if (!vertex)
     326             :         {
     327           0 :                 printExit ("recGenerateKsTree: malloc vertex");
     328             :         }
     329             :         // default not a key
     330           0 :         vertex->isKey = 0;
     331           0 :         elektraRand (seed);
     332             :         // used for parent determination
     333           0 :         int8_t dp = *seed >> 24;
     334             :         // vertex name generation
     335           0 :         vertex->name = generateName (parent, seed, shape);
     336             :         // determine subKeys and label
     337             :         KsShapeFunctionReturn ret;
     338           0 :         shape->shapef (size, *actualSize, level, seed, &ret, data);
     339             :         // if too many set max
     340           0 :         if (ret.subKeys > (ssize_t) *actualSize + 1)
     341             :         {
     342           0 :                 ret.subKeys = *actualSize;
     343             :         }
     344           0 :         if (ret.subKeys >= 0)
     345             :         {
     346           0 :                 vertex->isLink = 0;
     347             :                 // vertex children generation
     348           0 :                 if (ret.subKeys > 0)
     349             :                 {
     350             :                         // create branch
     351             :                         // remove costs for subkeys
     352           0 :                         *actualSize -= (ret.subKeys - 1); // the cost for one is included in the size from the parent call
     353             :                         // see if parent
     354           0 :                         if (*actualSize && shape->parent && (dp % shape->parent) == 0)
     355             :                         {
     356             :                                 // counts extra so costs need to be removed
     357           0 :                                 --*actualSize;
     358           0 :                                 vertex->isKey = 1;
     359             :                         }
     360             :                         // prepare children
     361           0 :                         vertex->numberofChildren = 0;
     362           0 :                         vertex->mallocSize = ret.subKeys;
     363           0 :                         createHashMap (vertex);
     364           0 :                         vertex->children = elektraMalloc (vertex->mallocSize * sizeof (KsTreeVertex *));
     365           0 :                         if (!vertex->children)
     366             :                         {
     367           0 :                                 printExit ("recGenerateKsTree: malloc children");
     368             :                         }
     369           0 :                         ++level;
     370             :                         // make children
     371           0 :                         for (size_t i = 0; i < vertex->mallocSize; ++i)
     372             :                         {
     373           0 :                                 vertex->children[i] = recGenerateKsTree (vertex, size, actualSize, level, seed, shape, data);
     374           0 :                                 ++vertex->numberofChildren;
     375             :                         }
     376             :                 }
     377             :                 else
     378             :                 {
     379             :                         // terminate branch
     380           0 :                         vertex->isKey = 1;
     381           0 :                         vertex->numberofChildren = 0;
     382             :                 }
     383           0 :                 if (ret.label)
     384             :                 {
     385             :                         // set label at vertex
     386           0 :                         if (ret.label > NUMBER_OF_LABELS)
     387             :                         {
     388           0 :                                 printExit ("recGenerateKsTree: label > NUMBER_OF_LABELS");
     389             :                         }
     390           0 :                         --ret.label;
     391           0 :                         labels[ret.label] = vertex;
     392             :                 }
     393             :         }
     394             :         else
     395             :         {
     396             :                 // links will not be followed by recFreeKsTree (...)
     397           0 :                 vertex->isLink = 1;
     398           0 :                 if (!ret.label || ret.label > NUMBER_OF_LABELS)
     399             :                 {
     400           0 :                         printExit ("recGenerateKsTree: subKeys < 0 but no label set or label > NUMBER_OF_LABELS");
     401             :                 }
     402             :                 // take children from label vertex
     403           0 :                 --ret.label;
     404           0 :                 KsTreeVertex * linkVertex = labels[ret.label];
     405             :                 // copy children, if space actualSize includes the costs for the actual key
     406           0 :                 size_t linkTreeSize = getSizeOfVertex (linkVertex) - 1;
     407             :                 // linkVertex->isKey will not be copied, so remove it from size if set
     408           0 :                 if (linkVertex->isKey)
     409             :                 {
     410           0 :                         --linkTreeSize;
     411             :                 }
     412           0 :                 if (*actualSize >= linkTreeSize)
     413             :                 {
     414           0 :                         vertex->mallocSize = linkVertex->mallocSize;
     415           0 :                         vertex->numberofChildren = linkVertex->numberofChildren;
     416           0 :                         vertex->children = linkVertex->children;
     417           0 :                         *actualSize -= linkTreeSize;
     418             :                         // link has children so it can have a parent
     419           0 :                         if (*actualSize && shape->parent && (dp % shape->parent) == 0)
     420             :                         {
     421             :                                 // counts extra so costs need to be removed
     422           0 :                                 --*actualSize;
     423           0 :                                 vertex->isKey = 1;
     424             :                         }
     425             :                 }
     426             :                 else
     427             :                 {
     428             :                         // if no space terminate branch
     429           0 :                         vertex->numberofChildren = 0;
     430           0 :                         vertex->isKey = 1;
     431             :                 }
     432             :         }
     433           0 :         return vertex;
     434             : }
     435             : 
     436             : /**
     437             :  * @brief Transforms a given branch of the KsTree to a KeySet.
     438             :  *
     439             :  * The KeySet and Key must be initialized. Every vertex with isKey set will be a Key in the resulting KeySet.
     440             :  * The resulting Key name is every KsTreeVertex->name in the path from root to vertex.
     441             :  *
     442             :  * @param ks the KeySet
     443             :  * @param key the actual Key
     444             :  * @param vertex starting point
     445             :  *
     446             :  * @retval KeySet * the resulting KeySet
     447             :  */
     448           0 : static void recGenerateKeySet (KeySet * ks, Key * key, KsTreeVertex * vertex)
     449             : {
     450             :         // add name to key
     451           0 :         if (keyAddBaseName (key, vertex->name) < 0)
     452             :         {
     453           0 :                 printExit ("recGenerateKeySet: Can not add KeyBaseName ");
     454             :         }
     455             :         // add if Key
     456           0 :         if (vertex->isKey)
     457             :         {
     458           0 :                 Key * dupKey = keyDup (key);
     459           0 :                 if (!dupKey)
     460             :                 {
     461           0 :                         printExit ("recGenerateKeySet: Can not dup Key");
     462             :                 }
     463           0 :                 ssize_t sizeBefore = ksGetSize (ks);
     464           0 :                 if (ksAppendKey (ks, dupKey) < 0)
     465             :                 {
     466           0 :                         printExit ("recGenerateKeySet: Can not add Key");
     467             :                 }
     468           0 :                 if (sizeBefore == ksGetSize (ks))
     469             :                 {
     470           0 :                         printExit ("recGenerateKeySet: Add Key with on effect");
     471             :                 }
     472             :         }
     473             :         // go to children
     474           0 :         for (size_t i = 0; i < vertex->numberofChildren; ++i)
     475             :         {
     476           0 :                 Key * dupKey = keyDup (key);
     477           0 :                 if (!dupKey)
     478             :                 {
     479           0 :                         printExit ("recGenerateKeySet: Can not dup Key");
     480             :                 }
     481           0 :                 recGenerateKeySet (ks, dupKey, vertex->children[i]);
     482             :         }
     483           0 :         keyDel (key);
     484           0 : }
     485             : 
     486             : /**
     487             :  * @brief Frees recursively to whole KsTree under the passed vertex.
     488             :  *
     489             :  * @param vertex the start vertex
     490             :  */
     491           0 : static void recFreeKsTree (KsTreeVertex * vertex)
     492             : {
     493           0 :         if (!vertex->isLink)
     494             :         {
     495           0 :                 for (size_t i = 0; i < vertex->numberofChildren; ++i)
     496             :                 {
     497           0 :                         recFreeKsTree (vertex->children[i]);
     498             :                 }
     499             :         }
     500           0 :         if (vertex->name) elektraFree (vertex->name);
     501           0 :         if (vertex->numberofChildren && !vertex->isLink)
     502             :         {
     503           0 :                 elektraFree (vertex->children);
     504           0 :                 deleteHashMap (vertex);
     505             :         }
     506           0 :         elektraFree (vertex);
     507           0 : }
     508             : 
     509             : /**
     510             :  * @brief Generates a KeySet.
     511             :  *
     512             :  * Generates a KsTree and transforms the KsTree to the resulting KeySet.
     513             :  *
     514             :  * @param size the desired KeySet size
     515             :  * @param seed the seed for the random generation
     516             :  * @param shape the KeySetShape
     517             :  *
     518             :  * @retval KeySet * the resulting KeySet
     519             :  */
     520           0 : KeySet * generateKeySet (const size_t size, int32_t * seed, KeySetShape * shape)
     521             : {
     522           0 :         ELEKTRA_ASSERT (size > 4, "size < 5");
     523           0 :         int32_t defaultSeed = 1;
     524           0 :         if (!seed)
     525             :         {
     526           0 :                 seed = &defaultSeed;
     527             :         }
     528             :         KeySetShape shapeDefault;
     529           0 :         if (!shape)
     530             :         {
     531             :                 /**
     532             :                  * Default KeySetShape
     533             :                  */
     534           0 :                 shapeDefault.parent = 3;
     535           0 :                 shapeDefault.special = 50;
     536           0 :                 shapeDefault.minWordLength = 4;
     537           0 :                 shapeDefault.maxWordLength = 7;
     538           0 :                 shapeDefault.shapeInit = shapeDefaultInit;
     539           0 :                 shapeDefault.shapef = shapefDefault;
     540           0 :                 shapeDefault.shapeDel = shapeDefaultDel;
     541             : 
     542           0 :                 shape = &shapeDefault;
     543             :         }
     544           0 :         ELEKTRA_ASSERT (shape->minWordLength <= shape->maxWordLength, "minWordLength > maxWordLength");
     545           0 :         ELEKTRA_ASSERT (shape->maxWordLength - shape->minWordLength <= 16777215, "max world length variation exceeded 16777215");
     546           0 :         ELEKTRA_ASSERT (shape->parent <= 127, "parent > 127");
     547           0 :         ELEKTRA_ASSERT (shape->special <= 127, "parent > 127");
     548           0 :         ELEKTRA_ASSERT (shape->minWordLength != 0, "minWordLength is 0");
     549           0 :         ELEKTRA_ASSERT (shape->maxWordLength != 0, "maxWordLength is 0");
     550           0 :         ELEKTRA_ASSERT (shape->shapef, "shape->shapef");
     551           0 :         ELEKTRA_ASSERT ((shape->shapeInit && shape->shapeDel) || (!shape->shapeInit && !shape->shapeDel),
     552             :                         "shape->shapeInit or shape->shapeDel not set");
     553             :         // init data
     554           0 :         void * data = NULL;
     555           0 :         if (shape->shapeInit)
     556             :         {
     557           0 :                 data = shape->shapeInit ();
     558           0 :                 if (!data)
     559             :                 {
     560           0 :                         printExit ("generateKeySet: shapeInit returned NULL");
     561             :                 }
     562             :         }
     563             :         // create root and init root
     564           0 :         KsTreeVertex * root = elektraMalloc (sizeof (KsTreeVertex));
     565           0 :         if (!root)
     566             :         {
     567           0 :                 printExit ("generateKeySet: malloc root vertex");
     568             :         }
     569           0 :         root->name = NULL;
     570           0 :         root->isKey = 0;
     571           0 :         root->isLink = 0;
     572           0 :         root->mallocSize = size;
     573           0 :         createHashMap (root);
     574           0 :         root->numberofChildren = 0;
     575           0 :         root->children = elektraMalloc (root->mallocSize * sizeof (KsTreeVertex *));
     576           0 :         if (!root->children)
     577             :         {
     578           0 :                 printExit ("generateKeySet: root children malloc");
     579             :         }
     580             :         // generate ksTree
     581           0 :         size_t actualSize = size;
     582           0 :         while (actualSize)
     583             :         {
     584           0 :                 --actualSize;
     585           0 :                 root->children[root->numberofChildren] = recGenerateKsTree (root, size, &actualSize, 1, seed, shape, data);
     586           0 :                 ++root->numberofChildren;
     587             :         }
     588             :         // del data
     589           0 :         if (shape->shapeDel)
     590             :         {
     591           0 :                 shape->shapeDel (data);
     592             :         }
     593             :         // generate KeySet out of KsTree
     594           0 :         KeySet * ks = ksNew (size, KS_END);
     595           0 :         if (!ks)
     596             :         {
     597           0 :                 printExit ("generateKeySet: Can not create KeySet");
     598             :         }
     599           0 :         for (size_t i = 0; i < root->numberofChildren; ++i)
     600             :         {
     601           0 :                 Key * key = keyNew ("", KEY_END);
     602           0 :                 if (!key)
     603             :                 {
     604           0 :                         printExit ("generateKeySet: Can not create Key");
     605             :                 }
     606           0 :                 recGenerateKeySet (ks, key, root->children[i]);
     607             :         }
     608             :         // delete KsTree
     609           0 :         recFreeKsTree (root);
     610           0 :         return ks;
     611             : }
     612             : 
     613             : /**
     614             :  * Default KeySetShape
     615             :  *
     616             :  * Create two labels at second level and use them constantly.
     617             :  * The KeySet with default seed and 20 elements looks like:
     618             :  *
     619             :  * /6iyrg67
     620             :  * /6iyrg67/CFQK5/t24RHQJ/mvh*Hr
     621             :  * /6iyrg67/CFQK5/wxaP1Ar
     622             :  * /6iyrg67/CFQK5/wxaP1Ar/7'FE
     623             :  * /6iyrg67/jdEm/EYFex
     624             :  * /6iyrg67/jdEm/EYFex/nGH5z
     625             :  * /6iyrg67/jdEm/c5oY8cj/nd3C5L
     626             :  * /KZUr/TWNK/EYFex
     627             :  * /KZUr/TWNK/EYFex/nGH5z
     628             :  * /KZUr/TWNK/c5oY8cj/nd3C5L
     629             :  * /KZUr/csj9t/t24RHQJ/mvh*Hr
     630             :  * /KZUr/csj9t/wxaP1Ar
     631             :  * /KZUr/csj9t/wxaP1Ar/7'FE
     632             :  * /u002/sACrr
     633             :  * /u002/sACrr/EYFex
     634             :  * /u002/sACrr/EYFex/nGH5z
     635             :  * /u002/sACrr/c5oY8cj/nd3C5L
     636             :  * /u002/y10bqcj/t24RHQJ/mvh*Hr
     637             :  * /u002/y10bqcj/wxaP1Ar
     638             :  * /u002/y10bqcj/wxaP1Ar/7'FE
     639             :  */
     640           0 : static void * shapeDefaultInit (void)
     641             : {
     642           0 :         void * data = elektraMalloc (3 * sizeof (uint8_t));
     643           0 :         if (!data)
     644             :         {
     645             :                 return NULL;
     646             :         }
     647           0 :         uint8_t * b = data;
     648             :         // three boolean flags
     649           0 :         b[0] = 0; // if first label was set
     650           0 :         b[1] = 0; // if second label was set
     651           0 :         b[2] = 0; // alternation bit, to use the labels
     652           0 :         return data;
     653             : }
     654           0 : static void shapeDefaultDel (void * data)
     655             : {
     656           0 :         elektraFree (data);
     657           0 : }
     658           0 : static void shapefDefault (const size_t initSize ELEKTRA_UNUSED, size_t size ELEKTRA_UNUSED, size_t level, int32_t * seed ELEKTRA_UNUSED,
     659             :                            KsShapeFunctionReturn * ret, void * data)
     660             : {
     661           0 :         uint8_t * labelSet = data;
     662           0 :         if (level == 1)
     663             :         {
     664             :                 // create 2 keys
     665           0 :                 ret->subKeys = 2;
     666           0 :                 ret->label = 0;
     667             :         }
     668           0 :         else if (level == 2)
     669             :         {
     670           0 :                 if (!labelSet[0] && !labelSet[1])
     671             :                 {
     672             :                         // no label set, so set the first one
     673           0 :                         ret->subKeys = 2;
     674           0 :                         ret->label = 1;
     675           0 :                         labelSet[0] = 1;
     676             :                 }
     677           0 :                 else if (labelSet[0] && !labelSet[1])
     678             :                 {
     679             :                         // first one set, so set the second
     680           0 :                         ret->subKeys = 2;
     681           0 :                         ret->label = 2;
     682           0 :                         labelSet[1] = 1;
     683             :                 }
     684             :                 else
     685             :                 {
     686             :                         // both set, alternation to assign
     687           0 :                         ret->subKeys = -1;
     688           0 :                         if (labelSet[2])
     689             :                         {
     690           0 :                                 ret->label = 1;
     691           0 :                                 labelSet[2] = 0;
     692             :                         }
     693             :                         else
     694             :                         {
     695           0 :                                 ret->label = 2;
     696           0 :                                 labelSet[2] = 1;
     697             :                         }
     698             :                 }
     699             :         }
     700           0 :         else if (level == 3)
     701             :         {
     702             :                 // some names after labels
     703           0 :                 ret->subKeys = 1;
     704           0 :                 ret->label = 0;
     705             :         }
     706             :         else
     707             :         {
     708             :                 // terminate branch
     709           0 :                 ret->subKeys = 0;
     710           0 :                 ret->label = 0;
     711             :         }
     712           0 : }
     713             : 
     714             : /**
     715             :  * @brief Print message to stderr and exit with failure code.
     716             :  *
     717             :  * @param msg the message
     718             :  */
     719           0 : void printExit (const char * msg)
     720             : {
     721           0 :         fprintf (stderr, "FATAL: %s\n", msg);
     722           0 :         exit (EXIT_FAILURE);
     723             : }

Generated by: LCOV version 1.13