inline static constexpr size_t SOURCE_BUFF_SIZE { 6 };
// Not All Functions Can Be Made `constexpr` due to the usage of `std::memset()` and `std::to_chars()`
class Format_Source_Loc
{
public:
explicit Format_Source_Loc(const std::source_location& src, const source_flag& flag)
: srcLocation(src), buff(std::array<char, SOURCE_BUFF_SIZE> {}), spec(flag), result(std::string {}) { }
Format_Source_Loc(const Format_Source_Loc&) = delete;
Format_Source_Loc& operator=(const Format_Source_Loc&) = delete;
~Format_Source_Loc() = default;
void FormatAll() {
auto data { buff.data() };
result.append("[ ").append(std::move(std::filesystem::path { srcLocation.file_name() }.filename().string())).append("(");
std::memset(data, 0, SOURCE_BUFF_SIZE);
result.append(data, std::to_chars(data, data + SOURCE_BUFF_SIZE, srcLocation.line()).ptr - data).append(":");
std::memset(data, 0, SOURCE_BUFF_SIZE);
result.append(data, std::to_chars(data, data + SOURCE_BUFF_SIZE, srcLocation.column()).ptr - data).append(") ");
result.append(srcLocation.function_name()).append(" ]");
}
void FormatLine() {
auto data { buff.data() };
std::memset(data, 0, SOURCE_BUFF_SIZE);
result.append(data, std::to_chars(data, data + SOURCE_BUFF_SIZE, srcLocation.line()).ptr - data);
}
void FormatColumn() {
auto data { buff.data() };
std::memset(data, 0, SOURCE_BUFF_SIZE);
result.append(data, std::to_chars(data, data + SOURCE_BUFF_SIZE, srcLocation.column()).ptr - data);
}
void FormatFile() {
result.append(std::move(std::filesystem::path { srcLocation.file_name() }.filename().string()));
}
inline constexpr void FormatFunction() {
result.append(srcLocation.function_name());
}
std::string FormatUserPattern() {
using enum source_flag;
result.clear();
switch( static_cast(spec) ) {
case 1: FormatLine(); break;
case 2: FormatColumn(); break;
case 3:
FormatLine();
result.append(":");
FormatColumn();
break;
case 4: FormatFile(); break;
case 5:
FormatFile();
result.append(" ");
FormatLine();
break;
case 7:
FormatFile();
result.append("(");
FormatLine();
result.append(":");
FormatColumn();
result.append(")");
break;
case 8: FormatFunction(); break;
case 9:
FormatFunction();
result.append(" ");
FormatLine();
break;
case 11:
FormatFunction();
result.append(": (");
FormatLine();
result.append(":");
FormatColumn();
result.append(")");
break;
case 12:
FormatFile();
result.append(" ");
FormatFunction();
break;
default: FormatAll(); break;
}
return result;
}
private:
const std::source_location& srcLocation;
std::array<char, SOURCE_BUFF_SIZE> buff;
const source_flag& spec;
std::string result;
};
inline static constexpr size_t defaultThreadIdLength = 10; // Precision argument dictates the length of the hashed id returned (0-10)
inline static constexpr size_t THREAD_BUFF_SIZE = 64;
class Format_Thread_ID
{
public:
explicit Format_Thread_ID(const std::thread::id& id): thread(id) { }
Format_Thread_ID(const Format_Thread_ID&) = delete;
Format_Thread_ID& operator=(const Format_Thread_ID&) = delete;
~Format_Thread_ID() = default;
std::string FormatUserPattern(size_t precision) {
std::array<char, THREAD_BUFF_SIZE> buf {};
std::to_chars(buf.data(), buf.data() + THREAD_BUFF_SIZE, std::hash<std::thread::id>()(thread));
return std::string(buf.data(), buf.data() + ((precision != 0) ? precision : defaultThreadIdLength));
}
private:
const std::thread::id& thread;
};