Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "global.hpp"
00024
00025 #include "SDL.h"
00026
00027 #include "log.hpp"
00028 #include "foreach.hpp"
00029
00030 #include <map>
00031 #include <sstream>
00032 #include <ctime>
00033
00034 namespace {
00035
00036 class null_streambuf : public std::streambuf
00037 {
00038 virtual int overflow(int c) { return std::char_traits< char >::not_eof(c); }
00039 public:
00040 null_streambuf() {}
00041 };
00042
00043 }
00044
00045 static std::ostream null_ostream(new null_streambuf);
00046 static int indent = 0;
00047 static bool timestamp = true;
00048
00049 static std::ostream *output_stream = NULL;
00050
00051 static std::ostream& output()
00052 {
00053 if(output_stream) {
00054 return *output_stream;
00055 }
00056 return std::cerr;
00057 }
00058
00059 namespace lg {
00060
00061 tredirect_output_setter::tredirect_output_setter(std::ostream& stream)
00062 : old_stream_(output_stream)
00063 {
00064 output_stream = &stream;
00065 }
00066
00067 tredirect_output_setter::~tredirect_output_setter()
00068 {
00069 output_stream = old_stream_;
00070 }
00071
00072 typedef std::map<std::string, int> domain_map;
00073 static domain_map *domains;
00074 void timestamps(bool t) { timestamp = t; }
00075
00076 logger err("error", 0), warn("warning", 1), info("info", 2), debug("debug", 3);
00077 log_domain general("general");
00078
00079 log_domain::log_domain(char const *name)
00080 : domain_(NULL)
00081 {
00082
00083 if (!domains) domains = new domain_map;
00084 domain_ = &*domains->insert(logd(name, 1)).first;
00085 }
00086
00087 bool set_log_domain_severity(std::string const &name, int severity)
00088 {
00089 std::string::size_type s = name.size();
00090 if (name == "all") {
00091 foreach (logd &l, *domains) {
00092 l.second = severity;
00093 }
00094 } else if (s > 2 && name.compare(s - 2, 2, "/*") == 0) {
00095 foreach (logd &l, *domains) {
00096 if (l.first.compare(0, s - 1, name, 0, s - 1) == 0)
00097 l.second = severity;
00098 }
00099 } else {
00100 domain_map::iterator it = domains->find(name);
00101 if (it == domains->end())
00102 return false;
00103 it->second = severity;
00104 }
00105 return true;
00106 }
00107
00108 std::string list_logdomains(const std::string& filter)
00109 {
00110 std::ostringstream res;
00111 foreach (logd &l, *domains) {
00112 if(l.first.find(filter) != std::string::npos)
00113 res << l.first << "\n";
00114 }
00115 return res.str();
00116 }
00117
00118 std::string get_timestamp(const time_t& t, const std::string& format) {
00119 char buf[100] = {0};
00120 tm* lt = localtime(&t);
00121 if (lt) {
00122 strftime(buf, 100, format.c_str(), lt);
00123 }
00124 return buf;
00125 }
00126
00127 std::ostream &logger::operator()(log_domain const &domain, bool show_names, bool do_indent) const
00128 {
00129 if (severity_ > domain.domain_->second)
00130 return null_ostream;
00131 else {
00132 std::ostream& stream = output();
00133 if(do_indent) {
00134 for(int i = 0; i != indent; ++i)
00135 stream << " ";
00136 }
00137 if (timestamp) {
00138 stream << get_timestamp(time(NULL));
00139 }
00140 if (show_names) {
00141 stream << name_ << ' ' << domain.domain_->first << ": ";
00142 }
00143 return stream;
00144 }
00145 }
00146
00147 void scope_logger::do_log_entry(log_domain const &domain, const std::string& str)
00148 {
00149 output_ = &debug(domain, false, true);
00150 str_ = str;
00151 ticks_ = SDL_GetTicks();
00152 (*output_) << "{ BEGIN: " << str_ << "\n";
00153 ++indent;
00154 }
00155
00156 void scope_logger::do_log_exit()
00157 {
00158 const int ticks = SDL_GetTicks() - ticks_;
00159 --indent;
00160 do_indent();
00161 if (timestamp) (*output_) << get_timestamp(time(NULL));
00162 (*output_) << "} END: " << str_ << " (took " << ticks << "ms)\n";
00163 }
00164
00165 void scope_logger::do_indent() const
00166 {
00167 for(int i = 0; i != indent; ++i)
00168 (*output_) << " ";
00169 }
00170
00171 std::stringstream wml_error;
00172
00173 }
00174