From 510b5bc19bc1d21fe2bba78db1327ec91fc77d84 Mon Sep 17 00:00:00 2001 From: Peter Meisrimel Date: Thu, 8 Aug 2024 17:13:53 +0200 Subject: [PATCH] Moving generic scheme interaction functions to new file --- Config.cmake/fmixml.cmake | 1 + src/XML/src/FMI3/fmi3_xml_parser.c | 112 +--------------- src/XML/src/FMI3/fmi3_xml_parser.h | 21 --- .../src/FMI3/fmi3_xml_parser_context_impl.h | 15 --- src/XML/src/FMI3/fmi3_xml_parser_scheme.c | 125 ++++++++++++++++++ src/XML/src/FMI3/fmi3_xml_parser_scheme.h | 32 +++++ 6 files changed, 159 insertions(+), 147 deletions(-) create mode 100644 src/XML/src/FMI3/fmi3_xml_parser_scheme.c diff --git a/Config.cmake/fmixml.cmake b/Config.cmake/fmixml.cmake index ba03446b..6a2942b5 100644 --- a/Config.cmake/fmixml.cmake +++ b/Config.cmake/fmixml.cmake @@ -186,6 +186,7 @@ set(FMIXMLSOURCE src/FMI3/fmi3_xml_vendor_annotations.c src/FMI3/fmi3_xml_variable.c src/FMI3/fmi3_xml_model_description_scheme.c + src/FMI3/fmi3_xml_parser_scheme.c ) include(ExternalProject) diff --git a/src/XML/src/FMI3/fmi3_xml_parser.c b/src/XML/src/FMI3/fmi3_xml_parser.c index f6c1085f..c80b4cb3 100644 --- a/src/XML/src/FMI3/fmi3_xml_parser.c +++ b/src/XML/src/FMI3/fmi3_xml_parser.c @@ -29,7 +29,7 @@ #include "../FMI/fmi_xml_terminals_and_icons_impl.h" #include "fmi3_xml_parser.h" #include "JM/jm_portability.h" -#include "fmi3_xml_parser_context_impl.h" // TODO: Really needed here? +#include "fmi3_xml_parser_context_impl.h" static const char* module = "FMI3XML"; @@ -42,85 +42,6 @@ typedef unsigned long long int fmi3_uint_buf_t; /* same size as fmi3_int_buf_t #define UINTXX_MIN (0) #define FMI3_FLOAT32_MAX (3.402823466e+38F) /* FLT_MAX from float.h is platform-dependent (doesn't have to be 32 bit) */ -static jm_string fmi3_xml_get_xml_attr_name(fmi3_xml_parser_context_t* context, const fmi3_xml_attr_t enu) { - const fmi3_xml_type_t xmlType = context->xmlType; - switch (xmlType) { - case fmi3_xml_type_modelDescription: - return fmi3_xml_scheme_get_modelDescription_attrName(enu.modelDescription); - case fmi3_xml_type_terminalAndIcons: - return fmi_xml_scheme_get_termIcon_attrName(enu.termIcon); - } - return "unknown"; -} - -// TODO: Move to more suitable place? -static fmi3_xml_scheme_info_t fmi3_xml_get_scheme_info(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t enu) { - const fmi3_xml_type_t xmlType = context->xmlType; - - fmi3_xml_scheme_modelDescription_info_t info_modelDescription; - fmi_xml_scheme_termIcon_info_t info_termIcon; - - fmi3_xml_scheme_info_t ret; - switch (xmlType) { - case fmi3_xml_type_modelDescription: - info_modelDescription = fmi3_xml_scheme_get_modelDescription_info(enu.modelDescription); - - ret.superID = FMI3_ELM(info_modelDescription.superID); - ret.parentID = FMI3_ELM(info_modelDescription.parentID); - ret.siblingIndex = info_modelDescription.siblingIndex; - ret.multipleAllowed = info_modelDescription.multipleAllowed; - break; - case fmi3_xml_type_terminalAndIcons: - info_termIcon = fmi_xml_scheme_get_termIcon_info(enu.termIcon); - - ret.superID = FMI_ELM_TERMICON(info_termIcon.superID); - ret.parentID = FMI_ELM_TERMICON(info_termIcon.parentID); - ret.siblingIndex = info_termIcon.siblingIndex; - ret.multipleAllowed = info_termIcon.multipleAllowed; - break; - default: - // erroneous output - ret.superID = FMI3_ELM_ANY(FMI_XML_ELMID_NONE); - ret.parentID = FMI3_ELM_ANY(FMI_XML_ELMID_NONE); - ret.siblingIndex = -1; - ret.multipleAllowed = -1; - } - return ret; -} - -// TODO: Move to more suitable place? -static fmi3_xml_element_handle_map_t fmi3_xml_get_element_handle(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t enu) { - const fmi3_xml_type_t xmlType = context->xmlType; - - fmi3_xml_modelDescription_element_handle_map_t map_modelDescription; - fmi_xml_termIcon_element_handle_map_t map_termIcon; - - fmi3_xml_element_handle_map_t ret; - switch (xmlType) { - case fmi3_xml_type_modelDescription: - map_modelDescription = fmi3_xml_scheme_get_modelDescription_handle(enu.modelDescription); - - ret.elementName = map_modelDescription.elementName; - ret.elementHandle = (fmi3_xml_element_handle_ft) map_modelDescription.elementHandle; - ret.elemID = FMI3_ELM(map_modelDescription.elemID); - break; - case fmi3_xml_type_terminalAndIcons: - map_termIcon = fmi_xml_scheme_get_termIcon_handle(enu.termIcon); - - ret.elementName = map_termIcon.elementName; - ret.elementHandle = (fmi3_xml_element_handle_ft) map_termIcon.elementHandle; - ret.elemID = FMI_ELM_TERMICON(map_termIcon.elemID); - break; - default: - // erroneous output - ret.elementName = "unknown"; - ret.elementHandle = NULL; - ret.elemID = FMI3_ELM_ANY(FMI_XML_ELMID_NONE); - } - return ret; -} - -// TODO: Move to better place? const char* fmi3_xml_elmid_to_name(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t id){ fmi3_xml_element_handle_map_t item = fmi3_xml_get_element_handle(context, id); return item.elementName; @@ -1066,37 +987,6 @@ void fmi3_xml_set_element_handle(fmi3_xml_parser_context_t* context, const char* currentElMap->elemID = id; } -/** - * Returns true if parent element's type or super type (recursively) matches - * the expected type. - */ -int fmi3_xml_is_valid_parent(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t child_id, fmi3_xml_elm_t parent_id) { - fmi3_xml_elm_t p_id_expected = fmi3_xml_get_scheme_info(context, child_id).parentID; - - while (parent_id.any != p_id_expected.any && parent_id.any != FMI_XML_ELMID_NONE) { - parent_id = fmi3_xml_get_scheme_info(context, parent_id).superID; - } - return parent_id.any == p_id_expected.any; -} - -/** - * Returns top level super type of the element. - */ -int fmi3_xml_get_super_type_rec(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t id) { - fmi3_xml_elm_t id_top = id; - while ((fmi3_xml_get_scheme_info(context, id_top).superID).any != FMI_XML_ELMID_NONE) { - id_top = fmi3_xml_get_scheme_info(context, id_top).superID; - } - return id_top.any; -} - -/** - * Returns true if the top-level super types are the same. - */ -int fmi3_xml_are_same_type(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t id1, fmi3_xml_elm_t id2) { - return fmi3_xml_get_super_type_rec(context, id1) == fmi3_xml_get_super_type_rec(context, id2); -} - /** * Expat callback which is called after reading an element and its attributes. * diff --git a/src/XML/src/FMI3/fmi3_xml_parser.h b/src/XML/src/FMI3/fmi3_xml_parser.h index 0c9eb3a1..f77d53d1 100644 --- a/src/XML/src/FMI3/fmi3_xml_parser.h +++ b/src/XML/src/FMI3/fmi3_xml_parser.h @@ -25,10 +25,6 @@ #include #include -#include -#include -#include "fmi3_xml_model_description_scheme.h" -#include "../FMI/fmi_xml_terminals_and_icons_scheme.h" #include "fmi3_xml_parser_context_impl.h" #include "fmi3_xml_parser_util.h" @@ -38,17 +34,6 @@ extern "C" { jm_vector_declare_template(fmi3_value_reference_t) -// /** Keeps information about the allowed parent element ID, index among siblings in a sequence and if -// multiple elements of this type are allowed in a sequence. -// */ -typedef struct { - fmi3_xml_elm_t superID; /* ID of super type or NULL if none */ - fmi3_xml_elm_t parentID; /* expected parent ID for an element */ - int siblingIndex; /* index among siblings */ - int multipleAllowed; /* multiple elements of this kind kan come in a sequence as siblings*/ -} fmi3_xml_scheme_info_t; - - #define fmi3_xml_diff_elmName(a, b) strcmp(a.elementName,b.elementName) jm_define_comp_f(fmi3_xml_compare_elmName, fmi3_xml_element_handle_map_t, fmi3_xml_diff_elmName) @@ -113,12 +98,6 @@ jm_string fmi3_xml_peek_attr_str(fmi3_xml_parser_context_t* context, const fmi3_ int fmi3_xml_get_attr_str(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t elmID, const fmi3_xml_attr_t attrID, int required, const char** valp); void fmi3_xml_set_element_handle(fmi3_xml_parser_context_t* context, const char* elm, fmi3_xml_elm_t id); - -// TODO: These last 3 should probably go to a scheme file -int fmi3_xml_is_valid_parent(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t child_id, fmi3_xml_elm_t parent_id); -int fmi3_xml_get_super_type_rec(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t id); -int fmi3_xml_are_same_type(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t id1, fmi3_xml_elm_t id2); - const char* fmi3_xml_elmid_to_name(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t id); #ifdef __cplusplus diff --git a/src/XML/src/FMI3/fmi3_xml_parser_context_impl.h b/src/XML/src/FMI3/fmi3_xml_parser_context_impl.h index b1c19bb8..65f447fd 100644 --- a/src/XML/src/FMI3/fmi3_xml_parser_context_impl.h +++ b/src/XML/src/FMI3/fmi3_xml_parser_context_impl.h @@ -28,21 +28,6 @@ extern "C" { #endif -/** Flag for current XML file being handled. */ -// TODO: Might be more suited in parser.h? -typedef enum fmi3_xml_type_t { - fmi3_xml_type_modelDescription, - fmi3_xml_type_terminalAndIcons -} fmi3_xml_type_t; - -typedef struct fmi3_xml_element_handle_map_t fmi3_xml_element_handle_map_t; -typedef int (*fmi3_xml_element_handle_ft)(fmi3_xml_parser_context_t* context, const char* data); -struct fmi3_xml_element_handle_map_t { - const char* elementName; - fmi3_xml_element_handle_ft elementHandle; - fmi3_xml_elm_t elemID; -}; - jm_vector_declare_template(fmi3_xml_element_handle_map_t) /** diff --git a/src/XML/src/FMI3/fmi3_xml_parser_scheme.c b/src/XML/src/FMI3/fmi3_xml_parser_scheme.c new file mode 100644 index 00000000..014591e7 --- /dev/null +++ b/src/XML/src/FMI3/fmi3_xml_parser_scheme.c @@ -0,0 +1,125 @@ +/* + Copyright (C) 2024 Modelon AB + + This program is free software: you can redistribute it and/or modify + it under the terms of the BSD style license. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + FMILIB_License.txt file for more details. + + You should have received a copy of the FMILIB_License.txt file + along with this program. If not, contact Modelon AB . +*/ + +#include "JM/jm_portability.h" +#include "fmi3_xml_parser_scheme.h" +#include "fmi3_xml_parser_context_impl.h" + +jm_string fmi3_xml_get_xml_attr_name(fmi3_xml_parser_context_t* context, const fmi3_xml_attr_t enu) { + const fmi3_xml_type_t xmlType = context->xmlType; + switch (xmlType) { + case fmi3_xml_type_modelDescription: + return fmi3_xml_scheme_get_modelDescription_attrName(enu.modelDescription); + case fmi3_xml_type_terminalAndIcons: + return fmi_xml_scheme_get_termIcon_attrName(enu.termIcon); + } + return "unknown"; +} + +fmi3_xml_scheme_info_t fmi3_xml_get_scheme_info(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t enu) { + const fmi3_xml_type_t xmlType = context->xmlType; + + fmi3_xml_scheme_modelDescription_info_t info_modelDescription; + fmi_xml_scheme_termIcon_info_t info_termIcon; + + fmi3_xml_scheme_info_t ret; + switch (xmlType) { + case fmi3_xml_type_modelDescription: + info_modelDescription = fmi3_xml_scheme_get_modelDescription_info(enu.modelDescription); + + ret.superID = FMI3_ELM(info_modelDescription.superID); + ret.parentID = FMI3_ELM(info_modelDescription.parentID); + ret.siblingIndex = info_modelDescription.siblingIndex; + ret.multipleAllowed = info_modelDescription.multipleAllowed; + break; + case fmi3_xml_type_terminalAndIcons: + info_termIcon = fmi_xml_scheme_get_termIcon_info(enu.termIcon); + + ret.superID = FMI_ELM_TERMICON(info_termIcon.superID); + ret.parentID = FMI_ELM_TERMICON(info_termIcon.parentID); + ret.siblingIndex = info_termIcon.siblingIndex; + ret.multipleAllowed = info_termIcon.multipleAllowed; + break; + default: + // erroneous output + ret.superID = FMI3_ELM_ANY(FMI_XML_ELMID_NONE); + ret.parentID = FMI3_ELM_ANY(FMI_XML_ELMID_NONE); + ret.siblingIndex = -1; + ret.multipleAllowed = -1; + } + return ret; +} + +fmi3_xml_element_handle_map_t fmi3_xml_get_element_handle(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t enu) { + const fmi3_xml_type_t xmlType = context->xmlType; + + fmi3_xml_modelDescription_element_handle_map_t map_modelDescription; + fmi_xml_termIcon_element_handle_map_t map_termIcon; + + fmi3_xml_element_handle_map_t ret; + switch (xmlType) { + case fmi3_xml_type_modelDescription: + map_modelDescription = fmi3_xml_scheme_get_modelDescription_handle(enu.modelDescription); + + ret.elementName = map_modelDescription.elementName; + ret.elementHandle = (fmi3_xml_element_handle_ft) map_modelDescription.elementHandle; + ret.elemID = FMI3_ELM(map_modelDescription.elemID); + break; + case fmi3_xml_type_terminalAndIcons: + map_termIcon = fmi_xml_scheme_get_termIcon_handle(enu.termIcon); + + ret.elementName = map_termIcon.elementName; + ret.elementHandle = (fmi3_xml_element_handle_ft) map_termIcon.elementHandle; + ret.elemID = FMI_ELM_TERMICON(map_termIcon.elemID); + break; + default: + // erroneous output + ret.elementName = "unknown"; + ret.elementHandle = NULL; + ret.elemID = FMI3_ELM_ANY(FMI_XML_ELMID_NONE); + } + return ret; +} + +/** + * Returns true if parent element's type or super type (recursively) matches + * the expected type. + */ +int fmi3_xml_is_valid_parent(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t child_id, fmi3_xml_elm_t parent_id) { + fmi3_xml_elm_t p_id_expected = fmi3_xml_get_scheme_info(context, child_id).parentID; + + while (parent_id.any != p_id_expected.any && parent_id.any != FMI_XML_ELMID_NONE) { + parent_id = fmi3_xml_get_scheme_info(context, parent_id).superID; + } + return parent_id.any == p_id_expected.any; +} + +/** + * Returns top level super type of the element. + */ +int fmi3_xml_get_super_type_rec(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t id) { + fmi3_xml_elm_t id_top = id; + while ((fmi3_xml_get_scheme_info(context, id_top).superID).any != FMI_XML_ELMID_NONE) { + id_top = fmi3_xml_get_scheme_info(context, id_top).superID; + } + return id_top.any; +} + +/** + * Returns true if the top-level super types are the same. + */ +int fmi3_xml_are_same_type(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t id1, fmi3_xml_elm_t id2) { + return fmi3_xml_get_super_type_rec(context, id1) == fmi3_xml_get_super_type_rec(context, id2); +} diff --git a/src/XML/src/FMI3/fmi3_xml_parser_scheme.h b/src/XML/src/FMI3/fmi3_xml_parser_scheme.h index ee03b345..54bbee42 100644 --- a/src/XML/src/FMI3/fmi3_xml_parser_scheme.h +++ b/src/XML/src/FMI3/fmi3_xml_parser_scheme.h @@ -46,6 +46,38 @@ typedef union fmi3_xml_elm_t { #define FMI3_ELM(enu) (fmi3_xml_elm_t){.modelDescription = enu} #define FMI_ELM_TERMICON(enu) (fmi3_xml_elm_t){.termIcon = enu} +// /** Keeps information about the allowed parent element ID, index among siblings in a sequence and if +// multiple elements of this type are allowed in a sequence. +// */ +typedef struct { + fmi3_xml_elm_t superID; /* ID of super type or NULL if none */ + fmi3_xml_elm_t parentID; /* expected parent ID for an element */ + int siblingIndex; /* index among siblings */ + int multipleAllowed; /* multiple elements of this kind kan come in a sequence as siblings*/ +} fmi3_xml_scheme_info_t; + +/** Flag for current XML file being handled. */ +typedef enum fmi3_xml_type_t { + fmi3_xml_type_modelDescription, + fmi3_xml_type_terminalAndIcons +} fmi3_xml_type_t; + +typedef struct fmi3_xml_element_handle_map_t fmi3_xml_element_handle_map_t; +typedef int (*fmi3_xml_element_handle_ft)(fmi3_xml_parser_context_t* context, const char* data); +struct fmi3_xml_element_handle_map_t { + const char* elementName; + fmi3_xml_element_handle_ft elementHandle; + fmi3_xml_elm_t elemID; +}; + +jm_string fmi3_xml_get_xml_attr_name(fmi3_xml_parser_context_t* context, const fmi3_xml_attr_t enu); +fmi3_xml_scheme_info_t fmi3_xml_get_scheme_info(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t enu); +fmi3_xml_element_handle_map_t fmi3_xml_get_element_handle(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t enu); + +int fmi3_xml_is_valid_parent(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t child_id, fmi3_xml_elm_t parent_id); +int fmi3_xml_get_super_type_rec(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t id); +int fmi3_xml_are_same_type(fmi3_xml_parser_context_t* context, fmi3_xml_elm_t id1, fmi3_xml_elm_t id2); + #ifdef __cplusplus } #endif