From: Vladimir Davydov <vdavydov.dev@gmail.com>
To: Serge Petrenko <sergepetrenko@tarantool.org>
Cc: georgy@tarantool.org, tarantool-patches@freelists.org,
kostja@tarantool.org
Subject: Re: [PATCH v3 4/4] decimal: add MessagePack encoding/decoding support
Date: Wed, 5 Jun 2019 15:40:14 +0300 [thread overview]
Message-ID: <20190605124014.vylxrh6nfgoki2g4@esperanza> (raw)
In-Reply-To: <eecbfaa3676f0e63200e53bb5be69341133f53b4.1559663794.git.sergepetrenko@tarantool.org>
On Tue, Jun 04, 2019 at 07:04:19PM +0300, Serge Petrenko wrote:
> Add methods to encode/decode decimals as msgpack.
>
> Part of #692
> ---
> cmake/BuildDecNumber.cmake | 1 +
> src/lib/core/decimal.c | 64 +++++++++++
> src/lib/core/decimal.h | 38 +++++++
> src/lib/core/mp_user_types.h | 38 +++++++
> test/unit/decimal.c | 73 ++++++++++++-
> test/unit/decimal.result | 204 ++++++++++++++++++++++++++++++++++-
> 6 files changed, 416 insertions(+), 2 deletions(-)
> create mode 100644 src/lib/core/mp_user_types.h
>
> diff --git a/cmake/BuildDecNumber.cmake b/cmake/BuildDecNumber.cmake
> index 80942fe05..abc6c64c4 100644
> --- a/cmake/BuildDecNumber.cmake
> +++ b/cmake/BuildDecNumber.cmake
> @@ -4,6 +4,7 @@ macro(decnumber_build)
> set(decnumber_src
> ${PROJECT_SOURCE_DIR}/third_party/decNumber/decNumber.c
> ${PROJECT_SOURCE_DIR}/third_party/decNumber/decContext.c
> + ${PROJECT_SOURCE_DIR}/third_party/decNumber/decPacked.c
> )
>
> add_library(decNumber STATIC ${decnumber_src})
> diff --git a/src/lib/core/decimal.c b/src/lib/core/decimal.c
> index 12250da95..7b3b1d8c9 100644
> --- a/src/lib/core/decimal.c
> +++ b/src/lib/core/decimal.c
> @@ -30,7 +30,10 @@
> */
>
> #include "decimal.h"
> +#include "mp_user_types.h"
> +#include "src/lib/msgpuck/msgpuck.h"
> #include "third_party/decNumber/decContext.h"
> +#include "third_party/decNumber/decPacked.h"
> #include <stdlib.h>
> #include <assert.h>
>
> @@ -291,3 +294,64 @@ decimal_sqrt(decimal *res, const decimal *lhs, uint32_t precision)
>
> return decimal_finalize(res, &op_context);
> }
> +
> +static inline uint32_t
> +decimal_len(decimal *dec)
> +{
> + /* 1 + ceil((digits + 1) / 2) */
Bad indentation.
> + return 2 + dec->digits / 2;
> +}
> +
> +uint32_t
> +mp_sizeof_decimal(decimal *dec) {
> + uint32_t l = decimal_len(dec);
> + return mp_sizeof_extl(l) + l;
Better use mp_sizeof_ext instead of mp_sizeof_extl here?
> +}
> +
> +char *
> +mp_encode_decimal(char *data, decimal *dec)
> +{
> + uint32_t len = decimal_len(dec);
> + data = mp_encode_extl(data, MP_DECIMAL, len);
> + data = mp_store_u8(data, decimal_scale(dec));
> + len--;
> + int32_t scale;
> + char *tmp = (char *)decPackedFromNumber((uint8_t *)data, len, &scale, dec);
> + assert(tmp == data);
> + assert(scale == (int32_t)decimal_scale(dec));
> + data += len;
> + return data;
> +}
> +
> +decimal *
> +mp_decode_decimal_raw(const char **data, decimal *dec, uint32_t len)
> +{
> + int32_t scale = mp_load_u8(data);
> + len--;
> + decimal *res = decPackedToNumber((uint8_t *)*data, len, &scale, dec);
> + if (res)
> + *data += len;
> + else
> + (*data)--;
> + return res;
> +}
> +
> +decimal *
> +mp_decode_decimal(const char **data, decimal *dec)
> +{
> + int8_t type;
> + uint32_t len;
> +
> + if (mp_typeof(**data) != MP_EXT)
> + return NULL;
> + const char *const svp = *data;
> + len = mp_decode_extl(data, &type);
> +
> + if (type != MP_DECIMAL || len == 0)
> + return NULL;
> + decimal *res = mp_decode_decimal_raw(data, dec, len);
> + if (!res) {
> + *data = svp;
> + }
> + return res;
> +}
> diff --git a/src/lib/core/decimal.h b/src/lib/core/decimal.h
> index f2812f500..cfcc98073 100644
> --- a/src/lib/core/decimal.h
> +++ b/src/lib/core/decimal.h
> @@ -156,4 +156,42 @@ decimal_exp(decimal *res, const decimal *lhs, uint32_t precision);
> decimal *
> decimal_sqrt(decimal *res, const decimal *lhs, uint32_t precision);
>
> +
> +/**
> + * Return length of message pack encoded decimal with extension header.
> + * Equivalent to mp_sizeof_ext(decimal representation length)
> + */
> +uint32_t
> +mp_sizeof_decimal(decimal *dec);
> +
> +/**
> + * Encode a decimal value to msgpack.
> + *
> + * @return data + mp_sizeof_decimal(dec)
> + */
> +char *
> +mp_encode_decimal(char *data, decimal *dec);
> +
> +/**
> + * Decode a decimal value as though msgpack
> + * ext header was already decoded.
> + *
> + * \post *data = *data + value representation length
> + * @return NULL if value encoding is incorrect
> + * dec otherwise.
> + */
> +decimal *
> +mp_decode_decimal_raw(const char **data, decimal *dec, uint32_t len);
> +
> +/**
> + * Decode a decimal encoded as msgpack with ext header.
> + *
> + * \post *data = *data + mp_sizeof_decimal(dec)
> + * @return NULL if mp_typeof(**data) != MP_EXT
> + * or value encoding is incorrect
> + * dec otherwise.
> + */
> +decimal *
> +mp_decode_decimal(const char **data, decimal *dec);
> +
Mixing mp_ and decimal_ methods in the same file looks ugly, because
msgpack is just one format - we might add other formats in future and it
doesn't sound like a good idea to implement their decoders in decimal.c.
IMO decimal.h should only contain methods to pack/unpack decimals in
some format, say
decimal_pack_len/decimal_pack/decimal_unpack
or
decimal_encode/decimal_decode
mp_ methods should live in some other file (mp_ext, mp_ext_decimal,
mp_decimal.[hc]?)
And I think it's better add and test those generic methods in patch 2,
along with the decimal infrastructure while this patch should be about
msgpack ext only.
prev parent reply other threads:[~2019-06-05 12:40 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-04 16:04 [PATCH v3 0/4] Introduce decimal type to tarantool core Serge Petrenko
2019-06-04 16:04 ` [PATCH v3 1/4] third-party: add decNumber library Serge Petrenko
2019-06-05 8:04 ` Георгий Кириченко
2019-06-04 16:04 ` [PATCH v3 2/4] lib/core: introduce decimal type to tarantool Serge Petrenko
2019-06-05 8:11 ` Георгий Кириченко
2019-06-05 10:03 ` Serge Petrenko
2019-06-05 12:19 ` Vladimir Davydov
2019-06-11 16:14 ` [tarantool-patches] " Serge Petrenko
2019-06-04 16:04 ` [PATCH v3 3/4] lib: update msgpuck library Serge Petrenko
2019-06-04 16:04 ` [PATCH v3 4/4] decimal: add MessagePack encoding/decoding support Serge Petrenko
2019-06-05 8:20 ` Георгий Кириченко
2019-06-05 12:40 ` Vladimir Davydov [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190605124014.vylxrh6nfgoki2g4@esperanza \
--to=vdavydov.dev@gmail.com \
--cc=georgy@tarantool.org \
--cc=kostja@tarantool.org \
--cc=sergepetrenko@tarantool.org \
--cc=tarantool-patches@freelists.org \
--subject='Re: [PATCH v3 4/4] decimal: add MessagePack encoding/decoding support' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox