From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 12.4 \(3445.104.11\)) Subject: Re: [tarantool-patches] [PATCH v3 4/4] decimal: add MessagePack encoding/decoding support From: Serge Petrenko In-Reply-To: <20190606092757.otvjaigijmx72wjd@esperanza> Date: Tue, 11 Jun 2019 19:04:56 +0300 Content-Transfer-Encoding: quoted-printable Message-Id: <2A1C9D7D-9F17-4B9C-905B-E15461F006B6@tarantool.org> References: <20190606092757.otvjaigijmx72wjd@esperanza> To: Vladimir Davydov Cc: Georgy Kirichenko , Konstantin Osipov , tarantool-patches@freelists.org List-ID: > 6 =D0=B8=D1=8E=D0=BD=D1=8F 2019 =D0=B3., =D0=B2 12:27, Vladimir = Davydov =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=BB= (=D0=B0): >=20 > [ RESEND ] >=20 > On Tue, Jun 04, 2019 at 07:04:19PM +0300, Serge Petrenko wrote: >> Add methods to encode/decode decimals as msgpack. >>=20 >> 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 >>=20 >> 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 >> ) >>=20 >> 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 @@ >> */ >>=20 >> #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 >> #include >>=20 >> @@ -291,3 +294,64 @@ decimal_sqrt(decimal *res, const decimal *lhs, = uint32_t precision) >>=20 >> return decimal_finalize(res, &op_context); >> } >> + >> +static inline uint32_t >> +decimal_len(decimal *dec) >> +{ >> + /* 1 + ceil((digits + 1) / 2) */ >=20 > Bad indentation. >=20 >> + return 2 + dec->digits / 2; >> +} >> + >> +uint32_t >> +mp_sizeof_decimal(decimal *dec) { >> + uint32_t l =3D decimal_len(dec); >> + return mp_sizeof_extl(l) + l; >=20 > Better use mp_sizeof_ext instead of mp_sizeof_extl here? >=20 >> +} >> + >> +char * >> +mp_encode_decimal(char *data, decimal *dec) >> +{ >> + uint32_t len =3D decimal_len(dec); >> + data =3D mp_encode_extl(data, MP_DECIMAL, len); >> + data =3D mp_store_u8(data, decimal_scale(dec)); >> + len--; >> + int32_t scale; >> + char *tmp =3D (char *)decPackedFromNumber((uint8_t *)data, len, = &scale, dec); >> + assert(tmp =3D=3D data); >> + assert(scale =3D=3D (int32_t)decimal_scale(dec)); >> + data +=3D len; >> + return data; >> +} >> + >> +decimal * >> +mp_decode_decimal_raw(const char **data, decimal *dec, uint32_t len) >> +{ >> + int32_t scale =3D mp_load_u8(data); >> + len--; >> + decimal *res =3D decPackedToNumber((uint8_t *)*data, len, = &scale, dec); >> + if (res) >> + *data +=3D len; >> + else >> + (*data)--; >> + return res; >> +} >> + >> +decimal * >> +mp_decode_decimal(const char **data, decimal *dec) >> +{ >> + int8_t type; >> + uint32_t len; >> + >> + if (mp_typeof(**data) !=3D MP_EXT) >> + return NULL; >> + const char *const svp =3D *data; >> + len =3D mp_decode_extl(data, &type); >> + >> + if (type !=3D MP_DECIMAL || len =3D=3D 0) >> + return NULL; >> + decimal *res =3D mp_decode_decimal_raw(data, dec, len); >> + if (!res) { >> + *data =3D 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); >>=20 >> + >> +/** >> + * 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 =3D *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 =3D *data + mp_sizeof_decimal(dec) >> + * @return NULL if mp_typeof(**data) !=3D MP_EXT >> + * or value encoding is incorrect >> + * dec otherwise. >> + */ >> +decimal * >> +mp_decode_decimal(const char **data, decimal *dec); >> + >=20 > 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 >=20 > decimal_pack_len/decimal_pack/decimal_unpack >=20 > or >=20 > decimal_encode/decimal_decode >=20 > mp_ methods should live in some other file (mp_ext, mp_ext_decimal, > mp_decimal.[hc]?) Will do after decimal to Lua exposure, no problem. >=20 > 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. Added the methods to patch 2 and resent the patchset as v4. -- Serge Petrenko sergepetrenko@tarantool.org