mirror of
https://github.com/depp/syncfiles.git
synced 2024-05-28 08:41:28 +00:00
Add byte order conversion utilities
This commit is contained in:
parent
16f3764790
commit
d980169ec6
|
@ -1,4 +1,4 @@
|
||||||
load("@rules_cc//cc:defs.bzl", "cc_library")
|
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
|
||||||
load("//bazel:copts.bzl", "COPTS")
|
load("//bazel:copts.bzl", "COPTS")
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
|
@ -8,8 +8,20 @@ cc_library(
|
||||||
],
|
],
|
||||||
hdrs = [
|
hdrs = [
|
||||||
"defs.h",
|
"defs.h",
|
||||||
|
"endian.h",
|
||||||
"test.h",
|
"test.h",
|
||||||
],
|
],
|
||||||
copts = COPTS,
|
copts = COPTS,
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_test(
|
||||||
|
name = "endian_test",
|
||||||
|
srcs = [
|
||||||
|
"endian_test.c",
|
||||||
|
],
|
||||||
|
copts = COPTS,
|
||||||
|
deps = [
|
||||||
|
":lib",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
54
lib/defs.h
54
lib/defs.h
|
@ -1,13 +1,59 @@
|
||||||
#ifndef defs_h
|
#ifndef lib_defs_h
|
||||||
#define defs_h
|
#define lib_defs_h
|
||||||
/* defs.h - common definitions. */
|
/* defs.h - common definitions. */
|
||||||
|
|
||||||
/*==============================================================================
|
/*==============================================================================
|
||||||
Basic definitions
|
Target information
|
||||||
==============================================================================*/
|
==============================================================================*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Note that this code does not need to be especially portable. It just runs on
|
||||||
|
Mac OS and development systems (for testing). We can assume that the
|
||||||
|
development system has GCC.
|
||||||
|
|
||||||
|
Macros we care about:
|
||||||
|
|
||||||
|
TARGET_OS_MAC OS is some Macintosh variant (broadly speaking)
|
||||||
|
TARGET_API_MAC_OS8 Targeting classic Mac OS (9.x and earlier)
|
||||||
|
|
||||||
|
TARGET_RT_LITTLE_ENDIAN Little-endian byte order
|
||||||
|
TARGET_RT_BIG_ENDIAN Big-endian byte order
|
||||||
|
*/
|
||||||
#if macintosh
|
#if macintosh
|
||||||
|
|
||||||
|
/* Classic Mac OS. Header is part of Universal Interfaces & Carbon. */
|
||||||
|
#include <ConditionalMacros.h>
|
||||||
|
|
||||||
|
#elif __APPLE__
|
||||||
|
|
||||||
|
/* Newer apple systems, including macOS >= 10. Header is in /usr/include, or
|
||||||
|
within /usr/include inside the SDK. */
|
||||||
|
#include <TargetConditionals.h>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if __BYTE_ORDER__
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
|
#define TARGET_RT_LITTLE_ENDIAN 1
|
||||||
|
#define TARGET_RT_BIG_ENDIAN 0
|
||||||
|
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
#define TARGET_RT_LITTLE_ENDIAN 0
|
||||||
|
#define TARGET_RT_BIG_ENDIAN 1
|
||||||
|
#else
|
||||||
|
#error "unknown endian"
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#error "could not determine byte order"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*==============================================================================
|
||||||
|
Basic types
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#if TARGET_API_MAC_OS8
|
||||||
|
|
||||||
#include <MacTypes.h>
|
#include <MacTypes.h>
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -65,7 +111,7 @@ typedef enum
|
||||||
Memory allocation
|
Memory allocation
|
||||||
==============================================================================*/
|
==============================================================================*/
|
||||||
|
|
||||||
#if macintosh
|
#if TARGET_API_MAC_OS8
|
||||||
|
|
||||||
#include <MacMemory.h>
|
#include <MacMemory.h>
|
||||||
|
|
||||||
|
|
75
lib/endian.h
Normal file
75
lib/endian.h
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#ifndef lib_endian_h
|
||||||
|
#define lib_endian_h
|
||||||
|
/* endian.h - byte order and byte swapping */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Defines macros for swapping to and from big-endian:
|
||||||
|
|
||||||
|
EndianU16_BtoN
|
||||||
|
EndianU16_NtoB
|
||||||
|
EndianU32_BtoN
|
||||||
|
EndianU32_NtoB
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib/defs.h"
|
||||||
|
|
||||||
|
#if TARGET_API_MAC_OS8
|
||||||
|
|
||||||
|
/* Use the legacy Mac OS header, if available. */
|
||||||
|
#include <Endian.h>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* Use the compiler built-in, if available. */
|
||||||
|
#if __clang__
|
||||||
|
|
||||||
|
#if __has_builtin(__builtin_bswap16)
|
||||||
|
#define Endian16_Swap(x) __builtin_bswap16(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __has_builtin(__builtin_bswap32)
|
||||||
|
#define Endian32_Swap(x) __builtin_bswap32(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif __GNUC__
|
||||||
|
|
||||||
|
#if __GNUC__ && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 3)
|
||||||
|
#define Endian16_Swap(x) __builtin_bswap16(x)
|
||||||
|
#define Endian32_Swap(x) __builtin_bswap32(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Fallback implementations. */
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
#ifndef Endian16_Swap
|
||||||
|
#define Endian16_Swap(x) \
|
||||||
|
((((UInt16)(x) << 8) & 0xff00) | \
|
||||||
|
(((UInt16)(x) >> 8) & 0x00ff))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Endian32_Swap
|
||||||
|
#define Endian32_Swap(x) \
|
||||||
|
((((UInt32)(x) << 24) & 0xff000000) | \
|
||||||
|
(((UInt32)(x) << 8) & 0x00ff0000) | \
|
||||||
|
(((UInt32)(x) >> 8) & 0x0000ff00) | \
|
||||||
|
(((UInt32)(x) >> 24) & 0x000000ff))
|
||||||
|
#endif
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
|
#if TARGET_RT_BIG_ENDIAN
|
||||||
|
#define EndianU16_BtoN(x) (x)
|
||||||
|
#define EndianU16_NtoB(x) (x)
|
||||||
|
#define EndianU32_BtoN(x) (x)
|
||||||
|
#define EndianU32_NtoB(x) (x)
|
||||||
|
#else
|
||||||
|
#define EndianU16_BtoN(x) Endian16_Swap(x)
|
||||||
|
#define EndianU16_NtoB(x) Endian16_Swap(x)
|
||||||
|
#define EndianU32_BtoN(x) Endian32_Swap(x)
|
||||||
|
#define EndianU32_NtoB(x) Endian32_Swap(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* TARGET_API_MAC_OS8 */
|
||||||
|
|
||||||
|
#endif /* lib_endian_h */
|
62
lib/endian_test.c
Normal file
62
lib/endian_test.c
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#include "lib/endian.h"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static int gDidFail;
|
||||||
|
|
||||||
|
static void Fail(const char *name, UInt32 got, UInt32 expect)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s = 0x%" PRIx32 ", expect 0x%" PRIx32 "\n", name, got,
|
||||||
|
expect);
|
||||||
|
gDidFail = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CHECK(fn, expect) \
|
||||||
|
be = fn(u.i); \
|
||||||
|
if (be != expect) { \
|
||||||
|
Fail(#fn, be, expect); \
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Test16(void)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
UInt16 i;
|
||||||
|
UInt8 b[2];
|
||||||
|
} u;
|
||||||
|
UInt16 be;
|
||||||
|
|
||||||
|
u.b[0] = 0x12;
|
||||||
|
u.b[1] = 0x34;
|
||||||
|
|
||||||
|
CHECK(EndianU16_BtoN, 0x1234)
|
||||||
|
CHECK(EndianU16_NtoB, 0x1234)
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Test32(void)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
UInt32 i;
|
||||||
|
UInt8 b[2];
|
||||||
|
} u;
|
||||||
|
UInt32 be;
|
||||||
|
|
||||||
|
u.b[0] = 0x12;
|
||||||
|
u.b[1] = 0x34;
|
||||||
|
u.b[2] = 0x56;
|
||||||
|
u.b[3] = 0x78;
|
||||||
|
|
||||||
|
CHECK(EndianU32_BtoN, 0x12345678)
|
||||||
|
CHECK(EndianU32_NtoB, 0x12345678)
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
|
Test16();
|
||||||
|
Test32();
|
||||||
|
return gDidFail;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user