UniRec 3.3.2
Loading...
Searching...
No Matches
unirec2csv.c
Go to the documentation of this file.
1#include <stdint.h>
2#include <inttypes.h>
3#include <ctype.h>
4#include <time.h>
5#include <unirec/unirec2csv.h>
6
7urcsv_t *urcsv_init(ur_template_t *tmplt, char delimiter)
8{
9 if (tmplt == NULL) {
10 return NULL;
11 }
12 urcsv_t *s = malloc(sizeof(urcsv_t));
13 if (s != NULL) {
14 s->tmplt = tmplt;
15 s->delimiter = delimiter;
16 /* default size of buffer */
17 s->buffer_size = 4096;
18 s->free_space = s->buffer_size;
19 s->buffer = calloc(s->buffer_size, sizeof(s->buffer[0]));
20 if (s->buffer == NULL) {
21 free(s);
22 return NULL;
23 }
24 }
25 return s;
26}
27
28void urcsv_free(urcsv_t **urcsv)
29{
30 if (urcsv != NULL && *urcsv != NULL) {
31 free((*urcsv)->buffer);
32 free(*urcsv);
33 (*urcsv) = NULL;
34 }
35}
36
37char *urcsv_header(urcsv_t *urcsv)
38{
39 if (urcsv == NULL) {
40 return NULL;
41 }
42 return ur_template_string_delimiter(urcsv->tmplt, urcsv->delimiter);
43}
44
45int urcsv_value(char *dst, uint32_t size, void *ptr, int type, int field_len)
46{
47 int written = 0;
48 char *p = dst;
49
50 // Static field - check what type is it and use appropriate format
51 switch (type) {
52 case UR_TYPE_UINT8:
53 written = snprintf(p, size, "%" PRIu8, *(uint8_t*) ptr);
54 break;
55 case UR_TYPE_UINT16:
56 written = snprintf(p, size, "%" PRIu16, *(uint16_t*) ptr);
57 break;
58 case UR_TYPE_UINT32:
59 written = snprintf(p, size, "%" PRIu32, *(uint32_t*) ptr);
60 break;
61 case UR_TYPE_UINT64:
62 written = snprintf(p, size, "%" PRIu64, *(uint64_t*) ptr);
63 break;
64 case UR_TYPE_INT8:
65 written = snprintf(p, size, "%" PRIi8, *(int8_t*) ptr);
66 break;
67 case UR_TYPE_INT16:
68 written = snprintf(p, size, "%" PRIi16, *(int16_t*) ptr);
69 break;
70 case UR_TYPE_INT32:
71 written = snprintf(p, size, "%" PRIi32, *(int32_t*) ptr);
72 break;
73 case UR_TYPE_INT64:
74 written = snprintf(p, size, "%" PRIi64, *(int64_t*) ptr);
75 break;
76 case UR_TYPE_CHAR:
77 written = snprintf(p, size, "%c", *(char*) ptr);
78 break;
79 case UR_TYPE_FLOAT:
80 written = snprintf(p, size, "%f", *(float*) ptr);
81 break;
82 case UR_TYPE_DOUBLE:
83 written = snprintf(p, size, "%f", *(double*) ptr);
84 break;
85 case UR_TYPE_IP:
86 {
87 // IP address - convert to human-readable format and print
88 char str[46];
89 ip_to_str((ip_addr_t*) ptr, str);
90 written = snprintf(p, size, "%s", str);
91 }
92 break;
93 case UR_TYPE_MAC:
94 {
95 // MAC address - convert to human-readable format and print
96 char str[MAC_STR_LEN];
97 mac_to_str((mac_addr_t *) ptr, str);
98 written = snprintf(p, size, "%s", str);
99 }
100 break;
101 case UR_TYPE_TIME:
102 {
103 // Timestamp - convert to human-readable format and print
104 time_t sec = ur_time_get_sec(*(ur_time_t*) ptr);
105 int usec = ur_time_get_usec(*(ur_time_t*) ptr);
106 char str[40];
107 struct tm tm_tmp;
108 strftime(str, 39, "%FT%T", gmtime_r(&sec, &tm_tmp));
109 written = snprintf(p, size, "%s.%06i", str, usec);
110 }
111 break;
112 default:
113 {
114 // Unknown type - print the value in hex
115 strncpy(p, "0x", size);
116 written += 2;
117 p += 2;
118 for (int i = 0; i < field_len && written < size; i++) {
119 int w = snprintf(p, size - written, "%02x", ((unsigned char *) ptr)[i]);
120 written += w;
121 p += w;
122 }
123 }
124 break;
125 } // case (field type)
126
127 return written;
128}
129
130int urcsv_field(char *dst, uint32_t size, const void *rec, ur_field_type_t id, ur_template_t *tmplt)
131{
132 int written = 0;
133 char *p = dst;
134
135 // Get pointer to the field (valid for static fields only)
136 void *ptr = ur_get_ptr_by_id(tmplt, rec, id);
137 int type = ur_get_type(id);
138
139 if (type == UR_TYPE_STRING) {
140 // Printable string - print it as it is
141 int fs = ur_get_var_len(tmplt, rec, id);
142 char *data = ur_get_ptr_by_id(tmplt, rec, id);
143 *(p++) = '"';
144 written++;
145
146 while (fs-- && (written < size)) {
147 switch (*data) {
148 case '\n': // Replace newline with space
149 /* TODO / FIXME possible bug - info lost */
150 *(p++) = ' ';
151 written++;
152 break;
153 case '"' : // Double quotes in string
154 *(p++) = '"';
155 written++;
156 *(p++) = '"';
157 written++;
158 break;
159 default: // Check if character is printable
160 if (isprint(*data)) {
161 *(p++) = *data;
162 written++;
163 }
164 }
165 data++;
166 }
167 *(p++) = '"';
168 written++;
169 } else if (type == UR_TYPE_BYTES) {
170 // Generic string of bytes - print each byte as two hex digits
171 int fs = ur_get_var_len(tmplt, rec, id);
172 unsigned char *data = ur_get_ptr_by_id(tmplt, rec, id);
173 while (fs-- && (written < size)) {
174 int w = snprintf(p, size, "%02x", *data++);
175 written += w;
176 p += w;
177 }
178 } else if (ur_is_varlen(id)) {
179 int elem_type = ur_array_get_elem_type(id);
180 int elem_size = ur_array_get_elem_size(id);
181 int elem_cnt = ur_array_get_elem_cnt(tmplt, rec, id);
182 int array_len = ur_get_len(tmplt, rec, id);
183 int i;
184
185 if (written + 2 < size) {
186 written += 2;
187 *(p++) = '[';
188 for (i = 0; i < elem_cnt; i++) {
189 int w = urcsv_value(p, size - written, ((char *) ptr) + i * elem_size, elem_type, array_len);
190 written += w;
191 p += w;
192 if (written + 1 >= size) {
193 /* not enough space */
194 return 0;
195 }
196 if (i + 1 != elem_cnt) {
197 *(p++) = '|';
198 written++;
199 }
200 }
201 *(p++) = ']';
202 }
203 } else {
204 return urcsv_value(p, size, ptr, type, ur_get_len(tmplt, rec, id));
205 }
206
207 return written;
208}
209
210char *urcsv_record(urcsv_t *urcsv, const void *rec)
211{
212 int delim = 0;
213 int i = 0, written = 0;
214 ur_field_id_t id = 0;
215
216 if (urcsv == NULL || rec == NULL) {
217 return NULL;
218 }
219
220 urcsv->curpos = urcsv->buffer;
221 urcsv->free_space = urcsv->buffer_size;
222
223 // Iterate over all output fields
224 while ((id = ur_iter_fields_record_order(urcsv->tmplt, i++)) != UR_ITER_END) {
225 if (delim != 0) {
226 *(urcsv->curpos++) = urcsv->delimiter;
227 urcsv->free_space -= 1;
228 }
229
230 delim = 1;
231 if (ur_is_present(urcsv->tmplt, id)) {
232 // check buffer and field size
233 size_t field_size = ur_get_len(urcsv->tmplt, rec, id);
234 if (field_size > urcsv->free_space) {
235 size_t size = urcsv->buffer_size / 2;
236 if (urcsv->free_space + size < field_size)
237 size = field_size;
238 urcsv->free_space += size;
239 urcsv->buffer_size += size;
240 uint32_t offset = urcsv->curpos - urcsv->buffer;
241 void *temp = realloc(urcsv->buffer, urcsv->buffer_size);
242 if (temp != NULL) {
243 urcsv->buffer = temp;
244 urcsv->curpos = urcsv->buffer + offset;
245 } else {
246 return NULL;
247 }
248 }
249 written = urcsv_field(urcsv->curpos, urcsv->free_space, rec, id, urcsv->tmplt);
250
251 urcsv->free_space -= written;
252 urcsv->curpos += written;
253 } else {
254 continue;
255 }
256 } // loop over fields
257
258 *urcsv->curpos = 0;
259 return strdup(urcsv->buffer);
260}
261
uint32_t buffer_size
Definition unirec2csv.h:66
uint32_t free_space
Definition unirec2csv.h:71
char delimiter
Definition unirec2csv.h:76
char * curpos
Definition unirec2csv.h:61
ur_template_t * tmplt
Definition unirec2csv.h:51
char * buffer
Definition unirec2csv.h:56
char * urcsv_record(urcsv_t *urcsv, const void *rec)
Definition unirec2csv.c:210
void urcsv_free(urcsv_t **urcsv)
Definition unirec2csv.c:28
char * urcsv_header(urcsv_t *urcsv)
Definition unirec2csv.c:37
urcsv_t * urcsv_init(ur_template_t *tmplt, char delimiter)
Definition unirec2csv.c:7
int urcsv_field(char *dst, uint32_t size, const void *rec, ur_field_type_t id, ur_template_t *tmplt)
Definition unirec2csv.c:130
INLINE_IMPL void ip_to_str(const ip_addr_t *addr, char *str)
Definition ipaddr.h:325
#define ur_is_varlen(field_id)
Is given field variable-length? Return true (non-zero value) if given ID refers to a field with varia...
Definition unirec.h:646
char * ur_template_string_delimiter(const ur_template_t *tmplt, int delimiter)
Get UniRec specifier of the tmplt template with delimiter between fields.
Definition unirec.c:257
#define ur_array_get_elem_type(field_id)
Get type of an element stored in an UniRec array.
Definition unirec.h:555
ur_iter_t ur_iter_fields_record_order(const ur_template_t *tmplt, int index)
Iterate over fields of a template This function can be used to iterate over all fields of a given tem...
Definition unirec.c:1312
#define ur_get_var_len(tmplt, rec, field_id)
Get size of a variable sized field in the record. Get size of a variable-length field in the record....
Definition unirec.h:474
#define ur_array_get_elem_cnt(tmplt, rec, field_id)
Get number of elements stored in an UniRec array.
Definition unirec.h:546
#define ur_array_get_elem_size(field_id)
Get size of a single element of UniRec field.
Definition unirec.h:535
#define ur_get_len(tmplt, rec, field)
Get length of UniRec field Get actual length of fixed or variable-length UniRec field.
Definition unirec.h:506
#define ur_get_type(field_id)
Get type of UniRec field Get type of any UniRec defined field.
Definition unirec.h:388
#define ur_get_ptr_by_id(tmplt, data, field_id)
Get pointer to UniRec field Get pointer to fixed or varible length UniRec field. In contrast to ur_ge...
Definition unirec.h:442
#define ur_is_present(tmplt, field_id)
Is given field present in given template? Return true (non-zero value) if given template contains fie...
Definition unirec.h:638
#define ur_time_get_sec(time)
Get number of seconds from ur_time_t.
Definition ur_time.h:124
#define ur_time_get_usec(time)
Get number of microeconds from ur_time_t.
Definition ur_time.h:139
uint64_t ur_time_t
Type of timestamps used in UniRec Timestamps in UniRec are stored as number of seconds from Unix epoc...
Definition ur_time.h:61
mac_addr_t
Definition macaddr.h:75
#define MAC_STR_LEN
Definition macaddr.h:57
int urcsv_value(char *dst, uint32_t size, void *ptr, int type, int field_len)
Definition unirec2csv.c:45
Definition of UniRec API to create CSV-like representation of UniRec data.
INLINE_IMPL void mac_to_str(const mac_addr_t *addr, char *str)
Definition macaddr.h:129
ur_field_type_t
Definition unirec.h:95
@ UR_TYPE_UINT64
unsigned int (64b)
Definition unirec.h:105
@ UR_TYPE_INT16
int (8b)
Definition unirec.h:102
@ UR_TYPE_IP
IP address (128b)
Definition unirec.h:109
@ UR_TYPE_INT8
int (8b)
Definition unirec.h:100
@ UR_TYPE_CHAR
char
Definition unirec.h:98
@ UR_TYPE_DOUBLE
double (64b)
Definition unirec.h:108
@ UR_TYPE_TIME
time (64b)
Definition unirec.h:111
@ UR_TYPE_UINT8
unsigned int (8b)
Definition unirec.h:99
@ UR_TYPE_INT64
int (64b)
Definition unirec.h:106
@ UR_TYPE_STRING
var-len fields (string where only printable characters are expected; '\0' at the end should NOT be in...
Definition unirec.h:96
@ UR_TYPE_INT32
int (32b)
Definition unirec.h:104
@ UR_TYPE_UINT16
unsigned int (16b)
Definition unirec.h:101
@ UR_TYPE_UINT32
unsigned int (32b)
Definition unirec.h:103
@ UR_TYPE_MAC
MAC address (48b)
Definition unirec.h:110
@ UR_TYPE_BYTES
var-len fields (generic string of bytes)
Definition unirec.h:97
@ UR_TYPE_FLOAT
float (32b)
Definition unirec.h:107
int16_t ur_field_id_t
Type of UniRec field identifiers.
Definition unirec.h:136
#define UR_ITER_END
Last value in iterating through the fields.
Definition unirec.h:76
UniRec template. It contains a table mapping a field to its position in an UniRec record.
Definition unirec.h:191