[ox/std] Add oxTracef
This commit is contained in:
parent
ef6673067b
commit
55a4f2451e
1
deps/ox/src/ox/std/CMakeLists.txt
vendored
1
deps/ox/src/ox/std/CMakeLists.txt
vendored
@ -60,6 +60,7 @@ install(
|
|||||||
byteswap.hpp
|
byteswap.hpp
|
||||||
defines.hpp
|
defines.hpp
|
||||||
error.hpp
|
error.hpp
|
||||||
|
fmt.hpp
|
||||||
hardware.hpp
|
hardware.hpp
|
||||||
hashmap.hpp
|
hashmap.hpp
|
||||||
heapmgr.hpp
|
heapmgr.hpp
|
||||||
|
13
deps/ox/src/ox/std/bstring.hpp
vendored
13
deps/ox/src/ox/std/bstring.hpp
vendored
@ -45,6 +45,8 @@ class BString {
|
|||||||
|
|
||||||
constexpr char &operator[](std::size_t i) noexcept;
|
constexpr char &operator[](std::size_t i) noexcept;
|
||||||
|
|
||||||
|
void append(const char *str, std::size_t sz) noexcept;
|
||||||
|
|
||||||
constexpr char *data() noexcept;
|
constexpr char *data() noexcept;
|
||||||
|
|
||||||
constexpr const char *c_str() const noexcept;
|
constexpr const char *c_str() const noexcept;
|
||||||
@ -153,6 +155,17 @@ constexpr char &BString<buffLen>::operator[](std::size_t i) noexcept {
|
|||||||
return m_buff[i];
|
return m_buff[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<std::size_t buffLen>
|
||||||
|
void BString<buffLen>::append(const char *str, std::size_t strLen) noexcept {
|
||||||
|
auto currentLen = len();
|
||||||
|
if (cap() < currentLen + strLen + 1) {
|
||||||
|
strLen = cap() - currentLen;
|
||||||
|
}
|
||||||
|
ox_memcpy(m_buff + currentLen, str, strLen);
|
||||||
|
// make sure last element is a null terminator
|
||||||
|
m_buff[currentLen + strLen] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
template<std::size_t buffLen>
|
template<std::size_t buffLen>
|
||||||
constexpr char *BString<buffLen>::data() noexcept {
|
constexpr char *BString<buffLen>::data() noexcept {
|
||||||
return static_cast<char*>(m_buff);
|
return static_cast<char*>(m_buff);
|
||||||
|
6
deps/ox/src/ox/std/byteswap.hpp
vendored
6
deps/ox/src/ox/std/byteswap.hpp
vendored
@ -175,12 +175,16 @@ class OX_PACKED ByteSwapInteger {
|
|||||||
return newVal;
|
return newVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr auto get() const noexcept -> T {
|
||||||
|
return static_cast<T>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the integer as it is stored. If it is stored as little endian,
|
* Returns the integer as it is stored. If it is stored as little endian,
|
||||||
* a little endian integer is returned regardless of the endianness of
|
* a little endian integer is returned regardless of the endianness of
|
||||||
* the system.
|
* the system.
|
||||||
*/
|
*/
|
||||||
constexpr auto raw() noexcept -> T {
|
[[nodiscard]] constexpr auto raw() const noexcept -> T {
|
||||||
return m_value;
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
184
deps/ox/src/ox/std/fmt.hpp
vendored
Normal file
184
deps/ox/src/ox/std/fmt.hpp
vendored
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 - 2021 gary@drinkingtea.net
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ox/std/strops.hpp>
|
||||||
|
#include <ox/std/types.hpp>
|
||||||
|
#include <ox/std/typetraits.hpp>
|
||||||
|
|
||||||
|
namespace ox::detail {
|
||||||
|
|
||||||
|
class FmtArg {
|
||||||
|
|
||||||
|
private:
|
||||||
|
char dataStr[10] = {};
|
||||||
|
|
||||||
|
public:
|
||||||
|
const char *out = nullptr;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr FmtArg(T v) noexcept {
|
||||||
|
if constexpr(is_bool_v<T>) {
|
||||||
|
out = v ? "true" : "false";
|
||||||
|
} else if constexpr(is_integral_v<T>) {
|
||||||
|
out = ox_itoa(v, dataStr);
|
||||||
|
} else {
|
||||||
|
out = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr uint64_t argCount(const char *str) noexcept {
|
||||||
|
uint64_t cnt = 0;
|
||||||
|
const auto prev = [str](std::size_t i) -> char {
|
||||||
|
if (i > 0) {
|
||||||
|
return str[i - 1];
|
||||||
|
} else {
|
||||||
|
return '\0';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const auto next = [str](std::size_t i) -> char {
|
||||||
|
if (i < ox_strlen(str) - 1) {
|
||||||
|
return str[i + 1];
|
||||||
|
} else {
|
||||||
|
return '\0';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for (std::size_t i = 0; i < ox_strlen(str); ++i) {
|
||||||
|
if (str[i] == '{' && prev(i) != '\\' && next(i) == '}') {
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(argCount("{}") == 1);
|
||||||
|
static_assert(argCount("{}{}") == 2);
|
||||||
|
static_assert(argCount("thing1: {}, thing2: {}") == 2);
|
||||||
|
static_assert(argCount("thing1: {}, thing2: {}{}") == 3);
|
||||||
|
|
||||||
|
struct FmtSegment {
|
||||||
|
const char *str = nullptr;
|
||||||
|
unsigned length = 0;
|
||||||
|
|
||||||
|
constexpr bool operator==(const FmtSegment &o) const noexcept {
|
||||||
|
return length == o.length && ox_strncmp(str, o.str, length) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator!=(const FmtSegment &o) const noexcept {
|
||||||
|
return length != o.length || ox_strncmp(str, o.str, length) != 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t sz>
|
||||||
|
struct Fmt {
|
||||||
|
static constexpr std::size_t size = sz;
|
||||||
|
FmtSegment segments[sz];
|
||||||
|
|
||||||
|
constexpr bool operator==(const Fmt<sz> &o) const noexcept {
|
||||||
|
for (std::size_t i = 0; i < sz; ++i) {
|
||||||
|
if (segments[i] != o.segments[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t segementCnt>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Fmt<segementCnt> fmtSegments(const char *fmt) noexcept {
|
||||||
|
Fmt<segementCnt> out;
|
||||||
|
const auto prev = [fmt](std::size_t i) -> char {
|
||||||
|
if (i > 0) {
|
||||||
|
return fmt[i - 1];
|
||||||
|
} else {
|
||||||
|
return '\0';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const auto next = [fmt](std::size_t i) -> char {
|
||||||
|
if (i < ox_strlen(fmt) - 1) {
|
||||||
|
return fmt[i + 1];
|
||||||
|
} else {
|
||||||
|
return '\0';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
auto current = &out.segments[0];
|
||||||
|
current->str = fmt;
|
||||||
|
for (std::size_t i = 0; i < ox_strlen(fmt); ++i) {
|
||||||
|
if (fmt[i] == '{' && prev(i) != '\\' && next(i) == '}') {
|
||||||
|
++current;
|
||||||
|
current->str = fmt + i + 2;
|
||||||
|
current->length = 0;
|
||||||
|
i += 1;
|
||||||
|
} else {
|
||||||
|
++current->length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert([] {
|
||||||
|
constexpr auto fmt = "{}";
|
||||||
|
return fmtSegments<argCount(fmt) + 1>(fmt) == Fmt<2>{
|
||||||
|
{
|
||||||
|
{"", 0},
|
||||||
|
{"", 0},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}()
|
||||||
|
);
|
||||||
|
static_assert([] {
|
||||||
|
constexpr auto fmt = "thing: {}";
|
||||||
|
return fmtSegments<argCount(fmt) + 1>(fmt) == Fmt<2>{
|
||||||
|
{
|
||||||
|
{"thing: ", 7},
|
||||||
|
{"", 0},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}()
|
||||||
|
);
|
||||||
|
static_assert([] {
|
||||||
|
constexpr auto fmt = "thing: {}, thing2: {}";
|
||||||
|
return fmtSegments<argCount(fmt) + 1>(fmt) == Fmt<3>{
|
||||||
|
{
|
||||||
|
{"thing: ", 7},
|
||||||
|
{", thing2: ", 10},
|
||||||
|
{"", 0},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}()
|
||||||
|
);
|
||||||
|
static_assert([] {
|
||||||
|
constexpr auto fmt = "thing: {}, thing2: {}s";
|
||||||
|
return fmtSegments<argCount(fmt) + 1>(fmt) == Fmt<3>{
|
||||||
|
{
|
||||||
|
{"thing: ", 7},
|
||||||
|
{", thing2: ", 10},
|
||||||
|
{"s", 1},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}()
|
||||||
|
);
|
||||||
|
static_assert([] {
|
||||||
|
constexpr auto fmt = "loadTexture: section: {}, w: {}, h: {}";
|
||||||
|
return fmtSegments<argCount(fmt) + 1>(fmt) == Fmt<4>{
|
||||||
|
{
|
||||||
|
{"loadTexture: section: ", 22},
|
||||||
|
{", w: ", 5},
|
||||||
|
{", h: ", 5},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
1
deps/ox/src/ox/std/std.hpp
vendored
1
deps/ox/src/ox/std/std.hpp
vendored
@ -14,6 +14,7 @@
|
|||||||
#include "byteswap.hpp"
|
#include "byteswap.hpp"
|
||||||
#include "defines.hpp"
|
#include "defines.hpp"
|
||||||
#include "error.hpp"
|
#include "error.hpp"
|
||||||
|
#include "fmt.hpp"
|
||||||
#include "hardware.hpp"
|
#include "hardware.hpp"
|
||||||
#include "hashmap.hpp"
|
#include "hashmap.hpp"
|
||||||
#include "heapmgr.hpp"
|
#include "heapmgr.hpp"
|
||||||
|
50
deps/ox/src/ox/std/trace.cpp
vendored
50
deps/ox/src/ox/std/trace.cpp
vendored
@ -6,60 +6,10 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(OX_USE_STDLIB)
|
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "trace.hpp"
|
#include "trace.hpp"
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
void oxTraceInitHook();
|
|
||||||
|
|
||||||
void oxTraceHook(const char *file, int line, const char *ch, const char *msg);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace ox::trace {
|
namespace ox::trace {
|
||||||
|
|
||||||
#if defined(OX_USE_STDLIB)
|
|
||||||
static const auto OxPrintTrace = std::getenv("OXTRACE");
|
|
||||||
#else
|
|
||||||
constexpr auto OxPrintTrace = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
OutStream::OutStream(const char *file, int line, const char *ch, const char *msg) {
|
|
||||||
m_msg.file = file;
|
|
||||||
m_msg.line = line;
|
|
||||||
m_msg.ch = ch;
|
|
||||||
m_msg.msg = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
OutStream::~OutStream() {
|
|
||||||
oxTraceHook(m_msg.file.c_str(), m_msg.line, m_msg.ch.c_str(), m_msg.msg.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
StdOutStream::StdOutStream(const char *file, int line, const char *ch, const char *msg) {
|
|
||||||
m_msg.file = file;
|
|
||||||
m_msg.line = line;
|
|
||||||
m_msg.ch = ch;
|
|
||||||
m_msg.msg = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
StdOutStream::~StdOutStream() {
|
|
||||||
oxTraceHook(m_msg.file.c_str(), m_msg.line, m_msg.ch.c_str(), m_msg.msg.c_str());
|
|
||||||
#if defined(OX_USE_STDLIB)
|
|
||||||
if (OxPrintTrace) {
|
|
||||||
std::cout << std::setw(53) << std::left << m_msg.ch.c_str() << '|';
|
|
||||||
std::cout << std::setw(65) << std::left << m_msg.msg.c_str() << '|';
|
|
||||||
std::cout << " " << m_msg.file.c_str() << ':' << m_msg.line << "\n";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void logError(const char *file, int line, Error err) {
|
void logError(const char *file, int line, Error err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
TraceStream trc(file, line, "ox::error");
|
TraceStream trc(file, line, "ox::error");
|
||||||
|
102
deps/ox/src/ox/std/trace.hpp
vendored
102
deps/ox/src/ox/std/trace.hpp
vendored
@ -8,15 +8,25 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ox/std/std.hpp>
|
#include "bstring.hpp"
|
||||||
|
#include "fmt.hpp"
|
||||||
|
#include "hashmap.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
void oxTraceInitHook();
|
||||||
|
|
||||||
|
void oxTraceHook(const char *file, int line, const char *ch, const char *msg);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace ox::trace {
|
namespace ox::trace {
|
||||||
|
|
||||||
struct TraceMsg {
|
struct TraceMsg {
|
||||||
ox::BString<255> file = "";
|
const char *file = "";
|
||||||
int line = 0;
|
int line = 0;
|
||||||
uint64_t time = 0;
|
uint64_t time = 0;
|
||||||
ox::BString<75> ch = "";
|
const char *ch = "";
|
||||||
ox::BString<100> msg;
|
ox::BString<100> msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -33,26 +43,51 @@ Error model(T *io, ox::trace::TraceMsg *obj) {
|
|||||||
|
|
||||||
class OutStream {
|
class OutStream {
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
const char *m_delimiter = " ";
|
const char *m_delimiter = " ";
|
||||||
TraceMsg m_msg;
|
TraceMsg m_msg;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OutStream() = default;
|
constexpr OutStream(const char *file, int line, const char *ch, const char *msg = "") {
|
||||||
|
m_msg.file = file;
|
||||||
|
m_msg.line = line;
|
||||||
|
m_msg.ch = ch;
|
||||||
|
m_msg.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
OutStream(const char *file, int line, const char *ch, const char *msg = "");
|
template<std::size_t fmtSegmentCnt, typename ...Args>
|
||||||
|
constexpr OutStream(const char *file, int line, const char *ch, detail::Fmt<fmtSegmentCnt> fmtSegments, Args... args) {
|
||||||
|
static_assert(sizeof...(args) == fmtSegmentCnt - 1, "Wrong number of trace arguments for format.");
|
||||||
|
m_msg.file = file;
|
||||||
|
m_msg.line = line;
|
||||||
|
m_msg.ch = ch;
|
||||||
|
const auto &firstSegment = fmtSegments.segments[0];
|
||||||
|
m_msg.msg.append(firstSegment.str, firstSegment.length);
|
||||||
|
const detail::FmtArg elements[sizeof...(args)] = {args...};
|
||||||
|
for (auto i = 0u; i < fmtSegments.size - 1; ++i) {
|
||||||
|
m_msg.msg += elements[i].out;
|
||||||
|
const auto &s = fmtSegments.segments[i + 1];
|
||||||
|
m_msg.msg.append(s.str, s.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~OutStream();
|
inline ~OutStream() {
|
||||||
|
oxTraceHook(m_msg.file, m_msg.line, m_msg.ch, m_msg.msg.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline OutStream &operator<<(const T &v) {
|
constexpr OutStream &operator<<(const T &v) {
|
||||||
m_msg.msg += m_delimiter;
|
if (m_msg.msg.len()) {
|
||||||
|
m_msg.msg += m_delimiter;
|
||||||
|
}
|
||||||
m_msg.msg += v;
|
m_msg.msg += v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline OutStream &operator<<(Error err) {
|
constexpr OutStream &operator<<(Error err) {
|
||||||
m_msg.msg += m_delimiter;
|
if (m_msg.msg.len()) {
|
||||||
|
m_msg.msg += m_delimiter;
|
||||||
|
}
|
||||||
m_msg.msg += static_cast<int64_t>(err);
|
m_msg.msg += static_cast<int64_t>(err);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -60,38 +95,7 @@ class OutStream {
|
|||||||
/**
|
/**
|
||||||
* del sets the delimiter between log segments.
|
* del sets the delimiter between log segments.
|
||||||
*/
|
*/
|
||||||
inline OutStream &del(const char *delimiter) {
|
constexpr OutStream &del(const char *delimiter) {
|
||||||
m_delimiter = delimiter;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class StdOutStream {
|
|
||||||
|
|
||||||
private:
|
|
||||||
const char *m_delimiter = " ";
|
|
||||||
TraceMsg m_msg;
|
|
||||||
|
|
||||||
public:
|
|
||||||
StdOutStream() = default;
|
|
||||||
|
|
||||||
StdOutStream(const char *file, int line, const char *ch, const char *msg = "");
|
|
||||||
|
|
||||||
~StdOutStream();
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr inline StdOutStream &operator<<(const T &v) {
|
|
||||||
m_msg.msg += m_delimiter;
|
|
||||||
m_msg.msg += v;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* del sets the delimiter between log segments.
|
|
||||||
*/
|
|
||||||
inline StdOutStream &del(const char *delimiter) {
|
|
||||||
m_delimiter = delimiter;
|
m_delimiter = delimiter;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -102,19 +106,19 @@ class StdOutStream {
|
|||||||
class NullStream {
|
class NullStream {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr NullStream() = default;
|
|
||||||
|
|
||||||
constexpr NullStream(const char*, int, const char*, const char* = "") {
|
constexpr NullStream(const char*, int, const char*, const char* = "") {
|
||||||
}
|
}
|
||||||
|
|
||||||
~NullStream() = default;
|
template<std::size_t fmtSegmentCnt, typename ...Args>
|
||||||
|
constexpr NullStream(const char*, int, const char*, detail::Fmt<fmtSegmentCnt>, Args...) {
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr inline NullStream &operator<<(const T&) {
|
constexpr NullStream &operator<<(const T&) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline NullStream &del(const char*) {
|
constexpr NullStream &del(const char*) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,3 +139,5 @@ void init();
|
|||||||
#define oxLogError(err) ox::trace::logError(__FILE__, __LINE__, err)
|
#define oxLogError(err) ox::trace::logError(__FILE__, __LINE__, err)
|
||||||
|
|
||||||
#define oxTrace(ch) ox::trace::TraceStream(__FILE__, __LINE__, ch)
|
#define oxTrace(ch) ox::trace::TraceStream(__FILE__, __LINE__, ch)
|
||||||
|
|
||||||
|
#define oxTracef(ch, fmt, ...) ox::trace::TraceStream(__FILE__, __LINE__, ch, ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), ##__VA_ARGS__)
|
||||||
|
16
deps/ox/src/ox/std/tracehook.cpp
vendored
16
deps/ox/src/ox/std/tracehook.cpp
vendored
@ -6,6 +6,15 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(OX_USE_STDLIB)
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
static const auto OxPrintTrace = std::getenv("OXTRACE") != nullptr;
|
||||||
|
#else
|
||||||
|
constexpr auto OxPrintTrace = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
void oxTraceInitHook() {
|
void oxTraceInitHook() {
|
||||||
@ -13,6 +22,13 @@ void oxTraceInitHook() {
|
|||||||
|
|
||||||
void oxTraceHook([[maybe_unused]] const char *file, [[maybe_unused]] int line,
|
void oxTraceHook([[maybe_unused]] const char *file, [[maybe_unused]] int line,
|
||||||
[[maybe_unused]] const char *ch, [[maybe_unused]] const char *msg) {
|
[[maybe_unused]] const char *ch, [[maybe_unused]] const char *msg) {
|
||||||
|
#if defined(OX_USE_STDLIB)
|
||||||
|
if (OxPrintTrace) {
|
||||||
|
std::cout << std::setw(53) << std::left << ch << "| ";
|
||||||
|
std::cout << std::setw(65) << std::left << msg << '|';
|
||||||
|
std::cout << " " << file << ':' << line << "\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
9
deps/ox/src/ox/std/typetraits.hpp
vendored
9
deps/ox/src/ox/std/typetraits.hpp
vendored
@ -63,6 +63,15 @@ template<> struct is_integral<uint32_t>: ox::true_type {};
|
|||||||
template<> struct is_integral<int64_t> : ox::true_type {};
|
template<> struct is_integral<int64_t> : ox::true_type {};
|
||||||
template<> struct is_integral<uint64_t>: ox::true_type {};
|
template<> struct is_integral<uint64_t>: ox::true_type {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr bool is_integral_v = ox::is_integral<T>::value;
|
||||||
|
|
||||||
|
template<typename T> struct is_bool: ox::false_type {};
|
||||||
|
template<> struct is_bool<bool> : ox::true_type {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr bool is_bool_v = ox::is_bool<T>::value;
|
||||||
|
|
||||||
template<typename T> struct is_union: ox::integral_constant<bool, std::is_union_v<T>> {};
|
template<typename T> struct is_union: ox::integral_constant<bool, std::is_union_v<T>> {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user