2018-10-06 20:37:09 -07:00
|
|
|
#pragma once
|
2014-04-20 02:14:15 -07:00
|
|
|
|
2019-08-15 17:03:56 -07:00
|
|
|
#include <ostream>
|
2016-03-04 15:00:12 -08:00
|
|
|
#include "athena/Types.hpp"
|
2014-04-20 02:14:15 -07:00
|
|
|
|
2019-07-19 21:19:44 -07:00
|
|
|
#include <fmt/format.h>
|
|
|
|
|
2014-12-28 20:46:43 -08:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning(disable : 4996)
|
2015-06-19 21:40:15 -07:00
|
|
|
|
2017-12-05 19:22:03 -08:00
|
|
|
#if defined(WINAPI_FAMILY) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP
|
|
|
|
#define WINDOWS_STORE 1
|
|
|
|
#else
|
|
|
|
#define WINDOWS_STORE 0
|
|
|
|
#endif
|
|
|
|
|
2015-06-19 21:40:15 -07:00
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
|
2017-01-03 10:32:56 -08:00
|
|
|
#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
|
2015-06-19 21:40:15 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
|
2017-01-03 10:32:56 -08:00
|
|
|
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
|
2015-06-19 21:40:15 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !defined(S_ISLNK)
|
|
|
|
#define S_ISLNK(m) 0
|
|
|
|
#endif
|
2019-10-19 03:39:44 -07:00
|
|
|
#endif // _MSC_VER
|
2015-06-19 21:40:15 -07:00
|
|
|
|
2017-01-03 10:32:56 -08:00
|
|
|
// clang-format off
|
2014-12-28 20:46:43 -08:00
|
|
|
#ifndef AT_PRETTY_FUNCTION
|
2015-05-03 20:57:00 -07:00
|
|
|
# if defined(__PRETTY_FUNCTION__) || defined(__GNUC__)
|
2014-12-28 20:46:43 -08:00
|
|
|
# define AT_PRETTY_FUNCTION __PRETTY_FUNCTION__
|
|
|
|
# elif defined(__FUNCSIG__)
|
|
|
|
# define AT_PRETTY_FUNCTION __FUNCSIG__
|
2014-06-02 20:09:40 -07:00
|
|
|
# elif defined(__FUNCTION__)
|
2014-12-28 20:46:43 -08:00
|
|
|
# define AT_PRETTY_FUNCTION __FUNCTION__
|
2014-06-02 20:09:40 -07:00
|
|
|
# elif defined(__FUNC__)
|
2014-12-28 20:46:43 -08:00
|
|
|
# define AT_PRETTY_FUNCTION __FUNC__
|
2014-06-02 20:09:40 -07:00
|
|
|
# elif defined(__func__)
|
2014-12-28 20:46:43 -08:00
|
|
|
# define AT_PRETTY_FUNCTION __func__
|
2014-06-02 20:09:40 -07:00
|
|
|
# else
|
2014-12-28 20:46:43 -08:00
|
|
|
# define AT_PRETTY_FUNCTION "<unknown>"
|
2014-06-02 20:09:40 -07:00
|
|
|
# endif
|
2014-05-14 22:42:20 -07:00
|
|
|
#endif
|
2017-01-03 10:32:56 -08:00
|
|
|
// clang-format on
|
2015-05-20 21:57:27 -07:00
|
|
|
|
2022-08-03 15:16:30 -07:00
|
|
|
#if defined(GEKKO) || defined(__SWITCH__) || defined(EMSCRIPTEN)
|
2015-05-20 21:57:27 -07:00
|
|
|
#include "gekko_support.h"
|
2016-10-15 11:40:39 -07:00
|
|
|
typedef struct stat atStat64_t;
|
|
|
|
#define atStat64 stat
|
2015-06-19 21:40:15 -07:00
|
|
|
#elif _WIN32
|
2016-10-15 11:40:39 -07:00
|
|
|
typedef struct _stat64 atStat64_t;
|
2016-10-19 17:51:38 -07:00
|
|
|
#define atStat64 _stat64
|
2016-10-15 11:40:39 -07:00
|
|
|
#elif __APPLE__ || __FreeBSD__
|
|
|
|
typedef struct stat atStat64_t;
|
|
|
|
#define atStat64 stat
|
2015-05-20 21:57:27 -07:00
|
|
|
#else
|
2016-10-15 11:40:39 -07:00
|
|
|
typedef struct stat64 atStat64_t;
|
2016-10-15 12:17:06 -07:00
|
|
|
#define atStat64 stat64
|
2015-05-20 21:57:27 -07:00
|
|
|
#endif
|
|
|
|
|
2014-04-20 02:14:15 -07:00
|
|
|
#ifndef BLOCKSZ
|
|
|
|
#define BLOCKSZ 512
|
|
|
|
#endif
|
|
|
|
|
2016-04-03 19:26:47 -07:00
|
|
|
#define ROUND_UP_256(val) (((val) + 255) & ~255)
|
2016-04-03 19:31:25 -07:00
|
|
|
#define ROUND_UP_64(val) (((val) + 63) & ~63)
|
2015-04-10 17:04:13 -07:00
|
|
|
#define ROUND_UP_32(val) (((val) + 31) & ~31)
|
|
|
|
#define ROUND_UP_16(val) (((val) + 15) & ~15)
|
2017-01-03 21:24:31 -08:00
|
|
|
#define ROUND_UP_8(val) (((val) + 7) & ~7)
|
2016-03-30 23:17:05 -07:00
|
|
|
#define ROUND_UP_4(val) (((val) + 3) & ~3)
|
2015-04-10 17:04:13 -07:00
|
|
|
|
2016-04-03 19:26:47 -07:00
|
|
|
#define _XSTR(s) _STR(s)
|
|
|
|
#define _STR(s) #s
|
|
|
|
|
2015-11-21 20:20:15 -08:00
|
|
|
#ifndef ENABLE_BITWISE_ENUM
|
2017-01-03 10:32:56 -08:00
|
|
|
#define ENABLE_BITWISE_ENUM(type) \
|
2019-09-07 09:39:49 -07:00
|
|
|
constexpr type operator|(type a, type b) noexcept { \
|
2018-12-07 21:18:17 -08:00
|
|
|
using T = std::underlying_type_t<type>; \
|
|
|
|
return type(static_cast<T>(a) | static_cast<T>(b)); \
|
|
|
|
} \
|
2019-09-07 09:39:49 -07:00
|
|
|
constexpr type operator&(type a, type b) noexcept { \
|
2018-12-07 21:18:17 -08:00
|
|
|
using T = std::underlying_type_t<type>; \
|
|
|
|
return type(static_cast<T>(a) & static_cast<T>(b)); \
|
|
|
|
} \
|
2019-09-07 09:39:49 -07:00
|
|
|
constexpr type& operator|=(type& a, type b) noexcept { \
|
2018-12-07 21:18:17 -08:00
|
|
|
using T = std::underlying_type_t<type>; \
|
|
|
|
a = type(static_cast<T>(a) | static_cast<T>(b)); \
|
|
|
|
return a; \
|
|
|
|
} \
|
2019-09-07 09:39:49 -07:00
|
|
|
constexpr type& operator&=(type& a, type b) noexcept { \
|
2018-12-07 21:18:17 -08:00
|
|
|
using T = std::underlying_type_t<type>; \
|
|
|
|
a = type(static_cast<T>(a) & static_cast<T>(b)); \
|
|
|
|
return a; \
|
|
|
|
} \
|
2019-09-07 09:39:49 -07:00
|
|
|
constexpr type operator~(type key) noexcept { \
|
2018-12-07 21:18:17 -08:00
|
|
|
using T = std::underlying_type_t<type>; \
|
|
|
|
return type(~static_cast<T>(key)); \
|
2019-04-02 21:28:05 -07:00
|
|
|
} \
|
2019-09-07 09:39:49 -07:00
|
|
|
constexpr bool True(type key) noexcept { \
|
2019-04-02 21:28:05 -07:00
|
|
|
using T = std::underlying_type_t<type>; \
|
|
|
|
return static_cast<T>(key) != 0; \
|
|
|
|
} \
|
2019-09-07 09:39:49 -07:00
|
|
|
constexpr bool False(type key) noexcept { \
|
2019-04-02 21:28:05 -07:00
|
|
|
using T = std::underlying_type_t<type>; \
|
|
|
|
return static_cast<T>(key) == 0; \
|
2018-12-07 21:18:17 -08:00
|
|
|
}
|
2015-11-21 20:20:15 -08:00
|
|
|
#endif
|
2015-11-20 17:11:23 -08:00
|
|
|
|
2018-12-07 21:18:17 -08:00
|
|
|
namespace athena {
|
|
|
|
namespace error {
|
|
|
|
enum class Level { Message, Warning, Error, Fatal };
|
2015-07-21 22:37:22 -07:00
|
|
|
}
|
2019-09-14 06:22:14 -07:00
|
|
|
enum class SeekOrigin { Begin, Current, End };
|
2018-12-07 21:18:17 -08:00
|
|
|
|
2019-09-23 15:37:07 -07:00
|
|
|
enum class Endian { Little, Big };
|
2018-12-07 21:18:17 -08:00
|
|
|
|
|
|
|
namespace io {
|
2018-02-21 23:18:59 -08:00
|
|
|
template <Endian DNAE>
|
|
|
|
struct DNA;
|
|
|
|
template <Endian DNAE>
|
|
|
|
struct DNAV;
|
|
|
|
|
|
|
|
template <class T>
|
2019-08-15 06:41:30 -07:00
|
|
|
using __IsDNARecord = std::disjunction<std::is_base_of<DNA<Endian::Big>, T>, std::is_base_of<DNA<Endian::Little>, T>>;
|
2018-02-21 23:18:59 -08:00
|
|
|
template <class T>
|
2019-08-15 05:46:55 -07:00
|
|
|
constexpr bool __IsDNARecord_v = __IsDNARecord<T>::value;
|
2018-02-26 22:02:24 -08:00
|
|
|
|
|
|
|
template <class T>
|
2018-12-07 21:18:17 -08:00
|
|
|
using __IsDNAVRecord =
|
2019-08-15 06:41:30 -07:00
|
|
|
std::disjunction<std::is_base_of<DNAV<Endian::Big>, T>, std::is_base_of<DNAV<Endian::Little>, T>>;
|
2018-02-26 22:02:24 -08:00
|
|
|
template <class T>
|
2019-08-15 05:46:55 -07:00
|
|
|
constexpr bool __IsDNAVRecord_v = __IsDNAVRecord<T>::value;
|
2018-12-07 21:18:17 -08:00
|
|
|
} // namespace io
|
|
|
|
} // namespace athena
|
2014-04-20 02:14:15 -07:00
|
|
|
|
2019-07-19 21:19:44 -07:00
|
|
|
typedef void (*atEXCEPTION_HANDLER)(athena::error::Level level, const char* /*file*/, const char*, int /*line*/,
|
|
|
|
fmt::string_view fmt, fmt::format_args args);
|
2015-05-18 16:28:17 -07:00
|
|
|
|
|
|
|
atEXCEPTION_HANDLER atGetExceptionHandler();
|
2016-02-03 13:33:08 -08:00
|
|
|
/**
|
|
|
|
* atSetExceptionHandler is only meant to be used a the start and end of an application's lifetime,
|
|
|
|
* this function cannot be considered thread-safe, therefore modifying during runtime is not recommended.
|
|
|
|
*/
|
2015-05-18 16:28:17 -07:00
|
|
|
void atSetExceptionHandler(atEXCEPTION_HANDLER func);
|
|
|
|
|
2016-03-04 15:00:12 -08:00
|
|
|
std::ostream& operator<<(std::ostream& os, const athena::SeekOrigin& origin);
|
|
|
|
std::ostream& operator<<(std::ostream& os, const athena::Endian& endian);
|
2015-07-21 22:37:22 -07:00
|
|
|
|
2019-07-19 21:19:44 -07:00
|
|
|
template <typename First, typename... Rest>
|
|
|
|
constexpr auto __FIRST_ARG__(First first, Rest...) { return first; }
|
|
|
|
template <typename S, typename... Args>
|
2019-08-15 05:46:55 -07:00
|
|
|
auto __make_args_checked__(const S& format_str, Args&&... args) {
|
2021-04-06 09:54:56 -07:00
|
|
|
return fmt::make_args_checked<Args...>(format_str, std::forward<Args>(args)...);
|
2019-07-19 21:19:44 -07:00
|
|
|
}
|
|
|
|
|
2015-07-21 22:37:22 -07:00
|
|
|
#ifndef NDEBUG
|
2019-07-19 21:19:44 -07:00
|
|
|
#define atDebug(...) \
|
2018-12-07 21:18:17 -08:00
|
|
|
do { \
|
|
|
|
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
|
|
|
|
if (__handler) \
|
2019-07-19 21:19:44 -07:00
|
|
|
__handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, __FIRST_ARG__(__VA_ARGS__), \
|
|
|
|
__make_args_checked__(__VA_ARGS__)); \
|
2018-12-07 21:18:17 -08:00
|
|
|
} while (0)
|
2015-07-21 22:37:22 -07:00
|
|
|
#else
|
2019-07-19 21:19:44 -07:00
|
|
|
#define atDebug(...)
|
2015-07-21 22:37:22 -07:00
|
|
|
#endif
|
|
|
|
|
2019-07-19 21:19:44 -07:00
|
|
|
#define atMessage(...) \
|
2018-12-07 21:18:17 -08:00
|
|
|
do { \
|
|
|
|
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
|
|
|
|
if (__handler) \
|
2019-07-19 21:19:44 -07:00
|
|
|
__handler(athena::error::Level::Message, __FILE__, AT_PRETTY_FUNCTION, __LINE__, __FIRST_ARG__(__VA_ARGS__), \
|
|
|
|
__make_args_checked__(__VA_ARGS__)); \
|
2018-12-07 21:18:17 -08:00
|
|
|
} while (0)
|
2017-01-03 10:32:56 -08:00
|
|
|
|
2019-07-19 21:19:44 -07:00
|
|
|
#define atWarning(...) \
|
2018-12-07 21:18:17 -08:00
|
|
|
do { \
|
|
|
|
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
|
2019-07-19 21:19:44 -07:00
|
|
|
if (__handler) { \
|
|
|
|
__handler(athena::error::Level::Warning, __FILE__, AT_PRETTY_FUNCTION, __LINE__, __FIRST_ARG__(__VA_ARGS__), \
|
|
|
|
__make_args_checked__(__VA_ARGS__)); \
|
|
|
|
} \
|
2018-12-07 21:18:17 -08:00
|
|
|
} while (0)
|
2017-01-03 10:32:56 -08:00
|
|
|
|
2019-07-19 21:19:44 -07:00
|
|
|
#define atError(...) \
|
2018-12-07 21:18:17 -08:00
|
|
|
do { \
|
|
|
|
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
|
|
|
|
if (__handler) \
|
2019-07-19 21:19:44 -07:00
|
|
|
__handler(athena::error::Level::Error, __FILE__, AT_PRETTY_FUNCTION, __LINE__, __FIRST_ARG__(__VA_ARGS__), \
|
|
|
|
__make_args_checked__(__VA_ARGS__)); \
|
2018-12-07 21:18:17 -08:00
|
|
|
} while (0)
|
2017-01-03 10:32:56 -08:00
|
|
|
|
2019-07-19 21:19:44 -07:00
|
|
|
#define atFatal(...) \
|
2018-12-07 21:18:17 -08:00
|
|
|
do { \
|
|
|
|
atEXCEPTION_HANDLER __handler = atGetExceptionHandler(); \
|
|
|
|
if (__handler) \
|
2019-07-19 21:19:44 -07:00
|
|
|
__handler(athena::error::Level::Fatal, __FILE__, AT_PRETTY_FUNCTION, __LINE__, __FIRST_ARG__(__VA_ARGS__), \
|
|
|
|
__make_args_checked__(__VA_ARGS__)); \
|
2018-12-07 21:18:17 -08:00
|
|
|
} while (0)
|