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
13#include <sstream>
14
15namespace consolix {
16
27 public:
28
29#if CONSOLIX_USE_LOGIT == 1
32 : m_level(logit::LogLevel::LOG_LVL_TRACE), m_file(__FILE__),
33 m_line(__LINE__),
34 m_function(logit::make_relative(__FILE__, LOGIT_BASE_PATH)) {
35 }
36
43 logit::LogLevel level,
44 const std::string& file,
45 int line,
46 const std::string& function)
47 : m_level(level), m_file(file), m_line(line), m_function(function) {
48 }
49
50# else
51
54 MultiStream(bool use_utf8 = true) : m_use_utf8(use_utf8) {};
55
56# endif
57
60# if CONSOLIX_USE_LOGIT == 1
61 auto str = utf8_to_cp866(m_stream.str());
62# else
63# if defined(_WIN32)
64 auto str = m_use_utf8 ? utf8_to_cp866(m_stream.str()) : m_stream.str();
65# else
66 auto str = m_stream.str();
67# endif // if defined(_WIN32)
68# endif // if CONSOLIX_USE_LOGIT == 1
69
70# if CONSOLIX_USE_LOGIT == 1
71 if (LOGIT_IS_SINGLE_MODE(CONSOLIX_LOGIT_CONSOLE_INDEX)) {
72 LOGIT_STREAM_TRACE_TO(CONSOLIX_LOGIT_CONSOLE_INDEX) << str;
73 }
74 logit::LogStream(m_level, m_file, m_line, m_function, CONSOLIX_LOGIT_LOGGER_INDEX) << str;
75# else
76
77# if defined(_WIN32)
78 handle_ansi_colors_windows(str);
79# else
81# endif // if defined(_WIN32)
82
83# endif // if CONSOLIX_USE_LOGIT == 1
84 }
85
90 template <typename T>
91 MultiStream& operator<<(const T& value) {
92 m_stream << value;
93 return *this;
94 }
95
99 MultiStream& operator<<(std::ostream& (*manip)(std::ostream&)) {
100 m_stream << manip;
101 return *this;
102 }
103
104 private:
105 std::ostringstream m_stream;
106
107#if CONSOLIX_USE_LOGIT == 1
108 logit::LogLevel m_level;
109 std::string m_file;
110 int m_line;
111 std::string m_function;
112# else
114# endif
115
118 void flush_to_console(const std::string& message) const {
119 if (!message.empty()) {
120 if (message.back() == '\n') {
121 std::cout << message;
122 } else {
123 std::cout << message << std::endl;
124 }
125 }
126 }
127
128# if CONSOLIX_USE_LOGIT == 0 && defined(_WIN32)
129
132 void handle_ansi_colors_windows(const std::string& message) const {
133 std::string::size_type start = 0;
134 std::string::size_type pos = 0;
135
136 HANDLE handle_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
137
138 while ((pos = message.find("\033[", start)) != std::string::npos) {
139 // Output the part of the string before the ANSI code
140 if (pos > start) {
141 std::cout << message.substr(start, pos - start);
142 }
143
144 // Find the end of the ANSI code
145 std::string::size_type end_pos = message.find('m', pos);
146 if (end_pos != std::string::npos) {
147 // Extract the ANSI code
148 std::string ansi_code = message.substr(pos + 2, end_pos - pos - 2);
149 apply_color_from_ansi_code(ansi_code, handle_stdout);
150
151 // Update position
152 start = end_pos + 1;
153 } else {
154 break;
155 }
156 }
157
158 // Output any remaining part of the message
159 if (start < message.size()) {
160 std::cout << message.substr(start);
161 }
162 if (!message.empty()) std::cout << std::endl;
163
164 // Reset the console color to default
165 SetConsoleTextAttribute(handle_stdout, to_windows_color(CONSOLIX_DEFAULT_COLOR));
166 }
167
171 void apply_color_from_ansi_code(const std::string& ansi_code, HANDLE handle_stdout) const {
172 WORD color_value = to_windows_color(CONSOLIX_DEFAULT_COLOR); // Default color
173 const int code = std::stoi(ansi_code);
174 switch (code) {
175 case 30: color_value = to_windows_color(TextColor::Black); break;
176 case 31: color_value = to_windows_color(TextColor::DarkRed); break;
177 case 32: color_value = to_windows_color(TextColor::DarkGreen); break;
178 case 33: color_value = to_windows_color(TextColor::DarkYellow); break;
179 case 34: color_value = to_windows_color(TextColor::DarkBlue); break;
180 case 35: color_value = to_windows_color(TextColor::DarkMagenta); break;
181 case 36: color_value = to_windows_color(TextColor::DarkCyan); break;
182 case 37: color_value = to_windows_color(TextColor::LightGray); break;
183 case 90: color_value = to_windows_color(TextColor::DarkGray); break;
184 case 91: color_value = to_windows_color(TextColor::Red); break;
185 case 92: color_value = to_windows_color(TextColor::Green); break;
186 case 93: color_value = to_windows_color(TextColor::Yellow); break;
187 case 94: color_value = to_windows_color(TextColor::Blue); break;
188 case 95: color_value = to_windows_color(TextColor::Magenta); break;
189 case 96: color_value = to_windows_color(TextColor::Cyan); break;
190 case 97: color_value = to_windows_color(TextColor::White); break;
191 default:
192 // Unknown code, use default color
193 break;
194 };
195 // Set the console text attribute to the desired color
196 SetConsoleTextAttribute(handle_stdout, color_value);
197 }
198
199# endif
200
201 }; // MultiStream
202
203}; // namespace consolix
204
205#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.
#define CONSOLIX_DEFAULT_COLOR
Default text color for console output.
< Utility modules and helpers.