Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 150
Functions: 0.0% 0 / 0 / 22
Branches: 0.0% 0 / 0 / 72

OMCompiler/SimulationRuntime/c/util/doubleEndedList.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 doubleEndedList.c
29 *
30 * Description: This file contains a simple double ended linked list.
31 */
32
33 #include "doubleEndedList.h"
34 #include "omc_error.h"
35
36 #include <stdlib.h>
37 #include <string.h>
38
39
40 /**
41 * @brief A single node element of a double ended list.
42 *
43 * Knows previous and next node and has some data.
44 */
45 struct DOUBLE_ENDED_LIST_NODE {
46 void* data; /**< Item data */
47 DOUBLE_ENDED_LIST_NODE* prev; /**< Pointer to previous node in list */
48 DOUBLE_ENDED_LIST_NODE* next; /**< Pointer to next node in list */
49 };
50
51
52 /**
53 * @brief Double ended list.
54 *
55 * Has pointers to first and last element and can be iterated over forward and backward.
56 *
57 */
58 struct DOUBLE_ENDED_LIST {
59 DOUBLE_ENDED_LIST_NODE* first; /**< Pointer to first element of list */
60 DOUBLE_ENDED_LIST_NODE* last; /**< Pointer to last element of list */
61 unsigned int itemSize; /**< Size of item data */
62 unsigned int length; /**< Number of elements in list */
63 };
64
65
66 // ############################################################################
67 //
68 // Section for allocating and freeing double ended list
69 //
70 // ############################################################################
71
72
73 /**
74 * @brief Create new empty double ended list.
75 *
76 * @param itemSize Size of item data.
77 * @return DOUBLE_ENDED_LIST* Pointer to new created double ended list.
78 */
79 ✗ DOUBLE_ENDED_LIST* allocDoubleEndedList(unsigned int itemSize) {
80 ✗ DOUBLE_ENDED_LIST* list = (DOUBLE_ENDED_LIST*) malloc(sizeof(DOUBLE_ENDED_LIST));
81 ✗ list->first = NULL;
82 ✗ list->last = NULL;
83 ✗ list->itemSize = itemSize;
84 ✗ list->length = 0;
85
86 ✗ return list;
87 }
88
89
90 /**
91 * @brief Free double ended list.
92 *
93 * Frees list items as well.
94 *
95 * @param list Pointer to list to be freed.
96 */
97 ✗ void freeDoubleEndedList(DOUBLE_ENDED_LIST *list) {
98 ✗ if(list) {
99 ✗ clearDoubleEndedList(list);
100 ✗ free(list);
101 }
102 ✗ }
103
104
105 /**
106 * @brief Free double ended list node.
107 *
108 * Assumes that all memory inside node->data is allready freed by user of double ended list.
109 *
110 * @param node Pointer to list node.
111 */
112 ✗ void freeNodeDoubleEndedList(DOUBLE_ENDED_LIST_NODE *node) {
113 ✗ free(node->data);
114 ✗ free(node);
115 ✗ }
116
117
118
119 // ############################################################################
120 //
121 // Section for adding nodes
122 //
123 // ############################################################################
124
125
126 /**
127 * @brief Create a double ended list node.
128 *
129 * Will copy provided data into node->data.
130 *
131 * @param data Date copied into node data.
132 * @param itemSize Size of data.
133 * @return DOUBLE_ENDED_LIST_NODE* New created node.
134 */
135 ✗ DOUBLE_ENDED_LIST_NODE* createNodeDoubleEndedList(const void* data, unsigned int itemSize) {
136 /* Variables */
137 DOUBLE_ENDED_LIST_NODE* newNode;
138
139 /* Allocate memory */
140 ✗ newNode = (DOUBLE_ENDED_LIST_NODE*) malloc(sizeof(DOUBLE_ENDED_LIST_NODE));
141 ✗ assertStreamPrint(NULL, 0 != newNode, "createNodeDoubleEndedList: Out of memory");
142
143 ✗ newNode->data = (void*) malloc(itemSize);
144 assertStreamPrint(NULL, 0 != newNode, "createNodeDoubleEndedList: Out of memory");
145
146 /* Set node data */
147 memcpy(newNode->data, data, itemSize);
148 ✗ newNode->prev = NULL;
149 ✗ newNode->next = NULL;
150 ✗ return newNode;
151 }
152
153
154 /**
155 * @brief Create new node from data and insert at front of list.
156 *
157 * Will copy data.
158 *
159 * @param list Pointer to double ended list.
160 * @param data Pointer to data to be coppied into new node.
161 */
162 ✗ void pushFrontDoubleEndedList(DOUBLE_ENDED_LIST* list, const void* data) {
163 /* Error checking */
164 ✗ assertStreamPrint(NULL, 0 != list, "pushFrontDoubleEndedList: invalid list-pointer");
165
166 /* Create new node */
167 ✗ DOUBLE_ENDED_LIST_NODE* newFirstNode = createNodeDoubleEndedList(data, list->itemSize);
168
169 /* Add node at front */
170 ✗ if (list->length==0) {
171 ✗ list->first = newFirstNode;
172 ✗ list->last = newFirstNode;
173 } else {
174 ✗ list->first->prev = newFirstNode;
175 ✗ newFirstNode->next = list->first;
176 ✗ list->first = newFirstNode;
177 }
178
179 ✗ list->length+= 1;
180 ✗ }
181
182
183 /**
184 * @brief Create new node from data and insert at back of list.
185 *
186 * @param list Pointer to double ended list.
187 * @param data Pointer to data to be coppied into new node.
188 */
189 ✗ void pushBackDoubleEndedList(DOUBLE_ENDED_LIST* list, const void* data) {
190 /* Error checking */
191 ✗ assertStreamPrint(NULL, 0 != list, "pushBackDoubleEndedList: invalid list-pointer");
192
193 /* Create new node */
194 ✗ DOUBLE_ENDED_LIST_NODE* newLastNode = createNodeDoubleEndedList(data, list->itemSize);
195
196 /* Append node at back */
197 ✗ if (list->length==0) {
198 ✗ list->first = newLastNode;
199 ✗ list->last = newLastNode;
200 } else {
201 ✗ list->last->next = newLastNode;
202 ✗ newLastNode->prev = list->last;
203 ✗ list->last = newLastNode;
204 }
205
206 ✗ list->length+= 1;
207 ✗ }
208
209
210 /**
211 * @brief Insert list element after given node.
212 *
213 * @param list Pointer to double ended list.
214 * @param prevNode Previous node for new created node.
215 * @param data Pointer to data to be coppied into new node.
216 */
217 ✗ void insertDoubleEndedList(DOUBLE_ENDED_LIST *list, DOUBLE_ENDED_LIST_NODE* prevNode, const void *data) {
218 /* Error checking */
219 ✗ assertStreamPrint(NULL, 0 != list, "insertDoubleEndedList: invalid list-pointer");
220 ✗ assertStreamPrint(NULL, 0 != prevNode, "insertDoubleEndedList: invalid previous-node-pointer");
221
222 /* Create new node */
223 ✗ DOUBLE_ENDED_LIST_NODE* newNode = createNodeDoubleEndedList(data, list->itemSize);
224
225 ✗ newNode->prev = prevNode;
226 ✗ newNode->next = prevNode->next;
227 ✗ prevNode->next = newNode;
228
229 /* Update end of list */
230 ✗ if(list->last == prevNode)
231 ✗ list->last = newNode;
232
233 ✗ list->length+= 1;
234 ✗ }
235
236
237 // ############################################################################
238 //
239 // Section for removing nodes
240 //
241 // ############################################################################
242
243
244 /**
245 * @brief Remove single node from list.
246 *
247 * @param list Double ended list.
248 * @param node Node to be deleted from list.
249 */
250 ✗ void removeNodeDoubleEndedList(DOUBLE_ENDED_LIST* list, DOUBLE_ENDED_LIST_NODE *node) {
251 ✗ if (node != NULL) {
252 /* Update previous node */
253 ✗ if (node->prev) {
254 ✗ if (node->next) {
255 ✗ node->prev->next = node->next; /* Set next of previous node to be the node after deleted one */
256 } else {
257 ✗ node->prev->next = NULL;
258 ✗ if (node->next == NULL) { /* Previous node is now last node */
259 ✗ list->last = node->prev;
260 }
261 }
262 }
263 /* Update next node */
264 ✗ if (node->next) {
265 ✗ if (node->prev) {
266 ✗ node->next->prev = node->prev; /* Set previous of next node to be the node before deleted one */
267 } else {
268 ✗ node->next->prev = NULL;
269 ✗ if (node->prev == NULL) { /* Next node is now first node */
270 ✗ list->first = node->next;
271 }
272 }
273 }
274
275 /* Free node */
276 ✗ freeNodeDoubleEndedList(node);
277 ✗ list->length -= 1;
278 ✗ if (list->length == 0) {
279 ✗ list->first = NULL;
280 ✗ list->last = NULL;
281 }
282 }
283 ✗ }
284
285
286 /**
287 * @brief Removes first node from list.
288 *
289 * @param list Double ended list.
290 */
291 ✗ void removeFirstDoubleEndedList(DOUBLE_ENDED_LIST *list) {
292 ✗ if(list != NULL) {
293 ✗ if(list->first != NULL) {
294 ✗ removeNodeDoubleEndedList(list, list->first);
295 }
296 }
297 ✗ }
298
299
300 /**
301 * @brief Removes last node from list.
302 *
303 * @param list Double ended list.
304 */
305 ✗ void removeLastDoubleEndedList (DOUBLE_ENDED_LIST *list) {
306 ✗ if(list != NULL) {
307 ✗ removeNodeDoubleEndedList(list, list->last);
308 }
309 ✗ }
310
311
312 /**
313 * @brief Remove all items from double ended list.
314 *
315 * @param list Pointer to double ended list.
316 */
317 ✗ void clearDoubleEndedList(DOUBLE_ENDED_LIST *list) {
318 DOUBLE_ENDED_LIST_NODE *delNode;
319
320 ✗ if(list == NULL) {
321 return;
322 }
323
324 ✗ delNode = list->first;
325 ✗ while(delNode) {
326 ✗ DOUBLE_ENDED_LIST_NODE *tmpNode = delNode->next;
327 ✗ freeNodeDoubleEndedList(delNode);
328 delNode = tmpNode;
329 }
330
331 ✗ list->length = 0;
332 ✗ list->first = NULL;
333 ✗ list->last = NULL;
334 }
335
336
337 /**
338 * @brief Remove all items from double ended list in front of given node.
339 *
340 * Given node will not be removed and will be the first node in the list.
341 *
342 * @param list Pointer to double ended list.
343 * @param newFrontNode Pointer to node which will be the first node.
344 */
345 ✗ void clearBeforeNodeDoubleEndedList(DOUBLE_ENDED_LIST *list, DOUBLE_ENDED_LIST_NODE* newFrontNode) {
346 DOUBLE_ENDED_LIST_NODE *delNode;
347
348 ✗ assertStreamPrint(NULL, 0 != list, "clearBeforeNodeDoubleEndedList: invalid list-pointer");
349 ✗ assertStreamPrint(NULL, 0 != list->length, "clearBeforeNodeDoubleEndedList: empty list");
350
351 ✗ delNode = newFrontNode->prev;
352 ✗ while(delNode) {
353 ✗ DOUBLE_ENDED_LIST_NODE *tmpNode = delNode->prev;
354 ✗ freeNodeDoubleEndedList(delNode);
355 ✗ list->length -= 1;
356 delNode = tmpNode;
357 }
358
359 /* Update end of list */
360 ✗ newFrontNode->prev = NULL;
361 ✗ list->first = newFrontNode;
362 ✗ }
363
364
365 /**
366 * @brief Remove all items from double ended list after given node.
367 *
368 * Given node will not be removed and will be the last node in the list.
369 *
370 * @param list Pointer to double ended list.
371 * @param newEndNode Pointer to node which will be the new last node.
372 */
373 ✗ void clearAfterNodeDoubleEndedList(DOUBLE_ENDED_LIST *list, DOUBLE_ENDED_LIST_NODE* newEndNode) {
374 DOUBLE_ENDED_LIST_NODE *delNode;
375
376 ✗ assertStreamPrint(NULL, 0 != list, "clearAfterNodeDoubleEndedList: invalid list-pointer");
377 ✗ assertStreamPrint(NULL, 0 != list->length, "clearAfterNodeDoubleEndedList: empty list");
378
379 ✗ delNode = newEndNode->next;
380 ✗ while(delNode) {
381 ✗ DOUBLE_ENDED_LIST_NODE *tmpNode = delNode->next;
382 ✗ freeNodeDoubleEndedList(delNode);
383 ✗ list->length -= 1;
384 delNode = tmpNode;
385 }
386
387 /* Update end of list */
388 ✗ newEndNode->next = NULL;
389 ✗ list->last = newEndNode;
390 ✗ }
391
392
393 // ############################################################################
394 //
395 // Section for getting nodes
396 //
397 // ############################################################################
398
399
400 /**
401 * @brief Get the first node of double ended list.
402 *
403 * @param list Double ended list.
404 * @return DOUBLE_ENDED_LIST_NODE* Pointer to first node element of list.
405 */
406 ✗ DOUBLE_ENDED_LIST_NODE* getFirstNodeDoubleEndedList(DOUBLE_ENDED_LIST *list) {
407 ✗ return list->first;
408 }
409
410
411 /**
412 * @brief Get the last node of double ended list.
413 *
414 * @param list Double ended list
415 * @return DOUBLE_ENDED_LIST_NODE* Pointer to last node element of list.
416 */
417 ✗ DOUBLE_ENDED_LIST_NODE* getLastNodeDoubleEndedList(DOUBLE_ENDED_LIST *list) {
418 ✗ return list->last;
419 }
420
421
422 /**
423 * @brief Get the previous node of current node.
424 *
425 * @param currentNode Current node of double ended list.
426 * @return DOUBLE_ENDED_LIST_NODE* Pointer to previous node element.
427 */
428 ✗ DOUBLE_ENDED_LIST_NODE* getPreviousNodeDoubleEndedList(DOUBLE_ENDED_LIST_NODE *currentNode) {
429 ✗ return currentNode->prev;
430 }
431
432
433 /**
434 * @brief Get the next node of current node.
435 *
436 * @param currentNode Current node of double ended list.
437 * @return DOUBLE_ENDED_LIST_NODE* Pointer to next node element.
438 */
439 ✗ DOUBLE_ENDED_LIST_NODE* getNextNodeDoubleEndedList(DOUBLE_ENDED_LIST_NODE *currentNode) {
440 ✗ return currentNode->next;
441 }
442
443
444 // ############################################################################
445 //
446 // Section for getting data from nodes
447 //
448 // ############################################################################
449
450
451 /**
452 * @brief Return pointer to data of first node.
453 *
454 * @param list Double ended list.
455 * @return void* Pointer to data of first list element.
456 */
457 ✗ void* firstDataDoubleEndedList(DOUBLE_ENDED_LIST *list) {
458 ✗ assertStreamPrint(NULL, 0 != list, "firstDataDoubleEndedList: invalid list-pointer");
459 ✗ assertStreamPrint(NULL, 0 != list->first, "firstDataDoubleEndedList: empty list");
460 ✗ return list->first->data;
461 }
462
463
464 /**
465 * @brief Return pointer to data of last node.
466 *
467 * @param list Double ended list.
468 * @return void* Pointer to data of last list element.
469 */
470 ✗ void* lastDataDoubleEndedList(DOUBLE_ENDED_LIST *list) {
471 ✗ assertStreamPrint(NULL, 0 != list, "lastDataDoubleEndedList: invalid list-pointer");
472 ✗ assertStreamPrint(NULL, 0 != list->last, "lastDataDoubleEndedList: empty list");
473 ✗ return list->last->data;
474 }
475
476
477 /**
478 * @brief Return pointer to data of given node.
479 *
480 * @param node Node element.
481 * @return void* Pointer to data of node.
482 */
483 ✗ void* dataDoubleEndedList(DOUBLE_ENDED_LIST_NODE *node) {
484 ✗ assertStreamPrint(NULL, 0 != node, "dataDoubleEndedList: invalid node-pointer");
485 ✗ return node->data;
486 }
487
488
489 // ############################################################################
490 //
491 // Section for small helper functions
492 //
493 // ############################################################################
494
495
496 /**
497 * @brief Returns length of double ended lists.
498 *
499 * @param list Double ended list.
500 * @return int Length of list.
501 */
502 ✗ int doubleEndedListLen(DOUBLE_ENDED_LIST *list) {
503 ✗ assertStreamPrint(NULL, 0 != list, "doubleEndedListLen: invalid list-pointer");
504 ✗ return list->length;
505 }
506
507
508 /**
509 * @brief Print a double ended list with provided print function.
510 *
511 * @param list List to print.
512 * @param stream Stream of type OMC_LOG_STREAM.
513 * @param printDataFunc Function to print address of node and list->data to stream.
514 */
515 ✗ void doubleEndedListPrint(DOUBLE_ENDED_LIST *list, int stream, void (*printDataFunc)(void*,int,void*)) {
516 int i;
517 DOUBLE_ENDED_LIST_NODE* tmpNode;
518
519 ✗ if (omc_useStream[stream]) {
520 ✗ infoStreamPrint(stream, 1, "Printing double ended list:");
521 ✗ infoStreamPrint(stream, 0, "list length: %i, size of each item data: %i (bytes)", list->length, list->itemSize);
522 ✗ infoStreamPrint(stream, 0, "Pointer to first: %p", (void*) list->first);
523 ✗ infoStreamPrint(stream, 0, "Pointer to last: %p", (void*) list->last);
524
525 ✗ tmpNode = list->first;
526 ✗ while(tmpNode != NULL) {
527 ✗ printDataFunc(tmpNode->data, stream, (void*) tmpNode);
528 ✗ tmpNode = tmpNode->next;
529 }
530
531 ✗ messageClose(stream);
532 }
533 ✗ }
534