summaryrefslogtreecommitdiffstats
path: root/lib/csv.h
blob: c780ab652f809cf7e9d85829a56ec151cca9f319 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// SPDX-License-Identifier: GPL-2.0-or-later
/* CSV
 * Copyright (C) 2013 Cumulus Networks, Inc.
 */

#ifndef __CSV_H__
#define __CSV_H__

/*
 * CSV encoding and decoding routines.
 *
 * Example:
 * Encoding side:
 *
 *      csv_t *csv;
 *      csv_record_t *fstrec;
 *      csv_record_t *rec;
 *      char  buf[BUFSIZ];
 *
 *      csv = csv_init(csv, buf, BUFSIZ);
 *      ...
 *      fstrec = csv_encode(csv, 2, "hello", "world");
 *      rec = csv_encode(csv, 2, "foo", "bar");
 *      ...
 *      fstrec = csv_encode_record(csv, fstrec, 2, "HELLO", "WORLD");
 *      ...
 *      csv_clean(csv);
 *
 * Decoding side:
 *
 *      csv_t *csv;
 *      csv_record_t *rec;
 *      csv_field_t *fld;
 *      char  *rcvdbuf;
 *
 *      csv = csv_init(csv, rcvdbuf, BUFSIZ);
 *      ...
 *      csv_decode(csv);
 *      csv_dump(csv);
 *
 *      for (rec = csv_record_iter(csv); rec;
 *           rec = csv_record_iter_next(rec)) {
 *          ...
 *          for (str = csv_field_iter(rec, &fld); str;
 *               str = csv_field_iter_next(&fld)) {
 *              ...
 *          }
 *      }
 *      ...
 *      csv_clean(csv);
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/queue.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct _csv_field_t_ csv_field_t;
typedef struct _csv_record_t_ csv_record_t;
typedef struct _csv_t_ csv_t;

/**
 * Initialize the CSV structure (if necessary, allocate first). Point to
 * the passed string buffer.
 */
csv_t *csv_init(csv_t *csv, char *buf, int buflen);

/**
 * Encode the variable list of arguments as CSV fields. The csv structure
 * should have been initialized (with the string buffer). The fields get
 * concatenated into the string.
 */
csv_record_t *csv_encode(csv_t *csv, int count, ...);

/**
 * Encode the variable list arguments into an existing record, essentially
 * overwriting the record. No checking is done for consistency. The number
 * of fields should be the same as what was encoded and the length of each
 * field should also be the same as what was encoded before. The "rec"
 * parameter should be the same as what was returned from a previous call
 * to csv_encode().
 *
 * Useful for message encoding/decoding that get passed around between
 * processes/nodes - e.g. the message header record can be rewritten AFTER
 * encoding all other records, with new information such as total length.
 */
csv_record_t *csv_encode_record(csv_t *csv, csv_record_t *rec, int count, ...);

/**
 * Decode a CSV formatted string. The csv structure should have been
 * initialized (with the string). The function creates a LIST of records
 * (csv_record_t structure) where each record is in turn a LIST of fields
 * (csv_field_t structure). The record points to the string containing the
 * list of fields. Similarly, the field points to the field string.
 * NB: csv initialized for discrete buf , caller will pass inbuf
 */
void csv_decode(csv_t *csv, char *inbuf);

/**
 * Dump all fields of a decoded CSV to stderr
 */
void csv_dump(csv_t *csv);

/**
 * Total length of all characters encoded in the CSV.
 */
int csvlen(csv_t *csv);

void csv_clean(csv_t *csv);
void csv_free(csv_t *csv);

/**
 * Iterate through the records and fields of an encoded/decoded CSV.
 */
csv_record_t *csv_record_iter(csv_t *csv);
csv_record_t *csv_record_iter_next(csv_record_t *rec);
char *csv_field_iter(csv_record_t *rec, csv_field_t **fld);
char *csv_field_iter_next(csv_field_t **fld);

/**
 * Return the length of field
 */
int csv_field_len(csv_field_t *fld);

/**
 * Checks to see if a record belongs to a csv
 */
int csv_is_record_valid(csv_t *csv, csv_record_t *in_rec);

/**
 * concat two records in a csv
 * Returns the newly formed record which includes fields from rec1 and rec2
 * rec1 and rec2 are removed
 */
csv_record_t *csv_concat_record(csv_t *csv, csv_record_t *rec1,
				csv_record_t *rec2);

/**
 * Remove a record from csv
 * Only works when csv has discrete record bufs
 */
void csv_remove_record(csv_t *csv, csv_record_t *rec);

/**
 * Insert a record into csv
 * Only works when csv has discrete record bufs
 */
void csv_insert_record(csv_t *csv, csv_record_t *rec);

/**
 * append fields to a record
 * Only works when csv has discrete record bufs
 */
csv_record_t *csv_append_record(csv_t *csv, csv_record_t *rec, int count, ...);

/**
 * Serialize contents of csv into string
 * Only works when csv has discrete record bufs
 */
int csv_serialize(csv_t *csv, char *msgbuf, int msglen);

/**
 * Clone a record.
 * Only works when csv has discrete record bufs
 */
void csv_clone_record(csv_t *csv, csv_record_t *in_rec, csv_record_t **out_rec);

/**
 * Return number of records
 */
int csv_num_records(csv_t *csv);

#ifdef __cplusplus
}
#endif

#endif