Line data Source code
1 : /**********************************************************************
2 : * $Id$
3 : *
4 : * Name: cpl_string.h
5 : * Project: CPL - Common Portability Library
6 : * Purpose: String and StringList functions.
7 : * Author: Daniel Morissette, dmorissette@mapgears.com
8 : *
9 : **********************************************************************
10 : * Copyright (c) 1998, Daniel Morissette
11 : * Copyright (c) 2008-2014, Even Rouault <even dot rouault at spatialys.com>
12 : *
13 : * SPDX-License-Identifier: MIT
14 : ****************************************************************************/
15 :
16 : #ifndef CPL_STRING_H_INCLUDED
17 : #define CPL_STRING_H_INCLUDED
18 :
19 : #include "cpl_error.h"
20 : #include "cpl_conv.h"
21 : #include "cpl_vsi.h"
22 :
23 : #include <stdbool.h>
24 :
25 : /**
26 : * \file cpl_string.h
27 : *
28 : * Various convenience functions for working with strings and string lists.
29 : *
30 : * A StringList is just an array of strings with the last pointer being
31 : * NULL. An empty StringList may be either a NULL pointer, or a pointer to
32 : * a pointer memory location with a NULL value.
33 : *
34 : * A common convention for StringLists is to use them to store name/value
35 : * lists. In this case the contents are treated like a dictionary of
36 : * name/value pairs. The actual data is formatted with each string having
37 : * the format "<name>:<value>" (though "=" is also an acceptable separator).
38 : * A number of the functions in the file operate on name/value style
39 : * string lists (such as CSLSetNameValue(), and CSLFetchNameValue()).
40 : *
41 : * To some extent the CPLStringList C++ class can be used to abstract
42 : * managing string lists a bit but still be able to return them from C
43 : * functions.
44 : *
45 : */
46 :
47 : CPL_C_START
48 :
49 : char CPL_DLL **CSLAddString(char **papszStrList,
50 : const char *pszNewString) CPL_WARN_UNUSED_RESULT;
51 : char CPL_DLL **
52 : CSLAddStringMayFail(char **papszStrList,
53 : const char *pszNewString) CPL_WARN_UNUSED_RESULT;
54 : int CPL_DLL CSLCount(CSLConstList papszStrList);
55 : const char CPL_DLL *CSLGetField(CSLConstList, int);
56 : void CPL_DLL CPL_STDCALL CSLDestroy(char **papszStrList);
57 : char CPL_DLL **CSLDuplicate(CSLConstList papszStrList) CPL_WARN_UNUSED_RESULT;
58 : char CPL_DLL **CSLMerge(char **papszOrig,
59 : CSLConstList papszOverride) CPL_WARN_UNUSED_RESULT;
60 :
61 : char CPL_DLL **CSLTokenizeString(const char *pszString) CPL_WARN_UNUSED_RESULT;
62 : char CPL_DLL **
63 : CSLTokenizeStringComplex(const char *pszString, const char *pszDelimiter,
64 : int bHonourStrings,
65 : int bAllowEmptyTokens) CPL_WARN_UNUSED_RESULT;
66 : char CPL_DLL **CSLTokenizeString2(const char *pszString,
67 : const char *pszDelimiter,
68 : int nCSLTFlags) CPL_WARN_UNUSED_RESULT;
69 :
70 : /** Flag for CSLTokenizeString2() to honour strings */
71 : #define CSLT_HONOURSTRINGS 0x0001
72 : /** Flag for CSLTokenizeString2() to allow empty tokens */
73 : #define CSLT_ALLOWEMPTYTOKENS 0x0002
74 : /** Flag for CSLTokenizeString2() to preserve quotes */
75 : #define CSLT_PRESERVEQUOTES 0x0004
76 : /** Flag for CSLTokenizeString2() to preserve escape characters */
77 : #define CSLT_PRESERVEESCAPES 0x0008
78 : /** Flag for CSLTokenizeString2() to strip leading spaces */
79 : #define CSLT_STRIPLEADSPACES 0x0010
80 : /** Flag for CSLTokenizeString2() to strip trailaing spaces */
81 : #define CSLT_STRIPENDSPACES 0x0020
82 :
83 : int CPL_DLL CSLPrint(CSLConstList papszStrList, FILE *fpOut);
84 : char CPL_DLL **CSLLoad(const char *pszFname) CPL_WARN_UNUSED_RESULT;
85 : char CPL_DLL **CSLLoad2(const char *pszFname, int nMaxLines, int nMaxCols,
86 : CSLConstList papszOptions) CPL_WARN_UNUSED_RESULT;
87 : int CPL_DLL CSLSave(CSLConstList papszStrList, const char *pszFname);
88 :
89 : char CPL_DLL **
90 : CSLInsertStrings(char **papszStrList, int nInsertAtLineNo,
91 : CSLConstList papszNewLines) CPL_WARN_UNUSED_RESULT;
92 : char CPL_DLL **CSLInsertString(char **papszStrList, int nInsertAtLineNo,
93 : const char *pszNewLine) CPL_WARN_UNUSED_RESULT;
94 : char CPL_DLL **
95 : CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete, int nNumToRemove,
96 : char ***ppapszRetStrings) CPL_WARN_UNUSED_RESULT;
97 : int CPL_DLL CSLFindString(CSLConstList papszList, const char *pszTarget);
98 : int CPL_DLL CSLFindStringCaseSensitive(CSLConstList papszList,
99 : const char *pszTarget);
100 : int CPL_DLL CSLPartialFindString(CSLConstList papszHaystack,
101 : const char *pszNeedle);
102 : int CPL_DLL CSLFindName(CSLConstList papszStrList, const char *pszName);
103 : int CPL_DLL CSLFetchBoolean(CSLConstList papszStrList, const char *pszKey,
104 : int bDefault);
105 :
106 : /* TODO: Deprecate CSLTestBoolean. Remove in GDAL 3.x. */
107 : int CPL_DLL CSLTestBoolean(const char *pszValue);
108 : /* Do not use CPLTestBoolean in C++ code. Use CPLTestBool. */
109 : int CPL_DLL CPLTestBoolean(const char *pszValue);
110 :
111 : bool CPL_DLL CPLTestBool(const char *pszValue);
112 : bool CPL_DLL CPLFetchBool(CSLConstList papszStrList, const char *pszKey,
113 : bool bDefault);
114 :
115 : CPLErr CPL_DLL CPLParseMemorySize(const char *pszValue, GIntBig *pnValue,
116 : bool *pbUnitSpecified);
117 :
118 : const char CPL_DLL *CPLParseNameValue(const char *pszNameValue, char **ppszKey);
119 : const char CPL_DLL *CPLParseNameValueSep(const char *pszNameValue,
120 : char **ppszKey, char chSep);
121 :
122 : const char CPL_DLL *CSLFetchNameValue(CSLConstList papszStrList,
123 : const char *pszName);
124 : const char CPL_DLL *CSLFetchNameValueDef(CSLConstList papszStrList,
125 : const char *pszName,
126 : const char *pszDefault);
127 : char CPL_DLL **CSLFetchNameValueMultiple(CSLConstList papszStrList,
128 : const char *pszName);
129 : char CPL_DLL **CSLAddNameValue(char **papszStrList, const char *pszName,
130 : const char *pszValue) CPL_WARN_UNUSED_RESULT;
131 : char CPL_DLL **CSLSetNameValue(char **papszStrList, const char *pszName,
132 : const char *pszValue) CPL_WARN_UNUSED_RESULT;
133 : void CPL_DLL CSLSetNameValueSeparator(char **papszStrList,
134 : const char *pszSeparator);
135 :
136 : char CPL_DLL **CSLParseCommandLine(const char *pszCommandLine);
137 :
138 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for backlash quoting */
139 : #define CPLES_BackslashQuotable 0
140 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for XML */
141 : #define CPLES_XML 1
142 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for URL */
143 : #define CPLES_URL 2
144 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for SQL */
145 : #define CPLES_SQL 3
146 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for CSV */
147 : #define CPLES_CSV 4
148 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for XML (preserves quotes)
149 : */
150 : #define CPLES_XML_BUT_QUOTES 5
151 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for CSV (forced quoting) */
152 : #define CPLES_CSV_FORCE_QUOTING 6
153 : /** Scheme for CPLEscapeString()/CPLUnescapeString() for SQL identifiers */
154 : #define CPLES_SQLI 7
155 :
156 : char CPL_DLL *CPLEscapeString(const char *pszString, int nLength,
157 : int nScheme) CPL_WARN_UNUSED_RESULT;
158 : char CPL_DLL *CPLUnescapeString(const char *pszString, int *pnLength,
159 : int nScheme) CPL_WARN_UNUSED_RESULT;
160 :
161 : char CPL_DLL *CPLBinaryToHex(int nBytes,
162 : const GByte *pabyData) CPL_WARN_UNUSED_RESULT;
163 : GByte CPL_DLL *CPLHexToBinary(const char *pszHex,
164 : int *pnBytes) CPL_WARN_UNUSED_RESULT;
165 :
166 : char CPL_DLL *CPLBase64Encode(int nBytes,
167 : const GByte *pabyData) CPL_WARN_UNUSED_RESULT;
168 : int CPL_DLL CPLBase64DecodeInPlace(GByte *pszBase64) CPL_WARN_UNUSED_RESULT;
169 :
170 : /** Type of value */
171 : typedef enum
172 : {
173 : CPL_VALUE_STRING, /**< String */
174 : CPL_VALUE_REAL, /**< Real number */
175 : CPL_VALUE_INTEGER /**< Integer */
176 : } CPLValueType;
177 :
178 : CPLValueType CPL_DLL CPLGetValueType(const char *pszValue);
179 :
180 : int CPL_DLL CPLToupper(int c);
181 : int CPL_DLL CPLTolower(int c);
182 :
183 : size_t CPL_DLL CPLStrlcpy(char *pszDest, const char *pszSrc, size_t nDestSize);
184 : size_t CPL_DLL CPLStrlcat(char *pszDest, const char *pszSrc, size_t nDestSize);
185 : size_t CPL_DLL CPLStrnlen(const char *pszStr, size_t nMaxLen);
186 :
187 : /* -------------------------------------------------------------------- */
188 : /* Locale independent formatting functions. */
189 : /* -------------------------------------------------------------------- */
190 : int CPL_DLL CPLvsnprintf(char *str, size_t size,
191 : CPL_FORMAT_STRING(const char *fmt), va_list args)
192 : CPL_PRINT_FUNC_FORMAT(3, 0);
193 :
194 : /* ALIAS_CPLSNPRINTF_AS_SNPRINTF might be defined to enable GCC 7 */
195 : /* -Wformat-truncation= warnings, but shouldn't be set for normal use */
196 : #if defined(ALIAS_CPLSNPRINTF_AS_SNPRINTF)
197 : #define CPLsnprintf snprintf
198 : #else
199 : int CPL_DLL CPLsnprintf(char *str, size_t size,
200 : CPL_FORMAT_STRING(const char *fmt), ...)
201 : CPL_PRINT_FUNC_FORMAT(3, 4);
202 : #endif
203 :
204 : /*! @cond Doxygen_Suppress */
205 : #if defined(GDAL_COMPILATION) && !defined(DONT_DEPRECATE_SPRINTF)
206 : int CPL_DLL CPLsprintf(char *str, CPL_FORMAT_STRING(const char *fmt), ...)
207 : CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_DEPRECATED("Use CPLsnprintf instead");
208 : #else
209 : int CPL_DLL CPLsprintf(char *str, CPL_FORMAT_STRING(const char *fmt), ...)
210 : CPL_PRINT_FUNC_FORMAT(2, 3);
211 : #endif
212 : /*! @endcond */
213 : int CPL_DLL CPLprintf(CPL_FORMAT_STRING(const char *fmt), ...)
214 : CPL_PRINT_FUNC_FORMAT(1, 2);
215 :
216 : /* For some reason Doxygen_Suppress is needed to avoid warning. Not sure why */
217 : /*! @cond Doxygen_Suppress */
218 : /* caution: only works with limited number of formats */
219 : int CPL_DLL CPLsscanf(const char *str, CPL_SCANF_FORMAT_STRING(const char *fmt),
220 : ...) CPL_SCAN_FUNC_FORMAT(2, 3);
221 : /*! @endcond */
222 :
223 : const char CPL_DLL *CPLSPrintf(CPL_FORMAT_STRING(const char *fmt), ...)
224 : CPL_PRINT_FUNC_FORMAT(1, 2) CPL_WARN_UNUSED_RESULT;
225 : char CPL_DLL **CSLAppendPrintf(char **papszStrList,
226 : CPL_FORMAT_STRING(const char *fmt), ...)
227 : CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_UNUSED_RESULT;
228 : int CPL_DLL CPLVASPrintf(char **buf, CPL_FORMAT_STRING(const char *fmt),
229 : va_list args) CPL_PRINT_FUNC_FORMAT(2, 0);
230 :
231 : /* -------------------------------------------------------------------- */
232 : /* RFC 23 character set conversion/recoding API (cpl_recode.cpp). */
233 : /* -------------------------------------------------------------------- */
234 : /** Encoding of the current locale */
235 : #define CPL_ENC_LOCALE ""
236 : /** UTF-8 encoding */
237 : #define CPL_ENC_UTF8 "UTF-8"
238 : /** UTF-16 encoding */
239 : #define CPL_ENC_UTF16 "UTF-16"
240 : /** UCS-2 encoding */
241 : #define CPL_ENC_UCS2 "UCS-2"
242 : /** UCS-4 encoding */
243 : #define CPL_ENC_UCS4 "UCS-4"
244 : /** ASCII encoding */
245 : #define CPL_ENC_ASCII "ASCII"
246 : /** ISO-8859-1 (LATIN1) encoding */
247 : #define CPL_ENC_ISO8859_1 "ISO-8859-1"
248 :
249 : int CPL_DLL CPLEncodingCharSize(const char *pszEncoding);
250 : /*! @cond Doxygen_Suppress */
251 : void CPL_DLL CPLClearRecodeWarningFlags(void);
252 : /*! @endcond */
253 : char CPL_DLL *CPLRecode(const char *pszSource, const char *pszSrcEncoding,
254 : const char *pszDstEncoding)
255 : CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
256 : char CPL_DLL *
257 : CPLRecodeFromWChar(const wchar_t *pwszSource, const char *pszSrcEncoding,
258 : const char *pszDstEncoding) CPL_WARN_UNUSED_RESULT;
259 : wchar_t CPL_DLL *
260 : CPLRecodeToWChar(const char *pszSource, const char *pszSrcEncoding,
261 : const char *pszDstEncoding) CPL_WARN_UNUSED_RESULT;
262 : int CPL_DLL CPLIsUTF8(const char *pabyData, int nLen);
263 : bool CPL_DLL CPLIsASCII(const char *pabyData, size_t nLen);
264 : char CPL_DLL *CPLForceToASCII(const char *pabyData, int nLen,
265 : char chReplacementChar) CPL_WARN_UNUSED_RESULT;
266 : char CPL_DLL *CPLUTF8ForceToASCII(const char *pszStr, char chReplacementChar)
267 : CPL_WARN_UNUSED_RESULT;
268 : int CPL_DLL CPLStrlenUTF8(const char *pszUTF8Str);
269 : int CPL_DLL CPLCanRecode(const char *pszTestStr, const char *pszSrcEncoding,
270 : const char *pszDstEncoding) CPL_WARN_UNUSED_RESULT;
271 : CPL_C_END
272 :
273 : /************************************************************************/
274 : /* CPLString */
275 : /************************************************************************/
276 :
277 : #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
278 :
279 : extern "C++"
280 : {
281 : #ifndef DOXYGEN_SKIP
282 : #include <string>
283 : #include <vector>
284 : #endif
285 :
286 : // VC++ implicitly applies __declspec(dllexport) to template base classes
287 : // of classes marked with __declspec(dllexport).
288 : // Hence, if marked with CPL_DLL, VC++ would export symbols for the
289 : // specialization of std::basic_string<char>, since it is a base class of
290 : // CPLString. As a result, if an application linked both gdal.dll and a static
291 : // library that (implicitly) instantiates std::string (almost all do!), then the
292 : // linker would emit an error concerning duplicate symbols for std::string. The
293 : // least intrusive solution is to not mark the whole class with
294 : // __declspec(dllexport) for VC++, but only its non-inline methods.
295 : #ifdef _MSC_VER
296 : #define CPLSTRING_CLASS_DLL
297 : #define CPLSTRING_METHOD_DLL CPL_DLL
298 : #else
299 : /*! @cond Doxygen_Suppress */
300 : #define CPLSTRING_CLASS_DLL CPL_DLL
301 : #define CPLSTRING_METHOD_DLL
302 : /*! @endcond */
303 : #endif
304 :
305 : //! Convenient string class based on std::string.
306 20 : class CPLSTRING_CLASS_DLL CPLString : public std::string
307 : {
308 : public:
309 : /** Constructor */
310 14300756 : CPLString(void)
311 14300756 : {
312 14300536 : }
313 :
314 : /** Constructor */
315 : // cppcheck-suppress noExplicitConstructor
316 4283838 : CPLString(const std::string &oStr) : std::string(oStr)
317 : {
318 4283838 : }
319 :
320 : /** Constructor */
321 : // cppcheck-suppress noExplicitConstructor
322 7914574 : CPLString(const char *pszStr) : std::string(pszStr)
323 : {
324 7914527 : }
325 :
326 : /** Constructor */
327 59836 : CPLString(const char *pszStr, size_t n) : std::string(pszStr, n)
328 : {
329 59833 : }
330 :
331 : /** Return string as zero terminated character array */
332 21473179 : operator const char *(void) const
333 : {
334 21473179 : return c_str();
335 : }
336 :
337 : /** Return character at specified index */
338 46018012 : char &operator[](std::string::size_type i)
339 : {
340 46018012 : return std::string::operator[](i);
341 : }
342 :
343 : /** Return character at specified index */
344 201638 : const char &operator[](std::string::size_type i) const
345 : {
346 201638 : return std::string::operator[](i);
347 : }
348 :
349 : /** Return character at specified index */
350 118145 : char &operator[](int i)
351 : {
352 : return std::string::operator[](
353 118145 : static_cast<std::string::size_type>(i));
354 : }
355 :
356 : /** Return character at specified index */
357 21548 : const char &operator[](int i) const
358 : {
359 : return std::string::operator[](
360 21548 : static_cast<std::string::size_type>(i));
361 : }
362 :
363 : /** Clear the string */
364 23760 : void Clear()
365 : {
366 23760 : resize(0);
367 23760 : }
368 :
369 : /** Assign specified string and take ownership of it (assumed to be
370 : * allocated with CPLMalloc()). NULL can be safely passed to clear the
371 : * string. */
372 0 : void Seize(char *pszValue)
373 : {
374 0 : if (pszValue == nullptr)
375 0 : Clear();
376 : else
377 : {
378 0 : *this = pszValue;
379 0 : CPLFree(pszValue);
380 : }
381 0 : }
382 :
383 : /* There seems to be a bug in the way the compiler count indices...
384 : * Should be CPL_PRINT_FUNC_FORMAT (1, 2) */
385 : CPLSTRING_METHOD_DLL CPLString &
386 : Printf(CPL_FORMAT_STRING(const char *pszFormat), ...)
387 : CPL_PRINT_FUNC_FORMAT(2, 3);
388 : CPLSTRING_METHOD_DLL CPLString &
389 : vPrintf(CPL_FORMAT_STRING(const char *pszFormat), va_list args)
390 : CPL_PRINT_FUNC_FORMAT(2, 0);
391 : CPLSTRING_METHOD_DLL CPLString &
392 : FormatC(double dfValue, const char *pszFormat = nullptr);
393 : CPLSTRING_METHOD_DLL CPLString &Trim();
394 : CPLSTRING_METHOD_DLL CPLString &Recode(const char *pszSrcEncoding,
395 : const char *pszDstEncoding);
396 : CPLSTRING_METHOD_DLL CPLString &replaceAll(const std::string &osBefore,
397 : const std::string &osAfter);
398 : CPLSTRING_METHOD_DLL CPLString &replaceAll(const std::string &osBefore,
399 : char chAfter);
400 : CPLSTRING_METHOD_DLL CPLString &replaceAll(char chBefore,
401 : const std::string &osAfter);
402 : CPLSTRING_METHOD_DLL CPLString &replaceAll(char chBefore, char chAfter);
403 :
404 : /* case insensitive find alternates */
405 : CPLSTRING_METHOD_DLL size_t ifind(const std::string &str,
406 : size_t pos = 0) const;
407 : CPLSTRING_METHOD_DLL size_t ifind(const char *s, size_t pos = 0) const;
408 : CPLSTRING_METHOD_DLL CPLString &toupper(void);
409 : CPLSTRING_METHOD_DLL CPLString &tolower(void);
410 :
411 : CPLSTRING_METHOD_DLL bool endsWith(const std::string &osStr) const;
412 : };
413 :
414 : #undef CPLSTRING_CLASS_DLL
415 : #undef CPLSTRING_METHOD_DLL
416 :
417 : CPLString CPL_DLL CPLOPrintf(CPL_FORMAT_STRING(const char *pszFormat), ...)
418 : CPL_PRINT_FUNC_FORMAT(1, 2);
419 : CPLString CPL_DLL CPLOvPrintf(CPL_FORMAT_STRING(const char *pszFormat),
420 : va_list args) CPL_PRINT_FUNC_FORMAT(1, 0);
421 : CPLString CPL_DLL CPLQuotedSQLIdentifier(const char *pszIdent);
422 :
423 : /* -------------------------------------------------------------------- */
424 : /* URL processing functions, here since they depend on CPLString. */
425 : /* -------------------------------------------------------------------- */
426 : CPLString CPL_DLL CPLURLGetValue(const char *pszURL, const char *pszKey);
427 : CPLString CPL_DLL CPLURLAddKVP(const char *pszURL, const char *pszKey,
428 : const char *pszValue);
429 :
430 : /************************************************************************/
431 : /* CPLStringList */
432 : /************************************************************************/
433 :
434 : //! String list class designed around our use of C "char**" string lists.
435 9366820 : class CPL_DLL CPLStringList
436 : {
437 : char **papszList = nullptr;
438 : mutable int nCount = 0;
439 : mutable int nAllocation = 0;
440 : bool bOwnList = false;
441 : bool bIsSorted = false;
442 :
443 : bool MakeOurOwnCopy();
444 : bool EnsureAllocation(int nMaxLength);
445 : int FindSortedInsertionPoint(const char *pszLine);
446 :
447 : public:
448 : CPLStringList();
449 : explicit CPLStringList(char **papszList, int bTakeOwnership = TRUE);
450 : explicit CPLStringList(CSLConstList papszList);
451 : explicit CPLStringList(const std::vector<std::string> &aosList);
452 : explicit CPLStringList(std::initializer_list<const char *> oInitList);
453 : CPLStringList(const CPLStringList &oOther);
454 : CPLStringList(CPLStringList &&oOther);
455 : ~CPLStringList();
456 :
457 : static const CPLStringList BoundToConstList(CSLConstList papszList);
458 :
459 : CPLStringList &Clear();
460 :
461 : /** Clear the list */
462 1 : inline void clear()
463 : {
464 1 : Clear();
465 1 : }
466 :
467 : /** Return size of list */
468 872195 : int size() const
469 : {
470 872195 : return Count();
471 : }
472 :
473 : int Count() const;
474 :
475 : /** Return whether the list is empty. */
476 27708 : bool empty() const
477 : {
478 27708 : return Count() == 0;
479 : }
480 :
481 : CPLStringList &AddString(const char *pszNewString);
482 : CPLStringList &AddStringDirectly(char *pszNewString);
483 :
484 218 : CPLStringList &InsertString(int nInsertAtLineNo, const char *pszNewLine)
485 : {
486 218 : return InsertStringDirectly(nInsertAtLineNo, CPLStrdup(pszNewLine));
487 : }
488 :
489 : CPLStringList &InsertStringDirectly(int nInsertAtLineNo,
490 : char *pszNewLine);
491 :
492 : // CPLStringList &InsertStrings( int nInsertAtLineNo, char
493 : // **papszNewLines ); CPLStringList &RemoveStrings( int
494 : // nFirstLineToDelete, int nNumToRemove=1 );
495 :
496 : /** Return index of pszTarget in the list, or -1 */
497 15868 : int FindString(const char *pszTarget) const
498 : {
499 15868 : return CSLFindString(papszList, pszTarget);
500 : }
501 :
502 : /** Return index of pszTarget in the list (using partial search), or -1
503 : */
504 : int PartialFindString(const char *pszNeedle) const
505 : {
506 : return CSLPartialFindString(papszList, pszNeedle);
507 : }
508 :
509 : int FindName(const char *pszName) const;
510 : bool FetchBool(const char *pszKey, bool bDefault) const;
511 : // Deprecated.
512 : int FetchBoolean(const char *pszKey, int bDefault) const;
513 : const char *FetchNameValue(const char *pszKey) const;
514 : const char *FetchNameValueDef(const char *pszKey,
515 : const char *pszDefault) const;
516 : CPLStringList &AddNameValue(const char *pszKey, const char *pszValue);
517 : CPLStringList &SetNameValue(const char *pszKey, const char *pszValue);
518 :
519 : CPLStringList &Assign(char **papszListIn, int bTakeOwnership = TRUE);
520 :
521 : /** Assignment operator */
522 34241 : CPLStringList &operator=(char **papszListIn)
523 : {
524 34241 : return Assign(papszListIn, TRUE);
525 : }
526 :
527 : /** Assignment operator */
528 : CPLStringList &operator=(const CPLStringList &oOther);
529 : /** Assignment operator */
530 : CPLStringList &operator=(CSLConstList papszListIn);
531 : /** Move assignment operator */
532 : CPLStringList &operator=(CPLStringList &&oOther);
533 :
534 : /** Return string at specified index */
535 : char *operator[](int i);
536 :
537 : /** Return string at specified index */
538 1188 : char *operator[](size_t i)
539 : {
540 1188 : return (*this)[static_cast<int>(i)];
541 : }
542 :
543 : /** Return string at specified index */
544 : const char *operator[](int i) const;
545 :
546 : /** Return string at specified index */
547 112 : const char *operator[](size_t i) const
548 : {
549 112 : return (*this)[static_cast<int>(i)];
550 : }
551 :
552 : /** Return value corresponding to pszKey, or nullptr */
553 4161 : const char *operator[](const char *pszKey) const
554 : {
555 4161 : return FetchNameValue(pszKey);
556 : }
557 :
558 : /** Return first element */
559 : inline const char *front() const
560 : {
561 : return papszList[0];
562 : }
563 :
564 : /** Return last element */
565 432624 : inline const char *back() const
566 : {
567 432624 : return papszList[size() - 1];
568 : }
569 :
570 : /** begin() implementation */
571 4588 : const char *const *begin() const
572 : {
573 4588 : return papszList ? &papszList[0] : nullptr;
574 : }
575 :
576 : /** end() implementation */
577 4588 : const char *const *end() const
578 : {
579 4588 : return papszList ? &papszList[size()] : nullptr;
580 : }
581 :
582 : /** Return list. Ownership remains to the object */
583 2829751 : char **List()
584 : {
585 2829751 : return papszList;
586 : }
587 :
588 : /** Return list. Ownership remains to the object */
589 1949792 : CSLConstList List() const
590 : {
591 1949792 : return papszList;
592 : }
593 :
594 : char **StealList();
595 :
596 : CPLStringList &Sort();
597 :
598 : /** Returns whether the list is sorted */
599 19083295 : int IsSorted() const
600 : {
601 19083295 : return bIsSorted;
602 : }
603 :
604 : /** Return lists */
605 1422 : operator char **(void)
606 : {
607 1422 : return List();
608 : }
609 :
610 : /** Return lists */
611 752 : operator CSLConstList(void) const
612 : {
613 752 : return List();
614 : }
615 :
616 : /** Return the list as a vector of strings */
617 433 : operator std::vector<std::string>(void) const
618 : {
619 433 : return std::vector<std::string>{begin(), end()};
620 : }
621 : };
622 :
623 : #ifdef GDAL_COMPILATION
624 :
625 : #include <iterator> // For std::input_iterator_tag
626 : #include <memory>
627 : #include <utility> // For std::pair
628 :
629 : /*! @cond Doxygen_Suppress */
630 : struct CPL_DLL CSLDestroyReleaser
631 : {
632 : void operator()(char **papszStr) const
633 : {
634 : CSLDestroy(papszStr);
635 : }
636 : };
637 :
638 : /*! @endcond */
639 :
640 : /** Unique pointer type to use with CSL functions returning a char** */
641 : using CSLUniquePtr = std::unique_ptr<char *, CSLDestroyReleaser>;
642 :
643 : /** Unique pointer type to use with functions returning a char* to release
644 : * with VSIFree */
645 : using CPLCharUniquePtr = std::unique_ptr<char, VSIFreeReleaser>;
646 :
647 : namespace cpl
648 : {
649 :
650 : /*! @cond Doxygen_Suppress */
651 : /** Iterator for a CSLConstList */
652 : struct CPL_DLL CSLIterator
653 : {
654 : using iterator_category = std::input_iterator_tag;
655 : using difference_type = std::ptrdiff_t;
656 : using value_type = const char *;
657 : using pointer = value_type *;
658 : using reference = value_type &;
659 :
660 : CSLConstList m_papszList = nullptr;
661 : bool m_bAtEnd = false;
662 :
663 137901 : inline const char *operator*() const
664 : {
665 137901 : return *m_papszList;
666 : }
667 :
668 137720 : inline CSLIterator &operator++()
669 : {
670 137720 : if (m_papszList)
671 137720 : ++m_papszList;
672 137720 : return *this;
673 : }
674 :
675 : bool operator==(const CSLIterator &other) const;
676 :
677 254685 : inline bool operator!=(const CSLIterator &other) const
678 : {
679 254685 : return !(operator==(other));
680 : }
681 : };
682 :
683 : /*! @endcond */
684 :
685 : /** Wrapper for a CSLConstList that can be used with C++ iterators.
686 : *
687 : * @since GDAL 3.9
688 : */
689 : struct CPL_DLL CSLIteratorWrapper
690 : {
691 : public:
692 : /** Constructor */
693 116967 : inline explicit CSLIteratorWrapper(CSLConstList papszList)
694 116967 : : m_papszList(papszList)
695 : {
696 116967 : }
697 :
698 : /** Get the begin of the list */
699 116967 : inline CSLIterator begin() const
700 : {
701 116967 : return {m_papszList, false};
702 : }
703 :
704 : /** Get the end of the list */
705 116967 : inline CSLIterator end() const
706 : {
707 116967 : return {m_papszList, true};
708 : }
709 :
710 : private:
711 : CSLConstList m_papszList;
712 : };
713 :
714 : /** Wraps a CSLConstList in a structure that can be used with C++ iterators.
715 : *
716 : * @since GDAL 3.9
717 : */
718 116966 : inline CSLIteratorWrapper Iterate(CSLConstList papszList)
719 : {
720 116966 : return CSLIteratorWrapper{papszList};
721 : }
722 :
723 : /*! @cond Doxygen_Suppress */
724 1540 : inline CSLIteratorWrapper Iterate(const CPLStringList &aosList)
725 : {
726 1540 : return Iterate(aosList.List());
727 : }
728 :
729 : /*! @endcond */
730 :
731 : /*! @cond Doxygen_Suppress */
732 : inline CSLIteratorWrapper Iterate(char **) = delete;
733 :
734 : /*! @endcond */
735 :
736 : /*! @cond Doxygen_Suppress */
737 : /** Iterator for a CSLConstList as (name, value) pairs. */
738 : struct CPL_DLL CSLNameValueIterator
739 : {
740 : using iterator_category = std::input_iterator_tag;
741 : using difference_type = std::ptrdiff_t;
742 : using value_type = std::pair<const char *, const char *>;
743 : using pointer = value_type *;
744 : using reference = value_type &;
745 :
746 : CSLConstList m_papszList = nullptr;
747 : bool m_bReturnNullKeyIfNotNameValue = false;
748 : std::string m_osKey{};
749 :
750 : value_type operator*();
751 :
752 1199 : inline CSLNameValueIterator &operator++()
753 : {
754 1199 : if (m_papszList)
755 1199 : ++m_papszList;
756 1199 : return *this;
757 : }
758 :
759 4892 : inline bool operator==(const CSLNameValueIterator &other) const
760 : {
761 4892 : return m_papszList == other.m_papszList;
762 : }
763 :
764 4890 : inline bool operator!=(const CSLNameValueIterator &other) const
765 : {
766 4890 : return !(operator==(other));
767 : }
768 : };
769 :
770 : /*! @endcond */
771 :
772 : /** Wrapper for a CSLConstList that can be used with C++ iterators
773 : * to get (name, value) pairs.
774 : *
775 : * This can for example be used to do the following:
776 : * for (const auto& [name, value]: cpl::IterateNameValue(papszList)) {}
777 : *
778 : * Note that a (name, value) pair returned by dereferencing an iterator
779 : * is invalidated by the next iteration on the iterator.
780 : *
781 : * @since GDAL 3.9
782 : */
783 : struct CPL_DLL CSLNameValueIteratorWrapper
784 : {
785 : public:
786 : /** Constructor */
787 3693 : inline explicit CSLNameValueIteratorWrapper(
788 : CSLConstList papszList, bool bReturnNullKeyIfNotNameValue)
789 3693 : : m_papszList(papszList),
790 3693 : m_bReturnNullKeyIfNotNameValue(bReturnNullKeyIfNotNameValue)
791 : {
792 3693 : }
793 :
794 : /** Get the begin of the list */
795 3693 : inline CSLNameValueIterator begin() const
796 : {
797 3693 : return {m_papszList, m_bReturnNullKeyIfNotNameValue};
798 : }
799 :
800 : /** Get the end of the list */
801 : CSLNameValueIterator end() const;
802 :
803 : private:
804 : CSLConstList m_papszList;
805 : const bool m_bReturnNullKeyIfNotNameValue;
806 : };
807 :
808 : /** Wraps a CSLConstList in a structure that can be used with C++ iterators
809 : * to get (name, value) pairs.
810 : *
811 : * This can for example be used to do the following:
812 : * for (const auto& [name, value]: cpl::IterateNameValue(papszList)) {}
813 : *
814 : * Note that a (name, value) pair returned by dereferencing an iterator
815 : * is invalidated by the next iteration on the iterator.
816 : *
817 : * @param papszList List to iterate over.
818 : * @param bReturnNullKeyIfNotNameValue When this is set to true, if a string
819 : * contained in the list if not of the form name=value, then the value of
820 : * the iterator will be (nullptr, string).
821 : *
822 : * @since GDAL 3.9
823 : */
824 : inline CSLNameValueIteratorWrapper
825 3693 : IterateNameValue(CSLConstList papszList,
826 : bool bReturnNullKeyIfNotNameValue = false)
827 : {
828 3693 : return CSLNameValueIteratorWrapper{papszList,
829 3693 : bReturnNullKeyIfNotNameValue};
830 : }
831 :
832 : /*! @cond Doxygen_Suppress */
833 : inline CSLNameValueIteratorWrapper
834 2439 : IterateNameValue(const CPLStringList &aosList,
835 : bool bReturnNullKeyIfNotNameValue = false)
836 : {
837 2439 : return IterateNameValue(aosList.List(), bReturnNullKeyIfNotNameValue);
838 : }
839 :
840 : /*! @endcond */
841 :
842 : /*! @cond Doxygen_Suppress */
843 : inline CSLIteratorWrapper IterateNameValue(char **, bool = false) = delete;
844 :
845 : /*! @endcond */
846 :
847 : /** Converts a CSLConstList to a std::vector<std::string> */
848 94 : inline std::vector<std::string> ToVector(CSLConstList papszList)
849 : {
850 188 : return CPLStringList::BoundToConstList(papszList);
851 : }
852 :
853 : inline std::vector<std::string> ToVector(char **) = delete;
854 :
855 : } // namespace cpl
856 :
857 : #endif
858 :
859 : } // extern "C++"
860 :
861 : #endif /* def __cplusplus && !CPL_SUPRESS_CPLUSPLUS */
862 :
863 : #endif /* CPL_STRING_H_INCLUDED */
|