FIFE  2008.0
 All Classes Namespaces Functions Variables Enumerations Enumerator
logger.cpp
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2008 by the FIFE team                              *
00003  *   http://www.fifengine.de                                               *
00004  *   This file is part of FIFE.                                            *
00005  *                                                                         *
00006  *   FIFE is free software; you can redistribute it and/or                 *
00007  *   modify it under the terms of the GNU Lesser General Public            *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2.1 of the License, or (at your option) any later version.    *
00010  *                                                                         *
00011  *   This library 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 GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the                 *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
00020  ***************************************************************************/
00021 
00022 // Standard C++ library includes
00023 #include <algorithm>
00024 #include <iomanip>
00025 #include <fstream>
00026 
00027 // 3rd party library includes
00028 #include <SDL.h>
00029 
00030 // FIFE includes
00031 // These includes are split up in two parts, separated by one empty line
00032 // First block: files included from the FIFE root src directory
00033 // Second block: files included from the same folder
00034 // #include "guichan_addon/console.h"
00035 #include "modules.h"
00036 #include "logger.h"
00037 #include "util/base/exception.h"
00038 
00039 // define the module info relationships structure here, begin
00040 struct ModuleInfo {
00041     logmodule_t module;
00042     logmodule_t parent;
00043     std::string name;
00044 };
00045 MODULE_INFO_RELATIONSHIPS
00046 // end
00047 
00048 namespace FIFE {
00049     LogManager* LogManager::m_instance = NULL;
00050 
00051     Logger::Logger(logmodule_t module):
00052         m_module(module) {
00053     }
00054 
00055     Logger::~Logger() {
00056     }
00057 
00058     void Logger::log(LogManager::LogLevel level, const std::string& msg) {
00059         LogManager::instance()->log(level, m_module, msg);
00060     }
00061 
00062     void Logger::log(LogManager::LogLevel level, const LMsg& msg) {
00063         LogManager::instance()->log(level, m_module, msg.str);
00064     }
00065 
00066     LogManager* LogManager::instance() {
00067         if (!m_instance) {
00068             m_instance = new LogManager();
00069         }
00070         return m_instance;
00071     }
00072 
00073     LogManager::~LogManager() {
00074         delete m_instance;
00075     }
00076 
00077 
00078     void LogManager::log(LogLevel level, logmodule_t module, const std::string& msg) {
00079         if (level < m_level) {
00080             return;
00081         }
00082         if (!isVisible(module)) {
00083             return;
00084         }
00085         std::string lvlstr = "";
00086         switch (level) {
00087             case LEVEL_DEBUG: lvlstr = "dbg";
00088             break;
00089 
00090             case LEVEL_LOG: lvlstr = "log";
00091             break;
00092 
00093             case LEVEL_WARN: lvlstr = "warn";
00094             break;
00095 
00096             case LEVEL_ERROR: lvlstr = "error";
00097             break;
00098 
00099             case LEVEL_PANIC: lvlstr = "panic";
00100             break;
00101 
00102             default: lvlstr = "error";
00103             break;
00104         }
00105         if (m_logtoprompt) {
00106             std::cout << moduleInfos[module].name << ": " << lvlstr << ": " << msg << std::endl;
00107         }
00108         if (m_logtofile) {
00109             *m_logfile << moduleInfos[module].name << ": " << lvlstr << ": " << msg << std::endl;
00110         }
00111         if (level == LEVEL_PANIC) {
00112             abort();
00113         }
00114     }
00115 
00116     void LogManager::setLevelFilter(LogLevel level) {
00117         m_level = level;
00118     }
00119 
00120     LogManager::LogLevel LogManager::getLevelFilter() {
00121         return m_level;
00122     }
00123 
00124     void LogManager::addVisibleModule(logmodule_t module) {
00125         validateModule(module);
00126         int ind = static_cast<int>(module);
00127         m_modules[ind] = true;
00128         if (moduleInfos[ind].parent != LM_CORE) {
00129             addVisibleModule(moduleInfos[ind].parent);
00130         }
00131     }
00132 
00133     void LogManager::removeVisibleModule(logmodule_t module) {
00134         validateModule(module);
00135         m_modules[module] = false;
00136     }
00137 
00138     void LogManager::clearVisibleModules() {
00139         for (int i = 0; i < LM_MODULE_MAX; i++) {
00140             m_modules[i] = false;
00141         }
00142     }
00143 
00144     void LogManager::setLogToPrompt(bool log_to_promt) {
00145         m_logtoprompt = log_to_promt;
00146     }
00147 
00148     bool LogManager::isLoggingToPrompt() {
00149         return m_logtoprompt;
00150     }
00151 
00152     void LogManager::setLogToFile(bool logtofile) {
00153         if(logtofile){
00154             m_logfile = new std::ofstream("fife.log");
00155         }
00156         else {
00157             if (m_logfile){
00158                 delete m_logfile;
00159             }
00160         }
00161         m_logtofile = logtofile;
00162     }
00163 
00164     bool LogManager::isLoggingToFile() {
00165         return m_logtofile;
00166     }
00167 
00168     bool LogManager::isVisible(logmodule_t module) {
00169         if (!m_modules[module]) {
00170             return false;
00171         }
00172         if (moduleInfos[module].parent != LM_CORE) {
00173             return isVisible(moduleInfos[module].parent);
00174         }
00175         return true;
00176     }
00177 
00178     LogManager::LogManager():
00179         m_level(LEVEL_DEBUG),
00180         module_check_stack(),
00181         m_logtofile(false),
00182         m_logtoprompt(false) {
00183         validateModuleDescription(LM_CORE);
00184         m_logfile = 0;
00185         clearVisibleModules();
00186     }
00187 
00188     void LogManager::validateModule(logmodule_t m) {
00189         if ((m <= LM_CORE) || (m >= LM_MODULE_MAX)) {
00190             std::cout << "Invalid module received in LogManager: " << m << ", aborting\n";
00191             abort();
00192         }
00193     }
00194 
00195     void LogManager::validateModuleDescription(logmodule_t module) {
00196         if (module == LM_CORE) {
00197             for (int m = static_cast<int>(LM_CORE)+1; m < static_cast<int>(LM_MODULE_MAX); m++) {
00198                 if (moduleInfos[m].module != static_cast<logmodule_t>(m)) {
00199                     std::ostringstream stream;
00200                     stream << m;
00201                     std::string msg = "Log module definition ids do not match in index ";
00202                     msg += stream.str();
00203                     std::cout << msg << std::endl;
00204                     throw InvalidFormat(msg);
00205                 }
00206                 module_check_stack.clear();
00207                 validateModuleDescription(static_cast<logmodule_t>(m));
00208             }
00209         } else {
00210             module_check_stack.push_back(module);
00211             if (count(module_check_stack.begin(), module_check_stack.end(), module) > 1) {
00212                 throw InvalidFormat("Log module definition hierachy contains cycles");
00213             }
00214         }
00215     }
00216 
00217     std::string LogManager::getModuleName(logmodule_t module) {
00218         return moduleInfos[module].name;
00219     }
00220 }