Coverage Report

Created: 2025-06-13 06:29

/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
        // Allocate room for the new object.
97
0
        CPLList *psLast = CPLListGetLast(psList);
98
0
        for (int i = nCount; i <= nPosition - 1; i++)
99
0
        {
100
0
            psLast = CPLListAppend(psLast, nullptr);
101
0
            if (psList == nullptr)
102
0
                psList = psLast;
103
0
            else
104
0
                psLast = psLast->psNext;
105
0
        }
106
0
        psLast = CPLListAppend(psLast, pData);
107
0
        if (psList == nullptr)
108
0
            psList = psLast;
109
110
        /* coverity[leaked_storage] */
111
0
        return psList;
112
0
    }
113
114
0
    CPLList *psNew = static_cast<CPLList *>(CPLMalloc(sizeof(CPLList)));
115
0
    psNew->pData = pData;
116
117
0
    CPLList *psCurrent = psList;
118
0
    for (int i = 0; i < nPosition - 1; i++)
119
0
        psCurrent = psCurrent->psNext;
120
0
    psNew->psNext = psCurrent->psNext;
121
0
    psCurrent->psNext = psNew;
122
123
0
    return psList;
124
0
}
125
126
/************************************************************************/
127
/*                          CPLListGetLast()                            */
128
/************************************************************************/
129
130
/**
131
 * Return the pointer to last element in a list.
132
 *
133
 * @param psList pointer to list head.
134
 *
135
 * @return pointer to last element in a list.
136
 */
137
138
CPLList *CPLListGetLast(CPLList *const psList)
139
0
{
140
0
    if (psList == nullptr)
141
0
        return nullptr;
142
143
0
    CPLList *psCurrent = psList;
144
0
    while (psCurrent->psNext)
145
0
        psCurrent = psCurrent->psNext;
146
147
0
    return psCurrent;
148
0
}
149
150
/************************************************************************/
151
/*                          CPLListGet()                                */
152
/************************************************************************/
153
154
/**
155
 * Return the pointer to the specified element in a list.
156
 *
157
 * @param psList pointer to list head.
158
 * @param nPosition the index of the element in the list, 0 being the
159
 * first element.
160
 *
161
 * @return pointer to the specified element in a list.
162
 */
163
164
CPLList *CPLListGet(CPLList *psList, int nPosition)
165
0
{
166
0
    if (nPosition < 0)
167
0
        return nullptr;
168
169
0
    CPLList *psCurrent = psList;
170
0
    int iItem = 0;
171
0
    while (iItem < nPosition && psCurrent)
172
0
    {
173
0
        psCurrent = psCurrent->psNext;
174
0
        iItem++;
175
0
    }
176
177
0
    return psCurrent;
178
0
}
179
180
/************************************************************************/
181
/*                          CPLListCount()                              */
182
/************************************************************************/
183
184
/**
185
 * Return the number of elements in a list.
186
 *
187
 * @param psList pointer to list head.
188
 *
189
 * @return number of elements in a list.
190
 */
191
192
int CPLListCount(const CPLList *psList)
193
0
{
194
0
    int nItems = 0;
195
0
    const CPLList *psCurrent = psList;
196
197
0
    while (psCurrent)
198
0
    {
199
0
        nItems++;
200
0
        psCurrent = psCurrent->psNext;
201
0
    }
202
203
0
    return nItems;
204
0
}
205
206
/************************************************************************/
207
/*                          CPLListRemove()                             */
208
/************************************************************************/
209
210
/**
211
 * Remove the element from the specified position (zero based) in a list. Data
212
 * object contained in removed element must be freed by the caller first.
213
 *
214
 * @param psList pointer to list head.
215
 * @param nPosition position number to delete an element.
216
 *
217
 * @return pointer to the head of modified list.
218
 */
219
220
CPLList *CPLListRemove(CPLList *psList, int nPosition)
221
0
{
222
223
0
    if (psList == nullptr)
224
0
        return nullptr;
225
226
0
    if (nPosition < 0)
227
0
        return psList; /* Nothing to do. */
228
229
0
    if (nPosition == 0)
230
0
    {
231
0
        CPLList *psCurrent = psList->psNext;
232
0
        CPLFree(psList);
233
0
        psList = psCurrent;
234
0
        return psList;
235
0
    }
236
237
0
    CPLList *psCurrent = psList;
238
0
    for (int i = 0; i < nPosition - 1; i++)
239
0
    {
240
0
        psCurrent = psCurrent->psNext;
241
        // psCurrent == NULL if nPosition >= CPLListCount(psList).
242
0
        if (psCurrent == nullptr)
243
0
            return psList;
244
0
    }
245
0
    CPLList *psRemoved = psCurrent->psNext;
246
    // psRemoved == NULL if nPosition >= CPLListCount(psList).
247
0
    if (psRemoved == nullptr)
248
0
        return psList;
249
0
    psCurrent->psNext = psRemoved->psNext;
250
0
    CPLFree(psRemoved);
251
252
0
    return psList;
253
0
}
254
255
/************************************************************************/
256
/*                          CPLListDestroy()                            */
257
/************************************************************************/
258
259
/**
260
 * Destroy a list. Caller responsible for freeing data objects contained in
261
 * list elements.
262
 *
263
 * @param psList pointer to list head.
264
 *
265
 */
266
267
void CPLListDestroy(CPLList *psList)
268
0
{
269
0
    CPLList *psCurrent = psList;
270
271
0
    while (psCurrent)
272
0
    {
273
0
        CPLList *const psNext = psCurrent->psNext;
274
0
        CPLFree(psCurrent);
275
0
        psCurrent = psNext;
276
0
    }
277
0
}
278
279
/************************************************************************/
280
/*                          CPLListGetNext()                            */
281
/************************************************************************/
282
283
/**
284
 * Return the pointer to next element in a list.
285
 *
286
 * @param psElement pointer to list element.
287
 *
288
 * @return pointer to the list element preceded by the given element.
289
 */
290
291
CPLList *CPLListGetNext(const CPLList *psElement)
292
0
{
293
0
    if (psElement == nullptr)
294
0
        return nullptr;
295
296
0
    return psElement->psNext;
297
0
}
298
299
/************************************************************************/
300
/*                          CPLListGetData()                            */
301
/************************************************************************/
302
303
/**
304
 * Return pointer to the data object contained in given list element.
305
 *
306
 * @param psElement pointer to list element.
307
 *
308
 * @return pointer to the data object contained in given list element.
309
 */
310
311
void *CPLListGetData(const CPLList *psElement)
312
0
{
313
0
    if (psElement == nullptr)
314
0
        return nullptr;
315
316
0
    return psElement->pData;
317
0
}