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