Loading...
Searching...
No Matches
decimal64.c
Go to the documentation of this file.
#include "plugins_types.h"
#include <stdint.h>
#include <stdlib.h>
#include "libyang.h"
/* additional internal headers for some useful simple macros */
#include "compat.h"
#include "ly_common.h"
#include "plugins_internal.h" /* LY_TYPE_*_STR */
static LY_ERR lyplg_type_validate_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node), const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err);
static LY_ERR
decimal64_num2str(int64_t num, struct lysc_type_dec *type, char **str)
{
char *ret;
/* allocate the value */
ret = calloc(1, LY_NUMBER_MAXLEN);
LY_CHECK_RET(!ret, LY_EMEM);
if (num) {
int count = sprintf(ret, "%" PRId64 " ", num);
if (((num > 0) && ((count - 1) <= type->fraction_digits)) || ((count - 2) <= type->fraction_digits)) {
/* we have 0. value, print the value with the leading zeros
* (one for 0. and also keep the correct with of num according
* to fraction-digits value)
* for (num < 0) - extra character for '-' sign */
count = sprintf(ret, "%0*" PRId64 " ", (num > 0) ? (type->fraction_digits + 1) : (type->fraction_digits + 2), num);
}
for (uint8_t i = type->fraction_digits, j = 1; i > 0; i--) {
if (j && (i > 1) && (ret[count - 2] == '0')) {
/* we have trailing zero to skip */
ret[count - 1] = '\0';
} else {
j = 0;
ret[count - 1] = ret[count - 2];
}
count--;
}
ret[count - 1] = '.';
} else {
/* zero */
sprintf(ret, "0.0");
}
*str = ret;
return LY_SUCCESS;
}
LIBYANG_API_DEF LY_ERR
lyplg_type_store_decimal64(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 *UNUSED(prefix_data), uint32_t hints,
const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
struct ly_err_item **err)
{
struct lysc_type_dec *type_dec = (struct lysc_type_dec *)type;
LY_ERR ret = LY_SUCCESS;
int64_t num = 0;
char *canon;
/* init storage */
memset(storage, 0, sizeof *storage);
storage->realtype = type;
if (format == LY_VALUE_LYB) {
/* validation */
if (value_len != 8) {
ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid LYB decimal64 value size %zu (expected 8).",
value_len);
goto cleanup;
}
/* we have the decimal64 number, in host byte order */
memcpy(&num, value, value_len);
num = le64toh(num);
} else {
/* check hints */
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
LY_CHECK_GOTO(ret, cleanup);
/* parse decimal64 value */
ret = lyplg_type_parse_dec64(type_dec->fraction_digits, value, value_len, &num, err);
LY_CHECK_GOTO(ret, cleanup);
}
/* store value */
storage->dec64 = num;
/* we need canonical value for the range check */
if (format == LY_VALUE_CANON) {
/* store canonical value */
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
ret = lydict_insert_zc(ctx, (char *)value, &storage->_canonical);
options &= ~LYPLG_TYPE_STORE_DYNAMIC;
LY_CHECK_GOTO(ret, cleanup);
} else {
ret = lydict_insert(ctx, value, value_len, &storage->_canonical);
LY_CHECK_GOTO(ret, cleanup);
}
} else {
/* generate canonical value */
ret = decimal64_num2str(num, type_dec, &canon);
LY_CHECK_GOTO(ret, cleanup);
/* store it */
ret = lydict_insert_zc(ctx, canon, (const char **)&storage->_canonical);
LY_CHECK_GOTO(ret, cleanup);
}
if (!(options & LYPLG_TYPE_STORE_ONLY)) {
/* validate value */
ret = lyplg_type_validate_decimal64(ctx, type, NULL, NULL, storage, err);
LY_CHECK_GOTO(ret, cleanup);
}
cleanup:
if (options & LYPLG_TYPE_STORE_DYNAMIC) {
free((void *)value);
}
if (ret) {
lyplg_type_free_simple(ctx, storage);
}
return ret;
}
static LY_ERR
lyplg_type_validate_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lysc_type *type, const struct lyd_node *UNUSED(ctx_node),
const struct lyd_node *UNUSED(tree), struct lyd_value *storage, struct ly_err_item **err)
{
LY_ERR ret;
struct lysc_type_dec *type_dec = (struct lysc_type_dec *)type;
int64_t num;
LY_CHECK_ARG_RET(NULL, type, storage, err, LY_EINVAL);
*err = NULL;
num = storage->dec64;
if (type_dec->range) {
/* check range of the number */
ret = lyplg_type_validate_range(type->basetype, type_dec->range, num, storage->_canonical,
strlen(storage->_canonical), err);
LY_CHECK_RET(ret);
}
return LY_SUCCESS;
}
LIBYANG_API_DEF LY_ERR
lyplg_type_compare_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1,
const struct lyd_value *val2)
{
/* if type is the same, the fraction digits are, too */
if (val1->dec64 != val2->dec64) {
return LY_ENOT;
}
return LY_SUCCESS;
}
LIBYANG_API_DEF int
lyplg_type_sort_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2)
{
if (val1->dec64 > val2->dec64) {
return 1;
} else if (val1->dec64 < val2->dec64) {
return -1;
} else {
return 0;
}
}
LIBYANG_API_DEF const void *
lyplg_type_print_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format,
void *UNUSED(prefix_data), ly_bool *dynamic, size_t *value_len)
{
int64_t num = 0;
void *buf;
if (format == LY_VALUE_LYB) {
num = htole64(value->dec64);
if (num == value->dec64) {
/* values are equal, little-endian */
*dynamic = 0;
if (value_len) {
*value_len = sizeof value->dec64;
}
return &value->dec64;
} else {
/* values differ, big-endian */
buf = calloc(1, sizeof value->dec64);
LY_CHECK_RET(!buf, NULL);
*dynamic = 1;
if (value_len) {
*value_len = sizeof value->dec64;
}
memcpy(buf, &num, sizeof value->dec64);
return buf;
}
}
/* use the cached canonical value */
if (dynamic) {
*dynamic = 0;
}
if (value_len) {
*value_len = strlen(value->_canonical);
}
return value->_canonical;
}
const struct lyplg_type_record plugins_decimal64[] = {
{
.module = "",
.revision = NULL,
.name = LY_TYPE_DEC64_STR,
.plugin.id = "libyang 2 - decimal64, version 1",
.plugin.store = lyplg_type_store_decimal64,
.plugin.validate = lyplg_type_validate_decimal64,
.plugin.compare = lyplg_type_compare_decimal64,
.plugin.sort = lyplg_type_sort_decimal64,
.plugin.print = lyplg_type_print_decimal64,
.plugin.duplicate = lyplg_type_dup_simple,
.plugin.free = lyplg_type_free_simple,
.plugin.lyb_data_len = 8,
},
{0}
};
lyplg_type_print_decimal64
LIBYANG_API_DEF const void * lyplg_type_print_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format, void *UNUSED(prefix_data), ly_bool *dynamic, size_t *value_len)
Definition decimal64.c:211
lyplg_type_store_decimal64
LIBYANG_API_DEF LY_ERR lyplg_type_store_decimal64(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 *UNUSED(prefix_data), uint32_t hints, const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres), struct ly_err_item **err)
Definition decimal64.c:86
plugins_decimal64
const struct lyplg_type_record plugins_decimal64[]
Plugin information for decimal64 type implementation.
Definition decimal64.c:257
lyplg_type_sort_decimal64
LIBYANG_API_DEF int lyplg_type_sort_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2)
Definition decimal64.c:199
lyplg_type_compare_decimal64
LIBYANG_API_DEF LY_ERR lyplg_type_compare_decimal64(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *val1, const struct lyd_value *val2)
Definition decimal64.c:188
ly_ctx
libyang context handler.
lydict_insert
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...
lydict_insert_zc
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
LY_ERR
libyang's error codes returned by the libyang functions.
Definition log.h:237
LYVE_DATA
@ LYVE_DATA
Definition log.h:274
LY_EINVAL
@ LY_EINVAL
Definition log.h:241
LY_EMEM
@ LY_EMEM
Definition log.h:239
LY_ENOT
@ LY_ENOT
Definition log.h:251
LY_EVALID
@ LY_EVALID
Definition log.h:245
LY_SUCCESS
@ LY_SUCCESS
Definition log.h:238
ly_err_item
Libyang full error structure.
Definition log.h:282
lyplg_type_store_decimal64
LIBYANG_API_DECL LY_ERR lyplg_type_store_decimal64(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 decimal64 type.
lyplg_type_print_decimal64
LIBYANG_API_DECL const void * lyplg_type_print_decimal64(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 decimal64 type.
lyplg_type_compare_decimal64
LIBYANG_API_DECL LY_ERR lyplg_type_compare_decimal64(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 decimal64 type.
lyplg_type_sort_decimal64
LIBYANG_API_DEF int lyplg_type_sort_decimal64(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 decimal64 type.
lyplg_type_validate_range
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.
lyplg_type_check_hints
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.
ly_err_new
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_type_parse_dec64
LIBYANG_API_DECL LY_ERR lyplg_type_parse_dec64(uint8_t fraction_digits, const char *value, size_t value_len, int64_t *ret, struct ly_err_item **err)
Convert a string with a decimal64 value into libyang representation: ret = value * 10^fraction-digits...
lyplg_type_record
Definition plugins_types.h:635
lyplg_type_dup_simple
LIBYANG_API_DECL LY_ERR lyplg_type_dup_simple(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
Implementation of lyplg_type_dup_clb for a generic simple type.
lyplg_type_free_simple
LIBYANG_API_DECL void lyplg_type_free_simple(const struct ly_ctx *ctx, struct lyd_value *value)
Implementation of lyplg_type_free_clb for a generic simple type.
LYPLG_TYPE_STORE_DYNAMIC
#define LYPLG_TYPE_STORE_DYNAMIC
Definition plugins_types.h:471
LYPLG_TYPE_STORE_ONLY
#define LYPLG_TYPE_STORE_ONLY
Definition plugins_types.h:478
lysc_type_dec::range
struct lysc_range * range
Definition tree_schema.h:1310
lysc_type::basetype
LY_DATA_TYPE basetype
Definition tree_schema.h:1287
lysc_type_dec::fraction_digits
uint8_t fraction_digits
Definition tree_schema.h:1309
lysc_node
Compiled YANG data node.
Definition tree_schema.h:1421
lysc_type
Definition tree_schema.h:1283
lysc_type_dec
Definition tree_schema.h:1302
LY_VALUE_FORMAT
LY_VALUE_FORMAT
All kinds of supported value formats and prefix mappings to modules.
Definition tree.h:234
LY_VALUE_CANON
@ LY_VALUE_CANON
Definition tree.h:235
LY_VALUE_LYB
@ LY_VALUE_LYB
Definition tree.h:240
libyang.h
The main libyang public header.
ly_bool
uint8_t ly_bool
Type to indicate boolean value.
Definition log.h:35
plugins_types.h
API for (user) types plugins.
lyd_value::realtype
const struct lysc_type * realtype
Definition tree_data.h:571
lyd_value::_canonical
const char * _canonical
Definition tree_data.h:568
lyd_node
Generic structure for a data node.
Definition tree_data.h:795
lyd_value
YANG data representation.
Definition tree_data.h:567