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# else
50
52 MultiStream() = default;
53
54# endif
55
58# if defined(_WIN32) || defined(_WIN64)
59 auto str = utf8_to_cp866(m_stream.str());
60# else
61 auto str = m_stream.str();
62# endif // if defined(_WIN32) || defined(_WIN64)
63
64# if CONSOLIX_USE_LOGIT == 1
65 if (LOGIT_IS_SINGLE_MODE(CONSOLIX_LOGIT_CONSOLE_INDEX)) {
66 LOGIT_STREAM_TRACE_TO(CONSOLIX_LOGIT_CONSOLE_INDEX) << str;
67 }
68 logit::LogStream(m_level, m_file, m_line, m_function, CONSOLIX_LOGIT_LOGGER_INDEX) << str;
69# else
70
71# if defined(_WIN32) || defined(_WIN64)
72 handle_ansi_colors_windows(str);
73# else
75# endif // if defined(_WIN32) || defined(_WIN64)
76
77# endif // if CONSOLIX_USE_LOGIT == 1
78 }
79
84 template <typename T>
85 MultiStream& operator<<(const T& value) {
86 m_stream << value;
87 return *this;
88 }
89
93 MultiStream& operator<<(std::ostream& (*manip)(std::ostream&)) {
94 m_stream << manip;
95 return *this;
96 }
97
98 private:
99 std::ostringstream m_stream;
100
101#if CONSOLIX_USE_LOGIT == 1
102 logit::LogLevel m_level;
103 std::string m_file;
104 int m_line;
105 std::string m_function;
106# endif
107
110 void flush_to_console(const std::string& message) const {
111 if (!message.empty()) {
112 if (message.back() == '\n') {
113 std::cout << message;
114 } else {
115 std::cout << message << std::endl;
116 }
117 }
118 }
119
120# if CONSOLIX_USE_LOGIT == 0 && (defined(_WIN32) || defined(_WIN64))
121
124 void handle_ansi_colors_windows(const std::string& message) const {
125 std::string::size_type start = 0;
126 std::string::size_type pos = 0;
127
128 HANDLE handle_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
129
130 while ((pos = message.find("\033[", start)) != std::string::npos) {
131 // Output the part of the string before the ANSI code
132 if (pos > start) {
133 std::cout << message.substr(start, pos - start);
134 }
135
136 // Find the end of the ANSI code
137 std::string::size_type end_pos = message.find('m', pos);
138 if (end_pos != std::string::npos) {
139 // Extract the ANSI code
140 std::string ansi_code = message.substr(pos + 2, end_pos - pos - 2);
141 apply_color_from_ansi_code(ansi_code, handle_stdout);
142
143 // Update position
144 start = end_pos + 1;
145 } else {
146 break;
147 }
148 }
149
150 // Output any remaining part of the message
151 if (start < message.size()) {
152 std::cout << message.substr(start);
153 }
154 if (!message.empty()) std::cout << std::endl;
155
156 // Reset the console color to default
157 SetConsoleTextAttribute(handle_stdout, to_windows_color(CONSOLIX_DEFAULT_COLOR));
158 }
159
163 void apply_color_from_ansi_code(const std::string& ansi_code, HANDLE handle_stdout) const {
164 WORD color_value = to_windows_color(CONSOLIX_DEFAULT_COLOR); // Default color
165 const int code = std::stoi(ansi_code);
166 switch (code) {
167 case 30: color_value = to_windows_color(TextColor::Black); break;
168 case 31: color_value = to_windows_color(TextColor::DarkRed); break;
169 case 32: color_value = to_windows_color(TextColor::DarkGreen); break;
170 case 33: color_value = to_windows_color(TextColor::DarkYellow); break;
171 case 34: color_value = to_windows_color(TextColor::DarkBlue); break;
172 case 35: color_value = to_windows_color(TextColor::DarkMagenta); break;
173 case 36: color_value = to_windows_color(TextColor::DarkCyan); break;
174 case 37: color_value = to_windows_color(TextColor::LightGray); break;
175 case 90: color_value = to_windows_color(TextColor::DarkGray); break;
176 case 91: color_value = to_windows_color(TextColor::Red); break;
177 case 92: color_value = to_windows_color(TextColor::Green); break;
178 case 93: color_value = to_windows_color(TextColor::Yellow); break;
179 case 94: color_value = to_windows_color(TextColor::Blue); break;
180 case 95: color_value = to_windows_color(TextColor::Magenta); break;
181 case 96: color_value = to_windows_color(TextColor::Cyan); break;
182 case 97: color_value = to_windows_color(TextColor::White); break;
183 default:
184 // Unknown code, use default color
185 break;
186 };
187 // Set the console text attribute to the desired color
188 SetConsoleTextAttribute(handle_stdout, color_value);
189 }
190# endif
191 }; // MultiStream
192
193}; // namespace consolix
194
195#endif // _CONSOLIX_MULTI_STREAM_HPP_INCLUDED
MultiStream & operator<<(const T &value)
Overloaded operator<< for adding content to the stream.
MultiStream & operator<<(std::ostream &(*manip)(std::ostream &))
Overloaded operator<< for manipulators (e.g., std::endl).
~MultiStream()
Destructor to flush the accumulated log content.
MultiStream()=default
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.