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