Compare commits
No commits in common. "c8d12c21c673d9d1cbce82daf9b02e20477cd1b2" and "48095f5c418978708c53f6fbf074b2a0f1de007b" have entirely different histories.
c8d12c21c6
...
48095f5c41
|
@ -1 +1,9 @@
|
|||
/cmake-build-*/
|
||||
/cmake-build-debug/
|
||||
./cmake-build-debug/
|
||||
cmake-build-debug/
|
||||
/cmake-build-release/
|
||||
./cmake-build-release/
|
||||
cmake-build-release/
|
||||
cmake-build-relwithdebinfo/
|
||||
cmake-build-reldebug-asan/
|
||||
./cmake-build-relwithdebinfo/
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* BLT C++ 20 / C++ 17 Compatability helper file
|
||||
* Copyright (C) 2023 Brett Terpstra
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef INSANE_DNS_COMPATIBILITY_H
|
||||
#define INSANE_DNS_COMPATIBILITY_H
|
||||
|
||||
#if __cplusplus >= 202002L
|
||||
#define BLT_CONTAINS(container, value) container.contains(value)
|
||||
#define BLT_CPP20_CONSTEXPR constexpr
|
||||
#define BLT_USE_CPP20
|
||||
#else
|
||||
#include <algorithm>
|
||||
#define BLT_CONTAINS(container, value) std::find(container.begin(), container.end(), value) != container.end()
|
||||
#define BLT_CPP20_CONSTEXPR
|
||||
#undef BLT_USE_CPP20
|
||||
#endif
|
||||
|
||||
#define INCLUDE_FS \
|
||||
#if defined(CXX17_FILESYSTEM) || defined (CXX17_FILESYSTEM_LIBFS) \
|
||||
#include <filesystem>\
|
||||
#elif defined(CXX11_EXP_FILESYSTEM) || defined (CXX11_EXP_FILESYSTEM_LIBFS)\
|
||||
#include <experimental/filesystem>\
|
||||
#else\
|
||||
#error Filesystem ops not supported!\
|
||||
#endif
|
||||
|
||||
#endif //INSANE_DNS_COMPATIBILITY_H
|
|
@ -12,12 +12,10 @@
|
|||
#include <cstring>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
|
||||
#include "blt/std/format.h"
|
||||
#include "blt/std/filesystem.h"
|
||||
#include "blt/std/logging.h"
|
||||
#include "blt/std/memory.h"
|
||||
|
||||
#include <blt/std/hashmap.h>
|
||||
|
||||
|
@ -27,10 +25,36 @@ namespace blt::nbt {
|
|||
|
||||
std::string readUTF8String(blt::fs::block_reader& stream);
|
||||
|
||||
// Used to grab the byte-data of any T element. Defaults to Big Endian, however can be configured to use little endian
|
||||
template <typename T>
|
||||
inline static int toBytes(const T& in, char* out) {
|
||||
std::memcpy(out, (void*) &in, sizeof(T));
|
||||
|
||||
if constexpr (std::endian::native == std::endian::little) {
|
||||
for (size_t i = 0; i < sizeof(T) / 2; i++)
|
||||
std::swap(out[i], out[sizeof(T) - 1 - i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Used to cast the binary data of any T object, into a T object.
|
||||
template <typename T>
|
||||
inline static int fromBytes(const char* in, T* out) {
|
||||
memcpy(out, in, sizeof(T));
|
||||
|
||||
if constexpr (std::endian::native == std::endian::little) {
|
||||
for (size_t i = 0; i < sizeof(T) / 2; i++)
|
||||
std::swap(((char*) (out))[i], ((char*) (out))[sizeof(T) - 1 - i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline static void writeData(blt::fs::block_writer& out, const T& d){
|
||||
char data[sizeof(T)];
|
||||
mem::toBytes(d, data);
|
||||
toBytes(d, data);
|
||||
out.write(data, sizeof(T));
|
||||
}
|
||||
|
||||
|
@ -38,7 +62,7 @@ namespace blt::nbt {
|
|||
inline static void readData(blt::fs::block_reader& in, T& d) {
|
||||
char data[sizeof(T)];
|
||||
in.read(data, sizeof(T));
|
||||
mem::fromBytes(data, &d);
|
||||
fromBytes(data, &d);
|
||||
}
|
||||
|
||||
enum class nbt_tag : char {
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <initializer_list>
|
||||
#include <optional>
|
||||
#include <blt/std/hashmap.h>
|
||||
#include <blt/std/string.h>
|
||||
#include <variant>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
@ -50,27 +49,19 @@ namespace blt
|
|||
void validateFlags();
|
||||
|
||||
public:
|
||||
explicit arg_vector_t(std::vector<std::string> flags): flags(std::move(flags))
|
||||
arg_vector_t(std::vector<std::string> flags): flags(std::move(flags))
|
||||
{
|
||||
validateFlags();
|
||||
}
|
||||
|
||||
arg_vector_t(std::initializer_list<std::string> f): flags(f)
|
||||
arg_vector_t(std::initializer_list<std::string> flags): flags(flags)
|
||||
{
|
||||
if (flags.size() == 1) {
|
||||
if (!blt::string::starts_with(flags[0], '-'))
|
||||
{
|
||||
name = flags[0];
|
||||
flags.clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
validateFlags();
|
||||
}
|
||||
|
||||
explicit arg_vector_t(const char* str);
|
||||
arg_vector_t(const char* str);
|
||||
|
||||
explicit arg_vector_t(const std::string& str);
|
||||
arg_vector_t(const std::string& str);
|
||||
|
||||
[[nodiscard]] inline bool isFlag() const
|
||||
{
|
||||
|
@ -127,6 +118,7 @@ namespace blt
|
|||
|
||||
struct arg_properties_t
|
||||
{
|
||||
private:
|
||||
public:
|
||||
arg_vector_t a_flags;
|
||||
arg_action_t a_action = arg_action_t::STORE;
|
||||
|
@ -138,14 +130,6 @@ namespace blt
|
|||
std::string a_version{};
|
||||
std::string a_metavar{};
|
||||
bool a_required = true;
|
||||
|
||||
arg_properties_t() = delete;
|
||||
|
||||
explicit arg_properties_t(arg_vector_t flags): a_flags(std::move(flags))
|
||||
{}
|
||||
|
||||
explicit arg_properties_t(const std::string& pos_arg): a_flags(pos_arg)
|
||||
{}
|
||||
};
|
||||
|
||||
class arg_builder
|
||||
|
@ -156,14 +140,11 @@ namespace blt
|
|||
explicit arg_builder(const arg_vector_t& flags): properties(flags)
|
||||
{}
|
||||
|
||||
explicit arg_builder(const std::string& pos_arg): properties(pos_arg)
|
||||
{}
|
||||
|
||||
arg_builder(const std::initializer_list<std::string>& flags): properties(flags)
|
||||
{}
|
||||
|
||||
template<typename... string_args>
|
||||
explicit arg_builder(string_args... flags): properties(arg_vector_t{flags...})
|
||||
explicit arg_builder(string_args... flags): properties({flags...})
|
||||
{}
|
||||
|
||||
inline arg_properties_t build()
|
||||
|
@ -256,13 +237,13 @@ namespace blt
|
|||
// returns true if the current arg is a flag
|
||||
inline bool isFlag()
|
||||
{
|
||||
return blt::string::starts_with(args[currentIndex], '-');
|
||||
return args[currentIndex].starts_with('-');
|
||||
}
|
||||
|
||||
// returns true if we have next and the next arg is a flag
|
||||
inline bool isNextFlag()
|
||||
{
|
||||
return hasNext() && blt::string::starts_with(args[currentIndex + 1], '-');
|
||||
return hasNext() && args[currentIndex + 1].starts_with('-');
|
||||
}
|
||||
|
||||
// advances to the next flag
|
||||
|
@ -325,7 +306,6 @@ namespace blt
|
|||
return static_cast<T>(std::stoll(s));
|
||||
return static_cast<T>(std::stoull(s));
|
||||
}
|
||||
|
||||
private:
|
||||
struct
|
||||
{
|
||||
|
@ -361,9 +341,6 @@ namespace blt
|
|||
template<typename T>
|
||||
inline T get(const std::string& key)
|
||||
{
|
||||
if constexpr (std::is_same_v<T, std::string>)
|
||||
return blt::arg_parse::get<T>(data[key]);
|
||||
else
|
||||
return blt::arg_parse::get_cast<T>(data[key]);
|
||||
}
|
||||
|
||||
|
@ -379,9 +356,9 @@ namespace blt
|
|||
|
||||
inline bool contains(const std::string& key)
|
||||
{
|
||||
if (blt::string::starts_with(key, "--"))
|
||||
if (key.starts_with("--"))
|
||||
return data.find(key.substr(2)) != data.end();
|
||||
if (blt::string::starts_with(key, '-'))
|
||||
if (key.starts_with('-'))
|
||||
return data.find(key.substr(1)) != data.end();
|
||||
return data.find(key) != data.end();
|
||||
}
|
||||
|
|
|
@ -51,11 +51,6 @@ namespace blt
|
|||
|
||||
std::uint64_t count = 0;
|
||||
std::string interval_name;
|
||||
|
||||
interval_t() = default;
|
||||
|
||||
interval_t(pf_time_t wallStart, pf_time_t wallEnd, pf_time_t wallTotal, pf_time_t threadStart, pf_time_t threadEnd, pf_time_t threadTotal,
|
||||
pf_cycle_t cyclesStart, pf_cycle_t cyclesEnd, pf_cycle_t cyclesTotal, uint64_t count, std::string intervalName);
|
||||
};
|
||||
|
||||
struct cycle_interval_t
|
||||
|
@ -87,8 +82,7 @@ namespace blt
|
|||
|
||||
void startInterval(interval_t* interval);
|
||||
|
||||
inline interval_t* startInterval(profile_t& profiler, std::string interval_name)
|
||||
{
|
||||
inline interval_t* startInterval(profile_t& profiler, std::string interval_name){
|
||||
auto* p = createInterval(profiler, std::move(interval_name));
|
||||
startInterval(p);
|
||||
return p;
|
||||
|
|
|
@ -14,53 +14,12 @@ namespace blt
|
|||
void b_assert_failed(const char* expression, const char* path, int line);
|
||||
|
||||
void b_throw(const char* what, const char* path, int line);
|
||||
|
||||
#if defined(__GNUC__) || defined(__llvm__)
|
||||
#define BLT_ATTRIB_NO_INLINE __attribute__ ((noinline))
|
||||
#else
|
||||
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
|
||||
#define BLT_ATTRIB_NO_INLINE __declspec(noinline)
|
||||
#else
|
||||
#define BLT_ATTRIB_NO_INLINE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
void BLT_ATTRIB_NO_INLINE black_box_ref(const T& val){
|
||||
volatile void* hell;
|
||||
hell = (void*)&val;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void BLT_ATTRIB_NO_INLINE black_box(T val){
|
||||
volatile void* hell2;
|
||||
hell2 = (void*)&val;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T& BLT_ATTRIB_NO_INLINE black_box_ref_ret(const T& val){
|
||||
volatile void* hell;
|
||||
hell = (void*)&val;
|
||||
return val;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T BLT_ATTRIB_NO_INLINE black_box_ret(T val){
|
||||
volatile void* hell2;
|
||||
hell2 = (void*)&val;
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
// prints error with stack trace if assertion fails. Does not stop execution.
|
||||
#define blt_assert(expr) do {static_cast<bool>(expr) ? void(0) : blt::b_assert_failed(#expr, __FILE__, __LINE__) } while (0)
|
||||
// prints error with stack trace then exits with failure.
|
||||
#define BLT_ASSERT(expr) do { \
|
||||
if (!static_cast<bool>(expr)) { \
|
||||
blt::b_assert_failed(#expr, __FILE__, __LINE__); \
|
||||
std::exit(EXIT_FAILURE); \
|
||||
} \
|
||||
} while (0)
|
||||
#define BLT_ASSERT(expr) do {static_cast<bool>(expr) ? void(0) : blt::b_assert_failed(#expr, __FILE__, __LINE__); std::exit(EXIT_FAILURE); } while (0)
|
||||
// prints as error but does not throw the exception.
|
||||
#define blt_throw(throwable) do {blt::b_throw(throwable.what(), __FILE__, __LINE__);} while (0)
|
||||
// prints as error with stack trace and throws the exception.
|
||||
|
|
|
@ -14,53 +14,18 @@
|
|||
#include <string>
|
||||
#include <blt/std/string.h>
|
||||
#include <blt/std/logging.h>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace blt::fs
|
||||
{
|
||||
struct include_guard
|
||||
{
|
||||
char open = '<';
|
||||
char close = '>';
|
||||
};
|
||||
|
||||
std::string getFile(const std::string& path);
|
||||
|
||||
namespace blt::fs {
|
||||
std::vector<std::string> getLinesFromFile(const std::string& path);
|
||||
|
||||
/**
|
||||
* Recursively include files
|
||||
* @param path initial file to load
|
||||
* @param include_header the beginning of the line that should be used to recognize when a line is to be treated as an include
|
||||
* @param guards characters used to identify the parts that specify the file path. if empty it will assume everything after the include header
|
||||
* @return a list of lines in all files. added together in order.
|
||||
*/
|
||||
std::vector<std::string> recursiveInclude(const std::string& path, const std::string& include_header = "#include",
|
||||
const std::vector<include_guard>& guards = {{'<', '>'}, {'"', '"'}});
|
||||
std::vector<std::string> recursiveShaderInclude(const std::string& path);
|
||||
|
||||
static inline std::string loadBrainFuckFile(const std::string& path)
|
||||
{
|
||||
std::string buffer;
|
||||
|
||||
auto lines = recursiveInclude(path, "~", {});
|
||||
|
||||
for (auto& line : lines)
|
||||
{
|
||||
buffer += line;
|
||||
buffer += '\n';
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static inline std::string loadShaderFile(const std::string& path)
|
||||
{
|
||||
static inline std::string loadShaderFile(const std::string& path) {
|
||||
std::stringstream stringStream;
|
||||
|
||||
auto lines = recursiveInclude(path);
|
||||
auto lines = recursiveShaderInclude(path);
|
||||
|
||||
for (const auto& line : lines)
|
||||
{
|
||||
for (const auto& line : lines) {
|
||||
// now process the defines, if they exist
|
||||
// if (line.starts_with("#define")) {
|
||||
// auto defineParts = String::split(line, " ");
|
||||
|
|
|
@ -10,19 +10,14 @@
|
|||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <blt/config.h>
|
||||
#include <iostream>
|
||||
#include <cstdarg>
|
||||
|
||||
namespace blt::logging
|
||||
{
|
||||
namespace blt::logging {
|
||||
|
||||
template<typename K, typename V>
|
||||
using hashmap = std::unordered_map<K, V>;
|
||||
|
||||
enum class log_level
|
||||
{
|
||||
enum class log_level {
|
||||
// default
|
||||
NONE,
|
||||
// low level
|
||||
|
@ -33,22 +28,19 @@ namespace blt::logging
|
|||
WARN, ERROR, FATAL,
|
||||
};
|
||||
|
||||
struct tag_func_param
|
||||
{
|
||||
struct tag_func_param {
|
||||
blt::logging::log_level level;
|
||||
const std::string& file, line, raw_string, formatted_string;
|
||||
};
|
||||
|
||||
struct tag
|
||||
{
|
||||
struct tag {
|
||||
// tag without the ${{ or }}
|
||||
std::string tag;
|
||||
// function to run: log level, file, line, and raw user input string are provided
|
||||
std::function<std::string(const tag_func_param&)> func;
|
||||
};
|
||||
|
||||
struct log_format
|
||||
{
|
||||
struct log_format {
|
||||
/**
|
||||
* the log output format is the string which will be used to create the log output string
|
||||
*
|
||||
|
@ -77,8 +69,7 @@ namespace blt::logging
|
|||
*/
|
||||
std::string logOutputFormat = "\033[94m[${{TIME}}]${{RC}} ${{LF}}[${{LOG_LEVEL}}]${{RC}} \033[35m(${{FILE}}:${{LINE}})${{RC}} ${{CNR}}${{STR}}${{RC}}\n";
|
||||
std::string levelNames[11] = {"STDOUT", "TRACE0", "TRACE1", "TRACE2", "TRACE3", "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"};
|
||||
std::string levelColors[11] = {"\033[0m", "\033[22;97m", "\033[97m", "\033[97m", "\033[97m", "\033[97m", "\033[36m", "\033[92m", "\033[93m",
|
||||
"\033[91m", "\033[97;41m"};
|
||||
std::string levelColors[11] = {"\033[0m", "\033[22;97m", "\033[97m", "\033[97m", "\033[97m", "\033[97m", "\033[36m", "\033[92m", "\033[93m", "\033[91m", "\033[97;41m"};
|
||||
// if true prints the whole path to the file (eg /home/user/.../.../project/src/source.cpp:line#)
|
||||
bool printFullFileName = false;
|
||||
// the logging lib will keep track of the largest line found so far and try to keep the spacing accordingly
|
||||
|
@ -105,94 +96,60 @@ namespace blt::logging
|
|||
std::string lastFile;
|
||||
};
|
||||
|
||||
struct logger
|
||||
{
|
||||
struct logger {
|
||||
log_level level;
|
||||
const char* file;
|
||||
int line;
|
||||
};
|
||||
|
||||
struct empty_logger
|
||||
{
|
||||
struct empty_logger {
|
||||
|
||||
};
|
||||
|
||||
void log_internal(const std::string& format, log_level level, const char* file, int line, std::va_list& args);
|
||||
void log(const std::string& format, log_level level, const char* file, int line, ...);
|
||||
void log_stream(const std::string& str, const logger& logger);
|
||||
|
||||
void log_stream_internal(const std::string& str, const logger& logger);
|
||||
|
||||
template<typename T>
|
||||
inline static void log_stream(const T& t, const logger& logger)
|
||||
{
|
||||
if constexpr (std::is_arithmetic_v<T> && !std::is_same_v<T, char>)
|
||||
{
|
||||
log_stream_internal(std::to_string(t), logger);
|
||||
} else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, const char*>)
|
||||
{
|
||||
log_stream_internal(t, logger);
|
||||
} else
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << t;
|
||||
log_stream_internal(stream.str(), logger);
|
||||
}
|
||||
template<typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
|
||||
inline void log(T t, log_level level, const char* file, int line) {
|
||||
log(std::to_string(t), level, file, line);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void log(T t, log_level level, const char* file, int line, ...)
|
||||
{
|
||||
std::va_list args;
|
||||
va_start(args, line);
|
||||
if constexpr (std::is_arithmetic_v<T>)
|
||||
{
|
||||
log_internal(std::to_string(t), level, file, line, args);
|
||||
} else if constexpr (std::is_same_v<T, std::string>)
|
||||
{
|
||||
log_internal(t, level, file, line, args);
|
||||
} else if constexpr (std::is_same_v<T, const char*>){
|
||||
log_internal(std::string(t), level, file, line, args);
|
||||
} else
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << t;
|
||||
log_internal(stream.str(), level, file, line, args);
|
||||
}
|
||||
va_end(args);
|
||||
template<typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
|
||||
inline void log_stream(T t, const logger& logger) {
|
||||
log_stream(std::to_string(t), logger);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline const blt::logging::logger& operator<<(const blt::logging::logger& out, const T& t)
|
||||
{
|
||||
log_stream(t, out);
|
||||
static inline const blt::logging::logger& operator<<(const blt::logging::logger& out, const std::string& str) {
|
||||
log_stream(str, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline const blt::logging::empty_logger& operator<<(const blt::logging::empty_logger& out, const T&)
|
||||
{
|
||||
template<typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
|
||||
static inline const blt::logging::logger& operator<<(const blt::logging::logger& out, T t) {
|
||||
log_stream(std::to_string(t), out);
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline const blt::logging::empty_logger& operator<<(const blt::logging::empty_logger& out, const std::string&) {
|
||||
return out;
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
|
||||
static inline const blt::logging::empty_logger& operator<<(const blt::logging::empty_logger& out, T) {
|
||||
return out;
|
||||
}
|
||||
|
||||
void flush();
|
||||
|
||||
void setThreadName(const std::string& name);
|
||||
|
||||
void setLogFormat(const log_format& format);
|
||||
|
||||
void setLogColor(log_level level, const std::string& newFormat);
|
||||
|
||||
void setLogName(log_level level, const std::string& newFormat);
|
||||
|
||||
void setLogOutputFormat(const std::string& newFormat);
|
||||
|
||||
void setLogToFile(bool shouldLogToFile);
|
||||
|
||||
void setLogToConsole(bool shouldLogToConsole);
|
||||
|
||||
void setLogPath(const std::string& path);
|
||||
|
||||
void setLogFileName(const std::string& fileName);
|
||||
|
||||
void setMaxFileSize(size_t fileSize);
|
||||
}
|
||||
|
||||
|
@ -206,13 +163,7 @@ namespace blt::logging
|
|||
#include <thread>
|
||||
#include <cstdarg>
|
||||
#include <iostream>
|
||||
#if defined(CXX17_FILESYSTEM) || defined (CXX17_FILESYSTEM_LIBFS)
|
||||
#include <filesystem>
|
||||
#elif defined(CXX11_EXP_FILESYSTEM) || defined (CXX11_EXP_FILESYSTEM_LIBFS)
|
||||
#include <experimental/filesystem>
|
||||
#else
|
||||
#include <filesystem>
|
||||
#endif
|
||||
#include <ios>
|
||||
#include <fstream>
|
||||
|
||||
|
@ -318,7 +269,7 @@ namespace blt::logging {
|
|||
}
|
||||
};
|
||||
|
||||
#define BLT_NOW() auto t = std::time(nullptr); auto now = std::localtime(&t)
|
||||
#define BLT_NOW() auto t = std::time(nullptr); auto now = std::localtime(&t)
|
||||
#define BLT_ISO_YEAR(S) auto S = std::to_string(now->tm_year + 1900); \
|
||||
S += '-'; \
|
||||
S += ensureHasDigits(now->tm_mon+1, 2); \
|
||||
|
@ -486,7 +437,7 @@ namespace blt::logging {
|
|||
return out;
|
||||
}
|
||||
|
||||
void applyCFormatting(const std::string& format, std::string& output, std::va_list& args){
|
||||
void applyCFormatting(const std::string& format, std::string& output, va_list& args){
|
||||
// args must be copied because they will be consumed by the first vsnprintf
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
|
@ -566,7 +517,10 @@ namespace blt::logging {
|
|||
return out;
|
||||
}
|
||||
|
||||
void log_internal(const std::string& format, log_level level, const char* file, int line, std::va_list& args) {
|
||||
void log(const std::string& format, log_level level, const char* file, int line, ...) {
|
||||
va_list args;
|
||||
va_start(args, line);
|
||||
|
||||
std::string withoutLn = format;
|
||||
auto len = withoutLn.length();
|
||||
|
||||
|
@ -619,9 +573,11 @@ namespace blt::logging {
|
|||
writer.writeLine(path, stripANSI(finalFormattedOutput));
|
||||
}
|
||||
//std::cout.flush();
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void log_stream_internal(const std::string& str, const logger& logger) {
|
||||
void log_stream(const std::string& str, const logger& logger) {
|
||||
auto& s = loggingStreamLines[std::this_thread::get_id()][logger.level];
|
||||
s += str;
|
||||
for (char c : str){
|
||||
|
|
|
@ -10,177 +10,12 @@
|
|||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <cstring>
|
||||
#include "queue.h"
|
||||
#include <blt/std/assert.h>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <cstring>
|
||||
#include <array>
|
||||
|
||||
#if defined(__clang__) || defined(__llvm__) || defined(__GNUC__) || defined(__GNUG__)
|
||||
|
||||
#include <byteswap.h>
|
||||
|
||||
#define SWAP16(val) bswap_16(val)
|
||||
#define SWAP32(val) bswap_32(val)
|
||||
#define SWAP64(val) bswap_64(val)
|
||||
#if __cplusplus >= 202002L
|
||||
|
||||
#include <bit>
|
||||
|
||||
#define ENDIAN_LOOKUP(little_endian) (std::endian::native == std::endian::little && !little_endian) || \
|
||||
(std::endian::native == std::endian::big && little_endian)
|
||||
#else
|
||||
#define ENDIAN_LOOKUP(little_endian) !little_endian
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#define SWAP16(val) _byteswap_ushort(val)
|
||||
#define SWAP32(val) _byteswap_ulong(val)
|
||||
#define SWAP64(val) _byteswap_uint64(val)
|
||||
#define ENDIAN_LOOKUP(little_endian) !little_endian
|
||||
#endif
|
||||
#include "queue.h"
|
||||
|
||||
namespace blt
|
||||
{
|
||||
|
||||
namespace mem
|
||||
{
|
||||
// Used to grab the byte-data of any T element. Defaults to Big Endian, however can be configured to use little endian
|
||||
template<bool little_endian = false, typename BYTE_TYPE, typename T>
|
||||
inline static int toBytes(const T& in, BYTE_TYPE* out)
|
||||
{
|
||||
if constexpr (!(std::is_same_v<BYTE_TYPE, std::int8_t> || std::is_same_v<BYTE_TYPE, std::uint8_t>))
|
||||
static_assert("Must provide a signed/unsigned int8 type");
|
||||
std::memcpy(out, (void*) &in, sizeof(T));
|
||||
|
||||
if constexpr (ENDIAN_LOOKUP(little_endian))
|
||||
{
|
||||
// TODO: this but better.
|
||||
for (size_t i = 0; i < sizeof(T) / 2; i++)
|
||||
std::swap(out[i], out[sizeof(T) - 1 - i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Used to cast the binary data of any T object, into a T object. Assumes data is in big ending (configurable)
|
||||
template<bool little_endian = false, typename BYTE_TYPE, typename T>
|
||||
inline static int fromBytes(const BYTE_TYPE* in, T& out)
|
||||
{
|
||||
if constexpr (!(std::is_same_v<BYTE_TYPE, std::int8_t> || std::is_same_v<BYTE_TYPE, std::uint8_t>))
|
||||
static_assert("Must provide a signed/unsigned int8 type");
|
||||
|
||||
std::array<BYTE_TYPE, sizeof(T)> data;
|
||||
std::memcpy(data.data(), in, sizeof(T));
|
||||
|
||||
if constexpr (ENDIAN_LOOKUP(little_endian))
|
||||
{
|
||||
// if we need to swap find the best way to do so
|
||||
if constexpr (std::is_same_v<T, int16_t> || std::is_same_v<T, uint16_t>)
|
||||
out = SWAP16(*reinterpret_cast<T*>(data.data()));
|
||||
else if constexpr (std::is_same_v<T, int32_t> || std::is_same_v<T, uint32_t>)
|
||||
out = SWAP32(*reinterpret_cast<T*>(data.data()));
|
||||
else if constexpr (std::is_same_v<T, int64_t> || std::is_same_v<T, uint64_t>)
|
||||
out = SWAP64(*reinterpret_cast<T*>(data.data()));
|
||||
else
|
||||
{
|
||||
std::reverse(data.begin(), data.end());
|
||||
out = *reinterpret_cast<T*>(data.data());
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<bool little_endian = false, typename BYTE_TYPE, typename T>
|
||||
inline static int fromBytes(const BYTE_TYPE* in, T* out)
|
||||
{
|
||||
return fromBytes(in, *out);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct range_itr
|
||||
{
|
||||
private:
|
||||
T current;
|
||||
public:
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using difference_type = T;
|
||||
using value_type = T;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
|
||||
explicit range_itr(T current): current(current)
|
||||
{}
|
||||
|
||||
value_type operator*() const
|
||||
{ return current; }
|
||||
|
||||
value_type operator->()
|
||||
{ return current; }
|
||||
|
||||
range_itr& operator++()
|
||||
{
|
||||
current++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
range_itr& operator--()
|
||||
{
|
||||
current--;
|
||||
return *this;
|
||||
}
|
||||
|
||||
range_itr operator++(int)
|
||||
{
|
||||
auto tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
range_itr operator--(int)
|
||||
{
|
||||
auto tmp = *this;
|
||||
--(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(const range_itr& a, const range_itr& b)
|
||||
{
|
||||
return a.current == b.current;
|
||||
}
|
||||
|
||||
friend bool operator!=(const range_itr& a, const range_itr& b)
|
||||
{
|
||||
return a.current != b.current;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct range
|
||||
{
|
||||
private:
|
||||
T _begin;
|
||||
T _end;
|
||||
public:
|
||||
range(T begin, T end): _begin(begin), _end(end)
|
||||
{}
|
||||
|
||||
range_itr<T> begin()
|
||||
{
|
||||
return range_itr{_begin};
|
||||
}
|
||||
|
||||
range_itr<T> end()
|
||||
{
|
||||
return range_itr{_end};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename V>
|
||||
struct ptr_iterator
|
||||
{
|
||||
|
@ -242,98 +77,36 @@ namespace blt
|
|||
|
||||
/**
|
||||
* Creates an encapsulation of a T array which will be automatically deleted when this object goes out of scope.
|
||||
* This is a simple buffer meant to be used only inside of a function and not copied around.
|
||||
* This is a simple buffer meant to be used only inside of a function and not moved around, with a few minor exceptions.
|
||||
* The internal buffer is allocated on the heap.
|
||||
* The operator * has been overloaded to return the internal buffer.
|
||||
* @tparam T type that is stored in buffer eg char
|
||||
*/
|
||||
template<typename T, bool = std::is_copy_constructible_v<T> || std::is_copy_assignable_v<T>>
|
||||
class scoped_buffer
|
||||
template<typename T>
|
||||
struct scoped_buffer
|
||||
{
|
||||
private:
|
||||
T* _buffer = nullptr;
|
||||
T* _buffer;
|
||||
size_t _size;
|
||||
public:
|
||||
scoped_buffer(): _buffer(nullptr), _size(0)
|
||||
{}
|
||||
|
||||
explicit scoped_buffer(size_t size): _size(size)
|
||||
{
|
||||
if (size > 0)
|
||||
_buffer = new T[size];
|
||||
else
|
||||
_buffer = nullptr;
|
||||
}
|
||||
|
||||
scoped_buffer(const scoped_buffer& copy)
|
||||
{
|
||||
if (copy.size() == 0)
|
||||
{
|
||||
_buffer = nullptr;
|
||||
_size = 0;
|
||||
return;
|
||||
}
|
||||
_buffer = new T[copy.size()];
|
||||
_size = copy._size;
|
||||
|
||||
if constexpr (std::is_trivially_copyable_v<T>)
|
||||
{
|
||||
std::memcpy(_buffer, copy._buffer, copy.size() * sizeof(T));
|
||||
} else
|
||||
{
|
||||
if constexpr (std::is_copy_constructible_v<T> && !std::is_copy_assignable_v<T>)
|
||||
{
|
||||
for (size_t i = 0; i < this->_size; i++)
|
||||
_buffer[i] = T(copy[i]);
|
||||
} else
|
||||
for (size_t i = 0; i < this->_size; i++)
|
||||
_buffer[i] = copy[i];
|
||||
}
|
||||
}
|
||||
|
||||
scoped_buffer& operator=(const scoped_buffer& copy)
|
||||
{
|
||||
if (© == this)
|
||||
return *this;
|
||||
|
||||
if (copy.size() == 0)
|
||||
{
|
||||
_buffer = nullptr;
|
||||
_size = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
delete[] this->_buffer;
|
||||
_buffer = new T[copy.size()];
|
||||
_size = copy._size;
|
||||
|
||||
if constexpr (std::is_trivially_copyable_v<T>)
|
||||
{
|
||||
std::memcpy(_buffer, copy._buffer, copy.size() * sizeof(T));
|
||||
} else
|
||||
{
|
||||
if constexpr (std::is_copy_constructible_v<T> && !std::is_copy_assignable_v<T>)
|
||||
{
|
||||
for (size_t i = 0; i < this->_size; i++)
|
||||
_buffer[i] = T(copy[i]);
|
||||
} else
|
||||
for (size_t i = 0; i < this->_size; i++)
|
||||
_buffer[i] = copy[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
scoped_buffer(const scoped_buffer& copy) = delete;
|
||||
|
||||
scoped_buffer(scoped_buffer&& move) noexcept
|
||||
{
|
||||
delete[] _buffer;
|
||||
_buffer = move._buffer;
|
||||
_size = move.size();
|
||||
move._buffer = nullptr;
|
||||
}
|
||||
|
||||
scoped_buffer operator=(scoped_buffer& copyAssignment) = delete;
|
||||
|
||||
scoped_buffer& operator=(scoped_buffer&& moveAssignment) noexcept
|
||||
{
|
||||
delete[] _buffer;
|
||||
_buffer = moveAssignment._buffer;
|
||||
_size = moveAssignment.size();
|
||||
moveAssignment._buffer = nullptr;
|
||||
|
@ -361,22 +134,7 @@ namespace blt
|
|||
return _size;
|
||||
}
|
||||
|
||||
inline T*& ptr()
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
inline const T* const& ptr() const
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
inline const T* const& data() const
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
inline T*& data()
|
||||
inline T* ptr()
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
@ -397,16 +155,6 @@ namespace blt
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class scoped_buffer<T, false> : scoped_buffer<T, true>
|
||||
{
|
||||
using scoped_buffer<T, true>::scoped_buffer;
|
||||
public:
|
||||
scoped_buffer(const scoped_buffer& copy) = delete;
|
||||
|
||||
scoped_buffer operator=(scoped_buffer& copyAssignment) = delete;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct nullptr_initializer
|
||||
{
|
||||
|
|
|
@ -12,14 +12,10 @@
|
|||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <cctype>
|
||||
#include <blt/compatibility.h>
|
||||
|
||||
namespace blt::string
|
||||
{
|
||||
namespace blt::string {
|
||||
|
||||
class StringBuffer
|
||||
{
|
||||
class StringBuffer {
|
||||
private:
|
||||
const size_t BLOCK_SIZE = 4096;
|
||||
size_t front = 0;
|
||||
|
@ -27,130 +23,68 @@ namespace blt::string
|
|||
char* characterBuffer = nullptr;
|
||||
|
||||
void expand();
|
||||
|
||||
public:
|
||||
void trim();
|
||||
|
||||
std::string str();
|
||||
|
||||
StringBuffer()
|
||||
{
|
||||
StringBuffer(){
|
||||
characterBuffer = static_cast<char*>(malloc(BLOCK_SIZE));
|
||||
size = BLOCK_SIZE;
|
||||
}
|
||||
|
||||
StringBuffer& operator<<(char c);
|
||||
|
||||
StringBuffer& operator<<(const std::string& str)
|
||||
{
|
||||
StringBuffer& operator<<(const std::string& str) {
|
||||
for (char c : str)
|
||||
*this << c;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline StringBuffer& operator<<(T t)
|
||||
{
|
||||
inline StringBuffer& operator<<(T t) {
|
||||
*this << std::to_string(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~StringBuffer()
|
||||
{
|
||||
~StringBuffer() {
|
||||
free(characterBuffer);
|
||||
}
|
||||
};
|
||||
|
||||
static inline BLT_CPP20_CONSTEXPR bool starts_with(const std::string& string, const std::string& search)
|
||||
{
|
||||
#ifdef BLT_USE_CPP20
|
||||
return string.starts_with(search);
|
||||
#else
|
||||
static inline bool starts_with(const std::string& string, const std::string& search){
|
||||
if (search.length() > string.length())
|
||||
return false;
|
||||
auto chars = string.c_str();
|
||||
auto search_chars = search.c_str();
|
||||
for (unsigned int i = 0; i < search.length(); i++)
|
||||
{
|
||||
for (unsigned int i = 0; i < search.length(); i++){
|
||||
if (chars[i] != search_chars[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline BLT_CPP20_CONSTEXPR bool starts_with(const std::string& string, char search)
|
||||
{
|
||||
#ifdef BLT_USE_CPP20
|
||||
return string.starts_with(search);
|
||||
#else
|
||||
if (string.empty())
|
||||
return false;
|
||||
return string[0] == search;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline BLT_CPP20_CONSTEXPR bool ends_with(const std::string& string, const std::string& search)
|
||||
{
|
||||
#ifdef BLT_USE_CPP20
|
||||
return string.ends_with(search);
|
||||
#else
|
||||
static inline bool ends_with(const std::string& string, const std::string& search){
|
||||
if (search.length() > string.length())
|
||||
return false;
|
||||
auto chars = string.c_str();
|
||||
auto search_chars = search.c_str();
|
||||
auto startPosition = string.length() - search.length();
|
||||
for (unsigned int i = 0; i < search.length(); i++)
|
||||
{
|
||||
for (unsigned int i = 0; i < search.length(); i++){
|
||||
if (chars[startPosition + i] != search_chars[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline BLT_CPP20_CONSTEXPR bool ends_with(const std::string& string, char search)
|
||||
{
|
||||
#ifdef BLT_USE_CPP20
|
||||
return string.ends_with(search);
|
||||
#else
|
||||
if (string.empty())
|
||||
return false;
|
||||
return string[string.size() - 1] == search;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline BLT_CPP20_CONSTEXPR bool contains(const std::string& string, const char search)
|
||||
{
|
||||
#if __cplusplus >= 202002L
|
||||
return std::ranges::any_of(string, [search](const char c) -> bool {
|
||||
return c == search;
|
||||
});
|
||||
#else
|
||||
for (const char c : string)
|
||||
{
|
||||
if (c == search)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline BLT_CPP20_CONSTEXPR bool contains(const std::string& string, const std::string& search)
|
||||
{
|
||||
static inline bool contains(const std::string& string, const std::string& search){
|
||||
if (search.length() > string.length())
|
||||
return false;
|
||||
auto chars = string.c_str();
|
||||
auto search_chars = search.c_str();
|
||||
for (unsigned int i = 0; i < string.length(); i++)
|
||||
{
|
||||
if (chars[i] == search_chars[0])
|
||||
{
|
||||
for (unsigned int i = 0; i < string.length(); i++){
|
||||
if (chars[i] == search_chars[0]) {
|
||||
bool correct = true;
|
||||
for (unsigned int j = 0; j < search.length(); j++)
|
||||
{
|
||||
if (chars[i + j] != search_chars[j])
|
||||
{
|
||||
for (unsigned int j = 0; j < search.length(); j++) {
|
||||
if (chars[i + j] != search_chars[j]) {
|
||||
correct = false;
|
||||
break;
|
||||
}
|
||||
|
@ -161,21 +95,19 @@ namespace blt::string
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the string into lower case
|
||||
* @param s string to lower case
|
||||
* @return a string copy that is all lower case
|
||||
*/
|
||||
static inline BLT_CPP20_CONSTEXPR std::string toLowerCase(const std::string& s)
|
||||
{
|
||||
std::string str;
|
||||
static inline std::string toLowerCase(const std::string& s) {
|
||||
std::stringstream str;
|
||||
std::for_each(
|
||||
s.begin(), s.end(), [&str](unsigned char ch) {
|
||||
str += (char) std::tolower(ch);
|
||||
str << (char) std::tolower(ch);
|
||||
}
|
||||
);
|
||||
return str;
|
||||
return str.str();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -183,25 +115,22 @@ namespace blt::string
|
|||
* @param s string to upper case
|
||||
* @return a string copy that is all upper case
|
||||
*/
|
||||
static inline BLT_CPP20_CONSTEXPR std::string toUpperCase(const std::string& s)
|
||||
{
|
||||
std::string str;
|
||||
static inline std::string toUpperCase(const std::string& s) {
|
||||
std::stringstream str;
|
||||
std::for_each(
|
||||
s.begin(), s.end(), [&str](unsigned char ch) {
|
||||
str += (char) std::toupper(ch);
|
||||
str << (char) std::toupper(ch);
|
||||
}
|
||||
);
|
||||
return str;
|
||||
return str.str();
|
||||
}
|
||||
|
||||
// taken from https://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c
|
||||
// extended to return a vector
|
||||
static inline BLT_CPP20_CONSTEXPR std::vector<std::string> split(std::string s, const std::string& delim)
|
||||
{
|
||||
static inline std::vector<std::string> split(std::string s, const std::string& delim) {
|
||||
size_t pos = 0;
|
||||
std::vector<std::string> tokens;
|
||||
while ((pos = s.find(delim)) != std::string::npos)
|
||||
{
|
||||
while ((pos = s.find(delim)) != std::string::npos) {
|
||||
auto token = s.substr(0, pos);
|
||||
tokens.push_back(token);
|
||||
s.erase(0, pos + delim.length());
|
||||
|
@ -210,37 +139,20 @@ namespace blt::string
|
|||
return tokens;
|
||||
}
|
||||
|
||||
static inline BLT_CPP20_CONSTEXPR std::vector<std::string> split(std::string s, char delim)
|
||||
{
|
||||
size_t pos = 0;
|
||||
std::vector<std::string> tokens;
|
||||
while ((pos = s.find(delim)) != std::string::npos)
|
||||
{
|
||||
auto token = s.substr(0, pos);
|
||||
tokens.push_back(token);
|
||||
s.erase(0, pos + 1);
|
||||
}
|
||||
tokens.push_back(s);
|
||||
return tokens;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/3418231/replace-part-of-a-string-with-another-string
|
||||
static inline BLT_CPP20_CONSTEXPR bool replace(std::string& str, const std::string& from, const std::string& to)
|
||||
{
|
||||
static inline bool replace(std::string& str, const std::string& from, const std::string& to) {
|
||||
size_t start_pos = str.find(from);
|
||||
if (start_pos == std::string::npos)
|
||||
if(start_pos == std::string::npos)
|
||||
return false;
|
||||
str.replace(start_pos, from.length(), to);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline BLT_CPP20_CONSTEXPR void replaceAll(std::string& str, const std::string& from, const std::string& to)
|
||||
{
|
||||
if (from.empty())
|
||||
static inline void replaceAll(std::string& str, const std::string& from, const std::string& to) {
|
||||
if(from.empty())
|
||||
return;
|
||||
size_t start_pos = 0;
|
||||
while ((start_pos = str.find(from, start_pos)) != std::string::npos)
|
||||
{
|
||||
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
|
||||
str.replace(start_pos, from.length(), to);
|
||||
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
|
||||
}
|
||||
|
@ -250,8 +162,7 @@ namespace blt::string
|
|||
// taken from https://stackoverflow.com/questions/216823/how-to-trim-an-stdstring
|
||||
// would've preferred to use boost lib but instructions said to avoid external libs
|
||||
// trim from start (in place)
|
||||
static inline BLT_CPP20_CONSTEXPR std::string& ltrim(std::string& s)
|
||||
{
|
||||
static inline std::string& ltrim(std::string& s) {
|
||||
s.erase(
|
||||
s.begin(), std::find_if(
|
||||
s.begin(), s.end(), [](unsigned char ch) {
|
||||
|
@ -262,8 +173,7 @@ namespace blt::string
|
|||
}
|
||||
|
||||
// trim from end (in place)
|
||||
static inline BLT_CPP20_CONSTEXPR std::string& rtrim(std::string& s)
|
||||
{
|
||||
static inline std::string& rtrim(std::string& s) {
|
||||
s.erase(
|
||||
std::find_if(
|
||||
s.rbegin(), s.rend(), [](unsigned char ch) {
|
||||
|
@ -274,50 +184,30 @@ namespace blt::string
|
|||
}
|
||||
|
||||
// trim from both ends (in place)
|
||||
static inline BLT_CPP20_CONSTEXPR std::string& trim(std::string& s)
|
||||
{
|
||||
static inline std::string& trim(std::string& s) {
|
||||
ltrim(s);
|
||||
rtrim(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
// trim from start (copying)
|
||||
static inline BLT_CPP20_CONSTEXPR std::string ltrim_copy(std::string s)
|
||||
{
|
||||
static inline std::string ltrim_copy(std::string s) {
|
||||
ltrim(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
// trim from end (copying)
|
||||
static inline BLT_CPP20_CONSTEXPR std::string rtrim_copy(std::string s)
|
||||
{
|
||||
static inline std::string rtrim_copy(std::string s) {
|
||||
rtrim(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
// trim from both ends (copying)
|
||||
static inline BLT_CPP20_CONSTEXPR std::string trim_copy(std::string s)
|
||||
{
|
||||
static inline std::string trim_copy(std::string s) {
|
||||
trim(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline BLT_CPP20_CONSTEXPR bool is_numeric(const std::string& s)
|
||||
{
|
||||
#if __cplusplus >= 202002L
|
||||
return std::ranges::all_of(s, [](char c) -> bool {
|
||||
return std::isdigit(c);
|
||||
});
|
||||
#else
|
||||
for (const char c : s)
|
||||
{
|
||||
if (!std::isdigit(c))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //BLT_STRING_H
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
namespace blt::system
|
||||
{
|
||||
|
||||
static inline std::string ensureHasDigits(int current, int digits)
|
||||
{
|
||||
std::string asString = std::to_string(current);
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <blt/std/string.h>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
|
||||
namespace blt::uuid
|
||||
{
|
||||
|
@ -85,7 +84,7 @@ namespace blt::uuid
|
|||
std::stringstream ss;
|
||||
ss << std::hex;
|
||||
|
||||
const char dash[] = {0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0};
|
||||
const char dash[] = { 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0 };
|
||||
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
|
@ -156,7 +155,7 @@ namespace blt::uuid
|
|||
static uuid_t genV4()
|
||||
{
|
||||
std::random_device rd;
|
||||
std::seed_seq seed{rd(), rd(), rd(), rd()};
|
||||
std::seed_seq seed{ rd(), rd(), rd(), rd() };
|
||||
std::mt19937_64 gen(seed);
|
||||
std::uniform_int_distribution<int> dis(0, 15);
|
||||
std::uniform_int_distribution<> dis2(8, 11);
|
||||
|
@ -164,29 +163,24 @@ namespace blt::uuid
|
|||
std::stringstream ss;
|
||||
int i;
|
||||
ss << std::hex;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
for (i = 0; i < 8; i++) {
|
||||
ss << dis(gen);
|
||||
}
|
||||
ss << "-";
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
for (i = 0; i < 4; i++) {
|
||||
ss << dis(gen);
|
||||
}
|
||||
ss << "-4";
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
for (i = 0; i < 3; i++) {
|
||||
ss << dis(gen);
|
||||
}
|
||||
ss << "-";
|
||||
ss << dis2(gen);
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
for (i = 0; i < 3; i++) {
|
||||
ss << dis(gen);
|
||||
}
|
||||
ss << "-";
|
||||
for (i = 0; i < 12; i++)
|
||||
{
|
||||
for (i = 0; i < 12; i++) {
|
||||
ss << dis(gen);
|
||||
};
|
||||
|
||||
|
@ -194,6 +188,7 @@ namespace blt::uuid
|
|||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //BLT_UUID_H
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 401552da80b0971f818e648621260720ad40934e
|
||||
Subproject commit 93201da2ba5a6aba0a6e57ada64973555629b3e3
|
|
@ -54,7 +54,7 @@ namespace blt
|
|||
arg_vector_t::arg_vector_t(const char* str)
|
||||
{
|
||||
std::string as_string(str);
|
||||
if (blt::string::starts_with(str, '-'))
|
||||
if (as_string.starts_with('-'))
|
||||
flags.emplace_back(as_string);
|
||||
else
|
||||
name = as_string;
|
||||
|
@ -62,7 +62,7 @@ namespace blt
|
|||
|
||||
arg_vector_t::arg_vector_t(const std::string& str)
|
||||
{
|
||||
if (blt::string::starts_with(str, '-'))
|
||||
if (str.starts_with('-'))
|
||||
flags.emplace_back(str);
|
||||
else
|
||||
name = str;
|
||||
|
|
|
@ -248,12 +248,4 @@ namespace blt
|
|||
blt::printProfile(profile, flags, sort, log_level);
|
||||
profiles.erase(profile_name);
|
||||
}
|
||||
|
||||
interval_t::interval_t(pf_time_t wallStart, pf_time_t wallEnd, pf_time_t wallTotal, pf_time_t threadStart, pf_time_t threadEnd,
|
||||
pf_time_t threadTotal, pf_cycle_t cyclesStart, pf_cycle_t cyclesEnd, pf_cycle_t cyclesTotal, uint64_t count,
|
||||
std::string intervalName):
|
||||
wall_start(wallStart), wall_end(wallEnd), wall_total(wallTotal), thread_start(threadStart), thread_end(threadEnd),
|
||||
thread_total(threadTotal), cycles_start(cyclesStart), cycles_end(cyclesEnd), cycles_total(cyclesTotal), count(count),
|
||||
interval_name(std::move(intervalName))
|
||||
{}
|
||||
}
|
|
@ -4,87 +4,83 @@
|
|||
* See LICENSE file for license detail
|
||||
*/
|
||||
#include <blt/std/loader.h>
|
||||
#include <blt/std/assert.h>
|
||||
|
||||
std::vector<std::string> blt::fs::getLinesFromFile(const std::string& path)
|
||||
{
|
||||
std::string file = getFile(path);
|
||||
// split the file into the lines, this way we can get out the #include statements.
|
||||
return string::split(file, "\n");
|
||||
}
|
||||
|
||||
std::vector<std::string> blt::fs::recursiveInclude(const std::string& path, const std::string& include_header,
|
||||
const std::vector<include_guard>& guards)
|
||||
{
|
||||
std::string pathOnly = path.substr(0, path.find_last_of('/'));
|
||||
|
||||
auto mainLines = getLinesFromFile(path);
|
||||
std::vector<std::string> return_lines;
|
||||
|
||||
for (auto& line : mainLines)
|
||||
{
|
||||
// if the line is an include statement then we want to add lines recursively.
|
||||
auto include_pos = line.find(include_header);
|
||||
if (include_pos != std::string::npos)
|
||||
{
|
||||
auto past_include = include_pos + include_header.size();
|
||||
std::string file_to_include;
|
||||
|
||||
if (guards.empty())
|
||||
{
|
||||
file_to_include = line.substr(past_include);
|
||||
} else
|
||||
{
|
||||
size_t index = past_include;
|
||||
while (std::find_if(guards.begin(), guards.end(), [&](const include_guard& item) {
|
||||
return index < line.size() && line[index] == item.open;
|
||||
}) == guards.end())
|
||||
index++;
|
||||
index++;
|
||||
BLT_ASSERT(index < line.size() && "Include found but no file was provided!");
|
||||
|
||||
while (std::find_if(guards.begin(), guards.end(), [&](const include_guard& item) {
|
||||
return index < line.size() && line[index] == item.close;
|
||||
}) == guards.end())
|
||||
file_to_include += line[index++];
|
||||
}
|
||||
// ignore absolute paths TODO: path lib
|
||||
//if (!blt::string::starts_with(blt::string::trim(file_to_include), '/'))
|
||||
|
||||
auto lines = recursiveInclude(file_to_include, include_header, guards);
|
||||
for (const auto& i_line : lines)
|
||||
return_lines.push_back(i_line);
|
||||
} else
|
||||
return_lines.push_back(line);
|
||||
}
|
||||
|
||||
return return_lines;
|
||||
}
|
||||
|
||||
std::string blt::fs::getFile(const std::string& path)
|
||||
{
|
||||
std::string file_contents;
|
||||
std::ifstream the_file;
|
||||
if (!the_file.good())
|
||||
std::vector<std::string> blt::fs::getLinesFromFile(const std::string& path) {
|
||||
std::string shaderSource;
|
||||
std::ifstream shaderFile;
|
||||
if (!shaderFile.good())
|
||||
BLT_ERROR("Input stream not good!\n");
|
||||
// ensure ifstream objects can throw exceptions:
|
||||
the_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
try
|
||||
{
|
||||
shaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
try {
|
||||
// open file
|
||||
the_file.open(path);
|
||||
std::stringstream file_stream;
|
||||
shaderFile.open(path);
|
||||
std::stringstream shaderStream;
|
||||
// read file's buffer contents into streams
|
||||
file_stream << the_file.rdbuf();
|
||||
shaderStream << shaderFile.rdbuf();
|
||||
// close file handlers
|
||||
the_file.close();
|
||||
shaderFile.close();
|
||||
// convert stream into std::string
|
||||
file_contents = file_stream.str();
|
||||
} catch (std::ifstream::failure& e)
|
||||
{
|
||||
shaderSource = shaderStream.str();
|
||||
} catch (std::ifstream::failure& e) {
|
||||
BLT_WARN("Unable to read file '%s'!\n", path.c_str());
|
||||
BLT_WARN("Exception: %s", e.what());
|
||||
throw std::runtime_error("Failed to read file!\n");
|
||||
}
|
||||
return file_contents;
|
||||
|
||||
// split the shader into the lines, this way we can get out the #include statements.
|
||||
return string::split(shaderSource, "\n");
|
||||
}
|
||||
|
||||
std::vector<std::string> blt::fs::recursiveShaderInclude(const std::string& path) {
|
||||
std::string pathOnly = path.substr(0, path.find_last_of('/'));
|
||||
|
||||
auto mainLines = getLinesFromFile(path);
|
||||
std::unordered_map<int, std::vector<std::string>> includes;
|
||||
|
||||
for (unsigned int i = 0; i < mainLines.size(); i++) {
|
||||
auto& line = mainLines[i];
|
||||
// if the line is an include statement then we want to add lines recursively.
|
||||
if (string::starts_with(line, "#include")) {
|
||||
std::vector<std::string> include_statement = string::split(line, "<");
|
||||
|
||||
if (include_statement.size() <= 1)
|
||||
include_statement = string::split(line, "\"");
|
||||
|
||||
string::trim(line);
|
||||
if (!(string::ends_with(line, ">") || string::ends_with(line, "\""))) {
|
||||
BLT_FATAL("Shader file contains an invalid #include statement. (Missing terminator)\n");
|
||||
std::abort();
|
||||
}
|
||||
try {
|
||||
// filter out the > or " at the end of the include statement.
|
||||
std::string file;
|
||||
file = include_statement[1];
|
||||
if (string::ends_with(include_statement[1], ">"))
|
||||
file = file.substr(0, file.size() - 1);
|
||||
|
||||
BLT_TRACE("Recusing into %s/%s\n", pathOnly.c_str(), file.c_str());
|
||||
|
||||
includes.insert({i, recursiveShaderInclude((pathOnly + "/" + file))});
|
||||
} catch (std::exception& e) {
|
||||
BLT_FATAL("Shader file contains an invalid #include statement. (Missing < or \")\n");
|
||||
BLT_FATAL("Exception: %s", e.what());
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> returnLines;
|
||||
|
||||
// now combine all the loaded files while respecting the include's position in the file.
|
||||
for (unsigned int i = 0; i < mainLines.size(); i++) {
|
||||
if (!includes[i].empty()) {
|
||||
auto includedFileLines = includes[i];
|
||||
|
||||
for (const auto& line : includedFileLines)
|
||||
returnLines.push_back(line);
|
||||
} else
|
||||
returnLines.push_back(mainLines[i]);
|
||||
}
|
||||
return returnLines;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue