plugins types FEATURE fixed size values
Refs #1552
Signed-off-by: Christian Hopps <chopps@labn.net>
diff --git a/src/config.h.in b/src/config.h.in
index ab861bd..65c4934 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -15,6 +15,9 @@
#ifndef LY_CONFIG_H_
#define LY_CONFIG_H_
+/** size of fixed_mem in lyd_value, minimum is 8 (B) */
+#define LYD_VALUE_FIXED_MEM_SIZE @LYD_VALUE_SIZE@
+
/*
* Plugins
*/
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 3a1372f..ac23c24 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -301,7 +301,7 @@
lyplg_type_dup_simple(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
LY_CHECK_RET(lydict_insert(ctx, original->_canonical, strlen(original->_canonical), &dup->_canonical));
- dup->ptr = original->ptr;
+ memcpy(dup->fixed_mem, original->fixed_mem, sizeof dup->fixed_mem);
dup->realtype = original->realtype;
return LY_SUCCESS;
}
diff --git a/src/plugins_types.h b/src/plugins_types.h
index 43e567f..dc7ca13 100644
--- a/src/plugins_types.h
+++ b/src/plugins_types.h
@@ -18,6 +18,7 @@
#include <stddef.h>
#include <stdint.h>
+#include "config.h"
#include "log.h"
#include "plugins.h"
#include "tree.h"
@@ -170,6 +171,38 @@
const struct lyplg_type_record plugins_types__[]
/**
+ * @brief Check whether specific type value needs to be allocated dynamically.
+ *
+ * @param[in] type_val Pointer to specific type value storage.
+ */
+#define LYPLG_TYPE_VAL_IS_DYN(type_val) \
+ (sizeof *(type_val) > LYD_VALUE_FIXED_MEM_SIZE)
+
+/**
+ * @brief Prepare value memory for storing a specific type value, may be allocated dynamically.
+ *
+ * Must be called for values larger than 8 bytes.
+ * To be used in ::lyplg_type_store_clb.
+ *
+ * @param[in] storage Pointer to the value storage to use (struct ::lyd_value *).
+ * @param[in,out] type_val Pointer to specific type value structure.
+ */
+#define LYPLG_TYPE_VAL_INLINE_PREPARE(storage, type_val) \
+ (LYPLG_TYPE_VAL_IS_DYN(type_val) \
+ ? ((type_val) = ((storage)->dyn_mem = calloc(1, sizeof *(type_val)))) \
+ : ((type_val) = memset((storage)->fixed_mem, 0, sizeof *(type_val))))
+
+/**
+ * @brief Destroy a prepared value.
+ *
+ * Must be called for values prepared with ::LYPLG_TYPE_VAL_INLINE_PREPARE.
+ *
+ * @param[in] type_val Pointer to specific type value structure.
+ */
+#define LYPLG_TYPE_VAL_INLINE_DESTROY(type_val) \
+ do { if (LYPLG_TYPE_VAL_IS_DYN(type_val)) free(type_val); } while(0)
+
+/**
* @brief Create and fill error structure.
*
* Helper function for various plugin functions to generate error information structure.
diff --git a/src/plugins_types/binary.c b/src/plugins_types/binary.c
index aed2c35..7fe387b 100644
--- a/src/plugins_types/binary.c
+++ b/src/plugins_types/binary.c
@@ -215,19 +215,13 @@
struct lysc_type_bin *type_bin = (struct lysc_type_bin *)type;
struct lyd_value_binary *val;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(storage, val);
+ LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
+ storage->realtype = type;
if (format == LY_VALUE_LYB) {
- /* allocate the value */
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
-
- /* init storage */
- storage->_canonical = NULL;
- storage->bin = val;
- storage->realtype = type;
-
/* store value */
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
val->data = (void *)value;
@@ -255,15 +249,6 @@
LY_CHECK_GOTO(ret, cleanup);
}
- /* allocate the value */
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
-
- /* init storage */
- storage->_canonical = NULL;
- storage->bin = val;
- storage->realtype = type;
-
/* get the binary value */
ret = binary_base64_decode(value, value_len, &val->data, &val->size);
LY_CHECK_GOTO(ret, cleanup);
@@ -292,12 +277,15 @@
API LY_ERR
lyplg_type_compare_binary(const struct lyd_value *val1, const struct lyd_value *val2)
{
- struct lyd_value_binary *v1 = val1->bin, *v2 = val2->bin;
+ struct lyd_value_binary *v1, *v2;
if (val1->realtype != val2->realtype) {
return LY_ENOT;
}
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
if ((v1->size != v2->size) || memcmp(v1->data, v2->data, v1->size)) {
return LY_ENOT;
}
@@ -308,10 +296,12 @@
lyplg_type_print_binary(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
void *UNUSED(prefix_data), ly_bool *dynamic, size_t *value_len)
{
- struct lyd_value_binary *val = value->bin;
+ struct lyd_value_binary *val;
char *ret;
size_t ret_len = 0;
+ LYD_VALUE_GET(value, val);
+
if (format == LY_VALUE_LYB) {
*dynamic = 0;
if (value_len) {
@@ -348,27 +338,27 @@
lyplg_type_dup_binary(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
LY_ERR ret;
- struct lyd_value_binary *orig_val = original->bin, *dup_val;
+ struct lyd_value_binary *orig_val, *dup_val;
ret = lydict_insert(ctx, original->_canonical, ly_strlen(original->_canonical), &dup->_canonical);
LY_CHECK_RET(ret);
- dup_val = calloc(1, sizeof *dup_val);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(dup, dup_val);
if (!dup_val) {
lydict_remove(ctx, dup->_canonical);
return LY_EMEM;
}
+ LYD_VALUE_GET(original, orig_val);
dup_val->data = malloc(orig_val->size);
if (!dup_val->data) {
lydict_remove(ctx, dup->_canonical);
- free(dup_val);
+ LYPLG_TYPE_VAL_INLINE_DESTROY(dup_val);
return LY_EMEM;
}
memcpy(dup_val->data, orig_val->data, orig_val->size);
dup_val->size = orig_val->size;
- dup->bin = dup_val;
dup->realtype = original->realtype;
return LY_SUCCESS;
}
@@ -376,12 +366,13 @@
API void
lyplg_type_free_binary(const struct ly_ctx *ctx, struct lyd_value *value)
{
- struct lyd_value_binary *val = value->bin;
+ struct lyd_value_binary *val;
lydict_remove(ctx, value->_canonical);
+ LYD_VALUE_GET(value, val);
if (val) {
free(val->data);
- free(val);
+ LYPLG_TYPE_VAL_INLINE_DESTROY(val);
}
}
diff --git a/src/plugins_types/bits.c b/src/plugins_types/bits.c
index 481d71b..bd76e4d 100644
--- a/src/plugins_types/bits.c
+++ b/src/plugins_types/bits.c
@@ -297,8 +297,11 @@
struct lysc_type_bits *type_bits = (struct lysc_type_bits *)type;
struct lyd_value_bits *val;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(storage, val);
+ LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
+ storage->realtype = type;
if (format == LY_VALUE_LYB) {
/* validation */
@@ -308,15 +311,6 @@
goto cleanup;
}
- /* allocate the value */
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
-
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = val;
- storage->realtype = type;
-
/* store value (bitmap) */
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
val->bitmap = (char *)value;
@@ -339,15 +333,6 @@
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
- /* allocate the value */
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
-
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = val;
- storage->realtype = type;
-
/* allocate the bitmap */
val->bitmap = malloc(lyplg_type_bits_bitmap_size(type_bits));
LY_CHECK_ERR_GOTO(!val->bitmap, ret = LY_EMEM, cleanup);
@@ -387,13 +372,16 @@
API LY_ERR
lyplg_type_compare_bits(const struct lyd_value *val1, const struct lyd_value *val2)
{
- struct lyd_value_bits *v1 = val1->ptr, *v2 = val2->ptr;
+ struct lyd_value_bits *v1, *v2;
struct lysc_type_bits *type_bits = (struct lysc_type_bits *)val1->realtype;
if (val1->realtype != val2->realtype) {
return LY_ENOT;
}
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
if (memcmp(v1->bitmap, v2->bitmap, lyplg_type_bits_bitmap_size(type_bits))) {
return LY_ENOT;
}
@@ -405,9 +393,11 @@
void *UNUSED(prefix_data), ly_bool *dynamic, size_t *value_len)
{
struct lysc_type_bits *type_bits = (struct lysc_type_bits *)value->realtype;
- struct lyd_value_bits *val = value->ptr;
+ struct lyd_value_bits *val;
char *ret;
+ LYD_VALUE_GET(value, val);
+
if (format == LY_VALUE_LYB) {
*dynamic = 0;
if (value_len) {
@@ -446,7 +436,7 @@
LY_ERR ret;
struct lysc_type_bits *type_bits = (struct lysc_type_bits *)original->realtype;
LY_ARRAY_COUNT_TYPE u;
- struct lyd_value_bits *orig_val = original->ptr, *dup_val;
+ struct lyd_value_bits *orig_val, *dup_val;
memset(dup, 0, sizeof *dup);
@@ -455,9 +445,10 @@
LY_CHECK_GOTO(ret, error);
/* allocate value */
- dup_val = calloc(1, sizeof *dup_val);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(dup, dup_val);
LY_CHECK_ERR_GOTO(!dup_val, ret = LY_EMEM, error);
- dup->ptr = dup_val;
+
+ LYD_VALUE_GET(original, orig_val);
/* duplicate bitmap */
dup_val->bitmap = malloc(lyplg_type_bits_bitmap_size(type_bits));
@@ -471,7 +462,6 @@
dup_val->items[u] = orig_val->items[u];
}
- dup->ptr = dup_val;
dup->realtype = original->realtype;
return LY_SUCCESS;
@@ -483,13 +473,14 @@
API void
lyplg_type_free_bits(const struct ly_ctx *ctx, struct lyd_value *value)
{
- struct lyd_value_bits *val = value->ptr;
+ struct lyd_value_bits *val;
lydict_remove(ctx, value->_canonical);
+ LYD_VALUE_GET(value, val);
if (val) {
free(val->bitmap);
LY_ARRAY_FREE(val->items);
- free(val);
+ LYPLG_TYPE_VAL_INLINE_DESTROY(val);
}
}
diff --git a/src/plugins_types/boolean.c b/src/plugins_types/boolean.c
index 842832f..72358c2 100644
--- a/src/plugins_types/boolean.c
+++ b/src/plugins_types/boolean.c
@@ -44,6 +44,10 @@
LY_ERR ret = LY_SUCCESS;
int8_t i;
+ /* init storage */
+ memset(storage, 0, sizeof *storage);
+ storage->realtype = type;
+
if (format == LY_VALUE_LYB) {
/* validation */
if (value_len != 1) {
@@ -52,13 +56,9 @@
goto cleanup;
}
- /* cast the value */
+ /* store value */
i = *(int8_t *)value;
-
- /* init storage and set the value */
- storage->_canonical = NULL;
storage->boolean = i ? 1 : 0;
- storage->realtype = type;
/* store canonical value */
ret = lydict_insert(ctx, i ? "true" : "false", 0, &storage->_canonical);
@@ -72,7 +72,7 @@
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
- /* validate and get the value */
+ /* validate and store the value */
if ((value_len == ly_strlen_const("true")) && !strncmp(value, "true", ly_strlen_const("true"))) {
i = 1;
} else if ((value_len == ly_strlen_const("false")) && !strncmp(value, "false", ly_strlen_const("false"))) {
@@ -82,11 +82,7 @@
(char *)value);
goto cleanup;
}
-
- /* init storage and set the value */
- storage->_canonical = NULL;
storage->boolean = i;
- storage->realtype = type;
/* store canonical value, it always is */
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
diff --git a/src/plugins_types/date_and_time.c b/src/plugins_types/date_and_time.c
index 4554ae2..cbfb809 100644
--- a/src/plugins_types/date_and_time.c
+++ b/src/plugins_types/date_and_time.c
@@ -186,8 +186,11 @@
uint32_t i;
char c;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(storage, val);
+ LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
+ storage->realtype = type;
if (format == LY_VALUE_LYB) {
/* validation */
@@ -205,15 +208,6 @@
}
}
- /* allocate the value */
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
-
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = val;
- storage->realtype = type;
-
/* store timestamp */
memcpy(&val->time, value, sizeof val->time);
@@ -241,15 +235,6 @@
ret = lyplg_type_validate_patterns(type_dat->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
- /* allocate the value */
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
-
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = val;
- storage->realtype = type;
-
/* pattern validation succeeded, convert to UNIX time and fractions of second */
ret = dat_str2time(value, &val->time, &val->fractions_s);
LY_CHECK_GOTO(ret, cleanup);
@@ -283,12 +268,15 @@
static LY_ERR
lyplg_type_compare_date_and_time(const struct lyd_value *val1, const struct lyd_value *val2)
{
- struct lyd_value_date_and_time *v1 = val1->ptr, *v2 = val2->ptr;
+ struct lyd_value_date_and_time *v1, *v2;
if (val1->realtype != val2->realtype) {
return LY_ENOT;
}
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
/* compare timestamp */
if (v1->time != v2->time) {
return LY_ENOT;
@@ -309,9 +297,11 @@
lyplg_type_print_date_and_time(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
void *UNUSED(prefix_data), ly_bool *dynamic, size_t *value_len)
{
- struct lyd_value_date_and_time *val = value->ptr;
+ struct lyd_value_date_and_time *val;
char *ret;
+ LYD_VALUE_GET(value, val);
+
if (format == LY_VALUE_LYB) {
if (val->fractions_s) {
ret = malloc(8 + strlen(val->fractions_s));
@@ -364,7 +354,7 @@
lyplg_type_dup_date_and_time(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
LY_ERR ret;
- struct lyd_value_date_and_time *orig_val = original->ptr, *dup_val;
+ struct lyd_value_date_and_time *orig_val, *dup_val;
memset(dup, 0, sizeof *dup);
@@ -373,9 +363,10 @@
LY_CHECK_GOTO(ret, error);
/* allocate value */
- dup_val = calloc(1, sizeof *dup_val);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(dup, dup_val);
LY_CHECK_ERR_GOTO(!dup_val, ret = LY_EMEM, error);
- dup->ptr = dup_val;
+
+ LYD_VALUE_GET(original, orig_val);
/* copy timestamp */
dup_val->time = orig_val->time;
@@ -386,7 +377,6 @@
LY_CHECK_ERR_GOTO(!dup_val->fractions_s, ret = LY_EMEM, error);
}
- dup->ptr = dup_val;
dup->realtype = original->realtype;
return LY_SUCCESS;
@@ -401,12 +391,13 @@
static void
lyplg_type_free_date_and_time(const struct ly_ctx *ctx, struct lyd_value *value)
{
- struct lyd_value_date_and_time *val = value->ptr;
+ struct lyd_value_date_and_time *val;
lydict_remove(ctx, value->_canonical);
+ LYD_VALUE_GET(value, val);
if (val) {
free(val->fractions_s);
- free(val);
+ LYPLG_TYPE_VAL_INLINE_DESTROY(val);
}
}
diff --git a/src/plugins_types/decimal64.c b/src/plugins_types/decimal64.c
index 4df6bb9..7c8a6b9 100644
--- a/src/plugins_types/decimal64.c
+++ b/src/plugins_types/decimal64.c
@@ -93,8 +93,9 @@
int64_t num;
char *canon;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ storage->realtype = type;
if (format == LY_VALUE_LYB) {
/* validation */
@@ -116,12 +117,10 @@
LY_CHECK_GOTO(ret, cleanup);
}
- /* init storage */
- storage->_canonical = NULL;
+ /* store value */
storage->dec64 = num;
- storage->realtype = type;
- /* we need canonical value for hash */
+ /* we need canonical value for the range check */
if (format == LY_VALUE_CANON) {
/* store canonical value */
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
diff --git a/src/plugins_types/empty.c b/src/plugins_types/empty.c
index c7aa6db..3753923 100644
--- a/src/plugins_types/empty.c
+++ b/src/plugins_types/empty.c
@@ -42,8 +42,9 @@
{
LY_ERR ret = LY_SUCCESS;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ storage->realtype = type;
/* check hints */
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
@@ -55,11 +56,6 @@
goto cleanup;
}
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = NULL;
- storage->realtype = type;
-
/* store canonical value */
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
diff --git a/src/plugins_types/enumeration.c b/src/plugins_types/enumeration.c
index e233943..092bd57 100644
--- a/src/plugins_types/enumeration.c
+++ b/src/plugins_types/enumeration.c
@@ -45,8 +45,9 @@
LY_ARRAY_COUNT_TYPE u;
ly_bool found = 0;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ storage->realtype = type;
if (format == LY_VALUE_LYB) {
/* validation */
@@ -91,10 +92,8 @@
}
}
- /* init storage */
- storage->_canonical = NULL;
+ /* store value */
storage->enum_item = &type_enum->enums[u];
- storage->realtype = type;
/* store canonical value */
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
diff --git a/src/plugins_types/identityref.c b/src/plugins_types/identityref.c
index e06fce9..c8e655a 100644
--- a/src/plugins_types/identityref.c
+++ b/src/plugins_types/identityref.c
@@ -194,8 +194,9 @@
char *canon;
struct lysc_ident *ident;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ storage->realtype = type;
/* check hints */
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
@@ -222,10 +223,8 @@
ret = identityref_check_base(ident, type_ident, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
- /* init storage */
- storage->_canonical = NULL;
+ /* store value */
storage->ident = ident;
- storage->realtype = type;
/* store canonical value */
if (format == LY_VALUE_CANON) {
diff --git a/src/plugins_types/instanceid.c b/src/plugins_types/instanceid.c
index c8c52f5..7559f8e 100644
--- a/src/plugins_types/instanceid.c
+++ b/src/plugins_types/instanceid.c
@@ -154,8 +154,9 @@
struct ly_path *path;
char *canon;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ storage->realtype = type;
/* check hints */
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
@@ -166,10 +167,8 @@
unres, &path, err);
LY_CHECK_GOTO(ret, cleanup);
- /* init storage */
- storage->_canonical = NULL;
+ /* store value */
storage->target = path;
- storage->realtype = type;
/* store canonical value */
if (format == LY_VALUE_CANON) {
diff --git a/src/plugins_types/integer.c b/src/plugins_types/integer.c
index 451d3d9..2e63a4e 100644
--- a/src/plugins_types/integer.c
+++ b/src/plugins_types/integer.c
@@ -58,8 +58,9 @@
char *canon;
struct lysc_type_num *type_num = (struct lysc_type_num *)type;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ storage->realtype = type;
if (format == LY_VALUE_LYB) {
/* validation */
@@ -115,9 +116,7 @@
LY_CHECK_GOTO(ret, cleanup);
}
- /* init storage */
- storage->_canonical = NULL;
- /* matters for big-endian */
+ /* set the value, matters for big-endian */
switch (type->basetype) {
case LY_TYPE_INT8:
storage->int8 = num;
@@ -134,7 +133,6 @@
default:
break;
}
- storage->realtype = type;
if (format == LY_VALUE_CANON) {
/* store canonical value */
@@ -253,8 +251,9 @@
char *canon;
struct lysc_type_num *type_num = (struct lysc_type_num *)type;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ storage->realtype = type;
if (format == LY_VALUE_LYB) {
/* validation */
@@ -309,9 +308,7 @@
LY_CHECK_GOTO(ret, cleanup);
}
- /* init storage */
- storage->_canonical = NULL;
- /* matters for big-endian */
+ /* store value, matters for big-endian */
switch (type->basetype) {
case LY_TYPE_UINT8:
storage->uint8 = num;
@@ -328,7 +325,6 @@
default:
break;
}
- storage->realtype = type;
if (format == LY_VALUE_CANON) {
/* store canonical value */
diff --git a/src/plugins_types/ipv4_address.c b/src/plugins_types/ipv4_address.c
index ff7d752..96af2d2 100644
--- a/src/plugins_types/ipv4_address.c
+++ b/src/plugins_types/ipv4_address.c
@@ -135,8 +135,11 @@
struct lyd_value_ipv4_address *val;
size_t i;
- /* zero storage so we can always free it */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(storage, val);
+ LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
+ storage->realtype = type;
if (format == LY_VALUE_LYB) {
/* validation */
@@ -153,15 +156,6 @@
}
}
- /* allocate the value */
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
-
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = val;
- storage->realtype = type;
-
/* store IP address */
memcpy(&val->addr, value, sizeof val->addr);
@@ -192,15 +186,6 @@
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
- /* allocate the value */
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
-
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = val;
- storage->realtype = type;
-
/* get the network-byte order address */
ret = ipv4address_str2ip(value, value_len, options, ctx, &val->addr, &val->zone, err);
LY_CHECK_GOTO(ret, cleanup);
@@ -232,12 +217,15 @@
static LY_ERR
lyplg_type_compare_ipv4_address(const struct lyd_value *val1, const struct lyd_value *val2)
{
- struct lyd_value_ipv4_address *v1 = val1->ptr, *v2 = val2->ptr;
+ struct lyd_value_ipv4_address *v1, *v2;
if (val1->realtype != val2->realtype) {
return LY_ENOT;
}
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
/* zones are NULL or in the dictionary */
if (memcmp(&v1->addr, &v2->addr, sizeof v1->addr) || (v1->zone != v2->zone)) {
return LY_ENOT;
@@ -252,10 +240,12 @@
lyplg_type_print_ipv4_address(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
void *UNUSED(prefix_data), ly_bool *dynamic, size_t *value_len)
{
- struct lyd_value_ipv4_address *val = value->ptr;
+ struct lyd_value_ipv4_address *val;
size_t zone_len;
char *ret;
+ LYD_VALUE_GET(value, val);
+
if (format == LY_VALUE_LYB) {
if (!val->zone) {
/* address-only, const */
@@ -324,25 +314,26 @@
lyplg_type_dup_ipv4_address(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
LY_ERR ret;
- struct lyd_value_ipv4_address *orig_val = original->ptr, *dup_val;
+ struct lyd_value_ipv4_address *orig_val, *dup_val;
ret = lydict_insert(ctx, original->_canonical, ly_strlen(original->_canonical), &dup->_canonical);
LY_CHECK_RET(ret);
- dup_val = calloc(1, sizeof *dup_val);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(dup, dup_val);
if (!dup_val) {
lydict_remove(ctx, dup->_canonical);
return LY_EMEM;
}
+
+ LYD_VALUE_GET(original, orig_val);
memcpy(&dup_val->addr, &orig_val->addr, sizeof orig_val->addr);
ret = lydict_insert(ctx, orig_val->zone, 0, &dup_val->zone);
if (ret) {
lydict_remove(ctx, dup->_canonical);
- free(dup_val);
+ LYPLG_TYPE_VAL_INLINE_DESTROY(dup_val);
return ret;
}
- dup->ptr = dup_val;
dup->realtype = original->realtype;
return LY_SUCCESS;
}
@@ -353,12 +344,13 @@
static void
lyplg_type_free_ipv4_address(const struct ly_ctx *ctx, struct lyd_value *value)
{
- struct lyd_value_ipv4_address *val = value->ptr;
+ struct lyd_value_ipv4_address *val;
lydict_remove(ctx, value->_canonical);
+ LYD_VALUE_GET(value, val);
if (val) {
lydict_remove(ctx, val->zone);
- free(val);
+ LYPLG_TYPE_VAL_INLINE_DESTROY(val);
}
}
diff --git a/src/plugins_types/ipv4_address_no_zone.c b/src/plugins_types/ipv4_address_no_zone.c
index 94330e8..0c99351 100644
--- a/src/plugins_types/ipv4_address_no_zone.c
+++ b/src/plugins_types/ipv4_address_no_zone.c
@@ -61,9 +61,13 @@
{
LY_ERR ret = LY_SUCCESS;
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
+ struct lyd_value_ipv4_address_no_zone *val;
- /* zero storage so we can always free it */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(storage, val);
+ LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
+ storage->realtype = type;
if (format == LY_VALUE_LYB) {
/* validation */
@@ -73,13 +77,8 @@
goto cleanup;
}
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = NULL;
- storage->realtype = type;
-
- /* store IP address as uint32_t value */
- memcpy(&storage->uint32, value, 4);
+ /* store IP address */
+ memcpy(&val->addr, value, 4);
/* success */
goto cleanup;
@@ -100,11 +99,6 @@
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = NULL;
- storage->realtype = type;
-
/* we always need a dynamic value */
if (!(options & LYPLG_TYPE_STORE_DYNAMIC)) {
value = strndup(value, value_len);
@@ -114,7 +108,7 @@
}
/* get the network-byte order address */
- if (!inet_pton(AF_INET, value, &storage->uint32)) {
+ if (!inet_pton(AF_INET, value, &val->addr)) {
ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Failed to convert IPv4 address \"%s\".", (char *)value);
goto cleanup;
}
@@ -141,11 +135,16 @@
static LY_ERR
lyplg_type_compare_ipv4_address_no_zone(const struct lyd_value *val1, const struct lyd_value *val2)
{
+ struct lyd_value_ipv4_address_no_zone *v1, *v2;
+
if (val1->realtype != val2->realtype) {
return LY_ENOT;
}
- if (val1->uint32 != val2->uint32) {
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
+ if (memcmp(&v1->addr, &v2->addr, sizeof v1->addr)) {
return LY_ENOT;
}
return LY_SUCCESS;
@@ -158,14 +157,17 @@
lyplg_type_print_ipv4_address_no_zone(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
void *UNUSED(prefix_data), ly_bool *dynamic, size_t *value_len)
{
+ struct lyd_value_ipv4_address_no_zone *val;
char *ret;
+ LYD_VALUE_GET(value, val);
+
if (format == LY_VALUE_LYB) {
*dynamic = 0;
if (value_len) {
*value_len = 4;
}
- return &value->uint32;
+ return &val->addr;
}
/* generate canonical value if not already (loaded from LYB) */
@@ -174,7 +176,7 @@
LY_CHECK_RET(!ret, NULL);
/* get the address in string */
- if (!inet_ntop(AF_INET, &value->uint32, ret, INET_ADDRSTRLEN)) {
+ if (!inet_ntop(AF_INET, &val->addr, ret, INET_ADDRSTRLEN)) {
free(ret);
LOGERR(ctx, LY_EVALID, "Failed to get IPv4 address in string (%s).", strerror(errno));
return NULL;
diff --git a/src/plugins_types/ipv4_prefix.c b/src/plugins_types/ipv4_prefix.c
index 85dff33..2d66b00 100644
--- a/src/plugins_types/ipv4_prefix.c
+++ b/src/plugins_types/ipv4_prefix.c
@@ -125,8 +125,11 @@
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
struct lyd_value_ipv4_prefix *val;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(storage, val);
+ LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
+ storage->realtype = type;
if (format == LY_VALUE_LYB) {
/* validation */
@@ -141,20 +144,8 @@
goto cleanup;
}
- /* store/allocate value */
- if (options & LYPLG_TYPE_STORE_DYNAMIC) {
- val = (void *)value;
- options &= ~LYPLG_TYPE_STORE_DYNAMIC;
- } else {
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
- memcpy(val, value, value_len);
- }
-
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = val;
- storage->realtype = type;
+ /* store addr + prefix */
+ memcpy(val, value, value_len);
/* zero host */
ipv4prefix_zero_host(&val->addr, val->prefix);
@@ -178,15 +169,6 @@
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
- /* allocate the value */
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
-
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = val;
- storage->realtype = type;
-
/* get the mask in network-byte order */
ret = ipv4prefix_str2ip(value, value_len, &val->addr, &val->prefix, err);
LY_CHECK_GOTO(ret, cleanup);
@@ -223,12 +205,15 @@
static LY_ERR
lyplg_type_compare_ipv4_prefix(const struct lyd_value *val1, const struct lyd_value *val2)
{
- struct lyd_value_ipv4_prefix *v1 = val1->ptr, *v2 = val2->ptr;
+ struct lyd_value_ipv4_prefix *v1, *v2;
if (val1->realtype != val2->realtype) {
return LY_ENOT;
}
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
if (memcmp(v1, v2, sizeof *v1)) {
return LY_ENOT;
}
@@ -242,9 +227,11 @@
lyplg_type_print_ipv4_prefix(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
void *UNUSED(prefix_data), ly_bool *dynamic, size_t *value_len)
{
- struct lyd_value_ipv4_prefix *val = value->ptr;
+ struct lyd_value_ipv4_prefix *val;
char *ret;
+ LYD_VALUE_GET(value, val);
+
if (format == LY_VALUE_LYB) {
*dynamic = 0;
if (value_len) {
@@ -292,19 +279,20 @@
lyplg_type_dup_ipv4_prefix(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
LY_ERR ret;
- struct lyd_value_ipv4_prefix *orig_val = original->ptr, *dup_val;
+ struct lyd_value_ipv4_prefix *orig_val, *dup_val;
ret = lydict_insert(ctx, original->_canonical, ly_strlen(original->_canonical), &dup->_canonical);
LY_CHECK_RET(ret);
- dup_val = calloc(1, sizeof *dup_val);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(dup, dup_val);
if (!dup_val) {
lydict_remove(ctx, dup->_canonical);
return LY_EMEM;
}
+
+ LYD_VALUE_GET(original, orig_val);
memcpy(dup_val, orig_val, sizeof *orig_val);
- dup->ptr = dup_val;
dup->realtype = original->realtype;
return LY_SUCCESS;
}
@@ -315,8 +303,11 @@
static void
lyplg_type_free_ipv4_prefix(const struct ly_ctx *ctx, struct lyd_value *value)
{
+ struct lyd_value_ipv4_prefix *val;
+
lydict_remove(ctx, value->_canonical);
- free(value->ptr);
+ LYD_VALUE_GET(value, val);
+ LYPLG_TYPE_VAL_INLINE_DESTROY(val);
}
/**
diff --git a/src/plugins_types/ipv6_address.c b/src/plugins_types/ipv6_address.c
index 2b43d1d..39450f1f 100644
--- a/src/plugins_types/ipv6_address.c
+++ b/src/plugins_types/ipv6_address.c
@@ -135,8 +135,11 @@
struct lyd_value_ipv6_address *val;
size_t i;
- /* zero storage so we can always free it */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(storage, val);
+ LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
+ storage->realtype = type;
if (format == LY_VALUE_LYB) {
/* validation */
@@ -153,15 +156,6 @@
}
}
- /* allocate the value */
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
-
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = val;
- storage->realtype = type;
-
/* store IP address */
memcpy(&val->addr, value, sizeof val->addr);
@@ -192,15 +186,6 @@
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
- /* allocate the value */
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
-
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = val;
- storage->realtype = type;
-
/* get the network-byte order address */
ret = ipv6address_str2ip(value, value_len, options, ctx, &val->addr, &val->zone, err);
LY_CHECK_GOTO(ret, cleanup);
@@ -234,12 +219,15 @@
static LY_ERR
lyplg_type_compare_ipv6_address(const struct lyd_value *val1, const struct lyd_value *val2)
{
- struct lyd_value_ipv6_address *v1 = val1->ptr, *v2 = val2->ptr;
+ struct lyd_value_ipv6_address *v1, *v2;
if (val1->realtype != val2->realtype) {
return LY_ENOT;
}
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
/* zones are NULL or in the dictionary */
if (memcmp(&v1->addr, &v2->addr, sizeof v1->addr) || (v1->zone != v2->zone)) {
return LY_ENOT;
@@ -254,10 +242,12 @@
lyplg_type_print_ipv6_address(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
void *UNUSED(prefix_data), ly_bool *dynamic, size_t *value_len)
{
- struct lyd_value_ipv6_address *val = value->ptr;
+ struct lyd_value_ipv6_address *val;
size_t zone_len;
char *ret;
+ LYD_VALUE_GET(value, val);
+
if (format == LY_VALUE_LYB) {
if (!val->zone) {
/* address-only, const */
@@ -326,16 +316,18 @@
lyplg_type_dup_ipv6_address(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
LY_ERR ret;
- struct lyd_value_ipv6_address *orig_val = original->ptr, *dup_val;
+ struct lyd_value_ipv6_address *orig_val, *dup_val;
ret = lydict_insert(ctx, original->_canonical, ly_strlen(original->_canonical), &dup->_canonical);
LY_CHECK_RET(ret);
- dup_val = calloc(1, sizeof *dup_val);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(dup, dup_val);
if (!dup_val) {
lydict_remove(ctx, dup->_canonical);
return LY_EMEM;
}
+
+ LYD_VALUE_GET(original, orig_val);
memcpy(&dup_val->addr, &orig_val->addr, sizeof orig_val->addr);
ret = lydict_insert(ctx, orig_val->zone, 0, &dup_val->zone);
if (ret) {
@@ -344,7 +336,6 @@
return ret;
}
- dup->ptr = dup_val;
dup->realtype = original->realtype;
return LY_SUCCESS;
}
@@ -355,12 +346,13 @@
static void
lyplg_type_free_ipv6_address(const struct ly_ctx *ctx, struct lyd_value *value)
{
- struct lyd_value_ipv6_address *val = value->ptr;
+ struct lyd_value_ipv6_address *val;
lydict_remove(ctx, value->_canonical);
+ LYD_VALUE_GET(value, val);
if (val) {
lydict_remove(ctx, val->zone);
- free(val);
+ LYPLG_TYPE_VAL_INLINE_DESTROY(val);
}
}
diff --git a/src/plugins_types/ipv6_address_no_zone.c b/src/plugins_types/ipv6_address_no_zone.c
index bead9ed..409f381 100644
--- a/src/plugins_types/ipv6_address_no_zone.c
+++ b/src/plugins_types/ipv6_address_no_zone.c
@@ -102,8 +102,9 @@
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
struct lyd_value_ipv6_address_no_zone *val;
- /* zero storage so we can always free it */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ storage->realtype = type;
if (format == LY_VALUE_LYB) {
/* validation */
@@ -113,20 +114,14 @@
goto cleanup;
}
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = NULL;
- storage->realtype = type;
-
- if (options & LYPLG_TYPE_STORE_DYNAMIC) {
+ if ((options & LYPLG_TYPE_STORE_DYNAMIC) && LYPLG_TYPE_VAL_IS_DYN(val)) {
/* use the value directly */
- storage->ptr = (void *)value;
+ storage->dyn_mem = (void *)value;
options &= ~LYPLG_TYPE_STORE_DYNAMIC;
} else {
- /* allocate the value */
- val = calloc(1, sizeof *val);
+ /* allocate value */
+ LYPLG_TYPE_VAL_INLINE_PREPARE(storage, val);
LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
- storage->ptr = val;
/* store IP address */
memcpy(&val->addr, value, sizeof val->addr);
@@ -136,6 +131,10 @@
goto cleanup;
}
+ /* allocate value */
+ LYPLG_TYPE_VAL_INLINE_PREPARE(storage, val);
+ LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
+
/* check hints */
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
@@ -151,15 +150,6 @@
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
- /* allocate the value */
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
-
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = val;
- storage->realtype = type;
-
/* get the network-byte order address */
ret = ipv6addressnozone_str2ip(value, value_len, options, &val->addr, err);
LY_CHECK_GOTO(ret, cleanup);
@@ -193,12 +183,15 @@
static LY_ERR
lyplg_type_compare_ipv6_address_no_zone(const struct lyd_value *val1, const struct lyd_value *val2)
{
- struct lyd_value_ipv6_address_no_zone *v1 = val1->ptr, *v2 = val2->ptr;
+ struct lyd_value_ipv6_address_no_zone *v1, *v2;
if (val1->realtype != val2->realtype) {
return LY_ENOT;
}
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
if (memcmp(&v1->addr, &v2->addr, sizeof v1->addr)) {
return LY_ENOT;
}
@@ -212,9 +205,11 @@
lyplg_type_print_ipv6_address_no_zone(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
void *UNUSED(prefix_data), ly_bool *dynamic, size_t *value_len)
{
- struct lyd_value_ipv6_address_no_zone *val = value->ptr;
+ struct lyd_value_ipv6_address_no_zone *val;
char *ret;
+ LYD_VALUE_GET(value, val);
+
if (format == LY_VALUE_LYB) {
*dynamic = 0;
if (value_len) {
@@ -260,19 +255,20 @@
lyplg_type_dup_ipv6_address_no_zone(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
LY_ERR ret;
- struct lyd_value_ipv6_address_no_zone *orig_val = original->ptr, *dup_val;
+ struct lyd_value_ipv6_address_no_zone *orig_val, *dup_val;
ret = lydict_insert(ctx, original->_canonical, ly_strlen(original->_canonical), &dup->_canonical);
LY_CHECK_RET(ret);
- dup_val = calloc(1, sizeof *dup_val);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(dup, dup_val);
if (!dup_val) {
lydict_remove(ctx, dup->_canonical);
return LY_EMEM;
}
+
+ LYD_VALUE_GET(original, orig_val);
memcpy(&dup_val->addr, &orig_val->addr, sizeof orig_val->addr);
- dup->ptr = dup_val;
dup->realtype = original->realtype;
return LY_SUCCESS;
}
@@ -283,10 +279,11 @@
static void
lyplg_type_free_ipv6_address_no_zone(const struct ly_ctx *ctx, struct lyd_value *value)
{
- struct lyd_value_ipv6_address *val = value->ptr;
+ struct lyd_value_ipv6_address_no_zone *val;
lydict_remove(ctx, value->_canonical);
- free(val);
+ LYD_VALUE_GET(value, val);
+ LYPLG_TYPE_VAL_INLINE_DESTROY(val);
}
/**
diff --git a/src/plugins_types/ipv6_prefix.c b/src/plugins_types/ipv6_prefix.c
index ce7767b..22fa2c6 100644
--- a/src/plugins_types/ipv6_prefix.c
+++ b/src/plugins_types/ipv6_prefix.c
@@ -127,8 +127,9 @@
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
struct lyd_value_ipv6_prefix *val;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ storage->realtype = type;
if (format == LY_VALUE_LYB) {
/* validation */
@@ -145,19 +146,15 @@
/* store/allocate value */
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
- val = (void *)value;
+ storage->dyn_mem = (void *)value;
options &= ~LYPLG_TYPE_STORE_DYNAMIC;
} else {
- val = calloc(1, sizeof *val);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(storage, val);
LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
+
memcpy(val, value, value_len);
}
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = val;
- storage->realtype = type;
-
/* zero host */
ipv6prefix_zero_host(&val->addr, val->prefix);
@@ -165,6 +162,10 @@
goto cleanup;
}
+ /* allocate value */
+ LYPLG_TYPE_VAL_INLINE_PREPARE(storage, val);
+ LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
+
/* check hints */
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
@@ -180,15 +181,6 @@
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
- /* allocate the value */
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
-
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = val;
- storage->realtype = type;
-
/* get the mask in network-byte order */
ret = ipv6prefix_str2ip(value, value_len, &val->addr, &val->prefix, err);
LY_CHECK_GOTO(ret, cleanup);
@@ -225,12 +217,15 @@
static LY_ERR
lyplg_type_compare_ipv6_prefix(const struct lyd_value *val1, const struct lyd_value *val2)
{
- struct lyd_value_ipv6_prefix *v1 = val1->ptr, *v2 = val2->ptr;
+ struct lyd_value_ipv6_prefix *v1, *v2;
if (val1->realtype != val2->realtype) {
return LY_ENOT;
}
+ LYD_VALUE_GET(val1, v1);
+ LYD_VALUE_GET(val2, v2);
+
if (memcmp(v1, v2, sizeof *v1)) {
return LY_ENOT;
}
@@ -244,9 +239,11 @@
lyplg_type_print_ipv6_prefix(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
void *UNUSED(prefix_data), ly_bool *dynamic, size_t *value_len)
{
- struct lyd_value_ipv6_prefix *val = value->ptr;
+ struct lyd_value_ipv6_prefix *val;
char *ret;
+ LYD_VALUE_GET(value, val);
+
if (format == LY_VALUE_LYB) {
*dynamic = 0;
if (value_len) {
@@ -294,19 +291,20 @@
lyplg_type_dup_ipv6_prefix(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
LY_ERR ret;
- struct lyd_value_ipv6_prefix *orig_val = original->ptr, *dup_val;
+ struct lyd_value_ipv6_prefix *orig_val, *dup_val;
ret = lydict_insert(ctx, original->_canonical, ly_strlen(original->_canonical), &dup->_canonical);
LY_CHECK_RET(ret);
- dup_val = calloc(1, sizeof *dup_val);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(dup, dup_val);
if (!dup_val) {
lydict_remove(ctx, dup->_canonical);
return LY_EMEM;
}
+
+ LYD_VALUE_GET(original, orig_val);
memcpy(dup_val, orig_val, sizeof *orig_val);
- dup->ptr = dup_val;
dup->realtype = original->realtype;
return LY_SUCCESS;
}
@@ -317,8 +315,11 @@
static void
lyplg_type_free_ipv6_prefix(const struct ly_ctx *ctx, struct lyd_value *value)
{
+ struct lyd_value_ipv6_prefix *val;
+
lydict_remove(ctx, value->_canonical);
- free(value->ptr);
+ LYD_VALUE_GET(value, val);
+ LYPLG_TYPE_VAL_INLINE_DESTROY(val);
}
/**
diff --git a/src/plugins_types/string.c b/src/plugins_types/string.c
index 0083da7..eede579 100644
--- a/src/plugins_types/string.c
+++ b/src/plugins_types/string.c
@@ -43,8 +43,9 @@
LY_ERR ret = LY_SUCCESS;
struct lysc_type_str *type_str = (struct lysc_type_str *)type;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ storage->realtype = type;
/* check hints */
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
@@ -61,11 +62,6 @@
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = NULL;
- storage->realtype = type;
-
/* store canonical value */
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
diff --git a/src/plugins_types/union.c b/src/plugins_types/union.c
index 6bfb6df..cda1e1a 100644
--- a/src/plugins_types/union.c
+++ b/src/plugins_types/union.c
@@ -144,13 +144,16 @@
{
LY_ERR ret = LY_SUCCESS;
struct lysc_type_union *type_u = (struct lysc_type_union *)type;
- struct lyd_value_union *subvalue = NULL;
+ struct lyd_value_union *subvalue;
uint32_t type_idx;
*err = NULL;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(storage, subvalue);
+ LY_CHECK_ERR_GOTO(!subvalue, ret = LY_EMEM, cleanup);
+ storage->realtype = type;
if (format == LY_VALUE_LYB) {
/* basic validation */
@@ -167,18 +170,6 @@
}
}
- /* prepare subvalue */
- subvalue = calloc(1, sizeof *subvalue);
- if (!subvalue) {
- ret = ly_err_new(err, LY_EMEM, 0, NULL, NULL, LY_EMEM_MSG);
- goto cleanup;
- }
-
- /* init storage */
- storage->_canonical = NULL;
- storage->subvalue = subvalue;
- storage->realtype = type;
-
/* remember the original value */
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
subvalue->original = (void *)value;
@@ -339,9 +330,10 @@
API void
lyplg_type_free_union(const struct ly_ctx *ctx, struct lyd_value *value)
{
- struct lyd_value_union *val = value->subvalue;
+ struct lyd_value_union *val;
lydict_remove(ctx, value->_canonical);
+ LYD_VALUE_GET(value, val);
if (val) {
if (val->value.realtype) {
val->value.realtype->plugin->free(ctx, &val->value);
@@ -349,7 +341,7 @@
lyplg_type_prefix_data_free(val->format, val->prefix_data);
free(val->original);
- free(val);
+ LYPLG_TYPE_VAL_INLINE_DESTROY(val);
}
}
diff --git a/src/plugins_types/xpath1.0.c b/src/plugins_types/xpath1.0.c
index a743dd0..29059ba 100644
--- a/src/plugins_types/xpath1.0.c
+++ b/src/plugins_types/xpath1.0.c
@@ -43,8 +43,8 @@
struct lyd_value_xpath10 {
struct lyxp_expr *exp;
const struct ly_ctx *ctx;
- LY_VALUE_FORMAT format;
void *prefix_data;
+ LY_VALUE_FORMAT format;
};
/**
@@ -216,8 +216,11 @@
struct lyd_value_xpath10 *val;
char *canon;
- /* clear storage */
+ /* init storage */
memset(storage, 0, sizeof *storage);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(storage, val);
+ LY_CHECK_ERR_GOTO(!val, ret = LY_EMEM, cleanup);
+ storage->realtype = type;
/* check hints */
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
@@ -234,16 +237,6 @@
ret = lyplg_type_validate_patterns(type_str->patterns, value, value_len, err);
LY_CHECK_GOTO(ret, cleanup);
- /* init storage */
- storage->_canonical = NULL;
- storage->ptr = NULL;
- storage->realtype = type;
-
- /* allocate value */
- val = calloc(1, sizeof *val);
- LY_CHECK_ERR_GOTO(!val, LOGMEM(ctx); ret = LY_EMEM, cleanup);
- storage->ptr = val;
-
/* store format-specific data and context for later prefix resolution */
ret = lyplg_type_prefix_data_new(ctx, value, value_len, format, prefix_data, &val->format, &val->prefix_data);
LY_CHECK_GOTO(ret, cleanup);
@@ -287,9 +280,12 @@
lyplg_type_print_xpath10(const struct ly_ctx *ctx, const struct lyd_value *value, LY_VALUE_FORMAT format,
void *prefix_data, ly_bool *dynamic, size_t *value_len)
{
+ struct lyd_value_xpath10 *val;
char *ret;
struct ly_err_item *err = NULL;
+ LYD_VALUE_GET(value, val);
+
if ((format == LY_VALUE_CANON) || (format == LY_VALUE_JSON) || (format == LY_VALUE_LYB)) {
/* canonical */
if (dynamic) {
@@ -302,7 +298,7 @@
}
/* print in the specific format */
- if (xpath10_print_value(value->ptr, format, prefix_data, &ret, &err)) {
+ if (xpath10_print_value(val, format, prefix_data, &ret, &err)) {
if (err) {
LOGVAL_ERRITEM(ctx, err);
ly_err_free(err);
@@ -321,7 +317,7 @@
lyplg_type_dup_xpath10(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
{
LY_ERR ret = LY_SUCCESS;
- struct lyd_value_xpath10 *orig_val = original->ptr, *dup_val;
+ struct lyd_value_xpath10 *orig_val, *dup_val;
/* init dup value */
memset(dup, 0, sizeof *dup);
@@ -330,17 +326,17 @@
ret = lydict_insert(ctx, original->_canonical, ly_strlen(original->_canonical), &dup->_canonical);
LY_CHECK_GOTO(ret, cleanup);
- dup_val = calloc(1, sizeof *dup_val);
+ LYPLG_TYPE_VAL_INLINE_PREPARE(dup, dup_val);
LY_CHECK_ERR_GOTO(!dup_val, LOGMEM(ctx); ret = LY_EMEM, cleanup);
dup_val->ctx = ctx;
- dup->ptr = dup_val;
+ LYD_VALUE_GET(original, orig_val);
ret = lyxp_expr_dup(ctx, orig_val->exp, &dup_val->exp);
LY_CHECK_GOTO(ret, cleanup);
- dup_val->format = orig_val->format;
ret = lyplg_type_prefix_data_dup(ctx, orig_val->format, orig_val->prefix_data, &dup_val->prefix_data);
LY_CHECK_GOTO(ret, cleanup);
+ dup_val->format = orig_val->format;
cleanup:
if (ret) {
@@ -352,14 +348,15 @@
API void
lyplg_type_free_xpath10(const struct ly_ctx *ctx, struct lyd_value *value)
{
- struct lyd_value_xpath10 *val = value->ptr;
+ struct lyd_value_xpath10 *val;
lydict_remove(ctx, value->_canonical);
+ LYD_VALUE_GET(value, val);
if (val) {
lyxp_expr_free(ctx, val->exp);
lyplg_type_prefix_data_free(val->format, val->prefix_data);
- free(val);
+ LYPLG_TYPE_VAL_INLINE_DESTROY(val);
}
}
diff --git a/src/tree_data.h b/src/tree_data.h
index 1fcc38a..0e8ac71 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -18,6 +18,7 @@
#include <stddef.h>
#include <stdint.h>
+#include "config.h"
#include "log.h"
#include "tree.h"
#include "tree_schema.h"
@@ -522,6 +523,13 @@
const char *_canonical; /**< Should never be accessed directly, instead ::lyd_get_value() and ::lyd_get_meta_value()
should be used. Serves as a cache for the canonical value or the JSON
representation if no canonical value is defined. */
+ const struct lysc_type *realtype; /**< pointer to the real type of the data stored in the value structure. This type can differ from the type
+ in the schema node of the data node since the type's store plugin can use other types/plugins for
+ storing data. Speaking about built-in types, this is the case of leafref which stores data as its
+ target type. In contrast, union type also uses its subtype's callbacks, but inside an internal data
+ stored in subvalue member of ::lyd_value structure, so here is the pointer to the union type.
+ In general, this type is used to get free callback for this lyd_value structure, so it must reflect
+ the type used to store data directly in the same lyd_value instance. */
union {
int8_t boolean; /**< 0 as false, 1 as true */
@@ -535,25 +543,30 @@
uint32_t uint32; /**< 32-bit unsigned integer */
uint64_t uint64; /**< 64-bit unsigned integer */
struct lysc_type_bitenum_item *enum_item; /**< pointer to the definition of the enumeration value */
- struct lyd_value_bits *bits; /**< bits value */
struct lysc_ident *ident; /**< pointer to the schema definition of the identityref value */
struct ly_path *target; /**< Instance-identifier target path. */
struct lyd_value_union *subvalue; /** Union value with some metadata. */
- struct lyd_value_binary *bin; /** Binary value */
- void *ptr; /**< generic data type structure used to store the data */
+
+ void *dyn_mem; /**< pointer to generic data type value stored in dynamic memory */
+ uint8_t fixed_mem[LYD_VALUE_FIXED_MEM_SIZE]; /**< fixed-size buffer for a generic data type value */
}; /**< The union is just a list of shorthands to possible values stored by a type's plugin. libyang itself uses the ::lyd_value.realtype
plugin's callbacks to work with the data.*/
-
- const struct lysc_type *realtype; /**< pointer to the real type of the data stored in the value structure. This type can differ from the type
- in the schema node of the data node since the type's store plugin can use other types/plugins for
- storing data. Speaking about built-in types, this is the case of leafref which stores data as its
- target type. In contrast, union type also uses its subtype's callbacks, but inside an internal data
- stored in subvalue member of ::lyd_value structure, so here is the pointer to the union type.
- In general, this type is used to get free callback for this lyd_value structure, so it must reflect
- the type used to store data directly in the same lyd_value instance. */
};
/**
+ * @brief Get the value in format specific to the type.
+ *
+ * Should be used for any types that do not have their specific representation in the ::lyd_value union.
+ *
+ * @param[in] value Pointer to the value structure to read from (struct ::lyd_value *).
+ * @param[out] type_val Pointer to the type-specific value structure.
+ */
+#define LYD_VALUE_GET(value, type_val) \
+ ((sizeof *(type_val) > LYD_VALUE_FIXED_MEM_SIZE) \
+ ? ((type_val) = (((value)->dyn_mem))) \
+ : ((type_val) = ((void *)((value)->fixed_mem))))
+
+/**
* @brief Special lyd_value structure for union.
*
* Represents data with multiple types (union). The ::lyd_value_union.value contains representation according to