Coverage Report

Created: 2025-07-01 06:54

/src/S2OPC/src/Common/helpers/sopc_array.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Licensed to Systerel under one or more contributor license
3
 * agreements. See the NOTICE file distributed with this work
4
 * for additional information regarding copyright ownership.
5
 * Systerel licenses this file to you under the Apache
6
 * License, Version 2.0 (the "License"); you may not use this
7
 * file except in compliance with the License. You may obtain
8
 * a copy of the License at
9
 *
10
 *   http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19
20
#include "sopc_array.h"
21
22
#include <stdint.h>
23
#include <stdlib.h> /* qsort */
24
#include <string.h>
25
26
#include "sopc_assert.h"
27
#include "sopc_mem_alloc.h"
28
29
0
#define ARRAY_ELT(a, idx) ((void*) (a->data + idx * a->element_size))
30
31
struct _SOPC_Array
32
{
33
    uint8_t* data;
34
    size_t element_size;
35
    size_t sz;
36
    size_t cap;
37
    SOPC_Array_Free_Func* free_func;
38
};
39
40
static bool array_grow(SOPC_Array* a, size_t min_size)
41
0
{
42
0
    SOPC_ASSERT(a != NULL);
43
44
0
    if (a->cap >= min_size)
45
0
    {
46
0
        return true;
47
0
    }
48
49
0
    size_t cap = (a->cap != 0 ? a->cap : 1);
50
51
0
    while (cap < min_size)
52
0
    {
53
0
        cap *= 2;
54
0
    }
55
56
0
    void* data = SOPC_Realloc(a->data, a->cap * a->element_size, cap * a->element_size);
57
58
0
    if (data == NULL)
59
0
    {
60
0
        return false;
61
0
    }
62
63
0
    a->data = data;
64
0
    a->cap = cap;
65
66
0
    return true;
67
0
}
68
69
SOPC_Array* SOPC_Array_Create(size_t element_size, size_t initial_capacity, SOPC_Array_Free_Func* free_func)
70
0
{
71
0
    SOPC_Array* a = SOPC_Calloc(1, sizeof(SOPC_Array));
72
73
0
    if (a == NULL)
74
0
    {
75
0
        return NULL;
76
0
    }
77
78
0
    a->element_size = element_size;
79
0
    a->free_func = free_func;
80
81
0
    if (!array_grow(a, initial_capacity))
82
0
    {
83
0
        SOPC_Free(a);
84
0
        return NULL;
85
0
    }
86
87
0
    return a;
88
0
}
89
90
SOPC_Array* SOPC_Array_Copy(const SOPC_Array* array)
91
0
{
92
0
    if (NULL == array)
93
0
    {
94
0
        return NULL;
95
0
    }
96
97
0
    SOPC_Array* copy = SOPC_Array_Create(array->element_size, array->sz, array->free_func);
98
99
0
    if (copy == NULL)
100
0
    {
101
0
        return NULL;
102
0
    }
103
104
0
    if (copy->data != NULL)
105
0
    {
106
0
        memcpy(copy->data, array->data, array->element_size * array->sz);
107
0
    }
108
109
0
    copy->sz = array->sz;
110
111
0
    return copy;
112
0
}
113
114
void SOPC_Array_Delete(SOPC_Array* array)
115
0
{
116
0
    if (array == NULL)
117
0
    {
118
0
        return;
119
0
    }
120
121
0
    if (array->free_func != NULL)
122
0
    {
123
0
        for (size_t i = 0; i < array->sz; ++i)
124
0
        {
125
0
            array->free_func(ARRAY_ELT(array, i));
126
0
        }
127
0
    }
128
129
0
    SOPC_Free(array->data);
130
0
    SOPC_Free(array);
131
0
}
132
133
bool SOPC_Array_Append_Values(SOPC_Array* array, const void* data, size_t n_elements)
134
0
{
135
0
    if (NULL == array)
136
0
    {
137
0
        return false;
138
0
    }
139
140
0
    if (n_elements == 0)
141
0
    {
142
0
        return true;
143
0
    }
144
145
0
    if (!array_grow(array, array->sz + n_elements))
146
0
    {
147
0
        return false;
148
0
    }
149
150
0
    if (data != NULL)
151
0
    {
152
0
        memcpy(ARRAY_ELT(array, array->sz), data, n_elements * array->element_size);
153
0
    }
154
0
    else
155
0
    {
156
0
        memset(ARRAY_ELT(array, array->sz), 0, n_elements * array->element_size);
157
0
    }
158
159
0
    array->sz += n_elements;
160
161
0
    return true;
162
0
}
163
164
void* SOPC_Array_Get_Ptr(const SOPC_Array* array, size_t index)
165
0
{
166
0
    if (NULL == array)
167
0
    {
168
0
        return NULL;
169
0
    }
170
0
    SOPC_ASSERT(index < array->sz);
171
172
0
    return ARRAY_ELT(array, index);
173
0
}
174
175
size_t SOPC_Array_Size(const SOPC_Array* array)
176
0
{
177
0
    if (array != NULL)
178
0
    {
179
0
        return array->sz;
180
0
    }
181
0
    return 0;
182
0
}
183
184
void SOPC_Array_Sort(SOPC_Array* array, SOPC_Array_Compare_Func* compare_func)
185
0
{
186
0
    SOPC_ASSERT(array != NULL);
187
0
    qsort(array->data, array->sz, array->element_size, compare_func);
188
0
}
189
190
void* SOPC_Array_Into_Raw(SOPC_Array* array)
191
0
{
192
0
    if (NULL == array)
193
0
    {
194
0
        return NULL;
195
0
    }
196
197
0
    void* data = array->data;
198
199
0
    if (array->sz < array->cap)
200
0
    {
201
0
        data = SOPC_Realloc(data, array->cap * array->element_size, array->sz * array->element_size);
202
0
    }
203
204
0
    SOPC_Free(array);
205
206
0
    return data;
207
0
}
208
209
SOPC_Array_Free_Func* SOPC_Array_Get_Free_Func(SOPC_Array* array)
210
0
{
211
0
    if (NULL == array)
212
0
    {
213
0
        return NULL;
214
0
    }
215
0
    return array->free_func;
216
0
}
217
218
void SOPC_Array_Set_Free_Func(SOPC_Array* array, SOPC_Array_Free_Func* func)
219
0
{
220
0
    SOPC_ASSERT(array != NULL);
221
0
    array->free_func = func;
222
0
}