// // The developer of the original code and/or files is Tripwire, Inc. // Portions created by Tripwire, Inc. are copyright (C) 2000-2018 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 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& s, bool fCStyleFormatting) { static const std::num_get* png; std::basic_istringstream 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(), 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& Format(numT n, std::basic_string& sBuf, bool fCStyleFormatting = false) { static const std::num_put* pnp; std::basic_ostringstream 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::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::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::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::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; }