UniRec 3.3.2
Loading...
Searching...
No Matches
unirec.c
Go to the documentation of this file.
1
8/*
9 * Copyright (C) 2015 CESNET
10
11 *
12 * LICENSE TERMS
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in
21 * the documentation and/or other materials provided with the
22 * distribution.
23 * 3. Neither the name of the Company nor the names of its contributors
24 * may be used to endorse or promote products derived from this
25 * software without specific prior written permission.
26 *
27 * ALTERNATIVELY, provided that this notice is retained in full, this
28 * product may be distributed under the terms of the GNU General Public
29 * License (GPL) version 2 or later, in which case the provisions
30 * of the GPL apply INSTEAD OF those given above.
31 *
32 * This software is provided ``as is'', and any express or implied
33 * warranties, including, but not limited to, the implied warranties of
34 * merchantability and fitness for a particular purpose are disclaimed.
35 * In no event shall the company or contributors be liable for any
36 * direct, indirect, incidental, special, exemplary, or consequential
37 * damages (including, but not limited to, procurement of substitute
38 * goods or services; loss of use, data, or profits; or business
39 * interruption) however caused and on any theory of liability, whether
40 * in contract, strict liability, or tort (including negligence or
41 * otherwise) arising in any way out of the use of this software, even
42 * if advised of the possibility of such damage.
43 *
44 */
45
46#define _DEFAULT_SOURCE
47#define _BSD_SOURCE
48#define _XOPEN_SOURCE
49#define __USE_XOPEN
50#include <stdlib.h>
51#include <stdio.h>
52#include <inttypes.h>
53#include <time.h>
54#include <string.h>
55#include <regex.h>
56#include <assert.h>
57#include <ctype.h>
58#include <unirec/unirec.h>
59#include <unirec/inline.h>
60#include <libtrap/trap.h>
61#include <inttypes.h>
63
64#ifndef MAX
65#define MAX(A, B) ((A >= B) ? (A) : (B))
66#endif
67
68// All inline functions from ipaddr.h must be declared again with "extern"
69// in exactly one translation unit (it generates externally linkable code of
70// these function)
71// See this for explanation (Nemo's answer):
72// http://stackoverflow.com/questions/6312597/is-inline-without-static-or-extern-ever-useful-in-c99
73INLINE_IMPL int ip_is4(const ip_addr_t *addr);
74INLINE_IMPL int ip_is6(const ip_addr_t *addr);
75INLINE_IMPL uint32_t ip_get_v4_as_int(const ip_addr_t *addr);
82INLINE_IMPL int ip_cmp(const ip_addr_t *addr1, const ip_addr_t *addr2);
83INLINE_IMPL int ip_from_str(const char *str, ip_addr_t *addr);
84INLINE_IMPL void ip_to_str(const ip_addr_t *addr, char *str);
85
86INLINE_IMPL mac_addr_t mac_from_bytes(const uint8_t *array);
87INLINE_IMPL int mac_from_str(const char *str, mac_addr_t *addr);
88INLINE_IMPL int mac_cmp(const mac_addr_t *addr1, const mac_addr_t *addr2);
89INLINE_IMPL void mac_to_str(const mac_addr_t *addr, char *str);
90INLINE_IMPL void mac_to_bytes(const mac_addr_t *addr, uint8_t *array);
91
92
98const int ur_field_type_size[] = {
99 -1, /*UR_TYPE_STRING*/
100 -1, /*UR_TYPE_BYTES*/
101 1, /*UR_TYPE_CHAR*/
102 1, /*UR_TYPE_UINT8*/
103 1, /*UR_TYPE_INT8*/
104 2, /*UR_TYPE_UINT16*/
105 2, /*UR_TYPE_INT16*/
106 4, /*UR_TYPE_UINT32*/
107 4, /*UR_TYPE_INT32*/
108 8, /*UR_TYPE_UINT64*/
109 8, /*UR_TYPE_INT64*/
110 4, /*UR_TYPE_FLOAT*/
111 8, /*UR_TYPE_DOUBLE*/
112 16, /*UR_TYPE_IP*/
113 6, /*UR_TYPE_MAC*/
114 8, /*UR_TYPE_TIME*/
115
116 // arrays
117 -1, /*UR_TYPE_A_UINT8*/
118 -1, /*UR_TYPE_A_INT8*/
119 -2, /*UR_TYPE_A_UINT16*/
120 -2, /*UR_TYPE_A_INT16*/
121 -4, /*UR_TYPE_A_UINT32*/
122 -4, /*UR_TYPE_A_INT32*/
123 -8, /*UR_TYPE_A_UINT64*/
124 -8, /*UR_TYPE_A_INT64*/
125 -4, /*UR_TYPE_A_FLOAT*/
126 -8, /*UR_TYPE_A_DOUBLE*/
127 -16, /*UR_TYPE_A_IP*/
128 -6, /*UR_TYPE_A_MAC*/
129 -8, /*UR_TYPE_A_TIME*/
130};
131
137const char *ur_field_type_str[] = {
138 "string", /*UR_TYPE_STRING*/
139 "bytes", /*UR_TYPE_BYTES*/
140 "char", /*UR_TYPE_CHAR*/
141 "uint8", /*UR_TYPE_UINT8*/
142 "int8", /*UR_TYPE_INT8*/
143 "uint16", /*UR_TYPE_UINT16*/
144 "int16", /*UR_TYPE_INT16*/
145 "uint32", /*UR_TYPE_UINT32*/
146 "int32", /*UR_TYPE_INT32*/
147 "uint64", /*UR_TYPE_UINT64*/
148 "int64", /*UR_TYPE_INT64*/
149 "float", /*UR_TYPE_FLOAT*/
150 "double", /*UR_TYPE_DOUBLE*/
151 "ipaddr", /*UR_TYPE_IP*/
152 "macaddr", /*UR_TYPE_MAC*/
153 "time", /*UR_TYPE_TIME*/
154 "uint8*", /*UR_TYPE_A_UINT8*/
155 "int8*", /*UR_TYPE_A_INT8*/
156 "uint16*", /*UR_TYPE_A_UINT16*/
157 "int16*", /*UR_TYPE_A_INT16*/
158 "uint32*", /*UR_TYPE_A_UINT32*/
159 "int32*", /*UR_TYPE_A_INT32*/
160 "uint64*", /*UR_TYPE_A_UINT64*/
161 "int64*", /*UR_TYPE_A_INT64*/
162 "float*", /*UR_TYPE_A_FLOAT*/
163 "double*", /*UR_TYPE_A_DOUBLE*/
164 "ipaddr*", /*UR_TYPE_A_IP*/
165 "macaddr*", /*UR_TYPE_A_MAC*/
166 "time*", /*UR_TYPE_A_TIME*/
167};
168
173 UR_TYPE_STRING, /* UR_TYPE_STRING */
174 UR_TYPE_BYTES, /* UR_TYPE_BYTES */
175 UR_TYPE_CHAR, /* UR_TYPE_CHAR */
176 UR_TYPE_UINT8, /* UR_TYPE_UINT8 */
177 UR_TYPE_INT8, /* UR_TYPE_INT8 */
178 UR_TYPE_UINT16, /* UR_TYPE_UINT16 */
179 UR_TYPE_INT16, /* UR_TYPE_INT16 */
180 UR_TYPE_UINT32, /* UR_TYPE_UINT32 */
181 UR_TYPE_INT32, /* UR_TYPE_INT32 */
182 UR_TYPE_UINT64, /* UR_TYPE_UINT64 */
183 UR_TYPE_INT64, /* UR_TYPE_INT64 */
184 UR_TYPE_FLOAT, /* UR_TYPE_FLOAT */
185 UR_TYPE_DOUBLE, /* UR_TYPE_DOUBLE */
186 UR_TYPE_IP, /* UR_TYPE_IP */
187 UR_TYPE_MAC, /* UR_TYPE_MAC */
188 UR_TYPE_TIME, /* UR_TYPE_TIME */
189 UR_TYPE_UINT8, /* UR_TYPE_A_UINT8 */
190 UR_TYPE_INT8, /* UR_TYPE_A_INT8 */
191 UR_TYPE_UINT16, /* UR_TYPE_A_UINT16 */
192 UR_TYPE_INT16, /* UR_TYPE_A_INT16 */
193 UR_TYPE_UINT32, /* UR_TYPE_A_UINT32 */
194 UR_TYPE_INT32, /* UR_TYPE_A_INT32 */
195 UR_TYPE_UINT64, /* UR_TYPE_A_UINT64 */
196 UR_TYPE_INT64, /* UR_TYPE_A_INT64 */
197 UR_TYPE_FLOAT, /* UR_TYPE_A_FLOAT */
198 UR_TYPE_DOUBLE, /* UR_TYPE_A_DOUBLE */
199 UR_TYPE_IP, /* UR_TYPE_A_IP */
200 UR_TYPE_MAC, /* UR_TYPE_A_MAC */
201 UR_TYPE_TIME, /* UR_TYPE_A_TIME */
202};
203
204
207
208const char UR_MEMORY_ERROR[] = "Memory allocation error";
209
210int ur_init(ur_static_field_specs_t field_specs_static)
211{
212 int i, j;
214 return UR_OK;
215 }
216 //copy size
218 ur_field_specs.ur_last_id = field_specs_static.ur_last_id;
220 //copy field type
222 if (ur_field_specs.ur_field_types == NULL) {
223 return UR_E_MEMORY;
224 }
225 memcpy(ur_field_specs.ur_field_types, field_specs_static.ur_field_types, sizeof(ur_field_type_t) * field_specs_static.ur_last_id);
226 //copy field sizes
227 ur_field_specs.ur_field_sizes = (short *) calloc(sizeof(short), ur_field_specs.ur_allocated_fields);
228 if (ur_field_specs.ur_field_sizes == NULL) {
230 return UR_E_MEMORY;
231 }
232 memcpy(ur_field_specs.ur_field_sizes, field_specs_static.ur_field_sizes, sizeof(short) * field_specs_static.ur_last_id);
233 //copy field names
234 ur_field_specs.ur_field_names = (char **) calloc(sizeof(char *), ur_field_specs.ur_allocated_fields);
235 if (ur_field_specs.ur_field_names == NULL) {
238 return UR_E_MEMORY;
239 }
240 for (i = 0; i < field_specs_static.ur_last_id; i++) {
241 ur_field_specs.ur_field_names[i] = (char *) calloc(sizeof(char), strlen(field_specs_static.ur_field_names[i]) + 1);
242 if (ur_field_specs.ur_field_names[i] == NULL) {
245 for (j = 0; j < i; j++) {
247 }
249 return UR_E_MEMORY;
250 }
251 strcpy(ur_field_specs.ur_field_names[i], field_specs_static.ur_field_names[i]);
252 }
254 return UR_OK;
255}
256
257char *ur_template_string_delimiter(const ur_template_t *tmplt, int delimiter)
258{
259 char *str = NULL, *strmove = NULL, *str_new = NULL;
260 int len = UR_DEFAULT_LENGTH_OF_TEMPLATE, act_len = 0;
261
262 if (tmplt == NULL) {
263 return NULL;
264 }
265
266 str = (char *) calloc(sizeof(char), len);
267 if (str == NULL) {
268 return NULL;
269 }
270 strmove = str;
271 for (int i = 0; i < tmplt->count; i++) {
272 act_len += strlen(ur_field_type_str[ur_get_type(tmplt->ids[i])]) + strlen(ur_get_name(tmplt->ids[i])) + 2;
273 if (act_len >= len) {
274 len *= 2;
275 str_new = (char *) realloc(str, sizeof(char) * len);
276 if (str_new == NULL) {
277 free(str);
278 return NULL;
279 }
280 strmove = str_new + (strmove - str);
281 str = str_new;
282 }
283 sprintf(strmove, "%s %s%c", ur_field_type_str[ur_get_type(tmplt->ids[i])], ur_get_name(tmplt->ids[i]), delimiter);
284 strmove += strlen(strmove);
285 }
286 if (tmplt->count != 0) {
287 strmove[-1] = '\0';
288 }
289 return str;
290}
291
293{
294 ur_field_id_linked_list_t * first;
295 //check if UniRec is initialized, if not initialize it
297 int init_val = ur_init(UR_FIELD_SPECS_STATIC);
298 if (init_val != UR_OK) {
299 return init_val;
300 }
301 }
302 //check undefined fields
304 //resuse old undefined fields
305 int id;
308 id = first->id;
309 free(first);
310 return id;
311 } else {
312 //take new id
314 //take value from remaining space
315 return ur_field_specs.ur_last_id++;
317 //increase space for fields
318 int new_size;
319
320 char **ur_field_names_new;
321 short *ur_field_sizes_new;
322 ur_field_type_t *ur_field_types_new;
323
325
326 //copy field type
327 ur_field_types_new = (ur_field_type_t *) realloc(ur_field_specs.ur_field_types, sizeof(ur_field_type_t) * new_size);
328 if (ur_field_types_new == NULL) {
329 return UR_E_MEMORY;
330 }
331
332 //copy field sizes
333 ur_field_sizes_new = (short *) realloc(ur_field_specs.ur_field_sizes, sizeof(short) * new_size);
334 if (ur_field_sizes_new == NULL) {
335 free(ur_field_types_new);
336 return UR_E_MEMORY;
337 }
338
339 //copy field names
340 ur_field_names_new = (char **) realloc(ur_field_specs.ur_field_names, sizeof(char *) * new_size);
341 if (ur_field_names_new == NULL) {
342 free(ur_field_types_new);
343 free(ur_field_sizes_new);
344 return UR_E_MEMORY;
345 }
346 //replace for new values
347 ur_field_specs.ur_field_names = ur_field_names_new;
348 ur_field_specs.ur_field_sizes = ur_field_sizes_new;
349 ur_field_specs.ur_field_types = ur_field_types_new;
351 return ur_field_specs.ur_last_id++;
352 } else {
353 //no more space for new fields
354 return UR_E_MEMORY;
355 }
356 }
357}
358
359int ur_get_field_type_from_str(const char *type)
360{
361 if (type == NULL) {
362 return UR_E_INVALID_TYPE;
363 }
364 for (int i = 0; i < UR_COUNT_OF_TYPES; i++) {
365 if (strcmp(type, ur_field_type_str[i]) == 0) {
366 return i;
367 }
368 }
369 return UR_E_INVALID_TYPE;
370}
371
372const char *ur_get_type_and_name_from_string(const char *source, char **name, char **type, int *length_name, int *length_type)
373{
374 int length_type_2 = 0, length_name_2 = 0;
375 const char *source_cpy;
376 /* skip white spaces */
377 while (*source != 0 && isspace(*source)) {
378 source++;
379 }
380 /* start of type */
381 source_cpy = source;
382 while (*source != 0 && !isspace(*source)) {
383 length_type_2++;
384 source++;
385 }
386 /* end of type */
387
388 /* copy "type" string (realloc destination if needed) */
389 if (length_type_2 >= *length_type) {
390 if (*type != NULL) {
391 free(*type);
392 }
393 *type = (char *) malloc(sizeof(char) * (length_type_2 + 1));
394 if (*type == NULL) {
395 return NULL;
396 }
397 *length_type = length_type_2 + 1;
398 }
399 memcpy(*type, source_cpy, length_type_2);
400 (*type)[length_type_2] = 0;
401
402 /* skip white spaces */
403 while (*source != 0 && isspace(*source)) {
404 source++;
405 }
406 /* start of name */
407 source_cpy = source;
408 while (*source != 0 && !isspace(*source) && *source != ',') {
409 length_name_2++;
410 source++;
411 }
412 /* end of name */
413
414 /* copy "name" string (realloc destination if needed) */
415 if (length_name_2 >= *length_name) {
416 if (*name != NULL) {
417 free(*name);
418 }
419 *name = (char *) malloc(sizeof(char) * (length_name_2 + 1));
420 if (*name == NULL) {
421 return NULL;
422 }
423 *length_name = length_name_2 + 1;
424 }
425 memcpy(*name, source_cpy, length_name_2);
426 (*name)[length_name_2] = 0;
427 /* skip white spaces */
428 while (*source != 0 && isspace(*source)) {
429 source++;
430 }
431 /* skip comma */
432 if (*source == ',') {
433 source++;
434 }
435 return source;
436}
437
438char *ur_ifc_data_fmt_to_field_names(const char *ifc_data_fmt)
439{
440 const char *source_cpy = NULL, *p = ifc_data_fmt;
441 char *out_str;
442 int name_len = 0, act_len = 0, str_len;
443 str_len = strlen(ifc_data_fmt);
444 out_str = (char *) calloc(str_len + 1, sizeof(char));
445 if (out_str == NULL) {
446 return NULL;
447 }
448 while (*p != 0) {
449 /* skip white spaces */
450 while (*p != 0 && isspace(*p)) {
451 p++;
452 }
453 /* field type */
454 while (*p != 0 && *p != ' ') {
455 p++;
456 }
457 /* skip white spaces */
458 while (*p != 0 && isspace(*p)) {
459 p++;
460 }
461
462 //copy name
463 source_cpy = p;
464 name_len = 0;
465 while (*p != 0 && *p != ',' && !isspace(*p)) {
466 name_len++;
467 p++;
468 }
469 assert(name_len + act_len + 1 <= str_len);
470 memcpy(out_str + act_len, source_cpy, name_len);
471 act_len += name_len;
472 /* skip white spaces */
473 while (*p != 0 && isspace(*p)) {
474 p++;
475 }
476 if (*p == ',') {
477 p++;
478 } else if (*p == 0) {
479 break;
480 } else {
481 free(out_str);
482 return NULL; /* name must be followed by a comma or end of string */
483 }
484 out_str[act_len] = ',';
485 act_len++;
486 }
487 return out_str;
488}
489
490ur_template_t *ur_expand_template(const char *ifc_data_fmt, ur_template_t *tmplt)
491{
492 int name_len = 0, act_len = 0, concat_str_len = strlen(ifc_data_fmt);
493 char *concat_str;
494 const char *source_cpy, *p = ifc_data_fmt;
496 uint32_t ifc_out = 0;
497 concat_str = (char *) malloc(sizeof(char) * concat_str_len);
498 if (concat_str == NULL) {
499 return NULL;
500 }
501 while (*p != 0) {
502 while (*p != 0 && !isspace(*p)) {
503 p++;
504 }
505 p++;
506 //copy name
507 source_cpy = p;
508 name_len = 0;
509 while (*p != 0 && *p != ',') {
510 name_len++;
511 p++;
512 }
513 if (name_len + act_len + 1 > concat_str_len) {
514 char *str_new;
515 size_t req_size = MAX(name_len + act_len + 1, (concat_str_len * 2));
516 str_new = (char *) realloc(concat_str, sizeof(char) * req_size);
517 if (str_new == NULL) {
518 /* XXX memory leak original concat_str? */
519 return NULL;
520 }
521 concat_str_len = req_size;
522 concat_str = str_new;
523 }
524 memcpy(concat_str + act_len, source_cpy, name_len);
525 act_len += name_len;
526 concat_str[act_len] = ',';
527 act_len++;
528 }
529 if (tmplt != NULL) {
530 direction = tmplt->direction;
531 ifc_out = tmplt->ifc_out;
532 for (int i = 0; i < tmplt->count; i++) {
533 const char *f_name = ur_get_name(tmplt->ids[i]);
534 name_len = strlen(f_name);
535 if (name_len + act_len + 1 > concat_str_len) {
536 char *str_new;
537 size_t req_size = MAX(name_len + act_len + 1, (concat_str_len * 2));
538 str_new = (char *) realloc(concat_str, sizeof(char) * req_size);
539 if (str_new == NULL) {
540 /* XXX memory leak original concat_str? */
541 return NULL;
542 }
543 concat_str_len = req_size;
544 concat_str = str_new;
545 }
546 memcpy(concat_str + act_len, f_name, name_len);
547 act_len += name_len;
548 *(concat_str + act_len) = ',';
549 act_len++;
550 }
551 ur_free_template(tmplt);
552 }
553 if (act_len > 0) {
554 act_len--;
555 concat_str[act_len] = 0;
556 }
557 tmplt = ur_create_template(concat_str, NULL);
558 tmplt->direction = direction;
559 tmplt->ifc_out = ifc_out;
560 free(concat_str);
561 return tmplt;
562}
563
564int ur_define_set_of_fields(const char *ifc_data_fmt)
565{
566 const char *new_fields_move;
567 new_fields_move = ifc_data_fmt;
568 char *field_name, *field_type;
569 int field_name_length = UR_DEFAULT_LENGTH_OF_FIELD_NAME, field_type_length = UR_DEFAULT_LENGTH_OF_FIELD_TYPE;
570 int field_id = 0, field_type_id = 0;
571 field_name = (char *) malloc(sizeof(char) * field_name_length);
572 if (field_name == NULL) {
573 return UR_E_MEMORY;
574 }
575 field_type = (char *) malloc(sizeof(char) * field_type_length);
576 if (field_type == NULL) {
577 free(field_name);
578 return UR_E_MEMORY;
579 }
580 while (*new_fields_move != 0) {
581 new_fields_move = ur_get_type_and_name_from_string(new_fields_move, &field_name, &field_type, &field_name_length, &field_type_length);
582 if (new_fields_move == NULL) {
583 if (field_name != NULL) {
584 free(field_name);
585 }
586 if (field_type != NULL) {
587 free(field_type);
588 }
589 return UR_E_MEMORY;
590 }
591 //through all fields of receiver
592 field_type_id = ur_get_field_type_from_str(field_type);
593 if (field_type_id < 0) {
594 if (field_name != NULL) {
595 free(field_name);
596 }
597 free(field_type);
598 return field_type_id;
599 }
600 field_id = ur_define_field(field_name, field_type_id);
601 if (field_id < 0) {
602 if (field_name != NULL) {
603 free(field_name);
604 }
605 free(field_type);
606 return field_id;
607 }
608 }
609 if (field_name != NULL) {
610 free(field_name);
611 }
612 free(field_type);
613 return UR_OK;
614}
615
617{
618 ur_template_t *new_tmplt;
619 if (ur_define_set_of_fields(ifc_data_fmt) < 0) {
620 return NULL;
621 }
622 new_tmplt = ur_create_template_from_ifc_spec(ifc_data_fmt);
623 if (new_tmplt != NULL && tmplt != NULL) {
624 new_tmplt->ifc_out = tmplt->ifc_out;
625 new_tmplt->direction = tmplt->direction;
626 ur_free_template(tmplt);
627 }
628 return new_tmplt;
629}
630
632{
633 char *field_names = ur_ifc_data_fmt_to_field_names(ifc_data_fmt);
634 if (field_names == NULL) {
635 return NULL;
636 }
637 ur_template_t *new_tmplt = ur_create_template(field_names, NULL);
638 free(field_names);
639 return new_tmplt;
640}
641
642int ur_define_field(const char *name, ur_field_type_t type)
643{
644 int insert_id;
645 char * name_copy;
646 int name_len;
647 if (name == NULL) {
648 return UR_E_INVALID_NAME;
649 }
650 //check the regural expression of a name
651 name_len = strlen(name);
652 if (name_len == 0) {
653 return UR_E_INVALID_NAME;
654 }
655 if (!((name[0] >= 'A' && name[0] <= 'Z') || (name[0] >= 'a' && name[0] <= 'z'))) {
656 return UR_E_INVALID_NAME;
657 }
658 for (int i = 1; i < name_len; i++) {
659 if (!((name[i] >= 'A' && name[i] <= 'Z') || (name[i] >= 'a' && name[i] <= 'z') || (name[i] >= '0' && name[i] <= '9') || name[i] == '_')) {
660 return UR_E_INVALID_NAME;
661 }
662 }
663 // If this is the first dynamically allocated field, call ur_init
665 int init_val = ur_init(UR_FIELD_SPECS_STATIC);
666 if (init_val != 0) {
667 return init_val;
668 }
669 }
670 //check if the field is already defined
671 for (int i = 0; i < ur_field_specs.ur_last_id; i++) {
672 if (ur_field_specs.ur_field_names[i] != NULL && strcmp(name, ur_field_specs.ur_field_names[i]) == 0) {
673 if (type == ur_field_specs.ur_field_types[i]) {
674 //name exists and type is equal
675 return i;
676 } else {
677 //name exists, but type is different
678 return UR_E_TYPE_MISMATCH;
679 }
680 }
681 }
682 //create new field
683 name_copy = (char *) calloc(sizeof(char), strlen(name) + 1);
684 if (name_copy == NULL) {
685 //error during allocation
686 return UR_E_MEMORY;
687 }
688 strcpy(name_copy, name);
689 insert_id = ur_get_empty_id();
690 if (insert_id < 0) {
691 //error
692 free(name_copy);
693 return insert_id;
694 }
695 ur_field_specs.ur_field_names[insert_id] = name_copy;
696 ur_field_specs.ur_field_sizes[insert_id] = ur_size_of(type);
697 ur_field_specs.ur_field_types[insert_id] = type;
698 return insert_id;
699}
700
702{
703 if (field_id < ur_field_specs.ur_last_statically_defined_id || field_id >= ur_field_specs.ur_last_id) {
704 //id is invalid
706 } else if (ur_field_specs.ur_field_names[field_id] == NULL) {
707 //ID is already undefined
709 } else {
710 //undefine field
711 ur_field_id_linked_list_t *undefined_item;
712 undefined_item = (ur_field_id_linked_list_t *) calloc(sizeof(ur_field_id_linked_list_t), 1);
713 if (undefined_item == NULL) {
714 //error during allocation
715 return UR_E_MEMORY;
716 }
717 free(ur_field_specs.ur_field_names[field_id]);
718 ur_field_specs.ur_field_names[field_id] = NULL;
719 undefined_item->id = field_id;
720 undefined_item->next = ur_field_specs.ur_undefine_fields;
721 ur_field_specs.ur_undefine_fields = undefined_item;
722 }
723 return UR_OK;
724}
725
726int ur_undefine_field(const char *name)
727{
728 int i;
729 //find id of field
731 if (ur_field_specs.ur_field_names[i] != NULL && strcmp(name, ur_field_specs.ur_field_names[i]) == 0) {
732 return ur_undefine_field_by_id(i);
733 }
734 }
735 //field with given name was not found
736 return UR_E_INVALID_NAME;
737}
738
739
741{
743 //there is no need for deallocation, because nothing has been allocated.
744 return;
745 }
746 if (ur_field_specs.ur_field_names != NULL) {
747 for (int i=0; i < ur_field_specs.ur_last_id; i++) {
748 if (ur_field_specs.ur_field_names[i] != NULL) {
750 }
751 }
753 }
755 ur_field_id_linked_list_t *next, * act_del;
757 while (act_del != NULL) {
758 next = act_del->next;
759 free(act_del);
760 act_del = next;
761 }
762 }
763 if (ur_field_specs.ur_field_sizes != NULL) {
765 }
766 if (ur_field_specs.ur_field_types != NULL) {
768 }
777}
778
779// Find field ID given its name
780int ur_get_id_by_name(const char *name)
781{
782 for (int id = 0; id < ur_field_specs.ur_last_id; id++) {
783 if (ur_field_specs.ur_field_names[id] != NULL && strcmp(name, ur_field_specs.ur_field_names[id]) == 0) {
784 return id;
785 }
786 }
787 return UR_E_INVALID_NAME;
788}
789
790// Return -1 if f1 should go before f2, 0 if f1 is the same as f2, 1 otherwise
791int compare_fields(const void *field1, const void *field2)
792{
793 const field_spec_t *f1 = field1;
794 const field_spec_t *f2 = field2;
795 if (f1->size > f2->size) {
796 return -1;
797 } else if (f1->size < f2->size) {
798 return 1;
799 } else {
800 return strcmp(f1->name, f2->name);
801 }
802}
803
804ur_template_t *ur_ctx_create_input_template(trap_ctx_t *ctx, int ifc, const char *fields, char **errstr)
805{
806 ur_template_t *tmplt = ur_create_template(fields, errstr);
807 if (tmplt == NULL) {
808 return NULL;
809 }
810 if (ur_ctx_set_input_template(ctx, ifc, tmplt) != UR_OK) {
811 if (errstr != NULL) {
812 *errstr = (char *) malloc(strlen(UR_MEMORY_ERROR) + 1);
813 if (*errstr != NULL) {
814 strcpy(*errstr, UR_MEMORY_ERROR);
815 }
816 }
817 ur_free_template(tmplt);
818 return NULL;
819 }
820 return tmplt;
821}
822
823ur_template_t *ur_ctx_create_output_template(trap_ctx_t *ctx, int ifc, const char *fields, char **errstr)
824{
825 ur_template_t *tmplt = ur_create_template(fields, errstr);
826 if (tmplt == NULL) {
827 return NULL;
828 }
829 if (ur_ctx_set_output_template(ctx, ifc, tmplt) != UR_OK) {
830 if (errstr != NULL) {
831 *errstr = (char *) malloc(strlen(UR_MEMORY_ERROR) + 1);
832 if (*errstr != NULL) {
833 strcpy(*errstr, UR_MEMORY_ERROR);
834 }
835 }
836 ur_free_template(tmplt);
837 return NULL;
838 }
839 return tmplt;
840}
841
842int ur_ctx_set_output_template(trap_ctx_t *ctx, int ifc, ur_template_t *tmplt)
843{
844 if (tmplt == NULL) {
845 return UR_OK;
846 }
847 if (tmplt->direction == UR_TMPLT_DIRECTION_IN) {
849 } else {
851 }
852 tmplt->ifc_out = ifc;
853 char * tmplt_str = ur_template_string(tmplt);
854 if (tmplt_str == NULL) {
855 return UR_E_MEMORY;
856 }
857 trap_ctx_set_data_fmt(ctx, ifc, TRAP_FMT_UNIREC, tmplt_str);
858 free(tmplt_str);
859 return UR_OK;
860}
861
862int ur_ctx_set_input_template(trap_ctx_t *ctx, int ifc, ur_template_t *tmplt)
863{
864 if (tmplt == NULL) {
865 return UR_OK;
866 }
867 if (tmplt->direction == UR_TMPLT_DIRECTION_OUT) {
869 } else {
871 }
872 char * tmplt_str = ur_template_string(tmplt);
873 if (tmplt_str == NULL) {
874 return UR_E_MEMORY;
875 }
876 trap_ctx_set_required_fmt(ctx, ifc, TRAP_FMT_UNIREC, tmplt_str);
877 free(tmplt_str);
878 return UR_OK;
879}
880
881ur_template_t *ur_ctx_create_bidirectional_template(trap_ctx_t *ctx, int ifc_in, int ifc_out, const char *fields, char **errstr)
882{
883 ur_template_t *tmplt = ur_create_template(fields, errstr);
884 if (tmplt == NULL) {
885 return NULL;
886 }
888 tmplt->ifc_out = ifc_out;
889 char * tmplt_str = ur_template_string(tmplt);
890 if (tmplt_str == NULL) {
891 if (errstr != NULL) {
892 *errstr = (char *) malloc(strlen(UR_MEMORY_ERROR) + 1);
893 if (*errstr != NULL) {
894 strcpy(*errstr, UR_MEMORY_ERROR);
895 }
896 }
897 ur_free_template(tmplt);
898 return NULL;
899 }
900 trap_ctx_set_required_fmt(ctx, ifc_in, TRAP_FMT_UNIREC, tmplt_str);
901 trap_ctx_set_data_fmt(ctx, ifc_out, TRAP_FMT_UNIREC, tmplt_str);
902 free(tmplt_str);
903 return tmplt;
904}
905
906ur_template_t *ur_create_template(const char *fields, char **errstr)
907{
908 // Count number of fields
909 int n_fields = 0, written_fields = 0;
910 if (fields) {
911 /* skip leading spaces */
912 while (*fields != '\0' && isspace(*fields)) {
913 fields++;
914 }
915 /* Count number of fields */
916 if (*fields != '\0') {
917 n_fields = 1;
918 const char *tmp = fields;
919 while (*tmp != '\0') {
920 if (*(tmp++) == ',') {
921 n_fields++;
922 }
923 }
924 }
925 }
926 // Allocate array of field_spec structs
927 field_spec_t *fields_spec = malloc(n_fields * sizeof(field_spec_t));
928 if (fields_spec == NULL && n_fields > 0) {
929 if (errstr != NULL) {
930 *errstr = (char *) malloc(strlen(UR_MEMORY_ERROR) + 1);
931 if (*errstr != NULL) {
932 strcpy(*errstr, UR_MEMORY_ERROR);
933 }
934 }
935 return NULL;
936 }
937 // Parse fields and fill the array
938 const char *start_ptr = fields;
939 const char *end_ptr;
940 for (int i = 0; i < n_fields; i++) {
941 // Get field name
942 end_ptr = start_ptr;
943 /* go to the first space / comma / end-of-string */
944 while (!isspace(*end_ptr) && *end_ptr != ',' && *end_ptr != '\0') {
945 end_ptr++;
946 }
947 int len = end_ptr - start_ptr;
948 fields_spec[written_fields].name = malloc(len + 1);
949 if (fields_spec[written_fields].name == NULL) {
950 if (errstr != NULL) {
951 *errstr = (char *) malloc(strlen(UR_MEMORY_ERROR) + 1);
952 if (*errstr != NULL) {
953 strcpy(*errstr, UR_MEMORY_ERROR);
954 }
955 }
956 for (int j = 0; j < i; j++) {
957 free(fields_spec[j].name);
958 }
959 free(fields_spec);
960 return NULL;
961 }
962 memcpy(fields_spec[written_fields].name, start_ptr, len);
963 fields_spec[written_fields].name[len] = 0;
964 start_ptr = end_ptr;
965 while ((isspace(*start_ptr) || *start_ptr == ',') && *start_ptr != '\0') {
966 start_ptr++;
967 }
968 // Get field ID
969 int id_by_name = ur_get_id_by_name(fields_spec[written_fields].name);
970 if (id_by_name == UR_E_INVALID_NAME) {
971 // Unknown field name
972 if (errstr != NULL) {
973 *errstr = (char *) malloc(100);
974 if (*errstr != NULL) {
975 int n;
976 n = snprintf(*errstr, 100, "field: %s is not defined.", fields_spec[written_fields].name);
977 if (n >= 100) {
978 strcpy(*errstr, "given field is not defined");
979 }
980 }
981 }
982 for (int j = 0; j <= written_fields; j++) {
983 free(fields_spec[j].name);
984 }
985 free(fields_spec);
986 return NULL;
987 }
988 //check if the field is not in the template.
989 int in_the_template = 0;
990 for (int j = 0; j < written_fields; j++) {
991 if (fields_spec[j].id == id_by_name) {
992 in_the_template = 1;
993 break;
994 }
995 }
996 //if the field is not already int the template, copy values and move the index, otherwise just free the string with name.
997 if (in_the_template == 0) {
998 fields_spec[written_fields].id = id_by_name;
999 // Get field size
1000 fields_spec[written_fields].size = ur_get_size(fields_spec[written_fields].id);
1001 written_fields++;
1002 } else {
1003 free(fields_spec[written_fields].name);
1004 fields_spec[written_fields].name = NULL;
1005 }
1006 }
1007 // Sort fields according to UniRec specification (by size and names)
1008 if (n_fields > 0) {
1009 qsort(fields_spec, written_fields, sizeof(field_spec_t), compare_fields);
1010 }
1011 // Allocate memory for the template
1012 ur_template_t *tmplt = (ur_template_t *) calloc(sizeof(ur_template_t), 1);
1013 if (tmplt == NULL) {
1014 for (int i = 0; i < written_fields; i++) {
1015 free(fields_spec[i].name);
1016 }
1017 free(fields_spec);
1018 if (errstr != NULL) {
1019 *errstr = (char *) malloc(strlen(UR_MEMORY_ERROR) + 1);
1020 if (*errstr != NULL) {
1021 strcpy(*errstr, UR_MEMORY_ERROR);
1022 }
1023 }
1024 return NULL;
1025 }
1026 //set no direction to the template
1028 //allocate memory for offset table
1030 tmplt->offset = malloc(ur_field_specs.ur_last_id * sizeof(uint16_t));
1031 if (tmplt->offset == NULL) {
1032 for (int i = 0; i < written_fields; i++) {
1033 free(fields_spec[i].name);
1034 }
1035 free(fields_spec);
1036 free(tmplt);
1037 if (errstr != NULL) {
1038 *errstr = (char *) malloc(strlen(UR_MEMORY_ERROR) + 1);
1039 if (*errstr != NULL) {
1040 strcpy(*errstr, UR_MEMORY_ERROR);
1041 }
1042 }
1043 return NULL;
1044 }
1045 // Set all fields to invalid offset
1046 memset(tmplt->offset, 0xff, ur_field_specs.ur_last_id * sizeof(uint16_t));
1047 // Fill offsets of all fields into the table
1048 uint16_t offset = 0;
1049 uint16_t first_dynamic = UR_NO_DYNAMIC_VALUES;
1050 for (int i = 0; i < written_fields; i++) {
1051 // Set offset
1052 if (fields_spec[i].size < 0) { // dynamic field
1053 tmplt->offset[fields_spec[i].id] = offset;
1054 offset += 4;
1055 if (first_dynamic == UR_NO_DYNAMIC_VALUES) {
1056 first_dynamic = i;
1057 }
1058 } else { // static field
1059 tmplt->offset[fields_spec[i].id] = offset;
1060 offset += fields_spec[i].size;
1061 }
1062 }
1063 tmplt->first_dynamic = first_dynamic;
1064 tmplt->static_size = offset;
1065
1066 //save ids to template
1067 tmplt->ids = (ur_field_id_t *) malloc(sizeof(ur_field_id_t) * written_fields);
1068 if (tmplt->ids == NULL) {
1069 for (int i = 0; i < written_fields; i++) {
1070 free(fields_spec[i].name);
1071 }
1072 free(fields_spec);
1073 free(tmplt);
1074 if (errstr != NULL) {
1075 *errstr = (char *) malloc(strlen(UR_MEMORY_ERROR) + 1);
1076 if (*errstr != NULL) {
1077 strcpy(*errstr, UR_MEMORY_ERROR);
1078 }
1079 }
1080 return NULL;
1081 }
1082 tmplt->count = written_fields;
1083 for (int i = 0; i < written_fields; i++) {
1084 tmplt->ids[i] = fields_spec[i].id;
1085 }
1086 // Free array of field specs
1087 for (int i = 0; i < written_fields; i++) {
1088 free(fields_spec[i].name);
1089 }
1090 free(fields_spec);
1091 return tmplt;
1092}
1093
1095 if (tmplt == NULL) {
1096 return;
1097 }
1098 //free offset table
1099 if (tmplt->offset != NULL) {
1100 free(tmplt->offset);
1101 }
1102 //free ids
1103 if (tmplt->ids != NULL) {
1104 free(tmplt->ids);
1105 }
1106 free(tmplt);
1107}
1108
1109// Compare fields of two templates
1110int ur_template_compare(const ur_template_t *tmpltA, const ur_template_t *tmpltB)
1111{
1112 if (tmpltA->count == tmpltB->count) {
1113 return memcmp(tmpltA->ids, tmpltB->ids, sizeof(uint16_t) * tmpltA->count) == 0;
1114 } else {
1115 return 0;
1116 }
1117}
1118
1119
1120// Print template
1122{
1123 printf("static_size: %hu, first_dynamic: ", tmplt->static_size);
1124 (tmplt->first_dynamic == UR_NO_DYNAMIC_VALUES) ? (printf("-")) : (printf("%d", tmplt->ids[tmplt->first_dynamic]));
1125 printf(", offsets:\n"
1126 "ID\t%-30s\toffset\n","name");
1127 for (int i = 0; i < tmplt->count; i++) {
1128 printf("%d\t%-30s\t%6hu\n", tmplt->ids[i], ur_field_specs.ur_field_names[tmplt->ids[i]], tmplt->offset[tmplt->ids[i]]);
1129 }
1130}
1131
1132void ur_var_change_size(const ur_template_t *tmplt, void *rec, int field_id, int new_val_len)
1133{
1134 // pointer to field and size of a field
1135 char *out_ptr = ur_get_ptr_by_id(tmplt, rec, field_id);
1136 int old_size_of_field = ur_get_len(tmplt, rec, field_id);
1137 //if the size is different, move following fields
1138 if (old_size_of_field != new_val_len) {
1139 uint16_t size = new_val_len;
1140 uint16_t offset_static = ur_get_var_offset(tmplt, rec, field_id);
1141 int index = 0;
1142 //find index of changed field in record array
1143 for (int i = 0; i< tmplt->count; i++) {
1144 if (field_id == tmplt->ids[i]) {
1145 index = i;
1146 }
1147 }
1148 //set new offset for dynamic fields which are situated behind changed field
1149 for (int i = index + 1; i < tmplt->count; i++) {
1150 ur_set_var_offset(tmplt, rec, tmplt->ids[i], offset_static + size);
1151 size += ur_get_len(tmplt, rec, tmplt->ids[i]);
1152 }
1153 memmove(out_ptr + new_val_len, out_ptr + old_size_of_field, size - new_val_len);
1154 ur_set_var_len(tmplt, rec, field_id, new_val_len);
1155 }
1156}
1157
1158int ur_set_var(const ur_template_t *tmplt, void *rec, int field_id, const void *val_ptr, int val_len)
1159{
1160 if (tmplt->offset[field_id] == UR_INVALID_OFFSET) {
1161 return UR_E_INVALID_FIELD_ID;
1162 }
1163 // wrong parameters or template does not contain dynamic fields
1164 if (tmplt->first_dynamic == UR_NO_DYNAMIC_VALUES || ur_is_static(field_id)) {
1165 return UR_E_INVALID_FIELD_ID;
1166 }
1167 // pointer to field and size of a field
1168 char * out_ptr = ur_get_ptr_by_id(tmplt, rec, field_id);
1169 //change size of a variable length field
1170 ur_var_change_size(tmplt, rec, field_id, val_len);
1171 //copy new value
1172 memcpy(out_ptr, val_ptr, val_len);
1173 return UR_OK;
1174}
1175
1176int ur_array_resize(const ur_template_t *tmplt, void *rec, int field_id, int len)
1177{
1178 if (tmplt->offset[field_id] == UR_INVALID_OFFSET) {
1179 return UR_E_INVALID_FIELD_ID;
1180 }
1181 // wrong parameters or template does not contain dynamic fields
1182 if (tmplt->first_dynamic == UR_NO_DYNAMIC_VALUES || ur_is_static(field_id)) {
1183 return UR_E_INVALID_FIELD_ID;
1184 }
1185 //change size of a variable length field
1186 ur_var_change_size(tmplt, rec, field_id, len);
1187 return UR_OK;
1188}
1189
1190char *ur_array_append_get_ptr(const ur_template_t *tmplt, void *rec, int field_id)
1191{
1192 int elem_cnt = ur_array_get_elem_cnt(tmplt, rec, field_id);
1193 int elem_size = ur_array_get_elem_size(field_id);
1194 if (ur_array_resize(tmplt, rec, field_id, (elem_cnt + 1) * elem_size) == UR_OK) {
1195 return (char *) ur_get_ptr_by_id(tmplt, rec, field_id) + elem_cnt * elem_size;
1196 } else {
1197 return NULL;
1198 }
1199}
1200
1201void ur_clear_varlen(const ur_template_t * tmplt, void *rec)
1202{
1203 //set null offset and length for all dynamic fields
1204 for (int i = tmplt->first_dynamic; i < tmplt->count; i++) {
1205 ur_set_var_offset(tmplt, rec, tmplt->ids[i], 0);
1206 ur_set_var_len(tmplt, rec, tmplt->ids[i], 0);
1207 }
1208}
1209
1210uint16_t ur_rec_varlen_size(const ur_template_t *tmplt, const void *rec)
1211{
1212 int size = 0;
1213 for (int i = tmplt->first_dynamic; i < tmplt->count; i++) {
1214 size += ur_get_var_len(tmplt, rec, tmplt->ids[i]);
1215 }
1216 return size;
1217}
1218
1219// Allocate memory for UniRec record
1220void *ur_create_record(const ur_template_t *tmplt, uint16_t max_var_size)
1221{
1222 unsigned int size = (unsigned int)tmplt->static_size + max_var_size;
1223 if (size > UR_MAX_SIZE)
1224 size = UR_MAX_SIZE;
1225 return (void *) calloc(size, 1);
1226}
1227
1228// Free UniRec record
1229void ur_free_record(void *record)
1230{
1231 free(record);
1232}
1233
1234// Get dynamic field as C string (allocate, copy and append '\0')
1235char *ur_get_var_as_str(const ur_template_t *tmplt, const void *rec, ur_field_id_t field_id)
1236{
1237 uint16_t size = ur_get_var_len(tmplt, rec, field_id);
1238 char *str = malloc(size + 1);
1239 if (str == NULL)
1240 return NULL;
1241 if (size > 0) {
1242 const char *p = ur_get_ptr_by_id(tmplt, rec, field_id);
1243 memcpy(str, p, size);
1244 }
1245 str[size] = '\0';
1246 return str;
1247}
1248
1249inline void *ur_clone_record(const ur_template_t *tmplt, const void *src)
1250{
1251 uint16_t varsize = ur_rec_varlen_size(tmplt, src);
1252 void *copy = ur_create_record(tmplt, varsize);
1253 if (copy) {
1254 memcpy(copy, src, ur_rec_fixlen_size(tmplt) + varsize);
1255 }
1256 return copy;
1257}
1258
1259void ur_copy_fields(const ur_template_t *dst_tmplt, void *dst, const ur_template_t *src_tmplt, const void *src)
1260{
1261 int size_of_field = 0;
1262 void * ptr_dst = NULL;
1263 void * ptr_src = NULL;
1264 uint16_t size = src_tmplt->offset_size < dst_tmplt->offset_size ? src_tmplt->offset_size : dst_tmplt->offset_size;
1265 //Fields with same template can be copied by fully by memcpy
1266 if (src_tmplt == dst_tmplt) {
1267 memcpy(dst, src, ur_rec_size(src_tmplt, src));
1268 return;
1269
1270 }
1271 // minimal value from offset table size
1272 for (int i = 0; i < size; i++) {
1273 // if two templates have the same field
1274 if (src_tmplt->offset[i] != UR_INVALID_OFFSET && dst_tmplt->offset[i] != UR_INVALID_OFFSET) {
1275 size_of_field = ur_get_size(i);
1276 if (size_of_field > 0) {
1277 // static fields
1278 ptr_dst = ur_get_ptr_by_id(dst_tmplt, dst, i);
1279 ptr_src = ur_get_ptr_by_id(src_tmplt, src, i);
1280 memcpy(ptr_dst, ptr_src, size_of_field);
1281 } else {
1282 // variable-size fields
1283 ptr_src = ur_get_ptr_by_id(src_tmplt, src, i);
1284 size_of_field = ur_get_var_len(src_tmplt, src, i);
1285 ur_set_var(dst_tmplt, dst, i, ptr_src, size_of_field);
1286 }
1287 }
1288 }
1289}
1290
1291// Function for iterating over all fields in a given template
1293{
1294 // Set first ID to check
1295 if (id == UR_ITER_BEGIN) {
1296 id = 0;
1297 } else {
1298 id++;
1299 }
1300 // Find first ID which is present in the template
1301 while (id < tmplt->offset_size) {
1302 if (tmplt->offset[id] != UR_INVALID_OFFSET) {
1303 return id;
1304 }
1305 id++;
1306 }
1307 return UR_ITER_END;
1308}
1309
1310// Function for iterating over all fields in a given template. Fields are in the same
1311// order like in record
1313{
1314 // Set first ID to check
1315 if (index >= tmplt->count || index < 0) {
1316 return UR_ITER_END;
1317 }
1318 return tmplt->ids[index];
1319}
1320
1321int ur_set_array_from_string(const ur_template_t *tmpl, void *data, ur_field_id_t f_id, const char *v)
1322{
1323 ip_addr_t addr;
1324 mac_addr_t macaddr;
1325 int rv = 0;
1326 ur_time_t urtime = 0;
1327 void *ptr = ur_get_ptr_by_id(tmpl, data, f_id);
1328 int elems_parsed = 0;
1329 int elems_allocated = UR_ARRAY_ALLOC;
1330 const char *scan_format = NULL;
1331 const int element_size = ur_array_get_elem_size(f_id);
1332
1333 if (ur_is_present(tmpl, f_id) == 0 || !ur_is_array(f_id)) {
1334 return 1;
1335 }
1336 if (ur_array_allocate(tmpl, data, f_id, elems_allocated) != UR_OK) {
1337 return 1;
1338 }
1339 while (v && *v == UR_ARRAY_DELIMITER) {
1340 v++; // Skip the delimiter, move to beginning of the next value
1341 }
1342 switch (ur_get_type(f_id)) {
1343 case UR_TYPE_A_UINT8:
1344 scan_format = "%" SCNu8;
1345 break;
1346 case UR_TYPE_A_UINT16:
1347 scan_format = "%" SCNu16;
1348 break;
1349 case UR_TYPE_A_UINT32:
1350 scan_format = "%" SCNu32;
1351 break;
1352 case UR_TYPE_A_UINT64:
1353 scan_format = "%" SCNu64;
1354 break;
1355 case UR_TYPE_A_INT8:
1356 scan_format = "%" SCNi8;
1357 break;
1358 case UR_TYPE_A_INT16:
1359 scan_format = "%" SCNi16;
1360 break;
1361 case UR_TYPE_A_INT32:
1362 scan_format = "%" SCNi32;
1363 break;
1364 case UR_TYPE_A_INT64:
1365 scan_format = "%" SCNi64;
1366 break;
1367 case UR_TYPE_A_FLOAT:
1368 scan_format = "%f";
1369 break;
1370 case UR_TYPE_A_DOUBLE:
1371 scan_format = "%lf";
1372 break;
1373 case UR_TYPE_A_IP:
1374 // IP address - convert to human-readable format
1375 while (v && *v) {
1376 char tmp[64];
1377 const char *ip = tmp;
1378 char *end;
1379 end = strchr(v, UR_ARRAY_DELIMITER);
1380 if (end == NULL) {
1381 ip = v;
1382 if (*v == 0) {
1383 break;
1384 }
1385 } else {
1386 memcpy(tmp, v, end - v);
1387 tmp[end - v] = 0;
1388 }
1389 v = end;
1390 if (ip_from_str(ip, &addr) == 0) {
1391 rv = 1;
1392 break;
1393 }
1394 ((ip_addr_t *) ptr)[elems_parsed] = addr;
1395 elems_parsed++;
1396 if (elems_parsed >= elems_allocated) {
1397 elems_allocated += UR_ARRAY_ALLOC;
1398 if (ur_array_allocate(tmpl, data, f_id, elems_allocated) != UR_OK) {
1399 return 1;
1400 }
1401 }
1402 while (v && *v == UR_ARRAY_DELIMITER) {
1403 v++; // Skip the delimiter, move to beginning of the next value
1404 }
1405 }
1406 break;
1407 case UR_TYPE_A_MAC:
1408 // MAC address - convert to human-readable format
1409 while (v && *v) {
1410 if (mac_from_str(v, &macaddr) == 0) {
1411 rv = 1;
1412 break;
1413 }
1414 ((mac_addr_t *) ptr)[elems_parsed] = macaddr;
1415 elems_parsed++;
1416 if (elems_parsed >= elems_allocated) {
1417 elems_allocated += UR_ARRAY_ALLOC;
1418 if (ur_array_allocate(tmpl, data, f_id, elems_allocated) != UR_OK) {
1419 return 1;
1420 }
1421 }
1422 v = strchr(v, UR_ARRAY_DELIMITER);
1423 while (v && *v == UR_ARRAY_DELIMITER) {
1424 v++; // Skip the delimiter, move to beginning of the next value
1425 }
1426 }
1427 break;
1428 case UR_TYPE_A_TIME:
1429 // Timestamp - convert from human-readable format
1430 while (v && *v) {
1431 char tmp[64];
1432 const char *time = tmp;
1433 char *end;
1434 end = strchr(v, UR_ARRAY_DELIMITER);
1435 if (end == NULL) {
1436 time = v;
1437 if (*v == 0) {
1438 break;
1439 }
1440 } else {
1441 memcpy(tmp, v, end - v);
1442 tmp[end - v] = 0;
1443 }
1444 if (ur_time_from_string(&urtime, time) != 0) {
1445 rv = 1;
1446 break;
1447 }
1448 ((ur_time_t *) ptr)[elems_parsed] = urtime;
1449 elems_parsed++;
1450 if (elems_parsed >= elems_allocated) {
1451 elems_allocated += UR_ARRAY_ALLOC;
1452 if (ur_array_allocate(tmpl, data, f_id, elems_allocated) != UR_OK) {
1453 return 1;
1454 }
1455 }
1456 v = strchr(v, UR_ARRAY_DELIMITER);
1457 while (v && *v == UR_ARRAY_DELIMITER) {
1458 v++; // Skip the delimiter, move to beginning of the next value
1459 }
1460 }
1461 break;
1462 default:
1463 fprintf(stderr, "Unsupported UniRec field type, skipping.\n");
1464 ur_array_allocate(tmpl, data, f_id, 0);
1465 break;
1466 }
1467
1468 if (scan_format != NULL) {
1469 while (v && *v) {
1470 if (sscanf(v, scan_format, (void *) ((char*) ptr + elems_parsed * element_size)) != 1) {
1471 rv = 1;
1472 break;
1473 }
1474 elems_parsed++;
1475 if (elems_parsed >= elems_allocated) {
1476 elems_allocated += UR_ARRAY_ALLOC;
1477 if (ur_array_allocate(tmpl, data, f_id, elems_allocated) != UR_OK) {
1478 return 1;
1479 }
1480 }
1481 v = strchr(v, UR_ARRAY_DELIMITER);
1482 while (v && *v == UR_ARRAY_DELIMITER) {
1483 v++; // Skip the delimiter, move to beginning of the next value
1484 }
1485 }
1486 }
1487
1488 if (elems_allocated > elems_parsed) {
1489 ur_array_allocate(tmpl, data, f_id, elems_parsed);
1490 }
1491 return rv;
1492}
1493int ur_set_from_string(const ur_template_t *tmpl, void *data, ur_field_id_t f_id, const char *v)
1494{
1495 ip_addr_t *addr_p = NULL, addr;
1496 mac_addr_t *macaddr_p = NULL, macaddr;
1497 int rv = 0;
1498 ur_time_t urtime = 0;
1499 void *ptr = ur_get_ptr_by_id(tmpl, data, f_id);
1500
1501 if (ur_is_present(tmpl, f_id) == 0) {
1502 return 1;
1503 }
1504 switch (ur_get_type(f_id)) {
1505 case UR_TYPE_UINT8:
1506 if (sscanf(v, "%" SCNu8, (uint8_t *) ptr) != 1) {
1507 rv = 1;
1508 }
1509 break;
1510 case UR_TYPE_UINT16:
1511 if (sscanf(v, "%" SCNu16 , (uint16_t *) ptr) != 1) {
1512 rv = 1;
1513 }
1514 break;
1515 case UR_TYPE_UINT32:
1516 if (sscanf(v, "%" SCNu32, (uint32_t *) ptr) != 1) {
1517 rv = 1;
1518 }
1519 break;
1520 case UR_TYPE_UINT64:
1521 if (sscanf(v, "%" SCNu64, (uint64_t *) ptr) != 1) {
1522 rv = 1;
1523 }
1524 break;
1525 case UR_TYPE_INT8:
1526 if (sscanf(v, "%" SCNi8, (int8_t *) ptr) != 1) {
1527 rv = 1;
1528 }
1529 break;
1530 case UR_TYPE_INT16:
1531 if (sscanf(v, "%" SCNi16, (int16_t *) ptr) != 1) {
1532 rv = 1;
1533 }
1534 break;
1535 case UR_TYPE_INT32:
1536 if (sscanf(v, "%" SCNi32, (int32_t *) ptr) != 1) {
1537 rv = 1;
1538 }
1539 break;
1540 case UR_TYPE_INT64:
1541 if (sscanf(v, "%" SCNi64, (int64_t *) ptr) != 1) {
1542 rv = 1;
1543 }
1544 break;
1545 case UR_TYPE_CHAR:
1546 if (sscanf(v, "%c", (char *) ptr) != 1) {
1547 rv = 1;
1548 }
1549 break;
1550 case UR_TYPE_FLOAT:
1551 if (sscanf(v, "%f", (float *) ptr) != 1) {
1552 rv = 1;
1553 }
1554 break;
1555 case UR_TYPE_DOUBLE:
1556 if (sscanf(v, "%lf", (double *) ptr) != 1) {
1557 rv = 1;
1558 }
1559 break;
1560 case UR_TYPE_IP:
1561 // IP address - convert to human-readable format
1562 if (ip_from_str(v, &addr) == 0) {
1563 rv = 1;
1564 break;
1565 }
1566 addr_p = (ip_addr_t *) ptr;
1567 (*addr_p) = addr;
1568 break;
1569 case UR_TYPE_MAC:
1570 // MAC address - convert to human-readable format
1571 if (mac_from_str(v, &macaddr) == 0) {
1572 rv = 1;
1573 break;
1574 }
1575 macaddr_p = (mac_addr_t *) ptr;
1576 (*macaddr_p) = macaddr;
1577 break;
1578 case UR_TYPE_TIME:
1579 // Timestamp - convert from human-readable format
1580 if (ur_time_from_string(&urtime, v) != 0) {
1581 fprintf(stderr, "Failed to parse time.\n");
1582 }
1583 (*(ur_time_t *) ptr) = urtime;
1584 break;
1585 case UR_TYPE_STRING:
1586 // Printable string
1587 ur_set_var(tmpl, data, f_id, v, strlen(v));
1588 break;
1589 case UR_TYPE_BYTES:
1590 {
1591 // Generic string of bytes
1592 int size = strlen(v)/2;
1593 ur_var_change_size(tmpl, data, f_id, size);
1594 unsigned char *data_ptr = ur_get_ptr_by_id(tmpl, data, f_id);
1595 for ( ; size > 0; --size, v += 2, ++data_ptr) {
1596 if (sscanf(v, "%2hhx", data_ptr) != 1) {
1597 rv = 1;
1598 }
1599 }
1600 }
1601 break;
1602 default:
1603 if (ur_is_array(f_id)) {
1604 return ur_set_array_from_string(tmpl, data, f_id, v);
1605 }
1606 fprintf(stderr, "Unsupported UniRec field type, skipping.\n");
1607 break;
1608 }
1609 return rv;
1610}
1611
1612uint8_t ur_time_from_string(ur_time_t *ur, const char *str)
1613{
1614 struct tm t;
1615 time_t sec = -1;
1616 uint64_t nsec = 0;
1617 char *res = NULL;
1618
1619 if (ur == NULL || str == NULL) {
1620 return 2;
1621 }
1622
1623 res = strptime(str, "%Y-%m-%dT%T", &t);
1624 /* parsed to sec - msec delimiter */
1625 if ((res != NULL) && ((*res == '.') || (*res == 0) || (*res == 'z') || (*res == 'Z'))) {
1626 sec = timegm(&t);
1627 if (sec != -1) {
1628 if (*res != 0 && *++res != 0) {
1629 char frac_buffer[10];
1630 memset(frac_buffer, '0', 9);
1631 frac_buffer[9] = 0;
1632
1633 // now "res" points to the beginning of the fractional part or 'Z' for UTC timezone,
1634 // which have at least one char.
1635 // Expand the number by zeros to the right to get it in ns
1636 // (if there are more than 9 digits, truncate the rest)
1637 size_t frac_len = strlen(res);
1638 if (frac_len > 0 && (res[frac_len - 1] == 'z' || res[frac_len - 1] == 'Z')) {
1639 frac_len--;
1640 }
1641 if (frac_len > 9) {
1642 frac_len = 9;
1643 }
1644 memcpy(frac_buffer, res, frac_len);
1645 nsec = strtoul(frac_buffer, NULL, 10); // returns 0 on error - that's OK
1646 }
1647 *ur = ur_time_from_sec_nsec((uint64_t) sec, nsec);
1648 } else {
1649 goto failed_time_parsing;
1650 }
1651 /* success */
1652 return 0;
1653 } else {
1654failed_time_parsing:
1655 *ur = (ur_time_t) 0;
1656 /* parsing error */
1657 return 1;
1658 }
1659}
1660
1661char *ur_cpy_string(const char *str)
1662{
1663 int str_len = strlen(str) + 1;
1664 char *new_str = malloc(sizeof(char) * str_len);
1665 if (new_str == NULL) {
1666 return NULL;
1667 }
1668 memcpy(new_str, str, str_len);
1669 return new_str;
1670}
1671
1672const char *ur_values_get_name_start_end(uint32_t start, uint32_t end, int32_t value)
1673{
1674 for (int i = start; i < end; i++) {
1675 if (ur_values[i].value == value) {
1676 return ur_values[i].name;
1677 }
1678 }
1679 return NULL;
1680}
1681
1682const char *ur_values_get_description_start_end(uint32_t start, uint32_t end, int32_t value)
1683{
1684 for (int i = start; i < end; i++) {
1685 if (ur_values[i].value == value) {
1686 return ur_values[i].description;
1687 }
1688 }
1689 return NULL;
1690}
1691// *****************************************************************************
1692// ** "Links" part - set of functions for handling LINK_BIT_FIELD
1693
1694// Create and initialize links structure.
1695ur_links_t *ur_create_links(const char *mask)
1696{
1697 uint64_t checker;
1698 unsigned int indexer;
1699 ur_links_t *lm;
1700
1701 // Allocate memory for structure.
1702 lm = (ur_links_t *) malloc(sizeof(ur_links_t));
1703 if (lm == NULL) {
1704 return NULL;
1705 }
1706
1707 // Try to convert passed mask in string to uint64_t.
1708 if (sscanf(mask, "%"SCNx64, &lm->link_mask) < 1) {
1709 free(lm);
1710 return NULL;
1711 }
1712
1713 // Get link count.
1714 lm->link_count = 0;
1715 checker = 1;
1716 for (int i = 0; i < MAX_LINK_COUNT; ++i) {
1717 if (lm->link_mask & checker) {
1718 lm->link_count++;
1719 }
1720 checker <<= 1;
1721 }
1722 if (lm->link_count == 0) {
1723 free(lm);
1724 return NULL;
1725 }
1726 // Allocate array for link indexes
1727 lm->link_indexes = (uint64_t *) malloc(lm->link_count * sizeof(uint64_t));
1728 if (lm->link_indexes == NULL) {
1729 free(lm);
1730 return NULL;
1731 }
1732
1733 // Fill link indexes
1734 indexer = 0;
1735 checker = 1;
1736 for (int i = 0; i < MAX_LINK_COUNT; ++i) {
1737 if (lm->link_mask & checker) {
1738 lm->link_indexes[indexer++] = i;
1739 }
1740 checker <<= 1;
1741 }
1742
1743 return lm;
1744}
1745
1746// Destroy links structure.
1748{
1749 if (links != NULL) {
1750 free(links->link_indexes);
1751 free(links);
1752 }
1753}
1754// Following functions are defined in links.h
1755// (their headers are repeated here with INLINE_IMPL to generate externally
1756// linkable code)
1757
1758// Get index of link (0 - (link_count-1))
1759INLINE_IMPL int ur_get_link_index(ur_links_t *links, uint64_t link_bit_field);
1760
1761// Get position in link_bit_field of link
1762INLINE_IMPL uint64_t ur_get_link_bit_field_position(ur_links_t *links, unsigned int index);
1763
1764// Get link mask.
1765INLINE_IMPL uint64_t ur_get_link_mask(ur_links_t *links);
1766
1767// Get link count.
1768INLINE_IMPL unsigned int ur_get_link_count(ur_links_t *links);
1769
1770// END OF "Links" part *********************************************************
1771// *****************************************************************************
1772
INLINE_IMPL char * ip_get_v4_as_bytes(const ip_addr_t *addr)
Definition ipaddr.h:171
INLINE_IMPL ip_addr_t ip_from_16_bytes_be(const char b[16])
Definition ipaddr.h:236
INLINE_IMPL void ip_to_str(const ip_addr_t *addr, char *str)
Definition ipaddr.h:325
INLINE_IMPL ip_addr_t ip_from_4_bytes_le(const char b[4])
Definition ipaddr.h:218
INLINE_IMPL int ip_cmp(const ip_addr_t *addr1, const ip_addr_t *addr2)
Definition ipaddr.h:266
INLINE_IMPL ip_addr_t ip_from_16_bytes_le(const char b[16])
Definition ipaddr.h:249
INLINE_IMPL int ip_is4(const ip_addr_t *addr)
Definition ipaddr.h:131
INLINE_IMPL ip_addr_t ip_from_int(uint32_t i)
Definition ipaddr.h:183
INLINE_IMPL int ip_from_str(const char *str, ip_addr_t *addr)
Definition ipaddr.h:301
INLINE_IMPL int ip_is6(const ip_addr_t *addr)
Definition ipaddr.h:143
INLINE_IMPL uint32_t ip_get_v4_as_int(const ip_addr_t *addr)
Definition ipaddr.h:157
INLINE_IMPL ip_addr_t ip_from_4_bytes_be(const char b[4])
Definition ipaddr.h:199
ur_template_t * ur_create_template_from_ifc_spec(const char *ifc_data_fmt)
Create UniRec template from data format string. Creates new UniRec template (function ur_create_templ...
Definition unirec.c:631
int ur_undefine_field_by_id(ur_field_id_t field_id)
Undefine UniRec field by its id Undefine UniRec field created at run-time. It erases given field from...
Definition unirec.c:701
void ur_print_template(ur_template_t *tmplt)
Print UniRec template Print static_size, first_dynamic and table of offsets to stdout (for debugging)...
Definition unirec.c:1121
#define ur_rec_fixlen_size(tmplt)
Get size of fixed-length part of UniRec record Get total size of UniRec record except variable-length...
Definition unirec.h:671
#define ur_set_var_offset(tmplt, rec, field_id, offset_val)
Set offset of variable-length field in the record. Set offset of specified variable-length field in t...
Definition unirec.h:496
void ur_clear_varlen(const ur_template_t *tmplt, void *rec)
Clear variable-length part of a record. For better performance of setting content to variable-length ...
Definition unirec.c:1201
int ur_init(ur_static_field_specs_t field_specs_static)
Initialize UniRec structures Initialize UniRec structures. Function is called during defining first o...
Definition unirec.c:210
ur_template_t * ur_define_fields_and_update_template(const char *ifc_data_fmt, ur_template_t *tmplt)
Defined new fields and expand an UniRec template Define new fields (function ur_define_set_of_fields)...
Definition unirec.c:616
const char * ur_field_type_str[]
UniRec data types.
Definition unirec.c:137
ur_template_t * ur_expand_template(const char *ifc_data_fmt, ur_template_t *tmplt)
Expand UniRec template Expand existing UniRec template by a string containing types and names of its ...
Definition unirec.c:490
char * ur_get_var_as_str(const ur_template_t *tmplt, const void *rec, ur_field_id_t field_id)
Get variable-length UniRec field as a C string Copy data of a variable-length field from UniRec recor...
Definition unirec.c:1235
const char * ur_values_get_description_start_end(uint32_t start, uint32_t end, int32_t value)
Returns description of specified value (Helper function) Helper function for ur_values_get_descriptio...
Definition unirec.c:1682
int ur_undefine_field(const char *name)
Undefine UniRec field by its name Undefine UniRec field created at run-time. It erases given field fr...
Definition unirec.c:726
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
uint16_t ur_rec_varlen_size(const ur_template_t *tmplt, const void *rec)
Get size of variable sized part of UniRec record Get total size of all variable-length fields in an U...
Definition unirec.c:1210
#define ur_array_allocate(tmplt, rec, field_id, elem_cnt)
Preallocates UniRec array field to have requested number of elements.
Definition unirec.h:629
int ur_array_resize(const ur_template_t *tmplt, void *rec, int field_id, int len)
Change length of a array field.
Definition unirec.c:1176
#define ur_is_array(field_id)
Definition unirec.h:526
#define ur_get_var_offset(tmplt, rec, field_id)
Get offset of variable-length field in the record. Get offset of a specified variable-length field in...
Definition unirec.h:464
ur_static_field_specs_t UR_FIELD_SPECS_STATIC
Structure that lists staticaly defined UniRec field specifications such as names, types,...
Definition unirec.c:206
char * ur_array_append_get_ptr(const ur_template_t *tmplt, void *rec, int field_id)
Allocate new element at the end of array and return its pointer.
Definition unirec.c:1190
void ur_free_template(ur_template_t *tmplt)
Destroy UniRec template Free all memory allocated for a template created previously by ur_create_temp...
Definition unirec.c:1094
#define ur_rec_size(tmplt, rec)
Get size of UniRec record (static and variable length) Get total size of whole UniRec record.
Definition unirec.h:680
#define ur_get_size(field_id)
Get size of UniRec field Get size of a fixed-length UniRec field. When variable-length field is passe...
Definition unirec.h:405
void ur_finalize()
Deallocate UniRec structures Deallocate UniRec structures at the end of a program....
Definition unirec.c:740
#define ur_template_string(tmplt)
Get string of a template Get names and sizes of fields separated by comma. Return string has to be fr...
Definition unirec.h:364
const int ur_field_type_size[]
Sizes of UniRec data types.
Definition unirec.c:98
#define UR_MAX_SIZE
Definition unirec.h:1013
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
ur_field_specs_t ur_field_specs
Structure that lists UniRec field specifications such as names, types, id.
Definition unirec.c:205
ur_template_t * ur_ctx_create_bidirectional_template(trap_ctx_t *ctx, int ifc_in, int ifc_out, const char *fields, char **errstr)
Create UniRec template and set it to input and output interface on specified context Creates UniRec t...
Definition unirec.c:881
int ur_get_empty_id()
Return first empty id for new UniRec field Return first empty id for new UniRec field....
Definition unirec.c:292
void * ur_create_record(const ur_template_t *tmplt, uint16_t max_var_size)
Definition unirec.c:1220
int ur_ctx_set_input_template(trap_ctx_t *ctx, int ifc, ur_template_t *tmplt)
Set UniRec template to input interface on specified context.
Definition unirec.c:862
int ur_ctx_set_output_template(trap_ctx_t *ctx, int ifc, ur_template_t *tmplt)
Set UniRec template to ouput interface on specified context.
Definition unirec.c:842
#define ur_size_of(type)
Get size of UniRec type Get size of fixed-length UniRec type. For variable-length type return value <...
Definition unirec.h:372
#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_is_static(field_id)
Alias for ur_is_fixlen (for backwards compatibility only)
Definition unirec.h:662
int ur_template_compare(const ur_template_t *tmpltA, const ur_template_t *tmpltB)
Compares fields of two UniRec templates Function compares only sets of UniRec fields (direction is no...
Definition unirec.c:1110
int ur_field_array_elem_type[]
UniRec array element data types.
Definition unirec.c:172
#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_set_var_len(tmplt, rec, field_id, len)
Set size of variable-length field in the record. Set size of specified variable-length field in the r...
Definition unirec.h:485
#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
void * ur_clone_record(const ur_template_t *tmplt, const void *src)
Create new UniRec and copy the source UniRec into it. Function creates new UniRec record and fills it...
Definition unirec.c:1249
#define ur_get_name(field_id)
Get name of UniRec field Get name of any UniRec defined field.
Definition unirec.h:380
char * ur_ifc_data_fmt_to_field_names(const char *ifc_data_fmt)
Parses field names from data format Function parses field names from data format and returns pointer ...
Definition unirec.c:438
int ur_set_var(const ur_template_t *tmplt, void *rec, int field_id, const void *val_ptr, int val_len)
Set content of variable-length UniRec field Copy given data into variable-length UniRec field,...
Definition unirec.c:1158
int ur_define_set_of_fields(const char *ifc_data_fmt)
Define set of new UniRec fields Define new UniRec fields at run-time. It adds new fields into existin...
Definition unirec.c:564
void ur_copy_fields(const ur_template_t *dst_tmplt, void *dst, const ur_template_t *src_tmplt, const void *src)
Copy data from one UniRec record to another. Copies all fields present in both templates from src to ...
Definition unirec.c:1259
ur_template_t * ur_ctx_create_output_template(trap_ctx_t *ctx, int ifc, const char *fields, char **errstr)
Create UniRec template and set it to output interface on specified context Creates UniRec template,...
Definition unirec.c:823
int ur_get_id_by_name(const char *name)
Get ID of a field by its name Get ID of a field by its name.
Definition unirec.c:780
int ur_set_array_from_string(const ur_template_t *tmpl, void *data, ur_field_id_t f_id, const char *v)
Set value of a UniRec array field.
Definition unirec.c:1321
#define ur_get_type(field_id)
Get type of UniRec field Get type of any UniRec defined field.
Definition unirec.h:388
int ur_get_field_type_from_str(const char *type)
Definition unirec.c:359
int ur_set_from_string(const ur_template_t *tmpl, void *data, ur_field_id_t f_id, const char *v)
Set value of a UniRec field.
Definition unirec.c:1493
int ur_define_field(const char *name, ur_field_type_t type)
Define new UniRec field Define new UniRec field at run-time. It adds new field into existing structur...
Definition unirec.c:642
ur_template_t * ur_ctx_create_input_template(trap_ctx_t *ctx, int ifc, const char *fields, char **errstr)
Create UniRec template and set it to input interface on specified context Creates UniRec template,...
Definition unirec.c:804
const char * ur_values_get_name_start_end(uint32_t start, uint32_t end, int32_t value)
Returns name of specified value (Helper function) Helper function for ur_values_get_name....
Definition unirec.c:1672
void ur_free_record(void *record)
Definition unirec.c:1229
int compare_fields(const void *field1, const void *field2)
Compare fields Compare two fields. This function is for sorting the fields in the right order....
Definition unirec.c:791
ur_template_t * ur_create_template(const char *fields, char **errstr)
Create UniRec template Create new UniRec template specified by a string containing names of its field...
Definition unirec.c:906
#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
ur_iter_t ur_iter_fields(const ur_template_t *tmplt, ur_iter_t id)
Iterate over fields of a template in order of a record This function can be used to iterate over all ...
Definition unirec.c:1292
char * ur_cpy_string(const char *str)
Duplicates given string. Helper function which returns pointer to duplicated string....
Definition unirec.c:1661
#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
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
uint8_t ur_time_from_string(ur_time_t *ur, const char *str)
Definition unirec.c:1612
#define ur_time_from_sec_nsec(sec, nsec)
Convert seconds and nanoseconds to ur_time_t.
Definition ur_time.h:100
#define INLINE_IMPL
Definition inline.h:13
mac_addr_t
Definition macaddr.h:75
INLINE_IMPL void mac_to_str(const mac_addr_t *addr, char *str)
Definition macaddr.h:129
INLINE_IMPL void mac_to_bytes(const mac_addr_t *addr, uint8_t *array)
Definition macaddr.h:144
INLINE_IMPL int mac_cmp(const mac_addr_t *addr1, const mac_addr_t *addr2)
Definition macaddr.h:118
void ur_var_change_size(const ur_template_t *tmplt, void *rec, int field_id, int new_val_len)
Definition unirec.c:1132
INLINE_IMPL int mac_from_str(const char *str, mac_addr_t *addr)
Definition macaddr.h:99
const char * ur_get_type_and_name_from_string(const char *source, char **name, char **type, int *length_name, int *length_type)
Definition unirec.c:372
const char UR_MEMORY_ERROR[]
Definition unirec.c:208
#define MAX(A, B)
Definition unirec.c:65
INLINE_IMPL mac_addr_t mac_from_bytes(const uint8_t *array)
Definition macaddr.h:83
Definition of UniRec structures and functions.
ur_field_type_t
Definition unirec.h:95
@ UR_TYPE_A_UINT32
unsigned int (32b) array
Definition unirec.h:118
@ UR_TYPE_UINT64
unsigned int (64b)
Definition unirec.h:105
@ UR_TYPE_A_UINT16
unsigned int (16b) array
Definition unirec.h:116
@ UR_TYPE_A_INT64
int (64b) array
Definition unirec.h:121
@ UR_TYPE_A_DOUBLE
double (64b) array
Definition unirec.h:123
@ UR_TYPE_A_IP
IP address (128b) array.
Definition unirec.h:124
@ UR_TYPE_INT16
int (8b)
Definition unirec.h:102
@ UR_TYPE_A_INT32
int (32b) array
Definition unirec.h:119
@ UR_TYPE_A_INT8
int (8b) array
Definition unirec.h:115
@ UR_TYPE_A_INT16
int (8b) array
Definition unirec.h:117
@ 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_A_UINT8
unsigned int (8b) array
Definition unirec.h:114
@ UR_TYPE_DOUBLE
double (64b)
Definition unirec.h:108
@ UR_TYPE_A_FLOAT
float (32b) array
Definition unirec.h:122
@ UR_TYPE_A_UINT64
unsigned int (64b) array
Definition unirec.h:120
@ UR_TYPE_A_MAC
MAC address (48b) array.
Definition unirec.h:125
@ 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_A_TIME
time (64b) array
Definition unirec.h:126
@ 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
ur_field_id_t ur_last_id
The highest ID of a field + 1.
Definition unirec.h:169
#define UR_UNINITIALIZED
Indicator if the UniRec has not been initialized by calling function ur_init.
Definition unirec.h:80
ur_tmplt_direction direction
Direction of data input, output, bidirection, no direction.
Definition unirec.h:198
ur_field_id_t ur_iter_t
Type for identifying iteration id through all fields.
Definition unirec.h:137
#define UR_E_MEMORY
Problem during allocating memory.
Definition unirec.h:89
int16_t ur_field_id_t
Type of UniRec field identifiers.
Definition unirec.h:136
#define UR_ITER_BEGIN
First value in iterating through the fields.
Definition unirec.h:75
#define UR_DEFAULT_LENGTH_OF_FIELD_TYPE
Definition unirec.h:68
#define UR_OK
No problem.
Definition unirec.h:90
#define UR_INITIALIZED
Indicator if the UniRec has been initialized by calling function ur_init.
Definition unirec.h:81
uint8_t intialized
If the UniRec is initialized by function ur_init variable is set to UR_INITIALIZED,...
Definition unirec.h:175
int size
Size of a field.
Definition unirec.h:184
ur_field_id_linked_list_t * ur_undefine_fields
linked list of free (undefined) IDs
Definition unirec.h:174
#define UR_ARRAY_DELIMITER
Delimiter of array elements in string.
Definition unirec.h:72
#define UR_E_TYPE_MISMATCH
The type of a field is different.
Definition unirec.h:86
ur_field_id_t ur_last_statically_defined_id
Last statically defined field by UR_FIELDS(...)
Definition unirec.h:168
#define UR_E_INVALID_NAME
The given name is not present in a template.
Definition unirec.h:87
uint16_t count
Count of fields in template.
Definition unirec.h:196
ur_field_type_t * ur_field_types
Array of types of fields.
Definition unirec.h:167
char * name
Name of a field.
Definition unirec.h:183
uint16_t first_dynamic
First dynamic (variable-length) field. Index to the ids array.
Definition unirec.h:195
#define UR_DEFAULT_LENGTH_OF_FIELD_NAME
Definition unirec.h:67
uint16_t * offset
Table of offsets.
Definition unirec.h:192
uint32_t ifc_out
output interface number (stored only if the direction == UR_TMPLT_DIRECTION_BI)
Definition unirec.h:199
uint16_t static_size
Size of static part.
Definition unirec.h:197
#define UR_DEFAULT_LENGTH_OF_TEMPLATE
Definition unirec.h:66
#define UR_ARRAY_ALLOC
Default alloc size increment for ur_set_array_from_string.
Definition unirec.h:73
ur_field_id_t id
ID of a field.
Definition unirec.h:185
short * ur_field_sizes
Array of sizes of fields.
Definition unirec.h:154
#define UR_INVALID_OFFSET
Default value of all offsets (value is not in the record)
Definition unirec.h:78
ur_field_id_t ur_last_id
Last specified ID.
Definition unirec.h:156
ur_tmplt_direction
Definition unirec.h:129
@ UR_TMPLT_DIRECTION_IN
input direction
Definition unirec.h:131
@ UR_TMPLT_DIRECTION_NO
template is not used for sending data
Definition unirec.h:130
@ UR_TMPLT_DIRECTION_OUT
ouput direction
Definition unirec.h:132
@ UR_TMPLT_DIRECTION_BI
bidirection
Definition unirec.h:133
#define UR_NO_DYNAMIC_VALUES
Value of variable "first_dynamic" if no dynamic values are present.
Definition unirec.h:79
short * ur_field_sizes
Array of sizes of fields.
Definition unirec.h:166
char ** ur_field_names
Array of names of fields.
Definition unirec.h:153
#define UR_COUNT_OF_TYPES
Constants for all possible types of UniRec fields.
Definition unirec.h:94
char ** ur_field_names
Array of names of fields.
Definition unirec.h:165
#define UR_INITIAL_SIZE_FIELDS_TABLE
Initial size of free space in fields tables.
Definition unirec.h:69
#define UR_FIELD_ID_MAX
Max ID of a field.
Definition unirec.h:70
#define UR_E_INVALID_PARAMETER
The given parameter is wrong.
Definition unirec.h:84
#define UR_E_INVALID_TYPE
The type of a field is not defined.
Definition unirec.h:88
ur_field_id_t ur_allocated_fields
Definition unirec.h:173
#define UR_ITER_END
Last value in iterating through the fields.
Definition unirec.h:76
int16_t * ids
Array of ids in template.
Definition unirec.h:194
ur_field_type_t * ur_field_types
Array of types of fields.
Definition unirec.h:155
uint16_t offset_size
size of offset table.
Definition unirec.h:193
#define UR_E_INVALID_FIELD_ID
The field ID is not present in a template.
Definition unirec.h:85
Sorting fields structure This structure is used to sort fields by their size and name....
Definition unirec.h:182
UniRec fields structure It contains all fields which are statically defined by UR_FIELDS(....
Definition unirec.h:164
UniRec default field list It contains all fields which are specified statically in source code of a m...
Definition unirec.h:152
UniRec template. It contains a table mapping a field to its position in an UniRec record.
Definition unirec.h:191
const ur_values_t ur_values[]
Definition ur_values.c:6
char * name
Name of Value.
Definition ur_values.h:15
char * description
Description of Value.
Definition ur_values.h:16