mirror of
https://github.com/Microsoft/calculator.git
synced 2025-08-22 06:13:14 -07:00
General improvement of the CopyPasteManager:
- Reject expressions like '4 8 15' (the current app ignores spaces and understands 4815) - Accept 16e23 and not only 16e+23 - ignore more types of white spaces characters - remove Calculator::IsValidRegularExpression (was buggy and not used) - Simplify prototype of ValidatePasteExpression (return a bool instead of a string we didn't need) - simplify regex
This commit is contained in:
parent
1eb717f336
commit
c0cfe54c51
8 changed files with 152 additions and 139 deletions
|
@ -25,39 +25,42 @@ String^ CopyPasteManager::supportedFormats[] =
|
|||
|
||||
constexpr wstring_view c_validCharacterSet{ L"0123456789()+-*/.abcdefABCDEF" };
|
||||
// [\s\x85] means white-space characters
|
||||
static const wstring c_wspc = L"[\\s\\x85]*";
|
||||
static const wstring c_wspcLParens = c_wspc + L"[(]*" + c_wspc;
|
||||
static const wstring c_wspcRParens = c_wspc + L"[)]*" + c_wspc;
|
||||
static const wstring c_wspcLParens = L"[(]*";
|
||||
static const wstring c_wspcRParens = L"[)]*";
|
||||
static const wstring c_signedDecFloat = L"[-+]?\\d*(\\d|[.])\\d*";
|
||||
|
||||
// Programmer Mode Integer patterns
|
||||
// Support digit separators ` (WinDbg/MASM), ' (C++), and _ (C# and other languages)
|
||||
static const wstring c_hexProgrammerChars = L"([a-f]|[A-F]|\\d)+((_|'|`)([a-f]|[A-F]|\\d)+)*";
|
||||
static const wstring c_decProgrammerChars = L"\\d+((_|'|`)\\d+)*";
|
||||
static const wstring c_octProgrammerChars = L"[0-7]+((_|'|`)[0-7]+)*";
|
||||
static const wstring c_binProgrammerChars = L"[0-1]+((_|'|`)[0-1]+)*";
|
||||
static const wstring c_hexProgrammerChars = L"[a-fA-F0-9]+([_'`][a-fA-F0-9]+)*";
|
||||
static const wstring c_decProgrammerChars = L"\\d+([_'`]\\d+)*";
|
||||
static const wstring c_octProgrammerChars = L"[0-7]+([_'`][0-7]+)*";
|
||||
static const wstring c_binProgrammerChars = L"[0-1]+([_'`][0-1]+)*";
|
||||
static const wstring c_uIntSuffixes = L"[uU]?[lL]{0,2}";
|
||||
|
||||
// Regex used to format the string coming from the clipboard
|
||||
static const wstring c_formatSpaces = L"[\\s\\x85]+";
|
||||
static const wstring c_formatTrimAndRemoveUselessChars = L"^ | $|,|\"";
|
||||
|
||||
// RegEx Patterns used by various modes
|
||||
static const array<wregex, 1> standardModePatterns =
|
||||
{
|
||||
wregex(c_wspc + c_signedDecFloat + c_wspc)
|
||||
wregex(c_signedDecFloat)
|
||||
};
|
||||
static const array<wregex, 2> scientificModePatterns =
|
||||
{
|
||||
wregex(c_wspcLParens + c_signedDecFloat + c_wspcRParens),
|
||||
wregex(c_wspcLParens + c_signedDecFloat + L"[e]([+]|[-])+\\d+" + c_wspcRParens)
|
||||
wregex(c_wspcLParens + c_signedDecFloat + L"e[+-]?\\d+" + c_wspcRParens)
|
||||
};
|
||||
static const array<array<wregex, 5>, 4> programmerModePatterns =
|
||||
{ {
|
||||
// Hex numbers like 5F, 4A0C, 0xa9, 0xFFull, 47CDh
|
||||
{
|
||||
wregex(c_wspcLParens + L"(0[xX])?" + c_hexProgrammerChars + c_uIntSuffixes + c_wspcRParens),
|
||||
wregex(c_wspcLParens + c_hexProgrammerChars + L"[hH]?" + c_wspcRParens)
|
||||
},
|
||||
// Hex numbers like 5F, 4A0C, 0xa9, 0xFFull, 47CDh
|
||||
{
|
||||
wregex(c_wspcLParens + L"(0[xX])?" + c_hexProgrammerChars + c_uIntSuffixes + c_wspcRParens),
|
||||
wregex(c_wspcLParens + c_hexProgrammerChars + L"[hH]?" + c_wspcRParens)
|
||||
},
|
||||
// Decimal numbers like -145, 145, 0n145, 123ull etc
|
||||
{
|
||||
wregex(c_wspcLParens + L"[-+]?" + c_decProgrammerChars + L"[lL]{0,2}" +c_wspcRParens),
|
||||
wregex(c_wspcLParens + L"[-+]?" + c_decProgrammerChars + L"[lL]{0,2}" + c_wspcRParens),
|
||||
wregex(c_wspcLParens + L"(0[nN])?" + c_decProgrammerChars + c_uIntSuffixes + c_wspcRParens)
|
||||
},
|
||||
// Octal numbers like 06, 010, 0t77, 0o77, 077ull etc
|
||||
|
@ -72,9 +75,29 @@ static const array<array<wregex, 5>, 4> programmerModePatterns =
|
|||
} };
|
||||
static const array<wregex, 1> unitConverterPatterns =
|
||||
{
|
||||
wregex(c_wspc + L"[-+]?\\d*[.]?\\d*" + c_wspc)
|
||||
wregex(c_signedDecFloat)
|
||||
};
|
||||
|
||||
|
||||
//Used by ExtractOperands
|
||||
//Trim extra blank space before and after the string we want to extract (c_formatSpaces already replaces the sequences of white spaces by a single blank character)
|
||||
std::wstring _subStrWithBasicTrim(const std::wstring & text, unsigned int pos, unsigned int len)
|
||||
{
|
||||
if (len == 0)
|
||||
{
|
||||
return wstring();
|
||||
}
|
||||
if (text[pos] == ' ')
|
||||
{
|
||||
++pos;
|
||||
--len;
|
||||
}
|
||||
|
||||
if (text[pos + len - 1] == ' ')
|
||||
--len;
|
||||
return text.substr(pos, len);
|
||||
}
|
||||
|
||||
void CopyPasteManager::CopyToClipboard(String^ stringToCopy)
|
||||
{
|
||||
// Copy the string to the clipboard
|
||||
|
@ -89,14 +112,15 @@ task<String^> CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupTyp
|
|||
auto dataPackageView = Clipboard::GetContent();
|
||||
|
||||
// TODO: Support all formats supported by ClipboardHasText
|
||||
//-- add support to avoid pasting of expressions like 12 34(as of now we allow 1234)
|
||||
//-- add support to allow pasting for expressions like .2 , -.2
|
||||
//-- add support to allow pasting for expressions like 1.3e12(as of now we allow 1.3e+12)
|
||||
|
||||
return create_task((dataPackageView->GetTextAsync(::StandardDataFormats::Text)))
|
||||
.then([mode, modeType, programmerNumberBase, bitLengthType](String^ pastedText)
|
||||
{
|
||||
return ValidatePasteExpression(pastedText, mode, modeType, programmerNumberBase, bitLengthType);
|
||||
if (ValidatePasteExpression(pastedText, mode, modeType, programmerNumberBase, bitLengthType))
|
||||
{
|
||||
return pastedText;
|
||||
}
|
||||
return ref new String(PasteErrorString);
|
||||
}
|
||||
, task_continuation_context::use_arbitrary());
|
||||
}
|
||||
|
@ -118,29 +142,36 @@ int CopyPasteManager::ClipboardTextFormat()
|
|||
return result;
|
||||
}
|
||||
|
||||
String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode mode, int programmerNumberBase, int bitLengthType)
|
||||
bool CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode mode, int programmerNumberBase, int bitLengthType)
|
||||
{
|
||||
return CopyPasteManager::ValidatePasteExpression(pastedText, mode, NavCategory::GetGroupType(mode), programmerNumberBase, bitLengthType);
|
||||
}
|
||||
|
||||
// return "NoOp" if pastedText is invalid else return pastedText
|
||||
|
||||
String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
|
||||
bool CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
|
||||
{
|
||||
if (pastedText->Length() > MaxPasteableLength)
|
||||
{
|
||||
// return NoOp to indicate don't paste anything.
|
||||
TraceLogger::GetInstance().LogInvalidInputPasted(L"PastedExpressionSizeGreaterThanMaxAllowed", L"MoreThanMaxInput", mode, programmerNumberBase, bitLengthType);
|
||||
return StringReference(PasteErrorString);
|
||||
return false;
|
||||
}
|
||||
|
||||
wstring pasteExpression = pastedText->Data();
|
||||
|
||||
// Verify if string contains the en-US digit separator if the local digit separator is a different one.
|
||||
wchar_t localDigitSeparator = LocalizationSettings::GetInstance().GetDecimalSeparator();
|
||||
if (localDigitSeparator != '.' && pasteExpression.find('.') != std::string::npos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get english translated expression
|
||||
String^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pasteExpression);
|
||||
|
||||
// Removing the spaces, comma separator from the pasteExpression to allow pasting of expressions like 1 + 2+1,333
|
||||
pasteExpression = Utils::RemoveUnwantedCharsFromWstring(englishString->Data());
|
||||
//replace all sequences of whitespace characters by 1 single blank space character (u+0020).
|
||||
pasteExpression = regex_replace(englishString->Data(), wregex(c_formatSpaces),
|
||||
mode == ViewMode::Programmer? L"" : L" ");
|
||||
//Trim the string and remove commas
|
||||
pasteExpression = regex_replace(pasteExpression, wregex(c_formatTrimAndRemoveUselessChars), L"");
|
||||
|
||||
// If the last character is an = sign, remove it from the pasteExpression to allow evaluating the result on paste.
|
||||
if (!pasteExpression.empty() && pasteExpression.back() == L'=')
|
||||
|
@ -153,8 +184,7 @@ String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode m
|
|||
vector<wstring> operands = ExtractOperands(pasteExpression, mode, programmerNumberBase, bitLengthType);
|
||||
if (operands.empty())
|
||||
{
|
||||
// return NoOp to indicate don't paste anything.
|
||||
return StringReference(PasteErrorString);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (modeType == CategoryGroupType::Converter)
|
||||
|
@ -166,10 +196,10 @@ String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode m
|
|||
if (!ExpressionRegExMatch(operands, mode, modeType, programmerNumberBase, bitLengthType))
|
||||
{
|
||||
TraceLogger::GetInstance().LogInvalidInputPasted(L"InvalidExpressionForPresentMode", pastedText->Data(), mode, programmerNumberBase, bitLengthType);
|
||||
return StringReference(PasteErrorString);
|
||||
return false;
|
||||
}
|
||||
|
||||
return ref new String(pastedText->Data());
|
||||
return true;
|
||||
}
|
||||
|
||||
vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression, ViewMode mode, int programmerNumberBase, int bitLengthType)
|
||||
|
@ -236,7 +266,7 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
|
|||
expLength = 0;
|
||||
haveOperator = true;
|
||||
isPreviousOperator = true;
|
||||
operands.push_back(pasteExpression.substr(lastIndex, i - lastIndex));
|
||||
operands.push_back(_subStrWithBasicTrim(pasteExpression, lastIndex, i - lastIndex));
|
||||
lastIndex = i + 1;
|
||||
}
|
||||
else
|
||||
|
@ -255,7 +285,7 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
|
|||
}
|
||||
else
|
||||
{
|
||||
operands.push_back(pasteExpression.substr(lastIndex, pasteExpression.length() - 1));
|
||||
operands.push_back(_subStrWithBasicTrim(pasteExpression, lastIndex, pasteExpression.length() - lastIndex));
|
||||
}
|
||||
|
||||
return operands;
|
||||
|
@ -298,7 +328,11 @@ bool CopyPasteManager::ExpressionRegExMatch(vector<wstring> operands, ViewMode m
|
|||
bool operandMatched = false;
|
||||
for (const wregex& pattern : patterns)
|
||||
{
|
||||
operandMatched = operandMatched || regex_match(operand, pattern);
|
||||
if (regex_match(operand, pattern))
|
||||
{
|
||||
operandMatched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (operandMatched)
|
||||
|
|
|
@ -37,12 +37,12 @@ namespace CalculatorApp
|
|||
|
||||
private:
|
||||
static int ClipboardTextFormat();
|
||||
static Platform::String^ ValidatePasteExpression(
|
||||
static bool ValidatePasteExpression(
|
||||
Platform::String^ pastedText,
|
||||
CalculatorApp::Common::ViewMode mode,
|
||||
int programmerNumberBase,
|
||||
int bitLengthType);
|
||||
static Platform::String^ ValidatePasteExpression(
|
||||
static bool ValidatePasteExpression(
|
||||
Platform::String^ pastedText,
|
||||
CalculatorApp::Common::ViewMode mode,
|
||||
CalculatorApp::Common::CategoryGroupType modeType,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
//
|
||||
|
@ -86,13 +86,6 @@ bool Utils::IsLastCharacterTarget(_In_ wstring const &input, _In_ wchar_t target
|
|||
return !input.empty() && input.back() == target;
|
||||
}
|
||||
|
||||
//return wstring after removing characters like space, comma, and double quotes
|
||||
wstring Utils::RemoveUnwantedCharsFromWstring(wstring input)
|
||||
{
|
||||
wchar_t unWantedChars[] = { L' ', L',', L'"', 8234, 8235, 8236, 8237 };
|
||||
return RemoveUnwantedCharsFromWstring(input, unWantedChars, 6);
|
||||
}
|
||||
|
||||
//return wstring after removing characters specified by unwantedChars array
|
||||
wstring Utils::RemoveUnwantedCharsFromWstring(wstring input, wchar_t* unwantedChars, unsigned int size)
|
||||
{
|
||||
|
|
|
@ -280,7 +280,6 @@ namespace Utils
|
|||
Platform::String^ GetStringValue(Platform::String^ input);
|
||||
bool IsLastCharacterTarget(std::wstring const &input, wchar_t target);
|
||||
std::wstring RemoveUnwantedCharsFromWstring(std::wstring inputString, wchar_t* unwantedChars, unsigned int size);
|
||||
std::wstring RemoveUnwantedCharsFromWstring(std::wstring input);
|
||||
double GetDoubleFromWstring(std::wstring input);
|
||||
int GetWindowId();
|
||||
void RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ Windows::UI::Core::CoreDispatcher^ currentDispatcher);
|
||||
|
|
|
@ -862,14 +862,26 @@ void StandardCalculatorViewModel::OnPaste(String^ pastedString, ViewMode mode)
|
|||
if (mappedNumOp == NumbersAndOperatorsEnum::Exp)
|
||||
{
|
||||
++it;
|
||||
if (!(MapCharacterToButtonId(*it, canSendNegate) == NumbersAndOperatorsEnum::Add))
|
||||
switch (MapCharacterToButtonId(*it, canSendNegate))
|
||||
{
|
||||
Command cmdNegate = ConvertToOperatorsEnum(NumbersAndOperatorsEnum::Negate);
|
||||
m_standardCalculatorManager.SendCommand(cmdNegate);
|
||||
case NumbersAndOperatorsEnum::Subtract:
|
||||
{
|
||||
Command cmdNegate = ConvertToOperatorsEnum(NumbersAndOperatorsEnum::Negate);
|
||||
m_standardCalculatorManager.SendCommand(cmdNegate);
|
||||
++it;
|
||||
}
|
||||
break;
|
||||
case NumbersAndOperatorsEnum::Add:
|
||||
{
|
||||
++it;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++it;
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1400,29 +1412,29 @@ void StandardCalculatorViewModel::SaveEditedCommand(_In_ unsigned int tokenPosit
|
|||
|
||||
switch (nOpCode)
|
||||
{
|
||||
case static_cast<int>(Command::CommandASIN) :
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast<int>(Command::CommandSIN), true, angleType);
|
||||
break;
|
||||
case static_cast<int>(Command::CommandACOS) :
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast<int>(Command::CommandCOS), true, angleType);
|
||||
break;
|
||||
case static_cast<int>(Command::CommandATAN) :
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast<int>(Command::CommandTAN), true, angleType);
|
||||
break;
|
||||
case static_cast<int>(Command::CommandASINH) :
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast<int>(Command::CommandSINH), true, angleType);
|
||||
break;
|
||||
case static_cast<int>(Command::CommandACOSH) :
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast<int>(Command::CommandCOSH), true, angleType);
|
||||
break;
|
||||
case static_cast<int>(Command::CommandATANH) :
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast<int>(Command::CommandTANH), true, angleType);
|
||||
break;
|
||||
case static_cast<int>(Command::CommandPOWE) :
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast<int>(Command::CommandLN), true, angleType);
|
||||
break;
|
||||
default:
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(nOpCode, false, angleType);
|
||||
case static_cast<int>(Command::CommandASIN) :
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast<int>(Command::CommandSIN), true, angleType);
|
||||
break;
|
||||
case static_cast<int>(Command::CommandACOS) :
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast<int>(Command::CommandCOS), true, angleType);
|
||||
break;
|
||||
case static_cast<int>(Command::CommandATAN) :
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast<int>(Command::CommandTAN), true, angleType);
|
||||
break;
|
||||
case static_cast<int>(Command::CommandASINH) :
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast<int>(Command::CommandSINH), true, angleType);
|
||||
break;
|
||||
case static_cast<int>(Command::CommandACOSH) :
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast<int>(Command::CommandCOSH), true, angleType);
|
||||
break;
|
||||
case static_cast<int>(Command::CommandATANH) :
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast<int>(Command::CommandTANH), true, angleType);
|
||||
break;
|
||||
case static_cast<int>(Command::CommandPOWE) :
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast<int>(Command::CommandLN), true, angleType);
|
||||
break;
|
||||
default:
|
||||
updatedToken = CCalcEngine::OpCodeToUnaryString(nOpCode, false, angleType);
|
||||
}
|
||||
if ((token.first.length() > 0) && (token.first[token.first.length() - 1] == L'('))
|
||||
{
|
||||
|
|
|
@ -690,28 +690,6 @@ void Calculator::expressionContainer_LayoutUpdated(_In_ Object^ sender, _In_ Obj
|
|||
expressionText->UpdateScrollButtons();
|
||||
}
|
||||
|
||||
bool Calculator::IsValidRegularExpression(std::wstring str)
|
||||
{
|
||||
bool result = false;
|
||||
std::wregex regexPatterns[3];
|
||||
regexPatterns[0] = L"[-]{0,1}[0-9]{0,}[.]{0,1}[0-9]{0,}";
|
||||
regexPatterns[1] = L"[-]{0,1}[0-9]{0,}[.]{0,1}[0-9]{0,}[e]{1}[+]{1}[0-9]{1,}";
|
||||
regexPatterns[2] = L"[-]{0,1}[0-9]{0,}[.]{0,1}[0-9]{0,}[e]{1}[-]{1}[0-9]{1,}";
|
||||
|
||||
const auto& localizer = LocalizationSettings::GetInstance();
|
||||
String^ englishString = localizer.GetEnglishValueFromLocalizedDigits(str);
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
if (regex_match(englishString->Data(), regexPatterns[i]))
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Calculator::DockPanelTapped(_In_ TappedRoutedEventArgs^ e)
|
||||
{
|
||||
int index = DockPivot->SelectedIndex;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
@ -131,7 +131,6 @@ namespace CalculatorApp
|
|||
void OnMemoryFlyOutTapped(_In_ Platform::Object^ sender, _In_ Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e);
|
||||
void OnHistoryFlyOutTapped(_In_ Platform::Object^ sender, _In_ Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e);
|
||||
void expressionContainer_LayoutUpdated(_In_ Platform::Object^ sender, _In_ Platform::Object^ e);
|
||||
bool IsValidRegularExpression(std::wstring str);
|
||||
void DockPanelTapped(_In_ Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e);
|
||||
void OnResultsLayoutChanged(_In_ Platform::Object^ sender, _In_ Platform::Object^ e);
|
||||
void SetResultStyles();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
|
@ -28,7 +28,7 @@ namespace CalculatorUnitTests
|
|||
int size = sizeof(dataSet)/sizeof(*dataSet);\
|
||||
while(--size)\
|
||||
{\
|
||||
VERIFY_ARE_EQUAL(func(dataSet[size]), dataSet[size]);\
|
||||
VERIFY_IS_TRUE(func(dataSet[size]));\
|
||||
}\
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace CalculatorUnitTests
|
|||
int size = sizeof(dataSet)/sizeof(*dataSet);;\
|
||||
while(--size)\
|
||||
{\
|
||||
VERIFY_ARE_EQUAL(func(dataSet[size]), StringReference(L"NoOp"));\
|
||||
VERIFY_IS_FALSE(func(dataSet[size]));\
|
||||
}\
|
||||
}
|
||||
|
||||
|
@ -71,15 +71,15 @@ namespace CalculatorUnitTests
|
|||
{
|
||||
exp_TooLong += L"-1234567";
|
||||
}
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ValidatePasteExpression(StringReference(exp_TooLong.c_str()), ViewMode::Standard, CategoryGroupType::Calculator, -1, -1), StringReference(exp_TooLong.c_str()), L"Verify ValidatePasteExpression handles expressions up to max length");
|
||||
VERIFY_IS_TRUE(m_CopyPasteManager.ValidatePasteExpression(StringReference(exp_TooLong.c_str()), ViewMode::Standard, CategoryGroupType::Calculator, -1, -1), L"Verify ValidatePasteExpression handles expressions up to max length");
|
||||
exp_TooLong += L"1";
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ValidatePasteExpression(StringReference(exp_TooLong.c_str()), ViewMode::Standard, CategoryGroupType::Calculator, -1, -1), StringReference(L"NoOp"), L"Verify ValidatePasteExpression returns NoOp for strings over max length");
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ValidatePasteExpression(StringReference(exp_TooLong.c_str()), ViewMode::Standard, CategoryGroupType::Calculator, -1, -1), L"Verify ValidatePasteExpression returns NoOp for strings over max length");
|
||||
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ValidatePasteExpression(StringReference(L""), ViewMode::Standard, CategoryGroupType::Calculator, -1, -1), StringReference(L"NoOp"), L"Verify empty string is invalid");
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ValidatePasteExpression(StringReference(L""), ViewMode::Standard, CategoryGroupType::Calculator, -1, -1), L"Verify empty string is invalid");
|
||||
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ValidatePasteExpression(StringReference(L"123e456"), ViewMode::Standard, CategoryGroupType::Calculator, -1, -1), StringReference(L"NoOp"), L"Verify pasting unsupported strings for the current mode is invalid");
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ValidatePasteExpression(StringReference(L"123e+456"), ViewMode::Standard, CategoryGroupType::Calculator, -1, -1), L"Verify pasting unsupported strings for the current mode is invalid");
|
||||
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ValidatePasteExpression(StringReference(L"123"), ViewMode::None, CategoryGroupType::None, -1, -1), StringReference(L"NoOp"), L"Verify pasting without a ViewMode or Category is invalid");
|
||||
VERIFY_IS_FALSE(m_CopyPasteManager.ValidatePasteExpression(StringReference(L"123"), ViewMode::None, CategoryGroupType::None, -1, -1), L"Verify pasting without a ViewMode or Category is invalid");
|
||||
};
|
||||
|
||||
TEST_METHOD(ValidateExtractOperands)
|
||||
|
@ -89,9 +89,7 @@ namespace CalculatorUnitTests
|
|||
vector<wstring> oneOperand = { L"123456" };
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123456", ViewMode::Standard), oneOperand);
|
||||
oneOperand = { L"123^456" };
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123^456", ViewMode::Standard), oneOperand);
|
||||
|
||||
vector<wstring> twoOperands = { L"123", L"456" };
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123^456", ViewMode::Standard), oneOperand); vector<wstring> twoOperands = { L"123", L"456" };
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123+456", ViewMode::Standard), twoOperands);
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123-456", ViewMode::Standard), twoOperands);
|
||||
VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123*456", ViewMode::Standard), twoOperands);
|
||||
|
@ -313,97 +311,97 @@ namespace CalculatorUnitTests
|
|||
|
||||
private:
|
||||
CopyPasteManager m_CopyPasteManager;
|
||||
String^ ValidateStandardPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateStandardPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Standard, -1/*number base*/, -1/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateScientificPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateScientificPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Scientific, -1/*number base*/, -1/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateConverterPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateConverterPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::None, CategoryGroupType::Converter, -1/*number base*/, -1/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerHexQwordPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerHexQwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, QwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerHexDwordPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerHexDwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, DwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerHexWordPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerHexWordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, WordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerHexBytePasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerHexBytePasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, ByteType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerDecQwordPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerDecQwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, QwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerDecDwordPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerDecDwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, DwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerDecWordPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerDecWordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, WordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerDecBytePasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerDecBytePasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, ByteType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerOctQwordPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerOctQwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, QwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerOctDwordPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerOctDwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, DwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerOctWordPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerOctWordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, WordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerOctBytePasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerOctBytePasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, ByteType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerBinQwordPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerBinQwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, QwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerBinDwordPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerBinDwordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, DwordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerBinWordPasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerBinWordPasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, WordType/*bitlength Type*/);
|
||||
}
|
||||
|
||||
String^ ValidateProgrammerBinBytePasteExpression(_In_ String^ pastedText)
|
||||
bool ValidateProgrammerBinBytePasteExpression(_In_ String^ pastedText)
|
||||
{
|
||||
return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, ByteType/*bitlength Type*/);
|
||||
}
|
||||
|
@ -455,17 +453,17 @@ namespace CalculatorUnitTests
|
|||
START_LOOP(input)
|
||||
// paste number in standard mode and then validate the pastability of displayed number for other modes
|
||||
scvm->OnPaste(input[size], ViewMode::Standard);
|
||||
VERIFY_ARE_EQUAL(ValidateStandardPasteExpression(scvm->DisplayValue), scvm->DisplayValue);
|
||||
VERIFY_ARE_EQUAL(ValidateScientificPasteExpression(scvm->DisplayValue), scvm->DisplayValue);
|
||||
VERIFY_ARE_EQUAL(ValidateProgrammerHexQwordPasteExpression(scvm->DisplayValue), scvm->DisplayValue);
|
||||
VERIFY_IS_TRUE(ValidateStandardPasteExpression(scvm->DisplayValue));
|
||||
VERIFY_IS_TRUE(ValidateScientificPasteExpression(scvm->DisplayValue));
|
||||
VERIFY_IS_TRUE(ValidateProgrammerHexQwordPasteExpression(scvm->DisplayValue));
|
||||
END_LOOP
|
||||
}
|
||||
|
||||
|
||||
void CopyPasteManagerTest::ValidateStandardPasteExpressionTest()
|
||||
{
|
||||
String^ positiveInput[] = { L"123", L"+123", L"-133", L"12345.", L"+12.34", L"12.345", L"012.034", L"-23.032", L"-.123", L".1234", L"012.012", L"123+456", L"123+-234", L"123*-345", L"123*4*-3", L"123*+4*-3", L"1,234", L"1 2 3", L"\n\r1,234\n", L"\f\n1+2\t\r\v\x85", L"\n 1+\n2 ", L"1\"2", L"1234567891234567"/*boundary condition <=16 digits*/, L"2+2=", L"2+2= " };
|
||||
String^ negativeInput[] = { L"(123)+(456)", L"1.2e23"/*unsigned exponent*/, L"12345e-23", L"abcdef", L"xyz", L"ABab", L"e+234", L"12345678912345678"/*boundary condition: greater than 16 digits*/, L"SIN(2)", L"2+2==", L"2=+2" };
|
||||
String^ positiveInput[] = { L"123", L"+123", L"-133", L"12345.", L"+12.34", L"12.345", L"012.034", L"-23.032", L"-.123", L".1234", L"012.012", L"123+456", L"123+-234", L"123*-345", L"123*4*-3", L"123*+4*-3", L"1,234", L"\n\r1,234\n", L"\f\n1+2\t\r\v\x85", L"\n 1+\n2 ", L"1\"2", L"1234567891234567"/*boundary condition <=16 digits*/, L"2+2=", L"2+2= " };
|
||||
String^ negativeInput[] = { L"(123)+(456)", L"1.2e23"/*unsigned exponent*/, L"12345e-23", L"abcdef", L"xyz", L"ABab", L"e+234", L"12345678912345678"/*boundary condition: greater than 16 digits*/, L"SIN(2)", L"2+2==", L"2=+2", L"1 2 3" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateStandardPasteExpression, positiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateStandardPasteExpression, negativeInput);
|
||||
|
@ -473,8 +471,8 @@ namespace CalculatorUnitTests
|
|||
|
||||
void CopyPasteManagerTest::ValidateScientificPasteExpressionTest()
|
||||
{
|
||||
String^ positiveInput[] = { L"123", L"+123", L"-133", L"123+456", L"12345e+023", L"1,234", L"1.23", L"-.123", L".1234", L"012.012", L"123+-234", L"123*-345", L"123*4*-3", L"123*+4*-3", L"1 2 3", L"\n\r1,234\n", L"\f\n1+2\t\r\v\x85", L"\n 1+\n2 ", L"1\"2", L"1.2e+023", L"12345e-23", L"(123)+(456)", L"12345678912345678123456789012345", L"(123)+(456)=", L"2+2= " };
|
||||
String^ negativeInput[] = { L"1.2e23"/*unsigned exponent*/, L"abcdef", L"xyz", L"ABab", L"e+234", L"123456789123456781234567890123456"/*boundary condition: greater than 32 digits*/, L"SIN(2)", L"2+2==", L"2=+2" };
|
||||
String^ positiveInput[] = { L"1.2e23", L"123", L"+123", L"-133", L"123+456", L"12345e+023", L"1,234", L"1.23", L"-.123", L".1234", L"012.012", L"123+-234", L"123*-345", L"123*4*-3", L"123*+4*-3", L"\n\r1,234\n", L"\f\n1+2\t\r\v\x85", L"\n 1+\n2 ", L"1\"2", L"1.2e+023", L"12345e-23", L"(123)+(456)", L"12345678912345678123456789012345", L"(123)+(456)=", L"2+2= " };
|
||||
String^ negativeInput[] = { L"abcdef", L"xyz", L"ABab", L"e+234", L"123456789123456781234567890123456"/*boundary condition: greater than 32 digits*/, L"SIN(2)", L"2+2==", L"2=+2", L"1 2 3" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateScientificPasteExpression, positiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateScientificPasteExpression, negativeInput);
|
||||
|
@ -590,8 +588,8 @@ namespace CalculatorUnitTests
|
|||
|
||||
void CopyPasteManagerTest::ValidateConverterPasteExpressionTest()
|
||||
{
|
||||
String^ positiveInput[] = { L"123", L"+123", L"-133", L"12345.", L"012.012", L"1,234", L"1 2 3", L"\n\r1,234\n", L"\f\n12\t\r\v\x85", L"1\"2", L"100=", L"100= " };
|
||||
String^ negativeInput[] = { L"(123)+(456)", L"1.2e23"/*unsigned exponent*/, L"12345e-23", L"\n 1+\n2 ", L"123+456", L"abcdef", L"\n 1+\n2 ", L"xyz", L"ABab", L"e+234", L"12345678912345678"/*boundary condition: greater than 16 bits*/, L"SIN(2)", L"123+-234", L"100==", L"=100" };
|
||||
String^ positiveInput[] = { L"123", L"+123", L"-133", L"12345.", L"012.012", L"1,234", L"\n\r1,234\n", L"\f\n12\t\r\v\x85", L"1\"2", L"100=", L"100= " };
|
||||
String^ negativeInput[] = { L"(123)+(456)", L"1.2e23"/*unsigned exponent*/, L"12345e-23", L"\n 1+\n2 ", L"123+456", L"abcdef", L"\n 1+\n2 ", L"xyz", L"ABab", L"e+234", L"12345678912345678"/*boundary condition: greater than 16 bits*/, L"SIN(2)", L"123+-234", L"100==", L"=100", L"1 2 3" };
|
||||
|
||||
ASSERT_POSITIVE_TESTCASES(ValidateConverterPasteExpression, positiveInput);
|
||||
ASSERT_NEGATIVE_TESTCASES(ValidateConverterPasteExpression, negativeInput);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue