#pragma once #include #include #include #include #include #include #include #include #include #include #include #ifdef __MINGW32__ #include #else #include #endif #if defined(__APPLE__) || defined(__FreeBSD__) #define off64_t off_t #define fopen64 fopen #define fseeko64 fseek #define ftello64 ftell #endif namespace hex { template struct is_integral_helper : public std::false_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template<> struct is_integral_helper : public std::true_type { }; template struct is_integral : public is_integral_helper>::type { }; template struct is_signed_helper : public std::false_type { }; template<> struct is_signed_helper : public std::true_type { }; template<> struct is_signed_helper : public std::true_type { }; template<> struct is_signed_helper : public std::true_type { }; template<> struct is_signed_helper : public std::true_type { }; template<> struct is_signed_helper : public std::true_type { }; template<> struct is_signed_helper : public std::true_type { }; template<> struct is_signed_helper : public std::true_type { }; template<> struct is_signed_helper : public std::true_type { }; template<> struct is_signed_helper : public std::true_type { }; template struct is_signed : public is_signed_helper>::type { }; template struct is_floating_point_helper : public std::false_type { }; template<> struct is_floating_point_helper : public std::true_type { }; template<> struct is_floating_point_helper : public std::true_type { }; template<> struct is_floating_point_helper : public std::true_type { }; template struct is_floating_point : public is_floating_point_helper>::type { }; } #if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 12000 #if __has_include() // Make sure we break when derived_from is implemented in libc++. Then we can fix a compatibility version above #include #endif // libcxx 12 still doesn't have many default concepts implemented, as a result we need to define it ourself using clang built-ins. // [concept.derived] (patch from https://reviews.llvm.org/D74292) namespace hex { template concept derived_from = __is_base_of(_Bp, _Dp) && __is_convertible_to(const volatile _Dp*, const volatile _Bp*); } #else // Assume supported #include namespace hex { using std::derived_from; } #endif // [concepts.arithmetic] namespace hex { template concept integral = hex::is_integral<_Tp>::value; template concept signed_integral = integral<_Tp> && hex::is_signed<_Tp>::value; template concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; template concept floating_point = std::is_floating_point<_Tp>::value; } #define TOKEN_CONCAT_IMPL(x, y) x ## y #define TOKEN_CONCAT(x, y) TOKEN_CONCAT_IMPL(x, y) #define ANONYMOUS_VARIABLE(prefix) TOKEN_CONCAT(prefix, __COUNTER__) namespace hex { std::string to_string(u128 value); std::string to_string(s128 value); std::string toByteString(u64 bytes); std::string makePrintable(char c); void openWebpage(std::string_view url); template inline std::string format(std::string_view format, Args ... args) { return fmt::format(fmt::runtime(format), args...); } template inline void print(std::string_view format, Args ... args) { fmt::print(fmt::runtime(format), args...); } [[nodiscard]] constexpr inline u64 extract(u8 from, u8 to, const hex::unsigned_integral auto &value) { using ValueType = std::remove_cvref_t; ValueType mask = (std::numeric_limits::max() >> (((sizeof(value) * 8) - 1) - (from - to))) << to; return (value & mask) >> to; } template struct always_false : std::false_type {}; template struct overloaded : Ts... { using Ts::operator()...; }; template overloaded(Ts...) -> overloaded; template constexpr T changeEndianess(T value, std::endian endian) { if (endian == std::endian::native) return value; if constexpr (sizeof(T) == 1) return value; else if constexpr (sizeof(T) == 2) return __builtin_bswap16(value); else if constexpr (sizeof(T) == 4) return __builtin_bswap32(value); else if constexpr (sizeof(T) == 8) return __builtin_bswap64(value); else if constexpr (sizeof(T) == 16) return T(__builtin_bswap64(value & 0xFFFF'FFFF'FFFF'FFFF)) << 64 | __builtin_bswap64(value >> 64); else static_assert(always_false::value, "Invalid type provided!"); } template constexpr T changeEndianess(T value, size_t size, std::endian endian) { if (endian == std::endian::native) return value; if (size == 1) return value; else if (size == 2) return __builtin_bswap16(value); else if (size == 4) return __builtin_bswap32(value); else if (size == 8) return __builtin_bswap64(value); else if (size == 16) return u128(__builtin_bswap64(u128(value) & 0xFFFF'FFFF'FFFF'FFFF)) << 64 | __builtin_bswap64(u128(value) >> 64); else throw std::invalid_argument("Invalid value size!"); } template< class T > constexpr T bit_width(T x) noexcept { return std::numeric_limits::digits - std::countl_zero(x); } template constexpr T bit_ceil(T x) noexcept { if (x <= 1u) return T(1); return T(1) << bit_width(T(x - 1)); } std::vector splitString(std::string_view string, std::string_view delimiter); std::string combineStrings(const std::vector &strings, std::string_view delimiter = ""); std::string toEngineeringString(double value); std::vector readFile(std::string_view path); template std::vector toBytes(T value) { std::vector bytes(sizeof(T)); std::memcpy(bytes.data(), &value, sizeof(T)); return bytes; } inline std::vector parseByteString(std::string_view string) { auto byteString = std::string(string); byteString.erase(std::remove(byteString.begin(), byteString.end(), ' '), byteString.end()); if ((byteString.length() % 2) != 0) return { }; std::vector result; for (u32 i = 0; i < byteString.length(); i += 2) { if (!std::isxdigit(byteString[i]) || !std::isxdigit(byteString[i + 1])) return { }; result.push_back(std::strtoul(byteString.substr(i, 2).c_str(), nullptr, 16)); } return result; } inline std::string toBinaryString(hex::unsigned_integral auto number) { if (number == 0) return "0"; std::string result; for (s16 bit = hex::bit_width(number) - 1; bit >= 0; bit--) result += (number & (0b1 << bit)) == 0 ? '0' : '1'; return result; } inline void trimLeft(std::string &s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); } inline void trimRight(std::string &s) { s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); } inline void trim(std::string &s) { trimLeft(s); trimRight(s); } enum class ImHexPath { Patterns, PatternsInclude, Magic, Python, Plugins, Yara, Config, Resources, Constants }; std::vector getPath(ImHexPath path); #define SCOPE_GUARD ::hex::ScopeGuardOnExit() + [&]() #define ON_SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_) = SCOPE_GUARD template class ScopeGuard { private: F m_func; bool m_active; public: constexpr ScopeGuard(F func) : m_func(std::move(func)), m_active(true) { } ~ScopeGuard() { if (this->m_active) { this->m_func(); } } void release() { this->m_active = false; } ScopeGuard(ScopeGuard &&other) noexcept : m_func(std::move(other.m_func)), m_active(other.m_active) { other.cancel(); } ScopeGuard& operator=(ScopeGuard &&) = delete; }; enum class ScopeGuardOnExit { }; template constexpr ScopeGuard operator+(ScopeGuardOnExit, F&& f) { return ScopeGuard(std::forward(f)); } struct Region { u64 address; size_t size; }; }