Refactor <locale> RAII guards to aid upcoming Windows locale changes.
Previously <locale> used std::unique_ptr<remove_ptr<locale_t>, locale-mgmt-function>
as a scope guard for (A) creating new locales, and (B) setting the thread specific locale
in RAII safe manner.
However using unique_ptr has some problems, first it requires that locale_t is a pointer
type, which may not be the case (Windows will need a non-pointer locale_t type that emulates _locale_t).
The second problem is that users of the guards had to supply the locale management function to the custom
deleter at every call site. However these locale management functions don't exist natively Windows, making
a good Windows implementation of locale more difficult.
This patch creates distinct and simply RAII guards that replace unique_ptr. These guards handle calling
the correct locale management function so that callers don't have too. This simplification will
aid in upcoming Windows fixes.
llvm-svn: 302474
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: b4ddab26bce7a30b05d4e21b648927dd1571ca7e
diff --git a/src/locale.cpp b/src/locale.cpp
index 1ed9b41..4163c2c 100644
--- a/src/locale.cpp
+++ b/src/locale.cpp
@@ -45,6 +45,24 @@
_LIBCPP_BEGIN_NAMESPACE_STD
+struct __libcpp_unique_locale {
+ __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
+
+ ~__libcpp_unique_locale() {
+ if (__loc_)
+ freelocale(__loc_);
+ }
+
+ explicit operator bool() const { return __loc_; }
+
+ locale_t& get() { return __loc_; }
+
+ locale_t __loc_;
+private:
+ __libcpp_unique_locale(__libcpp_unique_locale const&);
+ __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
+};
+
#ifdef __cloc_defined
locale_t __cloc() {
// In theory this could create a race condition. In practice
@@ -4185,7 +4203,7 @@
static bool checked_string_to_wchar_convert(wchar_t& dest,
const char* ptr,
- __locale_struct* loc) {
+ locale_t loc) {
if (*ptr == '\0')
return false;
mbstate_t mb = {};
@@ -4200,7 +4218,7 @@
static bool checked_string_to_char_convert(char& dest,
const char* ptr,
- __locale_struct* __loc) {
+ locale_t __loc) {
if (*ptr == '\0')
return false;
if (!ptr[1]) {
@@ -4295,8 +4313,8 @@
{
if (strcmp(nm, "C") != 0)
{
- __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
- if (loc == nullptr)
+ __libcpp_unique_locale loc(nm);
+ if (!loc)
__throw_runtime_error("numpunct_byname<char>::numpunct_byname"
" failed to construct for " + string(nm));
@@ -4333,8 +4351,8 @@
{
if (strcmp(nm, "C") != 0)
{
- __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
- if (loc == nullptr)
+ __libcpp_unique_locale loc(nm);
+ if (!loc)
__throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
" failed to construct for " + string(nm));
@@ -5820,8 +5838,8 @@
moneypunct_byname<char, false>::init(const char* nm)
{
typedef moneypunct<char, false> base;
- __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
- if (loc == nullptr)
+ __libcpp_unique_locale loc(nm);
+ if (!loc)
__throw_runtime_error("moneypunct_byname"
" failed to construct for " + string(nm));
@@ -5864,8 +5882,8 @@
moneypunct_byname<char, true>::init(const char* nm)
{
typedef moneypunct<char, true> base;
- __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
- if (loc == nullptr)
+ __libcpp_unique_locale loc(nm);
+ if (!loc)
__throw_runtime_error("moneypunct_byname"
" failed to construct for " + string(nm));
@@ -5924,8 +5942,8 @@
moneypunct_byname<wchar_t, false>::init(const char* nm)
{
typedef moneypunct<wchar_t, false> base;
- __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
- if (loc == nullptr)
+ __libcpp_unique_locale loc(nm);
+ if (!loc)
__throw_runtime_error("moneypunct_byname"
" failed to construct for " + string(nm));
lconv* lc = __libcpp_localeconv_l(loc.get());
@@ -5989,8 +6007,8 @@
moneypunct_byname<wchar_t, true>::init(const char* nm)
{
typedef moneypunct<wchar_t, true> base;
- __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
- if (loc == nullptr)
+ __libcpp_unique_locale loc(nm);
+ if (!loc)
__throw_runtime_error("moneypunct_byname"
" failed to construct for " + string(nm));