diff --git a/cimgen/languages/cpp/lang_pack.py b/cimgen/languages/cpp/lang_pack.py index 6c914b3e..0522108e 100644 --- a/cimgen/languages/cpp/lang_pack.py +++ b/cimgen/languages/cpp/lang_pack.py @@ -39,6 +39,10 @@ def setup(output_path: str, cgmes_profile_details: list, cim_namespace: str): # {"filename": "cpp_enum_header_template.mustache", "ext": ".hpp"}, {"filename": "cpp_enum_object_template.mustache", "ext": ".cpp"}, ] +string_template_files = [ + {"filename": "cpp_string_header_template.mustache", "ext": ".hpp"}, + {"filename": "cpp_string_object_template.mustache", "ext": ".cpp"}, +] def get_class_location(class_name, class_map, version): # NOSONAR @@ -60,10 +64,12 @@ def run_template(output_path, class_details): templates = float_template_files elif class_details["is_an_enum_class"]: templates = enum_template_files + elif class_details["is_a_primitive_class"]: + templates = string_template_files else: templates = template_files - if class_details["class_name"] in ("String", "Integer", "Boolean", "Date"): + if class_details["class_name"] in ("Integer", "Boolean"): # These classes are defined already # We have to implement operators for them return @@ -75,7 +81,6 @@ def run_template(output_path, class_details): def _write_templated_file(class_file, class_details, template_filename): with open(class_file, "w", encoding="utf-8") as file: - class_details["setDefault"] = _set_default templates = files("cimgen.languages.cpp.templates") with templates.joinpath(template_filename).open(encoding="utf-8") as f: args = { @@ -109,7 +114,7 @@ def insert_assign_fn(text, render): label = attribute_json["label"] class_name = attribute_json["domain"] return ( - 'assign_map.insert(std::make_pair(std::string("cim:' + ' assign_map.insert(std::make_pair(std::string("cim:' + class_name + "." + label @@ -129,7 +134,7 @@ def insert_class_assign_fn(text, render): label = attribute_json["label"] class_name = attribute_json["domain"] return ( - 'assign_map.insert(std::make_pair(std::string("cim:' + ' assign_map.insert(std::make_pair(std::string("cim:' + class_name + "." + label @@ -147,13 +152,13 @@ def create_nullptr_assigns(text, render): return "" else: attributes_json = eval(attributes_txt) - nullptr_init_string = ": " + nullptr_init_string = "" for attribute in attributes_json: if attribute["is_class_attribute"]: nullptr_init_string += "LABEL(nullptr), ".replace("LABEL", attribute["label"]) if len(nullptr_init_string) > 2: - return nullptr_init_string[:-2] + return " : " + nullptr_init_string[:-2] else: return "" @@ -168,34 +173,72 @@ def create_class_assign(text, render): if _attribute_is_primitive_or_datatype_or_enum(attribute_json): return "" if attribute_json["is_list_attribute"]: - assign = ( - """ -bool assign_OBJECT_CLASS_LABEL(BaseClass* BaseClass_ptr1, BaseClass* BaseClass_ptr2) { - if(OBJECT_CLASS* element = dynamic_cast(BaseClass_ptr1)) { - if(dynamic_cast(BaseClass_ptr2) != nullptr) { - element->LABEL.push_back(dynamic_cast(BaseClass_ptr2)); + if "inverseRole" in attribute_json: + inverse = attribute_json["inverseRole"].split(".") + assign = ( + """ +bool assign_INVERSEC_INVERSEL(BaseClass*, BaseClass*); +bool assign_OBJECT_CLASS_LABEL(BaseClass* BaseClass_ptr1, BaseClass* BaseClass_ptr2) +{ + OBJECT_CLASS* element = dynamic_cast(BaseClass_ptr1); + ATTRIBUTE_CLASS* element2 = dynamic_cast(BaseClass_ptr2); + if (element != nullptr && element2 != nullptr) + { + if (std::find(element->LABEL.begin(), element->LABEL.end(), element2) == element->LABEL.end()) + { + element->LABEL.push_back(element2); + return assign_INVERSEC_INVERSEL(BaseClass_ptr2, BaseClass_ptr1); + } + return true; + } + return false; +}""".replace( # noqa: E101,W191 + "OBJECT_CLASS", attribute_json["domain"] + ) + .replace("ATTRIBUTE_CLASS", attribute_class) + .replace("LABEL", attribute_json["label"]) + .replace("INVERSEC", inverse[0]) + .replace("INVERSEL", inverse[1]) + ) + else: + assign = ( + """ +bool assign_OBJECT_CLASS_LABEL(BaseClass* BaseClass_ptr1, BaseClass* BaseClass_ptr2) +{ + if (OBJECT_CLASS* element = dynamic_cast(BaseClass_ptr1)) + { + if (dynamic_cast(BaseClass_ptr2) != nullptr) + { + element->LABEL.push_back(dynamic_cast(BaseClass_ptr2)); return true; } } return false; }""".replace( # noqa: E101,W191 - "OBJECT_CLASS", attribute_json["domain"] + "OBJECT_CLASS", attribute_json["domain"] + ) + .replace("ATTRIBUTE_CLASS", attribute_class) + .replace("LABEL", attribute_json["label"]) ) - .replace("ATTRIBUTE_CLASS", attribute_class) - .replace("LABEL", attribute_json["label"]) - ) - elif "inverseRole" in attribute_json and attribute_json["is_used"]: + elif "inverseRole" in attribute_json: inverse = attribute_json["inverseRole"].split(".") assign = ( """ bool assign_INVERSEC_INVERSEL(BaseClass*, BaseClass*); -bool assign_OBJECT_CLASS_LABEL(BaseClass* BaseClass_ptr1, BaseClass* BaseClass_ptr2) { - if(OBJECT_CLASS* element = dynamic_cast(BaseClass_ptr1)) { - element->LABEL = dynamic_cast(BaseClass_ptr2); - if(element->LABEL != nullptr) - return assign_INVERSEC_INVERSEL(BaseClass_ptr2, BaseClass_ptr1); - } - return false; +bool assign_OBJECT_CLASS_LABEL(BaseClass* BaseClass_ptr1, BaseClass* BaseClass_ptr2) +{ + OBJECT_CLASS* element = dynamic_cast(BaseClass_ptr1); + ATTRIBUTE_CLASS* element2 = dynamic_cast(BaseClass_ptr2); + if (element != nullptr && element2 != nullptr) + { + if (element->LABEL != element2) + { + element->LABEL = element2; + return assign_INVERSEC_INVERSEL(BaseClass_ptr2, BaseClass_ptr1); + } + return true; + } + return false; }""".replace( # noqa: E101,W191 "OBJECT_CLASS", attribute_json["domain"] ) @@ -207,13 +250,17 @@ def create_class_assign(text, render): else: assign = ( """ -bool assign_OBJECT_CLASS_LABEL(BaseClass* BaseClass_ptr1, BaseClass* BaseClass_ptr2) { - if(OBJECT_CLASS* element = dynamic_cast(BaseClass_ptr1)) { - element->LABEL = dynamic_cast(BaseClass_ptr2); - if(element->LABEL != nullptr) - return true; - } - return false; +bool assign_OBJECT_CLASS_LABEL(BaseClass* BaseClass_ptr1, BaseClass* BaseClass_ptr2) +{ + if(OBJECT_CLASS* element = dynamic_cast(BaseClass_ptr1)) + { + element->LABEL = dynamic_cast(BaseClass_ptr2); + if (element->LABEL != nullptr) + { + return true; + } + } + return false; }""".replace( # noqa: E101,W191 "OBJECT_CLASS", attribute_json["domain"] ) @@ -228,38 +275,20 @@ def create_assign(text, render): attribute_txt = render(text) attribute_json = eval(attribute_txt) assign = "" - _class = attribute_json["attribute_class"] if not _attribute_is_primitive_or_datatype_or_enum(attribute_json): return "" label_without_keyword = attribute_json["label"] if label_without_keyword == "switch": label_without_keyword = "_switch" - if _class != "String": - assign = ( - """ -bool assign_CLASS_LABEL(std::stringstream &buffer, BaseClass* BaseClass_ptr1) { - if(CLASS* element = dynamic_cast(BaseClass_ptr1)) { - buffer >> element->LBL_WO_KEYWORD; - if(buffer.fail()) - return false; - else - return true; - } - else - return false; -}""".replace( # noqa: E101,W191 - "CLASS", attribute_json["domain"] - ) - .replace("LABEL", attribute_json["label"]) - .replace("LBL_WO_KEYWORD", label_without_keyword) - ) - else: - assign = """ -bool assign_CLASS_LABEL(std::stringstream &buffer, BaseClass* BaseClass_ptr1) { - if(CLASS* element = dynamic_cast(BaseClass_ptr1)) { - element->LABEL = buffer.str(); - if(buffer.fail()) + assign = ( + """ +bool assign_CLASS_LABEL(std::stringstream &buffer, BaseClass* BaseClass_ptr1) +{ + if (CLASS* element = dynamic_cast(BaseClass_ptr1)) + { + buffer >> element->LBL_WO_KEYWORD; + if (buffer.fail()) return false; else return true; @@ -267,9 +296,10 @@ def create_assign(text, render): return false; }""".replace( # noqa: E101,W191 "CLASS", attribute_json["domain"] - ).replace( - "LABEL", attribute_json["label"] ) + .replace("LABEL", attribute_json["label"]) + .replace("LBL_WO_KEYWORD", label_without_keyword) + ) return assign @@ -301,8 +331,8 @@ def _create_attribute_includes(text, render): for attribute in attributes: if _attribute_is_primitive_or_datatype_or_enum(attribute): unique[attribute["attribute_class"]] = True - for clarse in unique: - include_string += '\n#include "' + clarse + '.hpp"' + for clarse in sorted(unique): + include_string += '#include "' + clarse + '.hpp"\n' return include_string @@ -317,8 +347,8 @@ def _create_attribute_class_declarations(text, render): for attribute in attributes: if attribute["is_class_attribute"] or attribute["is_list_attribute"]: unique[attribute["attribute_class"]] = True - for clarse in unique: - include_string += "\nclass " + clarse + ";" + for clarse in sorted(unique): + include_string += " class " + clarse + ";\n" return include_string @@ -372,7 +402,6 @@ def _attribute_is_primitive_or_datatype(attribute: dict) -> bool: "Factory", "Folders", "IEC61970", - "String", "Task", "UnknownType", ] @@ -380,26 +409,24 @@ def _attribute_is_primitive_or_datatype(attribute: dict) -> bool: iec61970_blacklist = ["CIMClassList", "CIMNamespaces", "Folders", "Task", "IEC61970"] -def _is_enum_class(filepath): +def _is_primitive_or_enum_class(filepath): with open(filepath, encoding="utf-8") as f: try: for line in f: - if "enum class" in line: - return True + if "static const BaseClassDefiner declare();" in line: + return False except UnicodeDecodeError as error: print("Warning: UnicodeDecodeError parsing {0}: {1}".format(filepath, error)) - return False + return True def _create_header_include_file(directory, header_include_filename, header, footer, before, after, blacklist): - lines = [] - for filename in sorted(os.listdir(directory)): filepath = os.path.join(directory, filename) basepath, ext = os.path.splitext(filepath) basename = os.path.basename(basepath) - if ext == ".hpp" and not _is_enum_class(filepath) and basename not in blacklist: + if ext == ".hpp" and not _is_primitive_or_enum_class(filepath) and basename not in blacklist: lines.append(before + basename + after) for line in lines: header.append(line) @@ -414,12 +441,18 @@ def resolve_headers(path: str, version: str): # NOSONAR class_list_header = [ "#ifndef CIMCLASSLIST_H\n", "#define CIMCLASSLIST_H\n", - "using namespace CIMPP;\n", + "/*\n", + "Generated from the CGMES files via cimgen: https://github.com/sogno-platform/cimgen\n", + "*/\n", "#include \n", - "static std::list CIMClassList = {\n", + '#include "IEC61970.hpp"\n', + "using namespace CIMPP;\n", + "static std::list CIMClassList =\n", + "{\n", ] class_list_footer = [ - " UnknownType::declare() };\n", + " UnknownType::declare(),\n", + "};\n", "#endif // CIMCLASSLIST_H\n", ] @@ -428,13 +461,23 @@ def resolve_headers(path: str, version: str): # NOSONAR "CIMClassList.hpp", class_list_header, class_list_footer, - " ", + " ", "::declare(),\n", class_blacklist, ) - iec61970_header = ["#ifndef IEC61970_H\n", "#define IEC61970_H\n"] - iec61970_footer = ['#include "UnknownType.hpp"\n', "#endif"] + iec61970_header = [ + "#ifndef IEC61970_H\n", + "#define IEC61970_H\n", + "/*\n", + "Generated from the CGMES files via cimgen: https://github.com/sogno-platform/cimgen\n", + "*/\n", + "\n", + ] + iec61970_footer = [ + '#include "UnknownType.hpp"\n', + "#endif", + ] _create_header_include_file( path, diff --git a/cimgen/languages/cpp/static/BaseClass.cpp b/cimgen/languages/cpp/static/BaseClass.cpp new file mode 100644 index 00000000..ff3a94a5 --- /dev/null +++ b/cimgen/languages/cpp/static/BaseClass.cpp @@ -0,0 +1,20 @@ +#include "BaseClass.hpp" + +using namespace CIMPP; + +BaseClass::~BaseClass() {} + +const char BaseClass::debugName[] = "BaseClass"; +const char* BaseClass::debugString() const +{ + return BaseClass::debugName; +} + +void BaseClass::addConstructToMap(std::unordered_map& factory_map) {} +void BaseClass::addPrimitiveAssignFnsToMap(std::unordered_map& assign_map) {} +void BaseClass::addClassAssignFnsToMap(std::unordered_map& assign_map) {} + +const BaseClassDefiner BaseClass::declare() +{ + return BaseClassDefiner(BaseClass::addConstructToMap, BaseClass::addPrimitiveAssignFnsToMap, BaseClass::addClassAssignFnsToMap, BaseClass::debugName); +} diff --git a/cimgen/languages/cpp/static/BaseClass.h b/cimgen/languages/cpp/static/BaseClass.h new file mode 100644 index 00000000..d1ebb818 --- /dev/null +++ b/cimgen/languages/cpp/static/BaseClass.h @@ -0,0 +1 @@ +#include "BaseClass.hpp" diff --git a/cimgen/languages/cpp/static/BaseClass.hpp b/cimgen/languages/cpp/static/BaseClass.hpp new file mode 100644 index 00000000..7af998c6 --- /dev/null +++ b/cimgen/languages/cpp/static/BaseClass.hpp @@ -0,0 +1,27 @@ +#ifndef BASECLASS_HPP +#define BASECLASS_HPP + +#ifndef CGMES_BUILD +#define CGMES_BUILD +#endif + +#include +#include + +#include "BaseClassDefiner.hpp" + +class BaseClass +{ +public: + enum cgmesProfile {EQ = 0, SSH = 1, TP = 2, SV = 3, DY = 4, GL = 5, DI = 6}; + virtual ~BaseClass(); + + static const char debugName[]; + virtual const char* debugString() const; + + static void addConstructToMap(std::unordered_map& factory_map); + static void addPrimitiveAssignFnsToMap(std::unordered_map& assign_map); + static void addClassAssignFnsToMap(std::unordered_map& assign_map); + static const CIMPP::BaseClassDefiner declare(); +}; +#endif // BASECLASS_HPP diff --git a/cimgen/languages/cpp/static/BaseClassDefiner.cpp b/cimgen/languages/cpp/static/BaseClassDefiner.cpp new file mode 100644 index 00000000..95bcb95d --- /dev/null +++ b/cimgen/languages/cpp/static/BaseClassDefiner.cpp @@ -0,0 +1,14 @@ + +#include "BaseClassDefiner.hpp" + +using namespace CIMPP; + +BaseClassDefiner::BaseClassDefiner(void(*addConstruct)(std::unordered_map&), + void(*addPrimitiveAssignFns)(std::unordered_map&), + void(*addClassAssignFns)(std::unordered_map&), + const char *debugStr) { + addConstructToMap = addConstruct; + addPrimitiveAssignFnsToMap = addPrimitiveAssignFns; + addClassAssignFnsToMap = addClassAssignFns; + debugString = debugStr; +} diff --git a/cimgen/languages/cpp/static/BaseClassDefiner.hpp b/cimgen/languages/cpp/static/BaseClassDefiner.hpp new file mode 100644 index 00000000..a8735384 --- /dev/null +++ b/cimgen/languages/cpp/static/BaseClassDefiner.hpp @@ -0,0 +1,24 @@ +#ifndef BASECLASSDEFINER_HPP +#define BASECLASSDEFINER_HPP + +#include +#include + +class BaseClass; +typedef bool (*class_assign_function)(BaseClass*, BaseClass*); +typedef bool (*assign_function)(std::stringstream&, BaseClass*); +namespace CIMPP { + + class BaseClassDefiner { + public: + BaseClassDefiner(void(*addConstruct)(std::unordered_map&), + void(*addPrimitiveAssignFns)(std::unordered_map&), + void(*addClassAssignFns)(std::unordered_map&), + const char *debugStr); + void (*addConstructToMap)(std::unordered_map&); + void (*addPrimitiveAssignFnsToMap)(std::unordered_map&); + void (*addClassAssignFnsToMap)(std::unordered_map&); + const char* debugString; + }; +} +#endif // BASECLASSDEFINER diff --git a/cimgen/languages/cpp/static/Boolean.cpp b/cimgen/languages/cpp/static/Boolean.cpp new file mode 100644 index 00000000..1818ab8a --- /dev/null +++ b/cimgen/languages/cpp/static/Boolean.cpp @@ -0,0 +1,73 @@ +#include "Boolean.hpp" + +#include +#include + +#include "../src/CIMExceptions.hpp" + +using namespace CIMPP; + +Boolean& Boolean::operator=(bool rop) +{ + value = rop; + initialized = true; + return *this; +} + +Boolean::operator bool() +{ + if (!initialized) + { + throw new ReadingUninitializedField(); + } + return value; +} + +const char Boolean::debugName[] = "Boolean"; +const char* Boolean::debugString() const +{ + return Boolean::debugName; +} + +namespace CIMPP +{ + std::istream& operator>>(std::istream& lop, Boolean& rop) + { + rop.initialized = false; + + std::string tmp; + lop >> tmp; + + if (tmp == "true" || tmp == "True" || tmp == "TRUE") + { + rop.value = true; + rop.initialized = true; + return lop; + } + if (tmp == "false" || tmp == "False" || tmp == "FALSE") + { + rop.value = false; + rop.initialized = true; + return lop; + } + + lop.setstate(std::ios::failbit); + return lop; + } + + std::ostream& operator<<(std::ostream& os, const Boolean& obj) + { + if (obj.initialized) + { + if (obj.value) + { + os << "true"; + } + else + { + os << "false"; + } + } + return os; + } +} diff --git a/cimgen/languages/cpp/static/Boolean.hpp b/cimgen/languages/cpp/static/Boolean.hpp new file mode 100644 index 00000000..9dc8d09c --- /dev/null +++ b/cimgen/languages/cpp/static/Boolean.hpp @@ -0,0 +1,31 @@ +#ifndef BOOLEAN_H +#define BOOLEAN_H + +#include +#include + +namespace CIMPP +{ + /** + * A type with the value space "true" and "false". + */ + class Boolean + { + public: + Boolean() : value(false), initialized(false) {} + Boolean(bool value) : value(value), initialized(true) {} + + Boolean& operator=(bool rop); + operator bool(); + + bool value; + bool initialized; + + static const char debugName[]; + const char* debugString() const; + + friend std::istream& operator>>(std::istream& lop, Boolean& rop); + friend std::ostream& operator<<(std::ostream& os, const Boolean& obj); + }; +} +#endif // BOOLEAN_H diff --git a/cimgen/languages/cpp/static/Integer.cpp b/cimgen/languages/cpp/static/Integer.cpp new file mode 100644 index 00000000..2a1cda43 --- /dev/null +++ b/cimgen/languages/cpp/static/Integer.cpp @@ -0,0 +1,74 @@ +#include "Integer.hpp" + +#include + +#include "../src/CIMExceptions.hpp" + +using namespace CIMPP; + +Integer& Integer::operator=(long int rop) +{ + value = rop; + initialized = true; + return *this; +} + +Integer::operator long int() +{ + if (!initialized) + { + throw new ReadingUninitializedField(); + } + return value; +} + +const char Integer::debugName[] = "Integer"; +const char* Integer::debugString() const +{ + return Integer::debugName; +} + +Integer& Integer::operator+=(const Integer& rhs) +{ + value += rhs.value; + return *this; +} + +Integer& Integer::operator-=(const Integer& rhs) +{ + value -= rhs.value; + return *this; +} + +Integer& Integer::operator*=(const Integer& rhs) +{ + value *= rhs.value; + return *this; +} + +Integer& Integer::operator/=(const Integer& rhs) +{ + value /= rhs.value; + return *this; +} + +namespace CIMPP +{ + std::istream& operator>>(std::istream& lop, Integer& rop) + { + std::string tmp; + lop >> tmp; + rop.value = stol(tmp); + rop.initialized = true; + return lop; + } + + std::ostream& operator<<(std::ostream& os, const Integer& obj) + { + if (obj.initialized) + { + os << obj.value; + } + return os; + } +} diff --git a/cimgen/languages/cpp/static/Integer.hpp b/cimgen/languages/cpp/static/Integer.hpp new file mode 100644 index 00000000..fab9a715 --- /dev/null +++ b/cimgen/languages/cpp/static/Integer.hpp @@ -0,0 +1,36 @@ +#ifndef INTEGER_H +#define INTEGER_H + +#include +#include + +namespace CIMPP +{ + /** + * An Integer number. The range is unspecified and not limited. + */ + class Integer + { + public: + Integer() : value(0), initialized(false) {} + Integer(long int value) : value(value), initialized(true) {} + + Integer& operator=(long int rop); + operator long int(); + + long int value; + bool initialized; + + static const char debugName[]; + const char* debugString() const; + + Integer& operator+=(const Integer& rhs); + Integer& operator-=(const Integer& rhs); + Integer& operator*=(const Integer& rhs); + Integer& operator/=(const Integer& rhs); + + friend std::istream& operator>>(std::istream& lop, Integer& rop); + friend std::ostream& operator<<(std::ostream& os, const Integer& obj); + }; +} +#endif // INTEGER_H diff --git a/cimgen/languages/cpp/templates/cpp_enum_header_template.mustache b/cimgen/languages/cpp/templates/cpp_enum_header_template.mustache index 888ac3c6..3076101c 100644 --- a/cimgen/languages/cpp/templates/cpp_enum_header_template.mustache +++ b/cimgen/languages/cpp/templates/cpp_enum_header_template.mustache @@ -1,19 +1,48 @@ #ifndef {{class_name}}_H #define {{class_name}}_H +/* +Generated from the CGMES files via cimgen: https://github.com/sogno-platform/cimgen +*/ -namespace CIMPP { +#include +#include + +namespace CIMPP +{ +{{#class_comment}} /* {{{class_comment}}} */ - enum class {{class_name}} +{{/class_comment}} + class {{class_name}} { + public: + enum {{class_name}}_ENUM + { {{#enum_instances}} - /** - * {{comment}} - */ - {{label}}, +{{#comment}} + /** + * {{comment}} + */ +{{/comment}} + {{label}}, {{/enum_instances}} + }; + + {{class_name}}() : value(), initialized(false) {} + {{class_name}}({{class_name}}_ENUM value) : value(value), initialized(true) {} + + {{class_name}}& operator=({{class_name}}_ENUM rop); + operator {{class_name}}_ENUM() const; + + {{class_name}}_ENUM value; + bool initialized; + + static const char debugName[]; + const char* debugString() const; + + friend std::istream& operator>>(std::istream& lop, {{class_name}}& rop); + friend std::ostream& operator<<(std::ostream& os, const {{class_name}}& obj); }; - std::istream& operator>>(std::istream& lop, CIMPP::{{class_name}}& rop); } #endif diff --git a/cimgen/languages/cpp/templates/cpp_enum_object_template.mustache b/cimgen/languages/cpp/templates/cpp_enum_object_template.mustache index 63eecaed..cb2998b5 100644 --- a/cimgen/languages/cpp/templates/cpp_enum_object_template.mustache +++ b/cimgen/languages/cpp/templates/cpp_enum_object_template.mustache @@ -1,12 +1,43 @@ -#include -#include +/* +Generated from the CGMES files via cimgen: https://github.com/sogno-platform/cimgen +*/ #include "{{class_name}}.hpp" +#include +#include + +#include "../src/CIMExceptions.hpp" + using namespace CIMPP; -namespace CIMPP { - std::istream& operator>>(std::istream& lop, CIMPP::{{class_name}}& rop) +{{class_name}}& {{class_name}}::operator=({{class_name}}_ENUM rop) +{ + value = rop; + initialized = true; + return *this; +} + +{{class_name}}::operator {{class_name}}_ENUM() const +{ + if (!initialized) + { + throw new ReadingUninitializedField(); + } + return value; +} + +const char {{class_name}}::debugName[] = "{{class_name}}"; +const char* {{class_name}}::debugString() const +{ + return {{class_name}}::debugName; +} + +namespace CIMPP +{ + std::istream& operator>>(std::istream& lop, {{class_name}}& rop) { + rop.initialized = false; + std::string EnumSymbol; lop >> EnumSymbol; @@ -30,4 +61,25 @@ namespace CIMPP { lop.setstate(std::ios::failbit); return lop; } + + std::ostream& operator<<(std::ostream& os, const {{class_name}}& obj) + { + if (obj.initialized) + { + std::string EnumSymbol; + +{{#enum_instances}} + if (obj.value == {{class_name}}::{{label}}) + { + EnumSymbol = "{{label}}"; + } +{{/enum_instances}} + + if (!EnumSymbol.empty()) + { + os << "{{class_name}}." << EnumSymbol; + } + } + return os; + } } diff --git a/cimgen/languages/cpp/templates/cpp_float_header_template.mustache b/cimgen/languages/cpp/templates/cpp_float_header_template.mustache index 7517148a..e558d709 100644 --- a/cimgen/languages/cpp/templates/cpp_float_header_template.mustache +++ b/cimgen/languages/cpp/templates/cpp_float_header_template.mustache @@ -1,38 +1,41 @@ #ifndef {{class_name}}_H #define {{class_name}}_H +/* +Generated from the CGMES files via cimgen: https://github.com/sogno-platform/cimgen +*/ -#include #include - -#include "BaseClass.hpp" +#include namespace CIMPP { - class {{class_name}} : public BaseClass +{{#class_comment}} + /* + {{{class_comment}}} + */ +{{/class_comment}} + class {{class_name}} { - public: - {{class_name}}(); - virtual ~{{class_name}}(); - {{class_name}}(long double value); - static const BaseClassDefiner declare(); - {{class_name}}& operator=(long double &rop); + {{class_name}}() : value(0.0), initialized(false) {} + {{class_name}}(long double value) : value(value), initialized(true) {} + + {{class_name}}& operator=(long double rop); + operator long double() const; + + long double value; + bool initialized; + + static const char debugName[]; + const char* debugString() const; + {{class_name}}& operator+=(const {{class_name}}& rhs); {{class_name}}& operator-=(const {{class_name}}& rhs); {{class_name}}& operator*=(const {{class_name}}& rhs); {{class_name}}& operator/=(const {{class_name}}& rhs); - friend std::istream& operator>>(std::istream& lop, {{class_name}}& rop); - operator long double(); - - long double value = 0.0; - bool initialized = false; - static const char debugName[]; - virtual const char* debugString(); - - static void addConstructToMap(std::unordered_map& factory_map); - static void addPrimitiveAssignFnsToMap(std::unordered_map&); - static void addClassAssignFnsToMap(std::unordered_map&); + friend std::istream& operator>>(std::istream& lop, {{class_name}}& rop); + friend std::ostream& operator<<(std::ostream& os, const {{class_name}}& obj); }; } #endif diff --git a/cimgen/languages/cpp/templates/cpp_float_object_template.mustache b/cimgen/languages/cpp/templates/cpp_float_object_template.mustache index 1d7116a4..ca84b71e 100644 --- a/cimgen/languages/cpp/templates/cpp_float_object_template.mustache +++ b/cimgen/languages/cpp/templates/cpp_float_object_template.mustache @@ -1,70 +1,77 @@ +/* +Generated from the CGMES files via cimgen: https://github.com/sogno-platform/cimgen +*/ #include "{{class_name}}.hpp" -#include "../src/CIMExceptions.hpp" - -using namespace CIMPP; - -{{class_name}}::{{class_name}}() {} -{{class_name}}::~{{class_name}}(){} +#include -{{class_name}}::{{class_name}}(long double value) : value(value), initialized(true) {} +#include "../src/CIMExceptions.hpp" -void {{class_name}}::addConstructToMap(std::unordered_map& factory_map) {} +using namespace CIMPP; -void {{class_name}}::addPrimitiveAssignFnsToMap(std::unordered_map& assign_map) {} +{{class_name}}& {{class_name}}::operator=(long double rop) +{ + value = rop; + initialized = true; + return *this; +} -void {{class_name}}::addClassAssignFnsToMap(std::unordered_map& assign_map) {} +{{class_name}}::operator long double() const +{ + if (!initialized) + { + throw new ReadingUninitializedField(); + } + return value; +} const char {{class_name}}::debugName[] = "{{class_name}}"; -const char* {{class_name}}::debugString() { +const char* {{class_name}}::debugString() const +{ return {{class_name}}::debugName; } - -const BaseClassDefiner {{class_name}}::declare() { - return BaseClassDefiner({{class_name}}::addConstructToMap, {{class_name}}::addPrimitiveAssignFnsToMap, {{class_name}}::addClassAssignFnsToMap, {{class_name}}::debugName); +{{class_name}}& {{class_name}}::operator+=(const {{class_name}}& rhs) +{ + value += rhs.value; + return *this; } -namespace CIMPP { - {{class_name}}& {{class_name}}::operator=(long double &rop) { - value = rop; - initialized = true; - return *this; - } - - {{class_name}}& {{class_name}}::operator-=(const {{class_name}}& rhs) { - value -= rhs.value; - return *this; - } - - {{class_name}}& {{class_name}}::operator*=(const {{class_name}}& rhs) { - value *= rhs.value; - return *this; - } - - {{class_name}}& {{class_name}}::operator/=(const {{class_name}}& rhs) { - value /= rhs.value; - return *this; - } +{{class_name}}& {{class_name}}::operator-=(const {{class_name}}& rhs) +{ + value -= rhs.value; + return *this; +} - {{class_name}}& {{class_name}}::operator+=(const {{class_name}}& rhs) { - value += rhs.value; - return *this; - } +{{class_name}}& {{class_name}}::operator*=(const {{class_name}}& rhs) +{ + value *= rhs.value; + return *this; +} - {{class_name}}::operator long double() { - if(!initialized) - { - throw new ReadingUninitializedField(); - } - return value; - } +{{class_name}}& {{class_name}}::operator/=(const {{class_name}}& rhs) +{ + value /= rhs.value; + return *this; +} - std::istream& operator>>(std::istream& lop, {{class_name}}& rop) { +namespace CIMPP +{ + std::istream& operator>>(std::istream& lop, {{class_name}}& rop) + { std::string tmp; lop >> tmp; rop.value = stold(tmp); rop.initialized = true; return lop; } + + std::ostream& operator<<(std::ostream& os, const {{class_name}}& obj) + { + if (obj.initialized) + { + os << obj.value; + } + return os; + } } diff --git a/cimgen/languages/cpp/templates/cpp_header_template.mustache b/cimgen/languages/cpp/templates/cpp_header_template.mustache index 6205a4c2..2d8322de 100644 --- a/cimgen/languages/cpp/templates/cpp_header_template.mustache +++ b/cimgen/languages/cpp/templates/cpp_header_template.mustache @@ -1,39 +1,42 @@ #ifndef {{class_name}}_H #define {{class_name}}_H +/* +Generated from the CGMES files via cimgen: https://github.com/sogno-platform/cimgen +*/ -#include "{{sub_class_of}}.hpp" #include -#include "Boolean.hpp" -#include "Float.hpp" +#include +#include +#include "{{sub_class_of}}.hpp" +#include "BaseClassDefiner.hpp" {{#langPack._create_attribute_includes}}{{attributes}}{{/langPack._create_attribute_includes}} - -namespace CIMPP { - +namespace CIMPP +{ {{#langPack._create_attribute_class_declarations}}{{attributes}}{{/langPack._create_attribute_class_declarations}} +{{#class_comment}} /* {{{class_comment}}} */ - class {{class_name}}: public {{sub_class_of}} +{{/class_comment}} + class {{class_name}} : public {{sub_class_of}} { - public: - {{#attributes}} - {{> attribute}} {{> label}}; /* {{comment}} Default: {{#langPack._set_default}}{{dataType}}{{/langPack._set_default}} */ - {{/attributes}} - - static const char debugName[]; - virtual const char* debugString(); - /* constructor initialising all attributes to null */ {{class_name}}(); - virtual ~{{class_name}}(); + ~{{class_name}}() override; + +{{#attributes}} + {{> attribute}} {{> label}}; /* {{comment}} Default: {{#langPack._set_default}}{{dataType}}{{/langPack._set_default}} */ +{{/attributes}} + + static const char debugName[]; + const char* debugString() const override; static void addConstructToMap(std::unordered_map& factory_map); - static void addPrimitiveAssignFnsToMap(std::unordered_map&); - static void addClassAssignFnsToMap(std::unordered_map&); + static void addPrimitiveAssignFnsToMap(std::unordered_map& assign_map); + static void addClassAssignFnsToMap(std::unordered_map& assign_map); static const BaseClassDefiner declare(); - }; BaseClass* {{class_name}}_factory(); diff --git a/cimgen/languages/cpp/templates/cpp_object_template.mustache b/cimgen/languages/cpp/templates/cpp_object_template.mustache index ae60165d..eec1a96b 100644 --- a/cimgen/languages/cpp/templates/cpp_object_template.mustache +++ b/cimgen/languages/cpp/templates/cpp_object_template.mustache @@ -1,7 +1,11 @@ -#include -#include "{{sub_class_of}}.hpp" +/* +Generated from the CGMES files via cimgen: https://github.com/sogno-platform/cimgen +*/ #include "{{class_name}}.hpp" +#include +#include + {{#attributes}} #include "{{attribute_class}}.hpp" {{/attributes}} @@ -9,7 +13,6 @@ using namespace CIMPP; {{class_name}}::{{class_name}}(){{#langPack.create_nullptr_assigns}} {{attributes}} {{/langPack.create_nullptr_assigns}} {}; - {{class_name}}::~{{class_name}}() {}; {{#attributes}} @@ -20,35 +23,40 @@ using namespace CIMPP; {{#langPack.create_class_assign}}{{.}}{{/langPack.create_class_assign}} {{/attributes}} -namespace CIMPP { - BaseClass* {{class_name}}_factory() { - return new {{class_name}}; - } +const char {{class_name}}::debugName[] = "{{class_name}}"; +const char* {{class_name}}::debugString() const +{ + return {{class_name}}::debugName; } -void {{class_name}}::addConstructToMap(std::unordered_map& factory_map) { +void {{class_name}}::addConstructToMap(std::unordered_map& factory_map) +{ factory_map.insert(std::make_pair(std::string("cim:{{class_name}}"), &{{class_name}}_factory)); } -void {{class_name}}::addPrimitiveAssignFnsToMap(std::unordered_map& assign_map) { +void {{class_name}}::addPrimitiveAssignFnsToMap(std::unordered_map& assign_map) +{ {{#attributes}} - {{> insert_assign}} +{{> insert_assign}} {{/attributes}} } -void {{class_name}}::addClassAssignFnsToMap(std::unordered_map& assign_map) { +void {{class_name}}::addClassAssignFnsToMap(std::unordered_map& assign_map) +{ {{#attributes}} - {{> insert_class_assign}} +{{> insert_class_assign}} {{/attributes}} } -const char {{class_name}}::debugName[] = "{{class_name}}"; -const char* {{class_name}}::debugString() +const BaseClassDefiner {{class_name}}::declare() { - return {{class_name}}::debugName; + return BaseClassDefiner({{class_name}}::addConstructToMap, {{class_name}}::addPrimitiveAssignFnsToMap, {{class_name}}::addClassAssignFnsToMap, {{class_name}}::debugName); } -const BaseClassDefiner {{class_name}}::declare() +namespace CIMPP { - return BaseClassDefiner({{class_name}}::addConstructToMap, {{class_name}}::addPrimitiveAssignFnsToMap, {{class_name}}::addClassAssignFnsToMap, {{class_name}}::debugName); + BaseClass* {{class_name}}_factory() + { + return new {{class_name}}; + } } diff --git a/cimgen/languages/cpp/templates/cpp_string_header_template.mustache b/cimgen/languages/cpp/templates/cpp_string_header_template.mustache new file mode 100644 index 00000000..acec4bae --- /dev/null +++ b/cimgen/languages/cpp/templates/cpp_string_header_template.mustache @@ -0,0 +1,37 @@ +#ifndef {{class_name}}_H +#define {{class_name}}_H +/* +Generated from the CGMES files via cimgen: https://github.com/sogno-platform/cimgen +*/ + +#include +#include +#include + +namespace CIMPP +{ +{{#class_comment}} + /* + {{{class_comment}}} + */ +{{/class_comment}} + class {{class_name}} + { + public: + {{class_name}}() : initialized(false) {} + {{class_name}}(const std::string& value) : value(value), initialized(true) {} + + {{class_name}}& operator=(const std::string &rop); + operator std::string() const; + + std::string value; + bool initialized; + + static const char debugName[]; + const char* debugString() const; + + friend std::istream& operator>>(std::istream& lop, {{class_name}}& rop); + friend std::ostream& operator<<(std::ostream& os, const {{class_name}}& obj); + }; +} +#endif diff --git a/cimgen/languages/cpp/templates/cpp_string_object_template.mustache b/cimgen/languages/cpp/templates/cpp_string_object_template.mustache new file mode 100644 index 00000000..07434496 --- /dev/null +++ b/cimgen/languages/cpp/templates/cpp_string_object_template.mustache @@ -0,0 +1,49 @@ +/* +Generated from the CGMES files via cimgen: https://github.com/sogno-platform/cimgen +*/ +#include "{{class_name}}.hpp" + +#include "../src/CIMExceptions.hpp" + +using namespace CIMPP; + +{{class_name}}& {{class_name}}::operator=(const std::string& rop) +{ + value = rop; + initialized = true; + return *this; +} + +{{class_name}}::operator std::string() const +{ + if (!initialized) + { + throw new ReadingUninitializedField(); + } + return value; +} + +const char {{class_name}}::debugName[] = "{{class_name}}"; +const char* {{class_name}}::debugString() const +{ + return {{class_name}}::debugName; +} + +namespace CIMPP +{ + std::istream& operator>>(std::istream& lop, {{class_name}}& rop) + { + lop >> rop.value; + rop.initialized = true; + return lop; + } + + std::ostream& operator<<(std::ostream& os, const {{class_name}}& obj) + { + if (obj.initialized) + { + os << obj.value; + } + return os; + } +}