Coverage Report

Created: 2025-06-22 06:59

/src/gdal/port/cpl_list.cpp
Line
Count
Source (jump to first uncovered line)
1
/**********************************************************************
2
 *
3
 * Name:     cpl_list.cpp
4
 * Project:  CPL - Common Portability Library
5
 * Purpose:  List functions.
6
 * Author:   Andrey Kiselev, dron@remotesensing.org
7
 *
8
 **********************************************************************
9
 * Copyright (c) 2003, Andrey Kiselev <dron@remotesensing.org>
10
 * Copyright (c) 2008, Even Rouault <even dot rouault at spatialys.com>
11
 *
12
 * SPDX-License-Identifier: MIT
13
 ****************************************************************************/
14
15
#include "cpl_list.h"
16
17
#include <cstddef>
18
19
#include "cpl_conv.h"
20
21
/*=====================================================================
22
                    List manipulation functions.
23
 =====================================================================*/
24
25
/************************************************************************/
26
/*                          CPLListAppend()                             */
27
/************************************************************************/
28
29
/**
30
 * Append an object list and return a pointer to the modified list.
31
 * If the input list is NULL, then a new list is created.
32
 *
33
 * @param psList pointer to list head.
34
 * @param pData pointer to inserted data object. May be NULL.
35
 *
36
 * @return pointer to the head of modified list.
37
 */
38
39
CPLList *CPLListAppend(CPLList *psList, void *pData)
40
0
{
41
0
    CPLList *psLast = nullptr;
42
43
    // Allocate room for the new object.
44
0
    if (psList == nullptr)
45
0
    {
46
0
        psLast = static_cast<CPLList *>(CPLMalloc(sizeof(CPLList)));
47
0
        psList = psLast;
48
0
    }
49
0
    else
50
0
    {
51
0
        psLast = CPLListGetLast(psList);
52
0
        psLast = psLast->psNext =
53
0
            static_cast<CPLList *>(CPLMalloc(sizeof(CPLList)));
54
0
    }
55
56
    // Append object to the end of list.
57
0
    psLast->pData = pData;
58
0
    psLast->psNext = nullptr;
59
60
0
    return psList;
61
0
}
62
63
/************************************************************************/
64
/*                          CPLListInsert()                             */
65
/************************************************************************/
66
67
/**
68
 * Insert an object into list at specified position (zero based).
69
 * If the input list is NULL, then a new list is created.
70
 *
71
 * @param psList pointer to list head.
72
 * @param pData pointer to inserted data object. May be NULL.
73
 * @param nPosition position number to insert an object.
74
 *
75
 * @return pointer to the head of modified list.
76
 */
77
78
CPLList *CPLListInsert(CPLList *psList, void *pData, int nPosition)
79
0
{
80
0
    if (nPosition < 0)
81
0
        return psList;  // Nothing to do.
82
83
0
    if (nPosition == 0)
84
0
    {
85
0
        CPLList *psNew = static_cast<CPLList *>(CPLMalloc(sizeof(CPLList)));
86
0
        psNew->pData = pData;
87
0
        psNew->psNext = psList;
88
0
        psList = psNew;
89
0
        return psList;
90
0
    }
91
92
0
    const int nCount = CPLListCount(psList);
93
94
0
    if (nCount < nPosition)
95
0
    {
96
#ifdef __COVERITY__
97
        CPLError(CE_Failure, CPLE_AppDefined, "Not implemented");
98
#else
99
        // Allocate room for the new object.
100
0
        CPLList *psLast = CPLListGetLast(psList);
101
0
        for (int i = nCount; i <= nPosition - 1; i++)
102
0
        {
103
0
            psLast = CPLListAppend(psLast, nullptr);
104
0
            if (psList == nullptr)
105
0
                psList = psLast;
106
0
            else
107
0
                psLast = psLast->psNext;
108
0
        }
109
0
        psLast = CPLListAppend(psLast, pData);
110
0
        if (psList == nullptr)
111
0
            psList = psLast;
112
113
        /* coverity[leaked_storage] */
114
0
        return psList;
115
0
#endif
116
0
    }
117
118
0
    CPLList *psNew = static_cast<CPLList *>(CPLMalloc(sizeof(CPLList)));
119
0
    psNew->pData = pData;
120
121
0
    CPLList *psCurrent = psList;
122
0
    for (int i = 0; i < nPosition - 1; i++)
123
0
        psCurrent = psCurrent->psNext;
124
0
    psNew->psNext = psCurrent->psNext;
125
0
    psCurrent->psNext = psNew;
126
127
0
    return psList;
128
0
}
129
130
/************************************************************************/
131
/*                          CPLListGetLast()                            */
132
/************************************************************************/
133
134
/**
135
 * Return the pointer to last element in a list.
136
 *
137
 * @param psList pointer to list head.
138
 *
139
 * @return pointer to last element in a list.
140
 */
