mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-11-04 13:30:17 +00:00 
			
		
		
		
	These files were submitted by Cumulus but did not properly setup the licensing of them. This fixes that issue. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
		
			
				
	
	
		
			705 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			705 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* CSV
 | 
						|
 * Copyright (C) 2013 Cumulus Networks, Inc.
 | 
						|
 *
 | 
						|
 * This file is part of Quagga.
 | 
						|
 *
 | 
						|
 * Quagga is free software; you can redistribute it and/or modify it
 | 
						|
 * under the terms of the GNU General Public License as published by the
 | 
						|
 * Free Software Foundation; either version 2, or (at your option) any
 | 
						|
 * later version.
 | 
						|
 *
 | 
						|
 * Quagga is distributed in the hope that it will be useful, but
 | 
						|
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
 * General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License
 | 
						|
 * along with Quagga; see the file COPYING.  If not, write to the Free
 | 
						|
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
						|
 * 02111-1307, USA.
 | 
						|
 */
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <stdarg.h>
 | 
						|
#include <assert.h>
 | 
						|
#include <sys/queue.h>
 | 
						|
#include <fcntl.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include "csv.h"
 | 
						|
 | 
						|
#define DEBUG_E 1
 | 
						|
#define DEBUG_V 1
 | 
						|
 | 
						|
#define log_error(fmt, ...) \
 | 
						|
  do { if (DEBUG_E) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \
 | 
						|
			    __LINE__, __func__, ##__VA_ARGS__); } while (0)
 | 
						|
 | 
						|
#define log_verbose(fmt, ...) \
 | 
						|
  do { if (DEBUG_V) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \
 | 
						|
			    __LINE__, __func__, __VA_ARGS__); } while (0)
 | 
						|
 | 
						|
struct _csv_field_t_ {
 | 
						|
  TAILQ_ENTRY(_csv_field_t_) next_field;
 | 
						|
  char *field;
 | 
						|
  int field_len;
 | 
						|
};
 | 
						|
 | 
						|
struct _csv_record_t_ {
 | 
						|
  TAILQ_HEAD(, _csv_field_t_) fields;
 | 
						|
  TAILQ_ENTRY(_csv_record_t_) next_record;
 | 
						|
  char *record;
 | 
						|
  int rec_len;
 | 
						|
};
 | 
						|
 | 
						|
