Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 13.3% 54 / 0 / 407
Functions: 20.8% 11 / 1 / 54
Branches: 6.0% 14 / 0 / 232

OMCompiler/SimulationRuntime/c/util/string_array.c
Line Branch Exec Source
1 /*
2 * This file belongs to the OpenModelica Run-Time System
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC), c/o Linköpings
5 * universitet, Department of Computer and Information Science, SE-58183 Linköping, Sweden. All rights
6 * reserved.
7 *
8 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF THE BSD NEW LICENSE OR THE
9 * AGPL VERSION 3 LICENSE OR THE OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. ANY
10 * USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S
11 * ACCEPTANCE OF THE BSD NEW LICENSE OR THE OSMC PUBLIC LICENSE OR THE AGPL
12 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
13 *
14 * The OpenModelica software and the OSMC (Open Source Modelica Consortium) Public License
15 * (OSMC-PL) are obtained from OSMC, either from the above address, from the URLs:
16 * http://www.openmodelica.org or https://github.com/OpenModelica/ or
17 * http://www.ida.liu.se/projects/OpenModelica, and in the OpenModelica distribution. GNU
18 * AGPL version 3 is obtained from: https://www.gnu.org/licenses/licenses.html#GPL. The BSD NEW
19 * License is obtained from: http://www.opensource.org/licenses/BSD-3-Clause.
20 *
21 * This program is distributed WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY
23 * SET FORTH IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF
24 * OSMC-PL.
25 *
26 */
27
28
29 #include "string_array.h"
30 #if defined(OMC_METAMODELICA_RUNTIME)
31 /* The string vocabulary of this runtime; util/omc_string.h stands down here. */
32 #include "../meta/meta_modelica_string.h"
33 #endif
34 #include "../gc/omc_gc.h"
35 #include "index_spec.h"
36 #include "modelica_string.h"
37 #include "omc_error.h"
38 #include "generic_array.h"
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <assert.h>
43 #include <stdarg.h>
44
45 static inline modelica_string *string_ptrget(const string_array *a, size_t i)
46 {
47 ✗ return ((modelica_string *) a->data) + i;
48 }
49
50 /* An element slot owns its reference, like every other slot a string can live
51 in; a freshly allocated buffer is zeroed, so the release is a no-op there. */
52 287 static inline void string_set(string_array *a, size_t i, modelica_string r)
53 {
54
1/2
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
287 omc_string_store(((modelica_string *) a->data) + i, r);
55 287 }
56
57 75 modelica_string string_get(const string_array a, size_t i)
58 {
59 75 return ((modelica_string *) a.data)[i];
60 }
61
62 ✗ modelica_string string_get_2D(const string_array a, size_t i, size_t j)
63 {
64 ✗ return string_get(a, getIndex_2D(a.dim_size,i,j));
65 }
66
67 ✗ modelica_string string_get_3D(const string_array a, size_t i, size_t j, size_t k)
68 {
69 ✗ return string_get(a, getIndex_3D(a.dim_size,i,j,k));
70 }
71
72 ✗ modelica_string string_get_4D(const string_array a, size_t i, size_t j, size_t k, size_t l)
73 {
74 ✗ return string_get(a, getIndex_4D(a.dim_size,i,j,k,l));
75 }
76
77 ✗ modelica_string string_get_5D(const string_array a, size_t i, size_t j, size_t k, size_t l, size_t m)
78 {
79 ✗ return string_get(a, getIndex_5D(a.dim_size,i,j,k,l,m));
80 }
81
82
83 /** function: string_array_create
84 **
85 ** sets all fields in a string_array, i.e. data, ndims and dim_size.
86 **/
87
88 508 void string_array_create(string_array *dest, modelica_string *data,
89 int ndims, ...)
90 {
91 va_list ap;
92 508 va_start(ap, ndims);
93 508 base_array_create(dest, data, ndims, ap);
94 508 va_end(ap);
95 508 }
96
97 1940 void simple_alloc_1d_string_array(string_array* dest, int n)
98 {
99 1940 simple_alloc_1d_base_array(dest, n, string_alloc(n));
100 1940 }
101
102 ✗ void simple_alloc_2d_string_array(string_array* dest, int r, int c)
103 {
104 ✗ simple_alloc_2d_base_array(dest, r, c, string_alloc(r * c));
105 ✗ }
106
107 5 void alloc_string_array(string_array *dest, int ndims, ...)
108 {
109 size_t elements = 0;
110 va_list ap;
111 5 va_start(ap, ndims);
112 5 elements = alloc_base_array(dest, ndims, ap);
113 5 va_end(ap);
114 5 dest->data = string_alloc(elements);
115 5 }
116
117 ✗ void alloc_string_array_data(string_array* a)
118 {
119 ✗ a->data = string_alloc(base_array_nr_of_elements(*a));
120 ✗ }
121
122 ✗ void copy_string_array_data_mem(const string_array source, modelica_string *dest)
123 {
124 size_t i, nr_of_elements;
125
126 ✗ assert(base_array_ok(&source));
127
128 ✗ nr_of_elements = base_array_nr_of_elements(source);
129
130 ✗ for(i = 0; i < nr_of_elements; ++i) {
131 ✗ omc_string_store(dest + i, string_get(*&source, i));
132 }
133 ✗ }
134
135 ✗ void copy_string_array(const string_array source, string_array *dest)
136 {
137 ✗ string_array_alloc_copy(source,*dest);
138 ✗ }
139
140 /* What simple_array_copy_data is for the other element types. A memcpy would
141 duplicate the pointers without the destination taking a reference. */
142 ✗ void omc_string_array_alloc_copy(const string_array source, string_array *dest)
143 {
144 size_t i, nr_of_elements;
145
146 ✗ simple_array_alloc_copy(source, dest, sizeof(modelica_string));
147 ✗ nr_of_elements = base_array_nr_of_elements(*dest);
148 ✗ for(i = 0; i < nr_of_elements; ++i) {
149 ✗ omc_string_retain(((modelica_string *) dest->data)[i]);
150 }
151 ✗ }
152
153 5 void omc_string_array_copy_data(const string_array source, string_array *dest)
154 {
155 size_t i, nr_of_elements;
156
157
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 assert(base_array_ok(&source));
158
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 assert(base_array_ok(dest));
159
160 5 nr_of_elements = base_array_nr_of_elements(source);
161
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 assert(nr_of_elements == base_array_nr_of_elements(*dest));
162
163
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 5 times.
80 for(i = 0; i < nr_of_elements; ++i) {
164 75 string_set(dest, i, string_get(source, i));
165 }
166 5 }
167
168 /*
169 a[1:3] := b;
170 */
171
172 static inline modelica_string *calc_string_index_spec(int ndims, const _index_t *idx_vec,
173 const string_array *arr,
174 const index_spec_t *spec)
175 {
176 return string_ptrget(arr, calc_base_index_spec(ndims, idx_vec, arr, spec));
177 }
178
179 /* Uses zero based indexing */
180 ✗ modelica_string *calc_string_index(int ndims, const _index_t *idx_vec,
181 const string_array *arr)
182 {
183 ✗ return string_ptrget(arr, calc_base_index(ndims, idx_vec, arr));
184 }
185
186 /* One based index*/
187 ✗ modelica_string *calc_string_index_va(const string_array *source, int ndims,
188 va_list ap)
189 {
190 ✗ return string_ptrget(source, calc_base_index_va(source, ndims, ap));
191 }
192
193 ✗ void print_string_matrix(const string_array *source)
194 {
195 ✗ if(source->ndims == 2) {
196 _index_t i,j;
197 modelica_string value;
198
199 ✗ printf("%d X %d matrix:\n", (int) source->dim_size[0], (int) source->dim_size[1]);
200 ✗ for(i = 0; i < source->dim_size[0]; ++i) {
201 ✗ for(j = 0; j < source->dim_size[1]; ++j) {
202 ✗ value = string_get(*source, (i * source->dim_size[1]) + j);
203 ✗ printf("%s\t", omc_string_data(value));
204 }
205 printf("\n");
206 }
207 } else {
208 printf("array with %d dimensions\n", source->ndims);
209 }
210 ✗ }
211
212 ✗ void print_string_array(const string_array *source)
213 {
214 _index_t i;
215 modelica_string *data;
216 ✗ assert(base_array_ok(source));
217
218 ✗ data = (modelica_string *) source->data;
219 ✗ if(source->ndims == 1) {
220 ✗ for(i = 1; i < source->dim_size[0]; ++i) {
221 ✗ printf("%s, ", omc_string_data(*data));
222 ✗ ++data;
223 }
224 ✗ if(0 < source->dim_size[0]) {
225 ✗ printf("%s", omc_string_data(*data));
226 }
227 ✗ } else if(source->ndims > 1) {
228 size_t k, n;
229 _index_t j;
230
231 ✗ n = base_array_nr_of_elements(*source) /
232 ✗ (source->dim_size[0] * source->dim_size[1]);
233 ✗ for(k = 0; k < n; ++k) {
234 ✗ for(i = 0; i < source->dim_size[1]; ++i) {
235 ✗ for(j = 0; j < source->dim_size[0]; ++j) {
236 ✗ printf("%s, ", omc_string_data(*data));
237 ✗ ++data;
238 }
239 ✗ if(0 < source->dim_size[0]) {
240 ✗ printf("%s", omc_string_data(*data));
241 }
242 printf("\n");
243 }
244 ✗ if((k + 1) < n) {
245 printf("\n =================\n");
246 }
247 }
248 }
249 ✗ }
250
251 137 void put_string_element(modelica_string value, int i1, string_array *dest)
252 {
253 /* Assert that dest has correct dimension */
254 /* Assert that i1 is a valid index */
255 137 string_set(dest, i1, value);
256 137 }
257
258 ✗ void put_string_matrix_element(modelica_string value, int r, int c,
259 string_array* dest)
260 {
261 /* Assert that dest hast correct dimension */
262 /* Assert that r and c are valid indices */
263 ✗ string_set(dest, (r * dest->dim_size[1]) + c, value);
264 /* printf("Index %d\n",r*dest->dim_size[1]+c); */
265 ✗ }
266
267 /* Zero based index */
268 ✗ void simple_indexed_assign_string_array1(const string_array * source,
269 int i1,
270 string_array* dest)
271 {
272 /* Assert that source has the correct dimension */
273 /* Assert that dest has the correct dimension */
274 ✗ string_set(dest, i1, string_get(*source, i1));
275 ✗ }
276
277 ✗ void simple_indexed_assign_string_array2(const string_array * source,
278 int i1, int i2,
279 string_array* dest)
280 {
281 size_t index;
282 /* Assert that source has correct dimension */
283 /* Assert that dest has correct dimension */
284 ✗ index = (i1 * source->dim_size[1]) + i2;
285 ✗ string_set(dest, index, string_get(*source, index));
286 ✗ }
287
288 ✗ void indexed_assign_string_array(const string_array source,
289 string_array* dest,
290 const index_spec_t* dest_spec)
291 {
292 _index_t *idx_vec1, *idx_size;
293 _index_t j, n;
294 ✗ indexed_assign_base_array_size_alloc(&source, dest, dest_spec, &idx_vec1, &idx_size);
295
296 ✗ n = base_array_nr_of_elements(source);
297 ✗ for (j = 0; j < n; j++) {
298 ✗ string_set(dest,
299 calc_base_index_spec(dest->ndims, idx_vec1, dest, dest_spec),
300 string_get(source, j));
301 ✗ next_index(dest_spec->ndims, idx_vec1, idx_size);
302 }
303
304 ✗ omc_rc_release_inline(idx_vec1);
305 ✗ omc_rc_release_inline(idx_size);
306 ✗ }
307
308 /*
309 * function: index_string_array
310 *
311 * Returns an subscript of the source array in the destination array.
312 * Assumes that both source array and destination array is properly
313 * allocated.
314 *
315 * a := b[1:3];
316 *
317 */
318
319 ✗ void index_string_array(const string_array * source,
320 const index_spec_t* source_spec,
321 string_array* dest)
322 {
323 _index_t* idx_vec1;
324 _index_t* idx_vec2;
325 _index_t* idx_size;
326 int j;
327 int i;
328
329 ✗ assert(base_array_ok(source));
330 ✗ assert(base_array_ok(dest));
331 ✗ assert(index_spec_ok(source_spec));
332 ✗ assert(index_spec_fit_base_array(source_spec,source));
333 ✗ for(i = 0, j = 0; i < source->ndims; ++i) {
334 ✗ if((source_spec->index_type[i] == 'W')
335 ✗ ||
336 (source_spec->index_type[i] == 'A')) {
337 ✗ ++j;
338 }
339 }
340 ✗ assert(j == dest->ndims);
341 ✗ if (base_array_nr_of_elements(*dest) == 0) {
342 return;
343 }
344
345 ✗ idx_vec1 = size_alloc(source->ndims); /*indices in the source array*/
346 ✗ idx_vec2 = size_alloc(dest->ndims); /* indices in the destination array*/
347 ✗ idx_size = size_alloc(source_spec->ndims);
348
349 ✗ for(i = 0; i < source->ndims; ++i) {
350 ✗ idx_vec1[i] = 0;
351 }
352 ✗ for(i = 0; i < source_spec->ndims; ++i) {
353 ✗ if(source_spec->index_type[i] != 'W') {
354 ✗ idx_size[i] = imax(source_spec->dim_size[i],1);
355 } else {
356 ✗ idx_size[i] = source->dim_size[i];
357 }
358 }
359
360 do {
361 ✗ for(i = 0, j = 0; i < source->ndims; ++i) {
362 ✗ if((source_spec->index_type[i] == 'W')
363 ✗ ||
364 (source_spec->index_type[i] == 'A')) {
365 ✗ idx_vec2[j] = idx_vec1[i];
366 ✗ j++;
367 }
368 }
369
370 ✗ string_set(dest, calc_base_index(dest->ndims, idx_vec2, dest),
371 string_get(*source,
372 calc_base_index_spec(source->ndims, idx_vec1,
373 source, source_spec)));
374
375 ✗ } while(0 == next_index(source->ndims, idx_vec1, idx_size));
376 ✗ omc_rc_release_inline(idx_vec1);
377 ✗ omc_rc_release_inline(idx_vec2);
378 ✗ omc_rc_release_inline(idx_size);
379 }
380
381 /*
382 * function: index_alloc_string_array
383 *
384 * Returns an subscript of the source array in the destination array
385 * in the same manner as index_string_array, except that the destination
386 * array is allocated.
387 *
388 *
389 * a := b[1:3];
390 */
391
392 ✗ void index_alloc_string_array(const string_array * source,
393 const index_spec_t* source_spec,
394 string_array* dest)
395 {
396 ✗ index_alloc_base_array_size(source, source_spec, dest);
397 ✗ alloc_string_array_data(dest);
398 ✗ index_string_array(source, source_spec, dest);
399 ✗ }
400
401 /* Returns dest := source[i1,:,:...]*/
402 ✗ void simple_index_alloc_string_array1(const string_array * source, int i1,
403 string_array* dest)
404 {
405 int i;
406 ✗ assert(base_array_ok(source));
407
408 ✗ dest->ndims = source->ndims - 1;
409 ✗ dest->dim_size = size_alloc(dest->ndims);
410 ✗ dest->owns_data = 1;
411
412 ✗ for(i = 0; i < dest->ndims; ++i) {
413 ✗ dest->dim_size[i] = source->dim_size[i+1];
414 }
415 ✗ alloc_string_array_data(dest);
416
417 ✗ simple_index_string_array1(source, i1, dest);
418 ✗ }
419
420 ✗ void simple_index_string_array1(const string_array * source, int i1,
421 string_array* dest)
422 {
423 size_t i;
424 ✗ size_t nr_of_elements = base_array_nr_of_elements(*dest);
425 ✗ size_t off = nr_of_elements * i1;
426
427 ✗ assert(dest->ndims == (source->ndims - 1));
428
429 ✗ for(i = 0 ; i < nr_of_elements ; i++) {
430 ✗ string_set(dest, i, string_get(*source, off + i));
431 }
432 ✗ }
433
434 ✗ void simple_index_string_array2(const string_array * source,
435 int i1, int i2,
436 string_array* dest)
437 {
438 size_t i;
439 ✗ size_t nr_of_elements = base_array_nr_of_elements(*dest);
440 ✗ size_t off = nr_of_elements * ((source->dim_size[1] * i1) + i2);
441
442 ✗ for(i = 0 ; i < nr_of_elements ; i++) {
443 ✗ string_set(dest, i, string_get(*source, off + i));
444 }
445 ✗ }
446
447 ✗ void array_string_array(string_array* dest,int n,string_array first,...)
448 {
449 int i,j,c;
450 va_list ap;
451
452 ✗ string_array *elts=(string_array*)malloc(sizeof(string_array) * n);
453 ✗ assert(elts);
454 /* collect all array ptrs to simplify traversal.*/
455 ✗ va_start(ap,first);
456 ✗ elts[0] = first;
457 ✗ for(i = 1; i < n; ++i) {
458 ✗ elts[i] = va_arg(ap, string_array);
459 }
460 ✗ va_end(ap);
461
462 ✗ check_base_array_dim_sizes(elts,n);
463
464 ✗ for(i = 0, c = 0; i < n; ++i) {
465 ✗ int m = base_array_nr_of_elements(elts[i]);
466 ✗ for(j = 0; j < m; ++j) {
467 ✗ string_set(dest, c, string_get(elts[i], j));
468 ✗ c++;
469 }
470 }
471 ✗ free(elts);
472 ✗ }
473
474 ✗ void array_alloc_string_array(string_array* dest, int n,
475 string_array first,...)
476 {
477 int i,j,c;
478 va_list ap;
479
480 ✗ string_array *elts = (string_array*)malloc(sizeof(string_array) * n);
481 ✗ assert(elts);
482 /* collect all array ptrs to simplify traversal.*/
483 ✗ va_start(ap,first);
484 ✗ elts[0] = first;
485 ✗ for(i = 1; i < n; ++i) {
486 ✗ elts[i] = va_arg(ap, string_array);
487 }
488 ✗ va_end(ap);
489
490 ✗ check_base_array_dim_sizes(elts, n);
491
492 ✗ if(first.ndims == 1) {
493 ✗ alloc_string_array(dest, 2, n, first.dim_size[0]);
494 ✗ } else if(first.ndims == 2) {
495 ✗ alloc_string_array(dest, 3, n, first.dim_size[0], first.dim_size[1]);
496 ✗ } else if(first.ndims == 3) {
497 ✗ alloc_string_array(dest, 4, n, first.dim_size[0], first.dim_size[1], first.dim_size[2]);
498 ✗ } else if(first.ndims == 4) {
499 ✗ alloc_string_array(dest, 5, n, first.dim_size[0], first.dim_size[1], first.dim_size[2], first.dim_size[3]);
500 } else {
501 ✗ assert(0 && "Dimension size > 4 not impl. yet");
502 }
503
504 ✗ for(i = 0, c = 0; i < n; ++i) {
505 ✗ int m = base_array_nr_of_elements(elts[i]);
506 ✗ for(j = 0; j < m; ++j) {
507 ✗ string_set(dest, c, string_get(elts[i], j));
508 ✗ c++;
509 }
510 }
511 ✗ free(elts);
512 ✗ }
513
514 /* array_alloc_scalar_string_array
515 *
516 * Creates(incl allocation) an array from scalar elements.
517 */
518
519 136 void array_alloc_scalar_string_array(string_array* dest, int n,
520 modelica_string first,...)
521 {
522 int i;
523 va_list ap;
524 136 simple_alloc_1d_string_array(dest,n);
525 136 va_start(ap,first);
526 136 put_string_element(first,0,dest);
527
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 136 times.
137 for(i = 1; i < n; ++i) {
528 1 put_string_element(va_arg(ap, modelica_string),i,dest);
529 }
530 136 va_end(ap);
531 136 }
532
533
534 /* function: cat_string_array
535 *
536 * Concatenates n string arrays along the k:th dimension.
537 * k is one based
538 */
539 ✗ void cat_string_array(int k, string_array* dest, int n,
540 const string_array* first,...)
541 {
542 va_list ap;
543 int i, j, r, c;
544 int n_sub = 1, n_super = 1;
545 int new_k_dim_size = 0;
546 ✗ const string_array **elts = (const string_array**)malloc(sizeof(string_array *) * n);
547
548 ✗ assert(elts);
549 /* collect all array ptrs to simplify traversal.*/
550 ✗ va_start(ap, first);
551 ✗ elts[0] = first;
552
553 ✗ for(i = 1; i < n; i++) {
554 ✗ elts[i] = va_arg(ap,const string_array*);
555 }
556 ✗ va_end(ap);
557
558 /* check dim sizes of all inputs and dest */
559 ✗ assert(elts[0]->ndims >= k);
560 ✗ for(i = 0; i < n; i++) {
561 ✗ assert(dest->ndims == elts[i]->ndims);
562 ✗ for(j = 0; j < (k - 1); j++) {
563 ✗ assert(dest->dim_size[j] == elts[i]->dim_size[j]);
564 }
565 ✗ new_k_dim_size += elts[i]->dim_size[k-1];
566 ✗ for(j = k; j < elts[0]->ndims; j++) {
567 ✗ assert(dest->dim_size[j] == elts[i]->dim_size[j]);
568 }
569 }
570 ✗ assert(dest->dim_size[k-1] == new_k_dim_size);
571
572 /* calculate size of sub and super structure in 1-dim data representation */
573 ✗ for(i = 0; i < (k - 1); i++) {
574 ✗ n_super *= elts[0]->dim_size[i];
575 }
576 ✗ for(i = k; i < elts[0]->ndims; i++) {
577 ✗ n_sub *= elts[0]->dim_size[i];
578 }
579
580 /* concatenation along k-th dimension */
581 j = 0;
582 ✗ for(i = 0; i < n_super; i++) {
583 ✗ for(c = 0; c < n; c++) {
584 ✗ int n_sub_k = n_sub * elts[c]->dim_size[k-1];
585 ✗ for(r = 0; r < n_sub_k; r++) {
586 ✗ string_set(dest, j,
587 ✗ string_get(*elts[c], r + (i * n_sub_k)));
588 ✗ j++;
589 }
590 }
591 }
592 ✗ free(elts);
593 ✗ }
594
595 /* function: cat_alloc_string_array
596 *
597 * Concatenates n string arrays along the k:th dimension.
598 * allocates space in dest array
599 * k is one based
600 */
601 ✗ void cat_alloc_string_array(int k, string_array* dest, int n,
602 const string_array* first,...)
603 {
604 va_list ap;
605 int i, j, r, c;
606 int n_sub = 1, n_super = 1;
607 int new_k_dim_size = 0;
608 ✗ const string_array **elts = (const string_array**)malloc(sizeof(string_array *) * n);
609
610 ✗ assert(elts);
611 /* collect all array ptrs to simplify traversal.*/
612 ✗ va_start(ap, first);
613 ✗ elts[0] = first;
614
615 ✗ for(i = 1; i < n; i++) {
616 ✗ elts[i] = va_arg(ap,const string_array*);
617 }
618 ✗ va_end(ap);
619
620 /* check dim sizes of all inputs */
621 ✗ assert(elts[0]->ndims >= k);
622 ✗ new_k_dim_size = elts[0]->dim_size[k-1];
623 ✗ for(i = 1; i < n; i++) {
624 ✗ assert(elts[0]->ndims == elts[i]->ndims);
625 ✗ for(j = 0; j < (k - 1); j++) {
626 ✗ assert(elts[0]->dim_size[j] == elts[i]->dim_size[j]);
627 }
628 ✗ new_k_dim_size += elts[i]->dim_size[k-1];
629 ✗ for(j = k; j < elts[0]->ndims; j++) {
630 ✗ assert(elts[0]->dim_size[j] == elts[i]->dim_size[j]);
631 }
632 }
633
634 /* calculate size of sub and super structure in 1-dim data representation */
635 ✗ for(i = 0; i < (k - 1); i++) {
636 ✗ n_super *= elts[0]->dim_size[i];
637 }
638 ✗ for(i = k; i < elts[0]->ndims; i++) {
639 ✗ n_sub *= elts[0]->dim_size[i];
640 }
641 /* allocate dest structure */
642 ✗ dest->data = string_alloc( n_super * new_k_dim_size * n_sub);
643 ✗ dest->ndims = elts[0]->ndims;
644 ✗ dest->dim_size = size_alloc(dest->ndims);
645 ✗ dest->owns_data = 1;
646 ✗ for(j = 0; j < dest->ndims; j++) {
647 ✗ dest->dim_size[j] = elts[0]->dim_size[j];
648 }
649 ✗ dest->dim_size[k-1] = new_k_dim_size;
650 /* concatenation along k-th dimension */
651 j = 0;
652 ✗ for(i = 0; i < n_super; i++) {
653 ✗ for(c = 0; c < n; c++) {
654 ✗ int n_sub_k = n_sub * elts[c]->dim_size[k-1];
655 ✗ for(r = 0; r < n_sub_k; r++) {
656 ✗ string_set(dest, j,
657 ✗ string_get(*elts[c], r + (i * n_sub_k)));
658 ✗ j++;
659 }
660 }
661 }
662 ✗ free(elts);
663 ✗ }
664
665 /* function: promote_alloc_string_array
666 *
667 * Implementation of promote(A,n) same as promote_string_array except
668 * that the destination array is allocated.
669 */
670 ✗ void promote_alloc_string_array(const string_array * a, int n,
671 string_array* dest)
672 {
673 ✗ dest->flexible = a->flexible;
674 ✗ promote_string_array(a, n, dest);
675 ✗ }
676
677 /* function: promote_string_array.
678 *
679 * Implementation of promote(a,n)
680 * Adds n onesized array dimensions to the array a to "the right of array dimensions".
681 * For instance
682 * promote_exp( {1,2},1) => {{1},{2}}
683 * promote_exp( {1,2},2) => { {{1}},{{2}} }
684 */
685 ✗ void promote_string_array(const string_array * a, int n,string_array* dest)
686 {
687 int i;
688
689 ✗ dest->dim_size = size_alloc(n+a->ndims);
690 ✗ dest->data = a->data;
691 ✗ dest->owns_data = a->owns_data;
692 ✗ if (dest->owns_data) {
693 omc_rc_retain_inline(dest->data);
694 }
695 /* Assert a->ndims>=n */
696 ✗ for(i = 0; i < a->ndims; ++i) {
697 ✗ dest->dim_size[i] = a->dim_size[i];
698 }
699 ✗ for(i = a->ndims; i < (n + a->ndims); ++i) {
700 ✗ dest->dim_size[i] = 1;
701 }
702
703 ✗ dest->ndims=n+a->ndims;
704 ✗ }
705
706 /* function: promote_scalar_string_array
707 *
708 * promotes a scalar value to an n dimensional array.
709 */
710
711 ✗ void promote_scalar_string_array(modelica_string s,int n,
712 string_array* dest)
713 {
714 int i;
715
716 /* Assert that dest is of correct dimension */
717
718 /* Alloc size */
719 ✗ dest->dim_size = size_alloc(n);
720 ✗ dest->owns_data = 1;
721
722 /* Alloc data */
723 ✗ dest->data = string_alloc(1);
724
725 ✗ dest->ndims = n;
726 ✗ string_set(dest, 0, s);
727
728 ✗ for(i = 0; i < n; ++i) {
729 ✗ dest->dim_size[i] = 1;
730 }
731 ✗ }
732
733 /* return a vector of length ndims(a) containing the dimension sizes of a */
734 ✗ void size_string_array(const string_array * a, integer_array* dest)
735 {
736 int i;
737
738 ✗ assert(dest->ndims == 1);
739 ✗ assert(dest->dim_size[0] == a->ndims);
740
741 ✗ for(i = 0 ; i < a->ndims ; i++) {
742 ✗ ((modelica_integer *) dest->data)[i] = a->dim_size[i];
743 }
744 ✗ }
745
746 ✗ modelica_string scalar_string_array(const string_array * a)
747 {
748 ✗ assert(base_array_ok(a));
749 ✗ assert(base_array_one_element_ok(a));
750
751 ✗ return string_get(*a, 0);
752 }
753
754 ✗ void vector_string_array(const string_array * a, string_array* dest)
755 {
756 size_t i, nr_of_elements;
757
758 /* Assert that a has at most one dimension with dim_size>1*/
759
760 ✗ nr_of_elements = base_array_nr_of_elements(*a);
761 ✗ for(i = 0; i < nr_of_elements; ++i) {
762 ✗ string_set(dest, i, string_get(*a, i));
763 }
764 ✗ }
765
766 ✗ void vector_string_scalar(modelica_string a,string_array* dest)
767 {
768 /* Assert that dest is a 1-vector */
769 ✗ string_set(dest, 0, a);
770 ✗ }
771
772 ✗ void matrix_string_array(const string_array * a, string_array* dest)
773 {
774 size_t i, cnt;
775 /* Assert that size(A,i)=1 for 2 <i<=ndims(A)*/
776 ✗ dest->dim_size[0] = a->dim_size[0];
777 ✗ dest->dim_size[1] = (a->ndims < 2)? 1 : a->dim_size[1];
778
779 ✗ cnt = dest->dim_size[0] * dest->dim_size[1];
780
781 ✗ for(i = 0; i < cnt; ++i) {
782 ✗ string_set(dest, i, string_get(*a, i));
783 }
784 ✗ }
785
786 ✗ void matrix_string_scalar(modelica_string a, string_array* dest)
787 {
788 ✗ dest->ndims = 2;
789 ✗ dest->dim_size[0] = 1;
790 ✗ dest->dim_size[1] = 1;
791 ✗ string_set(dest, 0, a);
792 ✗ }
793
794 /* function: transpose_alloc_string_array
795 *
796 * Implementation of transpose(A) for matrix A. Same as transpose_string_array
797 * except that destionation array is allocated.
798 */
799
800 ✗ void transpose_alloc_string_array(const string_array * a, string_array* dest)
801 {
802 clone_string_array_spec(a,dest); /* allocation*/
803
804 /* transpose only valid for matrices.*/
805
806 ✗ assert(a->ndims == 2);
807 ✗ dest->dim_size[0]=a->dim_size[1];
808 ✗ dest->dim_size[1]=a->dim_size[0];
809 ✗ dest->ndims = 2;
810
811 ✗ alloc_string_array_data(dest);
812 ✗ transpose_string_array(a,dest);
813 ✗ }
814
815 /* function: transpose_string_array
816 *
817 * Implementation of transpose(A) for matrix A.
818 */
819 ✗ void transpose_string_array(const string_array * a, string_array* dest)
820 {
821 size_t i;
822 size_t j;
823 /* size_t k;*/
824 size_t n,m;
825
826 ✗ if(a->ndims == 1) {
827 ✗ string_array_copy_data(*a, *dest);
828 ✗ return;
829 }
830
831 ✗ assert(a->ndims==2 && dest->ndims==2);
832
833 ✗ n = a->dim_size[0];
834 ✗ m = a->dim_size[1];
835
836 ✗ assert(dest->dim_size[0] == m && dest->dim_size[1] == n);
837
838 ✗ for(i = 0; i < n; ++i) {
839 ✗ for(j = 0; j < m; ++j) {
840 ✗ string_set(dest, (j * n) + i, string_get(*a, (i * m) + j));
841 }
842 }
843 }
844
845 5 void fill_string_array(string_array* dest,modelica_string s)
846 {
847 size_t nr_of_elements;
848 size_t i;
849
850 5 nr_of_elements = base_array_nr_of_elements(*dest);
851
2/4
✓ Branch 0 taken 75 times.
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 1 not taken.
80 for(i = 0; i < nr_of_elements; ++i) {
852 75 string_set(dest, i, s);
853 }
854 5 }
855
856 ✗ void convert_alloc_string_array_to_f77(const string_array * a,
857 string_array* dest)
858 {
859 int i;
860 ✗ clone_reverse_base_array_spec(a, dest);
861 ✗ alloc_string_array_data(dest);
862 ✗ transpose_string_array(a, dest);
863 ✗ for(i = 0; i < dest->ndims; ++i) {
864 ✗ dest->dim_size[i] = a->dim_size[i];
865 }
866 ✗ }
867
868 ✗ void convert_alloc_string_array_from_f77(const string_array * a,
869 string_array* dest)
870 {
871 int i;
872 ✗ clone_reverse_base_array_spec(a,dest);
873 ✗ alloc_string_array_data(dest);
874 ✗ for(i = 0; i < dest->ndims; ++i) {
875 ✗ int tmp = dest->dim_size[i];
876 ✗ dest->dim_size[i] = a->dim_size[i];
877 ✗ a->dim_size[i] = tmp;
878 }
879 ✗ transpose_string_array(a, dest);
880 ✗ }
881
882 ✗ void fill_alloc_string_array(string_array* dest, modelica_string value, int ndims, ...)
883 {
884 size_t i;
885 size_t elements = 0;
886 va_list ap;
887 ✗ va_start(ap, ndims);
888 ✗ elements = alloc_base_array(dest, ndims, ap);
889 ✗ va_end(ap);
890 ✗ dest->data = string_alloc(elements);
891
892 ✗ for(i = 0; i < elements; ++i) {
893 ✗ string_set(dest, i, value);
894 }
895 ✗ }
896
897 9 const char** data_of_string_c89_array(const string_array a)
898 {
899 long i;
900 9 size_t sz = base_array_nr_of_elements(a);
901 9 const char **res = (const char**) omc_alloc_interface.malloc(sz*sizeof(const char*));
902
2/4
✗ Branch 0 not taken.
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 1 taken 9 times.
89 for (i=0; i<sz; i++) {
903 80 res[i] = omc_string_data(((void**)a.data)[i]);
904 }
905 9 return res;
906 }
907
908 5 void unpack_string_array(const string_array *a, const char **data)
909 {
910 5 size_t sz = base_array_nr_of_elements(*a);
911 long i;
912
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 5 times.
80 for (i=0; i<sz; i++) {
913 75 ((void**)a->data)[i] = omc_string_new(data[i]);
914 }
915 5 }
916
917 ✗ static int string_element_to_string(char *buffer, size_t bufsize, const void *data, _index_t i)
918 {
919 ✗ modelica_string s = ((const modelica_string *)data)[i];
920 ✗ return snprintf(buffer, bufsize, "\"%s\"", s ? omc_string_data(s) : "");
921 }
922
923 /**
924 * @brief Write string vector into null-terminated string.
925 *
926 * @param source String vector to write to `buffer`.
927 * @param isScalar Treat vector as scalar.
928 * @param buffer Buffer to write into.
929 * @param bufsize Length of `buffer`.
930 */
931 ✗ void string_vector_to_string(const string_array *source, modelica_boolean isScalar, char *buffer, size_t bufsize)
932 {
933 ✗ base_vector_to_string(source, isScalar, string_element_to_string, buffer, bufsize);
934 ✗ }
935