1 /* CSV 2 * Copyright (C) 2013 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 #ifndef __CSV_H__ 22 #define __CSV_H__ 23 24 /* 25 * CSV encoding and decoding routines. 26 * 27 * Example: 28 * Encoding side: 29 * 30 * csv_t *csv; 31 * csv_record_t *fstrec; 32 * csv_record_t *rec; 33 * char buf[BUFSIZ]; 34 * 35 * csv = csv_init(csv, buf, BUFSIZ); 36 * ... 37 * fstrec = csv_encode(csv, 2, "hello", "world"); 38 * rec = csv_encode(csv, 2, "foo", "bar"); 39 * ... 40 * fstrec = csv_encode_record(csv, fstrec, 2, "HELLO", "WORLD"); 41 * ... 42 * csv_clean(csv); 43 * 44 * Decoding side: 45 * 46 * csv_t *csv; 47 * csv_record_t *rec; 48 * csv_field_t *fld; 49 * char *rcvdbuf; 50 * 51 * csv = csv_init(csv, rcvdbuf, BUFSIZ); 52 * ... 53 * csv_decode(csv); 54 * csv_dump(csv); 55 * 56 * for (rec = csv_record_iter(csv); rec; 57 * rec = csv_record_iter_next(rec)) { 58 * ... 59 * for (str = csv_field_iter(rec, &fld); str; 60 * str = csv_field_iter_next(&fld)) { 61 * ... 62 * } 63 * } 64 * ... 65 * csv_clean(csv); 66 */ 67 #include <stdio.h> 68 #include <stdlib.h> 69 #include <string.h> 70 #include <stdarg.h> 71 #include <sys/queue.h> 72 73 #ifdef __cplusplus 74 extern "C" { 75 #endif 76 77 typedef struct _csv_field_t_ csv_field_t; 78 typedef struct _csv_record_t_ csv_record_t; 79 typedef struct _csv_t_ csv_t; 80 81 /** 82 * Initialize the CSV structure (if necessary, allocate first). Point to 83 * the passed string buffer. 84 */ 85 csv_t *csv_init(csv_t *csv, char *buf, int buflen); 86 87 /** 88 * Encode the variable list of arguments as CSV fields. The csv structure 89 * should have been initialized (with the string buffer). The fields get 90 * concatenated into the string. 91 */ 92 csv_record_t *csv_encode(csv_t *csv, int count, ...); 93 94 /** 95 * Encode the variable list arguments into an existing record, essentially 96 * overwriting the record. No checking is done for consistency. The number 97 * of fields should be the same as what was encoded and the length of each 98 * field should also be the same as what was encoded before. The "rec" 99 * parameter should be the same as what was returned from a previous call 100 * to csv_encode(). 101 * 102 * Useful for message encoding/decoding that get passed around between 103 * processes/nodes - e.g. the message header record can be rewritten AFTER 104 * encoding all other records, with new information such as total length. 105 */ 106 csv_record_t *csv_encode_record(csv_t *csv, csv_record_t *rec, int count, ...); 107 108 /** 109 * Decode a CSV formatted string. The csv structure should have been 110 * initialized (with the string). The function creates a LIST of records 111 * (csv_record_t structure) where each record is in turn a LIST of fields 112 * (csv_field_t structure). The record points to the string containing the 113 * list of fields. Similarly, the field points to the field string. 114 * NB: csv initialized for discrete buf , caller will pass inbuf 115 */ 116 void csv_decode(csv_t *csv, char *inbuf); 117 118 /** 119 * Dump all fields of a decoded CSV to stderr 120 */ 121 void csv_dump(csv_t *csv); 122 123 /** 124 * Total length of all characters encoded in the CSV. 125 */ 126 int csvlen(csv_t *csv); 127 128 void csv_clean(csv_t *csv); 129 void csv_free(csv_t *csv); 130 131 /** 132 * Iterate through the records and fields of an encoded/decoded CSV. 133 */ 134 csv_record_t *csv_record_iter(csv_t *csv); 135 csv_record_t *csv_record_iter_next(csv_record_t *rec); 136 char *csv_field_iter(csv_record_t *rec, csv_field_t **fld); 137 char *csv_field_iter_next(csv_field_t **fld); 138 139 /** 140 * Return the length of field 141 */ 142 int csv_field_len(csv_field_t *fld); 143 144 /** 145 * Checks to see if a record belongs to a csv 146 */ 147 int csv_is_record_valid(csv_t *csv, csv_record_t *in_rec); 148 149 /** 150 * concat two records in a csv 151 * Returns the newly formed record which includes fields from rec1 and rec2 152 * rec1 and rec2 are removed 153 */ 154 csv_record_t *csv_concat_record(csv_t *csv, csv_record_t *rec1, 155 csv_record_t *rec2); 156 157 /** 158 * Remove a record from csv 159 * Only works when csv has discrete record bufs 160 */ 161 void csv_remove_record(csv_t *csv, csv_record_t *rec); 162 163 /** 164 * Insert a record into csv 165 * Only works when csv has discrete record bufs 166 */ 167 void csv_insert_record(csv_t *csv, csv_record_t *rec); 168 169 /** 170 * append fields to a record 171 * Only works when csv has discrete record bufs 172 */ 173 csv_record_t *csv_append_record(csv_t *csv, csv_record_t *rec, int count, ...); 174 175 /** 176 * Serialize contents of csv into string 177 * Only works when csv has discrete record bufs 178 */ 179 int csv_serialize(csv_t *csv, char *msgbuf, int msglen); 180 181 /** 182 * Clone a record. 183 * Only works when csv has discrete record bufs 184 */ 185 void csv_clone_record(csv_t *csv, csv_record_t *in_rec, csv_record_t **out_rec); 186 187 /** 188 * Return number of records 189 */ 190 int csv_num_records(csv_t *csv); 191 192 #ifdef __cplusplus 193 } 194 #endif 195 196 #endif 197