struct _csv_t_ {
 | 
						|
  TAILQ_HEAD(, _csv_record_t_) records;
 | 
						|
  char *buf;
 | 
						|
  int buflen;
 | 
						|
  int csv_len;
 | 
						|
  int pointer;
 | 
						|
  int num_recs;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
int
 | 
						|
csvlen (csv_t *csv)
 | 
						|
{
 | 
						|
  return (csv->csv_len);
 | 
						|
}
 | 
						|
 | 
						|
csv_t *
 | 
						|
csv_init (csv_t *csv,
 | 
						|
	  char *buf,
 | 
						|
	  int buflen)
 | 
						|
{
 | 
						|
  if (csv == NULL) {
 | 
						|
    csv = malloc(sizeof(csv_t));
 | 
						|
    if (csv == NULL) {
 | 
						|
      log_error("CSV Malloc failed\n");
 | 
						|
      return (NULL);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  memset(csv, 0, sizeof(csv_t));
 | 
						|
 | 
						|
  csv->buf = buf;
 | 
						|
  csv->buflen = buflen;
 | 
						|
  TAILQ_INIT(&(csv->records));
 | 
						|
  return (csv);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
csv_clean (csv_t *csv)
 | 
						|
{
 | 
						|
  csv_record_t *rec;
 | 
						|
  csv_record_t *rec_n;
 | 
						|
 | 
						|
  rec = TAILQ_FIRST(&(csv->records));
 | 
						|
  while (rec != NULL) {
 | 
						|
    rec_n = TAILQ_NEXT(rec, next_record);
 | 
						|
    csv_remove_record(csv, rec);
 | 
						|
    rec = rec_n;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
csv_free (csv_t *csv)
 | 
						|
{
 | 
						|
  if (csv != NULL) {
 | 
						|
    free(csv);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
csv_init_record (csv_record_t *record)
 | 
						|
{
 | 
						|
  TAILQ_INIT(&(record->fields));
 | 
						|
  record->rec_len = 0;
 | 
						|
}
 | 
						|
 | 
						|
csv_record_t *
 | 
						|
csv_record_iter (csv_t *csv)
 | 
						|
{
 | 
						|
  return(TAILQ_FIRST(&(csv->records)));
 | 
						|
}
 | 
						|
 | 
						|
csv_record_t *
 | 
						|
csv_record_iter_next (csv_record_t *rec)
 | 
						|
{
 | 
						|
  if(!rec) return NULL;
 | 
						|
  return(TAILQ_NEXT(rec, next_record));
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
csv_field_iter (csv_record_t *rec,
 | 
						|
		csv_field_t **fld)
 | 
						|
{
 | 
						|
  if(!rec) return NULL;
 | 
						|
  *fld = TAILQ_FIRST(&(rec->fields));
 | 
						|
  return ((*fld)->field);
 | 
						|
}
 | 
						|
 | 
						|
char *
 | 
						|
csv_field_iter_next (csv_field_t **fld)
 | 
						|
{
 | 
						|
  *fld = TAILQ_NEXT(*fld, next_field);
 | 
						|
  if ((*fld) == NULL) {
 | 
						|
    return (NULL);
 | 
						|
  }
 | 
						|
  return ((*fld)->field);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
csv_field_len(csv_field_t *fld)
 | 
						|
{
 | 
						|
  if (fld) {
 | 
						|
    return fld->field_len;
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
csv_decode_record(csv_record_t *rec)
 | 
						|
{
 | 
						|
    char *curr = rec->record;
 | 
						|
    char *field;
 | 
						|
    csv_field_t *fld;
 | 
						|
 | 
						|
    field = strpbrk(curr, ",");
 | 
						|
    while (field != NULL) {
 | 
						|
        fld = malloc(sizeof(csv_field_t));
 | 
						|
        if (fld) {
 | 
						|
            TAILQ_INSERT_TAIL(&(rec->fields), fld, next_field);
 | 
						|
            fld->field = curr;
 | 
						|
            fld->field_len = field-curr;
 | 
						|
        }
 | 
						|
        curr = field + 1;
 | 
						|
        field = strpbrk(curr, ",");
 | 
						|
    }
 | 
						|
    field = strstr(curr, "\n");
 | 
						|
    fld = malloc(sizeof(csv_field_t));
 | 
						|
    if (field && fld) {
 | 
						|
        fld->field = curr;
 | 
						|
        fld->field_len = field-curr;
 | 
						|
        TAILQ_INSERT_TAIL(&(rec->fields), fld, next_field);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static csv_field_t *
 | 
						|
csv_add_field_to_record(csv_t *csv,
 | 
						|
                        csv_record_t *rec,
 | 
						|
                        char *col)
 | 
						|
{
 | 
						|
    csv_field_t *fld;
 | 
						|
    char *str = rec->record;
 | 
						|
    int rlen = rec->rec_len;
 | 
						|
    int blen = csv->buflen;
 | 
						|
 | 
						|
    fld = malloc(sizeof(csv_field_t));
 | 
						|
    if (!fld) {
 | 
						|
        log_error("field malloc failed\n");
 | 
						|
        /* more cleanup needed */
 | 
						|
        return (NULL);
 | 
						|
    }
 | 
						|
    TAILQ_INSERT_TAIL(&(rec->fields), fld, next_field);
 | 
						|
    fld->field = str+rlen;
 | 
						|
    fld->field_len = snprintf((str+rlen), (blen - rlen), "%s", col);
 | 
						|
    rlen += fld->field_len;
 | 
						|
    rec->rec_len = rlen;
 | 
						|
    return fld;
 | 
						|
}
 | 
						|
 | 
						|
csv_record_t *
 | 
						|
csv_encode (csv_t *csv,
 | 
						|
	    int count,
 | 
						|
	    ...)
 | 
						|
{
 | 
						|
  int tempc;
 | 
						|
  va_list list;
 | 
						|
  char *buf = csv->buf;
 | 
						|
  int len = csv->buflen;
 | 
						|
  int pointer = csv->pointer;
 | 
						|
  char *str = NULL;
 | 
						|
  char *col;
 | 
						|
  csv_record_t *rec;
 | 
						|
  csv_field_t *fld;
 | 
						|
 | 
						|
  if (buf) {
 | 
						|
     str = buf + pointer;
 | 
						|
  } else {
 | 
						|
     /* allocate sufficient buffer */
 | 
						|
     str = (char *)malloc(csv->buflen);
 | 
						|
     if (!str) {
 | 
						|
        log_error("field str malloc failed\n");
 | 
						|
        return (NULL);
 | 
						|
     }
 | 
						|
  }
 | 
						|
 | 
						|
  va_start(list, count);
 | 
						|
  rec = malloc(sizeof(csv_record_t));
 | 
						|
  if (!rec) {
 | 
						|
    log_error("record malloc failed\n");
 | 
						|
    return (NULL);
 | 
						|
  }
 | 
						|
  csv_init_record(rec);
 | 
						|
  rec->record = str;
 | 
						|
  TAILQ_INSERT_TAIL(&(csv->records), rec, next_record);
 | 
						|
  csv->num_recs++;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Iterate through the fields passed as a variable list and add them
 | 
						|
   */
 | 
						|
  for (tempc = 0; tempc < count; tempc++) {
 | 
						|
    col = va_arg(list, char *);
 | 
						|
    fld = csv_add_field_to_record(csv, rec, col);
 | 
						|
    if (!fld) {
 | 
						|
      log_error("fld malloc failed\n");
 | 
						|
      csv_remove_record(csv, rec);
 | 
						|
      return (NULL);
 | 
						|
    }
 | 
						|
    if (tempc < (count - 1)) {
 | 
						|
      rec->rec_len += snprintf((str+rec->rec_len), (len - rec->rec_len), ",");
 | 
						|
    }
 | 
						|
  }
 | 
						|
  rec->rec_len += snprintf((str+rec->rec_len), (len - rec->rec_len), "\n");
 | 
						|
  va_end(list);
 | 
						|
  csv->csv_len += rec->rec_len;
 | 
						|
  csv->pointer += rec->rec_len;
 | 
						|
  return (rec);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
csv_num_records (csv_t *csv)
 | 
						|
{
 | 
						|
    if (csv) {
 | 
						|
        return csv->num_recs;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
csv_record_t *
 | 
						|
csv_encode_record (csv_t *csv,
 | 
						|
		   csv_record_t *rec,
 | 
						|
		   int count,
 | 
						|
		   ...)
 | 
						|
{
 | 
						|
  int tempc;
 | 
						|
  va_list list;
 | 
						|
  char *str;
 | 
						|
  char *col;
 | 
						|
  csv_field_t *fld = NULL;
 | 
						|
  int i;
 | 
						|
 | 
						|
  va_start(list, count);
 | 
						|
  str = csv_field_iter(rec, &fld);
 | 
						|
  for (tempc = 0; tempc < count; tempc++) {
 | 
						|
    col = va_arg(list, char *);
 | 
						|
    for (i = 0; i < fld->field_len; i++) {
 | 
						|
      str[i] = col[i];
 | 
						|
    }
 | 
						|
    str = csv_field_iter_next(&fld);
 | 
						|
  }
 | 
						|
  va_end(list);
 | 
						|
  return (rec);
 | 
						|
}
 | 
						|
 | 
						|
csv_record_t *
 | 
						|
csv_append_record (csv_t *csv,
 | 
						|
                   csv_record_t *rec,
 | 
						|
                   int count,
 | 
						|
                   ...)
 | 
						|
{
 | 
						|
    int tempc;
 | 
						|
    va_list list;
 | 
						|
    int len = csv->buflen, tlen;
 | 
						|
    char *str;
 | 
						|
    csv_field_t *fld;
 | 
						|
    char *col;
 | 
						|
 | 
						|
    if (csv->buf) {
 | 
						|
        /* not only works with discrete bufs */
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!rec) {
 | 
						|
        /* create a new rec */
 | 
						|
        rec = calloc(1, sizeof(csv_record_t));
 | 
						|
        if (!rec) {
 | 
						|
            log_error("record malloc failed\n");
 | 
						|
            return NULL;
 | 
						|
        }
 | 
						|
        csv_init_record(rec);
 | 
						|
        rec->record = calloc(1, csv->buflen);
 | 
						|
        if (!rec->record) {
 | 
						|
            log_error("field str malloc failed\n");
 | 
						|
            free(rec);
 | 
						|
            return NULL;
 | 
						|
        }
 | 
						|
        csv_insert_record(csv, rec);
 | 
						|
    }
 | 
						|
 | 
						|
    str = rec->record;
 | 
						|
 | 
						|
    va_start(list, count);
 | 
						|
 | 
						|
    if (rec->rec_len && (str[rec->rec_len-1] == '\n'))
 | 
						|
            str[rec->rec_len-1] = ',';
 | 
						|
 | 
						|
    /**
 | 
						|
     * Iterate through the fields passed as a variable list and add them
 | 
						|
     */
 | 
						|
    tlen = rec->rec_len;
 | 
						|
    for (tempc = 0; tempc < count; tempc++) {
 | 
						|
        col = va_arg(list, char *);
 | 
						|
        fld = csv_add_field_to_record(csv, rec, col);
 | 
						|
        if (!fld) {
 | 
						|
            log_error("fld malloc failed\n");
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        if (tempc < (count - 1)) {
 | 
						|
            rec->rec_len += snprintf((str+rec->rec_len),
 | 
						|
                                     (len - rec->rec_len), ",");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    rec->rec_len += snprintf((str+rec->rec_len),
 | 
						|
                             (len - rec->rec_len), "\n");
 | 
						|
    va_end(list);
 | 
						|
    csv->csv_len += (rec->rec_len - tlen);
 | 
						|
    csv->pointer += (rec->rec_len - tlen);
 | 
						|
    return (rec);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
csv_serialize(csv_t *csv, char *msgbuf, int msglen)
 | 
						|
{
 | 
						|
  csv_record_t *rec;
 | 
						|
  int offset = 0;
 | 
						|
 | 
						|
  if (!csv || !msgbuf) return -1;
 | 
						|
 | 
						|
  rec = csv_record_iter(csv);
 | 
						|
  while (rec != NULL) {
 | 
						|
    if ((offset + rec->rec_len) >= msglen)
 | 
						|
        return -1;
 | 
						|
    offset += sprintf(&msgbuf[offset], "%s", rec->record);
 | 
						|
    rec = csv_record_iter_next(rec);
 | 
						|
  }
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
csv_clone_record (csv_t *csv, csv_record_t *in_rec, csv_record_t **out_rec)
 | 
						|
{
 | 
						|
    char *curr;
 | 
						|
    csv_record_t *rec;
 | 
						|
 | 
						|
    /* first check if rec belongs to this csv */
 | 
						|
    if(!csv_is_record_valid(csv, in_rec)){
 | 
						|
        log_error("rec not in this csv\n");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    /* only works with csv with discrete bufs */
 | 
						|
    if (csv->buf) {
 | 
						|
        log_error("un-supported for this csv type - single buf detected\n");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    /* create a new rec */
 | 
						|
    rec = calloc(1, sizeof(csv_record_t));
 | 
						|
    if (!rec) {
 | 
						|
        log_error("record malloc failed\n");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    csv_init_record(rec);
 | 
						|
    curr = calloc(1, csv->buflen);
 | 
						|
    if (!curr) {
 | 
						|
        log_error("field str malloc failed\n");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    rec->record = curr;
 | 
						|
    rec->rec_len = in_rec->rec_len;
 | 
						|
    strcpy(rec->record, in_rec->record);
 | 
						|
 | 
						|
    /* decode record into fields */
 | 
						|
    csv_decode_record(rec);
 | 
						|
 | 
						|
    *out_rec = rec;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
csv_remove_record (csv_t *csv, csv_record_t *rec)
 | 
						|
{
 | 
						|
  csv_field_t *fld, *p_fld;
 | 
						|
 | 
						|
  /* first check if rec belongs to this csv */
 | 
						|
  if(!csv_is_record_valid(csv, rec)){
 | 
						|
    log_error("rec not in this csv\n");
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  /* remove fields */
 | 
						|
  csv_field_iter(rec, &fld);
 | 
						|
  while(fld) {
 | 
						|
    p_fld = fld;
 | 
						|
    csv_field_iter_next(&fld);
 | 
						|
    TAILQ_REMOVE(&(rec->fields), p_fld, next_field);
 | 
						|
    free(p_fld);
 | 
						|
  }
 | 
						|
 | 
						|
  TAILQ_REMOVE(&(csv->records), rec, next_record);
 | 
						|
 | 
						|
  csv->num_recs--;
 | 
						|
  csv->csv_len -= rec->rec_len;
 | 
						|
  csv->pointer -= rec->rec_len;
 | 
						|
  if (!csv->buf)
 | 
						|
    free(rec->record);
 | 
						|
  free(rec);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
csv_insert_record (csv_t *csv, csv_record_t *rec)
 | 
						|
{
 | 
						|
  /* first check if rec already in csv */
 | 
						|
  if(csv_is_record_valid(csv, rec)){
 | 
						|
    log_error("rec already in this csv\n");
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  /* we can only insert records if no buf was supplied during csv init */
 | 
						|
  if (csv->buf) {
 | 
						|
    log_error("un-supported for this csv type - single buf detected\n");
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  /* do we go beyond the max buf set for this csv ?*/
 | 
						|
  if ((csv->csv_len + rec->rec_len) > csv->buflen ) {
 | 
						|
    log_error("cannot insert - exceeded buf size\n");
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  TAILQ_INSERT_TAIL(&(csv->records), rec, next_record);
 | 
						|
  csv->num_recs++;
 | 
						|
  csv->csv_len += rec->rec_len;
 | 
						|
  csv->pointer += rec->rec_len;
 | 
						|
}
 | 
						|
 | 
						|
csv_record_t *
 | 
						|
csv_concat_record (csv_t *csv,
 | 
						|
		           csv_record_t *rec1,
 | 
						|
		           csv_record_t *rec2)
 | 
						|
{
 | 
						|
  char *curr;
 | 
						|
  char *ret;
 | 
						|
  csv_record_t *rec;
 | 
						|
 | 
						|
  /* first check if rec1 and rec2 belong to this csv */
 | 
						|
  if(!csv_is_record_valid(csv, rec1) ||
 | 
						|
     !csv_is_record_valid(csv, rec2)) {
 | 
						|
    log_error("rec1 and/or rec2 invalid\n");
 | 
						|
    return (NULL);
 | 
						|
  }
 | 
						|
 | 
						|
  /* we can only concat records if no buf was supplied during csv init */
 | 
						|
  if (csv->buf) {
 | 
						|
    log_error("un-supported for this csv type - single buf detected\n");
 | 
						|
    return (NULL);
 | 
						|
  }
 | 
						|
 | 
						|
  /* create a new rec */
 | 
						|
  rec = calloc(1, sizeof(csv_record_t));
 | 
						|
  if (!rec) {
 | 
						|
    log_error("record malloc failed\n");
 | 
						|
    return (NULL);
 | 
						|
  }
 | 
						|
  csv_init_record(rec);
 | 
						|
 | 
						|
  curr = (char *)calloc(1, csv->buflen);
 | 
						|
  if (!curr) {
 | 
						|
    log_error("field str malloc failed\n");
 | 
						|
    return (NULL);
 | 
						|
  }
 | 
						|
  rec->record = curr;
 | 
						|
 | 
						|
  /* concat the record string */
 | 
						|
  ret = strstr(rec1->record, "\n");
 | 
						|
  if (!ret) {
 | 
						|
    log_error("rec1 str not properly formatted\n");
 | 
						|
    return (NULL);
 | 
						|
  }
 | 
						|
 | 
						|
  snprintf(curr, (int)(ret - rec1->record + 1), "%s", rec1->record);
 | 
						|
  strcat(curr, ",");
 | 
						|
 | 
						|
  ret = strstr(rec2->record, "\n");
 | 
						|
  if (!ret) {
 | 
						|
    log_error("rec2 str not properly formatted\n");
 | 
						|
    return (NULL);
 | 
						|
  }
 | 
						|
 | 
						|
  snprintf((curr+strlen(curr)), (int)(ret - rec2->record + 1), "%s",
 | 
						|
           rec2->record);
 | 
						|
  strcat(curr, "\n");
 | 
						|
  rec->rec_len = strlen(curr);
 | 
						|
 | 
						|
  /* paranoia */
 | 
						|
  assert(csv->buflen >
 | 
						|
         (csv->csv_len - rec1->rec_len - rec2->rec_len + rec->rec_len));
 | 
						|
 | 
						|
  /* decode record into fields */
 | 
						|
  csv_decode_record(rec);
 | 
						|
 | 
						|
  /* now remove rec1 and rec2 and insert rec into this csv */
 | 
						|
  csv_remove_record(csv, rec1);
 | 
						|
  csv_remove_record(csv, rec2);
 | 
						|
  csv_insert_record(csv, rec);
 | 
						|
 | 
						|
  return rec;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
csv_decode (csv_t *csv, char *inbuf)
 | 
						|
{
 | 
						|
  char *buf;
 | 
						|
  char *pos;
 | 
						|
  csv_record_t *rec;
 | 
						|
 | 
						|
  buf = (inbuf)? inbuf:csv->buf;
 | 
						|
  pos = strpbrk(buf, "\n");
 | 
						|
  while (pos != NULL) {
 | 
						|
    rec = calloc(1, sizeof(csv_record_t));
 | 
						|
    csv_init_record(rec);
 | 
						|
    TAILQ_INSERT_TAIL(&(csv->records), rec, next_record);
 | 
						|
    csv->num_recs++;
 | 
						|
    if (csv->buf)
 | 
						|
      rec->record = buf;
 | 
						|
    else {
 | 
						|
      rec->record = calloc(1, csv->buflen);
 | 
						|
      if (!rec->record) {
 | 
						|
        log_error("field str malloc failed\n");
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      strncpy(rec->record, buf, pos-buf+1);
 | 
						|
    }
 | 
						|
    rec->rec_len = pos-buf+1;
 | 
						|
    /* decode record into fields */
 | 
						|
    csv_decode_record(rec);
 | 
						|
    buf = pos+1;
 | 
						|
    pos = strpbrk(buf, "\n");
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
csv_is_record_valid(csv_t *csv, csv_record_t *in_rec)
 | 
						|
{
 | 
						|
  csv_record_t *rec;
 | 
						|
  int valid = 0;
 | 
						|
 | 
						|
  rec = csv_record_iter(csv);
 | 
						|
  while (rec) {
 | 
						|
    if(rec == in_rec) {
 | 
						|
      valid = 1;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    rec = csv_record_iter_next(rec);
 | 
						|
  }
 | 
						|
 | 
						|
  return valid;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
csv_dump (csv_t *csv)
 | 
						|
{
 | 
						|
  csv_record_t *rec;
 | 
						|
  csv_field_t *fld;
 | 
						|
  char *str;
 | 
						|
 | 
						|
  rec = csv_record_iter(csv);
 | 
						|
  while (rec != NULL) {
 | 
						|
    str = csv_field_iter(rec, &fld);
 | 
						|
    while (str != NULL) {
 | 
						|
      fprintf(stderr, "%s\n", str);
 | 
						|
      str = csv_field_iter_next(&fld);
 | 
						|
    }
 | 
						|
    rec = csv_record_iter_next(rec);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
#ifdef TEST_CSV
 | 
						|
 | 
						|
static int
 | 
						|
get_memory_usage (pid_t pid)
 | 
						|
{
 | 
						|
  int fd, data, stack;
 | 
						|
  char buf[4096], status_child[BUFSIZ];
 | 
						|
  char *vm;
 | 
						|
 | 
						|
  sprintf(status_child, "/proc/%d/status", pid);
 | 
						|
  if ((fd = open(status_child, O_RDONLY)) < 0)
 | 
						|
    return -1;
 | 
						|
 | 
						|
  read(fd, buf, 4095);
 | 
						|
  buf[4095] = '\0';
 | 
						|
  close(fd);
 | 
						|
 | 
						|
  data = stack = 0;
 | 
						|
 | 
						|
  vm = strstr(buf, "VmData:");
 | 
						|
  if (vm) {
 | 
						|
    sscanf(vm, "%*s %d", &data);
 | 
						|
  }
 | 
						|
  vm = strstr(buf, "VmStk:");
 | 
						|
  if (vm) {
 | 
						|
    sscanf(vm, "%*s %d", &stack);
 | 
						|
  }
 | 
						|
 | 
						|
  return data + stack;
 | 
						|
}
 | 
						|
 | 
						|
int main ()
 | 
						|
{
 | 
						|
  char buf[10000];
 | 
						|
  csv_t csv;
 | 
						|
  int p;
 | 
						|
  int i, j;
 | 
						|
  csv_record_t *rec;
 | 
						|
  csv_field_t *fld;
 | 
						|
  char *str;
 | 
						|
  char hdr1[32], hdr2[32];
 | 
						|
 | 
						|
  log_verbose("Mem: %ld\n", get_memory_usage(getpid()));
 | 
						|
  csv_init(&csv, buf, 256);
 | 
						|
  sprintf(hdr1, "%4u", 0);
 | 
						|
  sprintf(hdr2, "%4u", 1);
 | 
						|
  log_verbose("(%d/%d/%d/%d)\n", strlen(hdr1),
 | 
						|
	  strlen(hdr2), atoi(hdr1), atoi(hdr2));
 | 
						|
  rec = csv_encode(&csv, 2, hdr1, hdr2);
 | 
						|
  csv_encode(&csv, 4, "name", "age", "sex", "hei");
 | 
						|
  csv_encode(&csv, 3, NULL, "0", NULL);
 | 
						|
  csv_encode(&csv, 2, "p", "35");
 | 
						|
  for (i=0; i < 50; i++) {
 | 
						|
    csv_encode(&csv, 2, "p", "10");
 | 
						|
  }
 | 
						|
  csv_encode(&csv, 2, "pdfadfadfadsadsaddfdfdsfdsd",
 | 
						|
                 "35444554545454545");
 | 
						|
  log_verbose("%s\n", buf);
 | 
						|
  sprintf(hdr1, "%4u", csv.csv_len);
 | 
						|
  sprintf(hdr2, "%4u", 1);
 | 
						|
  log_verbose("(%d/%d/%d/%d)\n", strlen(hdr1),
 | 
						|
	  strlen(hdr2), atoi(hdr1), atoi(hdr2));
 | 
						|
  rec = csv_encode_record(&csv, rec, 2, hdr1, hdr2);
 | 
						|
  log_verbose("(%d/%d)\n%s\n", rec->rec_len, csv.csv_len, buf);
 | 
						|
 | 
						|
  log_verbose("Mem: %ld\n", get_memory_usage(getpid()));
 | 
						|
  csv_clean(&csv);
 | 
						|
  log_verbose("Mem: %ld\n", get_memory_usage(getpid()));
 | 
						|
  csv_init(&csv, buf, 256);
 | 
						|
  csv_decode(&csv, NULL);
 | 
						|
  log_verbose("AFTER DECODE\n");
 | 
						|
  csv_dump(&csv);
 | 
						|
  csv_clean(&csv);
 | 
						|
  log_verbose("Mem: %ld\n", get_memory_usage(getpid()));
 | 
						|
}
 | 
						|
#endif
 |