Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/libcxx/src/support/ibm/xlocale_zos.cpp
35291 views
1
//===----------------------------------------------------------------------===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include <__assert>
10
#include <__support/ibm/xlocale.h>
11
#include <sstream>
12
#include <vector>
13
14
#ifdef __cplusplus
15
extern "C" {
16
#endif // __cplusplus
17
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));
21
22
// Check for errors.
23
if (category_mask == LC_ALL_MASK && setlocale(LC_ALL, locale) == NULL) {
24
errno = EINVAL;
25
return (locale_t)0;
26
} else {
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());
30
errno = EINVAL;
31
return (locale_t)0;
32
}
33
}
34
}
35
36
// Create new locale.
37
locale_t newloc = new locale_struct();
38
39
if (base) {
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;
44
}
45
delete base;
46
} else {
47
newloc->category_mask = category_mask;
48
}
49
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;
62
63
// Restore current locale.
64
setlocale(LC_ALL, current_loc_name.c_str());
65
return (locale_t)newloc;
66
}
67
68
void freelocale(locale_t locobj) { delete locobj; }
69
70
locale_t uselocale(locale_t newloc) {
71
// Maintain current locale name(s).
72
std::string current_loc_name(setlocale(LC_ALL, 0));
73
74
if (newloc) {
75
// Set locales and check for errors.
76
bool is_error =
77
(newloc->category_mask & LC_COLLATE_MASK && setlocale(LC_COLLATE, newloc->lc_collate.c_str()) == NULL) ||
78
(newloc->category_mask & LC_CTYPE_MASK && setlocale(LC_CTYPE, newloc->lc_ctype.c_str()) == NULL) ||
79
(newloc->category_mask & LC_MONETARY_MASK && setlocale(LC_MONETARY, newloc->lc_monetary.c_str()) == NULL) ||
80
(newloc->category_mask & LC_NUMERIC_MASK && setlocale(LC_NUMERIC, newloc->lc_numeric.c_str()) == NULL) ||
81
(newloc->category_mask & LC_TIME_MASK && setlocale(LC_TIME, newloc->lc_time.c_str()) == NULL) ||
82
(newloc->category_mask & LC_MESSAGES_MASK && setlocale(LC_MESSAGES, newloc->lc_messages.c_str()) == NULL);
83
84
if (is_error) {
85
setlocale(LC_ALL, current_loc_name.c_str());
86
errno = EINVAL;
87
return (locale_t)0;
88
}
89
}
90
91
// Construct and return previous locale.
92
locale_t previous_loc = new locale_struct();
93
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);
100
std::string s;
101
102
while (std::getline(ss, s, delimiter)) {
103
tokenized.push_back(s);
104
}
105
106
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(tokenized.size() >= _NCAT, "locale-name list is too short");
107
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];
113
// Skip LC_TOD.
114
previous_loc->lc_messages = tokenized[LC_MESSAGES];
115
} else {
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;
122
}
123
124
previous_loc->category_mask = LC_ALL_MASK;
125
return previous_loc;
126
}
127
128
#ifdef __cplusplus
129
}
130
#endif // __cplusplus
131
132