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 <initializer_list>
14#include <iostream>
15#include <sstream>
16#include <string>
17#include <vector>
18
19namespace consolix {
20
31 public:
32
33#if CONSOLIX_USE_LOGIT == 1
36 : m_level(logit::LogLevel::LOG_LVL_TRACE),
37 m_file(__FILE__),
38 m_line(__LINE__),
39 m_function(logit::make_relative(__FILE__, LOGIT_BASE_PATH)) {
40 }
41
48 logit::LogLevel level,
49 const std::string& file,
50 int line,
51 const std::string& function)
52 : m_level(level), m_file(file), m_line(line), m_function(function) {
53 }
54
64 logit::LogLevel level,
65 const std::string& file,
66 int line,
67 const std::string& function,
68 std::initializer_list<int> logger_indices)
69 : m_level(level),
70 m_file(file),
71 m_line(line),
72 m_function(function),
73 m_logger_indices(logger_indices) {
74 }
75
76# else
77
80 MultiStream(bool use_utf8 = true) : m_use_utf8(use_utf8) {};
81
82# endif
83
86# if defined(_WIN32)
87# if CONSOLIX_USE_LOGIT == 1
88 auto str = utf8_to_cp866(m_stream.str());
89# else
90 auto str = m_use_utf8 ? utf8_to_cp866(m_stream.str()) : m_stream.str();
91# endif // if CONSOLIX_USE_LOGIT == 1
92# else
93 auto str = m_stream.str();
94# endif // if defined(_WIN32)
95
96# if CONSOLIX_USE_LOGIT == 1
97 if (LOGIT_IS_SINGLE_MODE(CONSOLIX_LOGIT_CONSOLE_INDEX)) {
98 logit::LogStream(m_level, m_file, m_line, m_function, CONSOLIX_LOGIT_CONSOLE_INDEX) << str;
99 }
100 logit::LogStream(m_level, m_file, m_line, m_function, CONSOLIX_LOGIT_LOGGER_INDEX) << str;
101 for (int logger_index : m_logger_indices) {
102 logit::LogStream(m_level, m_file, m_line, m_function, logger_index) << str;
103 }
104# else
105
106# if defined(_WIN32)
107 handle_ansi_colors_windows(str);
108# else
109 flush_to_console(str);
110# endif // if defined(_WIN32)
111
112# endif // if CONSOLIX_USE_LOGIT == 1
113 }
114
119 template <typename T>
120 MultiStream& operator<<(const T& value) {
121 m_stream << value;
122 return *this;
123 }
124
128 MultiStream& operator<<(std::ostream& (*manip)(std::ostream&)) {
129 m_stream << manip;
130 return *this;
131 }
132
133 private:
134 std::ostringstream m_stream;
135
136#if CONSOLIX_USE_LOGIT == 1
137 logit::LogLevel m_level;
138 std::string m_file;
139 int m_line;
140 std::string m_function;
141 std::vector<int> m_logger_indices;
142# else
144# endif
145
148 void flush_to_console(const std::string& message) const {
149 if (!message.empty()) {
150 if (message.back() == '\n') {
151 std::cout << message;
152 } else {
153 std::cout << message << std::endl;
154 }
155 }
156 }
157
158# if CONSOLIX_USE_LOGIT == 0 && defined(_WIN32)
159
162 void handle_ansi_colors_windows(const std::string& message) const {
163 std::string::size_type start = 0;
164 std::string::size_type pos = 0;
165
166 HANDLE handle_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
167
168 while ((pos = message.find("\033[", start)) != std::string::npos) {
169 // Output the part of the string before the ANSI code
170 if (pos > start) {
171 std::cout << message.substr(start, pos - start);
172 }
173
174 // Find the end of the ANSI code
175 std::string::size_type end_pos = message.find('m', pos);
176 if (end_pos != std::string::npos) {
177 // Extract the ANSI code
178 std::string ansi_code = message.substr(pos + 2, end_pos - pos - 2);
179 apply_color_from_ansi_code(ansi_code, handle_stdout);
180
181 // Update position
182 start = end_pos + 1;
183 } else {
184 break;
185 }
186 }
187
188 // Output any remaining part of the message
189 if (start < message.size()) {
190 std::cout << message.substr(start);
191 }
192 if (!message.empty()) std::cout << std::endl;
193
194 // Reset the console color to default
195 SetConsoleTextAttribute(handle_stdout, to_windows_color(CONSOLIX_DEFAULT_COLOR));
196 }
197
201 void apply_color_from_ansi_code(const std::string& ansi_code, HANDLE handle_stdout) const {
202 WORD color_value = to_windows_color(CONSOLIX_DEFAULT_COLOR); // Default color
203 const int code = std::stoi(ansi_code);
204 switch (code) {
205 case 30: color_value = to_windows_color(TextColor::Black); break;
206 case 31: color_value = to_windows_color(TextColor::DarkRed); break;
207 case 32: color_value = to_windows_color(TextColor::DarkGreen); break;
208 case 33: color_value = to_windows_color(TextColor::DarkYellow); break;
209 case 34: color_value = to_windows_color(TextColor::DarkBlue); break;
210 case 35: color_value = to_windows_color(TextColor::DarkMagenta); break;
211 case 36: color_value = to_windows_color(TextColor::DarkCyan); break;
212 case 37: color_value = to_windows_color(TextColor::LightGray); break;
213 case 90: color_value = to_windows_color(TextColor::DarkGray); break;
214 case 91: color_value = to_windows_color(TextColor::Red); break;
215 case 92: color_value = to_windows_color(TextColor::Green); break;
216 case 93: color_value = to_windows_color(TextColor::Yellow); break;
217 case 94: color_value = to_windows_color(TextColor::Blue); break;
218 case 95: color_value = to_windows_color(TextColor::Magenta); break;
219 case 96: color_value = to_windows_color(TextColor::Cyan); break;
220 case 97: color_value = to_windows_color(TextColor::White); break;
221 default:
222 // Unknown code, use default color
223 break;
224 };
225 // Set the console text attribute to the desired color
226 SetConsoleTextAttribute(handle_stdout, color_value);
227 }
228
229# endif
230
231 }; // MultiStream
232
233}; // namespace consolix
234
235#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.