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 18763670 : CPLString(void)
346 18763670 : {
347 18763542 : }
348 :
349 : /** Constructor */
350 : // cppcheck-suppress noExplicitConstructor
351 5200956 : CPLString(const std::string &oStr) : std::string(oStr)
352 : {
353 5200946 : }
354 :
355 : /** Constructor */
356 : // cppcheck-suppress noExplicitConstructor
357 10333231 : CPLString(const char *pszStr) : std::string(pszStr)
358 : {
359 10333231 : }
360 :
361 : /** Constructor */
362 71900 : CPLString(const char *pszStr, size_t n) : std::string(pszStr, n)
363 : {
364 71900 : }
365 :
366 : /** Return string as zero terminated character array */
367 25382860 : operator const char *(void) const
368 : {
369 25382860 : return c_str();
370 : }
371 :
372 : /** Return character at specified index */
373 60696232 : char &operator[](std::string::size_type i)
374 : {
375 60696232 : return std::string::operator[](i);
376 : }
377 :
378 : /** Return character at specified index */
379 279584 : const char &operator[](std::string::size_type i) const
380 : {
381 279584 : return std::string::operator[](i);
382 : }
383 :
384 : /** Return character at specified index */
385 2942845 : char &operator[](int i)
386 : {
387 : return std::string::operator[](
388 2942845 : static_cast<std::string::size_type>(i));
389 : }
390 :
391 : /** Return character at specified index */
392 16907 : const char &operator[](int i) const
393 : {
394 : return std::string::operator[](
395 16907 : 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 14767900 : 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 1796469 : int size() const
513 : {
514 1796469 : return Count();
515 : }
516 :
517 : int Count() const;
518 :
519 : /** Return whether the list is empty. */
520 56236 : bool empty() const
521 : {
522 56236 : 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 &AddString(double adfNumber);
531 : CPLStringList &AddStringDirectly(char *pszNewString);
532 :
533 : /** Add a string to the list */
534 5479 : void push_back(const char *pszNewString)
535 : {
536 5479 : AddString(pszNewString);
537 5479 : }
538 :
539 : /** Add a string to the list */
540 1740 : void push_back(const std::string &osStr)
541 : {
542 1740 : AddString(osStr.c_str());
543 1740 : }
544 :
545 : #if defined(DOXYGEN_SKIP) || defined(HAVE_STRING_VIEW)
546 : void push_back(std::string_view svStr);
547 : #endif
548 :
549 396 : CPLStringList &InsertString(int nInsertAtLineNo, const char *pszNewLine)
550 : {
551 396 : return InsertStringDirectly(nInsertAtLineNo, CPLStrdup(pszNewLine));
552 : }
553 :
554 : CPLStringList &InsertStringDirectly(int nInsertAtLineNo,
555 : char *pszNewLine);
556 :
557 : // CPLStringList &InsertStrings( int nInsertAtLineNo, char
558 : // **papszNewLines );
559 :
560 : CPLStringList &RemoveStrings(int nFirstLineToDelete,
561 : int nNumToRemove = 1);
562 :
563 : /** Return index of pszTarget in the list, or -1 */
564 17968 : int FindString(const char *pszTarget) const
565 : {
566 17968 : return CSLFindString(papszList, pszTarget);
567 : }
568 :
569 : /** Return index of pszTarget in the list (using partial search), or -1
570 : */
571 33 : int PartialFindString(const char *pszNeedle) const
572 : {
573 33 : return CSLPartialFindString(papszList, pszNeedle);
574 : }
575 :
576 : int FindName(const char *pszName) const;
577 : bool FetchBool(const char *pszKey, bool bDefault) const;
578 : // Deprecated.
579 : int FetchBoolean(const char *pszKey, int bDefault) const;
580 : const char *FetchNameValue(const char *pszKey) const;
581 : const char *FetchNameValueDef(const char *pszKey,
582 : const char *pszDefault) const;
583 : CPLStringList &AddNameValue(const char *pszKey, const char *pszValue);
584 : CPLStringList &SetNameValue(const char *pszKey, const char *pszValue);
585 :
586 : CPLStringList &SetString(int pos, const char *pszString);
587 : CPLStringList &SetString(int pos, const std::string &osString);
588 : CPLStringList &SetStringDirectly(int pos, char *pszString);
589 :
590 : CPLStringList &Assign(char **papszListIn, int bTakeOwnership = TRUE);
591 :
592 : /** Assignment operator */
593 337822 : CPLStringList &operator=(char **papszListIn)
594 : {
595 337822 : return Assign(papszListIn, TRUE);
596 : }
597 :
598 : /** Assignment operator */
599 : CPLStringList &operator=(const CPLStringList &oOther);
600 : /** Assignment operator */
601 : CPLStringList &operator=(CSLConstList papszListIn);
602 : /** Move assignment operator */
603 : CPLStringList &operator=(CPLStringList &&oOther);
604 :
605 : /** Return string at specified index */
606 : char *operator[](int i);
607 :
608 : /** Return string at specified index */
609 2460 : char *operator[](size_t i)
610 : {
611 2460 : return (*this)[static_cast<int>(i)];
612 : }
613 :
614 : /** Return string at specified index */
615 : const char *operator[](int i) const;
616 :
617 : /** Return string at specified index */
618 2008 : const char *operator[](size_t i) const
619 : {
620 2008 : return (*this)[static_cast<int>(i)];
621 : }
622 :
623 : /** Return value corresponding to pszKey, or nullptr */
624 4493 : const char *operator[](const char *pszKey) const
625 : {
626 4493 : return FetchNameValue(pszKey);
627 : }
628 :
629 : /** Return first element */
630 : inline const char *front() const
631 : {
632 : return papszList[0];
633 : }
634 :
635 : /** Return last element */
636 737258 : inline const char *back() const
637 : {
638 737258 : return papszList[size() - 1];
639 : }
640 :
641 : /** begin() implementation */
642 18317 : const char *const *begin() const
643 : {
644 18317 : return papszList ? &papszList[0] : nullptr;
645 : }
646 :
647 : /** end() implementation */
648 18317 : const char *const *end() const
649 : {
650 18317 : return papszList ? &papszList[size()] : nullptr;
651 : }
652 :
653 : /** Return list. Ownership remains to the object */
654 3415330 : char **List()
655 : {
656 3415330 : return papszList;
657 : }
658 :
659 : /** Return list. Ownership remains to the object */
660 2399298 : CSLConstList List() const
661 : {
662 2399298 : return papszList;
663 : }
664 :
665 : char **StealList();
666 :
667 : CPLStringList &Sort();
668 :
669 : /** Returns whether the list is sorted */
670 23425222 : int IsSorted() const
671 : {
672 23425222 : return bIsSorted;
673 : }
674 :
675 : /** Return lists */
676 69182 : operator char **(void)
677 : {
678 69182 : return List();
679 : }
680 :
681 : /** Return lists */
682 3141 : operator CSLConstList(void) const
683 : {
684 3141 : return List();
685 : }
686 :
687 : /** Return the list as a vector of strings */
688 2462 : operator std::vector<std::string>(void) const
689 : {
690 2462 : return std::vector<std::string>{begin(), end()};
691 : }
692 :
693 : private:
694 : operator void *(void) = delete;
695 : };
696 :
697 : #ifdef GDAL_COMPILATION
698 :
699 : #include <iterator> // For std::input_iterator_tag
700 : #include <memory>
701 : #include <string_view>
702 : #include <utility> // For std::pair
703 :
704 : /*! @cond Doxygen_Suppress */
705 : struct CPL_DLL CSLDestroyReleaser
706 : {
707 : void operator()(char **papszStr) const
708 : {
709 : CSLDestroy(papszStr);
710 : }
711 : };
712 :
713 : /*! @endcond */
714 :
715 : /** Unique pointer type to use with CSL functions returning a char** */
716 : using CSLUniquePtr = std::unique_ptr<char *, CSLDestroyReleaser>;
717 :
718 : /** Unique pointer type to use with functions returning a char* to release
719 : * with VSIFree */
720 : using CPLCharUniquePtr = std::unique_ptr<char, VSIFreeReleaser>;
721 :
722 : namespace cpl
723 : {
724 :
725 : /*! @cond Doxygen_Suppress */
726 :
727 : #if defined(DOXYGEN_SKIP) || defined(HAVE_STRING_VIEW)
728 : bool CPL_DLL starts_with(std::string_view str, std::string_view prefix);
729 : bool CPL_DLL starts_with_ci(std::string_view str, std::string_view prefix);
730 :
731 : bool CPL_DLL ends_with(std::string_view str, std::string_view suffix);
732 : bool CPL_DLL ends_with_ci(std::string_view str, std::string_view suffix);
733 :
734 : bool CPL_DLL equals(std::string_view str1, std::string_view str2);
735 : bool CPL_DLL equals_ci(std::string_view str1, std::string_view str2);
736 :
737 : std::string_view CPL_DLL trim(std::string_view str);
738 : std::string_view CPL_DLL rtrim(std::string_view str);
739 : std::string_view CPL_DLL ltrim(std::string_view str);
740 :
741 : std::string_view CPL_DLL trim(const char *str);
742 : std::string_view CPL_DLL rtrim(const char *str);
743 : std::string_view CPL_DLL ltrim(const char *str);
744 :
745 : std::string_view trim(std::string &&) = delete;
746 : std::string_view rtrim(std::string &&) = delete;
747 : std::string_view ltrim(std::string &&) = delete;
748 :
749 : std::pair<std::string_view, std::string_view>
750 : CPL_DLL parse_name_value(std::string_view svNameValue);
751 :
752 : std::pair<std::string_view, std::string_view>
753 : CPL_DLL parse_name_value(const char *svNameValue);
754 :
755 : std::pair<std::string_view, std::string_view>
756 : parse_name_value(std::string &&) = delete;
757 :
758 : CPLStringList tokenize_string(std::string_view str,
759 : std::string_view delimiters, int nCSLTFlags);
760 : #endif
761 :
762 : /** Iterator for a CSLConstList */
763 : struct CPL_DLL CSLIterator
764 : {
765 : using iterator_category = std::input_iterator_tag;
766 : using difference_type = std::ptrdiff_t;
767 : using value_type = const char *;
768 : using pointer = value_type *;
769 : using reference = value_type &;
770 :
771 : CSLConstList m_papszList = nullptr;
772 : bool m_bAtEnd = false;
773 :
774 18948352 : inline const char *operator*() const
775 : {
776 18948352 : return *m_papszList;
777 : }
778 :
779 18939981 : inline CSLIterator &operator++()
780 : {
781 18939981 : if (m_papszList)
782 18939981 : ++m_papszList;
783 18939981 : return *this;
784 : }
785 :
786 : bool operator==(const CSLIterator &other) const;
787 :
788 22935078 : inline bool operator!=(const CSLIterator &other) const
789 : {
790 22935078 : return !(operator==(other));
791 : }
792 : };
793 :
794 : /*! @endcond */
795 :
796 : /** Wrapper for a CSLConstList that can be used with C++ iterators.
797 : *
798 : * @since GDAL 3.9
799 : */
800 : struct CPL_DLL CSLIteratorWrapper
801 : {
802 : public:
803 : /** Constructor */
804 3995098 : inline explicit CSLIteratorWrapper(CSLConstList papszList)
805 3995098 : : m_papszList(papszList)
806 : {
807 3995098 : }
808 :
809 : /** Get the begin of the list */
810 3995098 : inline CSLIterator begin() const
811 : {
812 3995098 : return {m_papszList, false};
813 : }
814 :
815 : /** Get the end of the list */
816 3995098 : inline CSLIterator end() const
817 : {
818 3995098 : return {m_papszList, true};
819 : }
820 :
821 : private:
822 : CSLConstList m_papszList;
823 : };
824 :
825 : /** Wraps a CSLConstList in a structure that can be used with C++ iterators.
826 : *
827 : * @since GDAL 3.9
828 : */
829 3995098 : inline CSLIteratorWrapper Iterate(CSLConstList papszList)
830 : {
831 3995098 : return CSLIteratorWrapper{papszList};
832 : }
833 :
834 : /*! @cond Doxygen_Suppress */
835 24929 : inline CSLIteratorWrapper Iterate(const CPLStringList &aosList)
836 : {
837 24929 : return Iterate(aosList.List());
838 : }
839 :
840 : /*! @endcond */
841 :
842 : /*! @cond Doxygen_Suppress */
843 : inline CSLIteratorWrapper Iterate(char **) = delete;
844 :
845 : /*! @endcond */
846 :
847 : /*! @cond Doxygen_Suppress */
848 : /** Iterator for a CSLConstList as (name, value) pairs. */
849 : struct CPL_DLL CSLNameValueIterator
850 : {
851 : using iterator_category = std::input_iterator_tag;
852 : using difference_type = std::ptrdiff_t;
853 : using value_type = std::pair<const char *, const char *>;
854 : using pointer = value_type *;
855 : using reference = value_type &;
856 :
857 : CSLConstList m_papszList = nullptr;
858 : bool m_bReturnNullKeyIfNotNameValue = false;
859 : std::string m_osKey{};
860 :
861 : value_type operator*();
862 :
863 8778 : inline CSLNameValueIterator &operator++()
864 : {
865 8778 : if (m_papszList)
866 8778 : ++m_papszList;
867 8778 : return *this;
868 : }
869 :
870 22979 : inline bool operator==(const CSLNameValueIterator &other) const
871 : {
872 22979 : return m_papszList == other.m_papszList;
873 : }
874 :
875 22977 : inline bool operator!=(const CSLNameValueIterator &other) const
876 : {
877 22977 : return !(operator==(other));
878 : }
879 : };
880 :
881 : /*! @endcond */
882 :
883 : /** Wrapper for a CSLConstList that can be used with C++ iterators
884 : * to get (name, value) pairs.
885 : *
886 : * This can for example be used to do the following:
887 : * for (const auto& [name, value]: cpl::IterateNameValue(papszList)) {}
888 : *
889 : * Note that a (name, value) pair returned by dereferencing an iterator
890 : * is invalidated by the next iteration on the iterator.
891 : *
892 : * @since GDAL 3.9
893 : */
894 : struct CPL_DLL CSLNameValueIteratorWrapper
895 : {
896 : public:
897 : /** Constructor */
898 14201 : inline explicit CSLNameValueIteratorWrapper(
899 : CSLConstList papszList, bool bReturnNullKeyIfNotNameValue)
900 14201 : : m_papszList(papszList),
901 14201 : m_bReturnNullKeyIfNotNameValue(bReturnNullKeyIfNotNameValue)
902 : {
903 14201 : }
904 :
905 : /** Get the begin of the list */
906 14201 : inline CSLNameValueIterator begin() const
907 : {
908 14201 : return {m_papszList, m_bReturnNullKeyIfNotNameValue};
909 : }
910 :
911 : /** Get the end of the list */
912 : CSLNameValueIterator end() const;
913 :
914 : private:
915 : CSLConstList m_papszList;
916 : const bool m_bReturnNullKeyIfNotNameValue;
917 : };
918 :
919 : /** Wraps a CSLConstList in a structure that can be used with C++ iterators
920 : * to get (name, value) pairs.
921 : *
922 : * This can for example be used to do the following:
923 : * for (const auto& [name, value]: cpl::IterateNameValue(papszList)) {}
924 : *
925 : * Note that a (name, value) pair returned by dereferencing an iterator
926 : * is invalidated by the next iteration on the iterator.
927 : *
928 : * @param papszList List to iterate over.
929 : * @param bReturnNullKeyIfNotNameValue When this is set to true, if a string
930 : * contained in the list is not of the form name=value, then the value of
931 : * the iterator will be (nullptr, string).
932 : *
933 : * @since GDAL 3.9
934 : */
935 : inline CSLNameValueIteratorWrapper
936 14201 : IterateNameValue(CSLConstList papszList,
937 : bool bReturnNullKeyIfNotNameValue = false)
938 : {
939 14201 : return CSLNameValueIteratorWrapper{papszList,
940 14201 : bReturnNullKeyIfNotNameValue};
941 : }
942 :
943 : /*! @cond Doxygen_Suppress */
944 : inline CSLNameValueIteratorWrapper
945 7987 : IterateNameValue(const CPLStringList &aosList,
946 : bool bReturnNullKeyIfNotNameValue = false)
947 : {
948 7987 : return IterateNameValue(aosList.List(), bReturnNullKeyIfNotNameValue);
949 : }
950 :
951 : /*! @endcond */
952 :
953 : /*! @cond Doxygen_Suppress */
954 : inline CSLIteratorWrapper IterateNameValue(char **, bool = false) = delete;
955 :
956 : /*! @endcond */
957 :
958 : /** Converts a CSLConstList to a std::vector<std::string> */
959 98 : inline std::vector<std::string> ToVector(CSLConstList papszList)
960 : {
961 196 : return CPLStringList::BoundToConstList(papszList);
962 : }
963 :
964 : inline std::vector<std::string> ToVector(char **) = delete;
965 :
966 : } // namespace cpl
967 :
968 : #endif
969 :
970 : } // extern "C++"
971 :
972 : #ifdef HAVE_STRING_VIEW
973 : #undef HAVE_STRING_VIEW
974 : #endif
975 :
976 : #endif /* def __cplusplus && !CPL_SUPRESS_CPLUSPLUS */
977 :
978 : #endif /* CPL_STRING_H_INCLUDED */
|