Author: carnold
Date: Wed Nov 7 14:45:35 2007
New Revision: 592933
URL: http://svn.apache.org/viewvc?rev=592933&view=rev
Log:
LOGCXX-18: Rewrite logstream, checking VC6 next
Modified:
logging/log4cxx/trunk/src/examples/cpp/stream.cpp
logging/log4cxx/trunk/src/main/cpp/logstream.cpp
logging/log4cxx/trunk/src/main/include/log4cxx/stream.h
logging/log4cxx/trunk/src/test/cpp/streamtestcase.cpp
Modified: logging/log4cxx/trunk/src/examples/cpp/stream.cpp
URL:
http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/examples/cpp/stream.cpp?rev=592933&r1=592932&r2=592933&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/examples/cpp/stream.cpp (original)
+++ logging/log4cxx/trunk/src/examples/cpp/stream.cpp Wed Nov 7 14:45:35 2007
@@ -25,7 +25,7 @@
using namespace log4cxx;
using namespace log4cxx::helpers;
-int main()
+int xmain()
{
setlocale(LC_ALL, "");
int result = EXIT_SUCCESS;
@@ -37,7 +37,7 @@
NDC::push("trivial context");
log4cxx::logstream logstream(rootLogger, Level::getDebug());
- logstream << "debug message " << 1 << LOG4CXX_ENDMSG;
+ logstream << "debug message " << 1 << LOG4CXX_LOCATION <<
LOG4CXX_ENDMSG;
logstream.setLevel(Level::getInfo());
#if LOG4CXX_HAS_WCHAR_T
logstream << L"info message" << LOG4CXX_ENDMSG;
@@ -62,3 +62,4 @@
return result;
}
+
Modified: logging/log4cxx/trunk/src/main/cpp/logstream.cpp
URL:
http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/logstream.cpp?rev=592933&r1=592932&r2=592933&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/logstream.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/logstream.cpp Wed Nov 7 14:45:35 2007
@@ -19,65 +19,151 @@
#include <log4cxx/stream.h>
#include <log4cxx/helpers/transcoder.h>
-#if LOG4CXX_HAS_WCHAR_T
-log4cxx::logstream& operator<<(
- ::log4cxx::logstream& lhs,
- const char* rhs) {
- LOG4CXX_DECODE_CHAR(tmp, rhs);
- LOG4CXX_ENCODE_WCHAR(msg, tmp);
- lhs.getStream() << msg;
- return lhs;
-}
-#else
-log4cxx::logstream& operator<<(
- ::log4cxx::logstream& lhs,
- const char* rhs) {
- LOG4CXX_DECODE_CHAR(tmp, rhs);
- LOG4CXX_ENCODE_CHAR(msg, tmp);
- lhs.getStream() << msg;
- return lhs;
-}
-#endif
-
-#if LOG4CXX_HAS_WCHAR_T
-log4cxx::logstream& operator<<(
- ::log4cxx::logstream& lhs,
- const ::log4cxx::LogString& rhs) {
- LOG4CXX_DECODE_CHAR(tmp, rhs);
- LOG4CXX_ENCODE_WCHAR(msg, tmp);
- lhs.getStream() << msg;
- return lhs;
-}
-#else
-log4cxx::logstream& operator<<(
- ::log4cxx::logstream& lhs,
- const ::log4cxx::LogString& rhs) {
- LOG4CXX_DECODE_CHAR(tmp, rhs);
- LOG4CXX_ENCODE_CHAR(msg, tmp);
- lhs.getStream() << msg;
- return lhs;
-}
-#endif
-
-::log4cxx::logstream& operator<<(
- ::log4cxx::logstream& lhs,
- const ::log4cxx::spi::LocationInfo& rhs) {
- lhs.setLocation(rhs);
- return lhs;
+using namespace log4cxx;
+
+logstream_base::logstream_base(const LoggerPtr& log,
+ const LevelPtr& lvl) : initset((std::ios_base::fmtflags) -1, 1),
+ initclear((std::ios_base::fmtflags) 0, 0), logger(log), level(lvl),
location(), fillchar(0), fillset(false) {
+ enabled = logger->isEnabledFor(level);
+}
+
+logstream_base::~logstream_base() {
+}
+
+logstream_base& logstream_base::operator<<(std::ios_base&
(*manip)(std::ios_base&)) {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ (*manip)(initset);
+ (*manip)(initclear);
+ refresh_stream_state();
+ return *this;
+}
+
+logstream_base& logstream_base::operator<<(logstream_base&
(*manip)(logstream_base&)) {
+ (*manip)(*this);
+ return *this;
+}
+
+logstream_base& logstream_base::operator<<(const LevelPtr& level) {
+ setLevel(level);
+ return *this;
+}
+
+bool logstream_base::set_stream_state(std::ios_base& dest, int& dstchar) {
+ std::ios_base::fmtflags setval = initset.flags();
+ std::ios_base::fmtflags clrval = initclear.flags();
+ std::ios_base::fmtflags mask = setval ^ (~clrval);
+ dest.setf(clrval, mask);
+ if (initset.precision() == initclear.precision()) {
+ dest.precision(initset.precision());
+ }
+ if (initset.width() == initclear.width()) {
+ dest.width(initset.width());
+ }
+ dstchar = fillchar;
+ return fillset;
+}
+
+logstream_base& logstream_base::log(logstream_base& stream) {
+ stream.log();
+ return stream;
+}
+
+void logstream_base::log() {
+ if (isEnabled()) {
+ log(logger, level, location);
+ }
+ erase();
}
-::log4cxx::logstream& operator<<(
- ::log4cxx::logstream& lhs,
- const ::log4cxx::LevelPtr& rhs) {
- lhs.setLevel(rhs);
- return lhs;
+int log4cxx::logstream_base::precision(int p) {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ initset.precision(p);
+ int oldVal = initclear.precision(p);
+ refresh_stream_state();
+ return oldVal;
}
+int log4cxx::logstream_base::precision() {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ return initclear.precision();
+}
+
+int log4cxx::logstream_base::width(int w) {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ initset.width(w);
+ int oldVal = initclear.width(w);
+ refresh_stream_state();
+ return oldVal;
+}
+
+int log4cxx::logstream_base::width() {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ return initclear.width();
+}
-::log4cxx::logstream& operator<<(
- ::log4cxx::logstream& lhs,
- ::std::ios_base& (*manip)(::std::ios_base&)) {
- (*manip)(lhs);
- return lhs;
+int log4cxx::logstream_base::fill(int newfill) {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ int oldfill = fillchar;
+ fillchar = newfill;
+ fillset = true;
+ refresh_stream_state();
+ return oldfill;
}
+
+int logstream_base::fill() {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ return fillchar;
+}
+
+std::ios_base::fmtflags logstream_base::flags(std::ios_base::fmtflags
newflags) {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ initset.flags(newflags);
+ std::ios_base::fmtflags oldVal = initclear.flags(newflags);
+ refresh_stream_state();
+ return oldVal;
+}
+
+std::ios_base::fmtflags logstream_base::setf(std::ios_base::fmtflags newflags,
std::ios_base::fmtflags mask) {
+ get_stream_state(initclear, initset, fillchar, fillset);
+ initset.setf(newflags, mask);
+ std::ios_base::fmtflags oldVal = initclear.setf(newflags, mask);
+ refresh_stream_state();
+ return oldVal;
+}
+
+std::ios_base::fmtflags logstream_base::setf(std::ios_base::fmtflags newflags)
{
+ get_stream_state(initclear, initset, fillchar, fillset);
+ initset.setf(newflags);
+ std::ios_base::fmtflags oldVal = initclear.setf(newflags);
+ refresh_stream_state();
+ return oldVal;
+}
+
+
+
+void logstream_base::setLevel(const ::log4cxx::LevelPtr& newlevel) {
+ level = newlevel;
+ bool oldLevel = enabled;
+ enabled = logger->isEnabledFor(level);
+ if (oldLevel != enabled) {
+ erase();
+ }
+}
+
+bool logstream_base::isEnabledFor(const ::log4cxx::LevelPtr& level) const {
+ return logger->isEnabledFor(level);
+}
+
+
+void logstream_base::setLocation(const log4cxx::spi::LocationInfo&
newlocation) {
+ if (LOG4CXX_UNLIKELY(enabled)) {
+ location = newlocation;
+ }
+}
+
+logstream_base& logstream_base::operator<<(const log4cxx::spi::LocationInfo&
newlocation) {
+ setLocation(newlocation);
+ return *this;
+}
+
Modified: logging/log4cxx/trunk/src/main/include/log4cxx/stream.h
URL:
http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/include/log4cxx/stream.h?rev=592933&r1=592932&r2=592933&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/include/log4cxx/stream.h (original)
+++ logging/log4cxx/trunk/src/main/include/log4cxx/stream.h Wed Nov 7 14:45:35
2007
@@ -24,170 +24,368 @@
namespace log4cxx
{
-#if LOG4CXX_HAS_WCHAR_T
-typedef wchar_t logstream_char;
-#else
-typedef char logstream_char;
-#endif
/**
- * This template acts as a proxy for base_logstreamimpl
- * and defers the potentially expensive construction
- * of basic_stream until needed.
+ * Base class for the basic_logstream template which attempts
+ * to emulate std::basic_ostream but attempts to short-circuit
+ * unnecessary operations.
+ *
+ * The logstream has a logger and level that are used for logging
+ * requests. The level of the stream is compared against the
+ * current level of the logger to determine if the request should be
processed.
*/
- class logstream : public ::std::basic_ios<logstream_char> {
- public:
+ class LOG4CXX_EXPORT logstream_base {
+ public:
/**
- * Constructor.
+ * Create new instance.
+ * @param logger logger logger used in log requests.
+ * @level level indicates level that will be used in log
requests. Can
+ * be modified later by inserting a level or calling
setLevel.
*/
- logstream(const ::log4cxx::LoggerPtr& loggr,
- const ::log4cxx::LevelPtr& level) :
- logger(loggr),
- currentLevel(level),
- impl(0),
- enabled(loggr->isEnabledFor(level)),
- currentLocation() {
- init(0);
- }
-
- /**
- * Constructor.
- */
- logstream(const char* logName,
- ::log4cxx::LevelPtr& level) :
- logger(::log4cxx::Logger::getLogger(logName)),
- currentLevel(level),
- impl(0),
- enabled(logger->isEnabledFor(level)),
- currentLocation() {
- init(0);
- }
-
-#if LOG4CXX_HAS_WCHAR_T
- /**
- * Constructor.
- */
- logstream(const wchar_t* logName,
- ::log4cxx::LevelPtr& level) :
- logger(::log4cxx::Logger::getLogger(logName)),
- currentLevel(level),
- impl(0),
- enabled(logger->isEnabledFor(level)),
- currentLocation() {
- init(0);
- }
-#endif
-
- ~logstream() {
- delete impl;
- }
-
-
+ logstream_base(const log4cxx::LoggerPtr& logger,
+ const log4cxx::LevelPtr& level);
+ /**
+ * Destructor.
+ */
+ virtual ~logstream_base();
+ /**
+ * Insertion operator for std::fixed and similar manipulators.
+ */
+ logstream_base& operator<<(std::ios_base&
(*manip)(std::ios_base&));
+ /**
+ * Insertion operator for logstream_base::log.
+ */
+ logstream_base& operator<<(logstream_base&
(*manip)(logstream_base&));
+ /**
+ * Insertion operator for level.
+ */
+ logstream_base& operator<<(const log4cxx::LevelPtr& level);
+ /**
+ * Insertion operator for location.
+ */
+ logstream_base& operator<<(const log4cxx::spi::LocationInfo&
location);
/**
+ * get precision.
+ */
+ int precision();
+ /**
+ * get width.
+ */
+ int width();
+ /**
+ * set precision. This should be used in preference to
inserting an std::setprecision(n)
+ * since the other requires construction of an STL stream which
may be expensive.
+ */
+ int precision(int newval);
+ /**
+ * set width. This should be used in preference to inserting
an std::setw(n)
+ * since the other requires construction of an STL stream which
may be expensive.
+ */
+ int width(int newval);
+ /**
+ * Get fill character.
+ */
+ int fill();
+ /**
+ * Set fill character.
+ */
+ int fill(int newval);
+
+ /**
+ * Set flags. see std::ios_base.
+ */
+ std::ios_base::fmtflags flags(std::ios_base::fmtflags newflags);
+ /**
+ * Set flags. see std::ios_base.
+ */
+ std::ios_base::fmtflags setf(std::ios_base::fmtflags newflags,
std::ios_base::fmtflags mask);
+ /**
+ * Set flags. see std::ios_base.
+ */
+ std::ios_base::fmtflags setf(std::ios_base::fmtflags newflags);
+
+
+ /**
+ * log manipulator.
+ */
+ static logstream_base& log(logstream_base&);
+
+ /**
+ * log operation.
+ */
+ void log();
+
+ /**
* Set the level.
* @param level level
*/
- void setLevel(const ::log4cxx::LevelPtr& level) {
- currentLevel = level;
- enabled = logger->isEnabledFor(currentLevel);
- }
-
+ void setLevel(const LevelPtr& level);
+ /**
+ * Returns true if the current level is the same or high as the
+ * level of logger at time of construction or last setLevel.
+ */
inline bool isEnabled() const {
return enabled;
}
- bool isEnabledFor(const ::log4cxx::LevelPtr& level) const {
- return logger->isEnabledFor(level);
- }
-
-
- void setLocation(const ::log4cxx::spi::LocationInfo& location) {
- if (LOG4CXX_UNLIKELY(enabled)) {
- currentLocation = location;
- }
- }
+ /**
+ * Returns if logger is currently enabled for the specified
level.
+ */
+ bool isEnabledFor(const LevelPtr& level) const;
+ /**
+ * Sets the location for subsequent log requests.
+ */
+ void setLocation(const log4cxx::spi::LocationInfo& location);
+ /**
+ * Sets the state of the embedded stream (if any)
+ * to the state of the formatting info.
+ * @param os stream to receive formatting info.
+ * @param fillchar receives fill charater.
+ * @return true if fill character was specified.
+ */
+ bool set_stream_state(std::ios_base& os, int& fillchar);
- inline void flush(const ::log4cxx::spi::LocationInfo& location) {
- if (LOG4CXX_UNLIKELY(enabled && 0 != impl)) {
- logger->log(currentLevel,
- impl->str(),
- location);
- const std::basic_string<logstream_char> emptyStr;
- impl->str(emptyStr);
+ protected:
+ /**
+ * Dispatches the pending log request.
+ */
+ virtual void log(LoggerPtr& logger,
+ const LevelPtr& level,
+ const log4cxx::spi::LocationInfo& location) = 0;
+ /**
+ * Erase any content in the message construction buffer.
+ */
+ virtual void erase() = 0;
+ /**
+ * Copy state of embedded stream (if any)
+ * to value and mask instances of std::ios_base
+ * and return fill character value.
+ */
+ virtual void get_stream_state(std::ios_base& base,
+ std::ios_base& mask,
+ int& fill,
+ bool& fillSet) const = 0;
+ virtual void refresh_stream_state() = 0;
+
+ private:
+ /**
+ * prevent copy constructor.
+ */
+ logstream_base(logstream_base&);
+ /**
+ * prevent copy operatpr.
+ */
+ logstream_base& operator=(logstream_base&);
+ /**
+ * Minimal extension of std::ios_base to allow creation
+ * of embedded IO states.
+ */
+ class logstream_ios_base : public std::ios_base {
+ public:
+ logstream_ios_base(std::ios_base::fmtflags initval,
+ int initsize) {
+ flags(initval);
+ precision(initsize);
+ width(initsize);
+
}
+ } initset, initclear;
+ /**
+ * fill character.
+ */
+ int fillchar;
+ /**
+ * true if fill character is set.
+ */
+ bool fillset;
+ /**
+ * true if assigned level was same or higher than level of
associated logger.
+ */
+ bool enabled;
+ /**
+ * associated logger.
+ */
+ log4cxx::LoggerPtr logger;
+ /**
+ * associated level.
+ */
+ log4cxx::LevelPtr level;
+ /**
+ * associated level.
+ */
+ log4cxx::spi::LocationInfo location;
+ };
+
+
+ /**
+ * Template for a STL-like stream API for log4cxx. Instances of
log4cxx::basic_logstream
+ * are emphatically not for use by multiple threads and in general
should be short-lived
+ * function scoped objects. Using log4cxx::basic_logstream as a
class member or
+ * static instance should be avoided in the same manner as you would
avoid placing a std::ostringstream
+ * in those locations. Insertion operations are generally
short-circuited if the
+ * level for the stream is not the same of higher that the level of
the associated logger.
+ */
+ template <class Ch>
+ class LOG4CXX_EXPORT basic_logstream : public logstream_base {
+ public:
+ /**
+ * Constructor.
+ */
+ inline basic_logstream(const log4cxx::LoggerPtr& logger,
+ const log4cxx::LevelPtr& level) : logstream_base(logger,
level), stream(0) {
}
-
- inline void flush() {
- flush(currentLocation);
+
+ /**
+ * Constructor.
+ */
+ inline basic_logstream(const Ch* loggerName,
+ const log4cxx::LevelPtr& level) :
logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0) {
}
+ /**
+ * Constructor.
+ */
+ inline basic_logstream(const std::basic_string<Ch>& loggerName,
+ const log4cxx::LevelPtr& level) :
logstream_base(log4cxx::Logger::getLogger(loggerName), level), stream(0) {
+ }
+
+ inline ~basic_logstream() {
+ }
+
+ /**
+ * Insertion operator for std::fixed and similar manipulators.
+ */
+ inline basic_logstream& operator<<(std::ios_base&
(*manip)(std::ios_base&)) {
+ logstream_base::operator<<(manip);
+ return *this;
+ }
+
+ /**
+ * Insertion operator for logstream_base::log.
+ */
+ inline basic_logstream& operator<<(logstream_base&
(*manip)(logstream_base&)) {
+ logstream_base::operator<<(manip);
+ return *this;
+ }
+
+ /**
+ * Insertion operator for level.
+ */
+ inline basic_logstream& operator<<(const log4cxx::LevelPtr& level)
{
+ logstream_base::operator<<(level);
+ return *this;
+ }
+ /**
+ * Insertion operator for location.
+ */
+ inline basic_logstream& operator<<(const
log4cxx::spi::LocationInfo& location) {
+ logstream_base::operator<<(location);
+ return *this;
+ }
+
+
+ /**
+ * Template to allow any class with an std::basic_ostream inserter
+ * to be applied to this class.
+ */
+ template <class V>
+ inline basic_logstream& operator<<(const V& val) {
+ if (LOG4CXX_UNLIKELY(isEnabled())) {
+ std::basic_ostream<Ch>& os = *this;
+ os << val;
+ }
+ return *this;
+ }
+
- ::std::basic_ostream<logstream_char>& getStream() {
- if (0 == impl) {
- impl = new ::std::basic_ostringstream<logstream_char>();
+ /**
+ * Cast operator to provide access to embedded
std::basic_ostream.
+ */
+ inline operator std::basic_ostream<Ch>&() {
+ if (stream == 0) {
+ stream = new std::basic_stringstream<Ch>();
+ refresh_stream_state();
+ }
+ return *stream;
+ }
+
+ protected:
+ /**
+ * [EMAIL PROTECTED]
+ */
+ virtual void log(LoggerPtr& logger,
+ const LevelPtr& level,
+ const log4cxx::spi::LocationInfo& location) {
+ if (stream != 0) {
+ std::basic_string<Ch> msg = stream->str();
+ if (!msg.empty()) {
+ logger->log(level, msg, location);
+ }
+ }
+ }
+
+ /**
+ * [EMAIL PROTECTED]
+ */
+ virtual void erase() {
+ if (stream != 0) {
+ std::basic_string<Ch> emptyStr;
+ stream->str(emptyStr);
+ }
+ }
+
+ /**
+ * [EMAIL PROTECTED]
+ */
+ virtual void get_stream_state(std::ios_base& base,
+ std::ios_base& mask,
+ int& fill,
+ bool& fillSet) const {
+ if (stream != 0) {
+ std::ios_base::fmtflags flags = stream->flags();
+ base.flags(flags);
+ mask.flags(flags);
+ int width = stream->width();
+ base.width(width);
+ mask.width(width);
+ int precision = stream->precision();
+ base.precision(precision);
+ mask.precision(precision);
+ fill = stream->fill();
+ fillSet = true;
+ }
+ }
+ /**
+ * [EMAIL PROTECTED]
+ */
+ virtual void refresh_stream_state() {
+ if (stream != 0) {
+ int fillchar;
+ if(logstream_base::set_stream_state(*stream, fillchar)) {
+ stream->fill(fillchar);
+ }
}
- impl->flags(flags());
- impl->precision(precision());
- impl->width(width());
- return *impl;
}
-
- private:
- logstream(const logstream&);
- logstream& operator=(const logstream&);
- LoggerPtr logger;
- LevelPtr currentLevel;
- ::std::basic_ostringstream<logstream_char>* impl;
- bool enabled;
- ::log4cxx::spi::LocationInfo currentLocation;
-
+
+
+ private:
+ std::basic_stringstream<Ch>* stream;
+
};
-
-} // namespace log4cxx
+
+ typedef basic_logstream<char> logstream;
+#if LOG4CXX_HAS_WCHAR_T
+ typedef basic_logstream<wchar_t> wlogstream;
+#endif
-LOG4CXX_EXPORT ::log4cxx::logstream& operator<<(
- ::log4cxx::logstream& lhs,
- const char* rhs);
-
-LOG4CXX_EXPORT ::log4cxx::logstream& operator<<(
- ::log4cxx::logstream& lhs,
- const ::log4cxx::LogString& rhs);
-
-
-LOG4CXX_EXPORT ::log4cxx::logstream& operator<<(
- ::log4cxx::logstream& lhs,
- const ::log4cxx::spi::LocationInfo& rhs);
-
-
-LOG4CXX_EXPORT ::log4cxx::logstream& operator<<(
- ::log4cxx::logstream& lhs,
- const ::log4cxx::LevelPtr& rhs);
-
-
-LOG4CXX_EXPORT ::log4cxx::logstream& operator<<(
- ::log4cxx::logstream& lhs,
- ::std::ios_base& (*manip)(::std::ios_base&));
-
-
-//
-// template for all other insertion operators
-//
-template<class ArbitraryType>
-::log4cxx::logstream& operator<<(
- ::log4cxx::logstream& lhs,
- const ArbitraryType& rhs) {
- if (LOG4CXX_UNLIKELY(lhs.isEnabled())) {
- lhs.getStream() << rhs;
- }
- return lhs;
-}
+} // namespace log4cxx
#if !defined(LOG4CXX_ENDMSG)
-#define LOG4CXX_ENDMSG LOG4CXX_LOCATION_FLUSH
+#define LOG4CXX_ENDMSG LOG4CXX_LOCATION << log4cxx::logstream_base::log;
#endif
Modified: logging/log4cxx/trunk/src/test/cpp/streamtestcase.cpp
URL:
http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/test/cpp/streamtestcase.cpp?rev=592933&r1=592932&r2=592933&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/test/cpp/streamtestcase.cpp (original)
+++ logging/log4cxx/trunk/src/test/cpp/streamtestcase.cpp Wed Nov 7 14:45:35
2007
@@ -24,9 +24,11 @@
#include <log4cxx/simplelayout.h>
#include <log4cxx/spi/loggingevent.h>
#include "insertwide.h"
+#include <log4cxx/stream.h>
using namespace log4cxx;
using namespace log4cxx::helpers;
+using namespace std;
class ExceptionOnInsert {
public:
@@ -65,6 +67,18 @@
CPPUNIT_TEST(testWideAppend);
CPPUNIT_TEST(testWideWidth);
#endif
+ CPPUNIT_TEST(testBaseFlags);
+ CPPUNIT_TEST(testBasePrecisionAndWidth);
+ CPPUNIT_TEST(testLogStreamSimple);
+ CPPUNIT_TEST(testLogStreamMultiple);
+ CPPUNIT_TEST(testLogStreamShortCircuit);
+ CPPUNIT_TEST_EXCEPTION(testLogStreamInsertException,
std::exception);
+ CPPUNIT_TEST(testLogStreamScientific);
+ CPPUNIT_TEST(testLogStreamPrecision);
+ CPPUNIT_TEST(testLogStreamWidth);
+ CPPUNIT_TEST(testLogStreamDelegate);
+ CPPUNIT_TEST(testLogStreamFormattingPersists);
+ CPPUNIT_TEST(testSetWidthInsert);
CPPUNIT_TEST_SUITE_END();
VectorAppenderPtr vectorAppender;
@@ -155,6 +169,135 @@
CPPUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("[__10.00]")), msg);
}
#endif
+ void testBaseFlags() {
+ logstream base1(Logger::getRootLogger(), Level::getInfo());
+ logstream base2(Logger::getRootLogger(), Level::getInfo());
+ base1 << std::boolalpha;
+ base2 << std::noboolalpha;
+ std::ostringstream os1a, os1b, os2a, os2b;
+ os1a << std::boolalpha;
+ int fillchar;
+ if (base1.set_stream_state(os1b, fillchar)) {
+ os1b.fill(fillchar);
+ }
+ CPPUNIT_ASSERT_EQUAL(os1a.flags(), os1b.flags());
+ os2a << std::noboolalpha;
+ if (base2.set_stream_state(os2b, fillchar)) {
+ os2b.fill(fillchar);
+ }
+ CPPUNIT_ASSERT_EQUAL(os2a.flags(), os2b.flags());
+ }
+
+
+ void testBasePrecisionAndWidth() {
+ logstream base(Logger::getRootLogger(), Level::getInfo());
+ base.precision(2);
+ base.width(5);
+ std::ostringstream os1, os2;
+ os1.precision(2);
+ os1.width(5);
+ os1 << 3.1415926;
+ int fillchar;
+ if (base.set_stream_state(os2, fillchar)) {
+ os2.fill(fillchar);
+ }
+ os2 << 3.1415926;
+ string expected(os1.str());
+ string actual(os2.str());
+ CPPUNIT_ASSERT_EQUAL(expected, actual);
+ }
+
+ void testLogStreamSimple() {
+ logstream root(Logger::getRootLogger(), Level::getInfo());
+ root << "This is a test" << LOG4CXX_ENDMSG;
+ CPPUNIT_ASSERT_EQUAL((size_t) 1,
vectorAppender->getVector().size());
+ }
+
+ void testLogStreamMultiple() {
+ logstream root(Logger::getRootLogger(), Level::getInfo());
+ root << "This is a test" << ": Details to follow" << LOG4CXX_ENDMSG;
+ CPPUNIT_ASSERT_EQUAL((size_t) 1,
vectorAppender->getVector().size());
+ }
+
+ void testLogStreamShortCircuit() {
+ LoggerPtr logger(Logger::getLogger("StreamTestCase.shortCircuit"));
+ logger->setLevel(Level::getInfo());
+ logstream os(logger, Level::getDebug());
+ ExceptionOnInsert someObj;
+ os << someObj << LOG4CXX_ENDMSG;
+ CPPUNIT_ASSERT_EQUAL((size_t) 0, vectorAppender->getVector().size());
+ }
+
+ void testLogStreamInsertException() {
+ LoggerPtr logger(Logger::getLogger("StreamTestCase.insertException"));
+ ExceptionOnInsert someObj;
+ logstream os(logger, Level::getInfo());
+ os << someObj << LOG4CXX_ENDMSG;
+ }
+
+ void testLogStreamScientific() {
+ LoggerPtr root(Logger::getRootLogger());
+ logstream os(root, Level::getInfo());
+ os << std::scientific << 0.000001115 << LOG4CXX_ENDMSG;
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ CPPUNIT_ASSERT(msg.find(LOG4CXX_STR("e-")) != LogString::npos ||
+ msg.find(LOG4CXX_STR("E-")) != LogString::npos);
+ }
+
+ void testLogStreamPrecision() {
+ LoggerPtr root(Logger::getRootLogger());
+ logstream os(root, Level::getInfo());
+ os << std::setprecision(4) << 1.000001 << LOG4CXX_ENDMSG;
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ CPPUNIT_ASSERT(msg.find(LOG4CXX_STR("1.00000")) == LogString::npos);
+ }
+
+
+ void testLogStreamWidth() {
+ LoggerPtr root(Logger::getRootLogger());
+ logstream os(root, Level::getInfo());
+ os << '[' << std::fixed << std::setprecision(2) << std::setw(7) <<
std::right << std::setfill('_') << 10.0 << ']' << LOG4CXX_ENDMSG;
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ CPPUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("[__10.00]")), msg);
+ }
+
+ void report(std::ostream& os) {
+ os << "This just in: \n";
+ os << "Use logstream in places that expect a std::ostream.\n";
+ }
+
+ void testLogStreamDelegate() {
+ logstream root(Logger::getRootLogger(), Level::getInfo());
+ report(root);
+ root << LOG4CXX_ENDMSG;
+ CPPUNIT_ASSERT_EQUAL((size_t) 1,
vectorAppender->getVector().size());
+ }
+
+ void testLogStreamFormattingPersists() {
+ LoggerPtr root(Logger::getRootLogger());
+ root->setLevel(Level::getInfo());
+ logstream os(root, Level::getDebug());
+ os << std::hex << 20 << LOG4CXX_ENDMSG;
+ os << Level::getInfo() << 16 << LOG4CXX_ENDMSG;
+ spi::LoggingEventPtr event(vectorAppender->getVector()[0]);
+ LogString msg(event->getMessage());
+ CPPUNIT_ASSERT_EQUAL(LogString(LOG4CXX_STR("10")), msg);
+ }
+
+ void testSetWidthInsert() {
+ LoggerPtr root(Logger::getRootLogger());
+ root->setLevel(Level::getInfo());
+ logstream os(root, Level::getInfo());
+ os << std::setw(5);
+ CPPUNIT_ASSERT_EQUAL(5, os.width());
+ }
+
+
+
+
};
CPPUNIT_TEST_SUITE_REGISTRATION(StreamTestCase);