29 #include "plugins_internal.h"
43 static const char b64_etable[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
58 binary_base64_encode(
const struct ly_ctx *ctx,
const char *data,
size_t size,
char **str,
size_t *str_len)
63 *str_len = (size + 2) / 3 * 4;
64 *str = malloc(*str_len + 1);
72 for (i = 0; i < size - 2; i += 3) {
73 *ptr++ = b64_etable[(data[i] >> 2) & 0x3F];
74 *ptr++ = b64_etable[((data[i] & 0x3) << 4) | ((int)(data[i + 1] & 0xF0) >> 4)];
75 *ptr++ = b64_etable[((data[i + 1] & 0xF) << 2) | ((int)(data[i + 2] & 0xC0) >> 6)];
76 *ptr++ = b64_etable[data[i + 2] & 0x3F];
79 *ptr++ = b64_etable[(data[i] >> 2) & 0x3F];
80 if (i == (size - 1)) {
81 *ptr++ = b64_etable[((data[i] & 0x3) << 4)];
84 *ptr++ = b64_etable[((data[i] & 0x3) << 4) | ((int)(data[i + 1] & 0xF0) >> 4)];
85 *ptr++ = b64_etable[((data[i + 1] & 0xF) << 2)];
97 static const int b64_dtable[256] = {
98 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63, 52, 53, 54, 55,
101 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6,
102 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0,
103 0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
104 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
119 binary_base64_decode(
const char *value,
size_t value_len,
void **data,
size_t *size)
121 unsigned char *ptr = (
unsigned char *)value;
122 uint32_t pad_chars, octet_count;
125 if (!value_len || (ptr[value_len - 1] !=
'=')) {
127 }
else if (ptr[value_len - 2] ==
'=') {
133 octet_count = ((value_len + 3) / 4 - (pad_chars ? 1 : 0)) * 4;
134 *size = octet_count / 4 * 3 + pad_chars;
136 str = malloc(*size + 1);
140 for (uint32_t i = 0, j = 0; i < octet_count; i += 4) {
141 int n = b64_dtable[ptr[i]] << 18 | b64_dtable[ptr[i + 1]] << 12 | b64_dtable[ptr[i + 2]] << 6 | b64_dtable[ptr[i + 3]];
143 str[j++] = n >> 8 & 0xFF;
147 int n = b64_dtable[ptr[octet_count]] << 18 | b64_dtable[ptr[octet_count + 1]] << 12;
148 str[*size - pad_chars] = n >> 16;
150 if (pad_chars == 2) {
151 n |= b64_dtable[ptr[octet_count + 2]] << 6;
153 str[*size - pad_chars + 1] = n;
171 binary_base64_validate(
const char *value,
size_t value_len,
const struct lysc_type_bin *type,
struct ly_err_item **err)
177 while ((idx < value_len) &&
178 (((
'A' <= value[idx]) && (value[idx] <=
'Z')) ||
179 ((
'a' <= value[idx]) && (value[idx] <=
'z')) ||
180 ((
'0' <= value[idx]) && (value[idx] <=
'9')) ||
181 (
'+' == value[idx]) || (
'/' == value[idx]))) {
187 while ((idx + pad < value_len) && (pad < 2) && (value[idx + pad] ==
'=')) {
192 if (value_len != idx + pad) {
193 if (isprint(value[idx + pad])) {
207 const uint32_t octet_count = ((idx + pad) / 4) * 3 - pad;
216 uint32_t options,
LY_VALUE_FORMAT format,
void *UNUSED(prefix_data), uint32_t hints,
217 const struct lysc_node *UNUSED(ctx_node),
struct lyd_value *storage,
struct lys_glob_unres *UNUSED(unres),
225 memset(storage, 0,
sizeof *storage);
227 LY_CHECK_ERR_GOTO(!val, ret =
LY_EMEM, cleanup);
233 val->
data = (
void *)value;
234 options &= ~LYPLG_TYPE_STORE_DYNAMIC;
235 }
else if (value_len) {
236 val->
data = malloc(value_len);
237 LY_CHECK_ERR_GOTO(!val->
data, ret =
LY_EMEM, cleanup);
238 memcpy(val->
data, value, value_len);
240 val->
data = strdup(
"");
241 LY_CHECK_ERR_GOTO(!val->
data, ret =
LY_EMEM, cleanup);
245 val->
size = value_len;
253 LY_CHECK_GOTO(ret, cleanup);
257 ret = binary_base64_validate(value, value_len, type_bin, err);
258 LY_CHECK_GOTO(ret, cleanup);
262 ret = binary_base64_decode(value, value_len, &val->
data, &val->
size);
263 LY_CHECK_GOTO(ret, cleanup);
268 options &= ~LYPLG_TYPE_STORE_DYNAMIC;
269 LY_CHECK_GOTO(ret, cleanup);
272 LY_CHECK_GOTO(ret, cleanup);
276 if (options & LYPLG_TYPE_STORE_DYNAMIC) {
306 void *UNUSED(prefix_data),
ly_bool *dynamic,
size_t *value_len)
317 *value_len = val->
size;
325 if (binary_base64_encode(ctx, val->
data, val->
size, &ret, &ret_len)) {
341 *value_len = ret_len ? ret_len : strlen(value->
_canonical);
352 memset(dup, 0,
sizeof *dup);
355 LY_CHECK_GOTO(ret, error);
358 LY_CHECK_ERR_GOTO(!dup_val, ret =
LY_EMEM, error);
362 dup_val->
data = orig_val->
size ? malloc(orig_val->
size) : strdup(
"");
363 LY_CHECK_ERR_GOTO(!dup_val->
data, ret =
LY_EMEM, error);
401 .name = LY_TYPE_BINARY_STR,
403 .plugin.id =
"libyang 2 - binary, version 1",
405 .plugin.validate = NULL,
411 .plugin.lyb_data_len = -1,
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.
struct lysc_type * realtype
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.
uint8_t ly_bool
Type to indicate boolean value.
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 ...
#define LYPLG_TYPE_STORE_DYNAMIC
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...
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.
struct lysc_range * length
The main libyang public header.
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.
YANG data representation.
LY_ERR lyplg_type_compare_binary(const struct lyd_value *val1, const struct lyd_value *val2)
Implementation of lyplg_type_compare_clb for the built-in binary type.
Libyang full error structure.
#define LYD_VALUE_GET(value, type_val)
Get the value in format specific to the type.
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.
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.
struct lyplg_type_record plugins_binary[]
Plugin information for binray type implementation.
#define LYPLG_TYPE_VAL_INLINE_DESTROY(type_val)
Destroy a prepared value.
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.
LY_ERR
libyang's error codes returned by the libyang functions.
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.
API for (user) types plugins.
Special lyd_value structure for built-in binary values.
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.