Convert CopyPasteManager to runtime class (#766)

* Convert CopyPasteManager to runtime class
* merge AssertUtils and Helpers.h
* update onpastemanager
This commit is contained in:
Rudy Huyn
2019-11-13 15:15:13 -08:00
committed by GitHub
parent a217e0534b
commit b9b0e068cd
15 changed files with 604 additions and 360 deletions

View File

@@ -337,6 +337,7 @@
<ClInclude Include="Common\MyVirtualKey.h" />
<ClInclude Include="Common\NavCategory.h" />
<ClInclude Include="Common\NetworkManager.h" />
<ClInclude Include="Common\NumberBase.h" />
<ClInclude Include="Common\TraceActivity.h" />
<ClInclude Include="Common\TraceLogger.h" />
<ClInclude Include="Common\Utils.h" />

View File

@@ -196,6 +196,9 @@
<ClInclude Include="Common\BitLength.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\NumberBase.h">
<Filter>Common</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="DataLoaders\DefaultFromToCurrency.json">

View File

@@ -11,9 +11,11 @@ using namespace concurrency;
using namespace CalculatorApp;
using namespace CalculatorApp::Common;
using namespace Platform;
using namespace Platform::Collections;
using namespace Windows::Foundation;
using namespace Windows::System;
using namespace Windows::ApplicationModel::DataTransfer;
using namespace Windows::Foundation::Collections;
StringReference PasteErrorString(L"NoOp");
@@ -58,6 +60,7 @@ static const array<array<wregex, 5>, 4> programmerModePatterns = {
wregex(c_wspcLParens + c_binProgrammerChars + L"[bB]?" + c_wspcRParens) } }
};
static const array<wregex, 1> unitConverterPatterns = { wregex(c_wspc + c_signedDecFloat + c_wspc) };
void CopyPasteManager::CopyToClipboard(String ^ stringToCopy)
{
// Copy the string to the clipboard
@@ -66,7 +69,7 @@ void CopyPasteManager::CopyToClipboard(String ^ stringToCopy)
Clipboard::SetContent(dataPackage);
}
IAsyncOperation<String ^> ^ CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, BitLength bitLengthType)
IAsyncOperation<String ^> ^ CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupType modeType, NumberBase programmerNumberBase, BitLength bitLengthType)
{
// Retrieve the text in the clipboard
auto dataPackageView = Clipboard::GetContent();
@@ -91,7 +94,7 @@ bool CopyPasteManager::HasStringToPaste()
return Clipboard::GetContent()->Contains(StandardDataFormats::Text);
}
String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, int programmerNumberBase, BitLength bitLengthType)
String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, NumberBase programmerNumberBase, BitLength bitLengthType)
{
return ValidatePasteExpression(pastedText, mode, NavCategory::GetGroupType(mode), programmerNumberBase, bitLengthType);
}
@@ -102,7 +105,7 @@ String
String ^ pastedText,
ViewMode mode,
CategoryGroupType modeType,
int programmerNumberBase,
NumberBase programmerNumberBase,
BitLength bitLengthType)
{
if (pastedText->Length() > MaxPasteableLength)
@@ -116,7 +119,7 @@ String
String ^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pastedText);
// Removing the spaces, comma separator from the pasteExpression to allow pasting of expressions like 1 + 2+1,333
wstring pasteExpression = RemoveUnwantedCharsFromWstring(englishString->Data());
auto pasteExpression = wstring(RemoveUnwantedCharsFromString(englishString)->Data());
// 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'=')
@@ -126,8 +129,8 @@ String
// Extract operands from the expression to make regex comparison easy and quick. For whole expression it was taking too much of time.
// Operands vector will have the list of operands in the pasteExpression
vector<wstring> operands = ExtractOperands(pasteExpression, mode);
if (operands.empty())
auto operands = ExtractOperands(StringReference(pasteExpression.c_str()), mode);
if (operands->Size == 0)
{
// return NoOp to indicate don't paste anything.
return PasteErrorString;
@@ -135,7 +138,8 @@ String
if (modeType == CategoryGroupType::Converter)
{
operands = { pasteExpression };
operands->Clear();
operands->Append(ref new String(pasteExpression.c_str()));
}
// validate each operand with patterns for different modes
@@ -148,9 +152,9 @@ String
return pastedText;
}
vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression, ViewMode mode)
IVector<Platform::String ^> ^ CopyPasteManager::ExtractOperands(Platform::String ^ pasteExpression, ViewMode mode)
{
vector<wstring> operands{};
auto operands = ref new Vector<Platform::String ^>();
size_t lastIndex = 0;
bool haveOperator = false;
bool startExpCounting = false;
@@ -176,19 +180,20 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
// This will have the exponent length
size_t expLength = 0;
for (size_t i = 0; i < pasteExpression.length(); i++)
int i = -1;
for (auto currentChar : pasteExpression)
{
wchar_t currentChar = pasteExpression.at(i);
++i;
// if the current character is not a valid one don't process it
if (validCharacterSet.find(currentChar) == wstring_view::npos)
{
continue;
}
if (operands.size() >= MaxOperandCount)
if (operands->Size >= MaxOperandCount)
{
TraceLogger::GetInstance()->LogError(mode, L"CopyPasteManager::ExtractOperands", L"OperandCountGreaterThanMaxCount");
operands.clear();
operands->Clear();
return operands;
}
@@ -202,7 +207,7 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
if (expLength > MaxExponentLength)
{
TraceLogger::GetInstance()->LogError(mode, L"CopyPasteManager::ExtractOperands", L"ExponentLengthGreaterThanMaxLength");
operands.clear();
operands->Clear();
return operands;
}
}
@@ -222,7 +227,7 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
{
// don't break the expression into operands if the encountered character corresponds to sign command(+-)
if (isPreviousOpenParen || startOfExpression || isPreviousOperator
|| ((mode != ViewMode::Programmer) && !((i != 0) && (pasteExpression.at(i - 1) != L'e'))))
|| ((mode != ViewMode::Programmer) && !((i != 0) && pasteExpression->Data()[i - 1] != L'e')))
{
isPreviousOperator = false;
continue;
@@ -233,7 +238,7 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
expLength = 0;
haveOperator = true;
isPreviousOperator = true;
operands.push_back(pasteExpression.substr(lastIndex, i - lastIndex));
operands->Append(ref new String(wstring(pasteExpression->Data()).substr(lastIndex, i - lastIndex).c_str()));
lastIndex = i + 1;
}
else
@@ -241,31 +246,31 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
isPreviousOperator = false;
}
isPreviousOpenParen = (pasteExpression.at(i) == L'(');
isPreviousOpenParen = (currentChar == L'(');
startOfExpression = false;
}
if (!haveOperator)
{
operands.clear();
operands.push_back(pasteExpression);
operands->Clear();
operands->Append(pasteExpression);
}
else
{
operands.push_back(pasteExpression.substr(lastIndex, pasteExpression.length() - 1));
operands->Append(ref new String(wstring(pasteExpression->Data()).substr(lastIndex, pasteExpression->Length() - 1).c_str()));
}
return operands;
}
bool CopyPasteManager::ExpressionRegExMatch(
vector<wstring> operands,
IVector<String ^> ^ operands,
ViewMode mode,
CategoryGroupType modeType,
int programmerNumberBase,
NumberBase programmerNumberBase,
BitLength bitLengthType)
{
if (operands.empty())
if (operands->Size == 0)
{
return false;
}
@@ -282,14 +287,16 @@ bool CopyPasteManager::ExpressionRegExMatch(
}
else if (mode == ViewMode::Programmer)
{
patterns.assign(programmerModePatterns[programmerNumberBase - HexBase].begin(), programmerModePatterns[programmerNumberBase - HexBase].end());
patterns.assign(
programmerModePatterns[(int)programmerNumberBase - (int)NumberBase::HexBase].begin(),
programmerModePatterns[(int)programmerNumberBase - (int)NumberBase::HexBase].end());
}
else if (modeType == CategoryGroupType::Converter)
{
patterns.assign(unitConverterPatterns.begin(), unitConverterPatterns.end());
}
const auto [maxOperandLength, maxOperandValue] = GetMaxOperandLengthAndValue(mode, modeType, programmerNumberBase, bitLengthType);
auto maxOperandLengthAndValue = GetMaxOperandLengthAndValue(mode, modeType, programmerNumberBase, bitLengthType);
bool expMatched = true;
for (const auto& operand : operands)
@@ -298,34 +305,34 @@ bool CopyPasteManager::ExpressionRegExMatch(
bool operandMatched = false;
for (const auto& pattern : patterns)
{
operandMatched = operandMatched || regex_match(operand, pattern);
operandMatched = operandMatched || regex_match(operand->Data(), pattern);
}
if (operandMatched)
{
// Remove characters that are valid in the expression but we do not want to include in length calculations
// or which will break conversion from string-to-ULL.
const wstring operandValue = SanitizeOperand(operand);
auto operandValue = SanitizeOperand(operand);
// If an operand exceeds the maximum length allowed, break and return.
if (OperandLength(operandValue, mode, modeType, programmerNumberBase) > maxOperandLength)
if (OperandLength(operandValue, mode, modeType, programmerNumberBase) > maxOperandLengthAndValue.maxLength)
{
expMatched = false;
break;
}
// If maxOperandValue is set and the operandValue exceeds it, break and return.
if (maxOperandValue != 0)
if (maxOperandLengthAndValue.maxValue != 0)
{
unsigned long long int operandAsULL = 0;
if (!TryOperandToULL(operandValue, programmerNumberBase, operandAsULL))
auto operandAsULL = TryOperandToULL(operandValue, programmerNumberBase);
if (operandAsULL == nullptr)
{
// Operand was empty, received invalid_argument, or received out_of_range. Input is invalid.
expMatched = false;
break;
}
if (operandAsULL > maxOperandValue)
if (operandAsULL->Value > maxOperandLengthAndValue.maxValue)
{
expMatched = false;
break;
@@ -339,19 +346,23 @@ bool CopyPasteManager::ExpressionRegExMatch(
return expMatched;
}
pair<size_t, uint64_t>
CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, BitLength bitLengthType)
CopyPasteMaxOperandLengthAndValue
CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mode, CategoryGroupType modeType, NumberBase programmerNumberBase, BitLength bitLengthType)
{
constexpr size_t defaultMaxOperandLength = 0;
constexpr uint64_t defaultMaxValue = 0;
CopyPasteMaxOperandLengthAndValue res;
if (mode == ViewMode::Standard)
{
return make_pair(MaxStandardOperandLength, defaultMaxValue);
res.maxLength = MaxStandardOperandLength;
res.maxValue = defaultMaxValue;
return res;
}
else if (mode == ViewMode::Scientific)
{
return make_pair(MaxScientificOperandLength, defaultMaxValue);
res.maxLength = MaxScientificOperandLength;
res.maxValue = defaultMaxValue;
return res;
}
else if (mode == ViewMode::Programmer)
{
@@ -375,65 +386,69 @@ CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mode, CategoryGroupType m
double bitsPerDigit = 0;
switch (programmerNumberBase)
{
case BinBase:
case NumberBase::BinBase:
bitsPerDigit = log2(2);
break;
case OctBase:
case NumberBase::OctBase:
bitsPerDigit = log2(8);
break;
case DecBase:
case NumberBase::DecBase:
bitsPerDigit = log2(10);
break;
case HexBase:
case NumberBase::HexBase:
bitsPerDigit = log2(16);
break;
}
unsigned int signBit = (programmerNumberBase == DecBase) ? 1 : 0;
unsigned int signBit = (programmerNumberBase == NumberBase::DecBase) ? 1 : 0;
const auto maxLength = static_cast<size_t>(ceil((bitLength - signBit) / bitsPerDigit));
const auto maxLength = static_cast<unsigned int>(ceil((bitLength - signBit) / bitsPerDigit));
const uint64_t maxValue = UINT64_MAX >> (MaxProgrammerBitLength - (bitLength - signBit));
return make_pair(maxLength, maxValue);
res.maxLength = maxLength;
res.maxValue = maxValue;
return res;
}
else if (modeType == CategoryGroupType::Converter)
{
return make_pair(MaxConverterInputLength, defaultMaxValue);
res.maxLength = MaxConverterInputLength;
res.maxValue = defaultMaxValue;
return res;
}
return make_pair(defaultMaxOperandLength, defaultMaxValue);
res.maxLength = defaultMaxOperandLength;
res.maxValue = defaultMaxValue;
return res;
}
wstring CopyPasteManager::SanitizeOperand(const wstring& operand)
Platform::String ^ CopyPasteManager::SanitizeOperand(Platform::String ^ operand)
{
wchar_t unWantedChars[] = { L'\'', L'_', L'`', L'(', L')', L'-', L'+' };
return Utils::RemoveUnwantedCharsFromWstring(operand, unWantedChars, static_cast<int>(size(unWantedChars)));
return ref new String(Utils::RemoveUnwantedCharsFromString(operand->Data(), unWantedChars, static_cast<int>(size(unWantedChars))).c_str());
}
bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, unsigned long long int& result)
IBox<unsigned long long int> ^ CopyPasteManager::TryOperandToULL(String ^ operand, NumberBase numberBase)
{
result = 0;
if (operand.length() == 0 || operand.front() == L'-')
if (operand->Length() == 0 || operand->Data()[0] == L'-')
{
return false;
return nullptr;
}
int intBase;
switch (numberBase)
{
case HexBase:
case NumberBase::HexBase:
intBase = 16;
break;
case OctBase:
case NumberBase::OctBase:
intBase = 8;
break;
case BinBase:
case NumberBase::BinBase:
intBase = 2;
break;
default:
case DecBase:
case NumberBase::DecBase:
intBase = 10;
break;
}
@@ -441,8 +456,7 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u
wstring::size_type size = 0;
try
{
result = stoull(operand, &size, intBase);
return true;
return stoull(operand->Data(), &size, intBase);
}
catch (const invalid_argument&)
{
@@ -453,14 +467,14 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u
// Do nothing
}
return false;
return nullptr;
}
size_t CopyPasteManager::OperandLength(const wstring& operand, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase)
ULONG32 CopyPasteManager::OperandLength(Platform::String ^ operand, ViewMode mode, CategoryGroupType modeType, NumberBase programmerNumberBase)
{
if (modeType == CategoryGroupType::Converter)
{
return operand.length();
return operand->Length();
}
switch (mode)
@@ -477,45 +491,46 @@ size_t CopyPasteManager::OperandLength(const wstring& operand, ViewMode mode, Ca
}
}
size_t CopyPasteManager::StandardScientificOperandLength(const wstring& operand)
ULONG32 CopyPasteManager::StandardScientificOperandLength(Platform::String ^ operand)
{
const bool hasDecimal = operand.find('.') != wstring::npos;
auto operandWstring = wstring(operand->Data());
const bool hasDecimal = operandWstring.find('.') != wstring::npos;
if (hasDecimal)
{
if (operand.length() >= 2)
if (operandWstring.length() >= 2)
{
if ((operand[0] == L'0') && (operand[1] == L'.'))
if ((operandWstring[0] == L'0') && (operandWstring[1] == L'.'))
{
return operand.length() - 2;
return static_cast<ULONG32>(operandWstring.length() - 2);
}
else
{
return operand.length() - 1;
return static_cast<ULONG32>(operandWstring.length() - 1);
}
}
}
return operand.length();
return static_cast<ULONG32>(operandWstring.length());
}
size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int numberBase)
ULONG32 CopyPasteManager::ProgrammerOperandLength(Platform::String ^ operand, NumberBase numberBase)
{
vector<wstring> prefixes{};
vector<wstring> suffixes{};
switch (numberBase)
{
case BinBase:
case NumberBase::BinBase:
prefixes = { L"0B", L"0Y" };
suffixes = { L"B" };
break;
case DecBase:
case NumberBase::DecBase:
prefixes = { L"-", L"0N" };
break;
case OctBase:
case NumberBase::OctBase:
prefixes = { L"0T", L"0O" };
break;
case HexBase:
case NumberBase::HexBase:
prefixes = { L"0X" };
suffixes = { L"H" };
break;
@@ -528,10 +543,10 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num
const array<wstring, 5> uintSuffixes = { L"ULL", L"UL", L"LL", L"U", L"L" };
suffixes.insert(suffixes.end(), uintSuffixes.begin(), uintSuffixes.end());
wstring operandUpper = operand;
wstring operandUpper = wstring(operand->Data());
transform(operandUpper.begin(), operandUpper.end(), operandUpper.begin(), towupper);
size_t len = operand.length();
size_t len = operand->Length();
// Detect if there is a suffix and subtract its length
// Check suffixes first to allow e.g. "0b" to result in length 1 (value 0), rather than length 0 (no value).
@@ -564,7 +579,7 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num
}
}
return len;
return static_cast<ULONG32>(len);
}
// return wstring after removing characters like space, comma, double quotes, and monetary prefix currency symbols supported by the Windows keyboard:
@@ -579,10 +594,10 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num
// Indian rupee(₹) - 8377
// pound(£) - 163
// euro(€) - 8364
wstring CopyPasteManager::RemoveUnwantedCharsFromWstring(const wstring& input)
Platform::String ^ CopyPasteManager::RemoveUnwantedCharsFromString(Platform::String ^ input)
{
wchar_t unWantedChars[] = { L' ', L',', L'"', 165, 164, 8373, 36, 8353, 8361, 8362, 8358, 8377, 163, 8364, 8234, 8235, 8236, 8237 };
return Utils::RemoveUnwantedCharsFromWstring(input, unWantedChars, 18);
return ref new String(Utils::RemoveUnwantedCharsFromString(input->Data(), unWantedChars, 18).c_str());
}
bool CopyPasteManager::IsErrorMessage(Platform::String ^ message)

