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