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")
|
||||
|
||||
cc_library(
|
||||
|
@ -8,8 +8,20 @@ cc_library(
|
|||
],
|
||||
hdrs = [
|
||||
"defs.h",
|
||||
"endian.h",
|
||||
"test.h",
|
||||
],
|
||||
copts = COPTS,
|
||||
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
|
||||
#define defs_h
|
||||
#ifndef lib_defs_h
|
||||
#define lib_defs_h
|
||||
/* 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
|
||||
|
||||
/* 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>
|
||||
|
||||
#else
|
||||
|
@ -65,7 +111,7 @@ typedef enum
|
|||
Memory allocation
|
||||
==============================================================================*/
|
||||
|
||||
#if macintosh
|
||||
#if TARGET_API_MAC_OS8
|
||||
|
||||
#include <MacMemory.h>
|
||||
|
||||
|
|
|
@ -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 */
|
|
@ -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