libyang 4.3.4
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
16#define _GNU_SOURCE /* strdup */
17
18#include "plugins_types.h"
19
20#include <stdint.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include "libyang.h"
25
26/* additional internal headers for some useful simple macros */
27#include "compat.h"
28#include "ly_common.h"
29#include "plugins_internal.h" /* LY_TYPE_*_STR */
30
39
40#define ENUM_FIXED_SIZE_BITS(type) \
41 lyplg_type_get_highest_set_bit_pos(\
42 ((struct lysc_type_enum *)type)->enums[LY_ARRAY_COUNT(((struct lysc_type_enum *)type)->enums) - 1].value)
43
44static void
45lyplg_type_lyb_size_enum(const struct lysc_type *type, enum lyplg_lyb_size_type *size_type, uint32_t *fixed_size_bits)
46{
47 const struct lysc_type_enum *type_enum = (struct lysc_type_enum *)type;
48 uint32_t max_value;
49
50 *size_type = LYPLG_LYB_SIZE_FIXED_BITS;
51
52 if (type_enum->enums[0].value < 0) {
53 /* we need the full 4 bytes */
54 *fixed_size_bits = 32;
55 return;
56 }
57
58 /* value of the last enum, sorted */
59 max_value = type_enum->enums[LY_ARRAY_COUNT(type_enum->enums) - 1].value;
60
61 /* learn the position of the highest set bit, the least amount of bits that can hold the number */
62 *fixed_size_bits = lyplg_type_get_highest_set_bit_pos(max_value);
63}
64
65static LY_ERR
66lyplg_type_store_enum(const struct ly_ctx *ctx, const struct lysc_type *type, const void *value, uint32_t value_size_bits,
67 uint32_t options, LY_VALUE_FORMAT format, void *UNUSED(prefix_data), uint32_t hints,
68 const struct lysc_node *UNUSED(ctx_node), const struct lysc_ext_instance *UNUSED(top_ext),
69 struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres), struct ly_err_item **err)
70{
71 struct lysc_type_enum *type_enum = (struct lysc_type_enum *)type;
72 LY_ERR ret = LY_SUCCESS;
74 ly_bool found = 0;
75 uint32_t value_size;
76 int64_t num = 0;
77 int32_t num_val;
78
79 /* init storage */
80 memset(storage, 0, sizeof *storage);
81 storage->realtype = type;
82
83 /* check value length */
84 ret = lyplg_type_check_value_size("enumeration", format, value_size_bits, LYPLG_LYB_SIZE_FIXED_BITS,
85 ENUM_FIXED_SIZE_BITS(type), &value_size, err);
86 LY_CHECK_GOTO(ret, cleanup);
87
88 if (format == LY_VALUE_LYB) {
89 /* convert the value to host byte order */
90 memcpy(&num, value, value_size);
91 num = le64toh(num);
92 num_val = num;
93
94 /* find the matching enumeration value item */
95 LY_ARRAY_FOR(type_enum->enums, u) {
96 if (type_enum->enums[u].value == num_val) {
97 found = 1;
98 break;
99 }
100 }
101
102 if (!found) {
103 /* value not found */
104 ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid enumeration value % " PRIi32 ".", num_val);
105 goto cleanup;
106 }
107
108 /* store value */
109 storage->enum_item = &type_enum->enums[u];
110
111 /* canonical settings via dictionary due to free callback */
112 ret = lydict_insert(ctx, type_enum->enums[u].name, 0, &storage->_canonical);
113 LY_CHECK_GOTO(ret, cleanup);
114
115 /* success */
116 goto cleanup;
117 }
118
119 /* check hints */
120 ret = lyplg_type_check_hints(hints, value, value_size, type->basetype, NULL, err);
121 LY_CHECK_GOTO(ret, cleanup);
122
123 /* find the matching enumeration value item */
124 LY_ARRAY_FOR(type_enum->enums, u) {
125 if (!ly_strncmp(type_enum->enums[u].name, value, value_size)) {
126 found = 1;
127 break;
128 }
129 }
130
131 if (!found) {
132 /* enum not found */
133 ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid enumeration value \"%.*s\".", (int)value_size,
134 (char *)value);
135 goto cleanup;
136 }
137
138 /* store value */
139 storage->enum_item = &type_enum->enums[u];
140
141 /* store canonical value, it always is */
142 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
143 ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
144 options &= ~LYPLG_TYPE_STORE_DYNAMIC;
145 LY_CHECK_GOTO(ret, cleanup);
146 } else {
147 ret = lydict_insert(ctx, value, value_size, &storage->_canonical);
148 LY_CHECK_GOTO(ret, cleanup);
149 }
150
151cleanup:
152 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
153 free((void *)value);
154 }
155
156 if (ret) {
157 lyplg_type_free_simple(ctx, storage);
158 }
159 return ret;
160}
161
162static int
163lyplg_type_sort_enum(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1,
164 const struct lyd_value *val2)
165{
166 if (val1->enum_item->value < val2->enum_item->value) {
167 return -1;
168 } else if (val1->enum_item->value > val2->enum_item->value) {
169 return 1;
170 } else {
171 return 0;
172 }
173}
174
175static const void *
176lyplg_type_print_enum(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format,
177 void *UNUSED(prefix_data), ly_bool *dynamic, uint32_t *value_size_bits)
178{
179 int64_t prev_num = 0, num = 0;
180 void *buf;
181
182 if (format == LY_VALUE_LYB) {
183 prev_num = num = value->enum_item->value;
184 num = htole64(num);
185 if (num == prev_num) {
186 /* values are equal, little-endian */
187 *dynamic = 0;
188 if (value_size_bits) {
189 *value_size_bits = ENUM_FIXED_SIZE_BITS(value->realtype);
190 }
191 return &value->enum_item->value;
192 } else {
193 /* values differ, big-endian */
194 buf = calloc(1, 4);
195 LY_CHECK_RET(!buf, NULL);
196
197 *dynamic = 1;
198 if (value_size_bits) {
199 *value_size_bits = ENUM_FIXED_SIZE_BITS(value->realtype);
200 }
201 memcpy(buf, &num, 4);
202 return buf;
203 }
204 }
205
206 /* use the cached canonical value */
207 if (dynamic) {
208 *dynamic = 0;
209 }
210 if (value_size_bits) {
211 *value_size_bits = strlen(value->_canonical) * 8;
212 }
213 return value->_canonical;
214}
215
224 {
225 .module = "",
226 .revision = NULL,
227 .name = LY_TYPE_ENUM_STR,
228
229 .plugin.id = "ly2 enumeration",
230 .plugin.lyb_size = lyplg_type_lyb_size_enum,
231 .plugin.store = lyplg_type_store_enum,
232 .plugin.validate_value = NULL,
233 .plugin.validate_tree = NULL,
234 .plugin.compare = lyplg_type_compare_simple,
235 .plugin.sort = lyplg_type_sort_enum,
236 .plugin.print = lyplg_type_print_enum,
237 .plugin.duplicate = lyplg_type_dup_simple,
238 .plugin.free = lyplg_type_free_simple,
239 },
240 {0}
241};
const struct lyplg_type_record plugins_enumeration[]
Plugin information for enumeration type implementation.
#define ENUM_FIXED_SIZE_BITS(type)
Definition enumeration.c:40
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:237
@ LYVE_DATA
Definition log.h:274
@ LY_EVALID
Definition log.h:245
@ LY_SUCCESS
Definition log.h:238
Libyang full error structure.
Definition log.h:282
YANG extension compiled instance.
lyplg_lyb_size_type
Type of the LYB size of a value of a particular type.
LIBYANG_API_DECL LY_ERR lyplg_type_check_hints(uint32_t hints, const char *value, uint32_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 uint64_t lyplg_type_get_highest_set_bit_pos(uint64_t num)
Learn the position of the highest set bit in a number. Represents also the least amount of bits requi...
LIBYANG_API_DECL LY_ERR lyplg_type_check_value_size(const char *type_name, LY_VALUE_FORMAT format, uint32_t value_size_bits, enum lyplg_lyb_size_type lyb_size_type, uint32_t lyb_fixed_size_bits, uint32_t *value_size, struct ly_err_item **err)
Check a value type in bits is correct and as expected.
LIBYANG_API_DECL LY_ERR ly_err_new(struct ly_err_item **err, LY_ERR ecode, LY_VECODE vecode, char *data_path, char *apptag, const char *err_format,...) _FORMAT_PRINTF(6
Create and fill error structure.
@ LYPLG_LYB_SIZE_FIXED_BITS
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 ly_ctx *ctx, 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_COUNT(ARRAY)
Get the number of records in the ARRAY.
Definition tree.h:148
#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:567
const char * _canonical
Definition tree_data.h:564
YANG data representation.
Definition tree_data.h:563