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);


Reply via email to