29 #include "ly_common.h"
30 #include "plugins_internal.h"
44 static const char b64_etable[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
46 static void lyplg_type_free_binary(
const struct ly_ctx *ctx,
struct lyd_value *value);
47 static LY_ERR lyplg_type_validate_value_binary(
const struct ly_ctx *ctx,
const struct lysc_type *type,
63 binary_base64_encode(
const struct ly_ctx *ctx,
const char *data, uint32_t size,
char **str, uint32_t *str_len)
68 *str_len = (size + 2) / 3 * 4;
69 *str = malloc(*str_len + 1);
77 for (i = 0; i + 2 < size; i += 3) {
78 *ptr++ = b64_etable[(data[i] >> 2) & 0x3F];
79 *ptr++ = b64_etable[((data[i] & 0x3) << 4) | ((int)(data[i + 1] & 0xF0) >> 4)];
80 *ptr++ = b64_etable[((data[i + 1] & 0xF) << 2) | ((int)(data[i + 2] & 0xC0) >> 6)];
81 *ptr++ = b64_etable[data[i + 2] & 0x3F];
84 *ptr++ = b64_etable[(data[i] >> 2) & 0x3F];
85 if (i == (size - 1)) {
86 *ptr++ = b64_etable[((data[i] & 0x3) << 4)];
89 *ptr++ = b64_etable[((data[i] & 0x3) << 4) | ((int)(data[i + 1] & 0xF0) >> 4)];
90 *ptr++ = b64_etable[((data[i + 1] & 0xF) << 2)];
102 static const int b64_dtable[256] = {
103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63, 52, 53, 54, 55,
106 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6,
107 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0,
108 0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
109 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
124 binary_base64_decode(
const char *value, uint32_t value_size,
void **data, uint32_t *size)
126 unsigned char *ptr = (
unsigned char *)value;
127 uint32_t pad_chars, octet_count;
130 if (!value_size || (ptr[value_size - 1] !=
'=')) {
132 }
else if (ptr[value_size - 2] ==
'=') {
138 octet_count = ((value_size + 3) / 4 - (pad_chars ? 1 : 0)) * 4;
139 *size = octet_count / 4 * 3 + pad_chars;
141 str = malloc(*size + 1);
145 for (uint32_t i = 0, j = 0; i < octet_count; i += 4) {
146 int n = b64_dtable[ptr[i]] << 18 | b64_dtable[ptr[i + 1]] << 12 | b64_dtable[ptr[i + 2]] << 6 | b64_dtable[ptr[i + 3]];
149 str[j++] = n >> 8 & 0xFF;
153 int n = b64_dtable[ptr[octet_count]] << 18 | b64_dtable[ptr[octet_count + 1]] << 12;
155 str[*size - pad_chars] = n >> 16;
157 if (pad_chars == 2) {
158 n |= b64_dtable[ptr[octet_count + 2]] << 6;
160 str[*size - pad_chars + 1] = n;
177 binary_base64_validate(
const char *value, uint32_t value_size,
struct ly_err_item **err)
183 while ((idx < value_size) &&
184 (((
'A' <= value[idx]) && (value[idx] <=
'Z')) ||
185 ((
'a' <= value[idx]) && (value[idx] <=
'z')) ||
186 ((
'0' <= value[idx]) && (value[idx] <=
'9')) ||
187 (
'+' == value[idx]) || (
'/' == value[idx]))) {
193 while ((idx + pad < value_size) && (pad < 2) && (value[idx + pad] ==
'=')) {
198 if (value_size != idx + pad) {
199 if (isprint(value[idx + pad])) {
206 if (value_size & 3) {
224 binary_base64_newlines(
char **value, uint32_t *value_size, uint32_t *options,
struct ly_err_item **err)
229 if ((*value_size < 65) || ((*value)[64] !=
'\n')) {
236 *value = strndup(*value, *value_size);
237 LY_CHECK_RET(!*value,
LY_EMEM);
244 if (val[64] !=
'\n') {
250 memmove(val + 64, val + 65, size - 64);
260 lyplg_type_store_binary(
const struct ly_ctx *ctx,
const struct lysc_type *type,
const void *value, uint32_t value_size_bits,
261 uint32_t options,
LY_VALUE_FORMAT format,
void *UNUSED(prefix_data), uint32_t hints,
270 memset(storage, 0,
sizeof *storage);
272 LY_CHECK_ERR_GOTO(!val, ret =
LY_EMEM, cleanup);
278 LY_CHECK_GOTO(ret, cleanup);
282 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
283 val->
data = (
void *)value;
284 options &= ~LYPLG_TYPE_STORE_DYNAMIC;
285 }
else if (value_size) {
286 val->
data = malloc(value_size);
287 LY_CHECK_ERR_GOTO(!val->
data, ret =
LY_EMEM, cleanup);
288 memcpy(val->
data, value, value_size);
290 val->
data = strdup(
"");
291 LY_CHECK_ERR_GOTO(!val->
data, ret =
LY_EMEM, cleanup);
295 val->
size = value_size;
303 LY_CHECK_GOTO(ret, cleanup);
307 ret = binary_base64_newlines((
char **)&value, &value_size, &options, err);
308 LY_CHECK_GOTO(ret, cleanup);
311 ret = binary_base64_validate(value, value_size, err);
312 LY_CHECK_GOTO(ret, cleanup);
316 ret = binary_base64_decode(value, value_size, &val->
data, &val->
size);
317 LY_CHECK_GOTO(ret, cleanup);
320 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
322 options &= ~LYPLG_TYPE_STORE_DYNAMIC;
323 LY_CHECK_GOTO(ret, cleanup);
329 LY_CHECK_GOTO(ret, cleanup);
334 ret = lyplg_type_validate_value_binary(ctx, type, storage, err);
335 LY_CHECK_GOTO(ret, cleanup);
339 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
344 lyplg_type_free_binary(ctx, storage);
361 LY_CHECK_ARG_RET(NULL, type, storage, err,
LY_EINVAL);
365 value_len = strlen(value);
377 lyplg_type_compare_binary(
const struct ly_ctx *UNUSED(ctx),
const struct lyd_value *val1,
const struct lyd_value *val2)
391 lyplg_type_sort_binary(
const struct ly_ctx *UNUSED(ctx),
const struct lyd_value *val1,
const struct lyd_value *val2)
412 void *UNUSED(prefix_data),
ly_bool *dynamic, uint32_t *value_size_bits)
416 uint32_t ret_size = 0;
422 if (value_size_bits) {
423 *value_size_bits = val->
size * 8;
431 if (binary_base64_encode(ctx, val->
data, val->
size, &ret, &ret_size)) {
446 if (value_size_bits) {
447 *value_size_bits = ret_size ? ret_size * 8 : strlen(value->
_canonical) * 8;
458 memset(dup, 0,
sizeof *dup);
461 LY_CHECK_GOTO(ret, error);
464 LY_CHECK_ERR_GOTO(!dup_val, ret =
LY_EMEM, error);
468 dup_val->
data = orig_val->
size ? malloc(orig_val->
size) : strdup(
"");
469 LY_CHECK_ERR_GOTO(!dup_val->
data, ret =
LY_EMEM, error);
478 lyplg_type_free_binary(ctx, dup);
483 lyplg_type_free_binary(
const struct ly_ctx *ctx,
struct lyd_value *value)
507 .name = LY_TYPE_BINARY_STR,
509 .plugin.id =
"ly2 binary",
511 .plugin.store = lyplg_type_store_binary,
512 .plugin.validate_value = lyplg_type_validate_value_binary,
513 .plugin.validate_tree = NULL,
514 .plugin.compare = lyplg_type_compare_binary,
515 .plugin.sort = lyplg_type_sort_binary,
516 .plugin.print = lyplg_type_print_binary,
517 .plugin.duplicate = lyplg_type_dup_binary,
518 .plugin.free = lyplg_type_free_binary,
struct lysc_type * realtype
memset(value->fixed_mem, 0, LYD_VALUE_FIXED_MEM_SIZE)
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.
YANG extension compiled instance.
LY_ERR
libyang's error codes returned by the libyang functions.
uint8_t ly_bool
Type to indicate boolean value.
#define LYPLG_TYPE_STORE_DYNAMIC
LYPLG_TYPE_VAL_INLINE_DESTROY(val)
struct lysc_range * length
The main libyang public header.
LIBYANG_API_DECL void lyplg_type_lyb_size_variable_bytes(const struct lysc_type *type, enum lyplg_lyb_size_type *size_type, uint32_t *fixed_size_bits)
Implementation of lyplg_type_lyb_size_clb for a type with variable length rounded to bytes...
YANG data representation.
Libyang full error structure.
LIBYANG_API_DECL const char * lyd_value_get_canonical(const struct ly_ctx *ctx, const struct lyd_value *value)
Get the (canonical) value of a lyd_value.
#define LYD_VALUE_GET(value, type_val)
Get the value in format specific to the type.
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.
LIBYANG_API_DECL LY_ERR lydict_remove(const struct ly_ctx *ctx, const char *value)
Remove specified string from the dictionary. It decrement reference counter for the string and if it ...
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...
struct lyplg_type_record plugins_binary[]
Plugin information for binray type implementation.
#define LYPLG_TYPE_VAL_IS_DYN(type_val)
Check whether specific type value needs to be allocated dynamically.
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.
#define LYPLG_TYPE_VAL_INLINE_PREPARE(storage, type_val)
Prepare value memory for storing a specific type value, may be allocated dynamically.
return memcmp(v1->data, v2->data, bitmap_size)
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.
API for (user) types plugins.
LIBYANG_API_DECL LY_ERR lyplg_type_validate_range(LY_DATA_TYPE basetype, struct lysc_range *range, int64_t value, const char *strval, uint32_t strval_len, struct ly_err_item **err)
Data type validator for a range/length-restricted values.
Special lyd_value structure for built-in binary values.
#define LYPLG_TYPE_STORE_ONLY