]> git.seodisparate.com - SimpleArchiver/commitdiff
Add helpers for conversion to/from big-endian
authorStephen Seo <seo.disparate@gmail.com>
Tue, 2 Jul 2024 05:25:01 +0000 (14:25 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Tue, 2 Jul 2024 05:25:01 +0000 (14:25 +0900)
Also added tests for big-endian-conversion functions.

CMakeLists.txt
cosmopolitan/Makefile
src/helpers.c [new file with mode: 0644]
src/helpers.h [new file with mode: 0644]
src/test.c

index 59396030d8a374ca64084da766af4c190fcfa240..2b73cb7d011070811c14ce974b08f1e2c1951312 100644 (file)
@@ -6,6 +6,7 @@ set(SimpleArchiver_VERSION 1.0)
 set(SimpleArchiver_SOURCES
     src/main.c
     src/parser.c
+    src/helpers.c
     src/data_structures/linked_list.c
     src/data_structures/hash_map.c
     src/data_structures/priority_heap.c
@@ -37,4 +38,5 @@ add_executable(test_datastructures
 add_executable(test_simplearchiver
     src/test.c
     src/parser.c
+    src/helpers.c
 )
index 25b01881277143490062f175d3baac548a58e919..7ac2466d6462a727599ccd36920270ffea0795e4 100644 (file)
@@ -6,6 +6,7 @@ OUTDIR = out
 SOURCES = \
                ../src/main.c \
                ../src/parser.c \
+               ../src/helpers.c \
                ../src/algorithms/linear_congruential_gen.c \
                ../src/data_structures/linked_list.c \
                ../src/data_structures/hash_map.c \
@@ -14,6 +15,7 @@ SOURCES = \
 HEADERS = \
                ../src/parser.h \
                ../src/parser_internal.h \
+               ../src/helpers.h \
                ../src/algorithms/linear_congruential_gen.h \
                ../src/data_structures/linked_list.h \
                ../src/data_structures/hash_map.h \
diff --git a/src/helpers.c b/src/helpers.c
new file mode 100644 (file)
index 0000000..0007f20
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2024 Stephen Seo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * `helpers.c` is the source for helpful/utility functions.
+ */
+
+#include "helpers.h"
+
+int simple_archiver_helper_is_big_endian(void) {
+  union {
+    unsigned int i;
+    char c[4];
+  } bint = {0x01020304};
+
+  return bint.c[0] == 1 ? 1 : 0;
+}
+
+void simple_archiver_helper_16_bit_be(unsigned short *value) {
+  if (simple_archiver_helper_is_big_endian() == 0) {
+    unsigned char c = ((unsigned char *)value)[0];
+    ((unsigned char *)value)[0] = ((unsigned char *)value)[1];
+    ((unsigned char *)value)[1] = c;
+  }
+}
+
+void simple_archiver_helper_32_bit_be(unsigned int *value) {
+  if (simple_archiver_helper_is_big_endian() == 0) {
+    for (unsigned int i = 0; i < 2; ++i) {
+      unsigned char c = ((unsigned char *)value)[i];
+      ((unsigned char *)value)[i] = ((unsigned char *)value)[3 - i];
+      ((unsigned char *)value)[3 - i] = c;
+    }
+  }
+}
+
+void simple_archiver_helper_64_bit_be(unsigned long long *value) {
+  if (simple_archiver_helper_is_big_endian() == 0) {
+    for (unsigned int i = 0; i < 4; ++i) {
+      unsigned char c = ((unsigned char *)value)[i];
+      ((unsigned char *)value)[i] = ((unsigned char *)value)[7 - i];
+      ((unsigned char *)value)[7 - i] = c;
+    }
+  }
+}
diff --git a/src/helpers.h b/src/helpers.h
new file mode 100644 (file)
index 0000000..3089b33
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2024 Stephen Seo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * `helpers.h` is the header for helpful/utility functions.
+ */
+
+#ifndef SEODISPARATE_COM_SIMPLE_ARCHIVER_HELPERS_H_
+#define SEODISPARATE_COM_SIMPLE_ARCHIVER_HELPERS_H_
+
+/// Returns non-zero if this system is big-endian.
+int simple_archiver_helper_is_big_endian(void);
+
+/// Swaps value from/to big-endian. Nop on big-endian systems.
+void simple_archiver_helper_16_bit_be(unsigned short *value);
+
+/// Swaps value from/to big-endian. Nop on big-endian systems.
+void simple_archiver_helper_32_bit_be(unsigned int *value);
+
+/// Swaps value from/to big-endian. Nop on big-endian systems.
+void simple_archiver_helper_64_bit_be(unsigned long long *value);
+
+#endif
index cf6cb4fde32e9250ec7d94e2eb97bfdb3104b23e..7f070976beabf1926591c76d6c5f879516b118a8 100644 (file)
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "helpers.h"
 #include "parser_internal.h"
 
 static int checks_checked = 0;
@@ -109,6 +110,66 @@ int main(void) {
     simple_archiver_free_parsed(&parsed);
   }
 
+  // Test helpers.
+  {
+    // Only if system is little-endian.
+    if (simple_archiver_helper_is_big_endian() == 0) {
+      unsigned short u16 = 0x0102;
+      CHECK_TRUE(((unsigned char *)&u16)[0] == 2);
+      CHECK_TRUE(((unsigned char *)&u16)[1] == 1);
+      simple_archiver_helper_16_bit_be(&u16);
+      CHECK_TRUE(((unsigned char *)&u16)[0] == 1);
+      CHECK_TRUE(((unsigned char *)&u16)[1] == 2);
+      simple_archiver_helper_16_bit_be(&u16);
+      CHECK_TRUE(((unsigned char *)&u16)[0] == 2);
+      CHECK_TRUE(((unsigned char *)&u16)[1] == 1);
+
+      unsigned int u32 = 0x01020304;
+      CHECK_TRUE(((unsigned char *)&u32)[0] == 4);
+      CHECK_TRUE(((unsigned char *)&u32)[1] == 3);
+      CHECK_TRUE(((unsigned char *)&u32)[2] == 2);
+      CHECK_TRUE(((unsigned char *)&u32)[3] == 1);
+      simple_archiver_helper_32_bit_be(&u32);
+      CHECK_TRUE(((unsigned char *)&u32)[0] == 1);
+      CHECK_TRUE(((unsigned char *)&u32)[1] == 2);
+      CHECK_TRUE(((unsigned char *)&u32)[2] == 3);
+      CHECK_TRUE(((unsigned char *)&u32)[3] == 4);
+      simple_archiver_helper_32_bit_be(&u32);
+      CHECK_TRUE(((unsigned char *)&u32)[0] == 4);
+      CHECK_TRUE(((unsigned char *)&u32)[1] == 3);
+      CHECK_TRUE(((unsigned char *)&u32)[2] == 2);
+      CHECK_TRUE(((unsigned char *)&u32)[3] == 1);
+
+      unsigned long long u64 = 0x010203040a0b0c0d;
+      CHECK_TRUE(((unsigned char *)&u64)[0] == 0xd);
+      CHECK_TRUE(((unsigned char *)&u64)[1] == 0xc);
+      CHECK_TRUE(((unsigned char *)&u64)[2] == 0xb);
+      CHECK_TRUE(((unsigned char *)&u64)[3] == 0xa);
+      CHECK_TRUE(((unsigned char *)&u64)[4] == 0x4);
+      CHECK_TRUE(((unsigned char *)&u64)[5] == 0x3);
+      CHECK_TRUE(((unsigned char *)&u64)[6] == 0x2);
+      CHECK_TRUE(((unsigned char *)&u64)[7] == 0x1);
+      simple_archiver_helper_64_bit_be(&u64);
+      CHECK_TRUE(((unsigned char *)&u64)[0] == 0x1);
+      CHECK_TRUE(((unsigned char *)&u64)[1] == 0x2);
+      CHECK_TRUE(((unsigned char *)&u64)[2] == 0x3);
+      CHECK_TRUE(((unsigned char *)&u64)[3] == 0x4);
+      CHECK_TRUE(((unsigned char *)&u64)[4] == 0xa);
+      CHECK_TRUE(((unsigned char *)&u64)[5] == 0xb);
+      CHECK_TRUE(((unsigned char *)&u64)[6] == 0xc);
+      CHECK_TRUE(((unsigned char *)&u64)[7] == 0xd);
+      simple_archiver_helper_64_bit_be(&u64);
+      CHECK_TRUE(((unsigned char *)&u64)[0] == 0xd);
+      CHECK_TRUE(((unsigned char *)&u64)[1] == 0xc);
+      CHECK_TRUE(((unsigned char *)&u64)[2] == 0xb);
+      CHECK_TRUE(((unsigned char *)&u64)[3] == 0xa);
+      CHECK_TRUE(((unsigned char *)&u64)[4] == 0x4);
+      CHECK_TRUE(((unsigned char *)&u64)[5] == 0x3);
+      CHECK_TRUE(((unsigned char *)&u64)[6] == 0x2);
+      CHECK_TRUE(((unsigned char *)&u64)[7] == 0x1);
+    }
+  }
+
   printf("Checks checked: %u\n", checks_checked);
   printf("Checks passed:  %u\n", checks_passed);
   return checks_passed == checks_checked ? 0 : 1;