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>.
19 #include <JM/jm_named_ptr.h>
21 #include "fmi2_xml_model_description_impl.h"
22 #include "fmi2_xml_type_impl.h"
23 #include "fmi2_xml_unit_impl.h"
24 #include "fmi2_xml_parser.h"
26 static const char* module = "FMI2XML";
28 fmi2_xml_display_unit_t* fmi2_xml_get_type_display_unit(fmi2_xml_real_typedef_t* t) {
29 fmi2_xml_variable_typedef_t* vt = (void*)t;
30 fmi2_xml_real_type_props_t * props = (fmi2_xml_real_type_props_t*)vt->typeBase.baseTypeStruct;
31 fmi2_xml_display_unit_t* du = props->displayUnit;
32 if(!du || (&du->baseUnit->defaultDisplay == du)) return 0;
36 unsigned int fmi2_xml_get_type_definition_number(fmi2_xml_type_definitions_t* td) {
37 return (unsigned int)jm_vector_get_size(jm_named_ptr)(&td->typeDefinitions);
40 fmi2_xml_variable_typedef_t* fmi2_xml_get_typedef(fmi2_xml_type_definitions_t* td, unsigned int index) {
41 if(index >= fmi2_xml_get_type_definition_number(td)) return 0;
42 return (fmi2_xml_variable_typedef_t*)jm_vector_get_item(jm_named_ptr)(&td->typeDefinitions, index).ptr;
45 const char* fmi2_xml_get_type_name(fmi2_xml_variable_typedef_t* t) {
49 const char* fmi2_xml_get_type_description(fmi2_xml_variable_typedef_t* t) {
50 const char * ret = t->description;
51 return (ret ? ret : "");
54 fmi2_base_type_enu_t fmi2_xml_get_base_type(fmi2_xml_variable_typedef_t* t) {
55 return t->typeBase.baseType;
58 fmi2_xml_real_typedef_t* fmi2_xml_get_type_as_real(fmi2_xml_variable_typedef_t* t) {
59 if(fmi2_xml_get_base_type(t) == fmi2_base_type_real) return (fmi2_xml_real_typedef_t*)t;
62 fmi2_xml_integer_typedef_t* fmi2_xml_get_type_as_int(fmi2_xml_variable_typedef_t* t) {
63 if(fmi2_xml_get_base_type(t) == fmi2_base_type_int) return (fmi2_xml_integer_typedef_t*)t;
67 fmi2_xml_enumeration_typedef_t* fmi2_xml_get_type_as_enum(fmi2_xml_variable_typedef_t* t) {
68 if(fmi2_xml_get_base_type(t) == fmi2_base_type_enum) return (fmi2_xml_enumeration_typedef_t*)t;
72 /* Note that 0-pointer is returned for strings and booleans, empty string quantity if not defined*/
73 const char* fmi2_xml_get_type_quantity(fmi2_xml_variable_typedef_t* t) {
74 fmi2_xml_variable_type_base_t* props = t->typeBase.baseTypeStruct;
76 if(props->structKind != fmi2_xml_type_struct_enu_props) return 0;
77 switch(props->baseType) {
78 case fmi2_base_type_real:
79 ret = ((fmi2_xml_real_type_props_t*)props)->quantity;
81 case fmi2_base_type_int:
82 ret = ((fmi2_xml_integer_type_props_t*)props)->quantity;
84 case fmi2_base_type_bool:
86 case fmi2_base_type_str:
88 case fmi2_base_type_enum:
89 ret = ((fmi2_xml_enum_variable_props_t*)props)->quantity;
94 return (ret ? ret : 0);
97 double fmi2_xml_get_real_type_min(fmi2_xml_real_typedef_t* t) {
98 fmi2_xml_variable_typedef_t* vt = (void*)t;
99 fmi2_xml_real_type_props_t* props = (fmi2_xml_real_type_props_t*)(vt->typeBase.baseTypeStruct);
100 return props->typeMin;
103 double fmi2_xml_get_real_type_max(fmi2_xml_real_typedef_t* t) {
104 fmi2_xml_variable_typedef_t* vt = (void*)t;
105 fmi2_xml_real_type_props_t* props = (fmi2_xml_real_type_props_t*)(vt->typeBase.baseTypeStruct);
106 return props->typeMax;
109 double fmi2_xml_get_real_type_nominal(fmi2_xml_real_typedef_t* t) {
110 fmi2_xml_variable_typedef_t* vt = (void*)t;
111 fmi2_xml_real_type_props_t* props = (fmi2_xml_real_type_props_t*)(vt->typeBase.baseTypeStruct);
112 return props->typeNominal;
115 fmi2_xml_unit_t* fmi2_xml_get_real_type_unit(fmi2_xml_real_typedef_t* t) {
116 fmi2_xml_variable_typedef_t* vt = (void*)t;
117 fmi2_xml_real_type_props_t* props = (fmi2_xml_real_type_props_t*)(vt->typeBase.baseTypeStruct);
118 fmi2_xml_display_unit_t* du = props->displayUnit;
119 if(du) return du->baseUnit;
123 int fmi2_xml_get_real_type_is_relative_quantity(fmi2_xml_real_typedef_t* t) {
124 fmi2_xml_variable_typedef_t* vt = (void*)t;
125 fmi2_xml_real_type_props_t* props = (fmi2_xml_real_type_props_t*)(vt->typeBase.baseTypeStruct);
126 return props->typeBase.isRelativeQuantity;
129 int fmi2_xml_get_real_type_is_unbounded(fmi2_xml_real_typedef_t* t) {
130 fmi2_xml_variable_typedef_t* vt = (void*)t;
131 fmi2_xml_real_type_props_t* props = (fmi2_xml_real_type_props_t*)(vt->typeBase.baseTypeStruct);
132 return props->typeBase.isUnbounded;
136 fmi2_integer_t fmi2_xml_get_integer_type_min(fmi2_xml_integer_typedef_t* t) {
137 fmi2_xml_variable_typedef_t* vt = (void*)t;
138 fmi2_xml_integer_type_props_t* props = (fmi2_xml_integer_type_props_t*)(vt->typeBase.baseTypeStruct);
139 return props->typeMin;
142 fmi2_integer_t fmi2_xml_get_integer_type_max(fmi2_xml_integer_typedef_t* t){
143 fmi2_xml_variable_typedef_t* vt = (void*)t;
144 fmi2_xml_integer_type_props_t* props = (fmi2_xml_integer_type_props_t*)(vt->typeBase.baseTypeStruct);
145 return props->typeMax;
148 int fmi2_xml_get_enum_type_min(fmi2_xml_enumeration_typedef_t* t){
149 fmi2_xml_variable_typedef_t* vt = (void*)t;
150 fmi2_xml_enum_typedef_props_t* props = (fmi2_xml_enum_typedef_props_t*)(vt->typeBase.baseTypeStruct);
151 fmi2_xml_enum_type_item_t* item;
152 if(jm_vector_get_size(jm_named_ptr)(&props->enumItems) == 0) return 0;
153 item = jm_vector_get_item(jm_named_ptr)(&props->enumItems, 0).ptr;
157 int fmi2_xml_get_enum_type_max(fmi2_xml_enumeration_typedef_t* t){
158 fmi2_xml_variable_typedef_t* vt = (void*)t;
159 fmi2_xml_enum_typedef_props_t* props = (fmi2_xml_enum_typedef_props_t*)(vt->typeBase.baseTypeStruct);
160 jm_named_ptr* itemp = jm_vector_get_lastp(jm_named_ptr)(&props->enumItems);
161 fmi2_xml_enum_type_item_t* item;
167 unsigned int fmi2_xml_get_enum_type_size(fmi2_xml_enumeration_typedef_t* t) {
168 fmi2_xml_variable_typedef_t* vt = (void*)t;
169 fmi2_xml_enum_typedef_props_t* props = (fmi2_xml_enum_typedef_props_t*)(vt->typeBase.baseTypeStruct);
170 return (unsigned int)jm_vector_get_size(jm_named_ptr)(&props->enumItems);
173 const char* fmi2_xml_get_enum_type_item_name(fmi2_xml_enumeration_typedef_t* t, unsigned int item) {
174 fmi2_xml_variable_typedef_t* vt = (fmi2_xml_variable_typedef_t*)(void*)t;
175 fmi2_xml_enum_typedef_props_t* props = (fmi2_xml_enum_typedef_props_t*)(vt->typeBase.baseTypeStruct);
176 if((item == 0) || (item > fmi2_xml_get_enum_type_size(t) )) return 0;
177 return jm_vector_get_item(jm_named_ptr)(&props->enumItems,item-1).name;
180 int fmi2_xml_get_enum_type_item_value(fmi2_xml_enumeration_typedef_t* t, unsigned int item) {
181 fmi2_xml_variable_typedef_t* vt = (fmi2_xml_variable_typedef_t*)(void*)t;
182 fmi2_xml_enum_typedef_props_t* props = (fmi2_xml_enum_typedef_props_t*)(vt->typeBase.baseTypeStruct);
183 fmi2_xml_enum_type_item_t* eitem;
184 if((item == 0) || (item > fmi2_xml_get_enum_type_size(t) )) return 0;
185 eitem = jm_vector_get_item(jm_named_ptr)(&props->enumItems,item-1).ptr;
189 const char* fmi2_xml_get_enum_type_value_name(fmi2_xml_enumeration_typedef_t* t, int value) {
190 fmi2_xml_variable_typedef_t* vt = (fmi2_xml_variable_typedef_t*)(void*)t;
191 fmi2_xml_enum_typedef_props_t* props = (fmi2_xml_enum_typedef_props_t*)(vt->typeBase.baseTypeStruct);
192 fmi2_xml_enum_type_item_t keyitem;
193 jm_named_ptr* itemp, key;
194 keyitem.value = value;
196 itemp = jm_vector_bsearch(jm_named_ptr)(&props->enumItems, &key, fmi1_xml_compare_enum_val);
202 const char* fmi2_xml_get_enum_type_item_description(fmi2_xml_enumeration_typedef_t* t, unsigned int item){
203 fmi2_xml_variable_typedef_t* vt = (void*)t;
204 fmi2_xml_enum_typedef_props_t* props = (fmi2_xml_enum_typedef_props_t*)(vt->typeBase.baseTypeStruct);
205 fmi2_xml_enum_type_item_t* e;
206 if(item > fmi2_xml_get_enum_type_size(t) ) return 0;
207 e = jm_vector_get_item(jm_named_ptr)(&props->enumItems,item-1).ptr;
208 return e->itemDesciption;
211 void fmi2_xml_init_variable_type_base(fmi2_xml_variable_type_base_t* type, fmi2_xml_type_struct_kind_enu_t kind, fmi2_base_type_enu_t baseType) {
212 type->baseTypeStruct = 0;
214 type->structKind = kind;
215 type->baseType = baseType;
216 type->isRelativeQuantity = 0;
217 type->isUnbounded = 0;
220 void fmi2_xml_init_real_type_properties(fmi2_xml_real_type_props_t* type) {
221 fmi2_xml_init_variable_type_base(&type->typeBase, fmi2_xml_type_struct_enu_props,fmi2_base_type_real);
223 type->typeMin = -DBL_MAX;
224 type->typeMax = DBL_MAX;
225 type->typeNominal = 1.0;
226 type->displayUnit = 0;
229 void fmi2_xml_init_integer_type_properties(fmi2_xml_integer_type_props_t* type) {
230 fmi2_xml_init_variable_type_base(&type->typeBase, fmi2_xml_type_struct_enu_props,fmi2_base_type_int);
232 type->typeMin = INT_MIN;
233 type->typeMax = INT_MAX;
236 void fmi2_xml_init_enumeration_variable_properties(fmi2_xml_enum_variable_props_t* type, jm_callbacks* cb) {
237 fmi2_xml_init_variable_type_base(&type->typeBase, fmi2_xml_type_struct_enu_props,fmi2_base_type_enum);
243 void fmi2_xml_init_enumeration_type_properties(fmi2_xml_enum_typedef_props_t* type, jm_callbacks* cb) {
244 fmi2_xml_init_enumeration_variable_properties(&type->base, cb);
245 jm_vector_init(jm_named_ptr)(&type->enumItems,0,cb);
248 void fmi2_xml_free_enumeration_type_props(fmi2_xml_enum_typedef_props_t* type) {
249 jm_named_vector_free_data(&type->enumItems);
252 void fmi2_xml_init_type_definitions(fmi2_xml_type_definitions_t* td, jm_callbacks* cb) {
253 jm_vector_init(jm_named_ptr)(&td->typeDefinitions,0,cb);
255 jm_vector_init(jm_string)(&td->quantities, 0, cb);
257 fmi2_xml_init_real_type_properties(&td->defaultRealType);
258 fmi2_xml_init_enumeration_type_properties(&td->defaultEnumType,cb);
259 fmi2_xml_init_integer_type_properties(&td->defaultIntegerType);
261 fmi2_xml_init_variable_type_base(&td->defaultBooleanType, fmi2_xml_type_struct_enu_props,fmi2_base_type_bool);
262 fmi2_xml_init_variable_type_base(&td->defaultStringType, fmi2_xml_type_struct_enu_props,fmi2_base_type_str);
264 td->typePropsList = 0;
267 void fmi2_xml_free_type_definitions_data(fmi2_xml_type_definitions_t* td) {
268 jm_callbacks* cb = td->typeDefinitions.callbacks;
270 jm_vector_foreach(jm_string)(&td->quantities,(void(*)(const char*))cb->free);
271 jm_vector_free_data(jm_string)(&td->quantities);
274 fmi2_xml_variable_type_base_t* next;
275 fmi2_xml_variable_type_base_t* cur = td->typePropsList;
278 if( (cur->baseType == fmi2_base_type_enum)
279 && (cur->structKind == fmi2_xml_type_struct_enu_props)
280 && (cur->baseTypeStruct == 0)
282 fmi2_xml_enum_typedef_props_t* props = (fmi2_xml_enum_typedef_props_t*)cur;
283 fmi2_xml_free_enumeration_type_props(props);
288 td->typePropsList = 0;
291 jm_named_vector_free_data(&td->typeDefinitions);
294 int fmi2_xml_handle_TypeDefinitions(fmi2_xml_parser_context_t *context, const char* data) {
296 jm_log_verbose(context->callbacks, module, "Parsing XML element TypeDefinitions");
299 fmi2_xml_type_definitions_t* defs = &context->modelDescription->typeDefinitions;
301 jm_vector_qsort(jm_named_ptr)(&defs->typeDefinitions, jm_compare_named);
302 /* might give out a warning if(data[0] != 0) */
308 int fmi2_xml_handle_SimpleType(fmi2_xml_parser_context_t *context, const char* data) {
310 fmi2_xml_model_description_t* md = context->modelDescription;
311 fmi2_xml_type_definitions_t* td = &md->typeDefinitions;
312 jm_named_ptr named, *pnamed;
313 jm_vector(char)* bufName = fmi2_xml_reserve_parse_buffer(context,1,100);
314 jm_vector(char)* bufDescr = fmi2_xml_reserve_parse_buffer(context,2,100);
316 if(!bufName || !bufDescr) return -1;
318 /* <xs:attribute name="name" type="xs:normalizedString" use="required"/> */
319 fmi2_xml_set_attr_string(context, fmi2_xml_elmID_SimpleType, fmi_attr_id_name, 1, bufName) ||
320 /* <xs:attribute name="description" type="xs:string"/> */
321 fmi2_xml_set_attr_string(context, fmi2_xml_elmID_SimpleType, fmi_attr_id_description, 0, bufDescr)
325 pnamed = jm_vector_push_back(jm_named_ptr)(&td->typeDefinitions,named);
327 fmi2_xml_variable_typedef_t dummy;
328 *pnamed = named = jm_named_alloc_v(bufName, sizeof(fmi2_xml_variable_typedef_t), dummy.typeName - (char*)&dummy, context->callbacks);
330 if(!pnamed || !named.ptr) {
331 fmi2_xml_parse_fatal(context, "Could not allocate memory");
335 fmi2_xml_variable_typedef_t* type = named.ptr;
336 fmi2_xml_init_variable_type_base(&type->typeBase,fmi2_xml_type_struct_enu_typedef,fmi2_base_type_real);
337 if(jm_vector_get_size(char)(bufDescr)) {
338 const char* description = jm_string_set_put(&md->descriptions, jm_vector_get_itemp(char)(bufDescr,0));
339 type->description = description;
341 else type->description = "";
345 jm_named_ptr named = jm_vector_get_last(jm_named_ptr)(&(context->modelDescription->typeDefinitions.typeDefinitions));
346 fmi2_xml_variable_typedef_t* type = named.ptr;
347 if(type->typeBase.baseTypeStruct == 0) {
348 fmi2_xml_parse_fatal(context, "No specific type given for type definition %s", type->typeName);
351 /* might give out a warning if(data[0] != 0) */
357 fmi2_xml_variable_type_base_t* fmi2_xml_alloc_variable_type_props(fmi2_xml_type_definitions_t* td, fmi2_xml_variable_type_base_t* base, size_t typeSize) {
358 jm_callbacks* cb = td->typeDefinitions.callbacks;
359 fmi2_xml_variable_type_base_t* type = cb->malloc(typeSize);
361 fmi2_xml_init_variable_type_base(type,fmi2_xml_type_struct_enu_props,base->baseType);
362 type->baseTypeStruct = base;
363 type->next = td->typePropsList;
364 td->typePropsList = type;
368 fmi2_xml_variable_type_base_t* fmi2_xml_alloc_variable_type_start(fmi2_xml_type_definitions_t* td,fmi2_xml_variable_type_base_t* base, size_t typeSize) {
369 jm_callbacks* cb = td->typeDefinitions.callbacks;
370 fmi2_xml_variable_type_base_t* type = cb->malloc(typeSize);
372 fmi2_xml_init_variable_type_base(type,fmi2_xml_type_struct_enu_start,base->baseType);
373 type->baseTypeStruct = base;
374 type->next = td->typePropsList;
375 td->typePropsList = type;
380 fmi2_xml_real_type_props_t* fmi2_xml_parse_real_type_properties(fmi2_xml_parser_context_t* context, fmi2_xml_elm_enu_t elmID) {
381 jm_named_ptr named, *pnamed;
382 fmi2_xml_model_description_t* md = context->modelDescription;
383 fmi2_xml_real_type_props_t* props;
384 const char* quantity = 0;
385 unsigned int relQuanBuf, unboundedBuf;
387 /* jm_vector(char)* bufName = fmi_get_parse_buffer(context,1);
388 jm_vector(char)* bufDescr = fmi_get_parse_buffer(context,2); */
389 jm_vector(char)* bufQuantity = fmi2_xml_reserve_parse_buffer(context,3,100);
390 jm_vector(char)* bufUnit = fmi2_xml_reserve_parse_buffer(context,4,100);
391 jm_vector(char)* bufDispUnit = fmi2_xml_reserve_parse_buffer(context,5,100);
393 props = (fmi2_xml_real_type_props_t*)fmi2_xml_alloc_variable_type_props(&md->typeDefinitions, &md->typeDefinitions.defaultRealType.typeBase, sizeof(fmi2_xml_real_type_props_t));
395 if(!bufQuantity || !bufUnit || !bufDispUnit || !props ||
396 /* <xs:attribute name="quantity" type="xs:normalizedString"/> */
397 fmi2_xml_set_attr_string(context, elmID, fmi_attr_id_quantity, 0, bufQuantity) ||
398 /* <xs:attribute name="unit" type="xs:normalizedString"/> */
399 fmi2_xml_set_attr_string(context, elmID, fmi_attr_id_unit, 0, bufUnit) ||
400 /* <xs:attribute name="displayUnit" type="xs:normalizedString"> */
401 fmi2_xml_set_attr_string(context, elmID, fmi_attr_id_displayUnit, 0, bufDispUnit)
403 fmi2_xml_parse_fatal(context, "Error parsing real type properties");
406 if(jm_vector_get_size(char)(bufQuantity))
407 quantity = jm_string_set_put(&md->typeDefinitions.quantities, jm_vector_get_itemp(char)(bufQuantity, 0));
409 props->quantity = quantity;
410 props->displayUnit = 0;
411 if(jm_vector_get_size(char)(bufDispUnit)) {
412 named.name = jm_vector_get_itemp(char)(bufDispUnit, 0);
413 pnamed = jm_vector_bsearch(jm_named_ptr)(&(md->displayUnitDefinitions), &named, jm_compare_named);
415 fmi2_xml_parse_fatal(context, "Unknown display unit %s in real type definition", jm_vector_get_itemp(char)(bufDispUnit, 0));
418 props->displayUnit = pnamed->ptr;
421 if(jm_vector_get_size(char)(bufUnit)) {
422 props->displayUnit = fmi2_xml_get_parsed_unit(context, bufUnit, 1);
425 if( /* <xs:attribute name="relativeQuantity" type="xs:boolean" default="false"> */
426 fmi2_xml_set_attr_boolean(context, elmID, fmi_attr_id_relativeQuantity, 0, &relQuanBuf, 0) ||
427 /* <xs:attribute name="unbounded" type="xs:boolean" default="false"> */
428 fmi2_xml_set_attr_boolean(context, elmID, fmi_attr_id_unbounded, 0, &unboundedBuf, 0) ||
429 /* <xs:attribute name="min" type="xs:double"/> */
430 fmi2_xml_set_attr_double(context, elmID, fmi_attr_id_min, 0, &props->typeMin, -DBL_MAX) ||
431 /* <xs:attribute name="max" type="xs:double"/> */
432 fmi2_xml_set_attr_double(context, elmID, fmi_attr_id_max, 0, &props->typeMax, DBL_MAX) ||
433 /* <xs:attribute name="nominal" type="xs:double"/> */
434 fmi2_xml_set_attr_double(context, elmID, fmi_attr_id_nominal, 0, &props->typeNominal, 1)
436 props->typeBase.isRelativeQuantity = (relQuanBuf) ? 1:0;
437 props->typeBase.isUnbounded = (unboundedBuf) ? 1 : 0;
441 int fmi2_xml_handle_Real(fmi2_xml_parser_context_t *context, const char* data) {
443 fmi2_xml_model_description_t* md = context->modelDescription;
445 fmi2_xml_variable_typedef_t* type;
446 fmi2_xml_real_type_props_t * props;
448 props = fmi2_xml_parse_real_type_properties(context, fmi2_xml_elmID_Real);
449 if(!props) return -1;
450 named = jm_vector_get_last(jm_named_ptr)(&md->typeDefinitions.typeDefinitions);
452 type->typeBase.baseType = fmi2_base_type_real;
453 type->typeBase.baseTypeStruct = &props->typeBase;
456 /* don't do anything. might give out a warning if(data[0] != 0) */
462 fmi2_xml_integer_type_props_t * fmi2_xml_parse_integer_type_properties(fmi2_xml_parser_context_t* context, fmi2_xml_elm_enu_t elmID) {
464 fmi2_xml_model_description_t* md = context->modelDescription;
465 fmi2_xml_integer_type_props_t * props = 0;
466 const char* quantity = 0;
468 /* jm_vector(char)* bufName = fmi_get_parse_buffer(context,1);
469 jm_vector(char)* bufDescr = fmi_get_parse_buffer(context,2); */
470 jm_vector(char)* bufQuantity = fmi2_xml_reserve_parse_buffer(context,3,100);
472 props = (fmi2_xml_integer_type_props_t*)fmi2_xml_alloc_variable_type_props(&md->typeDefinitions, &md->typeDefinitions.defaultIntegerType.typeBase, sizeof(fmi2_xml_integer_type_props_t));
474 if(!bufQuantity || !props ||
475 /* <xs:attribute name="quantity" type="xs:normalizedString"/> */
476 fmi2_xml_set_attr_string(context, elmID, fmi_attr_id_quantity, 0, bufQuantity)
479 if(jm_vector_get_size(char)(bufQuantity))
480 quantity = jm_string_set_put(&md->typeDefinitions.quantities, jm_vector_get_itemp(char)(bufQuantity, 0));
482 props->quantity = quantity;
485 /* <xs:attribute name="min" type="xs:int"/> */
486 fmi2_xml_set_attr_int(context, elmID, fmi_attr_id_min, 0, &props->typeMin, INT_MIN) ||
487 /* <xs:attribute name="max" type="xs:int"/> */
488 fmi2_xml_set_attr_int(context, elmID, fmi_attr_id_max, 0, &props->typeMax, INT_MAX)
493 int fmi2_xml_handle_Integer(fmi2_xml_parser_context_t *context, const char* data) {
495 fmi2_xml_model_description_t* md = context->modelDescription;
497 fmi2_xml_variable_typedef_t* type;
498 fmi2_xml_integer_type_props_t * props;
500 props = fmi2_xml_parse_integer_type_properties(context, fmi2_xml_elmID_Integer);
501 if(!props) return -1;
502 named = jm_vector_get_last(jm_named_ptr)(&md->typeDefinitions.typeDefinitions);
504 type->typeBase.baseType = fmi2_base_type_int;
505 type->typeBase.baseTypeStruct = &props->typeBase;
508 /* don't do anything. might give out a warning if(data[0] != 0) */
515 int fmi2_xml_handle_Boolean(fmi2_xml_parser_context_t *context, const char* data) {
517 fmi2_xml_model_description_t* md = context->modelDescription;
519 fmi2_xml_variable_typedef_t* type;
521 named = jm_vector_get_last(jm_named_ptr)(&context->modelDescription->typeDefinitions.typeDefinitions);
523 type->typeBase.baseType = fmi2_base_type_bool;
524 type->typeBase.baseTypeStruct = &md->typeDefinitions.defaultBooleanType;
527 /* don't do anything. might give out a warning if(data[0] != 0) */
533 int fmi2_xml_handle_String(fmi2_xml_parser_context_t *context, const char* data) {
535 fmi2_xml_model_description_t* md = context->modelDescription;
537 fmi2_xml_variable_typedef_t* type;
539 named = jm_vector_get_last(jm_named_ptr)(&context->modelDescription->typeDefinitions.typeDefinitions);
541 type->typeBase.baseType = fmi2_base_type_str;
542 type->typeBase.baseTypeStruct = &md->typeDefinitions.defaultStringType;
545 /* don't do anything. might give out a warning if(data[0] != 0) */
551 int fmi2_xml_handle_Enumeration(fmi2_xml_parser_context_t *context, const char* data) {
554 fmi2_xml_model_description_t* md = context->modelDescription;
555 fmi2_xml_enum_typedef_props_t * props;
556 fmi2_xml_variable_typedef_t* type;
557 const char * quantity = 0;
558 jm_vector(char)* bufQuantity = fmi2_xml_reserve_parse_buffer(context,3,100);
560 props = (fmi2_xml_enum_typedef_props_t*)fmi2_xml_alloc_variable_type_props(
561 &md->typeDefinitions,
562 &md->typeDefinitions.defaultEnumType.base.typeBase,
563 sizeof(fmi2_xml_enum_typedef_props_t));
564 props->base.typeBase.baseTypeStruct = 0;
565 if(props) jm_vector_init(jm_named_ptr)(&props->enumItems,0,context->callbacks);
566 if(!bufQuantity || !props ||
567 /* <xs:attribute name="quantity" type="xs:normalizedString"/> */
568 fmi2_xml_set_attr_string(context, fmi2_xml_elmID_Integer, fmi_attr_id_quantity, 0, bufQuantity)
571 if(jm_vector_get_size(char)(bufQuantity))
572 quantity = jm_string_set_put(&md->typeDefinitions.quantities, jm_vector_get_itemp(char)(bufQuantity, 0));
574 props->base.quantity = quantity;
576 named = jm_vector_get_last(jm_named_ptr)(&context->modelDescription->typeDefinitions.typeDefinitions);
578 type->typeBase.baseType = fmi2_base_type_enum;
579 type->typeBase.baseTypeStruct = &props->base.typeBase;
582 /* sort enum items, check that there are no duplicates */
583 jm_named_ptr named = jm_vector_get_last(jm_named_ptr)(&context->modelDescription->typeDefinitions.typeDefinitions);
584 fmi2_xml_variable_typedef_t* type = named.ptr;
585 fmi2_xml_enum_typedef_props_t * props = (fmi2_xml_enum_typedef_props_t *)type->typeBase.baseTypeStruct;
586 jm_vector(jm_named_ptr)* items = &props->enumItems;
587 size_t i, n = jm_vector_get_size(jm_named_ptr)(items);
588 jm_vector_qsort(jm_named_ptr)(items, fmi1_xml_compare_enum_val);
589 for(i = 1; i < n; i++) {
590 fmi2_xml_enum_type_item_t* a = jm_vector_get_itemp(jm_named_ptr)(items, i-1)->ptr;
591 fmi2_xml_enum_type_item_t* b = jm_vector_get_itemp(jm_named_ptr)(items, i)->ptr;
592 if(a->value == b->value) {
593 jm_log_error(context->callbacks, module, "Enum items '%s' and '%s' within enumeration '%s' have the same value %d",
594 a->itemName, b->itemName, type->typeName, a->value);
602 int fmi2_xml_handle_Item(fmi2_xml_parser_context_t *context, const char* data) {
605 fmi2_xml_model_description_t* md = context->modelDescription;
606 jm_vector(char)* bufName = fmi2_xml_reserve_parse_buffer(context,1,100);
607 jm_vector(char)* bufDescr = fmi2_xml_reserve_parse_buffer(context,2,100);
608 /* this enum item belongs to the last created enum = head of typePropsList */
609 fmi2_xml_enum_typedef_props_t * enumProps = (fmi2_xml_enum_typedef_props_t*)md->typeDefinitions.typePropsList;
610 fmi2_xml_enum_type_item_t * item;
611 jm_named_ptr named, *pnamed;
615 assert((enumProps->base.typeBase.structKind == fmi2_xml_type_struct_enu_props)
616 && (enumProps->base.typeBase.baseType == fmi2_base_type_enum));
618 if(!bufName || !bufDescr ||
619 /* <xs:attribute name="name" type="xs:normalizedString" use="required"/> */
620 fmi2_xml_set_attr_string(context, fmi2_xml_elmID_Item, fmi_attr_id_name, 1, bufName) ||
621 /* <xs:attribute name="description" type="xs:string"/> */
622 fmi2_xml_set_attr_string(context, fmi2_xml_elmID_Item, fmi_attr_id_description, 0, bufDescr) ||
623 /* <xs:attribute name="value" type="xs:int" use="required"> */
624 fmi2_xml_set_attr_int(context, fmi2_xml_elmID_Item, fmi_attr_id_value, 1, &value, 0)
627 descrlen = jm_vector_get_size(char)(bufDescr);
630 pnamed = jm_vector_push_back(jm_named_ptr)(&enumProps->enumItems, named);
632 if(pnamed) *pnamed = named = jm_named_alloc_v(bufName,sizeof(fmi2_xml_enum_type_item_t)+descrlen+1,sizeof(fmi2_xml_enum_type_item_t)+descrlen,context->callbacks);
634 if( !pnamed || !item ) {
635 fmi2_xml_parse_fatal(context, "Could not allocate memory");
638 item->itemName = named.name;
641 memcpy(item->itemDesciption,jm_vector_get_itemp(char)(bufDescr,0), descrlen);
642 item->itemDesciption[descrlen] = 0;
646 /* don't do anything. might give out a warning if(data[0] != 0) */
652 fmi2_xml_variable_type_base_t* fmi2_get_declared_type(fmi2_xml_parser_context_t *context, fmi2_xml_elm_enu_t elmID, fmi2_xml_variable_type_base_t* defaultType) {
653 jm_named_ptr key, *found;
654 jm_vector(char)* bufDeclaredType = fmi2_xml_reserve_parse_buffer(context,1, 100);
655 /* <xs:attribute name="declaredType" type="xs:normalizedString"> */
656 fmi2_xml_set_attr_string(context, elmID, fmi_attr_id_declaredType, 0, bufDeclaredType);
657 if(! jm_vector_get_size(char)(bufDeclaredType) ) return defaultType;
658 key.name = jm_vector_get_itemp(char)(bufDeclaredType,0);
659 found = jm_vector_bsearch(jm_named_ptr)(&(context->modelDescription->typeDefinitions.typeDefinitions),&key, jm_compare_named);
661 jm_log_error(context->callbacks, module, "Declared type %s not found in type definitions. Ignoring.", key.name);
665 fmi2_xml_variable_type_base_t* retType = found->ptr;
666 if(retType->baseType != defaultType->baseType) {
667 jm_log_error(context->callbacks, module, "Declared type %s does not match variable type. Ignoring.", key.name);