From 35212ccc906586f68b574947756bbf57aee74dab Mon Sep 17 00:00:00 2001 From: Lionel Parreaux Date: Mon, 6 May 2013 15:27:19 +0200 Subject: [PATCH 1/9] adapted eoLogger for redirecting to ostreams --- eo/src/utils/eoLogger.cpp | 48 +++++++++++++++++++++++++++------------ eo/src/utils/eoLogger.h | 31 ++++++++++++++----------- eo/test/t-eoLogger.cpp | 24 ++++++++++++++++++-- 3 files changed, 73 insertions(+), 30 deletions(-) diff --git a/eo/src/utils/eoLogger.cpp b/eo/src/utils/eoLogger.cpp index 1330c5323..3a9b20098 100644 --- a/eo/src/utils/eoLogger.cpp +++ b/eo/src/utils/eoLogger.cpp @@ -40,6 +40,11 @@ Caner Candan #include "eoLogger.h" +/* TODO? +- changer oprateurs +- virer la structure "file" +*/ + void eoLogger::_init() { _standard_io_streams[&std::cout] = 1; @@ -55,6 +60,8 @@ void eoLogger::_init() addLevel("logging", eo::logging); addLevel("debug", eo::debug); addLevel("xdebug", eo::xdebug); + + //outStream = &std::cout; } eoLogger::eoLogger() : @@ -66,13 +73,12 @@ eoLogger::eoLogger() : _selectedLevel(eo::progress), _contextLevel(eo::quiet), - _fd(2), - _obuf(_fd, _contextLevel, _selectedLevel) + _obuf(_contextLevel, _selectedLevel) { std::ostream::init(&_obuf); _init(); } - +/* eoLogger::eoLogger(eo::file file) : std::ostream(NULL), @@ -88,11 +94,11 @@ eoLogger::eoLogger(eo::file file) : std::ostream::init(&_obuf); _init(); *this << file; -} +}*/ eoLogger::~eoLogger() { - if (_fd > 2) { ::close(_fd); } + //if (_fd > 2) { ::close(_fd); } } void eoLogger::_createParameters( eoParser& parser ) @@ -112,11 +118,14 @@ void eoLogger::_createParameters( eoParser& parser ) //------------------------------------------------------------------ // we're gonna redirect the log to the given filename if -o is used. //------------------------------------------------------------------ - +/* if ( ! _output.value().empty() ) { eo::log << eo::file( _output.value() ); } +*/ +// TODO with a stream + //------------------------------------------------------------------ @@ -162,12 +171,12 @@ eoLogger& operator<<(eoLogger& l, const eo::Levels lvl) l._contextLevel = lvl; return l; } - +/* eoLogger& operator<<(eoLogger& l, eo::file f) { l._fd = ::open(f._f.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644); return l; -} +}*/ eoLogger& operator<<(eoLogger& l, eo::setlevel v) { @@ -177,26 +186,35 @@ eoLogger& operator<<(eoLogger& l, eo::setlevel v) eoLogger& operator<<(eoLogger& l, std::ostream& os) { +/* if (l._standard_io_streams.find(&os) != l._standard_io_streams.end()) { l._fd = l._standard_io_streams[&os]; } +*/ + l._obuf.outStream = &os; return l; } -eoLogger::outbuf::outbuf(const int& fd, - const eo::Levels& contexlvl, +void eoLogger::redirectTo(std::ostream& os) +{ + _obuf.outStream = &os; +} + + +eoLogger::outbuf::outbuf(const eo::Levels& contexlvl, const eo::Levels& selectedlvl) - : _fd(fd), _contextLevel(contexlvl), _selectedLevel(selectedlvl) + : outStream(&std::cout), /*ownedFileStream(NULL),*/ _contextLevel(contexlvl), _selectedLevel(selectedlvl) {} int eoLogger::outbuf::overflow(int_type c) { if (_selectedLevel >= _contextLevel) { - if (_fd >= 0 && c != EOF) + if (outStream && c != EOF) { - ::write(_fd, &c, 1); + //::write(_fd, &c, 1); + (*outStream) << (char) c; } } return c; @@ -204,9 +222,9 @@ int eoLogger::outbuf::overflow(int_type c) namespace eo { - file::file(const std::string f) + /*file::file(const std::string f) : _f(f) - {} + {}*/ setlevel::setlevel(const std::string v) : _v(v), _lvl((Levels)-1) diff --git a/eo/src/utils/eoLogger.h b/eo/src/utils/eoLogger.h index 9ac1c2115..99bafa001 100644 --- a/eo/src/utils/eoLogger.h +++ b/eo/src/utils/eoLogger.h @@ -91,6 +91,7 @@ Caner Candan #include #include #include +#include #include "eoObject.h" #include "eoParser.h" @@ -113,12 +114,12 @@ namespace eo /** * file * this structure combined with the friend operator<< below is an easy way to select a file as output. - */ + * struct file { explicit file(const std::string f); const std::string _f; - }; + };*/ /** * setlevel @@ -146,7 +147,7 @@ public: eoLogger(); //! overidded ctor in order to instanciate a logger with a file define in parameter - eoLogger(eo::file file); + //eoLogger(eo::file file); //! dtor ~eoLogger(); @@ -189,11 +190,12 @@ private: class outbuf : public std::streambuf { public: - outbuf(const int& fd, const eo::Levels& contexlvl, const eo::Levels& selectedlvl); + outbuf(const eo::Levels& contexlvl, const eo::Levels& selectedlvl); + std::ostream * outStream; protected: virtual int overflow(int_type c); private: - const int& _fd; + //std::ofstream * ownedFileStream; const eo::Levels& _contextLevel; const eo::Levels& _selectedLevel; }; @@ -215,7 +217,7 @@ public: * operator<< used there to set a filename through the class file. */ //! in order to use stream style to define a file to dump instead the standart output - friend eoLogger& operator<<(eoLogger&, eo::file); + //friend eoLogger& operator<<(eoLogger&, eo::file); /** * operator<< used there to set a verbose level through the class setlevel. @@ -224,12 +226,21 @@ 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. */ //! 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&); + /** + * Redirects the logger to a given output stream. Closing the stream and returning its memory is at the charge of the caller, + * but should not be done while the log is still redirected to it. + */ + void redirectTo(std::ostream&); + + private: friend void make_verbose(eoParser&); @@ -244,13 +255,7 @@ private: eo::Levels _contextLevel; /** - * _fd in storing the file descriptor at this place we can disable easily the buffer in - * changing the value at -1. It is used by operator <<. - */ - int _fd; - - /** - * _obuf std::ostream mandates to use a buffer. _obuf is a outbuf inheriting of std::streambuf. + * _obuf std::ostream mandates to use a buffer. _obuf is a outbuf inheriting from std::streambuf. */ outbuf _obuf; diff --git a/eo/test/t-eoLogger.cpp b/eo/test/t-eoLogger.cpp index 198a88720..65f9df603 100644 --- a/eo/test/t-eoLogger.cpp +++ b/eo/test/t-eoLogger.cpp @@ -3,6 +3,10 @@ //----------------------------------------------------------------------------- #include +//#include +#include +#include +#include //----------------------------------------------------------------------------- @@ -25,8 +29,24 @@ int main(int ac, char** av) eo::log << "We are writing on the default output stream" << std::endl; - eo::log << eo::file("test.txt") << "In FILE" << std::endl; - eo::log << std::cout << "on COUT" << std::endl; + //eo::log << eo::file("test.txt") << "In FILE" << std::endl; + + std::ofstream ofs("test.txt"); + //eo::log << ofs << "In FILE" << std::endl; + eo::log.redirectTo(ofs); + eo::log << "In FILE" << std::endl; + + std::ostringstream oss; + //eo::log << oss << "In STRINGSTREAM"; + eo::log.redirectTo(oss); + eo::log << oss << "In STRINGSTREAM"; + + //ofs << oss; + std::cout << "Content of ostringstream: " << oss.str() << std::endl; + + //eo::log << std::cout << "on COUT" << std::endl; + eo::log.redirectTo(std::cout); + eo::log << "on COUT" << std::endl; eo::log << eo::setlevel("errors"); eo::log << eo::setlevel(eo::errors); From 002e4a196469f301e0dbb7fa0215ca85f9da88a5 Mon Sep 17 00:00:00 2001 From: Lionel Parreaux Date: Mon, 6 May 2013 17:33:36 +0200 Subject: [PATCH 2/9] added possibility to open files and close them automatically --- eo/src/utils/eoLogger.cpp | 87 ++++++++++++++++----------------------- eo/src/utils/eoLogger.h | 18 ++++---- eo/test/t-eoLogger.cpp | 11 +++-- 3 files changed, 52 insertions(+), 64 deletions(-) diff --git a/eo/src/utils/eoLogger.cpp b/eo/src/utils/eoLogger.cpp index 3a9b20098..79813137c 100644 --- a/eo/src/utils/eoLogger.cpp +++ b/eo/src/utils/eoLogger.cpp @@ -47,9 +47,6 @@ Caner Candan void eoLogger::_init() { - _standard_io_streams[&std::cout] = 1; - _standard_io_streams[&std::clog] = 2; - _standard_io_streams[&std::cerr] = 2; // /!\ If you want to add a level dont forget to add it at the header file in the enumerator Levels @@ -61,7 +58,6 @@ void eoLogger::_init() addLevel("debug", eo::debug); addLevel("xdebug", eo::xdebug); - //outStream = &std::cout; } eoLogger::eoLogger() : @@ -78,27 +74,13 @@ eoLogger::eoLogger() : std::ostream::init(&_obuf); _init(); } -/* -eoLogger::eoLogger(eo::file file) : - std::ostream(NULL), - - _verbose("quiet", "verbose", "Set the verbose level", 'v'), - _printVerboseLevels(false, "print-verbose-levels", "Print verbose levels", 'l'), - _output("", "output", "Redirect a standard output to a file", 'o'), - - _selectedLevel(eo::progress), - _contextLevel(eo::quiet), - _fd(2), - _obuf(_fd, _contextLevel, _selectedLevel) -{ - std::ostream::init(&_obuf); - _init(); - *this << file; -}*/ eoLogger::~eoLogger() { - //if (_fd > 2) { ::close(_fd); } + //redirect(NULL); + if (_obuf._ownedFileStream != NULL) { + delete _obuf._ownedFileStream; + } } void eoLogger::_createParameters( eoParser& parser ) @@ -116,22 +98,21 @@ void eoLogger::_createParameters( eoParser& parser ) //------------------------------------------------------------------ - // we're gonna redirect the log to the given filename if -o is used. + // we redirect the log to the given filename if -o is used. //------------------------------------------------------------------ -/* + if ( ! _output.value().empty() ) { - eo::log << eo::file( _output.value() ); + redirect(_output.value()); } -*/ -// TODO with a stream + //------------------------------------------------------------------ //------------------------------------------------------------------ - // we're gonna print the list of levels if -l parameter is used. + // we print the list of levels if -l parameter is used. //------------------------------------------------------------------ if ( _printVerboseLevels.value() ) @@ -171,12 +152,6 @@ eoLogger& operator<<(eoLogger& l, const eo::Levels lvl) l._contextLevel = lvl; return l; } -/* -eoLogger& operator<<(eoLogger& l, eo::file f) -{ - l._fd = ::open(f._f.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644); - return l; -}*/ eoLogger& operator<<(eoLogger& l, eo::setlevel v) { @@ -186,35 +161,49 @@ eoLogger& operator<<(eoLogger& l, eo::setlevel v) eoLogger& operator<<(eoLogger& l, std::ostream& os) { -/* - if (l._standard_io_streams.find(&os) != l._standard_io_streams.end()) - { - l._fd = l._standard_io_streams[&os]; - } -*/ - l._obuf.outStream = &os; + l._obuf._outStream = &os; return l; } -void eoLogger::redirectTo(std::ostream& os) +void eoLogger::redirect(std::ostream& os) { - _obuf.outStream = &os; + if (_obuf._ownedFileStream != NULL) { + delete _obuf._ownedFileStream; + _obuf._ownedFileStream = NULL; + } + _obuf._outStream = &os; +} + +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; +} + +void eoLogger::redirect(const std::string& filename) +{ + redirect(filename.c_str()); } eoLogger::outbuf::outbuf(const eo::Levels& contexlvl, const eo::Levels& selectedlvl) - : outStream(&std::cout), /*ownedFileStream(NULL),*/ _contextLevel(contexlvl), _selectedLevel(selectedlvl) + : _outStream(&std::cout), _ownedFileStream(NULL), _contextLevel(contexlvl), _selectedLevel(selectedlvl) {} int eoLogger::outbuf::overflow(int_type c) { if (_selectedLevel >= _contextLevel) { - if (outStream && c != EOF) + if (_outStream && c != EOF) { - //::write(_fd, &c, 1); - (*outStream) << (char) c; + (*_outStream) << (char) c; } } return c; @@ -222,10 +211,6 @@ int eoLogger::outbuf::overflow(int_type c) namespace eo { - /*file::file(const std::string f) - : _f(f) - {}*/ - setlevel::setlevel(const std::string v) : _v(v), _lvl((Levels)-1) {} diff --git a/eo/src/utils/eoLogger.h b/eo/src/utils/eoLogger.h index 99bafa001..e655848c7 100644 --- a/eo/src/utils/eoLogger.h +++ b/eo/src/utils/eoLogger.h @@ -191,11 +191,11 @@ private: { public: outbuf(const eo::Levels& contexlvl, const eo::Levels& selectedlvl); - std::ostream * outStream; + std::ostream * _outStream; + std::ofstream * _ownedFileStream; protected: virtual int overflow(int_type c); private: - //std::ofstream * ownedFileStream; const eo::Levels& _contextLevel; const eo::Levels& _selectedLevel; }; @@ -213,12 +213,6 @@ public: //! in order to use stream style to define the context verbose level where the following logs will be saved friend eoLogger& operator<<(eoLogger&, const eo::Levels); - /** - * operator<< used there to set a filename through the class file. - */ - //! in order to use stream style to define a file to dump instead the standart output - //friend eoLogger& operator<<(eoLogger&, eo::file); - /** * operator<< used there to set a verbose level through the class setlevel. */ @@ -238,8 +232,14 @@ public: * Redirects the logger to a given output stream. Closing the stream and returning its memory is at the charge of the caller, * but should not be done while the log is still redirected to it. */ - void redirectTo(std::ostream&); + void redirect(std::ostream&); + /** + * Redirects the logger to a file using a filename. + * Closing the file will be done automatically when the logger is redirected again or destroyed. + */ + void redirect(const char * filename); + void redirect(const std::string& filename); private: friend void make_verbose(eoParser&); diff --git a/eo/test/t-eoLogger.cpp b/eo/test/t-eoLogger.cpp index 65f9df603..a1ea4b60c 100644 --- a/eo/test/t-eoLogger.cpp +++ b/eo/test/t-eoLogger.cpp @@ -31,21 +31,24 @@ int main(int ac, char** av) //eo::log << eo::file("test.txt") << "In FILE" << std::endl; - std::ofstream ofs("test.txt"); + std::ofstream ofs("logtest.txt"); //eo::log << ofs << "In FILE" << std::endl; - eo::log.redirectTo(ofs); + eo::log.redirect(ofs); eo::log << "In FILE" << std::endl; + + eo::log.redirect("logtest2.txt"); + eo::log << "In FILE 2" << std::endl; std::ostringstream oss; //eo::log << oss << "In STRINGSTREAM"; - eo::log.redirectTo(oss); + eo::log.redirect(oss); eo::log << oss << "In STRINGSTREAM"; //ofs << oss; std::cout << "Content of ostringstream: " << oss.str() << std::endl; //eo::log << std::cout << "on COUT" << std::endl; - eo::log.redirectTo(std::cout); + eo::log.redirect(std::cout); eo::log << "on COUT" << std::endl; eo::log << eo::setlevel("errors"); From b66c38ce2cb39933db411c7cdf543e358008a5d3 Mon Sep 17 00:00:00 2001 From: LPTK Date: Mon, 10 Jun 2013 18:34:57 +0200 Subject: [PATCH 3/9] minor fixes --- eo/src/utils/eoLogger.cpp | 4 +-- eo/src/utils/eoLogger.h | 57 +++------------------------------------ eo/test/t-eoLogger.cpp | 6 ----- 3 files changed, 6 insertions(+), 61 deletions(-) diff --git a/eo/src/utils/eoLogger.cpp b/eo/src/utils/eoLogger.cpp index 79813137c..cd80ba67e 100644 --- a/eo/src/utils/eoLogger.cpp +++ b/eo/src/utils/eoLogger.cpp @@ -41,8 +41,8 @@ Caner Candan #include "eoLogger.h" /* TODO? -- changer oprateurs -- virer la structure "file" +add a possibility to redirect to several streams +add_redirect/remove_redirect */ void eoLogger::_init() diff --git a/eo/src/utils/eoLogger.h b/eo/src/utils/eoLogger.h index e655848c7..6c2599eb6 100644 --- a/eo/src/utils/eoLogger.h +++ b/eo/src/utils/eoLogger.h @@ -30,56 +30,7 @@ Caner Candan Global logger for EO. - Here's an example explaning how to use eoLogger: -\code - #include - - int main(int ac, char** av) - { - // We are declaring the usual eoParser class - eoParser parser(ac, av); - - // This call is important to allow -v parameter to change user level. - make_verbose(parser); - - // At this time we are switching to warning message and messages - // which are going to follow it are going to be warnings message too. - // These messages can be displayed only if the user level (sets with - // eo::setlevel function) is set to eo::warnings. - eo::log << eo::warnings; - - // With the following eo::file function we are defining that - // all future logs are going to this new file resource which is - // test.txt - eo::log << eo::file("test.txt") << "In FILE" << std::endl; - - // Now we are changing again the resources destination to cout which - // is the standard output. - eo::log << std::cout << "In COUT" << std::endl; - - // Here are 2 differents examples of how to set the errors user level - // in using either a string or an identifier. - eo::log << eo::setlevel("errors"); - eo::log << eo::setlevel(eo::errors); - - // Now we are writting a message, that will be displayed only if we are above the "quiet" level - eo::log << eo::quiet << "1) Must be in quiet mode to see that" << std::endl; - - // And so on... - eo::log << eo::setlevel(eo::warnings) << eo::warnings << "2) Must be in warnings mode to see that" << std::endl; - - eo::log << eo::setlevel(eo::logging); - - eo::log << eo::errors; - eo::log << "3) Must be in errors mode to see that"; - eo::log << std::endl; - - eo::log << eo::debug << 4 << ')' - << " Must be in debug mode to see that\n"; - - return 0; - } -\endcode + For an example explaning of how to use eoLogger, see paradiseo/eo/test/t-eoLogger.cpp @{ */ @@ -220,7 +171,7 @@ public: friend eoLogger& operator<<(eoLogger&, eo::setlevel); /** - * DEPRECATED: Use instead the redirectTo method + * DEPRECATED: Use instead the redirect 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. */ //! in order to use stream style to go back to a standart output defined by STL @@ -230,7 +181,7 @@ public: /** * Redirects the logger to a given output stream. Closing the stream and returning its memory is at the charge of the caller, - * but should not be done while the log is still redirected to it. + * but should not be done while the logger is still redirected to it. */ void redirect(std::ostream&); @@ -249,7 +200,7 @@ private: eoValueParam _output; /** - * _selectedLevel is the member storing verbose level setted by the user thanks to operator() + * _selectedLevel is the member storing verbose level set by the user thanks to operator() */ eo::Levels _selectedLevel; eo::Levels _contextLevel; diff --git a/eo/test/t-eoLogger.cpp b/eo/test/t-eoLogger.cpp index a1ea4b60c..67a06c8e3 100644 --- a/eo/test/t-eoLogger.cpp +++ b/eo/test/t-eoLogger.cpp @@ -29,10 +29,7 @@ int main(int ac, char** av) eo::log << "We are writing on the default output stream" << std::endl; - //eo::log << eo::file("test.txt") << "In FILE" << std::endl; - std::ofstream ofs("logtest.txt"); - //eo::log << ofs << "In FILE" << std::endl; eo::log.redirect(ofs); eo::log << "In FILE" << std::endl; @@ -40,14 +37,11 @@ int main(int ac, char** av) eo::log << "In FILE 2" << std::endl; std::ostringstream oss; - //eo::log << oss << "In STRINGSTREAM"; eo::log.redirect(oss); eo::log << oss << "In STRINGSTREAM"; - //ofs << oss; std::cout << "Content of ostringstream: " << oss.str() << std::endl; - //eo::log << std::cout << "on COUT" << std::endl; eo::log.redirect(std::cout); eo::log << "on COUT" << std::endl; From de9af0ba21e221ca096520754b124b6acc6b6477 Mon Sep 17 00:00:00 2001 From: LPTK Date: Tue, 11 Jun 2013 14:08:06 +0200 Subject: [PATCH 4/9] new logger interface --- eo/src/utils/eoLogger.h | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/eo/src/utils/eoLogger.h b/eo/src/utils/eoLogger.h index 6c2599eb6..97cc73467 100644 --- a/eo/src/utils/eoLogger.h +++ b/eo/src/utils/eoLogger.h @@ -30,7 +30,7 @@ Caner Candan Global logger for EO. - For an example explaning of how to use eoLogger, see paradiseo/eo/test/t-eoLogger.cpp + For an example explaning how to use eoLogger, please refer to paradiseo/eo/test/t-eoLogger.cpp @{ */ @@ -171,7 +171,7 @@ public: friend eoLogger& operator<<(eoLogger&, eo::setlevel); /** - * DEPRECATED: Use instead the redirect method + * 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. */ //! in order to use stream style to go back to a standart output defined by STL @@ -180,11 +180,27 @@ public: friend eoLogger& operator<<(eoLogger&, std::ostream&); /** - * Redirects the logger to a given output stream. Closing the stream and returning its memory is at the charge of the caller, - * but should not be done while the logger is still redirected to it. + * Redirects the logger to a given output stream. + * Closing the stream and returning its memory is at the charge of the caller, + * but should not be done while the log is still redirected to it. + * This resets all previous redirections set up with redirect and add_redirect. */ void redirect(std::ostream&); + /** + * Adds a redirection from the logger to a given output stream. + * Closing the stream and returning its memory is at the charge of the caller, + * but should not be done while the log is still redirected to it. + * This does not reset previous redirections, which remain active. + */ + void addRedirect(std::ostream&); + + /** + * Removes a redirection from the logger to the given output stream. + * This only resets the redirection to the stream passed in argument. + */ + void removeRedirect(std::ostream&); + /** * Redirects the logger to a file using a filename. * Closing the file will be done automatically when the logger is redirected again or destroyed. @@ -200,7 +216,7 @@ private: eoValueParam _output; /** - * _selectedLevel is the member storing verbose level set by the user thanks to operator() + * _selectedLevel is the member storing verbose level setted by the user thanks to operator() */ eo::Levels _selectedLevel; eo::Levels _contextLevel; From b30a15b746047fe6789ca32ff406a4598656a971 Mon Sep 17 00:00:00 2001 From: LPTK Date: Tue, 11 Jun 2013 16:04:42 +0200 Subject: [PATCH 5/9] logger tests with assertions --- eo/test/t-eoLogger.cpp | 46 +++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/eo/test/t-eoLogger.cpp b/eo/test/t-eoLogger.cpp index 67a06c8e3..355870671 100644 --- a/eo/test/t-eoLogger.cpp +++ b/eo/test/t-eoLogger.cpp @@ -7,6 +7,9 @@ #include #include #include +#include + +// TODO test multiple redirection //----------------------------------------------------------------------------- @@ -15,10 +18,10 @@ int main(int ac, char** av) eoParser parser(ac, av); if (parser.userNeedsHelp()) - { - parser.printHelp(std::cout); - exit(1); - } + { + parser.printHelp(std::cout); + exit(1); + } make_help(parser); make_verbose(parser); @@ -29,18 +32,37 @@ int main(int ac, char** av) eo::log << "We are writing on the default output stream" << std::endl; - 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; + { + 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; + } + + std::ifstream ifs("logtest.txt"); + //ifs >> str; + std::string line; + assert(std::getline(ifs, line)); + assert(line == "In FILE"); + //std::cout << (line == "In FILE") << std::endl; + assert(!std::getline(ifs, line)); std::ostringstream oss; eo::log.redirect(oss); - eo::log << oss << "In STRINGSTREAM"; + //eo::log << oss << "In STRINGSTREAM"; + eo::log << "In STRINGSTREAM"; std::cout << "Content of ostringstream: " << oss.str() << std::endl; + assert(oss.str() == "In STRINGSTREAM"); + + ifs.close(); + ifs.open("logtest2.txt"); + assert(std::getline(ifs, line)); + assert(line == "In FILE 2"); + assert(!std::getline(ifs, line)); + //assert(false); + eo::log.redirect(std::cout); eo::log << "on COUT" << std::endl; @@ -59,7 +81,7 @@ int main(int ac, char** av) eo::log << std::endl; eo::log << eo::debug << 4 << ')' - << "4) in debug mode\n"; + << "4) in debug mode\n"; return 0; } From 11c32bb5f1388081b715c13a31c666f0802d99ce Mon Sep 17 00:00:00 2001 From: LPTK Date: Tue, 11 Jun 2013 17:01:52 +0200 Subject: [PATCH 6/9] performance tests map/vector --- eo/src/utils/eoLogger.cpp | 143 ++++++++++++++++++++++++++++++-------- eo/src/utils/eoLogger.h | 30 ++++++-- eo/test/t-eoLogger.cpp | 53 +++++++++++--- 3 files changed, 182 insertions(+), 44 deletions(-) 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; + } //----------------------------------------------------------------------------- From 9fc61f5a3b3c7f8515d2c20de3b8980f073e9007 Mon Sep 17 00:00:00 2001 From: LPTK Date: Tue, 11 Jun 2013 17:11:20 +0200 Subject: [PATCH 7/9] performance tests adjusted --- eo/src/utils/eoLogger.h | 2 +- eo/test/t-eoLogger.cpp | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/eo/src/utils/eoLogger.h b/eo/src/utils/eoLogger.h index 81ce0da8e..e5fd34b34 100644 --- a/eo/src/utils/eoLogger.h +++ b/eo/src/utils/eoLogger.h @@ -49,7 +49,7 @@ Caner Candan #include "eoParser.h" #define USE_SET -#undef USE_SET +//#undef USE_SET #ifdef USE_SET #include diff --git a/eo/test/t-eoLogger.cpp b/eo/test/t-eoLogger.cpp index f030c2de3..431920ebe 100644 --- a/eo/test/t-eoLogger.cpp +++ b/eo/test/t-eoLogger.cpp @@ -22,8 +22,12 @@ static void test2() 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--)); + eo::log.removeRedirect(*(os--));*/ + os = (std::ostream*) 1; + for (int i = 0; i < NB; i++) + eo::log.removeRedirect(*(++os)); } int main(int ac, char** av) From a0464934cbe6810d0e73273b1fdda0344c07ca89 Mon Sep 17 00:00:00 2001 From: LPTK Date: Wed, 12 Jun 2013 11:58:38 +0200 Subject: [PATCH 8/9] cleaning & doc --- eo/src/utils/eoLogger.cpp | 34 ---------------------------------- eo/src/utils/eoLogger.h | 18 ++++++------------ eo/test/t-eoLogger.cpp | 39 +++++---------------------------------- 3 files changed, 11 insertions(+), 80 deletions(-) diff --git a/eo/src/utils/eoLogger.cpp b/eo/src/utils/eoLogger.cpp index 8a2c37831..10371b0a0 100644 --- a/eo/src/utils/eoLogger.cpp +++ b/eo/src/utils/eoLogger.cpp @@ -41,10 +41,6 @@ Caner Candan #include "eoLogger.h" -/* TODO? -add a possibility to redirect to several streams -add_redirect/remove_redirect -*/ #ifdef USE_SET typedef std::set::iterator StreamIter; @@ -85,7 +81,6 @@ eoLogger::eoLogger() : eoLogger::~eoLogger() { - //redirect(NULL); if (_obuf._ownedFileStream != NULL) { delete _obuf._ownedFileStream; } @@ -187,7 +182,6 @@ void eoLogger::doRedirect(std::ostream* os) } _obuf._outStreams.clear(); if (os != NULL) - //_obuf._outStreams.push_back(os); #ifdef USE_SET _obuf._outStreams.insert(os); #else @@ -197,13 +191,7 @@ void eoLogger::doRedirect(std::ostream* os) 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 @@ -216,33 +204,11 @@ void eoLogger::addRedirect(std::ostream& os) 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; diff --git a/eo/src/utils/eoLogger.h b/eo/src/utils/eoLogger.h index e5fd34b34..98ba09660 100644 --- a/eo/src/utils/eoLogger.h +++ b/eo/src/utils/eoLogger.h @@ -48,8 +48,12 @@ Caner Candan #include "eoObject.h" #include "eoParser.h" -#define USE_SET -//#undef USE_SET +#define USE_SET // defines if a set is to be used instead of a vector for storing streams the logger is redirected to +#undef USE_SET +/* expriments have shown that here a vector is by far faster than a set even if O(n), + * because it needs less dynamic allocations, uses less memory and less instructions + */ + #ifdef USE_SET #include @@ -71,16 +75,6 @@ namespace eo debug, xdebug}; - /** - * file - * this structure combined with the friend operator<< below is an easy way to select a file as output. - * - struct file - { - explicit file(const std::string f); - const std::string _f; - };*/ - /** * setlevel * this structure combined with the friend operator<< below is an easy way to set a verbose level. diff --git a/eo/test/t-eoLogger.cpp b/eo/test/t-eoLogger.cpp index 431920ebe..0406cb6b1 100644 --- a/eo/test/t-eoLogger.cpp +++ b/eo/test/t-eoLogger.cpp @@ -9,27 +9,10 @@ #include #include -// TODO test multiple redirection - //----------------------------------------------------------------------------- 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--));*/ - os = (std::ostream*) 1; - for (int i = 0; i < NB; i++) - eo::log.removeRedirect(*(++os)); -} - int main(int ac, char** av) { eoParser parser(ac, av); @@ -43,9 +26,7 @@ int main(int ac, char** av) make_help(parser); make_verbose(parser); - for (int i = 0; i < 10000; i++) - //test(); - test2(); + test(); return 0; } @@ -59,37 +40,28 @@ static void test() eo::log << "We are writing on the default output stream" << std::endl; { - /*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"); + std::ofstream ofs("logtest2.txt"); // closed and destroyed at the en of the scope eo::log.addRedirect(ofs); eo::log << "In FILE 2" << std::endl; - eo::log.removeRedirect(ofs); + eo::log.removeRedirect(ofs); // must be removed because the associated stream is closed } - std::ifstream ifs("logtest2.txt"); - //ifs >> str; + std::ifstream ifs("logtest2.txt"); // stream to logtest2.txt is closed, we can start reading std::string line; assert(std::getline(ifs, line)); - //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.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.redirect(std::cout); // removes all previously redirected streams; closes the file logtest.txt eo::log << "on COUT" << std::endl; @@ -102,7 +74,6 @@ static void test() assert(std::getline(ifs, line)); assert(line == "In STRINGSTREAM"); assert(!std::getline(ifs, line)); - //assert(false); eo::log << eo::setlevel("errors"); From 395f3f20aa74e3a1585fcbfb0052eae57f096c3f Mon Sep 17 00:00:00 2001 From: LPTK Date: Fri, 14 Jun 2013 11:23:20 +0200 Subject: [PATCH 9/9] doc --- eo/src/utils/eoLogger.cpp | 1 + eo/src/utils/eoLogger.h | 1 + 2 files changed, 2 insertions(+) diff --git a/eo/src/utils/eoLogger.cpp b/eo/src/utils/eoLogger.cpp index 10371b0a0..505942c77 100644 --- a/eo/src/utils/eoLogger.cpp +++ b/eo/src/utils/eoLogger.cpp @@ -23,6 +23,7 @@ Contact: http://eodev.sourceforge.net Authors: Johann Dréo Caner Candan +Lionel Parreaux */ diff --git a/eo/src/utils/eoLogger.h b/eo/src/utils/eoLogger.h index 98ba09660..dcef5f414 100644 --- a/eo/src/utils/eoLogger.h +++ b/eo/src/utils/eoLogger.h @@ -23,6 +23,7 @@ Contact: http://eodev.sourceforge.net Authors: Johann Dréo Caner Candan +Lionel Parreaux */