Coverage Report

Created: 2026-09-14 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/port/cpl_string.h
Line
Count
Source
1
/**********************************************************************
2
 *
3
 * Name:     cpl_string.h
4
 * Project:  CPL - Common Portability Library
5
 * Purpose:  String and StringList functions.
6
 * Author:   Daniel Morissette, dmorissette@mapgears.com
7
 *
8
 **********************************************************************
9
 * Copyright (c) 1998, Daniel Morissette
10
 * Copyright (c) 2008-2014, Even Rouault <even dot rouault at spatialys.com>
11
 *
12
 * SPDX-License-Identifier: MIT
13
 ****************************************************************************/
14
15
#ifndef CPL_STRING_H_INCLUDED
16
#define CPL_STRING_H_INCLUDED
17
18
#include "cpl_error.h"
19
#include "cpl_conv.h"
20
#include "cpl_vsi.h"
21
22
#include <stdbool.h>
23
24
/**
25
 * \file cpl_string.h
26
 *
27
 * Various convenience functions for working with strings and string lists.
28
 *
29
 * A StringList is just an array of strings with the last pointer being
30
 * NULL.  An empty StringList may be either a NULL pointer, or a pointer to
31
 * a pointer memory location with a NULL value.
32
 *
33
 * A common convention for StringLists is to use them to store name/value
34
 * lists.  In this case the contents are treated like a dictionary of
35
 * name/value pairs.  The actual data is formatted with each string having
36
 * the format "<name>:<value>" (though "=" is also an acceptable separator).
37
 * A number of the functions in the file operate on name/value style
38
 * string lists (such as CSLSetNameValue(), and CSLFetchNameValue()).
39
 *
40
 * To some extent the CPLStringList C++ class can be used to abstract
41
 * managing string lists a bit but still be able to return them from C
42
 * functions.
43
 *
44
 */
45
46
CPL_C_START
47
48
char CPL_DLL **CSLAddString(char **papszStrList,
49
                            const char *pszNewString) CPL_WARN_UNUSED_RESULT;
50
char CPL_DLL **
51
CSLAddStringMayFail(char **papszStrList,
52
                    const char *pszNewString) CPL_WARN_UNUSED_RESULT;
53
int CPL_DLL CSLCount(CSLConstList papszStrList);
54
const char CPL_DLL *CSLGetField(CSLConstList, int);
55
void CPL_DLL CPL_STDCALL CSLDestroy(char **papszStrList);
56
char CPL_DLL **CSLDuplicate(CSLConstList papszStrList) CPL_WARN_UNUSED_RESULT;
57
char CPL_DLL **CSLMerge(char **papszOrig,
58
                        CSLConstList papszOverride) CPL_WARN_UNUSED_RESULT;
59
60
char CPL_DLL **CSLTokenizeString(const char *pszString) CPL_WARN_UNUSED_RESULT;
61
char CPL_DLL **
62
CSLTokenizeStringComplex(const char *pszString, const char *pszDelimiter,
63
                         int bHonourStrings,
64
                         int bAllowEmptyTokens) CPL_WARN_UNUSED_RESULT;
65
char CPL_DLL **CSLTokenizeString2(const char *pszString,
66
                                  const char *pszDelimiter,
67
                                  int nCSLTFlags) CPL_WARN_UNUSED_RESULT;
68
69
/** Flag for CSLTokenizeString2() to honour strings delimited by double quotes */
70
1.41k
#define CSLT_HONOURSTRINGS 0x0001
71
/** Flag for CSLTokenizeString2() to allow empty tokens */
72
1.41k
#define CSLT_ALLOWEMPTYTOKENS 0x0002
73
/** Flag for CSLTokenizeString2() to preserve quotes */
74
0
#define CSLT_PRESERVEQUOTES 0x0004
75
/** Flag for CSLTokenizeString2() to preserve escape characters */
76
0
#define CSLT_PRESERVEESCAPES 0x0008
77
/** Flag for CSLTokenizeString2() to strip leading spaces */
78
1.41k
#define CSLT_STRIPLEADSPACES 0x0010
79
/** Flag for CSLTokenizeString2() to strip trailing spaces */
80
1.41k
#define CSLT_STRIPENDSPACES 0x0020
81
/** Flag for CSLTokenizeString2() to honour strings delimited by single quotes (GDAL >= 3.14) */
82
1.41k
#define CSLT_HONOURSINGLEQUOTES 0x0040
83
84
int CPL_DLL CSLPrint(CSLConstList papszStrList, FILE *fpOut);
85
char CPL_DLL **CSLLoad(const char *pszFname) CPL_WARN_UNUSED_RESULT;
86
char CPL_DLL **CSLLoad2(const char *pszFname, int nMaxLines, int nMaxCols,
87
                        CSLConstList papszOptions) CPL_WARN_UNUSED_RESULT;
88
int CPL_DLL CSLSave(CSLConstList papszStrList, const char *pszFname);
89
90
char CPL_DLL **
91
CSLInsertStrings(char **papszStrList, int nInsertAtLineNo,
92
                 CSLConstList papszNewLines) CPL_WARN_UNUSED_RESULT;
93
char CPL_DLL **CSLInsertString(char **papszStrList, int nInsertAtLineNo,
94
                               const char *pszNewLine) CPL_WARN_UNUSED_RESULT;
