From 2a367cd7c4b8e92e85c3ab614cd4e47a044b0351 Mon Sep 17 00:00:00 2001 From: Hamid Reza Date: Sun, 9 Aug 2020 05:33:04 +0430 Subject: [PATCH 01/11] Fix Issue 1126 --- stl/inc/xlocale | 2 +- stl/inc/xloctime | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/stl/inc/xlocale b/stl/inc/xlocale index 5877d9aecb8..fc136ad5ae5 100644 --- a/stl/inc/xlocale +++ b/stl/inc/xlocale @@ -490,7 +490,7 @@ int __CRTDECL _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields, const _ || _Ptr[_Off] == _Elem{}) { // matched all of field, save as possible answer _Str[_Field] = static_cast(_Column < 127 ? _Column : 127); // save skip count if small enough _Ans = static_cast(_Field); // save answer - } else if (_First == _Last || _Ptr[_Off] != *_First) { + } else if (_First == _Last || tolower(_Ptr[_Off]) != towlower(*_First)) { _Str[_Field] = static_cast(_Column < 127 ? _Column : 127); // no match, just save skip count } else { _Prefix = true; // still a valid prefix diff --git a/stl/inc/xloctime b/stl/inc/xloctime index bf342ba6bd9..c0120f138d7 100644 --- a/stl/inc/xloctime +++ b/stl/inc/xloctime @@ -132,6 +132,9 @@ public: } _First = do_get(_First, _Last, _Iosbase, _State, _Pt, _Specifier, _Modifier); // convert a single field + if (_State != 0) { + break; + } } } From ef44749b4a6da5d9158087abbed3cce8ec253a62 Mon Sep 17 00:00:00 2001 From: Hamid Reza Arzaghi Date: Mon, 10 Aug 2020 01:37:19 +0430 Subject: [PATCH 02/11] Update xlocale Use ctype and facet for comparing case-insensitive --- stl/inc/xlocale | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stl/inc/xlocale b/stl/inc/xlocale index fc136ad5ae5..cd01311908d 100644 --- a/stl/inc/xlocale +++ b/stl/inc/xlocale @@ -472,6 +472,7 @@ int __CRTDECL _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields, const _ } string _Str(_Numfields, '\0'); // one column counter for each field + const ctype<_Elem>& _CType = use_facet>(locale()); int _Ans = -2; // no candidates so far for (size_t _Column = 1;; ++_Column, (void) ++_First, _Ans = -1) { // test each element against all viable fields @@ -490,7 +491,7 @@ int __CRTDECL _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields, const _ || _Ptr[_Off] == _Elem{}) { // matched all of field, save as possible answer _Str[_Field] = static_cast(_Column < 127 ? _Column : 127); // save skip count if small enough _Ans = static_cast(_Field); // save answer - } else if (_First == _Last || tolower(_Ptr[_Off]) != towlower(*_First)) { + } else if (_First == _Last || _CType.tolower(_Ptr[_Off]) != _CType.tolower(*_First)) { _Str[_Field] = static_cast(_Column < 127 ? _Column : 127); // no match, just save skip count } else { _Prefix = true; // still a valid prefix From 39f492aef0cfb6dcbf22dd610aeb5e24aef1cbe3 Mon Sep 17 00:00:00 2001 From: Hamid Reza Date: Wed, 12 Aug 2020 18:27:08 +0430 Subject: [PATCH 03/11] Update xlocale to support date and time in case-insensitive approach --- stl/inc/xlocale | 495 ++++++++++++++++++++++++------------------------ 1 file changed, 248 insertions(+), 247 deletions(-) diff --git a/stl/inc/xlocale b/stl/inc/xlocale index cd01311908d..6aab7e428ee 100644 --- a/stl/inc/xlocale +++ b/stl/inc/xlocale @@ -461,6 +461,252 @@ const _Facet& __CRTDECL use_facet(const locale& _Loc) { // get facet reference f _END_LOCK() } // end of use_facet body +// STRUCT ctype_base +struct _CRTIMP2_PURE_IMPORT ctype_base : locale::facet { // base for ctype + enum { // constants for character classifications + alnum = _DI | _LO | _UP | _XA, + alpha = _LO | _UP | _XA, + cntrl = _BB, + digit = _DI, + graph = _DI | _LO | _PU | _UP | _XA, + lower = _LO, + print = _DI | _LO | _PU | _SP | _UP | _XA | _XD, + punct = _PU, + space = _CN | _SP | _XS, + upper = _UP, + xdigit = _XD, + blank = _CN | _SP | _XS | _XB + }; + using mask = short; // to match + + __CLR_OR_THIS_CALL ctype_base(size_t _Refs = 0) : locale::facet(_Refs) {} + + __CLR_OR_THIS_CALL ~ctype_base() noexcept {} +}; + + +// CLASS TEMPLATE ctype +template +class ctype : public ctype_base { // facet for classifying elements, converting cases +public: + // ctype, ctype, and ctype are explicitly specialized below. + static_assert(!_ENFORCE_FACET_SPECIALIZATIONS || _Always_false<_Elem>, _FACET_SPECIALIZATION_MESSAGE); + + using char_type = _Elem; + + bool __CLR_OR_THIS_CALL is(mask _Maskval, _Elem _Ch) const { // test if element fits any mask classifications + return do_is(_Maskval, _Ch); + } + + const _Elem* __CLR_OR_THIS_CALL is(const _Elem* _First, const _Elem* _Last, + mask* _Dest) const { // get mask sequence for elements in [_First, _Last) + return do_is(_First, _Last, _Dest); + } + + const _Elem* __CLR_OR_THIS_CALL scan_is(mask _Maskval, const _Elem* _First, + const _Elem* _Last) const { // find first in [_First, _Last) that fits mask classification + return do_scan_is(_Maskval, _First, _Last); + } + + const _Elem* __CLR_OR_THIS_CALL scan_not(mask _Maskval, const _Elem* _First, + const _Elem* _Last) const { // find first in [_First, _Last) not fitting mask classification + return do_scan_not(_Maskval, _First, _Last); + } + + _Elem __CLR_OR_THIS_CALL tolower(_Elem _Ch) const { // convert element to lower case + return do_tolower(_Ch); + } + + const _Elem* __CLR_OR_THIS_CALL tolower( + _Elem* _First, const _Elem* _Last) const { // convert [_First, _Last) in place to lower case + return do_tolower(_First, _Last); + } + + _Elem __CLR_OR_THIS_CALL toupper(_Elem _Ch) const { // convert element to upper case + return do_toupper(_Ch); + } + + const _Elem* __CLR_OR_THIS_CALL toupper( + _Elem* _First, const _Elem* _Last) const { // convert [_First, _Last) in place to upper case + return do_toupper(_First, _Last); + } + + _Elem __CLR_OR_THIS_CALL widen(char _Byte) const { // widen char + return do_widen(_Byte); + } + + const char* __CLR_OR_THIS_CALL widen(const char* _First, const char* _Last, + _Elem* _Dest) const { // widen chars in [_First, _Last) + return do_widen(_First, _Last, _Dest); + } + + char __CLR_OR_THIS_CALL narrow(_Elem _Ch, char _Dflt = '\0') const { // narrow element to char + return do_narrow(_Ch, _Dflt); + } + + const _Elem* __CLR_OR_THIS_CALL narrow(const _Elem* _First, const _Elem* _Last, char _Dflt, + char* _Dest) const { // narrow elements in [_First, _Last) to chars + return do_narrow(_First, _Last, _Dflt, _Dest); + } + + __PURE_APPDOMAIN_GLOBAL static locale::id id; + + explicit __CLR_OR_THIS_CALL ctype(size_t _Refs = 0) : ctype_base(_Refs) { + _BEGIN_LOCINFO(_Lobj) + _Init(_Lobj); + _END_LOCINFO() + } + + __CLR_OR_THIS_CALL ctype(const _Locinfo& _Lobj, size_t _Refs = 0) : ctype_base(_Refs) { + _Init(_Lobj); + } + + static size_t __CLRCALL_OR_CDECL _Getcat(const locale::facet** _Ppf = nullptr, const locale* _Ploc = nullptr) { + if (_Ppf && !*_Ppf) { + *_Ppf = new ctype<_Elem>(_Locinfo(_Ploc->c_str())); + } + + return _X_CTYPE; + } + +protected: + virtual __CLR_OR_THIS_CALL ~ctype() noexcept { + if (_Ctype._Delfl) { + _CSTD free(const_cast(_Ctype._Table)); + } + + _CSTD free(_Ctype._LocaleName); + } + + void __CLR_OR_THIS_CALL _Init(const _Locinfo& _Lobj) { // initialize from _Lobj + _Ctype = _Lobj._Getctype(); + _Cvt = _Lobj._Getcvt(); + } + + virtual bool __CLR_OR_THIS_CALL do_is( + mask _Maskval, _Elem _Ch) const { // test if element fits any mask classifications + return (_Ctype._Table[static_cast(narrow(_Ch))] & _Maskval) != 0; + } + + virtual const _Elem* __CLR_OR_THIS_CALL do_is(const _Elem* _First, const _Elem* _Last, + mask* _Dest) const { // get mask sequence for elements in [_First, _Last) + _Adl_verify_range(_First, _Last); + for (; _First != _Last; ++_First, ++_Dest) { + *_Dest = _Ctype._Table[static_cast(narrow(*_First))]; + } + + return _First; + } + + virtual const _Elem* __CLR_OR_THIS_CALL do_scan_is(mask _Maskval, const _Elem* _First, + const _Elem* _Last) const { // find first in [_First, _Last) that fits mask classification + _Adl_verify_range(_First, _Last); + while (_First != _Last && !is(_Maskval, *_First)) { + ++_First; + } + + return _First; + } + + virtual const _Elem* __CLR_OR_THIS_CALL do_scan_not(mask _Maskval, const _Elem* _First, + const _Elem* _Last) const { // find first in [_First, _Last) not fitting mask classification + _Adl_verify_range(_First, _Last); + while (_First != _Last && is(_Maskval, *_First)) { + ++_First; + } + + return _First; + } + + virtual _Elem __CLR_OR_THIS_CALL do_tolower(_Elem _Ch) const { // convert element to lower case + unsigned char _Byte = static_cast(narrow(_Ch, '\0')); + if (_Byte == '\0') { + return _Ch; + } + + return widen(static_cast(_Tolower(_Byte, &_Ctype))); + } + + virtual const _Elem* __CLR_OR_THIS_CALL do_tolower(_Elem* _First, + const _Elem* _Last) const { // convert [_First, _Last) in place to lower case + _Adl_verify_range(_First, _Last); + for (; _First != _Last; ++_First) { // convert *_First to lower case + unsigned char _Byte = static_cast(narrow(*_First, '\0')); + if (_Byte != '\0') { + *_First = (widen(static_cast(_Tolower(_Byte, &_Ctype)))); + } + } + return _First; + } + + virtual _Elem __CLR_OR_THIS_CALL do_toupper(_Elem _Ch) const { // convert element to upper case + unsigned char _Byte = static_cast(narrow(_Ch, '\0')); + if (_Byte == '\0') { + return _Ch; + } + + return widen(static_cast(_Toupper(_Byte, &_Ctype))); + } + + virtual const _Elem* __CLR_OR_THIS_CALL do_toupper(_Elem* _First, + const _Elem* _Last) const { // convert [_First, _Last) in place to upper case + _Adl_verify_range(_First, _Last); + for (; _First != _Last; ++_First) { // convert *_First to upper case + unsigned char _Byte = static_cast(narrow(*_First, '\0')); + if (_Byte != '\0') { + *_First = (widen(static_cast(_Toupper(_Byte, &_Ctype)))); + } + } + + return _First; + } + + virtual _Elem __CLR_OR_THIS_CALL do_widen(char _Byte) const { // widen char + return _Maklocchr(_Byte, static_cast<_Elem*>(nullptr), _Cvt); + } + + virtual const char* __CLR_OR_THIS_CALL do_widen( + const char* _First, const char* _Last, _Elem* _Dest) const { // widen chars in [_First, _Last) + _Adl_verify_range(_First, _Last); + for (; _First != _Last; ++_First, ++_Dest) { + *_Dest = _Maklocchr(*_First, static_cast<_Elem*>(nullptr), _Cvt); + } + + return _First; + } + + char __CLR_OR_THIS_CALL _Donarrow(_Elem _Ch, char _Dflt) const { // narrow element to char + char _Byte; + if (_Ch == _Elem{}) { + return '\0'; + } + + if ((_Byte = _Maklocbyte(_Ch, _Cvt)) == '\0') { + return _Dflt; + } + + return _Byte; + } + + virtual char __CLR_OR_THIS_CALL do_narrow(_Elem _Ch, char _Dflt) const { // narrow element to char + return _Donarrow(_Ch, _Dflt); + } + + virtual const _Elem* __CLR_OR_THIS_CALL do_narrow(const _Elem* _First, const _Elem* _Last, char _Dflt, + char* _Dest) const { // narrow elements in [_First, _Last) to chars + _Adl_verify_range(_First, _Last); + for (; _First != _Last; ++_First, ++_Dest) { + *_Dest = _Donarrow(*_First, _Dflt); + } + + return _First; + } + +private: + _Locinfo::_Ctypevec _Ctype; // locale info passed to _Tolower, etc. + _Locinfo::_Cvtvec _Cvt; // conversion information +}; + // FUNCTION TEMPLATE _Getloctxt template int __CRTDECL _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields, const _Elem* _Ptr) { @@ -472,7 +718,7 @@ int __CRTDECL _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields, const _ } string _Str(_Numfields, '\0'); // one column counter for each field - const ctype<_Elem>& _CType = use_facet>(locale()); + const _STD ctype<_Elem>& _CType = _STD use_facet<_STD ctype<_Elem>>(_STD locale()); int _Ans = -2; // no candidates so far for (size_t _Column = 1;; ++_Column, (void) ++_First, _Ans = -1) { // test each element against all viable fields @@ -491,7 +737,7 @@ int __CRTDECL _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields, const _ || _Ptr[_Off] == _Elem{}) { // matched all of field, save as possible answer _Str[_Field] = static_cast(_Column < 127 ? _Column : 127); // save skip count if small enough _Ans = static_cast(_Field); // save answer - } else if (_First == _Last || _CType.tolower(_Ptr[_Off]) != _CType.tolower(*_First)) { + } else if (_First == _Last || _CType.tolower(_Ptr[_Off]) != _CType.tolower(static_cast<_Elem>(*_First))) { _Str[_Field] = static_cast(_Column < 127 ? _Column : 127); // no match, just save skip count } else { _Prefix = true; // still a valid prefix @@ -2389,251 +2635,6 @@ protected: virtual __CLR_OR_THIS_CALL ~codecvt_byname() noexcept {} }; -// STRUCT ctype_base -struct _CRTIMP2_PURE_IMPORT ctype_base : locale::facet { // base for ctype - enum { // constants for character classifications - alnum = _DI | _LO | _UP | _XA, - alpha = _LO | _UP | _XA, - cntrl = _BB, - digit = _DI, - graph = _DI | _LO | _PU | _UP | _XA, - lower = _LO, - print = _DI | _LO | _PU | _SP | _UP | _XA | _XD, - punct = _PU, - space = _CN | _SP | _XS, - upper = _UP, - xdigit = _XD, - blank = _CN | _SP | _XS | _XB - }; - using mask = short; // to match - - __CLR_OR_THIS_CALL ctype_base(size_t _Refs = 0) : locale::facet(_Refs) {} - - __CLR_OR_THIS_CALL ~ctype_base() noexcept {} -}; - -// CLASS TEMPLATE ctype -template -class ctype : public ctype_base { // facet for classifying elements, converting cases -public: - // ctype, ctype, and ctype are explicitly specialized below. - static_assert(!_ENFORCE_FACET_SPECIALIZATIONS || _Always_false<_Elem>, _FACET_SPECIALIZATION_MESSAGE); - - using char_type = _Elem; - - bool __CLR_OR_THIS_CALL is(mask _Maskval, _Elem _Ch) const { // test if element fits any mask classifications - return do_is(_Maskval, _Ch); - } - - const _Elem* __CLR_OR_THIS_CALL is(const _Elem* _First, const _Elem* _Last, - mask* _Dest) const { // get mask sequence for elements in [_First, _Last) - return do_is(_First, _Last, _Dest); - } - - const _Elem* __CLR_OR_THIS_CALL scan_is(mask _Maskval, const _Elem* _First, - const _Elem* _Last) const { // find first in [_First, _Last) that fits mask classification - return do_scan_is(_Maskval, _First, _Last); - } - - const _Elem* __CLR_OR_THIS_CALL scan_not(mask _Maskval, const _Elem* _First, - const _Elem* _Last) const { // find first in [_First, _Last) not fitting mask classification - return do_scan_not(_Maskval, _First, _Last); - } - - _Elem __CLR_OR_THIS_CALL tolower(_Elem _Ch) const { // convert element to lower case - return do_tolower(_Ch); - } - - const _Elem* __CLR_OR_THIS_CALL tolower( - _Elem* _First, const _Elem* _Last) const { // convert [_First, _Last) in place to lower case - return do_tolower(_First, _Last); - } - - _Elem __CLR_OR_THIS_CALL toupper(_Elem _Ch) const { // convert element to upper case - return do_toupper(_Ch); - } - - const _Elem* __CLR_OR_THIS_CALL toupper( - _Elem* _First, const _Elem* _Last) const { // convert [_First, _Last) in place to upper case - return do_toupper(_First, _Last); - } - - _Elem __CLR_OR_THIS_CALL widen(char _Byte) const { // widen char - return do_widen(_Byte); - } - - const char* __CLR_OR_THIS_CALL widen(const char* _First, const char* _Last, - _Elem* _Dest) const { // widen chars in [_First, _Last) - return do_widen(_First, _Last, _Dest); - } - - char __CLR_OR_THIS_CALL narrow(_Elem _Ch, char _Dflt = '\0') const { // narrow element to char - return do_narrow(_Ch, _Dflt); - } - - const _Elem* __CLR_OR_THIS_CALL narrow(const _Elem* _First, const _Elem* _Last, char _Dflt, - char* _Dest) const { // narrow elements in [_First, _Last) to chars - return do_narrow(_First, _Last, _Dflt, _Dest); - } - - __PURE_APPDOMAIN_GLOBAL static locale::id id; - - explicit __CLR_OR_THIS_CALL ctype(size_t _Refs = 0) : ctype_base(_Refs) { - _BEGIN_LOCINFO(_Lobj) - _Init(_Lobj); - _END_LOCINFO() - } - - __CLR_OR_THIS_CALL ctype(const _Locinfo& _Lobj, size_t _Refs = 0) : ctype_base(_Refs) { - _Init(_Lobj); - } - - static size_t __CLRCALL_OR_CDECL _Getcat(const locale::facet** _Ppf = nullptr, const locale* _Ploc = nullptr) { - if (_Ppf && !*_Ppf) { - *_Ppf = new ctype<_Elem>(_Locinfo(_Ploc->c_str())); - } - - return _X_CTYPE; - } - -protected: - virtual __CLR_OR_THIS_CALL ~ctype() noexcept { - if (_Ctype._Delfl) { - _CSTD free(const_cast(_Ctype._Table)); - } - - _CSTD free(_Ctype._LocaleName); - } - - void __CLR_OR_THIS_CALL _Init(const _Locinfo& _Lobj) { // initialize from _Lobj - _Ctype = _Lobj._Getctype(); - _Cvt = _Lobj._Getcvt(); - } - - virtual bool __CLR_OR_THIS_CALL do_is( - mask _Maskval, _Elem _Ch) const { // test if element fits any mask classifications - return (_Ctype._Table[static_cast(narrow(_Ch))] & _Maskval) != 0; - } - - virtual const _Elem* __CLR_OR_THIS_CALL do_is(const _Elem* _First, const _Elem* _Last, - mask* _Dest) const { // get mask sequence for elements in [_First, _Last) - _Adl_verify_range(_First, _Last); - for (; _First != _Last; ++_First, ++_Dest) { - *_Dest = _Ctype._Table[static_cast(narrow(*_First))]; - } - - return _First; - } - - virtual const _Elem* __CLR_OR_THIS_CALL do_scan_is(mask _Maskval, const _Elem* _First, - const _Elem* _Last) const { // find first in [_First, _Last) that fits mask classification - _Adl_verify_range(_First, _Last); - while (_First != _Last && !is(_Maskval, *_First)) { - ++_First; - } - - return _First; - } - - virtual const _Elem* __CLR_OR_THIS_CALL do_scan_not(mask _Maskval, const _Elem* _First, - const _Elem* _Last) const { // find first in [_First, _Last) not fitting mask classification - _Adl_verify_range(_First, _Last); - while (_First != _Last && is(_Maskval, *_First)) { - ++_First; - } - - return _First; - } - - virtual _Elem __CLR_OR_THIS_CALL do_tolower(_Elem _Ch) const { // convert element to lower case - unsigned char _Byte = static_cast(narrow(_Ch, '\0')); - if (_Byte == '\0') { - return _Ch; - } - - return widen(static_cast(_Tolower(_Byte, &_Ctype))); - } - - virtual const _Elem* __CLR_OR_THIS_CALL do_tolower(_Elem* _First, - const _Elem* _Last) const { // convert [_First, _Last) in place to lower case - _Adl_verify_range(_First, _Last); - for (; _First != _Last; ++_First) { // convert *_First to lower case - unsigned char _Byte = static_cast(narrow(*_First, '\0')); - if (_Byte != '\0') { - *_First = (widen(static_cast(_Tolower(_Byte, &_Ctype)))); - } - } - return _First; - } - - virtual _Elem __CLR_OR_THIS_CALL do_toupper(_Elem _Ch) const { // convert element to upper case - unsigned char _Byte = static_cast(narrow(_Ch, '\0')); - if (_Byte == '\0') { - return _Ch; - } - - return widen(static_cast(_Toupper(_Byte, &_Ctype))); - } - - virtual const _Elem* __CLR_OR_THIS_CALL do_toupper(_Elem* _First, - const _Elem* _Last) const { // convert [_First, _Last) in place to upper case - _Adl_verify_range(_First, _Last); - for (; _First != _Last; ++_First) { // convert *_First to upper case - unsigned char _Byte = static_cast(narrow(*_First, '\0')); - if (_Byte != '\0') { - *_First = (widen(static_cast(_Toupper(_Byte, &_Ctype)))); - } - } - - return _First; - } - - virtual _Elem __CLR_OR_THIS_CALL do_widen(char _Byte) const { // widen char - return _Maklocchr(_Byte, static_cast<_Elem*>(nullptr), _Cvt); - } - - virtual const char* __CLR_OR_THIS_CALL do_widen( - const char* _First, const char* _Last, _Elem* _Dest) const { // widen chars in [_First, _Last) - _Adl_verify_range(_First, _Last); - for (; _First != _Last; ++_First, ++_Dest) { - *_Dest = _Maklocchr(*_First, static_cast<_Elem*>(nullptr), _Cvt); - } - - return _First; - } - - char __CLR_OR_THIS_CALL _Donarrow(_Elem _Ch, char _Dflt) const { // narrow element to char - char _Byte; - if (_Ch == _Elem{}) { - return '\0'; - } - - if ((_Byte = _Maklocbyte(_Ch, _Cvt)) == '\0') { - return _Dflt; - } - - return _Byte; - } - - virtual char __CLR_OR_THIS_CALL do_narrow(_Elem _Ch, char _Dflt) const { // narrow element to char - return _Donarrow(_Ch, _Dflt); - } - - virtual const _Elem* __CLR_OR_THIS_CALL do_narrow(const _Elem* _First, const _Elem* _Last, char _Dflt, - char* _Dest) const { // narrow elements in [_First, _Last) to chars - _Adl_verify_range(_First, _Last); - for (; _First != _Last; ++_First, ++_Dest) { - *_Dest = _Donarrow(*_First, _Dflt); - } - - return _First; - } - -private: - _Locinfo::_Ctypevec _Ctype; // locale info passed to _Tolower, etc. - _Locinfo::_Cvtvec _Cvt; // conversion information -}; - // STATIC ctype::id OBJECT #ifdef __clang__ #pragma clang diagnostic push From acbf454a86071707da7b9ddad946143519462cd3 Mon Sep 17 00:00:00 2001 From: Hamid Reza Date: Thu, 13 Aug 2020 00:16:40 +0430 Subject: [PATCH 04/11] move up _Maklocchr definitions --- stl/inc/xlocale | 307 ++++++++++++++++++++++++------------------------ 1 file changed, 153 insertions(+), 154 deletions(-) diff --git a/stl/inc/xlocale b/stl/inc/xlocale index 6aab7e428ee..c3405acf92d 100644 --- a/stl/inc/xlocale +++ b/stl/inc/xlocale @@ -461,6 +461,159 @@ const _Facet& __CRTDECL use_facet(const locale& _Loc) { // get facet reference f _END_LOCK() } // end of use_facet body +// FUNCTION TEMPLATE _Maklocbyte +template +char __CRTDECL _Maklocbyte(_Elem _Char, const _Locinfo::_Cvtvec&) { + // convert _Elem to char using _Cvtvec + return static_cast(static_cast(_Char)); +} + +template <> +inline char __CRTDECL _Maklocbyte(wchar_t _Char, const _Locinfo::_Cvtvec& _Cvt) { + // convert wchar_t to char using _Cvtvec + char _Byte = '\0'; + mbstate_t _Mbst1 = {}; + _Wcrtomb(&_Byte, _Char, &_Mbst1, &_Cvt); + return _Byte; +} + +#ifdef _NATIVE_WCHAR_T_DEFINED +template <> +inline char __CRTDECL _Maklocbyte(unsigned short _Char, const _Locinfo::_Cvtvec& _Cvt) { + // convert unsigned short to char using _Cvtvec + char _Byte = '\0'; + mbstate_t _Mbst1 = {}; + _Wcrtomb(&_Byte, static_cast(_Char), &_Mbst1, &_Cvt); + return _Byte; +} +#endif // _NATIVE_WCHAR_T_DEFINED + +// FUNCTION TEMPLATE _Maklocchr +template +_Elem __CRTDECL _Maklocchr(char _Byte, _Elem*, const _Locinfo::_Cvtvec&) { + // convert char to _Elem using _Cvtvec + return static_cast<_Elem>(static_cast(_Byte)); +} + +template <> +inline wchar_t __CRTDECL _Maklocchr(char _Byte, wchar_t*, const _Locinfo::_Cvtvec& _Cvt) { + // convert char to wchar_t using _Cvtvec + wchar_t _Wc = L'\0'; + mbstate_t _Mbst1 = {}; + _Mbrtowc(&_Wc, &_Byte, 1, &_Mbst1, &_Cvt); + return _Wc; +} + +#ifdef _NATIVE_WCHAR_T_DEFINED +template <> +inline unsigned short __CRTDECL _Maklocchr(char _Byte, unsigned short*, const _Locinfo::_Cvtvec& _Cvt) { + // convert char to unsigned short using _Cvtvec + unsigned short _Wc = 0; + mbstate_t _Mbst1 = {}; + _Mbrtowc(reinterpret_cast(&_Wc), &_Byte, 1, &_Mbst1, &_Cvt); + return _Wc; +} +#endif // _NATIVE_WCHAR_T_DEFINED + +// FUNCTION TEMPLATE _Maklocstr +template +_Elem* __CRTDECL _Maklocstr(const char* _Ptr, _Elem*, const _Locinfo::_Cvtvec&) { + // convert C string to _Elem sequence using _Cvtvec + size_t _Count = _CSTD strlen(_Ptr) + 1; + + _Elem* _Ptrdest = static_cast<_Elem*>(_calloc_dbg(_Count, sizeof(_Elem), _CRT_BLOCK, __FILE__, __LINE__)); + + if (!_Ptrdest) { + _Xbad_alloc(); + } + + for (_Elem* _Ptrnext = _Ptrdest; 0 < _Count; --_Count, ++_Ptrnext, ++_Ptr) { + *_Ptrnext = static_cast<_Elem>(static_cast(*_Ptr)); + } + + return _Ptrdest; +} + +template <> +inline wchar_t* __CRTDECL _Maklocstr(const char* _Ptr, wchar_t*, const _Locinfo::_Cvtvec& _Cvt) { + // convert C string to wchar_t sequence using _Cvtvec + size_t _Count; + size_t _Count1; + size_t _Wchars; + const char* _Ptr1; + int _Bytes; + wchar_t _Wc; + mbstate_t _Mbst1 = {}; + + _Count1 = _CSTD strlen(_Ptr) + 1; + for (_Count = _Count1, _Wchars = 0, _Ptr1 = _Ptr; 0 < _Count; _Count -= _Bytes, _Ptr1 += _Bytes, ++_Wchars) { + if ((_Bytes = _Mbrtowc(&_Wc, _Ptr1, _Count, &_Mbst1, &_Cvt)) <= 0) { + break; + } + } + + ++_Wchars; // count terminating nul + + wchar_t* _Ptrdest = static_cast(_calloc_dbg(_Wchars, sizeof(wchar_t), _CRT_BLOCK, __FILE__, __LINE__)); + + if (!_Ptrdest) { + _Xbad_alloc(); + } + + wchar_t* _Ptrnext = _Ptrdest; + mbstate_t _Mbst2 = {}; + + for (; 0 < _Wchars; _Count -= _Bytes, _Ptr += _Bytes, --_Wchars, ++_Ptrnext) { + if ((_Bytes = _Mbrtowc(_Ptrnext, _Ptr, _Count1, &_Mbst2, &_Cvt)) <= 0) { + break; + } + } + + *_Ptrnext = L'\0'; + + return _Ptrdest; +} + +#ifdef _NATIVE_WCHAR_T_DEFINED +template <> +inline unsigned short* __CRTDECL _Maklocstr(const char* _Ptr, unsigned short*, const _Locinfo::_Cvtvec& _Cvt) { + // convert C string to unsigned short sequence using _Cvtvec + size_t _Count; + size_t _Count1; + size_t _Wchars; + const char* _Ptr1; + int _Bytes; + unsigned short _Wc; + mbstate_t _Mbst1 = {}; + + _Count1 = _CSTD strlen(_Ptr) + 1; + for (_Count = _Count1, _Wchars = 0, _Ptr1 = _Ptr; 0 < _Count; _Count -= _Bytes, _Ptr1 += _Bytes, ++_Wchars) { + if ((_Bytes = _Mbrtowc(reinterpret_cast(&_Wc), _Ptr1, _Count, &_Mbst1, &_Cvt)) <= 0) { + break; + } + } + + ++_Wchars; // count terminating nul + + wchar_t* _Ptrdest = static_cast(_calloc_dbg(_Wchars, sizeof(wchar_t), _CRT_BLOCK, __FILE__, __LINE__)); + + if (!_Ptrdest) { + _Xbad_alloc(); + } + + wchar_t* _Ptrnext = _Ptrdest; + mbstate_t _Mbst2 = {}; + for (; 0 < _Wchars; _Count -= _Bytes, _Ptr += _Bytes, --_Wchars, ++_Ptrnext) { + if ((_Bytes = _Mbrtowc(_Ptrnext, _Ptr, _Count1, &_Mbst2, &_Cvt)) <= 0) { + break; + } + } + + *_Ptrnext = L'\0'; + return reinterpret_cast(_Ptrdest); +} +#endif // _NATIVE_WCHAR_T_DEFINED + // STRUCT ctype_base struct _CRTIMP2_PURE_IMPORT ctype_base : locale::facet { // base for ctype enum { // constants for character classifications @@ -484,7 +637,6 @@ struct _CRTIMP2_PURE_IMPORT ctype_base : locale::facet { // base for ctype __CLR_OR_THIS_CALL ~ctype_base() noexcept {} }; - // CLASS TEMPLATE ctype template class ctype : public ctype_base { // facet for classifying elements, converting cases @@ -751,159 +903,6 @@ int __CRTDECL _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields, const _ return _Ans; // return field number or negative value on failure } -// FUNCTION TEMPLATE _Maklocbyte -template -char __CRTDECL _Maklocbyte(_Elem _Char, const _Locinfo::_Cvtvec&) { - // convert _Elem to char using _Cvtvec - return static_cast(static_cast(_Char)); -} - -template <> -inline char __CRTDECL _Maklocbyte(wchar_t _Char, const _Locinfo::_Cvtvec& _Cvt) { - // convert wchar_t to char using _Cvtvec - char _Byte = '\0'; - mbstate_t _Mbst1 = {}; - _Wcrtomb(&_Byte, _Char, &_Mbst1, &_Cvt); - return _Byte; -} - -#ifdef _NATIVE_WCHAR_T_DEFINED -template <> -inline char __CRTDECL _Maklocbyte(unsigned short _Char, const _Locinfo::_Cvtvec& _Cvt) { - // convert unsigned short to char using _Cvtvec - char _Byte = '\0'; - mbstate_t _Mbst1 = {}; - _Wcrtomb(&_Byte, static_cast(_Char), &_Mbst1, &_Cvt); - return _Byte; -} -#endif // _NATIVE_WCHAR_T_DEFINED - -// FUNCTION TEMPLATE _Maklocchr -template -_Elem __CRTDECL _Maklocchr(char _Byte, _Elem*, const _Locinfo::_Cvtvec&) { - // convert char to _Elem using _Cvtvec - return static_cast<_Elem>(static_cast(_Byte)); -} - -template <> -inline wchar_t __CRTDECL _Maklocchr(char _Byte, wchar_t*, const _Locinfo::_Cvtvec& _Cvt) { - // convert char to wchar_t using _Cvtvec - wchar_t _Wc = L'\0'; - mbstate_t _Mbst1 = {}; - _Mbrtowc(&_Wc, &_Byte, 1, &_Mbst1, &_Cvt); - return _Wc; -} - -#ifdef _NATIVE_WCHAR_T_DEFINED -template <> -inline unsigned short __CRTDECL _Maklocchr(char _Byte, unsigned short*, const _Locinfo::_Cvtvec& _Cvt) { - // convert char to unsigned short using _Cvtvec - unsigned short _Wc = 0; - mbstate_t _Mbst1 = {}; - _Mbrtowc(reinterpret_cast(&_Wc), &_Byte, 1, &_Mbst1, &_Cvt); - return _Wc; -} -#endif // _NATIVE_WCHAR_T_DEFINED - -// FUNCTION TEMPLATE _Maklocstr -template -_Elem* __CRTDECL _Maklocstr(const char* _Ptr, _Elem*, const _Locinfo::_Cvtvec&) { - // convert C string to _Elem sequence using _Cvtvec - size_t _Count = _CSTD strlen(_Ptr) + 1; - - _Elem* _Ptrdest = static_cast<_Elem*>(_calloc_dbg(_Count, sizeof(_Elem), _CRT_BLOCK, __FILE__, __LINE__)); - - if (!_Ptrdest) { - _Xbad_alloc(); - } - - for (_Elem* _Ptrnext = _Ptrdest; 0 < _Count; --_Count, ++_Ptrnext, ++_Ptr) { - *_Ptrnext = static_cast<_Elem>(static_cast(*_Ptr)); - } - - return _Ptrdest; -} - -template <> -inline wchar_t* __CRTDECL _Maklocstr(const char* _Ptr, wchar_t*, const _Locinfo::_Cvtvec& _Cvt) { - // convert C string to wchar_t sequence using _Cvtvec - size_t _Count; - size_t _Count1; - size_t _Wchars; - const char* _Ptr1; - int _Bytes; - wchar_t _Wc; - mbstate_t _Mbst1 = {}; - - _Count1 = _CSTD strlen(_Ptr) + 1; - for (_Count = _Count1, _Wchars = 0, _Ptr1 = _Ptr; 0 < _Count; _Count -= _Bytes, _Ptr1 += _Bytes, ++_Wchars) { - if ((_Bytes = _Mbrtowc(&_Wc, _Ptr1, _Count, &_Mbst1, &_Cvt)) <= 0) { - break; - } - } - - ++_Wchars; // count terminating nul - - wchar_t* _Ptrdest = static_cast(_calloc_dbg(_Wchars, sizeof(wchar_t), _CRT_BLOCK, __FILE__, __LINE__)); - - if (!_Ptrdest) { - _Xbad_alloc(); - } - - wchar_t* _Ptrnext = _Ptrdest; - mbstate_t _Mbst2 = {}; - - for (; 0 < _Wchars; _Count -= _Bytes, _Ptr += _Bytes, --_Wchars, ++_Ptrnext) { - if ((_Bytes = _Mbrtowc(_Ptrnext, _Ptr, _Count1, &_Mbst2, &_Cvt)) <= 0) { - break; - } - } - - *_Ptrnext = L'\0'; - - return _Ptrdest; -} - -#ifdef _NATIVE_WCHAR_T_DEFINED -template <> -inline unsigned short* __CRTDECL _Maklocstr(const char* _Ptr, unsigned short*, const _Locinfo::_Cvtvec& _Cvt) { - // convert C string to unsigned short sequence using _Cvtvec - size_t _Count; - size_t _Count1; - size_t _Wchars; - const char* _Ptr1; - int _Bytes; - unsigned short _Wc; - mbstate_t _Mbst1 = {}; - - _Count1 = _CSTD strlen(_Ptr) + 1; - for (_Count = _Count1, _Wchars = 0, _Ptr1 = _Ptr; 0 < _Count; _Count -= _Bytes, _Ptr1 += _Bytes, ++_Wchars) { - if ((_Bytes = _Mbrtowc(reinterpret_cast(&_Wc), _Ptr1, _Count, &_Mbst1, &_Cvt)) <= 0) { - break; - } - } - - ++_Wchars; // count terminating nul - - wchar_t* _Ptrdest = static_cast(_calloc_dbg(_Wchars, sizeof(wchar_t), _CRT_BLOCK, __FILE__, __LINE__)); - - if (!_Ptrdest) { - _Xbad_alloc(); - } - - wchar_t* _Ptrnext = _Ptrdest; - mbstate_t _Mbst2 = {}; - for (; 0 < _Wchars; _Count -= _Bytes, _Ptr += _Bytes, --_Wchars, ++_Ptrnext) { - if ((_Bytes = _Mbrtowc(_Ptrnext, _Ptr, _Count1, &_Mbst2, &_Cvt)) <= 0) { - break; - } - } - - *_Ptrnext = L'\0'; - return reinterpret_cast(_Ptrdest); -} -#endif // _NATIVE_WCHAR_T_DEFINED - // STRUCT codecvt_base class _CRTIMP2_PURE_IMPORT codecvt_base : public locale::facet { // base class for codecvt public: From 44d0ed3580d999ba3d32755ecb6b2389423059cd Mon Sep 17 00:00:00 2001 From: Hamid Reza Date: Fri, 14 Aug 2020 06:35:45 +0430 Subject: [PATCH 05/11] Add tests to cover scenarios that discussed on Issue#1126 --- .../std/tests/Dev11_0836436_get_time/test.cpp | 224 +++++++++++++++++- 1 file changed, 222 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/Dev11_0836436_get_time/test.cpp b/tests/std/tests/Dev11_0836436_get_time/test.cpp index 78c69d18074..fa2c7d635f0 100644 --- a/tests/std/tests/Dev11_0836436_get_time/test.cpp +++ b/tests/std/tests/Dev11_0836436_get_time/test.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include @@ -29,6 +29,18 @@ tm helper(const char* const s, const char* const fmt) { return t; } +tm helper_locale(const wchar_t* const s, const wchar_t* const fmt, const char* _loc) { + tm t{}; + + wstringstream wss(s); + wss.imbue(locale(_loc)); + wss >> get_time(&t, fmt); + + assert(static_cast(wss)); + + return t; +} + int read_hour(const char* const s) { const auto t = helper(s, "%I %p"); @@ -59,6 +71,26 @@ tuple read_date(const char* const s) { return make_tuple(t.tm_mday, t.tm_mon, t.tm_year); } +tuple read_date_locale(const wchar_t* const s, const char* _loc) { + const auto t = helper_locale(s, L"%Y-%b-%d", _loc); + + // %x The date, using the locale's date format. + // "%d / %m / %y" + // %d The day of the month [01,31]; leading zeros are permitted but not required. + // %m The month number [01,12]; leading zeros are permitted but not required. + // %y The year within century. When a century is not otherwise specified, + // values in the range [69,99] shall refer to years 1969 to 1999 inclusive, and + // values in the range [00,68] shall refer to years 2000 to 2068 inclusive; + // leading zeros shall be permitted but shall not be required. + + // int tm_mday; // day of the month - [1, 31] + // int tm_mon; // months since January - [0, 11] + // int tm_year; // years since 1900 + + return make_tuple(t.tm_mday, t.tm_mon, t.tm_year); +} + + tuple read_time(const char* const s) { const auto t = helper(s, "%X"); @@ -77,13 +109,18 @@ tuple read_time(const char* const s) { void test_640278(); void test_990695(); +void test_locale_russian(); +void test_locale_german(); +void test_locale_chines(); int main() { assert(read_hour("12 AM") == 0); assert(read_hour("12 am") == 0); assert(read_hour("1 AM") == 1); - assert(read_hour("1 am") == 1); + assert(read_hour("1 am") == 1); + assert(read_hour("1 aM") == 1); + assert(read_hour("1 Am") == 1); assert(read_hour("2 AM") == 2); assert(read_hour("2 am") == 2); @@ -96,6 +133,8 @@ int main() { assert(read_hour("1 PM") == 13); assert(read_hour("1 pm") == 13); + assert(read_hour("1 Pm") == 13); + assert(read_hour("1 pM") == 13); assert(read_hour("2 PM") == 14); assert(read_hour("2 pm") == 14); @@ -113,6 +152,9 @@ int main() { test_640278(); test_990695(); + test_locale_russian(); + test_locale_german(); + test_locale_chines(); } typedef istreambuf_iterator Iter; @@ -207,6 +249,184 @@ void test_990695() { assert(t.tm_mon == 9); assert(t.tm_mday == 31); assert(t.tm_year == 114); + } + + { + istringstream iss("sep 31 2014"); + ios_base::iostate err = Bit; + tm t{}; + const string fmt("%b %d %Y"); + use_facet>(iss.getloc()) + .get(Iter(iss.rdbuf()), Iter(), iss, err, &t, fmt.c_str(), fmt.c_str() + fmt.size()); + assert(t.tm_mon == 8); + assert(t.tm_mday == 31); + assert(t.tm_year == 114); + } + + { + istringstream iss("aUG 14 2020"); + ios_base::iostate err = Bit; + tm t{}; + const string fmt("%b %d %Y"); + use_facet>(iss.getloc()) + .get(Iter(iss.rdbuf()), Iter(), iss, err, &t, fmt.c_str(), fmt.c_str() + fmt.size()); + assert(t.tm_mon == 7); + assert(t.tm_mday == 14); + assert(t.tm_year == 120); + } + + { + istringstream iss("feBRuArY 02 1991"); + ios_base::iostate err = Bit; + tm t{}; + const string fmt("%b %d %Y"); + use_facet>(iss.getloc()) + .get(Iter(iss.rdbuf()), Iter(), iss, err, &t, fmt.c_str(), fmt.c_str() + fmt.size()); + assert(t.tm_mon == 1); + assert(t.tm_mday == 2); + assert(t.tm_year == 91); + } + + { + istringstream iss("19 SKIP_THIS sEpTemBER SKIP_THIS 2005"); + ios_base::iostate err = Bit; + tm t{}; + const string fmt("%d SKIP_THIS %b SKIP_THIS %Y"); + use_facet>(iss.getloc()) + .get(Iter(iss.rdbuf()), Iter(), iss, err, &t, fmt.c_str(), fmt.c_str() + fmt.size()); + assert(t.tm_mon == 8); + assert(t.tm_mday == 19); + assert(t.tm_year == 105); + } + + { + istringstream iss("2011-D-18"); + ios_base::iostate err = Bit; + tm t{}; + const string fmt("%Y-%b-%d"); + use_facet>(iss.getloc()) + .get(Iter(iss.rdbuf()), Iter(), iss, err, &t, fmt.c_str(), fmt.c_str() + fmt.size()); + assert(err == ios_base::failbit); + } + + { + std::tm t = {}; + std::istringstream ss("2018-M-18"); + ss >> std::get_time(&t, "%Y-%b-%d"); + assert(ss.fail()); } } } + +void test_locale_russian(){ + assert(read_date_locale(L"2020-Январь-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + assert(read_date_locale(L"2020-янв-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + assert(read_date_locale(L"2020-янВАрЬ-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + + assert(read_date_locale(L"2020-Февраль-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + assert(read_date_locale(L"2020-фев-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + assert(read_date_locale(L"2020-феВрАль-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + + assert(read_date_locale(L"2020-Март-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + assert(read_date_locale(L"2020-мар-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + assert(read_date_locale(L"2020-МаРт-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + + assert(read_date_locale(L"2020-Апрель-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + assert(read_date_locale(L"2020-апр-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + assert(read_date_locale(L"2020-АпРЕль-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + + assert(read_date_locale(L"2020-Май-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + assert(read_date_locale(L"2020-мАЙ-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + + assert(read_date_locale(L"2020-Июнь-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + assert(read_date_locale(L"2020-июн-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + assert(read_date_locale(L"2020-ИюНЬ-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + + assert(read_date_locale(L"2020-Июль-12", "ru_RU.UTF-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + assert(read_date_locale(L"2020-июл-12", "ru_RU.UTF-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + assert(read_date_locale(L"2020-ИюЛь-12", "ru_RU.UTF-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + + assert(read_date_locale(L"2020-Август-02", "ru_RU.UTF-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + assert(read_date_locale(L"2020-авг-02", "ru_RU.UTF-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + assert(read_date_locale(L"2020-АвгУСт-02", "ru_RU.UTF-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + + assert(read_date_locale(L"2020-Сентябрь-21", "ru_RU.UTF-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + assert(read_date_locale(L"2020-сен-21", "ru_RU.UTF-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + assert(read_date_locale(L"2020-СентяБрь-21", "ru_RU.UTF-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + + assert(read_date_locale(L"2020-Октябрь-01", "ru_RU.UTF-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + assert(read_date_locale(L"2020-окт-01", "ru_RU.UTF-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + assert(read_date_locale(L"2020-ОктяБрь-01", "ru_RU.UTF-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + + assert(read_date_locale(L"2020-Ноябрь-09", "ru_RU.UTF-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + assert(read_date_locale(L"2020-ноя-09", "ru_RU.UTF-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + assert(read_date_locale(L"2020-НояБрь-09", "ru_RU.UTF-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + + assert(read_date_locale(L"2020-Декабрь-31", "ru_RU.UTF-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + assert(read_date_locale(L"2020-дек-31", "ru_RU.UTF-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + assert(read_date_locale(L"2020-ДекаБрь-31", "ru_RU.UTF-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); +} + +void test_locale_german(){ + assert(read_date_locale(L"2020-Januar-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + assert(read_date_locale(L"2020-Jan-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + assert(read_date_locale(L"2020-JanUAr-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + + assert(read_date_locale(L"2020-Februar-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + assert(read_date_locale(L"2020-Feb-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + assert(read_date_locale(L"2020-FebrUar-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + + assert(read_date_locale(L"2020-März-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + assert(read_date_locale(L"2020-mäRZ-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + + assert(read_date_locale(L"2020-April-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + assert(read_date_locale(L"2020-Apr-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + assert(read_date_locale(L"2020-apRiL-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + + assert(read_date_locale(L"2020-Mai-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + assert(read_date_locale(L"2020-mAi-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + + assert(read_date_locale(L"2020-Juni-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + assert(read_date_locale(L"2020-jUNi-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + assert(read_date_locale(L"2020-jUNi-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + + assert(read_date_locale(L"2020-Juli-12", "de_DE.utf-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + assert(read_date_locale(L"2020-JuLi-12", "de_DE.utf-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + assert(read_date_locale(L"2020-jUli-12", "de_DE.utf-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + + assert(read_date_locale(L"2020-August-02", "de_DE.utf-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + assert(read_date_locale(L"2020-Aug-02", "de_DE.utf-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + assert(read_date_locale(L"2020-auGuSt-02", "de_DE.utf-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + + assert(read_date_locale(L"2020-September-21", "de_DE.utf-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + assert(read_date_locale(L"2020-Sep-21", "de_DE.utf-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + assert(read_date_locale(L"2020-sEpTeMber-21", "de_DE.utf-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + + assert(read_date_locale(L"2020-Oktober-01", "de_DE.utf-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + assert(read_date_locale(L"2020-Okt-01", "de_DE.utf-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + assert(read_date_locale(L"2020-oKtoBeR-01", "de_DE.utf-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + + assert(read_date_locale(L"2020-November-09", "de_DE.utf-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + assert(read_date_locale(L"2020-Nov-09", "de_DE.utf-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + assert(read_date_locale(L"2020-noVemBeR-09", "de_DE.utf-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + + assert(read_date_locale(L"2020-Dezember-31", "de_DE.utf-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + assert(read_date_locale(L"2020-Dez-31", "de_DE.utf-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + assert(read_date_locale(L"2020-deZeMbEr-31", "de_DE.utf-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); +} + +void test_locale_chines(){ + assert(read_date_locale(L"2020-一月-05", "chinese") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + assert(read_date_locale(L"2020-二月-15", "chinese") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + assert(read_date_locale(L"2020-三月-25", "chinese") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + assert(read_date_locale(L"2020-四月-05", "chinese") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + assert(read_date_locale(L"2020-五月-15", "chinese") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + assert(read_date_locale(L"2020-六月-25", "chinese") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + assert(read_date_locale(L"2020-七月-12", "chinese") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + assert(read_date_locale(L"2020-八月-02", "chinese") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + assert(read_date_locale(L"2020-九月-21", "chinese") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + assert(read_date_locale(L"2020-十月-01", "chinese") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + assert(read_date_locale(L"2020-十一月-09", "chinese") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + assert(read_date_locale(L"2020-十二月-31", "chinese") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); +} + From e565fdefc35c20d7dae24afdc321f541810fd46e Mon Sep 17 00:00:00 2001 From: Hamid Reza Date: Fri, 14 Aug 2020 06:38:41 +0430 Subject: [PATCH 06/11] Add tests to cover scenarios that discussed on Issue#1126 --- .../std/tests/Dev11_0836436_get_time/test.cpp | 263 +++++++++--------- 1 file changed, 131 insertions(+), 132 deletions(-) diff --git a/tests/std/tests/Dev11_0836436_get_time/test.cpp b/tests/std/tests/Dev11_0836436_get_time/test.cpp index fa2c7d635f0..bd65da8c260 100644 --- a/tests/std/tests/Dev11_0836436_get_time/test.cpp +++ b/tests/std/tests/Dev11_0836436_get_time/test.cpp @@ -33,7 +33,7 @@ tm helper_locale(const wchar_t* const s, const wchar_t* const fmt, const char* _ tm t{}; wstringstream wss(s); - wss.imbue(locale(_loc)); + wss.imbue(locale(_loc)); wss >> get_time(&t, fmt); assert(static_cast(wss)); @@ -118,9 +118,9 @@ int main() { assert(read_hour("12 am") == 0); assert(read_hour("1 AM") == 1); - assert(read_hour("1 am") == 1); - assert(read_hour("1 aM") == 1); - assert(read_hour("1 Am") == 1); + assert(read_hour("1 am") == 1); + assert(read_hour("1 aM") == 1); + assert(read_hour("1 Am") == 1); assert(read_hour("2 AM") == 2); assert(read_hour("2 am") == 2); @@ -133,8 +133,8 @@ int main() { assert(read_hour("1 PM") == 13); assert(read_hour("1 pm") == 13); - assert(read_hour("1 Pm") == 13); - assert(read_hour("1 pM") == 13); + assert(read_hour("1 Pm") == 13); + assert(read_hour("1 pM") == 13); assert(read_hour("2 PM") == 14); assert(read_hour("2 pm") == 14); @@ -152,9 +152,9 @@ int main() { test_640278(); test_990695(); - test_locale_russian(); - test_locale_german(); - test_locale_chines(); + test_locale_russian(); + test_locale_german(); + test_locale_chines(); } typedef istreambuf_iterator Iter; @@ -250,8 +250,8 @@ void test_990695() { assert(t.tm_mday == 31); assert(t.tm_year == 114); } - - { + + { istringstream iss("sep 31 2014"); ios_base::iostate err = Bit; tm t{}; @@ -262,8 +262,8 @@ void test_990695() { assert(t.tm_mday == 31); assert(t.tm_year == 114); } - - { + + { istringstream iss("aUG 14 2020"); ios_base::iostate err = Bit; tm t{}; @@ -274,8 +274,8 @@ void test_990695() { assert(t.tm_mday == 14); assert(t.tm_year == 120); } - - { + + { istringstream iss("feBRuArY 02 1991"); ios_base::iostate err = Bit; tm t{}; @@ -286,8 +286,8 @@ void test_990695() { assert(t.tm_mday == 2); assert(t.tm_year == 91); } - - { + + { istringstream iss("19 SKIP_THIS sEpTemBER SKIP_THIS 2005"); ios_base::iostate err = Bit; tm t{}; @@ -298,8 +298,8 @@ void test_990695() { assert(t.tm_mday == 19); assert(t.tm_year == 105); } - - { + + { istringstream iss("2011-D-18"); ios_base::iostate err = Bit; tm t{}; @@ -308,125 +308,124 @@ void test_990695() { .get(Iter(iss.rdbuf()), Iter(), iss, err, &t, fmt.c_str(), fmt.c_str() + fmt.size()); assert(err == ios_base::failbit); } - - { - std::tm t = {}; - std::istringstream ss("2018-M-18"); - ss >> std::get_time(&t, "%Y-%b-%d"); - assert(ss.fail()); + + { + std::tm t = {}; + std::istringstream ss("2018-M-18"); + ss >> std::get_time(&t, "%Y-%b-%d"); + assert(ss.fail()); } } } -void test_locale_russian(){ - assert(read_date_locale(L"2020-Январь-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert(read_date_locale(L"2020-янв-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert(read_date_locale(L"2020-янВАрЬ-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - - assert(read_date_locale(L"2020-Февраль-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - assert(read_date_locale(L"2020-фев-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - assert(read_date_locale(L"2020-феВрАль-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - - assert(read_date_locale(L"2020-Март-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - assert(read_date_locale(L"2020-мар-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - assert(read_date_locale(L"2020-МаРт-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - - assert(read_date_locale(L"2020-Апрель-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert(read_date_locale(L"2020-апр-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert(read_date_locale(L"2020-АпРЕль-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - - assert(read_date_locale(L"2020-Май-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); - assert(read_date_locale(L"2020-мАЙ-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); - - assert(read_date_locale(L"2020-Июнь-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - assert(read_date_locale(L"2020-июн-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - assert(read_date_locale(L"2020-ИюНЬ-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - - assert(read_date_locale(L"2020-Июль-12", "ru_RU.UTF-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert(read_date_locale(L"2020-июл-12", "ru_RU.UTF-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert(read_date_locale(L"2020-ИюЛь-12", "ru_RU.UTF-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - - assert(read_date_locale(L"2020-Август-02", "ru_RU.UTF-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert(read_date_locale(L"2020-авг-02", "ru_RU.UTF-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert(read_date_locale(L"2020-АвгУСт-02", "ru_RU.UTF-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - - assert(read_date_locale(L"2020-Сентябрь-21", "ru_RU.UTF-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - assert(read_date_locale(L"2020-сен-21", "ru_RU.UTF-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - assert(read_date_locale(L"2020-СентяБрь-21", "ru_RU.UTF-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - - assert(read_date_locale(L"2020-Октябрь-01", "ru_RU.UTF-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - assert(read_date_locale(L"2020-окт-01", "ru_RU.UTF-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - assert(read_date_locale(L"2020-ОктяБрь-01", "ru_RU.UTF-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - - assert(read_date_locale(L"2020-Ноябрь-09", "ru_RU.UTF-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - assert(read_date_locale(L"2020-ноя-09", "ru_RU.UTF-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - assert(read_date_locale(L"2020-НояБрь-09", "ru_RU.UTF-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - - assert(read_date_locale(L"2020-Декабрь-31", "ru_RU.UTF-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); - assert(read_date_locale(L"2020-дек-31", "ru_RU.UTF-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); - assert(read_date_locale(L"2020-ДекаБрь-31", "ru_RU.UTF-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); -} +void test_locale_russian() { + assert(read_date_locale(L"2020-Январь-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + assert(read_date_locale(L"2020-янв-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + assert(read_date_locale(L"2020-янВАрЬ-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + + assert(read_date_locale(L"2020-Февраль-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + assert(read_date_locale(L"2020-фев-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + assert(read_date_locale(L"2020-феВрАль-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + + assert(read_date_locale(L"2020-Март-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + assert(read_date_locale(L"2020-мар-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + assert(read_date_locale(L"2020-МаРт-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + + assert(read_date_locale(L"2020-Апрель-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + assert(read_date_locale(L"2020-апр-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + assert(read_date_locale(L"2020-АпРЕль-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + + assert(read_date_locale(L"2020-Май-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + assert(read_date_locale(L"2020-мАЙ-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + + assert(read_date_locale(L"2020-Июнь-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + assert(read_date_locale(L"2020-июн-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + assert(read_date_locale(L"2020-ИюНЬ-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); -void test_locale_german(){ - assert(read_date_locale(L"2020-Januar-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert(read_date_locale(L"2020-Jan-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert(read_date_locale(L"2020-JanUAr-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - - assert(read_date_locale(L"2020-Februar-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - assert(read_date_locale(L"2020-Feb-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - assert(read_date_locale(L"2020-FebrUar-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - - assert(read_date_locale(L"2020-März-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - assert(read_date_locale(L"2020-mäRZ-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - - assert(read_date_locale(L"2020-April-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert(read_date_locale(L"2020-Apr-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert(read_date_locale(L"2020-apRiL-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - - assert(read_date_locale(L"2020-Mai-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); - assert(read_date_locale(L"2020-mAi-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); - - assert(read_date_locale(L"2020-Juni-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - assert(read_date_locale(L"2020-jUNi-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - assert(read_date_locale(L"2020-jUNi-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - - assert(read_date_locale(L"2020-Juli-12", "de_DE.utf-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert(read_date_locale(L"2020-JuLi-12", "de_DE.utf-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert(read_date_locale(L"2020-jUli-12", "de_DE.utf-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - - assert(read_date_locale(L"2020-August-02", "de_DE.utf-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert(read_date_locale(L"2020-Aug-02", "de_DE.utf-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert(read_date_locale(L"2020-auGuSt-02", "de_DE.utf-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - - assert(read_date_locale(L"2020-September-21", "de_DE.utf-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - assert(read_date_locale(L"2020-Sep-21", "de_DE.utf-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - assert(read_date_locale(L"2020-sEpTeMber-21", "de_DE.utf-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - - assert(read_date_locale(L"2020-Oktober-01", "de_DE.utf-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - assert(read_date_locale(L"2020-Okt-01", "de_DE.utf-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - assert(read_date_locale(L"2020-oKtoBeR-01", "de_DE.utf-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - - assert(read_date_locale(L"2020-November-09", "de_DE.utf-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - assert(read_date_locale(L"2020-Nov-09", "de_DE.utf-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - assert(read_date_locale(L"2020-noVemBeR-09", "de_DE.utf-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - - assert(read_date_locale(L"2020-Dezember-31", "de_DE.utf-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); - assert(read_date_locale(L"2020-Dez-31", "de_DE.utf-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); - assert(read_date_locale(L"2020-deZeMbEr-31", "de_DE.utf-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + assert(read_date_locale(L"2020-Июль-12", "ru_RU.UTF-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + assert(read_date_locale(L"2020-июл-12", "ru_RU.UTF-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + assert(read_date_locale(L"2020-ИюЛь-12", "ru_RU.UTF-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + + assert(read_date_locale(L"2020-Август-02", "ru_RU.UTF-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + assert(read_date_locale(L"2020-авг-02", "ru_RU.UTF-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + assert(read_date_locale(L"2020-АвгУСт-02", "ru_RU.UTF-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + + assert(read_date_locale(L"2020-Сентябрь-21", "ru_RU.UTF-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + assert(read_date_locale(L"2020-сен-21", "ru_RU.UTF-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + assert(read_date_locale(L"2020-СентяБрь-21", "ru_RU.UTF-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + + assert(read_date_locale(L"2020-Октябрь-01", "ru_RU.UTF-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + assert(read_date_locale(L"2020-окт-01", "ru_RU.UTF-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + assert(read_date_locale(L"2020-ОктяБрь-01", "ru_RU.UTF-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + + assert(read_date_locale(L"2020-Ноябрь-09", "ru_RU.UTF-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + assert(read_date_locale(L"2020-ноя-09", "ru_RU.UTF-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + assert(read_date_locale(L"2020-НояБрь-09", "ru_RU.UTF-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + + assert(read_date_locale(L"2020-Декабрь-31", "ru_RU.UTF-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + assert(read_date_locale(L"2020-дек-31", "ru_RU.UTF-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + assert(read_date_locale(L"2020-ДекаБрь-31", "ru_RU.UTF-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); } -void test_locale_chines(){ - assert(read_date_locale(L"2020-一月-05", "chinese") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert(read_date_locale(L"2020-二月-15", "chinese") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - assert(read_date_locale(L"2020-三月-25", "chinese") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - assert(read_date_locale(L"2020-四月-05", "chinese") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert(read_date_locale(L"2020-五月-15", "chinese") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); - assert(read_date_locale(L"2020-六月-25", "chinese") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - assert(read_date_locale(L"2020-七月-12", "chinese") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert(read_date_locale(L"2020-八月-02", "chinese") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert(read_date_locale(L"2020-九月-21", "chinese") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - assert(read_date_locale(L"2020-十月-01", "chinese") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - assert(read_date_locale(L"2020-十一月-09", "chinese") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - assert(read_date_locale(L"2020-十二月-31", "chinese") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); +void test_locale_german() { + assert(read_date_locale(L"2020-Januar-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + assert(read_date_locale(L"2020-Jan-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + assert(read_date_locale(L"2020-JanUAr-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + + assert(read_date_locale(L"2020-Februar-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + assert(read_date_locale(L"2020-Feb-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + assert(read_date_locale(L"2020-FebrUar-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + + assert(read_date_locale(L"2020-März-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + assert(read_date_locale(L"2020-mäRZ-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + + assert(read_date_locale(L"2020-April-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + assert(read_date_locale(L"2020-Apr-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + assert(read_date_locale(L"2020-apRiL-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + + assert(read_date_locale(L"2020-Mai-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + assert(read_date_locale(L"2020-mAi-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + + assert(read_date_locale(L"2020-Juni-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + assert(read_date_locale(L"2020-jUNi-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + assert(read_date_locale(L"2020-jUNi-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + + assert(read_date_locale(L"2020-Juli-12", "de_DE.utf-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + assert(read_date_locale(L"2020-JuLi-12", "de_DE.utf-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + assert(read_date_locale(L"2020-jUli-12", "de_DE.utf-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + + assert(read_date_locale(L"2020-August-02", "de_DE.utf-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + assert(read_date_locale(L"2020-Aug-02", "de_DE.utf-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + assert(read_date_locale(L"2020-auGuSt-02", "de_DE.utf-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + + assert(read_date_locale(L"2020-September-21", "de_DE.utf-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + assert(read_date_locale(L"2020-Sep-21", "de_DE.utf-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + assert(read_date_locale(L"2020-sEpTeMber-21", "de_DE.utf-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + + assert(read_date_locale(L"2020-Oktober-01", "de_DE.utf-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + assert(read_date_locale(L"2020-Okt-01", "de_DE.utf-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + assert(read_date_locale(L"2020-oKtoBeR-01", "de_DE.utf-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + + assert(read_date_locale(L"2020-November-09", "de_DE.utf-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + assert(read_date_locale(L"2020-Nov-09", "de_DE.utf-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + assert(read_date_locale(L"2020-noVemBeR-09", "de_DE.utf-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + + assert(read_date_locale(L"2020-Dezember-31", "de_DE.utf-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + assert(read_date_locale(L"2020-Dez-31", "de_DE.utf-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + assert(read_date_locale(L"2020-deZeMbEr-31", "de_DE.utf-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); } +void test_locale_chines() { + assert(read_date_locale(L"2020-一月-05", "chinese") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + assert(read_date_locale(L"2020-二月-15", "chinese") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + assert(read_date_locale(L"2020-三月-25", "chinese") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + assert(read_date_locale(L"2020-四月-05", "chinese") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + assert(read_date_locale(L"2020-五月-15", "chinese") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + assert(read_date_locale(L"2020-六月-25", "chinese") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + assert(read_date_locale(L"2020-七月-12", "chinese") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + assert(read_date_locale(L"2020-八月-02", "chinese") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + assert(read_date_locale(L"2020-九月-21", "chinese") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + assert(read_date_locale(L"2020-十月-01", "chinese") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + assert(read_date_locale(L"2020-十一月-09", "chinese") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + assert(read_date_locale(L"2020-十二月-31", "chinese") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); +} From 52b7ef36a7b0df0cbeb66c8d4d78dabc422f2b82 Mon Sep 17 00:00:00 2001 From: Hamid Reza Date: Fri, 14 Aug 2020 17:19:45 +0430 Subject: [PATCH 07/11] change UTF-16 characters to their Hex representation --- .../std/tests/Dev11_0836436_get_time/test.cpp | 305 ++++++++++++------ 1 file changed, 210 insertions(+), 95 deletions(-) diff --git a/tests/std/tests/Dev11_0836436_get_time/test.cpp b/tests/std/tests/Dev11_0836436_get_time/test.cpp index bd65da8c260..b2718b9923e 100644 --- a/tests/std/tests/Dev11_0836436_get_time/test.cpp +++ b/tests/std/tests/Dev11_0836436_get_time/test.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include @@ -300,6 +300,7 @@ void test_990695() { } { + // This case should fail istringstream iss("2011-D-18"); ios_base::iostate err = Bit; tm t{}; @@ -319,113 +320,227 @@ void test_990695() { } void test_locale_russian() { - assert(read_date_locale(L"2020-Январь-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert(read_date_locale(L"2020-янв-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert(read_date_locale(L"2020-янВАрЬ-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - - assert(read_date_locale(L"2020-Февраль-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - assert(read_date_locale(L"2020-фев-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - assert(read_date_locale(L"2020-феВрАль-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - - assert(read_date_locale(L"2020-Март-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - assert(read_date_locale(L"2020-мар-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - assert(read_date_locale(L"2020-МаРт-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - - assert(read_date_locale(L"2020-Апрель-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert(read_date_locale(L"2020-апр-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert(read_date_locale(L"2020-АпРЕль-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - - assert(read_date_locale(L"2020-Май-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); - assert(read_date_locale(L"2020-мАЙ-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); - - assert(read_date_locale(L"2020-Июнь-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - assert(read_date_locale(L"2020-июн-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - assert(read_date_locale(L"2020-ИюНЬ-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - - assert(read_date_locale(L"2020-Июль-12", "ru_RU.UTF-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert(read_date_locale(L"2020-июл-12", "ru_RU.UTF-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert(read_date_locale(L"2020-ИюЛь-12", "ru_RU.UTF-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - - assert(read_date_locale(L"2020-Август-02", "ru_RU.UTF-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert(read_date_locale(L"2020-авг-02", "ru_RU.UTF-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert(read_date_locale(L"2020-АвгУСт-02", "ru_RU.UTF-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - - assert(read_date_locale(L"2020-Сентябрь-21", "ru_RU.UTF-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - assert(read_date_locale(L"2020-сен-21", "ru_RU.UTF-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - assert(read_date_locale(L"2020-СентяБрь-21", "ru_RU.UTF-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - - assert(read_date_locale(L"2020-Октябрь-01", "ru_RU.UTF-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - assert(read_date_locale(L"2020-окт-01", "ru_RU.UTF-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - assert(read_date_locale(L"2020-ОктяБрь-01", "ru_RU.UTF-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - - assert(read_date_locale(L"2020-Ноябрь-09", "ru_RU.UTF-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - assert(read_date_locale(L"2020-ноя-09", "ru_RU.UTF-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - assert(read_date_locale(L"2020-НояБрь-09", "ru_RU.UTF-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - - assert(read_date_locale(L"2020-Декабрь-31", "ru_RU.UTF-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); - assert(read_date_locale(L"2020-дек-31", "ru_RU.UTF-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); - assert(read_date_locale(L"2020-ДекаБрь-31", "ru_RU.UTF-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + // Russian January in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x042f\x043d\x0432\x0430\x0440\x044c-05", "ru_RU.UTF-8") + == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + assert( + read_date_locale(L"2020-\x044f\x043d\x0432-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + assert(read_date_locale(L"2020-\x044f\x043d\x0412\x0410\x0440\x042c-05", "ru_RU.UTF-8") + == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + + // Russian February in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x0424\x0435\x0432\x0440\x0430\x043b\x044c-15", "ru_RU.UTF-8") + == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + assert( + read_date_locale(L"2020-\x0444\x0435\x0432-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + assert(read_date_locale(L"2020-\x0444\x0435\x0412\x0440\x0410\x043b\x044c-15", "ru_RU.UTF-8") + == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + + // Russian March in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x041c\x0430\x0440\x0442-25", "ru_RU.UTF-8") + == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + assert( + read_date_locale(L"2020-\x043c\x0430\x0440-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + assert(read_date_locale(L"2020-\x041c\x0430\x0420\x0442-25", "ru_RU.UTF-8") + == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + + // Russian April in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x0410\x043f\x0440\x0435\x043b\x044c-05", "ru_RU.UTF-8") + == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + assert( + read_date_locale(L"2020-\x0430\x043f\x0440-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + assert(read_date_locale(L"2020-\x0410\x043f\x0420\x0415\x043b\x044c-05", "ru_RU.UTF-8") + == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + + // Russian May in different cases (short, long, mixed cases) + assert( + read_date_locale(L"2020-\x041c\x0430\x0439-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + assert( + read_date_locale(L"2020-\x043c\x0410\x0419-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + + // Russian June in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x0418\x044e\x043d\x044c-25", "ru_RU.UTF-8") + == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + assert( + read_date_locale(L"2020-\x0438\x044e\x043d-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + assert(read_date_locale(L"2020-\x0418\x044e\x041d\x042c-25", "ru_RU.UTF-8") + == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + + // Russian July in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x0418\x044e\x043b\x044c-12", "ru_RU.UTF-8") + == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + assert( + read_date_locale(L"2020-\x0438\x044e\x043b-12", "ru_RU.UTF-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + assert(read_date_locale(L"2020-\x0418\x044e\x041b\x044c-12", "ru_RU.UTF-8") + == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + + // Russian Auguest in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x0410\x0432\x0433\x0443\x0441\x0442-02", "ru_RU.UTF-8") + == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + assert( + read_date_locale(L"2020-\x0430\x0432\x0433-02", "ru_RU.UTF-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + assert(read_date_locale(L"2020-\x0410\x0432\x0433\x0423\x0421\x0442-02", "ru_RU.UTF-8") + == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + + // Russian September in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x0421\x0435\x043d\x0442\x044f\x0431\x0440\x044c-21", "ru_RU.UTF-8") + == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + assert( + read_date_locale(L"2020-\x0441\x0435\x043d-21", "ru_RU.UTF-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + assert(read_date_locale(L"2020-\x0421\x0435\x043d\x0442\x044f\x0411\x0440\x044c-21", "ru_RU.UTF-8") + == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + + // Russian October in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x041e\x043a\x0442\x044f\x0431\x0440\x044c-01", "ru_RU.UTF-8") + == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + assert( + read_date_locale(L"2020-\x043e\x043a\x0442-01", "ru_RU.UTF-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + assert(read_date_locale(L"2020-\x041e\x043a\x0442\x044f\x0411\x0440\x044c-01", "ru_RU.UTF-8") + == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + + // Russian November in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x041d\x043e\x044f\x0431\x0440\x044c-09", "ru_RU.UTF-8") + == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + assert( + read_date_locale(L"2020-\x043d\x043e\x044f-09", "ru_RU.UTF-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + assert(read_date_locale(L"2020-\x041d\x043e\x044f\x0411\x0440\x044c-09", "ru_RU.UTF-8") + == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + + // Russian December in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x0414\x0435\x043a\x0430\x0431\x0440\x044c-31", "ru_RU.UTF-8") + == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + assert( + read_date_locale(L"2020-\x0434\x0435\x043a-31", "ru_RU.UTF-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + assert(read_date_locale(L"2020-\x0414\x0435\x043a\x0430\x0411\x0440\x044c-31", "ru_RU.UTF-8") + == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); } void test_locale_german() { - assert(read_date_locale(L"2020-Januar-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert(read_date_locale(L"2020-Jan-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert(read_date_locale(L"2020-JanUAr-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + // German January in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x004a\x0061\x006e\x0075\x0061\x0072-05", "de_DE.utf-8") + == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + assert( + read_date_locale(L"2020-\x004a\x0061\x006e-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + assert(read_date_locale(L"2020-\x004a\x0061\x006e\x0055\x0041\x0072-05", "de_DE.utf-8") + == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); + + // German February in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x0046\x0065\x0062\x0072\x0075\x0061\x0072-15", "de_DE.utf-8") + == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + assert( + read_date_locale(L"2020-\x0046\x0065\x0062-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + assert(read_date_locale(L"2020-\x0046\x0065\x0062\x0072\x0055\x0061\x0072-15", "de_DE.utf-8") + == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + + // German March in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x004d\x00e4\x0072\x007a-25", "de_DE.utf-8") + == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + assert(read_date_locale(L"2020-\x006d\x00e4\x0052\x005a-25", "de_DE.utf-8") + == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + + // German April in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x0041\x0070\x0072\x0069\x006c-05", "de_DE.utf-8") + == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + assert( + read_date_locale(L"2020-\x0041\x0070\x0072-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + assert(read_date_locale(L"2020-\x0061\x0070\x0052\x0069\x004c-05", "de_DE.utf-8") + == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + + // German May in different cases (short, long, mixed cases) + assert( + read_date_locale(L"2020-\x004d\x0061\x0069-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + assert( + read_date_locale(L"2020-\x006d\x0041\x0069-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + + // German June in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x004a\x0075\x006e\x0069-25", "de_DE.utf-8") + == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + assert(read_date_locale(L"2020-\x006a\x0055\x004e\x0069-25", "de_DE.utf-8") + == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + + // German July in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x004a\x0075\x006c\x0069-12", "de_DE.utf-8") + == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + assert(read_date_locale(L"2020-\x004a\x0075\x004c\x0069-12", "de_DE.utf-8") + == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + assert(read_date_locale(L"2020-\x006a\x0055\x006c\x0069-12", "de_DE.utf-8") + == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + + // German Auguest in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x0041\x0075\x0067\x0075\x0073\x0074-02", "de_DE.utf-8") + == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + assert( + read_date_locale(L"2020-\x0041\x0075\x0067-02", "de_DE.utf-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + assert(read_date_locale(L"2020-\x0061\x0075\x0047\x0075\x0053\x0074-02", "de_DE.utf-8") + == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + + // German September in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x0053\x0065\x0070\x0074\x0065\x006d\x0062\x0065\x0072-21", "de_DE.utf-8") + == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + assert( + read_date_locale(L"2020-\x0053\x0065\x0070-21", "de_DE.utf-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + assert(read_date_locale(L"2020-\x0073\x0045\x0070\x0054\x0065\x004d\x0062\x0065\x0072-21", "de_DE.utf-8") + == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + + // German October in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x004f\x006b\x0074\x006f\x0062\x0065\x0072-01", "de_DE.utf-8") + == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + assert( + read_date_locale(L"2020-\x004f\x006b\x0074-01", "de_DE.utf-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + assert(read_date_locale(L"2020-\x006f\x004b\x0074\x006f\x0042\x0065\x0052-01", "de_DE.utf-8") + == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + + // German November in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x004e\x006f\x0076\x0065\x006d\x0062\x0065\x0072-09", "de_DE.utf-8") + == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + assert( + read_date_locale(L"2020-\x004e\x006f\x0076-09", "de_DE.utf-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + assert(read_date_locale(L"2020-\x006e\x006f\x0056\x0065\x006d\x0042\x0065\x0052-09", "de_DE.utf-8") + == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + + // German December in different cases (short, long, mixed cases) + assert(read_date_locale(L"2020-\x0044\x0065\x007a\x0065\x006d\x0062\x0065\x0072-31", "de_DE.utf-8") + == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + assert( + read_date_locale(L"2020-\x0044\x0065\x007a-31", "de_DE.utf-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + assert(read_date_locale(L"2020-\x0064\x0065\x005a\x0065\x004d\x0062\x0045\x0072-31", "de_DE.utf-8") + == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); +} - assert(read_date_locale(L"2020-Februar-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - assert(read_date_locale(L"2020-Feb-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - assert(read_date_locale(L"2020-FebrUar-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); +void test_locale_chines() { + // January in Chines + assert(read_date_locale(L"2020-\x4e00\x6708-05", "chinese") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert(read_date_locale(L"2020-März-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - assert(read_date_locale(L"2020-mäRZ-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + // February in Chines + assert(read_date_locale(L"2020-\x4e8c\x6708-15", "chinese") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - assert(read_date_locale(L"2020-April-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert(read_date_locale(L"2020-Apr-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert(read_date_locale(L"2020-apRiL-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + // March in Chines + assert(read_date_locale(L"2020-\x4e09\x6708-25", "chinese") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - assert(read_date_locale(L"2020-Mai-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); - assert(read_date_locale(L"2020-mAi-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + // April in Chines + assert(read_date_locale(L"2020-\x56db\x6708-05", "chinese") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert(read_date_locale(L"2020-Juni-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - assert(read_date_locale(L"2020-jUNi-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - assert(read_date_locale(L"2020-jUNi-25", "de_DE.utf-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + // May in Chines + assert(read_date_locale(L"2020-\x4e94\x6708-15", "chinese") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); - assert(read_date_locale(L"2020-Juli-12", "de_DE.utf-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert(read_date_locale(L"2020-JuLi-12", "de_DE.utf-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert(read_date_locale(L"2020-jUli-12", "de_DE.utf-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + // June in Chines + assert(read_date_locale(L"2020-\x516d\x6708-25", "chinese") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - assert(read_date_locale(L"2020-August-02", "de_DE.utf-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert(read_date_locale(L"2020-Aug-02", "de_DE.utf-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert(read_date_locale(L"2020-auGuSt-02", "de_DE.utf-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + // July in Chines + assert(read_date_locale(L"2020-\x4e03\x6708-12", "chinese") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert(read_date_locale(L"2020-September-21", "de_DE.utf-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - assert(read_date_locale(L"2020-Sep-21", "de_DE.utf-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - assert(read_date_locale(L"2020-sEpTeMber-21", "de_DE.utf-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + // Auguest in Chines + assert(read_date_locale(L"2020-\x516b\x6708-02", "chinese") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert(read_date_locale(L"2020-Oktober-01", "de_DE.utf-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - assert(read_date_locale(L"2020-Okt-01", "de_DE.utf-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - assert(read_date_locale(L"2020-oKtoBeR-01", "de_DE.utf-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + // September in Chines + assert(read_date_locale(L"2020-\x4e5d\x6708-21", "chinese") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - assert(read_date_locale(L"2020-November-09", "de_DE.utf-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - assert(read_date_locale(L"2020-Nov-09", "de_DE.utf-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - assert(read_date_locale(L"2020-noVemBeR-09", "de_DE.utf-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + // October in Chines + assert(read_date_locale(L"2020-\x5341\x6708-01", "chinese") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - assert(read_date_locale(L"2020-Dezember-31", "de_DE.utf-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); - assert(read_date_locale(L"2020-Dez-31", "de_DE.utf-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); - assert(read_date_locale(L"2020-deZeMbEr-31", "de_DE.utf-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); -} + // November in Chines + assert(read_date_locale(L"2020-\x5341\x4e00\x6708-09", "chinese") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); -void test_locale_chines() { - assert(read_date_locale(L"2020-一月-05", "chinese") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert(read_date_locale(L"2020-二月-15", "chinese") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - assert(read_date_locale(L"2020-三月-25", "chinese") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - assert(read_date_locale(L"2020-四月-05", "chinese") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert(read_date_locale(L"2020-五月-15", "chinese") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); - assert(read_date_locale(L"2020-六月-25", "chinese") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - assert(read_date_locale(L"2020-七月-12", "chinese") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert(read_date_locale(L"2020-八月-02", "chinese") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert(read_date_locale(L"2020-九月-21", "chinese") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - assert(read_date_locale(L"2020-十月-01", "chinese") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - assert(read_date_locale(L"2020-十一月-09", "chinese") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - assert(read_date_locale(L"2020-十二月-31", "chinese") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + // December in Chines + assert(read_date_locale(L"2020-\x5341\x4e8c\x6708-31", "chinese") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); } From 234a9d238aff4666354645b8c67e1a51ff46d77f Mon Sep 17 00:00:00 2001 From: Hamid Reza Arzaghi Date: Tue, 18 Aug 2020 22:07:02 +0430 Subject: [PATCH 08/11] Improve test cases --- .../std/tests/Dev11_0836436_get_time/test.cpp | 368 +++++++++--------- 1 file changed, 180 insertions(+), 188 deletions(-) diff --git a/tests/std/tests/Dev11_0836436_get_time/test.cpp b/tests/std/tests/Dev11_0836436_get_time/test.cpp index b2718b9923e..d257b813bbc 100644 --- a/tests/std/tests/Dev11_0836436_get_time/test.cpp +++ b/tests/std/tests/Dev11_0836436_get_time/test.cpp @@ -111,7 +111,7 @@ void test_640278(); void test_990695(); void test_locale_russian(); void test_locale_german(); -void test_locale_chines(); +void test_locale_chinese(); int main() { assert(read_hour("12 AM") == 0); @@ -154,7 +154,7 @@ int main() { test_990695(); test_locale_russian(); test_locale_german(); - test_locale_chines(); + test_locale_chinese(); } typedef istreambuf_iterator Iter; @@ -311,236 +311,228 @@ void test_990695() { } { - std::tm t = {}; - std::istringstream ss("2018-M-18"); - ss >> std::get_time(&t, "%Y-%b-%d"); + // This case should fail + istringstream ss("2018-M-18"); + tm t = {}; + const string fmt("%Y-%b-%d"); + ss >> get_time(&t, fmt.c_str()); assert(ss.fail()); } } } void test_locale_russian() { - // Russian January in different cases (short, long, mixed cases) - assert(read_date_locale(L"2020-\x042f\x043d\x0432\x0430\x0440\x044c-05", "ru_RU.UTF-8") - == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert( - read_date_locale(L"2020-\x044f\x043d\x0432-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert(read_date_locale(L"2020-\x044f\x043d\x0412\x0410\x0440\x042c-05", "ru_RU.UTF-8") - == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - - // Russian February in different cases (short, long, mixed cases) + // Russian January in different cases (expanded, abbreviated, mixed cases) + assert(read_date_locale(L"2020-\x042f\x043d\x0432\x0430\x0440\x044c-05", "ru_RU.UTF-8") == make_tuple(5, 0, 120)); + assert(read_date_locale(L"2020-\x044f\x043d\x0432-05", "ru_RU.UTF-8") == make_tuple(5, 0, 120)); + assert(read_date_locale(L"2020-\x044f\x043d\x0412\x0410\x0440\x042c-05", "ru_RU.UTF-8") == make_tuple(5, 0, 120)); + assert(read_date_locale(L"2020-\x042f\x041d\x0412-05", "ru_RU.UTF-8") == make_tuple(5, 0, 120)); + + // Russian February in different cases (expanded, abbreviated, mixed cases) assert(read_date_locale(L"2020-\x0424\x0435\x0432\x0440\x0430\x043b\x044c-15", "ru_RU.UTF-8") - == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - assert( - read_date_locale(L"2020-\x0444\x0435\x0432-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + == make_tuple(15, 1, 120)); + assert(read_date_locale(L"2020-\x0444\x0435\x0432-15", "ru_RU.UTF-8") == make_tuple(15, 1, 120)); assert(read_date_locale(L"2020-\x0444\x0435\x0412\x0440\x0410\x043b\x044c-15", "ru_RU.UTF-8") - == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - - // Russian March in different cases (short, long, mixed cases) - assert(read_date_locale(L"2020-\x041c\x0430\x0440\x0442-25", "ru_RU.UTF-8") - == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - assert( - read_date_locale(L"2020-\x043c\x0430\x0440-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - assert(read_date_locale(L"2020-\x041c\x0430\x0420\x0442-25", "ru_RU.UTF-8") - == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - - // Russian April in different cases (short, long, mixed cases) - assert(read_date_locale(L"2020-\x0410\x043f\x0440\x0435\x043b\x044c-05", "ru_RU.UTF-8") - == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert( - read_date_locale(L"2020-\x0430\x043f\x0440-05", "ru_RU.UTF-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert(read_date_locale(L"2020-\x0410\x043f\x0420\x0415\x043b\x044c-05", "ru_RU.UTF-8") - == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - - // Russian May in different cases (short, long, mixed cases) - assert( - read_date_locale(L"2020-\x041c\x0430\x0439-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); - assert( - read_date_locale(L"2020-\x043c\x0410\x0419-15", "ru_RU.UTF-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); - - // Russian June in different cases (short, long, mixed cases) - assert(read_date_locale(L"2020-\x0418\x044e\x043d\x044c-25", "ru_RU.UTF-8") - == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - assert( - read_date_locale(L"2020-\x0438\x044e\x043d-25", "ru_RU.UTF-8") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - assert(read_date_locale(L"2020-\x0418\x044e\x041d\x042c-25", "ru_RU.UTF-8") - == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - - // Russian July in different cases (short, long, mixed cases) - assert(read_date_locale(L"2020-\x0418\x044e\x043b\x044c-12", "ru_RU.UTF-8") - == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert( - read_date_locale(L"2020-\x0438\x044e\x043b-12", "ru_RU.UTF-8") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert(read_date_locale(L"2020-\x0418\x044e\x041b\x044c-12", "ru_RU.UTF-8") - == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - - // Russian Auguest in different cases (short, long, mixed cases) - assert(read_date_locale(L"2020-\x0410\x0432\x0433\x0443\x0441\x0442-02", "ru_RU.UTF-8") - == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert( - read_date_locale(L"2020-\x0430\x0432\x0433-02", "ru_RU.UTF-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert(read_date_locale(L"2020-\x0410\x0432\x0433\x0423\x0421\x0442-02", "ru_RU.UTF-8") - == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - - // Russian September in different cases (short, long, mixed cases) + == make_tuple(15, 1, 120)); + assert(read_date_locale(L"2020-\x0424\x0435\x0412-15", "ru_RU.UTF-8") == make_tuple(15, 1, 120)); + + // Russian March in different cases (expanded, abbreviated, mixed cases) + assert(read_date_locale(L"2020-\x041c\x0430\x0440\x0442-25", "ru_RU.UTF-8") == make_tuple(25, 2, 120)); + assert(read_date_locale(L"2020-\x043c\x0430\x0440-25", "ru_RU.UTF-8") == make_tuple(25, 2, 120)); + assert(read_date_locale(L"2020-\x041c\x0430\x0420\x0442-25", "ru_RU.UTF-8") == make_tuple(25, 2, 120)); + assert(read_date_locale(L"2020-\x041c\x0430\x0420-25", "ru_RU.UTF-8") == make_tuple(25, 2, 120)); + + // Russian April in different cases (expanded, abbreviated, mixed cases) + assert(read_date_locale(L"2020-\x0410\x043f\x0440\x0435\x043b\x044c-05", "ru_RU.UTF-8") == make_tuple(5, 3, 120)); + assert(read_date_locale(L"2020-\x0430\x043f\x0440-05", "ru_RU.UTF-8") == make_tuple(5, 3, 120)); + assert(read_date_locale(L"2020-\x0410\x043f\x0420\x0415\x043b\x044c-05", "ru_RU.UTF-8") == make_tuple(5, 3, 120)); + assert(read_date_locale(L"2020-\x0430\x041f\x0420-05", "ru_RU.UTF-8") == make_tuple(5, 3, 120)); + + // Russian May in different cases (expanded, mixed cases) + // Expanded and abbreviated versions are identical + assert(read_date_locale(L"2020-\x041c\x0430\x0439-15", "ru_RU.UTF-8") == make_tuple(15, 4, 120)); + assert(read_date_locale(L"2020-\x043c\x0410\x0419-15", "ru_RU.UTF-8") == make_tuple(15, 4, 120)); + + // Russian June in different cases (expanded, abbreviated, mixed cases) + assert(read_date_locale(L"2020-\x0418\x044e\x043d\x044c-25", "ru_RU.UTF-8") == make_tuple(25, 5, 120)); + assert(read_date_locale(L"2020-\x0438\x044e\x043d-25", "ru_RU.UTF-8") == make_tuple(25, 5, 120)); + assert(read_date_locale(L"2020-\x0418\x044e\x041d\x042c-25", "ru_RU.UTF-8") == make_tuple(25, 5, 120)); + assert(read_date_locale(L"2020-\x0438\x042e\x041d-25", "ru_RU.UTF-8") == make_tuple(25, 5, 120)); + + // Russian July in different cases (expanded, abbreviated, mixed cases) + assert(read_date_locale(L"2020-\x0418\x044e\x043b\x044c-12", "ru_RU.UTF-8") == make_tuple(12, 6, 120)); + assert(read_date_locale(L"2020-\x0438\x044e\x043b-12", "ru_RU.UTF-8") == make_tuple(12, 6, 120)); + assert(read_date_locale(L"2020-\x0418\x044e\x041b\x044c-12", "ru_RU.UTF-8") == make_tuple(12, 6, 120)); + assert(read_date_locale(L"2020-\x0418\x044e\x041b-12", "ru_RU.UTF-8") == make_tuple(12, 6, 120)); + + // Russian August in different cases (expanded, abbreviated, mixed cases) + assert(read_date_locale(L"2020-\x0410\x0432\x0433\x0443\x0441\x0442-02", "ru_RU.UTF-8") == make_tuple(2, 7, 120)); + assert(read_date_locale(L"2020-\x0430\x0432\x0433-02", "ru_RU.UTF-8") == make_tuple(2, 7, 120)); + assert(read_date_locale(L"2020-\x0410\x0432\x0433\x0423\x0421\x0442-02", "ru_RU.UTF-8") == make_tuple(2, 7, 120)); + assert(read_date_locale(L"2020-\x0430\x0412\x0413-02", "ru_RU.UTF-8") == make_tuple(2, 7, 120)); + + // Russian September in different cases (expanded, abbreviated, mixed cases) assert(read_date_locale(L"2020-\x0421\x0435\x043d\x0442\x044f\x0431\x0440\x044c-21", "ru_RU.UTF-8") - == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - assert( - read_date_locale(L"2020-\x0441\x0435\x043d-21", "ru_RU.UTF-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + == make_tuple(21, 8, 120)); + assert(read_date_locale(L"2020-\x0441\x0435\x043d-21", "ru_RU.UTF-8") == make_tuple(21, 8, 120)); assert(read_date_locale(L"2020-\x0421\x0435\x043d\x0442\x044f\x0411\x0440\x044c-21", "ru_RU.UTF-8") - == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + == make_tuple(21, 8, 120)); + assert(read_date_locale(L"2020-\x0441\x0415\x041d-21", "ru_RU.UTF-8") == make_tuple(21, 8, 120)); - // Russian October in different cases (short, long, mixed cases) + // Russian October in different cases (expanded, abbreviated, mixed cases) assert(read_date_locale(L"2020-\x041e\x043a\x0442\x044f\x0431\x0440\x044c-01", "ru_RU.UTF-8") - == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - assert( - read_date_locale(L"2020-\x043e\x043a\x0442-01", "ru_RU.UTF-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + == make_tuple(1, 9, 120)); + assert(read_date_locale(L"2020-\x043e\x043a\x0442-01", "ru_RU.UTF-8") == make_tuple(1, 9, 120)); assert(read_date_locale(L"2020-\x041e\x043a\x0442\x044f\x0411\x0440\x044c-01", "ru_RU.UTF-8") - == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + == make_tuple(1, 9, 120)); + assert(read_date_locale(L"2020-\x043e\x041a\x0442-01", "ru_RU.UTF-8") == make_tuple(1, 9, 120)); - // Russian November in different cases (short, long, mixed cases) - assert(read_date_locale(L"2020-\x041d\x043e\x044f\x0431\x0440\x044c-09", "ru_RU.UTF-8") - == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - assert( - read_date_locale(L"2020-\x043d\x043e\x044f-09", "ru_RU.UTF-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - assert(read_date_locale(L"2020-\x041d\x043e\x044f\x0411\x0440\x044c-09", "ru_RU.UTF-8") - == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + // Russian November in different cases (expanded, abbreviated, mixed cases) + assert(read_date_locale(L"2020-\x041d\x043e\x044f\x0431\x0440\x044c-09", "ru_RU.UTF-8") == make_tuple(9, 10, 120)); + assert(read_date_locale(L"2020-\x043d\x043e\x044f-09", "ru_RU.UTF-8") == make_tuple(9, 10, 120)); + assert(read_date_locale(L"2020-\x041d\x043e\x044f\x0411\x0440\x044c-09", "ru_RU.UTF-8") == make_tuple(9, 10, 120)); + assert(read_date_locale(L"2020-\x043d\x041e\x042f-09", "ru_RU.UTF-8") == make_tuple(9, 10, 120)); - // Russian December in different cases (short, long, mixed cases) + // Russian December in different cases (expanded, abbreviated, mixed cases) assert(read_date_locale(L"2020-\x0414\x0435\x043a\x0430\x0431\x0440\x044c-31", "ru_RU.UTF-8") - == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); - assert( - read_date_locale(L"2020-\x0434\x0435\x043a-31", "ru_RU.UTF-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + == make_tuple(31, 11, 120)); + assert(read_date_locale(L"2020-\x0434\x0435\x043a-31", "ru_RU.UTF-8") == make_tuple(31, 11, 120)); assert(read_date_locale(L"2020-\x0414\x0435\x043a\x0430\x0411\x0440\x044c-31", "ru_RU.UTF-8") - == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + == make_tuple(31, 11, 120)); + assert(read_date_locale(L"2020-\x0434\x0415\x043a-31", "ru_RU.UTF-8") == make_tuple(31, 11, 120)); } void test_locale_german() { - // German January in different cases (short, long, mixed cases) - assert(read_date_locale(L"2020-\x004a\x0061\x006e\x0075\x0061\x0072-05", "de_DE.utf-8") - == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert( - read_date_locale(L"2020-\x004a\x0061\x006e-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - assert(read_date_locale(L"2020-\x004a\x0061\x006e\x0055\x0041\x0072-05", "de_DE.utf-8") - == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); - - // German February in different cases (short, long, mixed cases) + // German January in different cases (expanded, abbreviated, mixed cases) + assert(read_date_locale(L"2020-\x004a\x0061\x006e\x0075\x0061\x0072-05", "de_DE.utf-8") == make_tuple(5, 0, 120)); + assert(read_date_locale(L"2020-\x004a\x0061\x006e-05", "de_DE.utf-8") == make_tuple(5, 0, 120)); + assert(read_date_locale(L"2020-\x004a\x0061\x006e\x0055\x0041\x0072-05", "de_DE.utf-8") == make_tuple(5, 0, 120)); + assert(read_date_locale(L"2020-\x006a\x0041\x004e-05", "de_DE.utf-8") == make_tuple(5, 0, 120)); + + // German February in different cases (expanded, abbreviated, mixed cases) assert(read_date_locale(L"2020-\x0046\x0065\x0062\x0072\x0075\x0061\x0072-15", "de_DE.utf-8") - == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - assert( - read_date_locale(L"2020-\x0046\x0065\x0062-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + == make_tuple(15, 1, 120)); + assert(read_date_locale(L"2020-\x0046\x0065\x0062-15", "de_DE.utf-8") == make_tuple(15, 1, 120)); assert(read_date_locale(L"2020-\x0046\x0065\x0062\x0072\x0055\x0061\x0072-15", "de_DE.utf-8") - == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); - - // German March in different cases (short, long, mixed cases) - assert(read_date_locale(L"2020-\x004d\x00e4\x0072\x007a-25", "de_DE.utf-8") - == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - assert(read_date_locale(L"2020-\x006d\x00e4\x0052\x005a-25", "de_DE.utf-8") - == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); - - // German April in different cases (short, long, mixed cases) - assert(read_date_locale(L"2020-\x0041\x0070\x0072\x0069\x006c-05", "de_DE.utf-8") - == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert( - read_date_locale(L"2020-\x0041\x0070\x0072-05", "de_DE.utf-8") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - assert(read_date_locale(L"2020-\x0061\x0070\x0052\x0069\x004c-05", "de_DE.utf-8") - == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); - - // German May in different cases (short, long, mixed cases) - assert( - read_date_locale(L"2020-\x004d\x0061\x0069-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); - assert( - read_date_locale(L"2020-\x006d\x0041\x0069-15", "de_DE.utf-8") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); - - // German June in different cases (short, long, mixed cases) - assert(read_date_locale(L"2020-\x004a\x0075\x006e\x0069-25", "de_DE.utf-8") - == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - assert(read_date_locale(L"2020-\x006a\x0055\x004e\x0069-25", "de_DE.utf-8") - == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); - - // German July in different cases (short, long, mixed cases) - assert(read_date_locale(L"2020-\x004a\x0075\x006c\x0069-12", "de_DE.utf-8") - == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert(read_date_locale(L"2020-\x004a\x0075\x004c\x0069-12", "de_DE.utf-8") - == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - assert(read_date_locale(L"2020-\x006a\x0055\x006c\x0069-12", "de_DE.utf-8") - == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); - - // German Auguest in different cases (short, long, mixed cases) - assert(read_date_locale(L"2020-\x0041\x0075\x0067\x0075\x0073\x0074-02", "de_DE.utf-8") - == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert( - read_date_locale(L"2020-\x0041\x0075\x0067-02", "de_DE.utf-8") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - assert(read_date_locale(L"2020-\x0061\x0075\x0047\x0075\x0053\x0074-02", "de_DE.utf-8") - == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); - - // German September in different cases (short, long, mixed cases) + == make_tuple(15, 1, 120)); + assert(read_date_locale(L"2020-\x0066\x0045\x0062-15", "de_DE.utf-8") == make_tuple(15, 1, 120)); + + // German March in different cases (expanded, abbreviated, mixed cases) + assert(read_date_locale(L"2020-\x004d\x00e4\x0072\x007a-25", "de_DE.utf-8") == make_tuple(25, 2, 120)); + assert(read_date_locale(L"2020-\x004d\x0072\x007a-25", "de_DE.utf-8") == make_tuple(25, 2, 120)); + assert(read_date_locale(L"2020-\x006d\x00e4\x0052\x005a-25", "de_DE.utf-8") == make_tuple(25, 2, 120)); + assert(read_date_locale(L"2020-\x006d\x0052\x005a-25", "de_DE.utf-8") == make_tuple(25, 2, 120)); + + // German April in different cases (expanded, abbreviated, mixed cases) + assert(read_date_locale(L"2020-\x0041\x0070\x0072\x0069\x006c-05", "de_DE.utf-8") == make_tuple(5, 3, 120)); + assert(read_date_locale(L"2020-\x0041\x0070\x0072-05", "de_DE.utf-8") == make_tuple(5, 3, 120)); + assert(read_date_locale(L"2020-\x0061\x0070\x0052\x0069\x004c-05", "de_DE.utf-8") == make_tuple(5, 3, 120)); + assert(read_date_locale(L"2020-\x0061\x0050\x0052-05", "de_DE.utf-8") == make_tuple(5, 3, 120)); + + // German May in different cases (expanded, mixed cases) + // Expanded and abbreviated versions are identical + assert(read_date_locale(L"2020-\x004d\x0061\x0069-15", "de_DE.utf-8") == make_tuple(15, 4, 120)); + assert(read_date_locale(L"2020-\x006d\x0041\x0069-15", "de_DE.utf-8") == make_tuple(15, 4, 120)); + + // German June in different cases (expanded, abbreviated, mixed cases) + assert(read_date_locale(L"2020-\x004a\x0075\x006e\x0069-25", "de_DE.utf-8") == make_tuple(25, 5, 120)); + assert(read_date_locale(L"2020-\x004a\x0075\x006e-25", "de_DE.utf-8") == make_tuple(25, 5, 120)); + assert(read_date_locale(L"2020-\x006a\x0055\x004e\x0069-25", "de_DE.utf-8") == make_tuple(25, 5, 120)); + assert(read_date_locale(L"2020-\x006a\x0055\x004e-25", "de_DE.utf-8") == make_tuple(25, 5, 120)); + + // German July in different cases (expanded, mixed cases) + // Expanded and abbreviated are identical + assert(read_date_locale(L"2020-\x004a\x0075\x006c\x0069-12", "de_DE.utf-8") == make_tuple(12, 6, 120)); + assert(read_date_locale(L"2020-\x004a\x0075\x004c\x0069-12", "de_DE.utf-8") == make_tuple(12, 6, 120)); + + // German August in different cases (expanded, abbreviated, mixed cases) + assert(read_date_locale(L"2020-\x0041\x0075\x0067\x0075\x0073\x0074-02", "de_DE.utf-8") == make_tuple(2, 7, 120)); + assert(read_date_locale(L"2020-\x0041\x0075\x0067-02", "de_DE.utf-8") == make_tuple(2, 7, 120)); + assert(read_date_locale(L"2020-\x0061\x0075\x0047\x0075\x0053\x0074-02", "de_DE.utf-8") == make_tuple(2, 7, 120)); + assert(read_date_locale(L"2020-\x0061\x0055\x0047-02", "de_DE.utf-8") == make_tuple(2, 7, 120)); + + // German September in different cases (expanded, abbreviated, mixed cases) assert(read_date_locale(L"2020-\x0053\x0065\x0070\x0074\x0065\x006d\x0062\x0065\x0072-21", "de_DE.utf-8") - == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); - assert( - read_date_locale(L"2020-\x0053\x0065\x0070-21", "de_DE.utf-8") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + == make_tuple(21, 8, 120)); + assert(read_date_locale(L"2020-\x0053\x0065\x0070-21", "de_DE.utf-8") == make_tuple(21, 8, 120)); assert(read_date_locale(L"2020-\x0073\x0045\x0070\x0054\x0065\x004d\x0062\x0065\x0072-21", "de_DE.utf-8") - == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + == make_tuple(21, 8, 120)); + assert(read_date_locale(L"2020-\x0053\x0065\x0070-21", "de_DE.utf-8") == make_tuple(21, 8, 120)); + assert(read_date_locale(L"2020-\x0073\x0045\x0050-21", "de_DE.utf-8") == make_tuple(21, 8, 120)); - // German October in different cases (short, long, mixed cases) + // German October in different cases (expanded, abbreviated, mixed cases) assert(read_date_locale(L"2020-\x004f\x006b\x0074\x006f\x0062\x0065\x0072-01", "de_DE.utf-8") - == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); - assert( - read_date_locale(L"2020-\x004f\x006b\x0074-01", "de_DE.utf-8") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + == make_tuple(1, 9, 120)); + assert(read_date_locale(L"2020-\x004f\x006b\x0074-01", "de_DE.utf-8") == make_tuple(1, 9, 120)); assert(read_date_locale(L"2020-\x006f\x004b\x0074\x006f\x0042\x0065\x0052-01", "de_DE.utf-8") - == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + == make_tuple(1, 9, 120)); + assert(read_date_locale(L"2020-\x006f\x004b\x0074-01", "de_DE.utf-8") == make_tuple(1, 9, 120)); - // German November in different cases (short, long, mixed cases) + // German November in different cases (expanded, abbreviated, mixed cases) assert(read_date_locale(L"2020-\x004e\x006f\x0076\x0065\x006d\x0062\x0065\x0072-09", "de_DE.utf-8") - == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); - assert( - read_date_locale(L"2020-\x004e\x006f\x0076-09", "de_DE.utf-8") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + == make_tuple(9, 10, 120)); + assert(read_date_locale(L"2020-\x004e\x006f\x0076-09", "de_DE.utf-8") == make_tuple(9, 10, 120)); assert(read_date_locale(L"2020-\x006e\x006f\x0056\x0065\x006d\x0042\x0065\x0052-09", "de_DE.utf-8") - == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + == make_tuple(9, 10, 120)); + assert(read_date_locale(L"2020-\x006e\x004f\x0056-09", "de_DE.utf-8") == make_tuple(9, 10, 120)); - // German December in different cases (short, long, mixed cases) + // German December in different cases (expanded, abbreviated, mixed cases) assert(read_date_locale(L"2020-\x0044\x0065\x007a\x0065\x006d\x0062\x0065\x0072-31", "de_DE.utf-8") - == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); - assert( - read_date_locale(L"2020-\x0044\x0065\x007a-31", "de_DE.utf-8") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + == make_tuple(31, 11, 120)); + assert(read_date_locale(L"2020-\x0044\x0065\x007a-31", "de_DE.utf-8") == make_tuple(31, 11, 120)); assert(read_date_locale(L"2020-\x0064\x0065\x005a\x0065\x004d\x0062\x0045\x0072-31", "de_DE.utf-8") - == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + == make_tuple(31, 11, 120)); + assert(read_date_locale(L"2020-\x0064\x0045\x005a-31", "de_DE.utf-8") == make_tuple(31, 11, 120)); } -void test_locale_chines() { - // January in Chines - assert(read_date_locale(L"2020-\x4e00\x6708-05", "chinese") == make_tuple(5, /*NOTE DIFFERENCE:*/ 0, 120)); +void test_locale_chinese() { + // Chinese letters don't have distinct upper and lower cases + + // January in Chinese (expanded and abbreviated) + assert(read_date_locale(L"2020-\x4e00\x6708-05", "chinese") == make_tuple(5, 0, 120)); + assert(read_date_locale(L"2020-\x0031\x6708-05", "chinese") == make_tuple(5, 0, 120)); - // February in Chines - assert(read_date_locale(L"2020-\x4e8c\x6708-15", "chinese") == make_tuple(15, /*NOTE DIFFERENCE:*/ 1, 120)); + // February in Chinese (expanded and abbreviated) + assert(read_date_locale(L"2020-\x4e8c\x6708-15", "chinese") == make_tuple(15, 1, 120)); + assert(read_date_locale(L"2020-\x0032\x6708-15", "chinese") == make_tuple(15, 1, 120)); - // March in Chines - assert(read_date_locale(L"2020-\x4e09\x6708-25", "chinese") == make_tuple(25, /*NOTE DIFFERENCE:*/ 2, 120)); + // March in Chinese (expanded and abbreviated) + assert(read_date_locale(L"2020-\x4e09\x6708-25", "chinese") == make_tuple(25, 2, 120)); + assert(read_date_locale(L"2020-\x0033\x6708-25", "chinese") == make_tuple(25, 2, 120)); - // April in Chines - assert(read_date_locale(L"2020-\x56db\x6708-05", "chinese") == make_tuple(5, /*NOTE DIFFERENCE:*/ 3, 120)); + // April in Chinese (expanded and abbreviated) + assert(read_date_locale(L"2020-\x56db\x6708-05", "chinese") == make_tuple(5, 3, 120)); + assert(read_date_locale(L"2020-\x0034\x6708-05", "chinese") == make_tuple(5, 3, 120)); - // May in Chines - assert(read_date_locale(L"2020-\x4e94\x6708-15", "chinese") == make_tuple(15, /*NOTE DIFFERENCE:*/ 4, 120)); + // May in Chinese (expanded and abbreviated) + assert(read_date_locale(L"2020-\x4e94\x6708-15", "chinese") == make_tuple(15, 4, 120)); + assert(read_date_locale(L"2020-\x0035\x6708-15", "chinese") == make_tuple(15, 4, 120)); - // June in Chines - assert(read_date_locale(L"2020-\x516d\x6708-25", "chinese") == make_tuple(25, /*NOTE DIFFERENCE:*/ 5, 120)); + // June in Chinese (expanded and abbreviated) + assert(read_date_locale(L"2020-\x516d\x6708-25", "chinese") == make_tuple(25, 5, 120)); + assert(read_date_locale(L"2020-\x0036\x6708-25", "chinese") == make_tuple(25, 5, 120)); - // July in Chines - assert(read_date_locale(L"2020-\x4e03\x6708-12", "chinese") == make_tuple(12, /*NOTE DIFFERENCE:*/ 6, 120)); + // July in Chinese (expanded and abbreviated) + assert(read_date_locale(L"2020-\x4e03\x6708-12", "chinese") == make_tuple(12, 6, 120)); + assert(read_date_locale(L"2020-\x0037\x6708-12", "chinese") == make_tuple(12, 6, 120)); - // Auguest in Chines - assert(read_date_locale(L"2020-\x516b\x6708-02", "chinese") == make_tuple(2, /*NOTE DIFFERENCE:*/ 7, 120)); + // August in Chinese (expanded and abbreviated) + assert(read_date_locale(L"2020-\x516b\x6708-02", "chinese") == make_tuple(2, 7, 120)); + assert(read_date_locale(L"2020-\x0038\x6708-02", "chinese") == make_tuple(2, 7, 120)); - // September in Chines - assert(read_date_locale(L"2020-\x4e5d\x6708-21", "chinese") == make_tuple(21, /*NOTE DIFFERENCE:*/ 8, 120)); + // September in Chinese (expanded and abbreviated) + assert(read_date_locale(L"2020-\x4e5d\x6708-21", "chinese") == make_tuple(21, 8, 120)); + assert(read_date_locale(L"2020-\x0039\x6708-21", "chinese") == make_tuple(21, 8, 120)); - // October in Chines - assert(read_date_locale(L"2020-\x5341\x6708-01", "chinese") == make_tuple(1, /*NOTE DIFFERENCE:*/ 9, 120)); + // October in Chinese (expanded and abbreviated) + assert(read_date_locale(L"2020-\x5341\x6708-01", "chinese") == make_tuple(1, 9, 120)); + assert(read_date_locale(L"2020-\x0031\x0030\x6708-01", "chinese") == make_tuple(1, 9, 120)); - // November in Chines - assert(read_date_locale(L"2020-\x5341\x4e00\x6708-09", "chinese") == make_tuple(9, /*NOTE DIFFERENCE:*/ 10, 120)); + // November in Chinese (expanded and abbreviated) + assert(read_date_locale(L"2020-\x5341\x4e00\x6708-09", "chinese") == make_tuple(9, 10, 120)); + assert(read_date_locale(L"2020-\x0031\x0031\x6708-09", "chinese") == make_tuple(9, 10, 120)); - // December in Chines - assert(read_date_locale(L"2020-\x5341\x4e8c\x6708-31", "chinese") == make_tuple(31, /*NOTE DIFFERENCE:*/ 11, 120)); + // December in Chinese (expanded and abbreviated) + assert(read_date_locale(L"2020-\x5341\x4e8c\x6708-31", "chinese") == make_tuple(31, 11, 120)); + assert(read_date_locale(L"2020-\x0031\x0032\x6708-31", "chinese") == make_tuple(31, 11, 120)); } From 5b0583d2fd09a79faf317dda31759e3dfb7ca490 Mon Sep 17 00:00:00 2001 From: Hamid Reza Arzaghi Date: Sat, 22 Aug 2020 20:48:06 +0430 Subject: [PATCH 09/11] update xlocale xloctime and a test --- stl/inc/xlocale | 2 +- stl/inc/xloctime | 4 +- .../std/tests/Dev11_0836436_get_time/test.cpp | 63 ++++++++----------- 3 files changed, 31 insertions(+), 38 deletions(-) diff --git a/stl/inc/xlocale b/stl/inc/xlocale index c3405acf92d..d5f6b805996 100644 --- a/stl/inc/xlocale +++ b/stl/inc/xlocale @@ -870,7 +870,7 @@ int __CRTDECL _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields, const _ } string _Str(_Numfields, '\0'); // one column counter for each field - const _STD ctype<_Elem>& _CType = _STD use_facet<_STD ctype<_Elem>>(_STD locale()); + const ctype<_Elem>& _CType = _STD use_facet>(locale{}); int _Ans = -2; // no candidates so far for (size_t _Column = 1;; ++_Column, (void) ++_First, _Ans = -1) { // test each element against all viable fields diff --git a/stl/inc/xloctime b/stl/inc/xloctime index c0120f138d7..f2b6de3fbc2 100644 --- a/stl/inc/xloctime +++ b/stl/inc/xloctime @@ -132,7 +132,9 @@ public: } _First = do_get(_First, _Last, _Iosbase, _State, _Pt, _Specifier, _Modifier); // convert a single field - if (_State != 0) { + + if (_State != ios_base::goodbit) { + // failed in converting the field. do not proceed to the next fields. return with failed _State break; } } diff --git a/tests/std/tests/Dev11_0836436_get_time/test.cpp b/tests/std/tests/Dev11_0836436_get_time/test.cpp index d257b813bbc..12b64dfc8ae 100644 --- a/tests/std/tests/Dev11_0836436_get_time/test.cpp +++ b/tests/std/tests/Dev11_0836436_get_time/test.cpp @@ -74,15 +74,6 @@ tuple read_date(const char* const s) { tuple read_date_locale(const wchar_t* const s, const char* _loc) { const auto t = helper_locale(s, L"%Y-%b-%d", _loc); - // %x The date, using the locale's date format. - // "%d / %m / %y" - // %d The day of the month [01,31]; leading zeros are permitted but not required. - // %m The month number [01,12]; leading zeros are permitted but not required. - // %y The year within century. When a century is not otherwise specified, - // values in the range [69,99] shall refer to years 1969 to 1999 inclusive, and - // values in the range [00,68] shall refer to years 2000 to 2068 inclusive; - // leading zeros shall be permitted but shall not be required. - // int tm_mday; // day of the month - [1, 31] // int tm_mon; // months since January - [0, 11] // int tm_year; // years since 1900 @@ -312,11 +303,11 @@ void test_990695() { { // This case should fail - istringstream ss("2018-M-18"); + istringstream iss("2018-M-18"); tm t = {}; const string fmt("%Y-%b-%d"); - ss >> get_time(&t, fmt.c_str()); - assert(ss.fail()); + iss >> get_time(&t, fmt.c_str()); + assert(iss.fail()); } } } @@ -489,50 +480,50 @@ void test_locale_chinese() { // Chinese letters don't have distinct upper and lower cases // January in Chinese (expanded and abbreviated) - assert(read_date_locale(L"2020-\x4e00\x6708-05", "chinese") == make_tuple(5, 0, 120)); - assert(read_date_locale(L"2020-\x0031\x6708-05", "chinese") == make_tuple(5, 0, 120)); + assert(read_date_locale(L"2020-\x4e00\x6708-05", "zh-CN.utf-8") == make_tuple(5, 0, 120)); + assert(read_date_locale(L"2020-\x0031\x6708-05", "zh-CN.utf-8") == make_tuple(5, 0, 120)); // February in Chinese (expanded and abbreviated) - assert(read_date_locale(L"2020-\x4e8c\x6708-15", "chinese") == make_tuple(15, 1, 120)); - assert(read_date_locale(L"2020-\x0032\x6708-15", "chinese") == make_tuple(15, 1, 120)); + assert(read_date_locale(L"2020-\x4e8c\x6708-15", "zh-CN.utf-8") == make_tuple(15, 1, 120)); + assert(read_date_locale(L"2020-\x0032\x6708-15", "zh-CN.utf-8") == make_tuple(15, 1, 120)); // March in Chinese (expanded and abbreviated) - assert(read_date_locale(L"2020-\x4e09\x6708-25", "chinese") == make_tuple(25, 2, 120)); - assert(read_date_locale(L"2020-\x0033\x6708-25", "chinese") == make_tuple(25, 2, 120)); + assert(read_date_locale(L"2020-\x4e09\x6708-25", "zh-CN.utf-8") == make_tuple(25, 2, 120)); + assert(read_date_locale(L"2020-\x0033\x6708-25", "zh-CN.utf-8") == make_tuple(25, 2, 120)); // April in Chinese (expanded and abbreviated) - assert(read_date_locale(L"2020-\x56db\x6708-05", "chinese") == make_tuple(5, 3, 120)); - assert(read_date_locale(L"2020-\x0034\x6708-05", "chinese") == make_tuple(5, 3, 120)); + assert(read_date_locale(L"2020-\x56db\x6708-05", "zh-CN.utf-8") == make_tuple(5, 3, 120)); + assert(read_date_locale(L"2020-\x0034\x6708-05", "zh-CN.utf-8") == make_tuple(5, 3, 120)); // May in Chinese (expanded and abbreviated) - assert(read_date_locale(L"2020-\x4e94\x6708-15", "chinese") == make_tuple(15, 4, 120)); - assert(read_date_locale(L"2020-\x0035\x6708-15", "chinese") == make_tuple(15, 4, 120)); + assert(read_date_locale(L"2020-\x4e94\x6708-15", "zh-CN.utf-8") == make_tuple(15, 4, 120)); + assert(read_date_locale(L"2020-\x0035\x6708-15", "zh-CN.utf-8") == make_tuple(15, 4, 120)); // June in Chinese (expanded and abbreviated) - assert(read_date_locale(L"2020-\x516d\x6708-25", "chinese") == make_tuple(25, 5, 120)); - assert(read_date_locale(L"2020-\x0036\x6708-25", "chinese") == make_tuple(25, 5, 120)); + assert(read_date_locale(L"2020-\x516d\x6708-25", "zh-CN.utf-8") == make_tuple(25, 5, 120)); + assert(read_date_locale(L"2020-\x0036\x6708-25", "zh-CN.utf-8") == make_tuple(25, 5, 120)); // July in Chinese (expanded and abbreviated) - assert(read_date_locale(L"2020-\x4e03\x6708-12", "chinese") == make_tuple(12, 6, 120)); - assert(read_date_locale(L"2020-\x0037\x6708-12", "chinese") == make_tuple(12, 6, 120)); + assert(read_date_locale(L"2020-\x4e03\x6708-12", "zh-CN.utf-8") == make_tuple(12, 6, 120)); + assert(read_date_locale(L"2020-\x0037\x6708-12", "zh-CN.utf-8") == make_tuple(12, 6, 120)); // August in Chinese (expanded and abbreviated) - assert(read_date_locale(L"2020-\x516b\x6708-02", "chinese") == make_tuple(2, 7, 120)); - assert(read_date_locale(L"2020-\x0038\x6708-02", "chinese") == make_tuple(2, 7, 120)); + assert(read_date_locale(L"2020-\x516b\x6708-02", "zh-CN.utf-8") == make_tuple(2, 7, 120)); + assert(read_date_locale(L"2020-\x0038\x6708-02", "zh-CN.utf-8") == make_tuple(2, 7, 120)); // September in Chinese (expanded and abbreviated) - assert(read_date_locale(L"2020-\x4e5d\x6708-21", "chinese") == make_tuple(21, 8, 120)); - assert(read_date_locale(L"2020-\x0039\x6708-21", "chinese") == make_tuple(21, 8, 120)); + assert(read_date_locale(L"2020-\x4e5d\x6708-21", "zh-CN.utf-8") == make_tuple(21, 8, 120)); + assert(read_date_locale(L"2020-\x0039\x6708-21", "zh-CN.utf-8") == make_tuple(21, 8, 120)); // October in Chinese (expanded and abbreviated) - assert(read_date_locale(L"2020-\x5341\x6708-01", "chinese") == make_tuple(1, 9, 120)); - assert(read_date_locale(L"2020-\x0031\x0030\x6708-01", "chinese") == make_tuple(1, 9, 120)); + assert(read_date_locale(L"2020-\x5341\x6708-01", "zh-CN.utf-8") == make_tuple(1, 9, 120)); + assert(read_date_locale(L"2020-\x0031\x0030\x6708-01", "zh-CN.utf-8") == make_tuple(1, 9, 120)); // November in Chinese (expanded and abbreviated) - assert(read_date_locale(L"2020-\x5341\x4e00\x6708-09", "chinese") == make_tuple(9, 10, 120)); - assert(read_date_locale(L"2020-\x0031\x0031\x6708-09", "chinese") == make_tuple(9, 10, 120)); + assert(read_date_locale(L"2020-\x5341\x4e00\x6708-09", "zh-CN.utf-8") == make_tuple(9, 10, 120)); + assert(read_date_locale(L"2020-\x0031\x0031\x6708-09", "zh-CN.utf-8") == make_tuple(9, 10, 120)); // December in Chinese (expanded and abbreviated) - assert(read_date_locale(L"2020-\x5341\x4e8c\x6708-31", "chinese") == make_tuple(31, 11, 120)); - assert(read_date_locale(L"2020-\x0031\x0032\x6708-31", "chinese") == make_tuple(31, 11, 120)); + assert(read_date_locale(L"2020-\x5341\x4e8c\x6708-31", "zh-CN.utf-8") == make_tuple(31, 11, 120)); + assert(read_date_locale(L"2020-\x0031\x0032\x6708-31", "zh-CN.utf-8") == make_tuple(31, 11, 120)); } From 2f8558d2c73beb3370682985145d2e95c5193e65 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 24 Aug 2020 13:30:09 -0700 Subject: [PATCH 10/11] Change comment to complete sentences. --- stl/inc/xloctime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/xloctime b/stl/inc/xloctime index f2b6de3fbc2..082bbd4e35e 100644 --- a/stl/inc/xloctime +++ b/stl/inc/xloctime @@ -134,7 +134,7 @@ public: _First = do_get(_First, _Last, _Iosbase, _State, _Pt, _Specifier, _Modifier); // convert a single field if (_State != ios_base::goodbit) { - // failed in converting the field. do not proceed to the next fields. return with failed _State + // Failed to convert the field. Do not proceed to the next fields. Return with failed _State. break; } } From b571ca9441d1a985cc07423792e54aa15ad724c1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 24 Aug 2020 13:33:59 -0700 Subject: [PATCH 11/11] Rearrange xlocale code. --- stl/inc/xlocale | 1026 +++++++++++++++++++++++------------------------ 1 file changed, 513 insertions(+), 513 deletions(-) diff --git a/stl/inc/xlocale b/stl/inc/xlocale index d5f6b805996..3f2a2a488de 100644 --- a/stl/inc/xlocale +++ b/stl/inc/xlocale @@ -614,295 +614,6 @@ inline unsigned short* __CRTDECL _Maklocstr(const char* _Ptr, unsigned short*, c } #endif // _NATIVE_WCHAR_T_DEFINED -// STRUCT ctype_base -struct _CRTIMP2_PURE_IMPORT ctype_base : locale::facet { // base for ctype - enum { // constants for character classifications - alnum = _DI | _LO | _UP | _XA, - alpha = _LO | _UP | _XA, - cntrl = _BB, - digit = _DI, - graph = _DI | _LO | _PU | _UP | _XA, - lower = _LO, - print = _DI | _LO | _PU | _SP | _UP | _XA | _XD, - punct = _PU, - space = _CN | _SP | _XS, - upper = _UP, - xdigit = _XD, - blank = _CN | _SP | _XS | _XB - }; - using mask = short; // to match - - __CLR_OR_THIS_CALL ctype_base(size_t _Refs = 0) : locale::facet(_Refs) {} - - __CLR_OR_THIS_CALL ~ctype_base() noexcept {} -}; - -// CLASS TEMPLATE ctype -template -class ctype : public ctype_base { // facet for classifying elements, converting cases -public: - // ctype, ctype, and ctype are explicitly specialized below. - static_assert(!_ENFORCE_FACET_SPECIALIZATIONS || _Always_false<_Elem>, _FACET_SPECIALIZATION_MESSAGE); - - using char_type = _Elem; - - bool __CLR_OR_THIS_CALL is(mask _Maskval, _Elem _Ch) const { // test if element fits any mask classifications - return do_is(_Maskval, _Ch); - } - - const _Elem* __CLR_OR_THIS_CALL is(const _Elem* _First, const _Elem* _Last, - mask* _Dest) const { // get mask sequence for elements in [_First, _Last) - return do_is(_First, _Last, _Dest); - } - - const _Elem* __CLR_OR_THIS_CALL scan_is(mask _Maskval, const _Elem* _First, - const _Elem* _Last) const { // find first in [_First, _Last) that fits mask classification - return do_scan_is(_Maskval, _First, _Last); - } - - const _Elem* __CLR_OR_THIS_CALL scan_not(mask _Maskval, const _Elem* _First, - const _Elem* _Last) const { // find first in [_First, _Last) not fitting mask classification - return do_scan_not(_Maskval, _First, _Last); - } - - _Elem __CLR_OR_THIS_CALL tolower(_Elem _Ch) const { // convert element to lower case - return do_tolower(_Ch); - } - - const _Elem* __CLR_OR_THIS_CALL tolower( - _Elem* _First, const _Elem* _Last) const { // convert [_First, _Last) in place to lower case - return do_tolower(_First, _Last); - } - - _Elem __CLR_OR_THIS_CALL toupper(_Elem _Ch) const { // convert element to upper case - return do_toupper(_Ch); - } - - const _Elem* __CLR_OR_THIS_CALL toupper( - _Elem* _First, const _Elem* _Last) const { // convert [_First, _Last) in place to upper case - return do_toupper(_First, _Last); - } - - _Elem __CLR_OR_THIS_CALL widen(char _Byte) const { // widen char - return do_widen(_Byte); - } - - const char* __CLR_OR_THIS_CALL widen(const char* _First, const char* _Last, - _Elem* _Dest) const { // widen chars in [_First, _Last) - return do_widen(_First, _Last, _Dest); - } - - char __CLR_OR_THIS_CALL narrow(_Elem _Ch, char _Dflt = '\0') const { // narrow element to char - return do_narrow(_Ch, _Dflt); - } - - const _Elem* __CLR_OR_THIS_CALL narrow(const _Elem* _First, const _Elem* _Last, char _Dflt, - char* _Dest) const { // narrow elements in [_First, _Last) to chars - return do_narrow(_First, _Last, _Dflt, _Dest); - } - - __PURE_APPDOMAIN_GLOBAL static locale::id id; - - explicit __CLR_OR_THIS_CALL ctype(size_t _Refs = 0) : ctype_base(_Refs) { - _BEGIN_LOCINFO(_Lobj) - _Init(_Lobj); - _END_LOCINFO() - } - - __CLR_OR_THIS_CALL ctype(const _Locinfo& _Lobj, size_t _Refs = 0) : ctype_base(_Refs) { - _Init(_Lobj); - } - - static size_t __CLRCALL_OR_CDECL _Getcat(const locale::facet** _Ppf = nullptr, const locale* _Ploc = nullptr) { - if (_Ppf && !*_Ppf) { - *_Ppf = new ctype<_Elem>(_Locinfo(_Ploc->c_str())); - } - - return _X_CTYPE; - } - -protected: - virtual __CLR_OR_THIS_CALL ~ctype() noexcept { - if (_Ctype._Delfl) { - _CSTD free(const_cast(_Ctype._Table)); - } - - _CSTD free(_Ctype._LocaleName); - } - - void __CLR_OR_THIS_CALL _Init(const _Locinfo& _Lobj) { // initialize from _Lobj - _Ctype = _Lobj._Getctype(); - _Cvt = _Lobj._Getcvt(); - } - - virtual bool __CLR_OR_THIS_CALL do_is( - mask _Maskval, _Elem _Ch) const { // test if element fits any mask classifications - return (_Ctype._Table[static_cast(narrow(_Ch))] & _Maskval) != 0; - } - - virtual const _Elem* __CLR_OR_THIS_CALL do_is(const _Elem* _First, const _Elem* _Last, - mask* _Dest) const { // get mask sequence for elements in [_First, _Last) - _Adl_verify_range(_First, _Last); - for (; _First != _Last; ++_First, ++_Dest) { - *_Dest = _Ctype._Table[static_cast(narrow(*_First))]; - } - - return _First; - } - - virtual const _Elem* __CLR_OR_THIS_CALL do_scan_is(mask _Maskval, const _Elem* _First, - const _Elem* _Last) const { // find first in [_First, _Last) that fits mask classification - _Adl_verify_range(_First, _Last); - while (_First != _Last && !is(_Maskval, *_First)) { - ++_First; - } - - return _First; - } - - virtual const _Elem* __CLR_OR_THIS_CALL do_scan_not(mask _Maskval, const _Elem* _First, - const _Elem* _Last) const { // find first in [_First, _Last) not fitting mask classification - _Adl_verify_range(_First, _Last); - while (_First != _Last && is(_Maskval, *_First)) { - ++_First; - } - - return _First; - } - - virtual _Elem __CLR_OR_THIS_CALL do_tolower(_Elem _Ch) const { // convert element to lower case - unsigned char _Byte = static_cast(narrow(_Ch, '\0')); - if (_Byte == '\0') { - return _Ch; - } - - return widen(static_cast(_Tolower(_Byte, &_Ctype))); - } - - virtual const _Elem* __CLR_OR_THIS_CALL do_tolower(_Elem* _First, - const _Elem* _Last) const { // convert [_First, _Last) in place to lower case - _Adl_verify_range(_First, _Last); - for (; _First != _Last; ++_First) { // convert *_First to lower case - unsigned char _Byte = static_cast(narrow(*_First, '\0')); - if (_Byte != '\0') { - *_First = (widen(static_cast(_Tolower(_Byte, &_Ctype)))); - } - } - return _First; - } - - virtual _Elem __CLR_OR_THIS_CALL do_toupper(_Elem _Ch) const { // convert element to upper case - unsigned char _Byte = static_cast(narrow(_Ch, '\0')); - if (_Byte == '\0') { - return _Ch; - } - - return widen(static_cast(_Toupper(_Byte, &_Ctype))); - } - - virtual const _Elem* __CLR_OR_THIS_CALL do_toupper(_Elem* _First, - const _Elem* _Last) const { // convert [_First, _Last) in place to upper case - _Adl_verify_range(_First, _Last); - for (; _First != _Last; ++_First) { // convert *_First to upper case - unsigned char _Byte = static_cast(narrow(*_First, '\0')); - if (_Byte != '\0') { - *_First = (widen(static_cast(_Toupper(_Byte, &_Ctype)))); - } - } - - return _First; - } - - virtual _Elem __CLR_OR_THIS_CALL do_widen(char _Byte) const { // widen char - return _Maklocchr(_Byte, static_cast<_Elem*>(nullptr), _Cvt); - } - - virtual const char* __CLR_OR_THIS_CALL do_widen( - const char* _First, const char* _Last, _Elem* _Dest) const { // widen chars in [_First, _Last) - _Adl_verify_range(_First, _Last); - for (; _First != _Last; ++_First, ++_Dest) { - *_Dest = _Maklocchr(*_First, static_cast<_Elem*>(nullptr), _Cvt); - } - - return _First; - } - - char __CLR_OR_THIS_CALL _Donarrow(_Elem _Ch, char _Dflt) const { // narrow element to char - char _Byte; - if (_Ch == _Elem{}) { - return '\0'; - } - - if ((_Byte = _Maklocbyte(_Ch, _Cvt)) == '\0') { - return _Dflt; - } - - return _Byte; - } - - virtual char __CLR_OR_THIS_CALL do_narrow(_Elem _Ch, char _Dflt) const { // narrow element to char - return _Donarrow(_Ch, _Dflt); - } - - virtual const _Elem* __CLR_OR_THIS_CALL do_narrow(const _Elem* _First, const _Elem* _Last, char _Dflt, - char* _Dest) const { // narrow elements in [_First, _Last) to chars - _Adl_verify_range(_First, _Last); - for (; _First != _Last; ++_First, ++_Dest) { - *_Dest = _Donarrow(*_First, _Dflt); - } - - return _First; - } - -private: - _Locinfo::_Ctypevec _Ctype; // locale info passed to _Tolower, etc. - _Locinfo::_Cvtvec _Cvt; // conversion information -}; - -// FUNCTION TEMPLATE _Getloctxt -template -int __CRTDECL _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields, const _Elem* _Ptr) { - // find field at _Ptr that matches longest in [_First, _Last) - for (size_t _Off = 0; _Ptr[_Off] != _Elem{}; ++_Off) { - if (_Ptr[_Off] == _Ptr[0]) { - ++_Numfields; // add fields with leading mark to initial count - } - } - - string _Str(_Numfields, '\0'); // one column counter for each field - const ctype<_Elem>& _CType = _STD use_facet>(locale{}); - - int _Ans = -2; // no candidates so far - for (size_t _Column = 1;; ++_Column, (void) ++_First, _Ans = -1) { // test each element against all viable fields - bool _Prefix = false; // seen at least one valid prefix - size_t _Off = 0; // offset into fields - size_t _Field = 0; // current field number - - for (; _Field < _Numfields; ++_Field) { // test element at _Column in field _Field - while (_Ptr[_Off] != _Elem{} && _Ptr[_Off] != _Ptr[0]) { // find beginning of field - ++_Off; - } - - if (_Str[_Field] != '\0') { - _Off += _Str[_Field]; // skip tested columns in field - } else if (_Ptr[_Off += _Column] == _Ptr[0] - || _Ptr[_Off] == _Elem{}) { // matched all of field, save as possible answer - _Str[_Field] = static_cast(_Column < 127 ? _Column : 127); // save skip count if small enough - _Ans = static_cast(_Field); // save answer - } else if (_First == _Last || _CType.tolower(_Ptr[_Off]) != _CType.tolower(static_cast<_Elem>(*_First))) { - _Str[_Field] = static_cast(_Column < 127 ? _Column : 127); // no match, just save skip count - } else { - _Prefix = true; // still a valid prefix - } - } - - if (!_Prefix || _First == _Last) { - break; // no pending prefixes or no input, give up - } - } - return _Ans; // return field number or negative value on failure -} - // STRUCT codecvt_base class _CRTIMP2_PURE_IMPORT codecvt_base : public locale::facet { // base class for codecvt public: @@ -2135,59 +1846,256 @@ protected: } virtual int __CLR_OR_THIS_CALL do_length( - mbstate_t&, const char8_t* _First1, const char8_t* _Last1, size_t _Count) const { + mbstate_t&, const char8_t* _First1, const char8_t* _Last1, size_t _Count) const { + // return p - _First1, for the largest value p in [_First1, _Last1] such that [_First1, p) successfully + // converts to at most _Count UTF-32 code units + _Adl_verify_range(_First1, _Last1); + + const auto _Old_first1 = _First1; + + for (; _First1 != _Last1 && _Count > 0u; ++_First1, --_Count) { + char32_t _Code_point = *_First1; + if (_Code_point < 0b1000'0000u) { // single-byte sequence + continue; + } + + int _Trailing_count = 1; + if (_Code_point < 0b1110'0000u) { + if (_Code_point < 0b1100'0000u) { // out-of-sequence trailing byte + break; + } + + // lead byte of 2-byte sequence + _Code_point &= 0b0001'1111u; + } else if (_Code_point < 0b1111'0000u) { // lead byte of 3-byte sequence + _Code_point &= 0b0000'1111u; + _Trailing_count = 2; + } else if (_Code_point < 0b1111'1000u) { // lead byte of 4-byte sequence + _Code_point &= 0b0000'0111u; + _Trailing_count = 3; + } else { // invalid UTF-8 code unit + break; + } + + if (_Last1 - _First1 < _Trailing_count + 1) { // not enough input + break; + } + + const char8_t* _Peek = _First1; + bool _Done = false; + do { + const char8_t _By = *++_Peek; + if ((_By & 0b1100'0000u) != 0b1000'0000u) { // out-of-sequence lead byte + _Done = true; + break; + } + + _Code_point = (_Code_point << 6) | (_By & 0b11'1111u); + } while (--_Trailing_count != 0); + + if (_Done || (_Code_point >= 0xd800u && (_Code_point < 0xe000u || _Code_point >= 0x110000u))) { + // invalid code point (surrogate or out of range) + break; + } + + _First1 = _Peek; + } + + return static_cast((_STD min)(_First1 - _Old_first1, ptrdiff_t{INT_MAX})); + } + + virtual bool __CLR_OR_THIS_CALL do_always_noconv() const noexcept override { + // return true if conversions never change input + return false; + } + + virtual int __CLR_OR_THIS_CALL do_max_length() const noexcept override { + // return maximum length required for a conversion + return 4; + } + + virtual int __CLR_OR_THIS_CALL do_encoding() const noexcept override { + // return length of code sequence (from codecvt) + return 0; // varying length + } +}; +#endif // defined(__cpp_char8_t) && !defined(_M_CEE_PURE) + +// CLASS codecvt +template <> +class _CRTIMP2_PURE_IMPORT codecvt : public codecvt_base { + // facet for converting between wchar_t and char (_Byte) sequences +public: + using intern_type = wchar_t; + using extern_type = char; + using state_type = mbstate_t; + + result __CLR_OR_THIS_CALL in(mbstate_t& _State, const char* _First1, const char* _Last1, const char*& _Mid1, + wchar_t* _First2, wchar_t* _Last2, wchar_t*& _Mid2) const { + // convert bytes [_First1, _Last1) to [_First2, _Last2) + return do_in(_State, _First1, _Last1, _Mid1, _First2, _Last2, _Mid2); + } + + result __CLR_OR_THIS_CALL out(mbstate_t& _State, const wchar_t* _First1, const wchar_t* _Last1, + const wchar_t*& _Mid1, char* _First2, char* _Last2, char*& _Mid2) const { + // convert [_First1, _Last1) to bytes [_First2, _Last2) + return do_out(_State, _First1, _Last1, _Mid1, _First2, _Last2, _Mid2); + } + + result __CLR_OR_THIS_CALL unshift(mbstate_t& _State, char* _First2, char* _Last2, char*& _Mid2) const { + // generate bytes to return to default shift state + return do_unshift(_State, _First2, _Last2, _Mid2); + } + + int __CLR_OR_THIS_CALL length(mbstate_t& _State, const char* _First1, const char* _Last1, size_t _Count) const { + // return p - _First1, for the largest value p in [_First1, _Last1] such that [_First1, p) successfully + // converts to at most _Count wide characters + return do_length(_State, _First1, _Last1, _Count); + } + + __PURE_APPDOMAIN_GLOBAL static locale::id id; + + explicit __CLR_OR_THIS_CALL codecvt(size_t _Refs = 0) : codecvt_base(_Refs) { + _BEGIN_LOCINFO(_Lobj) + _Init(_Lobj); + _END_LOCINFO() + } + + explicit __CLR_OR_THIS_CALL codecvt(const _Locinfo& _Lobj, size_t _Refs = 0) : codecvt_base(_Refs) { + _Init(_Lobj); + } + + static size_t __CLRCALL_OR_CDECL _Getcat(const locale::facet** _Ppf = nullptr, const locale* _Ploc = nullptr) { + // return locale category mask and construct standard facet + if (_Ppf && !*_Ppf) { + *_Ppf = new codecvt(_Locinfo(_Ploc->c_str())); + } + + return _X_CTYPE; + } + +protected: + virtual __CLR_OR_THIS_CALL ~codecvt() noexcept {} + + void __CLR_OR_THIS_CALL _Init(const _Locinfo& _Lobj) { // initialize from _Lobj + _Cvt = _Lobj._Getcvt(); + } + + virtual result __CLR_OR_THIS_CALL do_in(mbstate_t&, const char* _First1, const char* _Last1, const char*& _Mid1, + wchar_t* _First2, wchar_t* _Last2, wchar_t*& _Mid2) const { + // convert bytes [_First1, _Last1) to [_First2, _Last2) + mbstate_t _Mystate{}; + _Adl_verify_range(_First1, _Last1); + _Adl_verify_range(_First2, _Last2); + _Mid1 = _First1; + _Mid2 = _First2; + for (;;) { + if (_Mid1 == _Last1) { + return ok; + } + + if (_Mid2 == _Last2) { + return partial; + } + + int _Bytes = _Mbrtowc(_Mid2, _Mid1, static_cast(_Last1 - _Mid1), &_Mystate, &_Cvt); + switch (_Bytes) { + case -2: // partial conversion + return partial; + + case -1: // failed conversion + return error; + + case 0: // converted NULL character, TRANSITION, VSO-654347 + _Bytes = 1; + // [[fallthrough]]; + + default: // converted some other character + _Mid1 += _Bytes; + ++_Mid2; + break; + } + } + } + + virtual result __CLR_OR_THIS_CALL do_out(mbstate_t& _State, const wchar_t* _First1, const wchar_t* _Last1, + const wchar_t*& _Mid1, char* _First2, char* _Last2, char*& _Mid2) const { + // convert [_First1, _Last1) to bytes [_First2, _Last2) + _Adl_verify_range(_First1, _Last1); + _Adl_verify_range(_First2, _Last2); + _Mid1 = _First1; + _Mid2 = _First2; + int _Bytes; + + while (_Mid1 != _Last1 && _Mid2 != _Last2) { + if (MB_LEN_MAX <= _Last2 - _Mid2) { + if ((_Bytes = _Wcrtomb(_Mid2, *_Mid1, &_State, &_Cvt)) < 0) { + return error; // locale-specific wcrtomb failed + } else { + ++_Mid1; + _Mid2 += _Bytes; + } + } else { // destination too small, convert into buffer + char _Buf[MB_LEN_MAX]; + mbstate_t _Stsave = _State; + + if ((_Bytes = _Wcrtomb(_Buf, *_Mid1, &_State, &_Cvt)) < 0) { + return error; // locale-specific wcrtomb failed + } else if (_Last2 - _Mid2 < _Bytes) { // converted too many, roll back and return previous + _State = _Stsave; + break; + } else { // copy converted bytes from buffer + _CSTD memcpy(_Mid2, _Buf, static_cast(_Bytes)); + ++_Mid1; + _Mid2 += _Bytes; + } + } + } + + return _Mid1 == _Last1 ? ok : partial; + } + + virtual result __CLR_OR_THIS_CALL do_unshift(mbstate_t& _State, char* _First2, char* _Last2, char*& _Mid2) const { + // generate bytes to return to default shift state + _Adl_verify_range(_First2, _Last2); + _Mid2 = _First2; + result _Ans = ok; + int _Bytes; + char _Buf[MB_LEN_MAX]; + mbstate_t _Stsave = _State; + + if ((_Bytes = _Wcrtomb(_Buf, L'\0', &_State, &_Cvt)) <= 0) { + _Ans = error; // locale-specific wcrtomb failed + } else if (_Last2 - _Mid2 < --_Bytes) { // converted too many, roll back and return + _State = _Stsave; + _Ans = partial; + } else if (0 < _Bytes) { // copy converted bytes from buffer + _CSTD memcpy(_Mid2, _Buf, static_cast(_Bytes)); + _Mid2 += _Bytes; + } + return _Ans; + } + + virtual int __CLR_OR_THIS_CALL do_length( + mbstate_t& _State, const char* _First1, const char* _Last1, size_t _Count) const { // return p - _First1, for the largest value p in [_First1, _Last1] such that [_First1, p) successfully - // converts to at most _Count UTF-32 code units + // converts to at most _Count wide characters _Adl_verify_range(_First1, _Last1); - const auto _Old_first1 = _First1; - for (; _First1 != _Last1 && _Count > 0u; ++_First1, --_Count) { - char32_t _Code_point = *_First1; - if (_Code_point < 0b1000'0000u) { // single-byte sequence - continue; - } - - int _Trailing_count = 1; - if (_Code_point < 0b1110'0000u) { - if (_Code_point < 0b1100'0000u) { // out-of-sequence trailing byte - break; - } - - // lead byte of 2-byte sequence - _Code_point &= 0b0001'1111u; - } else if (_Code_point < 0b1111'0000u) { // lead byte of 3-byte sequence - _Code_point &= 0b0000'1111u; - _Trailing_count = 2; - } else if (_Code_point < 0b1111'1000u) { // lead byte of 4-byte sequence - _Code_point &= 0b0000'0111u; - _Trailing_count = 3; - } else { // invalid UTF-8 code unit - break; - } - - if (_Last1 - _First1 < _Trailing_count + 1) { // not enough input + for (; _Count > 0u && _First1 != _Last1; --_Count) { + wchar_t _Ch; + int _Bytes = _Mbrtowc(&_Ch, _First1, static_cast(_Last1 - _First1), &_State, &_Cvt); + if (_Bytes < 0) { // partial or failed conversion break; } - const char8_t* _Peek = _First1; - bool _Done = false; - do { - const char8_t _By = *++_Peek; - if ((_By & 0b1100'0000u) != 0b1000'0000u) { // out-of-sequence lead byte - _Done = true; - break; - } - - _Code_point = (_Code_point << 6) | (_By & 0b11'1111u); - } while (--_Trailing_count != 0); - - if (_Done || (_Code_point >= 0xd800u && (_Code_point < 0xe000u || _Code_point >= 0x110000u))) { - // invalid code point (surrogate or out of range) - break; + if (_Bytes == 0) { // converted NULL character, TRANSITION, VSO-654347 + _Bytes = 1; } - _First1 = _Peek; + // converted _Bytes bytes to a wide character + _First1 += _Bytes; } return static_cast((_STD min)(_First1 - _Old_first1, ptrdiff_t{INT_MAX})); @@ -2199,34 +2107,37 @@ protected: } virtual int __CLR_OR_THIS_CALL do_max_length() const noexcept override { - // return maximum length required for a conversion - return 4; + // return maximum length required for a conversion (from codecvt) + return static_cast(_Cvt._Mbcurmax); } virtual int __CLR_OR_THIS_CALL do_encoding() const noexcept override { // return length of code sequence (from codecvt) - return 0; // varying length + return _Cvt._Mbcurmax == 1; // 0 => varying length, 1 => fixed length } + +private: + _Locinfo::_Cvtvec _Cvt; // locale info passed to _Mbrtowc, _Wcrtomb }; -#endif // defined(__cpp_char8_t) && !defined(_M_CEE_PURE) -// CLASS codecvt +#ifdef _NATIVE_WCHAR_T_DEFINED +// CLASS codecvt template <> -class _CRTIMP2_PURE_IMPORT codecvt : public codecvt_base { - // facet for converting between wchar_t and char (_Byte) sequences +class _CRTIMP2_PURE_IMPORT codecvt : public codecvt_base { + // facet for converting between unsigned short and char sequences public: - using intern_type = wchar_t; + using intern_type = unsigned short; using extern_type = char; using state_type = mbstate_t; result __CLR_OR_THIS_CALL in(mbstate_t& _State, const char* _First1, const char* _Last1, const char*& _Mid1, - wchar_t* _First2, wchar_t* _Last2, wchar_t*& _Mid2) const { + unsigned short* _First2, unsigned short* _Last2, unsigned short*& _Mid2) const { // convert bytes [_First1, _Last1) to [_First2, _Last2) return do_in(_State, _First1, _Last1, _Mid1, _First2, _Last2, _Mid2); } - result __CLR_OR_THIS_CALL out(mbstate_t& _State, const wchar_t* _First1, const wchar_t* _Last1, - const wchar_t*& _Mid1, char* _First2, char* _Last2, char*& _Mid2) const { + result __CLR_OR_THIS_CALL out(mbstate_t& _State, const unsigned short* _First1, const unsigned short* _Last1, + const unsigned short*& _Mid1, char* _First2, char* _Last2, char*& _Mid2) const { // convert [_First1, _Last1) to bytes [_First2, _Last2) return do_out(_State, _First1, _Last1, _Mid1, _First2, _Last2, _Mid2); } @@ -2238,7 +2149,7 @@ public: int __CLR_OR_THIS_CALL length(mbstate_t& _State, const char* _First1, const char* _Last1, size_t _Count) const { // return p - _First1, for the largest value p in [_First1, _Last1] such that [_First1, p) successfully - // converts to at most _Count wide characters + // converts to at most _Count _Elems return do_length(_State, _First1, _Last1, _Count); } @@ -2271,7 +2182,7 @@ protected: } virtual result __CLR_OR_THIS_CALL do_in(mbstate_t&, const char* _First1, const char* _Last1, const char*& _Mid1, - wchar_t* _First2, wchar_t* _Last2, wchar_t*& _Mid2) const { + unsigned short* _First2, unsigned short* _Last2, unsigned short*& _Mid2) const { // convert bytes [_First1, _Last1) to [_First2, _Last2) mbstate_t _Mystate{}; _Adl_verify_range(_First1, _Last1); @@ -2287,7 +2198,8 @@ protected: return partial; } - int _Bytes = _Mbrtowc(_Mid2, _Mid1, static_cast(_Last1 - _Mid1), &_Mystate, &_Cvt); + int _Bytes = _Mbrtowc( + reinterpret_cast(_Mid2), _Mid1, static_cast(_Last1 - _Mid1), &_Mystate, &_Cvt); switch (_Bytes) { case -2: // partial conversion return partial; @@ -2307,8 +2219,8 @@ protected: } } - virtual result __CLR_OR_THIS_CALL do_out(mbstate_t& _State, const wchar_t* _First1, const wchar_t* _Last1, - const wchar_t*& _Mid1, char* _First2, char* _Last2, char*& _Mid2) const { + virtual result __CLR_OR_THIS_CALL do_out(mbstate_t& _State, const unsigned short* _First1, + const unsigned short* _Last1, const unsigned short*& _Mid1, char* _First2, char* _Last2, char*& _Mid2) const { // convert [_First1, _Last1) to bytes [_First2, _Last2) _Adl_verify_range(_First1, _Last1); _Adl_verify_range(_First2, _Last2); @@ -2362,6 +2274,7 @@ protected: _CSTD memcpy(_Mid2, _Buf, static_cast(_Bytes)); _Mid2 += _Bytes; } + return _Ans; } @@ -2402,236 +2315,279 @@ protected: virtual int __CLR_OR_THIS_CALL do_encoding() const noexcept override { // return length of code sequence (from codecvt) - return _Cvt._Mbcurmax == 1; // 0 => varying length, 1 => fixed length + return _Cvt._Mbcurmax == 1u; // 0 => varying length, 1 => fixed length } private: _Locinfo::_Cvtvec _Cvt; // locale info passed to _Mbrtowc, _Wcrtomb }; +#endif // _NATIVE_WCHAR_T_DEFINED -#ifdef _NATIVE_WCHAR_T_DEFINED -// CLASS codecvt -template <> -class _CRTIMP2_PURE_IMPORT codecvt : public codecvt_base { - // facet for converting between unsigned short and char sequences +// CLASS TEMPLATE codecvt_byname +template +class codecvt_byname : public codecvt<_Elem, _Byte, _Statype> { // codecvt for named locale public: - using intern_type = unsigned short; - using extern_type = char; - using state_type = mbstate_t; + static_assert(!_ENFORCE_FACET_SPECIALIZATIONS + || _Is_any_of_v, codecvt_byname, +#endif // __cpp_char8_t + codecvt_byname, codecvt_byname>, + _FACET_SPECIALIZATION_MESSAGE); - result __CLR_OR_THIS_CALL in(mbstate_t& _State, const char* _First1, const char* _Last1, const char*& _Mid1, - unsigned short* _First2, unsigned short* _Last2, unsigned short*& _Mid2) const { - // convert bytes [_First1, _Last1) to [_First2, _Last2) - return do_in(_State, _First1, _Last1, _Mid1, _First2, _Last2, _Mid2); + explicit __CLR_OR_THIS_CALL codecvt_byname(const char* _Locname, size_t _Refs = 0) + : codecvt<_Elem, _Byte, _Statype>(_Locinfo(_Locname), _Refs) {} // construct for named locale + + explicit __CLR_OR_THIS_CALL codecvt_byname(const string& _Str, size_t _Refs = 0) + : codecvt<_Elem, _Byte, _Statype>(_Locinfo(_Str.c_str()), _Refs) {} // construct for named locale + +protected: + virtual __CLR_OR_THIS_CALL ~codecvt_byname() noexcept {} +}; + +// STRUCT ctype_base +struct _CRTIMP2_PURE_IMPORT ctype_base : locale::facet { // base for ctype + enum { // constants for character classifications + alnum = _DI | _LO | _UP | _XA, + alpha = _LO | _UP | _XA, + cntrl = _BB, + digit = _DI, + graph = _DI | _LO | _PU | _UP | _XA, + lower = _LO, + print = _DI | _LO | _PU | _SP | _UP | _XA | _XD, + punct = _PU, + space = _CN | _SP | _XS, + upper = _UP, + xdigit = _XD, + blank = _CN | _SP | _XS | _XB + }; + using mask = short; // to match + + __CLR_OR_THIS_CALL ctype_base(size_t _Refs = 0) : locale::facet(_Refs) {} + + __CLR_OR_THIS_CALL ~ctype_base() noexcept {} +}; + +// CLASS TEMPLATE ctype +template +class ctype : public ctype_base { // facet for classifying elements, converting cases +public: + // ctype, ctype, and ctype are explicitly specialized below. + static_assert(!_ENFORCE_FACET_SPECIALIZATIONS || _Always_false<_Elem>, _FACET_SPECIALIZATION_MESSAGE); + + using char_type = _Elem; + + bool __CLR_OR_THIS_CALL is(mask _Maskval, _Elem _Ch) const { // test if element fits any mask classifications + return do_is(_Maskval, _Ch); } - result __CLR_OR_THIS_CALL out(mbstate_t& _State, const unsigned short* _First1, const unsigned short* _Last1, - const unsigned short*& _Mid1, char* _First2, char* _Last2, char*& _Mid2) const { - // convert [_First1, _Last1) to bytes [_First2, _Last2) - return do_out(_State, _First1, _Last1, _Mid1, _First2, _Last2, _Mid2); + const _Elem* __CLR_OR_THIS_CALL is(const _Elem* _First, const _Elem* _Last, + mask* _Dest) const { // get mask sequence for elements in [_First, _Last) + return do_is(_First, _Last, _Dest); } - result __CLR_OR_THIS_CALL unshift(mbstate_t& _State, char* _First2, char* _Last2, char*& _Mid2) const { - // generate bytes to return to default shift state - return do_unshift(_State, _First2, _Last2, _Mid2); + const _Elem* __CLR_OR_THIS_CALL scan_is(mask _Maskval, const _Elem* _First, + const _Elem* _Last) const { // find first in [_First, _Last) that fits mask classification + return do_scan_is(_Maskval, _First, _Last); } - int __CLR_OR_THIS_CALL length(mbstate_t& _State, const char* _First1, const char* _Last1, size_t _Count) const { - // return p - _First1, for the largest value p in [_First1, _Last1] such that [_First1, p) successfully - // converts to at most _Count _Elems - return do_length(_State, _First1, _Last1, _Count); + const _Elem* __CLR_OR_THIS_CALL scan_not(mask _Maskval, const _Elem* _First, + const _Elem* _Last) const { // find first in [_First, _Last) not fitting mask classification + return do_scan_not(_Maskval, _First, _Last); + } + + _Elem __CLR_OR_THIS_CALL tolower(_Elem _Ch) const { // convert element to lower case + return do_tolower(_Ch); + } + + const _Elem* __CLR_OR_THIS_CALL tolower( + _Elem* _First, const _Elem* _Last) const { // convert [_First, _Last) in place to lower case + return do_tolower(_First, _Last); + } + + _Elem __CLR_OR_THIS_CALL toupper(_Elem _Ch) const { // convert element to upper case + return do_toupper(_Ch); + } + + const _Elem* __CLR_OR_THIS_CALL toupper( + _Elem* _First, const _Elem* _Last) const { // convert [_First, _Last) in place to upper case + return do_toupper(_First, _Last); + } + + _Elem __CLR_OR_THIS_CALL widen(char _Byte) const { // widen char + return do_widen(_Byte); + } + + const char* __CLR_OR_THIS_CALL widen(const char* _First, const char* _Last, + _Elem* _Dest) const { // widen chars in [_First, _Last) + return do_widen(_First, _Last, _Dest); + } + + char __CLR_OR_THIS_CALL narrow(_Elem _Ch, char _Dflt = '\0') const { // narrow element to char + return do_narrow(_Ch, _Dflt); + } + + const _Elem* __CLR_OR_THIS_CALL narrow(const _Elem* _First, const _Elem* _Last, char _Dflt, + char* _Dest) const { // narrow elements in [_First, _Last) to chars + return do_narrow(_First, _Last, _Dflt, _Dest); } __PURE_APPDOMAIN_GLOBAL static locale::id id; - explicit __CLR_OR_THIS_CALL codecvt(size_t _Refs = 0) : codecvt_base(_Refs) { + explicit __CLR_OR_THIS_CALL ctype(size_t _Refs = 0) : ctype_base(_Refs) { _BEGIN_LOCINFO(_Lobj) _Init(_Lobj); _END_LOCINFO() } - explicit __CLR_OR_THIS_CALL codecvt(const _Locinfo& _Lobj, size_t _Refs = 0) : codecvt_base(_Refs) { + __CLR_OR_THIS_CALL ctype(const _Locinfo& _Lobj, size_t _Refs = 0) : ctype_base(_Refs) { _Init(_Lobj); } static size_t __CLRCALL_OR_CDECL _Getcat(const locale::facet** _Ppf = nullptr, const locale* _Ploc = nullptr) { - // return locale category mask and construct standard facet if (_Ppf && !*_Ppf) { - *_Ppf = new codecvt(_Locinfo(_Ploc->c_str())); + *_Ppf = new ctype<_Elem>(_Locinfo(_Ploc->c_str())); + } + + return _X_CTYPE; + } + +protected: + virtual __CLR_OR_THIS_CALL ~ctype() noexcept { + if (_Ctype._Delfl) { + _CSTD free(const_cast(_Ctype._Table)); + } + + _CSTD free(_Ctype._LocaleName); + } + + void __CLR_OR_THIS_CALL _Init(const _Locinfo& _Lobj) { // initialize from _Lobj + _Ctype = _Lobj._Getctype(); + _Cvt = _Lobj._Getcvt(); + } + + virtual bool __CLR_OR_THIS_CALL do_is( + mask _Maskval, _Elem _Ch) const { // test if element fits any mask classifications + return (_Ctype._Table[static_cast(narrow(_Ch))] & _Maskval) != 0; + } + + virtual const _Elem* __CLR_OR_THIS_CALL do_is(const _Elem* _First, const _Elem* _Last, + mask* _Dest) const { // get mask sequence for elements in [_First, _Last) + _Adl_verify_range(_First, _Last); + for (; _First != _Last; ++_First, ++_Dest) { + *_Dest = _Ctype._Table[static_cast(narrow(*_First))]; } - return _X_CTYPE; + return _First; } -protected: - virtual __CLR_OR_THIS_CALL ~codecvt() noexcept {} + virtual const _Elem* __CLR_OR_THIS_CALL do_scan_is(mask _Maskval, const _Elem* _First, + const _Elem* _Last) const { // find first in [_First, _Last) that fits mask classification + _Adl_verify_range(_First, _Last); + while (_First != _Last && !is(_Maskval, *_First)) { + ++_First; + } - void __CLR_OR_THIS_CALL _Init(const _Locinfo& _Lobj) { // initialize from _Lobj - _Cvt = _Lobj._Getcvt(); + return _First; } - virtual result __CLR_OR_THIS_CALL do_in(mbstate_t&, const char* _First1, const char* _Last1, const char*& _Mid1, - unsigned short* _First2, unsigned short* _Last2, unsigned short*& _Mid2) const { - // convert bytes [_First1, _Last1) to [_First2, _Last2) - mbstate_t _Mystate{}; - _Adl_verify_range(_First1, _Last1); - _Adl_verify_range(_First2, _Last2); - _Mid1 = _First1; - _Mid2 = _First2; - for (;;) { - if (_Mid1 == _Last1) { - return ok; - } - - if (_Mid2 == _Last2) { - return partial; - } + virtual const _Elem* __CLR_OR_THIS_CALL do_scan_not(mask _Maskval, const _Elem* _First, + const _Elem* _Last) const { // find first in [_First, _Last) not fitting mask classification + _Adl_verify_range(_First, _Last); + while (_First != _Last && is(_Maskval, *_First)) { + ++_First; + } - int _Bytes = _Mbrtowc( - reinterpret_cast(_Mid2), _Mid1, static_cast(_Last1 - _Mid1), &_Mystate, &_Cvt); - switch (_Bytes) { - case -2: // partial conversion - return partial; + return _First; + } - case -1: // failed conversion - return error; + virtual _Elem __CLR_OR_THIS_CALL do_tolower(_Elem _Ch) const { // convert element to lower case + unsigned char _Byte = static_cast(narrow(_Ch, '\0')); + if (_Byte == '\0') { + return _Ch; + } - case 0: // converted NULL character, TRANSITION, VSO-654347 - _Bytes = 1; - // [[fallthrough]]; + return widen(static_cast(_Tolower(_Byte, &_Ctype))); + } - default: // converted some other character - _Mid1 += _Bytes; - ++_Mid2; - break; + virtual const _Elem* __CLR_OR_THIS_CALL do_tolower(_Elem* _First, + const _Elem* _Last) const { // convert [_First, _Last) in place to lower case + _Adl_verify_range(_First, _Last); + for (; _First != _Last; ++_First) { // convert *_First to lower case + unsigned char _Byte = static_cast(narrow(*_First, '\0')); + if (_Byte != '\0') { + *_First = (widen(static_cast(_Tolower(_Byte, &_Ctype)))); } } + return _First; } - virtual result __CLR_OR_THIS_CALL do_out(mbstate_t& _State, const unsigned short* _First1, - const unsigned short* _Last1, const unsigned short*& _Mid1, char* _First2, char* _Last2, char*& _Mid2) const { - // convert [_First1, _Last1) to bytes [_First2, _Last2) - _Adl_verify_range(_First1, _Last1); - _Adl_verify_range(_First2, _Last2); - _Mid1 = _First1; - _Mid2 = _First2; - int _Bytes; + virtual _Elem __CLR_OR_THIS_CALL do_toupper(_Elem _Ch) const { // convert element to upper case + unsigned char _Byte = static_cast(narrow(_Ch, '\0')); + if (_Byte == '\0') { + return _Ch; + } - while (_Mid1 != _Last1 && _Mid2 != _Last2) { - if (MB_LEN_MAX <= _Last2 - _Mid2) { - if ((_Bytes = _Wcrtomb(_Mid2, *_Mid1, &_State, &_Cvt)) < 0) { - return error; // locale-specific wcrtomb failed - } else { - ++_Mid1; - _Mid2 += _Bytes; - } - } else { // destination too small, convert into buffer - char _Buf[MB_LEN_MAX]; - mbstate_t _Stsave = _State; + return widen(static_cast(_Toupper(_Byte, &_Ctype))); + } - if ((_Bytes = _Wcrtomb(_Buf, *_Mid1, &_State, &_Cvt)) < 0) { - return error; // locale-specific wcrtomb failed - } else if (_Last2 - _Mid2 < _Bytes) { // converted too many, roll back and return previous - _State = _Stsave; - break; - } else { // copy converted bytes from buffer - _CSTD memcpy(_Mid2, _Buf, static_cast(_Bytes)); - ++_Mid1; - _Mid2 += _Bytes; - } + virtual const _Elem* __CLR_OR_THIS_CALL do_toupper(_Elem* _First, + const _Elem* _Last) const { // convert [_First, _Last) in place to upper case + _Adl_verify_range(_First, _Last); + for (; _First != _Last; ++_First) { // convert *_First to upper case + unsigned char _Byte = static_cast(narrow(*_First, '\0')); + if (_Byte != '\0') { + *_First = (widen(static_cast(_Toupper(_Byte, &_Ctype)))); } } - return _Mid1 == _Last1 ? ok : partial; + return _First; } - virtual result __CLR_OR_THIS_CALL do_unshift(mbstate_t& _State, char* _First2, char* _Last2, char*& _Mid2) const { - // generate bytes to return to default shift state - _Adl_verify_range(_First2, _Last2); - _Mid2 = _First2; - result _Ans = ok; - int _Bytes; - char _Buf[MB_LEN_MAX]; - mbstate_t _Stsave = _State; + virtual _Elem __CLR_OR_THIS_CALL do_widen(char _Byte) const { // widen char + return _Maklocchr(_Byte, static_cast<_Elem*>(nullptr), _Cvt); + } - if ((_Bytes = _Wcrtomb(_Buf, L'\0', &_State, &_Cvt)) <= 0) { - _Ans = error; // locale-specific wcrtomb failed - } else if (_Last2 - _Mid2 < --_Bytes) { // converted too many, roll back and return - _State = _Stsave; - _Ans = partial; - } else if (0 < _Bytes) { // copy converted bytes from buffer - _CSTD memcpy(_Mid2, _Buf, static_cast(_Bytes)); - _Mid2 += _Bytes; + virtual const char* __CLR_OR_THIS_CALL do_widen( + const char* _First, const char* _Last, _Elem* _Dest) const { // widen chars in [_First, _Last) + _Adl_verify_range(_First, _Last); + for (; _First != _Last; ++_First, ++_Dest) { + *_Dest = _Maklocchr(*_First, static_cast<_Elem*>(nullptr), _Cvt); } - return _Ans; + return _First; } - virtual int __CLR_OR_THIS_CALL do_length( - mbstate_t& _State, const char* _First1, const char* _Last1, size_t _Count) const { - // return p - _First1, for the largest value p in [_First1, _Last1] such that [_First1, p) successfully - // converts to at most _Count wide characters - _Adl_verify_range(_First1, _Last1); - const auto _Old_first1 = _First1; - - for (; _Count > 0u && _First1 != _Last1; --_Count) { - wchar_t _Ch; - int _Bytes = _Mbrtowc(&_Ch, _First1, static_cast(_Last1 - _First1), &_State, &_Cvt); - if (_Bytes < 0) { // partial or failed conversion - break; - } - - if (_Bytes == 0) { // converted NULL character, TRANSITION, VSO-654347 - _Bytes = 1; - } + char __CLR_OR_THIS_CALL _Donarrow(_Elem _Ch, char _Dflt) const { // narrow element to char + char _Byte; + if (_Ch == _Elem{}) { + return '\0'; + } - // converted _Bytes bytes to a wide character - _First1 += _Bytes; + if ((_Byte = _Maklocbyte(_Ch, _Cvt)) == '\0') { + return _Dflt; } - return static_cast((_STD min)(_First1 - _Old_first1, ptrdiff_t{INT_MAX})); + return _Byte; } - virtual bool __CLR_OR_THIS_CALL do_always_noconv() const noexcept override { - // return true if conversions never change input - return false; + virtual char __CLR_OR_THIS_CALL do_narrow(_Elem _Ch, char _Dflt) const { // narrow element to char + return _Donarrow(_Ch, _Dflt); } - virtual int __CLR_OR_THIS_CALL do_max_length() const noexcept override { - // return maximum length required for a conversion (from codecvt) - return static_cast(_Cvt._Mbcurmax); - } + virtual const _Elem* __CLR_OR_THIS_CALL do_narrow(const _Elem* _First, const _Elem* _Last, char _Dflt, + char* _Dest) const { // narrow elements in [_First, _Last) to chars + _Adl_verify_range(_First, _Last); + for (; _First != _Last; ++_First, ++_Dest) { + *_Dest = _Donarrow(*_First, _Dflt); + } - virtual int __CLR_OR_THIS_CALL do_encoding() const noexcept override { - // return length of code sequence (from codecvt) - return _Cvt._Mbcurmax == 1u; // 0 => varying length, 1 => fixed length + return _First; } private: - _Locinfo::_Cvtvec _Cvt; // locale info passed to _Mbrtowc, _Wcrtomb -}; -#endif // _NATIVE_WCHAR_T_DEFINED - -// CLASS TEMPLATE codecvt_byname -template -class codecvt_byname : public codecvt<_Elem, _Byte, _Statype> { // codecvt for named locale -public: - static_assert(!_ENFORCE_FACET_SPECIALIZATIONS - || _Is_any_of_v, codecvt_byname, -#endif // __cpp_char8_t - codecvt_byname, codecvt_byname>, - _FACET_SPECIALIZATION_MESSAGE); - - explicit __CLR_OR_THIS_CALL codecvt_byname(const char* _Locname, size_t _Refs = 0) - : codecvt<_Elem, _Byte, _Statype>(_Locinfo(_Locname), _Refs) {} // construct for named locale - - explicit __CLR_OR_THIS_CALL codecvt_byname(const string& _Str, size_t _Refs = 0) - : codecvt<_Elem, _Byte, _Statype>(_Locinfo(_Str.c_str()), _Refs) {} // construct for named locale - -protected: - virtual __CLR_OR_THIS_CALL ~codecvt_byname() noexcept {} + _Locinfo::_Ctypevec _Ctype; // locale info passed to _Tolower, etc. + _Locinfo::_Cvtvec _Cvt; // conversion information }; // STATIC ctype::id OBJECT @@ -3264,6 +3220,50 @@ protected: virtual __CLR_OR_THIS_CALL ~ctype_byname() noexcept {} }; +// FUNCTION TEMPLATE _Getloctxt +template +int __CRTDECL _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields, const _Elem* _Ptr) { + // find field at _Ptr that matches longest in [_First, _Last) + for (size_t _Off = 0; _Ptr[_Off] != _Elem{}; ++_Off) { + if (_Ptr[_Off] == _Ptr[0]) { + ++_Numfields; // add fields with leading mark to initial count + } + } + + string _Str(_Numfields, '\0'); // one column counter for each field + const ctype<_Elem>& _CType = _STD use_facet>(locale{}); + + int _Ans = -2; // no candidates so far + for (size_t _Column = 1;; ++_Column, (void) ++_First, _Ans = -1) { // test each element against all viable fields + bool _Prefix = false; // seen at least one valid prefix + size_t _Off = 0; // offset into fields + size_t _Field = 0; // current field number + + for (; _Field < _Numfields; ++_Field) { // test element at _Column in field _Field + while (_Ptr[_Off] != _Elem{} && _Ptr[_Off] != _Ptr[0]) { // find beginning of field + ++_Off; + } + + if (_Str[_Field] != '\0') { + _Off += _Str[_Field]; // skip tested columns in field + } else if (_Ptr[_Off += _Column] == _Ptr[0] + || _Ptr[_Off] == _Elem{}) { // matched all of field, save as possible answer + _Str[_Field] = static_cast(_Column < 127 ? _Column : 127); // save skip count if small enough + _Ans = static_cast(_Field); // save answer + } else if (_First == _Last || _CType.tolower(_Ptr[_Off]) != _CType.tolower(static_cast<_Elem>(*_First))) { + _Str[_Field] = static_cast(_Column < 127 ? _Column : 127); // no match, just save skip count + } else { + _Prefix = true; // still a valid prefix + } + } + + if (!_Prefix || _First == _Last) { + break; // no pending prefixes or no input, give up + } + } + return _Ans; // return field number or negative value on failure +} + #if defined(_DLL_CPPLIB) #if !defined(_CRTBLD) || defined(__FORCE_INSTANCE) template class _CRTIMP2_PURE_IMPORT codecvt;