Build CalcManager for WASM

This commit is contained in:
Jérôme Laban 2019-05-15 11:21:16 -04:00
commit d121432726
13 changed files with 48 additions and 1435 deletions

View file

@ -1,8 +1,14 @@
#define __STDC_WANT_LIB_EXT1__ 1
#include "pch.h"
#include "CCalcManager.h"
#include "CalculatorManager.h"
#include "CalculatorResource.h"
#include <codecvt>
#include <locale>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace CalculationManager;
@ -71,7 +77,12 @@ public:
{
auto str = convert.to_bytes(memorizedNumbers[i]);
auto pData = new char[str.size() + 1];
strncpy_s(pData, str.size(), str.data(), str.size());
#ifdef __STDC_LIB_EXT1__
strcpy_s(pData, str.size(), str.data());
#else
strcpy(pData, str.data());
#endif
numbers[i] = pData;
}
@ -114,10 +125,15 @@ public:
void* CalculatorManager_Create(CalculatorManager_CreateParams* pParams) {
printf("-> NativeCalcManager:CalculatorManager_Create(%p)\n", pParams);
auto calcDisplay = new CalcDisplay(*pParams);
auto resProvider = new ResourceProvider(*pParams);
printf("NativeCalcManager:CalculatorManager_Create: Got providers\n");
auto cm = new CalculatorManager(calcDisplay, resProvider);
printf("<- NativeCalcManager:CalculatorManager_Create(%p)\n", pParams);
return cm;
}

View file

@ -51,8 +51,14 @@ struct CalculatorManager_CreateParams {
GetCEngineStringFunc GetCEngineString;
};
#if defined(__EMSCRIPTEN__)
#define DLL_EXPORT
#else
#define DLL_EXPORT __declspec(dllexport)
#endif
extern "C" {
__declspec(dllexport) void* CalculatorManager_Create(CalculatorManager_CreateParams* params);
__declspec(dllexport) void CalculatorManager_SendCommand(void* manager, int command);
DLL_EXPORT void* CalculatorManager_Create(CalculatorManager_CreateParams* params);
DLL_EXPORT void CalculatorManager_SendCommand(void* manager, int command);
}

View file

@ -314,7 +314,6 @@
<ClInclude Include="Ratpack\CalcErr.h" />
<ClInclude Include="Ratpack\ratconst.h" />
<ClInclude Include="Ratpack\ratpak.h" />
<ClInclude Include="UnitConverter.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="CalculatorHistory.cpp" />
@ -355,7 +354,6 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="UnitConverter.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />

View file

@ -76,7 +76,6 @@
</ClCompile>
<ClCompile Include="CalculatorHistory.cpp" />
<ClCompile Include="CalculatorManager.cpp" />
<ClCompile Include="UnitConverter.cpp" />
<ClCompile Include="CEngine\CalcInput.cpp">
<Filter>CEngine</Filter>
</ClCompile>
@ -106,7 +105,6 @@
<Filter>RatPack</Filter>
</ClInclude>
<ClInclude Include="CalculatorVector.h" />
<ClInclude Include="UnitConverter.h" />
<ClInclude Include="CalculatorHistory.h" />
<ClInclude Include="CalculatorManager.h" />
<ClInclude Include="CalculatorResource.h" />

Binary file not shown.

View file

