diff --git a/src/CalcViewModel/Common/CopyPasteManager.cpp b/src/CalcViewModel/Common/CopyPasteManager.cpp index c8f9c5f0..f910195b 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.cpp +++ b/src/CalcViewModel/Common/CopyPasteManager.cpp @@ -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 standardModePatterns = { - wregex(c_wspc + c_signedDecFloat + c_wspc) + wregex(c_signedDecFloat) }; static const array 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, 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, 4> programmerModePatterns = } }; static const array 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 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 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 CopyPasteManager::ExtractOperands(const wstring& pasteExpression, ViewMode mode, int programmerNumberBase, int bitLengthType) @@ -236,7 +266,7 @@ vector 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 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 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) diff --git a/src/CalcViewModel/Common/CopyPasteManager.h b/src/CalcViewModel/Common/CopyPasteManager.h index 1da4af4e..1b52fddc 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.h +++ b/src/CalcViewModel/Common/CopyPasteManager.h @@ -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, diff --git a/src/CalcViewModel/Common/Utils.cpp b/src/CalcViewModel/Common/Utils.cpp index c0ddf69a..b4139372 100644 --- a/src/CalcViewModel/Common/Utils.cpp +++ b/src/CalcViewModel/Common/Utils.cpp @@ -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) { diff --git a/src/CalcViewModel/Common/Utils.h b/src/CalcViewModel/Common/Utils.h index 949ba0f0..f21c47fe 100644 --- a/src/CalcViewModel/Common/Utils.h +++ b/src/CalcViewModel/Common/Utils.h @@ -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&& function, _In_ Windows::UI::Core::CoreDispatcher^ currentDispatcher); diff --git a/src/CalcViewModel/StandardCalculatorViewModel.cpp b/src/CalcViewModel/StandardCalculatorViewModel.cpp index c8b87071..8575f8bf 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.cpp +++ b/src/CalcViewModel/StandardCalculatorViewModel.cpp @@ -42,7 +42,7 @@ namespace CalculatorApp::ViewModel StringReference IsInError(L"IsInError"); StringReference BinaryDisplayValue(L"BinaryDisplayValue"); } - + namespace CalculatorResourceKeys { StringReference CalculatorExpression(L"Format_CalculatorExpression"); @@ -574,7 +574,7 @@ void StandardCalculatorViewModel::OnButtonPressed(Object^ parameter) if (IsInError) { m_standardCalculatorManager.SendCommand(Command::CommandCLEAR); - + if (!IsRecoverableCommand((int)numOpEnum)) { return; @@ -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(Command::CommandASIN) : - updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandSIN), true, angleType); - break; - case static_cast(Command::CommandACOS) : - updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandCOS), true, angleType); - break; - case static_cast(Command::CommandATAN) : - updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandTAN), true, angleType); - break; - case static_cast(Command::CommandASINH) : - updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandSINH), true, angleType); - break; - case static_cast(Command::CommandACOSH) : - updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandCOSH), true, angleType); - break; - case static_cast(Command::CommandATANH) : - updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandTANH), true, angleType); - break; - case static_cast(Command::CommandPOWE) : - updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandLN), true, angleType); - break; - default: - updatedToken = CCalcEngine::OpCodeToUnaryString(nOpCode, false, angleType); + case static_cast(Command::CommandASIN) : + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandSIN), true, angleType); + break; + case static_cast(Command::CommandACOS) : + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandCOS), true, angleType); + break; + case static_cast(Command::CommandATAN) : + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandTAN), true, angleType); + break; + case static_cast(Command::CommandASINH) : + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandSINH), true, angleType); + break; + case static_cast(Command::CommandACOSH) : + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandCOSH), true, angleType); + break; + case static_cast(Command::CommandATANH) : + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandTANH), true, angleType); + break; + case static_cast(Command::CommandPOWE) : + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandLN), true, angleType); + break; + default: + updatedToken = CCalcEngine::OpCodeToUnaryString(nOpCode, false, angleType); } if ((token.first.length() > 0) && (token.first[token.first.length() - 1] == L'(')) { diff --git a/src/Calculator/Views/Calculator.xaml.cpp b/src/Calculator/Views/Calculator.xaml.cpp index d8ae99c9..3eecc30e 100644 --- a/src/Calculator/Views/Calculator.xaml.cpp +++ b/src/Calculator/Views/Calculator.xaml.cpp @@ -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; diff --git a/src/Calculator/Views/Calculator.xaml.h b/src/Calculator/Views/Calculator.xaml.h index ca385e68..dbcbc7e9 100644 --- a/src/Calculator/Views/Calculator.xaml.h +++ b/src/Calculator/Views/Calculator.xaml.h @@ -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(); diff --git a/src/CalculatorUnitTests/CopyPasteManagerTest.cpp b/src/CalculatorUnitTests/CopyPasteManagerTest.cpp index f06c0a87..d1c324ee 100644 --- a/src/CalculatorUnitTests/CopyPasteManagerTest.cpp +++ b/src/CalculatorUnitTests/CopyPasteManagerTest.cpp @@ -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 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 twoOperands = { L"123", L"456" }; + VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123^456", ViewMode::Standard), oneOperand); vector 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);