Consolix
Loading...
Searching...
No Matches
MultiStream.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef _CONSOLIX_MULTI_STREAM_HPP_INCLUDED
3#define _CONSOLIX_MULTI_STREAM_HPP_INCLUDED
4
12
14#include "../../utils/enums.hpp"
16
17#include <iostream>
18#include <sstream>
19#include <string>
20
21namespace consolix {
22
33 public:
34
35#if CONSOLIX_USE_LOGIT == 1
38 : m_level(logit::LogLevel::LOG_LVL_TRACE), m_file(__FILE__),
39 m_line(__LINE__),
40 m_function(logit::make_relative(__FILE__, LOGIT_BASE_PATH)) {
41 }
42
49 logit::LogLevel level,
50 const std::string& file,
51 int line,
52 const std::string& function)
53 : m_level(level), m_file(file), m_line(line), m_function(function) {
54 }
55
56# else
57
60 MultiStream(bool use_utf8 = true) : m_use_utf8(use_utf8) {};
61
62# endif
63
66# if defined(_WIN32)
67# if CONSOLIX_USE_LOGIT == 1
68 auto str = utf8_to_cp866(m_stream.str());
69# else
70 auto str = m_use_utf8 ? utf8_to_cp866(m_stream.str()) : m_stream.str();
71# endif // if CONSOLIX_USE_LOGIT == 1
72# else
73 auto str = m_stream.str();
74# endif // if defined(_WIN32)
75
76# if CONSOLIX_USE_LOGIT == 1
77 if (LOGIT_IS_SINGLE_MODE(CONSOLIX_LOGIT_CONSOLE_INDEX)) {
78 LOGIT_STREAM_TRACE_TO(CONSOLIX_LOGIT_CONSOLE_INDEX) << str;
79 }
80 logit::LogStream(m_level, m_file, m_line, m_function, CONSOLIX_LOGIT_LOGGER_INDEX) << str;
81# else
82
83# if defined(_WIN32)
84 handle_ansi_colors_windows(str);
85# else
87# endif // if defined(_WIN32)
88
89# endif // if CONSOLIX_USE_LOGIT == 1
90 }
91
96 template <typename T>
97 MultiStream& operator<<(const T& value) {
98 m_stream << value;
99 return *this;
100 }
101
105 MultiStream& operator<<(std::ostream& (*manip)(std::ostream&)) {
106 m_stream << manip;
107 return *this;
108 }
109
110 private:
111 std::ostringstream m_stream;
112
113#if CONSOLIX_USE_LOGIT == 1
114 logit::LogLevel m_level;
115 std::string m_file;
116 int m_line;
117 std::string m_function;
118# else
120# endif
121
124 void flush_to_console(const std::string& message) const {
125 if (!message.empty()) {
126 if (message.back() == '\n') {
127 std::cout << message;
128 } else {
129 std::cout << message << std::endl;
130 }
131 }
132 }
133
134# if CONSOLIX_USE_LOGIT == 0 && defined(_WIN32)
135
138 void handle_ansi_colors_windows(const std::string& message) const {
139 std::string::size_type start = 0;
140 std::string::size_type pos = 0;
141
142 HANDLE handle_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
143
144 while ((pos = message.find("\033[", start)) != std::string::npos) {
145 // Output the part of the string before the ANSI code
146 if (pos > start) {
147 std::cout << message.substr(start, pos - start);
148 }
149
150 // Find the end of the ANSI code
151 std::string::size_type end_pos = message.find('m', pos);
152 if (end_pos != std::string::npos) {
153 // Extract the ANSI code
154 std::string ansi_code = message.substr(pos + 2, end_pos - pos - 2);
155 apply_color_from_ansi_code(ansi_code, handle_stdout);
156
157 // Update position
158 start = end_pos + 1;
159 } else {
160 break;
161 }
162 }
163
164 // Output any remaining part of the message
165 if (start < message.size()) {
166 std::cout << message.substr(start);
167 }
168 if (!message.empty()) std::cout << std::endl;
169
170 // Reset the console color to default
171 SetConsoleTextAttribute(handle_stdout, to_windows_color(CONSOLIX_DEFAULT_COLOR));
172 }
173
177 void apply_color_from_ansi_code(const std::string& ansi_code, HANDLE handle_stdout) const {
178 WORD color_value = to_windows_color(CONSOLIX_DEFAULT_COLOR); // Default color
179 const int code = std::stoi(ansi_code);
180 switch (code) {
181 case 30: color_value = to_windows_color(TextColor::Black); break;
182 case 31: color_value = to_windows_color(TextColor::DarkRed); break;
183 case 32: color_value = to_windows_color(TextColor::DarkGreen); break;
184 case 33: color_value = to_windows_color(TextColor::DarkYellow); break;
185 case 34: color_value = to_windows_color(TextColor::DarkBlue); break;
186 case 35: color_value = to_windows_color(TextColor::DarkMagenta); break;
187 case 36: color_value = to_windows_color(TextColor::DarkCyan); break;
188 case 37: color_value = to_windows_color(TextColor::LightGray); break;
189 case 90: color_value = to_windows_color(TextColor::DarkGray); break;
190 case 91: color_value = to_windows_color(TextColor::Red); break;
191 case 92: color_value = to_windows_color(TextColor::Green); break;
192 case 93: color_value = to_windows_color(TextColor::Yellow); break;
193 case 94: color_value = to_windows_color(TextColor::Blue); break;
194 case 95: color_value = to_windows_color(TextColor::Magenta); break;
195 case 96: color_value = to_windows_color(TextColor::Cyan); break;
196 case 97: color_value = to_windows_color(TextColor::White); break;
197 default:
198 // Unknown code, use default color
199 break;
200 };
201 // Set the console text attribute to the desired color
202 SetConsoleTextAttribute(handle_stdout, color_value);
203 }
204
205# endif
206
207 }; // MultiStream
208
209}; // namespace consolix
210
211#endif // _CONSOLIX_MULTI_STREAM_HPP_INCLUDED
MultiStream & operator<<(const T &value)
Overloaded operator<< for adding content to the stream.
bool m_use_utf8
Flag indicating whether UTF-8 encoding should be used.
MultiStream & operator<<(std::ostream &(*manip)(std::ostream &))
Overloaded operator<< for manipulators (e.g., std::endl).
~MultiStream()
Destructor to flush the accumulated log content.
MultiStream(bool use_utf8=true)
Default constructor for MultiStream without LogIt integration.
std::ostringstream m_stream
Internal stream for accumulating log content.
void flush_to_console(const std::string &message) const
Flush the accumulated message to the console on non-Windows platforms.
Configuration macros for the Consolix framework.
#define CONSOLIX_DEFAULT_COLOR
Default text color for console output.
Utilities for working with character encodings and string transformations.
Contains enumerations and utility functions for text colors.
< Utility modules and helpers.