Coverage Report

Created: 2025-11-16 06:25

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