141
142
CPLList *CPLListGetLast(CPLList *const psList)
143
0
{
144
0
    if (psList == nullptr)
145
0
        return nullptr;
146
147
0
    CPLList *psCurrent = psList;
148
0
    while (psCurrent->psNext)
149
0
        psCurrent = psCurrent->psNext;
150
151
0
    return psCurrent;
152
0
}
153
154
/************************************************************************/
155
/*                          CPLListGet()                                */
156
/************************************************************************/
157
158
/**
159
 * Return the pointer to the specified element in a list.
160
 *
161
 * @param psList pointer to list head.
162
 * @param nPosition the index of the element in the list, 0 being the
163
 * first element.
164
 *
165
 * @return pointer to the specified element in a list.
166
 */
167
168
CPLList *CPLListGet(CPLList *psList, int nPosition)
169
0
{
170
0
    if (nPosition < 0)
171
0
        return nullptr;
172
173
0
    CPLList *psCurrent = psList;
174
0
    int iItem = 0;
175
0
    while (iItem < nPosition && psCurrent)
176
0
    {
177
0
        psCurrent = psCurrent->psNext;
178
0
        iItem++;
179
0
    }
180
181
0
    return psCurrent;
182
0
}
183
184
/************************************************************************/
185
/*                          CPLListCount()                              */
186
/************************************************************************/
187
188
/**
189
 * Return the number of elements in a list.
190
 *
191
 * @param psList pointer to list head.
192
 *
193
 * @return number of elements in a list.
194
 */
195
196
int CPLListCount(const CPLList *psList)
197
0
{
198
0
    int nItems = 0;
199
0
    const CPLList *psCurrent = psList;
200
201
0
    while (psCurrent)
202
0
    {
203
0
        nItems++;
204
0
        psCurrent = psCurrent->psNext;
205
0
    }
206
207
0
    return nItems;
208
0
}
209
210
/************************************************************************/
211
/*                          CPLListRemove()                             */
212
/************************************************************************/
213
214
/**
215
 * Remove the element from the specified position (zero based) in a list. Data
216
 * object contained in removed element must be freed by the caller first.
217
 *
218
 * @param psList pointer to list head.
219
 * @param nPosition position number to delete an element.
220
 *
221
 * @return pointer to the head of modified list.
222
 */
223
224
CPLList *CPLListRemove(CPLList *psList, int nPosition)
225
0
{
226
227
0
    if (psList == nullptr)
228
0
        return nullptr;
229
230
0
    if (nPosition < 0)
231
0
        return psList; /* Nothing to do. */
232
233
0
    if (nPosition == 0)
234
0
    {
235
0
        CPLList *psCurrent = psList->psNext;
236
0
        CPLFree(psList);
237
0
        psList = psCurrent;
238
0
        return psList;
239
0
    }
240
241
0
    CPLList *psCurrent = psList;
242
0
    for (int i = 0; i < nPosition - 1; i++)
243
0
    {
244
0
        psCurrent = psCurrent->psNext;
245
        // psCurrent == NULL if nPosition >= CPLListCount(psList).
246
0
        if (psCurrent == nullptr)
247
0
            return psList;
248
0
    }
249
0
    CPLList *psRemoved = psCurrent->psNext;
250
    // psRemoved == NULL if nPosition >= CPLListCount(psList).
251
0
    if (psRemoved == nullptr)
252
0
        return psList;
253
0
    psCurrent->psNext = psRemoved->psNext;
254
0
    CPLFree(psRemoved);
255
256
0
    return psList;
257
0
}
258
259
/************************************************************************/
260
/*                          CPLListDestroy()                            */
261
/************************************************************************/
262
263
/**
264
 * Destroy a list. Caller responsible for freeing data objects contained in
265
 * list elements.
266
 *
267
 * @param psList pointer to list head.
268
 *
269
 */
270
271
void CPLListDestroy(CPLList *psList)
272
0
{
273
0
    CPLList *psCurrent = psList;
274
275
0
    while (psCurrent)
276
0
    {
277
0
        CPLList *const psNext = psCurrent->psNext;
278
0
        CPLFree(psCurrent);
279
0
        psCurrent = psNext;
280
0
    }
281
0
}
282
283
/************************************************************************/
284
/*                          CPLListGetNext()                            */
285
/************************************************************************/
286
287
/**
288
 * Return the pointer to next element in a list.
289
 *
290
 * @param psElement pointer to list element.
291
 *
292
 * @return pointer to the list element preceded by the given element.
293
 */
294
295
CPLList *CPLListGetNext(const CPLList *psElement)
296
0
{
297
0
    if (psElement == nullptr)
298
0
        return nullptr;
299
300
0
    return psElement->psNext;
301
0
}
302
303
/************************************************************************/
304
/*                          CPLListGetData()                            */
305
/************************************************************************/
306
307
/**
308
 * Return pointer to the data object contained in given list element.
309
 *
310
 * @param psElement pointer to list element.
311
 *
312
 * @return pointer to the data object contained in given list element.
313
 */
314
315
void *CPLListGetData(const CPLList *psElement)
316
0
{
317
0
    if (psElement == nullptr)
318
0
        return nullptr;
319
320
0
    return psElement->pData;
321
0
}