Hi,

the attached patch fixes the UTF8 build on unix.

simpledateformat.cpp/h:
- new typedef for std::basic_string<localechar>
- Moved PatternToken to the .cpp file. This allows
  PatternToken::format to take a LocaleString which
  is necessary because LocaleString and LogString
  are not necessarily compatible when compiled with
  logchar=UTF8.

logstream.cpp/stream.h:
- Necessary changes to compile the test scenarios with
  logchar=utf8.

If there are no objections, I will commit those.

Thanks & Best Regards,

        Andreas

--- include/log4cxx/helpers/simpledateformat.h  2005-10-15 09:34:28.000000000 
+0200
+++ include/log4cxx/helpers/simpledateformat.h  2005-11-29 22:07:50.000000000 
+0100
@@ -27,6 +27,7 @@
 {
         namespace helpers
         {
+class PatternToken;
 
           /**
           Concrete class for formatting and parsing dates in a
@@ -56,53 +57,6 @@
                   */
                   void setTimeZone(const TimeZonePtr& zone);
 
-
-                  /**
-                  * Abstract inner class representing one format token
-                  * (one or more instances of a character).
-                  */
-                  class PatternToken {
-                  public:
-                       /**
-                        *   Constructor.
-                        */
-                       PatternToken();
-                       /**
-                       * Destructor.
-                       */
-                       virtual ~PatternToken();
-
-                       /**
-                       * Sets the time zone.
-                       * @param zone new time zone.
-                       */
-                       virtual void setTimeZone(const TimeZonePtr& zone);
-
-                      /**
-                      * Appends the formatted content to the string.
-                      * @param s string to which format contribution is 
appended.
-                      * @param date exploded date/time.
-                      * @param p memory pool.
-                      */
-                       virtual void format(LogString& s,
-                                           const apr_time_exp_t& date,
-                                           log4cxx::helpers::Pool& p) const = 
0;
-
-
-
-                  private:
-                      /**
-                      *    Private copy constructor.
-                      */
-                       PatternToken(const PatternToken&);
-                       /**
-                       * Private assignment operator.
-                       */
-                       PatternToken& operator=(const PatternToken&);
-                  };
-
-
-
           private:
                   /**
                   *    Time zone.
--- src/simpledateformat.cpp    2005-10-15 09:34:35.000000000 +0200
+++ src/simpledateformat.cpp    2005-11-29 22:09:25.000000000 +0100
@@ -24,29 +24,20 @@
 #include <locale>
 #endif
 
+
+/*
+ * implementation works on localechar sequences to avoid too many calls
+ * to Transformer::decode() when the date is formatted.
+ */
 #if LOG4CXX_HAS_STD_WLOCALE && LOG4CXX_HAS_WCHAR_T
-typedef wchar_t localechar;
-    #define LOG4CXX_LOCALE_STR(str) L ## str
-  #else
-typedef char localechar;
-    #define LOG4CXX_LOCALE_STR(str) str
+  typedef wchar_t localechar;
+  #define LOG4CXX_LOCALE_STR(str) L ## str
+#else
+  typedef char localechar;
+  #define LOG4CXX_LOCALE_STR(str) str
 #endif
 
-
-
-SimpleDateFormat::PatternToken::PatternToken()
-{
-}
-
-SimpleDateFormat::PatternToken::~PatternToken()
-{
-}
-
-void SimpleDateFormat::PatternToken::setTimeZone( const TimeZonePtr & zone )
-{
-}
-
-
+typedef std::basic_string < localechar > LocaleString;
 
 
 namespace log4cxx
@@ -56,26 +47,38 @@
     namespace SimpleDateFormatImpl
     {
 
-
-
-
 #if LOG4CXX_HAS_STD_LOCALE
-      void renderFacet( const std::locale & locale, std::basic_ostream < 
localechar > & buffer, const tm * time,
-           const localechar spec )
+     /**
+      * Renders a time structure according to a specific format.
+      *
+      * @param locale The locale to use for the formatting.
+      * @param buffer The buffer which retrieves the result.
+      * @param time The time structure to render.
+      * @param spec The format for rendering the structure.
+      */
+     void renderFacet( const std::locale & locale, std::basic_ostream < 
localechar > & buffer, 
+                       const tm * time, const localechar spec )
            {
+   //   std::basic_ostream < localechar > buffer;
 
        #if defined(_USEFAC)
              _USEFAC( locale, std::time_put < localechar > ).put( buffer, 
buffer, time, spec );
        #else
              std::use_facet < std::time_put < localechar > > ( locale ).put( 
buffer, buffer, buffer.fill(), time, spec );
        #endif
-
       }
 #endif
 
-
-      void renderFacet( LogString & result, apr_time_exp_t * tm, const char * 
format )
+      /**
+       * Renders an APR time structure according to a specific format.
+       *
+       * @param result The LogString which retrieves the result.
+       * @param tm The APR time structure to render.
+       * @param format The format for rendering the structure.
+       */
+      void renderFacet( LocaleString & res, apr_time_exp_t * tm, const char * 
format )
       {
+
         enum
         {
           BUFSIZE = 256
@@ -89,25 +92,78 @@
           buf[0] = '?';
           retsize = 1;
         }
+        LogString result;
         Transcoder::decode( buf, retsize, result );
+        Transcoder::encode( result, res );
       }
 
     }
+
+    /**
+     * Abstract inner class representing one format token
+     * (one or more instances of a character).
+     */
+    class PatternToken {
+    public:
+          PatternToken();
+
+          virtual ~PatternToken();
+
+          /**
+           * Sets the time zone.
+           * @param zone new time zone.
+           */
+          virtual void setTimeZone(const TimeZonePtr& zone);
+
+          /**
+           * Appends the formatted content to the string.
+           * @param s string to which format contribution is appended.
+           * @param date exploded date/time.
+           * @param p memory pool.
+           */
+          virtual void format(LocaleString& s,
+                              const apr_time_exp_t& date,
+                              log4cxx::helpers::Pool& p) const = 0;
+
+    private:
+          /**
+           * Private copy constructor.
+           */
+          PatternToken(const PatternToken&);
+
+          /**
+           * Private assignment operator.
+           */
+          PatternToken& operator=(const PatternToken&);
+    };
+
   }
 }
 
 using namespace log4cxx::helpers::SimpleDateFormatImpl;
