From 7624ec9003444dbd76f03dfeda38167f3831fc48 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Tue, 23 Dec 2014 18:16:13 +0100 Subject: [PATCH] proto: Added support for marshaling double-precision values. For this, determine the memory layout of doubles in 'configure' and then use IEEE-754 big-endian encoding on the wire. For now, only little- and big-endian IEEE-754 doubles are supported but that'll cover the vast majority of all systems. --- configure.ac | 60 +++++++++++++++++++++++++++++++++++++++ src/utils/proto.c | 24 +++++++++++----- t/unit/utils/proto_test.c | 11 +++++-- 3 files changed, 86 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index baf1137..59f4ee7 100644 --- a/configure.ac +++ b/configure.ac @@ -341,6 +341,66 @@ fi AC_SUBST([PROFILING_CFLAGS]) AC_SUBST([PROFILING_LDFLAGS]) +ieee754_layout="unknown" +AC_MSG_CHECKING([the memory layout of double precision values]) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[ +double d = 3.141592653e130; +char c[8]; +if (sizeof(d) != 8) + return 2; +memcpy(&c, &d, 8); +if (c[0] == '\x04' && c[1] == '\x10' && c[2] == '\x1E' && c[3] == '\x66' && + c[4] == '\x40' && c[5] == '\xA9' && c[6] == '\x06' && c[7] == '\x5B') + return 0; +else + return 1; + ]] + )], + [ieee754_layout="little-endian"], [ieee754_layout="unknown"]) +if test "x$ieee754_layout" = "xunknown"; then + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[ +double d = 3.141592653e130; +char c[8]; +if (sizeof(d) != 8) + return 2; +memcpy(&c, &d, 8); +if (c[7] == '\x04' && c[6] == '\x10' && c[5] == '\x1E' && c[4] == '\x66' && + c[3] == '\x40' && c[2] == '\xA9' && c[1] == '\x06' && c[0] == '\x5B') + return 0; +else + return 1; + ]] + )], + [ieee754_layout="big-endian"], [ieee754_layout="unknown"]) +fi +AC_MSG_RESULT([IEEE-754 $ieee754_layout]) + +AC_DEFINE([IEEE754_DOUBLE_LITTLE_ENDIAN], 1234, + [Identifier for IEEE-754 little-endian encoding of double precision values]) +AC_DEFINE([IEEE754_DOUBLE_BIG_ENDIAN], 4321, + [Identifier for IEEE-754 big-endian encoding of double precision values]) +if test "x$ieee754_layout" = "xlittle-endian"; then + AC_DEFINE([IEEE754_DOUBLE_BYTE_ORDER], 1234, + [Define to 1 if double precision values use IEEE-754 little-endian encoding]) +else if test "x$ieee754_layout" = "xbig-endian"; then + AC_DEFINE([IEEE754_DOUBLE_BYTE_ORDER], 4321, + [Define to 1 if double precision values use IEEE-754 little-endian encoding]) +else + AC_MSG_ERROR([Unknown memory layout of double precision values]) +fi; fi + m4_divert_once([HELP_ENABLE], [ Build dependencies:]) diff --git a/src/utils/proto.c b/src/utils/proto.c index cb88887..af4215b 100644 --- a/src/utils/proto.c +++ b/src/utils/proto.c @@ -25,14 +25,19 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_CONFIG_H +# include "config.h" +#endif + #include "core/data.h" #include "core/time.h" #include "utils/error.h" #include "utils/proto.h" -#include +#include #include +#include #include #include @@ -62,13 +67,18 @@ marshal_int(char *buf, size_t buf_len, int64_t v) } /* marshal_int */ static ssize_t -marshal_double(char __attribute__((unused)) *buf, - size_t __attribute__((unused)) buf_len, - double __attribute__((unused)) v) +marshal_double(char *buf, size_t buf_len, double v) { - /* XXX: find a good network representation */ - errno = ENOTSUP; - return -1; + uint64_t t = 0; + assert(sizeof(v) == sizeof(t)); + memcpy(&t, &v, sizeof(v)); +#if IEEE754_DOUBLE_BYTE_ORDER != IEEE754_DOUBLE_BIG_ENDIAN + t = (((int64_t)ntohl((int32_t)t)) << 32) + + ((int64_t)ntohl((int32_t)(t >> 32))); +#endif + if (buf_len >= sizeof(t)) + memcpy(buf, &t, sizeof(t)); + return sizeof(t); } /* marshal_double */ static ssize_t diff --git a/t/unit/utils/proto_test.c b/t/unit/utils/proto_test.c index d0516b3..1ec0615 100644 --- a/t/unit/utils/proto_test.c +++ b/t/unit/utils/proto_test.c @@ -49,6 +49,7 @@ START_TEST(test_marshal_data) regex_t dummy_re; int64_t int_values[] = { 47, 11, 23 }; + double dec_values[] = { 47.11, .5 }; char *string_values[] = { "foo", "abcd" }; struct { @@ -65,8 +66,8 @@ START_TEST(test_marshal_data) 12, INT_TYPE "\0\0\0\0\0\0\x12\x67", }, { - { SDB_TYPE_DECIMAL, { .integer = 4711 } }, - -1, NULL, /* not supported yet */ + { SDB_TYPE_DECIMAL, { .decimal = 3.141592653e130 } }, + 12, DECIMAL_TYPE "\x5b\x6\xa9\x40\x66\x1e\x10\x4", }, { { SDB_TYPE_STRING, { .string = "some string" } }, @@ -92,6 +93,12 @@ START_TEST(test_marshal_data) 32, INT_ARRAY "\0\0\0\x3" "\0\0\0\0\0\0\0\x2f" "\0\0\0\0\0\0\0\xb" "\0\0\0\0\0\0\0\x17" }, + { + { SDB_TYPE_DECIMAL | SDB_TYPE_ARRAY, { .array = { + 2, dec_values } } }, + 24, DECIMAL_ARRAY "\0\0\0\x2" "\x40\x47\x8e\x14\x7a\xe1\x47\xae" + "\x3f\xe0\0\0\0\0\0\0" + }, { { SDB_TYPE_STRING | SDB_TYPE_ARRAY, { .array = { 2, string_values } } }, -- 2.30.2