#include "wx/xlocale.h"
#include <errno.h>
+#include <locale.h>
// ----------------------------------------------------------------------------
// module globals
{
if ( !gs_cLocale )
{
- gs_cLocale = new wxXLocale(static_cast<wxXLocaleCTag *>(NULL));
+ // NOTE: bcc551 has trouble doing static_cast with incomplete
+ // type definition. reinterpret_cast used as workaround
+ gs_cLocale = new wxXLocale( reinterpret_cast<wxXLocaleCTag *>(NULL) );
}
return *gs_cLocale;
m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL);
}
}
-
+
// TODO: wxLocale performs many more manipulations of the given locale
// string in the attempt to set a valid locale; reusing that code
// (changing it to take a generic wxTryLocale callback) would be nice
#define CTYPE_UPPER 0x0200
#define CTYPE_XDIGIT 0x0400
-static unsigned int gs_lookup[] =
+static const unsigned int gs_lookup[] =
{
0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0004,
case !wxHAS_XLOCALE_SUPPORT...
*/
-#define IMPLEMENT_STRTOX_L_START \
- wxCHECK(loc.IsOk(), 0); \
- \
- /* (Try to) temporary set the locale to 'C' */ \
- const char *oldLocale = wxSetlocale(LC_NUMERIC, ""); \
- const char *tmp = wxSetlocale(LC_NUMERIC, "C"); \
- if ( !tmp ) \
- { \
- /* restore the original locale */ \
- wxSetlocale(LC_NUMERIC, oldLocale); \
- errno = EINVAL; \
- /* signal an error (better than nothing) */ \
- return 0; \
- } \
- \
-
-
-#define IMPLEMENT_STRTOX_L_END \
- /* restore the original locale */ \
- wxSetlocale(LC_NUMERIC, oldLocale); \
- return ret;
+namespace
+{
+
+// Helper class that changes LC_NUMERIC facet of the global locale in its ctor
+// to "C" locale and restores it in its dtor later.
+class CNumericLocaleSetter
+{
+public:
+ CNumericLocaleSetter()
+ : m_oldLocale(wxStrdupA(setlocale(LC_NUMERIC, NULL)))
+ {
+ if ( !wxSetlocale(LC_NUMERIC, "C") )
+ {
+ // Setting locale to "C" should really always work.
+ wxFAIL_MSG( wxS("Couldn't set LC_NUMERIC to \"C\"") );
+ }
+ }
+
+ ~CNumericLocaleSetter()
+ {
+ wxSetlocale(LC_NUMERIC, m_oldLocale);
+ free(m_oldLocale);
+ }
+
+private:
+ char * const m_oldLocale;
+
+ wxDECLARE_NO_COPY_CLASS(CNumericLocaleSetter);
+};
+
+} // anonymous namespace
double wxStrtod_l(const wchar_t* str, wchar_t **endptr, const wxXLocale& loc)
{
- IMPLEMENT_STRTOX_L_START
- double ret = wxStrtod(str, endptr);
- IMPLEMENT_STRTOX_L_END
+ wxCHECK( loc.IsOk(), 0. );
+
+ CNumericLocaleSetter locSetter;
+
+ return wxStrtod(str, endptr);
}
double wxStrtod_l(const char* str, char **endptr, const wxXLocale& loc)
{
- IMPLEMENT_STRTOX_L_START
- double ret = wxStrtod(str, endptr);
- IMPLEMENT_STRTOX_L_END
+ wxCHECK( loc.IsOk(), 0. );
+
+ CNumericLocaleSetter locSetter;
+
+ return wxStrtod(str, endptr);
}
long wxStrtol_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc)
-{
- IMPLEMENT_STRTOX_L_START
- long ret = wxStrtol(str, endptr, base);
- IMPLEMENT_STRTOX_L_END
+{
+ wxCHECK( loc.IsOk(), 0 );
+
+ CNumericLocaleSetter locSetter;
+
+ return wxStrtol(str, endptr, base);
}
long wxStrtol_l(const char* str, char **endptr, int base, const wxXLocale& loc)
{
- IMPLEMENT_STRTOX_L_START
- long ret = wxStrtol(str, endptr, base);
- IMPLEMENT_STRTOX_L_END
+ wxCHECK( loc.IsOk(), 0 );
+
+ CNumericLocaleSetter locSetter;
+
+ return wxStrtol(str, endptr, base);
}
unsigned long wxStrtoul_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc)
{
- IMPLEMENT_STRTOX_L_START
- unsigned long ret = wxStrtoul(str, endptr, base);
- IMPLEMENT_STRTOX_L_END
+ wxCHECK( loc.IsOk(), 0 );
+
+ CNumericLocaleSetter locSetter;
+
+ return wxStrtoul(str, endptr, base);
}
unsigned long wxStrtoul_l(const char* str, char **endptr, int base, const wxXLocale& loc)
{
- IMPLEMENT_STRTOX_L_START
- unsigned long ret = wxStrtoul(str, endptr, base);
- IMPLEMENT_STRTOX_L_END
-}
+ wxCHECK( loc.IsOk(), 0 );
+
+ CNumericLocaleSetter locSetter;
+ return wxStrtoul(str, endptr, base);
+}
#endif // !defined(wxHAS_XLOCALE_SUPPORT)