Skip to content

Commit

Permalink
Moving generic scheme interaction functions to new file
Browse files Browse the repository at this point in the history
  • Loading branch information
Peter Meisrimel authored and Peter Meisrimel committed Aug 8, 2024
1 parent 4fb2063 commit 510b5bc
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 147 deletions.
1 change: 1 addition & 0 deletions Config.cmake/fmixml.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
112 changes: 1 addition & 111 deletions src/XML/src/FMI3/fmi3_xml_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand All @@ -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;
Expand Down Expand Up @@ -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.
*
Expand Down
21 changes: 0 additions & 21 deletions src/XML/src/FMI3/fmi3_xml_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@
#include <FMI3/fmi3_xml_callbacks.h>

#include <FMI3/fmi3_enums.h>
#include <FMI3/fmi3_xml_model_description.h>
#include <FMI/fmi_xml_terminals_and_icons.h>
#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"

Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down
15 changes: 0 additions & 15 deletions src/XML/src/FMI3/fmi3_xml_parser_context_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

/**
Expand Down
125 changes: 125 additions & 0 deletions src/XML/src/FMI3/fmi3_xml_parser_scheme.c
Original file line number Diff line number Diff line change
@@ -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 <http://www.modelon.com>.
*/

#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);
}
32 changes: 32 additions & 0 deletions src/XML/src/FMI3/fmi3_xml_parser_scheme.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 510b5bc

Please sign in to comment.