Coverage Report

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