Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 42.9% 33 / 0 / 77
Functions: 50.0% 6 / 0 / 12
Branches: 23.8% 10 / 0 / 42

OMCompiler/SimulationRuntime/c/util/ringbuffer.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 * this does not work
30 * we need to separate RingBuffer and expandable queue
31 */
32
33 #include "ringbuffer.h"
34 #include "omc_error.h"
35
36 #include <assert.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40
41 struct RINGBUFFER
42 {
43 void *buffer; /* buffer itself */
44 int itemSize; /* size of one item in bytes */
45 int firstElement; /* position of first element in buffer */
46 int nElements; /* number of elements in buffer */
47 int bufferSize; /* number of elements which could be stored in buffer */
48 };
49 #include "ringbuffer.h"
50
51 /**
52 * @brief Allcoate memroy for ring buffer.
53 *
54 * Free memory with `freeRingBuffer`.
55 *
56 * @param bufferSize Number of elements in buffer.
57 * @param itemSize Size of single element in bits.
58 * @return RINGBUFFER* Pointer to allocated ring buffer.
59 */
60 1 RINGBUFFER *allocRingBuffer(int bufferSize, int itemSize)
61 {
62 1 RINGBUFFER *rb = (RINGBUFFER*)malloc(sizeof(RINGBUFFER));
63
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 assertStreamPrint(NULL, 0 != rb, "out of memory");
64
65 1 rb->firstElement = 0;
66 1 rb->nElements = 0;
67 1 rb->bufferSize = bufferSize > 0 ? bufferSize : 1;
68 1 rb->itemSize = itemSize;
69 1 rb->buffer = calloc(rb->bufferSize, rb->itemSize);
70
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 assertStreamPrint(NULL, 0 != rb->buffer, "out of memory");
71
72 1 return rb;
73 }
74
75 /**
76 * @brief Free ring buffer
77 *
78 * @param rb Pointer to ring buffer
79 */
80 1 void freeRingBuffer(RINGBUFFER *rb)
81 {
82 1 free(rb->buffer);
83 1 free(rb);
84 1 }
85
86 /**
87 * @brief Get data of i-th ring buffer element.
88 *
89 * Starts at rb->firstElement.
90 *
91 * @param rb Non-empty ring buffer.
92 * @param i Index of element to get data of. Must be in range of the buffer.
93 * @return void* Pointer to data of i-th ring buffer item.
94 */
95 ✗ void *getRingData(RINGBUFFER *rb, int i)
96 {
97 ✗ assertStreamPrint(NULL, rb->nElements > 0, "empty RingBuffer");
98 ✗ assertStreamPrint(NULL, i < rb->nElements, "index [%d] out of range [%d:%d]", i, -rb->nElements+1, rb->nElements-1);
99 ✗ assertStreamPrint(NULL, -rb->nElements < i, "index [%d] out of range [%d:%d]", i, -rb->nElements+1, rb->nElements-1);
100 ✗ return ((char*)rb->buffer)+(((rb->firstElement+i)%rb->bufferSize)*rb->itemSize);
101 }
102
103 /**
104 * @brief Increase maximum number of elements of ring buffer.
105 *
106 * Doubles the size of the original ring buffer
107 * and copies all values into updated buffer.
108 *
109 * @param rb Pointer to ring buffer.
110 */
111 ✗ void expandRingBuffer(RINGBUFFER *rb)
112 {
113 ✗ int oldSize = rb->bufferSize;
114 ✗ int wrapped = rb->firstElement + rb->nElements - oldSize;
115
116 ✗ rb->bufferSize *= 2;
117 ✗ rb->buffer = realloc(rb->buffer, rb->bufferSize*rb->itemSize);
118 ✗ assertStreamPrint(NULL, 0 != rb->buffer, "out of memory");
119
120 /* The elements that wrapped around to the start continue after the old end */
121 ✗ if (wrapped > 0) {
122 ✗ memcpy(((char*)rb->buffer) + oldSize*rb->itemSize, rb->buffer, wrapped*rb->itemSize);
123 }
124 ✗ }
125
126 /**
127 * @brief Add element to ring buffer.
128 *
129 * Will add to the end of the filled buffer.
130 * If the buffer isn't big enough it will be expanded.
131 *
132 * @param rb Pointer to ring buffer.
133 * @param value Data to add to ring buffer.
134 */
135 3 void appendRingData(RINGBUFFER *rb, void *value)
136 {
137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(rb->bufferSize < rb->nElements+1)
138 ✗ expandRingBuffer(rb);
139
140 3 memcpy(((char*)rb->buffer)+(((rb->firstElement+rb->nElements)%rb->bufferSize)*rb->itemSize), value, rb->itemSize);
141 3 ++rb->nElements;
142 3 }
143
144 /**
145 * @brief Deque first n ring data elements.
146 *
147 * Will only update pointer to fist element
148 * to be n elementes further.
149 * Dequeued data is not freed yet.
150 *
151 * @param rb
152 * @param n
153 */
154 ✗ void dequeueNFirstRingDatas(RINGBUFFER *rb, int n)
155 {
156 ✗ assertStreamPrint(NULL, rb->nElements > 0, "empty RingBuffer");
157 ✗ assertStreamPrint(NULL, n < rb->nElements, "index [%d] out of range [%d:%d]", n, 0, rb->nElements-1);
158 ✗ assertStreamPrint(NULL, n > 0, "Can't deque nothing or negative amount.");
159
160 ✗ rb->firstElement = (rb->firstElement+n)%rb->bufferSize;
161 ✗ rb->nElements -= n;
162 ✗ }
163
164 /**
165 * @brief Deque last n elements from ring buffer.
166 *
167 * Decrease counter nElements.
168 * Dequeued data is not freed yet.
169 *
170 * @param rb Pointer to ring buffer.
171 * @param n Number of elements to remove.
172 */
173 ✗ void removeLastRingData(RINGBUFFER *rb, int n)
174 {
175 ✗ assertStreamPrint(NULL, rb->nElements >= n, "empty RingBuffer");
176
177 ✗ rb->nElements -= n;
178 ✗ }
179
180 /**
181 * @brief Returns length of ring buffer.
182 *
183 * @param rb Pointer to ring buffer.
184 * @return int Length of ring buffer.
185 */
186 13 int ringBufferLength(RINGBUFFER *rb)
187 {
188 13 return rb->nElements;
189 }
190
191 /**
192 * @brief Rotate start point of ring buffer by n elements.
193 *
194 * @param rb Pointer to ring buffer.
195 * @param n Number of items to rotate.
196 */
197 1 void rotateRingBuffer(RINGBUFFER *rb, int n)
198 {
199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 assertStreamPrint(NULL, rb->nElements > 0, "empty RingBuffer");
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 assertStreamPrint(NULL, n < rb->nElements, "index [%d] out of range [%d:%d]", n, 0, rb->nElements-1);
201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 assertStreamPrint(NULL, 0 <= n, "index [%d] out of range [%d:%d]", n, 0, rb->nElements-1);
202
203 1 rb->firstElement = (rb->firstElement+(n*(rb->bufferSize-1)))%rb->bufferSize;
204 1 }
205
206 /**
207 * @brief Copy addresses of all buffer elements in order.
208 *
209 * @param rb Pointer to ring buffer.
210 * @param lookup Pointer to array of buffer element pointer type and of length buffer->nElements.
211 * Ring data addresses will be written into lookup.
212 */
213 2 void lookupRingBuffer(RINGBUFFER *rb, void **lookup)
214 {
215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assertStreamPrint(NULL, rb->nElements > 0, "empty RingBuffer");
216
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 assertStreamPrint(NULL, lookup, "Target buffer is NULL");
217
218
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (int i = 0; i < rb->nElements; i++) {
219 6 lookup[i] = ((char*)rb->buffer) + (((rb->firstElement+i)%rb->bufferSize)*rb->itemSize);
220 }
221 2 }
222
223 /**
224 * @brief Dumps information about ring buffer to stream.
225 *
226 * @param rb Pointer to ring buffer.
227 */
228 ✗ void infoRingBuffer(RINGBUFFER *rb, int stream)
229 {
230 ✗ if (OMC_ACTIVE_STREAM(stream)) {
231 ✗ infoStreamPrint(stream, 1, "RingBuffer-Info");
232 ✗ infoStreamPrint(stream, 0, "itemSize: %d [size of one item in bytes]", rb->itemSize);
233 ✗ infoStreamPrint(stream, 0, "firstElement: %d [position of first element in buffer]", rb->firstElement);
234 ✗ infoStreamPrint(stream, 0, "nElements: %d [number of elements in buffer]", rb->nElements);
235 ✗ infoStreamPrint(stream, 0, "bufferSize: %d [number of elements which could be stored in buffer]", rb->bufferSize);
236 ✗ messageClose(stream);
237 }
238 ✗ }
239
240 /**
241 * @brief Print a ring buffer with provided print function.
242 *
243 * @param rb Ring buffer to print.
244 * @param stream Stream of type OMC_LOG_STREAM.
245 * @param printDataFunc Function to print address of buffer element and its data to stream.
246 */
247 ✗ void printRingBuffer(RINGBUFFER *rb, int stream, void (*printDataFunc)(void*,int,void*)) {
248 int i;
249 void* bufferElemData;
250
251 ✗ if (omc_useStream[stream]) {
252 ✗ infoStreamPrint(stream, 1, "Printing ring buffer:");
253 ✗ infoRingBuffer(rb, stream);
254
255 ✗ for(i = 0; i < rb->nElements; ++i) {
256 ✗ bufferElemData = getRingData(rb, i);
257 ✗ printDataFunc(bufferElemData, stream, (void*) bufferElemData);
258 }
259
260 ✗ messageClose(stream);
261 }
262 ✗ }
263