Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 53.0% 96 / 0 / 181
Functions: 58.3% 14 / 0 / 24
Branches: 29.8% 34 / 0 / 114

OMCompiler/SimulationRuntime/c/util/list.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 /*! \file list.c
29 *
30 * Description: This file is a C header file for the simulation runtime.
31 * It contains a simple linked list
32 */
33
34 #include "list.h"
35 #include "omc_error.h"
36
37 #include <stdlib.h>
38 #include <string.h>
39
40 /* Private function prototypes */
41 modelica_boolean listIsIn(LIST *list, LIST_NODE *node);
42
43 struct LIST_NODE
44 {
45 void *data; /* Data of list element.
46 * Use allocListNodeFunc, freeListNodeFunc and copyListNodeDataFunc for alloc, free and copy. */
47 LIST_NODE *next; /* Pointer to next list element. */
48 };
49
50 struct LIST
51 {
52 LIST_NODE *first; /* Pointer to first list element */
53 LIST_NODE *last; /* Pointer to last list element */
54 unsigned int length; /* Number if list elements */
55 allocListNodeDataFunc_t* allocListNodeData; /* Function to allocate memory for LIST_NODE data. */
56 freeListNodeDataFunc_t* freeListNodeData; /* Function to free memory of LIST_NODE data. */
57 copyListNodeDataFunc_t* copyListNodeData; /* Function to copy memory of LIST_NODE data. */
58 };
59
60 /**
61 * @brief Allocates memory for a new empty list
62 *
63 * @param itemSize Size of data
64 * @return list Pointer to list
65 */
66
67 /**
68 * @brief Allocates memory for a new empty list
69 *
70 * @param allocListNodeData Function to allocate memory for new list elements data.
71 * @param freeListNodeData Function to free memory for list elements data.
72 * @param copyListNodeData Function to copy list elements data.
73 * @return LIST* New empty list.
74 */
75 30 LIST *allocList(allocListNodeDataFunc_t* allocListNodeData, freeListNodeDataFunc_t* freeListNodeData, copyListNodeDataFunc_t* copyListNodeData)
76 {
77 30 LIST *list = (LIST*)malloc(sizeof(LIST));
78
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 assertStreamPrint(NULL, 0 != list, "out of memory");
79
80 30 list->first = NULL;
81 30 list->last = NULL;
82 30 list->allocListNodeData = allocListNodeData;
83 30 list->freeListNodeData = freeListNodeData;
84 30 list->copyListNodeData = copyListNodeData;
85 30 list->length = 0;
86
87 30 return list;
88 }
89
90 /**
91 * @brief Frees list and everything inside it
92 *
93 * @param list Pointer to list
94 */
95 18 void freeList(LIST *list)
96 {
97
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1 time.
18 if(list)
98 {
99 17 listClear(list);
100 17 free(list);
101 }
102 18 }
103
104 /**
105 * @brief Frees node and data inside node
106 *
107 * @param node Pointer to node
108 */
109 29 void freeNode(LIST *list, LIST_NODE *node)
110 {
111 29 list->freeListNodeData(node->data);
112 29 free(node);
113 29 }
114
115 /**
116 * @brief Checks if a list is empty
117 *
118 * @param list Pointer to list
119 */
120 60 int listEmptyTest(LIST *list)
121 {
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
123
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 58 times.
60 if(list->first){
124 return 0;
125 }else{
126 2 return 1;
127 }
128 }
129
130 /**
131 * @brief Copies data into new tmpNode and pushes tmpNode to the front of list
132 *
133 * @param list Pointer to list
134 * @param data Pointer to data (copied)
135 */
136 4 void listPushFront(LIST *list, const void *data)
137 {
138 LIST_NODE *tmpNode = NULL;
139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
140
141 4 tmpNode = (LIST_NODE*)malloc(sizeof(LIST_NODE));
142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assertStreamPrint(NULL, 0 != tmpNode, "out of memory");
143
144 4 tmpNode->data = list->allocListNodeData(data);
145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assertStreamPrint(NULL, 0 != tmpNode->data, "out of memory");
146
147 4 list->copyListNodeData(tmpNode->data, data);
148 4 tmpNode->next = list->first;
149 4 ++(list->length);
150
151 4 list->first = tmpNode;
152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if(!list->last)
153 ✗ list->last = list->first;
154 4 }
155
156 /**
157 * @brief Pushes node to the front of list
158 *
159 * @param list Pointer to list
160 * @param node Pointer to node (not copied)
161 */
162 ✗ void listPushFrontNodeNoCopy(LIST *list, LIST_NODE *node)
163 {
164 ✗ assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
165 ✗ assertStreamPrint(NULL, 0 != node, "invalid list-node");
166
167 ✗ node->next = list->first;
168 ✗ ++(list->length);
169 ✗ list->first = node;
170 ✗ if(!list->last)
171 ✗ list->last = list->first;
172 ✗ }
173
174 /**
175 * @brief Copies data into new tmpNode and pushes tmpNode to the back of list
176 *
177 * @param list Pointer to list
178 * @param data Pointer to data (copied)
179 */
180 81 void listPushBack(LIST *list, const void *data)
181 {
182 LIST_NODE *tmpNode = NULL;
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
184
185 81 tmpNode = (LIST_NODE*)malloc(sizeof(LIST_NODE));
186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 assertStreamPrint(NULL, 0 != tmpNode, "out of memory");
187
188 81 tmpNode->data = list->allocListNodeData(data);
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 assertStreamPrint(NULL, 0 != tmpNode->data, "out of memory");
190
191 81 list->copyListNodeData(tmpNode->data, data);
192 81 tmpNode->next = NULL;
193 81 ++(list->length);
194
195
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 29 times.
81 if(list->last)
196 52 list->last->next = tmpNode;
197
198 81 list->last = tmpNode;
199
200
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 52 times.
81 if(!list->first)
201 29 list->first = list->last;
202 81 }
203
204 /**
205 * @brief Copies data into new node and inserts it into list after prevNode
206 *
207 * @param list Pointer to list
208 * @param prevNode Pointer to previous node
209 * @param data Pointer to data (copied)
210 */
211 8 void listInsert(LIST *list, LIST_NODE* prevNode, const void *data)
212 {
213 8 LIST_NODE *tmpNode = (LIST_NODE*)malloc(sizeof(LIST_NODE));
214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 assertStreamPrint(NULL, 0 != tmpNode, "out of memory");
215
216 8 tmpNode->data = list->allocListNodeData(data);
217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 assertStreamPrint(NULL, 0 != tmpNode->data, "out of memory");
218 8 list->copyListNodeData(tmpNode->data, data);
219
220 8 tmpNode->next = prevNode->next;
221 8 prevNode->next = tmpNode;
222
223 8 ++(list->length);
224
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if(list->last == prevNode)
225 8 list->last = tmpNode;
226 8 }
227
228 /**
229 * @brief Returns the length of list
230 *
231 * @param list Pointer to list
232 * @return length of list
233 */
234 37 int listLen(LIST *list)
235 {
236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
237 37 return list->length;
238 }
239
240 /**
241 * @brief Returns data of first node in list
242 *
243 * @param list Pointer to list
244 * @return Pointer to data of first node in list
245 */
246 154 void *listFirstData(LIST *list)
247 {
248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 assertStreamPrint(NULL, 0 != list->first, "empty list");
250 if(list->first){
251 154 return list->first->data;
252 }else{
253 return NULL;
254 }
255 }
256
257 /**
258 * @brief Returns data of last node in list
259 *
260 * @param list Pointer to list
261 * @return Pointer to data of last node in list
262 */
263 ✗ void *listLastData(LIST *list)
264 {
265 ✗ assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
266 ✗ assertStreamPrint(NULL, 0 != list->last, "empty list");
267 ✗ return list->last->data;
268 }
269
270 /**
271 * @brief Returns first node and pops node from list
272 *
273 * @param list Pointer to list
274 * @return node Pointer to node (must be freed by caller)
275 */
276 19 LIST_NODE *listPopFrontNode(LIST *list)
277 {
278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 assertStreamPrint(NULL, 0 != list->first, "empty list");
280
281 LIST_NODE *node = list->first;
282 19 list->first = node->next;
283 //node->next = NULL;
284 19 --(list->length);
285
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
19 if(!list->first)
286 2 list->last = list->first;
287 19 return node;
288 }
289
290 /**
291 * @brief Returns node and pops node from list
292 *
293 * @param list Pointer to list
294 * @param prevNode Node to remove after. prevNode won't be removed.
295 * @return node Pointer to node (must be freed by caller)
296 */
297 ✗ LIST_NODE *listPopNode(LIST *list, LIST_NODE *prevNode)
298 {
299 ✗ assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
300 ✗ assertStreamPrint(NULL, 0 != list->first, "empty list");
301
302 ✗ LIST_NODE *node = prevNode->next;
303 ✗ LIST_NODE *afterNode = node->next;
304 ✗ prevNode->next = afterNode;
305 ✗ --(list->length);
306 ✗ return node;
307 }
308
309 /**
310 * @brief Removes and frees first node from list
311 *
312 * @param list Pointer to list
313 */
314 ✗ void listRemoveFront(LIST *list)
315 {
316 ✗ assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
317 ✗ if(list->first)
318 {
319 ✗ LIST_NODE *tmpNode = list->first->next;
320 ✗ freeNode(list, list->first);
321
322 ✗ list->first = tmpNode;
323 ✗ --(list->length);
324 ✗ if(!list->first)
325 ✗ list->last = list->first;
326 }
327 ✗ }
328
329 /**
330 * @brief Removes and frees last node from list
331 *
332 * @param list Pointer to list
333 */
334 ✗ void listRemoveBack(LIST *list)
335 {
336 ✗ assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
337 ✗ if(list->last)
338 {
339 // case: one element
340 ✗ if (list->first == list->last)
341 {
342 ✗ listRemoveFront(list);
343 }
344 // general case: at least two elements -> find second last element
345 else
346 {
347 LIST_NODE *prev = list->first;
348 ✗ while (prev->next != list->last)
349 {
350 prev = prev->next;
351 }
352 LIST_NODE *delNode = list->last;
353
354 ✗ prev->next = NULL;
355 ✗ list->last = prev;
356 ✗ --(list->length);
357
358 ✗ freeNode(list, delNode);
359 }
360
361 }
362 ✗ }
363
364 /**
365 * @brief Frees all nodes and their data in list
366 *
367 * @param list Pointer to list
368 */
369 17 void listClear(LIST *list)
370 {
371 LIST_NODE *delNode;
372
373
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if(!list)
374 return;
375
376 17 delNode = list->first;
377
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 17 times.
46 while(delNode)
378 {
379 29 LIST_NODE *tmpNode = delNode->next;
380 29 freeNode(list, delNode);
381 delNode = tmpNode;
382 }
383
384 17 list->length = 0;
385 17 list->first = NULL;
386 17 list->last = NULL;
387 }
388
389 /**
390 * @brief Remove all nodes after startNode from list.
391 *
392 * Checks if startNode is part of list.
393 *
394 * @param list List to remove elements from.
395 * @param startNode Node to remove after. startNode won't be removed.
396 */
397 ✗ void listClearAfterNode(LIST *list, LIST_NODE *startNode) {
398 ✗ assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
399 ✗ assertStreamPrint(NULL, 0 != startNode, "invalid list-node");
400
401 ✗ assertStreamPrint(NULL, listIsIn(list, startNode), "listClearAfterNode: start node not in list!");
402
403 ✗ LIST_NODE* delNode = startNode->next;
404 ✗ while (delNode) {
405 ✗ LIST_NODE* nextNode = delNode->next;
406 ✗ freeNode(list, delNode);
407 ✗ list->length--;
408 delNode = nextNode;
409 }
410 ✗ startNode->next = NULL;
411 ✗ list->last = startNode;
412 ✗ }
413
414 /**
415 * @brief Returns first node of list
416 *
417 * @param list Pointer to list
418 * @return Pointer to first node (NULL if list is empty)
419 */
420 98 LIST_NODE *listFirstNode(LIST *list)
421 {
422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
423 98 return list->first;
424 }
425
426 /**
427 * @brief Returns next node after node (used for iterating over list)
428 *
429 * @param node Pointer to node
430 * @return Pointer to next node (NULL if end of list is reached)
431 */
432 235 LIST_NODE *listNextNode(LIST_NODE *node)
433 {
434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 235 times.
235 assertStreamPrint(NULL, 0 != node, "invalid list-node");
435 235 return node->next;
436 }
437
438 /**
439 * @brief Test if node is in list
440 *
441 * @param list Pointer to List.
442 * @param node Node to test if in list.
443 * @return modelica_boolean True if node is in list, false otherwise.
444 */
445 ✗ modelica_boolean listIsIn(LIST *list, LIST_NODE *node) {
446 ✗ assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
447 ✗ assertStreamPrint(NULL, 0 != node, "invalid list-node");
448
449 modelica_boolean isIn = FALSE;
450 ✗ LIST_NODE* tmpNode = list->first;
451 ✗ while (tmpNode) {
452 ✗ if (node == tmpNode) {
453 return TRUE;
454 }
455 ✗ tmpNode = tmpNode->next;
456 }
457
458 return FALSE;
459 }
460
461 /**
462 * @brief Returns node data.
463 *
464 * @param node Pointer to node
465 * @return Pointer to data
466 */
467 178 void *listNodeData(LIST_NODE *node)
468 {
469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 178 times.
178 assertStreamPrint(NULL, 0 != node, "invalid list-node");
470
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 178 times.
178 assertStreamPrint(NULL, 0 != node->data, "invalid list-data");
471 178 return node->data;
472 }
473
474 /**
475 * @brief Update content of node->data with data.
476 *
477 * Uses provided copyListNodeData function.
478 *
479 * @param list List containing node.
480 * @param node Node to update.
481 * @param data Data to copy into node data.
482 */
483 ✗ void updateNodeData(LIST *list, LIST_NODE *node, const void *data)
484 {
485 ✗ assertStreamPrint(NULL, 0 != list, "invalid list-pointer");
486 ✗ assertStreamPrint(NULL, 0 != node, "invalid list-node");
487 ✗ assertStreamPrint(NULL, 0 != node->data, "invalid list-data");
488 ✗ list->copyListNodeData(node->data, data);
489 ✗ return;
490 }
491
492 /**
493 * @brief Print list
494 *
495 * @param list Pointer to list.
496 * @param stream Stream to print to.
497 * @param printDataFunc Function to print address of buffer element and its data to stream.
498 */
499 ✗ void printList(LIST* list, int stream, void (*printDataFunc)(void*,int,void*))
500 {
501 LIST_NODE* listElem;
502
503 ✗ if (omc_useStream[stream]) {
504 ✗ infoStreamPrint(stream, 1, "Printing list:");
505 ✗ infoStreamPrint(stream, 0, "length: %d", list->length);
506
507 ✗ listElem = list->first;
508 ✗ for (int i=0; i<list->length; i++) {
509 ✗ assertStreamPrint(NULL, listElem != NULL, "list element is NULL");
510 ✗ printDataFunc(listElem->data, stream, (void*) listElem->data);
511 ✗ listElem = listElem->next;
512 }
513
514 ✗ messageClose(stream);
515 }
516 ✗ }
517
518 /**
519 * @brief apply function to all list elements
520 *
521 * @param list Pointer to list.
522 * @param applyDataFunc Function that is applied to each element.
523 */
524 ✗ void applyList(LIST* list, void(*applyDataFunc)(void*))
525 {
526 ✗ LIST_NODE* node = list->first;
527 ✗ while (node) {
528 ✗ applyDataFunc(node->data);
529 ✗ node = node->next;
530 }
531 ✗ }
532