]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/native/FMILibrary/src/Import/src/FMI2/fmi2_import.c
Switch to full JavaSE-11+ compatibility
[simantics/fmil.git] / org.simantics.fmil.core / native / FMILibrary / src / Import / src / FMI2 / fmi2_import.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 <stdio.h>
17 #include <stdarg.h>
18
19 #include <JM/jm_named_ptr.h>
20 #include <FMI2/fmi2_types.h>
21 #include <FMI2/fmi2_functions.h>
22 #include <FMI2/fmi2_enums.h>\r
23 #include <FMI2/fmi2_capi.h>
24
25 #include "fmi2_import_impl.h"
26 #include "fmi2_import_variable_list_impl.h"
27
28
29 static const char* module = "FMILIB";
30
31 /*#include "fmi2_import_vendor_annotations_impl.h"
32 #include "fmi2_import_parser.h"
33 */
34 fmi2_import_t* fmi2_import_allocate(jm_callbacks* cb) {
35         fmi2_import_t* fmu = (fmi2_import_t*)cb->calloc(1, sizeof(fmi2_import_t));
36
37         if(!fmu || (jm_vector_init(char)(&fmu->logMessageBufferCoded,JM_MAX_ERROR_MESSAGE_SIZE,cb) < JM_MAX_ERROR_MESSAGE_SIZE)) {
38                 jm_log_fatal(cb, module, "Could not allocate memory");
39         if(fmu) cb->free(fmu);
40                 return 0;
41         }
42         fmu->dirPath = 0;
43         fmu->resourceLocation = 0;
44         fmu->callbacks = cb;
45         fmu->capi = 0;
46         fmu->md = fmi2_xml_allocate_model_description(cb);
47         jm_vector_init(char)(&fmu->logMessageBufferExpanded,0,cb);
48
49         if(!fmu->md) {
50                 cb->free(fmu);
51                 return 0;
52         }
53
54         return fmu;
55 }
56
57 const char* fmi2_import_get_last_error(fmi2_import_t* fmu) {\r
58         return jm_get_last_error(fmu->callbacks);\r
59 }\r
60
61 fmi2_import_t* fmi2_import_parse_xml( fmi_import_context_t* context, const char* dirPath, fmi2_xml_callbacks_t* xml_callbacks) {
62         char* xmlPath;
63         char absPath[FILENAME_MAX + 2];
64         fmi2_import_t* fmu = 0;
65     int configuration = 0;
66
67         if(strlen(dirPath) + 20 > FILENAME_MAX) {
68                 jm_log_fatal(context->callbacks, module, "Directory path for FMU is too long");
69                 return 0;
70         }
71
72         xmlPath =  fmi_import_get_model_description_path(dirPath, context->callbacks);
73         fmu = fmi2_import_allocate(context->callbacks);
74
75         if(!fmu) {
76                 context->callbacks->free(xmlPath);
77                 return 0;
78         }
79
80         if(jm_get_dir_abspath(context->callbacks, dirPath, absPath, FILENAME_MAX + 2)) {\r
81                 size_t len = strlen(absPath);\r
82                 strcpy(absPath + len, FMI_FILE_SEP "resources");\r
83                 fmu->resourceLocation = fmi_import_create_URL_from_abs_path(context->callbacks, absPath);\r
84         }
85         fmu->dirPath = context->callbacks->malloc(strlen(dirPath) + 1);
86         if (!fmu->dirPath ||  !fmu->resourceLocation) {
87                 jm_log_fatal( context->callbacks, "FMILIB", "Could not allocated memory");
88                 fmi2_import_free(fmu);
89                 context->callbacks->free(xmlPath);
90                 return 0;
91         }
92         strcpy(fmu->dirPath, dirPath);
93
94         jm_log_verbose( context->callbacks, "FMILIB", "Parsing model description XML");
95
96     /* convert the import configuration to the xml configuration */
97     if (context->configuration & FMI_IMPORT_NAME_CHECK) {
98         configuration |= FMI2_XML_NAME_CHECK;
99     }
100
101         if (fmi2_xml_parse_model_description( fmu->md, xmlPath, xml_callbacks, configuration)) {
102                 fmi2_import_free(fmu);
103                 fmu = 0;
104         }
105         context->callbacks->free(xmlPath);
106
107         if(fmu)
108                 jm_log_verbose( context->callbacks, "FMILIB", "Parsing finished successfully");
109
110         return fmu;
111 }
112
113 void fmi2_import_free(fmi2_import_t* fmu) {
114     jm_callbacks* cb;
115
116         if(!fmu) return;
117     cb = fmu->callbacks;
118         jm_log_verbose( fmu->callbacks, "FMILIB", "Releasing allocated library resources");     
119
120         fmi2_import_destroy_dllfmu(fmu);\r
121         fmi2_xml_free_model_description(fmu->md);
122         jm_vector_free_data(char)(&fmu->logMessageBufferCoded);
123         jm_vector_free_data(char)(&fmu->logMessageBufferExpanded);
124
125         cb->free(fmu->resourceLocation);
126         cb->free(fmu->dirPath);
127     cb->free(fmu);
128 }
129
130 int fmi2_import_check_has_FMU(fmi2_import_t* fmu) {
131         if(!fmu->md) {
132                 jm_log_error(fmu->callbacks, module,"No FMU is loaded");
133                 return 0;
134         }
135         return 1;
136 }
137
138 const char* fmi2_import_get_model_name(fmi2_import_t* fmu) {
139         if(!fmi2_import_check_has_FMU(fmu)) return 0;
140
141         return fmi2_xml_get_model_name(fmu->md);
142 }
143
144 unsigned int fmi2_import_get_capability(fmi2_import_t* fmu , fmi2_capabilities_enu_t id) {
145         if(!fmi2_import_check_has_FMU(fmu)) return 0;
146
147         return fmi2_xml_get_capability(fmu->md, id);
148 }
149
150
151 const char* fmi2_import_get_model_identifier_ME(fmi2_import_t* fmu) {
152         if(!fmi2_import_check_has_FMU(fmu)) return 0;
153
154         return fmi2_xml_get_model_identifier_ME(fmu->md);
155 }
156
157 const char* fmi2_import_get_model_identifier_CS(fmi2_import_t* fmu) {
158         if(!fmi2_import_check_has_FMU(fmu)) return 0;
159
160         return fmi2_xml_get_model_identifier_CS(fmu->md);
161 }
162
163 const char* fmi2_import_get_GUID(fmi2_import_t* fmu){
164         if(!fmi2_import_check_has_FMU(fmu)) return 0;
165
166     return fmi2_xml_get_GUID(fmu->md);
167 }
168
169 const char* fmi2_import_get_description(fmi2_import_t* fmu) {
170         if(!fmi2_import_check_has_FMU(fmu)) return 0;
171
172         return fmi2_xml_get_description(fmu->md);
173 }
174
175 const char* fmi2_import_get_author(fmi2_import_t* fmu) {
176         if(!fmi2_import_check_has_FMU(fmu)) return 0;
177
178         return fmi2_xml_get_author(fmu->md);
179 }
180
181 const char* fmi2_import_get_license(fmi2_import_t* fmu) {
182         if(!fmi2_import_check_has_FMU(fmu)) return 0;
183
184         return fmi2_xml_get_license(fmu->md);
185 }
186 const char* fmi2_import_get_copyright(fmi2_import_t* fmu) {
187         if(!fmi2_import_check_has_FMU(fmu)) return 0;
188
189         return fmi2_xml_get_copyright(fmu->md);
190 }
191
192 const char* fmi2_import_get_model_standard_version(fmi2_import_t* fmu) {
193         if(!fmi2_import_check_has_FMU(fmu)) return 0;
194
195         return fmi2_xml_get_model_standard_version(fmu->md);
196 }
197
198 const char* fmi2_import_get_model_version(fmi2_import_t* fmu) {
199         if(!fmi2_import_check_has_FMU(fmu)) return 0;
200
201         return fmi2_xml_get_model_version(fmu->md);
202 }
203
204 const char* fmi2_import_get_generation_tool(fmi2_import_t* fmu) {
205         if(!fmi2_import_check_has_FMU(fmu)) return 0;
206
207         return fmi2_xml_get_generation_tool(fmu->md);
208 }
209
210 const char* fmi2_import_get_generation_date_and_time(fmi2_import_t* fmu) {
211         if(!fmi2_import_check_has_FMU(fmu)) return 0;
212
213         return fmi2_xml_get_generation_date_and_time(fmu->md);
214 }
215
216 fmi2_variable_naming_convension_enu_t fmi2_import_get_naming_convention(fmi2_import_t* fmu) {
217         if(!fmu->md) {
218                 jm_log_error(fmu->callbacks, module,"No FMU is loaded");
219                 return fmi2_naming_enu_unknown;
220         }
221         return fmi2_xml_get_naming_convention(fmu->md);
222 }
223
224 size_t fmi2_import_get_number_of_continuous_states(fmi2_import_t* fmu) {
225         if(!fmi2_import_check_has_FMU(fmu)) return 0;
226
227         return fmi2_xml_get_number_of_continuous_states(fmu->md);
228 }
229
230 size_t fmi2_import_get_number_of_event_indicators(fmi2_import_t* fmu) {
231         if(!fmi2_import_check_has_FMU(fmu)) return 0;
232
233         return fmi2_xml_get_number_of_event_indicators(fmu->md);
234 }
235
236 double fmi2_import_get_default_experiment_start(fmi2_import_t* fmu) {
237         if(!fmi2_import_check_has_FMU(fmu)) return 0;
238
239         return fmi2_xml_get_default_experiment_start(fmu->md);
240 }
241
242 double fmi2_import_get_default_experiment_stop(fmi2_import_t* fmu) {
243         if(!fmi2_import_check_has_FMU(fmu)) return 0;
244
245         return fmi2_xml_get_default_experiment_stop(fmu->md);
246 }
247
248 double fmi2_import_get_default_experiment_tolerance(fmi2_import_t* fmu) {
249         if(!fmi2_import_check_has_FMU(fmu)) return 0;
250
251         return fmi2_xml_get_default_experiment_tolerance(fmu->md);
252 }
253
254 double fmi2_import_get_default_experiment_step(fmi2_import_t* fmu) {
255         if(!fmi2_import_check_has_FMU(fmu)) return 0;
256
257         return fmi2_xml_get_default_experiment_step(fmu->md);
258 }
259
260 fmi2_import_unit_definitions_t* fmi2_import_get_unit_definitions(fmi2_import_t* fmu) {
261         if(!fmi2_import_check_has_FMU(fmu)) return 0;
262
263         return fmi2_xml_get_unit_definitions(fmu->md);
264 }
265
266 unsigned int  fmi2_import_get_unit_definitions_number(fmi2_import_unit_definitions_t* ud) {
267         return fmi2_xml_get_unit_definitions_number(ud);
268 }
269
270 fmi2_import_type_definitions_t* fmi2_import_get_type_definitions(fmi2_import_t* fmu) {
271         if(!fmi2_import_check_has_FMU(fmu)) return 0;
272
273         return fmi2_xml_get_type_definitions(fmu->md);
274 }
275
276 fmi2_import_variable_list_t* fmi2_import_vector_to_varlist(fmi2_import_t* fmu, jm_vector(jm_voidp)* vars) {
277     fmi2_import_variable_list_t* vl;
278     size_t nv, i;
279         if(!vars) return 0;
280
281     nv = jm_vector_get_size(jm_voidp)(vars);
282     vl = fmi2_import_alloc_variable_list(fmu, nv);
283     if(!vl) return 0;
284     for(i = 0; i< nv; i++) {
285         jm_vector_set_item(jm_voidp)(&vl->variables, i, jm_vector_get_item(jm_voidp)(vars, i));
286     }
287     return vl;
288
289 }
290
291 /* Get the list of all the variables in the model */
292 /* 0 - original order as found in the XML file; 1 - sorted alfabetically by variable name; 2 sorted by types/value references. */
293 fmi2_import_variable_list_t* fmi2_import_get_variable_list(fmi2_import_t* fmu, int sortOrder) {
294         if(!fmi2_import_check_has_FMU(fmu)) return 0;
295         switch(sortOrder) {
296         case 0:
297                 return fmi2_import_vector_to_varlist(fmu, fmi2_xml_get_variables_original_order(fmu->md));
298         case 1: {
299                 fmi2_import_variable_list_t* vl;
300                 size_t nv, i;
301                 jm_vector(jm_named_ptr)* vars = fmi2_xml_get_variables_alphabetical_order(fmu->md);
302                 if(!vars) return 0;
303                 nv = jm_vector_get_size(jm_named_ptr)(vars);
304                 vl = fmi2_import_alloc_variable_list(fmu, nv);
305                 if(!vl) return 0;
306                 for(i = 0; i< nv; i++) {
307                         jm_vector_set_item(jm_voidp)(&vl->variables, i, jm_vector_get_item(jm_named_ptr)(vars, i).ptr);
308                 }
309                 return vl;
310         }
311         case 2:
312                 return fmi2_import_vector_to_varlist(fmu, fmi2_xml_get_variables_vr_order(fmu->md));
313         default:
314                 assert(0);
315         }
316         return 0;
317 }
318
319 fmi2_fmu_kind_enu_t fmi2_import_get_fmu_kind(fmi2_import_t* fmu) {
320     return fmi2_xml_get_fmu_kind(fmu->md);
321 }
322 \r
323 size_t fmi2_import_get_vendors_num(fmi2_import_t* fmu){
324         if(!fmi2_import_check_has_FMU(fmu)) return 0;
325
326         return fmi2_xml_get_vendors_num(fmu->md);
327 }
328
329 const char* fmi2_import_get_vendor_name(fmi2_import_t* fmu, size_t  index){
330         if(!fmi2_import_check_has_FMU(fmu)) return 0;
331
332         return fmi2_xml_get_vendor_name(fmu->md, index);
333 }
334
335 /** \brief Get the number of log categories defined in the XML */
336 size_t fmi2_import_get_log_categories_num(fmi2_import_t* fmu) {
337         if(!fmi2_import_check_has_FMU(fmu)) return 0;
338
339         return jm_vector_get_size(jm_string)(fmi2_xml_get_log_categories(fmu->md));
340 }
341
342 /** \brief Get the log category by index */
343 const char* fmi2_import_get_log_category(fmi2_import_t* fmu, size_t  index) {
344         if(!fmi2_import_check_has_FMU(fmu)) return 0;
345
346         return jm_vector_get_item(jm_string)(fmi2_xml_get_log_categories(fmu->md), index);
347 }
348
349 /** \brief Get the log category description by index */
350 const char* fmi2_import_get_log_category_description(fmi2_import_t* fmu, size_t  index) {
351         if(!fmi2_import_check_has_FMU(fmu)) return 0;
352
353         return jm_vector_get_item(jm_string)(fmi2_xml_get_log_category_descriptions(fmu->md), index);
354 }
355
356 /** \brief Get the number of source files for ME defined in the XML */\r
357 size_t fmi2_import_get_source_files_me_num(fmi2_import_t* fmu) {
358         if(!fmi2_import_check_has_FMU(fmu)) return 0;
359
360         return jm_vector_get_size(jm_string)(fmi2_xml_get_source_files_me(fmu->md));
361 }
362
363 /** \brief Get the ME source file by index */\r
364 const char* fmi2_import_get_source_file_me(fmi2_import_t* fmu, size_t  index) {
365         if(!fmi2_import_check_has_FMU(fmu)) return 0;
366
367         return jm_vector_get_item(jm_string)(fmi2_xml_get_source_files_me(fmu->md), index);
368 }
369
370 /** \brief Get the number of source files for CS defined in the XML */\r
371 size_t fmi2_import_get_source_files_cs_num(fmi2_import_t* fmu) {
372         if(!fmi2_import_check_has_FMU(fmu)) return 0;
373
374         return jm_vector_get_size(jm_string)(fmi2_xml_get_source_files_cs(fmu->md));
375 }
376
377 /** \brief Get the CS source file by index */\r
378 const char* fmi2_import_get_source_file_cs(fmi2_import_t* fmu, size_t  index) {
379         if(!fmi2_import_check_has_FMU(fmu)) return 0;
380
381         return jm_vector_get_item(jm_string)(fmi2_xml_get_source_files_cs(fmu->md), index);
382 }
383
384
385 fmi2_import_variable_list_t* fmi2_import_get_outputs_list(fmi2_import_t* fmu) {
386         if(!fmi2_import_check_has_FMU(fmu)) return 0;
387         return fmi2_import_vector_to_varlist(fmu, fmi2_xml_get_outputs(fmi2_xml_get_model_structure(fmu->md)));
388 }
389
390 fmi2_import_variable_list_t* fmi2_import_get_derivatives_list(fmi2_import_t* fmu){
391         if(!fmi2_import_check_has_FMU(fmu)) return 0;
392         return fmi2_import_vector_to_varlist(fmu, fmi2_xml_get_derivatives(fmi2_xml_get_model_structure(fmu->md)));
393 }
394
395 fmi2_import_variable_list_t* fmi2_import_get_discrete_states_list(fmi2_import_t* fmu) {
396         if(!fmi2_import_check_has_FMU(fmu)) return 0;
397         return fmi2_import_vector_to_varlist(fmu, fmi2_xml_get_discrete_states(fmi2_xml_get_model_structure(fmu->md)));
398 }
399
400 fmi2_import_variable_list_t* fmi2_import_get_initial_unknowns_list(fmi2_import_t* fmu) {
401         if(!fmi2_import_check_has_FMU(fmu)) return 0;
402         return fmi2_import_vector_to_varlist(fmu, fmi2_xml_get_initial_unknowns(fmi2_xml_get_model_structure(fmu->md)));
403 }
404
405 void fmi2_import_get_outputs_dependencies(fmi2_import_t* fmu,size_t** startIndex, size_t** dependency, char** factorKind) { 
406     fmi2_xml_model_structure_t* ms; 
407     if(!fmi2_import_check_has_FMU(fmu)) {
408         *startIndex = 0;
409         return;
410     }    
411     ms = fmi2_xml_get_model_structure(fmu->md);
412     assert(ms);
413     fmi2_xml_get_outputs_dependencies(ms, startIndex, dependency, factorKind); 
414
415
416 void fmi2_import_get_derivatives_dependencies(fmi2_import_t* fmu,size_t** startIndex, size_t** dependency, char** factorKind) { 
417     fmi2_xml_model_structure_t* ms; 
418     if(!fmi2_import_check_has_FMU(fmu)) {
419         *startIndex = 0;
420         return;
421     }    
422     ms = fmi2_xml_get_model_structure(fmu->md);
423     assert(ms);
424     fmi2_xml_get_derivatives_dependencies(ms, startIndex, dependency, factorKind); 
425
426
427 void fmi2_import_get_discrete_states_dependencies(fmi2_import_t* fmu,size_t** startIndex, size_t** dependency, char** factorKind) { 
428     fmi2_xml_model_structure_t* ms; 
429     if(!fmi2_import_check_has_FMU(fmu)) {
430         *startIndex = 0;
431         return;
432     }    
433     ms = fmi2_xml_get_model_structure(fmu->md);
434     assert(ms);
435     fmi2_xml_get_discrete_states_dependencies(ms, startIndex, dependency, factorKind); 
436
437
438 void fmi2_import_get_initial_unknowns_dependencies(fmi2_import_t* fmu,size_t** startIndex, size_t** dependency, char** factorKind) { 
439     fmi2_xml_model_structure_t* ms; 
440     if(!fmi2_import_check_has_FMU(fmu)) {
441         *startIndex = 0;
442         return;
443     }    
444     ms = fmi2_xml_get_model_structure(fmu->md);
445     assert(ms);
446     fmi2_xml_get_initial_unknowns_dependencies(ms, startIndex, dependency, factorKind); 
447