View File

@@ -6,6 +6,7 @@
#include "AppResourceProvider.h"
#include "NavCategory.h"
#include "BitLength.h"
#include "NumberBase.h"
namespace CalculatorUnitTests
{
@@ -14,71 +15,119 @@ namespace CalculatorUnitTests
namespace CalculatorApp
{
inline constexpr auto HexBase = 5;
inline constexpr auto DecBase = 6;
inline constexpr auto OctBase = 7;
inline constexpr auto BinBase = 8;
public
value struct CopyPasteMaxOperandLengthAndValue
{
unsigned int maxLength;
unsigned long long maxValue;
};
public ref class CopyPasteManager sealed
{
public:
static void CopyToClipboard(Platform::String ^ stringToCopy);
static Windows::Foundation::IAsyncOperation<Platform::String ^>^ GetStringToPaste(
CalculatorApp::Common::ViewMode mode,
CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase,
CalculatorApp::Common::BitLength bitLengthType);
static Windows::Foundation::IAsyncOperation<
Platform::String
^> ^ GetStringToPaste(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, CalculatorApp::Common::NumberBase programmerNumberBase, CalculatorApp::Common::BitLength bitLengthType);
static bool HasStringToPaste();
static bool IsErrorMessage(Platform::String ^ message);
static property unsigned int MaxPasteableLength
{
unsigned int get()
{
return MaxPasteableLengthValue;
}
}
static property unsigned int MaxOperandCount
{
unsigned int get()
{
return MaxOperandCountValue;
}
}
static property unsigned int MaxStandardOperandLength
{
unsigned int get()
{
return MaxStandardOperandLengthValue;
}
}
static property unsigned int MaxScientificOperandLength
{
unsigned int get()
{
return MaxScientificOperandLengthValue;
}
}
static property unsigned int MaxConverterInputLength
{
unsigned int get()
{
return MaxConverterInputLengthValue;
}
}
static property unsigned int MaxExponentLength
{
unsigned int get()
{
return MaxExponentLengthValue;
}
}
static property unsigned int MaxProgrammerBitLength
{
unsigned int get()
{
return MaxProgrammerBitLengthValue;
}
}
private:
static Platform::String
^ ValidatePasteExpression(
Platform::String ^ pastedText,
CalculatorApp::Common::ViewMode mode,
int programmerNumberBase,
CalculatorApp::Common::NumberBase programmerNumberBase,
CalculatorApp::Common::BitLength bitLengthType);
static Platform::String
^ ValidatePasteExpression(
Platform::String ^ pastedText,
CalculatorApp::Common::ViewMode mode,
CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase,
CalculatorApp::Common::NumberBase programmerNumberBase,
CalculatorApp::Common::BitLength bitLengthType);
static std::vector<std::wstring>
ExtractOperands(const std::wstring& pasteExpression, CalculatorApp::Common::ViewMode mode);
static CopyPasteMaxOperandLengthAndValue GetMaxOperandLengthAndValue(
CalculatorApp::Common::ViewMode mode,
CalculatorApp::Common::CategoryGroupType modeType,
CalculatorApp::Common::NumberBase programmerNumberBase,
CalculatorApp::Common::BitLength bitLengthType);
static Windows::Foundation::Collections::IVector<
Platform::String ^> ^ ExtractOperands(Platform::String ^ pasteExpression, CalculatorApp::Common::ViewMode mode);
static bool ExpressionRegExMatch(
std::vector<std::wstring> operands,
Windows::Foundation::Collections::IVector<Platform::String ^> ^ operands,
CalculatorApp::Common::ViewMode mode,
CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase = -1,
CalculatorApp::Common::BitLength bitLengthType = CalculatorApp::Common::BitLength::BitLengthUnknown);
static std::pair<size_t, uint64_t> GetMaxOperandLengthAndValue(
CalculatorApp::Common::NumberBase programmerNumberBase,
CalculatorApp::Common::BitLength bitLengthType);
static Platform::String ^ SanitizeOperand(Platform::String ^ operand);
static Platform::String ^ RemoveUnwantedCharsFromString(Platform::String ^ input);
static Platform::IBox<unsigned long long int> ^ TryOperandToULL(Platform::String ^ operand, CalculatorApp::Common::NumberBase numberBase);
static ULONG32 StandardScientificOperandLength(Platform::String ^ operand);
static ULONG32 OperandLength(
Platform::String ^ operand,
CalculatorApp::Common::ViewMode mode,
CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase = -1,
CalculatorApp::Common::BitLength bitLengthType = CalculatorApp::Common::BitLength::BitLengthUnknown);
static std::wstring SanitizeOperand(const std::wstring& operand);
static bool TryOperandToULL(const std::wstring& operand, int numberBase, unsigned long long int& result);
static size_t OperandLength(
const std::wstring& operand,
CalculatorApp::Common::ViewMode mode,
CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase = -1);
static size_t StandardScientificOperandLength(const std::wstring& operand);
static size_t ProgrammerOperandLength(const std::wstring& operand, int numberBase);
static std::wstring RemoveUnwantedCharsFromWstring(const std::wstring& input);
CalculatorApp::Common::NumberBase programmerNumberBase);
static ULONG32 ProgrammerOperandLength(Platform::String ^ operand, CalculatorApp::Common::NumberBase numberBase);
static constexpr size_t MaxStandardOperandLength = 16;
static constexpr size_t MaxScientificOperandLength = 32;
static constexpr size_t MaxConverterInputLength = 16;
static constexpr size_t MaxOperandCount = 100;
static constexpr size_t MaxPasteableLength = 512;
static constexpr size_t MaxExponentLength = 4;
static constexpr size_t MaxProgrammerBitLength = 64;
friend class CalculatorUnitTests::CopyPasteManagerTest;
private:
static constexpr size_t MaxStandardOperandLengthValue = 16;
static constexpr size_t MaxScientificOperandLengthValue = 32;
static constexpr size_t MaxConverterInputLengthValue = 16;
static constexpr size_t MaxOperandCountValue = 100;
static constexpr size_t MaxExponentLengthValue = 4;
static constexpr size_t MaxProgrammerBitLengthValue = 64;
static constexpr size_t MaxPasteableLengthValue = 512;
};
}

