]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/native/FMILibrary/src/XML/src/FMI2/fmi2_xml_unit.c
Add FMILibrary-2.0.3 to org.simantics.fmil.core\native.
[simantics/fmil.git] / org.simantics.fmil.core / native / FMILibrary / src / XML / src / FMI2 / fmi2_xml_unit.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 "fmi2_xml_model_description_impl.h"
17 #include "fmi2_xml_unit_impl.h"
18
19 static const char* module = "FMI2XML";
20
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;
24 }
25
26 const char* fmi2_xml_get_unit_name(fmi2_xml_unit_t* u) {
27     return u->baseUnit;
28 }
29
30 /**
31         \brief Get fmi2_SI_base_units_Num SI base units exponents associated with the unit.
32 */
33 const int* fmi2_xml_get_SI_unit_exponents(fmi2_xml_unit_t* u) {
34         return u->SI_base_unit_exp;
35 }
36
37 /**
38         \brief Get factor to the corresponding SI base units.
39 */
40 double fmi2_xml_get_SI_unit_factor(fmi2_xml_unit_t* u){
41         return u->factor;
42 }
43
44
45 /**
46         \brief Get offset to the corresponding SI base units.
47 */
48 double fmi2_xml_get_SI_unit_offset(fmi2_xml_unit_t* u) {
49         return u->offset;
50 }
51
52 /**
53         \brief Convert a value with respect to the unit to the
54         value with respect to the SI base unit.
55 */
56 double fmi2_xml_convert_to_SI_base_unit(double uv, fmi2_xml_unit_t* u) {
57         return u->factor * uv + u->offset;
58 }
59
60 /**
61         \brief Convert a value with respect to the SI base unit to the
62         value with respect to the unit.
63 */
64 double fmi2_xml_convert_from_SI_base_unit(double SIv, fmi2_xml_unit_t* u) {
65         return (SIv - u->offset)/u->factor;
66 }
67
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);
70 }
71
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);
75 }
76
77
78 fmi2_xml_unit_t* fmi2_xml_get_base_unit(fmi2_xml_display_unit_t* du) {
79     return du->baseUnit;
80 }
81
82 const char* fmi2_xml_get_display_unit_name(fmi2_xml_display_unit_t* du) {
83     return du->displayUnit;
84 }
85
86 double fmi2_xml_get_display_unit_factor(fmi2_xml_display_unit_t* du) {
87     return du->factor;
88 }
89
90 double fmi2_xml_get_display_unit_offset(fmi2_xml_display_unit_t* du) {
91     return du->offset;
92 }
93
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)
98         return val *gain;
99     else
100         return (val*gain + offset);
101 }
102
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)
107         return val/factor;
108     else
109         return (val - offset)/factor;
110 }
111
112 int fmi2_xml_handle_UnitDefinitions(fmi2_xml_parser_context_t *context, const char* data) {
113     fmi2_xml_model_description_t* md = context->modelDescription;
114     if(!data) {
115                 jm_log_verbose(context->callbacks, module, "Parsing XML element UnitDefinitions");
116         }
117     else {
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) */
121     }
122     return 0;
123 }
124
125
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;
130         int i;
131         if(jm_vector_get_size(char)(name))
132                 named.name = jm_vector_get_itemp(char)(name,0);
133         else
134                 named.name = "";
135
136         if(sorted)
137         pnamed = jm_vector_bsearch(jm_named_ptr)(&(md->unitDefinitions), &named,jm_compare_named);
138     else
139         pnamed = jm_vector_find(jm_named_ptr)(&(md->unitDefinitions), &named,jm_compare_named);
140
141     if(pnamed) {
142         unit = pnamed->ptr;
143         return &unit->defaultDisplay;
144     }
145
146     named.ptr = 0;
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);
149
150     if(!pnamed || !named.ptr) {
151         fmi2_xml_parse_fatal(context, "Could not allocate memory");
152         return 0;
153     }
154
155     unit = named.ptr;
156         unit->factor = 1.0;
157         unit->offset = 0.0;
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);
165
166     if(sorted) jm_vector_qsort_jm_named_ptr(&(md->unitDefinitions), jm_compare_named);
167     return &unit->defaultDisplay;
168 }
169
170 int fmi2_xml_handle_BaseUnit(fmi2_xml_parser_context_t *context, const char* data) {
171     if(!data) {
172                         int ret;
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;
176
177             /* process the attributes */
178
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) ||
182                         ret =           
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);
188
189                         if(unit->factor == 0) {
190                                 unit->factor = 1.0;
191                                 if(!ret) {
192                                         fmi2_xml_parse_error(context, "Attribute 'factor' cannot be equal to zero");
193                                 }
194                         }
195
196             return ( ret );
197     }
198     else {
199         /* don't do anything. might give out a warning if(data[0] != 0) */
200         return 0;
201     }
202     return 0;
203 }
204
205
206
207 int fmi2_xml_handle_Unit(fmi2_xml_parser_context_t *context, const char* data) {
208     if(!data) {
209             fmi2_xml_display_unit_t* unit;
210             jm_vector(char)* buf = fmi2_xml_reserve_parse_buffer(context,1,100);
211
212             if(!buf) return -1;
213             if( 
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))
217                ) return -1;
218             context->lastBaseUnit = unit->baseUnit;
219     }
220     else {
221         /* don't do anything. might give out a warning if(data[0] != 0) */
222         return 0;
223     }
224     return 0;
225 }
226
227 int fmi2_xml_handle_DisplayUnit(fmi2_xml_parser_context_t *context, const char* data) {
228     if(!data) {
229                         int ret;
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;
237
238             if(!buf) return -1;
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);
242             if(ret) return ret;
243             /* alloc memory to the correct size and put display unit on the list for the base unit */
244             named.ptr = 0;
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");
251                 return -1;
252             }
253             dispUnit->baseUnit = unit;
254             /* finally process the attributes */
255                         ret =     
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;
262                                 if(!ret) {
263                                         fmi2_xml_parse_error(context, "Attribute 'factor' cannot be equal to zero");
264                                 }
265                         }
266
267             return ( ret );
268     }
269     else {
270         /* don't do anything. might give out a warning if(data[0] != 0) */
271         return 0;
272     }
273     return 0;
274 }
275