summaryrefslogtreecommitdiff
path: root/src/runtime/c/gu
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/c/gu')
-rw-r--r--src/runtime/c/gu/bits.c33
-rw-r--r--src/runtime/c/gu/bits.h3
-rw-r--r--src/runtime/c/gu/defs.h10
-rw-r--r--src/runtime/c/gu/in.c4
-rw-r--r--src/runtime/c/gu/out.c24
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;