+using namespace log4cxx::helpers;
 
+PatternToken::PatternToken()
+{
+}
 
+PatternToken::~PatternToken()
+{
+}
 
-class LiteralToken : public SimpleDateFormat::PatternToken
+void PatternToken::setTimeZone( const TimeZonePtr & zone )
+{
+}
+
+
+class LiteralToken : public PatternToken
 {
 public:
   LiteralToken( localechar ch, int count ) : ch( ch ), count( count )
   {
   }
 
-  void format( std::basic_string < localechar > & s, const apr_time_exp_t & 
tm, Pool & p ) const
+  void format( LocaleString& s, const apr_time_exp_t & tm, Pool & p ) const
   {
     s.append( count, ch );
   }
@@ -119,14 +175,14 @@
 
 
 
-class EraToken : public SimpleDateFormat::PatternToken
+class EraToken : public PatternToken
 {
 public:
   EraToken( int count, const std::locale * locale )
   {
   }
 
-  void format( std::basic_string < localechar > & s, const apr_time_exp_t & 
tm, Pool & p ) const
+  void format( LocaleString& s, const apr_time_exp_t & tm, Pool & p ) const
   {
     s.append( LOG4CXX_LOCALE_STR( "AD" ) );
   }
@@ -134,7 +190,7 @@
 
 
 
-class NumericToken : public SimpleDateFormat::PatternToken
+class NumericToken : public PatternToken
 {
 public:
   NumericToken( size_t width ) : width( width )
@@ -143,7 +199,7 @@
 
   virtual int getField( const apr_time_exp_t & tm ) const = 0;
 
-  void format( std::basic_string < localechar > & s, const apr_time_exp_t & 
tm, Pool & p ) const
+  void format( LocaleString& s, const apr_time_exp_t & tm, Pool & p ) const
   {
     size_t initialLength = s.length();
     StringHelper::toString( getField( tm ), p, s );
@@ -191,7 +247,7 @@
 
 
 
-class AbbreviatedMonthNameToken : public SimpleDateFormat::PatternToken
+class AbbreviatedMonthNameToken : public PatternToken
 {
 public:
   AbbreviatedMonthNameToken( int width, const std::locale * locale ) : names( 
12 )
@@ -207,7 +263,7 @@
       {
         time.tm_mon = imon;
         renderFacet( * locale, buffer, & time, LOG4CXX_LOCALE_STR( 'b' ) );
-        std::basic_string < localechar > monthnames( buffer.str() );
+        LocaleString monthnames( buffer.str() );
         names[imon] = monthnames.substr( start );
         start = monthnames.length();
       }
@@ -223,19 +279,19 @@
     }
   }
 
-  void format( std::basic_string < localechar > & s, const apr_time_exp_t & 
tm, Pool & p ) const
+  void format( LocaleString& s, const apr_time_exp_t & tm, Pool & p ) const
   {
     s.append( names[tm.tm_mon] );
   }
 
 private:
-  std::vector < std::basic_string < localechar > > names;
+  std::vector < LocaleString > names;
 
 };
 
 
 
-class FullMonthNameToken : public SimpleDateFormat::PatternToken
+class FullMonthNameToken : public PatternToken
 {
 public:
   FullMonthNameToken( int width, const std::locale * locale ) : names( 12 )
@@ -251,7 +307,7 @@
       {
         time.tm_mon = imon;
         renderFacet( * locale, buffer, & time, LOG4CXX_LOCALE_STR( 'B' ) );
-        std::basic_string < localechar > monthnames( buffer.str() );
+        LocaleString monthnames( buffer.str() );
         names[imon] = monthnames.substr( start );
         start = monthnames.length();
       }
@@ -267,14 +323,13 @@
     }
   }
 
-  void format( std::basic_string < localechar > & s, const apr_time_exp_t & 
tm, Pool & p ) const
+  void format( LocaleString& s, const apr_time_exp_t & tm, Pool & p ) const
   {
     s.append( names[tm.tm_mon] );
   }
 
 private:
-  std::vector < std::basic_string < localechar > > names;
-
+  std::vector < LocaleString > names;
 };
 
 
