зеркало из https://github.com/microsoft/STL.git
372 строки
12 KiB
C++
372 строки
12 KiB
C++
// xlocinfo internal header
|
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#pragma once
|
|
#ifndef _XLOCINFO_
|
|
#define _XLOCINFO_
|
|
#include <yvals_core.h>
|
|
#if _STL_COMPILER_PREPROCESSOR
|
|
#include <cstdlib>
|
|
#include <xlocinfo.h>
|
|
#include <xstddef>
|
|
#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 _Timevec
|
|
class _CRTIMP2_PURE_IMPORT _Timevec { // smart pointer to information used by _Strftime
|
|
public:
|
|
explicit __CLR_OR_THIS_CALL _Timevec(void* _Ptr = nullptr) : _Timeptr(_Ptr) {}
|
|
|
|
__CLR_OR_THIS_CALL _Timevec(const _Timevec& _Right) : _Timeptr(nullptr) {
|
|
*this = _Right;
|
|
}
|
|
|
|
__CLR_OR_THIS_CALL ~_Timevec() noexcept {
|
|
_CSTD free(_Timeptr);
|
|
}
|
|
|
|
_Timevec& __CLR_OR_THIS_CALL operator=(const _Timevec& _Right) { // transfer ownership of _Timeptr from _Right
|
|
if (this != &_Right) {
|
|
_CSTD free(_Timeptr);
|
|
_Timeptr = _Right._Timeptr;
|
|
const_cast<_Timevec&>(_Right)._Timeptr = nullptr; // TRANSITION, should be movable-only
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
void* __CLR_OR_THIS_CALL _Getptr() const {
|
|
return _Timeptr;
|
|
}
|
|
|
|
private:
|
|
void* _Timeptr; // pointer to time information
|
|
};
|
|
|
|
// CLASS TEMPLATE _Yarn
|
|
template <class _Elem>
|
|
class _CRTIMP2_PURE_IMPORT _Yarn { // wrap a NTCTS
|
|
public:
|
|
__CLR_OR_THIS_CALL _Yarn() noexcept : _Myptr(nullptr), _Nul(0) {}
|
|
|
|
__CLR_OR_THIS_CALL _Yarn(const _Yarn& _Right) noexcept : _Myptr(nullptr), _Nul(0) {
|
|
*this = _Right;
|
|
}
|
|
|
|
__CLR_OR_THIS_CALL _Yarn(const _Elem* _Right) noexcept : _Myptr(nullptr), _Nul(0) {
|
|
*this = _Right;
|
|
}
|
|
|
|
_Yarn& __CLR_OR_THIS_CALL operator=(const _Yarn& _Right) noexcept {
|
|
return *this = _Right._Myptr;
|
|
}
|
|
|
|
_Yarn& __CLR_OR_THIS_CALL operator=(const _Elem* _Right) noexcept {
|
|
if (_Myptr != _Right) { // new value, discard old and copy new
|
|
_Tidy();
|
|
|
|
if (_Right) { // new is not empty, copy it
|
|
const _Elem* _Ptr = _Right;
|
|
while (*_Ptr != _Elem{}) {
|
|
++_Ptr;
|
|
}
|
|
|
|
const auto _Count = (++_Ptr - _Right) * sizeof(_Elem);
|
|
|
|
#ifdef _DEBUG
|
|
_Myptr = static_cast<_Elem*>(_malloc_dbg(_Count, _CRT_BLOCK, __FILE__, __LINE__));
|
|
#else // _DEBUG
|
|
_Myptr = static_cast<_Elem*>(_CSTD malloc(_Count));
|
|
#endif // _DEBUG
|
|
|
|
if (_Myptr) {
|
|
_CSTD memcpy(_Myptr, _Right, _Count);
|
|
}
|
|
}
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
__CLR_OR_THIS_CALL ~_Yarn() noexcept {
|
|
_Tidy();
|
|
}
|
|
|
|
_NODISCARD bool __CLR_OR_THIS_CALL empty() const noexcept {
|
|
return _Myptr == nullptr;
|
|
}
|
|
|
|
_Ret_z_ const _Elem* __CLR_OR_THIS_CALL c_str() const noexcept {
|
|
return _Myptr ? _Myptr : &_Nul;
|
|
}
|
|
|
|
_NODISCARD bool __CLR_OR_THIS_CALL _Empty() const noexcept {
|
|
return _Myptr == nullptr;
|
|
}
|
|
|
|
_Ret_z_ const _Elem* __CLR_OR_THIS_CALL _C_str() const noexcept {
|
|
return _Myptr ? _Myptr : &_Nul;
|
|
}
|
|
|
|
private:
|
|
void __CLR_OR_THIS_CALL _Tidy() noexcept {
|
|
if (_Myptr) {
|
|
#ifdef _DEBUG
|
|
_free_dbg(_Myptr, _CRT_BLOCK);
|
|
#else // _DEBUG
|
|
_CSTD free(_Myptr);
|
|
#endif // _DEBUG
|
|
}
|
|
|
|
_Myptr = nullptr;
|
|
}
|
|
|
|
_Elem* _Myptr; // pointer to allocated string
|
|
_Elem _Nul; // nul terminator for unallocated string
|
|
};
|
|
|
|
// CLASS _Locinfo
|
|
class _CRTIMP2_PURE_IMPORT _Locinfo { // summary of all stuff specific to a locale used by standard facets
|
|
public:
|
|
using _Collvec = ::_Collvec;
|
|
using _Ctypevec = ::_Ctypevec;
|
|
using _Cvtvec = ::_Cvtvec;
|
|
using _Timevec = _STD _Timevec;
|
|
|
|
static void __CLRCALL_PURE_OR_CDECL _Locinfo_ctor(_Locinfo*, const char*);
|
|
static void __CLRCALL_PURE_OR_CDECL _Locinfo_ctor(_Locinfo*, int, const char*);
|
|
static void __CLRCALL_PURE_OR_CDECL _Locinfo_dtor(_Locinfo*);
|
|
static _Locinfo& __CLRCALL_PURE_OR_CDECL _Locinfo_Addcats(_Locinfo*, int, const char*);
|
|
|
|
__CLR_OR_THIS_CALL _Locinfo(const char* _Pch = "C")
|
|
#ifndef _M_CEE
|
|
: _Lock(_LOCK_LOCALE)
|
|
#endif // _M_CEE
|
|
|
|
{
|
|
if (_Pch) {
|
|
_Locinfo_ctor(this, _Pch);
|
|
return;
|
|
}
|
|
|
|
_Xruntime_error("bad locale name");
|
|
}
|
|
|
|
__CLR_OR_THIS_CALL _Locinfo(int _Cat, const char* _Pch)
|
|
#ifndef _M_CEE
|
|
: _Lock(_LOCK_LOCALE)
|
|
#endif // _M_CEE
|
|
|
|
{
|
|
if (_Pch) {
|
|
_Locinfo_ctor(this, _Cat, _Pch);
|
|
return;
|
|
}
|
|
|
|
_Xruntime_error("bad locale name");
|
|
}
|
|
|
|
__CLR_OR_THIS_CALL ~_Locinfo() noexcept {
|
|
_Locinfo_dtor(this);
|
|
}
|
|
|
|
_Locinfo& __CLR_OR_THIS_CALL _Addcats(int _Cat, const char* _Pch) { // add facets matching category mask and NTBS
|
|
if (_Pch) {
|
|
return _Locinfo_Addcats(this, _Cat, _Pch);
|
|
}
|
|
|
|
_Xruntime_error("bad locale name");
|
|
}
|
|
|
|
const char* __CLR_OR_THIS_CALL _Getname() const {
|
|
return _Newlocname._C_str();
|
|
}
|
|
|
|
_Collvec __CLR_OR_THIS_CALL _Getcoll() const {
|
|
return ::_Getcoll();
|
|
}
|
|
|
|
_Ctypevec __CLR_OR_THIS_CALL _Getctype() const {
|
|
return ::_Getctype();
|
|
}
|
|
|
|
_Cvtvec __CLR_OR_THIS_CALL _Getcvt() const {
|
|
return ::_Getcvt();
|
|
}
|
|
|
|
const lconv* __CLR_OR_THIS_CALL _Getlconv() const {
|
|
return localeconv();
|
|
}
|
|
|
|
_Timevec __CLR_OR_THIS_CALL _Gettnames() const {
|
|
return _Timevec(::_Gettnames());
|
|
}
|
|
|
|
const char* __CLR_OR_THIS_CALL _Getdays() const {
|
|
const char* _Ptr = ::_Getdays();
|
|
if (_Ptr) { // capture names and free allocated C string
|
|
const_cast<_Locinfo*>(this)->_Days = _Ptr;
|
|
_CSTD free(const_cast<char*>(_Ptr));
|
|
}
|
|
|
|
return !_Days._Empty() ? _Days._C_str()
|
|
: ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:Wednesday"
|
|
":Thu:Thursday:Fri:Friday:Sat:Saturday";
|
|
}
|
|
|
|
const char* __CLR_OR_THIS_CALL _Getmonths() const {
|
|
const char* _Ptr = ::_Getmonths();
|
|
if (_Ptr) { // capture names and free allocated C string
|
|
const_cast<_Locinfo*>(this)->_Months = _Ptr;
|
|
_CSTD free(const_cast<char*>(_Ptr));
|
|
}
|
|
|
|
return !_Months._Empty() ? _Months._C_str()
|
|
: ":Jan:January:Feb:February:Mar:March"
|
|
":Apr:April:May:May:Jun:June"
|
|
":Jul:July:Aug:August:Sep:September"
|
|
":Oct:October:Nov:November:Dec:December";
|
|
}
|
|
|
|
const char* __CLR_OR_THIS_CALL _Getfalse() const {
|
|
return "false";
|
|
}
|
|
|
|
const char* __CLR_OR_THIS_CALL _Gettrue() const {
|
|
return "true";
|
|
}
|
|
|
|
int __CLR_OR_THIS_CALL _Getdateorder() const {
|
|
return ::_Getdateorder();
|
|
}
|
|
|
|
_Timevec __CLR_OR_THIS_CALL _W_Gettnames() const {
|
|
return _Timevec(::_W_Gettnames());
|
|
}
|
|
|
|
const unsigned short* __CLR_OR_THIS_CALL _W_Getdays() const {
|
|
const wchar_t* _Ptr = ::_W_Getdays();
|
|
if (_Ptr) { // capture names and free allocated C string
|
|
const_cast<_Locinfo*>(this)->_W_Days = _Ptr;
|
|
_CSTD free(const_cast<wchar_t*>(_Ptr));
|
|
}
|
|
|
|
const wchar_t* _Ret;
|
|
|
|
if (_W_Days._Empty()) {
|
|
_Ret = L":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday";
|
|
} else {
|
|
_Ret = _W_Days._C_str();
|
|
}
|
|
|
|
return reinterpret_cast<const unsigned short*>(_Ret);
|
|
}
|
|
|
|
const unsigned short* __CLR_OR_THIS_CALL _W_Getmonths() const {
|
|
const wchar_t* _Ptr = ::_W_Getmonths();
|
|
if (_Ptr) { // capture names and free allocated C string
|
|
const_cast<_Locinfo*>(this)->_W_Months = _Ptr;
|
|
_CSTD free(const_cast<wchar_t*>(_Ptr));
|
|
}
|
|
|
|
const wchar_t* _Ret;
|
|
|
|
if (_W_Months._Empty()) {
|
|
_Ret = L":Jan:January:Feb:February:Mar:March:Apr:April:May:May:Jun:June"
|
|
L":Jul:July:Aug:August:Sep:September:Oct:October:Nov:November:Dec:December";
|
|
} else {
|
|
_Ret = _W_Months._C_str();
|
|
}
|
|
|
|
return reinterpret_cast<const unsigned short*>(_Ret);
|
|
}
|
|
|
|
_Locinfo(const _Locinfo&) = delete;
|
|
_Locinfo& operator=(const _Locinfo&) = delete;
|
|
|
|
private:
|
|
#ifdef _M_CEE
|
|
_EmptyLockit _Empty_lock; // to maintain same size
|
|
|
|
#else // _M_CEE
|
|
_Lockit _Lock; // thread lock, because global locale is altered
|
|
#endif // _M_CEE
|
|
|
|
_Yarn<char> _Days; // weekday names
|
|
_Yarn<char> _Months; // month names
|
|
_Yarn<wchar_t> _W_Days; // wide weekday names
|
|
_Yarn<wchar_t> _W_Months; // wide month names
|
|
_Yarn<char> _Oldlocname; // old locale name to revert to on destruction
|
|
_Yarn<char> _Newlocname; // new locale name for this object
|
|
};
|
|
|
|
// FUNCTION TEMPLATE _LStrcoll
|
|
template <class _Elem>
|
|
int __CRTDECL _LStrcoll(const _Elem* _First1, const _Elem* _Last1, const _Elem* _First2, const _Elem* _Last2,
|
|
const _Locinfo::_Collvec*) { // perform locale-specific comparison of _Elem sequences
|
|
for (; _First1 != _Last1 && _First2 != _Last2; ++_First1, ++_First2) {
|
|
if (*_First1 < *_First2) {
|
|
return -1; // [_First1, _Last1) < [_First2, _Last2)
|
|
} else if (*_First2 < *_First1) {
|
|
return +1; // [_First1, _Last1) > [_First2, _Last2)
|
|
}
|
|
}
|
|
|
|
return _First2 != _Last2 ? -1 : _First1 != _Last1 ? +1 : 0;
|
|
}
|
|
|
|
template <>
|
|
inline int __CRTDECL _LStrcoll(const char* _First1, const char* _Last1, const char* _First2, const char* _Last2,
|
|
const _Locinfo::_Collvec* _Vector) { // perform locale-specific comparison of char sequences
|
|
return _Strcoll(_First1, _Last1, _First2, _Last2, _Vector);
|
|
}
|
|
|
|
template <>
|
|
inline int __CRTDECL _LStrcoll(const wchar_t* _First1, const wchar_t* _Last1, const wchar_t* _First2,
|
|
const wchar_t* _Last2,
|
|
const _Locinfo::_Collvec* _Vector) { // perform locale-specific comparison of wchar_t sequences
|
|
return _Wcscoll(_First1, _Last1, _First2, _Last2, _Vector);
|
|
}
|
|
|
|
// FUNCTION TEMPLATE _LStrxfrm
|
|
template <class _Elem>
|
|
size_t __CRTDECL _LStrxfrm(_Elem* _First1, _Elem* _Last1, const _Elem* _First2, const _Elem* _Last2,
|
|
const _Locinfo::_Collvec*) { // perform locale-specific transform of _Elems [_First1, _Last1)
|
|
const ptrdiff_t _Count = _Last2 - _First2;
|
|
if (_Count <= _Last1 - _First1) {
|
|
_CSTD memcpy(_First1, _First2, _Count * sizeof(_Elem));
|
|
}
|
|
|
|
return _Count;
|
|
}
|
|
|
|
template <>
|
|
inline size_t __CRTDECL _LStrxfrm(_Out_writes_(_Last1 - _First1) _Post_readable_size_(return ) char* _First1,
|
|
_In_z_ char* _Last1, const char* _First2, const char* _Last2,
|
|
const _Locinfo::_Collvec* _Vector) { // perform locale-specific transform of chars [_First1, _Last1)
|
|
return _Strxfrm(_First1, _Last1, _First2, _Last2, _Vector);
|
|
}
|
|
|
|
template <>
|
|
inline size_t __CRTDECL _LStrxfrm(_Out_writes_(_Last1 - _First1) _Post_readable_size_(return ) wchar_t* _First1,
|
|
_In_z_ wchar_t* _Last1, const wchar_t* _First2, const wchar_t* _Last2,
|
|
const _Locinfo::_Collvec* _Vector) { // perform locale-specific transform of wchar_ts [_First1, _Last1)
|
|
return _Wcsxfrm(_First1, _Last1, _First2, _Last2, _Vector);
|
|
}
|
|
_STD_END
|
|
#pragma pop_macro("new")
|
|
_STL_RESTORE_CLANG_WARNINGS
|
|
#pragma warning(pop)
|
|
#pragma pack(pop)
|
|
#endif // _STL_COMPILER_PREPROCESSOR
|
|
#endif // _XLOCINFO_
|