// // The developer of the original code and/or files is Tripwire, Inc. // Portions created by Tripwire, Inc. are copyright (C) 2000-2017 Tripwire, // Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights // reserved. // // This program is free software. The contents of this file are subject // to the terms of the GNU General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your // option) any later version. You may redistribute it and/or modify it // only in compliance with the GNU General Public License. // // This program is distributed in the hope that it will be useful. // However, this program is distributed AS-IS WITHOUT ANY // WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS // FOR A PARTICULAR PURPOSE. Please see the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, // USA. // // Nothing in the GNU General Public License or any other license to use // the code or files shall permit you to use Tripwire's trademarks, // service marks, or other intellectual property without Tripwire's // prior written consent. // // If you have any questions, please contact Tripwire, Inc. at either // info@tripwire.org or www.tripwire.org. // /////////////////////////////////////////////////////////////////////////////// // twlocale.cpp // //========================================================================= // INCLUDES //========================================================================= #include "stdcore.h" #include "twlocale.h" #include "corestrings.h" //TODO:mdb -- for some reason, this isn't being included on gcc/stlport // How is this being included for other platforms (I can't find // references to locale.h anywhere in the code!) // #if HAVE_GCC #include #endif //HAVE_GCC //========================================================================= // STANDARD LIBRARY INCLUDES //========================================================================= //========================================================================= // UTIL FUNCTION PROTOTYPES //========================================================================= static TSTRING& util_FormatTimeC( struct tm* ptm, TSTRING& strBuf ); static TSTRING& util_FormatTime( struct tm* ptm, TSTRING& strBuf ); #if !USES_CLIB_DATE_FUNCTION static TSTRING& util_FormatTimeCPlusPlus( struct tm* ptm, TSTRING& strBuf ); #endif //========================================================================= // PUBLIC METHOD CODE //========================================================================= #if IS_AROS #define tzset() #endif void cTWLocale::InitGlobalLocale() { cDebug d("cTWLocale::InitGlobalLocale"); d.TraceDetail( "Attempting to set the program locale from the" "default \"C\" locale to the system-default locale." ); #if USE_CLIB_LOCALE char* pchLocale = setlocale( LC_ALL, "" ); d.TraceDetail( "C++ locale is incomplete or unavailable with this compiler, so" "only changing the C-language locale. Some C++ locale-specific functionality" "may not function properly." ); if( pchLocale ) { d.TraceDebug( "locale changed to the system-default locale (non-C++): <%s>\n", pchLocale ); } else { d.TraceDebug( "Error: unable to change locale to the system-default.\n" "It is possible that there is no other locale than\n" "the \"C\" locale on this platform.\n" ); } #else std::locale l(""); std::locale::global( l ); d.TraceDebug( "locale changed to the system default std::locale (C++): <%s>\n", l.name().c_str() ); #endif } TSTRING cTWLocale::FormatNumberAsHex( int32 i ) { // // preconditions // ASSERT( sizeof( long ) >= sizeof( int32 ) ); // must be able to cast to 'long' // // convert long to a string // TOSTRINGSTREAM sstr; sstr.imbue( std::locale::classic() ); sstr.setf( std::ios_base::hex, std::ios_base::basefield ); const std::num_put< TCHAR > *pnp = 0, &np = tss::GetFacet( sstr.getloc(), pnp ); np.put( sstr, sstr, sstr.fill(), (long)i ); // // return it // return( sstr.str() ); } template< class numT, class CharT > class cFormatNumberUtil { public: // TODO:BAM -- these functions should really maybe take a stringstream that has been // already set up for formatting (basefield, locale, etc.) that way we can merge //. the FormatNumberAsHex function as well // //============================================================================= // template< class numT, class CharT > // numT // cFormatNumberUtil::FormatNumber( const std::basic_string< CharT >& s, bool fCStyleFormatting = false ) //----------------------------------------------------------------------------- // EFFECTS: Does all actual formatting for FormatNumber methods static numT Format( const std::basic_string< CharT >& s, bool fCStyleFormatting ) { static const std::num_get< CharT >* png; std::basic_istringstream< CharT > ss( s ); std::ios_base::iostate state; numT n; if( fCStyleFormatting ) ss.imbue( std::locale::classic() ); tss::GetFacet( ss.getloc(), png ).get( ss, std::istreambuf_iterator< CharT >(), ss, state, n ); if( ( state & std::ios_base::failbit ) != 0 ) throw eTWLocaleBadNumFormat(); return( n ); } //============================================================================= // std::basic_string< CharT >& // Format( numT n, std::basic_string< CharT >& sBuf ) //----------------------------------------------------------------------------- // EFFECTS: Does all actual formatting for FormatNumber methods // static std::basic_string< CharT >& Format( numT n, std::basic_string< CharT >& sBuf, bool fCStyleFormatting = false ) { static const std::num_put< CharT >* pnp; std::basic_ostringstream< CharT > ss; if( fCStyleFormatting ) ss.imbue( std::locale::classic() ); tss::GetFacet( ss.getloc(), pnp ).put( ss, ss, ss.fill(), n ); sBuf = ss.str(); return( sBuf ); } }; TSTRING cTWLocale::FormatNumberClassic( int32 i ) { TSTRING s; return cFormatNumberUtil< long, TCHAR >::Format( i, s, true ); } int32 cTWLocale::FormatNumberClassic( const TSTRING& s ) { return cFormatNumberUtil< long, TCHAR >::Format( s, true ); } TSTRING& cTWLocale::FormatNumber( uint64 ui, TSTRING& strBuf ) { // try to use the int64 version if( ui <= (uint64)TSS_INT64_MAX ) return( FormatNumber( (int64)ui, strBuf ) ); else { #if IS_MSVC // MSVC can't convert from uint64 to a double for some reason strBuf = TSS_GetString( cCore, core::STR_NUMBER_TOO_BIG ); return( strBuf ); #else ASSERT( std::numeric_limits::max() >= TSS_UINT64_MAX ); return( cFormatNumberUtil< double, TCHAR >::Format( (double)ui, strBuf ) ); #endif } } TSTRING& cTWLocale::FormatNumber( int64 i, TSTRING& strBuf ) { // try to use the int32 version if( i <= (int64)TSS_INT32_MAX ) return( FormatNumber( (int32)i, strBuf ) ); else { ASSERT( std::numeric_limits::max() >= TSS_INT64_MAX ); return( cFormatNumberUtil< double, TCHAR >::Format( (double)i, strBuf ) ); } } TSTRING& cTWLocale::FormatNumber( uint32 ui, TSTRING& strBuf ) { ASSERT( sizeof(unsigned long) >= sizeof(uint32) ); // must be able to cast to 'ulong' return( cFormatNumberUtil< unsigned long, TCHAR >::Format( (unsigned long)ui, strBuf ) ); } TSTRING& cTWLocale::FormatNumber( int32 i, TSTRING& strBuf ) { ASSERT( sizeof(long) >= sizeof(int32) ); // must be able to cast to 'long' return( cFormatNumberUtil< long, TCHAR >::Format( (long)i, strBuf ) ); } TSTRING& cTWLocale::FormatTime( int64 t, TSTRING& strBuf ) { // clear return string strBuf.erase(); tzset(); time_t tmpTime = t; struct tm * ptm = localtime( &tmpTime ); if( ptm ) { util_FormatTime( ptm, strBuf ); } else { strBuf = TSS_GetString( cCore, core::STR_UNKNOWN_TIME ); } return( strBuf ); } //========================================================================= // UTIL FUNCTION IMPLEMENTATION //========================================================================= TSTRING& util_FormatTime( struct tm* ptm, TSTRING& strBuf ) { ASSERT( ptm ); #if USES_CLIB_DATE_FUNCTION return util_FormatTimeC( ptm, strBuf ); #else return util_FormatTimeCPlusPlus( ptm, strBuf ); #endif } #if !USES_CLIB_DATE_FUNCTION TSTRING& util_FormatTimeCPlusPlus( struct tm* ptm, TSTRING& strBuf ) { ASSERT( ptm ); TOSTRINGSTREAM sstr; static const std::time_put* ptp; // // format date // #if IS_MSVC // MSVC uses old put() signature which didn't have the fill character, (and uses proprietary '#') tss::GetFacet( sstr.getloc(), ptp ).put( sstr, sstr, ptm, 'c', '#' ); #else tss::GetFacet( sstr.getloc(), ptp ).put( sstr, sstr, sstr.fill(), ptm, 'c' ); #endif strBuf = sstr.str(); return strBuf; } #endif TSTRING& util_FormatTimeC( struct tm* ptm, TSTRING& strBuf ) { ASSERT( ptm ); TCHAR achTimeBuf[256]; /* XXX: This should check (#ifdef) for strftime - PH */ size_t nbWritten = _tcsftime( achTimeBuf, countof( achTimeBuf ), #if IS_MSVC // MSVC uses proprietary '#' _T("%#c"), #else _T("%c"), #endif ptm ); if( nbWritten ) strBuf = achTimeBuf; else strBuf = TSS_GetString( cCore, core::STR_UNKNOWN_TIME ); return strBuf; }