back to topotato report
topotato coverage report
Current view: top level - lib - csv.c (source / functions) Hit Total Coverage
Test: test_ospf_topo1.py::OSPFTopo1Test Lines: 0 341 0.0 %
Date: 2023-02-24 18:38:32 Functions: 0 23 0.0 %

          Line data    Source code
       1             : /* CSV
       2             :  * Copyright (C) 2013,2020  Cumulus Networks, Inc.
       3             :  *
       4             :  * This file is part of Quagga.
       5             :  *
       6             :  * Quagga is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * Quagga is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #ifdef HAVE_CONFIG_H
      22             : #include "config.h"
      23             : #endif
      24             : 
      25             : #include <zebra.h>
      26             : 
      27             : #include <stdio.h>
      28             : #include <stdlib.h>
      29             : #include <string.h>
      30             : #include <stdarg.h>
      31             : #include <assert.h>
      32             : #include <sys/queue.h>
      33             : #include <fcntl.h>
      34             : #include <unistd.h>
      35             : #include "csv.h"
      36             : 
      37             : #define DEBUG_E 1
      38             : #define DEBUG_V 1
      39             : 
      40             : #define log_error(fmt, ...)                                                    \
      41             :         do {                                                                   \
      42             :                 if (DEBUG_E)                                                   \
      43             :                         fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__,          \
      44             :                                 __LINE__, __func__, ##__VA_ARGS__);            \
      45             :         } while (0)
      46             : 
      47             : #define log_verbose(fmt, ...)                                                  \
      48             :         do {                                                                   \
      49             :                 if (DEBUG_V)                                                   \
      50             :                         fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__,          \
      51             :                                 __LINE__, __func__, __VA_ARGS__);              \
      52             :         } while (0)
      53             : 
      54             : struct _csv_field_t_ {
      55             :         TAILQ_ENTRY(_csv_field_t_) next_field;
      56             :         char *field;
      57             :         int field_len;
      58             : };
      59             : 
      60             : struct _csv_record_t_ {
      61             :         TAILQ_HEAD(, _csv_field_t_) fields;
      62             :         TAILQ_ENTRY(_csv_record_t_) next_record;
      63             :         char *record;
      64             :         int rec_len;
      65             : };
      66             : 
      67             : struct _csv_t_ {
      68             :         TAILQ_HEAD(, _csv_record_t_) records;
      69             :         char *buf;
      70             :         int buflen;
      71             :         int csv_len;
      72             :         int pointer;
      73             :         int num_recs;
      74             : };
      75             : 
      76             : 
      77           0 : int csvlen(csv_t *csv)
      78             : {
      79           0 :         return (csv->csv_len);
      80             : }
      81             : 
      82           0 : csv_t *csv_init(csv_t *csv, char *buf, int buflen)
      83             : {
      84           0 :         if (csv == NULL) {
      85           0 :                 csv = malloc(sizeof(csv_t));
      86           0 :                 if (csv == NULL) {
      87           0 :                         log_error("CSV Malloc failed\n");
      88           0 :                         return NULL;
      89             :                 }
      90             :         }
      91           0 :         memset(csv, 0, sizeof(csv_t));
      92             : 
      93           0 :         csv->buf = buf;
      94           0 :         csv->buflen = buflen;
      95           0 :         TAILQ_INIT(&(csv->records));
      96           0 :         return (csv);
      97             : }
      98             : 
      99           0 : void csv_clean(csv_t *csv)
     100             : {
     101           0 :         csv_record_t *rec;
     102           0 :         csv_record_t *rec_n;
     103             : 
     104           0 :         rec = TAILQ_FIRST(&(csv->records));
     105           0 :         while (rec != NULL) {
     106           0 :                 rec_n = TAILQ_NEXT(rec, next_record);
     107           0 :                 csv_remove_record(csv, rec);
     108           0 :                 rec = rec_n;
     109             :         }
     110           0 : }
     111             : 
     112           0 : void csv_free(csv_t *csv)
     113             : {
     114           0 :         if (csv != NULL) {
     115           0 :                 free(csv);
     116             :         }
     117           0 : }
     118             : 
     119           0 : static void csv_init_record(csv_record_t *record)
     120             : {
     121           0 :         TAILQ_INIT(&(record->fields));
     122           0 :         record->rec_len = 0;
     123             : }
     124             : 
     125           0 : csv_record_t *csv_record_iter(csv_t *csv)
     126             : {
     127           0 :         return (TAILQ_FIRST(&(csv->records)));
     128             : }
     129             : 
     130           0 : csv_record_t *csv_record_iter_next(csv_record_t *rec)
     131             : {
     132           0 :         if (!rec)
     133             :                 return NULL;
     134           0 :         return (TAILQ_NEXT(rec, next_record));
     135             : }
     136             : 
     137           0 : char *csv_field_iter(csv_record_t *rec, csv_field_t **fld)
     138             : {
     139           0 :         if (!rec)
     140             :                 return NULL;
     141           0 :         *fld = TAILQ_FIRST(&(rec->fields));
     142           0 :         return ((*fld)->field);
     143             : }
     144             : 
     145           0 : char *csv_field_iter_next(csv_field_t **fld)
     146             : {
     147           0 :         *fld = TAILQ_NEXT(*fld, next_field);
     148           0 :         if ((*fld) == NULL) {
     149             :                 return NULL;
     150             :         }
     151           0 :         return ((*fld)->field);
     152             : }
     153             : 
     154           0 : int csv_field_len(csv_field_t *fld)
     155             : {
     156           0 :         if (fld) {
     157           0 :                 return fld->field_len;
     158             :         }
     159             :         return 0;
     160             : }
     161             : 
     162           0 : static void csv_decode_record(csv_record_t *rec)
     163             : {
     164           0 :         char *curr = rec->record;
     165           0 :         char *field;
     166           0 :         csv_field_t *fld;
     167             : 
     168           0 :         field = strpbrk(curr, ",");
     169           0 :         while (field != NULL) {
     170           0 :                 fld = malloc(sizeof(csv_field_t));
     171           0 :                 if (fld) {
     172           0 :                         TAILQ_INSERT_TAIL(&(rec->fields), fld, next_field);
     173           0 :                         fld->field = curr;
     174           0 :                         fld->field_len = field - curr;
     175             :                 }
     176           0 :                 curr = field + 1;
     177           0 :                 field = strpbrk(curr, ",");
     178             :         }
     179           0 :         field = strstr(curr, "\n");
     180           0 :         if (!field)
     181             :                 return;
     182             : 
     183           0 :         fld = malloc(sizeof(csv_field_t));
     184           0 :         if (fld) {
     185           0 :                 fld->field = curr;
     186           0 :                 fld->field_len = field - curr;
     187           0 :                 TAILQ_INSERT_TAIL(&(rec->fields), fld, next_field);
     188             :         }
     189             : }
     190             : 
     191           0 : static csv_field_t *csv_add_field_to_record(csv_t *csv, csv_record_t *rec,
     192             :                                             char *col)
     193             : {
     194           0 :         csv_field_t *fld;
     195           0 :         char *str = rec->record;
     196           0 :         int rlen = rec->rec_len;
     197           0 :         int blen = csv->buflen;
     198             : 
     199           0 :         fld = malloc(sizeof(csv_field_t));
     200           0 :         if (!fld) {
     201           0 :                 log_error("field malloc failed\n");
     202             :                 /* more cleanup needed */
     203           0 :                 return NULL;
     204             :         }
     205           0 :         TAILQ_INSERT_TAIL(&(rec->fields), fld, next_field);
     206           0 :         fld->field = str + rlen;
     207           0 :         fld->field_len = snprintf((str + rlen), (blen - rlen), "%s", col);
     208           0 :         rlen += fld->field_len;
     209           0 :         rec->rec_len = rlen;
     210           0 :         return fld;
     211             : }
     212             : 
     213           0 : csv_record_t *csv_encode(csv_t *csv, int count, ...)
     214             : {
     215           0 :         int tempc;
     216           0 :         va_list list;
     217           0 :         char *buf = csv->buf;
     218           0 :         int len = csv->buflen;
     219           0 :         int pointer = csv->pointer;
     220           0 :         char *str = NULL;
     221           0 :         char *col;
     222           0 :         csv_record_t *rec;
     223           0 :         csv_field_t *fld;
     224             : 
     225           0 :         if (buf) {
     226           0 :                 str = buf + pointer;
     227             :         } else {
     228             :                 /* allocate sufficient buffer */
     229           0 :                 str = (char *)malloc(csv->buflen);
     230           0 :                 if (!str) {
     231           0 :                         log_error("field str malloc failed\n");
     232           0 :                         return NULL;
     233             :                 }
     234             :         }
     235             : 
     236           0 :         va_start(list, count);
     237           0 :         rec = malloc(sizeof(csv_record_t));
     238           0 :         if (!rec) {
     239           0 :                 log_error("record malloc failed\n");
     240           0 :                 if (!buf)
     241           0 :                         free(str);
     242           0 :                 va_end(list);
     243           0 :                 return NULL;
     244             :         }
     245           0 :         csv_init_record(rec);
     246           0 :         rec->record = str;
     247           0 :         TAILQ_INSERT_TAIL(&(csv->records), rec, next_record);
     248           0 :         csv->num_recs++;
     249             : 
     250             :         /**
     251             :          * Iterate through the fields passed as a variable list and add them
     252             :          */
     253           0 :         for (tempc = 0; tempc < count; tempc++) {
     254           0 :                 col = va_arg(list, char *);
     255           0 :                 fld = csv_add_field_to_record(csv, rec, col);
     256           0 :                 if (!fld) {
     257           0 :                         log_error("fld malloc failed\n");
     258           0 :                         csv_remove_record(csv, rec);
     259           0 :                         va_end(list);
     260           0 :                         return NULL;
     261             :                 }
     262           0 :                 if (tempc < (count - 1)) {
     263           0 :                         rec->rec_len += snprintf((str + rec->rec_len),
     264           0 :                                                  (len - rec->rec_len), ",");
     265             :                 }
     266             :         }
     267           0 :         rec->rec_len +=
     268           0 :                 snprintf((str + rec->rec_len), (len - rec->rec_len), "\n");
     269           0 :         va_end(list);
     270           0 :         csv->csv_len += rec->rec_len;
     271           0 :         csv->pointer += rec->rec_len;
     272           0 :         return (rec);
     273             : }
     274             : 
     275           0 : int csv_num_records(csv_t *csv)
     276             : {
     277           0 :         if (csv) {
     278           0 :                 return csv->num_recs;
     279             :         }
     280             :         return 0;
     281             : }
     282             : 
     283           0 : csv_record_t *csv_encode_record(csv_t *csv, csv_record_t *rec, int count, ...)
     284             : {
     285           0 :         int tempc;
     286           0 :         va_list list;
     287           0 :         char *str;
     288           0 :         char *col;
     289           0 :         csv_field_t *fld = NULL;
     290           0 :         int i;
     291             : 
     292           0 :         va_start(list, count);
     293           0 :         str = csv_field_iter(rec, &fld);
     294           0 :         if (!fld) {
     295           0 :                 va_end(list);
     296           0 :                 return NULL;
     297             :         }
     298             : 
     299           0 :         for (tempc = 0; tempc < count; tempc++) {
     300           0 :                 col = va_arg(list, char *);
     301           0 :                 for (i = 0; i < fld->field_len; i++) {
     302           0 :                         str[i] = col[i];
     303             :                 }
     304           0 :                 str = csv_field_iter_next(&fld);
     305             :         }
     306           0 :         va_end(list);
     307           0 :         return (rec);
     308             : }
     309             : 
     310           0 : csv_record_t *csv_append_record(csv_t *csv, csv_record_t *rec, int count, ...)
     311             : {
     312           0 :         int tempc;
     313           0 :         va_list list;
     314           0 :         int len = csv->buflen, tlen;
     315           0 :         char *str;
     316           0 :         csv_field_t *fld;
     317           0 :         char *col;
     318             : 
     319           0 :         if (csv->buf) {
     320             :                 /* not only works with discrete bufs */
     321             :                 return NULL;
     322             :         }
     323             : 
     324           0 :         if (!rec) {
     325             :                 /* create a new rec */
     326           0 :                 rec = calloc(1, sizeof(csv_record_t));
     327           0 :                 if (!rec) {
     328           0 :                         log_error("record malloc failed\n");
     329           0 :                         return NULL;
     330             :                 }
     331           0 :                 csv_init_record(rec);
     332           0 :                 rec->record = calloc(1, csv->buflen);
     333           0 :                 if (!rec->record) {
     334           0 :                         log_error("field str malloc failed\n");
     335           0 :                         free(rec);
     336           0 :                         return NULL;
     337             :                 }
     338           0 :                 csv_insert_record(csv, rec);
     339             :         }
     340             : 
     341           0 :         str = rec->record;
     342             : 
     343           0 :         va_start(list, count);
     344             : 
     345           0 :         if (rec->rec_len && (str[rec->rec_len - 1] == '\n'))
     346           0 :                 str[rec->rec_len - 1] = ',';
     347             : 
     348             :         /**
     349             :          * Iterate through the fields passed as a variable list and add them
     350             :          */
     351           0 :         tlen = rec->rec_len;
     352           0 :         for (tempc = 0; tempc < count; tempc++) {
     353           0 :                 col = va_arg(list, char *);
     354           0 :                 fld = csv_add_field_to_record(csv, rec, col);
     355           0 :                 if (!fld) {
     356           0 :                         log_error("fld malloc failed\n");
     357           0 :                         break;
     358             :                 }
     359           0 :                 if (tempc < (count - 1)) {
     360           0 :                         rec->rec_len += snprintf((str + rec->rec_len),
     361           0 :                                                  (len - rec->rec_len), ",");
     362             :                 }
     363             :         }
     364           0 :         rec->rec_len +=
     365           0 :                 snprintf((str + rec->rec_len), (len - rec->rec_len), "\n");
     366           0 :         va_end(list);
     367           0 :         csv->csv_len += (rec->rec_len - tlen);
     368           0 :         csv->pointer += (rec->rec_len - tlen);
     369           0 :         return (rec);
     370             : }
     371             : 
     372           0 : int csv_serialize(csv_t *csv, char *msgbuf, int msglen)
     373             : {
     374           0 :         csv_record_t *rec;
     375           0 :         int offset = 0;
     376             : 
     377           0 :         if (!csv || !msgbuf)
     378             :                 return -1;
     379             : 
     380           0 :         rec = csv_record_iter(csv);
     381           0 :         while (rec != NULL) {
     382           0 :                 if ((offset + rec->rec_len) >= msglen)
     383             :                         return -1;
     384           0 :                 offset += sprintf(&msgbuf[offset], "%s", rec->record);
     385           0 :                 rec = csv_record_iter_next(rec);
     386             :         }
     387             : 
     388             :         return 0;
     389             : }
     390             : 
     391           0 : void csv_clone_record(csv_t *csv, csv_record_t *in_rec, csv_record_t **out_rec)
     392             : {
     393           0 :         char *curr;
     394           0 :         csv_record_t *rec;
     395             : 
     396             :         /* first check if rec belongs to this csv */
     397           0 :         if (!csv_is_record_valid(csv, in_rec)) {
     398           0 :                 log_error("rec not in this csv\n");
     399           0 :                 return;
     400             :         }
     401             : 
     402             :         /* only works with csv with discrete bufs */
     403           0 :         if (csv->buf) {
     404           0 :                 log_error(
     405             :                         "un-supported for this csv type - single buf detected\n");
     406           0 :                 return;
     407             :         }
     408             : 
     409             :         /* create a new rec */
     410           0 :         rec = calloc(1, sizeof(csv_record_t));
     411           0 :         if (!rec) {
     412           0 :                 log_error("record malloc failed\n");
     413           0 :                 return;
     414             :         }
     415           0 :         csv_init_record(rec);
     416           0 :         curr = calloc(1, csv->buflen);
     417           0 :         if (!curr) {
     418           0 :                 log_error("field str malloc failed\n");
     419           0 :                 free(rec);
     420           0 :                 return;
     421             :         }
     422           0 :         rec->record = curr;
     423           0 :         rec->rec_len = in_rec->rec_len;
     424           0 :         strlcpy(rec->record, in_rec->record, csv->buflen);
     425             : 
     426             :         /* decode record into fields */
     427           0 :         csv_decode_record(rec);
     428             : 
     429           0 :         *out_rec = rec;
     430             : }
     431             : 
     432           0 : void csv_remove_record(csv_t *csv, csv_record_t *rec)
     433             : {
     434           0 :         csv_field_t *fld = NULL, *p_fld;
     435             : 
     436             :         /* first check if rec belongs to this csv */
     437           0 :         if (!csv_is_record_valid(csv, rec)) {
     438           0 :                 log_error("rec not in this csv\n");
     439           0 :                 return;
     440             :         }
     441             : 
     442             :         /* remove fields */
     443           0 :         csv_field_iter(rec, &fld);
     444           0 :         while (fld) {
     445           0 :                 p_fld = fld;
     446           0 :                 csv_field_iter_next(&fld);
     447           0 :                 TAILQ_REMOVE(&(rec->fields), p_fld, next_field);
     448           0 :                 free(p_fld);
     449             :         }
     450             : 
     451           0 :         TAILQ_REMOVE(&(csv->records), rec, next_record);
     452             : 
     453           0 :         csv->num_recs--;
     454           0 :         csv->csv_len -= rec->rec_len;
     455           0 :         csv->pointer -= rec->rec_len;
     456           0 :         if (!csv->buf)
     457           0 :                 free(rec->record);
     458           0 :         free(rec);
     459             : }
     460             : 
     461           0 : void csv_insert_record(csv_t *csv, csv_record_t *rec)
     462             : {
     463             :         /* first check if rec already in csv */
     464           0 :         if (csv_is_record_valid(csv, rec)) {
     465           0 :                 log_error("rec already in this csv\n");
     466           0 :                 return;
     467             :         }
     468             : 
     469             :         /* we can only insert records if no buf was supplied during csv init */
     470           0 :         if (csv->buf) {
     471           0 :                 log_error(
     472             :                         "un-supported for this csv type - single buf detected\n");
     473           0 :                 return;
     474             :         }
     475             : 
     476             :         /* do we go beyond the max buf set for this csv ?*/
     477           0 :         if ((csv->csv_len + rec->rec_len) > csv->buflen) {
     478           0 :                 log_error("cannot insert - exceeded buf size\n");
     479           0 :                 return;
     480             :         }
     481             : 
     482           0 :         TAILQ_INSERT_TAIL(&(csv->records), rec, next_record);
     483           0 :         csv->num_recs++;
     484           0 :         csv->csv_len += rec->rec_len;
     485           0 :         csv->pointer += rec->rec_len;
     486             : }
     487             : 
     488           0 : csv_record_t *csv_concat_record(csv_t *csv, csv_record_t *rec1,
     489             :                                 csv_record_t *rec2)
     490             : {
     491           0 :         char *curr;
     492           0 :         char *ret;
     493           0 :         csv_record_t *rec;
     494             : 
     495             :         /* first check if rec1 and rec2 belong to this csv */
     496           0 :         if (!csv_is_record_valid(csv, rec1)
     497           0 :             || !csv_is_record_valid(csv, rec2)) {
     498           0 :                 log_error("rec1 and/or rec2 invalid\n");
     499           0 :                 return NULL;
     500             :         }
     501             : 
     502             :         /* we can only concat records if no buf was supplied during csv init */
     503           0 :         if (csv->buf) {
     504           0 :                 log_error(
     505             :                         "un-supported for this csv type - single buf detected\n");
     506           0 :                 return NULL;
     507             :         }
     508             : 
     509             :         /* create a new rec */
     510           0 :         rec = calloc(1, sizeof(csv_record_t));
     511           0 :         if (!rec) {
     512           0 :                 log_error("record malloc failed\n");
     513           0 :                 return NULL;
     514             :         }
     515           0 :         csv_init_record(rec);
     516             : 
     517           0 :         curr = (char *)calloc(1, csv->buflen);
     518           0 :         if (!curr) {
     519           0 :                 log_error("field str malloc failed\n");
     520           0 :                 goto out_rec;
     521             :         }
     522           0 :         rec->record = curr;
     523             : 
     524             :         /* concat the record string */
     525           0 :         ret = strstr(rec1->record, "\n");
     526           0 :         if (!ret) {
     527           0 :                 log_error("rec1 str not properly formatted\n");
     528           0 :                 goto out_curr;
     529             :         }
     530             : 
     531           0 :         snprintf(curr, (int)(ret - rec1->record + 1), "%s", rec1->record);
     532           0 :         strcat(curr, ",");
     533             : 
     534           0 :         ret = strstr(rec2->record, "\n");
     535           0 :         if (!ret) {
     536           0 :                 log_error("rec2 str not properly formatted\n");
     537           0 :                 goto out_curr;
     538             :         }
     539             : 
     540           0 :         snprintf((curr + strlen(curr)), (int)(ret - rec2->record + 1), "%s",
     541             :                  rec2->record);
     542           0 :         strcat(curr, "\n");
     543           0 :         rec->rec_len = strlen(curr);
     544             : 
     545             :         /* paranoia */
     546           0 :         assert(csv->buflen
     547             :                > (csv->csv_len - rec1->rec_len - rec2->rec_len + rec->rec_len));
     548             : 
     549             :         /* decode record into fields */
     550           0 :         csv_decode_record(rec);
     551             : 
     552             :         /* now remove rec1 and rec2 and insert rec into this csv */
     553           0 :         csv_remove_record(csv, rec1);
     554           0 :         csv_remove_record(csv, rec2);
     555           0 :         csv_insert_record(csv, rec);
     556             : 
     557           0 :         return rec;
     558             : 
     559           0 : out_curr:
     560           0 :         free(curr);
     561           0 : out_rec:
     562           0 :         free(rec);
     563           0 :         return NULL;
     564             : }
     565             : 
     566           0 : void csv_decode(csv_t *csv, char *inbuf)
     567             : {
     568           0 :         char *buf;
     569           0 :         char *pos;
     570           0 :         csv_record_t *rec;
     571             : 
     572           0 :         buf = (inbuf) ? inbuf : csv->buf;
     573           0 :         assert(buf);
     574             : 
     575           0 :         pos = strpbrk(buf, "\n");
     576           0 :         while (pos != NULL) {
     577           0 :                 rec = calloc(1, sizeof(csv_record_t));
     578           0 :                 if (!rec)
     579             :                         return;
     580           0 :                 csv_init_record(rec);
     581           0 :                 TAILQ_INSERT_TAIL(&(csv->records), rec, next_record);
     582           0 :                 csv->num_recs++;
     583           0 :                 if (csv->buf)
     584           0 :                         rec->record = buf;
     585             :                 else {
     586           0 :                         rec->record = calloc(1, csv->buflen);
     587           0 :                         if (!rec->record) {
     588           0 :                                 log_error("field str malloc failed\n");
     589           0 :                                 return;
     590             :                         }
     591           0 :                         strncpy(rec->record, buf, pos - buf + 1);
     592             :                 }
     593           0 :                 rec->rec_len = pos - buf + 1;
     594             :                 /* decode record into fields */
     595           0 :                 csv_decode_record(rec);
     596           0 :                 buf = pos + 1;
     597           0 :                 pos = strpbrk(buf, "\n");
     598             :         }
     599             : }
     600             : 
     601           0 : int csv_is_record_valid(csv_t *csv, csv_record_t *in_rec)
     602             : {
     603           0 :         csv_record_t *rec;
     604           0 :         int valid = 0;
     605             : 
     606           0 :         rec = csv_record_iter(csv);
     607           0 :         while (rec) {
     608           0 :                 if (rec == in_rec) {
     609             :                         valid = 1;
     610             :                         break;
     611             :                 }
     612           0 :                 rec = csv_record_iter_next(rec);
     613             :         }
     614             : 
     615           0 :         return valid;
     616             : }
     617             : 
     618           0 : void csv_dump(csv_t *csv)
     619             : {
     620           0 :         csv_record_t *rec;
     621           0 :         csv_field_t *fld;
     622           0 :         char *str;
     623             : 
     624           0 :         rec = csv_record_iter(csv);
     625           0 :         while (rec != NULL) {
     626           0 :                 str = csv_field_iter(rec, &fld);
     627           0 :                 while (str != NULL) {
     628           0 :                         fprintf(stderr, "%s\n", str);
     629           0 :                         str = csv_field_iter_next(&fld);
     630             :                 }
     631           0 :                 rec = csv_record_iter_next(rec);
     632             :         }
     633           0 : }
     634             : 
     635             : #ifdef TEST_CSV
     636             : 
     637             : static int get_memory_usage(pid_t pid)
     638             : {
     639             :         int fd, data, stack;
     640             :         char buf[4096], status_child[PATH_MAX];
     641             :         char *vm;
     642             : 
     643             :         snprintf(status_child, sizeof(status_child), "/proc/%d/status", pid);
     644             :         fd = open(status_child, O_RDONLY);
     645             :         if (fd < 0)
     646             :                 return -1;
     647             : 
     648             :         read(fd, buf, 4095);
     649             :         buf[4095] = '\0';
     650             :         close(fd);
     651             : 
     652             :         data = stack = 0;
     653             : 
     654             :         vm = strstr(buf, "VmData:");
     655             :         if (vm) {
     656             :                 sscanf(vm, "%*s %d", &data);
     657             :         }
     658             :         vm = strstr(buf, "VmStk:");
     659             :         if (vm) {
     660             :                 sscanf(vm, "%*s %d", &stack);
     661             :         }
     662             : 
     663             :         return data + stack;
     664             : }
     665             : 
     666             : int main()
     667             : {
     668             :         char buf[10000];
     669             :         csv_t csv;
     670             :         int i;
     671             :         csv_record_t *rec;
     672             :         char hdr1[32], hdr2[32];
     673             : 
     674             :         log_verbose("Mem: %d\n", get_memory_usage(getpid()));
     675             :         csv_init(&csv, buf, 256);
     676             :         snprintf(hdr1, sizeof(hdr1), "%4d", 0);
     677             :         snprintf(hdr2, sizeof(hdr2), "%4d", 1);
     678             :         log_verbose("(%zu/%zu/%d/%d)\n", strlen(hdr1), strlen(hdr2), atoi(hdr1),
     679             :                     atoi(hdr2));
     680             :         rec = csv_encode(&csv, 2, hdr1, hdr2);
     681             :         csv_encode(&csv, 4, "name", "age", "sex", "hei");
     682             :         csv_encode(&csv, 3, NULL, "0", NULL);
     683             :         csv_encode(&csv, 2, "p", "35");
     684             :         for (i = 0; i < 50; i++) {
     685             :                 csv_encode(&csv, 2, "p", "10");
     686             :         }
     687             :         csv_encode(&csv, 2, "pdfadfadfadsadsaddfdfdsfdsd", "35444554545454545");
     688             :         log_verbose("%s\n", buf);
     689             :         snprintf(hdr1, sizeof(hdr1), "%4d", csv.csv_len);
     690             :         snprintf(hdr2, sizeof(hdr2), "%4d", 1);
     691             :         log_verbose("(%zu/%zu/%d/%d)\n", strlen(hdr1), strlen(hdr2), atoi(hdr1),
     692             :                     atoi(hdr2));
     693             :         rec = csv_encode_record(&csv, rec, 2, hdr1, hdr2);
     694             :         log_verbose("(%d/%d)\n%s\n", rec->rec_len, csv.csv_len, buf);
     695             : 
     696             :         log_verbose("Mem: %d\n", get_memory_usage(getpid()));
     697             :         csv_clean(&csv);
     698             :         log_verbose("Mem: %d\n", get_memory_usage(getpid()));
     699             :         csv_init(&csv, buf, 256);
     700             :         csv_decode(&csv, NULL);
     701             :         log_verbose("%s", "AFTER DECODE\n");
     702             :         csv_dump(&csv);
     703             :         csv_clean(&csv);
     704             :         log_verbose("Mem: %d\n", get_memory_usage(getpid()));
     705             : }
     706             : #endif

Generated by: LCOV version v1.16-topotato