95
char CPL_DLL **
96
CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete, int nNumToRemove,
97
                 char ***ppapszRetStrings) CPL_WARN_UNUSED_RESULT;
98
int CPL_DLL CSLFindString(CSLConstList papszList, const char *pszTarget);
99
int CPL_DLL CSLFindStringCaseSensitive(CSLConstList papszList,
100
                                       const char *pszTarget);
101
int CPL_DLL CSLPartialFindString(CSLConstList papszHaystack,
102
                                 const char *pszNeedle);
103
int CPL_DLL CSLFindName(CSLConstList papszStrList, const char *pszName);
104
int CPL_DLL CSLFetchBoolean(CSLConstList papszStrList, const char *pszKey,
105
                            int bDefault);
106
107
/* TODO: Deprecate CSLTestBoolean.  Remove in GDAL 3.x. */
108
int CPL_DLL CSLTestBoolean(const char *pszValue);
109
/* Do not use CPLTestBoolean in C++ code.  Use CPLTestBool. */
110
int CPL_DLL CPLTestBoolean(const char *pszValue);
111
112
bool CPL_DLL CPLTestBool(const char *pszValue);
113
bool CPL_DLL CPLFetchBool(CSLConstList papszStrList, const char *pszKey,
114
                          bool bDefault);
115
bool CPLTestConfigOption(const char *pszValue);
116
#ifdef __cplusplus
117
CPL_C_END
118
119
/*! @cond Doxygen_Suppress */
120
inline bool CPLFetchBool(CSLConstList papszStrList, const char *pszKey,
121
                         int bDefault)
122
0
{
123
0
    return CPLFetchBool(papszStrList, pszKey, bDefault != 0);
124
0
}
125
126
bool CPLFetchBool(CSLConstList papszStrList, const char *pszKey,
127
                  const char *) = delete;
128
129
/*! @endcond */
130
CPL_C_START
131
#endif
132
CPLErr CPL_DLL CPLParseMemorySize(const char *pszValue, GIntBig *pnValue,
133
                                  bool *pbUnitSpecified);
134
135
const char CPL_DLL *CPLParseNameValue(const char *pszNameValue, char **ppszKey);
136
const char CPL_DLL *CPLParseNameValueSep(const char *pszNameValue,
137
                                         char **ppszKey, char chSep);
138
139
const char CPL_DLL *CSLFetchNameValue(CSLConstList papszStrList,
140
                                      const char *pszName);
141
const char CPL_DLL *CSLFetchNameValueDef(CSLConstList papszStrList,
142
                                         const char *pszName,
143
                                         const char *pszDefault);
144
char CPL_DLL **CSLFetchNameValueMultiple(CSLConstList papszStrList,
145
                                         const char *pszName);
146
char CPL_DLL **CSLAddNameValue(char **papszStrList, const char *pszName,
147
                               const char *pszValue) CPL_WARN_UNUSED_RESULT;
148
char CPL_DLL **CSLSetNameValue(char **papszStrList, const char *pszName,
149
                               const char *pszValue) CPL_WARN_UNUSED_RESULT;
150
void CPL_DLL CSLSetNameValueSeparator(char **papszStrList,
151
                                      const char *pszSeparator);
152
153
char CPL_DLL **CSLParseCommandLine(const char *pszCommandLine);
154
155
/** Scheme for CPLEscapeString()/CPLUnescapeString() for backlash quoting */
156
0
#define CPLES_BackslashQuotable 0
157
/** Scheme for CPLEscapeString()/CPLUnescapeString() for XML */
158
0
#define CPLES_XML 1
159
/** Scheme for CPLEscapeString()/CPLUnescapeString() for URL */
160
0
#define CPLES_URL 2
161
/** Scheme for CPLEscapeString()/CPLUnescapeString() for SQL */
162
0
#define CPLES_SQL 3
163
/** Scheme for CPLEscapeString()/CPLUnescapeString() for CSV */
164
0
#define CPLES_CSV 4
165
/** Scheme for CPLEscapeString()/CPLUnescapeString() for XML (preserves quotes)
166
 */
167
0
#define CPLES_XML_BUT_QUOTES 5
168
/** Scheme for CPLEscapeString()/CPLUnescapeString() for CSV (forced quoting) */
169
0
#define CPLES_CSV_FORCE_QUOTING 6
170
/** Scheme for CPLEscapeString()/CPLUnescapeString() for SQL identifiers */
171
0
#define CPLES_SQLI 7
172
173
char CPL_DLL *CPLEscapeString(const char *pszString, int nLength,
174
                              int nScheme) CPL_WARN_UNUSED_RESULT;
175
char CPL_DLL *CPLUnescapeString(const char *pszString, int *pnLength,
176
                                int nScheme) CPL_WARN_UNUSED_RESULT;
177
178
char CPL_DLL *CPLBinaryToHex(int nBytes,
179
                             const GByte *pabyData) CPL_WARN_UNUSED_RESULT;
180
GByte CPL_DLL *CPLHexToBinary(const char *pszHex,
181
                              int *pnBytes) CPL_WARN_UNUSED_RESULT;
182
183
char CPL_DLL *CPLBase64Encode(int nBytes,
184
                              const GByte *pabyData) CPL_WARN_UNUSED_RESULT;
