// locale standard header // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #pragma once #ifndef _LOCALE_ #define _LOCALE_ #include #if _STL_COMPILER_PREPROCESSOR #include #include #include #include #include #include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) #pragma warning(disable : _STL_DISABLED_WARNINGS) _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new _STD_BEGIN // CLASS TEMPLATE collate template class collate : public locale::facet { // facet for ordering sequences of elements public: static_assert(!_ENFORCE_FACET_SPECIALIZATIONS || _Is_any_of_v<_Elem, char, wchar_t, unsigned short>, _FACET_SPECIALIZATION_MESSAGE); using char_type = _Elem; using string_type = basic_string<_Elem, char_traits<_Elem>, allocator<_Elem>>; int compare(const _Elem* _First1, const _Elem* _Last1, const _Elem* _First2, const _Elem* _Last2) const { // compare [_First1, _Last1) to [_First2, _Last2) return do_compare(_First1, _Last1, _First2, _Last2); } string_type transform(const _Elem* _First, const _Elem* _Last) const { // transform [_First, _Last) to key string return do_transform(_First, _Last); } long hash(const _Elem* _First, const _Elem* _Last) const { // compute hash code for [_First, _Last) return do_hash(_First, _Last); } __PURE_APPDOMAIN_GLOBAL _CRTIMP2_PURE_IMPORT static locale::id id; // unique facet id explicit collate(size_t _Refs = 0) : locale::facet(_Refs) { // construct from current locale _BEGIN_LOCINFO(_Lobj) _Init(_Lobj); _END_LOCINFO() } collate(const _Locinfo& _Lobj, size_t _Refs = 0) : locale::facet(_Refs) { _Init(_Lobj); } static size_t _Getcat(const locale::facet** _Ppf = nullptr, const locale* _Ploc = nullptr) { if (_Ppf && !*_Ppf) { *_Ppf = new collate<_Elem>(_Locinfo(_Ploc->name().c_str())); } return _X_COLLATE; } protected: __CLR_OR_THIS_CALL ~collate() noexcept { _CSTD free(_Coll._LocaleName); } collate(const char* _Locname, size_t _Refs = 0) : locale::facet(_Refs) { _BEGIN_LOCINFO(_Lobj(_Locname)) _Init(_Lobj); _END_LOCINFO() } void _Init(const _Locinfo& _Lobj) { // initialize from _Lobj _Coll = _Lobj._Getcoll(); } virtual int __CLR_OR_THIS_CALL do_compare(const _Elem* _First1, const _Elem* _Last1, const _Elem* _First2, const _Elem* _Last2) const { // compare [_First1, _Last1) to [_First2, _Last2) _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); int _Ans = _LStrcoll(_First1, _Last1, _First2, _Last2, &_Coll); return _Ans < 0 ? -1 : _Ans == 0 ? 0 : +1; } virtual string_type __CLR_OR_THIS_CALL do_transform(const _Elem* _First, const _Elem* _Last) const { // transform [_First, _Last) to key string _Adl_verify_range(_First, _Last); size_t _Count; string_type _Str; for (_Count = static_cast(_Last - _First); 0 < _Count;) { // grow string if locale-specific strxfrm fails _Str.resize(_Count); if ((_Count = _LStrxfrm(&_Str[0], &_Str[0] + _Str.size(), _First, _Last, &_Coll)) <= _Str.size()) { break; } } _Str.resize(_Count); return _Str; } virtual long __CLR_OR_THIS_CALL do_hash( const _Elem* _First, const _Elem* _Last) const { // compute hash code for [_First, _Last) _Adl_verify_range(_First, _Last); return static_cast(_Hash_array_representation(_First, static_cast(_Last - _First))); } private: _Locinfo::_Collvec _Coll; // used by _LStrcoll and _XStrxfrm }; // STATIC collate::id OBJECT #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdllimport-static-field-def" #endif // __clang__ template __PURE_APPDOMAIN_GLOBAL locale::id collate<_Elem>::id; #if defined(_DLL_CPPLIB) #if !defined(_CRTBLD) || defined(__FORCE_INSTANCE) template __PURE_APPDOMAIN_GLOBAL locale::id collate::id; template __PURE_APPDOMAIN_GLOBAL locale::id collate::id; #endif // !defined(_CRTBLD) || defined(__FORCE_INSTANCE) #ifdef __FORCE_INSTANCE template __PURE_APPDOMAIN_GLOBAL locale::id collate::id; #endif // __FORCE_INSTANCE #endif // defined(_DLL_CPPLIB) #ifdef __clang__ #pragma clang diagnostic pop #endif // __clang__ // CLASS TEMPLATE collate_byname template class collate_byname : public collate<_Elem> { // collate for named locale public: static_assert(!_ENFORCE_FACET_SPECIALIZATIONS || _Is_any_of_v<_Elem, char, wchar_t>, _FACET_SPECIALIZATION_MESSAGE); explicit collate_byname(const char* _Locname, size_t _Refs = 0) : collate<_Elem>(_Locname, _Refs) { // construct for named locale } explicit collate_byname(const string& _Str, size_t _Refs = 0) : collate<_Elem>(_Locinfo(_Str.c_str()), _Refs) { // construct for named locale } protected: virtual __CLR_OR_THIS_CALL ~collate_byname() noexcept {} }; // FUNCTION TEMPLATE has_facet template bool has_facet(const locale& _Loc) noexcept { _BEGIN_LOCK(_LOCK_LOCALE) // the thread lock, make get atomic size_t _Id = _Facet::id; return _Loc._Getfacet(_Id) || _Facet::_Getcat() != static_cast(-1); _END_LOCK() } // FUNCTION TEMPLATE isalnum template bool(isalnum)(_Elem _Ch, const locale& _Loc) { return _STD use_facet>(_Loc).is(ctype_base::alnum, _Ch); } // FUNCTION TEMPLATE isalpha template bool(isalpha)(_Elem _Ch, const locale& _Loc) { return _STD use_facet>(_Loc).is(ctype_base::alpha, _Ch); } // FUNCTION TEMPLATE isblank template bool(isblank)(_Elem _Ch, const locale& _Loc) { return _STD use_facet>(_Loc).is(ctype_base::blank, _Ch); } // FUNCTION TEMPLATE iscntrl template bool(iscntrl)(_Elem _Ch, const locale& _Loc) { return _STD use_facet>(_Loc).is(ctype_base::cntrl, _Ch); } // FUNCTION TEMPLATE isdigit template bool(isdigit)(_Elem _Ch, const locale& _Loc) { return _STD use_facet>(_Loc).is(ctype_base::digit, _Ch); } // FUNCTION TEMPLATE isgraph template bool(isgraph)(_Elem _Ch, const locale& _Loc) { return _STD use_facet>(_Loc).is(ctype_base::graph, _Ch); } // FUNCTION TEMPLATE islower template bool(islower)(_Elem _Ch, const locale& _Loc) { return _STD use_facet>(_Loc).is(ctype_base::lower, _Ch); } // FUNCTION TEMPLATE isprint template bool(isprint)(_Elem _Ch, const locale& _Loc) { return _STD use_facet>(_Loc).is(ctype_base::print, _Ch); } // FUNCTION TEMPLATE ispunct template bool(ispunct)(_Elem _Ch, const locale& _Loc) { return _STD use_facet>(_Loc).is(ctype_base::punct, _Ch); } // FUNCTION TEMPLATE isspace template bool(isspace)(_Elem _Ch, const locale& _Loc) { return _STD use_facet>(_Loc).is(ctype_base::space, _Ch); } // FUNCTION TEMPLATE isupper template bool(isupper)(_Elem _Ch, const locale& _Loc) { return _STD use_facet>(_Loc).is(ctype_base::upper, _Ch); } // FUNCTION TEMPLATE isxdigit template bool(isxdigit)(_Elem _Ch, const locale& _Loc) { return _STD use_facet>(_Loc).is(ctype_base::xdigit, _Ch); } // FUNCTION TEMPLATE tolower template _Elem(tolower)(_Elem _Ch, const locale& _Loc) { return _STD use_facet>(_Loc).tolower(_Ch); } // FUNCTION TEMPLATE toupper template _Elem(toupper)(_Elem _Ch, const locale& _Loc) { return _STD use_facet>(_Loc).toupper(_Ch); } _STD_END #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) #endif // _STL_COMPILER_PREPROCESSOR #endif // _LOCALE_