Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 51.4% 114 / 0 / 222
Functions: 50.0% 1 / 1 / 3
Branches: 45.7% 64 / 0 / 140

OMCompiler/Compiler/Util/Util.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated package Util
37 " file: Util.mo
38 package: Util
39 description: Miscellanous MetaModelica Compiler (MMC) utilities
40
41
42 This package contains various MetaModelica Compiler (MMC) utilities sigh, mostly
43 related to lists.
44 It is used pretty much everywhere. The difference between this
45 module and the ModUtil module is that ModUtil contains modelica
46 related utilities. The Util module only contains *low-level*
47 MetaModelica Compiler (MMC) utilities, for example finding elements in lists.
48
49 This modules contains many functions that use *type variables* in MetaModelica Compiler (MMC).
50 A type variable is exactly what it sounds like, a type bound to a variable.
51 It is used for higher order functions, i.e. in MetaModelica Compiler (MMC) the possibility to pass a
52 \"pointer\" to a function into another function. But it can also be used for
53 generic data types, like in C++ templates."
54
55 public uniontype Status "Used to signal success or failure of a function call"
56 record SUCCESS end SUCCESS;
57 record FAILURE end FAILURE;
58 end Status;
59
60 public uniontype DateTime
61 record DATETIME
62 Integer sec;
63 Integer min;
64 Integer hour;
65 Integer mday;
66 Integer mon;
67 Integer year;
68 end DATETIME;
69 end DateTime;
70
71 protected
72 import Autoconf;
73 import ClockIndexes;
74 import Global;
75 import List;
76 import Print;
77 import System;
78
79 public constant Integer HASH_SEED = 5381;
80 public constant SourceInfo dummyInfo = SOURCEINFO("",false,0,0,0,0,0.0);
81
82 public function isIntGreater "Author: BZ"
83 input Integer lhs;
84 input Integer rhs;
85 output Boolean b = lhs > rhs;
86 end isIntGreater;
87
88 public function isRealGreater "Author: BZ"
89 input Real lhs;
90 input Real rhs;
91 output Boolean b = lhs > rhs;
92 end isRealGreater;
93
94 public function linuxDotSlash "If operating system is Linux/Unix, return a './', otherwise return empty string"
95 output String str;
96 algorithm
97 str := Autoconf.os;
98 ✗ str := if str == "linux" or str == "darwin" then "./" else "";
99 end linuxDotSlash;
100
101 public function flagValue "author: x02lucpo
102 Extracts the flagvalue from an argument list:
103 flagValue('-s',{'-d','hej','-s','file'}) => 'file'"
104 input String flag;
105 input list<String> arguments;
106 output String flagVal;
107 protected
108 String arg;
109 list<String> rest = arguments;
110 algorithm
111
2/2
✓ Branch 0 taken 2677 times.
✓ Branch 1 taken 2677 times.
5354 while not listEmpty(rest) loop
112 2677 arg :: rest := rest;
113
114
1/4
✓ Branch 0 taken 2677 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2677 if arg == flag then
115 break;
116 end if;
117 end while;
118
119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2677 times.
2677 flagVal := if listEmpty(rest) then "" else listHead(rest);
120 end flagValue;
121
122 public function selectFirstNonEmptyString
123 "Selects the first non-empty string from a list of strings.
124 Returns an empty string if no such string exists."
125 input list<String> inStrings;
126 output String outResult;
127 algorithm
128 ✗ for e in inStrings loop
129 ✗ if e <> "" then
130 outResult := e;
131 ✗ return;
132 end if;
133 end for;
134 outResult := "";
135 end selectFirstNonEmptyString;
136
137 public function compareTupleIntGt<T>
138 " Function could used with List.sort to sort a
139 List as list< tuple<Integer, Type_a> > by first argument.
140 "
141 input tuple<Integer, T> inTplA;
142 input tuple<Integer, T> inTplB;
143 output Boolean res;
144 protected
145 Integer a,b;
146 algorithm
147 129477 (a, _) := inTplA;
148 129477 (b, _) := inTplB;
149 129477 res := intGt(a,b);
150 end compareTupleIntGt;
151
152 public function compareTupleIntLt<T>
153 " Function could used with List.sort to sort a
154 List as list< tuple<Integer, Type_a> > by first argument.
155 "
156 input tuple<Integer, T> inTplA;
157 input tuple<Integer, T> inTplB;
158 output Boolean res;
159 protected
160 Integer a,b;
161 algorithm
162 ✗ (a, _) := inTplA;
163 ✗ (b, _) := inTplB;
164 ✗ res := intLt(a,b);
165 end compareTupleIntLt;
166
167 public function compareTuple2IntGt<T>
168 " Function could used with List.sort to sort a
169 List as list< tuple<Type_a,Integer> > by second argument.
170 "
171 input tuple<T, Integer> inTplA;
172 input tuple<T, Integer> inTplB;
173 output Boolean res;
174 protected
175 Integer a,b;
176 algorithm
177 ✗ (_, a) := inTplA;
178 ✗ (_, b) := inTplB;
179 ✗ res := intGt(a,b);
180 end compareTuple2IntGt;
181
182 public function compareTuple2IntLt<T>
183 " Function could used with List.sort to sort a
184 List as list< tuple<Type_a,Integer> > by second argument.
185 "
186 input tuple<T, Integer> inTplA;
187 input tuple<T, Integer> inTplB;
188 output Boolean res;
189 protected
190 Integer a,b;
191 algorithm
192 ✗ (_, a) := inTplA;
193 ✗ (_, b) := inTplB;
194 ✗ res := intLt(a,b);
195 end compareTuple2IntLt;
196
197 public function tuple21<T1, T2>
198 "Takes a tuple of two values and returns the first value.
199 Example: tuple21(('a', 1)) => 'a'"
200 input tuple<T1, T2> inTuple;
201 output T1 outValue;
202 algorithm
203 12781606 (outValue, _) := inTuple;
204 end tuple21;
205
206 public function tuple22<T1, T2>
207 "Takes a tuple of two values and returns the second value.
208 Example: tuple22(('a',1)) => 1"
209 input tuple<T1, T2> inTuple;
210 output T2 outValue;
211 algorithm
212 3472397 (_, outValue) := inTuple;
213 end tuple22;
214
215 public function optTuple22<T1, T2>
216 "Takes an option tuple of two values and returns the second value.
217 Example: optTuple22(SOME('a',1)) => 1"
218 input Option<tuple<T1, T2>> inTuple;
219 output T2 outValue;
220 algorithm
221 ✗ SOME((_, outValue)) := inTuple;
222 end optTuple22;
223
224 public function tuple312<T1, T2, T3>
225 "Takes a tuple of three values and returns the tuple of the two first values.
226 Example: tuple312(('a',1,2)) => ('a',1)"
227 input tuple<T1, T2, T3> inTuple;
228 output tuple<T1, T2> outTuple;
229 protected
230 T1 e1;
231 T2 e2;
232 algorithm
233 102212 (e1, e2, _) := inTuple;
234 102212 outTuple := (e1, e2);
235 end tuple312;
236
237 public function tuple31<T1, T2, T3>
238 "Takes a tuple of three values and returns the first value.
239 Example: tuple31(('a',1,2)) => 'a'"
240 input tuple<T1, T2, T3> inValue;
241 output T1 outValue;
242 algorithm
243 25303 (outValue, _, _) := inValue;
244 end tuple31;
245
246 public function tuple32<T1, T2, T3>
247 "Takes a tuple of three values and returns the second value.
248 Example: tuple32(('a',1,2)) => 1"
249 input tuple<T1, T2, T3> inValue;
250 output T2 outValue;
251 algorithm
252 21481 (_, outValue, _) := inValue;
253 end tuple32;
254
255 public function tuple33<T1, T2, T3>
256 "Takes a tuple of three values and returns the first value.
257 Example: tuple33(('a',1,2)) => 2"
258 input tuple<T1, T2, T3> inValue;
259 output T3 outValue;
260 algorithm
261 63987 (_, _, outValue) := inValue;
262 end tuple33;
263
264 public function tuple41<T1, T2, T3, T4>
265 input tuple<T1, T2, T3, T4> inTuple;
266 output T1 outValue;
267 algorithm
268 2836 (outValue, _, _, _) := inTuple;
269 end tuple41;
270
271 public function tuple42<T1, T2, T3, T4>
272 input tuple<T1, T2, T3, T4> inTuple;
273 output T2 outValue;
274 algorithm
275 2836 (_, outValue, _, _) := inTuple;
276 end tuple42;
277
278 public function tuple43<T1, T2, T3, T4>
279 input tuple<T1, T2, T3, T4> inTuple;
280 output T3 outValue;
281 algorithm
282 2836 (_, _, outValue, _) := inTuple;
283 end tuple43;
284
285 public function tuple44<T1, T2, T3, T4>
286 input tuple<T1, T2, T3, T4> inTuple;
287 output T4 outValue;
288 algorithm
289 1744 (_, _, _, outValue) := inTuple;
290 end tuple44;
291
292 public function tuple51<T1, T2, T3, T4, T5>
293 input tuple<T1, T2, T3, T4, T5> inTuple;
294 output T1 outValue;
295 algorithm
296 ✗ (outValue, _, _, _, _) := inTuple;
297 end tuple51;
298
299 public function tuple52<T1, T2, T3, T4, T5>
300 input tuple<T1, T2, T3, T4, T5> inTuple;
301 output T2 outValue;
302 algorithm
303 ✗ (_, outValue, _, _, _) := inTuple;
304 end tuple52;
305
306 public function tuple53<T1, T2, T3, T4, T5>
307 input tuple<T1, T2, T3, T4, T5> inTuple;
308 output T3 outValue;
309 algorithm
310 ✗ (_, _, outValue, _, _) := inTuple;
311 end tuple53;
312
313 public function tuple54<T1, T2, T3, T4, T5>
314 input tuple<T1, T2, T3, T4, T5> inTuple;
315 output T4 outValue;
316 algorithm
317 ✗ (_, _, _, outValue, _) := inTuple;
318 end tuple54;
319
320 public function tuple55<T1, T2, T3, T4, T5>
321 input tuple<T1, T2, T3, T4, T5> inTuple;
322 output T5 outValue;
323 algorithm
324 ✗ (_, _, _, _, outValue) := inTuple;
325 end tuple55;
326
327 public function tuple61<T1, T2, T3, T4, T5, T6>
328 input tuple<T1, T2, T3, T4, T5, T6> inTuple;
329 output T1 outValue;
330 algorithm
331 3918 (outValue, _, _ ,_ ,_ ,_ ) := inTuple;
332 end tuple61;
333
334 public function tuple62<T1, T2, T3, T4, T5, T6>
335 input tuple<T1, T2, T3, T4, T5, T6> inTuple;
336 output T2 outValue;
337 algorithm
338 3918 (_, outValue, _ ,_ ,_ ,_ ) := inTuple;
339 end tuple62;
340
341 public function stringContainsChar "Returns true if a string contains a specified character"
342 input String str;
343 input String char;
344 output Boolean res = false;
345 protected
346 Integer ch;
347 algorithm
348 ✗ ch := stringCharInt(char);
349 ✗ for i in 1:stringLength(str) loop
350 ✗ if MetaModelica.Dangerous.stringGetNoBoundsChecking(str, i) == ch then
351 res := true;
352 ✗ return;
353 end if;
354 end for;
355 end stringContainsChar;
356
357 public function stringDelimitListPrintBuf "
358 Author: BZ, 2009-11
359 Same functionality as stringDelimitListPrint, but writes to print buffer instead of string variable.
360 Usefull for heavy string operations(causes malloc error on some models when generating init file).
361 "
362 input list<String> inStringLst;
363 input String inDelimiter;
364 algorithm
365 ():=
366 matchcontinue inStringLst
367 local
368 String f;
369 list<String> r;
370 case {} then ();
371 ✗ case {f} algorithm Print.printBuf(f); then ();
372 case f :: r
373 algorithm
374 ✗ stringDelimitListPrintBuf(r, inDelimiter);
375 ✗ Print.printBuf(f);
376 ✗ Print.printBuf(inDelimiter);
377 then
378 ();
379 end matchcontinue;
380 end stringDelimitListPrintBuf;
381
382 public function stringDelimitListAndSeparate "author: PA
383 This function is similar to stringDelimitList, i.e it inserts string delimiters between
384 consecutive strings in a list. But it also count the lists and inserts a second string delimiter
385 when the counter is reached. This can be used when for instance outputting large lists of values
386 and a newline is needed after ten or so items."
387 input list<String> str;
388 input String sep1;
389 input String sep2;
390 input Integer n;
391 output String res;
392 protected
393 Integer handle;
394 algorithm
395 ✗ handle := Print.saveAndClearBuf();
396 ✗ stringDelimitListAndSeparate2(str, sep1, sep2, n, 0);
397 ✗ res := Print.getString();
398 ✗ Print.restoreBuf(handle);
399 end stringDelimitListAndSeparate;
400
401 protected function stringDelimitListAndSeparate2 "author: PA
402 Helper function to stringDelimitListAndSeparate"
403 input list<String> inStringLst1;
404 input String inString2;
405 input String inString3;
406 input Integer inInteger4;
407 input Integer inInteger5;
408 algorithm
409 () := matchcontinue (inStringLst1,inString2,inString3,inInteger4,inInteger5)
410 local
411 String s,f,sep1,sep2;
412 list<String> r;
413 Integer n,iter_1,iter;
414 case ({},_,_,_,_) then (); /* iterator */
415 case ({s},_,_,_,_) algorithm
416 ✗ Print.printBuf(s);
417 then ();
418 case ((f :: r),sep1,sep2,n,0)
419 algorithm
420 ✗ Print.printBuf(f);Print.printBuf(sep1);
421 ✗ stringDelimitListAndSeparate2(r, sep1, sep2, n, 1) "special case for first element" ;
422 then
423 ();
424 case ((f :: r),sep1,sep2,n,iter)
425 algorithm
426 ✗ 0 := intMod(iter, n) "insert second delimiter" ;
427 ✗ iter_1 := iter + 1;
428 ✗ Print.printBuf(f);Print.printBuf(sep1);Print.printBuf(sep2);
429 ✗ stringDelimitListAndSeparate2(r, sep1, sep2, n, iter_1);
430 then
431 ();
432 case ((f :: r),sep1,sep2,n,iter)
433 algorithm
434 ✗ iter_1 := iter + 1 "not inserting second delimiter" ;
435 ✗ Print.printBuf(f);Print.printBuf(sep1);
436 ✗ stringDelimitListAndSeparate2(r, sep1, sep2, n, iter_1);
437 then
438 ();
439 else
440 algorithm
441 ✗ print("- stringDelimitListAndSeparate2 failed\n");
442 ✗ then
443 fail();
444 end matchcontinue;
445 end stringDelimitListAndSeparate2;
446
447 public function stringDelimitListNonEmptyElts "the string delimiter inserted between those elements that are not empty.
448 Example: stringDelimitListNonEmptyElts({\"x\",\"\",\"z\"}, \", \") => \"x, z\""
449 input list<String> lst;
450 input String delim;
451 output String str;
452 protected
453 list<String> lst1;
454 algorithm
455 75 lst1 := List.select(lst, isNotEmptyString);
456 75 str := stringDelimitList(lst1, delim);
457 end stringDelimitListNonEmptyElts;
458
459 public function mulStringDelimit2Int
460 " splits the input string at the delimiter string in list of strings and converts to integer list which is then summarized
461 "
462 input String inString;
463 input String delim;
464 output Integer i;
465 protected
466 list<String> lst;
467 list<Integer> lst2;
468 algorithm
469 1341 lst:=stringSplitAtChar(inString,delim);
470 1341 lst2:=List.map(lst, stringInt);
471
1/2
✓ Branch 0 taken 1341 times.
✗ Branch 1 not taken.
1341 if not listEmpty(lst2) then
472 1341 i := List.fold(lst2,intMul,1);
473 else
474 i := 0;
475 end if;
476 end mulStringDelimit2Int;
477
478 public function stringReplaceChar "Takes a string and two chars and replaces the first char with the second char:
479 Example: string_replace_char(\"hej.b.c\",\".\",\"_\") => \"hej_b_c\"
480 2007-11-26 BZ: Now it is possible to replace chars with emptychar, and
481 replace a char with a string
482 Example: string_replace_char(\"hej.b.c\",\".\",\"_dot_\") => \"hej_dot_b_dot_c\"
483 "
484 input String inString1;
485 input String inString2;
486 input String inString3;
487 output String outString;
488 algorithm
489 18419 outString := System.stringReplace(inString1, inString2, inString3);
490 end stringReplaceChar;
491
492 public function stringSplitAtChar "Takes a string and a char and split the string at the char returning the list of components.
493 Example: stringSplitAtChar(\"hej.b.c\",\".\") => {\"hej,\"b\",\"c\"}"
494 input String string;
495 input String token;
496 output list<String> strings = {};
497 protected
498 Integer ch = stringCharInt(token);
499 list<String> cur = {};
500 algorithm
501
2/2
✓ Branch 1 taken 128372 times.
✓ Branch 2 taken 4164 times.
132536 for c in stringListStringChar(string) loop
502
2/2
✓ Branch 1 taken 10295 times.
✓ Branch 2 taken 118077 times.
128372 if stringCharInt(c) == ch then
503 10295 strings := stringAppendList(listReverse(cur)) :: strings;
504 cur := {};
505 else
506 cur := c :: cur;
507 end if;
508 end for;
509
2/2
✓ Branch 0 taken 4098 times.
✓ Branch 1 taken 66 times.
4164 if not listEmpty(cur) then
510 4098 strings := stringAppendList(listReverse(cur)) :: strings;
511 end if;
512 4164 strings := listReverse(strings);
513 end stringSplitAtChar;
514
515 public function optionToString<T>
516 input Option<T> ot;
517 input FuncType f;
518 output String str;
519 partial function FuncType
520 input T t;
521 output String str;
522 end FuncType;
523 protected
524 T t;
525 algorithm
526 str := match ot
527 ✗ case SOME(t) then "SOME(" + f(t) + ")";
528 else "NONE()";
529 end match;
530 end optionToString;
531
532 public function applyOption<TI, TO>
533 "Takes an option value and a function over the value. It returns in another
534 option value, resulting from the application of the function on the value.
535
536 Example:
537 applyOption(SOME(1), intString) => SOME(\"1\")
538 applyOption(NONE(), intString) => NONE()
539 "
540 input Option<TI> inOption;
541 input FuncType inFunc;
542 output Option<TO> outOption;
543
544 partial function FuncType
545 input TI inValue;
546 output TO outValue;
547 end FuncType;
548 algorithm
549 outOption := match inOption
550 local
551 TI ival;
552
553
2/2
✓ Branch 0 taken 53382 times.
✓ Branch 1 taken 19672125 times.
19725507 case SOME(ival) then SOME(inFunc(ival));
554 else NONE();
555 end match;
556 end applyOption;
557
558 public function applyOption1<TI, TO, ArgT>
559 "Like applyOption but takes an additional argument"
560 input Option<TI> inOption;
561 input FuncType inFunc;
562 input ArgT inArg;
563 output Option<TO> outOption;
564
565 partial function FuncType
566 input TI inValue;
567 input ArgT inArg;
568 output TO outValue;
569 end FuncType;
570 algorithm
571 outOption := match inOption
572 local
573 TI ival;
574
575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 case SOME(ival) then SOME(inFunc(ival, inArg));
576 else NONE();
577 end match;
578 end applyOption1;
579
580 public function applyOptionOrDefault<TI, TO>
581 "Takes an optional value, a function and an extra value. If the optional value
582 is SOME, applies the function on that value and returns the result.
583 Otherwise returns the extra value."
584 input Option<TI> inValue;
585 input FuncType inFunc;
586 input TO inDefaultValue;
587 output TO outValue;
588
589 partial function FuncType
590 input TI inValue;
591 output TO outValue;
592 end FuncType;
593 algorithm
594 outValue := match inValue
595 local
596 TI value;
597
598
2/2
✓ Branch 0 taken 650 times.
✓ Branch 1 taken 48336 times.
48986 case SOME(value) then inFunc(value);
599 else inDefaultValue;
600 end match;
601 end applyOptionOrDefault;
602
603 public function applyOptionOrDefault1<TI, TO, ArgT>
604 "Takes an optional value, a function, an extra argument and an extra value.
605 If the optional value is SOME, applies the function on that value and the
606 extra argument and returns the result. Otherwise returns the extra value."
607 input Option<TI> inValue;
608 input FuncType inFunc;
609 input ArgT inArg;
610 input TO inDefaultValue;
611 output TO outValue;
612
613 partial function FuncType
614 input TI inValue;
615 input ArgT inArg;
616 output TO outValue;
617 end FuncType;
618 algorithm
619 outValue := match inValue
620 local
621 TI value;
622
623 ✗ case SOME(value) then inFunc(value, inArg);
624 else inDefaultValue;
625 end match;
626 end applyOptionOrDefault1;
627
628 public function applyOptionOrDefault2<TI, TO, ArgT1, ArgT2>
629 "Takes an optional value, a function, two extra arguments and an extra value.
630 If the optional value is SOME, applies the function on that value and the
631 extra argument and returns the result. Otherwise returns the extra value."
632 input Option<TI> inValue;
633 input FuncType inFunc;
634 input ArgT1 inArg1;
635 input ArgT2 inArg2;
636 input TO inDefaultValue;
637 output TO outValue;
638
639 partial function FuncType
640 input TI inValue;
641 input ArgT1 inArg1;
642 input ArgT2 inArg2;
643 output TO outValue;
644 end FuncType;
645 algorithm
646 outValue := match inValue
647 local
648 TI value;
649
650 ✗ case SOME(value) then inFunc(value, inArg1, inArg2);
651 else inDefaultValue;
652 end match;
653 end applyOptionOrDefault2;
654
655 public function applyOption_2<T>
656 input Option<T> inValue1;
657 input Option<T> inValue2;
658 input FuncType inFunc;
659 output Option<T> outValue;
660
661 partial function FuncType
662 input T inValue1;
663 input T inValue2;
664 output T outValue;
665 end FuncType;
666 algorithm
667 outValue := match (inValue1, inValue2)
668 case (NONE(), _) then inValue2;
669 case (_, NONE()) then inValue1;
670 ✗ else SOME(inFunc(getOption(inValue1), getOption(inValue2)));
671 end match;
672 end applyOption_2;
673
674 public function makeOption<T>
675 "Makes a value into value option, using SOME(value)"
676 input T inValue;
677 output Option<T> outOption = SOME(inValue);
678 annotation(__OpenModelica_EarlyInline = true);
679 end makeOption;
680
681 public function makeOptionOnTrue<T>
682 input Boolean inCondition;
683 input T inValue;
684 output Option<T> outOption = if inCondition then SOME(inValue) else NONE();
685 annotation(__OpenModelica_EarlyInline = true);
686 end makeOptionOnTrue;
687
688 public function getOption<T>
689 "Returns an option value if SOME, otherwise fails"
690 input Option<T> inOption;
691 output T outValue;
692 algorithm
693
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9849051 times.
✓ Branch 2 taken 1087175 times.
✓ Branch 3 taken 8761876 times.
9849051 SOME(outValue) := inOption;
694 end getOption;
695
696 public function getOptionOrDefault<T>
697 "Returns an option value if SOME, otherwise the default"
698 input Option<T> inOption;
699 input T inDefault;
700 output T outValue;
701 algorithm
702 outValue := match inOption
703 local
704 T value;
705
706 case SOME(value) then value;
707 else inDefault;
708 end match;
709 end getOptionOrDefault;
710
711 public function intGreaterZero
712 "Returns true if integer value is greater zero (> 0)"
713 input Integer v;
714 output Boolean res = v > 0;
715 end intGreaterZero;
716
717 public function intPositive
718 "Returns true if integer value is positive (>= 0)"
719 input Integer v;
720 output Boolean res = v >= 0;
721 end intPositive;
722
723 public function intNegative
724 "Returns true if integer value is negative (< 0)"
725 input Integer v;
726 output Boolean res = v < 0;
727 end intNegative;
728
729 public function intSign
730 input Integer i;
731 output Integer o = if i == 0 then 0 elseif i > 0 then 1 else -1;
732 end intSign;
733
734 public function intCompare
735 "Compares two integers and return -1 if the first is smallest, 1 if the second
736 is smallest, or 0 if they are equal."
737 input Integer inN;
738 input Integer inM;
739 output Integer outResult = if inN == inM then 0 elseif inN > inM then 1 else -1;
740 end intCompare;
741
742 public function intPow
743 "Performs integer exponentiation."
744 input Integer base;
745 input Integer exponent;
746 output Integer result = 1;
747 algorithm
748
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if exponent >= 0 then
749
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for i in 1:exponent loop
750 8 result := result * base;
751 end for;
752 else
753 ✗ fail();
754 end if;
755 end intPow;
756
757 public function realNegative
758 "Returns true if the Real value is negative, otherwise false."
759 input Real v;
760 output Boolean res = v < 0;
761 end realNegative;
762
763 public function realCompare
764 "Compares two reals and return -1 if the first is smallest, 1 if the second
765 is smallest, or 0 if they are equal."
766 input Real inN;
767 input Real inM;
768 output Integer outResult = if inN == inM then 0 elseif inN > inM then 1 else -1;
769 end realCompare;
770
771 public function boolCompare
772 "Compares two booleans and return -1 if the first is smallest, 1 if the second
773 is smallest, or 0 if they are equal."
774 input Boolean inN;
775 input Boolean inM;
776 output Integer outResult = if inN == inM then 0 elseif inN > inM then 1 else -1;
777 end boolCompare;
778
779 public function isNotEmptyString "Returns true if string is not the empty string."
780 input String inString;
781 output Boolean outIsNotEmpty = stringLength(inString) > 0;
782 end isNotEmptyString;
783
784 public function writeFileOrErrorMsg "This function tries to write to a file and if it fails then it
785 outputs \"# Cannot write to file: <filename>.\" to errorBuf"
786 input String inFilename;
787 input String inString;
788 algorithm
789 try
790 ✗ System.writeFile(inFilename, inString);
791 else
792 ✗ Print.printErrorBuf("# Cannot write to file: " + inFilename + ".");
793 end try;
794 end writeFileOrErrorMsg;
795
796 public function strncmp "Compare two strings up to the nth character
797 Returns true if they are equal."
798 input String inString1;
799 input String inString2;
800 input Integer inLength;
801 output Boolean outEqual;
802 algorithm
803 ✗ outEqual := (0 == System.strncmp(inString1, inString2, inLength));
804 end strncmp;
805
806 public function notStrncmp
807 "Compares two strings up to the nth character. Returns true if they are not
808 equal."
809 input String inString1;
810 input String inString2;
811 input Integer inLength;
812 output Boolean outEqual;
813 algorithm
814 34155 outEqual := (0 <> System.strncmp(inString1, inString2, inLength));
815 end notStrncmp;
816
817 public function tickStr "author: PA
818 Returns tick as a string, i.e. an unique number."
819 output String s = intString(tick());
820 end tickStr;
821
822 public function replaceWindowsBackSlashWithPathDelimiter
823 "@author: adrpo
824 replace \\ with path delimiter only in Windows!"
825 input String inPath;
826 output String outPath;
827 algorithm
828 if Autoconf.os == "Windows_NT" then
829 outPath := System.stringReplace(inPath, "\\", Autoconf.pathDelimiter);
830 else
831 outPath := inPath;
832 end if;
833 end replaceWindowsBackSlashWithPathDelimiter;
834
835 public function getAbsoluteDirectoryAndFile "author: x02lucpo
836 splits the filepath in directory and filename
837 (\"c:\\programs\\file.mo\") => (\"c:\\programs\",\"file.mo\")
838 (\"..\\work\\file.mo\") => (\"c:\\openmodelica123\\work\", \"file.mo\")"
839 input String filename;
840 output String dirname;
841 output String basename;
842 protected
843 String realpath;
844 algorithm
845 2026 realpath := System.realpath(filename);
846 2026 dirname := System.dirname(realpath);
847 2026 basename := System.basename(realpath);
848 2026 dirname := replaceWindowsBackSlashWithPathDelimiter(dirname);
849 end getAbsoluteDirectoryAndFile;
850
851 public function rawStringToInputString "author: x02lucpo
852 replace the double-backslash with backslash"
853 input String inString;
854 output String outString;
855 algorithm
856 ✗ outString := System.stringReplace(inString, "\\\"", "\"") "change backslash-double-quote to double-quote ";
857 ✗ outString := System.stringReplace(outString, "\\\\", "\\") "double-backslash with backslash ";
858 end rawStringToInputString;
859
860 public function escapeModelicaStringToCString
861 input String modelicaString;
862 output String cString;
863 algorithm
864 // C cannot handle newline in string constants
865 238842 cString := System.escapedString(modelicaString,true);
866 end escapeModelicaStringToCString;
867
868 public function escapeModelicaStringToJLString
869 input String modelicaString;
870 output String cString;
871 algorithm
872 //TODO. Do this the proper way. We just remove all the dollars for now
873 ✗ cString := System.stringReplace(modelicaString, "$", "");
874 ✗ cString := System.stringReplace(cString, "\"", "");
875 ✗ cString := System.stringReplace(cString, "\"", "");
876 ✗ cString := System.stringReplace(cString, "\"\"", "");
877 ✗ cString := System.escapedString(cString,true);
878 end escapeModelicaStringToJLString;
879
880 public function escapeModelicaStringToXmlString
881 input String modelicaString;
882 output String xmlString;
883 algorithm
884 // C cannot handle newline in string constants
885 43343 xmlString := System.stringReplace(modelicaString, "&", "&amp;");
886 43343 xmlString := System.stringReplace(xmlString, "\"", "&quot;");
887 43343 xmlString := System.stringReplace(xmlString, "<", "&lt;");
888 43343 xmlString := System.stringReplace(xmlString, ">", "&gt;");
889 43343 xmlString := System.stringReplace(xmlString, "\n", "&#10;");
890 43343 xmlString := System.stringReplace(xmlString, "\r", "&#13;");
891 // TODO! FIXME!, we have issues with accented chars in comments
892 // that end up in the Model_init.xml file and makes it not well
893 // formed but the line below does not work if the xmlString is
894 // already UTF-8. We should somehow detect the encoding.
895 // xmlString := System.iconv(xmlString, "", "UTF-8");
896 end escapeModelicaStringToXmlString;
897
898 public function makeQuotedIdentifier
899 input String str;
900 output String quotedIdentifier;
901 algorithm
902 544 quotedIdentifier := System.stringReplace(str, "\\", "\\\\");
903 544 quotedIdentifier := System.stringReplace(quotedIdentifier, "'", "\\'");
904 544 quotedIdentifier := "'" + quotedIdentifier + "'";
905 end makeQuotedIdentifier;
906
907 public function escapeQuotes
908 input String str;
909 output String quotes;
910 algorithm
911 5745 quotes := System.stringReplace(str, "\\", "\\\\");
912 5745 quotes := System.stringReplace(quotes, "'", "\\'");
913 end escapeQuotes;
914
915 public function makeTuple<T1, T2>
916 input T1 inValue1;
917 input T2 inValue2;
918 output tuple<T1, T2> outTuple = (inValue1, inValue2);
919 annotation(__OpenModelica_EarlyInline = true);
920 end makeTuple;
921
922 public function makeTupleR<T1, T2>
923 input T1 inValue1;
924 input T2 inValue2;
925 output tuple<T2, T1> outTuple = (inValue2, inValue1);
926 annotation(__OpenModelica_EarlyInline = true);
927 end makeTupleR;
928
929 public function make3Tuple<T1, T2, T3>
930 input T1 inValue1;
931 input T2 inValue2;
932 input T3 inValue3;
933 output tuple<T1, T2, T3> outTuple = (inValue1, inValue2, inValue3);
934 annotation(__OpenModelica_EarlyInline = true);
935 end make3Tuple;
936
937 public function mulListIntegerOpt
938 input list<Option<Integer>> inList;
939 input Integer inAccum = 1;
940 output Integer outResult;
941 algorithm
942 outResult := match inList
943 local
944 Integer i;
945 list<Option<Integer>> rest;
946
947 case {} then inAccum;
948 ✗ case SOME(i) :: rest then mulListIntegerOpt(rest, i * inAccum);
949 ✗ case NONE() :: rest then mulListIntegerOpt(rest, inAccum);
950 end match;
951 end mulListIntegerOpt;
952
953 public type StatefulBoolean = array<Boolean> "A single boolean value that can be updated (a destructive operation). NOTE: Use Mutable<Boolean> instead. This implementation is kept since Susan cannot use that type.";
954
955 public function makeStatefulBoolean
956 "Create a boolean with state (that is, it is mutable)"
957 input Boolean b;
958 output StatefulBoolean sb = arrayCreate(1, b);
959 end makeStatefulBoolean;
960
961 public function getStatefulBoolean
962 "Create a boolean with state (that is, it is mutable)"
963 input StatefulBoolean sb;
964 output Boolean b = sb[1];
965 end getStatefulBoolean;
966
967 public function setStatefulBoolean
968 "Update the state of a mutable boolean"
969 input StatefulBoolean sb;
970 input Boolean b;
971 algorithm
972
2/2
✓ Branch 0 taken 1484 times.
✓ Branch 1 taken 162 times.
3130 arrayUpdate(sb,1,b);
973 end setStatefulBoolean;
974
975 public function optionEqual<T1, T2>
976 "Takes two options and a function to compare the type."
977 input Option<T1> inOption1;
978 input Option<T2> inOption2;
979 input CompareFunc inFunc;
980 output Boolean outEqual;
981
982 partial function CompareFunc
983 input T1 inValue1;
984 input T2 inValue2;
985 output Boolean outEqual;
986 end CompareFunc;
987 algorithm
988 outEqual := match(inOption1, inOption2)
989 local
990 T1 val1;
991 T2 val2;
992
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 case (SOME(val1), SOME(val2)) then inFunc(val1, val2);
993 case (NONE(), NONE()) then true;
994 else false;
995 end match;
996 end optionEqual;
997
998 public function makeValueOrDefault<TI, TO>
999 "Returns the value if the function call succeeds, otherwise the default"
1000 input FuncType inFunc;
1001 input TI inArg;
1002 input TO inDefaultValue;
1003 output TO outValue;
1004
1005 partial function FuncType
1006 input TI inValue;
1007 output TO outValue;
1008 end FuncType;
1009 algorithm
1010 try
1011
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 665 times.
665 outValue := inFunc(inArg);
1012 else
1013 outValue := inDefaultValue;
1014 end try;
1015 end makeValueOrDefault;
1016
1017 public function xmlEscape "Escapes a String so that it can be used in xml"
1018 input String s1;
1019 output String s2;
1020 algorithm
1021 3306 s2 := stringReplaceChar(s1,"&","&amp;");
1022 3306 s2 := stringReplaceChar(s2,"<","&lt;");
1023 3306 s2 := stringReplaceChar(s2,">","&gt;");
1024 3306 s2 := stringReplaceChar(s2,"\"","&quot;");
1025 end xmlEscape;
1026
1027 public function strcmpBool
1028 "As strcmp, but has Boolean output as is expected by the sort function"
1029 input String s1;
1030 input String s2;
1031 output Boolean b = stringCompare(s1, s2) > 0;
1032 end strcmpBool;
1033
1034 public function strcmpNoCaseBool
1035 "String compare, but ignoring case.
1036 Boolean output as is expected by the sort function"
1037 input String s1;
1038 input String s2;
1039 output Boolean b = stringCompare(System.tolower(s1), System.tolower(s2)) > 0;
1040 end strcmpNoCaseBool;
1041
1042 public function stringAppendReverse
1043 "@author: adrpo
1044 This function will append the first string to the second string"
1045 input String str1;
1046 input String str2;
1047 output String str = stringAppend(str2, str1);
1048 end stringAppendReverse;
1049
1050 public function stringAppendNonEmpty
1051 input String inString1;
1052 input String inString2;
1053 output String outString;
1054 algorithm
1055 outString := match inString2
1056 case "" then inString2;
1057 ✗ else stringAppend(inString1, inString2);
1058 end match;
1059 end stringAppendNonEmpty;
1060
1061 public function getCurrentDateTime
1062 output DateTime dt;
1063 protected
1064 Integer sec;
1065 Integer min;
1066 Integer hour;
1067 Integer mday;
1068 Integer mon;
1069 Integer year;
1070 algorithm
1071 1217 (sec,min,hour,mday,mon,year) := System.getCurrentDateTime();
1072 1217 dt := DATETIME(sec,min,hour,mday,mon,year);
1073 end getCurrentDateTime;
1074
1075 public function isSuccess
1076 input Status status;
1077 output Boolean bool;
1078 algorithm
1079 bool := match status
1080 case SUCCESS() then true;
1081 case FAILURE() then false;
1082 end match;
1083 end isSuccess;
1084
1085 public function id<T>
1086 input T inValue;
1087 output T outValue = inValue;
1088 end id;
1089
1090 public function buildMapStr "Takes two lists of the same type and builds a string like x = val1, y = val2, ....
1091 Example: listThread({1,2,3},{4,5,6},'=',',') => 1=4, 2=5, 3=6"
1092 input list<String> inLst1;
1093 input list<String> inLst2;
1094 input String inMiddleDelimiter;
1095 input String inEndDelimiter;
1096 output String outStr;
1097 algorithm
1098 outStr := match (inLst1, inLst2, inMiddleDelimiter, inEndDelimiter)
1099 local
1100 list<String> ra,rb;
1101 String fa,fb, md, ed, str;
1102
1103 case ({}, {}, _, _) then "";
1104
1105 case ({fa}, {fb}, md, _)
1106 algorithm
1107 1211 str := stringAppendList({fa, md, fb});
1108 then
1109 str;
1110
1111 case (fa :: ra, fb :: rb, md, ed)
1112 algorithm
1113 12110 str := buildMapStr(ra, rb, md, ed);
1114 12110 str := stringAppendList({fa, md, fb, ed, str});
1115 then
1116 str;
1117
1118 end match;
1119 end buildMapStr;
1120
1121 public function assoc<Key, Val>
1122 "assoc(key,lst) => value, where lst is a tuple of (key,value) pairs.
1123 Does linear search using equality(). This means it is slow for large
1124 inputs (many elements or large elements); if you have large inputs, you
1125 should use a hash-table instead."
1126 input Key inKey;
1127 input list<tuple<Key,Val>> inList;
1128 output Val outValue;
1129 protected
1130 Key k;
1131 Val v;
1132 algorithm
1133 130960 (k, v) := listHead(inList);
1134
2/2
✓ Branch 1 taken 61355 times.
✓ Branch 2 taken 64335 times.
125690 outValue := if valueEq(inKey, k) then v else assoc(inKey, listRest(inList));
1135 end assoc;
1136
1137 public function boolInt
1138 "Returns 1 if the given boolean is true, otherwise 0."
1139 input Boolean inBoolean;
1140 output Integer outInteger = if inBoolean then 1 else 0;
1141 end boolInt;
1142
1143 public function intBool
1144 "Returns true if the given integer is larger than 0, otherwise false."
1145 input Integer inInteger;
1146 output Boolean outBoolean = inInteger > 0;
1147 end intBool;
1148
1149 public function stringBool
1150 "Converts a string to a boolean value. true and yes is converted to true,
1151 false and no is converted to false. The function is case-insensitive."
1152 input String inString;
1153 output Boolean outBoolean;
1154 algorithm
1155 38 outBoolean := stringBool2(System.tolower(inString));
1156 end stringBool;
1157
1158 protected function stringBool2
1159 "Helper function to stringBool."
1160 input String inString;
1161 output Boolean outBoolean;
1162 algorithm
1163 outBoolean := match inString
1164 case "true" then true;
1165 case "false" then false;
1166 case "yes" then true;
1167 case "no" then false;
1168 end match;
1169 end stringBool2;
1170
1171 public function stringEqCaseInsensitive
1172 input String str1, str2;
1173 output Boolean eq;
1174 algorithm
1175 ✗ eq := stringEq(System.tolower(str1), System.tolower(str2));
1176 end stringEqCaseInsensitive;
1177
1178 public function stringPadRight
1179 "Pads a string with the given padding so that the resulting string is as long
1180 as the given width. If the string is already longer nothing is done to it.
1181 Note that the length of the padding is assumed to be one, i.e. a single char."
1182 input String inString;
1183 input Integer inPadWidth;
1184 input String inPadString;
1185 output String outString;
1186 protected
1187 Integer pad_length;
1188 String pad_str;
1189 algorithm
1190 ✗ pad_length := inPadWidth - stringLength(inString);
1191
1192 ✗ if pad_length > 0 then
1193 ✗ pad_str := stringAppendList(list(inPadString for i in 1:pad_length));
1194 ✗ outString := inString + pad_str;
1195 else
1196 outString := inString;
1197 end if;
1198 end stringPadRight;
1199
1200 public function stringPadLeft
1201 "Pads a string with the given padding so that the resulting string is as long
1202 as the given width. If the string is already longer nothing is done to it.
1203 Note that the length of the padding is assumed to be one, i.e. a single char."
1204 input String inString;
1205 input Integer inPadWidth;
1206 input String inPadString;
1207 output String outString;
1208 protected
1209 Integer pad_length;
1210 String pad_str;
1211 algorithm
1212 ✗ pad_length := inPadWidth - stringLength(inString);
1213
1214 ✗ if pad_length > 0 then
1215 ✗ pad_str := stringAppendList(list(inPadString for i in 1:pad_length));
1216 ✗ outString := pad_str + inString;
1217 else
1218 outString := inString;
1219 end if;
1220 end stringPadLeft;
1221
1222 public function intProduct
1223 input list<Integer> lst;
1224 output Integer i = List.fold(lst, intMul, 1);
1225 end intProduct;
1226
1227 public function nextPrime
1228 "Given a positive integer, returns the closest prime number that is equal or
1229 larger. This algorithm checks every odd number larger than the given number
1230 until it finds a prime, but since the distance between primes is relatively
1231 small (the largest gap between primes up to 32 bit is only around 300) it's
1232 still reasonably fast. It's useful for e.g. determining a good size for a
1233 hash table with a known number of elements."
1234 input Integer inN;
1235 output Integer outNextPrime;
1236 algorithm
1237
2/2
✓ Branch 0 taken 340010 times.
✓ Branch 1 taken 131452 times.
471462 outNextPrime := if inN <= 2 then 2 else nextPrime2(inN + intMod(inN + 1, 2));
1238 end nextPrime;
1239
1240 protected function nextPrime2
1241 "Helper function to nextPrime2, does the actual work of finding the next
1242 prime."
1243 input Integer inN;
1244 output Integer outNextPrime;
1245 algorithm
1246
2/2
✓ Branch 1 taken 340010 times.
✓ Branch 2 taken 24043 times.
364053 outNextPrime := if nextPrime_isPrime(inN) then inN else nextPrime2(inN + 2);
1247 end nextPrime2;
1248
1249 protected function nextPrime_isPrime
1250 "Helper function to nextPrime2, checks if a given number is a prime or not.
1251 Note that this function is not a general prime checker, it only works for
1252 positive odd numbers."
1253 input Integer inN;
1254 output Boolean outIsPrime;
1255 protected
1256 Integer i = 3, q = intDiv(inN, 3);
1257 algorithm
1258 // Check all factors up to sqrt(inN)
1259
2/2
✓ Branch 0 taken 446546 times.
✓ Branch 1 taken 340010 times.
786556 while q >= i loop
1260 // The number is divisible by a factor => not a prime.
1261
2/2
✓ Branch 0 taken 24043 times.
✓ Branch 1 taken 422503 times.
446546 if inN == q * i then
1262 outIsPrime := false;
1263 24043 return;
1264 end if;
1265
1266 422503 i := i + 2;
1267 422503 q := intDiv(inN, i);
1268 end while;
1269
1270 // All factors have been checked, inN is a prime.
1271 outIsPrime := true;
1272 end nextPrime_isPrime;
1273
1274 public function anyToEmptyString<T> "Useful if you do not want to write an unparser"
1275 input T a;
1276 output String empty = "";
1277 end anyToEmptyString;
1278
1279 public function removeLast3Char
1280 input String str;
1281 output String outStr;
1282 algorithm
1283 1063677 outStr := substring(str,1,stringLength(str)-3);
1284 end removeLast3Char;
1285
1286 public function removeLast4Char
1287 input String str;
1288 output String outStr;
1289 algorithm
1290 4 outStr := substring(str,1,stringLength(str)-4);
1291 end removeLast4Char;
1292
1293 public function removeLastNChar
1294 input String str;
1295 input Integer n;
1296 output String outStr;
1297 algorithm
1298 2251 outStr := substring(str,1,stringLength(str)-n);
1299 end removeLastNChar;
1300
1301 public function stringNotEqual
1302 input String str1;
1303 input String str2;
1304 output Boolean b = not stringEq(str1,str2);
1305 end stringNotEqual;
1306
1307 public function swap<T>
1308 input Boolean cond;
1309 input T in1;
1310 input T in2;
1311 output T out1;
1312 output T out2;
1313 algorithm
1314 (out1,out2) := match cond
1315 case true then (in2, in1);
1316 else (in1, in2);
1317 end match;
1318 end swap;
1319
1320 function replace<T>
1321 input T replaced;
1322 input T arg;
1323 output T outArg = arg;
1324 end replace;
1325
1326 public function realRangeSize
1327 "Calculates the size of a Real range given the start, step and stop values."
1328 input Real inStart;
1329 input Real inStep;
1330 input Real inStop;
1331 output Integer outSize;
1332 algorithm
1333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
199 outSize := integer(floor(((inStop - inStart) / inStep) + 5e-15)) + 1;
1334 outSize := max(outSize, 0);
1335 end realRangeSize;
1336
1337 protected function createDirectoryTreeH
1338 input String inString;
1339 input String parentDir;
1340 input Boolean parentDirExists;
1341 output Boolean outBool;
1342 algorithm
1343 outBool := matchcontinue parentDirExists
1344 local
1345 Boolean b;
1346
1347 case _
1348 algorithm
1349 // this is because System.dirname(".openmodelica") != ".openmodelica"
1350 // System.dirname(".openmodelica") = "." on Windows!
1351
3/4
✓ Branch 1 taken 83 times.
✓ Branch 2 taken 1280 times.
✓ Branch 5 taken 83 times.
✗ Branch 6 not taken.
1363 true := stringEqual(parentDir, System.dirname(parentDir));
1352 83 b := System.createDirectory(inString);
1353 then b;
1354
1355 case true
1356 algorithm
1357 1094 b := System.createDirectory(inString);
1358 then b;
1359
1360 case false
1361 algorithm
1362
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 186 times.
186 true := createDirectoryTree(parentDir);
1363 186 b := System.createDirectory(inString);
1364 then b;
1365
1366 else false;
1367 end matchcontinue;
1368 end createDirectoryTreeH;
1369
1370 public function createDirectoryTree
1371 input String inString;
1372 output Boolean outBool;
1373 protected
1374 String parentDir;
1375 Boolean parentDirExists;
1376 algorithm
1377 // if is already there, just retrun true!
1378
2/2
✓ Branch 1 taken 1363 times.
✓ Branch 2 taken 4 times.
1367 if System.directoryExists(inString) then
1379 outBool := true;
1380 else
1381 1363 parentDir := System.dirname(inString);
1382 1363 parentDirExists := System.directoryExists(parentDir);
1383 1363 outBool := createDirectoryTreeH(inString,parentDir,parentDirExists);
1384 end if;
1385 end createDirectoryTree;
1386
1387 public function nextPowerOf2
1388 "Rounds up to the nearest power of 2"
1389 input Integer i;
1390 output Integer v;
1391 algorithm
1392 ✗ v := i - 1;
1393 ✗ v := intBitOr(v, intBitRShift(v, 1));
1394 ✗ v := intBitOr(v, intBitRShift(v, 2));
1395 ✗ v := intBitOr(v, intBitRShift(v, 4));
1396 ✗ v := intBitOr(v, intBitRShift(v, 8));
1397 ✗ v := intBitOr(v, intBitRShift(v, 16));
1398 ✗ v := v + 1;
1399 end nextPowerOf2;
1400
1401 public function isCIdentifier
1402 input String str;
1403 output Boolean b;
1404 protected
1405 Integer i;
1406 algorithm
1407 1168 (i,_) := System.regex(str, "^[_A-Za-z][_A-Za-z0-9]*$", 0, true, false);
1408 1168 b := i == 1;
1409 end isCIdentifier;
1410
1411 public function isIntegerString
1412 input String str;
1413 output Boolean b;
1414 protected
1415 Integer i;
1416 algorithm
1417 ✗ (i,_) := System.regex(str, "^[0-9][0-9]*$", 0, true, false);
1418 ✗ b := i == 1;
1419 end isIntegerString;
1420
1421 public function stringTrunc
1422 "@author:adrpo
1423 if the string is bigger than len keep only until len
1424 if not, return the same string"
1425 input String str;
1426 input Integer len;
1427 output String truncatedStr;
1428 algorithm
1429 ✗ truncatedStr := if stringLength(str) <= len then str else substring(str, 0, len);
1430 end stringTrunc;
1431
1432 public function getTempVariableIndex "Create an iterator or the like with a unique name"
1433 output String name;
1434 algorithm
1435 3223 name := stringAppend("$tmpVar",intString(System.tmpTickIndex(Global.tmpVariableIndex)));
1436 end getTempVariableIndex;
1437
1438 public function anyReturnTrue<T>
1439 input T a;
1440 output Boolean b = true;
1441 end anyReturnTrue;
1442
1443 public function absoluteOrRelative
1444 "@author: adrpo
1445 returns the given path if it exists
1446 if not it considers it relative and if it exists returns that
1447 if the releative path does not exists it returns the given path"
1448 input String inFileName;
1449 output String outFileName = inFileName;
1450 protected
1451 String pwd, pd, f;
1452 algorithm
1453 1385 pwd := System.pwd();
1454 pd := Autoconf.pathDelimiter;
1455
2/2
✓ Branch 1 taken 976 times.
✓ Branch 2 taken 409 times.
1385 if not System.regularFileExists(inFileName) then
1456 409 f := stringAppendList({pwd,pd,inFileName});
1457
1/2
✓ Branch 1 taken 409 times.
✗ Branch 2 not taken.
409 outFileName := if System.regularFileExists(f) then f else outFileName;
1458 end if;
1459 end absoluteOrRelative;
1460
1461 public function hashFileNamePrefix
1462 input String inFileNamePrefix;
1463 output String hashStr = substring(intString(stringHashDjb2(inFileNamePrefix)), 1, 3);
1464 end hashFileNamePrefix;
1465
1466 public function intLstString
1467 input list<Integer> lst;
1468 output String s;
1469 algorithm
1470 1 s := stringDelimitList(List.map(lst,intString),", ");
1471 end intLstString;
1472
1473 public function sourceInfoIsEmpty
1474 "Returns whether the given SourceInfo is empty or not."
1475 input SourceInfo inInfo;
1476 output Boolean outIsEmpty;
1477 algorithm
1478 outIsEmpty := match inInfo
1479 case SOURCEINFO(fileName = "") then true;
1480 else false;
1481 end match;
1482 end sourceInfoIsEmpty;
1483
1484 public function sourceInfoIsEqual
1485 "Returns whether two SourceInfo are equal or not."
1486 input SourceInfo inInfo1;
1487 input SourceInfo inInfo2;
1488 output Boolean outIsEqual;
1489 algorithm
1490 outIsEqual := match (inInfo1, inInfo2)
1491 case (SOURCEINFO(), SOURCEINFO())
1492
9/14
✓ Branch 0 taken 1939 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 1939 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1939 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1933 times.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 1933 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1933 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 1933 times.
1941 then inInfo1.fileName == inInfo2.fileName and
1493 inInfo1.isReadOnly == inInfo2.isReadOnly and
1494 inInfo1.lineNumberStart == inInfo2.lineNumberStart and
1495 inInfo1.columnNumberStart == inInfo2.columnNumberStart and
1496 inInfo1.lineNumberEnd == inInfo2.lineNumberEnd and
1497 inInfo1.columnNumberEnd == inInfo2.columnNumberEnd;
1498
1499 else false;
1500 end match;
1501 end sourceInfoIsEqual;
1502
1503 /*************************************************
1504 * profiler stuff
1505 ************************************************/
1506 public
1507
1508 function profilerinit
1509 algorithm
1510 ✗ setGlobalRoot(Global.profilerTime1Index, 0.0);
1511 ✗ setGlobalRoot(Global.profilerTime2Index, 0.0);
1512 ✗ System.realtimeTick(ClockIndexes.RT_PROFILER0);
1513 end profilerinit;
1514
1515 function profilerresults
1516 protected
1517 Real tg,t1,t2;
1518 algorithm
1519 ✗ tg := System.realtimeTock(ClockIndexes.RT_PROFILER0);
1520 ✗ t1 := profilertime1();
1521 ✗ t2 := profilertime2();
1522 ✗ print("Time all: "); print(realString(tg)); print("\n");
1523 ✗ print("Time t1: "); print(realString(t1)); print("\n");
1524 ✗ print("Time t2: "); print(realString(t2)); print("\n");
1525 ✗ print("Time all-t1-t2: "); print(realString(realSub(realSub(tg,t1),t2))); print("\n");
1526 end profilerresults;
1527
1528 function profilertime1
1529 output Real t1;
1530 algorithm
1531 ✗ t1 := getGlobalRoot(Global.profilerTime1Index);
1532 end profilertime1;
1533
1534 function profilertime2
1535 output Real t2;
1536 algorithm
1537 ✗ t2 := getGlobalRoot(Global.profilerTime2Index);
1538 end profilertime2;
1539
1540 function profilerstart1
1541 algorithm
1542 ✗ System.realtimeTick(ClockIndexes.RT_PROFILER1);
1543 end profilerstart1;
1544
1545 function profilerstart2
1546 algorithm
1547 ✗ System.realtimeTick(ClockIndexes.RT_PROFILER2);
1548 end profilerstart2;
1549
1550 function profilerstop1
1551 protected
1552 Real t;
1553 algorithm
1554 ✗ t := System.realtimeTock(ClockIndexes.RT_PROFILER1);
1555 ✗ setGlobalRoot(Global.profilerTime1Index,
1556 realAdd(getGlobalRoot(Global.profilerTime1Index),t));
1557 end profilerstop1;
1558
1559 function profilerstop2
1560 protected
1561 Real t;
1562 algorithm
1563 ✗ t := System.realtimeTock(ClockIndexes.RT_PROFILER2);
1564 ✗ setGlobalRoot(Global.profilerTime2Index,
1565 realAdd(getGlobalRoot(Global.profilerTime2Index),t));
1566 end profilerstop2;
1567
1568 function profilerreset1
1569 algorithm
1570 ✗ setGlobalRoot(Global.profilerTime1Index, 0.0);
1571 end profilerreset1;
1572
1573 function profilerreset2
1574 algorithm
1575 ✗ setGlobalRoot(Global.profilerTime2Index, 0.0);
1576 end profilerreset2;
1577
1578 function profilertock1
1579 output Real t;
1580 algorithm
1581 ✗ t := System.realtimeTock(ClockIndexes.RT_PROFILER1);
1582 end profilertock1;
1583
1584 function profilertock2
1585 output Real t;
1586 algorithm
1587 ✗ t := System.realtimeTock(ClockIndexes.RT_PROFILER2);
1588 end profilertock2;
1589
1590 function applyTuple21<T1, T2>
1591 "Applies a function to the first element of a tuple."
1592 input tuple<T1, T2> inTuple;
1593 input FuncT func;
1594 output tuple<T1, T2> outTuple;
1595
1596 partial function FuncT
1597 input output T1 e;
1598 end FuncT;
1599 protected
1600 T1 e1_1, e1_2;
1601 T2 e2;
1602 algorithm
1603 2535 (e1_1, e2) := inTuple;
1604
1/2
✓ Branch 0 taken 2535 times.
✗ Branch 1 not taken.
2535 e1_2 := func(e1_1);
1605
1/2
✓ Branch 0 taken 2535 times.
✗ Branch 1 not taken.
2535 outTuple := if referenceEq(e1_1, e1_2) then inTuple else (e1_2, e2);
1606 end applyTuple21;
1607
1608 function applyTuple22<T1, T2>
1609 "Applies a function to the second element of a tuple."
1610 input tuple<T1, T2> inTuple;
1611 input FuncT func;
1612 output tuple<T1, T2> outTuple;
1613
1614 partial function FuncT
1615 input output T2 e;
1616 end FuncT;
1617 protected
1618 T1 e1;
1619 T2 e2_1, e2_2;
1620 algorithm
1621 ✗ (e1, e2_1) := inTuple;
1622 ✗ e2_2 := func(e2_1);
1623 ✗ outTuple := if referenceEq(e2_1, e2_2) then inTuple else (e1, e2_2);
1624 end applyTuple22;
1625
1626 function applyTuple31<T1, T2, T3>
1627 input tuple<T1, T2, T3> inTuple;
1628 input FuncT func;
1629 output tuple<T1, T2, T3> outTuple;
1630
1631 partial function FuncT
1632 input output T1 e;
1633 end FuncT;
1634 protected
1635 T1 t1, t1_new;
1636 T2 t2;
1637 T3 t3;
1638 algorithm
1639 833 (t1, t2, t3) := inTuple;
1640
1/2
✓ Branch 0 taken 833 times.
✗ Branch 1 not taken.
833 t1_new := func(t1);
1641
1/2
✓ Branch 0 taken 833 times.
✗ Branch 1 not taken.
833 outTuple := if referenceEq(t1, t1_new) then inTuple else (t1_new, t2, t3);
1642 end applyTuple31;
1643
1644 833 function referenceCompare<T1, T2>
1645 "Returns -1, 0, or 1 depending on whether the memory address of ref1 is less,
1646 equal, or greater than the address of ref2."
1647 input T1 ref1;
1648 input T2 ref2;
1649 output Integer result;
1650 external "C" result = referenceCompareExt(ref1, ref2) annotation(Include="
1651 static inline int referenceCompareExt(void *ref1, void *ref2)
1652 {
1653 ✗ return (ref1 < ref2) ? -1 : (ref1 > ref2);
1654 }
1655 ");
1656 end referenceCompare;
1657
1658 function gcd
1659 "Returns the greatest common divisor of two integers."
1660 input Integer a;
1661 input Integer b;
1662 output Integer res;
1663 algorithm
1664
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 153 times.
297 res := if b == 0 then a else gcd(b, intMod(a, b));
1665 end gcd;
1666
1667 function lcm
1668 "Returns the least common multiplier of two integers."
1669 input Integer a;
1670 input Integer b;
1671 output Integer res;
1672 algorithm
1673 ✗ res := if a < 0 or b < 0 then -1 else intDiv((a * b), gcd(a, b));
1674 end lcm;
1675
1676 function msb
1677 "Returns the one-based index of the most significant set bit in an integer > 0,
1678 or 0 for an integer <= 0."
1679 input Integer n;
1680 output Integer res = 0;
1681 protected
1682 Integer i = n;
1683 algorithm
1684
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 13 times.
37 while i > 0 loop
1685 24 i := intBitRShift(i, 1);
1686 24 res := res + 1;
1687 end while;
1688 end msb;
1689
1690 public function foldcallN<FT>
1691 "Takes a value and a function operating on the value n times.
1692 Example: foldcallN(1, intAdd, 4) => 4"
1693 input Integer n;
1694 input FoldFunc inFoldFunc;
1695 input FT inStartValue;
1696 output FT outResult = inStartValue;
1697
1698 partial function FoldFunc
1699 input FT inFoldArg;
1700 output FT outFoldArg;
1701 end FoldFunc;
1702 algorithm
1703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 572 times.
1157 for i in 1:n loop
1704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 585 times.
585 outResult := inFoldFunc(outResult);
1705 end for;
1706 end foldcallN;
1707
1708 annotation(__OpenModelica_Interface="util");
1709 end Util;
1710