View File

@@ -0,0 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
namespace CalculatorApp::Common
{
public
enum class NumberBase
{
Unknown = -1,
HexBase = 5,
DecBase = 6,
OctBase = 7,
BinBase = 8
};
};

View File

@@ -48,7 +48,7 @@ String ^ Utils::GetStringValue(String ^ input)
double Utils::GetDoubleFromWstring(wstring input)
{
wchar_t unWantedChars[] = { L' ', L',', 8234, 8235, 8236, 8237 };
wstring ws = RemoveUnwantedCharsFromWstring(input, unWantedChars, 6);
wstring ws = RemoveUnwantedCharsFromString(input, unWantedChars, 6);
return stod(ws);
}
@@ -81,7 +81,7 @@ bool Utils::IsLastCharacterTarget(_In_ wstring const& input, _In_ wchar_t target
}
// Return wstring after removing characters specified by unwantedChars array
wstring Utils::RemoveUnwantedCharsFromWstring(wstring input, wchar_t* unwantedChars, unsigned int size)
wstring Utils::RemoveUnwantedCharsFromString(wstring input, wchar_t* unwantedChars, unsigned int size)
{
for (unsigned int i = 0; i < size; ++i)
{

View File

@@ -379,7 +379,7 @@ namespace Utils
void IFTPlatformException(HRESULT hr);
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 RemoveUnwantedCharsFromString(std::wstring inputString, wchar_t* unwantedChars, unsigned int size);
double GetDoubleFromWstring(std::wstring input);
int GetWindowId();
void RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ Windows::UI::Core::CoreDispatcher ^ currentDispatcher);

View File

@@ -14,6 +14,7 @@ using namespace CalculatorApp::Common;
using namespace CalculatorApp::Common::Automation;
using namespace CalculatorApp::ViewModel;
using namespace CalculationManager;
using namespace concurrency;
using namespace Platform;
using namespace Platform::Collections;
using namespace std;
@@ -680,23 +681,23 @@ void StandardCalculatorViewModel::OnButtonPressed(Object ^ parameter)
}
}
int StandardCalculatorViewModel::GetNumberBase()
NumberBase StandardCalculatorViewModel::GetNumberBase()
{
if (CurrentRadixType == HEX_RADIX)
{
return HexBase;
return NumberBase::HexBase;
}
else if (CurrentRadixType == DEC_RADIX)
{
return DecBase;
return NumberBase::DecBase;
}
else if (CurrentRadixType == OCT_RADIX)
{
return OctBase;
return NumberBase::OctBase;
}
else
{
return BinBase;
return NumberBase::BinBase;
}
}
@@ -712,7 +713,7 @@ void StandardCalculatorViewModel::OnPasteCommand(Object ^ parameter)
{
auto that(this);
ViewMode mode;
int NumberBase = -1;
NumberBase numberBase = NumberBase::Unknown;
BitLength bitLengthType = BitLength::BitLengthUnknown;
if (IsScientific)
{
@@ -721,7 +722,7 @@ void StandardCalculatorViewModel::OnPasteCommand(Object ^ parameter)
else if (IsProgrammer)
{
mode = ViewMode::Programmer;
NumberBase = GetNumberBase();
numberBase = GetNumberBase();
bitLengthType = m_valueBitLength;
}
else
@@ -735,7 +736,7 @@ void StandardCalculatorViewModel::OnPasteCommand(Object ^ parameter)
}
// Ensure that the paste happens on the UI thread
create_task(CopyPasteManager::GetStringToPaste(mode, NavCategory::GetGroupType(mode), NumberBase, bitLengthType))
create_task(CopyPasteManager::GetStringToPaste(mode, NavCategory::GetGroupType(mode), numberBase, bitLengthType))
.then([that, mode](String ^ pastedString) { that->OnPaste(pastedString); }, concurrency::task_continuation_context::use_current());
}

