back to topotato report
topotato coverage report
Current view: top level - lib - csv.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 0 341 0.0 %
Date: 2023-11-16 17:19:14 Functions: 0 46 0.0 %

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

Generated by: LCOV version v1.16-topotato