#define _LIBCPP_NONUNIQUE_RTTI_BIT (1ULL << 63)
#endif
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_LIBCPP_MSVCRT) || \
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_LIBCPP_MSVCRT_LIKE) || \
defined(__sun__) || defined(__NetBSD__) || defined(__CloudABI__)
#define _LIBCPP_LOCALE__L_EXTENSIONS 1
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
-#if !defined(_LIBCPP_LOCALE__L_EXTENSIONS) || defined(_LIBCPP_MSVCRT)
+#if !defined(_LIBCPP_LOCALE__L_EXTENSIONS)
struct __libcpp_locale_guard {
_LIBCPP_INLINE_VISIBILITY
__libcpp_locale_guard(locale_t& __loc) : __old_loc_(uselocale(__loc)) {}
__libcpp_locale_guard(__libcpp_locale_guard const&);
__libcpp_locale_guard& operator=(__libcpp_locale_guard const&);
};
+#elif defined(_LIBCPP_MSVCRT_LIKE)
+struct __libcpp_locale_guard {
+ __libcpp_locale_guard(locale_t __l) :
+ __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)),
+ __locale_collate(setlocale(LC_COLLATE, __l.__get_locale())),
+ __locale_ctype(setlocale(LC_CTYPE, __l.__get_locale())),
+ __locale_monetary(setlocale(LC_MONETARY, __l.__get_locale())),
+ __locale_numeric(setlocale(LC_NUMERIC, __l.__get_locale())),
+ __locale_time(setlocale(LC_TIME, __l.__get_locale()))
+ // LC_MESSAGES is not supported on Windows.
+ {}
+ ~__libcpp_locale_guard() {
+ setlocale(LC_COLLATE, __locale_collate);
+ setlocale(LC_CTYPE, __locale_ctype);
+ setlocale(LC_MONETARY, __locale_monetary);
+ setlocale(LC_NUMERIC, __locale_numeric);
+ setlocale(LC_TIME, __locale_time);
+ _configthreadlocale(__status);
+ }
+ int __status;
+ char* __locale_collate;
+ char* __locale_ctype;
+ char* __locale_monetary;
+ char* __locale_numeric;
+ char* __locale_time;
+};
#endif
#include <__config>
#include <stdio.h>
#include <xlocinfo.h> // _locale_t
+#include <__nullptr>
#define LC_COLLATE_MASK _M_COLLATE
#define LC_CTYPE_MASK _M_CTYPE
| LC_NUMERIC_MASK \
| LC_TIME_MASK )
-#define locale_t _locale_t
+class locale_t {
+public:
+ locale_t()
+ : __locale(nullptr), __locale_str(nullptr) {}
+ locale_t(std::nullptr_t)
+ : __locale(nullptr), __locale_str(nullptr) {}
+ locale_t(_locale_t __locale, const char* __locale_str)
+ : __locale(__locale), __locale_str(__locale_str) {}
+
+ friend bool operator==(const locale_t& __left, const locale_t& __right) {
+ return __left.__locale == __right.__locale;
+ }
+
+ friend bool operator==(const locale_t& __left, int __right) {
+ return __left.__locale == nullptr && __right == 0;
+ }
+
+ friend bool operator==(const locale_t& __left, std::nullptr_t) {
+ return __left.__locale == nullptr;
+ }
+
+ friend bool operator==(int __left, const locale_t& __right) {
+ return __left == 0 && nullptr == __right.__locale;
+ }
+
+ friend bool operator==(std::nullptr_t, const locale_t& __right) {
+ return nullptr == __right.__locale;
+ }
+
+ friend bool operator!=(const locale_t& __left, const locale_t& __right) {
+ return !(__left == __right);
+ }
+
+ friend bool operator!=(const locale_t& __left, int __right) {
+ return !(__left == __right);
+ }
+
+ friend bool operator!=(const locale_t& __left, std::nullptr_t __right) {
+ return !(__left == __right);
+ }
+
+ friend bool operator!=(int __left, const locale_t& __right) {
+ return !(__left == __right);
+ }
+
+ friend bool operator!=(std::nullptr_t __left, const locale_t& __right) {
+ return !(__left == __right);
+ }
+
+ operator bool() const {
+ return __locale != nullptr;
+ }
+
+ const char* __get_locale() const { return __locale_str; }
+
+ operator _locale_t() const {
+ return __locale;
+ }
+private:
+ _locale_t __locale;
+ const char* __locale_str;
+};
// Locale management functions
#define freelocale _free_locale
// FIXME: base currently unused. Needs manual work to construct the new locale
locale_t newlocale( int mask, const char * locale, locale_t base );
-locale_t uselocale( locale_t newloc );
+// uselocale can't be implemented on Windows because Windows allows partial modification
+// of thread-local locale and so _get_current_locale() returns a copy while uselocale does
+// not create any copies.
+// We can still implement raii even without uselocale though.
lconv *localeconv_l( locale_t loc );
// FIXME: base currently unused. Needs manual work to construct the new locale
locale_t newlocale( int mask, const char * locale, locale_t /*base*/ )
{
- return _create_locale( mask, locale );
-}
-
-locale_t uselocale( locale_t newloc )
-{
- locale_t old_locale = _get_current_locale();
- if ( newloc == NULL )
- return old_locale;
- // uselocale sets the thread's locale by definition, so unconditionally use thread-local locale
- _configthreadlocale( _ENABLE_PER_THREAD_LOCALE );
- // uselocale sets all categories
- // disable setting locale on Windows temporarily because the structure is opaque (PR31516)
- //setlocale( LC_ALL, newloc->locinfo->lc_category[LC_ALL].locale );
- // uselocale returns the old locale_t
- return old_locale;
+ return {_create_locale( LC_ALL, locale ), locale};
}
decltype(MB_CUR_MAX) MB_CUR_MAX_L( locale_t __l )