[Orxonox-commit 1276] r5994 - in code/branches/console/src/libraries: core util
rgrieder at orxonox.net
rgrieder at orxonox.net
Tue Oct 27 14:47:14 CET 2009
Author: rgrieder
Date: 2009-10-27 14:47:14 +0100 (Tue, 27 Oct 2009)
New Revision: 5994
Removed:
code/branches/console/src/libraries/util/OutputBuffer.cc
code/branches/console/src/libraries/util/OutputBuffer.h
Modified:
code/branches/console/src/libraries/core/ConfigValueIncludes.h
code/branches/console/src/libraries/core/Core.cc
code/branches/console/src/libraries/core/Core.h
code/branches/console/src/libraries/core/GUIManager.cc
code/branches/console/src/libraries/core/GraphicsManager.cc
code/branches/console/src/libraries/core/IOConsole.cc
code/branches/console/src/libraries/core/LuaState.cc
code/branches/console/src/libraries/core/Shell.cc
code/branches/console/src/libraries/core/Shell.h
code/branches/console/src/libraries/util/CMakeLists.txt
code/branches/console/src/libraries/util/Debug.h
code/branches/console/src/libraries/util/OrxAssert.h
code/branches/console/src/libraries/util/OutputHandler.cc
code/branches/console/src/libraries/util/OutputHandler.h
code/branches/console/src/libraries/util/UtilPrereqs.h
Log:
Changed Output concept a little bit to allow for more general use.
Every output (log) target has to be implemented as OutputListener. There is already a LogFileWriter and a MemoryLogWriter (stores ALL the log in a vector and provides iterators).
The OutputListener has a unique and constant name, a stream pointer and a soft debug level (that can only be changed via OutputHandler::setSoftDebugLevel(name, level)).
This concept doesn't require the OutputBuffer anymore, so I deleted it.
The adjustments in the Shell are just preliminary for this commit.
Modified: code/branches/console/src/libraries/core/ConfigValueIncludes.h
===================================================================
--- code/branches/console/src/libraries/core/ConfigValueIncludes.h 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/ConfigValueIncludes.h 2009-10-27 13:47:14 UTC (rev 5994)
@@ -46,17 +46,17 @@
@param varname The name of the variable
@param defvalue The default-value of the variable
*/
-#define SetConfigValueGeneric(type, varname, defvalue) \
+#define SetConfigValueGeneric(type, varname, entryname, sectionname, defvalue) \
static orxonox::Identifier* identifier##varname = this->getIdentifier(); \
orxonox::ConfigValueContainer* container##varname = identifier##varname->getConfigValueContainer(#varname); \
if (!container##varname) \
{ \
- container##varname = new orxonox::ConfigValueContainer(type, identifier##varname, identifier##varname->getName(), #varname, defvalue, varname); \
+ container##varname = new orxonox::ConfigValueContainer(type, identifier##varname, sectionname, entryname, defvalue, varname); \
identifier##varname->addConfigValueContainer(#varname, container##varname); \
} \
container##varname->getValue(&varname, this)
-#define SetConfigValue(varname, defvalue) SetConfigValueGeneric(ConfigFileType::Settings, varname, defvalue)
+#define SetConfigValue(varname, defvalue) SetConfigValueGeneric(ConfigFileType::Settings, varname, identifier##varname->getName(), #varname, defvalue)
/**
Modified: code/branches/console/src/libraries/core/Core.cc
===================================================================
--- code/branches/console/src/libraries/core/Core.cc 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/Core.cc 2009-10-27 13:47:14 UTC (rev 5994)
@@ -105,24 +105,14 @@
*/
void setConfigValues()
{
-#ifdef NDEBUG
- const unsigned int defaultLevelConsole = 1;
- const unsigned int defaultLevelLogfile = 3;
- const unsigned int defaultLevelShell = 1;
+#ifdef ORXONOX_RELEASE
+ const unsigned int defaultLevelLogFile = 3;
#else
- const unsigned int defaultLevelConsole = 3;
- const unsigned int defaultLevelLogfile = 4;
- const unsigned int defaultLevelShell = 3;
+ const unsigned int defaultLevelLogFile = 4;
#endif
- SetConfigValue(softDebugLevelConsole_, defaultLevelConsole)
- .description("The maximal level of debug output shown in the console")
- .callback(this, &CoreConfiguration::debugLevelChanged);
- SetConfigValue(softDebugLevelLogfile_, defaultLevelLogfile)
- .description("The maximal level of debug output shown in the logfile")
- .callback(this, &CoreConfiguration::debugLevelChanged);
- SetConfigValue(softDebugLevelShell_, defaultLevelShell)
- .description("The maximal level of debug output shown in the ingame shell")
- .callback(this, &CoreConfiguration::debugLevelChanged);
+ SetConfigValueGeneric(ConfigFileType::Settings, softDebugLevelLogFile_, "softDebugLevelLogFile", "OutputHandler", defaultLevelLogFile)
+ .description("The maximum level of debug output shown in the log file");
+ OutputHandler::getInstance().setSoftDebugLevel(OutputHandler::logFileOutputListenerName_s, this->softDebugLevelLogFile_);
SetConfigValue(language_, Language::getInstance().defaultLanguage_)
.description("The language of the in game text")
@@ -133,24 +123,6 @@
}
/**
- @brief Callback function if the debug level has changed.
- */
- void debugLevelChanged()
- {
- // softDebugLevel_ is the maximum of the 3 variables
- this->softDebugLevel_ = this->softDebugLevelConsole_;
- if (this->softDebugLevelLogfile_ > this->softDebugLevel_)
- this->softDebugLevel_ = this->softDebugLevelLogfile_;
- if (this->softDebugLevelShell_ > this->softDebugLevel_)
- this->softDebugLevel_ = this->softDebugLevelShell_;
-
- OutputHandler::setSoftDebugLevel(OutputHandler::LD_All, this->softDebugLevel_);
- OutputHandler::setSoftDebugLevel(OutputHandler::LD_Console, this->softDebugLevelConsole_);
- OutputHandler::setSoftDebugLevel(OutputHandler::LD_Logfile, this->softDebugLevelLogfile_);
- OutputHandler::setSoftDebugLevel(OutputHandler::LD_Shell, this->softDebugLevelShell_);
- }
-
- /**
@brief Callback function if the language has changed.
*/
void languageChanged()
@@ -178,10 +150,7 @@
}
}
- int softDebugLevel_; //!< The debug level
- int softDebugLevelConsole_; //!< The debug level for the console
- int softDebugLevelLogfile_; //!< The debug level for the logfile
- int softDebugLevelShell_; //!< The debug level for the ingame shell
+ int softDebugLevelLogFile_; //!< The debug level for the log file (belongs to OutputHandler)
std::string language_; //!< The language
bool bInitializeRandomNumberGenerator_; //!< If true, srand(time(0)) is called
};
@@ -227,7 +196,7 @@
this->signalHandler_->doCatch(PathConfig::getExecutablePathString(), PathConfig::getLogPathString() + "orxonox_crash.log");
// Set the correct log path. Before this call, /tmp (Unix) or %TEMP% (Windows) was used
- OutputHandler::getOutStream().setLogPath(PathConfig::getLogPathString());
+ OutputHandler::getInstance().setLogPath(PathConfig::getLogPathString());
// Parse additional options file now that we know its path
CommandLine::parseFile();
@@ -330,48 +299,6 @@
}
/**
- @brief Returns the softDebugLevel for the given device (returns a default-value if the class is right about to be created).
- @param device The device
- @return The softDebugLevel
- */
- /*static*/ int Core::getSoftDebugLevel(OutputHandler::OutputDevice device)
- {
- switch (device)
- {
- case OutputHandler::LD_All:
- return Core::getInstance().configuration_->softDebugLevel_;
- case OutputHandler::LD_Console:
- return Core::getInstance().configuration_->softDebugLevelConsole_;
- case OutputHandler::LD_Logfile:
- return Core::getInstance().configuration_->softDebugLevelLogfile_;
- case OutputHandler::LD_Shell:
- return Core::getInstance().configuration_->softDebugLevelShell_;
- default:
- assert(0);
- return 2;
- }
- }
-
- /**
- @brief Sets the softDebugLevel for the given device. Please use this only temporary and restore the value afterwards, as it overrides the configured value.
- @param device The device
- @param level The level
- */
- /*static*/ void Core::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
- {
- if (device == OutputHandler::LD_All)
- Core::getInstance().configuration_->softDebugLevel_ = level;
- else if (device == OutputHandler::LD_Console)
- Core::getInstance().configuration_->softDebugLevelConsole_ = level;
- else if (device == OutputHandler::LD_Logfile)
- Core::getInstance().configuration_->softDebugLevelLogfile_ = level;
- else if (device == OutputHandler::LD_Shell)
- Core::getInstance().configuration_->softDebugLevelShell_ = level;
-
- OutputHandler::setSoftDebugLevel(device, level);
- }
-
- /**
@brief Returns the configured language.
*/
/*static*/ const std::string& Core::getLanguage()
Modified: code/branches/console/src/libraries/core/Core.h
===================================================================
--- code/branches/console/src/libraries/core/Core.h 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/Core.h 2009-10-27 13:47:14 UTC (rev 5994)
@@ -68,8 +68,6 @@
void setConfigValues();
- static int getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
- static void setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
static const std::string& getLanguage();
static void resetLanguage();
Modified: code/branches/console/src/libraries/core/GUIManager.cc
===================================================================
--- code/branches/console/src/libraries/core/GUIManager.cc 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/GUIManager.cc 2009-10-27 13:47:14 UTC (rev 5994)
@@ -52,7 +52,6 @@
#include "util/Debug.h"
#include "util/Exception.h"
#include "util/OrxAssert.h"
-#include "Core.h"
#include "LuaState.h"
#include "PathConfig.h"
#include "Resource.h"
@@ -74,7 +73,7 @@
case CEGUI::Insane: orxonoxLevel = 6; break;
default: OrxAssert(false, "CEGUI log level out of range, inpect immediately!");
}
- OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)
+ OutputHandler::getOutStream(orxonoxLevel)
<< "CEGUI: " << message << std::endl;
CEGUI::DefaultLogger::logEvent(message, level);
@@ -120,7 +119,7 @@
ceguiLogger->setLogFilename(PathConfig::getLogPathString() + "cegui.log");
// set the log level according to ours (translate by subtracting 1)
ceguiLogger->setLoggingLevel(
- static_cast<LoggingLevel>(Core::getSoftDebugLevel(OutputHandler::LD_Logfile) - 1));
+ static_cast<LoggingLevel>(OutputHandler::getInstance().getSoftDebugLevel("logFile") - 1));
this->ceguiLogger_ = ceguiLogger.release();
// create the CEGUI system singleton
Modified: code/branches/console/src/libraries/core/GraphicsManager.cc
===================================================================
--- code/branches/console/src/libraries/core/GraphicsManager.cc 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/GraphicsManager.cc 2009-10-27 13:47:14 UTC (rev 5994)
@@ -407,7 +407,7 @@
default:
orxonoxLevel = 0;
}
- OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)
+ OutputHandler::getOutStream(orxonoxLevel)
<< "Ogre: " << message << std::endl;
}
Modified: code/branches/console/src/libraries/core/IOConsole.cc
===================================================================
--- code/branches/console/src/libraries/core/IOConsole.cc 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/IOConsole.cc 2009-10-27 13:47:14 UTC (rev 5994)
@@ -61,7 +61,7 @@
{
this->originalTerminalSettings_ = new termios;
this->setTerminalMode();
- this->shell_.registerListener(this);
+ this->shell_.registerListener(this);
}
IOConsole::~IOConsole()
@@ -233,6 +233,39 @@
std::cout.flush();
}
+#elif defined(ORXONOX_PLATFORM_WINDOWS)
+
+ IOConsole::IOConsole()
+ : shell_(Shell::getInstance())
+ , buffer_(Shell::getInstance().getInputBuffer())
+ {
+ this->setTerminalMode();
+ }
+
+ IOConsole::~IOConsole()
+ {
+ }
+
+ void IOConsole::setTerminalMode()
+ {
+ }
+
+ void IOConsole::resetTerminalMode()
+ {
+ }
+
+ void IOConsole::update(const Clock& time)
+ {
+ }
+
+ void IOConsole::print(const std::string& text)
+ {
+ }
+
+ void IOConsole::printInputLine()
+ {
+ }
+
#endif /* ORXONOX_PLATFORM_UNIX */
// ###############################
@@ -255,14 +288,14 @@
*/
void IOConsole::onlyLastLineChanged()
{
- // Save cursor position and move it the beginning of the second to last line
- std::cout << "\033[s\033[1F";
- // Erase the second to last line
- std::cout << "\033[K";
- this->print(*(this->shell_.getNewestLineIterator()));
- // Restore cursor
- std::cout << "\033[u";
- std::cout.flush();
+ // Save cursor position and move it the beginning of the second to last line
+ std::cout << "\033[s\033[1F";
+ // Erase the second to last line
+ std::cout << "\033[K";
+ this->print(*(this->shell_.getNewestLineIterator()));
+ // Restore cursor
+ std::cout << "\033[u";
+ std::cout.flush();
}
/**
@@ -271,11 +304,11 @@
*/
void IOConsole::lineAdded()
{
- // Move curosr the beginning of the line and erase it
- std::cout << "\033[1G\033[K";
- this->print(*(this->shell_.getNewestLineIterator()));
- std::cout << std::endl;
- this->printInputLine();
+ // Move curosr the beginning of the line and erase it
+ std::cout << "\033[1G\033[K";
+ this->print(*(this->shell_.getNewestLineIterator()));
+ std::cout << std::endl;
+ this->printInputLine();
}
/**
@@ -302,11 +335,11 @@
*/
void IOConsole::executed()
{
- // Move curosr the beginning of the line
- std::cout << "\033[1G";
- // Print command so the user knows what he typed
+ // Move cursor the beginning of the line
+ std::cout << "\033[1G";
+ // Print command so the user knows what he has typed
std::cout << "orxonox>" << this->shell_.getInput() << std::endl;
- this->printInputLine();
+ this->printInputLine();
}
Modified: code/branches/console/src/libraries/core/LuaState.cc
===================================================================
--- code/branches/console/src/libraries/core/LuaState.cc 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/LuaState.cc 2009-10-27 13:47:14 UTC (rev 5994)
@@ -181,7 +181,7 @@
void LuaState::luaLog(unsigned int level, const std::string& message)
{
- OutputHandler::getOutStream().setOutputLevel(level) << message << std::endl;
+ OutputHandler::getOutStream(level) << message << std::endl;
}
bool LuaState::fileExists(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
Modified: code/branches/console/src/libraries/core/Shell.cc
===================================================================
--- code/branches/console/src/libraries/core/Shell.cc 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/Shell.cc 2009-10-27 13:47:14 UTC (rev 5994)
@@ -50,10 +50,8 @@
Shell* Shell::singletonPtr_s = 0;
Shell::Shell()
+ : OutputListener("shell")
{
- int level = Core::getSoftDebugLevel(OutputHandler::LD_Shell);
- Core::setSoftDebugLevel(OutputHandler::LD_Shell, -1);
-
RegisterRootObject(Shell);
this->scrollPosition_ = 0;
@@ -68,32 +66,46 @@
this->inputBuffer_ = new InputBuffer();
this->configureInputBuffer();
- this->outputBuffer_.registerListener(this);
- OutputHandler::getOutStream().setOutputBuffer(&this->outputBuffer_);
-
// Get a config file for the command history
this->commandHistoryConfigFileType_ = ConfigFileManager::getInstance().getNewConfigFileType();
ConfigFileManager::getInstance().setFilename(this->commandHistoryConfigFileType_, "commandHistory.ini");
+ // Use a stringstream object to buffer the output and get it line by line in update()
+ this->outputStream_ = &this->outputBuffer_;
+
this->setConfigValues();
- Core::setSoftDebugLevel(OutputHandler::LD_Shell, level);
+ // Get the previous output and add it to the Shell
+ for (OutputHandler::OutputVectorIterator it = OutputHandler::getInstance().getOutputVectorBegin();
+ it != OutputHandler::getInstance().getOutputVectorEnd(); ++it)
+ this->addLine(it->second, it->first);
+
+ // Register the shell as output listener
+ OutputHandler::getInstance().registerOutputListener(this);
}
Shell::~Shell()
{
- OutputHandler::getOutStream().setOutputBuffer(0);
- if (this->inputBuffer_)
- this->inputBuffer_->destroy();
+ OutputHandler::getInstance().unregisterOutputListener(this);
+ this->inputBuffer_->destroy();
}
void Shell::setConfigValues()
{
- SetConfigValueGeneric(commandHistoryConfigFileType_, maxHistoryLength_, 100)
+ SetConfigValueGeneric(commandHistoryConfigFileType_, maxHistoryLength_, "maxHistoryLength_", "Shell", 100)
.callback(this, &Shell::commandHistoryLengthChanged);
- SetConfigValueGeneric(commandHistoryConfigFileType_, historyOffset_, 0)
+ SetConfigValueGeneric(commandHistoryConfigFileType_, historyOffset_, "historyOffset_", "Shell", 0)
.callback(this, &Shell::commandHistoryOffsetChanged);
SetConfigValueVectorGeneric(commandHistoryConfigFileType_, commandHistory_, std::vector<std::string>());
+
+#ifdef ORXONOX_RELEASE
+ const unsigned int defaultLevel = 1;
+#else
+ const unsigned int defaultLevel = 3;
+#endif
+ SetConfigValueGeneric(ConfigFileType::Settings, softDebugLevel_, "softDebugLevelShell", "OutputHandler", defaultLevel)
+ .description("The maximal level of debug output shown in the Shell");
+ OutputHandler::getInstance().setSoftDebugLevel("shell", this->softDebugLevel_);
}
void Shell::commandHistoryOffsetChanged()
@@ -181,14 +193,9 @@
void Shell::addLine(const std::string& line, int level)
{
- int original_level = OutputHandler::getOutStream().getOutputLevel();
- OutputHandler::getOutStream().setOutputLevel(level);
-
- if (!this->finishedLastLine_)
- this->outputBuffer_ << std::endl;
-
- this->outputBuffer_ << line << std::endl;
- OutputHandler::getOutStream().setOutputLevel(original_level);
+ if (level <= this->softDebugLevel_)
+ this->lines_.push_front(line);
+ this->updateListeners<&ShellListener::lineAdded>();
}
void Shell::clearLines()
@@ -237,17 +244,25 @@
bool newline;
do
{
- newline = this->outputBuffer_.getLine(&output);
+ std::getline(this->outputBuffer_, output);
+ bool eof = this->outputBuffer_.eof();
+ bool fail = this->outputBuffer_.fail();
+ if (eof)
+ this->outputBuffer_.flush();
+ if (eof || fail)
+ this->outputBuffer_.clear();
+ newline = (!eof && !fail);
+
if (!newline && output == "")
break;
if (this->finishedLastLine_)
{
if (this->bAddOutputLevel_)
- output.insert(0, 1, static_cast<char>(OutputHandler::getOutStream().getOutputLevel()));
+ output.insert(0, 1, static_cast<char>(OutputHandler::getInstance().getOutputLevel()));
- this->lines_.insert(this->lines_.begin(), output);
+ this->lines_.push_front(output);
if (this->scrollPosition_)
this->scrollPosition_++;
@@ -364,14 +379,14 @@
if (this->historyPosition_ == this->historyOffset_)
return;
unsigned int cursorPosition = this->getCursorPosition();
- std::string input_str( this->getInput().substr(0,cursorPosition) ); //only search for the expression from the beginning of the inputline untill the cursor position
- for (unsigned int newPos = this->historyPosition_+1; newPos<=this->historyOffset_; newPos++)
+ std::string input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning of the inputline untill the cursor position
+ for (unsigned int newPos = this->historyPosition_ + 1; newPos <= this->historyOffset_; newPos++)
{
- if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) //search case insensitive
+ if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // search case insensitive
{
this->historyPosition_ = newPos;
this->inputBuffer_->set(this->getFromHistory());
- this->setCursorPosition( cursorPosition );
+ this->setCursorPosition(cursorPosition);
return;
}
}
@@ -382,14 +397,14 @@
if (this->historyPosition_ == 0)
return;
unsigned int cursorPosition = this->getCursorPosition();
- std::string input_str( this->getInput().substr(0,cursorPosition) ); //only search for the expression from the beginn$
- for (unsigned int newPos = this->historyPosition_-1; newPos>0; newPos--)
+ std::string input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginn$
+ for (unsigned int newPos = this->historyPosition_ - 1; newPos > 0; newPos--)
{
- if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) //sear$
+ if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // sear$
{
this->historyPosition_ = newPos;
this->inputBuffer_->set(this->getFromHistory());
- this->setCursorPosition( cursorPosition );
+ this->setCursorPosition(cursorPosition);
return;
}
}
Modified: code/branches/console/src/libraries/core/Shell.h
===================================================================
--- code/branches/console/src/libraries/core/Shell.h 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/Shell.h 2009-10-27 13:47:14 UTC (rev 5994)
@@ -33,10 +33,11 @@
#include <cassert>
#include <list>
+#include <sstream>
#include <string>
#include <vector>
-#include "util/OutputBuffer.h"
+#include "util/OutputHandler.h"
#include "input/InputBuffer.h"
#include "OrxonoxClass.h"
#include "ConfigFileManager.h"
@@ -60,7 +61,7 @@
virtual void exit() {}
};
- class _CoreExport Shell : public Singleton<Shell>, virtual public OrxonoxClass, public OutputBufferListener
+ class _CoreExport Shell : public Singleton<Shell>, virtual public OrxonoxClass, public OutputListener
{
friend class Singleton<Shell>;
public:
@@ -70,7 +71,7 @@
static void clearShell();
static void history();
- virtual void setConfigValues();
+ void setConfigValues();
void commandHistoryOffsetChanged();
void commandHistoryLengthChanged();
@@ -79,8 +80,6 @@
inline InputBuffer* getInputBuffer()
{ return this->inputBuffer_; }
- inline OutputBuffer& getOutputBuffer()
- { return this->outputBuffer_; }
void setCursorPosition(unsigned int cursor);
inline unsigned int getCursorPosition() const
@@ -116,6 +115,7 @@
std::string getFromHistory() const;
virtual void outputChanged();
+
void inputChanged();
void execute();
void hintandcomplete();
@@ -143,7 +143,7 @@
std::list<ShellListener*> listeners_;
InputBuffer* inputBuffer_;
- OutputBuffer outputBuffer_;
+ std::stringstream outputBuffer_;
bool finishedLastLine_;
std::list<std::string> lines_;
std::list<std::string>::const_iterator scrollIterator_;
@@ -153,6 +153,7 @@
unsigned int historyPosition_;
unsigned int historyOffset_;
bool bAddOutputLevel_;
+ int softDebugLevel_;
ConfigFileType commandHistoryConfigFileType_;
Modified: code/branches/console/src/libraries/util/CMakeLists.txt
===================================================================
--- code/branches/console/src/libraries/util/CMakeLists.txt 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/CMakeLists.txt 2009-10-27 13:47:14 UTC (rev 5994)
@@ -28,7 +28,6 @@
Clock.cc
CRC32.cc
ExprParser.cc
- OutputBuffer.cc
OutputHandler.cc
SignalHandler.cc
Sleep.cc
Modified: code/branches/console/src/libraries/util/Debug.h
===================================================================
--- code/branches/console/src/libraries/util/Debug.h 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/Debug.h 2009-10-27 13:47:14 UTC (rev 5994)
@@ -75,9 +75,11 @@
}
/**
- at def COUT
+ at brief
Logs text output: use exactly like std::cout, but specify an output
- level as argument. For example COUT(3) << "Some info" << std::endl;
+ level as argument.
+ at example
+ COUT(3) << "Some info" << std::endl;
@note
The ? : operator requires both possible results to have the type of
the first. This is achieved by the int conversion operator dummy
Modified: code/branches/console/src/libraries/util/OrxAssert.h
===================================================================
--- code/branches/console/src/libraries/util/OrxAssert.h 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/OrxAssert.h 2009-10-27 13:47:14 UTC (rev 5994)
@@ -43,7 +43,7 @@
// define an assert macro that can display a message
#ifndef NDEBUG
#define OrxAssert(Assertion, ErrorMessage) \
- Assertion ? ((void)0) : (void)(orxonox::OutputHandler::getOutStream().setOutputLevel(1) << ErrorMessage << std::endl); \
+ Assertion ? ((void)0) : (void)(orxonox::OutputHandler::getOutStream(1) << ErrorMessage << std::endl); \
assert(Assertion)
#else
#define OrxAssert(condition, errorMessage) ((void)0)
Deleted: code/branches/console/src/libraries/util/OutputBuffer.cc
===================================================================
--- code/branches/console/src/libraries/util/OutputBuffer.cc 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/OutputBuffer.cc 2009-10-27 13:47:14 UTC (rev 5994)
@@ -1,127 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-/**
- @file
- @brief Implementation of the OutputBuffer.
-*/
-
-#include "OutputBuffer.h"
-
-namespace orxonox
-{
- /**
- @brief Adds a new listener to the list.
- @param listener The new listener
- */
- void OutputBuffer::registerListener(OutputBufferListener* listener)
- {
- this->listeners_.push_back(listener);
- }
-
- /**
- @brief Removes a listener from the list.
- @param listener The listener
- */
- void OutputBuffer::unregisterListener(OutputBufferListener* listener)
- {
- for (std::vector<OutputBufferListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
- {
- if ((*it) == listener)
- it = this->listeners_.erase(it);
- else
- ++it;
- }
- }
-
- /**
- @brief Puts a stream manipulator to the stream.
- @param manipulator The manipulator
- */
- OutputBuffer& OutputBuffer::operator<<(std::ostream& (*manipulator)(std::ostream&))
- {
- this->stream_ << manipulator;
- this->callListeners();
- return *this;
- }
-
- /**
- @brief Puts a stream manipulator to the stream.
- @param manipulator The manipulator
- */
- OutputBuffer& OutputBuffer::operator<<(std::ios& (*manipulator)(std::ios&))
- {
- this->stream_ << manipulator;
- this->callListeners();
- return *this;
- }
-
- /**
- @brief Puts a stream manipulator to the stream.
- @param manipulator The manipulator
- */
- OutputBuffer& OutputBuffer::operator<<(std::ios_base& (*manipulator)(std::ios_base&))
- {
- this->stream_ << manipulator;
- this->callListeners();
- return *this;
- }
-
- /**
- @brief Removes the first line from the stream and assigns it to a given string object.
- @param output The string object to assign the first line
- @return True if there was at least one line in the stream and this line was successfully assigned
-
- It's important to know the returned line will be removed from the stream. If there are more than one
- listener, they have to cooperate to avoid conflicts.
- */
- bool OutputBuffer::getLine(std::string* output)
- {
- std::getline(this->stream_, *output);
-
- bool eof = this->stream_.eof();
- bool fail = this->stream_.fail();
-
- if (eof)
- this->stream_.flush();
-
- if (eof || fail)
- this->stream_.clear();
-
- return (!eof && !fail);
- }
-
- /**
- @brief Calls the outputChanged() function of all registered listeners.
- */
- void OutputBuffer::callListeners()
- {
- for (std::vector<OutputBufferListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
- (*it)->outputChanged();
- }
-}
Deleted: code/branches/console/src/libraries/util/OutputBuffer.h
===================================================================
--- code/branches/console/src/libraries/util/OutputBuffer.h 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/OutputBuffer.h 2009-10-27 13:47:14 UTC (rev 5994)
@@ -1,173 +0,0 @@
-/*
- * ORXONOX - the hottest 3D action shooter ever to exist
- * > www.orxonox.net <
- *
- *
- * License notice:
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Author:
- * Fabian 'x3n' Landau
- * Co-authors:
- * ...
- *
- */
-
-/**
- @file
- @brief Declaration of the OutputBuffer class.
-
- The OutputBuffer acts almost like std::ostream. You can put text and other values to the
- OutputBuffer by using the << operator. The OutputBuffer stores the text and calls registerd
- listeners if new text gets assigned.
- The listeners are then able to retrieve the text line by line.
-
- It's important to know that getLine actually removes the line from the OutputBuffer, so it's
- better to only have one "active" listener.
-*/
-
-#ifndef _OutputBuffer_H__
-#define _OutputBuffer_H__
-
-#include "UtilPrereqs.h"
-
-#include <vector>
-#include <sstream>
-
-namespace orxonox
-{
- /**
- @brief A pure virtual baseclass for classes that want to register as listener to an OutputBuffer.
-
- This class is pure virtual, so an inheriting class has to implement the function on it's own.
- The function get's called, if an instance of the inheriting class registers as a listener at
- an OutputBuffer and this buffer changes.
- */
- class OutputBufferListener
- {
- friend class OutputBuffer;
-
- public:
- virtual ~OutputBufferListener() {}
-
- private:
- virtual void outputChanged() = 0;
- };
-
- /**
- @brief The OutputBuffer acts almost like std::ostream and stores the assigned text.
-
- If text gets assigned by using the << operator or another function, the OutputBuffer
- calls it's listeners, allowing them to retrieve the text line by line.
-
- It's important to know that getLine actually removes the line from the OutputBuffer, so it's
- better to only have one "active" listener.
- */
- class _UtilExport OutputBuffer
- {
- public:
- OutputBuffer() {}
- ~OutputBuffer() {}
-
- /**
- @brief Puts some object/value to the OutputBuffer. The text gets assigned and the OutputBuffer calls it's listeners.
- @param object The object/value to assign
- */
- template <class T>
- inline OutputBuffer& operator<<(T object)
- {
- this->stream_ << object;
- this->callListeners();
- return *this;
- }
-
- /**
- @brief Reads the stored text of the other OutputBuffer and calls the listeners.
- @param object The other OutputBuffer
- */
- template <const OutputBuffer&>
- inline OutputBuffer& operator<<(const OutputBuffer& object)
- {
- this->stream_ << object.stream_.rdbuf();
- this->callListeners();
- return *this;
- }
-
- OutputBuffer& operator<<(std::ostream& (*manipulator)(std::ostream&));
- OutputBuffer& operator<<(std::ios& (*manipulator)(std::ios&));
- OutputBuffer& operator<<(std::ios_base& (*manipulator)(std::ios_base&));
-
- /**
- @brief Does the same like operator<<: Assigns the object to the stream and calls the listeners.
- @param object The object/value
- */
- template <class T>
- inline void add(T object)
- {
- this->stream_ << object;
- this->callListeners();
- }
-
- /**
- @brief Assigns an object/value and adds std::endl.
- @param object The object/value
- */
- template <class T>
- inline void addLine(T object)
- {
- this->stream_ << object << std::endl;
- this->callListeners();
- }
-
- /**
- @brief Puts std::endl to the stream and calls the listeners.
- */
- inline void newline()
- {
- this->stream_ << std::endl;
- this->callListeners();
- }
-
- /**
- @brief Flushes the stored text (~empties the OutputBuffer).
- */
- inline void flush()
- {
- this->stream_.flush();
- }
-
- bool getLine(std::string* output);
-
- void registerListener(OutputBufferListener* listener);
- void unregisterListener(OutputBufferListener* listener);
-
- /**
- @brief Returns the internal stringstream object.
- */
- inline std::stringstream& getStream()
- {
- return this->stream_;
- }
-
- private:
- void callListeners();
-
- std::stringstream stream_; //!< The stringstream that stores the assigned text
- std::vector<OutputBufferListener*> listeners_; //!< A list of all listeners
- };
-}
-
-#endif /* _OutputBuffer_H__ */
Modified: code/branches/console/src/libraries/util/OutputHandler.cc
===================================================================
--- code/branches/console/src/libraries/util/OutputHandler.cc 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/OutputHandler.cc 2009-10-27 13:47:14 UTC (rev 5994)
@@ -22,210 +22,224 @@
* Author:
* Fabian 'x3n' Landau
* Co-authors:
- * ...
+ * Reto Grieder
*
*/
/**
- @file
- @brief Implementation of the OutputHandler class.
+ at file
+ at brief
+ Definition of classes related to output (logging).
*/
#include "OutputHandler.h"
+#include <algorithm>
#include <ctime>
#include <cstdlib>
+#include <fstream>
+#include <sstream>
+#include "Debug.h"
+
namespace orxonox
{
+ //! How the log file shall be named on the filesystem
+ const std::string logFileBaseName_g = "orxonox.log";
+
+ /////////////////////////
+ ///// LogFileWriter /////
+ /////////////////////////
/**
- @brief Constructor: Opens the logfile and writes the first line.
- @param logfilename The name of the logfile
+ @brief
+ Writes the output to the log file.
+ @note
+ As long as the correct log path is not yet known (for pre main code), the
+ LogFileWriter will write to a temporary file in /temp (Unix) or %TEMP% (Windows).
+ As soon as you set the correct path setLogPath the content of the temporary file
+ is read and put into the new file as well.
*/
- OutputHandler::OutputHandler()
+ class LogFileWriter : public OutputListener
{
+ public:
+ //! Gets temporary log path and starts the log file
+ LogFileWriter()
+ : OutputListener(OutputHandler::logFileOutputListenerName_s)
+ {
+ // Get path for a temporary file
#ifdef ORXONOX_PLATFORM_WINDOWS
- char* pTempDir = getenv("TEMP");
- this->logfilename_ = std::string(pTempDir) + "/orxonox.log";
+ char* pTempDir = getenv("TEMP");
+ this->logFilename_ = std::string(pTempDir) + "/" + logFileBaseName_g;
#else
- this->logfilename_ = "/tmp/orxonox.log";
+ this->logFilename_ = std::string("/tmp/") + logFileBaseName_g;
#endif
-#ifdef NDEBUG
- this->softDebugLevel_[LD_All] = this->softDebugLevel_[LD_Logfile] = 2;
- this->softDebugLevel_[LD_Console] = this->softDebugLevel_[LD_Shell] = 1;
-#else
- this->softDebugLevel_[LD_All] = this->softDebugLevel_[LD_Logfile] = 3;
- this->softDebugLevel_[LD_Console] = this->softDebugLevel_[LD_Shell] = 2;
-#endif
- this->outputBuffer_ = &this->fallbackBuffer_;
- this->logfile_.open(this->logfilename_.c_str(), std::fstream::out);
+ // Get current time
+ time_t rawtime;
+ struct tm* timeinfo;
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
- time_t rawtime;
- struct tm* timeinfo;
- time(&rawtime);
- timeinfo = localtime(&rawtime);
+ this->logFile_.open(this->logFilename_.c_str(), std::fstream::out);
+ this->logFile_ << "Started log on " << asctime(timeinfo) << std::endl;
+ this->logFile_.flush();
- this->logfile_ << "Started log on " << asctime(timeinfo) << std::endl;
- this->logfile_.flush();
- }
+ this->outputStream_ = &this->logFile_;
+ // Use default level until we get the configValue from the Core
+ OutputHandler::getInstance().setSoftDebugLevel(this->getOutputListenerName(), OutputLevel::Debug);
+ OutputHandler::getInstance().registerOutputListener(this);
+ }
+ //! Closes the log file
+ ~LogFileWriter()
+ {
+ this->logFile_ << "Closed log" << std::endl;
+ this->logFile_.close();
+ }
+
+ //! Changes the log path
+ void setLogPath(const std::string& path)
+ {
+ this->logFile_.close();
+ // Read old file into a buffer
+ std::ifstream old(this->logFilename_.c_str());
+ this->logFilename_ = path + logFileBaseName_g;
+ // Open the new file and feed it the content of the old one
+ this->logFile_.open(this->logFilename_.c_str(), std::fstream::out);
+ this->logFile_ << old.rdbuf();
+ this->logFile_.flush();
+ old.close();
+ }
+
+ private:
+ std::ofstream logFile_; //! File handle for the log file
+ std::string logFilename_; //! Filename of the log file
+ };
+
+
+ ///////////////////////////
+ ///// MemoryLogWriter /////
+ ///////////////////////////
/**
- @brief Destructor: Writes the last line to the logfile and closes it.
+ @brief
+ OutputListener that writes all the output piece by piece to an array
+ associated with the corresponding output level.
+ @note
+ Only output below or equal to the current soft debug level is written
+ to minimise huge arrays for the normal run.
*/
- OutputHandler::~OutputHandler()
+ class MemoryLogWriter : public OutputListener
{
- this->logfile_ << "Closed log" << std::endl;
- this->logfile_.close();
- }
+ public:
+ friend class OutputHandler;
- /**
- @brief Returns a reference to the only existing instance of the OutputHandler class.
- @return The instance
- */
- OutputHandler& OutputHandler::getOutStream()
+ //! Sets the right soft debug level and registers itself
+ MemoryLogWriter()
+ : OutputListener("memoryLog")
+ {
+ this->outputStream_ = &this->buffer_;
+ // We capture as much input as the listener with the highest level
+ OutputHandler::getInstance().setSoftDebugLevel(this->getOutputListenerName(), OutputHandler::getSoftDebugLevel());
+ OutputHandler::getInstance().registerOutputListener(this);
+ }
+
+ //! Pushed the just written output to the internal array
+ void outputChanged()
+ {
+ // Read ostringstream and store it
+ this->output_.push_back(std::make_pair(OutputHandler::getInstance().getOutputLevel(), this->buffer_.str()));
+ // Clear content and flags
+ this->buffer_.str(std::string());
+ this->buffer_.clear();
+ }
+
+ private:
+ std::ostringstream buffer_; //! Stream object used to process the output
+ std::vector<std::pair<int, std::string> > output_; //! Vector containing ALL output
+ };
+
+
+ /////////////////////////
+ ///// OutputHandler /////
+ /////////////////////////
+ const std::string OutputHandler::logFileOutputListenerName_s = "logFile";
+ int OutputHandler::softDebugLevel_s = hardDebugLevel;
+
+ //! Creates the LogFileWriter and the MemoryLogWriter
+ OutputHandler::OutputHandler()
+ : outputLevel_(OutputLevel::Verbose)
{
- static OutputHandler orxout;
- return orxout;
+ this->logFile_ = new LogFileWriter();
+ this->output_ = new MemoryLogWriter();
}
- /**
- @brief Sets the soft debug level for a given output device.
- @param device The output device
- @param level The debug level
- */
- void OutputHandler::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
+ //! Destroys the LogFileWriter and the MemoryLogWriter
+ OutputHandler::~OutputHandler()
{
- OutputHandler::getOutStream().softDebugLevel_[static_cast<unsigned int>(device)] = level;
+ delete this->logFile_;
+ delete this->output_;
}
- /**
- @brief Returns the soft debug level for a given output device.
- @param device The output device
- @return The debug level
- */
- int OutputHandler::getSoftDebugLevel(OutputHandler::OutputDevice device)
+ OutputHandler& OutputHandler::getInstance()
{
- return OutputHandler::getOutStream().softDebugLevel_[static_cast<unsigned int>(device)];
+ static OutputHandler orxout;
+ return orxout;
}
- /**
- @brief Sets the OutputBuffer, representing the third output stream.
- @param buffer The OutputBuffer
- */
- void OutputHandler::setOutputBuffer(OutputBuffer* buffer)
+ void OutputHandler::registerOutputListener(OutputListener* listener)
{
- if (buffer == NULL)
- this->outputBuffer_ = &this->fallbackBuffer_;
- else
+ for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
{
- buffer->getStream() >> this->outputBuffer_->getStream().rdbuf();
- this->outputBuffer_ = buffer;
+ if ((*it)->name_ == listener->name_)
+ {
+ COUT(2) << "OutputHandler, Warning: Trying to register two listeners with the same name!" << std::endl;
+ return;
+ }
}
+ this->listeners_.push_back(listener);
}
- /**
- @brief Sets the path where to create orxonox.log
- @param Path string with trailing slash
- */
+ void OutputHandler::unregisterOutputListener(OutputListener* listener)
+ {
+ this->listeners_.remove(listener);
+ }
+
void OutputHandler::setLogPath(const std::string& path)
{
- OutputHandler::getOutStream().logfile_.close();
- // store old content
- std::ifstream old;
- old.open(OutputHandler::getOutStream().logfilename_.c_str());
- OutputHandler::getOutStream().logfilename_ = path + "orxonox.log";
- OutputHandler::getOutStream().logfile_.open(OutputHandler::getOutStream().logfilename_.c_str(), std::fstream::out);
- OutputHandler::getOutStream().logfile_ << old.rdbuf();
- old.close();
- OutputHandler::getOutStream().logfile_.flush();
+ this->logFile_->setLogPath(path);
}
- /**
- @brief Overloaded << operator, redirects the output to the console and the logfile.
- @param sb The streambuffer that should be shown in the console
- @return A reference to the OutputHandler itself
- */
- OutputHandler& OutputHandler::operator<<(std::streambuf* sb)
+ OutputHandler::OutputVectorIterator OutputHandler::getOutputVectorBegin() const
{
- //if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
- // std::cout << sb;
-
- if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
- {
- this->logfile_ << sb;
- this->logfile_.flush();
- }
-
- if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
- (*this->outputBuffer_) << sb;
-
- return *this;
+ return this->output_->output_.begin();
}
- /**
- @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
- @param manipulator A function, manipulating the outstream.
- @return A reference to the OutputHandler itself
- */
- OutputHandler& OutputHandler::operator<<(std::ostream& (*manipulator)(std::ostream&))
+ OutputHandler::OutputVectorIterator OutputHandler::getOutputVectorEnd() const
{
- //if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
- // manipulator(std::cout);
-
- if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
- {
- manipulator(this->logfile_);
- this->logfile_.flush();
- }
-
- if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
- (*this->outputBuffer_) << manipulator;
-
- return *this;
+ return this->output_->output_.end();
}
- /**
- @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
- @param manipulator A function, manipulating the outstream.
- @return A reference to the OutputHandler itself
- */
- OutputHandler& OutputHandler::operator<<(std::ios& (*manipulator)(std::ios&))
+ int OutputHandler::getSoftDebugLevel(const std::string& name) const
{
- //if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
- // manipulator(std::cout);
-
- if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
+ for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
{
- manipulator(this->logfile_);
- this->logfile_.flush();
+ if ((*it)->name_ == name)
+ return (*it)->softDebugLevel_;
}
-
- if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
- (*this->outputBuffer_) << manipulator;
-
- return *this;
+ return -1;
}
- /**
- @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
- @param manipulator A function, manipulating the outstream.
- @return A reference to the OutputHandler itself
- */
- OutputHandler& OutputHandler::operator<<(std::ios_base& (*manipulator)(std::ios_base&))
+ void OutputHandler::setSoftDebugLevel(const std::string& name, int level)
{
- //if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
- // manipulator(std::cout);
-
- if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
+ int globalSoftDebugLevel = -1;
+ for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
{
- manipulator(this->logfile_);
- this->logfile_.flush();
+ if ((*it)->name_ == name)
+ (*it)->softDebugLevel_ = level;
+ if ((*it)->softDebugLevel_ > globalSoftDebugLevel)
+ globalSoftDebugLevel = (*it)->softDebugLevel_;
}
-
- if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
- (*this->outputBuffer_) << manipulator;
-
- return *this;
+ // Update global soft debug level
+ OutputHandler::softDebugLevel_s = globalSoftDebugLevel;
}
}
Modified: code/branches/console/src/libraries/util/OutputHandler.h
===================================================================
--- code/branches/console/src/libraries/util/OutputHandler.h 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/OutputHandler.h 2009-10-27 13:47:14 UTC (rev 5994)
@@ -22,16 +22,14 @@
* Author:
* Fabian 'x3n' Landau
* Co-authors:
- * ...
+ * Reto Grieder
*
*/
/**
- @file
- @brief Definition of the OutputHandler class.
-
- The OutputHandler acts like std::cout, but output isn't only shown in the console,
- but also written to the logfile and the ingame shell.
+ at file
+ at brief
+ Declaration of classes related to output (logging).
*/
#ifndef _OutputHandler_H__
@@ -39,14 +37,26 @@
#include "UtilPrereqs.h"
-#include <iostream>
-#include <fstream>
+#include <list>
+#include <ostream>
#include <string>
+#include <vector>
+#include <utility>
-#include "OutputBuffer.h"
-
namespace orxonox
{
+ /**
+ @brief
+ Denotes different levels of text output (log output)
+
+ 0, None : Very important output
+ 1, Error : Errors
+ 2, Warning: Warnings
+ 3, Info : Information
+ 4, Debug : Debug information
+ 5, Verbose: More debug information
+ 6, Ultra : Crazy debug information
+ */
namespace OutputLevel
{
enum Value
@@ -61,165 +71,197 @@
};
}
- //! The OutputHandler acts like std::cout, but redirects output to the console, the logfile and the ingame shell.
+ // Forward declarations for classes in the source file
+ class LogFileWriter;
+ class MemoryLogWriter;
+
+ /**
+ @brief
+ The OutputHandler acts like std::cout, but output isn't only shown in the console.
+
+ You can register your own listener for output by inheriting from OutputListner.
+ And if you need the output previously processed, iterate over it with
+ OutputHandler::getOutputVector[Begin/End].
+ The way to output text is to first set the desired output level with
+ OutputHandler::getOutStream(level) and then use the "<<" operator like with std::cout.
+ */
class _UtilExport OutputHandler
{
public:
- enum OutputDevice
- {
- LD_All = 0,
- LD_Console = 1,
- LD_Logfile = 2,
- LD_Shell = 3
- };
+ //! Returns a reference to the only existing instance of the OutputHandler class.
+ static OutputHandler& getInstance();
- static OutputHandler& getOutStream();
+ //! Sets the output level and returns a stream to be used with "<<"
static inline OutputHandler& getOutStream(int level)
- { return OutputHandler::getOutStream().setOutputLevel(level); }
+ { return OutputHandler::getInstance().setOutputLevel(level); }
- /** @brief Puts some text on the outstream. @param text The text */
+ typedef std::vector<std::pair<int, std::string> >::const_iterator OutputVectorIterator;
+ //! Returns an iterator to the beginning of the all-output vector
+ OutputVectorIterator getOutputVectorBegin() const;
+ //! Returns an iterator to the end of the all-output vector
+ OutputVectorIterator getOutputVectorEnd() const;
+
+ //! Writes to all output devices
static inline const std::string& log(const std::string& text)
- { OutputHandler::getOutStream().setOutputLevel(0); OutputHandler::getOutStream().output(text + "\n"); return text; }
+ { OutputHandler::getOutStream(0).output(text) << std::endl; return text; }
- /** @brief Puts an error on the outstream. @param text The text */
+ //! Writes an error message to the output
static inline const std::string& error(const std::string& text)
- { OutputHandler::getOutStream().setOutputLevel(1); OutputHandler::getOutStream().output(text + "\n"); return text; }
+ { OutputHandler::getOutStream(1).output(text) << std::endl; return text; }
- /** @brief Puts a warning on the outstream. @param text The text */
+ //! Writes a warning message to the output
static inline const std::string& warning(const std::string& text)
- { OutputHandler::getOutStream().setOutputLevel(2); OutputHandler::getOutStream().output(text + "\n"); return text; }
+ { OutputHandler::getOutStream(2).output(text) << std::endl; return text; }
- /** @brief Puts an info on the outstream. @param text The text */
+ //! Writes an informational message to the output
static inline const std::string& info(const std::string& text)
- { OutputHandler::getOutStream().setOutputLevel(3); OutputHandler::getOutStream().output(text + "\n"); return text; }
+ { OutputHandler::getOutStream(3).output(text) << std::endl; return text; }
- /** @brief Puts some debug output on the outstream. @param text The text */
+ //! Writes a debug message to the output
static inline const std::string& debug(const std::string& text)
- { OutputHandler::getOutStream().setOutputLevel(4); OutputHandler::getOutStream().output(text + "\n"); return text; }
+ { OutputHandler::getOutStream(4).output(text) << std::endl; return text; }
- /** @brief Returns a reference to the logfile. @return The logfile */
- inline std::ofstream& getLogfile()
- { return this->logfile_; }
+ //! Registers an object that receives output via a provided std::ostream
+ void registerOutputListener(OutputListener* listener);
+ //! Unregisters an object that receives output via a provided std::ostream
+ void unregisterOutputListener(OutputListener* listener);
- /** @brief Returns a pointer to the OutputBuffer. @return The OutputBuffer */
- inline OutputBuffer* getOutputBuffer()
- { return this->outputBuffer_; }
+ //! Set the log path once the program has been properly initialised
+ void setLogPath(const std::string& path);
- /** @brief Sets the level of the incoming output. @param level The level of the incoming output @return The OutputHandler itself */
+ //! Sets the level of the incoming output and returns the OutputHandler
inline OutputHandler& setOutputLevel(int level)
{ this->outputLevel_ = level; return *this; }
- /** @brief Returns the level of the incoming output. @return The level */
+ //! Returns the level of the incoming output
inline int getOutputLevel() const
{ return this->outputLevel_; }
- static void setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
- static int getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
+ //! Returns the maximum debug level over all registered listeners (devices)
+ static int getSoftDebugLevel() { return softDebugLevel_s; }
+ //! Returns the soft debug level for a device by its name @return The level or -1 if the listener was not found
+ int getSoftDebugLevel(const std::string& name) const;
+ //! Sets the soft debug level for a listener by its name
+ void setSoftDebugLevel(const std::string& name, int level);
- static void setLogPath(const std::string& path);
-
- void setOutputBuffer(OutputBuffer* buffer);
-
+ /**
+ @brief
+ General template that copes with all output.
+ Required because operator << might be ambiguous.
+ @a output will be streamed into every listener with an appropriate debug level
+ @return
+ Returns a reference to the OutputHandler so you can use it again directly
+ */
template <class T>
OutputHandler& output(const T& output);
- /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+ //! Overloaded << operator, redirects the output to the listeners
inline OutputHandler& operator<<(unsigned char val) { return this->output(val); }
- /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+ //! Overloaded << operator, redirects the output to the listeners
inline OutputHandler& operator<<(short val) { return this->output(val); }
- /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+ //! Overloaded << operator, redirects the output to the listeners
inline OutputHandler& operator<<(unsigned short val) { return this->output(val); }
- /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+ //! Overloaded << operator, redirects the output to the listeners
inline OutputHandler& operator<<(int val) { return this->output(val); }
- /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+ //! Overloaded << operator, redirects the output to the listeners
inline OutputHandler& operator<<(unsigned int val) { return this->output(val); }
- /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+ //! Overloaded << operator, redirects the output to the listeners
inline OutputHandler& operator<<(long val) { return this->output(val); }
- /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+ //! Overloaded << operator, redirects the output to the listeners
inline OutputHandler& operator<<(unsigned long val) { return this->output(val); }
- /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+ //! Overloaded << operator, redirects the output to the listeners
inline OutputHandler& operator<<(long long val) { return this->output(val); }
- /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+ //! Overloaded << operator, redirects the output to the listeners
inline OutputHandler& operator<<(unsigned long long val) { return this->output(val); }
- /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+ //! Overloaded << operator, redirects the output to the listeners
inline OutputHandler& operator<<(float val) { return this->output(val); }
- /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+ //! Overloaded << operator, redirects the output to the listeners
inline OutputHandler& operator<<(double val) { return this->output(val); }
- /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+ //! Overloaded << operator, redirects the output to the listeners
inline OutputHandler& operator<<(long double val) { return this->output(val); }
- /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+ //! Overloaded << operator, redirects the output to the listeners
inline OutputHandler& operator<<(const void* val) { return this->output(val); }
- /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+ //! Overloaded << operator, redirects the output to the listeners
inline OutputHandler& operator<<(bool val) { return this->output(val); }
- OutputHandler& operator<<(std::streambuf* sb);
+ //! Overloaded << operator, redirects the output to the listeners
+ inline OutputHandler& operator<<(std::streambuf* sb) { return this->output(sb); }
- OutputHandler& operator<<(std::ostream& (*manipulator)(std::ostream&));
- OutputHandler& operator<<(std::ios& (*manipulator)(std::ios&));
- OutputHandler& operator<<(std::ios_base& (*manipulator)(std::ios_base&));
+ //! Overloaded << operator, redirect the output of classes with self defined 'operator <<' to the listeners
+ template <class T>
+ inline OutputHandler& operator<<(const T& val) { return this->output(val); }
- /** @brief Dummy operator required by Debug.h for the ternary operator */
- inline operator int() { return 0; }
+ //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
+ inline OutputHandler& operator<<(std::ostream& (*manip)(std::ostream&)) { return this->output(manip); }
+ //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
+ inline OutputHandler& operator<<(std::ios& (*manip)(std::ios&)) { return this->output(manip); }
+ //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
+ inline OutputHandler& operator<<(std::ios_base& (*manip)(std::ios_base&)) { return this->output(manip); }
+ //! Dummy operator required by Debug.h for the ternary operator
+ inline operator int() const { return 0; }
+
+ //! Name of the OutputListener that writes to the log file
+ static const std::string logFileOutputListenerName_s;
+
private:
- explicit OutputHandler();
- OutputHandler(const OutputHandler& oh);
- virtual ~OutputHandler();
+ OutputHandler();
+ ~OutputHandler();
+ OutputHandler(const OutputHandler& rhs); //! Unused and undefined
- std::ofstream logfile_; //!< The logfile where the output is logged
- std::string logfilename_; //!< The name of the logfile
- OutputBuffer fallbackBuffer_; //!< The OutputBuffer that gets used if there is no other OutputBuffer
- OutputBuffer* outputBuffer_; //!< The OutputBuffer to put output in (usually used by the Shell)
- int outputLevel_; //!< The level of the incoming output
- int softDebugLevel_[4]; //!< The soft debug level for each OutputDevice - the configurable maximal output level
+ std::list<OutputListener*> listeners_; //!< Array with all registered output listeners
+ int outputLevel_; //!< The level of the incoming output
+ LogFileWriter* logFile_; //!< Listener that writes to the log file
+ MemoryLogWriter* output_; //!< Listener that Stores ALL output below the current soft debug level
+ static int softDebugLevel_s; //!< Maximum of all soft debug levels. @note This is only static for faster access
};
- /**
- @brief Redirects the output to the console and the logfile.
- @param output The value that should be shown in the console
- @return A reference to the OutputHandler itself
- */
template<class T>
- OutputHandler& OutputHandler::output(const T& output)
+ inline OutputHandler& OutputHandler::output(const T& output)
{
- //if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
- // std::cout << output;
-
- if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
+ for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
{
- this->logfile_ << output;
- this->logfile_.flush();
+ if (this->outputLevel_ <= (*it)->softDebugLevel_ && (*it)->outputStream_ != NULL)
+ {
+ std::ostream& stream = *((*it)->outputStream_);
+ stream << output;
+ stream.flush();
+ (*it)->outputChanged();
+ }
}
- if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
- (*this->outputBuffer_) << output;
-
return *this;
}
/**
- @brief Overloading of the non-member << operator to redirect the output of classes with self defined '<< to std::ostream' operators to the console and the logfile.
- @param out The OutputHandler itself
- @param output The class that should be shown in the console
- @return The OutputHandler itself
+ @brief
+ Interface for listening to output.
+ @remarks
+ Remember to register the listener (not done automatically!)
*/
- template<class T>
- OutputHandler& operator<<(OutputHandler& out, const T& output)
+ class OutputListener
{
- //if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Console) >= out.getOutputLevel())
- // std::cout << output;
+ friend class OutputHandler;
- if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Logfile) >= out.getOutputLevel())
- {
- out.getLogfile() << output;
- out.getLogfile().flush();
- }
+ public:
+ OutputListener(const std::string& name)
+ : outputStream_(NULL)
+ , name_(name)
+ {}
+ virtual ~OutputListener() {}
- if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= out.getOutputLevel())
- (*out.getOutputBuffer()) << output;
+ //! Gets called whenever output is put into the stream
+ virtual void outputChanged() {}
+ //! Returns the name of this output listener
+ const std::string& getOutputListenerName() const { return this->name_; }
- return out;
- }
+ protected:
+ std::ostream* outputStream_; //!< Pointer to the associated output stream, can be NULL
+
+ private:
+ const std::string name_; //!< Name of the listener, constant and unique!
+ int softDebugLevel_; //!< Current soft debug level that defines what kind of output is written to the stream
+ };
}
#endif /* _OutputHandler_H__ */
Modified: code/branches/console/src/libraries/util/UtilPrereqs.h
===================================================================
--- code/branches/console/src/libraries/util/UtilPrereqs.h 2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/UtilPrereqs.h 2009-10-27 13:47:14 UTC (rev 5994)
@@ -86,9 +86,8 @@
class IntVector2;
class IntVector3;
class MultiType;
- class OutputBuffer;
- class OutputBufferListener;
class OutputHandler;
+ class OutputListener;
template <ScopeID::Value>
class Scope;
template <class, ScopeID::Value>
More information about the Orxonox-commit
mailing list