28 #include "ly_common.h"
29 #include "plugins_internal.h"
43 static const char b64_etable[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
60 binary_base64_encode(
const struct ly_ctx *ctx,
const char *data,
size_t size,
char **str,
size_t *str_len)
65 *str_len = (size + 2) / 3 * 4;
66 *str = malloc(*str_len + 1);
74 for (i = 0; i + 2 < size; i += 3) {
75 *ptr++ = b64_etable[(data[i] >> 2) & 0x3F];
76 *ptr++ = b64_etable[((data[i] & 0x3) << 4) | ((
int)(data[i + 1] & 0xF0) >> 4)];
77 *ptr++ = b64_etable[((data[i + 1] & 0xF) << 2) | ((
int)(data[i + 2] & 0xC0) >> 6)];
78 *ptr++ = b64_etable[data[i + 2] & 0x3F];
81 *ptr++ = b64_etable[(data[i] >> 2) & 0x3F];
82 if (i == (size - 1)) {
83 *ptr++ = b64_etable[((data[i] & 0x3) << 4)];
86 *ptr++ = b64_etable[((data[i] & 0x3) << 4) | ((
int)(data[i + 1] & 0xF0) >> 4)];
87 *ptr++ = b64_etable[((data[i + 1] & 0xF) << 2)];
99 static const int b64_dtable[256] = {
100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63, 52, 53, 54, 55,
103 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6,
104 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0,
105 0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
106 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
121 binary_base64_decode(
const char *value,
size_t value_len,
void **data,
size_t *size)
123 unsigned char *ptr = (
unsigned char *)value;
124 uint32_t pad_chars, octet_count;
127 if (!value_len || (ptr[value_len - 1] !=
'=')) {
129 }
else if (ptr[value_len - 2] ==
'=') {
135 octet_count = ((value_len + 3) / 4 - (pad_chars ? 1 : 0)) * 4;
136 *size = octet_count / 4 * 3 + pad_chars;
138 str = malloc(*size + 1);
142 for (uint32_t i = 0, j = 0; i < octet_count; i += 4) {
143 int n = b64_dtable[ptr[i]] << 18 | b64_dtable[ptr[i + 1]] << 12 | b64_dtable[ptr[i + 2]] << 6 | b64_dtable[ptr[i + 3]];
146 str[j++] = n >> 8 & 0xFF;
150 int n = b64_dtable[ptr[octet_count]] << 18 | b64_dtable[ptr[octet_count + 1]] << 12;
152 str[*size - pad_chars] = n >> 16;
154 if (pad_chars == 2) {
155 n |= b64_dtable[ptr[octet_count + 2]] << 6;
157 str[*size - pad_chars + 1] = n;
174 binary_base64_validate(
const char *value,
size_t value_len,
struct ly_err_item **err)
180 while ((idx < value_len) &&
181 (((
'A' <= value[idx]) && (value[idx] <=
'Z')) ||
182 ((
'a' <= value[idx]) && (value[idx] <=
'z')) ||
183 ((
'0' <= value[idx]) && (value[idx] <=
'9')) ||
184 (
'+' == value[idx]) || (
'/' == value[idx]))) {
190 while ((idx + pad < value_len) && (pad < 2) && (value[idx + pad] ==
'=')) {
195 if (value_len != idx + pad) {
196 if (isprint(value[idx + pad])) {
221 binary_base64_newlines(
char **value,
size_t *value_len, uint32_t *options,
struct ly_err_item **err)
226 if ((*value_len < 65) || ((*value)[64] !=
'\n')) {
233 *value = strndup(*value, *value_len);
234 LY_CHECK_RET(!*value,
LY_EMEM);
241 if (val[64] !=
'\n') {
247 memmove(val + 64, val + 65, len - 64);
258 uint32_t options,
LY_VALUE_FORMAT format,
void *UNUSED(prefix_data), uint32_t hints,
259 const struct lysc_node *UNUSED(ctx_node),
struct lyd_value *storage,
struct lys_glob_unres *UNUSED(unres),
266 memset(storage, 0,
sizeof *storage);
268 LY_CHECK_ERR_GOTO(!val, ret =
LY_EMEM, cleanup);
273 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
274 val->
data = (
void *)value;
275 options &= ~LYPLG_TYPE_STORE_DYNAMIC;
276 }
else if (value_len) {
277 val->
data = malloc(value_len);
278 LY_CHECK_ERR_GOTO(!val->
data, ret =
LY_EMEM, cleanup);
279 memcpy(val->
data, value, value_len);
281 val->
data = strdup(
"");
282 LY_CHECK_ERR_GOTO(!val->
data, ret =
LY_EMEM, cleanup);
286 val->
size = value_len;
294 LY_CHECK_GOTO(ret, cleanup);
298 ret = binary_base64_newlines((
char **)&value, &value_len, &options, err);
299 LY_CHECK_GOTO(ret, cleanup);
302 ret = binary_base64_validate(value, value_len, err);
303 LY_CHECK_GOTO(ret, cleanup);
307 ret = binary_base64_decode(value, value_len, &val->
data, &val->
size);
308 LY_CHECK_GOTO(ret, cleanup);
311 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
313 options &= ~LYPLG_TYPE_STORE_DYNAMIC;
314 LY_CHECK_GOTO(ret, cleanup);
317 LY_CHECK_GOTO(ret, cleanup);
322 ret = lyplg_type_validate_binary(ctx, type, NULL, NULL, storage, err);
323 LY_CHECK_GOTO(ret, cleanup);
327 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
341 lyplg_type_validate_binary(
const struct ly_ctx *UNUSED(ctx),
const struct lysc_type *type,
const struct lyd_node *UNUSED(ctx_node),
349 LY_CHECK_ARG_RET(NULL, type, storage, err,
LY_EINVAL);
398 LIBYANG_API_DEF
const void *
400 void *UNUSED(prefix_data),
ly_bool *dynamic,
size_t *value_len)
411 *value_len = val->
size;
419 if (binary_base64_encode(ctx, val->
data, val->
size, &ret, &ret_len)) {
435 *value_len = ret_len ? ret_len : strlen(value->
_canonical);
446 memset(dup, 0,
sizeof *dup);
449 LY_CHECK_GOTO(ret, error);
452 LY_CHECK_ERR_GOTO(!dup_val, ret =
LY_EMEM, error);
456 dup_val->
data = orig_val->
size ? malloc(orig_val->
size) : strdup(
"");
457 LY_CHECK_ERR_GOTO(!dup_val->
data, ret =
LY_EMEM, error);
495 .name = LY_TYPE_BINARY_STR,
497 .plugin.id =
"libyang 2 - binary, version 1",
499 .plugin.validate = lyplg_type_validate_binary,
505 .plugin.lyb_data_len = -1,
struct lysc_type * realtype
memset(value->fixed_mem, 0, LYD_VALUE_FIXED_MEM_SIZE)
Generic structure for a data node.
uint8_t ly_bool
Type to indicate boolean value.
LIBYANG_API_DECL void lyplg_type_free_binary(const struct ly_ctx *ctx, struct lyd_value *value)
Implementation of lyplg_type_free_clb for the built-in binary type.
#define LYPLG_TYPE_STORE_DYNAMIC
LIBYANG_API_DECL LY_ERR lyplg_type_dup_binary(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
Implementation of lyplg_type_dup_clb for the built-in binary type.
LIBYANG_API_DECL LY_ERR lyplg_type_compare_binary(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
Implementation of lyplg_type_compare_clb for the built-in binary type.
LYPLG_TYPE_VAL_INLINE_DESTROY(val)
LIBYANG_API_DECL LY_ERR lyplg_type_store_binary(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 binary type.
struct lysc_range * length
The main libyang public header.
YANG data representation.
Libyang full error structure.
#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.
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 int lyplg_type_sort_binary(const struct ly_ctx *ctx, const struct lyd_value *val1, const struct lyd_value *val2)
Implementation of lyplg_type_sort_clb for the built-in binary type.
#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.
API for (user) types plugins.
LY_ERR
libyang's error codes returned by the libyang functions.
Special lyd_value structure for built-in binary values.
LIBYANG_API_DECL const void * lyplg_type_print_binary(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 binary type.
#define LYPLG_TYPE_STORE_ONLY
LIBYANG_API_DECL LY_ERR lyplg_type_validate_range(LY_DATA_TYPE basetype, struct lysc_range *range, int64_t value, const char *strval, size_t strval_len, struct ly_err_item **err)
Data type validator for a range/length-restricted values.