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 : #include <string_view>
316 : #endif
317 : #endif
318 :
319 : // VC++ implicitly applies __declspec(dllexport) to template base classes
320 : // of classes marked with __declspec(dllexport).
321 : // Hence, if marked with CPL_DLL, VC++ would export symbols for the
322 : // specialization of std::basic_string<char>, since it is a base class of
323 : // CPLString. As a result, if an application linked both gdal.dll and a static
324 : // library that (implicitly) instantiates std::string (almost all do!), then the
325 : // linker would emit an error concerning duplicate symbols for std::string. The
326 : // least intrusive solution is to not mark the whole class with
327 : // __declspec(dllexport) for VC++, but only its non-inline methods.
328 : #ifdef _MSC_VER
329 : #define CPLSTRING_CLASS_DLL
330 : #define CPLSTRING_METHOD_DLL CPL_DLL
331 : #else
332 : /*! @cond Doxygen_Suppress */
333 : #define CPLSTRING_CLASS_DLL CPL_DLL
334 : #define CPLSTRING_METHOD_DLL
335 : /*! @endcond */
336 : #endif
337 :
338 : //! Convenient string class based on std::string.
339 28 : class CPLSTRING_CLASS_DLL CPLString : public std::string
340 : {
341 : public:
342 : /** Constructor */
343 19164306 : CPLString(void)
344 19164306 : {
345 19164178 : }
346 :
347 : /** Constructor */
348 : // cppcheck-suppress noExplicitConstructor
349 5151046 : CPLString(const std::string &oStr) : std::string(oStr)
350 : {
351 5151046 : }
352 :
353 : /** Constructor */
354 : // cppcheck-suppress noExplicitConstructor
355 10465226 : CPLString(const char *pszStr) : std::string(pszStr)
356 : {
357 10465266 : }
358 :
359 : /** Constructor */
360 71890 : CPLString(const char *pszStr, size_t n) : std::string(pszStr, n)
361 : {
362 71890 : }
363 :
364 : /** Return string as zero terminated character array */
365 25691084 : operator const char *(void) const
366 : {
367 25691084 : return c_str();
368 : }
369 :
370 : /** Return character at specified index */
371 61797832 : char &operator[](std::string::size_type i)
372 : {
373 61797832 : return std::string::operator[](i);
374 : }
375 :
376 : /** Return character at specified index */
377 285964 : const char &operator[](std::string::size_type i) const
378 : {
379 285964 : return std::string::operator[](i);
380 : }
381 :
382 : /** Return character at specified index */
383 2944525 : char &operator[](int i)
384 : {
385 : return std::string::operator[](
386 2944525 : static_cast<std::string::size_type>(i));
387 : }
388 :
389 : /** Return character at specified index */
390 16913 : const char &operator[](int i) const
391 : {
392 : return std::string::operator[](
393 16913 : static_cast<std::string::size_type>(i));
394 : }
395 :
396 : /** Clear the string */
397 24398 : void Clear()
398 : {
399 24398 : resize(0);
400 24398 : }
401 :
402 : /** Assign specified string and take ownership of it (assumed to be
403 : * allocated with CPLMalloc()). NULL can be safely passed to clear the
404 : * string. */
405 0 : void Seize(char *pszValue)
406 : {
407 0 : if (pszValue == nullptr)
408 0 : Clear();
409 : else
410 : {
411 0 : *this = pszValue;
412 0 : CPLFree(pszValue);
413 : }
414 0 : }
415 :
416 : /* There seems to be a bug in the way the compiler count indices...
417 : * Should be CPL_PRINT_FUNC_FORMAT (1, 2) */
418 : CPLSTRING_METHOD_DLL CPLString &
419 : Printf(CPL_FORMAT_STRING(const char *pszFormat), ...)
420 : CPL_PRINT_FUNC_FORMAT(2, 3);
421 : CPLSTRING_METHOD_DLL CPLString &
422 : vPrintf(CPL_FORMAT_STRING(const char *pszFormat), va_list args)
423 : CPL_PRINT_FUNC_FORMAT(2, 0);
424 : CPLSTRING_METHOD_DLL CPLString &
425 : FormatC(double dfValue, const char *pszFormat = nullptr);
426 : CPLSTRING_METHOD_DLL CPLString &Trim();
427 : CPLSTRING_METHOD_DLL CPLString &Recode(const char *pszSrcEncoding,
428 : const char *pszDstEncoding);
429 : CPLSTRING_METHOD_DLL CPLString &replaceAll(const std::string &osBefore,
430 : const std::string &osAfter);
431 : CPLSTRING_METHOD_DLL CPLString &replaceAll(const std::string &osBefore,
432 : char chAfter);
433 : CPLSTRING_METHOD_DLL CPLString &replaceAll(char chBefore,
434 : const std::string &osAfter);
435 : CPLSTRING_METHOD_DLL CPLString &replaceAll(char chBefore, char chAfter);
436 :
437 : /* case insensitive find alternates */
438 : CPLSTRING_METHOD_DLL size_t ifind(const std::string &str,
439 : size_t pos = 0) const;
440 : CPLSTRING_METHOD_DLL size_t ifind(const char *s, size_t pos = 0) const;
441 : CPLSTRING_METHOD_DLL CPLString &toupper(void);
442 : CPLSTRING_METHOD_DLL CPLString &tolower(void);
443 :
444 : CPLSTRING_METHOD_DLL bool endsWith(const std::string &osStr) const;
445 :
446 : CPLSTRING_METHOD_DLL CPLString URLEncode() const;
447 :
448 : CPLSTRING_METHOD_DLL CPLString SQLQuotedIdentifier() const;
449 :
450 : CPLSTRING_METHOD_DLL CPLString SQLQuotedLiteral() const;
451 :
452 : private:
453 : operator void *(void) = delete;
454 : };
455 :
456 : #undef CPLSTRING_CLASS_DLL
457 : #undef CPLSTRING_METHOD_DLL
458 :
459 : CPLString CPL_DLL CPLOPrintf(CPL_FORMAT_STRING(const char *pszFormat), ...)
460 : CPL_PRINT_FUNC_FORMAT(1, 2);
461 : CPLString CPL_DLL CPLOvPrintf(CPL_FORMAT_STRING(const char *pszFormat),
462 : va_list args) CPL_PRINT_FUNC_FORMAT(1, 0);
463 : CPLString CPL_DLL CPLQuotedSQLIdentifier(const char *pszIdent);
464 :
465 : /* -------------------------------------------------------------------- */
466 : /* URL processing functions, here since they depend on CPLString. */
467 : /* -------------------------------------------------------------------- */
468 : CPLString CPL_DLL CPLURLGetValue(const char *pszURL, const char *pszKey);
469 : CPLString CPL_DLL CPLURLAddKVP(const char *pszURL, const char *pszKey,
470 : const char *pszValue);
471 :
472 : /************************************************************************/
473 : /* CPLStringList */
474 : /************************************************************************/
475 :
476 : //! String list class designed around our use of C "char**" string lists.
477 13405400 : class CPL_DLL CPLStringList
478 : {
479 : char **papszList = nullptr;
480 : mutable int nCount = 0;
481 : mutable int nAllocation = 0;
482 : bool bOwnList = false;
483 : bool bIsSorted = false;
484 :
485 : bool MakeOurOwnCopy();
486 : bool EnsureAllocation(int nMaxLength);
487 : int FindSortedInsertionPoint(const char *pszLine);
488 :
489 : public:
490 : CPLStringList();
491 : explicit CPLStringList(char **papszList, int bTakeOwnership = TRUE);
492 : explicit CPLStringList(CSLConstList papszList);
493 : explicit CPLStringList(const std::vector<std::string> &aosList);
494 : explicit CPLStringList(std::initializer_list<const char *> oInitList);
495 : CPLStringList(const CPLStringList &oOther);
496 : CPLStringList(CPLStringList &&oOther);
497 : ~CPLStringList();
498 :
499 : static const CPLStringList BoundToConstList(CSLConstList papszList);
500 :
501 : CPLStringList &Clear();
502 :
503 : /** Clear the list */
504 2 : inline void clear()
505 : {
506 2 : Clear();
507 2 : }
508 :
509 : /** Return size of list */
510 1801103 : int size() const
511 : {
512 1801103 : return Count();
513 : }
514 :
515 : int Count() const;
516 :
517 : /** Return whether the list is empty. */
518 56481 : bool empty() const
519 : {
520 56481 : return Count() == 0;
521 : }
522 :
523 : CPLStringList &AddString(const char *pszNewString);
524 : CPLStringList &AddString(const std::string &newString);
525 : CPLStringList &AddStringDirectly(char *pszNewString);
526 :
527 : /** Add a string to the list */
528 5437 : void push_back(const char *pszNewString)
529 : {
530 5437 : AddString(pszNewString);
531 5437 : }
532 :
533 : /** Add a string to the list */
534 1731 : void push_back(const std::string &osStr)
535 : {
536 1731 : AddString(osStr.c_str());
537 1731 : }
538 :
539 : #if defined(DOXYGEN_SKIP) || __cplusplus >= 201703L || \
540 : (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
541 : void push_back(std::string_view svStr);
542 : #endif
543 :
544 396 : CPLStringList &InsertString(int nInsertAtLineNo, const char *pszNewLine)
545 : {
546 396 : return InsertStringDirectly(nInsertAtLineNo, CPLStrdup(pszNewLine));
547 : }
548 :
549 : CPLStringList &InsertStringDirectly(int nInsertAtLineNo,
550 : char *pszNewLine);
551 :
552 : // CPLStringList &InsertStrings( int nInsertAtLineNo, char
553 : // **papszNewLines );
554 :
555 : CPLStringList &RemoveStrings(int nFirstLineToDelete,
556 : int nNumToRemove = 1);
557 :
558 : /** Return index of pszTarget in the list, or -1 */
559 17933 : int FindString(const char *pszTarget) const
560 : {
561 17933 : return CSLFindString(papszList, pszTarget);
562 : }
563 :
564 : /** Return index of pszTarget in the list (using partial search), or -1
565 : */
566 33 : int PartialFindString(const char *pszNeedle) const
567 : {
568 33 : return CSLPartialFindString(papszList, pszNeedle);
569 : }
570 :
571 : int FindName(const char *pszName) const;
572 : bool FetchBool(const char *pszKey, bool bDefault) const;
573 : // Deprecated.
574 : int FetchBoolean(const char *pszKey, int bDefault) const;
575 : const char *FetchNameValue(const char *pszKey) const;
576 : const char *FetchNameValueDef(const char *pszKey,
577 : const char *pszDefault) const;
578 : CPLStringList &AddNameValue(const char *pszKey, const char *pszValue);
579 : CPLStringList &SetNameValue(const char *pszKey, const char *pszValue);
580 :
581 : CPLStringList &SetString(int pos, const char *pszString);
582 : CPLStringList &SetString(int pos, const std::string &osString);
583 : CPLStringList &SetStringDirectly(int pos, char *pszString);
584 :
585 : CPLStringList &Assign(char **papszListIn, int bTakeOwnership = TRUE);
586 :
587 : /** Assignment operator */
588 338204 : CPLStringList &operator=(char **papszListIn)
589 : {
590 338204 : return Assign(papszListIn, TRUE);
591 : }
592 :
593 : /** Assignment operator */
594 : CPLStringList &operator=(const CPLStringList &oOther);
595 : /** Assignment operator */
596 : CPLStringList &operator=(CSLConstList papszListIn);
597 : /** Move assignment operator */
598 : CPLStringList &operator=(CPLStringList &&oOther);
599 :
600 : /** Return string at specified index */
601 : char *operator[](int i);
602 :
603 : /** Return string at specified index */
604 2149 : char *operator[](size_t i)
605 : {
606 2149 : return (*this)[static_cast<int>(i)];
607 : }
608 :
609 : /** Return string at specified index */
610 : const char *operator[](int i) const;
611 :
612 : /** Return string at specified index */
613 1972 : const char *operator[](size_t i) const
614 : {
615 1972 : return (*this)[static_cast<int>(i)];
616 : }
617 :
618 : /** Return value corresponding to pszKey, or nullptr */
619 4493 : const char *operator[](const char *pszKey) const
620 : {
621 4493 : return FetchNameValue(pszKey);
622 : }
623 :
624 : /** Return first element */
625 : inline const char *front() const
626 : {
627 : return papszList[0];
628 : }
629 :
630 : /** Return last element */
631 754399 : inline const char *back() const
632 : {
633 754399 : return papszList[size() - 1];
634 : }
635 :
636 : /** begin() implementation */
637 18190 : const char *const *begin() const
638 : {
639 18190 : return papszList ? &papszList[0] : nullptr;
640 : }
641 :
642 : /** end() implementation */
643 18190 : const char *const *end() const
644 : {
645 18190 : return papszList ? &papszList[size()] : nullptr;
646 : }
647 :
648 : /** Return list. Ownership remains to the object */
649 3378633 : char **List()
650 : {
651 3378633 : return papszList;
652 : }
653 :
654 : /** Return list. Ownership remains to the object */
655 2501562 : CSLConstList List() const
656 : {
657 2501562 : return papszList;
658 : }
659 :
660 : char **StealList();
661 :
662 : CPLStringList &Sort();
663 :
664 : /** Returns whether the list is sorted */
665 23889323 : int IsSorted() const
666 : {
667 23889323 : return bIsSorted;
668 : }
669 :
670 : /** Return lists */
671 69031 : operator char **(void)
672 : {
673 69031 : return List();
674 : }
675 :
676 : /** Return lists */
677 3037 : operator CSLConstList(void) const
678 : {
679 3037 : return List();
680 : }
681 :
682 : /** Return the list as a vector of strings */
683 2254 : operator std::vector<std::string>(void) const
684 : {
685 2254 : return std::vector<std::string>{begin(), end()};
686 : }
687 :
688 : private:
689 : operator void *(void) = delete;
690 : };
691 :
692 : #ifdef GDAL_COMPILATION
693 :
694 : #include <iterator> // For std::input_iterator_tag
695 : #include <memory>
696 : #include <string_view>
697 : #include <utility> // For std::pair
698 :
699 : /*! @cond Doxygen_Suppress */
700 : struct CPL_DLL CSLDestroyReleaser
701 : {
702 : void operator()(char **papszStr) const
703 : {
704 : CSLDestroy(papszStr);
705 : }
706 : };
707 :
708 : /*! @endcond */
709 :
710 : /** Unique pointer type to use with CSL functions returning a char** */
711 : using CSLUniquePtr = std::unique_ptr<char *, CSLDestroyReleaser>;
712 :
713 : /** Unique pointer type to use with functions returning a char* to release
714 : * with VSIFree */
715 : using CPLCharUniquePtr = std::unique_ptr<char, VSIFreeReleaser>;
716 :
717 : namespace cpl
718 : {
719 :
720 : /*! @cond Doxygen_Suppress */
721 :
722 : /** Equivalent of C++20 std::string::starts_with(const char*) */
723 : template <class StringType>
724 360867 : inline bool starts_with(const StringType &str, const char *prefix)
725 : {
726 360867 : const size_t prefixLen = strlen(prefix);
727 689847 : return str.size() >= prefixLen &&
728 689847 : str.compare(0, prefixLen, prefix, prefixLen) == 0;
729 : }
730 :
731 : /** Equivalent of C++20 std::string::starts_with(const std::string &) */
732 : template <class StringType>
733 44779 : inline bool starts_with(const StringType &str, const std::string &prefix)
734 : {
735 72302 : return str.size() >= prefix.size() &&
736 72316 : str.compare(0, prefix.size(), prefix) == 0;
737 : }
738 :
739 : /** Equivalent of C++20 std::string::starts_with(std::string_view) */
740 : template <class StringType>
741 1645 : inline bool starts_with(const StringType &str, std::string_view prefix)
742 : {
743 3290 : return str.size() >= prefix.size() &&
744 3290 : str.compare(0, prefix.size(), prefix) == 0;
745 : }
746 :
747 : /** Equivalent of C++20 std::string::ends_with(const char*) */
748 : template <class StringType>
749 253887 : inline bool ends_with(const StringType &str, const char *suffix)
750 : {
751 253887 : const size_t suffixLen = strlen(suffix);
752 503385 : return str.size() >= suffixLen &&
753 249498 : str.compare(str.size() - suffixLen, suffixLen, suffix,
754 503385 : suffixLen) == 0;
755 : }
756 :
757 : /** Equivalent of C++20 std::string::ends_with(const std::string &) */
758 : template <class StringType>
759 515 : inline bool ends_with(const StringType &str, const std::string &suffix)
760 : {
761 767 : return str.size() >= suffix.size() &&
762 252 : str.compare(str.size() - suffix.size(), suffix.size(), suffix) ==
763 515 : 0;
764 : }
765 :
766 : /** Equivalent of C++20 std::string::ends_with(std::string_view) */
767 : template <class StringType>
768 : inline bool ends_with(const StringType &str, std::string_view suffix)
769 : {
770 : return str.size() >= suffix.size() &&
771 : str.compare(str.size() - suffix.size(), suffix.size(), suffix) ==
772 : 0;
773 : }
774 :
775 : /** Iterator for a CSLConstList */
776 : struct CPL_DLL CSLIterator
777 : {
778 : using iterator_category = std::input_iterator_tag;
779 : using difference_type = std::ptrdiff_t;
780 : using value_type = const char *;
781 : using pointer = value_type *;
782 : using reference = value_type &;
783 :
784 : CSLConstList m_papszList = nullptr;
785 : bool m_bAtEnd = false;
786 :
787 18908032 : inline const char *operator*() const
788 : {
789 18908032 : return *m_papszList;
790 : }
791 :
792 18907814 : inline CSLIterator &operator++()
793 : {
794 18907814 : if (m_papszList)
795 18907814 : ++m_papszList;
796 18907814 : return *this;
797 : }
798 :
799 : bool operator==(const CSLIterator &other) const;
800 :
801 22916351 : inline bool operator!=(const CSLIterator &other) const
802 : {
803 22916351 : return !(operator==(other));
804 : }
805 : };
806 :
807 : /*! @endcond */
808 :
809 : /** Wrapper for a CSLConstList that can be used with C++ iterators.
810 : *
811 : * @since GDAL 3.9
812 : */
813 : struct CPL_DLL CSLIteratorWrapper
814 : {
815 : public:
816 : /** Constructor */
817 4008558 : inline explicit CSLIteratorWrapper(CSLConstList papszList)
818 4008558 : : m_papszList(papszList)
819 : {
820 4008558 : }
821 :
822 : /** Get the begin of the list */
823 4008558 : inline CSLIterator begin() const
824 : {
825 4008558 : return {m_papszList, false};
826 : }
827 :
828 : /** Get the end of the list */
829 4008558 : inline CSLIterator end() const
830 : {
831 4008558 : return {m_papszList, true};
832 : }
833 :
834 : private:
835 : CSLConstList m_papszList;
836 : };
837 :
838 : /** Wraps a CSLConstList in a structure that can be used with C++ iterators.
839 : *
840 : * @since GDAL 3.9
841 : */
842 4008558 : inline CSLIteratorWrapper Iterate(CSLConstList papszList)
843 : {
844 4008558 : return CSLIteratorWrapper{papszList};
845 : }
846 :
847 : /*! @cond Doxygen_Suppress */
848 15992 : inline CSLIteratorWrapper Iterate(const CPLStringList &aosList)
849 : {
850 15992 : return Iterate(aosList.List());
851 : }
852 :
853 : /*! @endcond */
854 :
855 : /*! @cond Doxygen_Suppress */
856 : inline CSLIteratorWrapper Iterate(char **) = delete;
857 :
858 : /*! @endcond */
859 :
860 : /*! @cond Doxygen_Suppress */
861 : /** Iterator for a CSLConstList as (name, value) pairs. */
862 : struct CPL_DLL CSLNameValueIterator
863 : {
864 : using iterator_category = std::input_iterator_tag;
865 : using difference_type = std::ptrdiff_t;
866 : using value_type = std::pair<const char *, const char *>;
867 : using pointer = value_type *;
868 : using reference = value_type &;
869 :
870 : CSLConstList m_papszList = nullptr;
871 : bool m_bReturnNullKeyIfNotNameValue = false;
872 : std::string m_osKey{};
873 :
874 : value_type operator*();
875 :
876 8307 : inline CSLNameValueIterator &operator++()
877 : {
878 8307 : if (m_papszList)
879 8307 : ++m_papszList;
880 8307 : return *this;
881 : }
882 :
883 21885 : inline bool operator==(const CSLNameValueIterator &other) const
884 : {
885 21885 : return m_papszList == other.m_papszList;
886 : }
887 :
888 21883 : inline bool operator!=(const CSLNameValueIterator &other) const
889 : {
890 21883 : return !(operator==(other));
891 : }
892 : };
893 :
894 : /*! @endcond */
895 :
896 : /** Wrapper for a CSLConstList that can be used with C++ iterators
897 : * to get (name, value) pairs.
898 : *
899 : * This can for example be used to do the following:
900 : * for (const auto& [name, value]: cpl::IterateNameValue(papszList)) {}
901 : *
902 : * Note that a (name, value) pair returned by dereferencing an iterator
903 : * is invalidated by the next iteration on the iterator.
904 : *
905 : * @since GDAL 3.9
906 : */
907 : struct CPL_DLL CSLNameValueIteratorWrapper
908 : {
909 : public:
910 : /** Constructor */
911 13578 : inline explicit CSLNameValueIteratorWrapper(
912 : CSLConstList papszList, bool bReturnNullKeyIfNotNameValue)
913 13578 : : m_papszList(papszList),
914 13578 : m_bReturnNullKeyIfNotNameValue(bReturnNullKeyIfNotNameValue)
915 : {
916 13578 : }
917 :
918 : /** Get the begin of the list */
919 13578 : inline CSLNameValueIterator begin() const
920 : {
921 13578 : return {m_papszList, m_bReturnNullKeyIfNotNameValue};
922 : }
923 :
924 : /** Get the end of the list */
925 : CSLNameValueIterator end() const;
926 :
927 : private:
928 : CSLConstList m_papszList;
929 : const bool m_bReturnNullKeyIfNotNameValue;
930 : };
931 :
932 : /** Wraps a CSLConstList in a structure that can be used with C++ iterators
933 : * to get (name, value) pairs.
934 : *
935 : * This can for example be used to do the following:
936 : * for (const auto& [name, value]: cpl::IterateNameValue(papszList)) {}
937 : *
938 : * Note that a (name, value) pair returned by dereferencing an iterator
939 : * is invalidated by the next iteration on the iterator.
940 : *
941 : * @param papszList List to iterate over.
942 : * @param bReturnNullKeyIfNotNameValue When this is set to true, if a string
943 : * contained in the list if not of the form name=value, then the value of
944 : * the iterator will be (nullptr, string).
945 : *
946 : * @since GDAL 3.9
947 : */
948 : inline CSLNameValueIteratorWrapper
949 13578 : IterateNameValue(CSLConstList papszList,
950 : bool bReturnNullKeyIfNotNameValue = false)
951 : {
952 13578 : return CSLNameValueIteratorWrapper{papszList,
953 13578 : bReturnNullKeyIfNotNameValue};
954 : }
955 :
956 : /*! @cond Doxygen_Suppress */
957 : inline CSLNameValueIteratorWrapper
958 7872 : IterateNameValue(const CPLStringList &aosList,
959 : bool bReturnNullKeyIfNotNameValue = false)
960 : {
961 7872 : return IterateNameValue(aosList.List(), bReturnNullKeyIfNotNameValue);
962 : }
963 :
964 : /*! @endcond */
965 :
966 : /*! @cond Doxygen_Suppress */
967 : inline CSLIteratorWrapper IterateNameValue(char **, bool = false) = delete;
968 :
969 : /*! @endcond */
970 :
971 : /** Converts a CSLConstList to a std::vector<std::string> */
972 98 : inline std::vector<std::string> ToVector(CSLConstList papszList)
973 : {
974 196 : return CPLStringList::BoundToConstList(papszList);
975 : }
976 :
977 : inline std::vector<std::string> ToVector(char **) = delete;
978 :
979 : } // namespace cpl
980 :
981 : #endif
982 :
983 : } // extern "C++"
984 :
985 : #endif /* def __cplusplus && !CPL_SUPRESS_CPLUSPLUS */
986 :
987 : #endif /* CPL_STRING_H_INCLUDED */
|