View File

@@ -10,6 +10,7 @@
#include "HistoryViewModel.h"
#include "MemoryItemViewModel.h"
#include "Common/BitLength.h"
#include "Common/NumberBase.h"
namespace CalculatorFunctionalTests
{
@@ -39,7 +40,7 @@ namespace CalculatorApp
StandardCalculatorViewModel();
void UpdateOperand(int pos, Platform::String ^ text);
void UpdatecommandsInRecordingMode();
int GetNumberBase();
CalculatorApp::Common::NumberBase GetNumberBase();
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
OBSERVABLE_PROPERTY_RW(Platform::String ^, DisplayValue);

View File

@@ -517,7 +517,7 @@ void UnitConverterViewModel::OnPasteCommand(Platform::Object ^ parameter)
// Any converter ViewMode is fine here.
auto that(this);
create_task(CopyPasteManager::GetStringToPaste(m_Mode, NavCategory::GetGroupType(m_Mode), -1, BitLength::BitLengthUnknown))
create_task(CopyPasteManager::GetStringToPaste(m_Mode, NavCategory::GetGroupType(m_Mode), NumberBase::Unknown, BitLength::BitLengthUnknown))
.then([that](String ^ pastedString) { that->OnPaste(pastedString); }, concurrency::task_continuation_context::use_current());
}

View File

@@ -31,6 +31,8 @@
#include <regex>
#include <iterator>
#include <intsafe.h>
#include <ppltasks.h>
// C++\WinRT Headers
#include "winrt/base.h"
#include "winrt/Windows.Foundation.Diagnostics.h"