@@ -354,7 +409,7 @@
 
 
 
-class AbbreviatedDayNameToken : public SimpleDateFormat::PatternToken
+class AbbreviatedDayNameToken : public PatternToken
 {
 public:
   AbbreviatedDayNameToken( int width, const std::locale * locale ) : names( 7 )
@@ -370,7 +425,7 @@
       {
         time.tm_wday = iday;
         renderFacet( * locale, buffer, & time, LOG4CXX_LOCALE_STR( 'a' ) );
-        std::basic_string < localechar > daynames( buffer.str() );
+        LocaleString daynames( buffer.str() );
         names[iday] = daynames.substr( start );
         start = daynames.length();
       }
@@ -386,19 +441,19 @@
     }
   }
 
-  void format( std::basic_string < localechar > & s, const apr_time_exp_t & 
tm, Pool & p ) const
+  void format( LocaleString& s, const apr_time_exp_t & tm, Pool & p ) const
   {
     s.append( names[tm.tm_wday] );
   }
 
 private:
-  std::vector < std::basic_string < localechar > > names;
+  std::vector < LocaleString > names;
 
 };
 
 
 
-class FullDayNameToken : public SimpleDateFormat::PatternToken
+class FullDayNameToken : public PatternToken
 {
 public:
   FullDayNameToken( int width, const std::locale * locale ) : names( 7 )
@@ -414,7 +469,7 @@
       {
         time.tm_wday = iday;
         renderFacet( * locale, buffer, & time, LOG4CXX_LOCALE_STR( 'A' ) );
-        std::basic_string < localechar > daynames( buffer.str() );
+        LocaleString daynames( buffer.str() );
         names[iday] = daynames.substr( start );
         start = daynames.length();
       }
@@ -430,13 +485,13 @@
     }
   }
 
-  void format( std::basic_string < localechar > & s, const apr_time_exp_t & 
tm, Pool & p ) const
+  void format( LocaleString& s, const apr_time_exp_t & tm, Pool & p ) const
   {
     s.append( names[tm.tm_wday] );
   }
 
 private:
-  std::vector < std::basic_string < localechar > > names;
+  std::vector < LocaleString > names;
 
 };
 
@@ -523,7 +578,7 @@
 
 
 
-class AMPMToken : public SimpleDateFormat::PatternToken
+class AMPMToken : public PatternToken
 {
 public:
   AMPMToken( int width, const std::locale * locale ) : names( 2 )
@@ -539,7 +594,7 @@
       {
         time.tm_hour = i * 12;
         renderFacet( * locale, buffer, & time, LOG4CXX_LOCALE_STR( 'p' ) );
-        std::basic_string < localechar > ampm = buffer.str();
+        LocaleString ampm = buffer.str();
         names[i] = ampm.substr( start );
         start = ampm.length();
       }
@@ -555,27 +610,27 @@
     }
   }
 
