Goby3 3.2.3
2025.05.13
Loading...
Searching...
No Matches
flex_ostream.h
Go to the documentation of this file.
1// Copyright 2012-2023:
2// GobySoft, LLC (2013-)
3// Massachusetts Institute of Technology (2007-2014)
4// Community contributors (see AUTHORS file)
5// File authors:
6// Toby Schneider <toby@gobysoft.org>
7//
8//
9// This file is part of the Goby Underwater Autonomy Project Libraries
10// ("The Goby Libraries").
11//
12// The Goby Libraries are free software: you can redistribute them and/or modify
13// them under the terms of the GNU Lesser General Public License as published by
14// the Free Software Foundation, either version 2.1 of the License, or
15// (at your option) any later version.
16//
17// The Goby Libraries are distributed in the hope that they will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20// GNU Lesser General Public License for more details.
21//
22// You should have received a copy of the GNU Lesser General Public License
23// along with Goby. If not, see <http://www.gnu.org/licenses/>.
24
25#ifndef GOBY_UTIL_DEBUG_LOGGER_FLEX_OSTREAM_H
26#define GOBY_UTIL_DEBUG_LOGGER_FLEX_OSTREAM_H
27
28#include <iomanip>
29#include <iostream>
30#include <string>
31
32#include <google/protobuf/io/tokenizer.h>
33#include <google/protobuf/text_format.h>
34
36#include "logger_manipulators.h"
37
38namespace goby
39{
40namespace util
41{
43class FlexOstream : public std::ostream
44{
45 public:
46 FlexOstream() : std::ostream(&sb_), sb_(this)
47 {
48 ++instances_;
49 if (instances_ > 1)
50 {
51 std::cerr << "Fatal error: cannot create more than one instance of FlexOstream. Use "
52 "global object goby::glog to access the Goby Logger. Do not instantiate "
53 "the FlexOstream directly."
54 << std::endl;
55 exit(EXIT_FAILURE);
56 }
57 }
58 ~FlexOstream() override = default;
59
61
62
63 void add_group(const std::string& name, Colors::Color color = Colors::nocolor,
64 const std::string& description = "");
65
67 void set_name(const std::string& s)
68 {
69 std::lock_guard<std::recursive_mutex> l(goby::util::logger::mutex);
70 sb_.name(s);
71 }
72
74 {
75 std::lock_guard<std::recursive_mutex> l(goby::util::logger::mutex);
76 sb_.enable_gui();
77 }
78
80
81 bool is_die() { return is(goby::util::logger::DIE); }
87
89 void add_stream(logger::Verbosity verbosity = logger::VERBOSE, std::ostream* os = nullptr)
90 {
91 std::lock_guard<std::recursive_mutex> l(goby::util::logger::mutex);
92 sb_.add_stream(verbosity, os);
93 }
94
97 std::ostream* os = nullptr)
98 {
99 std::lock_guard<std::recursive_mutex> l(goby::util::logger::mutex);
100 sb_.add_stream(static_cast<logger::Verbosity>(verbosity), os);
101 }
102
103 void remove_stream(std::ostream* os = nullptr)
104 {
105 std::lock_guard<std::recursive_mutex> l(goby::util::logger::mutex);
106 sb_.remove_stream(os);
107 }
108
109 const FlexOStreamBuf& buf() { return sb_; }
110
112
114
115 // overload this function so we can look for the die manipulator
116 // and set the die_flag
117 // to exit after this line
118 std::ostream& operator<<(FlexOstream& (*pf)(FlexOstream&));
119 std::ostream& operator<<(std::ostream& (*pf)(std::ostream&));
120
121 //provide interfaces to the rest of the types
122 std::ostream& operator<<(bool& val) { return std::ostream::operator<<(val); }
123 std::ostream& operator<<(const short& val) { return std::ostream::operator<<(val); }
124 std::ostream& operator<<(const unsigned short& val) { return std::ostream::operator<<(val); }
125 std::ostream& operator<<(const int& val) { return std::ostream::operator<<(val); }
126 std::ostream& operator<<(const unsigned int& val) { return std::ostream::operator<<(val); }
127 std::ostream& operator<<(const long& val) { return std::ostream::operator<<(val); }
128 std::ostream& operator<<(const long long& val) { return std::ostream::operator<<(val); }
129 std::ostream& operator<<(const unsigned long& val) { return std::ostream::operator<<(val); }
130 std::ostream& operator<<(const float& val) { return std::ostream::operator<<(val); }
131 std::ostream& operator<<(const double& val) { return std::ostream::operator<<(val); }
132 std::ostream& operator<<(const long double& val) { return std::ostream::operator<<(val); }
133 std::ostream& operator<<(std::streambuf* sb) { return std::ostream::operator<<(sb); }
134 std::ostream& operator<<(std::ios& (*pf)(std::ios&)) { return std::ostream::operator<<(pf); }
135 std::ostream& operator<<(std::ios_base& (*pf)(std::ios_base&))
136 {
137 return std::ostream::operator<<(pf);
138 }
139
141
143
144
145 std::recursive_mutex& mutex() { return logger::mutex; }
146
147 void set_lock_action(logger_lock::LockAction lock_action) { sb_.set_lock_action(lock_action); }
149
150 void refresh() { sb_.refresh(); }
151 void set_group(const std::string& s) { sb_.group_name(s); }
152
153 // void set_unset_verbosity()
154 // {
155 // if (sb_.verbosity_depth() == goby::util::logger::UNKNOWN)
156 // this->is(goby::util::logger::VERBOSE);
157 // }
158
159 private:
160 FlexOstream(const FlexOstream&);
161 FlexOstream& operator=(const FlexOstream&);
162
163 bool quiet() { return (sb_.is_quiet()); }
164
165 friend std::ostream& operator<<(FlexOstream& out, char c);
166 friend std::ostream& operator<<(FlexOstream& out, signed char c);
167 friend std::ostream& operator<<(FlexOstream& out, unsigned char c);
168 friend std::ostream& operator<<(FlexOstream& out, const char* s);
169 friend std::ostream& operator<<(FlexOstream& out, const signed char* s);
170 friend std::ostream& operator<<(FlexOstream& out, const unsigned char* s);
171
172 private:
173 static int instances_;
174
175 private:
176 FlexOStreamBuf sb_;
178};
179
180inline std::ostream& operator<<(FlexOstream& out, char c) { return std::operator<<(out, c); }
181inline std::ostream& operator<<(FlexOstream& out, signed char c) { return std::operator<<(out, c); }
182inline std::ostream& operator<<(FlexOstream& out, unsigned char c)
183{
184 return std::operator<<(out, c);
185}
186inline std::ostream& operator<<(FlexOstream& out, const char* s) { return std::operator<<(out, s); }
187inline std::ostream& operator<<(FlexOstream& out, const signed char* s)
188{
189 return std::operator<<(out, s);
190}
191inline std::ostream& operator<<(FlexOstream& out, const unsigned char* s)
192{
193 return std::operator<<(out, s);
194}
196
197template <typename _CharT, typename _Traits, typename _Alloc>
198inline std::ostream& operator<<(FlexOstream& out,
199 const std::basic_string<_CharT, _Traits, _Alloc>& s)
200{
201 return std::operator<<(out, s);
202}
203
204} // namespace util
205
207
208
209extern util::FlexOstream glog;
211namespace util
212{
213// for compatibility with Goby1
214[[deprecated("Use goby::glog")]] inline util::FlexOstream& glogger() { return goby::glog; }
215
216class FlexOStreamErrorCollector : public google::protobuf::io::ErrorCollector
217{
218 public:
219 FlexOStreamErrorCollector(const std::string& original)
220 : original_(original), has_warnings_(false), has_errors_(false)
221 {
222 }
223
224 void AddError(int line, int column, const std::string& message) override
225 {
227
228 print_original(line, column);
229 goby::glog.is(WARN) && goby::glog << "line: " << line << " col: " << column << " "
230 << message << std::endl;
231 has_errors_ = true;
232 }
233 void AddWarning(int line, int column, const std::string& message) override
234 {
236
237 print_original(line, column);
238 goby::glog.is(WARN) && goby::glog << "line: " << line << " col: " << column << " "
239 << message << std::endl;
240
241 has_warnings_ = true;
242 }
243
244 void print_original(int line, int /*column*/)
245 {
247
248 std::stringstream ss(original_ + "\n");
249 std::string line_str;
250
251 //for(int i = 0; i <= line; ++i)
252 // getline(ss, line_str);
253
254 int i = 0;
255 while (!getline(ss, line_str).eof())
256 {
257 if (i == line)
258 goby::glog.is(WARN) && goby::glog << goby::util::tcolor::lt_red << "[line "
259 << std::setw(3) << i++ << "]" << line_str
260 << goby::util::tcolor::nocolor << std::endl;
261 else
262 goby::glog.is(WARN) && goby::glog << "[line " << std::setw(3) << i++ << "]"
263 << line_str << std::endl;
264 }
265 }
266
267 bool has_errors() { return has_errors_; }
268 bool has_warnings() { return has_warnings_; }
269
270 private:
271 const std::string& original_;
272 bool has_warnings_;
273 bool has_errors_;
274};
275} // namespace util
276} // namespace goby
277
278#endif
void set_lock_action(logger_lock::LockAction lock_action)
void group_name(const std::string &s)
current group name (last insertion of group("") into the stream)
bool is_quiet() const
do all attached streams have Verbosity == quiet?
void name(const std::string &s)
name of the application being served
void refresh()
refresh the display (does nothing if !is_gui())
void remove_stream(std::ostream *os)
remove a stream from the logger
void add_stream(logger::Verbosity verbosity, std::ostream *os)
add a stream to the logger
Forms the basis of the Goby logger: std::ostream derived class for holding the FlexOStreamBuf.
~FlexOstream() override=default
std::ostream & operator<<(std::ios_base &(*pf)(std::ios_base &))
std::ostream & operator<<(const double &val)
std::ostream & operator<<(FlexOstream &(*pf)(FlexOstream &))
std::ostream & operator<<(const unsigned long &val)
friend std::ostream & operator<<(FlexOstream &out, char c)
void remove_stream(std::ostream *os=nullptr)
std::ostream & operator<<(std::ostream &(*pf)(std::ostream &))
std::ostream & operator<<(const long long &val)
std::ostream & operator<<(const short &val)
std::ostream & operator<<(bool &val)
std::ostream & operator<<(const long &val)
void add_stream(goby::util::protobuf::GLogConfig::Verbosity verbosity=goby::util::protobuf::GLogConfig::VERBOSE, std::ostream *os=nullptr)
std::ostream & operator<<(const int &val)
const FlexOStreamBuf & buf()
std::recursive_mutex & mutex()
Get a reference to the Goby logger mutex for scoped locking.
std::ostream & operator<<(const float &val)
void add_group(const std::string &name, Colors::Color color=Colors::nocolor, const std::string &description="")
Add another group to the logger. A group provides related manipulator for categorizing log messages.
std::ostream & operator<<(const long double &val)
std::ostream & operator<<(const unsigned short &val)
bool is(goby::util::logger::Verbosity verbosity)
void set_group(const std::string &s)
void set_name(const std::string &s)
Set the name of the application that the logger is serving.
std::ostream & operator<<(std::streambuf *sb)
std::ostream & operator<<(std::ios &(*pf)(std::ios &))
std::ostream & operator<<(const unsigned int &val)
void add_stream(logger::Verbosity verbosity=logger::VERBOSE, std::ostream *os=nullptr)
Attach a stream object (e.g. std::cout, std::ofstream, ...) to the logger with desired verbosity.
void set_lock_action(logger_lock::LockAction lock_action)
static constexpr Verbosity VERBOSE
LockAction
Mutex actions available to the Goby logger (glogger)
std::recursive_mutex mutex
std::ostream & nocolor(std::ostream &os)
All text following this manipulator is uncolored (e.g. std::cout << green << "green" << nocolor << "u...
Definition term_color.h:104
std::ostream & lt_red(std::ostream &os)
All text following this manipulator is light red (e.g. std::cout << lt_red << "text";)
Definition term_color.h:65
The global namespace for the Goby project.
util::FlexOstream glog
Access the Goby logger through this object.
STL namespace.
Color
The eight terminal colors (and bold or "light" variants)
Definition term_color.h:112