28#include "plugins_internal.h"
42static const char b64_etable[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
44static void lyplg_type_free_binary(
const struct ly_ctx *ctx,
struct lyd_value *value);
61binary_base64_encode(
const struct ly_ctx *ctx,
const char *data, uint32_t size,
char **str, uint32_t *str_len)
66 *str_len = (size + 2) / 3 * 4;
67 *str = malloc(*str_len + 1);
68 LY_CHECK_ERR_RET(!*str, LOGMEM(ctx),
LY_EMEM);
75 for (i = 0; i + 2 < size; i += 3) {
76 *ptr++ = b64_etable[(data[i] >> 2) & 0x3F];
77 *ptr++ = b64_etable[((data[i] & 0x3) << 4) | ((int)(data[i + 1] & 0xF0) >> 4)];
78 *ptr++ = b64_etable[((data[i + 1] & 0xF) << 2) | ((int)(data[i + 2] & 0xC0) >> 6)];
79 *ptr++ = b64_etable[data[i + 2] & 0x3F];
82 *ptr++ = b64_etable[(data[i] >> 2) & 0x3F];
83 if (i == (size - 1)) {
84 *ptr++ = b64_etable[((data[i] & 0x3) << 4)];
87 *ptr++ = b64_etable[((data[i] & 0x3) << 4) | ((int)(data[i + 1] & 0xF0) >> 4)];
88 *ptr++ = b64_etable[((data[i + 1] & 0xF) << 2)];
100static const int b64_dtable[256] = {
101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63, 52, 53, 54, 55,
104 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6,
105 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0,
106 0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
107 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
122binary_base64_decode(
const char *value, uint32_t value_size,
void **data, uint32_t *size)
124 unsigned char *ptr = (
unsigned char *)value;
125 uint32_t pad_chars, octet_count;
128 if (!value_size || (ptr[value_size - 1] !=
'=')) {
130 }
else if (ptr[value_size - 2] ==
'=') {
136 octet_count = ((value_size + 3) / 4 - (pad_chars ? 1 : 0)) * 4;
137 *size = octet_count / 4 * 3 + pad_chars;
139 str = malloc(*size + 1);
143 for (uint32_t i = 0, j = 0; i < octet_count; i += 4) {
144 int n = b64_dtable[ptr[i]] << 18 | b64_dtable[ptr[i + 1]] << 12 | b64_dtable[ptr[i + 2]] << 6 | b64_dtable[ptr[i + 3]];
147 str[j++] = n >> 8 & 0xFF;
151 int n = b64_dtable[ptr[octet_count]] << 18 | b64_dtable[ptr[octet_count + 1]] << 12;
153 str[*size - pad_chars] = n >> 16;
155 if (pad_chars == 2) {
156 n |= b64_dtable[ptr[octet_count + 2]] << 6;
158 str[*size - pad_chars + 1] = n;
175binary_base64_validate(
const char *value, uint32_t value_size,
struct ly_err_item **err)
181 while ((idx < value_size) &&
182 (((
'A' <= value[idx]) && (value[idx] <=
'Z')) ||
183 ((
'a' <= value[idx]) && (value[idx] <=
'z')) ||
184 ((
'0' <= value[idx]) && (value[idx] <=
'9')) ||
185 (
'+' == value[idx]) || (
'/' == value[idx]))) {
191 while ((idx + pad < value_size) && (pad < 2) && (value[idx + pad] ==
'=')) {
196 if (value_size != idx + pad) {
197 if (isprint(value[idx + pad])) {
204 if (value_size & 3) {
222binary_base64_newlines(
char **value, uint32_t *value_size, uint32_t *options,
struct ly_err_item **err)
227 if ((*value_size < 65) || ((*value)[64] !=
'\n')) {
234 *value = strndup(*value, *value_size);
235 LY_CHECK_RET(!*value,
LY_EMEM);
242 if (val[64] !=
'\n') {
248 memmove(val + 64, val + 65, size - 64);
258lyplg_type_store_binary(
const struct ly_ctx *ctx,
const struct lysc_type *type,
const void *value, uint64_t value_size_bits,
259 uint32_t options,
LY_VALUE_FORMAT format,
void *UNUSED(prefix_data), uint32_t hints,
260 const struct lysc_node *UNUSED(ctx_node),
struct lyd_value *storage,
struct lys_glob_unres *UNUSED(unres),
268 memset(storage, 0,
sizeof *storage);
270 LY_CHECK_ERR_GOTO(!val, ret =
LY_EMEM, cleanup);
276 LY_CHECK_GOTO(ret, cleanup);
281 val->
data = (
void *)value;
282 options &= ~LYPLG_TYPE_STORE_DYNAMIC;
283 }
else if (value_size) {
284 val->
data = malloc(value_size);
285 LY_CHECK_ERR_GOTO(!val->
data, ret =
LY_EMEM, cleanup);
286 memcpy(val->
data, value, value_size);
288 val->
data = strdup(
"");
289 LY_CHECK_ERR_GOTO(!val->
data, ret =
LY_EMEM, cleanup);
293 val->
size = value_size;
301 LY_CHECK_GOTO(ret, cleanup);
305 ret = binary_base64_newlines((
char **)&value, &value_size, &options, err);
306 LY_CHECK_GOTO(ret, cleanup);
309 ret = binary_base64_validate(value, value_size, err);
310 LY_CHECK_GOTO(ret, cleanup);
314 ret = binary_base64_decode(value, value_size, &val->
data, &val->
size);
315 LY_CHECK_GOTO(ret, cleanup);
320 options &= ~LYPLG_TYPE_STORE_DYNAMIC;
321 LY_CHECK_GOTO(ret, cleanup);
326 ret =
lydict_insert(ctx, value_size ? value :
"", value_size, &storage->_canonical);
327 LY_CHECK_GOTO(ret, cleanup);
332 ret = lyplg_type_validate_value_binary(ctx, type, storage, err);
333 LY_CHECK_GOTO(ret, cleanup);
342 lyplg_type_free_binary(ctx, storage);
359 LY_CHECK_ARG_RET(NULL, type, storage, err,
LY_EINVAL);
363 value_len = strlen(value);
375lyplg_type_compare_binary(
const struct ly_ctx *UNUSED(ctx),
const struct lyd_value *val1,
const struct lyd_value *val2)
410 void *UNUSED(prefix_data),
ly_bool *dynamic, uint64_t *value_size_bits)
414 uint32_t ret_size = 0;
420 if (value_size_bits) {
421 *value_size_bits = (uint64_t)val->
size * 8;
429 if (binary_base64_encode(ctx, val->
data, val->
size, &ret, &ret_size)) {
444 if (value_size_bits) {
445 *value_size_bits = ret_size ? ret_size * 8 : strlen(value->
_canonical) * 8;
456 memset(dup, 0,
sizeof *dup);
459 LY_CHECK_GOTO(ret, error);
462 LY_CHECK_ERR_GOTO(!dup_val, ret =
LY_EMEM, error);
466 dup_val->
data = orig_val->
size ? malloc(orig_val->
size) : strdup(
"");
467 LY_CHECK_ERR_GOTO(!dup_val->
data, ret =
LY_EMEM, error);
476 lyplg_type_free_binary(ctx, dup);
481lyplg_type_free_binary(
const struct ly_ctx *ctx,
struct lyd_value *value)
505 .name = LY_TYPE_BINARY_STR,
507 .plugin.id =
"ly2 binary",
509 .plugin.store = lyplg_type_store_binary,
510 .plugin.validate_value = lyplg_type_validate_value_binary,
511 .plugin.validate_tree = NULL,
512 .plugin.compare = lyplg_type_compare_binary,
513 .plugin.sort = lyplg_type_sort_binary,
514 .plugin.print = lyplg_type_print_binary,
515 .plugin.duplicate = lyplg_type_dup_binary,
516 .plugin.free = lyplg_type_free_binary,
const struct lyplg_type_record plugins_binary[]
Plugin information for binray type implementation.
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_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_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.
Libyang full error structure.
const char *const char * revision
#define LYPLG_TYPE_VAL_INLINE_PREPARE(storage, type_val)
Prepare value memory for storing a specific type value, may be allocated dynamically.
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.
#define LYPLG_TYPE_VAL_INLINE_DESTROY(type_val)
Destroy a prepared value.
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.
LIBYANG_API_DECL LY_ERR lyplg_type_check_value_size(const char *type_name, LY_VALUE_FORMAT format, uint64_t value_size_bits, enum lyplg_lyb_size_type lyb_size_type, uint64_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.
#define LYPLG_TYPE_VAL_IS_DYN(type_val)
Check whether specific type value needs to be allocated dynamically.
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_VARIABLE_BYTES
LIBYANG_API_DECL void lyplg_type_lyb_size_variable_bytes(const struct lysc_type *type, enum lyplg_lyb_size_type *size_type, uint64_t *fixed_size_bits)
Implementation of lyplg_type_lyb_size_clb for a type with variable length rounded to bytes.
#define LYPLG_TYPE_STORE_DYNAMIC
#define LYPLG_TYPE_STORE_ONLY
struct lysc_range * length
uint8_t ly_bool
Type to indicate boolean value.
API for (user) types plugins.
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.
const struct lysc_type * realtype
#define LYD_VALUE_GET(value, type_val)
Get the value in format specific to the type.
YANG data representation.
Special lyd_value structure for built-in binary values.
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.