From 0914d3145d288fb75e276d7ed9295b9689b264e6 Mon Sep 17 00:00:00 2001 From: Geoffrey Merck Date: Sun, 2 Jan 2022 09:50:51 +0100 Subject: [PATCH] #10 get rid of slow stringstream and add in place formating of string --- Log.h | 35 ++++++++++++++++++----------------- StringUtils.h | 13 ++++++++++++- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/Log.h b/Log.h index 26414c8..56a7c4c 100644 --- a/Log.h +++ b/Log.h @@ -19,11 +19,11 @@ #pragma once +#include #include #include #include #include -#include #include #include "StringUtils.h" @@ -36,45 +36,46 @@ private: static bool m_addedTargets; static std::recursive_mutex m_targetsMutex; - static void getTimeStamp(std::string & s); + static void getTimeStamp(std::string& s); - template static void formatLogMessage(std::string& output, LOG_SEVERITY severity, const std::string & f, Args... args) + template + static void formatLogMessage(std::string& output, LOG_SEVERITY severity, const std::string & f, Args... args) { assert(severity != LOG_NONE); - std::string severityStr; + std::string severityStr(" "); switch (severity) { case LOG_DEBUG: - severityStr = "DEBUG "; + severityStr.assign("DEBUG "); break; case LOG_ERROR: - severityStr = "ERROR "; + severityStr.assign("ERROR "); break; case LOG_FATAL: - severityStr = "FATAL "; + severityStr.assign("FATAL "); break; case LOG_INFO : - severityStr = "INFO "; + severityStr.assign("INFO "); break; case LOG_WARNING: - severityStr = "WARNING"; + severityStr.assign("WARNING"); break; case LOG_TRACE: - severityStr = "TRACE "; + severityStr.assign("TRACE "); break; default: break; } - std::string message = CStringUtils::string_format(f, args...); - boost::trim(message); - std::string timeUtc; - getTimeStamp(timeUtc); - std::stringstream s; - s << "[" << timeUtc << "] [" << severityStr << "] " << message << std::endl; + std::string timestamp; + getTimeStamp(timestamp); - output = s.str(); + std::string f2("[%s] [%s] "); + f2.append(f); + CStringUtils::string_format_in_place(output, f2, timestamp.c_str(), severityStr.c_str(), args...); + boost::trim_if(output, [](char c){ return c == '\n' || c == '\r' || c == ' ' || c == '\t'; }); + output.push_back('\n'); } public: diff --git a/StringUtils.h b/StringUtils.h index 2dadc82..3f8faef 100644 --- a/StringUtils.h +++ b/StringUtils.h @@ -30,12 +30,23 @@ class CStringUtils { public: template static std::string string_format( const std::string& format, Args ... args ) + { + std::string ret; + string_format_in_place(ret, format, args...); + return ret; + } + + template + static void string_format_in_place(std::string& output, const std::string& format, Args ... args ) { int size_s = std::snprintf( nullptr, 0, format.c_str(), args ... ) + 1; // Extra space for '\0' if( size_s <= 0 ){ throw std::runtime_error( "Error during formatting." ); } + auto size = static_cast( size_s ); auto buf = std::make_unique( size ); std::snprintf( buf.get(), size, format.c_str(), args ... ); - return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside + + output.reserve(size); + output.assign(buf.get(), size - 1); // -1 because we do not need trailing '\0' } };