Silly macro removed-2

This commit is contained in:
Nekotekina
2016-08-14 03:22:19 +03:00
parent 5e0489dcc0
commit 0f87c4485d
38 changed files with 346 additions and 445 deletions
-1
View File
@@ -1,7 +1,6 @@
#pragma once
#include "types.h"
#include "Platform.h"
// Helper class, provides access to compiler-specific atomic intrinsics
template<typename T, std::size_t Size>
+4 -2
View File
@@ -1,7 +1,6 @@
#pragma once
#include "types.h"
#include "Platform.h"
// 128-bit vector type and also se_storage<> storage type
union alignas(16) v128
@@ -353,7 +352,10 @@ struct se_storage
static type copy(const type& src)
{
type result;
std::memcpy(&result, &src, Size);
for (std::size_t i = 0; i < Size; i++)
{
reinterpret_cast<u8*>(&result)[i] = reinterpret_cast<const u8*>(&src)[i];
}
return result;
}
};
+1 -1
View File
@@ -9,7 +9,7 @@ struct bf_base
using vtype = simple_t<type>;
// Datatype bitsize
static constexpr uint bitmax = sizeof(T) * CHAR_BIT; static_assert(N - 1 < bitmax, "bf_base<> error: N out of bounds");
static constexpr uint bitmax = sizeof(T) * 8; static_assert(N - 1 < bitmax, "bf_base<> error: N out of bounds");
// Field bitsize
static constexpr uint bitsize = N;
+20 -71
View File
@@ -1,6 +1,5 @@
#include "File.h"
#include "StrFmt.h"
#include "Macro.h"
#include "SharedMutex.h"
#include "BEType.h"
#include "Crypto/sha1.h"
@@ -22,10 +21,7 @@ static std::unique_ptr<wchar_t[]> to_wchar(const std::string& source)
std::unique_ptr<wchar_t[]> buffer(new wchar_t[buf_size]); // allocate buffer assuming that length is the max possible size
if (!MultiByteToWideChar(CP_UTF8, 0, source.c_str(), size, buffer.get(), size))
{
fmt::throw_exception("to_wchar(): MultiByteToWideChar() failed: error %u.", GetLastError());
}
verify("to_wchar" HERE), MultiByteToWideChar(CP_UTF8, 0, source.c_str(), size, buffer.get(), size);
return buffer;
}
@@ -38,14 +34,10 @@ static void to_utf8(std::string& result, const wchar_t* source)
result.resize(buf_size); // set max possible length for utf-8 + null terminator
if (const int nwritten = WideCharToMultiByte(CP_UTF8, 0, source, static_cast<int>(length) + 1, &result.front(), buf_size, NULL, NULL))
{
result.resize(nwritten - 1); // fix the size, remove null terminator
}
else
{
fmt::throw_exception("to_utf8(): WideCharToMultiByte() failed: error %u.", GetLastError());
}
const int nwritten = verify(WideCharToMultiByte(CP_UTF8, 0, source, static_cast<int>(length) + 1, &result.front(), buf_size, NULL, NULL), "to_utf8" HERE);
// fix the size, remove null terminator
result.resize(nwritten - 1);
}
static time_t to_time(const ULARGE_INTEGER& ft)
@@ -692,10 +684,7 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
stat_t stat() override
{
FILE_BASIC_INFO basic_info;
if (!GetFileInformationByHandleEx(m_handle, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO)))
{
fmt::throw_exception("Win32 error: %u." HERE, GetLastError());
}
verify("file::stat" HERE), GetFileInformationByHandleEx(m_handle, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO));
stat_t info;
info.is_directory = (basic_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
@@ -726,14 +715,8 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
return false;
}
const BOOL result = SetEndOfFile(m_handle); // change file size
if (!result || !SetFilePointerEx(m_handle, old, NULL, FILE_BEGIN)) // restore position
{
fmt::throw_exception("Win32 error: %u." HERE, GetLastError());
}
return result != FALSE;
verify("file::trunc" HERE), SetEndOfFile(m_handle), SetFilePointerEx(m_handle, old, NULL, FILE_BEGIN);
return true;
}
u64 read(void* buffer, u64 count) override
@@ -743,10 +726,7 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
EXPECTS(size >= 0);
DWORD nread;
if (!ReadFile(m_handle, buffer, size, &nread, NULL))
{
fmt::throw_exception("Win32 error: %u." HERE, GetLastError());
}
verify("file::read" HERE), ReadFile(m_handle, buffer, size, &nread, NULL);
return nread;
}
@@ -758,10 +738,7 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
EXPECTS(size >= 0);
DWORD nwritten;
if (!WriteFile(m_handle, buffer, size, &nwritten, NULL))
{
fmt::throw_exception("Win32 error: %u." HERE, GetLastError());
}
verify("file::write" HERE), WriteFile(m_handle, buffer, size, &nwritten, NULL);
return nwritten;
}
@@ -777,10 +754,7 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
whence == seek_end ? FILE_END :
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
if (!SetFilePointerEx(m_handle, pos, &pos, mode))
{
fmt::throw_exception("Win32 error: %u." HERE, GetLastError());
}
verify("file::seek" HERE), SetFilePointerEx(m_handle, pos, &pos, mode);
return pos.QuadPart;
}
@@ -788,10 +762,7 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
u64 size() override
{
LARGE_INTEGER size;
if (!GetFileSizeEx(m_handle, &size))
{
fmt::throw_exception("Win32 error: %u." HERE, GetLastError());
}
verify("file::size" HERE), GetFileSizeEx(m_handle, &size);
return size.QuadPart;
}
@@ -836,10 +807,7 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
stat_t stat() override
{
struct ::stat file_info;
if (::fstat(m_fd, &file_info) != 0)
{
fmt::throw_exception("System error: %d." HERE, errno);
}
verify("file::stat" HERE), ::fstat(m_fd, &file_info) == 0;
stat_t info;
info.is_directory = S_ISDIR(file_info.st_mode);
@@ -866,10 +834,7 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
u64 read(void* buffer, u64 count) override
{
const auto result = ::read(m_fd, buffer, count);
if (result == -1)
{
fmt::throw_exception("System error: %d." HERE, errno);
}
verify("file::read" HERE), result != -1;
return result;
}
@@ -877,10 +842,7 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
u64 write(const void* buffer, u64 count) override
{
const auto result = ::write(m_fd, buffer, count);
if (result == -1)
{
fmt::throw_exception("System error: %d." HERE, errno);
}
verify("file::write" HERE), result != -1;
return result;
}
@@ -894,10 +856,7 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
(fmt::throw_exception("Invalid whence (0x%x)" HERE, whence), 0);
const auto result = ::lseek(m_fd, offset, mode);
if (result == -1)
{
fmt::throw_exception("System error: %d." HERE, errno);
}
verify("file::seek" HERE), result != -1;
return result;
}
@@ -905,10 +864,7 @@ bool fs::file::open(const std::string& path, bs_t<open_mode> mode)
u64 size() override
{
struct ::stat file_info;
if (::fstat(m_fd, &file_info) != 0)
{
fmt::throw_exception("System error: %d." HERE, errno);
}
verify("file::size" HERE), ::fstat(m_fd, &file_info) == 0;
return file_info.st_size;
}
@@ -1048,12 +1004,8 @@ bool fs::dir::open(const std::string& path)
WIN32_FIND_DATAW found;
if (!FindNextFileW(m_handle, &found))
{
if (ERROR_NO_MORE_FILES == GetLastError())
{
return false;
}
fmt::throw_exception("Win32 error: %u." HERE, GetLastError());
verify("dir::read" HERE), ERROR_NO_MORE_FILES == GetLastError();
return false;
}
add_entry(found);
@@ -1103,10 +1055,7 @@ bool fs::dir::open(const std::string& path)
}
struct ::stat file_info;
if (::fstatat(::dirfd(m_dd), found->d_name, &file_info, 0) != 0)
{
fmt::throw_exception("System error: %d." HERE, errno);
}
verify("dir::read" HERE), ::fstatat(::dirfd(m_dd), found->d_name, &file_info, 0) == 0;
info.name = found->d_name;
info.is_directory = S_ISDIR(file_info.st_mode);
+3 -4
View File
@@ -1,12 +1,11 @@
#pragma once
#include "types.h"
#include "bit_set.h"
#include <memory>
#include <string>
#include <vector>
#include <type_traits>
#include "types.h"
#include "bit_set.h"
namespace fs
{
-1
View File
@@ -7,7 +7,6 @@
#include <array>
#include "types.h"
#include "Macro.h"
#include "StrFmt.h"
#include "File.h"
#include "Log.h"
-1
View File
@@ -1,7 +1,6 @@
#pragma once
#include "types.h"
#include "Platform.h"
#include "Atomic.h"
#include "StrFmt.h"
-43
View File
@@ -1,43 +0,0 @@
#pragma once
#include "types.h"
#define CHECK_SIZE(type, size) static_assert(sizeof(type) == size, "Invalid " #type " type size")
#define CHECK_ALIGN(type, align) static_assert(alignof(type) == align, "Invalid " #type " type alignment")
#define CHECK_MAX_SIZE(type, size) static_assert(sizeof(type) <= size, #type " type size is too big")
#define CHECK_SIZE_ALIGN(type, size, align) CHECK_SIZE(type, size); CHECK_ALIGN(type, align)
#define CHECK_STORAGE(type, storage) static_assert(sizeof(type) <= sizeof(storage) && alignof(type) <= alignof(decltype(storage)), #type " is too small")
// Return 32 bit sizeof() to avoid widening/narrowing conversions with size_t
#define SIZE_32(type) static_cast<std::uint32_t>(sizeof(type))
// Return 32 bit alignof() to avoid widening/narrowing conversions with size_t
#define ALIGN_32(type) static_cast<std::uint32_t>(alignof(type))
// Return 32 bit custom offsetof()
#define OFFSET_32(type, x) static_cast<std::uint32_t>(reinterpret_cast<std::uintptr_t>(&reinterpret_cast<const volatile char&>(reinterpret_cast<type*>(0ull)->x)))
#define CONCATENATE_DETAIL(x, y) x ## y
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
#define STRINGIZE_DETAIL(x) #x
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
// Macro set, wraps an expression into lambda
#define WRAP_EXPR(expr, ...) [&](__VA_ARGS__) { return expr; }
#define COPY_EXPR(expr, ...) [=](__VA_ARGS__) { return expr; }
#define PURE_EXPR(expr, ...) [] (__VA_ARGS__) { return expr; }
#define HERE "\n(in file " __FILE__ ":" STRINGIZE(__LINE__) ")"
// Ensure that the expression is evaluated to true. Always evaluated and allowed to have side effects (unlike assert() macro).
#define VERIFY(expr) do { if (!(expr)) fmt::raw_error("Verification failed: " #expr HERE); } while (0)
// EXPECTS() and ENSURES() are intended to check function arguments and results.
// Expressions are not guaranteed to evaluate.
#define EXPECTS(expr) do { if (!(expr)) fmt::raw_error("Precondition failed: " #expr HERE); } while (0)
#define ENSURES(expr) do { if (!(expr)) fmt::raw_error("Postcondition failed: " #expr HERE); } while (0)
#define DECLARE(...) decltype(__VA_ARGS__) __VA_ARGS__
#define STR_CASE(value) case value: return #value
-51
View File
@@ -1,51 +0,0 @@
#include "Platform.h"
#ifdef __APPLE__
#include <sys/types.h>
#include <sys/_types/_timespec.h>
#include <mach/mach.h>
#include <mach/clock.h>
#include <mach/mach_time.h>
#undef CPU_STATE_MAX
#define MT_NANO (+1.0E-9)
#define MT_GIGA UINT64_C(1000000000)
// TODO create a list of timers,
static double mt_timebase = 0.0;
static uint64_t mt_timestart = 0;
// TODO be more careful in a multithreaded environement
int clock_gettime(clockid_t clk_id, struct timespec *tp)
{
kern_return_t retval = KERN_SUCCESS;
if( clk_id == TIMER_ABSTIME)
{
if (!mt_timestart) { // only one timer, initilized on the first call to the TIMER
mach_timebase_info_data_t tb = { 0 };
mach_timebase_info(&tb);
mt_timebase = tb.numer;
mt_timebase /= tb.denom;
mt_timestart = mach_absolute_time();
}
double diff = (mach_absolute_time() - mt_timestart) * mt_timebase;
tp->tv_sec = diff * MT_NANO;
tp->tv_nsec = diff - (tp->tv_sec * MT_GIGA);
}
else // other clk_ids are mapped to the coresponding mach clock_service
{
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), clk_id, &cclock);
retval = clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
tp->tv_sec = mts.tv_sec;
tp->tv_nsec = mts.tv_nsec;
}
return retval;
}
#endif /* __APPLE__ */
-128
View File
@@ -1,128 +0,0 @@
#pragma once
#include <cstdint>
#include <immintrin.h>
#include <emmintrin.h>
#define IS_LE_MACHINE 1
#define IS_BE_MACHINE 0
#ifdef _MSC_VER
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
#ifdef _MSC_VER
#define ASSUME(cond) __assume(cond)
#define LIKELY(cond) (cond)
#define UNLIKELY(cond) (cond)
#else
#define ASSUME(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)
#define LIKELY(cond) __builtin_expect(!!(cond), 1)
#define UNLIKELY(cond) __builtin_expect(!!(cond), 0)
#endif
// Some platforms don't support thread_local well yet.
#ifndef _MSC_VER
#define thread_local __thread
#endif
#ifdef _MSC_VER
#define SAFE_BUFFERS __declspec(safebuffers)
#else
#define SAFE_BUFFERS
#endif
#ifdef _MSC_VER
#define NEVER_INLINE __declspec(noinline)
#else
#define NEVER_INLINE __attribute__((noinline))
#endif
#ifdef _MSC_VER
#define FORCE_INLINE __forceinline
#else
#define FORCE_INLINE __attribute__((always_inline)) inline
#endif
#if defined(__GNUG__)
#include <stdlib.h>
#define _fpclass(x) std::fpclassify(x)
#define INFINITE 0xFFFFFFFF
#ifdef __APPLE__
// XXX only supports a single timer
#define TIMER_ABSTIME -1
/* The opengroup spec isn't clear on the mapping from REALTIME to CALENDAR
being appropriate or not.
http://pubs.opengroup.org/onlinepubs/009695299/basedefs/time.h.html */
#define CLOCK_REALTIME 1 // #define CALENDAR_CLOCK 1 from mach/clock_types.h
#define CLOCK_MONOTONIC 0 // #define SYSTEM_CLOCK 0
typedef int clockid_t;
/* the mach kernel uses struct mach_timespec, so struct timespec
is loaded from <sys/_types/_timespec.h> for compatability */
// struct timespec { time_t tv_sec; long tv_nsec; };
int clock_gettime(clockid_t clk_id, struct timespec *tp);
#endif /* __APPLE__ */
#endif /* __GNUG__ */
inline std::uint32_t cntlz32(std::uint32_t arg)
{
#if defined(_MSC_VER)
unsigned long res;
return _BitScanReverse(&res, arg) ? res ^ 31 : 32;
#else
return arg ? __builtin_clzll(arg) - 32 : 32;
#endif
}
inline std::uint64_t cntlz64(std::uint64_t arg)
{
#if defined(_MSC_VER)
unsigned long res;
return _BitScanReverse64(&res, arg) ? res ^ 63 : 64;
#else
return arg ? __builtin_clzll(arg) : 64;
#endif
}
// Helper function, used by ""_u16, ""_u32, ""_u64
constexpr std::uint8_t to_u8(char c)
{
return static_cast<std::uint8_t>(c);
}
// Convert 2-byte string to u16 value like reinterpret_cast does
constexpr std::uint16_t operator""_u16(const char* s, std::size_t length)
{
return length != 2 ? throw s :
#if IS_LE_MACHINE == 1
to_u8(s[1]) << 8 | to_u8(s[0]);
#endif
}
// Convert 4-byte string to u32 value like reinterpret_cast does
constexpr std::uint32_t operator""_u32(const char* s, std::size_t length)
{
return length != 4 ? throw s :
#if IS_LE_MACHINE == 1
to_u8(s[3]) << 24 | to_u8(s[2]) << 16 | to_u8(s[1]) << 8 | to_u8(s[0]);
#endif
}
// Convert 8-byte string to u64 value like reinterpret_cast does
constexpr std::uint64_t operator""_u64(const char* s, std::size_t length)
{
return length != 8 ? throw s :
#if IS_LE_MACHINE == 1
static_cast<std::uint64_t>(to_u8(s[7]) << 24 | to_u8(s[6]) << 16 | to_u8(s[5]) << 8 | to_u8(s[4])) << 32 | to_u8(s[3]) << 24 | to_u8(s[2]) << 16 | to_u8(s[1]) << 8 | to_u8(s[0]);
#endif
}
-1
View File
@@ -2,7 +2,6 @@
#include "types.h"
#include "Atomic.h"
#include "Platform.h"
// Binary semaphore
class benaphore
-1
View File
@@ -2,7 +2,6 @@
#include "types.h"
#include "Atomic.h"
#include "Platform.h"
//! An attempt to create effective implementation of "shared mutex", lock-free in optimistic case.
//! All locking and unlocking may be done by a single LOCK XADD or LOCK CMPXCHG instruction.
+20 -7
View File
@@ -1,11 +1,16 @@
#include "StrFmt.h"
#include "BEType.h"
#include "StrUtil.h"
#include "Macro.h"
#include "cfmt.h"
#include <algorithm>
#ifdef _WIN32
#include <Windows.h>
#else
#include <errno.h>
#endif
void fmt_class_string<const void*>::format(std::string& out, u64 arg)
{
fmt::append(out, "%p", reinterpret_cast<const void*>(static_cast<std::uintptr_t>(arg)));
@@ -124,18 +129,26 @@ namespace fmt
{
void raw_error(const char* msg)
{
std::string out{"Error"};
out += ": ";
out += msg;
throw std::runtime_error{out};
throw std::runtime_error{msg};
}
void raw_verify_error(const char* msg, uint position)
{
std::string out{"Verification failed"};
// Print error code (may be irrelevant)
#ifdef _WIN32
if (DWORD error = GetLastError())
{
fmt::append(out, " (e%#x)", error);
}
#else
if (int error = errno)
{
fmt::append(out, " (e%d)", error);
}
#endif
if (position)
{
out += " (+";
+4 -4
View File
@@ -1,11 +1,11 @@
#pragma once
#include <exception>
#include <string>
#include "Platform.h"
#include "types.h"
#include <exception>
#include <stdexcept>
#include <string>
namespace fmt
{
template <typename... Args>
+3 -3
View File
@@ -1,12 +1,12 @@
#pragma once
#include "types.h"
#include "Atomic.h"
#include <exception>
#include <string>
#include <memory>
#include "Platform.h"
#include "Atomic.h"
// Will report exception and call std::abort() if put in catch(...)
[[noreturn]] void catch_all_exceptions();
+1 -1
View File
@@ -59,7 +59,7 @@ struct bs_base
__bitset_set_type = 0 // SFINAE marker
};
static constexpr std::size_t bitmax = sizeof(T) * CHAR_BIT;
static constexpr std::size_t bitmax = sizeof(T) * 8;
static constexpr std::size_t bitsize = static_cast<under>(T::__bitset_enum_max);
static_assert(std::is_enum<T>::value, "bs_t<> error: invalid type (must be enum)");
+3 -2
View File
@@ -1,6 +1,7 @@
#pragma once
#include "types.h"
#include <climits>
#include <string>
#include <vector>
#include <algorithm>
@@ -55,7 +56,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
const auto write_octal = [&](u64 value, u64 min_num)
{
out.resize(out.size() + std::max<u64>(min_num, 66 / 3 - (cntlz64(value | 1) + 2) / 3), '0');
out.resize(out.size() + std::max<u64>(min_num, 66 / 3 - (cntlz64(value | 1, true) + 2) / 3), '0');
// Write in reversed order
for (auto i = out.rbegin(); value; i++, value /= 8)
@@ -66,7 +67,7 @@ std::size_t cfmt_append(Dst& out, const Char* fmt, Src&& src)
const auto write_hex = [&](u64 value, bool upper, u64 min_num)
{
out.resize(out.size() + std::max<u64>(min_num, 64 / 4 - cntlz64(value | 1) / 4), '0');
out.resize(out.size() + std::max<u64>(min_num, 64 / 4 - cntlz64(value | 1, true) / 4), '0');
// Write in reversed order
for (auto i = out.rbegin(); value; i++, value /= 16)
-1
View File
@@ -2,7 +2,6 @@
#include "types.h"
#include "Atomic.h"
#include "Platform.h"
//! Simple sizeless array base for concurrent access. Cannot shrink, only growths automatically.
//! There is no way to know the current size. The smaller index is, the faster it's accessed.
-1
View File
@@ -3,7 +3,6 @@
/* For internal use. Don't include. */
#include "types.h"
#include "Macro.h"
#include "Atomic.h"
#ifdef _WIN32
+127 -5
View File
@@ -1,8 +1,77 @@
#pragma once
#ifdef _MSC_VER
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
#include <immintrin.h>
#include <emmintrin.h>
#include <cstdint>
#include <climits>
#include <type_traits>
#include <utility>
// Assume little-endian
#define IS_LE_MACHINE 1
#define IS_BE_MACHINE 0
#ifdef _MSC_VER
#define ASSUME(cond) __assume(cond)
#define LIKELY(cond) (cond)
#define UNLIKELY(cond) (cond)
#define SAFE_BUFFERS __declspec(safebuffers)
#define NEVER_INLINE __declspec(noinline)
#define FORCE_INLINE __forceinline
#else
#define ASSUME(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)
#define LIKELY(cond) __builtin_expect(!!(cond), 1)
#define UNLIKELY(cond) __builtin_expect(!!(cond), 0)
#define SAFE_BUFFERS
#define NEVER_INLINE __attribute__((noinline))
#define FORCE_INLINE __attribute__((always_inline)) inline
// Some platforms don't support thread_local well yet.
#define thread_local __thread
#endif
#define CHECK_SIZE(type, size) static_assert(sizeof(type) == size, "Invalid " #type " type size")
#define CHECK_ALIGN(type, align) static_assert(alignof(type) == align, "Invalid " #type " type alignment")
#define CHECK_MAX_SIZE(type, size) static_assert(sizeof(type) <= size, #type " type size is too big")
#define CHECK_SIZE_ALIGN(type, size, align) CHECK_SIZE(type, size); CHECK_ALIGN(type, align)
#define CHECK_STORAGE(type, storage) static_assert(sizeof(type) <= sizeof(storage) && alignof(type) <= alignof(decltype(storage)), #type " is too small")
// Return 32 bit sizeof() to avoid widening/narrowing conversions with size_t
#define SIZE_32(...) static_cast<u32>(sizeof(__VA_ARGS__))
// Return 32 bit alignof() to avoid widening/narrowing conversions with size_t
#define ALIGN_32(...) static_cast<u32>(alignof(__VA_ARGS__))
// Return 32 bit offsetof()
#define OFFSET_32(type, x) static_cast<u32>(reinterpret_cast<std::uintptr_t>(&reinterpret_cast<const volatile char&>(reinterpret_cast<type*>(0ull)->x)))
#define CONCATENATE_DETAIL(x, y) x ## y
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
#define STRINGIZE_DETAIL(x) #x
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
#define HERE "\n(in file " __FILE__ ":" STRINGIZE(__LINE__) ")"
// Wrap an expression into lambda
#define WRAP_EXPR(...) [&] { return __VA_ARGS__; }
// Ensure that the expression is evaluated to true. Always evaluated and allowed to have side effects (unlike assert() macro).
#define VERIFY(...) do { if (!(__VA_ARGS__)) fmt::raw_error("Verification failed: " #__VA_ARGS__ HERE); } while (0)
// EXPECTS() and ENSURES() are intended to check function arguments and results.
// Expressions are not guaranteed to evaluate.
#define EXPECTS(...) do { if (!(__VA_ARGS__)) fmt::raw_error("Precondition failed: " #__VA_ARGS__ HERE); } while (0)
#define ENSURES(...) do { if (!(__VA_ARGS__)) fmt::raw_error("Postcondition failed: " #__VA_ARGS__ HERE); } while (0)
#define DECLARE(...) decltype(__VA_ARGS__) __VA_ARGS__
#define STR_CASE(...) case __VA_ARGS__: return #__VA_ARGS__
using schar = signed char;
using uchar = unsigned char;
@@ -159,8 +228,6 @@ using u128 = __uint128_t;
using s128 = __int128_t;
#else
#include "intrin.h"
// Unsigned 128-bit integer implementation (TODO)
struct alignas(16) u128
{
@@ -342,8 +409,8 @@ struct alignas(16) s128
};
#endif
static_assert(alignof(u128) == 16 && sizeof(u128) == 16, "Wrong u128 implementation");
static_assert(alignof(s128) == 16 && sizeof(s128) == 16, "Wrong s128 implementation");
CHECK_SIZE_ALIGN(u128, 16, 16);
CHECK_SIZE_ALIGN(s128, 16, 16);
union alignas(2) f16
{
@@ -366,6 +433,8 @@ union alignas(2) f16
}
};
CHECK_SIZE_ALIGN(f16, 2, 2);
using f32 = float;
using f64 = double;
@@ -383,6 +452,59 @@ constexpr T align(const T& value, std::uint64_t align)
return static_cast<T>((value + (align - 1)) & ~(align - 1));
}
inline std::uint32_t cntlz32(std::uint32_t arg, bool nonzero = false)
{
#if defined(_MSC_VER)
unsigned long res;
return _BitScanReverse(&res, arg) || nonzero ? res ^ 31 : 32;
#else
return arg || nonzero ? __builtin_clzll(arg) - 32 : 32;
#endif
}
inline std::uint64_t cntlz64(std::uint64_t arg, bool nonzero = false)
{
#if defined(_MSC_VER)
unsigned long res;
return _BitScanReverse64(&res, arg) || nonzero ? res ^ 63 : 64;
#else
return arg || nonzero ? __builtin_clzll(arg) : 64;
#endif
}
// Helper function, used by ""_u16, ""_u32, ""_u64
constexpr std::uint8_t to_u8(char c)
{
return static_cast<std::uint8_t>(c);
}
// Convert 2-byte string to u16 value like reinterpret_cast does
constexpr std::uint16_t operator""_u16(const char* s, std::size_t length)
{
return length != 2 ? throw s :
#if IS_LE_MACHINE == 1
to_u8(s[1]) << 8 | to_u8(s[0]);
#endif
}
// Convert 4-byte string to u32 value like reinterpret_cast does
constexpr std::uint32_t operator""_u32(const char* s, std::size_t length)
{
return length != 4 ? throw s :
#if IS_LE_MACHINE == 1
to_u8(s[3]) << 24 | to_u8(s[2]) << 16 | to_u8(s[1]) << 8 | to_u8(s[0]);
#endif
}
// Convert 8-byte string to u64 value like reinterpret_cast does
constexpr std::uint64_t operator""_u64(const char* s, std::size_t length)
{
return length != 8 ? throw s :
#if IS_LE_MACHINE == 1
static_cast<std::uint64_t>(to_u8(s[7]) << 24 | to_u8(s[6]) << 16 | to_u8(s[5]) << 8 | to_u8(s[4])) << 32 | to_u8(s[3]) << 24 | to_u8(s[2]) << 16 | to_u8(s[1]) << 8 | to_u8(s[0]);
#endif
}
namespace fmt
{
[[noreturn]] void raw_error(const char* msg);