1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___LOCALE_DIR_LOCALE_GUARD_H
10 #define _LIBCPP___LOCALE_DIR_LOCALE_GUARD_H
13 #include <__locale> // for locale_t
16 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
17 # pragma GCC system_header
20 _LIBCPP_BEGIN_NAMESPACE_STD
22 #if defined(_LIBCPP_MSVCRT_LIKE)
23 struct __locale_guard
{
24 __locale_guard(locale_t __l
) : __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE
)) {
25 // Setting the locale can be expensive even when the locale given is
26 // already the current locale, so do an explicit check to see if the
27 // current locale is already the one we want.
28 const char* __lc
= __setlocale(nullptr);
29 // If every category is the same, the locale string will simply be the
30 // locale name, otherwise it will be a semicolon-separated string listing
31 // each category. In the second case, we know at least one category won't
32 // be what we want, so we only have to check the first case.
33 if (std::strcmp(__l
.__get_locale(), __lc
) != 0) {
34 __locale_all
= _strdup(__lc
);
35 if (__locale_all
== nullptr)
37 __setlocale(__l
.__get_locale());
41 // The CRT documentation doesn't explicitly say, but setlocale() does the
42 // right thing when given a semicolon-separated list of locale settings
43 // for the different categories in the same format as returned by
44 // setlocale(LC_ALL, nullptr).
45 if (__locale_all
!= nullptr) {
46 __setlocale(__locale_all
);
49 _configthreadlocale(__status
);
51 static const char* __setlocale(const char* __locale
) {
52 const char* __new_locale
= setlocale(LC_ALL
, __locale
);
53 if (__new_locale
== nullptr)
58 char* __locale_all
= nullptr;
61 struct __locale_guard
{
62 _LIBCPP_HIDE_FROM_ABI
__locale_guard(locale_t
& __loc
) : __old_loc_(uselocale(__loc
)) {}
64 _LIBCPP_HIDE_FROM_ABI
~__locale_guard() {
66 uselocale(__old_loc_
);
71 __locale_guard(__locale_guard
const&) = delete;
72 __locale_guard
& operator=(__locale_guard
const&) = delete;
76 _LIBCPP_END_NAMESPACE_STD
78 #endif // _LIBCPP___LOCALE_DIR_LOCALE_GUARD_H