diff --git a/eo/src/utils/eoLogger.cpp b/eo/src/utils/eoLogger.cpp index cd80ba67e..8a2c37831 100644 --- a/eo/src/utils/eoLogger.cpp +++ b/eo/src/utils/eoLogger.cpp @@ -37,6 +37,7 @@ Caner Candan #include // used to define EOF #include +#include // std::find #include "eoLogger.h" @@ -45,6 +46,13 @@ add a possibility to redirect to several streams add_redirect/remove_redirect */ +#ifdef USE_SET +typedef std::set::iterator StreamIter; +#else +typedef std::vector::iterator StreamIter; +#endif + + void eoLogger::_init() { @@ -61,7 +69,7 @@ void eoLogger::_init() } eoLogger::eoLogger() : - std::ostream(NULL), + std::ostream(NULL), _verbose("quiet", "verbose", "Set the verbose level", 'v'), _printVerboseLevels(false, "print-verbose-levels", "Print verbose levels", 'l'), @@ -71,16 +79,16 @@ eoLogger::eoLogger() : _contextLevel(eo::quiet), _obuf(_contextLevel, _selectedLevel) { - std::ostream::init(&_obuf); + std::ostream::init(&_obuf); _init(); } eoLogger::~eoLogger() { - //redirect(NULL); - if (_obuf._ownedFileStream != NULL) { - delete _obuf._ownedFileStream; - } + //redirect(NULL); + if (_obuf._ownedFileStream != NULL) { + delete _obuf._ownedFileStream; + } } void eoLogger::_createParameters( eoParser& parser ) @@ -161,29 +169,97 @@ eoLogger& operator<<(eoLogger& l, eo::setlevel v) eoLogger& operator<<(eoLogger& l, std::ostream& os) { - l._obuf._outStream = &os; +#warning deprecated + l.addRedirect(os); return l; } void eoLogger::redirect(std::ostream& os) { - if (_obuf._ownedFileStream != NULL) { - delete _obuf._ownedFileStream; - _obuf._ownedFileStream = NULL; - } - _obuf._outStream = &os; + doRedirect(&os); +} + +void eoLogger::doRedirect(std::ostream* os) +{ + if (_obuf._ownedFileStream != NULL) { + delete _obuf._ownedFileStream; + _obuf._ownedFileStream = NULL; + } + _obuf._outStreams.clear(); + if (os != NULL) + //_obuf._outStreams.push_back(os); + #ifdef USE_SET + _obuf._outStreams.insert(os); + #else + _obuf._outStreams.push_back(os); + #endif +} + +void eoLogger::addRedirect(std::ostream& os) +{ + /* + if (tryRemoveRedirect(&os)) + //throw eoWrongParamTypeException("Cannot redirect the logger to a stream it is already redirected to"); + //eo::log << eo::warnings << "Cannot redirect the logger to a stream it is already redirected to."; + { eo::log << eo::warnings << "Cannot redirect the logger to a stream it is already redirected to."; std::cout << "OK!!!" << std::endl; }*/ + bool already_there = tryRemoveRedirect(&os); + //_obuf._outStreams.push_back(&os); +#ifdef USE_SET + _obuf._outStreams.insert(&os); +#else + _obuf._outStreams.push_back(&os); +#endif + if (already_there) + eo::log << eo::warnings << "Cannot redirect the logger to a stream it is already redirected to." << std::endl; +} + +void eoLogger::removeRedirect(std::ostream& os) +{ + if (!tryRemoveRedirect(&os)) + //throw eoWrongParamTypeException("Cannot remove from the logger a stream it was not redirected to"); + //throw eoWrongParamTypeException(std::string("Cannot remove from the logger a stream it was not redirected to")); + eo::log << eo::warnings << "Cannot remove from the logger a stream it was not redirected to."; +} + +bool eoLogger::tryRemoveRedirect(std::ostream* os) +{ + /* + std::vector::iterator it = find(_obuf._outStreams.begin(), _obuf._outStreams.end(), os); + //std::cout << _obuf._outStreams.size() << " " << (void*)&*_obuf._outStreams.begin() << " " << (void*)&*_obuf._outStreams.end() << std::endl; + //std::cout << "it: " << (void*)&*it << " " << (void*)os << std::endl; + if (it == _obuf._outStreams.end()) + return false; + _obuf._outStreams.erase(it); + return true;*/ + /* +#ifdef USE_SET + std::set::iterator it = find(_obuf._outStreams.begin(), _obuf._outStreams.end(), os); + if (it == _obuf._outStreams.end()) + return false; + _obuf._outStreams.erase(it); +#else + std::vector::iterator it = find(_obuf._outStreams.begin(), _obuf._outStreams.end(), os); + if (it == _obuf._outStreams.end()) + return false; + _obuf._outStreams.erase(it); +#endif*/ + StreamIter it = find(_obuf._outStreams.begin(), _obuf._outStreams.end(), os); + if (it == _obuf._outStreams.end()) + return false; + _obuf._outStreams.erase(it); + return true; } void eoLogger::redirect(const char * filename) { - std::ofstream * os; - if (filename == NULL) { - os = NULL; - } else { - os = new std::ofstream(filename); - } - redirect(*os); - _obuf._ownedFileStream = os; + std::ofstream * os; + if (filename == NULL) { + os = NULL; + } else { + os = new std::ofstream(filename); + } + doRedirect(os); + _obuf._ownedFileStream = os; } void eoLogger::redirect(const std::string& filename) @@ -194,18 +270,29 @@ void eoLogger::redirect(const std::string& filename) eoLogger::outbuf::outbuf(const eo::Levels& contexlvl, const eo::Levels& selectedlvl) - : _outStream(&std::cout), _ownedFileStream(NULL), _contextLevel(contexlvl), _selectedLevel(selectedlvl) -{} + : +#ifndef USE_SET + _outStreams(1, &std::cout), +#endif + _ownedFileStream(NULL), _contextLevel(contexlvl), _selectedLevel(selectedlvl) +{ +#ifdef USE_SET + _outStreams.insert(&std::cout); +#endif +} int eoLogger::outbuf::overflow(int_type c) { if (_selectedLevel >= _contextLevel) - { - if (_outStream && c != EOF) - { - (*_outStream) << (char) c; - } - } + { + for (StreamIter it = _outStreams.begin(); it != _outStreams.end(); it++) + { + if (c != EOF) + { + (**it) << (char) c; + } + } + } return c; } diff --git a/eo/src/utils/eoLogger.h b/eo/src/utils/eoLogger.h index 97cc73467..81ce0da8e 100644 --- a/eo/src/utils/eoLogger.h +++ b/eo/src/utils/eoLogger.h @@ -1,6 +1,7 @@ // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- /* + (c) Thales group, 2010 This library is free software; you can redistribute it and/or @@ -47,6 +48,14 @@ Caner Candan #include "eoObject.h" #include "eoParser.h" +#define USE_SET +#undef USE_SET + +#ifdef USE_SET +#include +#endif + + namespace eo { /** @@ -133,6 +142,12 @@ private: //! used by the set of ctors to initiate some useful variables void _init(); + //! helper function regrouping redirection operations; takes a pointer because can be given NULL + void doRedirect(std::ostream*); + + //! helper function searching for a stream and removing it, returning true if successful, false otherwise + bool tryRemoveRedirect(std::ostream*); + private: /** * outbuf @@ -142,7 +157,14 @@ private: { public: outbuf(const eo::Levels& contexlvl, const eo::Levels& selectedlvl); - std::ostream * _outStream; + //std::ostream * _outStream; + + #ifdef USE_SET + std::set _outStreams; + #else + std::vector _outStreams; + #endif + std::ofstream * _ownedFileStream; protected: virtual int overflow(int_type c); @@ -171,12 +193,8 @@ public: friend eoLogger& operator<<(eoLogger&, eo::setlevel); /** - * DEPRECATED: Use instead the redirectTo method - * operator<< used there to be able to use std::cout to say that we wish to redirect back the buffer to a standard output. + * DEPRECATED: Use instead the redirect or addRedirect method; has the same effect as addRedirect */ - //! in order to use stream style to go back to a standart output defined by STL - //! and to get retro-compatibility -#warning deprecated friend eoLogger& operator<<(eoLogger&, std::ostream&); /** diff --git a/eo/test/t-eoLogger.cpp b/eo/test/t-eoLogger.cpp index 355870671..f030c2de3 100644 --- a/eo/test/t-eoLogger.cpp +++ b/eo/test/t-eoLogger.cpp @@ -13,6 +13,19 @@ //----------------------------------------------------------------------------- +static void test(); + +static void test2() +{ + #define NB 100 + std::ostream* os = (std::ostream*) 1; + eo::log.redirect(*os); + for (int i = 0; i < NB; i++) + eo::log.addRedirect(*(++os)); + for (int i = 0; i < NB; i++) + eo::log.removeRedirect(*(os--)); +} + int main(int ac, char** av) { eoParser parser(ac, av); @@ -26,6 +39,15 @@ int main(int ac, char** av) make_help(parser); make_verbose(parser); + for (int i = 0; i < 10000; i++) + //test(); + test2(); + + return 0; +} + +static void test() +{ eo::log << eo::setlevel(eo::debug); eo::log << eo::warnings; @@ -33,40 +55,52 @@ int main(int ac, char** av) eo::log << "We are writing on the default output stream" << std::endl; { - std::ofstream ofs("logtest.txt"); + /*std::ofstream ofs("logtest.txt"); eo::log.redirect(ofs); eo::log << "In FILE" << std::endl; eo::log.redirect("logtest2.txt"); + eo::log << "In FILE 2" << std::endl;*/ + eo::log.redirect("logtest.txt"); + eo::log << "In FILE" << std::endl; + std::ofstream ofs("logtest2.txt"); + eo::log.addRedirect(ofs); eo::log << "In FILE 2" << std::endl; + eo::log.removeRedirect(ofs); } - std::ifstream ifs("logtest.txt"); + std::ifstream ifs("logtest2.txt"); //ifs >> str; std::string line; assert(std::getline(ifs, line)); - assert(line == "In FILE"); + //std::cout << line << std::endl; + assert(line == "In FILE 2"); //std::cout << (line == "In FILE") << std::endl; assert(!std::getline(ifs, line)); std::ostringstream oss; - eo::log.redirect(oss); + eo::log.addRedirect(oss); //eo::log << oss << "In STRINGSTREAM"; eo::log << "In STRINGSTREAM"; std::cout << "Content of ostringstream: " << oss.str() << std::endl; assert(oss.str() == "In STRINGSTREAM"); + eo::log.redirect(std::cout); + eo::log << "on COUT" << std::endl; + + ifs.close(); - ifs.open("logtest2.txt"); + ifs.open("logtest.txt"); + assert(std::getline(ifs, line)); + assert(line == "In FILE"); assert(std::getline(ifs, line)); assert(line == "In FILE 2"); + assert(std::getline(ifs, line)); + assert(line == "In STRINGSTREAM"); assert(!std::getline(ifs, line)); //assert(false); - eo::log.redirect(std::cout); - eo::log << "on COUT" << std::endl; - eo::log << eo::setlevel("errors"); eo::log << eo::setlevel(eo::errors); @@ -82,8 +116,7 @@ int main(int ac, char** av) eo::log << eo::debug << 4 << ')' << "4) in debug mode\n"; - - return 0; + } //-----------------------------------------------------------------------------