LCOV - code coverage report
Current view: top level - collection - collection_tools.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 30 292 10.3 %
Date: 2014-04-01 Functions: 2 13 15.4 %

          Line data    Source code
       1             : /*
       2             :     COLLECTION LIBRARY
       3             : 
       4             :     Additional functions for printing and debugging collections.
       5             : 
       6             :     Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
       7             : 
       8             :     Collection Library is free software: you can redistribute it and/or modify
       9             :     it under the terms of the GNU Lesser General Public License as published by
      10             :     the Free Software Foundation, either version 3 of the License, or
      11             :     (at your option) any later version.
      12             : 
      13             :     Collection Library is distributed in the hope that it will be useful,
      14             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :     GNU Lesser General Public License for more details.
      17             : 
      18             :     You should have received a copy of the GNU Lesser General Public License
      19             :     along with Collection Library.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "config.h"
      23             : #include <stdio.h>
      24             : #include <malloc.h>
      25             : #include <errno.h>
      26             : #include <string.h>
      27             : #include "trace.h"
      28             : #include "collection_priv.h"
      29             : #include "collection.h"
      30             : #include "collection_tools.h"
      31             : 
      32             : /* Debug handle */
      33           0 : int col_debug_handle(const char *property,
      34             :                      int property_len,
      35             :                      int type,
      36             :                      void *data,
      37             :                      int length,
      38             :                      void *custom_data,
      39             :                      int *dummy)
      40             : {
      41             :     int i;
      42             :     int nest_level;
      43           0 :     int ignore = 0;
      44             : 
      45             :     TRACE_FLOW_STRING("col_debug_handle", "Entry.");
      46             : 
      47             : 
      48           0 :     nest_level = *(int *)(custom_data);
      49           0 :     if (nest_level == -1) {
      50           0 :         ignore = 1;
      51           0 :         nest_level = 1;
      52             :     }
      53             : 
      54             :     TRACE_INFO_NUMBER("We are getting this pointer:", custom_data);
      55             :     TRACE_INFO_NUMBER("Nest level:", nest_level);
      56             : 
      57           0 :     switch (type) {
      58             :     case COL_TYPE_STRING:
      59           0 :         printf(">%*s%s[%d] str: %s (%d)\n",
      60           0 :                (nest_level -1) * 4, "",
      61             :                property,
      62             :                length,
      63             :                (char *)(data),
      64             :                nest_level);
      65           0 :         break;
      66             :     case COL_TYPE_BINARY:
      67           0 :         printf(">%*s%s[%d] bin: ",
      68           0 :                (nest_level -1) * 4, "",
      69             :                property,
      70             :                length);
      71           0 :         for (i = 0; i < length; i++)
      72           0 :             printf("%02X", ((unsigned char *)(data))[i]);
      73           0 :         printf(" (%d)\n", nest_level);
      74           0 :         break;
      75             :     case COL_TYPE_INTEGER:
      76           0 :         printf(">%*s%s[%d] int: %d (%d)\n",
      77           0 :                (nest_level -1) * 4, "",
      78             :                property,
      79             :                length,
      80             :                *((int32_t *)(data)),
      81             :                nest_level);
      82           0 :         break;
      83             :     case COL_TYPE_UNSIGNED:
      84           0 :         printf(">%*s%s[%d] uint: %u (%d)\n",
      85           0 :                (nest_level -1) * 4, "",
      86             :                property,
      87             :                length,
      88             :                *((uint32_t *)(data)),
      89             :                nest_level);
      90           0 :         break;
      91             :     case COL_TYPE_LONG:
      92           0 :         printf(">%*s%s[%d] long: %lld (%d)\n",
      93           0 :                (nest_level -1) * 4, "",
      94             :                property,
      95             :                length,
      96             :                (long long int)(*((int64_t *)(data))),
      97             :                nest_level);
      98           0 :         break;
      99             :     case COL_TYPE_ULONG:
     100           0 :         printf(">%*s%s[%d] ulong: %llu (%d)\n",
     101           0 :                (nest_level -1) * 4, "",
     102             :                property,
     103             :                length,
     104             :                (long long unsigned)(*((uint64_t *)(data))),
     105             :                nest_level);
     106           0 :         break;
     107             :     case COL_TYPE_DOUBLE:
     108           0 :         printf(">%*s%s[%d] double: %.4f (%d)\n",
     109           0 :                (nest_level -1) * 4, "",
     110             :                property,
     111             :                length,
     112             :                *((double *)(data)),
     113             :                nest_level);
     114           0 :         break;
     115             :     case COL_TYPE_BOOL:
     116           0 :         printf(">%*s%s[%d] bool: %s (%d)\n",
     117           0 :                (nest_level -1) * 4, "",
     118             :                property,
     119             :                length,
     120           0 :                (*((unsigned char *)(data)) == '\0') ? "false" : "true",
     121             :                nest_level);
     122           0 :         break;
     123             :     case COL_TYPE_COLLECTION:
     124           0 :         if (!ignore) nest_level++;
     125           0 :         printf(">%*s%s[%d] header: count %d, ref_count %d class %d data: ",
     126           0 :                (nest_level -1) * 4, "",
     127             :                property,
     128             :                length,
     129             :                ((struct collection_header *)(data))->count,
     130             :                ((struct collection_header *)(data))->reference_count,
     131             :                ((struct collection_header *)(data))->cclass);
     132             : /* Due to padding issues this is unsafe so ifdefed for now */
     133             : #ifdef COL_PRINT_BINARY_HEADER
     134             :         for (i = 0; i < length; i++)
     135             :             printf("%02X", ((unsigned char *)(data))[i]);
     136             : #endif
     137           0 :         printf(" (%d)\n", nest_level);
     138           0 :         break;
     139             :     case COL_TYPE_COLLECTIONREF:
     140           0 :         printf(">%*s%s[%d] external link: ",
     141           0 :                (nest_level -1) * 4, "",
     142             :                property,
     143             :                length);
     144           0 :         for (i = 0; i < length; i++)
     145           0 :             printf("%02X", ((unsigned char *)(data))[i]);
     146           0 :         printf(" (%d)\n", nest_level);
     147           0 :         break;
     148             :     case COL_TYPE_END:
     149           0 :         printf(">%*sEND[N/A] (%d)\n",
     150           0 :                (nest_level -1) * 4, "",
     151             :                nest_level);
     152           0 :         if (!ignore) nest_level--;
     153           0 :         break;
     154             :     default:
     155           0 :         printf("Not implemented yet.\n");
     156           0 :         break;
     157             :     }
     158           0 :     *(int *)(custom_data) = nest_level;
     159             :     TRACE_INFO_NUMBER("Nest level at the end:", nest_level);
     160             :     TRACE_FLOW_STRING("col_debug_handle", "Success exit.");
     161           0 :     return EOK;
     162             : }
     163             : 
     164             : /* Convenience function to debug an item */
     165           0 : inline int col_debug_item(struct collection_item *item)
     166             : {
     167           0 :     int dummy = 0;
     168           0 :     int nest_level = -1;
     169           0 :     return col_debug_handle(item->property,
     170             :                             item->property_len,
     171             :                             item->type,
     172             :                             item->data,
     173             :                             item->length,
     174             :                             (void *)(&nest_level),
     175             :                             &dummy);
     176             : }
     177             : 
     178             : 
     179             : /* Print collection for debugging purposes */
     180           0 : int col_debug_collection(struct collection_item *handle, int flag)
     181             : {
     182           0 :     int error = EOK;
     183           0 :     int nest_level = 0;
     184             : 
     185             :     TRACE_FLOW_STRING("col_debug_collection", "Entry.");
     186             : 
     187           0 :     printf("DEBUG COLLECTION %s\n", handle->property);
     188             : 
     189           0 :     flag |= COL_TRAVERSE_END;
     190             : 
     191           0 :     printf("Traverse flags %d\n", flag);
     192             : 
     193             :     /* Traverse collection */
     194           0 :     error = col_traverse_collection(handle, flag,
     195             :                                     col_debug_handle,
     196             :                                     (void *)(&nest_level));
     197           0 :     if (error) printf("Error debuging collection %d\n", error);
     198             : 
     199             :     TRACE_FLOW_STRING("col_debug_collection", "Exit.");
     200           0 :     return error;
     201             : }
     202             : 
     203             : 
     204             : /* Return a static string based on type of the element */
     205             : static inline const char *col_get_type(int type)
     206             : {
     207             :     switch (type) {
     208             :     case COL_TYPE_STRING:
     209             :         return COL_TYPE_NAME_STRING;
     210             : 
     211             :     case COL_TYPE_INTEGER:
     212             :         return COL_TYPE_NAME_INTEGER;
     213             : 
     214             :     case COL_TYPE_UNSIGNED:
     215             :         return COL_TYPE_NAME_UNSIGNED;
     216             : 
     217             :     case COL_TYPE_LONG:
     218             :         return COL_TYPE_NAME_LONG;
     219             : 
     220             :     case COL_TYPE_ULONG:
     221             :         return COL_TYPE_NAME_ULONG;
     222             : 
     223             :     case COL_TYPE_BINARY:
     224             :         return COL_TYPE_NAME_BINARY;
     225             : 
     226             :     case COL_TYPE_DOUBLE:
     227             :         return COL_TYPE_NAME_DOUBLE;
     228             : 
     229             :     case COL_TYPE_BOOL:
     230             :         return COL_TYPE_NAME_BOOL;
     231             : 
     232             :     default:
     233             :         return COL_TYPE_NAME_UNKNOWN;
     234             :     }
     235             : 
     236             : }
     237             : 
     238             : /* Calculate the potential size of the item */
     239           0 : int col_get_data_len(int type, int length)
     240             : {
     241           0 :     int len = 0;
     242             : 
     243             :     TRACE_FLOW_STRING("col_get_data_len", "Entry point");
     244             : 
     245           0 :     switch (type) {
     246             :     case COL_TYPE_INTEGER:
     247             :     case COL_TYPE_UNSIGNED:
     248           0 :         len = 11;
     249           0 :                 break;
     250             :     case COL_TYPE_LONG:
     251             :     case COL_TYPE_ULONG:
     252           0 :         len = 20;
     253           0 :         break;
     254             : 
     255             :     case COL_TYPE_STRING:
     256             :     case COL_TYPE_BINARY:
     257           0 :         len = length * 2 + 2;
     258           0 :         break;
     259             : 
     260             :     case COL_TYPE_DOUBLE:
     261           0 :         len = 64;
     262           0 :         break;
     263             : 
     264             :     case COL_TYPE_BOOL:
     265           0 :         len = 6;
     266           0 :         break;
     267             : 
     268             :     default:
     269           0 :         len = 0;
     270           0 :         break;
     271             :     }
     272             : 
     273             :     TRACE_FLOW_STRING("col_get_data_len","Exit point");
     274             : 
     275           0 :     return len;
     276             : }
     277             : 
     278             : /* Copy data escaping characters */
     279           0 : static int col_copy_esc(char *dest, const char *source, char esc)
     280             : {
     281           0 :     int i = 0;
     282           0 :     int j = 0;
     283             : 
     284           0 :     dest[j] = esc;
     285           0 :     j++;
     286             : 
     287           0 :     while (source[i]) {
     288           0 :         if ((source[i] == '\\') ||
     289           0 :             (source[i] == esc)) {
     290             : 
     291           0 :             dest[j] = '\\';
     292           0 :             j++;
     293             : 
     294             :         }
     295           0 :         dest[j] = source[i];
     296           0 :         i++;
     297           0 :         j++;
     298             :     }
     299           0 :     dest[j] = esc;
     300           0 :     j++;
     301             : 
     302           0 :     return j;
     303             : }
     304             : 
     305             : /* Grow buffer to accomodate more space */
     306           0 : int col_grow_buffer(struct col_serial_data *buf_data, int len)
     307             : {
     308             :     char *tmp;
     309             : 
     310             :     TRACE_FLOW_STRING("col_grow_buffer", "Entry point");
     311             :     TRACE_INFO_NUMBER("Current length: ", buf_data->length);
     312             :     TRACE_INFO_NUMBER("Increment length: ", len);
     313             :     TRACE_INFO_NUMBER("Expected length: ", buf_data->length+len);
     314             :     TRACE_INFO_NUMBER("Current size: ", buf_data->size);
     315             : 
     316             :     /* Grow buffer if needed */
     317           0 :     while (buf_data->length+len >= buf_data->size) {
     318           0 :         tmp = realloc(buf_data->buffer, buf_data->size + BLOCK_SIZE);
     319           0 :         if (tmp == NULL) {
     320             :             TRACE_ERROR_NUMBER("Error. Failed to allocate memory.", ENOMEM);
     321           0 :             return ENOMEM;
     322             :         }
     323           0 :         buf_data->buffer = tmp;
     324           0 :         buf_data->size += BLOCK_SIZE;
     325             :         TRACE_INFO_NUMBER("New size: ", buf_data->size);
     326             : 
     327             :     }
     328             : 
     329             :     TRACE_INFO_NUMBER("Final size: ", buf_data->size);
     330             :     TRACE_FLOW_STRING("col_grow_buffer", "Success Exit.");
     331           0 :     return EOK;
     332             : }
     333             : 
     334             : /* Specail function to add different formatting symbols to the output */
     335           0 : int col_put_marker(struct col_serial_data *buf_data, const void *data, int len)
     336             : {
     337           0 :     int error = EOK;
     338             : 
     339             :     TRACE_FLOW_STRING("col_put_marker", "Entry point");
     340             :     TRACE_INFO_NUMBER("Marker length: ", len);
     341             : 
     342           0 :     error = col_grow_buffer(buf_data, len);
     343           0 :     if (error) {
     344             :         TRACE_ERROR_NUMBER("col_grow_buffer failed with: ", error);
     345           0 :         return error;
     346             :     }
     347           0 :     memcpy(buf_data->buffer + buf_data->length, data, len);
     348           0 :     buf_data->length += len;
     349           0 :     buf_data->buffer[buf_data->length] = '\0';
     350             : 
     351             :     TRACE_FLOW_STRING("col_put_marker","Success exit");
     352           0 :     return error;
     353             : }
     354             : 
     355             : /* Add item's data */
     356           0 : int col_serialize(const char *property_in,
     357             :                   int property_len_in,
     358             :                   int type,
     359             :                   void *data_in,
     360             :                   int length_in,
     361             :                   void *custom_data,
     362             :                   int *dummy)
     363             : {
     364             :     int len;
     365             :     struct col_serial_data *buf_data;
     366             :     const char *property;
     367             :     const void *data;
     368             :     int  property_len;
     369             :     int length;
     370           0 :     int error = EOK;
     371             :     int i;
     372             : 
     373             :     TRACE_FLOW_STRING("col_serialize","Entry point");
     374             : 
     375           0 :     *dummy = 0;
     376             : 
     377             :     /* Check is there is buffer. If not allocate */
     378           0 :     buf_data = (struct col_serial_data *)custom_data;
     379           0 :     if (buf_data == NULL) {
     380             :         TRACE_ERROR_STRING("Error.", "Storage data is not passed in!");
     381           0 :         return EINVAL;
     382             :     }
     383           0 :     if (buf_data->buffer == NULL) {
     384             :         TRACE_INFO_STRING("First time use.", "Allocating buffer.");
     385           0 :         buf_data->buffer = malloc(BLOCK_SIZE);
     386           0 :         if (buf_data->buffer == NULL) {
     387             :             TRACE_ERROR_NUMBER("Error. Failed to allocate memory.", ENOMEM);
     388           0 :             return ENOMEM;
     389             :         }
     390           0 :         buf_data->buffer[0] = '\0';
     391           0 :         buf_data->length = 0;
     392           0 :         buf_data->size = BLOCK_SIZE;
     393             :     }
     394             : 
     395             :     TRACE_INFO_NUMBER("Buffer len: ", buf_data->length);
     396             :     TRACE_INFO_NUMBER("Buffer size: ", buf_data->size);
     397             :     TRACE_INFO_STRING("Buffer: ", buf_data->buffer);
     398             : 
     399             :     /* Check the beginning of the collection */
     400           0 :     if (type == COL_TYPE_COLLECTION) {
     401             :         TRACE_INFO_STRING("Serializing collection: ", property_in);
     402             :         TRACE_INFO_STRING("First header. ", "");
     403           0 :         error = col_put_marker(buf_data, "(", 1);
     404           0 :         if (error != EOK) return error;
     405           0 :         property = TEXT_COLLECTION;
     406           0 :         property_len = TEXT_COLLEN;
     407           0 :         data = property_in;
     408           0 :         length = property_len_in + 1;
     409           0 :         type = COL_TYPE_STRING;
     410           0 :         buf_data->nest_level++;
     411             :     }
     412             :     /* Check for subcollections */
     413           0 :     else if (type == COL_TYPE_COLLECTIONREF) {
     414             :         /* Skip */
     415             :         TRACE_FLOW_STRING("col_serialize", "skip reference return");
     416           0 :         return EOK;
     417             :     }
     418             :     /* Check for the end of the collection */
     419           0 :     else if (type == COL_TYPE_END) {
     420           0 :         if ((buf_data->length > 0) &&
     421           0 :             (buf_data->buffer[buf_data->length-1] == ',')) {
     422           0 :             buf_data->length--;
     423           0 :             buf_data->buffer[buf_data->length] = '\0';
     424             :         }
     425           0 :         if (buf_data->nest_level > 0) {
     426           0 :             buf_data->nest_level--;
     427           0 :             error = col_put_marker(buf_data, ")", 1);
     428           0 :             if (error != EOK) return error;
     429             :         }
     430             :         TRACE_FLOW_STRING("col_serialize", "end collection item processed returning");
     431           0 :         return EOK;
     432             :     }
     433             :     else {
     434           0 :         property = property_in;
     435           0 :         property_len = property_len_in;
     436           0 :         data = data_in;
     437           0 :         length = length_in;
     438             :     }
     439             : 
     440             :     TRACE_INFO_STRING("Property: ", property);
     441             :     TRACE_INFO_NUMBER("Property length: ", property_len);
     442             : 
     443             :     /* Start with property and "=" */
     444           0 :     if ((error = col_put_marker(buf_data, property, property_len)) ||
     445             :         (error = col_put_marker(buf_data, "=", 1))) {
     446             :         TRACE_ERROR_NUMBER("put_marker returned error: ", error);
     447           0 :         return error;
     448             :     }
     449             :     /* Get projected length of the item */
     450           0 :     len = col_get_data_len(type,length);
     451             :     TRACE_INFO_NUMBER("Expected data length: ",len);
     452             :     TRACE_INFO_STRING("Buffer so far: ", buf_data->buffer);
     453             : 
     454             :     /* Make sure we have enough space */
     455           0 :     if ((error = col_grow_buffer(buf_data, len))) {
     456             :         TRACE_ERROR_NUMBER("grow_buffer returned error: ", error);
     457           0 :         return error;
     458             :     }
     459             : 
     460             :     /* Add the value */
     461           0 :     switch (type) {
     462             :     case COL_TYPE_STRING:
     463             :         /* Escape double quotes */
     464           0 :         len = col_copy_esc(&buf_data->buffer[buf_data->length],
     465             :                            (const char *)(data), '"');
     466           0 :         break;
     467             : 
     468             :     /* Here and below it is safe to use sprintf() becuase we
     469             :      * already pre-calculated the length and allocated buffer
     470             :      * of the right size.
     471             :      */
     472             : 
     473             :     case COL_TYPE_BINARY:
     474           0 :         buf_data->buffer[buf_data->length] = '\'';
     475           0 :         for (i = 0; i < length; i++)
     476           0 :             sprintf(&buf_data->buffer[buf_data->length + i *2] + 1,
     477           0 :                     "%02X", (unsigned int)(((const unsigned char *)(data))[i]));
     478           0 :         len = length * 2 + 1;
     479           0 :         buf_data->buffer[buf_data->length + len] = '\'';
     480           0 :         len++;
     481           0 :         break;
     482             : 
     483             :     case COL_TYPE_INTEGER:
     484           0 :         len = sprintf(&buf_data->buffer[buf_data->length],
     485             :                       "%d", *((const int32_t *)(data)));
     486           0 :         break;
     487             : 
     488             :     case COL_TYPE_UNSIGNED:
     489           0 :         len = sprintf(&buf_data->buffer[buf_data->length],
     490             :                       "%u", *((const uint32_t *)(data)));
     491           0 :         break;
     492             : 
     493             :     case COL_TYPE_LONG:
     494           0 :         len = sprintf(&buf_data->buffer[buf_data->length],
     495             :                       "%lld",
     496             :                       (long long int)(*((const int64_t *)(data))));
     497           0 :         break;
     498             : 
     499             :     case COL_TYPE_ULONG:
     500           0 :         len = sprintf(&buf_data->buffer[buf_data->length],
     501             :                       "%llu",
     502             :                       (long long unsigned)(*((const uint64_t *)(data))));
     503           0 :         break;
     504             : 
     505             :     case COL_TYPE_DOUBLE:
     506           0 :         len = sprintf(&buf_data->buffer[buf_data->length],
     507             :                       "%.4f", *((const double *)(data)));
     508           0 :         break;
     509             : 
     510             :     case COL_TYPE_BOOL:
     511           0 :         len = sprintf(&buf_data->buffer[buf_data->length],
     512           0 :                       "%s", (*((const unsigned char *)(data))) ? "true" : "false");
     513           0 :         break;
     514             : 
     515             :     default:
     516           0 :         buf_data->buffer[buf_data->length] = '\0';
     517           0 :         len = 0;
     518           0 :         break;
     519             :     }
     520             : 
     521             :     /* Adjust length */
     522           0 :     buf_data->length += len;
     523           0 :     buf_data->buffer[buf_data->length] = '\0';
     524             : 
     525             :     /* Always put a comma at the end */
     526           0 :     error = col_put_marker(buf_data, ",", 1);
     527           0 :     if (error != EOK) {
     528             :         TRACE_ERROR_NUMBER("put_marker returned error: ", error);
     529           0 :         return error;
     530             :     }
     531             : 
     532             :     TRACE_INFO_STRING("Data: ", buf_data->buffer);
     533             :     TRACE_FLOW_STRING("col_serialize", "Exit point");
     534           0 :     return EOK;
     535             : 
     536             : }
     537             : 
     538             : /* Print the collection using default serialization */
     539           0 : int col_print_collection(struct collection_item *handle)
     540             : {
     541             :     struct col_serial_data buf_data;
     542           0 :     int error = EOK;
     543             : 
     544             :     TRACE_FLOW_STRING("col_print_collection", "Entry");
     545             : 
     546           0 :     printf("COLLECTION:\n");
     547             : 
     548           0 :     buf_data.buffer = NULL;
     549           0 :     buf_data.length = 0;
     550           0 :     buf_data.size = 0;
     551           0 :     buf_data.nest_level = 0;
     552             : 
     553             :     /* Traverse collection */
     554           0 :     error = col_traverse_collection(handle,
     555             :                                     COL_TRAVERSE_DEFAULT | COL_TRAVERSE_END ,
     556             :                                     col_serialize, (void *)(&buf_data));
     557           0 :     if (error)
     558           0 :         printf("Error traversing collection %d\n", error);
     559             :     else
     560           0 :         printf("%s\n", buf_data.buffer);
     561             : 
     562           0 :     free(buf_data.buffer);
     563             : 
     564             :     TRACE_FLOW_NUMBER("col_print_collection returning", error);
     565           0 :     return error;
     566             : }
     567             : 
     568             : /* Print the collection using iterator */
     569           0 : int col_print_collection2(struct collection_item *handle)
     570             : {
     571           0 :     struct collection_iterator *iterator = NULL;
     572           0 :     int error = EOK;
     573           0 :     struct collection_item *item = NULL;
     574           0 :     int nest_level = 0;
     575           0 :     int dummy = 0;
     576           0 :     int line = 1;
     577             : 
     578             :     TRACE_FLOW_STRING("col_print_collection2", "Entry");
     579             : 
     580             :     /* If we have something to print print it */
     581           0 :     if (handle == NULL) {
     582             :         TRACE_ERROR_STRING("No error list", "");
     583           0 :         return EINVAL;
     584             :     }
     585             : 
     586             :     /* Bind iterator */
     587           0 :     error = col_bind_iterator(&iterator, handle,
     588             :                               COL_TRAVERSE_DEFAULT |
     589             :                               COL_TRAVERSE_END |
     590             :                               COL_TRAVERSE_SHOWSUB);
     591           0 :     if (error) {
     592             :         TRACE_ERROR_NUMBER("Error (bind):", error);
     593           0 :         return error;
     594             :     }
     595             : 
     596             :     do {
     597             :         /* Loop through a collection */
     598           0 :         error = col_iterate_collection(iterator, &item);
     599           0 :         if (error) {
     600             :             TRACE_ERROR_NUMBER("Error (iterate):", error);
     601           0 :             col_unbind_iterator(iterator);
     602           0 :             return error;
     603             :         }
     604             : 
     605             :         /* Are we done ? */
     606           0 :         if (item == NULL) break;
     607             : 
     608           0 :         if (item->type != COL_TYPE_END) printf("%05d", line);
     609             : 
     610           0 :         col_debug_handle(item->property,
     611           0 :                          item->property_len,
     612           0 :                          item->type,
     613           0 :                          item->data,
     614           0 :                          item->length,
     615             :                          (void *)(&nest_level),
     616             :                          &dummy);
     617           0 :         line++;
     618             :     }
     619           0 :     while(1);
     620             : 
     621             :     /* Do not forget to unbind iterator - otherwise there will be a leak */
     622           0 :     col_unbind_iterator(iterator);
     623             : 
     624             :     TRACE_INFO_STRING("col_print_collection2", "Exit");
     625           0 :     return EOK;
     626             : }
     627             : 
     628             : /* Find and print one item using default serialization */
     629           0 : int col_print_item(struct collection_item *handle, const char *name)
     630             : {
     631             :     struct col_serial_data buf_data;
     632           0 :     int error = EOK;
     633             : 
     634             :     TRACE_FLOW_STRING("col_print_item", "Entry");
     635             : 
     636           0 :     printf("PRINT ITEM:\n");
     637             : 
     638           0 :     buf_data.buffer = NULL;
     639           0 :     buf_data.length = 0;
     640           0 :     buf_data.size = 0;
     641           0 :     buf_data.nest_level = 0;
     642             : 
     643           0 :     error =  col_get_item_and_do(handle, name, COL_TYPE_ANY,
     644             :                                  COL_TRAVERSE_DEFAULT,
     645             :                                  col_serialize, &buf_data);
     646           0 :     if(error) printf("Error searching collection %d\n", error);
     647             :     else {
     648           0 :         if (buf_data.buffer != NULL) {
     649           0 :             if (buf_data.length > 0) buf_data.length--;
     650           0 :             buf_data.buffer[buf_data.length] = '\0',
     651           0 :             printf("%s\n", buf_data.buffer);
     652           0 :             free(buf_data.buffer);
     653             :         }
     654             :         else {
     655           0 :             printf("Name %s is not found in the collection %s.\n",
     656             :                    name, handle->property);
     657             :         }
     658             :     }
     659             : 
     660             :     TRACE_FLOW_NUMBER("col_print_item returning", error);
     661           0 :     return error;
     662             : }
     663             : 
     664             : /* Function to free the list of properties. */
     665          32 : void col_free_property_list(char **str_list)
     666             : {
     667          32 :     int current = 0;
     668             : 
     669             :     TRACE_FLOW_STRING("col_free_property_list","Entry");
     670             : 
     671          32 :     if (str_list != NULL) {
     672         228 :         while(str_list[current]) {
     673         164 :             free(str_list[current]);
     674         164 :             current++;
     675             :         }
     676          32 :         free(str_list);
     677             :     }
     678             : 
     679             :     TRACE_FLOW_STRING("col_free_property_list","Exit");
     680          32 : }
     681             : 
     682             : 
     683             : /* Convert collection to list of properties */
     684           6 : char **col_collection_to_list(struct collection_item *handle, int *size, int *error)
     685             : {
     686             :     struct collection_iterator *iterator;
     687           6 :     struct collection_item *item = NULL;
     688             :     char **list;
     689             :     unsigned count;
     690             :     int err;
     691           6 :     int current = 0;
     692             : 
     693             :     TRACE_FLOW_STRING("col_collection_to_list","Entry");
     694             : 
     695             :     /* Get number of the subsections */
     696           6 :     err = col_get_collection_count(handle, &count);
     697           6 :     if (err) {
     698             :         TRACE_ERROR_NUMBER("Failed to get count of items from collection.", err);
     699           0 :         if (error) *error = err;
     700           0 :         return NULL;
     701             :     }
     702             : 
     703             :     /* Allocate memory for the sections */
     704           6 :     list = (char **)malloc(count * sizeof(char *));
     705           6 :     if (list == NULL) {
     706             :         TRACE_ERROR_NUMBER("Failed to get allocate memory.", ENOMEM);
     707           0 :         if (error) *error = ENOMEM;
     708           0 :         return NULL;
     709             :     }
     710             : 
     711             :     /* Now iterate to fill in the sections */
     712             :     /* Bind iterator */
     713           6 :     err =  col_bind_iterator(&iterator, handle, COL_TRAVERSE_ONELEVEL);
     714           6 :     if (err) {
     715             :         TRACE_ERROR_NUMBER("Failed to bind.", err);
     716           0 :         if (error) *error = err;
     717           0 :         free(list);
     718           0 :         return NULL;
     719             :     }
     720             : 
     721             :     while(1) {
     722             :         /* Loop through a collection */
     723          86 :         err = col_iterate_collection(iterator, &item);
     724          86 :         if (err) {
     725             :             TRACE_ERROR_NUMBER("Failed to iterate collection", err);
     726           0 :             if (error) *error = err;
     727           0 :             col_free_property_list(list);
     728           0 :             col_unbind_iterator(iterator);
     729           0 :             return NULL;
     730             :         }
     731             : 
     732             :         /* Are we done ? */
     733          86 :         if (item == NULL) break;
     734             : 
     735             :         TRACE_INFO_STRING("Property:", col_get_item_property(item, NULL));
     736             : 
     737             :         /* Skip head */
     738          80 :         if(col_get_item_type(item) == COL_TYPE_COLLECTION) continue;
     739             : 
     740             : 
     741             :         /* Allocate memory for the new string */
     742          74 :         list[current] = strdup(col_get_item_property(item, NULL));
     743          74 :         if (list[current] == NULL) {
     744             :             TRACE_ERROR_NUMBER("Failed to dup string.", ENOMEM);
     745           0 :             if (error) *error = ENOMEM;
     746           0 :             col_free_property_list(list);
     747           0 :             return NULL;
     748             :         }
     749          74 :         current++;
     750          80 :     }
     751             : 
     752           6 :     list[current] = NULL;
     753             : 
     754             :     /* Do not forget to unbind iterator - otherwise there will be a leak */
     755           6 :     col_unbind_iterator(iterator);
     756             : 
     757           6 :     if (size) *size = (int)(count - 1);
     758           6 :     if (error) *error = EOK;
     759             : 
     760             :     TRACE_FLOW_STRING("col_collection_to_list returning", ((list == NULL) ? "NULL" : list[0]));
     761           6 :     return list;
     762             : }

Generated by: LCOV version 1.10