From 8df8dd368490573370bf1d2e7fe89d527ea7f96d Mon Sep 17 00:00:00 2001
From: Bruce Cowan <bruce@bcowan.me.uk>
Date: Sun, 21 Jun 2020 12:06:31 +0100
Subject: [PATCH] Port to using endian.h

---
 meson.build      |  7 ++--
 src/bytedouble.c | 93 +++++++++++++++++++++++++++++++++++++++++-------
 src/meson.build  |  5 ++-
 3 files changed, 90 insertions(+), 15 deletions(-)

diff --git a/meson.build b/meson.build
index 978ed8f..13bb802 100644
--- a/meson.build
+++ b/meson.build
@@ -1,5 +1,4 @@
-# SPDX-FileCopyrightText: 2018, 2019 Bruce Cowan
-#
+# SPDX-FileCopyrightText: 2018-2020 Bruce Cowan
 # SPDX-License-Identifier: CC0-1.0
 
 project('stdlib', 'c',
@@ -18,6 +17,10 @@ if cc.has_function('reallocarray', prefix: '#define _GNU_SOURCE\n#include <stdli
   conf_data.set('HAVE_REALLOCARRAY', 1)
 endif
 
+if cc.has_header('endian.h')
+  has_endian_h = true
+endif
+
 configure_file(configuration: conf_data, output: 'config.h')
 config_dep = declare_dependency(include_directories: '.')
 
diff --git a/src/bytedouble.c b/src/bytedouble.c
index 35b9f65..daf6950 100644
--- a/src/bytedouble.c
+++ b/src/bytedouble.c
@@ -2,31 +2,100 @@
  * SPDX-FileCopyrightText: 2020 Bruce Cowan <bruce@bcowan.me.uk>
  * SPDX-License-Identifier: Apache-2.0
  */
+
+#include <endian.h>
+#include <errno.h>
 #include <inttypes.h>
-#include <math.h>
 #include <stdint.h>
-#include <stdio.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
 
-#define DOUBLE_TO_BYTES(d) ((uint8_t *) &(d))
-#define BYTES_TO_DOUBLE(b) (*((double *) (b)))
+typedef union
+{
+  uint8_t bytes[sizeof (double)];
+  double  d;
+} DoubleBytes;
 
-int
-main (void)
+static void
+bytes_to_be (uint8_t *bytes)
+{
+  uint64_t ret = htobe64 ((uint64_t) *(uint64_t *) bytes);
+  memcpy (bytes, &ret, 8);
+}
+
+static void
+bytes_from_be (uint8_t *bytes)
 {
-    double pi = M_PI;
+  uint64_t ret = be64toh ((uint64_t) * (uint64_t *) bytes);
+  memcpy (bytes, &ret, 8);
+}
 
-    uint8_t *bytes = DOUBLE_TO_BYTES (pi);
+static void
+double_to_be_bytes (double   d,
+                    uint8_t *bytes)
+{
+  DoubleBytes db;
+  db.d = d;
 
+  bytes_to_be (db.bytes);
+  memcpy (bytes, db.bytes, sizeof (double));
+}
+
+static double
+be_bytes_to_double (uint8_t *bytes)
+{
+  DoubleBytes db;
+  memcpy (db.bytes, bytes, sizeof (double));
+  bytes_from_be (db.bytes);
+
+  return db.d;
+}
+
+static void
+print_bytes (uint8_t *bytes,
+             size_t   len)
+{
     printf ("Bytes are [");
 
-    for (int i = 0; i < 7; i++)
+    for (size_t i = 0; i < len-1; i++)
         printf ("%02" PRIx8 ", ", bytes[i]);
 
-    printf ("%02" PRIx8 "]\n", bytes[7]);
+    printf ("%02" PRIx8 "]\n", bytes[len-1]);
+}
+
+int
+main (void)
+{
+    errno = 0;
+    char buf[32];
+    char *endptr;
+
+    puts ("Please enter a floating point number");
+    fgets (buf, 31, stdin);
+    double val = strtod (buf, &endptr);
+    if (errno)
+    {
+        perror ("strtod");
+        return EXIT_FAILURE;
+    }
+    if (buf == endptr)
+    {
+      fputs ("No digits found\n", stderr);
+      return EXIT_FAILURE;
+    }
+
+    uint8_t bytes[sizeof (double)];
+
+    memcpy (bytes, &val, sizeof (double));
+    print_bytes (bytes, sizeof (double));
+
+    double_to_be_bytes (val, bytes);
+    puts ("After swapping:");
+    print_bytes (bytes, sizeof (double));
 
-    double d = BYTES_TO_DOUBLE (bytes);
-    printf ("Converting back, the value is %f\n", d);
+    double d = be_bytes_to_double (bytes);
+    printf ("Converting back, the value is %.15g\n", d);
 
     return 0;
 }
diff --git a/src/meson.build b/src/meson.build
index 2682858..4b20046 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -6,7 +6,6 @@ executable('angle', 'angle.c', dependencies: libm)
 executable('array-length', 'array-length.c', dependencies: types_dep)
 executable('binary', 'binary.c')
 executable('binary2', 'binary2.c', dependencies: utils_dep)
-executable('bytedouble', 'bytedouble.c')
 executable('complex', 'complex.c', dependencies: libm)
 executable('doubles', 'doubles.c')
 executable('einstein', 'einstein.c')
@@ -30,6 +29,10 @@ executable('world', 'world.c')
 
 subdir('sockets')
 
+if has_endian_h
+  executable('bytedouble', 'bytedouble.c')
+endif
+
 if openmp_dep.found()
     subdir('openmp')
 endif
-- 
GitLab