185
int CPL_DLL CPLBase64DecodeInPlace(GByte *pszBase64) CPL_WARN_UNUSED_RESULT;
186
187
/** Type of value */
188
typedef enum
189
{
190
    CPL_VALUE_STRING, /**< String */
191
    CPL_VALUE_REAL,   /**< Real number */
192
    CPL_VALUE_INTEGER /**< Integer */
193
} CPLValueType;
194
195
CPLValueType CPL_DLL CPLGetValueType(const char *pszValue);
196
197
int CPL_DLL CPLToupper(int c);
198
int CPL_DLL CPLTolower(int c);
199
200
size_t CPL_DLL CPLStrlcpy(char *pszDest, const char *pszSrc, size_t nDestSize);
201
size_t CPL_DLL CPLStrlcat(char *pszDest, const char *pszSrc, size_t nDestSize);
202
size_t CPL_DLL CPLStrnlen(const char *pszStr, size_t nMaxLen);
203
204
/* -------------------------------------------------------------------- */
205
/*      Locale independent formatting functions.                        */
206
/* -------------------------------------------------------------------- */
207
int CPL_DLL CPLvsnprintf(char *str, size_t size,
208
                         CPL_FORMAT_STRING(const char *fmt), va_list args)
209
    CPL_PRINT_FUNC_FORMAT(3, 0);
210
211
/* ALIAS_CPLSNPRINTF_AS_SNPRINTF might be defined to enable GCC 7 */
212
/* -Wformat-truncation= warnings, but shouldn't be set for normal use */
213
#if defined(ALIAS_CPLSNPRINTF_AS_SNPRINTF)
214
#define CPLsnprintf snprintf
215
#else
216
int CPL_DLL CPLsnprintf(char *str, size_t size,
217
                        CPL_FORMAT_STRING(const char *fmt), ...)
218
    CPL_PRINT_FUNC_FORMAT(3, 4);
219
#endif
220
221
/*! @cond Doxygen_Suppress */
222
#if defined(GDAL_COMPILATION) && !defined(DONT_DEPRECATE_SPRINTF)
223
int CPL_DLL CPLsprintf(char *str, CPL_FORMAT_STRING(const char *fmt), ...)
224
    CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_DEPRECATED("Use CPLsnprintf instead");
225
#else
226
int CPL_DLL CPLsprintf(char *str, CPL_FORMAT_STRING(const char *fmt), ...)
227
    CPL_PRINT_FUNC_FORMAT(2, 3);
228
#endif
229
/*! @endcond */
230
int CPL_DLL CPLprintf(CPL_FORMAT_STRING(const char *fmt), ...)
231
    CPL_PRINT_FUNC_FORMAT(1, 2);
232
233
/* For some reason Doxygen_Suppress is needed to avoid warning. Not sure why */
234
/*! @cond Doxygen_Suppress */
235
/* caution: only works with limited number of formats */
236
int CPL_DLL CPLsscanf(const char *str, CPL_SCANF_FORMAT_STRING(const char *fmt),
237
                      ...) CPL_SCAN_FUNC_FORMAT(2, 3);
238
/*! @endcond */
239
240
const char CPL_DLL *CPLSPrintf(CPL_FORMAT_STRING(const char *fmt), ...)
241
    CPL_PRINT_FUNC_FORMAT(1, 2) CPL_WARN_UNUSED_RESULT;
242
char CPL_DLL **CSLAppendPrintf(char **papszStrList,
243
                               CPL_FORMAT_STRING(const char *fmt), ...)
244
    CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_UNUSED_RESULT;
245
int CPL_DLL CPLVASPrintf(char **buf, CPL_FORMAT_STRING(const char *fmt),
246
                         va_list args) CPL_PRINT_FUNC_FORMAT(2, 0);
247
248
/* -------------------------------------------------------------------- */
249
/*      RFC 23 character set conversion/recoding API (cpl_recode.cpp).  */
250
/* -------------------------------------------------------------------- */
251
/** Encoding of the current locale */
252
#define CPL_ENC_LOCALE ""
253
/** UTF-8 encoding */
254
0
#define CPL_ENC_UTF8 "UTF-8"
255
/** UTF-16 encoding */
256
0
#define CPL_ENC_UTF16 "UTF-16"
257
/** UCS-2 encoding */
258
0
#define CPL_ENC_UCS2 "UCS-2"
259
/** UCS-4 encoding */
260
0
#define CPL_ENC_UCS4 "UCS-4"
261
/** ASCII encoding */
262
0
#define CPL_ENC_ASCII "ASCII"
263
/** ISO-8859-1 (LATIN1) encoding */
264
0
#define CPL_ENC_ISO8859_1 "ISO-8859-1"
265
266
int CPL_DLL CPLEncodingCharSize(const char *pszEncoding);
267
/*! @cond Doxygen_Suppress */
268
void CPL_DLL CPLClearRecodeWarningFlags(void);
269
/*! @endcond */
270
char CPL_DLL *CPLRecode(const char *pszSource, const char *pszSrcEncoding,
271
                        const char *pszDstEncoding)
272
    CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
