log.cpp

Go to the documentation of this file.
00001 /* $Id: log.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2003 by David White <dave@whitevine.net>
00004                  2004 - 2012 by Guillaume Melquiond <guillaume.melquiond@gmail.com>
00005    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY.
00013 
00014    See the COPYING file for more details.
00015 */
00016 
00017 /**
00018  * @file
00019  * Standard logging facilities (implementation).
00020  * See also the command line switches --logdomains and --log-@<level@>="domain".
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 } // end anonymous namespace
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     // Indirection to prevent initialization depending on link order.
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 } // end namespace lg
00174 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:02:54 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs