Line data Source code
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 : #define CSLT_HONOURSTRINGS 0x0001
71 : /** Flag for CSLTokenizeString2() to allow empty tokens */
72 : #define CSLT_ALLOWEMPTYTOKENS 0x0002
73 : /** Flag for CSLTokenizeString2() to preserve quotes */
74 : #define CSLT_PRESERVEQUOTES 0x0004
75 : /** Flag for CSLTokenizeString2() to preserve escape characters */
76 : #define CSLT_PRESERVEESCAPES 0x0008
77 : /** Flag for CSLTokenizeString2() to strip leading spaces */
78 : #define CSLT_STRIPLEADSPACES 0x0010
79 : /** Flag for CSLTokenizeString2() to strip trailing spaces */
80 : #define CSLT_STRIPENDSPACES 0x0020
81 : /** Flag for CSLTokenizeString2() to honour strings delimited by single quotes (GDAL >= 3.14) */
82 : #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 0 : inline bool CPLFetchBool(CSLConstList papszStrList, const char *pszKey,
120 : int bDefault)
121 : {
122 0 : return CPLFetchBool(papszStrList, pszKey, bDefault != 0);
123 : }
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 : #define CPLES_BackslashQuotable 0
156 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for XML */
157 : #define CPLES_XML 1
158 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for URL */
159 : #define CPLES_URL 2
160 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for SQL */
161 : #define CPLES_SQL 3
162 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for CSV */
163 : #define CPLES_CSV 4
164 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for XML (preserves quotes)
165 : */
166 : #define CPLES_XML_BUT_QUOTES 5
167 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for CSV (forced quoting) */
168 : #define CPLES_CSV_FORCE_QUOTING 6
169 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for SQL identifiers */
170 : #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 : #define CPL_ENC_UTF8 "UTF-8"
254 : /** UTF-16 encoding */
255 : #define CPL_ENC_UTF16 "UTF-16"
256 : /** UCS-2 encoding */
257 : #define CPL_ENC_UCS2 "UCS-2"
258 : /** UCS-4 encoding */
259 : #define CPL_ENC_UCS4 "UCS-4"
260 : /** ASCII encoding */
261 : #define CPL_ENC_ASCII "ASCII"
262 : /** ISO-8859-1 (LATIN1) encoding */
263 : #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 28 : class CPLSTRING_CLASS_DLL CPLString : public std::string
341 : {
342 : public:
343 : /** Constructor */
344 19168714 : CPLString(void)
345 19168714 : {
346 19168586 : }
347 :
348 : /** Constructor */
349 : // cppcheck-suppress noExplicitConstructor
350 5153920 : CPLString(const std::string &oStr) : std::string(oStr)
351 : {
352 5153920 : }
353 :
354 : /** Constructor */
355 : // cppcheck-suppress noExplicitConstructor
356 10469071 : CPLString(const char *pszStr) : std::string(pszStr)
357 : {
358 10469131 : }
359 :
360 : /** Constructor */
361 71998 : CPLString(const char *pszStr, size_t n) : std::string(pszStr, n)
362 : {
363 71998 : }
364 :
365 : /** Return string as zero terminated character array */
366 25712494 : operator const char *(void) const
367 : {
368 25712494 : return c_str();
369 : }
370 :
371 : /** Return character at specified index */
372 61859732 : char &operator[](std::string::size_type i)
373 : {
374 61859732 : return std::string::operator[](i);
375 : }
376 :
377 : /** Return character at specified index */
378 285975 : const char &operator[](std::string::size_type i) const
379 : {
380 285975 : return std::string::operator[](i);
381 : }
382 :
383 : /** Return character at specified index */
384 2944545 : char &operator[](int i)
385 : {
386 : return std::string::operator[](
387 2944545 : static_cast<std::string::size_type>(i));
388 : }
389 :
390 : /** Return character at specified index */
391 16913 : const char &operator[](int i) const
392 : {
393 : return std::string::operator[](
394 16913 : static_cast<std::string::size_type>(i));
395 : }
396 :
397 : /** Clear the string */
398 24398 : void Clear()
399 : {
400 24398 : resize(0);
401 24398 : }
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 0 : void Seize(char *pszValue)
407 : {
408 0 : if (pszValue == nullptr)
409 0 : Clear();
410 : else
411 : {
412 0 : *this = pszValue;
413 0 : CPLFree(pszValue);
414 : }
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 14905600 : 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 2 : inline void clear()
506 : {
507 2 : Clear();
508 2 : }
509 :
510 : /** Return size of list */
511 1805400 : int size() const
512 : {
513 1805400 : return Count();
514 : }
515 :
516 : int Count() const;
517 :
518 : /** Return whether the list is empty. */
519 56615 : bool empty() const
520 : {
521 56615 : return Count() == 0;
522 : }
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 5437 : void push_back(const char *pszNewString)
533 : {
534 5437 : AddString(pszNewString);
535 5437 : }
536 :
537 : /** Add a string to the list */
538 1731 : void push_back(const std::string &osStr)
539 : {
540 1731 : AddString(osStr.c_str());
541 1731 : }
542 :
543 : #if defined(DOXYGEN_SKIP) || defined(HAVE_STRING_VIEW)
544 : void push_back(std::string_view svStr);
545 : #endif
546 :
547 396 : CPLStringList &InsertString(int nInsertAtLineNo, const char *pszNewLine)
548 : {
549 396 : return InsertStringDirectly(nInsertAtLineNo, CPLStrdup(pszNewLine));
550 : }
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 17941 : int FindString(const char *pszTarget) const
563 : {
564 17941 : return CSLFindString(papszList, pszTarget);
565 : }
566 :
567 : /** Return index of pszTarget in the list (using partial search), or -1
568 : */
569 33 : int PartialFindString(const char *pszNeedle) const
570 : {
571 33 : return CSLPartialFindString(papszList, pszNeedle);
572 : }
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 338204 : CPLStringList &operator=(char **papszListIn)
592 : {
593 338204 : return Assign(papszListIn, TRUE);
594 : }
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 2149 : char *operator[](size_t i)
608 : {
609 2149 : return (*this)[static_cast<int>(i)];
610 : }
611 :
612 : /** Return string at specified index */
613 : const char *operator[](int i) const;
614 :
615 : /** Return string at specified index */
616 1975 : const char *operator[](size_t i) const
617 : {
618 1975 : return (*this)[static_cast<int>(i)];
619 : }
620 :
621 : /** Return value corresponding to pszKey, or nullptr */
622 4493 : const char *operator[](const char *pszKey) const
623 : {
624 4493 : return FetchNameValue(pszKey);
625 : }
626 :
627 : /** Return first element */
628 : inline const char *front() const
629 : {
630 : return papszList[0];
631 : }
632 :
633 : /** Return last element */
634 754726 : inline const char *back() const
635 : {
636 754726 : return papszList[size() - 1];
637 : }
638 :
639 : /** begin() implementation */
640 18299 : const char *const *begin() const
641 : {
642 18299 : return papszList ? &papszList[0] : nullptr;
643 : }
644 :
645 : /** end() implementation */
646 18299 : const char *const *end() const
647 : {
648 18299 : return papszList ? &papszList[size()] : nullptr;
649 : }
650 :
651 : /** Return list. Ownership remains to the object */
652 3343054 : char **List()
653 : {
654 3343054 : return papszList;
655 : }
656 :
657 : /** Return list. Ownership remains to the object */
658 2498098 : CSLConstList List() const
659 : {
660 2498098 : return papszList;
661 : }
662 :
663 : char **StealList();
664 :
665 : CPLStringList &Sort();
666 :
667 : /** Returns whether the list is sorted */
668 23916823 : int IsSorted() const
669 : {
670 23916823 : return bIsSorted;
671 : }
672 :
673 : /** Return lists */
674 69032 : operator char **(void)
675 : {
676 69032 : return List();
677 : }
678 :
679 : /** Return lists */
680 3043 : operator CSLConstList(void) const
681 : {
682 3043 : return List();
683 : }
684 :
685 : /** Return the list as a vector of strings */
686 2360 : operator std::vector<std::string>(void) const
687 : {
688 2360 : return std::vector<std::string>{begin(), end()};
689 : }
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 : {
707 : CSLDestroy(papszStr);
708 : }
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 18908501 : inline const char *operator*() const
773 : {
774 18908501 : return *m_papszList;
775 : }
776 :
777 18908183 : inline CSLIterator &operator++()
778 : {
779 18908183 : if (m_papszList)
780 18908183 : ++m_papszList;
781 18908183 : return *this;
782 : }
783 :
784 : bool operator==(const CSLIterator &other) const;
785 :
786 22917220 : inline bool operator!=(const CSLIterator &other) const
787 : {
788 22917220 : return !(operator==(other));
789 : }
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 4009068 : inline explicit CSLIteratorWrapper(CSLConstList papszList)
803 4009068 : : m_papszList(papszList)
804 : {
805 4009068 : }
806 :
807 : /** Get the begin of the list */
808 4009068 : inline CSLIterator begin() const
809 : {
810 4009068 : return {m_papszList, false};
811 : }
812 :
813 : /** Get the end of the list */
814 4009068 : inline CSLIterator end() const
815 : {
816 4009068 : return {m_papszList, true};
817 : }
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 4009068 : inline CSLIteratorWrapper Iterate(CSLConstList papszList)
828 : {
829 4009068 : return CSLIteratorWrapper{papszList};
830 : }
831 :
832 : /*! @cond Doxygen_Suppress */
833 15992 : inline CSLIteratorWrapper Iterate(const CPLStringList &aosList)
834 : {
835 15992 : return Iterate(aosList.List());
836 : }
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 8323 : inline CSLNameValueIterator &operator++()
862 : {
863 8323 : if (m_papszList)
864 8323 : ++m_papszList;
865 8323 : return *this;
866 : }
867 :
868 21938 : inline bool operator==(const CSLNameValueIterator &other) const
869 : {
870 21938 : return m_papszList == other.m_papszList;
871 : }
872 :
873 21936 : inline bool operator!=(const CSLNameValueIterator &other) const
874 : {
875 21936 : return !(operator==(other));
876 : }
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 13615 : inline explicit CSLNameValueIteratorWrapper(
897 : CSLConstList papszList, bool bReturnNullKeyIfNotNameValue)
898 13615 : : m_papszList(papszList),
899 13615 : m_bReturnNullKeyIfNotNameValue(bReturnNullKeyIfNotNameValue)
900 : {
901 13615 : }
902 :
903 : /** Get the begin of the list */
904 13615 : inline CSLNameValueIterator begin() const
905 : {
906 13615 : return {m_papszList, m_bReturnNullKeyIfNotNameValue};
907 : }
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 13615 : IterateNameValue(CSLConstList papszList,
935 : bool bReturnNullKeyIfNotNameValue = false)
936 : {
937 13615 : return CSLNameValueIteratorWrapper{papszList,
938 13615 : bReturnNullKeyIfNotNameValue};
939 : }
940 :
941 : /*! @cond Doxygen_Suppress */
942 : inline CSLNameValueIteratorWrapper
943 7909 : IterateNameValue(const CPLStringList &aosList,
944 : bool bReturnNullKeyIfNotNameValue = false)
945 : {
946 7909 : return IterateNameValue(aosList.List(), bReturnNullKeyIfNotNameValue);
947 : }
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 98 : inline std::vector<std::string> ToVector(CSLConstList papszList)
958 : {
959 196 : return CPLStringList::BoundToConstList(papszList);
960 : }
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 */
|