Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix boolalpha extraction to be case-sensitive again #1543

Merged
merged 2 commits into from
Jan 15, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions stl/inc/xlocale
Original file line number Diff line number Diff line change
Expand Up @@ -3242,8 +3242,11 @@ protected:
};

// FUNCTION TEMPLATE _Getloctxt
template <class _Elem, class _InIt>
int __CRTDECL _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields, const _Elem* _Ptr) {
enum class _Case_sensitive : bool { _No, _Yes };

template <class _InIt, class _Elem>
int __CRTDECL _Getloctxt(
_InIt& _First, _InIt& _Last, size_t _Numfields, const _Elem* _Ptr, const _Case_sensitive _Matching) {
// find field at _Ptr that matches longest in [_First, _Last)
for (size_t _Off = 0; _Ptr[_Off] != _Elem{}; ++_Off) {
if (_Ptr[_Off] == _Ptr[0]) {
Expand Down Expand Up @@ -3271,7 +3274,10 @@ 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<char>(_Column < 127 ? _Column : 127); // save skip count if small enough
_Ans = static_cast<int>(_Field); // save answer
} else if (_First == _Last || _CType.tolower(_Ptr[_Off]) != _CType.tolower(static_cast<_Elem>(*_First))) {
} else if (_First == _Last
|| (_Matching == _Case_sensitive::_Yes
? _Ptr[_Off] != *_First
: _CType.tolower(_Ptr[_Off]) != _CType.tolower(static_cast<_Elem>(*_First)))) {
_Str[_Field] = static_cast<char>(_Column < 127 ? _Column : 127); // no match, just save skip count
} else {
_Prefix = true; // still a valid prefix
Expand Down
2 changes: 1 addition & 1 deletion stl/inc/xlocnum
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ protected:
_Str += _Punct_fac.falsename();
_Str.push_back(_Elem{});
_Str += _Punct_fac.truename(); // construct "\0false\0true"
switch (_Getloctxt(_First, _Last, 2, _Str.c_str())) {
switch (_Getloctxt(_First, _Last, 2, _Str.c_str(), _Case_sensitive::_Yes)) {
case 0:
_Val = false;
break;
Expand Down
6 changes: 3 additions & 3 deletions stl/inc/xloctime
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ protected:

virtual _InIt __CLR_OR_THIS_CALL do_get_weekday(_InIt _First, _InIt _Last, ios_base&, ios_base::iostate& _State,
tm* _Pt) const { // get weekday from [_First, _Last) into _Pt
int _Num = _Getloctxt(_First, _Last, 0, _Days);
int _Num = _Getloctxt(_First, _Last, 0, _Days, _Case_sensitive::_No);
if (_Num < 0) {
_State |= ios_base::failbit;
} else {
Expand All @@ -338,7 +338,7 @@ protected:

virtual _InIt __CLR_OR_THIS_CALL do_get_monthname(_InIt _First, _InIt _Last, ios_base&, ios_base::iostate& _State,
tm* _Pt) const { // get month from [_First, _Last) into _Pt
int _Num = _Getloctxt(_First, _Last, 0, _Months);
int _Num = _Getloctxt(_First, _Last, 0, _Months, _Case_sensitive::_No);

if (_Num < 0) {
_State |= ios_base::failbit;
Expand Down Expand Up @@ -444,7 +444,7 @@ protected:
break;

case 'p':
_Ans = _Getloctxt(_First, _Last, 0, ":AM:am:PM:pm");
_Ans = _Getloctxt(_First, _Last, 0, ":AM:am:PM:pm", _Case_sensitive::_No);
if (_Ans < 0) {
_State |= ios_base::failbit;
} else if (1 < _Ans) {
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ tests\GH_001103_countl_zero_correctness
tests\GH_001105_custom_streambuf_throws
tests\GH_001123_random_cast_out_of_range
tests\GH_001411_core_headers
tests\GH_001541_case_sensitive_boolalpha
tests\LWG2597_complex_branch_cut
tests\LWG3018_shared_ptr_function
tests\P0019R8_atomic_ref
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/GH_001541_case_sensitive_boolalpha/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_matrix.lst
41 changes: 41 additions & 0 deletions tests/std/tests/GH_001541_case_sensitive_boolalpha/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <cassert>
#include <ios>
#include <sstream>
using namespace std;

enum class Parse { Success, Failure };

struct TestCase {
const char* str;
ios_base::fmtflags flags;
Parse expected;
bool result;
};

// clang-format off
constexpr TestCase test_cases[] = {
{"0", ios_base::fmtflags{}, Parse::Success, false},
{"1", ios_base::fmtflags{}, Parse::Success, true },
{"2", ios_base::fmtflags{}, Parse::Failure, true }, // N4868 [facet.num.get.virtuals]/6
{"WOOF", ios_base::fmtflags{}, Parse::Failure, false}, // N4868 [facet.num.get.virtuals]/3.6
{"false", ios_base::boolalpha, Parse::Success, false},
{"true", ios_base::boolalpha, Parse::Success, true },
{"WOOF", ios_base::boolalpha, Parse::Failure, false}, // N4868 [facet.num.get.virtuals]/7
{"FALSE", ios_base::boolalpha, Parse::Failure, false}, // GH-1541
{"TRUE", ios_base::boolalpha, Parse::Failure, false}, // GH-1541
};
// clang-format on

int main() {
for (const auto& test : test_cases) {
bool val = !test.result;
istringstream iss(test.str);
iss.setf(test.flags);
iss >> val;
assert(iss.fail() == (test.expected == Parse::Failure));
assert(val == test.result);
}
}