Created
February 10, 2022 23:49
-
-
Save jacobmilligan/c9ee31891cceeba4c6c15dc8d845e6e4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* cplatform.h | |
* Collection of macros and utilities for writing cross-platform C/C++ code | |
* | |
* Copyright (c) 2021 Jacob Milligan. All rights reserved. | |
*/ | |
/* | |
********************** | |
* | |
* # Build type setup | |
* | |
********************** | |
*/ | |
#ifndef CPLATFORM_DEBUG | |
#define CPLATFORM_DEBUG 0 | |
#endif // CPLATFORM_DEBUG | |
#ifndef CPLATFORM_RELEASE | |
#define CPLATFORM_RELEASE 0 | |
#endif // CPLATFORM_RELEASE | |
/* | |
****************************************** | |
* | |
* # String expansion and token pasting | |
* | |
****************************************** | |
*/ | |
#define CPLATFORM_EXPAND(x) x | |
#define CPLATFORM_STRINGIFY(x) #x | |
#define CPLATFORM_CONCAT_BASE(x, y) x##y | |
#define CPLATFORM_CONCAT(x, y) CPLATFORM_CONCAT_BASE(x, y) | |
/* | |
****************************** | |
* | |
* # OS platform detection | |
* | |
****************************** | |
*/ | |
#if defined(__APPLE__) && defined(__MACH__) | |
#include <TargetConditionals.h> | |
#if TARGET_IPHONE_SIMULATOR == 1 | |
#define CPLATFORM_OS_IOS 1 | |
#define CPLATFORM_OS_NAME_STRING "iOS Simulator" | |
#elif TARGET_OS_IPHONE == 1 | |
#define CPLATFORM_OS_IOS 1 | |
#define CPLATFORM_OS_NAME_STRING "iOS" | |
#elif TARGET_OS_MAC == 1 | |
#define CPLATFORM_OS_MACOS 1 | |
#define CPLATFORM_OS_NAME_STRING "MacOS" | |
#endif // TARGET_* | |
#elif defined(__WIN32__) || defined(__WINDOWS__) || defined(_WIN64) || defined(_WIN32) || defined(_WINDOWS) || defined(__TOS_WIN__) | |
#define CPLATFORM_OS_WINDOWS 1 | |
#define CPLATFORM_OS_NAME_STRING "Windows" | |
#elif defined(__linux__) || defined(__linux) || defined(linux_generic) | |
#define CPLATFORM_OS_LINUX 1 | |
#define CPLATFORM_OS_NAME_STRING "Linux" | |
#elif defined(__ANDROID__) | |
#define CPLATFORM_OS_ANDROID 1 | |
#define CPLATFORM_ANDROID_API_LEVEL __ANDROID_API__ | |
#define CPLATFORM_OS_NAME_STRING "Android" | |
#endif // defined(<platform>) | |
#if CPLATFORM_OS_LINUX == 1 || CPLATFORM_OS_MACOS == 1 || CPLATFORM_OS_IOS == 1 || CPLATFORM_OS_ANDROID == 1 | |
#define CPLATFORM_OS_UNIX 1 | |
#else | |
#define CPLATFORM_OS_UNIX 0 | |
#endif // | |
#ifndef CPLATFORM_OS_MACOS | |
#define CPLATFORM_OS_MACOS 0 | |
#endif // CPLATFORM_OS_MACOS | |
#ifndef CPLATFORM_OS_IOS | |
#define CPLATFORM_OS_IOS 0 | |
#endif // CPLATFORM_OS_IOS | |
#ifndef CPLATFORM_OS_ANDROID | |
#define CPLATFORM_OS_ANDROID 0 | |
#endif // CPLATFORM_OS_ANDROID | |
#ifndef CPLATFORM_OS_WINDOWS | |
#define CPLATFORM_OS_WINDOWS 0 | |
#endif // CPLATFORM_OS_WINDOWS | |
#ifndef CPLATFORM_OS_LINUX | |
#define CPLATFORM_OS_LINUX 0 | |
#endif // CPLATFORM_OS_LINUX | |
#ifndef CPLATFORM_OS_NAME_STRING | |
#define CPLATFORM_OS_NAME_STRING "UNKNOWN_OS" | |
#endif // ifndef CPLATFORM_OS_NAME_STRING | |
/* | |
****************************** | |
* | |
* # Compiler detection | |
* | |
****************************** | |
*/ | |
#if defined(__clang__) | |
#define CPLATFORM_COMPILER_CLANG 1 | |
#elif defined(__GNUC__) | |
#define CPLATFORM_COMPILER_GCC 1 | |
#elif defined(_MSC_VER) | |
#define CPLATFORM_COMPILER_MSVC 1 | |
#endif // defined(_MSC_VER) | |
#ifndef CPLATFORM_COMPILER_CLANG | |
#define CPLATFORM_COMPILER_CLANG 0 | |
#endif // CPLATFORM_COMPILER_CLANG | |
#ifndef CPLATFORM_COMPILER_GCC | |
#define CPLATFORM_COMPILER_GCC 0 | |
#endif // CPLATFORM_COMPILER_GCC | |
#ifndef CPLATFORM_COMPILER_MSVC | |
#define CPLATFORM_COMPILER_MSVC 0 | |
#endif // CPLATFORM_COMPILER_MSVC | |
#if CPLATFORM_COMPILER_CLANG == 0 && CPLATFORM_COMPILER_GCC == 0 && CPLATFORM_COMPILER_MSVC == 0 | |
#define CPLATFORM_COMPILER_UNKNOWN 1 | |
#else | |
#define CPLATFORM_COMPILER_UNKNOWN 0 | |
#endif // CPLATFORM_COMPILER_CLANG == 0 || CPLATFORM_COMPILER_GCC == 0 || CPLATFORM_COMPILER_MSVC == 0 | |
// Clang and GCC shared definitions | |
#if CPLATFORM_COMPILER_CLANG == 1 || CPLATFORM_COMPILER_GCC == 1 | |
#define CPLATFORM_PACKED(n) __attribute__((packed, aligned(n))) | |
#define CPLATFORM_FUNCTION_NAME __PRETTY_FUNCTION__ | |
#define CPLATFORM_FORCE_INLINE inline __attribute__((always_inline)) | |
#define CPLATFORM_PRINTFLIKE(fmt, firstvararg) __attribute__((__format__ (__printf__, fmt, firstvararg))) | |
#define CPLATFORM_LIKELY(statement) __builtin_expect((statement), 1) | |
#define CPLATFORM_UNLIKELY(statement) __builtin_expect((statement), 0) | |
#define CPLATFORM_EXPORT_SYMBOL __attribute__ ((visibility("default"))) | |
#endif // CPLATFORM_COMPILER_CLANG || CPLATFORM_COMPILER_GCC | |
// Compiler-specific non-shared definitions | |
#if CPLATFORM_COMPILER_CLANG == 1 | |
#define CPLATFORM_PUSH_WARNING _Pragma("clang diagnostic push") | |
#define CPLATFORM_POP_WARNING _Pragma("clang diagnostic pop") | |
#define CPLATFORM_DISABLE_WARNING_CLANG(W) _Pragma(CPLATFORM_STRINGIFY(clang diagnostic ignored W)) | |
#elif CPLATFORM_COMPILER_GCC == 1 | |
#define CPLATFORM_PUSH_WARNING _Pragma("GCC diagnostic push") | |
#define CPLATFORM_POP_WARNING _Pragma("GCC diagnostic pop") | |
#define CPLATFORM_DISABLE_WARNING_GCC(W) _Pragma(CPLATFORM_STRINGIFY(GCC diagnostic ignored # W)) | |
#elif CPLATFORM_COMPILER_MSVC == 1 | |
// Displays type information, calling signature etc. much like __PRETTY_FUNCTION__ | |
// see: https://msdn.microsoft.com/en-us/library/b0084kay.aspx | |
#define CPLATFORM_FUNCTION_NAME __FUNCSIG__ | |
#define CPLATFORM_FORCE_INLINE __forceinline | |
#define CPLATFORM_PRINTFLIKE(fmt, firstvararg) | |
#define CPLATFORM_PUSH_WARNING __pragma(warning( push )) | |
#define CPLATFORM_DISABLE_WARNING_MSVC(w) __pragma(warning( disable: w )) | |
#define CPLATFORM_POP_WARNING __pragma(warning( pop )) | |
#define CPLATFORM_DISABLE_WARNING_CLANG(w) | |
#define CPLATFORM_LIKELY(statement) (statement) | |
#define CPLATFORM_UNLIKELY(statement) (statement) | |
#if _WIN64 | |
#else | |
#define CPLATFORM_ARCH_32BIT | |
#endif // _WIN64 | |
#endif // CPLATFORM_COMPILER_* | |
#ifndef CPLATFORM_DISABLE_WARNING_CLANG | |
#define CPLATFORM_DISABLE_WARNING_CLANG(W) | |
#endif // CPLATFORM_DISABLE_WARNING_CLANG | |
#ifndef CPLATFORM_DISABLE_WARNING_GCC | |
#define CPLATFORM_DISABLE_WARNING_GCC(W) | |
#endif // CPLATFORM_DISABLE_WARNING_GCC | |
#ifndef CPLATFORM_DISABLE_WARNING_MSVC | |
#define CPLATFORM_DISABLE_WARNING_MSVC(W) | |
#endif // CPLATFORM_DISABLE_WARNING_MSVC | |
// Define dllexport/import for windows if compiler is MSVC or Clang (supported in clang since at least v3.5) | |
#if CPLATFORM_OS_WINDOWS == 1 && CPLATFORM_COMPILER_GCC == 0 | |
#ifdef CPLATFORM_DLL | |
#undef CPLATFORM_EXPORT_SYMBOL | |
#undef CPLATFORM_IMPORT_SYMBOL | |
#define CPLATFORM_EXPORT_SYMBOL __declspec(dllexport) | |
#define CPLATFORM_IMPORT_SYMBOL __declspec(dllimport) | |
#endif // CPLATFORM_DLL | |
#endif | |
#ifndef CPLATFORM_EXPORT_SYMBOL | |
#define CPLATFORM_EXPORT_SYMBOL | |
#endif // CPLATFORM_EXPORT_SYMBOL | |
#ifndef CPLATFORM_IMPORT_SYMBOL | |
#define CPLATFORM_IMPORT_SYMBOL | |
#endif // CPLATFORM_IMPORT_SYMBOL | |
#if defined(__OBJC__) | |
#define CPLATFORM_OBJC_RELEASE(object) [object release], (object) = nil | |
#else | |
#define CPLATFORM_OBJC_RELEASE | |
#endif // defined(__OBJC__) | |
/* | |
********************************************************************************************************************** | |
* | |
* # Processor architecture | |
* | |
* this only works for x86_64 currently. | |
* see: http://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros | |
* | |
********************************************************************************************************************** | |
*/ | |
#if defined(__x86_64__) || defined(_M_X64) | |
#define CPLATFORM_ARCH_64BIT 1 | |
#define CPLATFORM_ARCH_BITS 64 | |
#else | |
#define CPLATFORM_ARCH_32BIT 1 | |
#define CPLATFORM_ARCH_BITS 32 | |
#endif // Processor arch | |
/* | |
******************************************************** | |
* | |
* # Endianness | |
* Only present if supplied by build system so define | |
* as little endian by default if missing | |
* | |
******************************************************* | |
*/ | |
#if !defined(CPLATFORM_BIG_ENDIAN) && !defined(CPLATFORM_LITTLE_ENDIAN) | |
#define CPLATFORM_LITTLE_ENDIAN | |
#endif // CPLATFORM_LITTLE_ENDIAN | |
/* | |
************************************************** | |
* | |
* # Assertion configuration | |
* allow user to force assertions on if needed | |
* | |
************************************************** | |
*/ | |
#if CPLATFORM_FORCE_ASSERTIONS_ENABLED == 1 | |
#define CPLATFORM_ENABLE_ASSERTIONS CPLATFORM_FORCE_ASSERTIONS_ENABLED | |
#else | |
#if CPLATFORM_DEBUG == 1 | |
#define CPLATFORM_ENABLE_ASSERTIONS 1 | |
#else | |
#define CPLATFORM_ENABLE_ASSERTIONS 0 | |
#endif // CPLATFORM_DEBUG == 1 | |
#endif // !defined(CPLATFORM_FORCE_ASSERTIONS_ENABLED) | |
/* | |
************************************************** | |
* | |
* # Utilities | |
* these are concise and reused enough across | |
* different files that they warrant being added | |
* to config.h | |
* | |
************************************************** | |
*/ | |
#define CPLATFORM_BEGIN_MACRO_BLOCK do { | |
#define CPLATFORM_END_MACRO_BLOCK } while (false) | |
#define CPLATFORM_EXPLICIT_SCOPE(x) do { x } while (false) | |
#define CPLATFORM_MIN(X, Y) ((X) < (Y) ? (X) : (Y)) | |
#define CPLATFORM_MAX(X, Y) ((X) >= (Y) ? (X) : (Y)) | |
#define CPLATFORM_ROUND_UP(SIZE, ALIGNMENT) (((SIZE) + (ALIGNMENT) - 1) & ~((ALIGNMENT) - 1)) | |
#define CPLATFORM_UNUSED(x) (void)(x) | |
// Allows using NOLINT for clang-tidy inside macros | |
#define CPLATFORM_NOLINT(...) __VA_ARGS__ // NOLINT | |
#if CPLATFORM_OS_WINDOWS == 1 | |
#define CPLATFORM_PATH_SEPARATOR '\\' | |
#else | |
#define CPLATFORM_PATH_SEPARATOR '/' | |
#endif // CPLATFORM_OS_WINDOWS == 1 | |
// Macros for working with explicit struct padding | |
#ifdef __cplusplus | |
#define CPLATFORM_PAD(N) char CPLATFORM_CONCAT(padding, __LINE__)[N] { 0 } | |
#else | |
#define CPLATFORM_PAD(N) char CPLATFORM_CONCAT(padding, __LINE__)[N] | |
#endif // __cplusplus | |
#define CPLATFORM_DISABLE_PADDING_WARNINGS CPLATFORM_DISABLE_WARNING_MSVC(4121 4820) | |
/* | |
********************************************************************************** | |
* | |
* # CPLATFORM_ALLOCA & CPLATFORM_ALLOCA_ARRAY | |
* | |
* Portable alloca implementations - CPLATFORM_ALLOCA_ARRAY | |
* calls CPLATFORM_ALLOCA with size==sizeof(T)*count and alignment==alignof(T) | |
* | |
********************************************************************************** | |
*/ | |
// Must be a macro because even a FORCE_INLINE function may possibly free the memory | |
#if CPLATFORM_OS_WINDOWS == 1 | |
#define CPLATFORM_ALLOCA(SIZE, ALIGNMENT) (_alloca(CPLATFORM_ROUND_UP(SIZE, ALIGNMENT))) | |
#else | |
#define CPLATFORM_ALLOCA(SIZE, ALIGNMENT) (alloca(CPLATFORM_ROUND_UP(SIZE, ALIGNMENT))) | |
#endif // CPLATFORM_OS_WINDOWS == 1 | |
#ifdef __cplusplus | |
#define CPLATFORM_ALLOCA_ARRAY(T, SIZE) (static_cast<T*>(CPLATFORM_ALLOCA(sizeof(T) * SIZE, alignof(T)))) | |
#else | |
#define CPLATFORM_ALLOCA_ARRAY(T, SIZE) ((T*)CPLATFORM_ALLOCA(sizeof(T) * (SIZE), _Alignof(T))) | |
#endif // __cplusplus | |
/* | |
************** | |
* | |
* C++ utils | |
* | |
************** | |
*/ | |
#ifdef __cplusplus | |
/* | |
* # CPLATFORM_MOVE | |
* | |
* this is a replacement for std::forward used to avoid having to include <utility> (which also includes <type_traits>) | |
*/ | |
#define CPLATFORM_FORWARD(...) static_cast<decltype(__VA_ARGS__)&&>(__VA_ARGS__) | |
namespace ccmd { | |
#ifndef CPLATFORM_STATIC_ARRAY_LENGTH_INLINE | |
#define CPLATFORM_STATIC_ARRAY_LENGTH_INLINE | |
template <typename T, int Size> | |
inline constexpr int static_array_length(T(&)[Size]) | |
{ | |
return Size; | |
} | |
#endif // CPLATFORM_STATIC_ARRAY_LENGTH_INLINE | |
} // namespace ccmd | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment