Mercurial > hg > orthanc-stone
view Resources/CodeGeneration/template.in.h.j2 @ 884:aad5ccf1be10 am-dev
cleanup
author | Alain Mazy <alain@mazy.be> |
---|---|
date | Tue, 09 Jul 2019 14:43:00 +0200 |
parents | 78f4317eb94b |
children | 8a0a62189f46 |
line wrap: on
line source
/* 1 2 3 4 5 6 7 12345678901234567890123456789012345678901234567890123456789012345678901234567890 Generated on {{currentDatetime}} by stonegentool */ #pragma once #include <exception> #include <iostream> #include <string> #include <sstream> #include <assert.h> #include <memory> #include <set> #include <json/json.h> //#define STONEGEN_NO_CPP11 1 #ifdef STONEGEN_NO_CPP11 #define StoneSmartPtr std::auto_ptr #else #define StoneSmartPtr std::unique_ptr #endif namespace {{rootName}} { /** Throws in case of problem */ inline void _StoneDeserializeValue(int32_t& destValue, const Json::Value& jsonValue) { if (!jsonValue.isNull()) { destValue = jsonValue.asInt(); } } inline Json::Value _StoneSerializeValue(int32_t value) { Json::Value result(value); return result; } inline void _StoneDeserializeValue(int64_t& destValue, const Json::Value& jsonValue) { if (!jsonValue.isNull()) { destValue = jsonValue.asInt64(); } } inline Json::Value _StoneSerializeValue(int64_t value) { Json::Value result(static_cast<Json::Value::Int64>(value)); return result; } inline void _StoneDeserializeValue(uint32_t& destValue, const Json::Value& jsonValue) { if (!jsonValue.isNull()) { destValue = jsonValue.asUInt(); } } inline Json::Value _StoneSerializeValue(uint32_t value) { Json::Value result(value); return result; } inline void _StoneDeserializeValue(uint64_t& destValue, const Json::Value& jsonValue) { if (!jsonValue.isNull()) { destValue = jsonValue.asUInt64(); } } inline Json::Value _StoneSerializeValue(uint64_t value) { Json::Value result(static_cast<Json::Value::UInt64>(value)); return result; } inline void _StoneDeserializeValue(Json::Value& destValue, const Json::Value& jsonValue) { destValue = jsonValue; } inline Json::Value _StoneSerializeValue(Json::Value value) { return value; } /** Throws in case of problem */ inline void _StoneDeserializeValue(double& destValue, const Json::Value& jsonValue) { if (!jsonValue.isNull()) { destValue = jsonValue.asDouble(); } } inline Json::Value _StoneSerializeValue(double value) { Json::Value result(value); return result; } /** 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()) { destValue = jsonValue.asBool(); } } inline Json::Value _StoneSerializeValue(bool value) { Json::Value result(value); return result; } /** Throws in case of problem */ inline void _StoneDeserializeValue( std::string& destValue , const Json::Value& jsonValue) { if (!jsonValue.isNull()) { destValue = jsonValue.asString(); } } inline Json::Value _StoneSerializeValue(const std::string& value) { // the following is better than Json::Value result(value.data(),value.data()+value.size()); return result; } inline std::string MakeIndent(size_t indent) { char* txt = reinterpret_cast<char*>(malloc(indent+1)); // NO EXCEPTION BELOW!!!!!!!!!!!! for(size_t i = 0; i < indent; ++i) txt[i] = ' '; txt[indent] = 0; std::string retVal(txt); free(txt); // NO EXCEPTION ABOVE !!!!!!!!!! return retVal; } // generic dumper template<typename T> std::ostream& StoneDumpValue(std::ostream& out, const T& value, size_t indent) { out << MakeIndent(indent) << value; return out; } // string dumper inline std::ostream& StoneDumpValue(std::ostream& out, const std::string& value, size_t indent) { out << MakeIndent(indent) << "\"" << value << "\""; 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 TK, typename TV> void _StoneDeserializeValue( std::map<TK, TV>& destValue, const Json::Value& jsonValue) { if (!jsonValue.isNull()) { destValue.clear(); for ( Json::Value::const_iterator itr = jsonValue.begin(); itr != jsonValue.end(); itr++) { 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) TV innerDestValue; _StoneDeserializeValue(innerDestValue, *itr); destValue[key] = innerDestValue; } } } template<typename TK, typename TV> Json::Value _StoneSerializeValue(const std::map<TK, TV>& value) { Json::Value result(Json::objectValue); for (typename std::map<TK, TV>::const_iterator it = value.cbegin(); it != value.cend(); ++it) { // it->first it->second result[ToString(it->first)] = _StoneSerializeValue(it->second); } return result; } 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<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; } /** Throws in case of problem */ template<typename T> void _StoneDeserializeValue( std::vector<T>& destValue, const Json::Value& jsonValue) { if (!jsonValue.isNull() && jsonValue.isArray()) { 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(_StoneSerializeValue(value[i])); } return result; } template<typename T> std::ostream& StoneDumpValue(std::ostream& out, const std::vector<T>& value, size_t indent) { out << MakeIndent(indent) << "[\n"; for (size_t i = 0; i < value.size(); ++i) { StoneDumpValue(out, value[i], indent+2); out << ", \n"; } out << MakeIndent(indent) << "]\n"; return out; } /** Throws in case of problem */ template<typename T> void _StoneDeserializeValue( std::set<T>& destValue, const Json::Value& jsonValue) { if (!jsonValue.isNull() && jsonValue.isArray()) { destValue.clear(); for (Json::Value::ArrayIndex i = 0; i != jsonValue.size(); i++) { T innerDestValue; _StoneDeserializeValue(innerDestValue, jsonValue[i]); destValue.insert(innerDestValue); } } } template<typename T> Json::Value _StoneSerializeValue(const std::set<T>& value) { Json::Value result(Json::arrayValue); for (typename std::set<T>::const_iterator it = value.begin(); it != value.end(); ++it) { result.append(_StoneSerializeValue(*it)); } return result; } template<typename T> std::ostream& StoneDumpValue(std::ostream& out, const std::set<T>& value, size_t indent) { out << MakeIndent(indent) << "[\n"; 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; } inline 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()); } } inline 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']%} {{enum['name']}}_{{key}}, {%endfor%} }; inline std::string ToString(const {{enum['name']}}& value) { {% for key in enum['fields']%} if( value == {{enum['name']}}_{{key}}) { return std::string("{{key}}"); } {%endfor%} std::stringstream ss; ss << "Value \"" << value << "\" cannot be converted to {{enum['name']}}. Possible values are: " {% for key in enum['fields']%} << " {{key}} = " << static_cast<int64_t>({{enum['name']}}_{{key}}) << ", " {% endfor %} << std::endl; std::string msg = ss.str(); throw std::runtime_error(msg); } inline void FromString({{enum['name']}}& value, std::string strValue) { {% for key in enum['fields']%} if( strValue == std::string("{{key}}") ) { value = {{enum['name']}}_{{key}}; return; } {%endfor%} std::stringstream ss; ss << "String \"" << strValue << "\" cannot be converted to {{enum['name']}}. Possible values are: {% for key in enum['fields']%}{{key}} {% endfor %}"; std::string msg = ss.str(); throw std::runtime_error(msg); } inline void _StoneDeserializeValue( {{enum['name']}}& destValue, const Json::Value& jsonValue) { if (!jsonValue.isNull()) { FromString(destValue, jsonValue.asString()); } } inline Json::Value _StoneSerializeValue(const {{enum['name']}}& value) { std::string strValue = ToString(value); return Json::Value(strValue); } inline std::ostream& StoneDumpValue(std::ostream& out, const {{enum['name']}}& value, size_t indent = 0) { {% for key in enum['fields']%} if( value == {{enum['name']}}_{{key}}) { out << MakeIndent(indent) << "{{key}}"; } {%endfor%} return out; } {%endfor%} {% for struct in structs%} #ifdef _MSC_VER #pragma region {{struct['name']}} #endif //_MSC_VER struct {{struct['name']}} { {% 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 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 %} } }; inline void _StoneDeserializeValue({{struct['name']}}& destValue, const Json::Value& value) { if (!value.isNull()) { {% if struct %}{% if struct['fields'] %}{% for key in struct['fields']%} _StoneDeserializeValue(destValue.{{key}}, value["{{key}}"]); {% endfor %}{% endif %}{% endif %} } } inline Json::Value _StoneSerializeValue(const {{struct['name']}}& value) { Json::Value result(Json::objectValue); {% if struct %}{% if struct['fields'] %}{% for key in struct['fields']%} result["{{key}}"] = _StoneSerializeValue(value.{{key}}); {% endfor %}{% endif %}{% endif %} return result; } 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+2) << "{{key}}: "; StoneDumpValue(out, value.{{key}},indent+2); out << ", \n"; {% endfor %}{% endif %}{% endif %} out << MakeIndent(indent) << "}"; return out; } inline void StoneDeserialize({{struct['name']}}& destValue, const Json::Value& value) { StoneCheckSerializedValueType(value, "{{rootName}}.{{struct['name']}}"); _StoneDeserializeValue(destValue, value["value"]); } inline Json::Value StoneSerializeToJson(const {{struct['name']}}& value) { Json::Value result(Json::objectValue); result["type"] = "{{rootName}}.{{struct['name']}}"; result["value"] = _StoneSerializeValue(value); return result; } inline std::string StoneSerialize(const {{struct['name']}}& value) { Json::Value resultJson = StoneSerializeToJson(value); std::string resultStr = resultJson.toStyledString(); return resultStr; } #ifdef _MSC_VER #pragma endregion {{struct['name']}} #endif //_MSC_VER {% endfor %} #ifdef _MSC_VER #pragma region Dispatching code #endif //_MSC_VER class IHandler { public: {% for struct in structs%}{% if struct['__meta__'].handleInCpp %} virtual bool Handle(const {{struct['name']}}& value) = 0; {% endif %}{% endfor %} }; /** Service function for StoneDispatchToHandler */ inline bool StoneDispatchJsonToHandler( const Json::Value& jsonValue, IHandler* handler) { 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%}{% if struct['__meta__'].handleInCpp %} else if (type == "{{rootName}}.{{struct['name']}}") { {{struct['name']}} value; _StoneDeserializeValue(value, jsonValue["value"]); return handler->Handle(value); } {% endif %}{% endfor %} else { return false; } } /** Takes a serialized type and passes this to the handler */ inline bool StoneDispatchToHandler(std::string strValue, IHandler* handler) { 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, handler); } #ifdef _MSC_VER #pragma endregion Dispatching code #endif //_MSC_VER }