/src/gdal/port/cpl_string.h
Line  | Count  | Source (jump to first uncovered line)  | 
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  | 452  | #define CSLT_HONOURSTRINGS 0x0001  | 
71  |  | /** Flag for CSLTokenizeString2() to allow empty tokens */  | 
72  | 452  | #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  | 452  | #define CSLT_STRIPLEADSPACES 0x0010  | 
79  |  | /** Flag for CSLTokenizeString2() to strip trailaing spaces */  | 
80  | 452  | #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  | 0  | #define CPLES_BackslashQuotable 0  | 
139  |  | /** Scheme for CPLEscapeString()/CPLUnescapeString() for XML */  | 
140  | 0  | #define CPLES_XML 1  | 
141  |  | /** Scheme for CPLEscapeString()/CPLUnescapeString() for URL */  | 
142  | 0  | #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  | 0  | #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  | 3.15k  |         { | 
325  | 3.15k  |         }  | 
326  |  |  | 
327  |  |         /** Constructor */  | 
328  |  |         // cppcheck-suppress noExplicitConstructor  | 
329  | 0  |         CPLString(const std::string &oStr) : std::string(oStr)  | 
330  | 0  |         { | 
331  | 0  |         }  | 
332  |  |  | 
333  |  |         /** Constructor */  | 
334  |  |         // cppcheck-suppress noExplicitConstructor  | 
335  | 44.2k  |         CPLString(const char *pszStr) : std::string(pszStr)  | 
336  | 44.2k  |         { | 
337  | 44.2k  |         }  | 
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  | 10.0k  |         { | 
347  | 10.0k  |             return c_str();  | 
348  | 10.0k  |         }  | 
349  |  |  | 
350  |  |         /** Return character at specified index */  | 
351  |  |         char &operator[](std::string::size_type i)  | 
352  | 426k  |         { | 
353  | 426k  |             return std::string::operator[](i);  | 
354  | 426k  |         }  | 
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  |  |  | 
427  |  | #undef CPLSTRING_CLASS_DLL  | 
428  |  | #undef CPLSTRING_METHOD_DLL  | 
429  |  |  | 
430  |  |     CPLString CPL_DLL CPLOPrintf(CPL_FORMAT_STRING(const char *pszFormat), ...)  | 
431  |  |         CPL_PRINT_FUNC_FORMAT(1, 2);  | 
432  |  |     CPLString CPL_DLL CPLOvPrintf(CPL_FORMAT_STRING(const char *pszFormat),  | 
433  |  |                                   va_list args) CPL_PRINT_FUNC_FORMAT(1, 0);  | 
434  |  |     CPLString CPL_DLL CPLQuotedSQLIdentifier(const char *pszIdent);  | 
435  |  |  | 
436  |  |     /* -------------------------------------------------------------------- */  | 
437  |  |     /*      URL processing functions, here since they depend on CPLString.  */  | 
438  |  |     /* -------------------------------------------------------------------- */  | 
439  |  |     CPLString CPL_DLL CPLURLGetValue(const char *pszURL, const char *pszKey);  | 
440  |  |     CPLString CPL_DLL CPLURLAddKVP(const char *pszURL, const char *pszKey,  | 
441  |  |                                    const char *pszValue);  | 
442  |  |  | 
443  |  |     /************************************************************************/  | 
444  |  |     /*                            CPLStringList                             */  | 
445  |  |     /************************************************************************/  | 
446  |  |  | 
447  |  |     //! String list class designed around our use of C "char**" string lists.  | 
448  |  |     class CPL_DLL CPLStringList  | 
449  |  |     { | 
450  |  |         char **papszList = nullptr;  | 
451  |  |         mutable int nCount = 0;  | 
452  |  |         mutable int nAllocation = 0;  | 
453  |  |         bool bOwnList = false;  | 
454  |  |         bool bIsSorted = false;  | 
455  |  |  | 
456  |  |         bool MakeOurOwnCopy();  | 
457  |  |         bool EnsureAllocation(int nMaxLength);  | 
458  |  |         int FindSortedInsertionPoint(const char *pszLine);  | 
459  |  |  | 
460  |  |       public:  | 
461  |  |         CPLStringList();  | 
462  |  |         explicit CPLStringList(char **papszList, int bTakeOwnership = TRUE);  | 
463  |  |         explicit CPLStringList(CSLConstList papszList);  | 
464  |  |         explicit CPLStringList(const std::vector<std::string> &aosList);  | 
465  |  |         explicit CPLStringList(std::initializer_list<const char *> oInitList);  | 
466  |  |         CPLStringList(const CPLStringList &oOther);  | 
467  |  |         CPLStringList(CPLStringList &&oOther);  | 
468  |  |         ~CPLStringList();  | 
469  |  |  | 
470  |  |         static const CPLStringList BoundToConstList(CSLConstList papszList);  | 
471  |  |  | 
472  |  |         CPLStringList &Clear();  | 
473  |  |  | 
474  |  |         /** Clear the list */  | 
475  |  |         inline void clear()  | 
476  | 0  |         { | 
477  | 0  |             Clear();  | 
478  | 0  |         }  | 
479  |  |  | 
480  |  |         /** Return size of list */  | 
481  |  |         int size() const  | 
482  | 0  |         { | 
483  | 0  |             return Count();  | 
484  | 0  |         }  | 
485  |  |  | 
486  |  |         int Count() const;  | 
487  |  |  | 
488  |  |         /** Return whether the list is empty. */  | 
489  |  |         bool empty() const  | 
490  | 0  |         { | 
491  | 0  |             return Count() == 0;  | 
492  | 0  |         }  | 
493  |  |  | 
494  |  |         CPLStringList &AddString(const char *pszNewString);  | 
495  |  |         CPLStringList &AddString(const std::string &newString);  | 
496  |  |         CPLStringList &AddStringDirectly(char *pszNewString);  | 
497  |  |  | 
498  |  |         /** Add a string to the list */  | 
499  |  |         void push_back(const char *pszNewString)  | 
500  | 0  |         { | 
501  | 0  |             AddString(pszNewString);  | 
502  | 0  |         }  | 
503  |  |  | 
504  |  |         /** Add a string to the list */  | 
505  |  |         void push_back(const std::string &osStr)  | 
506  | 0  |         { | 
507  | 0  |             AddString(osStr.c_str());  | 
508  | 0  |         }  | 
509  |  |  | 
510  |  |         CPLStringList &InsertString(int nInsertAtLineNo, const char *pszNewLine)  | 
511  | 0  |         { | 
512  | 0  |             return InsertStringDirectly(nInsertAtLineNo, CPLStrdup(pszNewLine));  | 
513  | 0  |         }  | 
514  |  |  | 
515  |  |         CPLStringList &InsertStringDirectly(int nInsertAtLineNo,  | 
516  |  |                                             char *pszNewLine);  | 
517  |  |  | 
518  |  |         // CPLStringList &InsertStrings( int nInsertAtLineNo, char  | 
519  |  |         // **papszNewLines ); CPLStringList &RemoveStrings( int  | 
520  |  |         // nFirstLineToDelete, int nNumToRemove=1 );  | 
521  |  |  | 
522  |  |         /** Return index of pszTarget in the list, or -1 */  | 
523  |  |         int FindString(const char *pszTarget) const  | 
524  | 0  |         { | 
525  | 0  |             return CSLFindString(papszList, pszTarget);  | 
526  | 0  |         }  | 
527  |  |  | 
528  |  |         /** Return index of pszTarget in the list (using partial search), or -1  | 
529  |  |          */  | 
530  |  |         int PartialFindString(const char *pszNeedle) const  | 
531  | 0  |         { | 
532  | 0  |             return CSLPartialFindString(papszList, pszNeedle);  | 
533  | 0  |         }  | 
534  |  |  | 
535  |  |         int FindName(const char *pszName) const;  | 
536  |  |         bool FetchBool(const char *pszKey, bool bDefault) const;  | 
537  |  |         // Deprecated.  | 
538  |  |         int FetchBoolean(const char *pszKey, int bDefault) const;  | 
539  |  |         const char *FetchNameValue(const char *pszKey) const;  | 
540  |  |         const char *FetchNameValueDef(const char *pszKey,  | 
541  |  |                                       const char *pszDefault) const;  | 
542  |  |         CPLStringList &AddNameValue(const char *pszKey, const char *pszValue);  | 
543  |  |         CPLStringList &SetNameValue(const char *pszKey, const char *pszValue);  | 
544  |  |  | 
545  |  |         CPLStringList &Assign(char **papszListIn, int bTakeOwnership = TRUE);  | 
546  |  |  | 
547  |  |         /** Assignment operator */  | 
548  |  |         CPLStringList &operator=(char **papszListIn)  | 
549  | 0  |         { | 
550  | 0  |             return Assign(papszListIn, TRUE);  | 
551  | 0  |         }  | 
552  |  |  | 
553  |  |         /** Assignment operator */  | 
554  |  |         CPLStringList &operator=(const CPLStringList &oOther);  | 
555  |  |         /** Assignment operator */  | 
556  |  |         CPLStringList &operator=(CSLConstList papszListIn);  | 
557  |  |         /** Move assignment operator */  | 
558  |  |         CPLStringList &operator=(CPLStringList &&oOther);  | 
559  |  |  | 
560  |  |         /** Return string at specified index */  | 
561  |  |         char *operator[](int i);  | 
562  |  |  | 
563  |  |         /** Return string at specified index */  | 
564  |  |         char *operator[](size_t i)  | 
565  | 0  |         { | 
566  | 0  |             return (*this)[static_cast<int>(i)];  | 
567  | 0  |         }  | 
568  |  |  | 
569  |  |         /** Return string at specified index */  | 
570  |  |         const char *operator[](int i) const;  | 
571  |  |  | 
572  |  |         /** Return string at specified index */  | 
573  |  |         const char *operator[](size_t i) const  | 
574  | 0  |         { | 
575  | 0  |             return (*this)[static_cast<int>(i)];  | 
576  | 0  |         }  | 
577  |  |  | 
578  |  |         /** Return value corresponding to pszKey, or nullptr */  | 
579  |  |         const char *operator[](const char *pszKey) const  | 
580  | 0  |         { | 
581  | 0  |             return FetchNameValue(pszKey);  | 
582  | 0  |         }  | 
583  |  |  | 
584  |  |         /** Return first element */  | 
585  |  |         inline const char *front() const  | 
586  | 0  |         { | 
587  | 0  |             return papszList[0];  | 
588  | 0  |         }  | 
589  |  |  | 
590  |  |         /** Return last element */  | 
591  |  |         inline const char *back() const  | 
592  | 0  |         { | 
593  | 0  |             return papszList[size() - 1];  | 
594  | 0  |         }  | 
595  |  |  | 
596  |  |         /** begin() implementation */  | 
597  |  |         const char *const *begin() const  | 
598  | 0  |         { | 
599  | 0  |             return papszList ? &papszList[0] : nullptr;  | 
600  | 0  |         }  | 
601  |  |  | 
602  |  |         /** end() implementation */  | 
603  |  |         const char *const *end() const  | 
604  | 0  |         { | 
605  | 0  |             return papszList ? &papszList[size()] : nullptr;  | 
606  | 0  |         }  | 
607  |  |  | 
608  |  |         /** Return list. Ownership remains to the object */  | 
609  |  |         char **List()  | 
610  | 452  |         { | 
611  | 452  |             return papszList;  | 
612  | 452  |         }  | 
613  |  |  | 
614  |  |         /** Return list. Ownership remains to the object */  | 
615  |  |         CSLConstList List() const  | 
616  | 0  |         { | 
617  | 0  |             return papszList;  | 
618  | 0  |         }  | 
619  |  |  | 
620  |  |         char **StealList();  | 
621  |  |  | 
622  |  |         CPLStringList &Sort();  | 
623  |  |  | 
624  |  |         /** Returns whether the list is sorted */  | 
625  |  |         int IsSorted() const  | 
626  | 0  |         { | 
627  | 0  |             return bIsSorted;  | 
628  | 0  |         }  | 
629  |  |  | 
630  |  |         /** Return lists */  | 
631  |  |         operator char **(void)  | 
632  | 0  |         { | 
633  | 0  |             return List();  | 
634  | 0  |         }  | 
635  |  |  | 
636  |  |         /** Return lists */  | 
637  |  |         operator CSLConstList(void) const  | 
638  | 0  |         { | 
639  | 0  |             return List();  | 
640  | 0  |         }  | 
641  |  |  | 
642  |  |         /** Return the list as a vector of strings */  | 
643  |  |         operator std::vector<std::string>(void) const  | 
644  | 0  |         { | 
645  | 0  |             return std::vector<std::string>{begin(), end()}; | 
646  | 0  |         }  | 
647  |  |     };  | 
648  |  |  | 
649  |  | #ifdef GDAL_COMPILATION  | 
650  |  |  | 
651  |  | #include <iterator>  // For std::input_iterator_tag  | 
652  |  | #include <memory>  | 
653  |  | #include <string_view>  | 
654  |  | #include <utility>  // For std::pair  | 
655  |  |  | 
656  |  |     /*! @cond Doxygen_Suppress */  | 
657  |  |     struct CPL_DLL CSLDestroyReleaser  | 
658  |  |     { | 
659  |  |         void operator()(char **papszStr) const  | 
660  | 0  |         { | 
661  | 0  |             CSLDestroy(papszStr);  | 
662  | 0  |         }  | 
663  |  |     };  | 
664  |  |  | 
665  |  |     /*! @endcond */  | 
666  |  |  | 
667  |  |     /** Unique pointer type to use with CSL functions returning a char** */  | 
668  |  |     using CSLUniquePtr = std::unique_ptr<char *, CSLDestroyReleaser>;  | 
669  |  |  | 
670  |  |     /** Unique pointer type to use with functions returning a char* to release  | 
671  |  |      * with VSIFree */  | 
672  |  |     using CPLCharUniquePtr = std::unique_ptr<char, VSIFreeReleaser>;  | 
673  |  |  | 
674  |  |     namespace cpl  | 
675  |  |     { | 
676  |  |  | 
677  |  |     /*! @cond Doxygen_Suppress */  | 
678  |  |  | 
679  |  |     /** Equivalent of C++20 std::string::starts_with(const char*) */  | 
680  |  |     template <class StringType>  | 
681  |  |     inline bool starts_with(const StringType &str, const char *prefix)  | 
682  |  |     { | 
683  |  |         const size_t prefixLen = strlen(prefix);  | 
684  |  |         return str.size() >= prefixLen &&  | 
685  |  |                str.compare(0, prefixLen, prefix, prefixLen) == 0;  | 
686  |  |     }  | 
687  |  |  | 
688  |  |     /** Equivalent of C++20 std::string::starts_with(const std::string &) */  | 
689  |  |     template <class StringType>  | 
690  |  |     inline bool starts_with(const StringType &str, const std::string &prefix)  | 
691  | 0  |     { | 
692  | 0  |         return str.size() >= prefix.size() &&  | 
693  | 0  |                str.compare(0, prefix.size(), prefix) == 0;  | 
694  | 0  |     }  | 
695  |  |  | 
696  |  |     /** Equivalent of C++20 std::string::starts_with(std::string_view) */  | 
697  |  |     template <class StringType>  | 
698  |  |     inline bool starts_with(const StringType &str, std::string_view prefix)  | 
699  |  |     { | 
700  |  |         return str.size() >= prefix.size() &&  | 
701  |  |                str.compare(0, prefix.size(), prefix) == 0;  | 
702  |  |     }  | 
703  |  |  | 
704  |  |     /** Equivalent of C++20 std::string::ends_with(const char*) */  | 
705  |  |     template <class StringType>  | 
706  |  |     inline bool ends_with(const StringType &str, const char *suffix)  | 
707  | 0  |     { | 
708  | 0  |         const size_t suffixLen = strlen(suffix);  | 
709  | 0  |         return str.size() >= suffixLen &&  | 
710  | 0  |                str.compare(str.size() - suffixLen, suffixLen, suffix,  | 
711  | 0  |                            suffixLen) == 0;  | 
712  | 0  |     }  | 
713  |  |  | 
714  |  |     /** Equivalent of C++20 std::string::ends_with(const std::string &) */  | 
715  |  |     template <class StringType>  | 
716  |  |     inline bool ends_with(const StringType &str, const std::string &suffix)  | 
717  |  |     { | 
718  |  |         return str.size() >= suffix.size() &&  | 
719  |  |                str.compare(str.size() - suffix.size(), suffix.size(), suffix) ==  | 
720  |  |                    0;  | 
721  |  |     }  | 
722  |  |  | 
723  |  |     /** Equivalent of C++20 std::string::ends_with(std::string_view) */  | 
724  |  |     template <class StringType>  | 
725  |  |     inline bool ends_with(const StringType &str, std::string_view suffix)  | 
726  |  |     { | 
727  |  |         return str.size() >= suffix.size() &&  | 
728  |  |                str.compare(str.size() - suffix.size(), suffix.size(), suffix) ==  | 
729  |  |                    0;  | 
730  |  |     }  | 
731  |  |  | 
732  |  |     /** Iterator for a CSLConstList */  | 
733  |  |     struct CPL_DLL CSLIterator  | 
734  |  |     { | 
735  |  |         using iterator_category = std::input_iterator_tag;  | 
736  |  |         using difference_type = std::ptrdiff_t;  | 
737  |  |         using value_type = const char *;  | 
738  |  |         using pointer = value_type *;  | 
739  |  |         using reference = value_type &;  | 
740  |  |  | 
741  |  |         CSLConstList m_papszList = nullptr;  | 
742  |  |         bool m_bAtEnd = false;  | 
743  |  |  | 
744  |  |         inline const char *operator*() const  | 
745  | 0  |         { | 
746  | 0  |             return *m_papszList;  | 
747  | 0  |         }  | 
748  |  |  | 
749  |  |         inline CSLIterator &operator++()  | 
750  | 0  |         { | 
751  | 0  |             if (m_papszList)  | 
752  | 0  |                 ++m_papszList;  | 
753  | 0  |             return *this;  | 
754  | 0  |         }  | 
755  |  |  | 
756  |  |         bool operator==(const CSLIterator &other) const;  | 
757  |  |  | 
758  |  |         inline bool operator!=(const CSLIterator &other) const  | 
759  | 0  |         { | 
760  | 0  |             return !(operator==(other));  | 
761  | 0  |         }  | 
762  |  |     };  | 
763  |  |  | 
764  |  |     /*! @endcond */  | 
765  |  |  | 
766  |  |     /** Wrapper for a CSLConstList that can be used with C++ iterators.  | 
767  |  |      *  | 
768  |  |      * @since GDAL 3.9  | 
769  |  |      */  | 
770  |  |     struct CPL_DLL CSLIteratorWrapper  | 
771  |  |     { | 
772  |  |       public:  | 
773  |  |         /** Constructor */  | 
774  |  |         inline explicit CSLIteratorWrapper(CSLConstList papszList)  | 
775  | 0  |             : m_papszList(papszList)  | 
776  | 0  |         { | 
777  | 0  |         }  | 
778  |  |  | 
779  |  |         /** Get the begin of the list */  | 
780  |  |         inline CSLIterator begin() const  | 
781  | 0  |         { | 
782  | 0  |             return {m_papszList, false}; | 
783  | 0  |         }  | 
784  |  |  | 
785  |  |         /** Get the end of the list */  | 
786  |  |         inline CSLIterator end() const  | 
787  | 0  |         { | 
788  | 0  |             return {m_papszList, true}; | 
789  | 0  |         }  | 
790  |  |  | 
791  |  |       private:  | 
792  |  |         CSLConstList m_papszList;  | 
793  |  |     };  | 
794  |  |  | 
795  |  |     /** Wraps a CSLConstList in a structure that can be used with C++ iterators.  | 
796  |  |      *  | 
797  |  |      * @since GDAL 3.9  | 
798  |  |      */  | 
799  |  |     inline CSLIteratorWrapper Iterate(CSLConstList papszList)  | 
800  | 0  |     { | 
801  | 0  |         return CSLIteratorWrapper{papszList}; | 
802  | 0  |     }  | 
803  |  |  | 
804  |  |     /*! @cond Doxygen_Suppress */  | 
805  |  |     inline CSLIteratorWrapper Iterate(const CPLStringList &aosList)  | 
806  | 0  |     { | 
807  | 0  |         return Iterate(aosList.List());  | 
808  | 0  |     }  | 
809  |  |  | 
810  |  |     /*! @endcond */  | 
811  |  |  | 
812  |  |     /*! @cond Doxygen_Suppress */  | 
813  |  |     inline CSLIteratorWrapper Iterate(char **) = delete;  | 
814  |  |  | 
815  |  |     /*! @endcond */  | 
816  |  |  | 
817  |  |     /*! @cond Doxygen_Suppress */  | 
818  |  |     /** Iterator for a CSLConstList as (name, value) pairs. */  | 
819  |  |     struct CPL_DLL CSLNameValueIterator  | 
820  |  |     { | 
821  |  |         using iterator_category = std::input_iterator_tag;  | 
822  |  |         using difference_type = std::ptrdiff_t;  | 
823  |  |         using value_type = std::pair<const char *, const char *>;  | 
824  |  |         using pointer = value_type *;  | 
825  |  |         using reference = value_type &;  | 
826  |  |  | 
827  |  |         CSLConstList m_papszList = nullptr;  | 
828  |  |         bool m_bReturnNullKeyIfNotNameValue = false;  | 
829  |  |         std::string m_osKey{}; | 
830  |  |  | 
831  |  |         value_type operator*();  | 
832  |  |  | 
833  |  |         inline CSLNameValueIterator &operator++()  | 
834  | 0  |         { | 
835  | 0  |             if (m_papszList)  | 
836  | 0  |                 ++m_papszList;  | 
837  | 0  |             return *this;  | 
838  | 0  |         }  | 
839  |  |  | 
840  |  |         inline bool operator==(const CSLNameValueIterator &other) const  | 
841  | 0  |         { | 
842  | 0  |             return m_papszList == other.m_papszList;  | 
843  | 0  |         }  | 
844  |  |  | 
845  |  |         inline bool operator!=(const CSLNameValueIterator &other) const  | 
846  | 0  |         { | 
847  | 0  |             return !(operator==(other));  | 
848  | 0  |         }  | 
849  |  |     };  | 
850  |  |  | 
851  |  |     /*! @endcond */  | 
852  |  |  | 
853  |  |     /** Wrapper for a CSLConstList that can be used with C++ iterators  | 
854  |  |      * to get (name, value) pairs.  | 
855  |  |      *  | 
856  |  |      * This can for example be used to do the following:  | 
857  |  |      * for (const auto& [name, value]: cpl::IterateNameValue(papszList)) {} | 
858  |  |      *  | 
859  |  |      * Note that a (name, value) pair returned by dereferencing an iterator  | 
860  |  |      * is invalidated by the next iteration on the iterator.  | 
861  |  |      *  | 
862  |  |      * @since GDAL 3.9  | 
863  |  |      */  | 
864  |  |     struct CPL_DLL CSLNameValueIteratorWrapper  | 
865  |  |     { | 
866  |  |       public:  | 
867  |  |         /** Constructor */  | 
868  |  |         inline explicit CSLNameValueIteratorWrapper(  | 
869  |  |             CSLConstList papszList, bool bReturnNullKeyIfNotNameValue)  | 
870  | 0  |             : m_papszList(papszList),  | 
871  | 0  |               m_bReturnNullKeyIfNotNameValue(bReturnNullKeyIfNotNameValue)  | 
872  | 0  |         { | 
873  | 0  |         }  | 
874  |  |  | 
875  |  |         /** Get the begin of the list */  | 
876  |  |         inline CSLNameValueIterator begin() const  | 
877  | 0  |         { | 
878  | 0  |             return {m_papszList, m_bReturnNullKeyIfNotNameValue}; | 
879  | 0  |         }  | 
880  |  |  | 
881  |  |         /** Get the end of the list */  | 
882  |  |         CSLNameValueIterator end() const;  | 
883  |  |  | 
884  |  |       private:  | 
885  |  |         CSLConstList m_papszList;  | 
886  |  |         const bool m_bReturnNullKeyIfNotNameValue;  | 
887  |  |     };  | 
888  |  |  | 
889  |  |     /** Wraps a CSLConstList in a structure that can be used with C++ iterators  | 
890  |  |      * to get (name, value) pairs.  | 
891  |  |      *  | 
892  |  |      * This can for example be used to do the following:  | 
893  |  |      * for (const auto& [name, value]: cpl::IterateNameValue(papszList)) {} | 
894  |  |      *  | 
895  |  |      * Note that a (name, value) pair returned by dereferencing an iterator  | 
896  |  |      * is invalidated by the next iteration on the iterator.  | 
897  |  |      *  | 
898  |  |      * @param papszList List to iterate over.  | 
899  |  |      * @param bReturnNullKeyIfNotNameValue When this is set to true, if a string  | 
900  |  |      * contained in the list if not of the form name=value, then the value of  | 
901  |  |      * the iterator will be (nullptr, string).  | 
902  |  |      *  | 
903  |  |      * @since GDAL 3.9  | 
904  |  |      */  | 
905  |  |     inline CSLNameValueIteratorWrapper  | 
906  |  |     IterateNameValue(CSLConstList papszList,  | 
907  |  |                      bool bReturnNullKeyIfNotNameValue = false)  | 
908  | 0  |     { | 
909  | 0  |         return CSLNameValueIteratorWrapper{papszList, | 
910  | 0  |                                            bReturnNullKeyIfNotNameValue};  | 
911  | 0  |     }  | 
912  |  |  | 
913  |  |     /*! @cond Doxygen_Suppress */  | 
914  |  |     inline CSLNameValueIteratorWrapper  | 
915  |  |     IterateNameValue(const CPLStringList &aosList,  | 
916  |  |                      bool bReturnNullKeyIfNotNameValue = false)  | 
917  | 0  |     { | 
918  | 0  |         return IterateNameValue(aosList.List(), bReturnNullKeyIfNotNameValue);  | 
919  | 0  |     }  | 
920  |  |  | 
921  |  |     /*! @endcond */  | 
922  |  |  | 
923  |  |     /*! @cond Doxygen_Suppress */  | 
924  |  |     inline CSLIteratorWrapper IterateNameValue(char **, bool = false) = delete;  | 
925  |  |  | 
926  |  |     /*! @endcond */  | 
927  |  |  | 
928  |  |     /** Converts a CSLConstList to a std::vector<std::string> */  | 
929  |  |     inline std::vector<std::string> ToVector(CSLConstList papszList)  | 
930  | 0  |     { | 
931  | 0  |         return CPLStringList::BoundToConstList(papszList);  | 
932  | 0  |     }  | 
933  |  |  | 
934  |  |     inline std::vector<std::string> ToVector(char **) = delete;  | 
935  |  |  | 
936  |  |     }  // namespace cpl  | 
937  |  |  | 
938  |  | #endif  | 
939  |  |  | 
940  |  | }  // extern "C++"  | 
941  |  |  | 
942  |  | #endif /* def __cplusplus && !CPL_SUPRESS_CPLUSPLUS */  | 
943  |  |  | 
944  |  | #endif /* CPL_STRING_H_INCLUDED */  |