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
) == NULL
) {
27 for (int _Cat
= 0; _Cat
<= _LC_MAX
; ++_Cat
) {
28 if ((_CATMASK(_Cat
) & category_mask
) != 0 && setlocale(_Cat
, locale
) == NULL
) {
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
) {
72 locale_t
uselocale(locale_t newloc
) {
73 // Maintain current locale name(s).
74 std::string
current_loc_name(setlocale(LC_ALL
, 0));
77 // Set locales and check for errors.
79 (newloc
->category_mask
& LC_COLLATE_MASK
&&
80 setlocale(LC_COLLATE
, newloc
->lc_collate
.c_str()) == NULL
) ||
81 (newloc
->category_mask
& LC_CTYPE_MASK
&&
82 setlocale(LC_CTYPE
, newloc
->lc_ctype
.c_str()) == NULL
) ||
83 (newloc
->category_mask
& LC_MONETARY_MASK
&&
84 setlocale(LC_MONETARY
, newloc
->lc_monetary
.c_str()) == NULL
) ||
85 (newloc
->category_mask
& LC_NUMERIC_MASK
&&
86 setlocale(LC_NUMERIC
, newloc
->lc_numeric
.c_str()) == NULL
) ||
87 (newloc
->category_mask
& LC_TIME_MASK
&&
88 setlocale(LC_TIME
, newloc
->lc_time
.c_str()) == NULL
) ||
89 (newloc
->category_mask
& LC_MESSAGES_MASK
&&
90 setlocale(LC_MESSAGES
, newloc
->lc_messages
.c_str()) == NULL
);
93 setlocale(LC_ALL
, current_loc_name
.c_str());
99 // Construct and return previous locale.
100 locale_t previous_loc
= new locale_struct();
102 // current_loc_name might be a comma-separated locale name list.
103 if (current_loc_name
.find(',') != std::string::npos
) {
104 // Tokenize locale name list.
105 const char delimiter
= ',';
106 std::vector
<std::string
> tokenized
;
107 std::stringstream
ss(current_loc_name
);
110 while (std::getline(ss
, s
, delimiter
)) {
111 tokenized
.push_back(s
);
114 _LIBCPP_ASSERT_UNCATEGORIZED(tokenized
.size() >= _NCAT
, "locale-name list is too short");
116 previous_loc
->lc_collate
= tokenized
[LC_COLLATE
];
117 previous_loc
->lc_ctype
= tokenized
[LC_CTYPE
];
118 previous_loc
->lc_monetary
= tokenized
[LC_MONETARY
];
119 previous_loc
->lc_numeric
= tokenized
[LC_NUMERIC
];
120 previous_loc
->lc_time
= tokenized
[LC_TIME
];
122 previous_loc
->lc_messages
= tokenized
[LC_MESSAGES
];
124 previous_loc
->lc_collate
= current_loc_name
;
125 previous_loc
->lc_ctype
= current_loc_name
;
126 previous_loc
->lc_monetary
= current_loc_name
;
127 previous_loc
->lc_numeric
= current_loc_name
;
128 previous_loc
->lc_time
= current_loc_name
;
129 previous_loc
->lc_messages
= current_loc_name
;
132 previous_loc
->category_mask
= LC_ALL_MASK
;
138 #endif // __cplusplus