]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/native/FMILibrary/src/XML/src/FMI2/fmi2_xml_type.c
Switch to full JavaSE-11+ compatibility
[simantics/fmil.git] / org.simantics.fmil.core / native / FMILibrary / src / XML / src / FMI2 / fmi2_xml_type.c
1 /*
2     Copyright (C) 2012 Modelon AB
3
4     This program is free software: you can redistribute it and/or modify
5     it under the terms of the BSD style license.
6
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.
11
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>.
14 */
15
16 #include <limits.h>
17 #include <float.h>
18 #include <string.h>
19 #include <JM/jm_named_ptr.h>
20
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"
25
26 static const char* module = "FMI2XML";
27
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;
33     return du;
34 }
35
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);
38 }
39
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;
43 }
44
45 const char* fmi2_xml_get_type_name(fmi2_xml_variable_typedef_t* t) {   
46     return t->typeName;
47 }
48
49 const char* fmi2_xml_get_type_description(fmi2_xml_variable_typedef_t* t) {
50         const char * ret = t->description;
51     return (ret ? ret : "");
52 }
53
54 fmi2_base_type_enu_t fmi2_xml_get_base_type(fmi2_xml_variable_typedef_t* t) {
55     return t->typeBase.baseType;
56 }
57
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;
60     return 0;
61 }
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;
64     return 0;
65 }
66
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;
69     return 0;
70 }
71
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;
75         const char * ret;
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;
80                 break;
81     case fmi2_base_type_int:
82         ret = ((fmi2_xml_integer_type_props_t*)props)->quantity;
83                 break;
84     case fmi2_base_type_bool:
85         return 0;
86     case fmi2_base_type_str:
87         return 0;
88     case fmi2_base_type_enum:
89                 ret = ((fmi2_xml_enum_variable_props_t*)props)->quantity;
90                 break;
91     default:
92         return 0;
93     }
94         return (ret ? ret : 0);
95 }
96
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;
101 }
102
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;
107 }
108
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;
113 }
114
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;
120     return 0;
121 }
122
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;
127 }
128
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;
133 }
134
135
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;
140 }
141
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;
146 }
147
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;
154         return item->value;
155 }
156
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;
162         if(!itemp) return 0;
163         item = itemp->ptr;
164         return item->value;
165 }
166
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);
171 }
172
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;
178 }
179
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;
186     return eitem->value;
187 }
188
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;
195         key.ptr = &keyitem;
196         itemp = jm_vector_bsearch(jm_named_ptr)(&props->enumItems, &key, fmi1_xml_compare_enum_val);
197     if(!itemp) return  0;
198         return itemp->name;
199 }
200
201
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;
209 }
210
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;
213     type->next = 0;
214     type->structKind = kind;
215     type->baseType = baseType;
216         type->isRelativeQuantity = 0;
217         type->isUnbounded = 0;
218 }
219
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);
222     type->quantity = 0;    
223     type->typeMin = -DBL_MAX;
224     type->typeMax = DBL_MAX;
225     type->typeNominal = 1.0;
226     type->displayUnit = 0;
227 }
228
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);
231     type->quantity = 0;
232     type->typeMin = INT_MIN;
233     type->typeMax = INT_MAX;
234 }
235
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);
238         type->quantity = 0;
239     type->typeMin = 0;
240     type->typeMax = 0;
241 }
242
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);
246 }
247
248 void fmi2_xml_free_enumeration_type_props(fmi2_xml_enum_typedef_props_t* type) {
249     jm_named_vector_free_data(&type->enumItems);
250 }
251
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);
254
255     jm_vector_init(jm_string)(&td->quantities, 0, cb);
256
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);
260
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);
263
264     td->typePropsList = 0;
265 }
266
267 void fmi2_xml_free_type_definitions_data(fmi2_xml_type_definitions_t* td) {
268     jm_callbacks* cb = td->typeDefinitions.callbacks;
269
270     jm_vector_foreach(jm_string)(&td->quantities,(void(*)(const char*))cb->free);
271     jm_vector_free_data(jm_string)(&td->quantities);
272
273     {
274         fmi2_xml_variable_type_base_t* next;
275         fmi2_xml_variable_type_base_t* cur = td->typePropsList;
276         while(cur) {
277             next = cur->next;
278             if(    (cur->baseType == fmi2_base_type_enum) 
279                                 && (cur->structKind == fmi2_xml_type_struct_enu_props)
280                                 && (cur->baseTypeStruct == 0)
281                                 ) {
282                 fmi2_xml_enum_typedef_props_t* props = (fmi2_xml_enum_typedef_props_t*)cur;
283                 fmi2_xml_free_enumeration_type_props(props);
284             }
285             cb->free(cur);
286             cur = next;
287         }
288                 td->typePropsList = 0;
289     }
290
291     jm_named_vector_free_data(&td->typeDefinitions);
292 }
293
294 int fmi2_xml_handle_TypeDefinitions(fmi2_xml_parser_context_t *context, const char* data) {
295     if(!data) {
296                 jm_log_verbose(context->callbacks, module, "Parsing XML element TypeDefinitions");
297     }
298     else {
299         fmi2_xml_type_definitions_t* defs =  &context->modelDescription->typeDefinitions;
300
301         jm_vector_qsort(jm_named_ptr)(&defs->typeDefinitions, jm_compare_named);
302         /* might give out a warning if(data[0] != 0) */
303         return 0;
304     }
305     return 0;
306 }
307
308 int fmi2_xml_handle_SimpleType(fmi2_xml_parser_context_t *context, const char* data) {
309     if(!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);
315
316             if(!bufName || !bufDescr) return -1;
317             if(
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)
322                     ) return -1;
323             named.ptr = 0;
324                         named.name = 0;
325             pnamed = jm_vector_push_back(jm_named_ptr)(&td->typeDefinitions,named);
326             if(pnamed) {
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);
329             }
330             if(!pnamed || !named.ptr) {
331                 fmi2_xml_parse_fatal(context, "Could not allocate memory");
332                 return -1;
333             }
334             else {
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;
340                 }
341                 else type->description = "";
342             }
343     }
344     else {
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);
349             return -1;
350         }
351         /* might give out a warning if(data[0] != 0) */
352         return 0;
353     }
354     return 0;
355 }
356
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);
360     if(!type) return 0;
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;
365     return type;
366 }
367
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);
371     if(!type) return 0;
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;
376     return type;
377 }
378
379
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;
386
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);
392
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));
394
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)
402             ) {
403         fmi2_xml_parse_fatal(context, "Error parsing real type properties");
404         return 0;
405     }
406     if(jm_vector_get_size(char)(bufQuantity))
407         quantity = jm_string_set_put(&md->typeDefinitions.quantities, jm_vector_get_itemp(char)(bufQuantity, 0));
408
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);
414         if(!pnamed) {
415             fmi2_xml_parse_fatal(context, "Unknown display unit %s in real type definition", jm_vector_get_itemp(char)(bufDispUnit, 0));
416             return 0;
417         }
418         props->displayUnit = pnamed->ptr;
419     }
420     else {
421         if(jm_vector_get_size(char)(bufUnit)) {
422             props->displayUnit = fmi2_xml_get_parsed_unit(context, bufUnit, 1);
423         }
424     }
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)
435             ) return 0;
436         props->typeBase.isRelativeQuantity = (relQuanBuf) ? 1:0;
437         props->typeBase.isUnbounded = (unboundedBuf) ? 1 : 0;
438     return props;
439 }
440
441 int fmi2_xml_handle_Real(fmi2_xml_parser_context_t *context, const char* data) {
442     if(!data) {
443         fmi2_xml_model_description_t* md = context->modelDescription;
444         jm_named_ptr named;
445         fmi2_xml_variable_typedef_t* type;
446         fmi2_xml_real_type_props_t * props;
447
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);
451         type = named.ptr;
452         type->typeBase.baseType = fmi2_base_type_real;
453         type->typeBase.baseTypeStruct = &props->typeBase;
454     }
455     else {
456         /* don't do anything. might give out a warning if(data[0] != 0) */
457         return 0;
458     }
459     return 0;
460 }
461
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) {
463
464     fmi2_xml_model_description_t* md = context->modelDescription;
465     fmi2_xml_integer_type_props_t * props = 0;
466     const char* quantity = 0;
467
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);
471
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));
473
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)
477             )
478         return 0;
479     if(jm_vector_get_size(char)(bufQuantity))
480         quantity = jm_string_set_put(&md->typeDefinitions.quantities, jm_vector_get_itemp(char)(bufQuantity, 0));
481
482     props->quantity = quantity;
483
484     if(
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)
489             ) return 0;
490     return props;
491 }
492
493 int fmi2_xml_handle_Integer(fmi2_xml_parser_context_t *context, const char* data) {
494     if(!data) {
495         fmi2_xml_model_description_t* md = context->modelDescription;
496         jm_named_ptr named;
497         fmi2_xml_variable_typedef_t* type;
498         fmi2_xml_integer_type_props_t * props;
499
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);
503         type = named.ptr;
504         type->typeBase.baseType = fmi2_base_type_int;
505         type->typeBase.baseTypeStruct = &props->typeBase;
506     }
507     else {
508         /* don't do anything. might give out a warning if(data[0] != 0) */
509         return 0;
510     }
511     return 0;
512 }
513
514
515 int fmi2_xml_handle_Boolean(fmi2_xml_parser_context_t *context, const char* data) {
516     if(!data) {
517         fmi2_xml_model_description_t* md = context->modelDescription;
518         jm_named_ptr named;
519         fmi2_xml_variable_typedef_t* type;
520
521         named = jm_vector_get_last(jm_named_ptr)(&context->modelDescription->typeDefinitions.typeDefinitions);
522         type = named.ptr;
523         type->typeBase.baseType = fmi2_base_type_bool;
524         type->typeBase.baseTypeStruct = &md->typeDefinitions.defaultBooleanType;
525     }
526     else {
527         /* don't do anything. might give out a warning if(data[0] != 0) */
528         return 0;
529     }
530     return 0;
531 }
532
533 int fmi2_xml_handle_String(fmi2_xml_parser_context_t *context, const char* data) {
534     if(!data) {
535         fmi2_xml_model_description_t* md = context->modelDescription;
536         jm_named_ptr named;
537         fmi2_xml_variable_typedef_t* type;
538
539         named = jm_vector_get_last(jm_named_ptr)(&context->modelDescription->typeDefinitions.typeDefinitions);
540         type = named.ptr;
541         type->typeBase.baseType = fmi2_base_type_str;
542         type->typeBase.baseTypeStruct = &md->typeDefinitions.defaultStringType;
543     }
544     else {
545         /* don't do anything. might give out a warning if(data[0] != 0) */
546         return 0;
547     }
548     return 0;
549 }
550
551 int fmi2_xml_handle_Enumeration(fmi2_xml_parser_context_t *context, const char* data) {
552     if(!data) {
553         jm_named_ptr named;
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);
559
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)
569                 )
570             return -1;
571         if(jm_vector_get_size(char)(bufQuantity))
572             quantity = jm_string_set_put(&md->typeDefinitions.quantities, jm_vector_get_itemp(char)(bufQuantity, 0));
573
574         props->base.quantity = quantity;
575
576         named = jm_vector_get_last(jm_named_ptr)(&context->modelDescription->typeDefinitions.typeDefinitions);
577         type = named.ptr;
578         type->typeBase.baseType = fmi2_base_type_enum;
579         type->typeBase.baseTypeStruct = &props->base.typeBase;
580     }
581     else {
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);
595                         }
596                 }
597         return 0;
598     }
599     return 0;
600 }
601
602 int fmi2_xml_handle_Item(fmi2_xml_parser_context_t *context, const char* data) {
603     if(!data) {
604         {
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;
612             size_t descrlen;
613                         int value;
614
615             assert((enumProps->base.typeBase.structKind == fmi2_xml_type_struct_enu_props) 
616                                 && (enumProps->base.typeBase.baseType == fmi2_base_type_enum));
617
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)
625                     )
626                 return -1;
627             descrlen = jm_vector_get_size(char)(bufDescr);
628             named.ptr = 0;
629                         named.name = 0;
630             pnamed = jm_vector_push_back(jm_named_ptr)(&enumProps->enumItems, named);
631
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);
633             item = named.ptr;
634             if( !pnamed || !item ) {
635                 fmi2_xml_parse_fatal(context, "Could not allocate memory");
636                 return -1;
637             }
638             item->itemName = named.name;
639                         item->value = value;
640             if(descrlen)
641                 memcpy(item->itemDesciption,jm_vector_get_itemp(char)(bufDescr,0), descrlen);
642             item->itemDesciption[descrlen] = 0;
643         }
644     }
645     else {
646         /* don't do anything. might give out a warning if(data[0] != 0) */
647         return 0;
648     }
649     return 0;
650 }
651
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);
660     if(!found) {
661         jm_log_error(context->callbacks, module, "Declared type %s not found in type definitions. Ignoring.", key.name);
662         return defaultType;
663     }
664     else  {
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);
668             return defaultType;
669         }
670         return retType;
671     }
672 }