Path: blob/main/contrib/llvm-project/libcxx/src/support/ibm/xlocale_zos.cpp
35291 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include <__assert>9#include <__support/ibm/xlocale.h>10#include <sstream>11#include <vector>1213#ifdef __cplusplus14extern "C" {15#endif // __cplusplus1617locale_t newlocale(int category_mask, const char* locale, locale_t base) {18// Maintain current locale name(s) to restore later.19std::string current_loc_name(setlocale(LC_ALL, 0));2021// Check for errors.22if (category_mask == LC_ALL_MASK && setlocale(LC_ALL, locale) == NULL) {23errno = EINVAL;24return (locale_t)0;25} else {26for (int _Cat = 0; _Cat <= _LC_MAX; ++_Cat) {27if ((_CATMASK(_Cat) & category_mask) != 0 && setlocale(_Cat, locale) == NULL) {28setlocale(LC_ALL, current_loc_name.c_str());29errno = EINVAL;30return (locale_t)0;31}32}33}3435// Create new locale.36locale_t newloc = new locale_struct();3738if (base) {39if (category_mask != LC_ALL_MASK) {40// Copy base when it will not be overwritten.41memcpy(newloc, base, sizeof(locale_struct));42newloc->category_mask = category_mask | base->category_mask;43}44delete base;45} else {46newloc->category_mask = category_mask;47}4849if (category_mask & LC_COLLATE_MASK)50newloc->lc_collate = locale;51if (category_mask & LC_CTYPE_MASK)52newloc->lc_ctype = locale;53if (category_mask & LC_MONETARY_MASK)54newloc->lc_monetary = locale;55if (category_mask & LC_NUMERIC_MASK)56newloc->lc_numeric = locale;57if (category_mask & LC_TIME_MASK)58newloc->lc_time = locale;59if (category_mask & LC_MESSAGES_MASK)60newloc->lc_messages = locale;6162// Restore current locale.63setlocale(LC_ALL, current_loc_name.c_str());64return (locale_t)newloc;65}6667void freelocale(locale_t locobj) { delete locobj; }6869locale_t uselocale(locale_t newloc) {70// Maintain current locale name(s).71std::string current_loc_name(setlocale(LC_ALL, 0));7273if (newloc) {74// Set locales and check for errors.75bool is_error =76(newloc->category_mask & LC_COLLATE_MASK && setlocale(LC_COLLATE, newloc->lc_collate.c_str()) == NULL) ||77(newloc->category_mask & LC_CTYPE_MASK && setlocale(LC_CTYPE, newloc->lc_ctype.c_str()) == NULL) ||78(newloc->category_mask & LC_MONETARY_MASK && setlocale(LC_MONETARY, newloc->lc_monetary.c_str()) == NULL) ||79(newloc->category_mask & LC_NUMERIC_MASK && setlocale(LC_NUMERIC, newloc->lc_numeric.c_str()) == NULL) ||80(newloc->category_mask & LC_TIME_MASK && setlocale(LC_TIME, newloc->lc_time.c_str()) == NULL) ||81(newloc->category_mask & LC_MESSAGES_MASK && setlocale(LC_MESSAGES, newloc->lc_messages.c_str()) == NULL);8283if (is_error) {84setlocale(LC_ALL, current_loc_name.c_str());85errno = EINVAL;86return (locale_t)0;87}88}8990// Construct and return previous locale.91locale_t previous_loc = new locale_struct();9293// current_loc_name might be a comma-separated locale name list.94if (current_loc_name.find(',') != std::string::npos) {95// Tokenize locale name list.96const char delimiter = ',';97std::vector<std::string> tokenized;98std::stringstream ss(current_loc_name);99std::string s;100101while (std::getline(ss, s, delimiter)) {102tokenized.push_back(s);103}104105_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(tokenized.size() >= _NCAT, "locale-name list is too short");106107previous_loc->lc_collate = tokenized[LC_COLLATE];108previous_loc->lc_ctype = tokenized[LC_CTYPE];109previous_loc->lc_monetary = tokenized[LC_MONETARY];110previous_loc->lc_numeric = tokenized[LC_NUMERIC];111previous_loc->lc_time = tokenized[LC_TIME];112// Skip LC_TOD.113previous_loc->lc_messages = tokenized[LC_MESSAGES];114} else {115previous_loc->lc_collate = current_loc_name;116previous_loc->lc_ctype = current_loc_name;117previous_loc->lc_monetary = current_loc_name;118previous_loc->lc_numeric = current_loc_name;119previous_loc->lc_time = current_loc_name;120previous_loc->lc_messages = current_loc_name;121}122123previous_loc->category_mask = LC_ALL_MASK;124return previous_loc;125}126127#ifdef __cplusplus128}129#endif // __cplusplus130131132