Goby Underwater Autonomy Project
Series: 1.1, revision: 163, released on 2013-02-06 14:23:27 -0500
|
00001 // copyright 2009 t. schneider tes@mit.edu 00002 // 00003 // this file is part of flex-ostream, a terminal display library 00004 // that provides an ostream with both terminal display and file logging 00005 // 00006 // This program is free software: you can redistribute it and/or modify 00007 // it under the terms of the GNU General Public License as published by 00008 // the Free Software Foundation, either version 3 of the License, or 00009 // (at your option) any later version. 00010 // 00011 // This software is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU General Public License 00017 // along with this software. If not, see <http://www.gnu.org/licenses/>. 00018 00019 #ifndef FlexOstream20091211H 00020 #define FlexOstream20091211H 00021 00022 #include <iostream> 00023 #include <string> 00024 #include <iomanip> 00025 00026 #include "flex_ostreambuf.h" 00027 #include "logger_manipulators.h" 00028 00029 #include <google/protobuf/text_format.h> 00030 #include <google/protobuf/io/tokenizer.h> 00031 00032 #include <boost/shared_ptr.hpp> 00033 00034 namespace goby 00035 { 00036 namespace util 00037 { 00038 namespace logger_lock 00039 { 00041 enum LockAction { none, lock }; 00042 } 00043 00045 class FlexOstream : public std::ostream 00046 { 00047 public: 00049 00050 00051 00052 void add_group(const std::string & name, 00053 Colors::Color color = Colors::nocolor, 00054 const std::string & description = ""); 00055 00057 void set_name(const std::string & s) 00058 { 00059 sb_.name(s); 00060 } 00061 00062 void add_stream(const std::string& verbosity, std::ostream* os = 0) 00063 { 00064 if(verbosity == "scope" || verbosity == "gui") 00065 add_stream(goby::util::Logger::gui, os); 00066 else if(verbosity == "quiet") 00067 add_stream(goby::util::Logger::quiet, os); 00068 else if(verbosity == "terse" || verbosity == "warn") 00069 add_stream(goby::util::Logger::warn, os); 00070 else if(verbosity == "debug") 00071 add_stream(goby::util::Logger::debug, os); 00072 else 00073 add_stream(goby::util::Logger::verbose, os); 00074 } 00075 00076 00078 void add_stream(Logger::Verbosity verbosity = Logger::verbose, std::ostream* os = 0) 00079 { 00080 sb_.add_stream(verbosity, os); 00081 } 00083 00085 00086 // overload this function so we can look for the die manipulator 00087 // and set the die_flag 00088 // to exit after this line 00089 std::ostream& operator<<(FlexOstream& (*pf) (FlexOstream&)); 00090 std::ostream& operator<<(std::ostream & (*pf) (std::ostream &)); 00091 00092 //provide interfaces to the rest of the types 00093 std::ostream& operator<< (bool& val ) 00094 { return std::ostream::operator<<(val); } 00095 std::ostream& operator<< (const short& val ) 00096 { return std::ostream::operator<<(val); } 00097 std::ostream& operator<< (const unsigned short& val ) 00098 { return std::ostream::operator<<(val); } 00099 std::ostream& operator<< (const int& val ) 00100 { return std::ostream::operator<<(val); } 00101 std::ostream& operator<< (const unsigned int& val ) 00102 { return std::ostream::operator<<(val); } 00103 std::ostream& operator<< (const long& val ) 00104 { return std::ostream::operator<<(val); } 00105 std::ostream& operator<< (const unsigned long& val ) 00106 { return std::ostream::operator<<(val); } 00107 std::ostream& operator<< (const float& val ) 00108 { return std::ostream::operator<<(val); } 00109 std::ostream& operator<< (const double& val ) 00110 { return std::ostream::operator<<(val); } 00111 std::ostream& operator<< (const long double& val ) 00112 { return std::ostream::operator<<(val); } 00113 std::ostream& operator<< (std::streambuf* sb ) 00114 { return std::ostream::operator<<(sb); } 00115 std::ostream& operator<< (std::ios& ( *pf )(std::ios&)) 00116 { return std::ostream::operator<<(pf); } 00117 std::ostream& operator<< (std::ios_base& ( *pf )(std::ios_base&)) 00118 { return std::ostream::operator<<(pf); } 00120 00122 00123 00124 boost::mutex& mutex() 00125 { return Logger::mutex; } 00127 00128 void refresh() 00129 { 00130 sb_.refresh(); 00131 } 00132 void set_group(const std::string & s) 00133 { 00134 sb_.group_name(s); 00135 } 00136 00137 private: 00138 bool quiet() 00139 { return (sb_.is_quiet()); } 00140 00141 00142 friend FlexOstream& glogger(logger_lock::LockAction lock_action); 00143 00144 template<typename T> 00145 friend void boost::checked_delete(T*); 00146 00147 friend std::ostream& operator<< (FlexOstream& out, char c ); 00148 friend std::ostream& operator<< (FlexOstream& out, signed char c ); 00149 friend std::ostream& operator<< (FlexOstream& out, unsigned char c ); 00150 friend std::ostream& operator<< (FlexOstream& out, const char *s ); 00151 friend std::ostream& operator<< (FlexOstream& out, const signed char* s ); 00152 friend std::ostream& operator<< (FlexOstream& out, const unsigned char* s ); 00153 00154 private: 00155 FlexOstream() : std::ostream(&sb_) {} 00156 ~FlexOstream() { } 00157 FlexOstream(const FlexOstream&); 00158 FlexOstream& operator = (const FlexOstream&); 00159 00160 private: 00161 static boost::shared_ptr<goby::util::FlexOstream> inst_; 00162 FlexOStreamBuf sb_; 00163 }; 00165 00166 00167 00168 00169 00170 00171 00172 00173 00174 00175 00176 00177 00178 00179 00180 00181 00182 00183 00184 FlexOstream& glogger(logger_lock::LockAction lock_action = logger_lock::none); 00185 00186 inline std::ostream& operator<< (FlexOstream& out, char c ) 00187 { return std::operator<<(out, c); } 00188 inline std::ostream& operator<< (FlexOstream& out, signed char c ) 00189 { return std::operator<<(out, c); } 00190 inline std::ostream& operator<< (FlexOstream& out, unsigned char c ) 00191 { return std::operator<<(out, c); } 00192 inline std::ostream& operator<< (FlexOstream& out, const char* s ) 00193 { return std::operator<<(out, s); } 00194 inline std::ostream& operator<< (FlexOstream& out, const signed char* s ) 00195 { return std::operator<<(out, s); } 00196 inline std::ostream& operator<< (FlexOstream& out, const unsigned char* s ) 00197 { return std::operator<<(out, s); } 00199 00200 } 00201 } 00202 00203 00205 inline std::ostream& unlock(std::ostream & os) 00206 { 00207 goby::util::Logger::mutex.unlock(); 00208 return os; 00209 } 00210 00211 class FlexOStreamErrorCollector : public google::protobuf::io::ErrorCollector 00212 { 00213 public: 00214 FlexOStreamErrorCollector(const std::string& original) 00215 : original_(original), 00216 has_warnings_(false), 00217 has_errors_(false) 00218 { } 00219 00220 void AddError(int line, int column, const std::string& message) 00221 { 00222 print_original(line, column); 00223 goby::util::glogger() << warn << "line: " << line << " col: " << column << " " << message << std::endl; 00224 has_errors_ = true; 00225 } 00226 void AddWarning(int line, int column, const std::string& message) 00227 { 00228 print_original(line, column); 00229 goby::util::glogger() << warn << "line: " << line << " col: " << column << " " << message << std::endl; 00230 has_warnings_ = true; 00231 } 00232 00233 void print_original(int line, int column) 00234 { 00235 std::stringstream ss(original_ + "\n"); 00236 std::string line_str; 00237 00238 //for(int i = 0; i <= line; ++i) 00239 // getline(ss, line_str); 00240 00241 int i = 0; 00242 while(!getline(ss, line_str).eof()) 00243 { 00244 if(i == line) 00245 goby::util::glogger() << goby::util::tcolor::lt_red << "[line " << std::setw(3) << i++ << "]" << line_str << goby::util::tcolor::nocolor << std::endl; 00246 else 00247 goby::util::glogger() << "[line " << std::setw(3) << i++ << "]" << line_str << std::endl; 00248 } 00249 } 00250 00251 00252 bool has_errors() { return has_errors_; } 00253 bool has_warnings() { return has_warnings_; } 00254 00255 00256 private: 00257 const std::string& original_; 00258 bool has_warnings_; 00259 bool has_errors_; 00260 }; 00261 00262 00263 #endif