зеркало из https://github.com/microsoft/STL.git
261 строка
8.5 KiB
C++
261 строка
8.5 KiB
C++
// locale standard header
|
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#pragma once
|
|
#ifndef _LOCALE_
|
|
#define _LOCALE_
|
|
#include <yvals_core.h>
|
|
#if _STL_COMPILER_PREPROCESSOR
|
|
#include <xlocbuf>
|
|
#include <xlocmes>
|
|
#include <xlocmon>
|
|
#include <xlocnum>
|
|
#include <xloctime>
|
|
#include <xstring>
|
|
|
|
#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 _Elem>
|
|
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>>;
|
|
|
|
_NODISCARD 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);
|
|
}
|
|
|
|
_NODISCARD string_type transform(
|
|
const _Elem* _First, const _Elem* _Last) const { // transform [_First, _Last) to key string
|
|
return do_transform(_First, _Last);
|
|
}
|
|
|
|
_NODISCARD 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();
|
|
}
|
|
|
|
_NODISCARD 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;
|
|
}
|
|
|
|
_NODISCARD 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<size_t>(_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;
|
|
}
|
|
|
|
_NODISCARD 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<long>(_Hash_array_representation(_First, static_cast<size_t>(_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 <class _Elem>
|
|
__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<char>::id;
|
|
template __PURE_APPDOMAIN_GLOBAL locale::id collate<wchar_t>::id;
|
|
#endif // !defined(_CRTBLD) || defined(__FORCE_INSTANCE)
|
|
|
|
#ifdef __FORCE_INSTANCE
|
|
template __PURE_APPDOMAIN_GLOBAL locale::id collate<unsigned short>::id;
|
|
#endif // __FORCE_INSTANCE
|
|
#endif // defined(_DLL_CPPLIB)
|
|
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic pop
|
|
#endif // __clang__
|
|
|
|
// CLASS TEMPLATE collate_byname
|
|
template <class _Elem>
|
|
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 <class _Facet>
|
|
_NODISCARD 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<size_t>(-1);
|
|
_END_LOCK()
|
|
}
|
|
|
|
// FUNCTION TEMPLATE isalnum
|
|
template <class _Elem>
|
|
_NODISCARD bool(isalnum)(_Elem _Ch, const locale& _Loc) {
|
|
return _STD use_facet<ctype<_Elem>>(_Loc).is(ctype_base::alnum, _Ch);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE isalpha
|
|
template <class _Elem>
|
|
_NODISCARD bool(isalpha)(_Elem _Ch, const locale& _Loc) {
|
|
return _STD use_facet<ctype<_Elem>>(_Loc).is(ctype_base::alpha, _Ch);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE isblank
|
|
template <class _Elem>
|
|
_NODISCARD bool(isblank)(_Elem _Ch, const locale& _Loc) {
|
|
return _STD use_facet<ctype<_Elem>>(_Loc).is(ctype_base::blank, _Ch);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE iscntrl
|
|
template <class _Elem>
|
|
_NODISCARD bool(iscntrl)(_Elem _Ch, const locale& _Loc) {
|
|
return _STD use_facet<ctype<_Elem>>(_Loc).is(ctype_base::cntrl, _Ch);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE isdigit
|
|
template <class _Elem>
|
|
_NODISCARD bool(isdigit)(_Elem _Ch, const locale& _Loc) {
|
|
return _STD use_facet<ctype<_Elem>>(_Loc).is(ctype_base::digit, _Ch);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE isgraph
|
|
template <class _Elem>
|
|
_NODISCARD bool(isgraph)(_Elem _Ch, const locale& _Loc) {
|
|
return _STD use_facet<ctype<_Elem>>(_Loc).is(ctype_base::graph, _Ch);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE islower
|
|
template <class _Elem>
|
|
_NODISCARD bool(islower)(_Elem _Ch, const locale& _Loc) {
|
|
return _STD use_facet<ctype<_Elem>>(_Loc).is(ctype_base::lower, _Ch);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE isprint
|
|
template <class _Elem>
|
|
_NODISCARD bool(isprint)(_Elem _Ch, const locale& _Loc) {
|
|
return _STD use_facet<ctype<_Elem>>(_Loc).is(ctype_base::print, _Ch);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE ispunct
|
|
template <class _Elem>
|
|
_NODISCARD bool(ispunct)(_Elem _Ch, const locale& _Loc) {
|
|
return _STD use_facet<ctype<_Elem>>(_Loc).is(ctype_base::punct, _Ch);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE isspace
|
|
template <class _Elem>
|
|
_NODISCARD bool(isspace)(_Elem _Ch, const locale& _Loc) {
|
|
return _STD use_facet<ctype<_Elem>>(_Loc).is(ctype_base::space, _Ch);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE isupper
|
|
template <class _Elem>
|
|
_NODISCARD bool(isupper)(_Elem _Ch, const locale& _Loc) {
|
|
return _STD use_facet<ctype<_Elem>>(_Loc).is(ctype_base::upper, _Ch);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE isxdigit
|
|
template <class _Elem>
|
|
_NODISCARD bool(isxdigit)(_Elem _Ch, const locale& _Loc) {
|
|
return _STD use_facet<ctype<_Elem>>(_Loc).is(ctype_base::xdigit, _Ch);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE tolower
|
|
template <class _Elem>
|
|
_NODISCARD _Elem(tolower)(_Elem _Ch, const locale& _Loc) {
|
|
return _STD use_facet<ctype<_Elem>>(_Loc).tolower(_Ch);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE toupper
|
|
template <class _Elem>
|
|
_NODISCARD _Elem(toupper)(_Elem _Ch, const locale& _Loc) {
|
|
return _STD use_facet<ctype<_Elem>>(_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_
|