Mercurial > hg > orthanc-stone
changeset 494:fc17251477d6 bgo-commands-codegen
TS and CPP tests OK. Ongoing code for C++ program that reads list of serialized messages in N files. Requires conan
author | bgo-osimis |
---|---|
date | Sat, 23 Feb 2019 10:18:13 +0100 |
parents | 6fbf2eae7c88 |
children | 6405435480ae |
files | .hgignore Resources/CodeGeneration/README.md Resources/CodeGeneration/runts.ps1 Resources/CodeGeneration/stonegentool.py Resources/CodeGeneration/stonegentool_test.py Resources/CodeGeneration/template.in.h Resources/CodeGeneration/template.in.ts Resources/CodeGeneration/testCppHandler/CMakeLists.txt Resources/CodeGeneration/testCppHandler/README.md Resources/CodeGeneration/testCppHandler/conanfile.txt Resources/CodeGeneration/testCppHandler/main.cpp Resources/CodeGeneration/test_data/test1.yaml Resources/CodeGeneration/test_stonegen.html Resources/CodeGeneration/test_stonegen.ts |
diffstat | 14 files changed, 766 insertions(+), 131 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Fri Feb 22 10:48:43 2019 +0100 +++ b/.hgignore Sat Feb 23 10:18:13 2019 +0100 @@ -11,3 +11,7 @@ Resources/CommandTool/flatc-tests/basic/build/ .vscode/ Resources/CodeGeneration/__pycache__ +Resources/CodeGeneration/build/ +Resources/CodeGeneration/build_browser/ +Resources/CodeGeneration/testCppHandler/build/ +Resources/CodeGeneration/testCppHandler/build_msbuild/
--- a/Resources/CodeGeneration/README.md Fri Feb 22 10:48:43 2019 +0100 +++ b/Resources/CodeGeneration/README.md Sat Feb 23 10:18:13 2019 +0100 @@ -1,24 +1,10 @@ -class TestMessage { - s1: string; - s2: Array<string>; - s3: Array<Array<string>>; - s4: Map<string, number>; - s5: Map<number, Array<string>>; - s6: Color; - s7: boolean; -} +Requirements +---------------- ---> +Install Node and npm. -{"s2":["toto","toto2","toto3"],"s4":{"toto":1999,"tatata":1999},"s6":0,"s7":true} - -(absent fields weren't specified) - +Then: +- `npm install browserify` +- `npm install typescript` +- `npm install tsify` -type:B -value:{"someAs":[{...},{},{}]}......................... -Deserialize - -jsonValue - -
--- a/Resources/CodeGeneration/runts.ps1 Fri Feb 22 10:48:43 2019 +0100 +++ b/Resources/CodeGeneration/runts.ps1 Sat Feb 23 10:18:13 2019 +0100 @@ -4,16 +4,60 @@ # tsc -t ES2015 .\template.in.ts; node .\template.in.js -echo "+----------------------+" -echo "| playground.ts |" -echo "+----------------------+" +# echo "+----------------------+" +# echo "| playground.ts |" +# echo "+----------------------+" + +# tsc -t ES2015 .\playground.ts; node .\playground.js -tsc -t ES2015 .\playground.ts; node .\playground.js +# echo "+----------------------+" +# echo "| playground3.ts |" +# echo "+----------------------+" + +# tsc -t ES2015 .\playground3.ts; node .\playground3.js echo "+----------------------+" -echo "| playground3.ts |" +echo "| stonegen |" echo "+----------------------+" -tsc -t ES2015 .\playground3.ts; node .\playground3.js +if(-not (test-Path "build")) { + mkdir "build" +} + +echo "Generate the TS and CPP wrapper... (to build/)" +python stonegentool.py -o "." test_data/test1.yaml +if($LASTEXITCODE -ne 0) { + Write-Error ("Code generation failed!") + exit $LASTEXITCODE +} + +echo "Compile the TS wrapper to JS... (in build/)" +tsc --module commonjs --sourceMap -t ES2015 --outDir "build/" VsolMessages_generated.ts +if($LASTEXITCODE -ne 0) { + Write-Error ("Code compilation failed!") + exit $LASTEXITCODE +} + +echo "Compile the test app..." +tsc --module commonjs --sourceMap -t ES2015 --outDir "build/" test_stonegen.ts +if($LASTEXITCODE -ne 0) { + Write-Error ("Code compilation failed!") + exit $LASTEXITCODE +} + +browserify "build/test_stonegen.js" "build/VsolMessages_generated.js" -o "build_browser/test_stonegen_fused.js" + +cp .\test_stonegen.html .\build_browser\ + +echo "Run the test app..." +Push-Location +cd build_browser +node .\test_stonegen_fused.js +Pop-Location +if($LASTEXITCODE -ne 0) { + Write-Error ("Code execution failed!") + exit $LASTEXITCODE +} +
--- a/Resources/CodeGeneration/stonegentool.py Fri Feb 22 10:48:43 2019 +0100 +++ b/Resources/CodeGeneration/stonegentool.py Sat Feb 23 10:18:13 2019 +0100 @@ -1,6 +1,7 @@ import json import yaml import re +import os import sys from jinja2 import Template from typing import ( @@ -117,6 +118,7 @@ retVal: str = canonicalTypename retVal = retVal.replace("map", "std::map") retVal = retVal.replace("vector", "std::vector") + retVal = retVal.replace("string", "std::string") retVal = retVal.replace("int32", "int32_t") retVal = retVal.replace("float32", "float") retVal = retVal.replace("float64", "double") @@ -137,9 +139,24 @@ retVal = retVal.replace("bool", "boolean") return retVal -def NeedsConstruction(canonTypename): +def NeedsTsConstruction(enums: Dict, tsType: str): + if tsType == 'boolean': + return False + elif tsType == 'number': + return False + elif tsType == 'string': + return False + else: + enumNames = [] + for enum in enums: + enumNames.append(enum['name']) + if tsType in enumNames: + return False return True +def NeedsCppConstruction(canonTypename): + return False + def RegisterTemplateFunction(template,func): """Makes a function callable by a jinja2 template""" template.globals[func.__name__] = func @@ -149,7 +166,8 @@ template = Template(templateStr) RegisterTemplateFunction(template,CanonToCpp) RegisterTemplateFunction(template,CanonToTs) - RegisterTemplateFunction(template,NeedsConstruction) + RegisterTemplateFunction(template,NeedsTsConstruction) + RegisterTemplateFunction(template,NeedsCppConstruction) return template def MakeTemplateFromFile(templateFileName): @@ -476,12 +494,28 @@ ) args = parser.parse_args() - inputSchemaFilename = args.input_schema + schemaFile = args.input_schema outDir = args.out_dir - schema: Dict = LoadSchema(inputSchemaFilename) - genOrder: List[str] = ComputeRequiredDeclarationOrder(schema) - processedSchema: Dict = ProcessSchema(schema,genOrder) + tdico: Dict = GetTemplatingDictFromSchemaFilename(schemaFile) + + tsTemplateFile = \ + os.path.join(os.path.dirname(__file__), 'template.in.ts') + template = MakeTemplateFromFile(tsTemplateFile) + renderedTsCode: str = template.render(**tdico) + outputTsFile = os.path.join( \ + outDir,f"{tdico['rootName']}_generated.ts") + with open(outputTsFile,"wt",encoding='utf8') as outFile: + outFile.write(renderedTsCode) + + cppTemplateFile = \ + os.path.join(os.path.dirname(__file__), 'template.in.h') + template = MakeTemplateFromFile(cppTemplateFile) + renderedCppCode: str = template.render(**tdico) + outputCppFile = os.path.join( \ + outDir,f"{tdico['rootName']}_generated.hpp") + with open(outputCppFile,"wt",encoding='utf8') as outFile: + outFile.write(renderedCppCode) # def GenEnumDecl(genc: GenCode, fullName: str, schema: Dict) -> None:
--- a/Resources/CodeGeneration/stonegentool_test.py Fri Feb 22 10:48:43 2019 +0100 +++ b/Resources/CodeGeneration/stonegentool_test.py Sat Feb 23 10:18:13 2019 +0100 @@ -6,7 +6,7 @@ from stonegentool import \ EatToken,SplitListOfTypes,ParseTemplateType,ProcessSchema, \ CheckSchemaSchema,LoadSchema,trim,ComputeRequiredDeclarationOrder, \ -GetTemplatingDictFromSchemaFilename,MakeTemplate +GetTemplatingDictFromSchemaFilename,MakeTemplate,MakeTemplateFromFile import unittest import os import re @@ -258,7 +258,7 @@ {% for key in struct['fields']%} {{key}}:{{CanonToTs(struct['fields'][key])}}; {% endfor %} constructor() { -{% for key in struct['fields']%} {{key}} = new {{CanonToTs(struct['fields'][key])}}(); +{% for key in struct['fields']%} this.{{key}} = new {{CanonToTs(struct['fields'][key])}}(); {% endfor %} } public StoneSerialize(): string { @@ -375,12 +375,13 @@ self.assertEqual(renderedCodeRef, renderedCode) def test_generateWholeTsFile(self): - schemaFile = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') + schemaFile = \ + os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') tdico = GetTemplatingDictFromSchemaFilename(schemaFile) - tsTemplateFile = os.path.join(os.path.dirname(__file__), 'test_data', 'test1.yaml') + tsTemplateFile = \ + os.path.join(os.path.dirname(__file__), 'template.in.ts') template = MakeTemplateFromFile(tsTemplateFile) renderedCode = template.render(**tdico) - print(renderedCode) def test_GenerateTypeScriptHandlerInterface(self):
--- a/Resources/CodeGeneration/template.in.h Fri Feb 22 10:48:43 2019 +0100 +++ b/Resources/CodeGeneration/template.in.h Sat Feb 23 10:18:13 2019 +0100 @@ -7,38 +7,95 @@ #include <string> #include <sstream> #include <assert.h> +#include <memory> +#include <optional> #include <json/json.h> +#include <gtest/gtest.h> +//#define STONEGEN_NO_CPP11 1 -namespace VsolStuff +#ifdef STONEGEN_NO_CPP11 +#define StoneSmartPtr std::auto_ptr +#else +#define StoneSmartPtr std::unique_ptr +#endif + +namespace {{rootName}} { - Json::Value StoneSerialize(int32_t value) + /** Throws in case of problem */ + void _StoneDeserializeValue(int32_t& destValue, const Json::Value& jsonValue) + { + destValue = jsonValue.asInt(); + } + + Json::Value _StoneSerializeValue(int32_t value) { Json::Value result(value); return result; } - Json::Value StoneSerialize(double value) + /** Throws in case of problem */ + void _StoneDeserializeValue(double& destValue, const Json::Value& jsonValue) + { + destValue = jsonValue.asDouble(); + } + + Json::Value _StoneSerializeValue(double value) { Json::Value result(value); return result; } - Json::Value StoneSerialize(bool value) + /** Throws in case of problem */ + void _StoneDeserializeValue(bool& destValue, const Json::Value& jsonValue) + { + destValue = jsonValue.asBool(); + } + + Json::Value _StoneSerializeValue(bool value) { Json::Value result(value); return result; } - Json::Value StoneSerialize(const std::string& value) + /** Throws in case of problem */ + void _StoneDeserializeValue( + std::string& destValue + , const Json::Value& jsonValue) + { + destValue = jsonValue.asString(); + } + + Json::Value _StoneSerializeValue(const std::string& value) { // the following is better than Json::Value result(value.data(),value.data()+value.size()); return result; } + /** Throws in case of problem */ template<typename T> - Json::Value StoneSerialize(const std::map<std::string,T>& value) + void _StoneDeserializeValue( + std::map<std::string, T>& destValue, const Json::Value& jsonValue) + { + destValue.clear(); + for ( + Json::Value::const_iterator itr = jsonValue.begin(); + itr != jsonValue.end(); + itr++) + { + std::string key; + _StoneDeserializeValue(key, itr.key()); + + T innerDestValue; + _StoneDeserializeValue(innerDestValue, *itr); + + destValue[key] = innerDestValue; + } + } + + template<typename T> + Json::Value _StoneSerializeValue(const std::map<std::string,T>& value) { Json::Value result(Json::objectValue); @@ -46,24 +103,190 @@ it != value.cend(); ++it) { // it->first it->second - result[it->first] = StoneSerialize(it->second); + result[it->first] = _StoneSerializeValue(it->second); } return result; } + /** Throws in case of problem */ template<typename T> - Json::Value StoneSerialize(const std::vector<T>& value) + void _StoneDeserializeValue( + std::vector<T>& destValue, const Json::Value& jsonValue) + { + destValue.clear(); + destValue.reserve(jsonValue.size()); + for (Json::Value::ArrayIndex i = 0; i != jsonValue.size(); i++) + { + T innerDestValue; + _StoneDeserializeValue(innerDestValue, jsonValue[i]); + destValue.push_back(innerDestValue); + } + } + + template<typename T> + Json::Value _StoneSerializeValue(const std::vector<T>& value) { Json::Value result(Json::arrayValue); for (size_t i = 0; i < value.size(); ++i) { - result.append(StoneSerialize(value[i])); + result.append(_StoneSerializeValue(value[i])); } return result; } - %enumerationscpp% + void StoneCheckSerializedValueTypeGeneric(const Json::Value& value) + { + if ((!value.isMember("type")) || (!value["type"].isString())) + { + std::stringstream ss; + ss << "Cannot deserialize value ('type' key invalid)"; + throw std::runtime_error(ss.str()); + } + } + + void StoneCheckSerializedValueType( + const Json::Value& value, std::string typeStr) + { + StoneCheckSerializedValueTypeGeneric(value); + + std::string actTypeStr = value["type"].asString(); + if (actTypeStr != typeStr) + { + std::stringstream ss; + ss << "Cannot deserialize type" << actTypeStr + << "into " << typeStr; + throw std::runtime_error(ss.str()); + } + } + + // end of generic methods + +// end of generic methods +{% for enum in enums%} + enum {{enum['name']}} { +{% for key in enum['fields']%} {{key}}, +{%endfor%} }; + + void _StoneDeserializeValue( + {{enum['name']}}& destValue, const Json::Value& jsonValue) + { + destValue = static_cast<{{enum['name']}}>(jsonValue.asInt64()); + } + + Json::Value _StoneSerializeValue(const {{enum['name']}}& value) + { + return Json::Value(static_cast<int64_t>(value)); + } +{%endfor%} +{% for struct in structs%} +#ifdef _MSC_VER +#pragma region {{struct['name']}} +#endif //_MSC_VER + + struct {{struct['name']}} + { +{% for key in struct['fields']%} {{CanonToCpp(struct['fields'][key])}} {{key}}; +{% endfor %} + {{struct['name']}}() + { +{% for key in struct['fields']%} {{key}} = {{CanonToCpp(struct['fields'][key])}}(); +{% endfor %} + } + }; + + void _StoneDeserializeValue({{struct['name']}}& destValue, const Json::Value& value) + { +{% for key in struct['fields']%} _StoneDeserializeValue(destValue.{{key}}, value["{{key}}"]); +{% endfor %} + } + + Json::Value _StoneSerializeValue(const {{struct['name']}}& value) + { + Json::Value result(Json::objectValue); +{% for key in struct['fields']%} result["{{key}}"] = _StoneSerializeValue(value.{{key}}); +{% endfor %} + return result; + } - %structscpp% + void StoneDeserialize({{struct['name']}}& destValue, const Json::Value& value) + { + StoneCheckSerializedValueType(value, "{{rootName}}.{{struct['name']}}"); + _StoneDeserializeValue(destValue, value["value"]); + } + + Json::Value StoneSerialize(const {{struct['name']}}& value) + { + Json::Value result(Json::objectValue); + result["type"] = "{{rootName}}.{{struct['name']}}"; + result["value"] = _StoneSerializeValue(value); + return result; + } + +#ifdef _MSC_VER +#pragma endregion {{struct['name']}} +#endif //_MSC_VER +{% endfor %} +#ifdef _MSC_VER +#pragma region Dispatching code +#endif //_MSC_VER + + class IDispatcher + { + public: +{% for struct in structs%} virtual bool Handle(const {{struct['name']}}& value) = 0; +{% endfor %} }; + /** Service function for StoneDispatchToHandler */ + bool StoneDispatchJsonToHandler( + const Json::Value& jsonValue, IDispatcher* dispatcher) + { + StoneCheckSerializedValueTypeGeneric(jsonValue); + std::string type = jsonValue["type"].asString(); + if (type == "") + { + // this should never ever happen + throw std::runtime_error("Caught empty type while dispatching"); + } +{% for struct in structs%} else if (type == "{{rootName}}.{{struct['name']}}") + { + {{struct['name']}} value; + _StoneDeserializeValue(value, jsonValue["value"]); + return dispatcher->Handle(value); + } +{% endfor %} else + { + return false; + } + } + + /** Takes a serialized type and passes this to the dispatcher */ + bool StoneDispatchToHandler(std::string strValue, IDispatcher* dispatcher) + { + Json::Value readValue; + + Json::CharReaderBuilder builder; + Json::CharReader* reader = builder.newCharReader(); + + StoneSmartPtr<Json::CharReader> ptr(reader); + + std::string errors; + + bool ok = reader->parse( + strValue.c_str(), + strValue.c_str() + strValue.size(), + &readValue, + &errors + ); + if (!ok) + { + std::stringstream ss; + ss << "Jsoncpp parsing error: " << errors; + throw std::runtime_error(ss.str()); + } + return StoneDispatchJsonToHandler(readValue, dispatcher); + } + +#ifdef _MSC_VER +#pragma endregion Dispatching code +#endif //_MSC_VER }
--- a/Resources/CodeGeneration/template.in.ts Fri Feb 22 10:48:43 2019 +0100 +++ b/Resources/CodeGeneration/template.in.ts Sat Feb 23 10:18:13 2019 +0100 @@ -3,107 +3,106 @@ 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */ -namespace {{rootName}} +function StoneCheckSerializedValueType(value: any, typeStr: string) { - function StoneCheckSerializedValueType(value: any, typeStr: string) - { - StoneCheckSerializedValueTypeGeneric(value); + StoneCheckSerializedValueTypeGeneric(value); - if (value['type'] != typeStr) - { - throw new Error( - `Cannot deserialize type ${value['type']} into ${typeStr}`); - } + if (value['type'] != typeStr) + { + throw new Error( + `Cannot deserialize type ${value['type']} into ${typeStr}`); } +} - function isString(val: any) :boolean - { - return ((typeof val === 'string') || (val instanceof String)); - } - - function StoneCheckSerializedValueTypeGeneric(value: any) +function isString(val: any) :boolean +{ + return ((typeof val === 'string') || (val instanceof String)); +} + +function StoneCheckSerializedValueTypeGeneric(value: any) +{ + // console.//log("+-------------------------------------------------+"); + // console.//log("| StoneCheckSerializedValueTypeGeneric |"); + // console.//log("+-------------------------------------------------+"); + // console.//log("value = "); + // console.//log(value); + if ( (!('type' in value)) || (!isString(value.type)) ) { - if ( (!('type' in value)) || (!isString(value)) ) - { - throw new Error( - "Cannot deserialize value ('type' key invalid)"); - } + throw new Error( + "Cannot deserialize value ('type' key invalid)"); } +} // end of generic methods {% for enum in enums%} - export enum {{enum['name']}} { - {% for key in enumDict.keys()%} - {{key}}, - {%endfor%} - }; +export enum {{enum['name']}} { + {% for key in enum['fields']%}{{key}}, + {%endfor%} +}; {%endfor%} - -""" // end of generic methods {% for struct in structs%} export class {{struct['name']}} { {% for key in struct['fields']%} {{key}}:{{CanonToTs(struct['fields'][key])}}; {% endfor %} - constructor() { -{% for key in struct['fields']%} {{key}} = new {{CanonToTs(struct['fields'][key])}}(); -{% endfor %} } + constructor() { +{% for key in struct['fields']%}{% if NeedsTsConstruction(enums,CanonToTs(struct['fields'][key])) %} this.{{key}} = new {{CanonToTs(struct['fields'][key])}}(); +{% endif %}{% endfor %} } - public StoneSerialize(): string { - let container: object = {}; - container['type'] = '{{rWholootName}}.{{struct['name']}}'; - container['value'] = this; - return JSON.stringify(container); - } + public StoneSerialize(): string { + let container: object = {}; + container['type'] = '{{rWholootName}}.{{struct['name']}}'; + container['value'] = this; + return JSON.stringify(container); + } - public static StoneDeserialize(valueStr: string) : {{struct['name']}} - { - let value: any = JSON.parse(valueStr); - StoneCheckSerializedValueType(value, '{{rootName}}.{{struct['name']}}'); - let result: {{struct['name']}} = value['value'] as {{struct['name']}}; - return result; - } - + public static StoneDeserialize(valueStr: string) : {{struct['name']}} + { + let value: any = JSON.parse(valueStr); + StoneCheckSerializedValueType(value, '{{rootName}}.{{struct['name']}}'); + let result: {{struct['name']}} = value['value'] as {{struct['name']}}; + return result; } +} {% endfor %} - }; +export interface IDispatcher { + {% for struct in structs%} Handle{{struct['name']}}(value: {{struct['name']}}): boolean; + {% endfor %} +}; - export interface IDispatcher - { - {% for struct in structs%} HandleMessage1(value: {{struct['name']}}): boolean; - {% endfor %} - }; - - /** Service function for StoneDispatchToHandler */ - export function StoneDispatchJsonToHandler( - jsonValueStr: string, dispatcher: IDispatcher): boolean +/** Service function for StoneDispatchToHandler */ +export function StoneDispatchJsonToHandler( + jsonValue: any, dispatcher: IDispatcher): boolean +{ + StoneCheckSerializedValueTypeGeneric(jsonValue); + let type: string = jsonValue["type"]; + if (type == "") { - let jsonValue: any = JSON.parse(jsonValueStr); - StoneCheckSerializedValueTypeGeneric(jsonValue); - let type: string = jsonValue["type"]; - if (type == "") - { - // this should never ever happen - throw new Error("Caught empty type while dispatching"); - } -{% for struct in structs%} else if (type == "VsolStuff.{{struct['name']}}") - { - let value = jsonValue["value"] as Message1; - return dispatcher.HandleMessage1(value); - } -{% enfor %} - else - { - return false; - } + // this should never ever happen + throw new Error("Caught empty type while dispatching"); } - - /** Takes a serialized type and passes this to the dispatcher */ - export function StoneDispatchToHandler( - strValue: string, dispatcher: IDispatcher): boolean +{% for struct in structs%} else if (type == "{{rootName}}.{{struct['name']}}") { - let jsonValue: any = JSON.parse(strValue) - return StoneDispatchJsonToHandler(jsonValue, dispatcher); + let value = jsonValue["value"] as {{struct['name']}}; + return dispatcher.Handle{{struct['name']}}(value); + } +{% endfor %} + else + { + return false; } } + +/** Takes a serialized type and passes this to the dispatcher */ +export function StoneDispatchToHandler( + strValue: string, dispatcher: IDispatcher): boolean +{ + // console.//log("+------------------------------------------------+"); + // console.//log("| StoneDispatchToHandler |"); + // console.//log("+------------------------------------------------+"); + // console.//log("strValue = "); + // console.//log(strValue); + let jsonValue: any = JSON.parse(strValue) + return StoneDispatchJsonToHandler(jsonValue, dispatcher); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CodeGeneration/testCppHandler/CMakeLists.txt Sat Feb 23 10:18:13 2019 +0100 @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 2.8) + +project(testCppHandler) + +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 + DEPENDS ${CMAKE_CURRENT_LIST_DIR}/../test_data/test1.yaml +) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo_multi.cmake) +conan_basic_setup() + +add_executable(testCppHandler main.cpp ${CMAKE_CURRENT_BINARY_DIR}/VsolMessages_generated.hpp) + +target_include_directories(testCppHandler PUBLIC ${CMAKE_BINARY_DIR}) + +conan_target_link_libraries(testCppHandler) + +set_property(TARGET testCppHandler PROPERTY CXX_STANDARD 17) + +install(TARGETS testCppHandler DESTINATION bin) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CodeGeneration/testCppHandler/README.md Sat Feb 23 10:18:13 2019 +0100 @@ -0,0 +1,32 @@ +Requirements +============== +- Install Python 3.x (tested with 3.7) +- Install conan with `pip install conan` (tested with 1.12.2) +- Install CMake (tested with 3.12) +- Under Windows: Visual Studio 2017 +- Under *nix*: Ninja + +How to build under *nix* +=============================== +- Navigate to `testCppHandler` folder +- `conan install . -g cmake` +- `mkdir build` +- `cd build` +- `cmake -G "Ninja" ..` +- `cmake --build . --config Debug` or - `cmake --build . --config Release` + +How to build under Windows with Visual Studio +============================================== +- Navigate to repo root +- `mkdir build` +- `cd build` +- `conan install .. -g cmake_multi -s build_type=Release` +- `conan install .. -g cmake_multi -s build_type=Debug` +- `cmake -G "Visual Studio 15 2017 Win64" ..` (modify for your current Visual Studio version) +- `cmake --build . --config Debug` or - `cmake --build . --config Release` + + + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CodeGeneration/testCppHandler/conanfile.txt Sat Feb 23 10:18:13 2019 +0100 @@ -0,0 +1,4 @@ +[requires] +jsoncpp/1.8.4@theirix/stable +gtest/1.8.1@bincrafters/stable +boost/1.69.0@conan/stable
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CodeGeneration/testCppHandler/main.cpp Sat Feb 23 10:18:13 2019 +0100 @@ -0,0 +1,72 @@ +#include <string> +#include <filesystem> +#include <regex> +using namespace std; +namespace fs = std::filesystem; + +#include <boost/program_options.hpp> +using namespace boost::program_options; + +#include "VsolMessages_generated.hpp" + +/** +Transforms `str` by replacing occurrences of `oldStr` with `newStr`, using +plain text (*not* regular expressions.) +*/ +static inline void ReplaceInString( + string& str, + const std::string& oldStr, + const std::string& newStr) +{ + std::string::size_type pos = 0u; + while ((pos = str.find(oldStr, pos)) != std::string::npos) { + str.replace(pos, oldStr.length(), newStr); + pos += newStr.length(); + } +} + +int main(int argc, char** argv) +{ + try + { + string pattern; + + options_description desc("Allowed options"); + desc.add_options() + // First parameter describes option name/short name + // The second is parameter to option + // The third is description + ("help,h", "print usage message") + ("pattern,p", value(&pattern), "pattern for input") + ; + + variables_map vm; + store(parse_command_line(argc, argv, desc), vm); + + if (vm.count("help")) + { + cout << desc << "\n"; + return 0; + } + + // tranform globbing pattern into regex + // we should deal with -, ., *... + string regexPatternStr = pattern; + regex regexPattern(regexPatternStr); + + for (auto& p : fs::directory_iterator(".")) + { + if (regex_match(p.path().string(), regexPattern)) + std::cout << "\"" << p << "\" is a match\n"; + else + std::cout << "\"" << p << "\" is *not* a match\n"; + } + return 0; + + + } + catch (exception& e) + { + cerr << e.what() << "\n"; + } +} \ No newline at end of file
--- a/Resources/CodeGeneration/test_data/test1.yaml Fri Feb 22 10:48:43 2019 +0100 +++ b/Resources/CodeGeneration/test_data/test1.yaml Sat Feb 23 10:18:13 2019 +0100 @@ -29,6 +29,7 @@ tutu: vector<string> titi: map<string, string> lulu: map<string, Message1> + movieType: MovieType enum MovieType: - RomCom @@ -37,7 +38,12 @@ - Vegetables enum CrispType: - - SaltAndPepper - - CreamAndChives - - Paprika - - Barbecue + - SaltAndPepper + - CreamAndChives + - Paprika + - Barbecue + +enum EnumMonth0: + - January + - February + - March
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CodeGeneration/test_stonegen.html Sat Feb 23 10:18:13 2019 +0100 @@ -0,0 +1,1 @@ +<script type="text/javascript" src="test_stonegen_fused.js"></script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CodeGeneration/test_stonegen.ts Sat Feb 23 10:18:13 2019 +0100 @@ -0,0 +1,206 @@ +import * as VsolMessages from "./VsolMessages_generated"; + +function TEST_StoneGen_SerializeComplex() { + let msg1_0 = new VsolMessages.Message1(); + msg1_0.a = 42; + msg1_0.b = "Benjamin"; + msg1_0.c = VsolMessages.EnumMonth0.January; + msg1_0.d = true; + let msg1_1 = new VsolMessages.Message1(); + msg1_1.a = 43; + msg1_1.b = "Sandrine"; + msg1_1.c = VsolMessages.EnumMonth0.March; + msg1_0.d = false; + let result1_0 = msg1_0.StoneSerialize(); + let resultStr1_0 = JSON.stringify(result1_0); + let result1_1 = msg1_1.StoneSerialize(); + let resultStr1_1 = JSON.stringify(result1_1); + // std::string toto; + // std::vector<Message1> tata; + // std::vector<std::string> tutu; + // std::map<int32_t, std::string> titi; + // std::map<int32_t, Message1> lulu; + let msg2_0 = new VsolMessages.Message2(); + msg2_0.toto = "Prout zizi"; + msg2_0.tata.push(msg1_0); + msg2_0.tata.push(msg1_1); + msg2_0.tutu.push("Mercadet"); + msg2_0.tutu.push("Poisson"); + msg2_0.titi["44"] = "key 44"; + msg2_0.titi["45"] = "key 45"; + msg2_0.lulu["54"] = msg1_1; + msg2_0.lulu["55"] = msg1_0; + let result2 = msg2_0.StoneSerialize(); + let resultStr2 = JSON.stringify(result2); + let refResult2 = `{ +"type" : "VsolMessages.Message2", +"value" : +{ + "lulu" : + { + "54" : + { + "a" : 43, + "b" : "Sandrine", + "c" : 2, + "d" : true + }, + "55" : + { + "a" : 42, + "b" : "Benjamin", + "c" : 0, + "d" : false + } + }, + "tata" : + [ + { + "a" : 42, + "b" : "Benjamin", + "c" : 0, + "d" : false + }, + { + "a" : 43, + "b" : "Sandrine", + "c" : 2, + "d" : true + } + ], + "titi" : + { + "44" : "key 44", + "45" : "key 45" + }, + "toto" : "Prout zizi", + "tutu" : + [ + "Mercadet", + "Poisson" + ] +} +} +`; + let refResult2Obj = JSON.parse(refResult2); + let resultStr2Obj = JSON.parse(resultStr2); + if (false) { + if (refResult2Obj !== resultStr2Obj) { + console.log("Results are different!"); + console.log(`refResult2Obj['value']['lulu']['54'] = ${refResult2Obj['value']['lulu']['54']}`); + console.log(`refResult2Obj['value']['lulu']['54']['a'] = ${refResult2Obj['value']['lulu']['54']['a']}`); + console.log("************************************************************"); + console.log("** REFERENCE OBJ **"); + console.log("************************************************************"); + console.log(refResult2Obj); + console.log("************************************************************"); + console.log("** ACTUAL OBJ **"); + console.log("************************************************************"); + console.log(resultStr2Obj); + console.log("************************************************************"); + console.log("** REFERENCE **"); + console.log("************************************************************"); + console.log(refResult2); + console.log("************************************************************"); + console.log("** ACTUAL **"); + console.log("************************************************************"); + console.log(resultStr2); + throw new Error("Wrong serialization"); + } + } + let refResultValue = JSON.parse(resultStr2); + console.log(refResultValue); +} +class MyDispatcher { + message1: VsolMessages.Message1; + message2: VsolMessages.Message2; + + HandleMessage1(value: VsolMessages.Message1) { + this.message1 = value; + return true; + } + HandleMessage2(value: VsolMessages.Message2) { + this.message2 = value; + return true; + } + HandleA(value) { + return true; + } + HandleB(value) { + return true; + } + HandleC(value) { + return true; + } +} +; +function TEST_StoneGen_DeserializeOkAndNok() { + let serializedMessage = `{ +"type" : "VsolMessages.Message2", +"value" : +{ + "lulu" : + { + "54" : + { + "a" : 43, + "b" : "Sandrine", + "c" : 2, + "d" : true + }, + "55" : + { + "a" : 42, + "b" : "Benjamin", + "c" : 0, + "d" : false + } + }, + "tata" : + [ + { + "a" : 42, + "b" : "Benjamin", + "c" : 0, + "d" : false + }, + { + "a" : 43, + "b" : "Sandrine", + "c" : 2, + "d" : true + } + ], + "titi" : + { + "44" : "key 44", + "45" : "key 45" + }, + "toto" : "Prout zizi", + "tutu" : + [ + "Mercadet", + "Poisson" + ] +} +}`; + let myDispatcher = new MyDispatcher(); + let ok = VsolMessages.StoneDispatchToHandler(serializedMessage, myDispatcher); + if (!ok) { + throw Error("Error when dispatching message!"); + } + if (myDispatcher.message1 != undefined) { + throw Error("(myDispatcher.Message1 != undefined)"); + } + if (myDispatcher.message2 == undefined) { + throw Error("(myDispatcher.Message2 == undefined)"); + } + console.log("TEST_StoneGen_DeserializeOkAndNok: OK!"); +} +function main() { + console.log("Entering main()"); + TEST_StoneGen_SerializeComplex(); + TEST_StoneGen_DeserializeOkAndNok(); + return 0; +} +console.log(`Exit code is: ${main()}`); \ No newline at end of file