]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/native/FMILibrary/src/XML/src/FMI1/fmi1_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 / FMI1 / fmi1_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 "fmi1_xml_model_description_impl.h"
17 #include "fmi1_xml_unit_impl.h"
18
19 static const char* module = "FMI1XML";
20
21 fmi1_xml_unit_t* fmi1_xml_get_unit(fmi1_xml_unit_definitions_t* ud, unsigned int  index) {
22     if(index >= fmi1_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* fmi1_xml_get_unit_name(fmi1_xml_unit_t* u) {
27     return u->baseUnit;
28 }
29
30 unsigned int fmi1_xml_get_unit_display_unit_number(fmi1_xml_unit_t* u) {
31     return (unsigned int)jm_vector_get_size(jm_voidp)(&u->displayUnits);
32 }
33
34 fmi1_xml_display_unit_t* fmi1_xml_get_unit_display_unit(fmi1_xml_unit_t* u, size_t index) {
35     if(index >= fmi1_xml_get_unit_display_unit_number(u)) return 0;
36     return jm_vector_get_item(jm_voidp)(&u->displayUnits, index);
37 }
38
39
40 fmi1_xml_unit_t* fmi1_xml_get_base_unit(fmi1_xml_display_unit_t* du) {
41     return du->baseUnit;
42 }
43
44 const char* fmi1_xml_get_display_unit_name(fmi1_xml_display_unit_t* du) {
45     return du->displayUnit;
46 }
47
48 double fmi1_xml_get_display_unit_gain(fmi1_xml_display_unit_t* du) {
49     return du->gain;
50 }
51
52 double fmi1_xml_get_display_unit_offset(fmi1_xml_display_unit_t* du) {
53     return du->offset;
54 }
55
56 double fmi1_xml_convert_to_display_unit(double val , fmi1_xml_display_unit_t* du, int isRelativeQuantity) {
57     double gain = fmi1_xml_get_display_unit_gain(du);
58     double offset = fmi1_xml_get_display_unit_offset(du);
59     if(isRelativeQuantity)
60         return val *gain;
61     else
62         return (val*gain + offset);
63 }
64
65 double fmi1_xml_convert_from_display_unit(double val, fmi1_xml_display_unit_t* du, int isRelativeQuantity) {
66     double gain = fmi1_xml_get_display_unit_gain(du);
67     double offset = fmi1_xml_get_display_unit_offset(du);
68     if(isRelativeQuantity)
69         return val/gain;
70     else
71         return (val - offset)/gain;
72 }
73
74 int fmi1_xml_handle_UnitDefinitions(fmi1_xml_parser_context_t *context, const char* data) {
75     fmi1_xml_model_description_t* md = context->modelDescription;
76     if(!data) {
77                 jm_log_verbose(context->callbacks, module, "Parsing XML element UnitDefinitions");
78         }
79     else {
80         jm_vector_qsort(jm_named_ptr)(&(md->unitDefinitions),jm_compare_named);
81         jm_vector_qsort(jm_named_ptr)(&(md->displayUnitDefinitions),jm_compare_named);
82         /* might give out a warning if(data[0] != 0) */
83     }
84     return 0;
85 }
86
87
88 fmi1_xml_display_unit_t* fmi1_xml_get_parsed_unit(fmi1_xml_parser_context_t *context, jm_vector(char)* name, int sorted) {
89     fmi1_xml_unit_t dummy, *unit;
90     jm_named_ptr named, *pnamed;
91     fmi1_xml_model_description_t* md = context->modelDescription;
92
93         if(jm_vector_get_size(char)(name))
94                 named.name = jm_vector_get_itemp(char)(name,0);
95         else
96                 named.name = "";
97     if(sorted)
98         pnamed = jm_vector_bsearch(jm_named_ptr)(&(md->unitDefinitions), &named,jm_compare_named);
99     else
100         pnamed = jm_vector_find(jm_named_ptr)(&(md->unitDefinitions), &named,jm_compare_named);
101
102     if(pnamed) {
103         unit = pnamed->ptr;
104         return &unit->defaultDisplay;
105     }
106
107     named.ptr = 0;
108     pnamed = jm_vector_push_back(jm_named_ptr)(&(md->unitDefinitions),named);
109     if(pnamed) *pnamed = named = jm_named_alloc_v(name,sizeof(fmi1_xml_unit_t),dummy.baseUnit - (char*)&dummy,context->callbacks);
110
111     if(!pnamed || !named.ptr) {
112         fmi1_xml_parse_fatal(context, "Could not allocate memory");
113         return 0;
114     }
115
116     unit = named.ptr;
117     unit->defaultDisplay.baseUnit = unit;
118     unit->defaultDisplay.offset = 0;
119     unit->defaultDisplay.gain = 1.0;
120     unit->defaultDisplay.displayUnit[0] = 0;
121     jm_vector_init(jm_voidp)(&(unit->displayUnits),0,context->callbacks);
122
123     if(sorted) jm_vector_qsort_jm_named_ptr(&(md->unitDefinitions), jm_compare_named);
124     return &unit->defaultDisplay;
125 }
126
127 int fmi1_xml_handle_BaseUnit(fmi1_xml_parser_context_t *context, const char* data) {
128     if(!data) {
129             fmi1_xml_display_unit_t* unit;
130             jm_vector(char)* buf = fmi1_xml_reserve_parse_buffer(context,1,100);
131
132             if(!buf) return -1;
133             if( /*  <xs:attribute name="unit" type="xs:normalizedString" use="required"/> */
134                 fmi1_xml_set_attr_string(context, fmi1_xml_elmID_BaseUnit, fmi_attr_id_unit, 1, buf) ||
135                 !(unit = fmi1_xml_get_parsed_unit(context, buf, 0))
136                ) return -1;
137             context->lastBaseUnit = unit->baseUnit;
138     }
139     else {
140         /* don't do anything. might give out a warning if(data[0] != 0) */
141         return 0;
142     }
143     return 0;
144 }
145
146 int fmi1_xml_handle_DisplayUnitDefinition(fmi1_xml_parser_context_t *context, const char* data) {
147     if(!data) {
148             fmi1_xml_model_description_t* md = context->modelDescription;
149             jm_vector(char)* buf = fmi1_xml_reserve_parse_buffer(context,1,100);
150             /* this display unit belongs to the last created base unit */
151             fmi1_xml_unit_t* unit = context->lastBaseUnit;
152             fmi1_xml_display_unit_t *dispUnit = 0;
153             fmi1_xml_display_unit_t dummyDU;
154             jm_named_ptr named, *pnamed;
155             int ret;
156
157             if(!buf) return -1;
158             /* first read the required name attribute */
159             /*  <xs:attribute name="displayUnit" type="xs:normalizedString" use="required"/> */
160             ret = fmi1_xml_set_attr_string(context, fmi1_xml_elmID_DisplayUnitDefinition, fmi_attr_id_displayUnit, 1, buf);
161             if(ret) return ret;
162             /* alloc memory to the correct size and put display unit on the list for the base unit */
163             named.ptr = 0;
164             pnamed = jm_vector_push_back(jm_named_ptr)(&(md->displayUnitDefinitions),named);
165             if(pnamed) *pnamed = jm_named_alloc(jm_vector_get_itemp_char(buf,0),sizeof(fmi1_xml_display_unit_t), dummyDU.displayUnit - (char*)&dummyDU,context->callbacks);
166             dispUnit = pnamed->ptr;
167             if( !pnamed || !dispUnit ||
168                 !jm_vector_push_back(jm_voidp)(&unit->displayUnits, dispUnit) ) {
169                 fmi1_xml_parse_fatal(context, "Could not allocate memory");
170                 return -1;
171             }
172             dispUnit->baseUnit = unit;
173             /* finally process the attributes */
174             return (
175                         /*  <xs:attribute name="gain" type="xs:double" default="1"/>  */
176                         fmi1_xml_set_attr_double(context, fmi1_xml_elmID_DisplayUnitDefinition, fmi_attr_id_gain, 0, &dispUnit->gain, 1)  ||
177                          /*  <xs:attribute name="offset" type="xs:double" default="0"/>  */
178                         fmi1_xml_set_attr_double(context, fmi1_xml_elmID_DisplayUnitDefinition, fmi_attr_id_offset, 0, &dispUnit->offset, 0)
179                      );
180     }
181     else {
182         /* don't do anything. might give out a warning if(data[0] != 0) */
183         return 0;
184     }
185     return 0;
186 }
187