2 Copyright (C) 2012 Modelon AB
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the BSD style license.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 FMILIB_License.txt file for more details.
12 You should have received a copy of the FMILIB_License.txt file
13 along with this program. If not, contact Modelon AB <http://www.modelon.com>.
16 #include "fmi2_xml_model_description_impl.h"
17 #include "fmi2_xml_unit_impl.h"
19 static const char* module = "FMI2XML";
21 fmi2_xml_unit_t* fmi2_xml_get_unit(fmi2_xml_unit_definitions_t* ud, unsigned int index) {
22 if(index >= fmi2_xml_get_unit_definitions_number(ud)) return 0;
23 return jm_vector_get_item(jm_named_ptr)(&ud->definitions, index).ptr;
26 const char* fmi2_xml_get_unit_name(fmi2_xml_unit_t* u) {
31 \brief Get fmi2_SI_base_units_Num SI base units exponents associated with the unit.
33 const int* fmi2_xml_get_SI_unit_exponents(fmi2_xml_unit_t* u) {
34 return u->SI_base_unit_exp;
38 \brief Get factor to the corresponding SI base units.
40 double fmi2_xml_get_SI_unit_factor(fmi2_xml_unit_t* u){
46 \brief Get offset to the corresponding SI base units.
48 double fmi2_xml_get_SI_unit_offset(fmi2_xml_unit_t* u) {
53 \brief Convert a value with respect to the unit to the
54 value with respect to the SI base unit.
56 double fmi2_xml_convert_to_SI_base_unit(double uv, fmi2_xml_unit_t* u) {
57 return u->factor * uv + u->offset;
61 \brief Convert a value with respect to the SI base unit to the
62 value with respect to the unit.
64 double fmi2_xml_convert_from_SI_base_unit(double SIv, fmi2_xml_unit_t* u) {
65 return (SIv - u->offset)/u->factor;
68 unsigned int fmi2_xml_get_unit_display_unit_number(fmi2_xml_unit_t* u) {
69 return (unsigned int)jm_vector_get_size(jm_voidp)(&u->displayUnits);
72 fmi2_xml_display_unit_t* fmi2_xml_get_unit_display_unit(fmi2_xml_unit_t* u, size_t index) {
73 if(index >= fmi2_xml_get_unit_display_unit_number(u)) return 0;
74 return jm_vector_get_item(jm_voidp)(&u->displayUnits, index);
78 fmi2_xml_unit_t* fmi2_xml_get_base_unit(fmi2_xml_display_unit_t* du) {
82 const char* fmi2_xml_get_display_unit_name(fmi2_xml_display_unit_t* du) {
83 return du->displayUnit;
86 double fmi2_xml_get_display_unit_factor(fmi2_xml_display_unit_t* du) {
90 double fmi2_xml_get_display_unit_offset(fmi2_xml_display_unit_t* du) {
94 double fmi2_xml_convert_to_display_unit(double val , fmi2_xml_display_unit_t* du, int isRelativeQuantity) {
95 double gain = fmi2_xml_get_display_unit_factor(du);
96 double offset = fmi2_xml_get_display_unit_offset(du);
97 if(isRelativeQuantity)
100 return (val*gain + offset);
103 double fmi2_xml_convert_from_display_unit(double val, fmi2_xml_display_unit_t* du, int isRelativeQuantity) {
104 double factor = fmi2_xml_get_display_unit_factor(du);
105 double offset = fmi2_xml_get_display_unit_offset(du);
106 if(isRelativeQuantity)
109 return (val - offset)/factor;
112 int fmi2_xml_handle_UnitDefinitions(fmi2_xml_parser_context_t *context, const char* data) {
113 fmi2_xml_model_description_t* md = context->modelDescription;
115 jm_log_verbose(context->callbacks, module, "Parsing XML element UnitDefinitions");
118 jm_vector_qsort(jm_named_ptr)(&(md->unitDefinitions),jm_compare_named);
119 jm_vector_qsort(jm_named_ptr)(&(md->displayUnitDefinitions),jm_compare_named);
120 /* might give out a warning if(data[0] != 0) */
126 fmi2_xml_display_unit_t* fmi2_xml_get_parsed_unit(fmi2_xml_parser_context_t *context, jm_vector(char)* name, int sorted) {
127 fmi2_xml_unit_t dummy, *unit;
128 jm_named_ptr named, *pnamed;
129 fmi2_xml_model_description_t* md = context->modelDescription;
131 if(jm_vector_get_size(char)(name))
132 named.name = jm_vector_get_itemp(char)(name,0);
137 pnamed = jm_vector_bsearch(jm_named_ptr)(&(md->unitDefinitions), &named,jm_compare_named);
139 pnamed = jm_vector_find(jm_named_ptr)(&(md->unitDefinitions), &named,jm_compare_named);
143 return &unit->defaultDisplay;
147 pnamed = jm_vector_push_back(jm_named_ptr)(&(md->unitDefinitions),named);
148 if(pnamed) *pnamed = named = jm_named_alloc_v(name,sizeof(fmi2_xml_unit_t),dummy.baseUnit - (char*)&dummy,context->callbacks);
150 if(!pnamed || !named.ptr) {
151 fmi2_xml_parse_fatal(context, "Could not allocate memory");
158 for(i = 0; i < fmi2_SI_base_units_Num; i++)
159 unit->SI_base_unit_exp[i] = 0;
160 unit->defaultDisplay.baseUnit = unit;
161 unit->defaultDisplay.offset = 0;
162 unit->defaultDisplay.factor = 1.0;
163 unit->defaultDisplay.displayUnit[0] = 0;
164 jm_vector_init(jm_voidp)(&(unit->displayUnits),0,context->callbacks);
166 if(sorted) jm_vector_qsort_jm_named_ptr(&(md->unitDefinitions), jm_compare_named);
167 return &unit->defaultDisplay;
170 int fmi2_xml_handle_BaseUnit(fmi2_xml_parser_context_t *context, const char* data) {
173 /* fmi2_xml_model_description_t* md = context->modelDescription; */
174 /* this base unit belongs to the last created base unit */
175 fmi2_xml_unit_t* unit = context->lastBaseUnit;
177 /* process the attributes */
179 /* <xs:attribute name="xxx" type="xs:int" default="0"> */
180 #define FMI2_PARSE_SI_BASE_UNIT_ENU(c) \
181 fmi2_xml_set_attr_int(context, fmi2_xml_elmID_BaseUnit, fmi_attr_id_ ## c,0,&(unit->SI_base_unit_exp[fmi2_SI_base_unit_ ## c]),0) ||
183 FMI2_SI_BASE_UNITS(FMI2_PARSE_SI_BASE_UNIT_ENU)
184 /* <xs:attribute name="factor" type="xs:double" default="1"/> */
185 fmi2_xml_set_attr_double(context, fmi2_xml_elmID_BaseUnit, fmi_attr_id_factor, 0, &unit->factor, 1) ||
186 /* <xs:attribute name="offset" type="xs:double" default="0"/> */
187 fmi2_xml_set_attr_double(context, fmi2_xml_elmID_BaseUnit, fmi_attr_id_offset, 0, &unit->offset, 0);
189 if(unit->factor == 0) {
192 fmi2_xml_parse_error(context, "Attribute 'factor' cannot be equal to zero");
199 /* don't do anything. might give out a warning if(data[0] != 0) */
207 int fmi2_xml_handle_Unit(fmi2_xml_parser_context_t *context, const char* data) {
209 fmi2_xml_display_unit_t* unit;
210 jm_vector(char)* buf = fmi2_xml_reserve_parse_buffer(context,1,100);
214 /* <xs:attribute name="name" type="xs:normalizedString" use="required"> */
215 fmi2_xml_set_attr_string(context, fmi2_xml_elmID_BaseUnit, fmi_attr_id_name, 1, buf) ||
216 !(unit = fmi2_xml_get_parsed_unit(context, buf, 0))
218 context->lastBaseUnit = unit->baseUnit;
221 /* don't do anything. might give out a warning if(data[0] != 0) */
227 int fmi2_xml_handle_DisplayUnit(fmi2_xml_parser_context_t *context, const char* data) {
230 fmi2_xml_model_description_t* md = context->modelDescription;
231 jm_vector(char)* buf = fmi2_xml_reserve_parse_buffer(context,1,100);
232 /* this display unit belongs to the last created base unit */
233 fmi2_xml_unit_t* unit = context->lastBaseUnit;
234 fmi2_xml_display_unit_t *dispUnit = 0;
235 fmi2_xml_display_unit_t dummyDU;
236 jm_named_ptr named, *pnamed;
239 /* first read the required name attribute */
240 /* <xs:attribute name="name" type="xs:normalizedString" use="required"/> */
241 ret = fmi2_xml_set_attr_string(context, fmi2_xml_elmID_DisplayUnit, fmi_attr_id_name, 1, buf);
243 /* alloc memory to the correct size and put display unit on the list for the base unit */
245 pnamed = jm_vector_push_back(jm_named_ptr)(&(md->displayUnitDefinitions),named);
246 if(pnamed) *pnamed = jm_named_alloc(jm_vector_get_itemp_char(buf,0),sizeof(fmi2_xml_display_unit_t), dummyDU.displayUnit - (char*)&dummyDU,context->callbacks);
247 dispUnit = pnamed->ptr;
248 if( !pnamed || !dispUnit ||
249 !jm_vector_push_back(jm_voidp)(&unit->displayUnits, dispUnit) ) {
250 fmi2_xml_parse_fatal(context, "Could not allocate memory");
253 dispUnit->baseUnit = unit;
254 /* finally process the attributes */
256 /* <xs:attribute name="factor" type="xs:double" default="1"/> */
257 fmi2_xml_set_attr_double(context, fmi2_xml_elmID_DisplayUnit, fmi_attr_id_factor, 0, &dispUnit->factor, 1) ||
258 /* <xs:attribute name="offset" type="xs:double" default="0"/> */
259 fmi2_xml_set_attr_double(context, fmi2_xml_elmID_DisplayUnit, fmi_attr_id_offset, 0, &dispUnit->offset, 0);
260 if(dispUnit->factor == 0) {
261 dispUnit->factor = 1.0;
263 fmi2_xml_parse_error(context, "Attribute 'factor' cannot be equal to zero");
270 /* don't do anything. might give out a warning if(data[0] != 0) */