Goby v2
flex_ostream.h
1 // Copyright 2009-2018 Toby Schneider (http://gobysoft.org/index.wt/people/toby)
2 // GobySoft, LLC (2013-)
3 // Massachusetts Institute of Technology (2007-2014)
4 // Community contributors (see AUTHORS file)
5 //
6 //
7 // This file is part of the Goby Underwater Autonomy Project Libraries
8 // ("The Goby Libraries").
9 //
10 // The Goby Libraries are free software: you can redistribute them and/or modify
11 // them under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 2.1 of the License, or
13 // (at your option) any later version.
14 //
15 // The Goby Libraries are distributed in the hope that they will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
22 
23 #ifndef FlexOstream20091211H
24 #define FlexOstream20091211H
25 
26 #include <iomanip>
27 #include <iostream>
28 #include <string>
29 
30 #include <google/protobuf/io/tokenizer.h>
31 #include <google/protobuf/text_format.h>
32 
33 #include <boost/static_assert.hpp>
34 
35 #include "goby/common/logger/flex_ostreambuf.h"
36 #include "logger_manipulators.h"
37 
38 namespace goby
39 {
40 namespace common
41 {
43 class FlexOstream : public std::ostream
44 {
45  public:
46  FlexOstream() : std::ostream(&sb_), sb_(this), lock_action_(logger_lock::none)
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() {}
59 
61 
62  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  boost::recursive_mutex::scoped_lock l(goby::common::logger::mutex);
70  sb_.name(s);
71  }
72 
73  void enable_gui()
74  {
75  boost::recursive_mutex::scoped_lock l(goby::common::logger::mutex);
76  sb_.enable_gui();
77  }
78 
79  bool is(goby::common::logger::Verbosity verbosity);
80 
81  /* void add_stream(const std::string& verbosity, std::ostream* os = 0) */
82  /* { */
83  /* if(verbosity == "scope" || verbosity == "gui") */
84  /* add_stream(goby::common::logger::GUI, os); */
85  /* else if(verbosity == "quiet") */
86  /* add_stream(goby::common::logger::QUIET, os); */
87  /* else if(verbosity == "terse" || verbosity == "warn") */
88  /* add_stream(goby::common::logger::WARN, os); */
89  /* else if(verbosity == "debug") */
90  /* add_stream(goby::common::logger::DEBUG1, os); */
91  /* else */
92  /* add_stream(goby::common::logger::VERBOSE, os); */
93  /* } */
94 
96  void add_stream(logger::Verbosity verbosity = logger::VERBOSE, std::ostream* os = 0)
97  {
98  boost::recursive_mutex::scoped_lock l(goby::common::logger::mutex);
99  sb_.add_stream(verbosity, os);
100  }
101 
102  void add_stream(goby::common::protobuf::GLogConfig::Verbosity verbosity =
103  goby::common::protobuf::GLogConfig::VERBOSE,
104  std::ostream* os = 0)
105  {
106  boost::recursive_mutex::scoped_lock l(goby::common::logger::mutex);
107  sb_.add_stream(static_cast<logger::Verbosity>(verbosity), os);
108  }
109 
110  const FlexOStreamBuf& buf() { return sb_; }
111 
113 
115 
116  // overload this function so we can look for the die manipulator
117  // and set the die_flag
118  // to exit after this line
119  std::ostream& operator<<(FlexOstream& (*pf)(FlexOstream&));
120  std::ostream& operator<<(std::ostream& (*pf)(std::ostream&));
121 
122  //provide interfaces to the rest of the types
123  std::ostream& operator<<(bool& val) { return std::ostream::operator<<(val); }
124  std::ostream& operator<<(const short& val) { return std::ostream::operator<<(val); }
125  std::ostream& operator<<(const unsigned short& val) { return std::ostream::operator<<(val); }
126  std::ostream& operator<<(const int& val) { return std::ostream::operator<<(val); }
127  std::ostream& operator<<(const unsigned int& val) { return std::ostream::operator<<(val); }
128  std::ostream& operator<<(const 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  boost::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::common::logger::UNKNOWN)
156  this->is(goby::common::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  template <typename T> friend void boost::checked_delete(T*);
166 
167  friend std::ostream& operator<<(FlexOstream& out, char c);
168  friend std::ostream& operator<<(FlexOstream& out, signed char c);
169  friend std::ostream& operator<<(FlexOstream& out, unsigned char c);
170  friend std::ostream& operator<<(FlexOstream& out, const char* s);
171  friend std::ostream& operator<<(FlexOstream& out, const signed char* s);
172  friend std::ostream& operator<<(FlexOstream& out, const unsigned char* s);
173 
174  private:
175  static int instances_;
176 
177  private:
178  FlexOStreamBuf sb_;
179  logger_lock::LockAction lock_action_;
180 };
181 
182 inline std::ostream& operator<<(FlexOstream& out, char c) { return std::operator<<(out, c); }
183 inline std::ostream& operator<<(FlexOstream& out, signed char c) { return std::operator<<(out, c); }
184 inline std::ostream& operator<<(FlexOstream& out, unsigned char c)
185 {
186  return std::operator<<(out, c);
187 }
188 inline std::ostream& operator<<(FlexOstream& out, const char* s) { return std::operator<<(out, s); }
189 inline std::ostream& operator<<(FlexOstream& out, const signed char* s)
190 {
191  return std::operator<<(out, s);
192 }
193 inline std::ostream& operator<<(FlexOstream& out, const unsigned char* s)
194 {
195  return std::operator<<(out, s);
196 }
198 
199 template <typename _CharT, typename _Traits, typename _Alloc>
200 inline std::ostream& operator<<(FlexOstream& out,
201  const std::basic_string<_CharT, _Traits, _Alloc>& s)
202 {
203  return std::operator<<(out, s);
204 }
205 
206 } // namespace common
207 
209 
213 namespace util
214 {
215 // for compatibility with Goby1
216 inline common::FlexOstream& glogger() { return goby::glog; }
217 } // namespace util
218 } // namespace goby
219 
221 {
222  public:
223  FlexOStreamErrorCollector(const std::string& original)
224  : original_(original), has_warnings_(false), has_errors_(false)
225  {
226  }
227 
228  void AddError(int line, int column, const std::string& message)
229  {
230  using goby::common::logger::WARN;
231 
232  print_original(line, column);
233  goby::glog.is(WARN) && goby::glog << "line: " << line << " col: " << column << " "
234  << message << std::endl;
235  has_errors_ = true;
236  }
237  void AddWarning(int line, int column, const std::string& message)
238  {
239  using goby::common::logger::WARN;
240 
241  print_original(line, column);
242  goby::glog.is(WARN) && goby::glog << "line: " << line << " col: " << column << " "
243  << message << std::endl;
244 
245  has_warnings_ = true;
246  }
247 
248  void print_original(int line, int column)
249  {
250  using goby::common::logger::WARN;
251 
252  std::stringstream ss(original_ + "\n");
253  std::string line_str;
254 
255  //for(int i = 0; i <= line; ++i)
256  // getline(ss, line_str);
257 
258  int i = 0;
259  while (!getline(ss, line_str).eof())
260  {
261  if (i == line)
262  goby::glog.is(WARN) && goby::glog << goby::common::tcolor::lt_red << "[line "
263  << std::setw(3) << i++ << "]" << line_str
264  << goby::common::tcolor::nocolor << std::endl;
265  else
266  goby::glog.is(WARN) && goby::glog << "[line " << std::setw(3) << i++ << "]"
267  << line_str << std::endl;
268  }
269  }
270 
271  bool has_errors() { return has_errors_; }
272  bool has_warnings() { return has_warnings_; }
273 
274  private:
275  const std::string& original_;
276  bool has_warnings_;
277  bool has_errors_;
278 };
279 
280 #endif
void refresh()
refresh the display (does nothing if !is_gui())
void set_name(const std::string &s)
Set the name of the application that the logger is serving.
Definition: flex_ostream.h:67
void name(const std::string &s)
name of the application being served
Forms the basis of the Goby logger: std::ostream derived class for holding the FlexOStreamBuf.
Definition: flex_ostream.h:43
void group_name(const std::string &s)
current group name (last insertion of group("") into the stream)
boost::recursive_mutex & mutex()
Get a reference to the Goby logger mutex for scoped locking.
Definition: flex_ostream.h:145
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
void add_stream(logger::Verbosity verbosity, std::ostream *os)
add a stream to the logger
Color
The eight terminal colors (and bold or "light" variants)
Definition: term_color.h:111
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...
bool is_quiet() const
do all attached streams have Verbosity == quiet?
common::FlexOstream glog
Access the Goby logger through this object.
The global namespace for the Goby project.
void add_stream(logger::Verbosity verbosity=logger::VERBOSE, std::ostream *os=0)
Attach a stream object (e.g. std::cout, std::ofstream, ...) to the logger with desired verbosity...
Definition: flex_ostream.h:96
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