libyang 2.1.148
libyang is YANG data modelling language parser and toolkit written (and providing API) in C.
Loading...
Searching...
No Matches
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
39LIBYANG_API_DEF LY_ERR
40lyplg_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
126cleanup:
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
137LIBYANG_API_DEF const void *
138lyplg_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_DEF 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 *UNUSED(prefix_data), uint32_t hints, const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres), struct ly_err_item **err)
Definition enumeration.c:40
const struct lyplg_type_record plugins_enumeration[]
Plugin information for enumeration type implementation.
LIBYANG_API_DEF const void * lyplg_type_print_enum(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format, void *UNUSED(prefix_data), ly_bool *dynamic, size_t *value_len)
libyang context handler.
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 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,...
LY_ERR
libyang's error codes returned by the libyang functions.
Definition log.h:248
@ LYVE_DATA
Definition log.h:285
@ LY_EVALID
Definition log.h:256
@ LY_SUCCESS
Definition log.h:249
Libyang full error structure.
Definition log.h:293
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.
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's hints (if any) in the specified format.
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.
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.
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.
#define LYPLG_TYPE_STORE_DYNAMIC
LY_DATA_TYPE basetype
struct lysc_type_bitenum_item * enums
Compiled YANG data node.
#define LY_ARRAY_FOR(ARRAY,...)
Sized-array iterator (for-loop).
Definition tree.h:167
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.
Definition tree.h:234
#define LY_ARRAY_COUNT_TYPE
Type (i.e. size) of the sized array's size counter.
Definition tree.h:104
@ LY_VALUE_LYB
Definition tree.h:240
The main libyang public header.
uint8_t ly_bool
Type to indicate boolean value.
Definition log.h:35
API for (user) types plugins.
const struct lysc_type * realtype
Definition tree_data.h:564
const char * _canonical
Definition tree_data.h:561
YANG data representation.
Definition tree_data.h:560