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