Mercurial > hg > orthanc-stone
changeset 729:529189f399ec
Merged am-dev into default
author | Alain Mazy <am@osimis.io> |
---|---|
date | Tue, 21 May 2019 13:27:54 +0200 |
parents | 853e30d17cae (current diff) 8190213e2279 (diff) |
children | ac4fe43551a1 c35e98d22764 |
files | Resources/CodeGeneration/testWasmIntegrated/testWasmIntegratedCpp_api.yaml Resources/CodeGeneration/test_data/test1.jsonc Resources/CodeGeneration/test_data/test1.yaml Resources/CodeGeneration/test_data/test1_bogus_json.jsonc Resources/CodeGeneration/test_data/test1_bogus_schema.jsonc |
diffstat | 22 files changed, 373 insertions(+), 574 deletions(-) [+] |
line wrap: on
line diff
--- a/Framework/Radiography/RadiographyMaskLayer.cpp Tue May 21 11:45:06 2019 +0200 +++ b/Framework/Radiography/RadiographyMaskLayer.cpp Tue May 21 13:27:54 2019 +0200 @@ -135,8 +135,16 @@ // first fill the complete image Orthanc::ImageProcessing::Set(*mask_, OUT_MASK_VALUE); + // clip corners + std::vector<Orthanc::ImageProcessing::ImagePoint> clippedCorners; + for (size_t i = 0; i < corners_.size(); i++) + { + clippedCorners.push_back(corners_[i]); + clippedCorners[i].ClipTo(0, mask_->GetWidth() - 1, 0, mask_->GetHeight() - 1); + } + // fill mask - Orthanc::ImageProcessing::FillPolygon(*mask_, corners_, IN_MASK_VALUE); + Orthanc::ImageProcessing::FillPolygon(*mask_, clippedCorners, IN_MASK_VALUE); }
--- a/Resources/CodeGeneration/README.md Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/README.md Tue May 21 13:27:54 2019 +0200 @@ -10,11 +10,11 @@ `testCppHandler` contains a C++ project that produces an executable slurping a set of text files representing messages defined against -the `test_data/test1.yaml' schema and dumping them to `cout`. +the `test_data/testTestStoneCodeGen.yaml' schema and dumping them to `cout`. 'testWasmIntegrated` contains a small Web app demonstrating the interaction between TypeScript and C++ in WASM. source ~/apps/emsdk/emsdk_env.sh -Install Python and the following packages `pip install pyyaml jinja2` +Install Python and the following packages `pip install pyyaml yamlloader jinja2`
--- a/Resources/CodeGeneration/stonegentool.py Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/stonegentool.py Tue May 21 13:27:54 2019 +0200 @@ -7,6 +7,7 @@ from io import StringIO import time import datetime +import yamlloader """ 1 2 3 4 5 6 7 @@ -186,7 +187,6 @@ RegisterTemplateFunction(template,NeedsCppConstruction) RegisterTemplateFunction(template, DefaultValueToTs) RegisterTemplateFunction(template, DefaultValueToCpp) - RegisterTemplateFunction(template, sorted) return template def MakeTemplateFromFile(templateFileName): @@ -533,7 +533,7 @@ if not (nextCh == ' ' or nextCh == '\n'): lineNumber = schemaText.count("\n",0,i) + 1 raise RuntimeError("Error at line " + str(lineNumber) + " in the schema: colons must be followed by a space or a newline!") - schema = yaml.load(schemaText, Loader = yaml.SafeLoader) + schema = yaml.load(schemaText, Loader = yamlloader.ordereddict.SafeLoader) return schema def GetTemplatingDictFromSchemaFilename(fn):
--- a/Resources/CodeGeneration/stonegentool_test.py Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/stonegentool_test.py Tue May 21 13:27:54 2019 +0200 @@ -87,13 +87,13 @@ self.assertEqual(b4,["int","vector<string>"]) def test_ParseSchema(self): - fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') + fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') obj = LoadSchema(fn) # we're happy if it does not crash :) CheckSchemaSchema(obj) def test_ComputeRequiredDeclarationOrder(self): - fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') + fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') obj = LoadSchema(fn) genOrder: str = ComputeRequiredDeclarationOrder(obj) self.assertEqual(5,len(genOrder)) @@ -110,7 +110,7 @@ def test_genEnums(self): self.maxDiff = None - fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') + fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') obj = LoadSchema(fn) genOrder: str = ComputeRequiredDeclarationOrder(obj) processedSchema = ProcessSchema(obj, genOrder) @@ -127,13 +127,15 @@ self.assertTrue('someBs' in structs['C']['fields']) self.assertTrue('CrispType' in enums) self.assertTrue('Message1' in structs) - self.assertEqual('int32', structs['Message1']['fields']['a'].type) - self.assertEqual('string', structs['Message1']['fields']['b'].type) - self.assertEqual('EnumMonth0', structs['Message1']['fields']['c'].type) - self.assertEqual('bool', structs['Message1']['fields']['d'].type) + self.assertEqual('int32', structs['Message1']['fields']['memberInt32'].type) + self.assertEqual('string', structs['Message1']['fields']['memberString'].type) + self.assertEqual('EnumMonth0', structs['Message1']['fields']['memberEnumMonth'].type) + self.assertEqual('bool', structs['Message1']['fields']['memberBool'].type) + self.assertEqual('float32', structs['Message1']['fields']['memberFloat32'].type) + self.assertEqual('float64', structs['Message1']['fields']['memberFloat64'].type) def test_GenerateTypeScriptEnums(self): - fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') + fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') tdico = GetTemplatingDictFromSchemaFilename(fn) template = Template(""" // end of generic methods {% for enum in enums%} export enum {{enum['name']}} { @@ -167,7 +169,7 @@ self.assertEqual(renderedCodeRef,renderedCode) def test_GenerateCplusplusEnums(self): - fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') + fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') tdico = GetTemplatingDictFromSchemaFilename(fn) template = Template(""" // end of generic methods {% for enum in enums%} enum {{enum['name']}} { @@ -201,45 +203,9 @@ self.assertEqual(renderedCodeRef,renderedCode) def test_generateTsStructType(self): - fn = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') + fn = os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') tdico = GetTemplatingDictFromSchemaFilename(fn) - ref = """ export class Message1 { - a: number; - b: string; - c: EnumMonth0; - d: boolean; - public StoneSerialize(): string { - let container: object = {}; - container['type'] = 'VsolStuff.Message1'; - container['value'] = this; - return JSON.stringify(container); - } - }; - export class Message2 { - toto: string; - tata: Message1[]; - tutu: string[]; - titi: Map<string, string>; - lulu: Map<string, Message1>; - - constructor() - { - this.tata = new Array<Message1>(); - this.tutu = new Array<string>(); - this.titi = new Map<string, string>(); - this.lulu = new Map<string, Message1>(); - } - - public StoneSerialize(): string { - let container: object = {}; - container['type'] = 'VsolStuff.Message2'; - container['value'] = this; - return JSON.stringify(container); - } - }; - -""" # template = MakeTemplate(""" // end of generic methods # {% for struct in struct%} export class {{struct['name']}} { # {% for key in struct['fields']%} {{key}}:{{struct['fields'][key]}}, @@ -290,7 +256,7 @@ public StoneSerialize(): string { let container: object = {}; - container['type'] = 'VsolMessages.A'; + container['type'] = 'TestStoneCodeGen.A'; container['value'] = this; return JSON.stringify(container); } @@ -307,7 +273,7 @@ public StoneSerialize(): string { let container: object = {}; - container['type'] = 'VsolMessages.B'; + container['type'] = 'TestStoneCodeGen.B'; container['value'] = this; return JSON.stringify(container); } @@ -324,53 +290,63 @@ public StoneSerialize(): string { let container: object = {}; - container['type'] = 'VsolMessages.C'; + container['type'] = 'TestStoneCodeGen.C'; container['value'] = this; return JSON.stringify(container); } }; export class Message1 { - a:number; - b:string; - c:EnumMonth0; - d:boolean; + memberInt32:number; + memberString:string; + memberEnumMonth:EnumMonth0; + memberBool:boolean; + memberFloat32:number; + memberFloat64:number; constructor() { - this.a = new number(); - this.b = new string(); - this.c = new EnumMonth0(); - this.d = new boolean(); + this.memberInt32 = new number(); + this.memberString = new string(); + this.memberEnumMonth = new EnumMonth0(); + this.memberBool = new boolean(); + this.memberFloat32 = new number(); + this.memberFloat64 = new number(); } public StoneSerialize(): string { let container: object = {}; - container['type'] = 'VsolMessages.Message1'; + container['type'] = 'TestStoneCodeGen.Message1'; container['value'] = this; return JSON.stringify(container); } }; export class Message2 { - toto:string; - tata:Array<Message1>; - tutu:Array<string>; - titi:Map<string, string>; - lulu:Map<string, Message1>; - movieType:MovieType; + memberString:string; + memberStringWithDefault:string; + memberVectorOfMessage1:Array<Message1>; + memberVectorOfString:Array<string>; + memberMapStringString:Map<string, string>; + memberMapStringStruct:Map<string, Message1>; + memberMapEnumFloat:Map<CrispType, number>; + memberEnumMovieType:MovieType; + memberJson:Object; constructor() { - this.toto = new string(); - this.tata = new Array<Message1>(); - this.tutu = new Array<string>(); - this.titi = new Map<string, string>(); - this.lulu = new Map<string, Message1>(); - this.movieType = new MovieType(); + this.memberString = new string(); + this.memberStringWithDefault = new string(); + this.memberVectorOfMessage1 = new Array<Message1>(); + this.memberVectorOfString = new Array<string>(); + this.memberMapStringString = new Map<string, string>(); + this.memberMapStringStruct = new Map<string, Message1>(); + this.memberMapEnumFloat = new Map<CrispType, number>(); + this.memberEnumMovieType = new MovieType(); + this.memberJson = new Object(); } public StoneSerialize(): string { let container: object = {}; - container['type'] = 'VsolMessages.Message2'; + container['type'] = 'TestStoneCodeGen.Message2'; container['value'] = this; return JSON.stringify(container); } @@ -383,7 +359,7 @@ def test_generateWholeTsFile(self): schemaFile = \ - os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') + os.path.join(os.path.dirname(__file__), 'test_data', 'testTestStoneCodeGen.yaml') tdico = GetTemplatingDictFromSchemaFilename(schemaFile) tsTemplateFile = \ os.path.join(os.path.dirname(__file__), 'template.in.ts.j2')
--- a/Resources/CodeGeneration/template.in.h.j2 Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/template.in.h.j2 Tue May 21 13:27:54 2019 +0200 @@ -109,6 +109,21 @@ } /** Throws in case of problem */ + inline void _StoneDeserializeValue(float& destValue, const Json::Value& jsonValue) + { + if (!jsonValue.isNull()) + { + destValue = jsonValue.asFloat(); + } + } + + inline Json::Value _StoneSerializeValue(float value) + { + Json::Value result(value); + return result; + } + + /** Throws in case of problem */ inline void _StoneDeserializeValue(bool& destValue, const Json::Value& jsonValue) { if (!jsonValue.isNull()) @@ -167,10 +182,21 @@ return out; } + inline std::string ToString(const std::string& str) + { + return str; + } + + inline void FromString(std::string& value, std::string strValue) + { + value = strValue; + } + + /** Throws in case of problem */ - template<typename T> + template<typename TK, typename TV> void _StoneDeserializeValue( - std::map<std::string, T>& destValue, const Json::Value& jsonValue) + std::map<TK, TV>& destValue, const Json::Value& jsonValue) { if (!jsonValue.isNull()) { @@ -180,10 +206,12 @@ itr != jsonValue.end(); itr++) { - std::string key; - _StoneDeserializeValue(key, itr.key()); + std::string strKey; + _StoneDeserializeValue(strKey, itr.key()); + TK key; + FromString(key, strKey); // if you have a compile error here, it means that your type is not suitable to be the key of a map (or you should overwrite the FromString/ToString in template.in.h.j2) - T innerDestValue; + TV innerDestValue; _StoneDeserializeValue(innerDestValue, *itr); destValue[key] = innerDestValue; @@ -191,29 +219,30 @@ } } - template<typename T> - Json::Value _StoneSerializeValue(const std::map<std::string,T>& value) + template<typename TK, typename TV> + Json::Value _StoneSerializeValue(const std::map<TK, TV>& value) { Json::Value result(Json::objectValue); - for (typename std::map<std::string, T>::const_iterator it = value.cbegin(); + for (typename std::map<TK, TV>::const_iterator it = value.cbegin(); it != value.cend(); ++it) { // it->first it->second - result[it->first] = _StoneSerializeValue(it->second); + result[ToString(it->first)] = _StoneSerializeValue(it->second); } return result; } - template<typename T> - std::ostream& StoneDumpValue(std::ostream& out, const std::map<std::string,T>& value, size_t indent) + template<typename TK, typename TV> + std::ostream& StoneDumpValue(std::ostream& out, const std::map<TK, TV>& value, size_t indent) { out << MakeIndent(indent) << "{\n"; - for (typename std::map<std::string, T>::const_iterator it = value.cbegin(); + for (typename std::map<TK, TV>::const_iterator it = value.cbegin(); it != value.cend(); ++it) { out << MakeIndent(indent+2) << "\"" << it->first << "\" : "; StoneDumpValue(out, it->second, indent+2); + out << ", \n"; } out << MakeIndent(indent) << "}\n"; return out; @@ -224,7 +253,7 @@ void _StoneDeserializeValue( std::vector<T>& destValue, const Json::Value& jsonValue) { - if (!jsonValue.isNull()) + if (!jsonValue.isNull() && jsonValue.isArray()) { destValue.clear(); destValue.reserve(jsonValue.size()); @@ -255,6 +284,7 @@ for (size_t i = 0; i < value.size(); ++i) { StoneDumpValue(out, value[i], indent+2); + out << ", \n"; } out << MakeIndent(indent) << "]\n"; return out; @@ -265,7 +295,7 @@ void _StoneDeserializeValue( std::set<T>& destValue, const Json::Value& jsonValue) { - if (!jsonValue.isNull()) + if (!jsonValue.isNull() && jsonValue.isArray()) { destValue.clear(); for (Json::Value::ArrayIndex i = 0; i != jsonValue.size(); i++) @@ -295,6 +325,7 @@ for (typename std::set<T>::const_iterator it = value.begin(); it != value.end(); ++it) { StoneDumpValue(out, *it, indent+2); + out << ", \n"; } out << MakeIndent(indent) << "]\n"; return out; @@ -381,7 +412,7 @@ { {% for key in enum['fields']%} if( value == {{enum['name']}}_{{key}}) { - out << MakeIndent(indent) << "{{key}}" << std::endl; + out << MakeIndent(indent) << "{{key}}"; } {%endfor%} return out; } @@ -394,9 +425,9 @@ struct {{struct['name']}} { -{% if struct %}{% if struct['fields'] %}{% for key in sorted(struct['fields']) %} {{CanonToCpp(struct['fields'][key]['type'])}} {{key}}; +{% if struct %}{% if struct['fields'] %}{% for key in struct['fields'] %} {{CanonToCpp(struct['fields'][key]['type'])}} {{key}}; {% endfor %}{% endif %}{% endif %} - {{struct['name']}}({% if struct %}{% if struct['fields'] %}{% for key in sorted(struct['fields']) %}{{CanonToCpp(struct['fields'][key]['type'])}} {{key}} = {% if struct['fields'][key]['defaultValue'] %}{{DefaultValueToCpp(rootName,enums,struct['fields'][key])}} {%else%} {{CanonToCpp(struct['fields'][key]['type'])}}() {%endif%} {{ ", " if not loop.last }}{% endfor %}{% endif %}{% endif %}) + {{struct['name']}}({% if struct %}{% if struct['fields'] %}{% for key in struct['fields'] %}{{CanonToCpp(struct['fields'][key]['type'])}} {{key}} = {% if struct['fields'][key]['defaultValue'] %}{{DefaultValueToCpp(rootName,enums,struct['fields'][key])}} {%else%} {{CanonToCpp(struct['fields'][key]['type'])}}() {%endif%} {{ ", " if not loop.last }}{% endfor %}{% endif %}{% endif %}) { {% if struct %}{% if struct['fields'] %}{% for key in struct['fields']%} this->{{key}} = {{key}}; {% endfor %}{% endif %}{% endif %} } @@ -421,11 +452,11 @@ inline std::ostream& StoneDumpValue(std::ostream& out, const {{struct['name']}}& value, size_t indent = 0) { out << MakeIndent(indent) << "{\n"; -{% if struct %}{% if struct['fields'] %}{% for key in struct['fields']%} out << MakeIndent(indent) << "{{key}}:\n"; +{% if struct %}{% if struct['fields'] %}{% for key in struct['fields']%} out << MakeIndent(indent+2) << "{{key}}: "; StoneDumpValue(out, value.{{key}},indent+2); - out << "\n"; + out << ", \n"; {% endfor %}{% endif %}{% endif %} - out << MakeIndent(indent) << "}\n"; + out << MakeIndent(indent) << "}"; return out; }
--- a/Resources/CodeGeneration/testCppHandler/CMakeLists.txt Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/testCppHandler/CMakeLists.txt Tue May 21 13:27:54 2019 +0200 @@ -3,13 +3,13 @@ project(testCppHandler) set(testCppHandler_Codegen_Deps - ${CMAKE_CURRENT_LIST_DIR}/../test_data/test1.yaml + ${CMAKE_CURRENT_LIST_DIR}/../test_data/testTestStoneCodeGen.yaml ${CMAKE_CURRENT_LIST_DIR}/../template.in.h.j2 ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/VsolMessages_generated.hpp - COMMAND python ${CMAKE_CURRENT_LIST_DIR}/../stonegentool.py -o ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/../test_data/test1.yaml + COMMAND python ${CMAKE_CURRENT_LIST_DIR}/../stonegentool.py -o ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/../test_data/testTestStoneCodeGen.yaml DEPENDS ${testCppHandler_Codegen_Deps} )
--- a/Resources/CodeGeneration/testCppHandler/README.md Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/testCppHandler/README.md Tue May 21 13:27:54 2019 +0200 @@ -25,8 +25,10 @@ - `cmake -G "Visual Studio 15 2017 Win64" ..` (modify for your current Visual Studio version) - `cmake --build . --config Debug` or - `cmake --build . --config Release` +How to execute the test +======================= +- `cd test_data && testCppHandler --pattern=*.json` -
--- a/Resources/CodeGeneration/testCppHandler/main.cpp Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/testCppHandler/main.cpp Tue May 21 13:27:54 2019 +0200 @@ -8,7 +8,7 @@ #include <boost/program_options.hpp> using namespace boost::program_options; -#include "VsolMessages_generated.hpp" +#include "TestStoneCodeGen_generated.hpp" /** Transforms `str` by replacing occurrences of `oldStr` with `newStr`, using @@ -39,32 +39,32 @@ return string(bytes.data(), fileSize); } -class MyHandler : public VsolMessages::IHandler +class MyHandler : public TestStoneCodeGen::IHandler { public: - virtual bool Handle(const VsolMessages::A& value) override + virtual bool Handle(const TestStoneCodeGen::A& value) override { - VsolMessages::StoneDumpValue(cout, value); + TestStoneCodeGen::StoneDumpValue(cout, value); return true; } - virtual bool Handle(const VsolMessages::B& value) override + virtual bool Handle(const TestStoneCodeGen::B& value) override { - VsolMessages::StoneDumpValue(cout, value); + TestStoneCodeGen::StoneDumpValue(cout, value); return true; } - virtual bool Handle(const VsolMessages::C& value) override + virtual bool Handle(const TestStoneCodeGen::C& value) override { - VsolMessages::StoneDumpValue(cout, value); + TestStoneCodeGen::StoneDumpValue(cout, value); return true; } - virtual bool Handle(const VsolMessages::Message1& value) override + virtual bool Handle(const TestStoneCodeGen::Message1& value) override { - VsolMessages::StoneDumpValue(cout, value); + TestStoneCodeGen::StoneDumpValue(cout, value); return true; } - virtual bool Handle(const VsolMessages::Message2& value) override + virtual bool Handle(const TestStoneCodeGen::Message2& value) override { - VsolMessages::StoneDumpValue(cout, value); + TestStoneCodeGen::StoneDumpValue(cout, value); return true; } }; @@ -77,7 +77,7 @@ cout << "+--------------------------------------------+\n"; MyHandler handler; auto contents = SlurpFile(filePath.path().string()); - VsolMessages::StoneDispatchToHandler(contents, &handler); + TestStoneCodeGen::StoneDispatchToHandler(contents, &handler); } int main(int argc, char** argv)
--- a/Resources/CodeGeneration/testCppHandler/test_data/test_Message2.json Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/testCppHandler/test_data/test_Message2.json Tue May 21 13:27:54 2019 +0200 @@ -1,40 +1,47 @@ { - "type": "VsolMessages.Message2", + "type": "TestStoneCodeGen.Message2", "value": { - "tata": [ + "memberVectorOfMessage1": [ { - "a": 42, - "b": "Benjamin", - "c": 0, - "d": false + "memberInt32": 42, + "memberString": "Benjamin", + "memberEnumMonth": "January", + "memberBool": false, + "memberFloat32": 0.1, + "memberFloat64": -0.2 }, { - "a": 43, - "b": "Sandrine", - "c": 2 + "memberInt32": 43, + "memberString": "Sandrine", + "memberEnumMonth": "March" } ], - "tutu": [ + "memberVectorOfString": [ "Mercadet", "Poisson" ], - "titi": { + "memberMapStringString": { "44": "key 44", "45": "key 45" }, - "lulu": { + "memberMapStringStruct": { "54": { - "a": 43, - "b": "Sandrine", - "c": 2 + "memberInt32": 43, + "memberString": "Sandrine", + "memberEnumMonth": "March" }, "55": { - "a": 42, - "b": "Benjamin", - "c": 0, - "d": false + "memberInt32": 42, + "memberString": "Benjamin", + "memberEnumMonth": "January", + "memberBool": false } }, - "toto": "Prout zizi" + "memberString": "Prout zizi", + "memberMapEnumFloat" : { + "SaltAndPepper" : 0.1, + "CreamAndChives" : -0.2 + }, + "memberJson" : {"custom-key": "custom-value"} } } \ No newline at end of file
--- a/Resources/CodeGeneration/testWasmIntegrated/CMakeLists.txt Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/testWasmIntegrated/CMakeLists.txt Tue May 21 13:27:54 2019 +0200 @@ -21,14 +21,14 @@ set(jsoncppRootDir ${CMAKE_CURRENT_LIST_DIR}/jsoncpp-1.8.4) add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/testWasmIntegratedCpp_generated.hpp ${CMAKE_CURRENT_BINARY_DIR}/testWasmIntegratedCpp_generated.ts - COMMAND python3 ${CMAKE_CURRENT_LIST_DIR}/../stonegentool.py -o ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/testWasmIntegratedCpp_api.yaml - DEPENDS ${testCppHandler_Codegen_Deps} ${CMAKE_CURRENT_LIST_DIR}/testWasmIntegratedCpp_api.yaml + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/TestStoneCodeGen_generated.hpp ${CMAKE_CURRENT_BINARY_DIR}/TestStoneCodeGen_generated.ts + COMMAND python3 ${CMAKE_CURRENT_LIST_DIR}/../stonegentool.py -o ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/../test_data/testTestStoneCodeGen.yaml + DEPENDS ${testCppHandler_Codegen_Deps} ${CMAKE_CURRENT_LIST_DIR}/../test_data/testTestStoneCodeGen.yaml ) add_executable(testWasmIntegratedCpp main.cpp - ${CMAKE_CURRENT_BINARY_DIR}/testWasmIntegratedCpp_generated.hpp + ${CMAKE_CURRENT_BINARY_DIR}/TestStoneCodeGen_generated.hpp ${jsoncppRootDir}/jsoncpp.cpp ${testCppHandler_Codegen_Deps})
--- a/Resources/CodeGeneration/testWasmIntegrated/DefaultLibrary.js Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/testWasmIntegrated/DefaultLibrary.js Tue May 21 13:27:54 2019 +0200 @@ -9,7 +9,7 @@ }, SendMessageFromCppJS: function(statusUpdateMessage) { var statusUpdateMessage_ = UTF8ToString(statusUpdateMessage); - SendMessageFromCpp(statusUpdateMessage_); + window.SendMessageFromCpp(statusUpdateMessage_); } });
--- a/Resources/CodeGeneration/testWasmIntegrated/build-web.sh Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/testWasmIntegrated/build-web.sh Tue May 21 13:27:54 2019 +0200 @@ -4,7 +4,7 @@ mkdir -p build-final # compile TS to JS -tsc --module commonjs --sourceMap -t ES2015 --outDir "build-tsc/" build-wasm/testWasmIntegratedCpp_generated.ts testWasmIntegrated.ts +tsc --module commonjs --sourceMap -t ES2015 --outDir "build-tsc/" build-wasm/TestStoneCodeGen_generated.ts testWasmIntegrated.ts # bundle JS files to final build dir browserify "build-tsc/build-wasm/testWasmIntegratedCpp_generated.js" "build-tsc/testWasmIntegrated.js" -o "build-final/testWasmIntegratedApp.js" @@ -22,8 +22,10 @@ # copy WASM binary to output dir cp build-wasm/testWasmIntegratedCpp.wasm build-final/ -echo "...Serving files at http://127.0.0.1:8080/" -echo "Please open build_final/testWasmIntegrated.html" +cp ../test_data/testTestStoneCodeGen.yaml build-final/ +cp ../testCppHandler/test_data/test_Message2.json build-final/cppHandler_test_Message2.json + +echo "...Serving files at http://127.0.0.1:8080/build-final/testWasmIntegrated.html" sudo python3 serve.py
--- a/Resources/CodeGeneration/testWasmIntegrated/main.cpp Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/testWasmIntegrated/main.cpp Tue May 21 13:27:54 2019 +0200 @@ -1,7 +1,7 @@ #include <iostream> #include <sstream> #include <emscripten/emscripten.h> -#include "testWasmIntegratedCpp_generated.hpp" +#include "TestStoneCodeGen_generated.hpp" using std::stringstream; @@ -55,35 +55,72 @@ #define HANDLE_MESSAGE(Type,value) \ stringstream ss; \ ss << "Received an instance of:\n" #Type "\n. Here's the dump:\n"; \ - testWasmIntegratedCpp::StoneDumpValue(ss, value, 0); \ + TestStoneCodeGen::StoneDumpValue(ss, value, 0); \ SendFreeTextFromCppJS(ss.str().c_str()); \ return true; -class MyHandler : public testWasmIntegratedCpp::IHandler +#define ECHO_MESSAGE(Type,value) \ + stringstream ss; \ + ss << "Received an instance of:\n" #Type "\n. Here's the dump:\n"; \ + TestStoneCodeGen::StoneDumpValue(ss, value, 0); \ + SendFreeTextFromCppJS(ss.str().c_str()); \ + std::string serializedInCpp = StoneSerialize(value); \ + SendMessageFromCppJS(serializedInCpp.c_str()); \ + return true; + +class MyHandler : public TestStoneCodeGen::IHandler { public: - virtual bool Handle(const testWasmIntegratedCpp::A& value) override + virtual bool Handle(const TestStoneCodeGen::A& value) override { - HANDLE_MESSAGE(testWasmIntegratedCpp::A,value) + HANDLE_MESSAGE(TestStoneCodeGen::A,value) + } + virtual bool Handle(const TestStoneCodeGen::B& value) override + { + HANDLE_MESSAGE(TestStoneCodeGen::B,value) } - virtual bool Handle(const testWasmIntegratedCpp::B& value) override + + virtual bool Handle(const TestStoneCodeGen::Message1& value) override { - HANDLE_MESSAGE(testWasmIntegratedCpp::B,value) + HANDLE_MESSAGE(TestStoneCodeGen::Message1,value) + } + + virtual bool Handle(const TestStoneCodeGen::Message2& value) override + { + HANDLE_MESSAGE(TestStoneCodeGen::Message2,value) } - virtual bool Handle(const testWasmIntegratedCpp::Message1& value) override + virtual bool Handle(const TestStoneCodeGen::C& value) override { - HANDLE_MESSAGE(testWasmIntegratedCpp::Message1,value) + HANDLE_MESSAGE(TestStoneCodeGen::C,value) + } +}; + +class MyEchoHandler : public TestStoneCodeGen::IHandler +{ + public: + virtual bool Handle(const TestStoneCodeGen::A& value) override + { + ECHO_MESSAGE(TestStoneCodeGen::A,value) + } + virtual bool Handle(const TestStoneCodeGen::B& value) override + { + ECHO_MESSAGE(TestStoneCodeGen::B,value) } - virtual bool Handle(const testWasmIntegratedCpp::Message2& value) override + virtual bool Handle(const TestStoneCodeGen::Message1& value) override { - HANDLE_MESSAGE(testWasmIntegratedCpp::Message2,value) + ECHO_MESSAGE(TestStoneCodeGen::Message1,value) } - virtual bool Handle(const testWasmIntegratedCpp::C& value) override + virtual bool Handle(const TestStoneCodeGen::Message2& value) override { - HANDLE_MESSAGE(testWasmIntegratedCpp::C,value) + ECHO_MESSAGE(TestStoneCodeGen::Message2,value) + } + + virtual bool Handle(const TestStoneCodeGen::C& value) override + { + ECHO_MESSAGE(TestStoneCodeGen::C,value) } }; @@ -92,10 +129,29 @@ MyHandler handler; try { - bool handled = testWasmIntegratedCpp::StoneDispatchToHandler(message,&handler); + bool handled = TestStoneCodeGen::StoneDispatchToHandler(message,&handler); if(!handled) { - SendFreeTextFromCppJS("This message is valid JSON, but was not recognized!"); + SendFreeTextFromCppJS("This message is valid JSON, but was not handled!"); + } + } + catch(std::exception& e) + { + stringstream ss; + ss << "Error while parsing message: " << e.what() << "\n"; + SendFreeTextFromCppJS(ss.str().c_str()); + } +} + +extern "C" void EMSCRIPTEN_KEEPALIVE SendMessageToCppForEcho(const char* message) +{ + MyEchoHandler echoHandler; + try + { + bool handled = TestStoneCodeGen::StoneDispatchToHandler(message,&echoHandler); + if(!handled) + { + SendFreeTextFromCppJS("This message is valid JSON, but was not handled by the echo handler!"); } } catch(std::exception& e)
--- a/Resources/CodeGeneration/testWasmIntegrated/styles.css Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/testWasmIntegrated/styles.css Tue May 21 13:27:54 2019 +0200 @@ -9,7 +9,7 @@ "Test1 Test2 Test3 Test4 . . ." ". . . . . . ." "Test5 Test6 Test7 Test8 . . ." - ". . . . . . ." + "TestTsCppTs . . . . . ." ". . . . . . ." ; height: 480px; @@ -59,6 +59,8 @@ .TestWasm-Test8 { grid-area: Test8; } +.TestWasm-ts-cpp-ts { grid-area: TestTsCppTs; } + .TestWasm-button { width:80px; }
--- a/Resources/CodeGeneration/testWasmIntegrated/testWasmIntegrated.html Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/testWasmIntegrated/testWasmIntegrated.html Tue May 21 13:27:54 2019 +0200 @@ -31,7 +31,7 @@ </div> <div class="TestWasm-Test1"> - <button class="TestWasm-button" tool-selector="Test 1">Test 1</button> + <button class="TestWasm-button" tool-selector="Test CppHandler message2">Test CppHandler message2</button> </div> <div class="TestWasm-Test2"> <button class="TestWasm-button" tool-selector="Test 2">Test 2</button> @@ -54,6 +54,9 @@ <div class="TestWasm-Test8"> <button class="TestWasm-button" tool-selector="Test 8">Test 8</button> </div> + <div class="TestWasm-ts-cpp-ts"> + <button class="TestWasm-button" tool-selector="Test-ts-cpp-ts">Test ts-cpp-ts</button> + </div> <!-- <button class="TestWasm-button" class="TestWasm-Test1" tool-selector="Test 1">Test 1</button> <button class="TestWasm-button" class="TestWasm-Test2" tool-selector="Test 2">Test 2</button>
--- a/Resources/CodeGeneration/testWasmIntegrated/testWasmIntegrated.ts Tue May 21 11:45:06 2019 +0200 +++ b/Resources/CodeGeneration/testWasmIntegrated/testWasmIntegrated.ts Tue May 21 13:27:54 2019 +0200 @@ -1,6 +1,8 @@ var SendMessageToCpp: Function = null; export var TestWasmIntegratedModule : any; +import * as TestStoneCodeGen from './build-wasm/TestStoneCodeGen_generated' + /* +--------------------------------------------------+ | install emscripten handlers | @@ -48,121 +50,23 @@ | define stock messages | +--------------------------------------------------+ */ -let schemaText: string = `rootName: testWasmIntegratedCpp - -struct B: - someAs: vector<A> - someInts: vector<int32> - -struct C: - someBs: vector<B> - ddd: vector<string> - definition: vector<json> - -struct A: - someStrings: vector<string> - someInts2: vector<int32> - movies: vector<MovieType> - -struct Message1: - a: int32 - b: string - c: EnumMonth0 - d: bool - -struct Message2: - toto: string - tata: vector<Message1> - tutu: vector<string> - titi: map<string, string> - lulu: map<string, Message1> - movieType: MovieType - definition: json - -enum MovieType: - - RomCom - - Horror - - ScienceFiction - - Vegetables - -enum CrispType: - - SaltAndPepper - - CreamAndChives - - Paprika - - Barbecue - -enum EnumMonth0: - - January - - February - - March -`; +let schemaText: string = null; +fetch("testTestStoneCodeGen.yaml").then(function(res) {return res.text();}).then(function(text) {schemaText = text;}); let stockSerializedMessages = new Map<string,string>(); -stockSerializedMessages["Test 1"] = `{ - "type" : "testWasmIntegratedCpp.Message2", - "value" : - { - "lulu" : - { - "54" : - { - "a" : 43, - "b" : "Sandrine", - "c" : "March", - "d" : true - }, - "55" : - { - "a" : 42, - "b" : "Benjamin", - "c" : "January", - "d" : false - } - }, - "tata" : - [ - { - "a" : 42, - "b" : "Benjamin", - "c" : "March", - "d" : false - }, - { - "a" : 43, - "b" : "Sandrine", - "c" : "January", - "d" : false - } - ], - "titi" : - { - "44" : "key 44", - "45" : "key 45" - }, - "toto" : "Prout zizi", - "tutu" : - [ - "Mercadet", - "Poisson" - ], - "definition": - { - "val" : [ "berk", 42 ], - "zozo" : - { - "23": "zloutch", - "lalala": 42 - } - } - } -}`; +stockSerializedMessages["Test CppHandler message2"] = null; +fetch("cppHandler_test_Message2.json").then(function(res) {return res.text();}).then(function(text) {stockSerializedMessages["Test CppHandler message2"] = text;}); + stockSerializedMessages["Test 2"] = ` { - "type" : "testWasmIntegratedCpp.Message1", + "type" : "TestStoneCodeGen.Message1", "value" : { - "a" : -987, - "b" : "Salomé", - "c" : 2, - "d" : true + "memberInt32" : -987, + "memberString" : "Salomé", + "memberEnumMonth" : "March", + "memberBool" : true, + "memberFloat32" : 0.1, + "memberFloat64" : -0.2, + "extraMember" : "don't care" } }`; stockSerializedMessages["Test 3"] = "Test 3 stock message sdfsfsdfsdf"; @@ -205,11 +109,60 @@ } (<any> window).SendFreeTextFromCpp = SendFreeTextFromCpp; +var referenceMessages = Array<any>(); + +function testTsCppTs() { + var r = new TestStoneCodeGen.Message2(); + r.memberEnumMovieType = TestStoneCodeGen.MovieType.RomCom; + r.memberStringWithDefault = "overriden"; + r.memberMapEnumFloat[TestStoneCodeGen.CrispType.CreamAndChives] = 0.5; + r.memberString = "reference-messsage2-test1"; + + referenceMessages[r.memberString] = r; + var strMsg2 = r.StoneSerialize(); + let SendMessageToCppForEchoLocal = (<any> window).Module.cwrap('SendMessageToCppForEcho', 'string', ['string']); + SendMessageToCppForEchoLocal(strMsg2); +} + +class MyEchoHandler implements TestStoneCodeGen.IHandler +{ + public HandleMessage2(value: TestStoneCodeGen.Message2): boolean + { + if (value.memberString in referenceMessages) { + let r = referenceMessages[value.memberString]; + let equals = (value.memberStringWithDefault == r.memberStringWithDefault); + if (TestStoneCodeGen.CrispType.CreamAndChives in r.memberMapEnumFloat) { + equals == equals && r.memberMapEnumFloat[TestStoneCodeGen.CrispType.CreamAndChives] == value.memberMapEnumFloat[TestStoneCodeGen.CrispType.CreamAndChives]; + } + // TODO continue comparison + + if (equals) { + console.log("objects are equals after round trip"); + return true; + } + } + console.log("problem after round trip"); + return true; + } +} + +function SendMessageFromCpp(txt: string):string +{ + setCppOutputValue(getCppOutputValue() + "\n" + txt); + TestStoneCodeGen.StoneDispatchToHandler(txt, new MyEchoHandler()); + return ""; +} +(<any> window).SendMessageFromCpp = SendMessageFromCpp; + + function ButtonClick(buttonName: string) { if (buttonName.startsWith('Test ')) { setSerializedInputValue(stockSerializedMessages[buttonName]); } + else if (buttonName == "Test-ts-cpp-ts") { + testTsCppTs(); + } else if(buttonName == 'Trigger') { let serializedInputValue:string = getSerializedInputValue();
--- a/Resources/CodeGeneration/testWasmIntegrated/testWasmIntegratedCpp_api.yaml Tue May 21 11:45:06 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -# -# 1 2 3 4 5 6 7 8 -# 345678901234567890123456789012345678901234567890123456789012345678901234567890 -# -rootName: testWasmIntegratedCpp - -struct B: - someAs: vector<A> - someInts: vector<int32> - -struct C: - someBs: vector<B> - ddd: vector<string> - definition: vector<json> - -struct A: - someStrings: vector<string> - someInts2: vector<int32> - movies: vector<MovieType> - -struct Message1: - a: int32 - b: string - c: EnumMonth0 - d: bool - -struct Message2: - toto: string - tata: vector<Message1> - tutu: vector<string> - titi: map<string, string> - lulu: map<string, Message1> - movieType: MovieType - definition: json - -enum MovieType: - - RomCom - - Horror - - ScienceFiction - - Vegetables - -enum CrispType: - - SaltAndPepper - - CreamAndChives - - Barbecue - - Paprika - -enum EnumMonth0: - - January - - February - - March - -enum Tata: - - Lolo - - Rrrrrrrrrrrr - - -
--- a/Resources/CodeGeneration/test_data/test1.jsonc Tue May 21 11:45:06 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/* - 1 2 3 4 5 6 7 -12345678901234567890123456789012345678901234567890123456789012345678901234567890 -*/ -{ - "root_name":"test1", - "types": [ - { - "name":"B", - "kind":"struct", - "fields": [ - { - "name":"someAs", - "type":"vector<A>" - }, - { - "name":"someInts", - "type":"vector<int32>" - } - ] - }, - { - "name":"C", - "kind":"struct", - "fields": [ - { - "name":"someBs", - "type":"vector<B>" - }, - { - "name":"ddd", - "type":"vector<D>" - } - ] - }, - { - "name":"A", - "kind":"struct", - "fields": [ - { - "name":"someStrings", - "type":"vector<string>" - }, - { - "name":"someInts2", - "type":"vector<int32>" - } - ] - }, - { - "name":"MovieType", - "kind":"enum", - "fields": [ - { - "name":"Romcom" - }, - { - "name":"Horror" - }, - { - "name":"ScienceFiction" - }, - { - "name":"Vegetables" - } - ] - }, - { - "name":"CrispType", - "kind":"enum", - "fields": [ - { - "name":"SaltAndPepper" - }, - { - "name":"CreamAndChives" - }, - { - "name":"Paprika" - }, - { - "name":"Barbecue" - } - ] - } - ] -}
--- a/Resources/CodeGeneration/test_data/test1.yaml Tue May 21 11:45:06 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -# -# 1 2 3 4 5 6 7 8 -# 345678901234567890123456789012345678901234567890123456789012345678901234567890 -# -rootName: VsolMessages - -struct B: - someAs: vector<A> - someInts: vector<int32> - -struct C: - someBs: vector<B> - ddd: vector<string> - -struct A: - someStrings: vector<string> - someInts2: vector<int32> - movies: vector<MovieType> - -struct Message1: - a: int32 - b: string - c: EnumMonth0 - d: bool - -struct Message2: - toto: string = "my-default-value" - tata: vector<Message1> - tutu: vector<string> - titi: map<string, string> - lulu: map<string, Message1> - movieType: MovieType - -enum MovieType: - - RomCom - - Horror - - ScienceFiction - - Vegetables - -enum CrispType: - - SaltAndPepper - - CreamAndChives - - Paprika - - Barbecue - -enum EnumMonth0: - - January - - February - - March
--- a/Resources/CodeGeneration/test_data/test1_bogus_json.jsonc Tue May 21 11:45:06 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -{ - "root_name":"test1", - "types": [ - { - "name":"B", - "kind":"struct", - "fields": [ - { - "name":"someAs", - "type":"vector<A>" - }}, - { - "name":"someInts", - "type":"vector<int32>" - } - ] - }, - { - "name":"A", - "kind":"struct", - "fields": [ - { - "name":"someStrings", - "type":"vector<string>" - }, - { - "name":"someInts2", - "type":"vector<int32>" - } - ] - }, - { - "name":"MovieType", - "kind":"enum", - "fields": [ - { - "name":"Romcom", - }, - { - "name":"Horror", - }, - { - "name":"ScienceFiction", - }, - { - "name":"Vegetables", - } - } - ] -} - -/* - 1 2 3 4 5 6 7 -12345678901234567890123456789012345678901234567890123456789012345678901234567890 -*/
--- a/Resources/CodeGeneration/test_data/test1_bogus_schema.jsonc Tue May 21 11:45:06 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -{ - "root_name":"test1", - "types": [ - { - "name":"B", - "kind":"struct", - "fields": [ - { - "name":"someAs", - "type":"vector<A>" - }, - { - "name":"someInts", - "type":"vector<int32>" - } - ] - }, - { - "name":"A", - "kiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiind":"struct", - "fields": [ - { - "name":"someStrings", - "type":"vector<string>" - }, - { - "name":"someInts2", - "type":"vector<int32>" - } - ] - }, - { - "name":"MovieType", - "kind":"enum", - "fields": [ - { - "naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaame":"Romcom" - }, - { - "name":"Horror" - }, - { - "name":"ScienceFiction" - }, - { - "name":"Vegetables" - } - ] - } - ] -} - -/* - 1 2 3 4 5 6 7 -12345678901234567890123456789012345678901234567890123456789012345678901234567890 -*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CodeGeneration/test_data/testTestStoneCodeGen.yaml Tue May 21 13:27:54 2019 +0200 @@ -0,0 +1,64 @@ +# +# 1 2 3 4 5 6 7 8 +# 345678901234567890123456789012345678901234567890123456789012345678901234567890 +# +rootName: TestStoneCodeGen + +struct B: + __handler: cpp + + someAs: vector<A> + someInts: vector<int32> + +struct C: + __handler: cpp + + someBs: vector<B> + ddd: vector<string> + +struct A: + __handler: cpp + + someStrings: vector<string> + someInts2: vector<int32> + movies: vector<MovieType> + +struct Message1: + __handler: cpp + + memberInt32: int32 + memberString: string + memberEnumMonth: EnumMonth0 + memberBool: bool + memberFloat32: float32 + memberFloat64: float64 + +struct Message2: + __handler: [cpp, ts] + + memberString: string + memberStringWithDefault: string = "my-default-value" + memberVectorOfMessage1: vector<Message1> + memberVectorOfString: vector<string> + memberMapStringString: map<string, string> + memberMapStringStruct: map<string, Message1> + memberMapEnumFloat: map<CrispType, float32> + memberEnumMovieType: MovieType + memberJson: json + +enum MovieType: + - RomCom + - Horror + - ScienceFiction + - Vegetables + +enum CrispType: + - SaltAndPepper + - CreamAndChives + - Paprika + - Barbecue + +enum EnumMonth0: + - January + - February + - March