From 68a161874343012ea789d73966a743689bc09f1c Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 22 Jan 2024 12:05:59 +0100 Subject: [PATCH 01/20] changed things to include plog --- dot vscode/c_cpp_properties.json | 12 +- dot vscode/launch.json | 4 +- dot vscode/tasks.json | 10 +- include/plog/Appenders/AndroidAppender.h | 47 ++ include/plog/Appenders/ArduinoAppender.h | 23 + include/plog/Appenders/ColorConsoleAppender.h | 108 +++ include/plog/Appenders/ConsoleAppender.h | 83 +++ include/plog/Appenders/DebugOutputAppender.h | 16 + include/plog/Appenders/DynamicAppender.h | 42 ++ include/plog/Appenders/EventLogAppender.h | 117 ++++ include/plog/Appenders/IAppender.h | 16 + include/plog/Appenders/RollingFileAppender.h | 148 +++++ include/plog/Converters/NativeEOLConverter.h | 44 ++ include/plog/Converters/UTF8Converter.h | 28 + include/plog/Formatters/CsvFormatter.h | 57 ++ .../plog/Formatters/FuncMessageFormatter.h | 23 + .../plog/Formatters/MessageOnlyFormatter.h | 23 + include/plog/Formatters/TxtFormatter.h | 36 + include/plog/Helpers/AscDump.h | 40 ++ include/plog/Helpers/HexDump.h | 79 +++ include/plog/Helpers/PrintVar.h | 24 + include/plog/Init.h | 17 + .../plog/Initializers/ConsoleInitializer.h | 22 + .../Initializers/RollingFileInitializer.h | 80 +++ include/plog/Log.h | 202 ++++++ include/plog/Logger.h | 84 +++ include/plog/Record.h | 465 +++++++++++++ include/plog/Severity.h | 61 ++ include/plog/Util.h | 616 ++++++++++++++++++ include/plog/WinApi.h | 175 +++++ main.cpp | 12 - io.cpp => src/io.cpp | 0 io.h => src/io.h | 0 src/main.cpp | 15 + 34 files changed, 2702 insertions(+), 27 deletions(-) create mode 100644 include/plog/Appenders/AndroidAppender.h create mode 100644 include/plog/Appenders/ArduinoAppender.h create mode 100644 include/plog/Appenders/ColorConsoleAppender.h create mode 100644 include/plog/Appenders/ConsoleAppender.h create mode 100644 include/plog/Appenders/DebugOutputAppender.h create mode 100644 include/plog/Appenders/DynamicAppender.h create mode 100644 include/plog/Appenders/EventLogAppender.h create mode 100644 include/plog/Appenders/IAppender.h create mode 100644 include/plog/Appenders/RollingFileAppender.h create mode 100644 include/plog/Converters/NativeEOLConverter.h create mode 100644 include/plog/Converters/UTF8Converter.h create mode 100644 include/plog/Formatters/CsvFormatter.h create mode 100644 include/plog/Formatters/FuncMessageFormatter.h create mode 100644 include/plog/Formatters/MessageOnlyFormatter.h create mode 100644 include/plog/Formatters/TxtFormatter.h create mode 100644 include/plog/Helpers/AscDump.h create mode 100644 include/plog/Helpers/HexDump.h create mode 100644 include/plog/Helpers/PrintVar.h create mode 100644 include/plog/Init.h create mode 100644 include/plog/Initializers/ConsoleInitializer.h create mode 100644 include/plog/Initializers/RollingFileInitializer.h create mode 100644 include/plog/Log.h create mode 100644 include/plog/Logger.h create mode 100644 include/plog/Record.h create mode 100644 include/plog/Severity.h create mode 100644 include/plog/Util.h create mode 100644 include/plog/WinApi.h delete mode 100644 main.cpp rename io.cpp => src/io.cpp (100%) rename io.h => src/io.h (100%) create mode 100644 src/main.cpp diff --git a/dot vscode/c_cpp_properties.json b/dot vscode/c_cpp_properties.json index a09e6ca..305b650 100644 --- a/dot vscode/c_cpp_properties.json +++ b/dot vscode/c_cpp_properties.json @@ -2,14 +2,8 @@ "configurations": [ { "name": "Win32", - "includePath": [ - "${workspaceFolder}/**" - ], - "defines": [ - "_DEBUG", - "UNICODE", - "_UNICODE" - ], + "includePath": ["${workspaceFolder}/**"], + "defines": ["_DEBUG", "UNICODE", "_UNICODE"], "compilerPath": "C:\\msys64\\mingw64\\bin\\gcc.exe", "cStandard": "c17", "cppStandard": "gnu++20", @@ -17,4 +11,4 @@ } ], "version": 4 -} \ No newline at end of file +} diff --git a/dot vscode/launch.json b/dot vscode/launch.json index 081340e..58291ac 100644 --- a/dot vscode/launch.json +++ b/dot vscode/launch.json @@ -4,7 +4,7 @@ "name": "Debug: C/C++", "type": "cppdbg", "request": "launch", - "program": "${fileDirname}\\build\\${fileBasenameNoExtension}.exe", + "program": "${workspaceFolder}\\build\\${fileBasenameNoExtension}.exe", "args": [], "stopAtEntry": false, "cwd": "${fileDirname}", @@ -30,7 +30,7 @@ "name": "Release: C/C++", "type": "cppdbg", "request": "launch", - "program": "${fileDirname}\\build\\${fileBasenameNoExtension}.exe", + "program": "${workspaceFolder}\\build\\${fileBasenameNoExtension}.exe", "args": [], "stopAtEntry": false, "cwd": "${fileDirname}", diff --git a/dot vscode/tasks.json b/dot vscode/tasks.json index 6037983..8299a09 100644 --- a/dot vscode/tasks.json +++ b/dot vscode/tasks.json @@ -6,12 +6,13 @@ "command": "C:\\msys64\\mingw64\\bin\\g++.exe", "args": [ "-fdiagnostics-color=always", + "-I${workspaceFolder}\\include", "-ggdb", "-std=c++20", "-pedantic-errors", - "${fileDirname}/**.cpp", + "${workspaceFolder}/src/**.cpp", "-o", - "${fileDirname}\\build\\${fileBasenameNoExtension}.exe" + "${workspaceFolder}\\build\\${fileBasenameNoExtension}.exe" ], "options": { "cwd": "${fileDirname}" @@ -26,13 +27,14 @@ "command": "C:\\msys64\\mingw64\\bin\\g++.exe", "args": [ "-fdiagnostics-color=always", + "-I${workspaceFolder}\\include", "-O2", "-DNDEBUG", "-std=c++20", "-pedantic-errors", - "${fileDirname}/**.cpp", + "${workspaceFolder}/src/**.cpp", "-o", - "${fileDirname}\\build\\${fileBasenameNoExtension}.exe" + "${workspaceFolder}\\build\\${fileBasenameNoExtension}.exe" ], "options": { "cwd": "${fileDirname}" diff --git a/include/plog/Appenders/AndroidAppender.h b/include/plog/Appenders/AndroidAppender.h new file mode 100644 index 0000000..722488a --- /dev/null +++ b/include/plog/Appenders/AndroidAppender.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include + +namespace plog +{ + template + class PLOG_LINKAGE_HIDDEN AndroidAppender : public IAppender + { + public: + AndroidAppender(const char* tag) : m_tag(tag) + { + } + + virtual void write(const Record& record) PLOG_OVERRIDE + { + std::string str = Formatter::format(record); + + __android_log_print(toPriority(record.getSeverity()), m_tag, "%s", str.c_str()); + } + + private: + static android_LogPriority toPriority(Severity severity) + { + switch (severity) + { + case fatal: + return ANDROID_LOG_FATAL; + case error: + return ANDROID_LOG_ERROR; + case warning: + return ANDROID_LOG_WARN; + case info: + return ANDROID_LOG_INFO; + case debug: + return ANDROID_LOG_DEBUG; + case verbose: + return ANDROID_LOG_VERBOSE; + default: + return ANDROID_LOG_UNKNOWN; + } + } + + private: + const char* const m_tag; + }; +} diff --git a/include/plog/Appenders/ArduinoAppender.h b/include/plog/Appenders/ArduinoAppender.h new file mode 100644 index 0000000..276af32 --- /dev/null +++ b/include/plog/Appenders/ArduinoAppender.h @@ -0,0 +1,23 @@ +#pragma once +#include +#include + +namespace plog +{ + template + class PLOG_LINKAGE_HIDDEN ArduinoAppender : public IAppender + { + public: + ArduinoAppender(Stream &stream) : m_stream(stream) + { + } + + virtual void write(const Record &record) PLOG_OVERRIDE + { + m_stream.print(Formatter::format(record).c_str()); + } + + private: + Stream &m_stream; + }; +} diff --git a/include/plog/Appenders/ColorConsoleAppender.h b/include/plog/Appenders/ColorConsoleAppender.h new file mode 100644 index 0000000..24bbc7d --- /dev/null +++ b/include/plog/Appenders/ColorConsoleAppender.h @@ -0,0 +1,108 @@ +#pragma once +#include +#include + +namespace plog +{ + template + class PLOG_LINKAGE_HIDDEN ColorConsoleAppender : public ConsoleAppender + { + public: +#ifdef _WIN32 +# ifdef _MSC_VER +# pragma warning(suppress: 26812) // Prefer 'enum class' over 'enum' +# endif + ColorConsoleAppender(OutputStream outStream = streamStdOut) + : ConsoleAppender(outStream) + , m_originalAttr() + { + if (this->m_isatty) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo(this->m_outputHandle, &csbiInfo); + + m_originalAttr = csbiInfo.wAttributes; + } + } +#else + ColorConsoleAppender(OutputStream outStream = streamStdOut) + : ConsoleAppender(outStream) + {} +#endif + + virtual void write(const Record& record) PLOG_OVERRIDE + { + util::nstring str = Formatter::format(record); + util::MutexLock lock(this->m_mutex); + + setColor(record.getSeverity()); + this->writestr(str); + resetColor(); + } + + protected: + void setColor(Severity severity) + { + if (this->m_isatty) + { + switch (severity) + { +#ifdef _WIN32 + case fatal: + SetConsoleTextAttribute(this->m_outputHandle, foreground::kRed | foreground::kGreen | foreground::kBlue | foreground::kIntensity | background::kRed); // white on red background + break; + + case error: + SetConsoleTextAttribute(this->m_outputHandle, static_cast(foreground::kRed | foreground::kIntensity | (m_originalAttr & 0xf0))); // red + break; + + case warning: + SetConsoleTextAttribute(this->m_outputHandle, static_cast(foreground::kRed | foreground::kGreen | foreground::kIntensity | (m_originalAttr & 0xf0))); // yellow + break; + + case debug: + case verbose: + SetConsoleTextAttribute(this->m_outputHandle, static_cast(foreground::kGreen | foreground::kBlue | foreground::kIntensity | (m_originalAttr & 0xf0))); // cyan + break; +#else + case fatal: + this->m_outputStream << "\x1B[97m\x1B[41m"; // white on red background + break; + + case error: + this->m_outputStream << "\x1B[91m"; // red + break; + + case warning: + this->m_outputStream << "\x1B[93m"; // yellow + break; + + case debug: + case verbose: + this->m_outputStream << "\x1B[96m"; // cyan + break; +#endif + default: + break; + } + } + } + + void resetColor() + { + if (this->m_isatty) + { +#ifdef _WIN32 + SetConsoleTextAttribute(this->m_outputHandle, m_originalAttr); +#else + this->m_outputStream << "\x1B[0m\x1B[0K"; +#endif + } + } + + private: +#ifdef _WIN32 + WORD m_originalAttr; +#endif + }; +} diff --git a/include/plog/Appenders/ConsoleAppender.h b/include/plog/Appenders/ConsoleAppender.h new file mode 100644 index 0000000..a8925a0 --- /dev/null +++ b/include/plog/Appenders/ConsoleAppender.h @@ -0,0 +1,83 @@ +#pragma once +#include +#include +#include +#include + +namespace plog +{ + enum OutputStream + { + streamStdOut, + streamStdErr + }; + + template + class PLOG_LINKAGE_HIDDEN ConsoleAppender : public IAppender + { + public: +#ifdef _WIN32 +# ifdef _MSC_VER +# pragma warning(suppress: 26812) // Prefer 'enum class' over 'enum' +# endif + ConsoleAppender(OutputStream outStream = streamStdOut) + : m_isatty(!!_isatty(_fileno(outStream == streamStdOut ? stdout : stderr))) + , m_outputStream(outStream == streamStdOut ? std::cout : std::cerr) + , m_outputHandle() + { + if (m_isatty) + { + m_outputHandle = GetStdHandle(outStream == streamStdOut ? stdHandle::kOutput : stdHandle::kErrorOutput); + } + } +#else + ConsoleAppender(OutputStream outStream = streamStdOut) + : m_isatty(!!isatty(fileno(outStream == streamStdOut ? stdout : stderr))) + , m_outputStream(outStream == streamStdOut ? std::cout : std::cerr) + {} +#endif + + virtual void write(const Record& record) PLOG_OVERRIDE + { + util::nstring str = Formatter::format(record); + util::MutexLock lock(m_mutex); + + writestr(str); + } + + protected: + void writestr(const util::nstring& str) + { +#ifdef _WIN32 + if (m_isatty) + { + const std::wstring& wstr = util::toWide(str); + WriteConsoleW(m_outputHandle, wstr.c_str(), static_cast(wstr.size()), NULL, NULL); + } + else + { +# if PLOG_CHAR_IS_UTF8 + m_outputStream << str << std::flush; +# else + m_outputStream << util::toNarrow(str, codePage::kActive) << std::flush; +# endif + } +#else + m_outputStream << str << std::flush; +#endif + } + + private: +#ifdef __BORLANDC__ + static int _isatty(int fd) { return ::isatty(fd); } +#endif + + protected: + util::Mutex m_mutex; + const bool m_isatty; + std::ostream& m_outputStream; +#ifdef _WIN32 + HANDLE m_outputHandle; +#endif + }; +} diff --git a/include/plog/Appenders/DebugOutputAppender.h b/include/plog/Appenders/DebugOutputAppender.h new file mode 100644 index 0000000..5d7c95e --- /dev/null +++ b/include/plog/Appenders/DebugOutputAppender.h @@ -0,0 +1,16 @@ +#pragma once +#include +#include + +namespace plog +{ + template + class PLOG_LINKAGE_HIDDEN DebugOutputAppender : public IAppender + { + public: + virtual void write(const Record& record) PLOG_OVERRIDE + { + OutputDebugStringW(util::toWide(Formatter::format(record)).c_str()); + } + }; +} diff --git a/include/plog/Appenders/DynamicAppender.h b/include/plog/Appenders/DynamicAppender.h new file mode 100644 index 0000000..f078c08 --- /dev/null +++ b/include/plog/Appenders/DynamicAppender.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include + +namespace plog +{ + class PLOG_LINKAGE_HIDDEN DynamicAppender : public IAppender + { + public: + DynamicAppender& addAppender(IAppender* appender) + { + assert(appender != this); + + util::MutexLock lock(m_mutex); + m_appenders.insert(appender); + + return *this; + } + + DynamicAppender& removeAppender(IAppender* appender) + { + util::MutexLock lock(m_mutex); + m_appenders.erase(appender); + + return *this; + } + + virtual void write(const Record& record) PLOG_OVERRIDE + { + util::MutexLock lock(m_mutex); + + for (std::set::iterator it = m_appenders.begin(); it != m_appenders.end(); ++it) + { + (*it)->write(record); + } + } + + private: + mutable util::Mutex m_mutex; + std::set m_appenders; + }; +} diff --git a/include/plog/Appenders/EventLogAppender.h b/include/plog/Appenders/EventLogAppender.h new file mode 100644 index 0000000..3b7065b --- /dev/null +++ b/include/plog/Appenders/EventLogAppender.h @@ -0,0 +1,117 @@ +#pragma once +#include +#include + +namespace plog +{ + template + class PLOG_LINKAGE_HIDDEN EventLogAppender : public IAppender + { + public: + EventLogAppender(const util::nchar* sourceName) : m_eventSource(RegisterEventSourceW(NULL, util::toWide(sourceName).c_str())) + { + } + + ~EventLogAppender() + { + DeregisterEventSource(m_eventSource); + } + + virtual void write(const Record& record) PLOG_OVERRIDE + { + util::nstring str = Formatter::format(record); + + write(record.getSeverity(), util::toWide(str).c_str()); + } + + private: + void write(Severity severity, const wchar_t* str) + { + const wchar_t* logMessagePtr[] = { str }; + + ReportEventW(m_eventSource, logSeverityToType(severity), static_cast(severity), 0, NULL, 1, 0, logMessagePtr, NULL); + } + + static WORD logSeverityToType(plog::Severity severity) + { + switch (severity) + { + case plog::fatal: + case plog::error: + return eventLog::kErrorType; + + case plog::warning: + return eventLog::kWarningType; + + case plog::info: + case plog::debug: + case plog::verbose: + default: + return eventLog::kInformationType; + } + } + + private: + HANDLE m_eventSource; + }; + + class EventLogAppenderRegistry + { + public: + static bool add(const util::nchar* sourceName, const util::nchar* logName = PLOG_NSTR("Application")) + { + std::wstring logKeyName; + std::wstring sourceKeyName; + getKeyNames(sourceName, logName, sourceKeyName, logKeyName); + + HKEY sourceKey; + if (0 != RegCreateKeyExW(hkey::kLocalMachine, sourceKeyName.c_str(), 0, NULL, 0, regSam::kSetValue, NULL, &sourceKey, NULL)) + { + return false; + } + + const DWORD kTypesSupported = eventLog::kErrorType | eventLog::kWarningType | eventLog::kInformationType; + RegSetValueExW(sourceKey, L"TypesSupported", 0, regType::kDword, reinterpret_cast(&kTypesSupported), sizeof(kTypesSupported)); + + const wchar_t kEventMessageFile[] = L"%windir%\\Microsoft.NET\\Framework\\v4.0.30319\\EventLogMessages.dll;%windir%\\Microsoft.NET\\Framework\\v2.0.50727\\EventLogMessages.dll"; + RegSetValueExW(sourceKey, L"EventMessageFile", 0, regType::kExpandSz, reinterpret_cast(kEventMessageFile), sizeof(kEventMessageFile) - sizeof(*kEventMessageFile)); + + RegCloseKey(sourceKey); + return true; + } + + static bool exists(const util::nchar* sourceName, const util::nchar* logName = PLOG_NSTR("Application")) + { + std::wstring logKeyName; + std::wstring sourceKeyName; + getKeyNames(sourceName, logName, sourceKeyName, logKeyName); + + HKEY sourceKey; + if (0 != RegOpenKeyExW(hkey::kLocalMachine, sourceKeyName.c_str(), 0, regSam::kQueryValue, &sourceKey)) + { + return false; + } + + RegCloseKey(sourceKey); + return true; + } + + static void remove(const util::nchar* sourceName, const util::nchar* logName = PLOG_NSTR("Application")) + { + std::wstring logKeyName; + std::wstring sourceKeyName; + getKeyNames(sourceName, logName, sourceKeyName, logKeyName); + + RegDeleteKeyW(hkey::kLocalMachine, sourceKeyName.c_str()); + RegDeleteKeyW(hkey::kLocalMachine, logKeyName.c_str()); + } + + private: + static void getKeyNames(const util::nchar* sourceName, const util::nchar* logName, std::wstring& sourceKeyName, std::wstring& logKeyName) + { + const std::wstring kPrefix = L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\"; + logKeyName = kPrefix + util::toWide(logName); + sourceKeyName = logKeyName + L"\\" + util::toWide(sourceName); + } + }; +} diff --git a/include/plog/Appenders/IAppender.h b/include/plog/Appenders/IAppender.h new file mode 100644 index 0000000..56b7827 --- /dev/null +++ b/include/plog/Appenders/IAppender.h @@ -0,0 +1,16 @@ +#pragma once +#include +#include + +namespace plog +{ + class PLOG_LINKAGE IAppender + { + public: + virtual ~IAppender() + { + } + + virtual void write(const Record& record) = 0; + }; +} diff --git a/include/plog/Appenders/RollingFileAppender.h b/include/plog/Appenders/RollingFileAppender.h new file mode 100644 index 0000000..3b66728 --- /dev/null +++ b/include/plog/Appenders/RollingFileAppender.h @@ -0,0 +1,148 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace plog +{ + template > + class PLOG_LINKAGE_HIDDEN RollingFileAppender : public IAppender + { + public: + RollingFileAppender(const util::nchar* fileName, size_t maxFileSize = 0, int maxFiles = 0) + : m_fileSize() + , m_maxFileSize() + , m_maxFiles(maxFiles) + , m_firstWrite(true) + { + setFileName(fileName); + setMaxFileSize(maxFileSize); + } + +#if defined(_WIN32) && !PLOG_CHAR_IS_UTF8 + RollingFileAppender(const char* fileName, size_t maxFileSize = 0, int maxFiles = 0) + : m_fileSize() + , m_maxFileSize() + , m_maxFiles(maxFiles) + , m_firstWrite(true) + { + setFileName(fileName); + setMaxFileSize(maxFileSize); + } +#endif + + virtual void write(const Record& record) PLOG_OVERRIDE + { + util::MutexLock lock(m_mutex); + + if (m_firstWrite) + { + openLogFile(); + m_firstWrite = false; + } + else if (m_maxFiles > 0 && m_fileSize > m_maxFileSize && static_cast(-1) != m_fileSize) + { + rollLogFiles(); + } + + size_t bytesWritten = m_file.write(Converter::convert(Formatter::format(record))); + + if (static_cast(-1) != bytesWritten) + { + m_fileSize += bytesWritten; + } + } + + void setFileName(const util::nchar* fileName) + { + util::MutexLock lock(m_mutex); + + util::splitFileName(fileName, m_fileNameNoExt, m_fileExt); + + m_file.close(); + m_firstWrite = true; + } + +#if defined(_WIN32) && !PLOG_CHAR_IS_UTF8 + void setFileName(const char* fileName) + { + setFileName(util::toWide(fileName).c_str()); + } +#endif + + void setMaxFiles(int maxFiles) + { + m_maxFiles = maxFiles; + } + + void setMaxFileSize(size_t maxFileSize) + { + m_maxFileSize = (std::max)(maxFileSize, static_cast(1000)); // set a lower limit for the maxFileSize + } + + void rollLogFiles() + { + m_file.close(); + + util::nstring lastFileName = buildFileName(m_maxFiles - 1); + util::File::unlink(lastFileName); + + for (int fileNumber = m_maxFiles - 2; fileNumber >= 0; --fileNumber) + { + util::nstring currentFileName = buildFileName(fileNumber); + util::nstring nextFileName = buildFileName(fileNumber + 1); + + util::File::rename(currentFileName, nextFileName); + } + + openLogFile(); + m_firstWrite = false; + } + + private: + void openLogFile() + { + m_fileSize = m_file.open(buildFileName()); + + if (0 == m_fileSize) + { + size_t bytesWritten = m_file.write(Converter::header(Formatter::header())); + + if (static_cast(-1) != bytesWritten) + { + m_fileSize += bytesWritten; + } + } + } + + util::nstring buildFileName(int fileNumber = 0) + { + util::nostringstream ss; + ss << m_fileNameNoExt; + + if (fileNumber > 0) + { + ss << '.' << fileNumber; + } + + if (!m_fileExt.empty()) + { + ss << '.' << m_fileExt; + } + + return ss.str(); + } + + private: + util::Mutex m_mutex; + util::File m_file; + size_t m_fileSize; + size_t m_maxFileSize; + int m_maxFiles; + util::nstring m_fileExt; + util::nstring m_fileNameNoExt; + bool m_firstWrite; + }; +} diff --git a/include/plog/Converters/NativeEOLConverter.h b/include/plog/Converters/NativeEOLConverter.h new file mode 100644 index 0000000..a395e4e --- /dev/null +++ b/include/plog/Converters/NativeEOLConverter.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include + +namespace plog +{ + template + class NativeEOLConverter : public NextConverter + { +#ifdef _WIN32 + public: + static std::string header(const util::nstring& str) + { + return NextConverter::header(fixLineEndings(str)); + } + + static std::string convert(const util::nstring& str) + { + return NextConverter::convert(fixLineEndings(str)); + } + + private: + static util::nstring fixLineEndings(const util::nstring& str) + { + util::nstring output; + output.reserve(str.length() * 2); // the worst case requires 2x chars + + for (size_t i = 0; i < str.size(); ++i) + { + util::nchar ch = str[i]; + + if (ch == PLOG_NSTR('\n')) + { + output.push_back(PLOG_NSTR('\r')); + } + + output.push_back(ch); + } + + return output; + } +#endif + }; +} diff --git a/include/plog/Converters/UTF8Converter.h b/include/plog/Converters/UTF8Converter.h new file mode 100644 index 0000000..9de5a63 --- /dev/null +++ b/include/plog/Converters/UTF8Converter.h @@ -0,0 +1,28 @@ +#pragma once +#include + +namespace plog +{ + class UTF8Converter + { + public: + static std::string header(const util::nstring& str) + { + const char kBOM[] = "\xEF\xBB\xBF"; + + return std::string(kBOM) + convert(str); + } + +#if PLOG_CHAR_IS_UTF8 + static const std::string& convert(const util::nstring& str) + { + return str; + } +#else + static std::string convert(const util::nstring& str) + { + return util::toNarrow(str, codePage::kUTF8); + } +#endif + }; +} diff --git a/include/plog/Formatters/CsvFormatter.h b/include/plog/Formatters/CsvFormatter.h new file mode 100644 index 0000000..282c57f --- /dev/null +++ b/include/plog/Formatters/CsvFormatter.h @@ -0,0 +1,57 @@ +#pragma once +#include +#include +#include + +namespace plog +{ + template + class CsvFormatterImpl + { + public: + static util::nstring header() + { + return PLOG_NSTR("Date;Time;Severity;TID;This;Function;Message\n"); + } + + static util::nstring format(const Record& record) + { + tm t; + useUtcTime ? util::gmtime_s(&t, &record.getTime().time) : util::localtime_s(&t, &record.getTime().time); + + util::nostringstream ss; + ss << t.tm_year + 1900 << PLOG_NSTR("/") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_mon + 1 << PLOG_NSTR("/") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_mday << PLOG_NSTR(";"); + ss << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_hour << PLOG_NSTR(":") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_min << PLOG_NSTR(":") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_sec << PLOG_NSTR(".") << std::setfill(PLOG_NSTR('0')) << std::setw(3) << static_cast (record.getTime().millitm) << PLOG_NSTR(";"); + ss << severityToString(record.getSeverity()) << PLOG_NSTR(";"); + ss << record.getTid() << PLOG_NSTR(";"); + ss << record.getObject() << PLOG_NSTR(";"); + ss << record.getFunc() << PLOG_NSTR("@") << record.getLine() << PLOG_NSTR(";"); + + util::nstring message = record.getMessage(); + + if (message.size() > kMaxMessageSize) + { + message.resize(kMaxMessageSize); + message.append(PLOG_NSTR("...")); + } + + util::nistringstream split(message); + util::nstring token; + + while (!split.eof()) + { + std::getline(split, token, PLOG_NSTR('"')); + ss << PLOG_NSTR("\"") << token << PLOG_NSTR("\""); + } + + ss << PLOG_NSTR("\n"); + + return ss.str(); + } + + static const size_t kMaxMessageSize = 32000; + }; + + class CsvFormatter : public CsvFormatterImpl {}; + class CsvFormatterUtcTime : public CsvFormatterImpl {}; +} diff --git a/include/plog/Formatters/FuncMessageFormatter.h b/include/plog/Formatters/FuncMessageFormatter.h new file mode 100644 index 0000000..aa57806 --- /dev/null +++ b/include/plog/Formatters/FuncMessageFormatter.h @@ -0,0 +1,23 @@ +#pragma once +#include +#include + +namespace plog +{ + class FuncMessageFormatter + { + public: + static util::nstring header() + { + return util::nstring(); + } + + static util::nstring format(const Record& record) + { + util::nostringstream ss; + ss << record.getFunc() << PLOG_NSTR("@") << record.getLine() << PLOG_NSTR(": ") << record.getMessage() << PLOG_NSTR("\n"); + + return ss.str(); + } + }; +} diff --git a/include/plog/Formatters/MessageOnlyFormatter.h b/include/plog/Formatters/MessageOnlyFormatter.h new file mode 100644 index 0000000..b2db5a5 --- /dev/null +++ b/include/plog/Formatters/MessageOnlyFormatter.h @@ -0,0 +1,23 @@ +#pragma once +#include +#include + +namespace plog +{ + class MessageOnlyFormatter + { + public: + static util::nstring header() + { + return util::nstring(); + } + + static util::nstring format(const Record& record) + { + util::nostringstream ss; + ss << record.getMessage() << PLOG_NSTR("\n"); + + return ss.str(); + } + }; +} diff --git a/include/plog/Formatters/TxtFormatter.h b/include/plog/Formatters/TxtFormatter.h new file mode 100644 index 0000000..48e2d50 --- /dev/null +++ b/include/plog/Formatters/TxtFormatter.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include + +namespace plog +{ + template + class TxtFormatterImpl + { + public: + static util::nstring header() + { + return util::nstring(); + } + + static util::nstring format(const Record& record) + { + tm t; + useUtcTime ? util::gmtime_s(&t, &record.getTime().time) : util::localtime_s(&t, &record.getTime().time); + + util::nostringstream ss; + ss << t.tm_year + 1900 << "-" << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_mon + 1 << PLOG_NSTR("-") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_mday << PLOG_NSTR(" "); + ss << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_hour << PLOG_NSTR(":") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_min << PLOG_NSTR(":") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_sec << PLOG_NSTR(".") << std::setfill(PLOG_NSTR('0')) << std::setw(3) << static_cast (record.getTime().millitm) << PLOG_NSTR(" "); + ss << std::setfill(PLOG_NSTR(' ')) << std::setw(5) << std::left << severityToString(record.getSeverity()) << PLOG_NSTR(" "); + ss << PLOG_NSTR("[") << record.getTid() << PLOG_NSTR("] "); + ss << PLOG_NSTR("[") << record.getFunc() << PLOG_NSTR("@") << record.getLine() << PLOG_NSTR("] "); + ss << record.getMessage() << PLOG_NSTR("\n"); + + return ss.str(); + } + }; + + class TxtFormatter : public TxtFormatterImpl {}; + class TxtFormatterUtcTime : public TxtFormatterImpl {}; +} diff --git a/include/plog/Helpers/AscDump.h b/include/plog/Helpers/AscDump.h new file mode 100644 index 0000000..18b9a6f --- /dev/null +++ b/include/plog/Helpers/AscDump.h @@ -0,0 +1,40 @@ +#pragma once +#include +#include + +namespace plog +{ + class AscDump + { + public: + AscDump(const void* ptr, size_t size) + : m_ptr(static_cast(ptr)) + , m_size(size) + { + } + + friend util::nostringstream& operator<<(util::nostringstream& stream, const AscDump& ascDump); + + private: + const char* m_ptr; + size_t m_size; + }; + + inline util::nostringstream& operator<<(util::nostringstream& stream, const AscDump& ascDump) + { + for (size_t i = 0; i < ascDump.m_size; ++i) + { + stream << (std::isprint(ascDump.m_ptr[i]) ? ascDump.m_ptr[i] : '.'); + } + + return stream; + } + + inline AscDump ascdump(const void* ptr, size_t size) { return AscDump(ptr, size); } + + template + inline AscDump ascdump(const Container& container) { return AscDump(container.data(), container.size() * sizeof(*container.data())); } + + template + inline AscDump ascdump(const T (&arr)[N]) { return AscDump(arr, N * sizeof(*arr)); } +} diff --git a/include/plog/Helpers/HexDump.h b/include/plog/Helpers/HexDump.h new file mode 100644 index 0000000..b0493d7 --- /dev/null +++ b/include/plog/Helpers/HexDump.h @@ -0,0 +1,79 @@ +#pragma once +#include +#include + +namespace plog +{ + class HexDump + { + public: + HexDump(const void* ptr, size_t size) + : m_ptr(static_cast(ptr)) + , m_size(size) + , m_group(8) + , m_digitSeparator(" ") + , m_groupSeparator(" ") + { + } + + HexDump& group(size_t group) + { + m_group = group; + return *this; + } + + HexDump& separator(const char* digitSeparator) + { + m_digitSeparator = digitSeparator; + return *this; + } + + HexDump& separator(const char* digitSeparator, const char* groupSeparator) + { + m_digitSeparator = digitSeparator; + m_groupSeparator = groupSeparator; + return *this; + } + + friend util::nostringstream& operator<<(util::nostringstream& stream, const HexDump&); + + private: + const unsigned char* m_ptr; + size_t m_size; + size_t m_group; + const char* m_digitSeparator; + const char* m_groupSeparator; + }; + + inline util::nostringstream& operator<<(util::nostringstream& stream, const HexDump& hexDump) + { + stream << std::hex << std::setfill(PLOG_NSTR('0')); + + for (size_t i = 0; i < hexDump.m_size;) + { + stream << std::setw(2) << static_cast(hexDump.m_ptr[i]); + + if (++i < hexDump.m_size) + { + if (hexDump.m_group > 0 && i % hexDump.m_group == 0) + { + stream << hexDump.m_groupSeparator; + } + else + { + stream << hexDump.m_digitSeparator; + } + } + } + + return stream; + } + + inline HexDump hexdump(const void* ptr, size_t size) { return HexDump(ptr, size); } + + template + inline HexDump hexdump(const Container& container) { return HexDump(container.data(), container.size() * sizeof(*container.data())); } + + template + inline HexDump hexdump(const T (&arr)[N]) { return HexDump(arr, N * sizeof(*arr)); } +} diff --git a/include/plog/Helpers/PrintVar.h b/include/plog/Helpers/PrintVar.h new file mode 100644 index 0000000..465e193 --- /dev/null +++ b/include/plog/Helpers/PrintVar.h @@ -0,0 +1,24 @@ +#pragma once + +#define PLOG_IMPL_PRINT_VAR_1(a1) #a1 ": " << a1 +#define PLOG_IMPL_PRINT_VAR_2(a1, a2) PLOG_IMPL_PRINT_VAR_1(a1) PLOG_IMPL_PRINT_VAR_TAIL(a2) +#define PLOG_IMPL_PRINT_VAR_3(a1, a2, a3) PLOG_IMPL_PRINT_VAR_2(a1, a2) PLOG_IMPL_PRINT_VAR_TAIL(a3) +#define PLOG_IMPL_PRINT_VAR_4(a1, a2, a3, a4) PLOG_IMPL_PRINT_VAR_3(a1, a2, a3) PLOG_IMPL_PRINT_VAR_TAIL(a4) +#define PLOG_IMPL_PRINT_VAR_5(a1, a2, a3, a4, a5) PLOG_IMPL_PRINT_VAR_4(a1, a2, a3, a4) PLOG_IMPL_PRINT_VAR_TAIL(a5) +#define PLOG_IMPL_PRINT_VAR_6(a1, a2, a3, a4, a5, a6) PLOG_IMPL_PRINT_VAR_5(a1, a2, a3, a4, a5) PLOG_IMPL_PRINT_VAR_TAIL(a6) +#define PLOG_IMPL_PRINT_VAR_7(a1, a2, a3, a4, a5, a6, a7) PLOG_IMPL_PRINT_VAR_6(a1, a2, a3, a4, a5, a6) PLOG_IMPL_PRINT_VAR_TAIL(a7) +#define PLOG_IMPL_PRINT_VAR_8(a1, a2, a3, a4, a5, a6, a7, a8) PLOG_IMPL_PRINT_VAR_7(a1, a2, a3, a4, a5, a6, a7) PLOG_IMPL_PRINT_VAR_TAIL(a8) +#define PLOG_IMPL_PRINT_VAR_9(a1, a2, a3, a4, a5, a6, a7, a8, a9) PLOG_IMPL_PRINT_VAR_8(a1, a2, a3, a4, a5, a6, a7, a8) PLOG_IMPL_PRINT_VAR_TAIL(a9) +#define PLOG_IMPL_PRINT_VAR_TAIL(a) << ", " PLOG_IMPL_PRINT_VAR_1(a) + +#define PLOG_IMPL_PRINT_VAR_EXPAND(x) x + +#ifdef __GNUC__ +#pragma GCC system_header // disable warning: variadic macros are a C99 feature +#endif + +#define PLOG_IMPL_PRINT_VAR_GET_MACRO(x1, x2, x3, x4, x5, x6, x7, x8, x9, NAME, ...) NAME + +#define PLOG_PRINT_VAR(...) PLOG_IMPL_PRINT_VAR_EXPAND(PLOG_IMPL_PRINT_VAR_GET_MACRO(__VA_ARGS__,\ + PLOG_IMPL_PRINT_VAR_9, PLOG_IMPL_PRINT_VAR_8, PLOG_IMPL_PRINT_VAR_7, PLOG_IMPL_PRINT_VAR_6, PLOG_IMPL_PRINT_VAR_5,\ + PLOG_IMPL_PRINT_VAR_4, PLOG_IMPL_PRINT_VAR_3, PLOG_IMPL_PRINT_VAR_2, PLOG_IMPL_PRINT_VAR_1, UNUSED)(__VA_ARGS__)) diff --git a/include/plog/Init.h b/include/plog/Init.h new file mode 100644 index 0000000..615c41d --- /dev/null +++ b/include/plog/Init.h @@ -0,0 +1,17 @@ +#pragma once +#include + +namespace plog +{ + template + PLOG_LINKAGE_HIDDEN inline Logger& init(Severity maxSeverity = none, IAppender* appender = NULL) + { + static Logger logger(maxSeverity); + return appender ? logger.addAppender(appender) : logger; + } + + inline Logger& init(Severity maxSeverity = none, IAppender* appender = NULL) + { + return init(maxSeverity, appender); + } +} diff --git a/include/plog/Initializers/ConsoleInitializer.h b/include/plog/Initializers/ConsoleInitializer.h new file mode 100644 index 0000000..5b504ab --- /dev/null +++ b/include/plog/Initializers/ConsoleInitializer.h @@ -0,0 +1,22 @@ +#pragma once +#include +#include + +namespace plog +{ + ////////////////////////////////////////////////////////////////////////// + // ColorConsoleAppender with any Formatter + + template + PLOG_LINKAGE_HIDDEN inline Logger& init(Severity maxSeverity, OutputStream outputStream) + { + static ColorConsoleAppender appender(outputStream); + return init(maxSeverity, &appender); + } + + template + inline Logger& init(Severity maxSeverity, OutputStream outputStream) + { + return init(maxSeverity, outputStream); + } +} diff --git a/include/plog/Initializers/RollingFileInitializer.h b/include/plog/Initializers/RollingFileInitializer.h new file mode 100644 index 0000000..dc0adda --- /dev/null +++ b/include/plog/Initializers/RollingFileInitializer.h @@ -0,0 +1,80 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace plog +{ + ////////////////////////////////////////////////////////////////////////// + // RollingFileAppender with any Formatter + + template + PLOG_LINKAGE_HIDDEN inline Logger& init(Severity maxSeverity, const util::nchar* fileName, size_t maxFileSize = 0, int maxFiles = 0) + { + static RollingFileAppender rollingFileAppender(fileName, maxFileSize, maxFiles); + return init(maxSeverity, &rollingFileAppender); + } + + template + inline Logger& init(Severity maxSeverity, const util::nchar* fileName, size_t maxFileSize = 0, int maxFiles = 0) + { + return init(maxSeverity, fileName, maxFileSize, maxFiles); + } + + ////////////////////////////////////////////////////////////////////////// + // RollingFileAppender with TXT/CSV chosen by file extension + + namespace + { + inline bool isCsv(const util::nchar* fileName) + { + const util::nchar* dot = util::findExtensionDot(fileName); +#if PLOG_CHAR_IS_UTF8 + return dot && 0 == std::strcmp(dot, ".csv"); +#else + return dot && 0 == std::wcscmp(dot, L".csv"); +#endif + } + } + + template + inline Logger& init(Severity maxSeverity, const util::nchar* fileName, size_t maxFileSize = 0, int maxFiles = 0) + { + return isCsv(fileName) ? init(maxSeverity, fileName, maxFileSize, maxFiles) : init(maxSeverity, fileName, maxFileSize, maxFiles); + } + + inline Logger& init(Severity maxSeverity, const util::nchar* fileName, size_t maxFileSize = 0, int maxFiles = 0) + { + return init(maxSeverity, fileName, maxFileSize, maxFiles); + } + + ////////////////////////////////////////////////////////////////////////// + // CHAR variants for Windows + +#if defined(_WIN32) && !PLOG_CHAR_IS_UTF8 + template + inline Logger& init(Severity maxSeverity, const char* fileName, size_t maxFileSize = 0, int maxFiles = 0) + { + return init(maxSeverity, util::toWide(fileName).c_str(), maxFileSize, maxFiles); + } + + template + inline Logger& init(Severity maxSeverity, const char* fileName, size_t maxFileSize = 0, int maxFiles = 0) + { + return init(maxSeverity, fileName, maxFileSize, maxFiles); + } + + template + inline Logger& init(Severity maxSeverity, const char* fileName, size_t maxFileSize = 0, int maxFiles = 0) + { + return init(maxSeverity, util::toWide(fileName).c_str(), maxFileSize, maxFiles); + } + + inline Logger& init(Severity maxSeverity, const char* fileName, size_t maxFileSize = 0, int maxFiles = 0) + { + return init(maxSeverity, fileName, maxFileSize, maxFiles); + } +#endif +} diff --git a/include/plog/Log.h b/include/plog/Log.h new file mode 100644 index 0000000..138d92f --- /dev/null +++ b/include/plog/Log.h @@ -0,0 +1,202 @@ +////////////////////////////////////////////////////////////////////////// +// Plog - portable and simple log for C++ +// Documentation and sources: https://github.com/SergiusTheBest/plog +// License: MIT, https://choosealicense.com/licenses/mit + +#pragma once +#include + +////////////////////////////////////////////////////////////////////////// +// Helper macros that get context info + +#if defined(PLOG_ENABLE_GET_THIS) && defined(_MSC_VER) && _MSC_VER >= 1600 && !defined(__INTELLISENSE__) && !defined(__INTEL_COMPILER) && !defined(__llvm__) && !defined(__RESHARPER__) // >= Visual Studio 2010, skip IntelliSense, Intel Compiler, Clang Code Model and ReSharper +# define PLOG_GET_THIS() __if_exists(this) { this } __if_not_exists(this) { 0 } +#else +# define PLOG_GET_THIS() reinterpret_cast(0) +#endif + +#ifdef _MSC_VER +# define PLOG_GET_FUNC() __FUNCTION__ +#elif defined(__BORLANDC__) +# define PLOG_GET_FUNC() __FUNC__ +#else +# define PLOG_GET_FUNC() __PRETTY_FUNCTION__ +#endif + +#ifdef PLOG_CAPTURE_FILE +# define PLOG_GET_FILE() __FILE__ +#else +# define PLOG_GET_FILE() "" +#endif + +////////////////////////////////////////////////////////////////////////// +// Log severity level checker + +#ifdef PLOG_DISABLE_LOGGING +# ifdef _MSC_VER +# define IF_PLOG_(instanceId, severity) __pragma(warning(push)) __pragma(warning(disable:4127)) if (true) {;} else __pragma(warning(pop)) // conditional expression is constant +# else +# define IF_PLOG_(instanceId, severity) if (true) {;} else +# endif +#else +# define IF_PLOG_(instanceId, severity) if (!plog::get() || !plog::get()->checkSeverity(severity)) {;} else +#endif + +#define IF_PLOG(severity) IF_PLOG_(PLOG_DEFAULT_INSTANCE_ID, severity) + +////////////////////////////////////////////////////////////////////////// +// Main logging macros + +#define PLOG_(instanceId, severity) IF_PLOG_(instanceId, severity) (*plog::get()) += plog::Record(severity, PLOG_GET_FUNC(), __LINE__, PLOG_GET_FILE(), PLOG_GET_THIS(), instanceId).ref() +#define PLOG(severity) PLOG_(PLOG_DEFAULT_INSTANCE_ID, severity) + +#define PLOG_VERBOSE PLOG(plog::verbose) +#define PLOG_DEBUG PLOG(plog::debug) +#define PLOG_INFO PLOG(plog::info) +#define PLOG_WARNING PLOG(plog::warning) +#define PLOG_ERROR PLOG(plog::error) +#define PLOG_FATAL PLOG(plog::fatal) +#define PLOG_NONE PLOG(plog::none) + +#define PLOG_VERBOSE_(instanceId) PLOG_(instanceId, plog::verbose) +#define PLOG_DEBUG_(instanceId) PLOG_(instanceId, plog::debug) +#define PLOG_INFO_(instanceId) PLOG_(instanceId, plog::info) +#define PLOG_WARNING_(instanceId) PLOG_(instanceId, plog::warning) +#define PLOG_ERROR_(instanceId) PLOG_(instanceId, plog::error) +#define PLOG_FATAL_(instanceId) PLOG_(instanceId, plog::fatal) +#define PLOG_NONE_(instanceId) PLOG_(instanceId, plog::none) + +#define PLOGV PLOG_VERBOSE +#define PLOGD PLOG_DEBUG +#define PLOGI PLOG_INFO +#define PLOGW PLOG_WARNING +#define PLOGE PLOG_ERROR +#define PLOGF PLOG_FATAL +#define PLOGN PLOG_NONE + +#define PLOGV_(instanceId) PLOG_VERBOSE_(instanceId) +#define PLOGD_(instanceId) PLOG_DEBUG_(instanceId) +#define PLOGI_(instanceId) PLOG_INFO_(instanceId) +#define PLOGW_(instanceId) PLOG_WARNING_(instanceId) +#define PLOGE_(instanceId) PLOG_ERROR_(instanceId) +#define PLOGF_(instanceId) PLOG_FATAL_(instanceId) +#define PLOGN_(instanceId) PLOG_NONE_(instanceId) + +////////////////////////////////////////////////////////////////////////// +// Conditional logging macros + +#define PLOG_IF_(instanceId, severity, condition) if (!(condition)) {;} else PLOG_(instanceId, severity) +#define PLOG_IF(severity, condition) PLOG_IF_(PLOG_DEFAULT_INSTANCE_ID, severity, condition) + +#define PLOG_VERBOSE_IF(condition) PLOG_IF(plog::verbose, condition) +#define PLOG_DEBUG_IF(condition) PLOG_IF(plog::debug, condition) +#define PLOG_INFO_IF(condition) PLOG_IF(plog::info, condition) +#define PLOG_WARNING_IF(condition) PLOG_IF(plog::warning, condition) +#define PLOG_ERROR_IF(condition) PLOG_IF(plog::error, condition) +#define PLOG_FATAL_IF(condition) PLOG_IF(plog::fatal, condition) +#define PLOG_NONE_IF(condition) PLOG_IF(plog::none, condition) + +#define PLOG_VERBOSE_IF_(instanceId, condition) PLOG_IF_(instanceId, plog::verbose, condition) +#define PLOG_DEBUG_IF_(instanceId, condition) PLOG_IF_(instanceId, plog::debug, condition) +#define PLOG_INFO_IF_(instanceId, condition) PLOG_IF_(instanceId, plog::info, condition) +#define PLOG_WARNING_IF_(instanceId, condition) PLOG_IF_(instanceId, plog::warning, condition) +#define PLOG_ERROR_IF_(instanceId, condition) PLOG_IF_(instanceId, plog::error, condition) +#define PLOG_FATAL_IF_(instanceId, condition) PLOG_IF_(instanceId, plog::fatal, condition) +#define PLOG_NONE_IF_(instanceId, condition) PLOG_IF_(instanceId, plog::none, condition) + +#define PLOGV_IF(condition) PLOG_VERBOSE_IF(condition) +#define PLOGD_IF(condition) PLOG_DEBUG_IF(condition) +#define PLOGI_IF(condition) PLOG_INFO_IF(condition) +#define PLOGW_IF(condition) PLOG_WARNING_IF(condition) +#define PLOGE_IF(condition) PLOG_ERROR_IF(condition) +#define PLOGF_IF(condition) PLOG_FATAL_IF(condition) +#define PLOGN_IF(condition) PLOG_NONE_IF(condition) + +#define PLOGV_IF_(instanceId, condition) PLOG_VERBOSE_IF_(instanceId, condition) +#define PLOGD_IF_(instanceId, condition) PLOG_DEBUG_IF_(instanceId, condition) +#define PLOGI_IF_(instanceId, condition) PLOG_INFO_IF_(instanceId, condition) +#define PLOGW_IF_(instanceId, condition) PLOG_WARNING_IF_(instanceId, condition) +#define PLOGE_IF_(instanceId, condition) PLOG_ERROR_IF_(instanceId, condition) +#define PLOGF_IF_(instanceId, condition) PLOG_FATAL_IF_(instanceId, condition) +#define PLOGN_IF_(instanceId, condition) PLOG_NONE_IF_(instanceId, condition) + +// Old macro names for downward compatibility. To bypass including these macro names, add +// #define PLOG_OMIT_LOG_DEFINES before #include +#ifndef PLOG_OMIT_LOG_DEFINES + +////////////////////////////////////////////////////////////////////////// +// Main logging macros - can be changed later to point at macros for a different logging package + +#define LOG_(instanceId, severity) IF_PLOG_(instanceId, severity) (*plog::get()) += plog::Record(severity, PLOG_GET_FUNC(), __LINE__, PLOG_GET_FILE(), PLOG_GET_THIS(), instanceId).ref() +#define LOG(severity) PLOG_(PLOG_DEFAULT_INSTANCE_ID, severity) + +#define LOG_VERBOSE PLOG(plog::verbose) +#define LOG_DEBUG PLOG(plog::debug) +#define LOG_INFO PLOG(plog::info) +#define LOG_WARNING PLOG(plog::warning) +#define LOG_ERROR PLOG(plog::error) +#define LOG_FATAL PLOG(plog::fatal) +#define LOG_NONE PLOG(plog::none) + +#define LOG_VERBOSE_(instanceId) PLOG_(instanceId, plog::verbose) +#define LOG_DEBUG_(instanceId) PLOG_(instanceId, plog::debug) +#define LOG_INFO_(instanceId) PLOG_(instanceId, plog::info) +#define LOG_WARNING_(instanceId) PLOG_(instanceId, plog::warning) +#define LOG_ERROR_(instanceId) PLOG_(instanceId, plog::error) +#define LOG_FATAL_(instanceId) PLOG_(instanceId, plog::fatal) +#define LOG_NONE_(instanceId) PLOG_(instanceId, plog::none) + +#define LOGV PLOG_VERBOSE +#define LOGD PLOG_DEBUG +#define LOGI PLOG_INFO +#define LOGW PLOG_WARNING +#define LOGE PLOG_ERROR +#define LOGF PLOG_FATAL +#define LOGN PLOG_NONE + +#define LOGV_(instanceId) PLOG_VERBOSE_(instanceId) +#define LOGD_(instanceId) PLOG_DEBUG_(instanceId) +#define LOGI_(instanceId) PLOG_INFO_(instanceId) +#define LOGW_(instanceId) PLOG_WARNING_(instanceId) +#define LOGE_(instanceId) PLOG_ERROR_(instanceId) +#define LOGF_(instanceId) PLOG_FATAL_(instanceId) +#define LOGN_(instanceId) PLOG_NONE_(instanceId) + +////////////////////////////////////////////////////////////////////////// +// Conditional logging macros + +#define LOG_IF_(instanceId, severity, condition) if (!(condition)) {;} else PLOG_(instanceId, severity) +#define LOG_IF(severity, condition) PLOG_IF_(PLOG_DEFAULT_INSTANCE_ID, severity, condition) + +#define LOG_VERBOSE_IF(condition) PLOG_IF(plog::verbose, condition) +#define LOG_DEBUG_IF(condition) PLOG_IF(plog::debug, condition) +#define LOG_INFO_IF(condition) PLOG_IF(plog::info, condition) +#define LOG_WARNING_IF(condition) PLOG_IF(plog::warning, condition) +#define LOG_ERROR_IF(condition) PLOG_IF(plog::error, condition) +#define LOG_FATAL_IF(condition) PLOG_IF(plog::fatal, condition) +#define LOG_NONE_IF(condition) PLOG_IF(plog::none, condition) + +#define LOG_VERBOSE_IF_(instanceId, condition) PLOG_IF_(instanceId, plog::verbose, condition) +#define LOG_DEBUG_IF_(instanceId, condition) PLOG_IF_(instanceId, plog::debug, condition) +#define LOG_INFO_IF_(instanceId, condition) PLOG_IF_(instanceId, plog::info, condition) +#define LOG_WARNING_IF_(instanceId, condition) PLOG_IF_(instanceId, plog::warning, condition) +#define LOG_ERROR_IF_(instanceId, condition) PLOG_IF_(instanceId, plog::error, condition) +#define LOG_FATAL_IF_(instanceId, condition) PLOG_IF_(instanceId, plog::fatal, condition) +#define LOG_NONE_IF_(instanceId, condition) PLOG_IF_(instanceId, plog::none, condition) + +#define LOGV_IF(condition) PLOG_VERBOSE_IF(condition) +#define LOGD_IF(condition) PLOG_DEBUG_IF(condition) +#define LOGI_IF(condition) PLOG_INFO_IF(condition) +#define LOGW_IF(condition) PLOG_WARNING_IF(condition) +#define LOGE_IF(condition) PLOG_ERROR_IF(condition) +#define LOGF_IF(condition) PLOG_FATAL_IF(condition) +#define LOGN_IF(condition) PLOG_NONE_IF(condition) + +#define LOGV_IF_(instanceId, condition) PLOG_VERBOSE_IF_(instanceId, condition) +#define LOGD_IF_(instanceId, condition) PLOG_DEBUG_IF_(instanceId, condition) +#define LOGI_IF_(instanceId, condition) PLOG_INFO_IF_(instanceId, condition) +#define LOGW_IF_(instanceId, condition) PLOG_WARNING_IF_(instanceId, condition) +#define LOGE_IF_(instanceId, condition) PLOG_ERROR_IF_(instanceId, condition) +#define LOGF_IF_(instanceId, condition) PLOG_FATAL_IF_(instanceId, condition) +#define LOGN_IF_(instanceId, condition) PLOG_NONE_IF_(instanceId, condition) +#endif diff --git a/include/plog/Logger.h b/include/plog/Logger.h new file mode 100644 index 0000000..0e116e4 --- /dev/null +++ b/include/plog/Logger.h @@ -0,0 +1,84 @@ +#pragma once +#include +#include +#include + +#ifdef PLOG_DEFAULT_INSTANCE // for backward compatibility +# define PLOG_DEFAULT_INSTANCE_ID PLOG_DEFAULT_INSTANCE +#endif + +#ifndef PLOG_DEFAULT_INSTANCE_ID +# define PLOG_DEFAULT_INSTANCE_ID 0 +#endif + +namespace plog +{ + template + class PLOG_LINKAGE Logger : public util::Singleton >, public IAppender + { + public: + Logger(Severity maxSeverity = none) : m_maxSeverity(maxSeverity) + { + } + + Logger& addAppender(IAppender* appender) + { + assert(appender != this); + m_appenders.push_back(appender); + return *this; + } + + Severity getMaxSeverity() const + { + return m_maxSeverity; + } + + void setMaxSeverity(Severity severity) + { + m_maxSeverity = severity; + } + + bool checkSeverity(Severity severity) const + { + return severity <= m_maxSeverity; + } + + virtual void write(const Record& record) PLOG_OVERRIDE + { + if (checkSeverity(record.getSeverity())) + { + *this += record; + } + } + + void operator+=(const Record& record) + { + for (std::vector::iterator it = m_appenders.begin(); it != m_appenders.end(); ++it) + { + (*it)->write(record); + } + } + + private: + Severity m_maxSeverity; +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4251) // needs to have dll-interface to be used by clients of class +#endif + std::vector m_appenders; +#ifdef _MSC_VER +# pragma warning(pop) +#endif + }; + + template + inline Logger* get() + { + return Logger::getInstance(); + } + + inline Logger* get() + { + return Logger::getInstance(); + } +} diff --git a/include/plog/Record.h b/include/plog/Record.h new file mode 100644 index 0000000..e8dbdfe --- /dev/null +++ b/include/plog/Record.h @@ -0,0 +1,465 @@ +#pragma once +#include +#include +#include + +#ifdef __cplusplus_cli +#include // For PtrToStringChars +#endif + +namespace plog +{ + namespace detail + { +#if !defined(_MSC_VER) || _MSC_VER > 1400 // MSVC 2005 doesn't understand `enableIf`, so drop all `meta` + namespace meta + { + template + inline T& declval() + { +#ifdef __INTEL_COMPILER +# pragma warning(suppress: 327) // NULL reference is not allowed +#endif + return *reinterpret_cast(0); + } + + template + struct enableIf {}; + + template + struct enableIf { typedef T type; }; + + struct No { char a[1]; }; + struct Yes { char a[2]; }; + + template + struct isConvertible + { + // `+ sizeof(U*)` is required for GCC 4.5-4.7 + template + static typename enableIf(meta::declval())) + sizeof(U*)), Yes>::type test(int); + + template + static No test(...); + + enum { value = sizeof(test(0)) == sizeof(Yes) }; + }; + + template + struct isConvertibleToString : isConvertible {}; + +#if PLOG_ENABLE_WCHAR_INPUT + template + struct isConvertibleToWString : isConvertible {}; +#endif + + template + struct isContainer + { + template + static typename meta::enableIf().begin()) + sizeof(meta::declval().end() +#else + typename U::const_iterator +#endif + )), Yes>::type test(int); + + template + static No test(...); + + enum { value = sizeof(test(0)) == sizeof(Yes) }; + }; + + // Detects `std::filesystem::path` and `boost::filesystem::path`. They look like containers + // but we don't want to treat them as containers, so we use this detector to filter them out. + template + struct isFilesystemPath + { + template + static typename meta::enableIf().preferred_separator)), Yes>::type test(int); + + template + static No test(...); + + enum { value = sizeof(test(0)) == sizeof(Yes) }; + }; + } +#endif + + ////////////////////////////////////////////////////////////////////////// + // Stream output operators as free functions + +#if PLOG_ENABLE_WCHAR_INPUT + inline void operator<<(util::nostringstream& stream, const wchar_t* data) + { + data = data ? data : L"(null)"; + +# ifdef _WIN32 +# if PLOG_CHAR_IS_UTF8 + std::operator<<(stream, util::toNarrow(data, codePage::kUTF8)); +# else + std::operator<<(stream, data); +# endif +# else + std::operator<<(stream, util::toNarrow(data)); +# endif + } + + inline void operator<<(util::nostringstream& stream, wchar_t* data) + { + plog::detail::operator<<(stream, const_cast(data)); + } + + inline void operator<<(util::nostringstream& stream, const std::wstring& data) + { + plog::detail::operator<<(stream, data.c_str()); + } +#endif + + inline void operator<<(util::nostringstream& stream, const char* data) + { + data = data ? data : "(null)"; + +#if defined(_WIN32) && defined(__BORLANDC__) +# if PLOG_CHAR_IS_UTF8 + stream << data; +# else + stream << util::toWide(data); +# endif +#elif defined(_WIN32) +# if PLOG_CHAR_IS_UTF8 + std::operator<<(stream, data); +# else + std::operator<<(stream, util::toWide(data)); +# endif +#else + std::operator<<(stream, data); +#endif + } + + inline void operator<<(util::nostringstream& stream, char* data) + { + plog::detail::operator<<(stream, const_cast(data)); + } + + inline void operator<<(util::nostringstream& stream, const std::string& data) + { + plog::detail::operator<<(stream, data.c_str()); + } + +#ifdef __cpp_char8_t + inline void operator<<(util::nostringstream& stream, const char8_t* data) + { +# if PLOG_CHAR_IS_UTF8 + plog::detail::operator<<(stream, reinterpret_cast(data)); +# else + plog::detail::operator<<(stream, util::toWide(reinterpret_cast(data), codePage::kUTF8)); +# endif + } +#endif //__cpp_char8_t + + // Print `std::pair` + template + inline void operator<<(util::nostringstream& stream, const std::pair& data) + { + stream << data.first; + stream << ":"; + stream << data.second; + } + +#if defined(__clang__) || !defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 // skip for GCC < 4.5 due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=38600 +#if !defined(_MSC_VER) || _MSC_VER > 1400 // MSVC 2005 doesn't understand `enableIf`, so drop all `meta` + // Print data that can be casted to `std::string` + template + inline typename meta::enableIf::value, void>::type operator<<(util::nostringstream& stream, const T& data) + { + plog::detail::operator<<(stream, static_cast(data)); + } + +#if PLOG_ENABLE_WCHAR_INPUT + // Print data that can be casted to `std::wstring` + template + inline typename meta::enableIf::value, void>::type operator<<(util::nostringstream& stream, const T& data) + { + plog::detail::operator<<(stream, static_cast(data)); + } +#endif + + // Print std containers + template + inline typename meta::enableIf::value && + !meta::isConvertibleToString::value && +#if PLOG_ENABLE_WCHAR_INPUT + !meta::isConvertibleToWString::value && +#endif + !meta::isFilesystemPath::value, void>::type operator<<(util::nostringstream& stream, const T& data) + { + stream << "["; + + for (typename T::const_iterator it = data.begin(); it != data.end();) + { + stream << *it; + + if (++it == data.end()) + { + break; + } + + stream << ", "; + } + + stream << "]"; + } +#endif +#endif + +#ifdef __cplusplus_cli + // Print managed C++ `System::String^` + inline void operator<<(util::nostringstream& stream, System::String^ data) + { + cli::pin_ptr ptr = PtrToStringChars(data); + plog::detail::operator<<(stream, static_cast(ptr)); + } +#endif + +#if PLOG_ENABLE_WCHAR_INPUT && (!defined(_MSC_VER) || _MSC_VER > 1400) // MSVC 2005 doesn't understand `enableIf`, so drop all `meta` + namespace meta + { + template + struct valueType { enum { value = Value }; }; + + template + inline No operator<<(Stream&, const T&); + + template + struct isStreamable : valueType(), meta::declval())) != sizeof(No)> {}; + + template + struct isStreamable : valueType {}; + + template + struct isStreamable : valueType {}; + + template + struct isStreamable : valueType {}; + + // meta doesn't work well for deleted functions and C++20 has `operator<<(std::ostream&, const wchar_t*) = delete` so exlicitly define it + template<> + struct isStreamable : valueType {}; + +# ifdef __cpp_char8_t + // meta doesn't work well for deleted functions and C++20 has `operator<<(std::ostream&, const char8_t*) = delete` so exlicitly define it + template + struct isStreamable : valueType {}; + + template + struct isStreamable : valueType {}; +# endif //__cpp_char8_t + } + +# if PLOG_CHAR_IS_UTF8 + // Print types that can be streamed into `std::owstringstream` but not into `std::ostringstream` when we use UTF-8 on Windows + template + inline typename meta::enableIf::value && + !meta::isStreamable::value && + !meta::isConvertibleToWString::value, void>::type operator<<(std::ostringstream& stream, const T& data) + { + std::wostringstream ss; + ss << data; + stream << ss.str(); + } +# else + // Print types that can be streamed into `std::ostringstream` but not into `std::owstringstream` when we use `wchar_t` on Windows + template + inline typename meta::enableIf::value && + !meta::isStreamable::value && + !meta::isConvertibleToString::value, void>::type operator<<(std::wostringstream& stream, const T& data) + { + std::ostringstream ss; + ss << data; + stream << ss.str(); + } +# endif +#endif + } + + class Record + { + public: + Record(Severity severity, const char* func, size_t line, const char* file, const void* object, int instanceId) + : m_severity(severity), m_tid(util::gettid()), m_object(object), m_line(line), m_func(func), m_file(file), m_instanceId(instanceId) + { + util::ftime(&m_time); + } + + Record& ref() + { + return *this; + } + + ////////////////////////////////////////////////////////////////////////// + // Stream output operators + + Record& operator<<(char data) + { + char str[] = { data, 0 }; + return *this << str; + } + +#if PLOG_ENABLE_WCHAR_INPUT + Record& operator<<(wchar_t data) + { + wchar_t str[] = { data, 0 }; + return *this << str; + } +#endif + + Record& operator<<(util::nostream& (PLOG_CDECL *data)(util::nostream&)) + { + m_message << data; + return *this; + } + +#ifdef QT_VERSION + Record& operator<<(const QString& data) + { +# if PLOG_CHAR_IS_UTF8 + return *this << data.toStdString(); +# else + return *this << data.toStdWString(); +# endif + } + +# if QT_VERSION < 0x060000 + Record& operator<<(const QStringRef& data) + { + return *this << data.toString(); + } +# endif + +# ifdef QSTRINGVIEW_H + Record& operator<<(QStringView data) + { + return *this << data.toString(); + } +# endif +#endif + + template + Record& operator<<(const T& data) + { + using namespace plog::detail; + + m_message << data; + return *this; + } + +#ifndef __cplusplus_cli + Record& printf(const char* format, ...) + { + using namespace util; + + char* str = NULL; + va_list ap; + + va_start(ap, format); + int len = vasprintf(&str, format, ap); + static_cast(len); + va_end(ap); + + *this << str; + free(str); + + return *this; + } + +#ifdef _WIN32 + Record& printf(const wchar_t* format, ...) + { + using namespace util; + + wchar_t* str = NULL; + va_list ap; + + va_start(ap, format); + int len = vaswprintf(&str, format, ap); + static_cast(len); + va_end(ap); + + *this << str; + free(str); + + return *this; + } +#endif +#endif //__cplusplus_cli + + ////////////////////////////////////////////////////////////////////////// + // Getters + + virtual const util::Time& getTime() const + { + return m_time; + } + + virtual Severity getSeverity() const + { + return m_severity; + } + + virtual unsigned int getTid() const + { + return m_tid; + } + + virtual const void* getObject() const + { + return m_object; + } + + virtual size_t getLine() const + { + return m_line; + } + + virtual const util::nchar* getMessage() const + { + m_messageStr = m_message.str(); + return m_messageStr.c_str(); + } + + virtual const char* getFunc() const + { + m_funcStr = util::processFuncName(m_func); + return m_funcStr.c_str(); + } + + virtual const char* getFile() const + { + return m_file; + } + + virtual ~Record() // virtual destructor to satisfy -Wnon-virtual-dtor warning + { + } + + virtual int getInstanceId() const + { + return m_instanceId; + } + + private: + util::Time m_time; + const Severity m_severity; + const unsigned int m_tid; + const void* const m_object; + const size_t m_line; + util::nostringstream m_message; + const char* const m_func; + const char* const m_file; + const int m_instanceId; + mutable std::string m_funcStr; + mutable util::nstring m_messageStr; + }; +} diff --git a/include/plog/Severity.h b/include/plog/Severity.h new file mode 100644 index 0000000..446768e --- /dev/null +++ b/include/plog/Severity.h @@ -0,0 +1,61 @@ +#pragma once +#include + +namespace plog +{ + enum Severity + { + none = 0, + fatal = 1, + error = 2, + warning = 3, + info = 4, + debug = 5, + verbose = 6 + }; + +#ifdef _MSC_VER +# pragma warning(suppress: 26812) // Prefer 'enum class' over 'enum' +#endif + inline const char* severityToString(Severity severity) + { + switch (severity) + { + case fatal: + return "FATAL"; + case error: + return "ERROR"; + case warning: + return "WARN"; + case info: + return "INFO"; + case debug: + return "DEBUG"; + case verbose: + return "VERB"; + default: + return "NONE"; + } + } + + inline Severity severityFromString(const char* str) + { + switch (std::toupper(str[0])) + { + case 'F': + return fatal; + case 'E': + return error; + case 'W': + return warning; + case 'I': + return info; + case 'D': + return debug; + case 'V': + return verbose; + default: + return none; + } + } +} diff --git a/include/plog/Util.h b/include/plog/Util.h new file mode 100644 index 0000000..ac01a52 --- /dev/null +++ b/include/plog/Util.h @@ -0,0 +1,616 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include + +#ifndef PLOG_ENABLE_WCHAR_INPUT +# ifdef _WIN32 +# define PLOG_ENABLE_WCHAR_INPUT 1 +# else +# define PLOG_ENABLE_WCHAR_INPUT 0 +# endif +#endif + +////////////////////////////////////////////////////////////////////////// +// PLOG_CHAR_IS_UTF8 specifies character encoding of `char` type. On *nix +// systems it's set to UTF-8 while on Windows in can be ANSI or UTF-8. It +// automatically detects `/utf-8` command line option in MSVC. Also it can +// be set manually if required. +// This option allows to support http://utf8everywhere.org approach. + +#ifndef PLOG_CHAR_IS_UTF8 +# if defined(_WIN32) && !defined(_UTF8) +# define PLOG_CHAR_IS_UTF8 0 +# else +# define PLOG_CHAR_IS_UTF8 1 +# endif +#endif + +#ifdef _WIN32 +# if defined(PLOG_EXPORT) +# define PLOG_LINKAGE __declspec(dllexport) +# elif defined(PLOG_IMPORT) +# define PLOG_LINKAGE __declspec(dllimport) +# endif +# if defined(PLOG_GLOBAL) +# error "PLOG_GLOBAL isn't supported on Windows" +# endif +#else +# if defined(PLOG_GLOBAL) +# define PLOG_LINKAGE __attribute__ ((visibility ("default"))) +# elif defined(PLOG_LOCAL) +# define PLOG_LINKAGE __attribute__ ((visibility ("hidden"))) +# define PLOG_LINKAGE_HIDDEN PLOG_LINKAGE +# endif +# if defined(PLOG_EXPORT) || defined(PLOG_IMPORT) +# error "PLOG_EXPORT/PLOG_IMPORT is supported only on Windows" +# endif +#endif + +#ifndef PLOG_LINKAGE +# define PLOG_LINKAGE +#endif + +#ifndef PLOG_LINKAGE_HIDDEN +# define PLOG_LINKAGE_HIDDEN +#endif + +#ifdef _WIN32 +# include +# include +# include +# include +# include +#else +# include +# include +# if defined(__linux__) || defined(__FreeBSD__) +# include +# elif defined(__rtems__) +# include +# endif +# if defined(_POSIX_THREADS) +# include +# endif +# if PLOG_ENABLE_WCHAR_INPUT +# include +# endif +#endif + +#if PLOG_CHAR_IS_UTF8 +# define PLOG_NSTR(x) x +#else +# define _PLOG_NSTR(x) L##x +# define PLOG_NSTR(x) _PLOG_NSTR(x) +#endif + +#ifdef _WIN32 +# define PLOG_CDECL __cdecl +#else +# define PLOG_CDECL +#endif + +#if __cplusplus >= 201103L || defined(_MSC_VER) && _MSC_VER >= 1700 +# define PLOG_OVERRIDE override +#else +# define PLOG_OVERRIDE +#endif + +namespace plog +{ + namespace util + { +#if PLOG_CHAR_IS_UTF8 + typedef std::string nstring; + typedef std::ostringstream nostringstream; + typedef std::istringstream nistringstream; + typedef std::ostream nostream; + typedef char nchar; +#else + typedef std::wstring nstring; + typedef std::wostringstream nostringstream; + typedef std::wistringstream nistringstream; + typedef std::wostream nostream; + typedef wchar_t nchar; +#endif + + inline void localtime_s(struct tm* t, const time_t* time) + { +#if defined(_WIN32) && defined(__BORLANDC__) + ::localtime_s(time, t); +#elif defined(_WIN32) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) + *t = *::localtime(time); +#elif defined(_WIN32) + ::localtime_s(t, time); +#else + ::localtime_r(time, t); +#endif + } + + inline void gmtime_s(struct tm* t, const time_t* time) + { +#if defined(_WIN32) && defined(__BORLANDC__) + ::gmtime_s(time, t); +#elif defined(_WIN32) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) + *t = *::gmtime(time); +#elif defined(_WIN32) + ::gmtime_s(t, time); +#else + ::gmtime_r(time, t); +#endif + } + +#ifdef _WIN32 + typedef timeb Time; + + inline void ftime(Time* t) + { + ::ftime(t); + } +#else + struct Time + { + time_t time; + unsigned short millitm; + }; + + inline void ftime(Time* t) + { + timeval tv; + ::gettimeofday(&tv, NULL); + + t->time = tv.tv_sec; + t->millitm = static_cast(tv.tv_usec / 1000); + } +#endif + + inline unsigned int gettid() + { +#ifdef _WIN32 + return GetCurrentThreadId(); +#elif defined(__linux__) + return static_cast(::syscall(__NR_gettid)); +#elif defined(__FreeBSD__) + long tid; + syscall(SYS_thr_self, &tid); + return static_cast(tid); +#elif defined(__rtems__) + return rtems_task_self(); +#elif defined(__APPLE__) + uint64_t tid64; + pthread_threadid_np(NULL, &tid64); + return static_cast(tid64); +#else + return 0; +#endif + } + +#ifndef _GNU_SOURCE + inline int vasprintf(char** strp, const char* format, va_list ap) + { + va_list ap_copy; +#if defined(_MSC_VER) && _MSC_VER <= 1600 + ap_copy = ap; // there is no va_copy on Visual Studio 2010 +#else + va_copy(ap_copy, ap); +#endif +#ifndef __STDC_SECURE_LIB__ + int charCount = vsnprintf(NULL, 0, format, ap_copy); +#else + int charCount = _vscprintf(format, ap_copy); +#endif + va_end(ap_copy); + if (charCount < 0) + { + return -1; + } + + size_t bufferCharCount = static_cast(charCount) + 1; + + char* str = static_cast(malloc(bufferCharCount)); + if (!str) + { + return -1; + } + +#ifndef __STDC_SECURE_LIB__ + int retval = vsnprintf(str, bufferCharCount, format, ap); +#else + int retval = vsnprintf_s(str, bufferCharCount, static_cast(-1), format, ap); +#endif + if (retval < 0) + { + free(str); + return -1; + } + + *strp = str; + return retval; + } +#endif + +#ifdef _WIN32 + inline int vaswprintf(wchar_t** strp, const wchar_t* format, va_list ap) + { +#if defined(__BORLANDC__) + int charCount = 0x1000; // there is no _vscwprintf on Borland/Embarcadero +#else + int charCount = _vscwprintf(format, ap); + if (charCount < 0) + { + return -1; + } +#endif + + size_t bufferCharCount = static_cast(charCount) + 1; + + wchar_t* str = static_cast(malloc(bufferCharCount * sizeof(wchar_t))); + if (!str) + { + return -1; + } + +#if defined(__BORLANDC__) + int retval = vsnwprintf_s(str, bufferCharCount, format, ap); +#elif defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) + int retval = _vsnwprintf(str, bufferCharCount, format, ap); +#else + int retval = _vsnwprintf_s(str, bufferCharCount, charCount, format, ap); +#endif + if (retval < 0) + { + free(str); + return -1; + } + + *strp = str; + return retval; + } +#endif + +#ifdef _WIN32 + inline std::wstring toWide(const char* str, UINT cp = codePage::kChar) + { + size_t len = ::strlen(str); + std::wstring wstr(len, 0); + + if (!wstr.empty()) + { + int wlen = MultiByteToWideChar(cp, 0, str, static_cast(len), &wstr[0], static_cast(wstr.size())); + wstr.resize(wlen); + } + + return wstr; + } + + inline std::wstring toWide(const std::string& str, UINT cp = codePage::kChar) + { + return toWide(str.c_str(), cp); + } + + inline const std::wstring& toWide(const std::wstring& str) // do nothing for already wide string + { + return str; + } + + inline std::string toNarrow(const std::wstring& wstr, long page) + { + int len = WideCharToMultiByte(page, 0, wstr.c_str(), static_cast(wstr.size()), 0, 0, 0, 0); + std::string str(len, 0); + + if (!str.empty()) + { + WideCharToMultiByte(page, 0, wstr.c_str(), static_cast(wstr.size()), &str[0], len, 0, 0); + } + + return str; + } +#elif PLOG_ENABLE_WCHAR_INPUT + inline std::string toNarrow(const wchar_t* wstr) + { + size_t wlen = ::wcslen(wstr); + std::string str(wlen * sizeof(wchar_t), 0); + + if (!str.empty()) + { + const char* in = reinterpret_cast(&wstr[0]); + char* out = &str[0]; + size_t inBytes = wlen * sizeof(wchar_t); + size_t outBytes = str.size(); + + iconv_t cd = ::iconv_open("UTF-8", "WCHAR_T"); + ::iconv(cd, const_cast(&in), &inBytes, &out, &outBytes); + ::iconv_close(cd); + + str.resize(str.size() - outBytes); + } + + return str; + } +#endif + + inline std::string processFuncName(const char* func) + { +#if (defined(_WIN32) && !defined(__MINGW32__)) || defined(__OBJC__) + return std::string(func); +#else + const char* funcBegin = func; + const char* funcEnd = ::strchr(funcBegin, '('); + int foundTemplate = 0; + + if (!funcEnd) + { + return std::string(func); + } + + for (const char* i = funcEnd - 1; i >= funcBegin; --i) // search backwards for the first space char + { + if (*i == '>') + { + foundTemplate++; + } + else if (*i == '<') + { + foundTemplate--; + } + else if (*i == ' ' && foundTemplate == 0) + { + funcBegin = i + 1; + break; + } + } + + return std::string(funcBegin, funcEnd); +#endif + } + + inline const nchar* findExtensionDot(const nchar* fileName) + { +#if PLOG_CHAR_IS_UTF8 + return std::strrchr(fileName, '.'); +#else + return std::wcsrchr(fileName, L'.'); +#endif + } + + inline void splitFileName(const nchar* fileName, nstring& fileNameNoExt, nstring& fileExt) + { + const nchar* dot = findExtensionDot(fileName); + + if (dot) + { + fileNameNoExt.assign(fileName, dot); + fileExt.assign(dot + 1); + } + else + { + fileNameNoExt.assign(fileName); + fileExt.clear(); + } + } + + class PLOG_LINKAGE NonCopyable + { + protected: + NonCopyable() + { + } + + private: + NonCopyable(const NonCopyable&); + NonCopyable& operator=(const NonCopyable&); + }; + + class PLOG_LINKAGE_HIDDEN File : NonCopyable + { + public: + File() : m_file(-1) + { + } + + ~File() + { + close(); + } + + size_t open(const nstring& fileName) + { +#if defined(_WIN32) && (defined(__BORLANDC__) || defined(__MINGW32__)) + m_file = ::_wsopen(toWide(fileName).c_str(), _O_CREAT | _O_WRONLY | _O_BINARY | _O_NOINHERIT, SH_DENYWR, _S_IREAD | _S_IWRITE); +#elif defined(_WIN32) + ::_wsopen_s(&m_file, toWide(fileName).c_str(), _O_CREAT | _O_WRONLY | _O_BINARY | _O_NOINHERIT, _SH_DENYWR, _S_IREAD | _S_IWRITE); +#elif defined(O_CLOEXEC) + m_file = ::open(fileName.c_str(), O_CREAT | O_APPEND | O_WRONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +#else + m_file = ::open(fileName.c_str(), O_CREAT | O_APPEND | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +#endif + return seek(0, SEEK_END); + } + + size_t write(const void* buf, size_t count) + { + return m_file != -1 ? static_cast( +#ifdef _WIN32 + ::_write(m_file, buf, static_cast(count)) +#else + ::write(m_file, buf, count) +#endif + ) : static_cast(-1); + } + + template + size_t write(const std::basic_string& str) + { + return write(str.data(), str.size() * sizeof(CharType)); + } + + size_t seek(size_t offset, int whence) + { + return m_file != -1 ? static_cast( +#if defined(_WIN32) && (defined(__BORLANDC__) || defined(__MINGW32__)) + ::_lseek(m_file, static_cast(offset), whence) +#elif defined(_WIN32) + ::_lseeki64(m_file, static_cast(offset), whence) +#else + ::lseek(m_file, static_cast(offset), whence) +#endif + ) : static_cast(-1); + } + + void close() + { + if (m_file != -1) + { +#ifdef _WIN32 + ::_close(m_file); +#else + ::close(m_file); +#endif + m_file = -1; + } + } + + static int unlink(const nstring& fileName) + { +#ifdef _WIN32 + return ::_wunlink(toWide(fileName).c_str()); +#else + return ::unlink(fileName.c_str()); +#endif + } + + static int rename(const nstring& oldFilename, const nstring& newFilename) + { +#ifdef _WIN32 + return MoveFileW(toWide(oldFilename).c_str(), toWide(newFilename).c_str()); +#else + return ::rename(oldFilename.c_str(), newFilename.c_str()); +#endif + } + + private: + int m_file; + }; + + class PLOG_LINKAGE_HIDDEN Mutex : NonCopyable + { + public: + Mutex() + { +#ifdef _WIN32 + InitializeCriticalSection(&m_sync); +#elif defined(__rtems__) + rtems_semaphore_create(0, 1, + RTEMS_PRIORITY | + RTEMS_BINARY_SEMAPHORE | + RTEMS_INHERIT_PRIORITY, 1, &m_sync); +#elif defined(_POSIX_THREADS) + ::pthread_mutex_init(&m_sync, 0); +#endif + } + + ~Mutex() + { +#ifdef _WIN32 + DeleteCriticalSection(&m_sync); +#elif defined(__rtems__) + rtems_semaphore_delete(m_sync); +#elif defined(_POSIX_THREADS) + ::pthread_mutex_destroy(&m_sync); +#endif + } + + friend class MutexLock; + + private: + void lock() + { +#ifdef _WIN32 + EnterCriticalSection(&m_sync); +#elif defined(__rtems__) + rtems_semaphore_obtain(m_sync, RTEMS_WAIT, RTEMS_NO_TIMEOUT); +#elif defined(_POSIX_THREADS) + ::pthread_mutex_lock(&m_sync); +#endif + } + + void unlock() + { +#ifdef _WIN32 + LeaveCriticalSection(&m_sync); +#elif defined(__rtems__) + rtems_semaphore_release(m_sync); +#elif defined(_POSIX_THREADS) + ::pthread_mutex_unlock(&m_sync); +#endif + } + + private: +#ifdef _WIN32 + CRITICAL_SECTION m_sync; +#elif defined(__rtems__) + rtems_id m_sync; +#elif defined(_POSIX_THREADS) + pthread_mutex_t m_sync; +#endif + }; + + class PLOG_LINKAGE_HIDDEN MutexLock : NonCopyable + { + public: + MutexLock(Mutex& mutex) : m_mutex(mutex) + { + m_mutex.lock(); + } + + ~MutexLock() + { + m_mutex.unlock(); + } + + private: + Mutex& m_mutex; + }; + + template +#ifdef _WIN32 + class Singleton : NonCopyable +#else + class PLOG_LINKAGE Singleton : NonCopyable +#endif + { + public: +#if (defined(__clang__) || defined(__GNUC__) && __GNUC__ >= 8) && !defined(__BORLANDC__) + // This constructor is called before the `T` object is fully constructed, and + // pointers are not dereferenced anyway, so UBSan shouldn't check vptrs. + __attribute__((no_sanitize("vptr"))) +#endif + Singleton() + { + assert(!m_instance); + m_instance = static_cast(this); + } + + ~Singleton() + { + assert(m_instance); + m_instance = 0; + } + + static T* getInstance() + { + return m_instance; + } + + private: + static T* m_instance; + }; + + template + T* Singleton::m_instance = NULL; + } +} diff --git a/include/plog/WinApi.h b/include/plog/WinApi.h new file mode 100644 index 0000000..ccf44af --- /dev/null +++ b/include/plog/WinApi.h @@ -0,0 +1,175 @@ +#pragma once + +#ifdef _WIN32 + +// These windows structs must be in a global namespace +struct HKEY__; +struct _SECURITY_ATTRIBUTES; +struct _CONSOLE_SCREEN_BUFFER_INFO; +struct _RTL_CRITICAL_SECTION; + +namespace plog +{ + typedef unsigned long DWORD; + typedef unsigned short WORD; + typedef unsigned char BYTE; + typedef unsigned int UINT; + typedef int BOOL; + typedef long LSTATUS; + typedef char* LPSTR; + typedef wchar_t* LPWSTR; + typedef const char* LPCSTR; + typedef const wchar_t* LPCWSTR; + typedef void* HANDLE; + typedef HKEY__* HKEY; + typedef size_t ULONG_PTR; + + struct CRITICAL_SECTION + { + void* DebugInfo; + long LockCount; + long RecursionCount; + HANDLE OwningThread; + HANDLE LockSemaphore; + ULONG_PTR SpinCount; + }; + + struct COORD + { + short X; + short Y; + }; + + struct SMALL_RECT + { + short Left; + short Top; + short Right; + short Bottom; + }; + + struct CONSOLE_SCREEN_BUFFER_INFO + { + COORD dwSize; + COORD dwCursorPosition; + WORD wAttributes; + SMALL_RECT srWindow; + COORD dwMaximumWindowSize; + }; + + namespace codePage + { + const UINT kActive = 0; + const UINT kUTF8 = 65001; +#if PLOG_CHAR_IS_UTF8 + const UINT kChar = kUTF8; +#else + const UINT kChar = kActive; +#endif + } + + namespace eventLog + { + const WORD kErrorType = 0x0001; + const WORD kWarningType = 0x0002; + const WORD kInformationType = 0x0004; + } + + namespace hkey + { + const HKEY kLocalMachine = reinterpret_cast(static_cast(0x80000002)); + } + + namespace regSam + { + const DWORD kQueryValue = 0x0001; + const DWORD kSetValue = 0x0002; + } + + namespace regType + { + const DWORD kExpandSz = 2; + const DWORD kDword = 4; + } + + namespace stdHandle + { + const DWORD kOutput = static_cast(-11); + const DWORD kErrorOutput = static_cast(-12); + } + + namespace foreground + { + const WORD kBlue = 0x0001; + const WORD kGreen = 0x0002; + const WORD kRed = 0x0004; + const WORD kIntensity = 0x0008; + } + + namespace background + { + const WORD kBlue = 0x0010; + const WORD kGreen = 0x0020; + const WORD kRed = 0x0040; + const WORD kIntensity = 0x0080; + } + + extern "C" + { + __declspec(dllimport) int __stdcall MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar); + __declspec(dllimport) int __stdcall WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, const char* lpDefaultChar, BOOL* lpUsedDefaultChar); + + __declspec(dllimport) DWORD __stdcall GetCurrentThreadId(); + + __declspec(dllimport) BOOL __stdcall MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName); + + __declspec(dllimport) void __stdcall InitializeCriticalSection(_RTL_CRITICAL_SECTION* lpCriticalSection); + __declspec(dllimport) void __stdcall EnterCriticalSection(_RTL_CRITICAL_SECTION* lpCriticalSection); + __declspec(dllimport) void __stdcall LeaveCriticalSection(_RTL_CRITICAL_SECTION* lpCriticalSection); + __declspec(dllimport) void __stdcall DeleteCriticalSection(_RTL_CRITICAL_SECTION* lpCriticalSection); + + __declspec(dllimport) HANDLE __stdcall RegisterEventSourceW(LPCWSTR lpUNCServerName, LPCWSTR lpSourceName); + __declspec(dllimport) BOOL __stdcall DeregisterEventSource(HANDLE hEventLog); + __declspec(dllimport) BOOL __stdcall ReportEventW(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, void* lpUserSid, WORD wNumStrings, DWORD dwDataSize, LPCWSTR* lpStrings, void* lpRawData); + + __declspec(dllimport) LSTATUS __stdcall RegCreateKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass, DWORD dwOptions, DWORD samDesired, _SECURITY_ATTRIBUTES* lpSecurityAttributes, HKEY* phkResult, DWORD* lpdwDisposition); + __declspec(dllimport) LSTATUS __stdcall RegSetValueExW(HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE* lpData, DWORD cbData); + __declspec(dllimport) LSTATUS __stdcall RegCloseKey(HKEY hKey); + __declspec(dllimport) LSTATUS __stdcall RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, DWORD samDesired, HKEY* phkResult); + __declspec(dllimport) LSTATUS __stdcall RegDeleteKeyW(HKEY hKey, LPCWSTR lpSubKey); + + __declspec(dllimport) HANDLE __stdcall GetStdHandle(DWORD nStdHandle); + + __declspec(dllimport) BOOL __stdcall WriteConsoleW(HANDLE hConsoleOutput, const void* lpBuffer, DWORD nNumberOfCharsToWrite, DWORD* lpNumberOfCharsWritten, void* lpReserved); + __declspec(dllimport) BOOL __stdcall GetConsoleScreenBufferInfo(HANDLE hConsoleOutput, _CONSOLE_SCREEN_BUFFER_INFO* lpConsoleScreenBufferInfo); + __declspec(dllimport) BOOL __stdcall SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttributes); + + __declspec(dllimport) void __stdcall OutputDebugStringW(LPCWSTR lpOutputString); + } + + inline void InitializeCriticalSection(CRITICAL_SECTION* criticalSection) + { + plog::InitializeCriticalSection(reinterpret_cast<_RTL_CRITICAL_SECTION*>(criticalSection)); + } + + inline void EnterCriticalSection(CRITICAL_SECTION* criticalSection) + { + plog::EnterCriticalSection(reinterpret_cast<_RTL_CRITICAL_SECTION*>(criticalSection)); + } + + inline void LeaveCriticalSection(CRITICAL_SECTION* criticalSection) + { + plog::LeaveCriticalSection(reinterpret_cast<_RTL_CRITICAL_SECTION*>(criticalSection)); + } + + inline void DeleteCriticalSection(CRITICAL_SECTION* criticalSection) + { + plog::DeleteCriticalSection(reinterpret_cast<_RTL_CRITICAL_SECTION*>(criticalSection)); + } + + inline BOOL GetConsoleScreenBufferInfo(HANDLE consoleOutput, CONSOLE_SCREEN_BUFFER_INFO* consoleScreenBufferInfo) + { + return plog::GetConsoleScreenBufferInfo(consoleOutput, reinterpret_cast<_CONSOLE_SCREEN_BUFFER_INFO*>(consoleScreenBufferInfo)); + } +} +#endif // _WIN32 diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 9cf4fd0..0000000 --- a/main.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include // for std::cout -#include "io.h" - -// Definition of function main() -int main() -{ - - int a{readNumber()}; - int b{readNumber()}; - writeAnswer(a + b); - return 0; -} \ No newline at end of file diff --git a/io.cpp b/src/io.cpp similarity index 100% rename from io.cpp rename to src/io.cpp diff --git a/io.h b/src/io.h similarity index 100% rename from io.h rename to src/io.h diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..5b525f2 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,15 @@ +#include +#include // Step1: include the headers +#include "plog/Initializers/RollingFileInitializer.h" +#include "io.h" + +// Definition of function main() +int main() +{ + plog::init(plog::debug, "../Hello.txt"); + PLOGD << "Hello log!"; + int a{readNumber()}; + int b{readNumber()}; + writeAnswer(a + b); + return 0; +} \ No newline at end of file From cda6ed407ab13a6d7fe279477c0539d0f329c3e8 Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 22 Jan 2024 12:20:24 +0100 Subject: [PATCH 02/20] refactor --- io.cpp => src/io.cpp | 0 io.h => src/io.h | 0 main.cpp => src/main.cpp | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename io.cpp => src/io.cpp (100%) rename io.h => src/io.h (100%) rename main.cpp => src/main.cpp (100%) diff --git a/io.cpp b/src/io.cpp similarity index 100% rename from io.cpp rename to src/io.cpp diff --git a/io.h b/src/io.h similarity index 100% rename from io.h rename to src/io.h diff --git a/main.cpp b/src/main.cpp similarity index 100% rename from main.cpp rename to src/main.cpp From ee652cb6ee5e8526aa2ef9fcedf5851e91bd658a Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 22 Jan 2024 12:22:28 +0100 Subject: [PATCH 03/20] refactor --- dot vscode/launch.json | 4 ++-- dot vscode/tasks.json | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/dot vscode/launch.json b/dot vscode/launch.json index 081340e..58291ac 100644 --- a/dot vscode/launch.json +++ b/dot vscode/launch.json @@ -4,7 +4,7 @@ "name": "Debug: C/C++", "type": "cppdbg", "request": "launch", - "program": "${fileDirname}\\build\\${fileBasenameNoExtension}.exe", + "program": "${workspaceFolder}\\build\\${fileBasenameNoExtension}.exe", "args": [], "stopAtEntry": false, "cwd": "${fileDirname}", @@ -30,7 +30,7 @@ "name": "Release: C/C++", "type": "cppdbg", "request": "launch", - "program": "${fileDirname}\\build\\${fileBasenameNoExtension}.exe", + "program": "${workspaceFolder}\\build\\${fileBasenameNoExtension}.exe", "args": [], "stopAtEntry": false, "cwd": "${fileDirname}", diff --git a/dot vscode/tasks.json b/dot vscode/tasks.json index 6037983..8299a09 100644 --- a/dot vscode/tasks.json +++ b/dot vscode/tasks.json @@ -6,12 +6,13 @@ "command": "C:\\msys64\\mingw64\\bin\\g++.exe", "args": [ "-fdiagnostics-color=always", + "-I${workspaceFolder}\\include", "-ggdb", "-std=c++20", "-pedantic-errors", - "${fileDirname}/**.cpp", + "${workspaceFolder}/src/**.cpp", "-o", - "${fileDirname}\\build\\${fileBasenameNoExtension}.exe" + "${workspaceFolder}\\build\\${fileBasenameNoExtension}.exe" ], "options": { "cwd": "${fileDirname}" @@ -26,13 +27,14 @@ "command": "C:\\msys64\\mingw64\\bin\\g++.exe", "args": [ "-fdiagnostics-color=always", + "-I${workspaceFolder}\\include", "-O2", "-DNDEBUG", "-std=c++20", "-pedantic-errors", - "${fileDirname}/**.cpp", + "${workspaceFolder}/src/**.cpp", "-o", - "${fileDirname}\\build\\${fileBasenameNoExtension}.exe" + "${workspaceFolder}\\build\\${fileBasenameNoExtension}.exe" ], "options": { "cwd": "${fileDirname}" From 943f09563ea3fbd2955383082963b4eec43e5f47 Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 22 Jan 2024 12:23:14 +0100 Subject: [PATCH 04/20] refactor --- include/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 include/.gitkeep diff --git a/include/.gitkeep b/include/.gitkeep new file mode 100644 index 0000000..e69de29 From 95bbaa9aab0d19445be9a4be8bb6f699b1248ee0 Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 22 Jan 2024 16:50:08 +0100 Subject: [PATCH 05/20] refactor snake case --- src/io.cpp | 4 ++-- src/io.h | 4 ++-- src/main.cpp | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/io.cpp b/src/io.cpp index 6c03ca8..e8bedeb 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -1,14 +1,14 @@ #include "io.h" #include -int readNumber() +int read_number() { std::cout << "Enter a number to add: "; int x{}; std::cin >> x; return x; } -void writeAnswer(int x) +void write_answer(int x) { std::cout << "The answer is: " << x << "\n"; } \ No newline at end of file diff --git a/src/io.h b/src/io.h index 7c489bc..a9b314e 100644 --- a/src/io.h +++ b/src/io.h @@ -1,4 +1,4 @@ #pragma once -int readNumber(); -void writeAnswer(int x); \ No newline at end of file +int read_number(); +void write_answer(int x); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 9cf4fd0..218873f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,8 +5,8 @@ int main() { - int a{readNumber()}; - int b{readNumber()}; - writeAnswer(a + b); + int a{read_number()}; + int b{read_number()}; + write_answer(a + b); return 0; } \ No newline at end of file From 0b7f4871524eb94eeacdcfd0902ca170dd6c215c Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 22 Jan 2024 19:08:07 +0100 Subject: [PATCH 06/20] update --- src/main.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 218873f..b582257 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,12 +1,24 @@ #include // for std::cout +#include #include "io.h" - +#include // Definition of function main() int main() { - int a{read_number()}; - int b{read_number()}; - write_answer(a + b); + // int a{read_number()}; + // int b{read_number()}; + // write_answer(a + b); + + std::cout << std::left; // left justify output + std::cout << std::setw(16) << "bool:" << sizeof(bool) << " bytes\n"; + std::cout << std::setw(16) << "char:" << sizeof(char) << " bytes\n"; + std::cout << std::setw(16) << "short:" << sizeof(short) << " bytes\n"; + std::cout << std::setw(16) << "int:" << sizeof(int) << " bytes\n"; + std::cout << std::setw(16) << "long:" << sizeof(long) << " bytes\n"; + std::cout << std::setw(16) << "long long:" << sizeof(long long) << " bytes\n"; + std::cout << std::setw(16) << "float:" << sizeof(float) << " bytes\n"; + std::cout << std::setw(16) << "double:" << sizeof(double) << " bytes\n"; + std::cout << std::setw(16) << "long double:" << sizeof(long double) << " bytes\n"; return 0; } \ No newline at end of file From 15d64721613c83cad80aa674475e51095c5bcd4f Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 22 Jan 2024 19:08:56 +0100 Subject: [PATCH 07/20] update --- src/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index b582257..2b1859d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,6 @@ #include // for std::cout #include #include "io.h" -#include // Definition of function main() int main() { From ebe10eb632a850a201dc9cf1c8582ba6daab94ab Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 29 Jan 2024 08:09:07 +0100 Subject: [PATCH 08/20] update --- src/io.cpp | 8 ++++++++ src/io.h | 3 ++- src/main.cpp | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/io.cpp b/src/io.cpp index e8bedeb..95a9159 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -11,4 +11,12 @@ int read_number() void write_answer(int x) { std::cout << "The answer is: " << x << "\n"; +} + +void convert_char_to_ascii() +{ + std::cout << "Enter a single character: "; + char c{}; + std::cin >> c; + std::cout << "You entered '" << c << "', which hass ASCII code " << static_cast(c) << "."; } \ No newline at end of file diff --git a/src/io.h b/src/io.h index a9b314e..ce5bab5 100644 --- a/src/io.h +++ b/src/io.h @@ -1,4 +1,5 @@ #pragma once int read_number(); -void write_answer(int x); \ No newline at end of file +void write_answer(int x); +void convert_char_to_ascii(); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 2b1859d..c0ebe3f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,6 +8,7 @@ int main() // int a{read_number()}; // int b{read_number()}; // write_answer(a + b); + // convert_char_to_ascii(); std::cout << std::left; // left justify output std::cout << std::setw(16) << "bool:" << sizeof(bool) << " bytes\n"; @@ -19,5 +20,6 @@ int main() std::cout << std::setw(16) << "float:" << sizeof(float) << " bytes\n"; std::cout << std::setw(16) << "double:" << sizeof(double) << " bytes\n"; std::cout << std::setw(16) << "long double:" << sizeof(long double) << " bytes\n"; + return 0; } \ No newline at end of file From 3964df59165f2470fdd304dfa1a9854ab11e97de Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 29 Jan 2024 16:13:08 +0100 Subject: [PATCH 09/20] update --- src/io.cpp | 22 ++++++++++++++++++++-- src/io.h | 4 +++- src/main.cpp | 19 +++---------------- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/io.cpp b/src/io.cpp index 95a9159..1da65ac 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -1,6 +1,12 @@ #include "io.h" #include - +#include +void add_two_numbers() +{ + int a{read_number()}; + int b{read_number()}; + write_answer(a + b); +} int read_number() { std::cout << "Enter a number to add: "; @@ -12,11 +18,23 @@ void write_answer(int x) { std::cout << "The answer is: " << x << "\n"; } - void convert_char_to_ascii() { std::cout << "Enter a single character: "; char c{}; std::cin >> c; std::cout << "You entered '" << c << "', which hass ASCII code " << static_cast(c) << "."; +} +void print_type_size_bytes() +{ + std::cout << std::left; // left justify output + std::cout << std::setw(16) << "bool:" << sizeof(bool) << " bytes\n"; + std::cout << std::setw(16) << "char:" << sizeof(char) << " bytes\n"; + std::cout << std::setw(16) << "short:" << sizeof(short) << " bytes\n"; + std::cout << std::setw(16) << "int:" << sizeof(int) << " bytes\n"; + std::cout << std::setw(16) << "long:" << sizeof(long) << " bytes\n"; + std::cout << std::setw(16) << "long long:" << sizeof(long long) << " bytes\n"; + std::cout << std::setw(16) << "float:" << sizeof(float) << " bytes\n"; + std::cout << std::setw(16) << "double:" << sizeof(double) << " bytes\n"; + std::cout << std::setw(16) << "long double:" << sizeof(long double) << " bytes\n"; } \ No newline at end of file diff --git a/src/io.h b/src/io.h index ce5bab5..39c803b 100644 --- a/src/io.h +++ b/src/io.h @@ -1,5 +1,7 @@ #pragma once +void add_two_numbers(); int read_number(); void write_answer(int x); -void convert_char_to_ascii(); \ No newline at end of file +void convert_char_to_ascii(); +void print_type_size_bytes(); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index c0ebe3f..7d4fe6f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,25 +1,12 @@ #include // for std::cout -#include #include "io.h" + // Definition of function main() int main() { - - // int a{read_number()}; - // int b{read_number()}; - // write_answer(a + b); + // add_two_numbers(); // convert_char_to_ascii(); - - std::cout << std::left; // left justify output - std::cout << std::setw(16) << "bool:" << sizeof(bool) << " bytes\n"; - std::cout << std::setw(16) << "char:" << sizeof(char) << " bytes\n"; - std::cout << std::setw(16) << "short:" << sizeof(short) << " bytes\n"; - std::cout << std::setw(16) << "int:" << sizeof(int) << " bytes\n"; - std::cout << std::setw(16) << "long:" << sizeof(long) << " bytes\n"; - std::cout << std::setw(16) << "long long:" << sizeof(long long) << " bytes\n"; - std::cout << std::setw(16) << "float:" << sizeof(float) << " bytes\n"; - std::cout << std::setw(16) << "double:" << sizeof(double) << " bytes\n"; - std::cout << std::setw(16) << "long double:" << sizeof(long double) << " bytes\n"; + // print_type_size_bytes(); return 0; } \ No newline at end of file From 79644bad85429744f1462ac64c8aa46bc2d9822f Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 29 Jan 2024 16:46:20 +0100 Subject: [PATCH 10/20] update --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 7d4fe6f..40a6f62 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,7 @@ int main() { // add_two_numbers(); // convert_char_to_ascii(); - // print_type_size_bytes(); + print_type_size_bytes(); return 0; } \ No newline at end of file From 7f0548cd6906b127fcdd232e5a061751af7e87cb Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 5 Feb 2024 08:39:20 +0100 Subject: [PATCH 11/20] added Bubblesort --- src/io.cpp | 15 +++++++++++++++ src/io.h | 3 ++- src/main.cpp | 16 +++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/io.cpp b/src/io.cpp index 1da65ac..e123476 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -37,4 +37,19 @@ void print_type_size_bytes() std::cout << std::setw(16) << "float:" << sizeof(float) << " bytes\n"; std::cout << std::setw(16) << "double:" << sizeof(double) << " bytes\n"; std::cout << std::setw(16) << "long double:" << sizeof(long double) << " bytes\n"; +} +void bubble_sort(int *a) +{ + for (size_t i = 0; i < 7; i++) + { + for (size_t j = 0; j < 7 - 1 - i; j++) + { + if (a[j] > a[j + 1]) + { + int temp{a[j]}; + a[j] = a[j + 1]; + a[j + 1] = temp; + } + } + } } \ No newline at end of file diff --git a/src/io.h b/src/io.h index 39c803b..e5ae628 100644 --- a/src/io.h +++ b/src/io.h @@ -4,4 +4,5 @@ void add_two_numbers(); int read_number(); void write_answer(int x); void convert_char_to_ascii(); -void print_type_size_bytes(); \ No newline at end of file +void print_type_size_bytes(); +void bubble_sort(int *a); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 40a6f62..da47634 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,12 +1,26 @@ #include // for std::cout #include "io.h" +#define ARRAY_SIZE 7 + // Definition of function main() +void bubble_sort_demo() +{ + int demo[ARRAY_SIZE]{11, 14, 3, 18, 8, 17, 43}; + for (int i = 0; i < 7; i++) + std::cout << demo[i] << ", "; + std::cout << "\n"; + bubble_sort(demo); + for (int i = 0; i < ARRAY_SIZE; i++) + std::cout << demo[i] << ", "; +} int main() { // add_two_numbers(); // convert_char_to_ascii(); print_type_size_bytes(); + bubble_sort_demo(); + return 0; -} \ No newline at end of file +} From 5911856dc626a46567b1b38be202380e51fc5193 Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 5 Feb 2024 10:37:52 +0100 Subject: [PATCH 12/20] update --- src/main.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index da47634..73e863b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,7 +3,23 @@ #define ARRAY_SIZE 7 -// Definition of function main() +template +void BubbleSort_T(T *a) +{ + for (size_t i = 0; i < 7; i++) + { + for (size_t j = 0; j < 7 - 1 - i; j++) + { + if (a[j] > a[j + 1]) + { + T temp{a[j]}; + a[j] = a[j + 1]; + a[j + 1] = temp; + } + } + } +} + void bubble_sort_demo() { int demo[ARRAY_SIZE]{11, 14, 3, 18, 8, 17, 43}; @@ -14,13 +30,40 @@ void bubble_sort_demo() for (int i = 0; i < ARRAY_SIZE; i++) std::cout << demo[i] << ", "; } + +void bubble_sort_T_demo() +{ + int demo[ARRAY_SIZE]{11, 14, 3, 18, 8, 17, 43}; + double demo2[ARRAY_SIZE]{11.2, 14.3, 3.2, 18.6, 8.7, 17.9, 43.3}; + std::cout << "Demo: "; + for (int i = 0; i < 7; i++) + std::cout << demo[i] << ", "; + std::cout << "\n"; + std::cout << "Demo2: "; + + for (int i = 0; i < 7; i++) + std::cout << demo2[i] << ", "; + std::cout << "\n"; + + BubbleSort_T(demo); + BubbleSort_T(demo2); + std::cout << "Demo: "; + for (int i = 0; i < 7; i++) + std::cout << demo[i] << ", "; + std::cout << "\n"; + std::cout << "Demo2: "; + + for (int i = 0; i < 7; i++) + std::cout << demo2[i] << ", "; + std::cout << "\n"; +} int main() { // add_two_numbers(); // convert_char_to_ascii(); print_type_size_bytes(); - bubble_sort_demo(); + bubble_sort_T_demo(); return 0; } From 29ee27dbab4b40aa39b7f25dfb055ff326d268bf Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 5 Feb 2024 12:07:16 +0100 Subject: [PATCH 13/20] update --- src/io.h | 33 ++++++++++++++++++++++++++-- src/main.cpp | 61 ++++------------------------------------------------ 2 files changed, 35 insertions(+), 59 deletions(-) diff --git a/src/io.h b/src/io.h index e5ae628..16eba01 100644 --- a/src/io.h +++ b/src/io.h @@ -1,8 +1,37 @@ #pragma once - +#include // for std::cout void add_two_numbers(); int read_number(); void write_answer(int x); void convert_char_to_ascii(); void print_type_size_bytes(); -void bubble_sort(int *a); \ No newline at end of file + +template +void bubble_sort(T *a) +{ + for (int i = 0; i < sizeof(&a) / sizeof(a); i++) + { + for (int j = 0; j < 7 - 1 - i; j++) + { + if (a[j] > a[j + 1]) + { + T temp{a[j]}; + a[j] = a[j + 1]; + a[j + 1] = temp; + } + } + } +} +template +void bubble_sort_print(int size, T *a) +{ + std::cout << "unsorted Array: "; + for (int i = 0; i < size; i++) + std::cout << a[i] << ", "; + std::cout << "\n"; + bubble_sort(a); + std::cout << "sorted Array: "; + for (int i = 0; i < size; i++) + std::cout << a[i] << ", "; + std::cout << "\n"; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 73e863b..92dd2f4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,69 +1,16 @@ #include // for std::cout #include "io.h" -#define ARRAY_SIZE 7 - -template -void BubbleSort_T(T *a) -{ - for (size_t i = 0; i < 7; i++) - { - for (size_t j = 0; j < 7 - 1 - i; j++) - { - if (a[j] > a[j + 1]) - { - T temp{a[j]}; - a[j] = a[j + 1]; - a[j + 1] = temp; - } - } - } -} - -void bubble_sort_demo() -{ - int demo[ARRAY_SIZE]{11, 14, 3, 18, 8, 17, 43}; - for (int i = 0; i < 7; i++) - std::cout << demo[i] << ", "; - std::cout << "\n"; - bubble_sort(demo); - for (int i = 0; i < ARRAY_SIZE; i++) - std::cout << demo[i] << ", "; -} - -void bubble_sort_T_demo() -{ - int demo[ARRAY_SIZE]{11, 14, 3, 18, 8, 17, 43}; - double demo2[ARRAY_SIZE]{11.2, 14.3, 3.2, 18.6, 8.7, 17.9, 43.3}; - std::cout << "Demo: "; - for (int i = 0; i < 7; i++) - std::cout << demo[i] << ", "; - std::cout << "\n"; - std::cout << "Demo2: "; - - for (int i = 0; i < 7; i++) - std::cout << demo2[i] << ", "; - std::cout << "\n"; - - BubbleSort_T(demo); - BubbleSort_T(demo2); - std::cout << "Demo: "; - for (int i = 0; i < 7; i++) - std::cout << demo[i] << ", "; - std::cout << "\n"; - std::cout << "Demo2: "; - - for (int i = 0; i < 7; i++) - std::cout << demo2[i] << ", "; - std::cout << "\n"; -} int main() { + int demo[]{11, 14, 3, 18, 8, 17, 43, 6, 5, 4}; + double demo2[]{11.2, 14.3, 3.2, 18.6, 8.7, 17.9, 43.3}; // add_two_numbers(); // convert_char_to_ascii(); print_type_size_bytes(); - bubble_sort_T_demo(); + bubble_sort_print(sizeof(demo) / sizeof(demo[0]), demo); + bubble_sort_print(sizeof(demo2) / sizeof(demo2[0]), demo2); return 0; } From 3f5945ca8c3a4cd7f4bb1e08d40dca1503fd0fa8 Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 5 Feb 2024 12:24:53 +0100 Subject: [PATCH 14/20] update --- src/io.h | 8 ++++---- src/main.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/io.h b/src/io.h index 16eba01..2ac5eb8 100644 --- a/src/io.h +++ b/src/io.h @@ -7,11 +7,11 @@ void convert_char_to_ascii(); void print_type_size_bytes(); template -void bubble_sort(T *a) +void bubble_sort(int size, T *a) { - for (int i = 0; i < sizeof(&a) / sizeof(a); i++) + for (int i = 0; i < size; i++) { - for (int j = 0; j < 7 - 1 - i; j++) + for (int j = 0; j < size - 1 - i; j++) { if (a[j] > a[j + 1]) { @@ -29,7 +29,7 @@ void bubble_sort_print(int size, T *a) for (int i = 0; i < size; i++) std::cout << a[i] << ", "; std::cout << "\n"; - bubble_sort(a); + bubble_sort(size, a); std::cout << "sorted Array: "; for (int i = 0; i < size; i++) std::cout << a[i] << ", "; diff --git a/src/main.cpp b/src/main.cpp index 92dd2f4..9c84a8e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,7 +4,7 @@ int main() { int demo[]{11, 14, 3, 18, 8, 17, 43, 6, 5, 4}; - double demo2[]{11.2, 14.3, 3.2, 18.6, 8.7, 17.9, 43.3}; + double demo2[]{11.2, 14.3, 3.2, 18.6, 8.7, 17.9, 43.3, 12.3}; // add_two_numbers(); // convert_char_to_ascii(); print_type_size_bytes(); From 921ca197bf855d17dc2df2faca7f62fb1701b573 Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 5 Feb 2024 12:38:25 +0100 Subject: [PATCH 15/20] Updated --- src/io.h | 23 +++++++++++++++++++++-- src/main.cpp | 2 ++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/io.h b/src/io.h index 2ac5eb8..ebe4d8d 100644 --- a/src/io.h +++ b/src/io.h @@ -6,6 +6,24 @@ void write_answer(int x); void convert_char_to_ascii(); void print_type_size_bytes(); +#include +template +struct TypeName +{ + static const char *Get() + { + return typeid(T).name(); + } +}; +template <> +struct TypeName +{ + static const char *Get() + { + return "s"; + } +}; + template void bubble_sort(int size, T *a) { @@ -25,12 +43,13 @@ void bubble_sort(int size, T *a) template void bubble_sort_print(int size, T *a) { - std::cout << "unsorted Array: "; + + std::cout << "unsorted " << TypeName::Get() << " Array: "; for (int i = 0; i < size; i++) std::cout << a[i] << ", "; std::cout << "\n"; bubble_sort(size, a); - std::cout << "sorted Array: "; + std::cout << "sorted " << TypeName::Get() << " Array: "; for (int i = 0; i < size; i++) std::cout << a[i] << ", "; std::cout << "\n"; diff --git a/src/main.cpp b/src/main.cpp index 9c84a8e..74fc882 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,12 +5,14 @@ int main() { int demo[]{11, 14, 3, 18, 8, 17, 43, 6, 5, 4}; double demo2[]{11.2, 14.3, 3.2, 18.6, 8.7, 17.9, 43.3, 12.3}; + std::string demo3[]{"hallo", "welo", "kekw", "imagin"}; // add_two_numbers(); // convert_char_to_ascii(); print_type_size_bytes(); bubble_sort_print(sizeof(demo) / sizeof(demo[0]), demo); bubble_sort_print(sizeof(demo2) / sizeof(demo2[0]), demo2); + bubble_sort_print(sizeof(demo3) / sizeof(demo3[0]), demo3); return 0; } From c50ef8bfe3337a0c91bff1a9ea8d915475c20824 Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Mon, 5 Feb 2024 12:42:03 +0100 Subject: [PATCH 16/20] update --- src/io.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/io.h b/src/io.h index ebe4d8d..3556351 100644 --- a/src/io.h +++ b/src/io.h @@ -1,12 +1,13 @@ #pragma once -#include // for std::cout +#include +#include + void add_two_numbers(); int read_number(); void write_answer(int x); void convert_char_to_ascii(); void print_type_size_bytes(); -#include template struct TypeName { @@ -39,7 +40,8 @@ void bubble_sort(int size, T *a) } } } -} +}; + template void bubble_sort_print(int size, T *a) { @@ -53,4 +55,4 @@ void bubble_sort_print(int size, T *a) for (int i = 0; i < size; i++) std::cout << a[i] << ", "; std::cout << "\n"; -} \ No newline at end of file +}; \ No newline at end of file From 69b4f6ecf8ed159f070d701b783d9ba51d748e02 Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Tue, 6 Feb 2024 07:18:11 +0100 Subject: [PATCH 17/20] update --- src/io.cpp | 23 +++++++++-------------- src/io.h | 10 ++++++---- src/main.cpp | 8 +------- 3 files changed, 16 insertions(+), 25 deletions(-) diff --git a/src/io.cpp b/src/io.cpp index e123476..e912c59 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -25,6 +25,7 @@ void convert_char_to_ascii() std::cin >> c; std::cout << "You entered '" << c << "', which hass ASCII code " << static_cast(c) << "."; } + void print_type_size_bytes() { std::cout << std::left; // left justify output @@ -36,20 +37,14 @@ void print_type_size_bytes() std::cout << std::setw(16) << "long long:" << sizeof(long long) << " bytes\n"; std::cout << std::setw(16) << "float:" << sizeof(float) << " bytes\n"; std::cout << std::setw(16) << "double:" << sizeof(double) << " bytes\n"; - std::cout << std::setw(16) << "long double:" << sizeof(long double) << " bytes\n"; + std::cout << std::setw(16) << "long double:" << sizeof(long double) << " bytes\n\n"; } -void bubble_sort(int *a) +void bubble_sort_print_demo() { - for (size_t i = 0; i < 7; i++) - { - for (size_t j = 0; j < 7 - 1 - i; j++) - { - if (a[j] > a[j + 1]) - { - int temp{a[j]}; - a[j] = a[j + 1]; - a[j + 1] = temp; - } - } - } + int demo[]{11, 14, 3, 18, 8, 17, 43, 6, 5, 4}; + double demo2[]{11.2, 14.3, 3.2, 18.6, 8.7, 17.9, 43.3, 12.3}; + std::string demo3[]{"hallo", "velo", "kekw", "imagin"}; + bubble_sort_print(sizeof(demo) / sizeof(demo[0]), demo); + bubble_sort_print(sizeof(demo2) / sizeof(demo2[0]), demo2); + bubble_sort_print(sizeof(demo3) / sizeof(demo3[0]), demo3); } \ No newline at end of file diff --git a/src/io.h b/src/io.h index 3556351..2a07d3a 100644 --- a/src/io.h +++ b/src/io.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include void add_two_numbers(); @@ -7,6 +8,7 @@ int read_number(); void write_answer(int x); void convert_char_to_ascii(); void print_type_size_bytes(); +void bubble_sort_print_demo(); template struct TypeName @@ -45,14 +47,14 @@ void bubble_sort(int size, T *a) template void bubble_sort_print(int size, T *a) { - - std::cout << "unsorted " << TypeName::Get() << " Array: "; + std::cout << std::left; // left justify output + std::cout << "unsorted " << TypeName::Get() << std::setw(10) << " Array: "; for (int i = 0; i < size; i++) std::cout << a[i] << ", "; std::cout << "\n"; bubble_sort(size, a); - std::cout << "sorted " << TypeName::Get() << " Array: "; + std::cout << "sorted " << TypeName::Get() << std::setw(12) << " Array: "; for (int i = 0; i < size; i++) std::cout << a[i] << ", "; - std::cout << "\n"; + std::cout << "\n\n"; }; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 74fc882..2f3e99c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,16 +3,10 @@ int main() { - int demo[]{11, 14, 3, 18, 8, 17, 43, 6, 5, 4}; - double demo2[]{11.2, 14.3, 3.2, 18.6, 8.7, 17.9, 43.3, 12.3}; - std::string demo3[]{"hallo", "welo", "kekw", "imagin"}; // add_two_numbers(); // convert_char_to_ascii(); print_type_size_bytes(); - - bubble_sort_print(sizeof(demo) / sizeof(demo[0]), demo); - bubble_sort_print(sizeof(demo2) / sizeof(demo2[0]), demo2); - bubble_sort_print(sizeof(demo3) / sizeof(demo3[0]), demo3); + bubble_sort_print_demo(); return 0; } From 6ecbab2b643b233d94b8010451b76199366f426b Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Thu, 8 Feb 2024 09:58:54 +0100 Subject: [PATCH 18/20] update --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 2f3e99c..c5e92d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,7 @@ int main() // add_two_numbers(); // convert_char_to_ascii(); print_type_size_bytes(); - bubble_sort_print_demo(); + // bubble_sort_print_demo(); return 0; } From 6a3935cac25ab952bbed881bccb582529888a47a Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Tue, 5 Mar 2024 09:58:45 +0100 Subject: [PATCH 19/20] update 05.03.24 --- src/algo.cpp | 11 +++++++++++ src/algo.h | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/io.cpp | 10 +--------- src/io.h | 53 -------------------------------------------------- src/main.cpp | 1 + 5 files changed, 68 insertions(+), 62 deletions(-) create mode 100644 src/algo.cpp create mode 100644 src/algo.h diff --git a/src/algo.cpp b/src/algo.cpp new file mode 100644 index 0000000..f13f6b4 --- /dev/null +++ b/src/algo.cpp @@ -0,0 +1,11 @@ +#include "algo.h" + +void bubble_sort_print_demo() +{ + int demo[]{11, 14, 3, 18, 8, 17, 43, 6, 5, 4}; + double demo2[]{11.2, 14.3, 3.2, 18.6, 8.7, 17.9, 43.3, 12.3}; + std::string demo3[]{"hallo", "velo", "kekw", "imagin"}; + bubble_sort_print(sizeof(demo) / sizeof(demo[0]), demo); + bubble_sort_print(sizeof(demo2) / sizeof(demo2[0]), demo2); + bubble_sort_print(sizeof(demo3) / sizeof(demo3[0]), demo3); +} \ No newline at end of file diff --git a/src/algo.h b/src/algo.h new file mode 100644 index 0000000..52bc41f --- /dev/null +++ b/src/algo.h @@ -0,0 +1,55 @@ +#pragma once +#include +#include +#include + +void bubble_sort_print_demo(); + +template +struct TypeName +{ + static const char *Get() + { + return typeid(T).name(); + } +}; +template <> +struct TypeName +{ + static const char *Get() + { + return "s"; + } +}; + +template +void bubble_sort(int size, T *a) +{ + for (int i = 0; i < size; i++) + { + for (int j = 0; j < size - 1 - i; j++) + { + if (a[j] > a[j + 1]) + { + T temp{a[j]}; + a[j] = a[j + 1]; + a[j + 1] = temp; + } + } + } +}; + +template +void bubble_sort_print(int size, T *a) +{ + std::cout << std::left; // left justify output + std::cout << "unsorted " << TypeName::Get() << std::setw(10) << " Array: "; + for (int i = 0; i < size; i++) + std::cout << a[i] << ", "; + std::cout << "\n"; + bubble_sort(size, a); + std::cout << "sorted " << TypeName::Get() << std::setw(12) << " Array: "; + for (int i = 0; i < size; i++) + std::cout << a[i] << ", "; + std::cout << "\n\n"; +}; \ No newline at end of file diff --git a/src/io.cpp b/src/io.cpp index e912c59..90f2791 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -1,6 +1,7 @@ #include "io.h" #include #include + void add_two_numbers() { int a{read_number()}; @@ -39,12 +40,3 @@ void print_type_size_bytes() std::cout << std::setw(16) << "double:" << sizeof(double) << " bytes\n"; std::cout << std::setw(16) << "long double:" << sizeof(long double) << " bytes\n\n"; } -void bubble_sort_print_demo() -{ - int demo[]{11, 14, 3, 18, 8, 17, 43, 6, 5, 4}; - double demo2[]{11.2, 14.3, 3.2, 18.6, 8.7, 17.9, 43.3, 12.3}; - std::string demo3[]{"hallo", "velo", "kekw", "imagin"}; - bubble_sort_print(sizeof(demo) / sizeof(demo[0]), demo); - bubble_sort_print(sizeof(demo2) / sizeof(demo2[0]), demo2); - bubble_sort_print(sizeof(demo3) / sizeof(demo3[0]), demo3); -} \ No newline at end of file diff --git a/src/io.h b/src/io.h index 2a07d3a..ecdefe3 100644 --- a/src/io.h +++ b/src/io.h @@ -1,60 +1,7 @@ #pragma once -#include -#include -#include void add_two_numbers(); int read_number(); void write_answer(int x); void convert_char_to_ascii(); void print_type_size_bytes(); -void bubble_sort_print_demo(); - -template -struct TypeName -{ - static const char *Get() - { - return typeid(T).name(); - } -}; -template <> -struct TypeName -{ - static const char *Get() - { - return "s"; - } -}; - -template -void bubble_sort(int size, T *a) -{ - for (int i = 0; i < size; i++) - { - for (int j = 0; j < size - 1 - i; j++) - { - if (a[j] > a[j + 1]) - { - T temp{a[j]}; - a[j] = a[j + 1]; - a[j + 1] = temp; - } - } - } -}; - -template -void bubble_sort_print(int size, T *a) -{ - std::cout << std::left; // left justify output - std::cout << "unsorted " << TypeName::Get() << std::setw(10) << " Array: "; - for (int i = 0; i < size; i++) - std::cout << a[i] << ", "; - std::cout << "\n"; - bubble_sort(size, a); - std::cout << "sorted " << TypeName::Get() << std::setw(12) << " Array: "; - for (int i = 0; i < size; i++) - std::cout << a[i] << ", "; - std::cout << "\n\n"; -}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index c5e92d2..0a793a6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include // for std::cout #include "io.h" +#include "algo.h" int main() { From 4a29e375f5d96d47aa9e1249bb3a4c348aa1a6e3 Mon Sep 17 00:00:00 2001 From: ZennDev1337 Date: Thu, 11 Apr 2024 13:58:59 +0200 Subject: [PATCH 20/20] first commit --- src/io.cpp | 12 ++++++++++++ src/io.h | 1 + src/main.cpp | 1 + 3 files changed, 14 insertions(+) diff --git a/src/io.cpp b/src/io.cpp index 90f2791..c8a8734 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -40,3 +40,15 @@ void print_type_size_bytes() std::cout << std::setw(16) << "double:" << sizeof(double) << " bytes\n"; std::cout << std::setw(16) << "long double:" << sizeof(long double) << " bytes\n\n"; } +void string_demo() +{ + using namespace std; + cout << "Enter your full name: "; + string name{}; + getline(cin >> ws, name); + cout << "Enter your age: "; + int age{}; + cin >> age; + int letters{static_cast(name.length())}; + cout << "Your age + length of name is: " << (letters + age) << "\n"; +} \ No newline at end of file diff --git a/src/io.h b/src/io.h index ecdefe3..74cc367 100644 --- a/src/io.h +++ b/src/io.h @@ -5,3 +5,4 @@ int read_number(); void write_answer(int x); void convert_char_to_ascii(); void print_type_size_bytes(); +void string_demo(); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 0a793a6..b0c8dde 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ int main() { + // string_demo(); // add_two_numbers(); // convert_char_to_ascii(); print_type_size_bytes();