Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 45.3% 48 / 0 / 106
Functions: 63.6% 7 / 0 / 11
Branches: 34.4% 22 / 0 / 64

OMCompiler/SimulationRuntime/c/util/modelica_string.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 "modelica_string.h"
30 #if defined(OMC_METAMODELICA_RUNTIME)
31 /* The string vocabulary of this runtime; util/omc_string.h stands down here.
32 The String(x) formatters below are built for both. */
33 #include "../meta/meta_modelica_string.h"
34 #endif
35 #include "../gc/omc_gc.h"
36 #include <stdio.h>
37 #include <assert.h>
38 #include <string.h>
39 #include "omc_error.h"
40
41 #define FMT_BUFSIZE 400
42
43 /* An assert may return (the error is raised), so a bad format ends the parse. */
44 #define FORMAT_ERROR(...) do { omc_assert(NULL, omc_dummyFileInfo, __VA_ARGS__); return NULL; } while (0)
45 #define checkBufSize(str, n) do { if ((n) >= FMT_BUFSIZE) FORMAT_ERROR("Could not parse format string; ran out of buffer size (%d): %s", FMT_BUFSIZE, str); } while (0)
46
47 36 modelica_string modelica_string_format_to_c_string_format(modelica_string format)
48 {
49 char buf[FMT_BUFSIZE];
50 ✗ const char *str = omc_string_data(format), *tmp = str;
51 int cont=1, n=0;
52 36 buf[n++] = '%';
53
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 36 times.
108 while (cont) { /* Parse flag characters */
54
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 switch (*tmp) {
55 /* Extended flags? ',I */
56 ✗ case '#':
57 case '0':
58 case '-':
59 case ' ':
60 case '+':
61 ✗ buf[n] = *(tmp++);
62 ✗ checkBufSize(str, n++);
63 break;
64 default:
65 cont = 0;
66 }
67 }
68 // width: [1-9][0-9]*
69 if ((*tmp >= '1') || (*tmp <= '9')) {
70
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 while (*tmp >= '0' && *tmp <= '9') {
71 ✗ buf[n] = *(tmp++);
72 ✗ checkBufSize(str, n++);
73 }
74 }
75 // precision: .[0-9]*
76
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (*tmp == '.') {
77 ✗ buf[n] = *(tmp++);
78 ✗ checkBufSize(str, n++);
79 ✗ while (*tmp >= '0' && *tmp <= '9') {
80 ✗ buf[n] = *(tmp++);
81 ✗ checkBufSize(str, n++);
82 }
83 }
84
85
1/4
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
36 switch (*tmp) {
86 36 case 'f':
87 case 'e':
88 case 'E':
89 case 'g':
90 case 'G':
91 /* double */
92 case 'c':
93 /* int */
94 36 buf[n] = *(tmp++);
95
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 checkBufSize(str, n++);
96 break;
97 ✗ case 'd':
98 case 'i':
99 /* int */
100 case 'o':
101 case 'x':
102 case 'X':
103 case 'u':
104 /* uint */
105 ✗ buf[n] = 'l'; /* we use long in OpenModelica */
106 ✗ checkBufSize(str, n++);
107 ✗ buf[n] = *(tmp++);
108 ✗ checkBufSize(str, n++);
109 break;
110 ✗ case 'h':
111 case 'l':
112 case 'L':
113 case 'q':
114 case 'j':
115 case 'z':
116 case 't':
117 ✗ FORMAT_ERROR("Length modifiers are not legal in Modelica format strings: %s", str);
118 ✗ default:
119 ✗ FORMAT_ERROR("Could not parse format string: invalid conversion specifier: %c in %s", *tmp, str);
120 }
121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (*tmp) {
122 ✗ FORMAT_ERROR("Could not parse format string: trailing data after the format directive");
123 }
124 36 buf[n] = '\0';
125 36 return omc_string_new(buf);
126 }
127
128 /* Convert a modelica_integer to a modelica_string, used in String(integer, format="xxx") */
129 ✗ modelica_string modelica_integer_to_modelica_string_format(modelica_integer i,modelica_string format)
130 {
131 void *res;
132 size_t sz;
133
134 ✗ void *c_fmt = modelica_string_format_to_c_string_format(format);
135 ✗ if (!c_fmt) {
136 ✗ return omc_string_new("");
137 }
138
139 ✗ switch (omc_string_data(c_fmt)[omc_string_len(c_fmt)-1]) {
140 ✗ case 'f':
141 case 'e':
142 case 'E':
143 case 'g':
144 case 'G':
145 /* double */
146 ✗ sz = snprintf(NULL, 0, omc_string_data(c_fmt), (double) i);
147 ✗ res = omc_string_alloc(sz);
148 ✗ sprintf(omc_string_data(res), omc_string_data(c_fmt), (double) i);
149 break;
150 ✗ case 'c':
151 case 'd':
152 case 'i':
153 /* int */
154 ✗ sz = snprintf(NULL, 0, omc_string_data(c_fmt), (long) i);
155 ✗ res = omc_string_alloc(sz);
156 ✗ sprintf(omc_string_data(res), omc_string_data(c_fmt), (long) i);
157 break;
158 ✗ case 'o':
159 case 'x':
160 case 'X':
161 case 'u':
162 /* uint */
163 ✗ sz = snprintf(NULL, 0, omc_string_data(c_fmt), (unsigned long) i);
164 ✗ res = omc_string_alloc(sz);
165 ✗ sprintf(omc_string_data(res), omc_string_data(c_fmt), (unsigned long) i);
166 break;
167 ✗ default:
168 /* integer values, etc */
169 ✗ omc_assert(NULL, omc_dummyFileInfo, "Invalid conversion specifier for Real: %c", omc_string_data(c_fmt)[omc_string_len(c_fmt)-1]);
170 ✗ res = omc_string_new("");
171 }
172 return res;
173 }
174
175 /* Convert a modelica_real to a modelica_string, used in String(real, format="xxx") */
176 36 modelica_string modelica_real_to_modelica_string_format(modelica_real r,modelica_string format)
177 {
178 void *res;
179 size_t sz;
180
181 36 void *c_fmt = modelica_string_format_to_c_string_format(format);
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!c_fmt) {
183 ✗ return omc_string_new("");
184 }
185
186
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 switch (omc_string_data(c_fmt)[omc_string_len(c_fmt)-1]) {
187 ✗ case 'f':
188 case 'e':
189 case 'E':
190 case 'g':
191 case 'G':
192 /* double */
193 36 sz = snprintf(NULL, 0, omc_string_data(c_fmt), (double) r);
194 36 res = omc_string_alloc(sz);
195 ✗ sprintf(omc_string_data(res), omc_string_data(c_fmt), (double) r);
196 break;
197 ✗ default:
198 /* integer values, etc */
199 ✗ omc_assert(NULL, omc_dummyFileInfo, "Invalid conversion specifier for Real: %c", omc_string_data(c_fmt)[omc_string_len(c_fmt)-1]);
200 ✗ res = omc_string_new("");
201 }
202 return res;
203 }
204
205 /* Convert a modelica_string to a modelica_string, used in String(s) */
206 ✗ modelica_string modelica_string_to_modelica_string(modelica_string s)
207 {
208 ✗ return omc_string_retain(s);
209 }
210
211 /* Convert a modelica_integer to a modelica_string, used in String(i) */
212 127282 modelica_string modelica_integer_to_modelica_string(modelica_integer i, modelica_integer minLen, modelica_boolean leftJustified)
213 {
214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 127282 times.
127282 size_t sz = snprintf(NULL, 0, leftJustified ? OMC_INT_WIDTH_LEFT_FORMAT : OMC_INT_WIDTH_FORMAT, (int) minLen, i);
215 127282 void *res = omc_string_alloc(sz);
216 121738 sprintf(omc_string_data(res), leftJustified ? OMC_INT_WIDTH_LEFT_FORMAT : OMC_INT_WIDTH_FORMAT, (int) minLen, i);
217 127282 return res;
218 }
219
220 /* Convert a modelica_real to a modelica_string, used in String(r) */
221
222 2125 modelica_string modelica_real_to_modelica_string(modelica_real r, modelica_integer signDigits, modelica_integer minLen, modelica_boolean leftJustified)
223 {
224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2125 times.
2125 size_t sz = snprintf(NULL, 0, leftJustified ? "%-*.*g" : "%*.*g", (int) minLen, (int) signDigits, r);
225 2125 void *res = omc_string_alloc(sz);
226 127 sprintf(omc_string_data(res), leftJustified ? "%-*.*g" : "%*.*g", (int) minLen, (int) signDigits, r);
227 2125 return res;
228 }
229
230 /* Convert a modelica_boolean to a modelica_string, used in String(b) */
231
232 2269791 modelica_string modelica_boolean_to_modelica_string(modelica_boolean b, modelica_integer minLen, modelica_boolean leftJustified)
233 {
234
3/4
✓ Branch 0 taken 1372624 times.
✓ Branch 1 taken 897167 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2269791 times.
3642415 size_t sz = snprintf(NULL, 0, leftJustified ? "%-*s" : "%*s", (int) minLen, b ? "true" : "false");
235 2269791 void *res = omc_string_alloc(sz);
236 2269791 sprintf(omc_string_data(res), leftJustified ? "%-*s" : "%*s", (int) minLen, b ? "true" : "false");
237 2269791 return res;
238 }
239
240 /* Convert a modelica_enumeration to a modelica_string, used in String(b) */
241
242 ✗ modelica_string enum_to_modelica_string(modelica_integer nr, const char *e[],modelica_integer minLen, modelica_boolean leftJustified)
243 {
244 ✗ size_t sz = snprintf(NULL, 0, leftJustified ? "%-*s" : "%*s", (int) minLen, e[nr-1]);
245 ✗ void *res = omc_string_alloc(sz);
246 ✗ sprintf(omc_string_data(res), leftJustified ? "%-*s" : "%*s", (int) minLen, e[nr-1]);
247 ✗ return res;
248 }
249
250 #if !defined(OMC_METAMODELICA_RUNTIME)
251 ✗ modelica_string alloc_modelica_string(int length)
252 {
253 /* Reserve place for null terminator too.*/
254 ✗ return omc_string_alloc(length);
255 }
256
257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86925 times.
86925 modelica_string stringAppend(modelica_string s1, modelica_string s2)
258 {
259 unsigned len1 = 0, len2 = 0, nbytes = 0;
260 modelica_string res = NULL;
261
262 86925 len1 = omc_string_len(s1);
263 86925 len2 = omc_string_len(s2);
264
265 /* An argument returned unchanged is still a reference of the caller's own. */
266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86925 times.
86925 if (len1==0) {
267 ✗ return omc_string_retain(s2);
268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86925 times.
86925 } else if (len2==0) {
269 ✗ return omc_string_retain(s1);
270 }
271
272 86925 nbytes = len1+len2;
273 86925 res = omc_string_alloc(nbytes);
274
275 memcpy(omc_string_data(res), omc_string_data(s1), len1);
276 86925 memcpy(omc_string_data(res) + len1, omc_string_data(s2), len2 + 1);
277
278 86925 return res;
279 }
280
281
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 modelica_integer stringCompare(modelica_string str1, modelica_string str2)
282 {
283 int res;
284 8 res = strcmp(omc_string_data(str1),omc_string_data(str2));
285
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (res < 0)
286 return -1;
287
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 if (res > 0)
288 3 return 1;
289 return 0;
290 }
291 #endif /* !OMC_METAMODELICA_RUNTIME */
292