273
char CPL_DLL *
274
CPLRecodeFromWChar(const wchar_t *pwszSource, const char *pszSrcEncoding,
275
                   const char *pszDstEncoding) CPL_WARN_UNUSED_RESULT;
276
wchar_t CPL_DLL *
277
CPLRecodeToWChar(const char *pszSource, const char *pszSrcEncoding,
278
                 const char *pszDstEncoding) CPL_WARN_UNUSED_RESULT;
279
int CPL_DLL CPLIsUTF8(const char *pabyData, int nLen);
280
bool CPL_DLL CPLIsASCII(const char *pabyData, size_t nLen);
281
char CPL_DLL *CPLForceToASCII(const char *pabyData, int nLen,
282
                              char chReplacementChar) CPL_WARN_UNUSED_RESULT;
283
char CPL_DLL *CPLUTF8ForceToASCII(const char *pszStr, char chReplacementChar)
284
    CPL_WARN_UNUSED_RESULT;
285
int CPL_DLL CPLStrlenUTF8(const char *pszUTF8Str)
286
    /*! @cond Doxygen_Suppress */
287
    CPL_WARN_DEPRECATED("Use CPLStrlenUTF8Ex() instead")
288
    /*! @endcond */
289
    ;
290
size_t CPL_DLL CPLStrlenUTF8Ex(const char *pszUTF8Str);
291
int CPL_DLL CPLCanRecode(const char *pszTestStr, const char *pszSrcEncoding,
292
                         const char *pszDstEncoding) CPL_WARN_UNUSED_RESULT;
