]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/native/FMILibrary/src/XML/src/FMI1/fmi1_xml_type.c
Merge remote-tracking branch 'origin/master' into release/1.35.1
[simantics/fmil.git] / org.simantics.fmil.core / native / FMILibrary / src / XML / src / FMI1 / fmi1_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
20 #include "fmi1_xml_model_description_impl.h"
21 #include "fmi1_xml_type_impl.h"
22 #include "fmi1_xml_unit_impl.h"
23 #include "fmi1_xml_parser.h"
24
25 static const char* module = "FMI1XML";
26
27 fmi1_xml_display_unit_t* fmi1_xml_get_type_display_unit(fmi1_xml_real_typedef_t* t) {
28     fmi1_xml_variable_typedef_t* vt = (void*)t;
29     fmi1_xml_real_type_props_t * props = (fmi1_xml_real_type_props_t*)vt->typeBase.baseTypeStruct;
30     fmi1_xml_display_unit_t* du = props->displayUnit;
31     if(du->displayUnit) return du;
32     return 0;
33 }
34
35 size_t fmi1_xml_get_type_definition_number(fmi1_xml_type_definitions_t* td) {
36     return jm_vector_get_size(jm_named_ptr)(&td->typeDefinitions);
37 }
38
39 fmi1_xml_variable_typedef_t* fmi1_xml_get_typedef(fmi1_xml_type_definitions_t* td, unsigned int  index) {
40     if(index >= fmi1_xml_get_type_definition_number(td)) return 0;
41     return (fmi1_xml_variable_typedef_t*)jm_vector_get_item(jm_named_ptr)(&td->typeDefinitions, index).ptr;
42 }
43
44 const char* fmi1_xml_get_type_name(fmi1_xml_variable_typedef_t* t) {   
45     return t->typeName;
46 }
47
48 const char* fmi1_xml_get_type_description(fmi1_xml_variable_typedef_t* t) {
49         const char * ret = t->description;
50     return (ret ? ret : "");
51 }
52
53 fmi1_base_type_enu_t fmi1_xml_get_base_type(fmi1_xml_variable_typedef_t* t) {
54     return t->typeBase.baseType;
55 }
56
57 fmi1_xml_real_typedef_t* fmi1_xml_get_type_as_real(fmi1_xml_variable_typedef_t* t) {
58     if(fmi1_xml_get_base_type(t) == fmi1_base_type_real) return (fmi1_xml_real_typedef_t*)t;
59     return 0;
60 }
61 fmi1_xml_integer_typedef_t* fmi1_xml_get_type_as_int(fmi1_xml_variable_typedef_t* t) {
62     if(fmi1_xml_get_base_type(t) == fmi1_base_type_int) return (fmi1_xml_integer_typedef_t*)t;
63     return 0;
64 }
65
66 fmi1_xml_enumeration_typedef_t* fmi1_xml_get_type_as_enum(fmi1_xml_variable_typedef_t* t) {
67     if(fmi1_xml_get_base_type(t) == fmi1_base_type_enum) return (fmi1_xml_enumeration_typedef_t*)t;
68     return 0;
69 }
70
71 /* Note that 0-pointer is returned for strings and booleans, empty string quantity if not defined*/
72 const char* fmi1_xml_get_type_quantity(fmi1_xml_variable_typedef_t* t) {
73     fmi1_xml_variable_type_base_t* props = t->typeBase.baseTypeStruct;
74         const char * ret;
75     if(props->structKind != fmi1_xml_type_struct_enu_props) return 0;
76     switch(props->baseType) {
77     case fmi1_base_type_real:
78         ret = ((fmi1_xml_real_type_props_t*)props)->quantity;
79                 break;
80     case fmi1_base_type_int:
81         ret = ((fmi1_xml_integer_type_props_t*)props)->quantity;
82                 break;
83     case fmi1_base_type_bool:
84         return 0;
85     case fmi1_base_type_str:
86         return 0;
87     case fmi1_base_type_enum:
88         ret = ((fmi1_xml_enum_type_props_t*)props)->quantity;
89                 break;
90     default:
91         return 0;
92     }
93         return (ret ? ret : 0);
94 }
95
96 double fmi1_xml_get_real_type_min(fmi1_xml_real_typedef_t* t) {
97     fmi1_xml_variable_typedef_t* vt = (void*)t;
98     fmi1_xml_real_type_props_t* props = (fmi1_xml_real_type_props_t*)(vt->typeBase.baseTypeStruct);
99     return props->typeMin;
100 }
101
102 double fmi1_xml_get_real_type_max(fmi1_xml_real_typedef_t* t) {
103     fmi1_xml_variable_typedef_t* vt = (void*)t;
104     fmi1_xml_real_type_props_t* props = (fmi1_xml_real_type_props_t*)(vt->typeBase.baseTypeStruct);
105     return props->typeMax;
106 }
107
108 double fmi1_xml_get_real_type_nominal(fmi1_xml_real_typedef_t* t) {
109     fmi1_xml_variable_typedef_t* vt = (void*)t;
110     fmi1_xml_real_type_props_t* props = (fmi1_xml_real_type_props_t*)(vt->typeBase.baseTypeStruct);
111     return props->typeNominal;
112 }
113
114 fmi1_xml_unit_t* fmi1_xml_get_real_type_unit(fmi1_xml_real_typedef_t* t) {    
115     fmi1_xml_variable_typedef_t* vt = (void*)t;
116     fmi1_xml_real_type_props_t* props = (fmi1_xml_real_type_props_t*)(vt->typeBase.baseTypeStruct);
117     fmi1_xml_display_unit_t* du = props->displayUnit;
118     if(du) return du->baseUnit;
119     return 0;
120 }
121
122 int fmi1_xml_get_real_type_is_relative_quantity(fmi1_xml_real_typedef_t* t) {
123     fmi1_xml_variable_typedef_t* vt = (void*)t;
124     fmi1_xml_real_type_props_t* props = (fmi1_xml_real_type_props_t*)(vt->typeBase.baseTypeStruct);
125     return props->typeBase.relativeQuantity;
126 }
127
128 fmi1_integer_t fmi1_xml_get_integer_type_min(fmi1_xml_integer_typedef_t* t) {
129     fmi1_xml_variable_typedef_t* vt = (void*)t;
130     fmi1_xml_integer_type_props_t* props = (fmi1_xml_integer_type_props_t*)(vt->typeBase.baseTypeStruct);
131     return props->typeMin;
132 }
133
134 fmi1_integer_t fmi1_xml_get_integer_type_max(fmi1_xml_integer_typedef_t* t){
135     fmi1_xml_variable_typedef_t* vt = (void*)t;
136     fmi1_xml_integer_type_props_t* props = (fmi1_xml_integer_type_props_t*)(vt->typeBase.baseTypeStruct);
137     return props->typeMax;
138 }
139
140 int fmi1_xml_get_enum_type_min(fmi1_xml_enumeration_typedef_t* t){
141     fmi1_xml_variable_typedef_t* vt = (void*)t;
142     fmi1_xml_enum_type_props_t* props = (fmi1_xml_enum_type_props_t*)(vt->typeBase.baseTypeStruct);
143     return props->typeMin;
144 }
145
146 int fmi1_xml_get_enum_type_max(fmi1_xml_enumeration_typedef_t* t){
147     fmi1_xml_variable_typedef_t* vt = (void*)t;
148     fmi1_xml_enum_type_props_t* props = (fmi1_xml_enum_type_props_t*)(vt->typeBase.baseTypeStruct);
149     return props->typeMax;
150 }
151
152 unsigned int  fmi1_xml_get_enum_type_size(fmi1_xml_enumeration_typedef_t* t) {
153     fmi1_xml_variable_typedef_t* vt = (void*)t;
154     fmi1_xml_enum_type_props_t* props = (fmi1_xml_enum_type_props_t*)(vt->typeBase.baseTypeStruct);
155     return (unsigned int)jm_vector_get_size(jm_named_ptr)(&props->enumItems);
156 }
157
158 const char* fmi1_xml_get_enum_type_item_name(fmi1_xml_enumeration_typedef_t* t, unsigned int  item) {
159     fmi1_xml_variable_typedef_t* vt = (fmi1_xml_variable_typedef_t*)(void*)t;
160     fmi1_xml_enum_type_props_t* props = (fmi1_xml_enum_type_props_t*)(vt->typeBase.baseTypeStruct);
161     if((item == 0) || (item > fmi1_xml_get_enum_type_size(t) )) return  0;
162     return jm_vector_get_item(jm_named_ptr)(&props->enumItems,item-1).name;
163 }
164
165 const char* fmi1_xml_get_enum_type_item_description(fmi1_xml_enumeration_typedef_t* t, unsigned int  item){
166     fmi1_xml_variable_typedef_t* vt = (void*)t;
167     fmi1_xml_enum_type_props_t* props = (fmi1_xml_enum_type_props_t*)(vt->typeBase.baseTypeStruct);
168     fmi1_xml_enum_type_item_t* e;
169     if((item == 0) || (item > fmi1_xml_get_enum_type_size(t) )) return  0;
170     e = jm_vector_get_item(jm_named_ptr)(&props->enumItems,item-1).ptr;
171     return e->itemDesciption;
172 }
173
174 void fmi1_xml_init_variable_type_base(fmi1_xml_variable_type_base_t* type, fmi1_xml_type_struct_kind_enu_t kind, fmi1_base_type_enu_t baseType) {
175     type->baseTypeStruct = 0;
176     type->next = 0;
177     type->structKind = kind;
178     type->baseType = baseType;
179     type->relativeQuantity = 0;
180     type->isFixed = 0;
181 }
182
183 void fmi1_xml_init_real_type_properties(fmi1_xml_real_type_props_t* type) {
184     fmi1_xml_init_variable_type_base(&type->typeBase, fmi1_xml_type_struct_enu_props,fmi1_base_type_real);
185     type->quantity = 0;    
186     type->typeMin = -DBL_MAX;
187     type->typeMax = DBL_MAX;
188     type->typeNominal = 1.0;
189     type->displayUnit = 0;
190 }
191
192 void fmi1_xml_init_integer_type_properties(fmi1_xml_integer_type_props_t* type) {
193     fmi1_xml_init_variable_type_base(&type->typeBase, fmi1_xml_type_struct_enu_props,fmi1_base_type_int);
194     type->quantity = 0;
195     type->typeMin = INT_MIN;
196     type->typeMax = INT_MAX;
197 }
198
199 void fmi1_xml_init_enumeration_type_properties(fmi1_xml_enum_type_props_t* type, jm_callbacks* cb) {
200     fmi1_xml_init_variable_type_base(&type->typeBase, fmi1_xml_type_struct_enu_props,fmi1_base_type_enum);
201     type->quantity = 0;
202     type->typeMin = 0;
203     type->typeMax = INT_MAX;
204     jm_vector_init(jm_named_ptr)(&type->enumItems,0,cb);
205 }
206
207 void fmi1_xml_free_enumeration_type_props(fmi1_xml_enum_type_props_t* type) {
208     jm_named_vector_free_data(&type->enumItems);
209 }
210
211
212 void fmi1_xml_init_type_definitions(fmi1_xml_type_definitions_t* td, jm_callbacks* cb) {
213     jm_vector_init(jm_named_ptr)(&td->typeDefinitions,0,cb);
214
215     jm_vector_init(jm_string)(&td->quantities, 0, cb);
216
217     fmi1_xml_init_real_type_properties(&td->defaultRealType);
218     td->defaultRealType.typeBase.structKind = fmi1_xml_type_struct_enu_base;
219     fmi1_xml_init_enumeration_type_properties(&td->defaultEnumType,cb);
220     td->defaultEnumType.typeBase.structKind = fmi1_xml_type_struct_enu_base;
221     fmi1_xml_init_integer_type_properties(&td->defaultIntegerType);
222     td->defaultIntegerType.typeBase.structKind = fmi1_xml_type_struct_enu_base;
223
224     fmi1_xml_init_variable_type_base(&td->defaultBooleanType, fmi1_xml_type_struct_enu_base,fmi1_base_type_bool);
225     fmi1_xml_init_variable_type_base(&td->defaultStringType, fmi1_xml_type_struct_enu_base,fmi1_base_type_str);
226
227     td->typePropsList = 0;
228 }
229
230 void fmi1_xml_free_type_definitions_data(fmi1_xml_type_definitions_t* td) {
231     jm_callbacks* cb = td->typeDefinitions.callbacks;
232
233     jm_vector_foreach(jm_string)(&td->quantities,(void(*)(const char*))cb->free);
234     jm_vector_free_data(jm_string)(&td->quantities);
235
236     {
237         fmi1_xml_variable_type_base_t* next;
238         fmi1_xml_variable_type_base_t* cur = td->typePropsList;
239         while(cur) {
240             next = cur->next;
241             if((cur->baseType == fmi1_base_type_enum) && (cur->structKind == fmi1_xml_type_struct_enu_props)) {
242                 fmi1_xml_enum_type_props_t* props = (fmi1_xml_enum_type_props_t*)cur;
243                 fmi1_xml_free_enumeration_type_props(props);
244             }
245             cb->free(cur);
246             cur = next;
247         }
248                 td->typePropsList = 0;
249     }
250
251     jm_named_vector_free_data(&td->typeDefinitions);
252 }
253
254 int fmi1_xml_handle_TypeDefinitions(fmi1_xml_parser_context_t *context, const char* data) {
255     if(!data) {
256                 jm_log_verbose(context->callbacks, module, "Parsing XML element TypeDefinitions");
257     }
258     else {
259         fmi1_xml_type_definitions_t* defs =  &context->modelDescription->typeDefinitions;
260
261         jm_vector_qsort(jm_named_ptr)(&defs->typeDefinitions, jm_compare_named);
262         /* might give out a warning if(data[0] != 0) */
263         return 0;
264     }
265     return 0;
266 }
267
268 int fmi1_xml_handle_Type(fmi1_xml_parser_context_t *context, const char* data) {
269     if(!data) {
270             fmi1_xml_model_description_t* md = context->modelDescription;
271             fmi1_xml_type_definitions_t* td = &md->typeDefinitions;
272             jm_named_ptr named, *pnamed;
273             jm_vector(char)* bufName = fmi1_xml_reserve_parse_buffer(context,1,100);
274             jm_vector(char)* bufDescr = fmi1_xml_reserve_parse_buffer(context,2,100);
275
276             if(!bufName || !bufDescr) return -1;
277             if(
278             /*  <xs:attribute name="name" type="xs:normalizedString" use="required"/> */
279                 fmi1_xml_set_attr_string(context, fmi1_xml_elmID_Type, fmi_attr_id_name, 1, bufName) ||
280             /* <xs:attribute name="description" type="xs:string"/> */
281                 fmi1_xml_set_attr_string(context, fmi1_xml_elmID_Type, fmi_attr_id_description, 0, bufDescr)
282                     ) return -1;
283             named.ptr = 0;
284                         named.name = 0;
285             pnamed = jm_vector_push_back(jm_named_ptr)(&td->typeDefinitions,named);
286             if(pnamed) {
287                 fmi1_xml_variable_typedef_t dummy;
288                 *pnamed = named = jm_named_alloc_v(bufName, sizeof(fmi1_xml_variable_typedef_t), dummy.typeName - (char*)&dummy,  context->callbacks);
289             }
290             if(!pnamed || !named.ptr) {
291                 fmi1_xml_parse_fatal(context, "Could not allocate memory");
292                 return -1;
293             }
294             else {
295                 fmi1_xml_variable_typedef_t* type = named.ptr;
296                 fmi1_xml_init_variable_type_base(&type->typeBase,fmi1_xml_type_struct_enu_typedef,fmi1_base_type_real);
297                 if(jm_vector_get_size(char)(bufDescr)) {
298                     const char* description = jm_string_set_put(&md->descriptions, jm_vector_get_itemp(char)(bufDescr,0));
299                     type->description = description;
300                 }
301                 else type->description = "";
302             }
303     }
304     else {
305         jm_named_ptr named = jm_vector_get_last(jm_named_ptr)(&(context->modelDescription->typeDefinitions.typeDefinitions));
306         fmi1_xml_variable_typedef_t* type = named.ptr;
307         if(type->typeBase.baseTypeStruct == 0) {
308             fmi1_xml_parse_fatal(context, "No specific type given for type definition %s", type->typeName);
309             return -1;
310         }
311         /* might give out a warning if(data[0] != 0) */
312         return 0;
313     }
314     return 0;
315 }
316
317 int fmi1_check_last_elem_is_specific_type(fmi1_xml_parser_context_t *context) {
318     if (
319                 (context->lastElmID == fmi1_xml_elmID_RealType)  ||
320                 (context->lastElmID == fmi1_xml_elmID_IntegerType)  ||
321                 (context->lastElmID == fmi1_xml_elmID_BooleanType)  ||
322                 (context->lastElmID == fmi1_xml_elmID_StringType)  ||
323                 (context->lastElmID == fmi1_xml_elmID_EnumerationType)
324                 ) {
325         fmi1_xml_parse_fatal(context, "Multiple definitions for a type are not allowed");
326         return -1;
327     }
328     return 0;
329 }
330
331 fmi1_xml_variable_type_base_t* fmi1_xml_alloc_variable_type_props(fmi1_xml_type_definitions_t* td, fmi1_xml_variable_type_base_t* base, size_t typeSize) {
332     jm_callbacks* cb = td->typeDefinitions.callbacks;
333     fmi1_xml_variable_type_base_t* type = cb->malloc(typeSize);
334     if(!type) return 0;
335     fmi1_xml_init_variable_type_base(type,fmi1_xml_type_struct_enu_props,base->baseType);
336     type->baseTypeStruct = base;
337     type->next = td->typePropsList;
338     td->typePropsList = type;
339     return type;
340 }
341
342 fmi1_xml_variable_type_base_t* fmi1_xml_alloc_variable_type_start(fmi1_xml_type_definitions_t* td,fmi1_xml_variable_type_base_t* base, size_t typeSize) {
343     jm_callbacks* cb = td->typeDefinitions.callbacks;
344     fmi1_xml_variable_type_base_t* type = cb->malloc(typeSize);
345     if(!type) return 0;
346     fmi1_xml_init_variable_type_base(type,fmi1_xml_type_struct_enu_start,base->baseType);
347     type->baseTypeStruct = base;
348     type->next = td->typePropsList;
349     td->typePropsList = type;
350     return type;
351 }
352
353
354 fmi1_xml_real_type_props_t* fmi1_xml_parse_real_type_properties(fmi1_xml_parser_context_t* context, fmi1_xml_elm_enu_t elmID) {
355     jm_named_ptr named, *pnamed;
356     fmi1_xml_model_description_t* md = context->modelDescription;
357     fmi1_xml_real_type_props_t* props;
358     const char* quantity = 0;
359     int boolBuf;
360
361 /*        jm_vector(char)* bufName = fmi_get_parse_buffer(context,1);
362     jm_vector(char)* bufDescr = fmi_get_parse_buffer(context,2); */
363     jm_vector(char)* bufQuantity = fmi1_xml_reserve_parse_buffer(context,3,100);
364     jm_vector(char)* bufUnit = fmi1_xml_reserve_parse_buffer(context,4,100);
365     jm_vector(char)* bufDispUnit = fmi1_xml_reserve_parse_buffer(context,5,100);
366
367     props = (fmi1_xml_real_type_props_t*)fmi1_xml_alloc_variable_type_props(&md->typeDefinitions, &md->typeDefinitions.defaultRealType.typeBase, sizeof(fmi1_xml_real_type_props_t));
368
369     if(!bufQuantity || !bufUnit || !bufDispUnit || !props ||
370             /* <xs:attribute name="quantity" type="xs:normalizedString"/> */
371             fmi1_xml_set_attr_string(context, elmID, fmi_attr_id_quantity, 0, bufQuantity) ||
372             /* <xs:attribute name="unit" type="xs:normalizedString"/>  */
373             fmi1_xml_set_attr_string(context, elmID, fmi_attr_id_unit, 0, bufUnit) ||
374             /* <xs:attribute name="displayUnit" type="xs:normalizedString">  */
375             fmi1_xml_set_attr_string(context, elmID, fmi_attr_id_displayUnit, 0, bufDispUnit)
376             ) {
377         fmi1_xml_parse_fatal(context, "Error parsing real type properties");
378         return 0;
379     }
380     if(jm_vector_get_size(char)(bufQuantity))
381         quantity = jm_string_set_put(&md->typeDefinitions.quantities, jm_vector_get_itemp(char)(bufQuantity, 0));
382
383     props->quantity = quantity;
384     props->displayUnit = 0;
385     if(jm_vector_get_size(char)(bufDispUnit)) {
386         named.name = jm_vector_get_itemp(char)(bufDispUnit, 0);
387         pnamed = jm_vector_bsearch(jm_named_ptr)(&(md->displayUnitDefinitions), &named, jm_compare_named);
388         if(!pnamed) {
389             fmi1_xml_parse_fatal(context, "Unknown display unit %s in real type definition", jm_vector_get_itemp(char)(bufDispUnit, 0));
390             return 0;
391         }
392         props->displayUnit = pnamed->ptr;
393     }
394     else {
395         if(jm_vector_get_size(char)(bufUnit)) {
396             props->displayUnit = fmi1_xml_get_parsed_unit(context, bufUnit, 1);
397         }
398     }
399     if(    /*    <xs:attribute name="relativeQuantity" type="xs:boolean" default="false"> */
400             fmi1_xml_set_attr_boolean(context, elmID, fmi_attr_id_relativeQuantity, 0, &boolBuf, 0) ||
401             /* <xs:attribute name="min" type="xs:double"/> */
402             fmi1_xml_set_attr_double(context, elmID, fmi_attr_id_min, 0, &props->typeMin, -DBL_MAX) ||
403             /* <xs:attribute name="max" type="xs:double"/> */
404             fmi1_xml_set_attr_double(context, elmID, fmi_attr_id_max, 0, &props->typeMax, DBL_MAX) ||
405             /*  <xs:attribute name="nominal" type="xs:double"/> */
406             fmi1_xml_set_attr_double(context, elmID, fmi_attr_id_nominal, 0, &props->typeNominal, 1)
407             ) return 0;
408     props->typeBase.relativeQuantity = boolBuf;
409     return props;
410 }
411
412 int fmi1_xml_handle_RealType(fmi1_xml_parser_context_t *context, const char* data) {
413     if(!data) {
414         fmi1_xml_model_description_t* md = context->modelDescription;
415         jm_named_ptr named;
416         fmi1_xml_variable_typedef_t* type;
417         fmi1_xml_real_type_props_t * props;
418         if(fmi1_check_last_elem_is_specific_type(context)) return -1;
419
420         props = fmi1_xml_parse_real_type_properties(context, fmi1_xml_elmID_RealType);
421         if(!props) return -1;
422         named = jm_vector_get_last(jm_named_ptr)(&md->typeDefinitions.typeDefinitions);
423         type = named.ptr;
424         type->typeBase.baseType = fmi1_base_type_real;
425         type->typeBase.baseTypeStruct = &props->typeBase;
426     }
427     else {
428         /* don't do anything. might give out a warning if(data[0] != 0) */
429         return 0;
430     }
431     return 0;
432 }
433
434 fmi1_xml_integer_type_props_t * fmi1_xml_parse_integer_type_properties(fmi1_xml_parser_context_t* context, fmi1_xml_elm_enu_t elmID) {
435
436     fmi1_xml_model_description_t* md = context->modelDescription;
437     fmi1_xml_integer_type_props_t * props = 0;
438     const char* quantity = 0;
439
440     /*        jm_vector(char)* bufName = fmi_get_parse_buffer(context,1);
441             jm_vector(char)* bufDescr = fmi_get_parse_buffer(context,2); */
442     jm_vector(char)* bufQuantity = fmi1_xml_reserve_parse_buffer(context,3,100);
443
444     props = (fmi1_xml_integer_type_props_t*)fmi1_xml_alloc_variable_type_props(&md->typeDefinitions, &md->typeDefinitions.defaultIntegerType.typeBase, sizeof(fmi1_xml_integer_type_props_t));
445
446     if(!bufQuantity || !props ||
447             /* <xs:attribute name="quantity" type="xs:normalizedString"/> */
448             fmi1_xml_set_attr_string(context, elmID, fmi_attr_id_quantity, 0, bufQuantity)
449             )
450         return 0;
451     if(jm_vector_get_size(char)(bufQuantity))
452         quantity = jm_string_set_put(&md->typeDefinitions.quantities, jm_vector_get_itemp(char)(bufQuantity, 0));
453
454     props->quantity = quantity;
455
456     if(
457             /* <xs:attribute name="min" type="xs:int"/> */
458             fmi1_xml_set_attr_int(context, elmID, fmi_attr_id_min, 0, &props->typeMin, INT_MIN) ||
459             /* <xs:attribute name="max" type="xs:int"/> */
460             fmi1_xml_set_attr_int(context, elmID, fmi_attr_id_max, 0, &props->typeMax, INT_MAX)
461             ) return 0;
462     return props;
463 }
464
465 int fmi1_xml_handle_IntegerType(fmi1_xml_parser_context_t *context, const char* data) {
466     if(!data) {
467         fmi1_xml_model_description_t* md = context->modelDescription;
468         jm_named_ptr named;
469         fmi1_xml_variable_typedef_t* type;
470         fmi1_xml_integer_type_props_t * props;
471         if(fmi1_check_last_elem_is_specific_type(context)) return -1;
472
473         props = fmi1_xml_parse_integer_type_properties(context, fmi1_xml_elmID_IntegerType);
474         if(!props) return -1;
475         named = jm_vector_get_last(jm_named_ptr)(&md->typeDefinitions.typeDefinitions);
476         type = named.ptr;
477         type->typeBase.baseType = fmi1_base_type_int;
478         type->typeBase.baseTypeStruct = &props->typeBase;
479     }
480     else {
481         /* don't do anything. might give out a warning if(data[0] != 0) */
482         return 0;
483     }
484     return 0;
485 }
486
487
488 int fmi1_xml_handle_BooleanType(fmi1_xml_parser_context_t *context, const char* data) {
489     if(!data) {
490         fmi1_xml_model_description_t* md = context->modelDescription;
491         jm_named_ptr named;
492         fmi1_xml_variable_typedef_t* type;
493         if(fmi1_check_last_elem_is_specific_type(context)) return -1;
494
495         named = jm_vector_get_last(jm_named_ptr)(&context->modelDescription->typeDefinitions.typeDefinitions);
496         type = named.ptr;
497         type->typeBase.baseType = fmi1_base_type_bool;
498         type->typeBase.baseTypeStruct = &md->typeDefinitions.defaultBooleanType;
499     }
500     else {
501         /* don't do anything. might give out a warning if(data[0] != 0) */
502         return 0;
503     }
504     return 0;
505 }
506
507 int fmi1_xml_handle_StringType(fmi1_xml_parser_context_t *context, const char* data) {
508     if(!data) {
509         fmi1_xml_model_description_t* md = context->modelDescription;
510         jm_named_ptr named;
511         fmi1_xml_variable_typedef_t* type;
512         if(fmi1_check_last_elem_is_specific_type(context)) return -1;
513
514         named = jm_vector_get_last(jm_named_ptr)(&context->modelDescription->typeDefinitions.typeDefinitions);
515         type = named.ptr;
516         type->typeBase.baseType = fmi1_base_type_str;
517         type->typeBase.baseTypeStruct = &md->typeDefinitions.defaultStringType;
518     }
519     else {
520         /* don't do anything. might give out a warning if(data[0] != 0) */
521         return 0;
522     }
523     return 0;
524 }
525
526 int fmi1_xml_handle_EnumerationType(fmi1_xml_parser_context_t *context, const char* data) {
527     if(!data) {
528         jm_named_ptr named;
529         fmi1_xml_model_description_t* md = context->modelDescription;
530         fmi1_xml_enum_type_props_t * props;
531         fmi1_xml_variable_typedef_t* type;
532         const char * quantity = 0;
533         /*        jm_vector(char)* bufName = fmi_get_parse_buffer(context,1);
534                 jm_vector(char)* bufDescr = fmi_get_parse_buffer(context,2); */
535         jm_vector(char)* bufQuantity = fmi1_xml_reserve_parse_buffer(context,3,100);
536
537         if(fmi1_check_last_elem_is_specific_type(context)) return -1;
538
539         props = (fmi1_xml_enum_type_props_t*)fmi1_xml_alloc_variable_type_props(&md->typeDefinitions, &md->typeDefinitions.defaultEnumType.typeBase, sizeof(fmi1_xml_enum_type_props_t));
540         if(props) jm_vector_init(jm_named_ptr)(&props->enumItems,0,context->callbacks);
541         if(!bufQuantity || !props ||
542                 /* <xs:attribute name="quantity" type="xs:normalizedString"/> */
543                 fmi1_xml_set_attr_string(context, fmi1_xml_elmID_IntegerType, fmi_attr_id_quantity, 0, bufQuantity)
544                 )
545             return -1;
546         if(jm_vector_get_size(char)(bufQuantity))
547             quantity = jm_string_set_put(&md->typeDefinitions.quantities, jm_vector_get_itemp(char)(bufQuantity, 0));
548
549         props->quantity = quantity;
550
551
552
553         if(
554                 /* <xs:attribute name="min" type="xs:int"/> */
555                 fmi1_xml_set_attr_int(context, fmi1_xml_elmID_EnumerationType, fmi_attr_id_min, 0,  &props->typeMin, 1) ||
556                 /* <xs:attribute name="max" type="xs:int"/> */
557                 fmi1_xml_set_attr_int(context, fmi1_xml_elmID_EnumerationType, fmi_attr_id_max, 0, &props->typeMax, INT_MAX)
558                 ) return -1;
559         named = jm_vector_get_last(jm_named_ptr)(&context->modelDescription->typeDefinitions.typeDefinitions);
560         type = named.ptr;
561         type->typeBase.baseType = fmi1_base_type_enum;
562         type->typeBase.baseTypeStruct = &props->typeBase;
563     }
564     else {
565         /* don't do anything. might give out a warning if(data[0] != 0) */
566         return 0;
567     }
568     return 0;
569 }
570
571 int fmi1_xml_handle_Item(fmi1_xml_parser_context_t *context, const char* data) {
572     if(!data) {
573         {
574             fmi1_xml_model_description_t* md = context->modelDescription;
575             jm_vector(char)* bufName = fmi1_xml_reserve_parse_buffer(context,1,100);
576             jm_vector(char)* bufDescr = fmi1_xml_reserve_parse_buffer(context,2,100);
577             /* this enum item belongs to the last created enum = head of typePropsList */
578             fmi1_xml_enum_type_props_t * enumProps = (fmi1_xml_enum_type_props_t*)md->typeDefinitions.typePropsList;
579             fmi1_xml_enum_type_item_t * item;
580             jm_named_ptr named, *pnamed;
581             size_t descrlen;
582
583             assert((enumProps->typeBase.structKind == fmi1_xml_type_struct_enu_props) && (enumProps->typeBase.baseType == fmi1_base_type_enum));
584
585             if(!bufName || !bufDescr ||
586             /*  <xs:attribute name="name" type="xs:normalizedString" use="required"/> */
587                 fmi1_xml_set_attr_string(context, fmi1_xml_elmID_Type, fmi_attr_id_name, 1, bufName) ||
588             /* <xs:attribute name="description" type="xs:string"/> */
589                 fmi1_xml_set_attr_string(context, fmi1_xml_elmID_Type, fmi_attr_id_description, 0, bufDescr)
590                     )
591                 return -1;
592             descrlen = jm_vector_get_size(char)(bufDescr);
593             named.ptr = 0;
594                         named.name = 0;
595             pnamed = jm_vector_push_back(jm_named_ptr)(&enumProps->enumItems, named);
596
597             if(pnamed) *pnamed = named = jm_named_alloc_v(bufName,sizeof(fmi1_xml_enum_type_item_t)+descrlen+1,sizeof(fmi1_xml_enum_type_item_t)+descrlen,context->callbacks);
598             item = named.ptr;
599             if( !pnamed || !item ) {
600                 fmi1_xml_parse_fatal(context, "Could not allocate memory");
601                 return -1;
602             }
603             item->itemName = named.name;
604             if(descrlen)
605                 memcpy(item->itemDesciption,jm_vector_get_itemp(char)(bufDescr,0), descrlen);
606             item->itemDesciption[descrlen] = 0;
607         }
608     }
609     else {
610         /* don't do anything. might give out a warning if(data[0] != 0) */
611         return 0;
612     }
613     return 0;
614 }
615
616 fmi1_xml_variable_type_base_t* fmi1_get_declared_type(fmi1_xml_parser_context_t *context, fmi1_xml_elm_enu_t elmID, fmi1_xml_variable_type_base_t* defaultType) {
617     jm_named_ptr key, *found;
618     jm_vector(char)* bufDeclaredType = fmi1_xml_reserve_parse_buffer(context,1, 100);
619     /*         <xs:attribute name="declaredType" type="xs:normalizedString"> */
620     fmi1_xml_set_attr_string(context, elmID, fmi_attr_id_declaredType, 0, bufDeclaredType);
621     if(! jm_vector_get_size(char)(bufDeclaredType) ) return defaultType;
622     key.name = jm_vector_get_itemp(char)(bufDeclaredType,0);
623     found = jm_vector_bsearch(jm_named_ptr)(&(context->modelDescription->typeDefinitions.typeDefinitions),&key, jm_compare_named);
624     if(!found) {
625         jm_log_error(context->callbacks, module, "Declared type %s not found in type definitions. Ignoring.", key.name);
626         return defaultType;
627     }
628     else  {
629         fmi1_xml_variable_type_base_t* retType = found->ptr;
630         if(retType->baseType != defaultType->baseType) {
631             jm_log_error(context->callbacks, module, "Declared type %s does not match variable type. Ignoring.", key.name);
632             return defaultType;
633         }
634         return retType;
635     }
636 }