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