diff options
Diffstat (limited to 'src/runtime/c/gu')
| -rw-r--r-- | src/runtime/c/gu/bits.c | 33 | ||||
| -rw-r--r-- | src/runtime/c/gu/bits.h | 3 | ||||
| -rw-r--r-- | src/runtime/c/gu/defs.h | 10 | ||||
| -rw-r--r-- | src/runtime/c/gu/in.c | 4 | ||||
| -rw-r--r-- | src/runtime/c/gu/out.c | 24 |
5 files changed, 71 insertions, 3 deletions
diff --git a/src/runtime/c/gu/bits.c b/src/runtime/c/gu/bits.c index 8c43b8477..b5696a19c 100644 --- a/src/runtime/c/gu/bits.c +++ b/src/runtime/c/gu/bits.c @@ -41,3 +41,36 @@ gu_decode_double(uint64_t u) } return sign ? copysign(ret, -1.0) : ret; } + +GU_INTERNAL uint64_t +gu_encode_double(double d) +{ + int sign = signbit(d) > 0; + unsigned rawexp; + uint64_t mantissa; + + switch (fpclassify(d)) { + case FP_NAN: + rawexp = 0x7ff; + mantissa = 1; + break; + case FP_INFINITE: + rawexp = 0x7ff; + mantissa = 0; + break; + default: { + int exp; + mantissa = (uint64_t) scalbn(frexp(d, &exp), 53); + mantissa &= ~ (1ULL << 52); + exp -= 53; + + rawexp = exp + 1075; + } + } + + uint64_t u = (((uint64_t) sign) << 63) | + (((uint64_t) rawexp & 0x7ff) << 52) | + mantissa; + + return u; +} diff --git a/src/runtime/c/gu/bits.h b/src/runtime/c/gu/bits.h index edf6a0049..ee619f400 100644 --- a/src/runtime/c/gu/bits.h +++ b/src/runtime/c/gu/bits.h @@ -144,6 +144,7 @@ gu_decode_2c64(uint64_t u, GuExn* err) GU_INTERNAL_DECL double gu_decode_double(uint64_t u); - +GU_INTERNAL_DECL uint64_t +gu_encode_double(double d); #endif // GU_BITS_H_ diff --git a/src/runtime/c/gu/defs.h b/src/runtime/c/gu/defs.h index 6b531979c..f5472a414 100644 --- a/src/runtime/c/gu/defs.h +++ b/src/runtime/c/gu/defs.h @@ -23,6 +23,14 @@ #define restrict __restrict +#elif defined(__MINGW32__) + +#define GU_API_DECL +#define GU_API + +#define GU_INTERNAL_DECL +#define GU_INTERNAL + #else #define GU_API_DECL @@ -30,7 +38,9 @@ #define GU_INTERNAL_DECL __attribute__ ((visibility ("hidden"))) #define GU_INTERNAL __attribute__ ((visibility ("hidden"))) + #endif + // end MSVC workaround #include <stddef.h> diff --git a/src/runtime/c/gu/in.c b/src/runtime/c/gu/in.c index b36df7924..c241d3086 100644 --- a/src/runtime/c/gu/in.c +++ b/src/runtime/c/gu/in.c @@ -152,7 +152,7 @@ gu_in_le(GuIn* in, GuExn* err, int n) uint8_t buf[8]; gu_in_bytes(in, buf, n, err); uint64_t u = 0; - for (int i = 0; i < n; i++) { + for (int i = n-1; i >= 0; i--) { u = u << 8 | buf[i]; } return u; @@ -246,7 +246,7 @@ gu_in_f64le(GuIn* in, GuExn* err) GU_API double gu_in_f64be(GuIn* in, GuExn* err) { - return gu_decode_double(gu_in_u64le(in, err)); + return gu_decode_double(gu_in_u64be(in, err)); } static void diff --git a/src/runtime/c/gu/out.c b/src/runtime/c/gu/out.c index 7a287cadb..164f483d1 100644 --- a/src/runtime/c/gu/out.c +++ b/src/runtime/c/gu/out.c @@ -1,6 +1,7 @@ #include <gu/seq.h> #include <gu/out.h> #include <gu/utf8.h> +#include <gu/bits.h> #include <stdio.h> static bool @@ -168,8 +169,31 @@ gu_out_is_buffered(GuOut* out); extern inline bool gu_out_try_u8_(GuOut* restrict out, uint8_t u); +GU_API void +gu_out_u16be(GuOut* out, uint16_t u, GuExn* err) +{ + gu_out_u8(out, (u>>8) & 0xFF, err); + gu_out_u8(out, u & 0xFF, err); +} +GU_API void +gu_out_u64be(GuOut* out, uint64_t u, GuExn* err) +{ + gu_out_u8(out, (u>>56) & 0xFF, err); + gu_out_u8(out, (u>>48) & 0xFF, err); + gu_out_u8(out, (u>>40) & 0xFF, err); + gu_out_u8(out, (u>>32) & 0xFF, err); + gu_out_u8(out, (u>>24) & 0xFF, err); + gu_out_u8(out, (u>>16) & 0xFF, err); + gu_out_u8(out, (u>>8) & 0xFF, err); + gu_out_u8(out, u & 0xFF, err); +} +GU_API void +gu_out_f64be(GuOut* out, double d, GuExn* err) +{ + gu_out_u64be(out, gu_encode_double(d), err); +} typedef struct GuBufferedOutStream GuBufferedOutStream; |
