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 //===----------------------------------------------------------------------===//
10 #include <__support/ibm/xlocale.h>
18 locale_t
newlocale(int category_mask
, const char* locale
, locale_t base
) {
19 // Maintain current locale name(s) to restore later.
20 std::string
current_loc_name(setlocale(LC_ALL
, 0));
23 if (category_mask
== LC_ALL_MASK
&& setlocale(LC_ALL
, locale
) == nullptr) {
27 for (int _Cat
= 0; _Cat
<= _LC_MAX
; ++_Cat
) {
28 if ((_CATMASK(_Cat
) & category_mask
) != 0 && setlocale(_Cat
, locale
) == nullptr) {
29 setlocale(LC_ALL
, current_loc_name
.c_str());
37 locale_t newloc
= new locale_struct();
40 if (category_mask
!= LC_ALL_MASK
) {
41 // Copy base when it will not be overwritten.
42 memcpy(newloc
, base
, sizeof(locale_struct
));
43 newloc
->category_mask
= category_mask
| base
->category_mask
;
47 newloc
->category_mask
= category_mask
;
50 if (category_mask
& LC_COLLATE_MASK
)
51 newloc
->lc_collate
= locale
;
52 if (category_mask
& LC_CTYPE_MASK
)
53 newloc
->lc_ctype
= locale
;
54 if (category_mask
& LC_MONETARY_MASK
)
55 newloc
->lc_monetary
= locale
;
56 if (category_mask
& LC_NUMERIC_MASK
)
57 newloc
->lc_numeric
= locale
;
58 if (category_mask
& LC_TIME_MASK
)
59 newloc
->lc_time
= locale
;
60 if (category_mask
& LC_MESSAGES_MASK
)
61 newloc
->lc_messages
= locale
;
63 // Restore current locale.
64 setlocale(LC_ALL
, current_loc_name
.c_str());
65 return (locale_t
)newloc
;
68 void freelocale(locale_t locobj
) { delete locobj
; }
70 locale_t
uselocale(locale_t newloc
) {
71 // Maintain current locale name(s).
72 std::string
current_loc_name(setlocale(LC_ALL
, 0));
75 // Set locales and check for errors.
77 (newloc
->category_mask
& LC_COLLATE_MASK
&& setlocale(LC_COLLATE
, newloc
->lc_collate
.c_str()) == nullptr) ||
78 (newloc
->category_mask
& LC_CTYPE_MASK
&& setlocale(LC_CTYPE
, newloc
->lc_ctype
.c_str()) == nullptr) ||
79 (newloc
->category_mask
& LC_MONETARY_MASK
&& setlocale(LC_MONETARY
, newloc
->lc_monetary
.c_str()) == nullptr) ||
80 (newloc
->category_mask
& LC_NUMERIC_MASK
&& setlocale(LC_NUMERIC
, newloc
->lc_numeric
.c_str()) == nullptr) ||
81 (newloc
->category_mask
& LC_TIME_MASK
&& setlocale(LC_TIME
, newloc
->lc_time
.c_str()) == nullptr) ||
82 (newloc
->category_mask
& LC_MESSAGES_MASK
&& setlocale(LC_MESSAGES
, newloc
->lc_messages
.c_str()) == nullptr);
85 setlocale(LC_ALL
, current_loc_name
.c_str());
91 // Construct and return previous locale.
92 locale_t previous_loc
= new locale_struct();
94 // current_loc_name might be a comma-separated locale name list.
95 if (current_loc_name
.find(',') != std::string::npos
) {
96 // Tokenize locale name list.
97 const char delimiter
= ',';
98 std::vector
<std::string
> tokenized
;
99 std::stringstream
ss(current_loc_name
);
102 while (std::getline(ss
, s
, delimiter
)) {
103 tokenized
.push_back(s
);
106 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(tokenized
.size() >= _NCAT
, "locale-name list is too short");
108 previous_loc
->lc_collate
= tokenized
[LC_COLLATE
];
109 previous_loc
->lc_ctype
= tokenized
[LC_CTYPE
];
110 previous_loc
->lc_monetary
= tokenized
[LC_MONETARY
];
111 previous_loc
->lc_numeric
= tokenized
[LC_NUMERIC
];
112 previous_loc
->lc_time
= tokenized
[LC_TIME
];
114 previous_loc
->lc_messages
= tokenized
[LC_MESSAGES
];
116 previous_loc
->lc_collate
= current_loc_name
;
117 previous_loc
->lc_ctype
= current_loc_name
;
118 previous_loc
->lc_monetary
= current_loc_name
;
119 previous_loc
->lc_numeric
= current_loc_name
;
120 previous_loc
->lc_time
= current_loc_name
;
121 previous_loc
->lc_messages
= current_loc_name
;
124 previous_loc
->category_mask
= LC_ALL_MASK
;
130 #endif // __cplusplus