-  void format( std::basic_string < localechar > & s, const apr_time_exp_t & 
tm, Pool & p ) const
+  void format( LocaleString& s, const apr_time_exp_t & tm, Pool & p ) const
   {
     s.append( names[tm.tm_hour / 12] );
   }
 
 private:
-  std::vector < std::basic_string < localechar > > names;
+  std::vector < LocaleString > names;
 };
 
 
 
-class GeneralTimeZoneToken : public SimpleDateFormat::PatternToken
+class GeneralTimeZoneToken : public PatternToken
 {
 public:
   GeneralTimeZoneToken( int width )
   {
   }
 
-  void format( std::basic_string < localechar > & s, const apr_time_exp_t & 
tm, Pool & p ) const
+  void format( LocaleString& s, const apr_time_exp_t & tm, Pool & p ) const
   {
-    std::basic_string < localechar > tzID;
+    LocaleString tzID;
     Transcoder::encode( timeZone->getID(), tzID );
     s.append( tzID );
   }
@@ -591,14 +646,14 @@
 
 
 
-class RFC822TimeZoneToken : public SimpleDateFormat::PatternToken
+class RFC822TimeZoneToken : public PatternToken
 {
 public:
   RFC822TimeZoneToken( int width )
   {
   }
 
-  void format( std::basic_string < localechar > & s, const apr_time_exp_t & 
tm, Pool & p ) const
+  void format( LocaleString& s, const apr_time_exp_t & tm, Pool & p ) const
   {
     if ( tm.tm_gmtoff == 0 )
     {
@@ -614,7 +669,7 @@
         s[basePos] = LOG4CXX_LOCALE_STR( '-' );
         off = -off;
       }
-      std::basic_string < localechar > hours;
+      LocaleString hours;
       StringHelper::toString( off / 3600, p, hours );
       size_t hourPos = basePos + 2;
       //
@@ -624,7 +679,7 @@
       {
         s[hourPos--] = hours[i];
       }
-      std::basic_string < localechar > min;
+      LocaleString min;
       StringHelper::toString( ( off % 3600 ) / 60, p, min );
       size_t minPos = basePos + 4;
       //
@@ -650,9 +705,9 @@
 
 
       void addToken( const localechar spec, const int repeat, const 
std::locale * locale,
-           std::vector < SimpleDateFormat::PatternToken * > & pattern )
+           std::vector < PatternToken * > & pattern )
            {
-             SimpleDateFormat::PatternToken * token = NULL;
+             PatternToken * token = NULL;
              switch ( spec )
              {
                case LOG4CXX_LOCALE_STR( 'G' ):
@@ -757,7 +812,7 @@
       }
 
       void parsePattern( const LogString & fmt, const std::locale * locale,
-           std::vector < SimpleDateFormat::PatternToken * > & pattern )
+           std::vector < PatternToken * > & pattern )
            {
              if ( !fmt.empty() )
              {
@@ -826,7 +881,7 @@
   apr_status_t stat = timeZone->explode( & exploded, time );
   if ( stat == APR_SUCCESS )
   {
-    std::basic_string < localechar > formatted;
+    LocaleString formatted;
     for ( PatternTokenList::const_iterator iter = pattern.begin(); iter != 
pattern.end(); iter++ )
     {
       ( * iter )->format( formatted, exploded, p );
diff -urN log4cxx-0.9.8.org/include/log4cxx/stream.h 
log4cxx-0.9.8/include/log4cxx/stream.h
--- include/log4cxx/stream.h    2005-11-27 18:11:43.000000000 +0100
+++ include/log4cxx/stream.h    2005-12-03 12:16:42.000000000 +0100
@@ -151,6 +151,10 @@
   ::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,
diff -urN log4cxx-0.9.8.org/src/logstream.cpp log4cxx-0.9.8/src/logstream.cpp
--- src/logstream.cpp   2005-11-27 18:11:56.000000000 +0100
+++ src/logstream.cpp   2005-12-03 12:14:27.000000000 +0100
@@ -37,6 +37,26 @@
 }
 #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) {

Reply via email to