Coverage Report

Created: 2026-04-01 06:20

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