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