@ -14,7 +14,11 @@ static constexpr size_t SERIALIZED_NUMBER_MINSIZE = 3;
// Converts Memory Command enum value to unsigned char,
// while ignoring Warning C4309: 'conversion' : truncation of constant value
#if defined(__EMSCRIPTEN__)
#define MEMORY_COMMAND_TO_UNSIGNED_CHAR(c) static_cast<unsigned char>(c)
#else
#define MEMORY_COMMAND_TO_UNSIGNED_CHAR(c) __pragma(warning(push)) __pragma(warning(disable : 4309)) static_cast<unsigned char>(c) __pragma(warning(pop))
#endif
namespace CalculationManager
{

View file

@ -10,7 +10,7 @@
#include "Ratpack/CalcErr.h"
#include <stdexcept> // for std::out_of_range
#if !defined(__WEBASSEMBLY__)
#if !defined(__EMSCRIPTEN__)
#include <winerror.h>
#include <sal.h> // for SAL
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,318 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include <vector>
#include <unordered_map>
#include <ppltasks.h>
#include <sal.h> // for SAL
#include <memory> // for std::shared_ptr
namespace UnitConversionManager
{
enum class Command;
struct Unit
{
Unit()
{
}
Unit(int id, std::wstring name, std::wstring abbreviation, bool isConversionSource, bool isConversionTarget, bool isWhimsical)
: id(id)
, name(name)
, accessibleName(name)
, abbreviation(abbreviation)
, isConversionSource(isConversionSource)
, isConversionTarget(isConversionTarget)
, isWhimsical(isWhimsical)
{
}
Unit(
int id,
std::wstring currencyName,
std::wstring countryName,
std::wstring abbreviation,
bool isRtlLanguage,
bool isConversionSource,
bool isConversionTarget)
: id(id)
, abbreviation(abbreviation)
, isConversionSource(isConversionSource)
, isConversionTarget(isConversionTarget)
, isWhimsical(false)
{
std::wstring nameValue1 = isRtlLanguage ? currencyName : countryName;
std::wstring nameValue2 = isRtlLanguage ? countryName : currencyName;
name = nameValue1 + L" - " + nameValue2;
accessibleName = nameValue1 + L" " + nameValue2;
}
virtual ~Unit()
{
}
int id;
std::wstring name;
std::wstring accessibleName;
std::wstring abbreviation;
bool isConversionSource;
bool isConversionTarget;
bool isWhimsical;
bool operator!=(const Unit& that) const
{
return that.id != id;
}
bool operator==(const Unit& that) const
{
return that.id == id;
}
};
// The EMPTY_UNIT acts as a 'null-struct' so that
// Unit pointers can safely be dereferenced without
// null checks.
//
// unitId, name, abbreviation, isConversionSource, isConversionTarget, isWhimsical
inline const Unit EMPTY_UNIT = Unit{ -1, L"", L"", true, true, false };
struct Category
{
Category()
{
}
Category(int id, std::wstring name, bool supportsNegative)
: id(id)
, name(name)
, supportsNegative(supportsNegative)
{
}
int id;
std::wstring name;
bool supportsNegative;
bool operator!=(const Category& that) const
{
return that.id != id;
}
bool operator==(const Category& that) const
{
return that.id == id;
}
};
class UnitHash
{
public:
size_t operator()(const Unit& x) const
{
return x.id;
}
};
class CategoryHash
{
public:
size_t operator()(const Category& x) const
{
return x.id;
}
};
struct SuggestedValueIntermediate
{
double magnitude;
double value;
Unit type;
};
struct ConversionData
{
ConversionData()
{
}
ConversionData(double ratio, double offset, bool offsetFirst)
: ratio(ratio)
, offset(offset)
, offsetFirst(offsetFirst)
{
}
virtual ~ConversionData()
{
}
double ratio;
double offset;
bool offsetFirst;
};
struct CurrencyStaticData
{
std::wstring countryCode;
std::wstring countryName;
std::wstring currencyCode;
std::wstring currencyName;
std::wstring currencySymbol;
};
struct CurrencyRatio
{
double ratio;
std::wstring sourceCurrencyCode;
std::wstring targetCurrencyCode;
};
typedef std::tuple<std::vector<UnitConversionManager::Unit>, UnitConversionManager::Unit, UnitConversionManager::Unit> CategorySelectionInitializer;
typedef std::unordered_map<
UnitConversionManager::Unit,
std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>,
UnitConversionManager::UnitHash>
UnitToUnitToConversionDataMap;
typedef std::unordered_map<UnitConversionManager::Category, std::vector<UnitConversionManager::Unit>, UnitConversionManager::CategoryHash>
CategoryToUnitVectorMap;
class IViewModelCurrencyCallback
{
public:
virtual ~IViewModelCurrencyCallback(){};
virtual void CurrencyDataLoadFinished(bool didLoad) = 0;
virtual void CurrencySymbolsCallback(_In_ const std::wstring& fromSymbol, _In_ const std::wstring& toSymbol) = 0;
virtual void CurrencyRatiosCallback(_In_ const std::wstring& ratioEquality, _In_ const std::wstring& accRatioEquality) = 0;
virtual void CurrencyTimestampCallback(_In_ const std::wstring& timestamp, bool isWeekOldData) = 0;
virtual void NetworkBehaviorChanged(_In_ int newBehavior) = 0;
};
class IConverterDataLoader
{
public:
virtual ~IConverterDataLoader(){};
virtual void LoadData() = 0; // prepare data if necessary before calling other functions
virtual std::vector<Category> LoadOrderedCategories() = 0;
virtual std::vector<Unit> LoadOrderedUnits(const Category& c) = 0;
virtual std::unordered_map<Unit, ConversionData, UnitHash> LoadOrderedRatios(const Unit& u) = 0;
virtual bool SupportsCategory(const Category& target) = 0;
};
class ICurrencyConverterDataLoader
{
public:
virtual void SetViewModelCallback(const std::shared_ptr<UnitConversionManager::IViewModelCurrencyCallback>& callback) = 0;
virtual std::pair<std::wstring, std::wstring>
GetCurrencySymbols(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0;
virtual std::pair<std::wstring, std::wstring>
GetCurrencyRatioEquality(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0;
virtual std::wstring GetCurrencyTimestamp() = 0;
virtual concurrency::task<bool> TryLoadDataFromCacheAsync() = 0;
virtual concurrency::task<bool> TryLoadDataFromWebAsync() = 0;
virtual concurrency::task<bool> TryLoadDataFromWebOverrideAsync() = 0;
};
class IUnitConverterVMCallback
{
public:
virtual ~IUnitConverterVMCallback(){};
virtual void DisplayCallback(const std::wstring& from, const std::wstring& to) = 0;
virtual void SuggestedValueCallback(const std::vector<std::tuple<std::wstring, Unit>>& suggestedValues) = 0;
virtual void MaxDigitsReached() = 0;
};
class IUnitConverter
{
public:
virtual ~IUnitConverter()
{
}
virtual void Initialize() = 0; // Use to initialize first time, use deserialize instead to rehydrate
virtual std::vector<Category> GetCategories() = 0;
virtual CategorySelectionInitializer SetCurrentCategory(const Category& input) = 0;
virtual Category GetCurrentCategory() = 0;
virtual void SetCurrentUnitTypes(const Unit& fromType, const Unit& toType) = 0;
virtual void SwitchActive(const std::wstring& newValue) = 0;
virtual std::wstring Serialize() = 0;
virtual void DeSerialize(const std::wstring& serializedData) = 0;
virtual std::wstring SaveUserPreferences() = 0;
virtual void RestoreUserPreferences(_In_ const std::wstring& userPreferences) = 0;
virtual void SendCommand(Command command) = 0;
virtual void SetViewModelCallback(_In_ const std::shared_ptr<IUnitConverterVMCallback>& newCallback) = 0;
virtual void SetViewModelCurrencyCallback(_In_ const std::shared_ptr<IViewModelCurrencyCallback>& newCallback) = 0;
virtual concurrency::task<std::pair<bool, std::wstring>> RefreshCurrencyRatios() = 0;
virtual void Calculate() = 0;
virtual void ResetCategoriesAndRatios() = 0;
};
class UnitConverter : public IUnitConverter, public std::enable_shared_from_this<UnitConverter>
{
public:
UnitConverter(_In_ const std::shared_ptr<IConverterDataLoader>& dataLoader);
UnitConverter(_In_ const std::shared_ptr<IConverterDataLoader>& dataLoader, _In_ const std::shared_ptr<IConverterDataLoader>& currencyDataLoader);
// IUnitConverter
void Initialize() override;
std::vector<Category> GetCategories() override;
CategorySelectionInitializer SetCurrentCategory(const Category& input) override;
Category GetCurrentCategory() override;
void SetCurrentUnitTypes(const Unit& fromType, const Unit& toType) override;
void SwitchActive(const std::wstring& newValue) override;
std::wstring Serialize() override;
void DeSerialize(const std::wstring& serializedData) override;
std::wstring SaveUserPreferences() override;
void RestoreUserPreferences(const std::wstring& userPreference) override;
void SendCommand(Command command) override;
void SetViewModelCallback(_In_ const std::shared_ptr<IUnitConverterVMCallback>& newCallback) override;
void SetViewModelCurrencyCallback(_In_ const std::shared_ptr<IViewModelCurrencyCallback>& newCallback) override;
concurrency::task<std::pair<bool, std::wstring>> RefreshCurrencyRatios() override;
void Calculate() override;
void ResetCategoriesAndRatios() override;
// IUnitConverter
static std::vector<std::wstring> StringToVector(const std::wstring& w, const wchar_t* delimiter, bool addRemainder = false);
static std::wstring Quote(const std::wstring& s);
static std::wstring Unquote(const std::wstring& s);
private:
bool CheckLoad();
double Convert(double value, ConversionData conversionData);
std::vector<std::tuple<std::wstring, Unit>> CalculateSuggested();
void ClearValues();
void TrimString(std::wstring& input);
void InitializeSelectedUnits();
std::wstring RoundSignificant(double num, int numSignificant);
Category StringToCategory(const std::wstring& w);
std::wstring CategoryToString(const Category& c, const wchar_t* delimiter);
std::wstring UnitToString(const Unit& u, const wchar_t* delimiter);
Unit StringToUnit(const std::wstring& w);
ConversionData StringToConversionData(const std::wstring& w);
std::wstring ConversionDataToString(ConversionData d, const wchar_t* delimiter);
void UpdateCurrencySymbols();
void UpdateViewModel();
bool AnyUnitIsEmpty();
std::shared_ptr<IConverterDataLoader> GetDataLoaderForCategory(const Category& category);
std::shared_ptr<ICurrencyConverterDataLoader> GetCurrencyConverterDataLoader();
private:
std::shared_ptr<IConverterDataLoader> m_dataLoader;
std::shared_ptr<IConverterDataLoader> m_currencyDataLoader;
std::shared_ptr<IUnitConverterVMCallback> m_vmCallback;
std::shared_ptr<IViewModelCurrencyCallback> m_vmCurrencyCallback;
std::vector<Category> m_categories;
CategoryToUnitVectorMap m_categoryToUnits;
UnitToUnitToConversionDataMap m_ratioMap;
Category m_currentCategory;
Unit m_fromType;
Unit m_toType;
std::wstring m_currentDisplay;
std::wstring m_returnDisplay;
bool m_currentHasDecimal;
bool m_returnHasDecimal;
bool m_switchedActive;
};
}

11
src/CalcManager/build.sh Normal file
View file

@ -0,0 +1,11 @@
emcc \
-std=c++17 \
-s WASM=1 \
-s LEGALIZE_JS_FFI=0 \
-s RESERVED_FUNCTION_POINTERS=64 \
-s ALLOW_MEMORY_GROWTH=1 \
-s BINARYEN=1 \
-s SIDE_MODULE=1 \
-o CalcManager.wasm \
-s EXPORT_ALL=1 \
CEngine/*.cpp RatPack/*.cpp *.cpp -I.

View file

@ -1,6 +1,6 @@
#pragma once
#if defined(__WEBASSEMBLY__)
#if defined(__EMSCRIPTEN__)
#define HRESULT long
#define _In_opt_
@ -27,4 +27,4 @@ typedef unsigned long DWORD;
#define HRESULT_CODE(hr) ((hr)&0xFFFF)
#define SCODE_CODE(sc) ((sc)&0xFFFF)
#endif
#endif

View file

View file

@ -11,12 +11,15 @@
#include <algorithm>
#include <array>
#include <cassert>
#include <intsafe.h>
#include <list>
#include <ppltasks.h>
#include <regex>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>
#if !defined(__EMSCRIPTEN__)
#include <ppltasks.h>
#include <winerror.h>
#include <intsafe.h>
#endif