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