293
CPL_C_END
294
295
#if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
296
297
extern "C++"
298
{
299
    std::string CPL_DLL CPLRemoveSQLComments(const std::string &osInput);
300
}
301
302
#endif
303
304
/************************************************************************/
305
/*                              CPLString                               */
306
/************************************************************************/
307
308
#if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
309
310
extern "C++"
311
{
312
#ifndef DOXYGEN_SKIP
313
#include <string>
314
#include <vector>
315
#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
316
#define HAVE_STRING_VIEW
317
#include <string_view>
318
#endif
319
#endif
320
321
// VC++ implicitly applies __declspec(dllexport) to template base classes
322
// of classes marked with __declspec(dllexport).
323
// Hence, if marked with CPL_DLL, VC++ would export symbols for the
324
// specialization of std::basic_string<char>, since it is a base class of
325
// CPLString. As a result, if an application linked both gdal.dll and a static
326
// library that (implicitly) instantiates std::string (almost all do!), then the
327
// linker would emit an error concerning duplicate symbols for std::string. The
328
// least intrusive solution is to not mark the whole class with
329
// __declspec(dllexport) for VC++, but only its non-inline methods.
330
#ifdef _MSC_VER
331
#define CPLSTRING_CLASS_DLL
332
#define CPLSTRING_METHOD_DLL CPL_DLL
333
#else
334
/*! @cond Doxygen_Suppress */
335
#define CPLSTRING_CLASS_DLL CPL_DLL
336
#define CPLSTRING_METHOD_DLL
337
/*! @endcond */
338
#endif
339
340
    //! Convenient string class based on std::string.
341
    class CPLSTRING_CLASS_DLL CPLString : public std::string
342
    {
343
      public:
344
        /** Constructor */
345
        CPLString(void)
346
6.62k
        {
347
6.62k
        }
348
349
        /** Constructor */
350
        // cppcheck-suppress noExplicitConstructor
351
25.9k
        CPLString(const std::string &oStr) : std::string(oStr)
352
25.9k
        {
353
25.9k
        }
354
355
        /** Constructor */
356
        // cppcheck-suppress noExplicitConstructor
357
8.01k
        CPLString(const char *pszStr) : std::string(pszStr)
358
8.01k
        {
359
8.01k
        }
360
361
        /** Constructor */
362
0
        CPLString(const char *pszStr, size_t n) : std::string(pszStr, n)
363
0
        {
364
0
        }
365
366
        /** Return string as zero terminated character array */
367
        operator const char *(void) const
368
6.41k
        {
369
6.41k
            return c_str();
370
6.41k
        }
371
372
        /** Return character at specified index */
373
        char &operator[](std::string::size_type i)
374
69.3k
        {
375
69.3k
            return std::string::operator[](i);
376
69.3k
        }
377
378
        /** Return character at specified index */
379
        const char &operator[](std::string::size_type i) const
380
0
        {
381
0
            return std::string::operator[](i);
382
0
        }
383
384
        /** Return character at specified index */
385
        char &operator[](int i)
386
0
        {
387
0
            return std::string::operator[](
388
0
                static_cast<std::string::size_type>(i));
389
0
        }
390
391
        /** Return character at specified index */
392
        const char &operator[](int i) const
393
0
        {
394
0
            return std::string::operator[](
395
0
                static_cast<std::string::size_type>(i));
396
0
        }
397
398
        /** Clear the string */
399
        void Clear()
400
0
        {
401
0
            resize(0);
402
0
        }
403
404
        /** Assign specified string and take ownership of it (assumed to be
405
         * allocated with CPLMalloc()). NULL can be safely passed to clear the
406
         * string. */
407
        void Seize(char *pszValue)
408
0
        {
409
0
            if (pszValue == nullptr)
410
0
                Clear();
411
0
            else
412
0
            {
413
0
                *this = pszValue;
414
0
                CPLFree(pszValue);
415
0
            }
416
0
        }
417
418
        /* There seems to be a bug in the way the compiler count indices...
419
         * Should be CPL_PRINT_FUNC_FORMAT (1, 2) */
420
        CPLSTRING_METHOD_DLL CPLString &
421
        Printf(CPL_FORMAT_STRING(const char *pszFormat), ...)
422
            CPL_PRINT_FUNC_FORMAT(2, 3);
423
        CPLSTRING_METHOD_DLL CPLString &
424
        vPrintf(CPL_FORMAT_STRING(const char *pszFormat), va_list args)
425
            CPL_PRINT_FUNC_FORMAT(2, 0);
426
        CPLSTRING_METHOD_DLL CPLString &
427
        FormatC(double dfValue, const char *pszFormat = nullptr);
428
        CPLSTRING_METHOD_DLL CPLString &Trim();
429
        CPLSTRING_METHOD_DLL CPLString &Recode(const char *pszSrcEncoding,
430
                                               const char *pszDstEncoding);
431
        CPLSTRING_METHOD_DLL CPLString &replaceAll(const std::string &osBefore,
432
                                                   const std::string &osAfter);
433
        CPLSTRING_METHOD_DLL CPLString &replaceAll(const std::string &osBefore,
434
                                                   char chAfter);
435
        CPLSTRING_METHOD_DLL CPLString &replaceAll(char chBefore,
436
                                                   const std::string &osAfter);
437
        CPLSTRING_METHOD_DLL CPLString &replaceAll(char chBefore, char chAfter);
438
439
        /* case insensitive find alternates */
440
        CPLSTRING_METHOD_DLL size_t ifind(const std::string &str,
441
                                          size_t pos = 0) const;
442
        CPLSTRING_METHOD_DLL size_t ifind(const char *s, size_t pos = 0) const;
443
        CPLSTRING_METHOD_DLL CPLString &toupper(void);
444
        CPLSTRING_METHOD_DLL CPLString &tolower(void);
445
446
        CPLSTRING_METHOD_DLL bool endsWith(const std::string &osStr) const;
447
448
        CPLSTRING_METHOD_DLL CPLString URLEncode() const;
449
450
        CPLSTRING_METHOD_DLL CPLString SQLQuotedIdentifier() const;
451
452
        CPLSTRING_METHOD_DLL CPLString SQLQuotedLiteral() const;
453
454
      private:
455
        operator void *(void) = delete;
456
    };
457
458
#undef CPLSTRING_CLASS_DLL
459
#undef CPLSTRING_METHOD_DLL
460
461
    CPLString CPL_DLL CPLOPrintf(CPL_FORMAT_STRING(const char *pszFormat), ...)
462
        CPL_PRINT_FUNC_FORMAT(1, 2);
463
    CPLString CPL_DLL CPLOvPrintf(CPL_FORMAT_STRING(const char *pszFormat),
464
                                  va_list args) CPL_PRINT_FUNC_FORMAT(1, 0);
465
    CPLString CPL_DLL CPLQuotedSQLIdentifier(const char *pszIdent);
466
467
    /* -------------------------------------------------------------------- */
468
    /*      URL processing functions, here since they depend on CPLString.  */
469
    /* -------------------------------------------------------------------- */
470
    CPLString CPL_DLL CPLURLGetValue(const char *pszURL, const char *pszKey);
471
    CPLString CPL_DLL CPLURLAddKVP(const char *pszURL, const char *pszKey,
472
                                   const char *pszValue);
473
474
    /************************************************************************/
475
    /*                            CPLStringList                             */
476
    /************************************************************************/
477
478
    //! String list class designed around our use of C "char**" string lists.
479
    class CPL_DLL CPLStringList
480
    {
481
        char **papszList = nullptr;
482
        mutable int nCount = 0;
483
        mutable int nAllocation = 0;
484
        bool bOwnList = false;
485
        bool bIsSorted = false;
486
487
        bool MakeOurOwnCopy();
488
        bool EnsureAllocation(int nMaxLength);
489
        int FindSortedInsertionPoint(const char *pszLine);
490
491
      public:
492
        CPLStringList();
493
        explicit CPLStringList(char **papszList, int bTakeOwnership = TRUE);
494
        explicit CPLStringList(CSLConstList papszList);
495
        explicit CPLStringList(const std::vector<std::string> &aosList);
496
        explicit CPLStringList(std::initializer_list<const char *> oInitList);
497
        CPLStringList(const CPLStringList &oOther);
498
        CPLStringList(CPLStringList &&oOther);
499
        ~CPLStringList();
500
501
        static const CPLStringList BoundToConstList(CSLConstList papszList);
502
503
        CPLStringList &Clear();
504
505
        /** Clear the list */
506
        inline void clear()
507
0
        {
508
0
            Clear();
509
0
        }
510
511
        /** Return size of list */
512
        int size() const
513
12
        {
514
12
            return Count();
515
12
        }
516
517
        int Count() const;
518
519
        /** Return whether the list is empty. */
520
        bool empty() const
521
0
        {
522
0
            return Count() == 0;
523
0
        }
524
525
        CPLStringList &AddString(const char *pszNewString);
526
        CPLStringList &AddString(const std::string &newString);
527
#if defined(DOXYGEN_SKIP) || defined(HAVE_STRING_VIEW)
528
        CPLStringList &AddString(std::string_view newString);
529
#endif
530
        CPLStringList &AddString(double adfNumber);
531
        CPLStringList &AddStringDirectly(char *pszNewString);
532
533
        /** Add a string to the list */
534
        void push_back(const char *pszNewString)
535
0
        {
536
0
            AddString(pszNewString);
537
0
        }
538
539
        /** Add a string to the list */
540
        void push_back(const std::string &osStr)
541
0
        {
542
0
            AddString(osStr.c_str());
543
0
        }
544
545
#if defined(DOXYGEN_SKIP) || defined(HAVE_STRING_VIEW)
546
        void push_back(std::string_view svStr);
547
#endif
548
549
        CPLStringList &InsertString(int nInsertAtLineNo, const char *pszNewLine)
550
0
        {
551
0
            return InsertStringDirectly(nInsertAtLineNo, CPLStrdup(pszNewLine));
552
0
        }
553
554
        CPLStringList &InsertStringDirectly(int nInsertAtLineNo,
555
                                            char *pszNewLine);
556
557
        // CPLStringList &InsertStrings( int nInsertAtLineNo, char
558
        // **papszNewLines );
559
560
        CPLStringList &RemoveStrings(int nFirstLineToDelete,
561
                                     int nNumToRemove = 1);
562
563
        /** Return index of pszTarget in the list, or -1 */
564
        int FindString(const char *pszTarget) const
565
0
        {
566
0
            return CSLFindString(papszList, pszTarget);
567
0
        }
568
569
        /** Return index of pszTarget in the list (using partial search), or -1
570
         */
571
        int PartialFindString(const char *pszNeedle) const
572
0
        {
573
0
            return CSLPartialFindString(papszList, pszNeedle);
574
0
        }
575
576
        int FindName(const char *pszName) const;
577
        bool FetchBool(const char *pszKey, bool bDefault) const;
578
        // Deprecated.
579
        int FetchBoolean(const char *pszKey, int bDefault) const;
580
        const char *FetchNameValue(const char *pszKey) const;
581
        const char *FetchNameValueDef(const char *pszKey,
582
                                      const char *pszDefault) const;
583
        CPLStringList &AddNameValue(const char *pszKey, const char *pszValue);
584
        CPLStringList &SetNameValue(const char *pszKey, const char *pszValue);
585
586
        CPLStringList &SetString(int pos, const char *pszString);
587
        CPLStringList &SetString(int pos, const std::string &osString);
588
        CPLStringList &SetStringDirectly(int pos, char *pszString);
589
590
        CPLStringList &Assign(char **papszListIn, int bTakeOwnership = TRUE);
591
592
        /** Assignment operator */
593
        CPLStringList &operator=(char **papszListIn)
594
0
        {
595
0
            return Assign(papszListIn, TRUE);
596
0
        }
597
598
        /** Assignment operator */
599
        CPLStringList &operator=(const CPLStringList &oOther);
600
        /** Assignment operator */
601
        CPLStringList &operator=(CSLConstList papszListIn);
602
        /** Move assignment operator */
603
        CPLStringList &operator=(CPLStringList &&oOther);
604
605
        /** Return string at specified index */
606
        char *operator[](int i);
607
608
        /** Return string at specified index */
609
        char *operator[](size_t i)
610
0
        {
611
0
            return (*this)[static_cast<int>(i)];
612
0
        }
613
614
        /** Return string at specified index */
615
        const char *operator[](int i) const;
616
617
        /** Return string at specified index */
618
        const char *operator[](size_t i) const
619
0
        {
620
0
            return (*this)[static_cast<int>(i)];
621
0
        }
622
623
        /** Return value corresponding to pszKey, or nullptr */
624
        const char *operator[](const char *pszKey) const
625
0
        {
626
0
            return FetchNameValue(pszKey);
627
0
        }
628
629
        /** Return first element */
630
        inline const char *front() const
631
0
        {
632
0
            return papszList[0];
633
0
        }
634
635
        /** Return last element */
636
        inline const char *back() const
637
12
        {
638
12
            return papszList[size() - 1];
639
12
        }
640
641
        /** begin() implementation */
642
        const char *const *begin() const
643
0
        {
644
0
            return papszList ? &papszList[0] : nullptr;
645
0
        }
646
647
        /** end() implementation */
648
        const char *const *end() const
649
0
        {
650
0
            return papszList ? &papszList[size()] : nullptr;
651
0
        }
652
653
        /** Return list. Ownership remains to the object */
654
        char **List()
655
1.41k
        {
656
1.41k
            return papszList;
657
1.41k
        }
658
659
        /** Return list. Ownership remains to the object */
660
        CSLConstList List() const
661
0
        {
662
0
            return papszList;
663
0
        }
664
665
        char **StealList();
666
667
        CPLStringList &Sort();
668
669
        /** Returns whether the list is sorted */
670
        int IsSorted() const
671
12.0k
        {
672
12.0k
            return bIsSorted;
673
12.0k
        }
674
675
        /** Return lists */
676
        operator char **(void)
677
0
        {
678
0
            return List();
679
0
        }
680
681
        /** Return lists */
682
        operator CSLConstList(void) const
683
0
        {
684
0
            return List();
685
0
        }
686
687
        /** Return the list as a vector of strings */
688
        operator std::vector<std::string>(void) const
689
0
        {
690
0
            return std::vector<std::string>{begin(), end()};
691
0
        }
692
693
      private:
694
        operator void *(void) = delete;
695
    };
696
697
#ifdef GDAL_COMPILATION
698
699
#include <iterator>  // For std::input_iterator_tag
700
#include <memory>
701
#include <string_view>
702
#include <utility>  // For std::pair
703
704
    /*! @cond Doxygen_Suppress */
705
    struct CPL_DLL CSLDestroyReleaser
706
    {
707
        void operator()(char **papszStr) const
708
0
        {
709
0
            CSLDestroy(papszStr);
710
0
        }
711
    };
712
713
    /*! @endcond */
714
715
    /** Unique pointer type to use with CSL functions returning a char** */
716
    using CSLUniquePtr = std::unique_ptr<char *, CSLDestroyReleaser>;
717
718
    /** Unique pointer type to use with functions returning a char* to release
719
     * with VSIFree */
720
    using CPLCharUniquePtr = std::unique_ptr<char, VSIFreeReleaser>;
721
722
    namespace cpl
723
    {
724
725
    /*! @cond Doxygen_Suppress */
726
727
#if defined(DOXYGEN_SKIP) || defined(HAVE_STRING_VIEW)
728
    bool CPL_DLL starts_with(std::string_view str, std::string_view prefix);
729
    bool CPL_DLL starts_with_ci(std::string_view str, std::string_view prefix);
730
731
    bool CPL_DLL ends_with(std::string_view str, std::string_view suffix);
732
    bool CPL_DLL ends_with_ci(std::string_view str, std::string_view suffix);
733
734
    bool CPL_DLL equals(std::string_view str1, std::string_view str2);
735
    bool CPL_DLL equals_ci(std::string_view str1, std::string_view str2);
736
737
    std::string_view CPL_DLL trim(std::string_view str);
738
    std::string_view CPL_DLL rtrim(std::string_view str);
739
    std::string_view CPL_DLL ltrim(std::string_view str);
740
741
    std::string_view CPL_DLL trim(const char *str);
742
    std::string_view CPL_DLL rtrim(const char *str);
743
    std::string_view CPL_DLL ltrim(const char *str);
744
745
    std::string_view trim(std::string &&) = delete;
746
    std::string_view rtrim(std::string &&) = delete;
747
    std::string_view ltrim(std::string &&) = delete;
748
749
    std::pair<std::string_view, std::string_view>
750
        CPL_DLL parse_name_value(std::string_view svNameValue);
751
752
    std::pair<std::string_view, std::string_view>
753
        CPL_DLL parse_name_value(const char *svNameValue);
754
755
    std::pair<std::string_view, std::string_view>
756
    parse_name_value(std::string &&) = delete;
757
758
    CPLStringList tokenize_string(std::string_view str,
759
                                  std::string_view delimiters, int nCSLTFlags);
760
#endif
761
762
    /** Iterator for a CSLConstList */
763
    struct CPL_DLL CSLIterator
764
    {
765
        using iterator_category = std::input_iterator_tag;
766
        using difference_type = std::ptrdiff_t;
767
        using value_type = const char *;
768
        using pointer = value_type *;
769
        using reference = value_type &;
770
771
        CSLConstList m_papszList = nullptr;
772
        bool m_bAtEnd = false;
773
774
        inline const char *operator*() const
775
0
        {
776
0
            return *m_papszList;
777
0
        }
778
779
        inline CSLIterator &operator++()
780
0
        {
781
0
            if (m_papszList)
782
0
                ++m_papszList;
783
0
            return *this;
784
0
        }
785
786
        bool operator==(const CSLIterator &other) const;
787
788
        inline bool operator!=(const CSLIterator &other) const
789
0
        {
790
0
            return !(operator==(other));
791
0
        }
792
    };
793
794
    /*! @endcond */
795
796
    /** Wrapper for a CSLConstList that can be used with C++ iterators.
797
     *
798
     * @since GDAL 3.9
799
     */
800
    struct CPL_DLL CSLIteratorWrapper
801
    {
802
      public:
803
        /** Constructor */
804
        inline explicit CSLIteratorWrapper(CSLConstList papszList)
805
0
            : m_papszList(papszList)
806
0
        {
807
0
        }
808
809
        /** Get the begin of the list */
810
        inline CSLIterator begin() const
811
0
        {
812
0
            return {m_papszList, false};
813
0
        }
814
815
        /** Get the end of the list */
816
        inline CSLIterator end() const
817
0
        {
818
0
            return {m_papszList, true};
819
0
        }
820
821
      private:
822
        CSLConstList m_papszList;
823
    };
824
825
    /** Wraps a CSLConstList in a structure that can be used with C++ iterators.
826
     *
827
     * @since GDAL 3.9
828
     */
829
    inline CSLIteratorWrapper Iterate(CSLConstList papszList)
830
0
    {
831
0
        return CSLIteratorWrapper{papszList};
832
0
    }
833
834
    /*! @cond Doxygen_Suppress */
835
    inline CSLIteratorWrapper Iterate(const CPLStringList &aosList)
836
0
    {
837
0
        return Iterate(aosList.List());
838
0
    }
839
840
    /*! @endcond */
841
842
    /*! @cond Doxygen_Suppress */
843
    inline CSLIteratorWrapper Iterate(char **) = delete;
844
845
    /*! @endcond */
846
847
    /*! @cond Doxygen_Suppress */
848
    /** Iterator for a CSLConstList as (name, value) pairs. */
849
    struct CPL_DLL CSLNameValueIterator
850
    {
851
        using iterator_category = std::input_iterator_tag;
852
        using difference_type = std::ptrdiff_t;
853
        using value_type = std::pair<const char *, const char *>;
854
        using pointer = value_type *;
855
        using reference = value_type &;
856
857
        CSLConstList m_papszList = nullptr;
858
        bool m_bReturnNullKeyIfNotNameValue = false;
859
        std::string m_osKey{};
860
861
        value_type operator*();
862
863
        inline CSLNameValueIterator &operator++()
864
0
        {
865
0
            if (m_papszList)
866
0
                ++m_papszList;
867
0
            return *this;
868
0
        }
869
870
        inline bool operator==(const CSLNameValueIterator &other) const
871
0
        {
872
0
            return m_papszList == other.m_papszList;
873
0
        }
874
875
        inline bool operator!=(const CSLNameValueIterator &other) const
876
0
        {
877
0
            return !(operator==(other));
878
0
        }
879
    };
880
881
    /*! @endcond */
882
883
    /** Wrapper for a CSLConstList that can be used with C++ iterators
884
     * to get (name, value) pairs.
885
     *
886
     * This can for example be used to do the following:
887
     * for (const auto& [name, value]: cpl::IterateNameValue(papszList)) {}
888
     *
889
     * Note that a (name, value) pair returned by dereferencing an iterator
890
     * is invalidated by the next iteration on the iterator.
891
     *
892
     * @since GDAL 3.9
893
     */
894
    struct CPL_DLL CSLNameValueIteratorWrapper
895
    {
896
      public:
897
        /** Constructor */
898
        inline explicit CSLNameValueIteratorWrapper(
899
            CSLConstList papszList, bool bReturnNullKeyIfNotNameValue)
900
0
            : m_papszList(papszList),
901
0
              m_bReturnNullKeyIfNotNameValue(bReturnNullKeyIfNotNameValue)
902
0
        {
903
0
        }
904
905
        /** Get the begin of the list */
906
        inline CSLNameValueIterator begin() const
907
0
        {
908
0
            return {m_papszList, m_bReturnNullKeyIfNotNameValue};
909
0
        }
910
911
        /** Get the end of the list */
912
        CSLNameValueIterator end() const;
913
914
      private:
915
        CSLConstList m_papszList;
916
        const bool m_bReturnNullKeyIfNotNameValue;
917
    };
918
919
    /** Wraps a CSLConstList in a structure that can be used with C++ iterators
920
     * to get (name, value) pairs.
921
     *
922
     * This can for example be used to do the following:
923
     * for (const auto& [name, value]: cpl::IterateNameValue(papszList)) {}
924
     *
925
     * Note that a (name, value) pair returned by dereferencing an iterator
926
     * is invalidated by the next iteration on the iterator.
927
     *
928
     * @param papszList List to iterate over.
929
     * @param bReturnNullKeyIfNotNameValue When this is set to true, if a string
930
     * contained in the list if not of the form name=value, then the value of
931
     * the iterator will be (nullptr, string).
932
     *
933
     * @since GDAL 3.9
934
     */
935
    inline CSLNameValueIteratorWrapper
936
    IterateNameValue(CSLConstList papszList,
937
                     bool bReturnNullKeyIfNotNameValue = false)
938
0
    {
939
0
        return CSLNameValueIteratorWrapper{papszList,
940
0
                                           bReturnNullKeyIfNotNameValue};
941
0
    }
942
943
    /*! @cond Doxygen_Suppress */
944
    inline CSLNameValueIteratorWrapper
945
    IterateNameValue(const CPLStringList &aosList,
946
                     bool bReturnNullKeyIfNotNameValue = false)
947
0
    {
948
0
        return IterateNameValue(aosList.List(), bReturnNullKeyIfNotNameValue);
949
0
    }
950
951
    /*! @endcond */
952
953
    /*! @cond Doxygen_Suppress */
954
    inline CSLIteratorWrapper IterateNameValue(char **, bool = false) = delete;
955
956
    /*! @endcond */
957
958
    /** Converts a CSLConstList to a std::vector<std::string> */
959
    inline std::vector<std::string> ToVector(CSLConstList papszList)
960
0
    {
961
0
        return CPLStringList::BoundToConstList(papszList);
962
0
    }
963
964
    inline std::vector<std::string> ToVector(char **) = delete;
965
966
    }  // namespace cpl
967
968
#endif
969
970
}  // extern "C++"
971
972
#ifdef HAVE_STRING_VIEW
973
#undef HAVE_STRING_VIEW
974
#endif
975
976
#endif /* def __cplusplus && !CPL_SUPRESS_CPLUSPLUS */
977
978
#endif /* CPL_STRING_H_INCLUDED */