diff --git a/src/util/compat/endian.h b/src/util/compat/endian.h new file mode 100644 index 0000000..8857dbe --- /dev/null +++ b/src/util/compat/endian.h @@ -0,0 +1,54 @@ +// Copyright (c) 2025 Quinn +// Licensed under the MIT Licence. See LICENSE for details +#pragma once + +#include +#include + +#include "../atrb.h" + +/* little endian */ +atrb_const static inline uint16_t le16ton(uint16_t); // converts little-endian (LE) encoding to native for a 16 bit integer. (NOOP if native is LE) +atrb_const static inline uint32_t le32ton(uint32_t); // converts little-endian (LE) encoding to native for a 32 bit integer. (NOOP if native is LE) +atrb_const static inline uint64_t le64ton(uint64_t); // converts little-endian (LE) encoding to native for a 64 bit integer. (NOOP if native is LE) +atrb_const static inline uint16_t ntole16(uint16_t); // converts native encoding to little-endian (LE) for a 16 bit integer. (NOOP if native is LE) +atrb_const static inline uint32_t ntole32(uint32_t); // converts native encoding to little-endian (LE) for a 32 bit integer. (NOOP if native is LE) +atrb_const static inline uint64_t ntole64(uint64_t); // converts native encoding to little-endian (LE) for a 64 bit integer. (NOOP if native is LE) + +/* big endian */ +atrb_const static inline uint16_t be16ton(uint16_t); // converts big-endian (BE) encoding to native for a 16 bit integer. (NOOP if native is BE) +atrb_const static inline uint32_t be32ton(uint32_t); // converts big-endian (BE) encoding to native for a 32 bit integer. (NOOP if native is BE) +atrb_const static inline uint64_t be64ton(uint64_t); // converts big-endian (BE) encoding to native for a 64 bit integer. (NOOP if native is BE) +atrb_const static inline uint16_t ntobe16(uint16_t); // converts native encoding to big-endian (BE) for a 16 bit integer. (NOOP if native is BE) +atrb_const static inline uint32_t ntobe32(uint32_t); // converts native encoding to big-endian (BE) for a 32 bit integer. (NOOP if native is BE) +atrb_const static inline uint64_t ntobe64(uint64_t); // converts native encoding to big-endian (BE) for a 64 bit integer. (NOOP if native is BE) + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +uint16_t le16ton(uint16_t x) { return x; } +uint32_t le32ton(uint32_t x) { return x; } +uint64_t le64ton(uint64_t x) { return x; } +uint16_t ntole16(uint16_t x) { return x; } +uint32_t ntole32(uint32_t x) { return x; } +uint64_t ntole64(uint64_t x) { return x; } +uint16_t be16ton(uint16_t x) { return bswap_16(x); } +uint32_t be32ton(uint32_t x) { return bswap_32(x); } +uint64_t be64ton(uint64_t x) { return bswap_64(x); } +uint16_t ntobe16(uint16_t x) { return bswap_16(x); } +uint32_t ntobe32(uint32_t x) { return bswap_32(x); } +uint64_t ntobe64(uint64_t x) { return bswap_64(x); } +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +uint16_t le16ton(uint16_t x) { bswap_16(x); } +uint32_t le32ton(uint32_t x) { bswap_32(x); } +uint64_t le64ton(uint64_t x) { bswap_64(x); } +uint16_t ntole16(uint16_t x) { bswap_16(x); } +uint32_t ntole32(uint32_t x) { bswap_32(x); } +uint64_t ntole64(uint64_t x) { bswap_64(x); } +uint16_t be16ton(uint16_t x) { return x; } +uint32_t be32ton(uint32_t x) { return x; } +uint64_t be64ton(uint64_t x) { return x; } +uint16_t ntobe16(uint16_t x) { return x; } +uint32_t ntobe32(uint32_t x) { return x; } +uint64_t ntobe64(uint64_t x) { return x; } +#else +#error machine architecture unsupported! Expected either big-endian or little-endian, make sure to use a compiler which defines __BYTE_ORDER__ (like clang or gcc) +#endif diff --git a/src/util/compat/io.h b/src/util/compat/io.h new file mode 100644 index 0000000..3853570 --- /dev/null +++ b/src/util/compat/io.h @@ -0,0 +1,48 @@ +// Copyright (c) 2025 Quinn +// Licensed under the MIT Licence. See LICENSE for details +#pragma once + +#if defined __unix__ +#include +#include +#elif defined _WIN32 +#include +#else +#error platform not supported! +#endif + +/* tests a files access with F_OK, X_OK, R_OK, W_OK OR'd together + returns 0 upon success. -1 when errno is set and anything else when one or more of the permissions isn't set */ +static inline int faccess(char const* restrict fname, int perms); + +// define the constants if they haven't been +#ifndef F_OK +#define F_OK 0 +#endif +#ifndef X_OK +#define X_OK 1 +#endif +#ifndef W_OK +#define W_OK 2 +#endif +#ifndef R_OK +#define R_OK 4 +#endif + +#if defined __unix__ && _POSIX_C_SOURCE >= 200809L +#define PATH_SEP '/' // contains the path separator as a character. Yes it is extremely annoying that this has to exist. +#define PATH_SEP_STR "/" // contains the path separator as a string, useful for concatenation. Yes it is extremely annoying that this has to exist. + +int faccess(char const* restrict fname, int perms) { + return access(fname, perms); +} +#elif defined(_WIN32) +#define PATH_SEP '\\' // contains the path separator as a character. Yes it is extremely annoying that this has to exist. +#define PATH_SEP_STR "\\" // contains the path separator as a string, useful for concatenation. Yes it is extremely annoying that this has to exist. + +int faccess(char const* restrict fname, int perms) { + return _access(fname, perms); +} +#else +#error platform unsupported! +#endif diff --git a/src/util/compat/os.h b/src/util/compat/os.h new file mode 100644 index 0000000..860cbb2 --- /dev/null +++ b/src/util/compat/os.h @@ -0,0 +1,13 @@ +// Copyright (c) 2025 Quinn +// Licensed under the MIT Licence. See LICENSE for details +#pragma once + +#if defined(__unix__) +#define unixonly(_exec) _exec // executes inline code when __unix__ is defined, otherwise is no-op +#define winonly(_exec) // (no-op) executes inline code when _WIN32 is defined, otherwise is no-op +#elif defined(_WIN32) +#define unixonly(_exec) // (no-op) executes inline code when __unix__ is defined, otherwise is no-op +#define winonly(_exec) _exec // executes inline code when _WIN32 is defined, otherwise is no-op +#else +#error platform unsupported!! +#endif