From 7fa4fd0af29e7c9eb7c6ab1adf48cef0b6d38850 Mon Sep 17 00:00:00 2001 From: Brett Laptop Date: Thu, 3 Oct 2024 19:55:04 -0400 Subject: [PATCH] some ansi codes --- CMakeLists.txt | 2 +- include/blt/std/logging.h | 996 +++++++++++++++++++++---------------- libraries/parallel-hashmap | 2 +- 3 files changed, 572 insertions(+), 428 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a55502f..46a7ffc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 2.0.4) +set(BLT_VERSION 2.0.5) set(BLT_TARGET BLT) diff --git a/include/blt/std/logging.h b/include/blt/std/logging.h index e68c71a..d017555 100644 --- a/include/blt/std/logging.h +++ b/include/blt/std/logging.h @@ -18,6 +18,149 @@ namespace blt::logging { + namespace ansi + { + inline auto ESC(std::string_view str) + { + return std::string("\033") += str; + } + + inline const auto CUR_HOME = ESC("[H"); + + inline auto CUR_MOVE(blt::size_t line, blt::size_t column) + { + return ESC("[{" + std::to_string(line) + "};{" + std::to_string(column) + "}H"); + } + + inline auto CUR_UP(blt::size_t lines) + { + return ESC("[" + std::to_string(lines) + "A"); + } + + inline auto CUR_DOWN(blt::size_t lines) + { + return ESC("[" + std::to_string(lines) + "B"); + } + + inline auto CUR_RIGHT(blt::size_t columns) + { + return ESC("[" + std::to_string(columns) + "C"); + } + + inline auto CUR_LEFT(blt::size_t columns) + { + return ESC("[" + std::to_string(columns) + "D"); + } + + inline auto CUR_BEGIN_NEXT(blt::size_t lines_down) + { + return ESC("[" + std::to_string(lines_down) + "E"); + } + + inline auto CUR_BEGIN_PREV(blt::size_t lines_up) + { + return ESC("[" + std::to_string(lines_up) + "F"); + } + + inline auto CUR_COLUMN(blt::size_t column) + { + return ESC("[" + std::to_string(column) + "G"); + } + + inline auto CUR_POS() + { + return ESC("[6n"); + } + + inline auto CUR_SCROLL_UP() + { + return ESC(" M"); + } + + inline auto CUR_SAVE_DEC() + { + return ESC(" 7"); + } + + inline auto CUR_LOAD_DEC() + { + return ESC(" 8"); + } + + inline auto CUR_SAVE_SCO() + { + return ESC("[s"); + } + + inline auto CUR_LOAD_SCO() + { + return ESC("[u"); + } + + inline auto RESET = ESC("[0m"); + inline auto BOLD = "1"; + inline auto RESET_BOLD = "22"; + inline auto DIM = "2"; + inline auto RESET_DIM = "22"; + inline auto ITALIC = "3"; + inline auto RESET_ITALIC = "23"; + inline auto UNDERLINE = "4"; + inline auto RESET_UNDERLINE = "24"; + inline auto BLINKING = "5"; + inline auto RESET_BLINKING = "25"; + inline auto INVERSE = "7"; + inline auto RESET_INVERSE = "27"; + inline auto HIDDEN = "8"; + inline auto RESET_HIDDEN = "28"; + inline auto STRIKETHROUGH = "9"; + inline auto RESET_STRIKETHROUGH = "29"; + + inline auto COLOR_DEFAULT = "39"; + inline auto BACKGROUND_DEFAULT = "49"; + + inline auto BLACK = "30"; + inline auto RED = "31"; + inline auto GREEN = "32"; + inline auto YELLOW = "33"; + inline auto BLUE = "34"; + inline auto MAGENTA = "35"; + inline auto CYAN = "36"; + inline auto WHITE = "37"; + inline auto BLACK_BACKGROUND = "40"; + inline auto RED_BACKGROUND = "41"; + inline auto GREEN_BACKGROUND = "42"; + inline auto YELLOW_BACKGROUND = "43"; + inline auto BLUE_BACKGROUND = "44"; + inline auto MAGENTA_BACKGROUND = "45"; + inline auto CYAN_BACKGROUND = "46"; + inline auto WHITE_BACKGROUND = "47"; + + inline auto BRIGHT_BLACK = "90"; + inline auto BRIGHT_RED = "91"; + inline auto BRIGHT_GREEN = "92"; + inline auto BRIGHT_YELLOW = "93"; + inline auto BRIGHT_BLUE = "94"; + inline auto BRIGHT_MAGENTA = "95"; + inline auto BRIGHT_CYAN = "96"; + inline auto BRIGHT_WHITE = "97"; + inline auto BRIGHT_BLACK_BACKGROUND = "100"; + inline auto BRIGHT_RED_BACKGROUND = "101"; + inline auto BRIGHT_GREEN_BACKGROUND = "102"; + inline auto BRIGHT_YELLOW_BACKGROUND = "103"; + inline auto BRIGHT_BLUE_BACKGROUND = "104"; + inline auto BRIGHT_MAGENTA_BACKGROUND = "105"; + inline auto BRIGHT_CYAN_BACKGROUND = "106"; + inline auto BRIGHT_WHITE_BACKGROUND = "107"; + + template + inline auto MAKE_COLOR(Args... colors) + { + std::string mode; + ((mode + std::string(colors) + ";"), ...); + return ESC("[" + mode.substr(0, mode.size() - 1) + "m"); + } + } + enum class log_level { // default @@ -146,7 +289,8 @@ namespace blt::logging } else if constexpr (std::is_same_v) { log_internal(t, level, file, line, args); - } else if constexpr (std::is_same_v){ + } else if constexpr (std::is_same_v) + { log_internal(std::string(t), level, file, line, args); } else { @@ -215,111 +359,111 @@ namespace blt::logging #endif #include #include - - template - using hashmap = std::unordered_map; + +template +using hashmap = std::unordered_map; namespace blt::logging { - - /** - * Used to store fast associations between built in tags and their respective values - */ - class tag_map { - private: - tag* tags; - size_t size; - - [[nodiscard]] static inline size_t hash(const tag& t) { - size_t h = t.tag[1] * 3 - t.tag[0]; - return h - 100; - } - - // TODO: fix - void expand() { - auto newSize = size * 2; - auto newTags = new tag[newSize]; - for (size_t i = 0; i < size; i++) - newTags[i] = tags[i]; - delete[] tags; - tags = newTags; - size = newSize; - } - public: - tag_map(std::initializer_list initial_tags){ - size_t max = 0; - for (const auto& t : initial_tags) - max = std::max(max, hash(t)); - tags = new tag[(size = max+1)]; - for (const auto& t : initial_tags) - insert(t); - } - tag_map(const tag_map& copy) { - tags = new tag[(size = copy.size)]; - for (size_t i = 0; i < size; i++) - tags[i] = copy.tags[i]; - } - - void insert(const tag& t) { - auto h = hash(t); - //if (h > size) - // expand(); - if (!tags[h].tag.empty()) - std::cerr << "Tag not empty! " << tags[h].tag << "!!!\n"; - tags[h] = t; - } - - tag& operator[](const std::string& name) const { - auto h = hash(tag{name, nullptr}); - if (h > size) - std::cerr << "Tag out of bounds"; - return tags[h]; - } - - ~tag_map(){ - delete[] tags; - tags = nullptr; - } - }; - - class LogFileWriter { - private: - std::string m_path; - std::fstream* output = nullptr; - public: - explicit LogFileWriter() = default; - - void writeLine(const std::string& path, const std::string& line){ - if (path != m_path || output == nullptr){ - clear(); - delete output; - output = new std::fstream(path, std::ios::out | std::ios::app); - if (!output->good()){ - throw std::runtime_error("Unable to open console filestream!\n"); - } - } - if (!output->good()){ - std::cerr << "There has been an error in the logging file stream!\n"; - output->clear(); - } - *output << line; - } - - void clear(){ - if (output != nullptr) { - try { - output->flush(); - output->close(); - } catch (std::exception& e){ - std::cerr << e.what() << "\n"; - } - } - } - - ~LogFileWriter() { + +/** + * Used to store fast associations between built in tags and their respective values + */ +class tag_map { + private: + tag* tags; + size_t size; + + [[nodiscard]] static inline size_t hash(const tag& t) { + size_t h = t.tag[1] * 3 - t.tag[0]; + return h - 100; + } + + // TODO: fix + void expand() { + auto newSize = size * 2; + auto newTags = new tag[newSize]; + for (size_t i = 0; i < size; i++) + newTags[i] = tags[i]; + delete[] tags; + tags = newTags; + size = newSize; + } + public: + tag_map(std::initializer_list initial_tags){ + size_t max = 0; + for (const auto& t : initial_tags) + max = std::max(max, hash(t)); + tags = new tag[(size = max+1)]; + for (const auto& t : initial_tags) + insert(t); + } + tag_map(const tag_map& copy) { + tags = new tag[(size = copy.size)]; + for (size_t i = 0; i < size; i++) + tags[i] = copy.tags[i]; + } + + void insert(const tag& t) { + auto h = hash(t); + //if (h > size) + // expand(); + if (!tags[h].tag.empty()) + std::cerr << "Tag not empty! " << tags[h].tag << "!!!\n"; + tags[h] = t; + } + + tag& operator[](const std::string& name) const { + auto h = hash(tag{name, nullptr}); + if (h > size) + std::cerr << "Tag out of bounds"; + return tags[h]; + } + + ~tag_map(){ + delete[] tags; + tags = nullptr; + } +}; + +class LogFileWriter { + private: + std::string m_path; + std::fstream* output = nullptr; + public: + explicit LogFileWriter() = default; + + void writeLine(const std::string& path, const std::string& line){ + if (path != m_path || output == nullptr){ clear(); - delete(output); + delete output; + output = new std::fstream(path, std::ios::out | std::ios::app); + if (!output->good()){ + throw std::runtime_error("Unable to open console filestream!\n"); + } } - }; + if (!output->good()){ + std::cerr << "There has been an error in the logging file stream!\n"; + output->clear(); + } + *output << line; + } + + void clear(){ + if (output != nullptr) { + try { + output->flush(); + output->close(); + } catch (std::exception& e){ + std::cerr << e.what() << "\n"; + } + } + } + + ~LogFileWriter() { + clear(); + delete(output); + } +}; #ifdef WIN32 #define BLT_NOW() auto t = std::time(nullptr); tm now{}; localtime_s(&now, &t) @@ -338,352 +482,352 @@ namespace blt::logging { S += ensureHasDigits(now.tm_min, 2); \ S += ':'; \ S += ensureHasDigits(now.tm_sec, 2); - - static inline std::string ensureHasDigits(int current, int digits) { - std::string asString = std::to_string(current); - auto length = digits - asString.length(); - if (length <= 0) - return asString; - std::string zeros; - zeros.reserve(length); - for (unsigned int i = 0; i < length; i++){ - zeros += '0'; - } - return zeros + asString; - } - log_format loggingFormat {}; - hashmap loggingThreadNames; - hashmap> loggingStreamLines; - LogFileWriter writer; - - const std::unique_ptr tagMap = std::make_unique(tag_map{ - {"YEAR", [](const tag_func_param&) -> std::string { - BLT_NOW(); - return std::to_string(now.tm_year); - }}, - {"MONTH", [](const tag_func_param&) -> std::string { - BLT_NOW(); - return ensureHasDigits(now.tm_mon+1, 2); - }}, - {"DAY", [](const tag_func_param&) -> std::string { - BLT_NOW(); - return ensureHasDigits(now.tm_mday, 2); - }}, - {"HOUR", [](const tag_func_param&) -> std::string { - BLT_NOW(); - return ensureHasDigits(now.tm_hour, 2); - }}, - {"MINUTE", [](const tag_func_param&) -> std::string { - BLT_NOW(); - return ensureHasDigits(now.tm_min, 2); - }}, - {"SECOND", [](const tag_func_param&) -> std::string { - BLT_NOW(); - return ensureHasDigits(now.tm_sec, 2); - }}, - {"MS", [](const tag_func_param&) -> std::string { - return std::to_string(std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch()).count() - ); - }}, - {"NS", [](const tag_func_param&) -> std::string { - return std::to_string(std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch()).count() - ); - }}, - {"ISO_YEAR", [](const tag_func_param&) -> std::string { - BLT_NOW(); - BLT_ISO_YEAR(returnStr); - return returnStr; - }}, - {"TIME", [](const tag_func_param&) -> std::string { - BLT_NOW(); - BLT_CUR_TIME(returnStr); - return returnStr; - }}, - {"FULL_TIME", [](const tag_func_param&) -> std::string { - BLT_NOW(); - BLT_ISO_YEAR(ISO); - BLT_CUR_TIME(TIME); - ISO += ' '; - ISO += TIME; - return ISO; - }}, - {"LF", [](const tag_func_param& f) -> std::string { - return loggingFormat.levelColors[(int)f.level]; - }}, - {"ER", [](const tag_func_param&) -> std::string { - return loggingFormat.levelColors[(int)log_level::ERROR]; - }}, - {"CNR", [](const tag_func_param& f) -> std::string { - return f.level >= log_level::ERROR ? loggingFormat.levelColors[(int)log_level::ERROR] : ""; - }}, - {"RC", [](const tag_func_param&) -> std::string { - return "\033[0m"; - }}, - {"LOG_LEVEL", [](const tag_func_param& f) -> std::string { - return loggingFormat.levelNames[(int)f.level]; - }}, - {"THREAD_NAME", [](const tag_func_param&) -> std::string { - if (loggingThreadNames.find(std::this_thread::get_id()) == loggingThreadNames.end()) - return "UNKNOWN"; - return loggingThreadNames[std::this_thread::get_id()]; - }}, - {"FILE", [](const tag_func_param& f) -> std::string { - return f.file; - }}, - {"LINE", [](const tag_func_param& f) -> std::string { - return f.line; - }}, - {"RAW_STR", [](const tag_func_param& f) -> std::string { - return f.raw_string; - }}, - {"STR", [](const tag_func_param& f) -> std::string { - return f.formatted_string; - }} - }); - - static inline std::vector split(std::string s, const std::string& delim) { - size_t pos = 0; - std::vector tokens; - while ((pos = s.find(delim)) != std::string::npos) { - auto token = s.substr(0, pos); - tokens.push_back(token); - s.erase(0, pos + delim.length()); +static inline std::string ensureHasDigits(int current, int digits) { + std::string asString = std::to_string(current); + auto length = digits - asString.length(); + if (length <= 0) + return asString; + std::string zeros; + zeros.reserve(length); + for (unsigned int i = 0; i < length; i++){ + zeros += '0'; + } + return zeros + asString; +} + +log_format loggingFormat {}; +hashmap loggingThreadNames; +hashmap> loggingStreamLines; +LogFileWriter writer; + +const std::unique_ptr tagMap = std::make_unique(tag_map{ + {"YEAR", [](const tag_func_param&) -> std::string { + BLT_NOW(); + return std::to_string(now.tm_year); + }}, + {"MONTH", [](const tag_func_param&) -> std::string { + BLT_NOW(); + return ensureHasDigits(now.tm_mon+1, 2); + }}, + {"DAY", [](const tag_func_param&) -> std::string { + BLT_NOW(); + return ensureHasDigits(now.tm_mday, 2); + }}, + {"HOUR", [](const tag_func_param&) -> std::string { + BLT_NOW(); + return ensureHasDigits(now.tm_hour, 2); + }}, + {"MINUTE", [](const tag_func_param&) -> std::string { + BLT_NOW(); + return ensureHasDigits(now.tm_min, 2); + }}, + {"SECOND", [](const tag_func_param&) -> std::string { + BLT_NOW(); + return ensureHasDigits(now.tm_sec, 2); + }}, + {"MS", [](const tag_func_param&) -> std::string { + return std::to_string(std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()).count() + ); + }}, + {"NS", [](const tag_func_param&) -> std::string { + return std::to_string(std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()).count() + ); + }}, + {"ISO_YEAR", [](const tag_func_param&) -> std::string { + BLT_NOW(); + BLT_ISO_YEAR(returnStr); + return returnStr; + }}, + {"TIME", [](const tag_func_param&) -> std::string { + BLT_NOW(); + BLT_CUR_TIME(returnStr); + return returnStr; + }}, + {"FULL_TIME", [](const tag_func_param&) -> std::string { + BLT_NOW(); + BLT_ISO_YEAR(ISO); + BLT_CUR_TIME(TIME); + ISO += ' '; + ISO += TIME; + return ISO; + }}, + {"LF", [](const tag_func_param& f) -> std::string { + return loggingFormat.levelColors[(int)f.level]; + }}, + {"ER", [](const tag_func_param&) -> std::string { + return loggingFormat.levelColors[(int)log_level::ERROR]; + }}, + {"CNR", [](const tag_func_param& f) -> std::string { + return f.level >= log_level::ERROR ? loggingFormat.levelColors[(int)log_level::ERROR] : ""; + }}, + {"RC", [](const tag_func_param&) -> std::string { + return "\033[0m"; + }}, + {"LOG_LEVEL", [](const tag_func_param& f) -> std::string { + return loggingFormat.levelNames[(int)f.level]; + }}, + {"THREAD_NAME", [](const tag_func_param&) -> std::string { + if (loggingThreadNames.find(std::this_thread::get_id()) == loggingThreadNames.end()) + return "UNKNOWN"; + return loggingThreadNames[std::this_thread::get_id()]; + }}, + {"FILE", [](const tag_func_param& f) -> std::string { + return f.file; + }}, + {"LINE", [](const tag_func_param& f) -> std::string { + return f.line; + }}, + {"RAW_STR", [](const tag_func_param& f) -> std::string { + return f.raw_string; + }}, + {"STR", [](const tag_func_param& f) -> std::string { + return f.formatted_string; + }} +}); + +static inline std::vector split(std::string s, const std::string& delim) { + size_t pos = 0; + std::vector tokens; + while ((pos = s.find(delim)) != std::string::npos) { + auto token = s.substr(0, pos); + tokens.push_back(token); + s.erase(0, pos + delim.length()); + } + tokens.push_back(s); + return tokens; +} + +inline std::string filename(const std::string& path){ + if (loggingFormat.printFullFileName) + return path; + auto paths = split(path, "/"); + auto final = paths[paths.size()-1]; + if (final == "/") + return paths[paths.size()-2]; + return final; +} + +class string_parser { + private: + std::string _str; + size_t _pos; + public: + explicit string_parser(std::string str): _str(std::move(str)), _pos(0) {} + + inline char next(){ + return _str[_pos++]; } - tokens.push_back(s); - return tokens; - } - - inline std::string filename(const std::string& path){ - if (loggingFormat.printFullFileName) - return path; - auto paths = split(path, "/"); - auto final = paths[paths.size()-1]; - if (final == "/") - return paths[paths.size()-2]; - return final; - } - - class string_parser { - private: - std::string _str; - size_t _pos; - public: - explicit string_parser(std::string str): _str(std::move(str)), _pos(0) {} - - inline char next(){ - return _str[_pos++]; - } - - [[nodiscard]] inline bool has_next() const { - return _pos < _str.size(); - } - }; - - std::string stripANSI(const std::string& str){ - string_parser parser(str); - std::string out; - while (parser.has_next()){ - char c = parser.next(); - if (c == '\033'){ - while (parser.has_next() && parser.next() != 'm'); - } else - out += c; + + [[nodiscard]] inline bool has_next() const { + return _pos < _str.size(); } - return out; +}; + +std::string stripANSI(const std::string& str){ + string_parser parser(str); + std::string out; + while (parser.has_next()){ + char c = parser.next(); + if (c == '\033'){ + while (parser.has_next() && parser.next() != 'm'); + } else + out += c; } + return out; +} + +void applyCFormatting(const std::string& format, std::string& output, std::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); - void applyCFormatting(const std::string& format, std::string& output, std::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); - - auto buffer_size = std::vsnprintf(nullptr, 0, format.c_str(), args_copy) + 1; - auto* buffer = new char[static_cast(buffer_size)]; - - vsnprintf(buffer, buffer_size, format.c_str(), args); - output = std::string(buffer); - - delete[] buffer; - - va_end(args_copy); - } + auto buffer_size = std::vsnprintf(nullptr, 0, format.c_str(), args_copy) + 1; + auto* buffer = new char[static_cast(buffer_size)]; - /** - * Checks if the next character in the parser is a tag opening, if not output the buffer to the out string - */ - inline bool tagOpening(string_parser& parser, std::string& out){ - char c = ' '; + vsnprintf(buffer, buffer_size, format.c_str(), args); + output = std::string(buffer); + + delete[] buffer; + + va_end(args_copy); +} + +/** + * Checks if the next character in the parser is a tag opening, if not output the buffer to the out string + */ +inline bool tagOpening(string_parser& parser, std::string& out){ + char c = ' '; + if (parser.has_next() && (c = parser.next()) == '{') if (parser.has_next() && (c = parser.next()) == '{') - if (parser.has_next() && (c = parser.next()) == '{') - return true; - else - out += c; + return true; else out += c; - return false; - } - - void parseString(string_parser& parser, std::string& out, const std::string& userStr, log_level level, const char* file, int line){ - while (parser.has_next()){ - char c = parser.next(); - std::string nonTag; - if (c == '$' && tagOpening(parser, nonTag)){ - std::string tag; - while (parser.has_next()){ - c = parser.next(); - if (c == '}') - break; - tag += c; - } + else + out += c; + return false; +} + +void parseString(string_parser& parser, std::string& out, const std::string& userStr, log_level level, const char* file, int line){ + while (parser.has_next()){ + char c = parser.next(); + std::string nonTag; + if (c == '$' && tagOpening(parser, nonTag)){ + std::string tag; + while (parser.has_next()){ c = parser.next(); - if (parser.has_next() && c != '}') { - std::cerr << "Error processing tag, is not closed with two '}'!\n"; + if (c == '}') break; + tag += c; + } + c = parser.next(); + if (parser.has_next() && c != '}') { + std::cerr << "Error processing tag, is not closed with two '}'!\n"; + break; + } + if (loggingFormat.ensureAlignment && tag == "STR") { + auto currentOutputWidth = out.size(); + auto& longestWidth = loggingFormat.currentWidth; + longestWidth = std::max(longestWidth, currentOutputWidth); + // pad with spaces + if (currentOutputWidth != longestWidth){ + for (size_t i = currentOutputWidth; i < longestWidth; i++) + out += ' '; } - if (loggingFormat.ensureAlignment && tag == "STR") { - auto currentOutputWidth = out.size(); - auto& longestWidth = loggingFormat.currentWidth; - longestWidth = std::max(longestWidth, currentOutputWidth); - // pad with spaces - if (currentOutputWidth != longestWidth){ - for (size_t i = currentOutputWidth; i < longestWidth; i++) - out += ' '; - } - } - tag_func_param param{ - level, filename({file}), std::to_string(line), userStr, userStr - }; - out += (*tagMap)[tag].func(param); - } else { - out += c; - out += nonTag; } + tag_func_param param{ + level, filename({file}), std::to_string(line), userStr, userStr + }; + out += (*tagMap)[tag].func(param); + } else { + out += c; + out += nonTag; } } +} + +std::string applyFormatString(const std::string& str, log_level level, const char* file, int line){ + // this can be speedup by preprocessing the string into an easily callable class + // where all the variables are ready to be substituted in one step + // and all static information already entered + string_parser parser(loggingFormat.logOutputFormat); + std::string out; + parseString(parser, out, str, level, file, line); - std::string applyFormatString(const std::string& str, log_level level, const char* file, int line){ - // this can be speedup by preprocessing the string into an easily callable class - // where all the variables are ready to be substituted in one step - // and all static information already entered - string_parser parser(loggingFormat.logOutputFormat); - std::string out; - parseString(parser, out, str, level, file, line); - - return out; + return out; +} + +void log_internal(const std::string& format, log_level level, const char* file, int line, std::va_list& args) { + std::string withoutLn = format; + auto len = withoutLn.length(); + + if (len > 0 && withoutLn[len - 1] == '\n') + withoutLn = withoutLn.substr(0, len-1); + + std::string out; + + applyCFormatting(withoutLn, out, args); + + if (level == log_level::NONE){ + std::cout << out << std::endl; + return; } - void log_internal(const std::string& format, log_level level, const char* file, int line, std::va_list& args) { - std::string withoutLn = format; - auto len = withoutLn.length(); - - if (len > 0 && withoutLn[len - 1] == '\n') - withoutLn = withoutLn.substr(0, len-1); - - std::string out; - - applyCFormatting(withoutLn, out, args); - - if (level == log_level::NONE){ - std::cout << out << std::endl; - return; - } - - std::string finalFormattedOutput = applyFormatString(out, level, file, line); - - if (loggingFormat.logToConsole) - std::cout << finalFormattedOutput; - - - if (loggingFormat.logToFile){ - string_parser parser(loggingFormat.logFileName); - std::string fileName; - parseString(parser, fileName, withoutLn, level, file, line); - - auto path = loggingFormat.logFilePath; - if (!path.empty() && path[path.length()-1] != '/') - path += '/'; - - // if the file has changed (new day in default case) we should reset the rollover count - if (loggingFormat.lastFile != fileName){ - loggingFormat.currentRollover = 0; - loggingFormat.lastFile = fileName; - } - - path += fileName; - path += '-'; - path += std::to_string(loggingFormat.currentRollover); - path += ".log"; - - if (std::filesystem::exists(path)) { - auto fileSize = std::filesystem::file_size(path); - - // will start on next file - if (fileSize > loggingFormat.logMaxFileSize) - loggingFormat.currentRollover++; - } - - writer.writeLine(path, stripANSI(finalFormattedOutput)); - } - //std::cout.flush(); - } + std::string finalFormattedOutput = applyFormatString(out, level, file, line); - void log_stream_internal(const std::string& str, const logger& logger) { - auto& s = loggingStreamLines[std::this_thread::get_id()][logger.level]; + if (loggingFormat.logToConsole) + std::cout << finalFormattedOutput; + + + if (loggingFormat.logToFile){ + string_parser parser(loggingFormat.logFileName); + std::string fileName; + parseString(parser, fileName, withoutLn, level, file, line); + + auto path = loggingFormat.logFilePath; + if (!path.empty() && path[path.length()-1] != '/') + path += '/'; + + // if the file has changed (new day in default case) we should reset the rollover count + if (loggingFormat.lastFile != fileName){ + loggingFormat.currentRollover = 0; + loggingFormat.lastFile = fileName; + } + + path += fileName; + path += '-'; + path += std::to_string(loggingFormat.currentRollover); + path += ".log"; + + if (std::filesystem::exists(path)) { + auto fileSize = std::filesystem::file_size(path); + + // will start on next file + if (fileSize > loggingFormat.logMaxFileSize) + loggingFormat.currentRollover++; + } + + writer.writeLine(path, stripANSI(finalFormattedOutput)); + } + //std::cout.flush(); +} + +void log_stream_internal(const std::string& str, const logger& logger) { + auto& s = loggingStreamLines[std::this_thread::get_id()][logger.level]; // s += str; - for (char c : str){ - s += c; - if (c == '\n'){ - log(s, logger.level, logger.file, logger.line); - s = ""; - } + for (char c : str){ + s += c; + if (c == '\n'){ + log(s, logger.level, logger.file, logger.line); + s = ""; } } - - void setThreadName(const std::string& name) { - loggingThreadNames[std::this_thread::get_id()] = name; - } - - void setLogFormat(const log_format& format){ - loggingFormat = format; - } - void setLogColor(log_level level, const std::string& newFormat){ - loggingFormat.levelColors[(int)level] = newFormat; - } - void setLogName(log_level level, const std::string& newFormat){ - loggingFormat.levelNames[(int)level] = newFormat; - } - void setLogOutputFormat(const std::string& newFormat){ - loggingFormat.logOutputFormat = newFormat; - } - void setLogToFile(bool shouldLogToFile){ - loggingFormat.logToFile = shouldLogToFile; - } - void setLogToConsole(bool shouldLogToConsole){ - loggingFormat.logToConsole = shouldLogToConsole; - } - void setLogPath(const std::string& path){ - loggingFormat.logFilePath = path; - } - void setLogFileName(const std::string& fileName){ - loggingFormat.logFileName = fileName; - } - void setMaxFileSize(size_t fileSize) { - loggingFormat.logMaxFileSize = fileSize; - } - - void flush() { - std::cerr.flush(); - std::cout.flush(); - } - - void newline() - { - std::cout << std::endl; - } - +} + +void setThreadName(const std::string& name) { + loggingThreadNames[std::this_thread::get_id()] = name; +} + +void setLogFormat(const log_format& format){ + loggingFormat = format; +} +void setLogColor(log_level level, const std::string& newFormat){ + loggingFormat.levelColors[(int)level] = newFormat; +} +void setLogName(log_level level, const std::string& newFormat){ + loggingFormat.levelNames[(int)level] = newFormat; +} +void setLogOutputFormat(const std::string& newFormat){ + loggingFormat.logOutputFormat = newFormat; +} +void setLogToFile(bool shouldLogToFile){ + loggingFormat.logToFile = shouldLogToFile; +} +void setLogToConsole(bool shouldLogToConsole){ + loggingFormat.logToConsole = shouldLogToConsole; +} +void setLogPath(const std::string& path){ + loggingFormat.logFilePath = path; +} +void setLogFileName(const std::string& fileName){ + loggingFormat.logFileName = fileName; +} +void setMaxFileSize(size_t fileSize) { + loggingFormat.logMaxFileSize = fileSize; +} + +void flush() { + std::cerr.flush(); + std::cout.flush(); +} + +void newline() +{ + std::cout << std::endl; +} + } #endif diff --git a/libraries/parallel-hashmap b/libraries/parallel-hashmap index 93201da..63acc33 160000 --- a/libraries/parallel-hashmap +++ b/libraries/parallel-hashmap @@ -1 +1 @@ -Subproject commit 93201da2ba5a6aba0a6e57ada64973555629b3e3 +Subproject commit 63acc3336f941c6f324c88eb9ee4ce623a460cd5