libyang  2.1.30
libyang is YANG data modelling language parser and toolkit written (and providing API) in C.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
enumeration.c
Go to the documentation of this file.
1 
15 #define _GNU_SOURCE /* strdup */
16 
17 #include "plugins_types.h"
18 
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include "libyang.h"
24 
25 /* additional internal headers for some useful simple macros */
26 #include "common.h"
27 #include "compat.h"
28 #include "plugins_internal.h" /* LY_TYPE_*_STR */
29 
39 LIBYANG_API_DEF LY_ERR
40 lyplg_type_store_enum(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len,
41  uint32_t options, LY_VALUE_FORMAT format, void *UNUSED(prefix_data), uint32_t hints,
42  const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
43  struct ly_err_item **err)
44 {
45  struct lysc_type_enum *type_enum = (struct lysc_type_enum *)type;
46  LY_ERR ret = LY_SUCCESS;
48  ly_bool found = 0;
49  int64_t num = 0;
50  int32_t num_val;
51 
52  /* init storage */
53  memset(storage, 0, sizeof *storage);
54  storage->realtype = type;
55 
56  if (format == LY_VALUE_LYB) {
57  /* validation */
58  if (value_len != 4) {
59  ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid LYB enumeration value size %zu (expected 4).",
60  value_len);
61  goto cleanup;
62  }
63 
64  /* convert the value to host byte order */
65  memcpy(&num, value, value_len);
66  num = le64toh(num);
67  num_val = num;
68 
69  /* find the matching enumeration value item */
70  LY_ARRAY_FOR(type_enum->enums, u) {
71  if (type_enum->enums[u].value == num_val) {
72  found = 1;
73  break;
74  }
75  }
76 
77  if (!found) {
78  /* value not found */
79  ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid enumeration value % " PRIi32 ".", num_val);
80  goto cleanup;
81  }
82 
83  /* store value */
84  storage->enum_item = &type_enum->enums[u];
85 
86  /* canonical settings via dictionary due to free callback */
87  ret = lydict_insert(ctx, type_enum->enums[u].name, 0, &storage->_canonical);
88  LY_CHECK_GOTO(ret, cleanup);
89 
90  /* success */
91  goto cleanup;
92  }
93 
94  /* check hints */
95  ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
96  LY_CHECK_GOTO(ret, cleanup);
97 
98  /* find the matching enumeration value item */
99  LY_ARRAY_FOR(type_enum->enums, u) {
100  if (!ly_strncmp(type_enum->enums[u].name, value, value_len)) {
101  found = 1;
102  break;
103  }
104  }
105 
106  if (!found) {
107  /* enum not found */
108  ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid enumeration value \"%.*s\".", (int)value_len,
109  (char *)value);
110  goto cleanup;
111  }
112 
113  /* store value */
114  storage->enum_item = &type_enum->enums[u];
115 
116  /* store canonical value, it always is */
117  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
118  ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
119  options &= ~LYPLG_TYPE_STORE_DYNAMIC;
120  LY_CHECK_GOTO(ret, cleanup);
121  } else {
122  ret = lydict_insert(ctx, value, value_len, &storage->_canonical);
123  LY_CHECK_GOTO(ret, cleanup);
124  }
125 
126 cleanup:
127  if (options & LYPLG_TYPE_STORE_DYNAMIC) {
128  free((void *)value);
129  }
130 
131  if (ret) {
132  lyplg_type_free_simple(ctx, storage);
133  }
134  return ret;
135 }
136 
137 LIBYANG_API_DEF const void *
138 lyplg_type_print_enum(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format,
139  void *UNUSED(prefix_data), ly_bool *dynamic, size_t *value_len)
140 {
141  int64_t prev_num = 0, num = 0;
142  void *buf;
143 
144  if (format == LY_VALUE_LYB) {
145  prev_num = num = value->enum_item->value;
146  num = htole64(num);
147  if (num == prev_num) {
148  /* values are equal, little-endian */
149  *dynamic = 0;
150  if (value_len) {
151  *value_len = 4;
152  }
153  return &value->enum_item->value;
154  } else {
155  /* values differ, big-endian */
156  buf = calloc(1, 4);
157  LY_CHECK_RET(!buf, NULL);
158 
159  *dynamic = 1;
160  if (value_len) {
161  *value_len = 4;
162  }
163  memcpy(buf, &num, 4);
164  return buf;
165  }
166  }
167 
168  /* use the cached canonical value */
169  if (dynamic) {
170  *dynamic = 0;
171  }
172  if (value_len) {
173  *value_len = strlen(value->_canonical);
174  }
175  return value->_canonical;
176 }
177 
186  {
187  .module = "",
188  .revision = NULL,
189  .name = LY_TYPE_ENUM_STR,
190 
191  .plugin.id = "libyang 2 - enumeration, version 1",
192  .plugin.store = lyplg_type_store_enum,
193  .plugin.validate = NULL,
194  .plugin.compare = lyplg_type_compare_simple,
195  .plugin.sort = NULL,
196  .plugin.print = lyplg_type_print_enum,
197  .plugin.duplicate = lyplg_type_dup_simple,
198  .plugin.free = lyplg_type_free_simple,
199  .plugin.lyb_data_len = 4,
200  },
201  {0}
202 };
LIBYANG_API_DECL LY_ERR lyplg_type_store_enum(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, size_t value_len, uint32_t options, LY_VALUE_FORMAT format, void *prefix_data, uint32_t hints, const struct lysc_node *ctx_node, struct lyd_value *storage, struct lys_glob_unres *unres, struct ly_err_item **err)
Implementation of lyplg_type_store_clb for the built-in enumeration type.
struct lysc_type * realtype
Definition: tree_data.h:564
LIBYANG_API_DECL LY_ERR lyplg_type_compare_simple(const struct lyd_value *val1, const struct lyd_value *val2)
Implementation of lyplg_type_compare_clb for a generic simple type.
Compiled YANG data node.
Definition: tree_schema.h:1414
LIBYANG_API_DECL LY_ERR ly_err_new(struct ly_err_item **err, LY_ERR ecode, LY_VECODE vecode, char *path, char *apptag, const char *err_format,...) _FORMAT_PRINTF(6
Create and fill error structure.
uint8_t ly_bool
Type to indicate boolean value.
Definition: log.h:28
#define LYPLG_TYPE_STORE_DYNAMIC
struct lyplg_type_record plugins_enumeration[]
Plugin information for enumeration type implementation.
Definition: enumeration.c:185
The main libyang public header.
YANG data representation.
Definition: tree_data.h:560
const char * _canonical
Definition: tree_data.h:561
Libyang full error structure.
Definition: log.h:299
Definition: log.h:291
Definition: log.h:262
LIBYANG_API_DECL LY_ERR lydict_insert(const struct ly_ctx *ctx, const char *value, size_t len, const char **str_p)
Insert string into dictionary. If the string is already present, only a reference counter is incremen...
LIBYANG_API_DECL LY_ERR lyplg_type_check_hints(uint32_t hints, const char *value, size_t value_len, LY_DATA_TYPE type, int *base, struct ly_err_item **err)
Check that the type is suitable for the parser&#39;s hints (if any) in the specified format.
const char * module
#define LY_ARRAY_FOR(ARRAY,...)
Sized-array iterator (for-loop).
Definition: tree.h:167
#define LY_ARRAY_COUNT_TYPE
Type (i.e. size) of the sized array&#39;s size counter.
Definition: tree.h:104
LIBYANG_API_DECL const void * lyplg_type_print_enum(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format, void *prefix_data, ly_bool *dynamic, size_t *value_len)
Implementation of lyplg_type_print_clb for the built-in enumeration type.
LIBYANG_API_DECL LY_ERR lydict_insert_zc(const struct ly_ctx *ctx, char *value, const char **str_p)
Insert string into dictionary - zerocopy version. If the string is already present, only a reference counter is incremented and no memory allocation is performed. This insert function variant avoids duplication of specified value - it is inserted into the dictionary directly.
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.
Definition: tree.h:234
struct lysc_type_bitenum_item * enums
Definition: tree_schema.h:1349
LY_DATA_TYPE basetype
Definition: tree_schema.h:1299
LIBYANG_API_DECL LY_ERR lyplg_type_dup_simple(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
Implementation of lyplg_type_dup_clb for a generic simple type.
LY_ERR
libyang&#39;s error codes returned by the libyang functions.
Definition: log.h:254
LIBYANG_API_DECL void lyplg_type_free_simple(const struct ly_ctx *ctx, struct lyd_value *value)
Implementation of lyplg_type_free_clb for a generic simple type.
API for (user) types plugins.
libyang context handler.