1 : /**********************************************************************
2 : * $Id: cpl_string.cpp 23719 2012-01-07 18:18:41Z rouault $
3 : *
4 : * Name: cpl_string.cpp
5 : * Project: CPL - Common Portability Library
6 : * Purpose: String and Stringlist manipulation functions.
7 : * Author: Daniel Morissette, danmo@videotron.ca
8 : *
9 : **********************************************************************
10 : * Copyright (c) 1998, Daniel Morissette
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : **********************************************************************
30 : *
31 : * Independent Security Audit 2003/04/04 Andrey Kiselev:
32 : * Completed audit of this module. All functions may be used without buffer
33 : * overflows and stack corruptions with any kind of input data strings with
34 : * except of CPLSPrintf() and CSLAppendPrintf() (see note below).
35 : *
36 : * Security Audit 2003/03/28 warmerda:
37 : * Completed security audit. I believe that this module may be safely used
38 : * to parse tokenize arbitrary input strings, assemble arbitrary sets of
39 : * names values into string lists, unescape and escape text even if provided
40 : * by a potentially hostile source.
41 : *
42 : * CPLSPrintf() and CSLAppendPrintf() may not be safely invoked on
43 : * arbitrary length inputs since it has a fixed size output buffer on system
44 : * without vsnprintf().
45 : *
46 : **********************************************************************/
47 :
48 : #include "cpl_string.h"
49 : #include "cpl_vsi.h"
50 : #include "cpl_multiproc.h"
51 :
52 : #if defined(WIN32CE)
53 : # include <wce_errno.h>
54 : # include <wce_string.h>
55 : #endif
56 :
57 : CPL_CVSID("$Id: cpl_string.cpp 23719 2012-01-07 18:18:41Z rouault $");
58 :
59 : /*=====================================================================
60 : StringList manipulation functions.
61 : =====================================================================*/
62 :
63 : /**********************************************************************
64 : * CSLAddString()
65 : *
66 : * Append a string to a StringList and return a pointer to the modified
67 : * StringList.
68 : * If the input StringList is NULL, then a new StringList is created.
69 : * Note that CSLAddString performance when building a list is in O(n^2)
70 : * which can cause noticable slow down when n > 10000.
71 : **********************************************************************/
72 15125151 : char **CSLAddString(char **papszStrList, const char *pszNewString)
73 : {
74 15125151 : int nItems=0;
75 :
76 15125151 : if (pszNewString == NULL)
77 0 : return papszStrList; /* Nothing to do!*/
78 :
79 : /* Allocate room for the new string */
80 15125151 : if (papszStrList == NULL)
81 1350726 : papszStrList = (char**) CPLCalloc(2,sizeof(char*));
82 : else
83 : {
84 13774425 : nItems = CSLCount(papszStrList);
85 : papszStrList = (char**)CPLRealloc(papszStrList,
86 13774425 : (nItems+2)*sizeof(char*));
87 : }
88 :
89 : /* Copy the string in the list */
90 15125151 : papszStrList[nItems] = CPLStrdup(pszNewString);
91 15125151 : papszStrList[nItems+1] = NULL;
92 :
93 15125151 : return papszStrList;
94 : }
95 :
96 : /************************************************************************/
97 : /* CSLCount() */
98 : /************************************************************************/
99 :
100 : /**
101 : * Return number of items in a string list.
102 : *
103 : * Returns the number of items in a string list, not counting the
104 : * terminating NULL. Passing in NULL is safe, and will result in a count
105 : * of zero.
106 : *
107 : * Lists are counted by iterating through them so long lists will
108 : * take more time than short lists. Care should be taken to avoid using
109 : * CSLCount() as an end condition for loops as it will result in O(n^2)
110 : * behavior.
111 : *
112 : * @param papszStrList the string list to count.
113 : *
114 : * @return the number of entries.
115 : */
116 22560358 : int CSLCount(char **papszStrList)
117 : {
118 22560358 : int nItems=0;
119 :
120 22560358 : if (papszStrList)
121 : {
122 300317085 : while(*papszStrList != NULL)
123 : {
124 259987309 : nItems++;
125 259987309 : papszStrList++;
126 : }
127 : }
128 :
129 22560358 : return nItems;
130 : }
131 :
132 :
133 : /************************************************************************/
134 : /* CSLGetField() */
135 : /* */
136 : /* Fetches the indicated field, being careful not to crash if */
137 : /* the field doesn't exist within this string list. The */
138 : /* returned pointer should not be freed, and doesn't */
139 : /* necessarily last long. */
140 : /************************************************************************/
141 :
142 230942 : const char * CSLGetField( char ** papszStrList, int iField )
143 :
144 : {
145 : int i;
146 :
147 230942 : if( papszStrList == NULL || iField < 0 )
148 23428 : return( "" );
149 :
150 1528348 : for( i = 0; i < iField+1; i++ )
151 : {
152 1320836 : if( papszStrList[i] == NULL )
153 2 : return "";
154 : }
155 :
156 207512 : return( papszStrList[iField] );
157 : }
158 :
159 : /************************************************************************/
160 : /* CSLDestroy() */
161 : /************************************************************************/
162 :
163 : /**
164 : * Free string list.
165 : *
166 : * Frees the passed string list (null terminated array of strings).
167 : * It is safe to pass NULL.
168 : *
169 : * @param papszStrList the list to free.
170 : */
171 13744137 : void CPL_STDCALL CSLDestroy(char **papszStrList)
172 : {
173 : char **papszPtr;
174 :
175 13744137 : if (papszStrList)
176 : {
177 9960038 : papszPtr = papszStrList;
178 46995590 : while(*papszPtr != NULL)
179 : {
180 27075514 : CPLFree(*papszPtr);
181 27075514 : papszPtr++;
182 : }
183 :
184 9960038 : CPLFree(papszStrList);
185 : }
186 13744137 : }
187 :
188 : /************************************************************************/
189 : /* CSLDuplicate() */
190 : /************************************************************************/
191 :
192 : /**
193 : * Clone a string list.
194 : *
195 : * Efficiently allocates a copy of a string list. The returned list is
196 : * owned by the caller and should be freed with CSLDestroy().
197 : *
198 : * @param papszStrList the input string list.
199 : *
200 : * @return newly allocated copy.
201 : */
202 :
203 212832 : char **CSLDuplicate(char **papszStrList)
204 : {
205 : char **papszNewList, **papszSrc, **papszDst;
206 : int nLines;
207 :
208 212832 : nLines = CSLCount(papszStrList);
209 :
210 212832 : if (nLines == 0)
211 162680 : return NULL;
212 :
213 50152 : papszNewList = (char **)CPLMalloc((nLines+1)*sizeof(char*));
214 50152 : papszSrc = papszStrList;
215 50152 : papszDst = papszNewList;
216 :
217 1157198 : while(*papszSrc != NULL)
218 : {
219 1056894 : *papszDst = CPLStrdup(*papszSrc);
220 :
221 1056894 : papszSrc++;
222 1056894 : papszDst++;
223 : }
224 50152 : *papszDst = NULL;
225 :
226 50152 : return papszNewList;
227 : }
228 :
229 : /************************************************************************/
230 : /* CSLMerge */
231 : /************************************************************************/
232 :
233 : /**
234 : * \brief Merge two lists.
235 : *
236 : * The two lists are merged, ensuring that if any keys appear in both
237 : * that the value from the second (papszOverride) list take precidence.
238 : *
239 : * @param papszOrig the original list, being modified.
240 : * @param papszOverride the list of items being merged in. This list
241 : * is unaltered and remains owned by the caller.
242 : *
243 : * @return updated list.
244 : */
245 :
246 1198 : char **CSLMerge( char **papszOrig, char **papszOverride )
247 :
248 : {
249 : int i;
250 :
251 1198 : if( papszOrig == NULL && papszOverride != NULL )
252 106 : return CSLDuplicate( papszOverride );
253 :
254 1092 : if( papszOverride == NULL )
255 764 : return papszOrig;
256 :
257 984 : for( i = 0; papszOverride[i] != NULL; i++ )
258 : {
259 656 : char *pszKey = NULL;
260 656 : const char *pszValue = CPLParseNameValue( papszOverride[i], &pszKey );
261 :
262 656 : papszOrig = CSLSetNameValue( papszOrig, pszKey, pszValue );
263 656 : CPLFree( pszKey );
264 : }
265 :
266 328 : return papszOrig;
267 : }
268 :
269 : /************************************************************************/
270 : /* CSLLoad2() */
271 : /************************************************************************/
272 :
273 : /**
274 : * Load a text file into a string list.
275 : *
276 : * The VSI*L API is used, so VSIFOpenL() supported objects that aren't
277 : * physical files can also be accessed. Files are returned as a string list,
278 : * with one item in the string list per line. End of line markers are
279 : * stripped (by CPLReadLineL()).
280 : *
281 : * If reading the file fails a CPLError() will be issued and NULL returned.
282 : *
283 : * @param pszFname the name of the file to read.
284 : * @param nMaxLines maximum number of lines to read before stopping, or -1 for no limit.
285 : * @param nMaxCols maximum number of characters in a line before stopping, or -1 for no limit.
286 : * @param papszOptions NULL-terminated array of options. Unused for now.
287 : *
288 : * @return a string list with the files lines, now owned by caller. To be freed with CSLDestroy()
289 : *
290 : * @since GDAL 1.7.0
291 : */
292 :
293 3588 : char **CSLLoad2(const char *pszFname, int nMaxLines, int nMaxCols, char** papszOptions)
294 : {
295 : VSILFILE *fp;
296 : const char *pszLine;
297 3588 : char **papszStrList=NULL;
298 3588 : int nLines = 0;
299 3588 : int nAllocatedLines = 0;
300 :
301 3588 : fp = VSIFOpenL(pszFname, "rb");
302 :
303 3588 : if (fp)
304 : {
305 890 : CPLErrorReset();
306 890 : while(!VSIFEofL(fp) && (nMaxLines == -1 || nLines < nMaxLines))
307 : {
308 7374 : if ( (pszLine = CPLReadLine2L(fp, nMaxCols, papszOptions)) != NULL )
309 : {
310 7374 : if (nLines + 1 >= nAllocatedLines)
311 : {
312 : char** papszStrListNew;
313 1004 : nAllocatedLines = 16 + nAllocatedLines * 2;
314 : papszStrListNew = (char**) VSIRealloc(papszStrList,
315 1004 : nAllocatedLines * sizeof(char*));
316 1004 : if (papszStrListNew == NULL)
317 : {
318 0 : VSIFCloseL(fp);
319 0 : CPLReadLineL( NULL );
320 : CPLError( CE_Failure, CPLE_OutOfMemory,
321 : "CSLLoad2(\"%s\") failed: not enough memory to allocate lines.",
322 0 : pszFname );
323 0 : return papszStrList;
324 : }
325 1004 : papszStrList = papszStrListNew;
326 : }
327 7374 : papszStrList[nLines] = CPLStrdup(pszLine);
328 7374 : papszStrList[nLines + 1] = NULL;
329 7374 : nLines ++;
330 : }
331 : else
332 0 : break;
333 : }
334 :
335 890 : VSIFCloseL(fp);
336 :
337 890 : CPLReadLineL( NULL );
338 : }
339 : else
340 : {
341 2698 : if (CSLFetchBoolean(papszOptions, "EMIT_ERROR_IF_CANNOT_OPEN_FILE", TRUE))
342 : {
343 : /* Unable to open file */
344 : CPLError( CE_Failure, CPLE_OpenFailed,
345 : "CSLLoad2(\"%s\") failed: unable to open file.",
346 0 : pszFname );
347 : }
348 : }
349 :
350 3588 : return papszStrList;
351 : }
352 :
353 : /************************************************************************/
354 : /* CSLLoad() */
355 : /************************************************************************/
356 :
357 : /**
358 : * Load a text file into a string list.
359 : *
360 : * The VSI*L API is used, so VSIFOpenL() supported objects that aren't
361 : * physical files can also be accessed. Files are returned as a string list,
362 : * with one item in the string list per line. End of line markers are
363 : * stripped (by CPLReadLineL()).
364 : *
365 : * If reading the file fails a CPLError() will be issued and NULL returned.
366 : *
367 : * @param pszFname the name of the file to read.
368 : *
369 : * @return a string list with the files lines, now owned by caller. To be freed with CSLDestroy()
370 : */
371 :
372 462 : char **CSLLoad(const char *pszFname)
373 : {
374 462 : return CSLLoad2(pszFname, -1, -1, NULL);
375 : }
376 :
377 : /**********************************************************************
378 : * CSLSave()
379 : *
380 : * Write a stringlist to a text file.
381 : *
382 : * Returns the number of lines written, or 0 if the file could not
383 : * be written.
384 : **********************************************************************/
385 92 : int CSLSave(char **papszStrList, const char *pszFname)
386 : {
387 : VSILFILE *fp;
388 92 : int nLines = 0;
389 :
390 92 : if (papszStrList)
391 : {
392 92 : if ((fp = VSIFOpenL(pszFname, "wt")) != NULL)
393 : {
394 830 : while(*papszStrList != NULL)
395 : {
396 646 : if( VSIFPrintfL( fp, "%s\n", *papszStrList ) < 1 )
397 : {
398 : CPLError( CE_Failure, CPLE_FileIO,
399 : "CSLSave(\"%s\") failed: unable to write to output file.",
400 0 : pszFname );
401 0 : break; /* A Problem happened... abort */
402 : }
403 :
404 646 : nLines++;
405 646 : papszStrList++;
406 : }
407 :
408 92 : VSIFCloseL(fp);
409 : }
410 : else
411 : {
412 : /* Unable to open file */
413 : CPLError( CE_Failure, CPLE_OpenFailed,
414 : "CSLSave(\"%s\") failed: unable to open output file.",
415 0 : pszFname );
416 : }
417 : }
418 :
419 92 : return nLines;
420 : }
421 :
422 : /**********************************************************************
423 : * CSLPrint()
424 : *
425 : * Print a StringList to fpOut. If fpOut==NULL, then output is sent
426 : * to stdout.
427 : *
428 : * Returns the number of lines printed.
429 : **********************************************************************/
430 0 : int CSLPrint(char **papszStrList, FILE *fpOut)
431 : {
432 0 : int nLines=0;
433 :
434 0 : if (fpOut == NULL)
435 0 : fpOut = stdout;
436 :
437 0 : if (papszStrList)
438 : {
439 0 : while(*papszStrList != NULL)
440 : {
441 0 : VSIFPrintf(fpOut, "%s\n", *papszStrList);
442 0 : nLines++;
443 0 : papszStrList++;
444 : }
445 : }
446 :
447 0 : return nLines;
448 : }
449 :
450 :
451 : /**********************************************************************
452 : * CSLInsertStrings()
453 : *
454 : * Copies the contents of a StringList inside another StringList
455 : * before the specified line.
456 : *
457 : * nInsertAtLineNo is a 0-based line index before which the new strings
458 : * should be inserted. If this value is -1 or is larger than the actual
459 : * number of strings in the list then the strings are added at the end
460 : * of the source StringList.
461 : *
462 : * Returns the modified StringList.
463 : **********************************************************************/
464 2374 : char **CSLInsertStrings(char **papszStrList, int nInsertAtLineNo,
465 : char **papszNewLines)
466 : {
467 : int i, nSrcLines, nDstLines, nToInsert;
468 : char **ppszSrc, **ppszDst;
469 :
470 2374 : if (papszNewLines == NULL ||
471 : ( nToInsert = CSLCount(papszNewLines) ) == 0)
472 4 : return papszStrList; /* Nothing to do!*/
473 :
474 2370 : nSrcLines = CSLCount(papszStrList);
475 2370 : nDstLines = nSrcLines + nToInsert;
476 :
477 : /* Allocate room for the new strings */
478 : papszStrList = (char**)CPLRealloc(papszStrList,
479 2370 : (nDstLines+1)*sizeof(char*));
480 :
481 : /* Make sure the array is NULL-terminated... it may not be if
482 : * papszStrList was NULL before Realloc()
483 : */
484 2370 : papszStrList[nSrcLines] = NULL;
485 :
486 : /* Make some room in the original list at the specified location
487 : * Note that we also have to move the NULL pointer at the end of
488 : * the source StringList.
489 : */
490 2370 : if (nInsertAtLineNo == -1 || nInsertAtLineNo > nSrcLines)
491 1164 : nInsertAtLineNo = nSrcLines;
492 :
493 2370 : ppszSrc = papszStrList + nSrcLines;
494 2370 : ppszDst = papszStrList + nDstLines;
495 :
496 6752 : for (i=nSrcLines; i>=nInsertAtLineNo; i--)
497 : {
498 4382 : *ppszDst = *ppszSrc;
499 4382 : ppszDst--;
500 4382 : ppszSrc--;
501 : }
502 :
503 : /* Copy the strings to the list */
504 2370 : ppszSrc = papszNewLines;
505 2370 : ppszDst = papszStrList + nInsertAtLineNo;
506 :
507 38866 : for (; *ppszSrc != NULL; ppszSrc++, ppszDst++)
508 : {
509 36496 : *ppszDst = CPLStrdup(*ppszSrc);
510 : }
511 :
512 2370 : return papszStrList;
513 : }
514 :
515 : /**********************************************************************
516 : * CSLInsertString()
517 : *
518 : * Insert a string at a given line number inside a StringList
519 : *
520 : * nInsertAtLineNo is a 0-based line index before which the new string
521 : * should be inserted. If this value is -1 or is larger than the actual
522 : * number of strings in the list then the string is added at the end
523 : * of the source StringList.
524 : *
525 : * Returns the modified StringList.
526 : **********************************************************************/
527 78 : char **CSLInsertString(char **papszStrList, int nInsertAtLineNo,
528 : const char *pszNewLine)
529 : {
530 : char *apszList[2];
531 :
532 : /* Create a temporary StringList and call CSLInsertStrings()
533 : */
534 78 : apszList[0] = (char *) pszNewLine;
535 78 : apszList[1] = NULL;
536 :
537 78 : return CSLInsertStrings(papszStrList, nInsertAtLineNo, apszList);
538 : }
539 :
540 :
541 : /**********************************************************************
542 : * CSLRemoveStrings()
543 : *
544 : * Remove strings inside a StringList
545 : *
546 : * nFirstLineToDelete is the 0-based line index of the first line to
547 : * remove. If this value is -1 or is larger than the actual
548 : * number of strings in list then the nNumToRemove last strings are
549 : * removed.
550 : *
551 : * If ppapszRetStrings != NULL then the deleted strings won't be
552 : * free'd, they will be stored in a new StringList and the pointer to
553 : * this new list will be returned in *ppapszRetStrings.
554 : *
555 : * Returns the modified StringList.
556 : **********************************************************************/
557 134 : char **CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete,
558 : int nNumToRemove, char ***ppapszRetStrings)
559 : {
560 : int i, nSrcLines, nDstLines;
561 : char **ppszSrc, **ppszDst;
562 :
563 134 : nSrcLines = CSLCount(papszStrList);
564 134 : nDstLines = nSrcLines - nNumToRemove;
565 :
566 134 : if (nNumToRemove < 1 || nSrcLines == 0)
567 0 : return papszStrList; /* Nothing to do!*/
568 :
569 : /* If operation will result in an empty StringList then don't waste
570 : * time here!
571 : */
572 134 : if (nDstLines < 1)
573 : {
574 38 : CSLDestroy(papszStrList);
575 38 : return NULL;
576 : }
577 :
578 :
579 : /* Remove lines from the source StringList...
580 : * Either free() each line or store them to a new StringList depending on
581 : * the caller's choice.
582 : */
583 96 : ppszDst = papszStrList + nFirstLineToDelete;
584 :
585 96 : if (ppapszRetStrings == NULL)
586 : {
587 : /* free() all the strings that will be removed.
588 : */
589 192 : for (i=0; i < nNumToRemove; i++)
590 : {
591 96 : CPLFree(*ppszDst);
592 96 : *ppszDst = NULL;
593 : }
594 : }
595 : else
596 : {
597 : /* Store the strings to remove in a new StringList
598 : */
599 0 : *ppapszRetStrings = (char **)CPLCalloc(nNumToRemove+1, sizeof(char*));
600 :
601 0 : for (i=0; i < nNumToRemove; i++)
602 : {
603 0 : (*ppapszRetStrings)[i] = *ppszDst;
604 0 : *ppszDst = NULL;
605 0 : ppszDst++;
606 : }
607 : }
608 :
609 :
610 : /* Shift down all the lines that follow the lines to remove.
611 : */
612 96 : if (nFirstLineToDelete == -1 || nFirstLineToDelete > nSrcLines)
613 0 : nFirstLineToDelete = nDstLines;
614 :
615 96 : ppszSrc = papszStrList + nFirstLineToDelete + nNumToRemove;
616 96 : ppszDst = papszStrList + nFirstLineToDelete;
617 :
618 422 : for ( ; *ppszSrc != NULL; ppszSrc++, ppszDst++)
619 : {
620 326 : *ppszDst = *ppszSrc;
621 : }
622 : /* Move the NULL pointer at the end of the StringList */
623 96 : *ppszDst = *ppszSrc;
624 :
625 : /* At this point, we could realloc() papszStrList to a smaller size, but
626 : * since this array will likely grow again in further operations on the
627 : * StringList we'll leave it as it is.
628 : */
629 :
630 96 : return papszStrList;
631 : }
632 :
633 : /************************************************************************/
634 : /* CSLFindString() */
635 : /************************************************************************/
636 :
637 : /**
638 : * Find a string within a string list.
639 : *
640 : * Returns the index of the entry in the string list that contains the
641 : * target string. The string in the string list must be a full match for
642 : * the target, but the search is case insensitive.
643 : *
644 : * @param papszList the string list to be searched.
645 : * @param pszTarget the string to be searched for.
646 : *
647 : * @return the index of the string within the list or -1 on failure.
648 : */
649 :
650 3557262 : int CSLFindString( char ** papszList, const char * pszTarget )
651 :
652 : {
653 : int i;
654 :
655 3557262 : if( papszList == NULL )
656 406156 : return -1;
657 :
658 9942837 : for( i = 0; papszList[i] != NULL; i++ )
659 : {
660 8845881 : if( EQUAL(papszList[i],pszTarget) )
661 2054150 : return i;
662 : }
663 :
664 1096956 : return -1;
665 : }
666 :
667 : /************************************************************************/
668 : /* CSLPartialFindString() */
669 : /************************************************************************/
670 :
671 : /**
672 : * Find a substring within a string list.
673 : *
674 : * Returns the index of the entry in the string list that contains the
675 : * target string as a substring. The search is case sensitive (unlike
676 : * CSLFindString()).
677 : *
678 : * @param papszHaystack the string list to be searched.
679 : * @param pszNeedle the substring to be searched for.
680 : *
681 : * @return the index of the string within the list or -1 on failure.
682 : */
683 :
684 6 : int CSLPartialFindString( char **papszHaystack, const char * pszNeedle )
685 : {
686 : int i;
687 6 : if (papszHaystack == NULL || pszNeedle == NULL)
688 0 : return -1;
689 :
690 22 : for (i = 0; papszHaystack[i] != NULL; i++)
691 : {
692 16 : if (strstr(papszHaystack[i],pszNeedle))
693 0 : return i;
694 : }
695 :
696 6 : return -1;
697 : }
698 :
699 :
700 : /**********************************************************************
701 : * CSLTokenizeString()
702 : *
703 : * Tokenizes a string and returns a StringList with one string for
704 : * each token.
705 : **********************************************************************/
706 10076 : char **CSLTokenizeString( const char *pszString )
707 : {
708 10076 : return CSLTokenizeString2( pszString, " ", CSLT_HONOURSTRINGS );
709 : }
710 :
711 : /************************************************************************/
712 : /* CSLTokenizeStringComplex() */
713 : /* */
714 : /* Obsolete tokenizing api. */
715 : /************************************************************************/
716 :
717 2883632 : char ** CSLTokenizeStringComplex( const char * pszString,
718 : const char * pszDelimiters,
719 : int bHonourStrings, int bAllowEmptyTokens )
720 :
721 : {
722 2883632 : int nFlags = 0;
723 :
724 2883632 : if( bHonourStrings )
725 2813780 : nFlags |= CSLT_HONOURSTRINGS;
726 2883632 : if( bAllowEmptyTokens )
727 992 : nFlags |= CSLT_ALLOWEMPTYTOKENS;
728 :
729 2883632 : return CSLTokenizeString2( pszString, pszDelimiters, nFlags );
730 : }
731 :
732 : /************************************************************************/
733 : /* CSLTokenizeString2() */
734 : /************************************************************************/
735 :
736 : /**
737 : * Tokenize a string.
738 : *
739 : * This function will split a string into tokens based on specified'
740 : * delimeter(s) with a variety of options. The returned result is a
741 : * string list that should be freed with CSLDestroy() when no longer
742 : * needed.
743 : *
744 : * The available parsing options are:
745 : *
746 : * - CSLT_ALLOWEMPTYTOKENS: allow the return of empty tokens when two
747 : * delimiters in a row occur with no other text between them. If not set,
748 : * empty tokens will be discarded;
749 : * - CSLT_STRIPLEADSPACES: strip leading space characters from the token (as
750 : * reported by isspace());
751 : * - CSLT_STRIPENDSPACES: strip ending space characters from the token (as
752 : * reported by isspace());
753 : * - CSLT_HONOURSTRINGS: double quotes can be used to hold values that should
754 : * not be broken into multiple tokens;
755 : * - CSLT_PRESERVEQUOTES: string quotes are carried into the tokens when this
756 : * is set, otherwise they are removed;
757 : * - CSLT_PRESERVEESCAPES: if set backslash escapes (for backslash itself,
758 : * and for literal double quotes) will be preserved in the tokens, otherwise
759 : * the backslashes will be removed in processing.
760 : *
761 : * \b Example:
762 : *
763 : * Parse a string into tokens based on various white space (space, newline,
764 : * tab) and then print out results and cleanup. Quotes may be used to hold
765 : * white space in tokens.
766 :
767 : \code
768 : char **papszTokens;
769 : int i;
770 :
771 : papszTokens =
772 : CSLTokenizeString2( pszCommand, " \t\n",
773 : CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS );
774 :
775 : for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++ )
776 : printf( "arg %d: '%s'", papszTokens[i] );
777 : CSLDestroy( papszTokens );
778 : \endcode
779 :
780 : * @param pszString the string to be split into tokens.
781 : * @param pszDelimiters one or more characters to be used as token delimeters.
782 : * @param nCSLTFlags an ORing of one or more of the CSLT_ flag values.
783 : *
784 : * @return a string list of tokens owned by the caller.
785 : */
786 :
787 2938914 : char ** CSLTokenizeString2( const char * pszString,
788 : const char * pszDelimiters,
789 : int nCSLTFlags )
790 :
791 : {
792 2938914 : if( pszString == NULL )
793 0 : return (char **) CPLCalloc(sizeof(char *),1);
794 2938914 : CPLStringList oRetList;
795 : char *pszToken;
796 : int nTokenMax, nTokenLen;
797 2938914 : int bHonourStrings = (nCSLTFlags & CSLT_HONOURSTRINGS);
798 2938914 : int bAllowEmptyTokens = (nCSLTFlags & CSLT_ALLOWEMPTYTOKENS);
799 2938914 : int bStripLeadSpaces = (nCSLTFlags & CSLT_STRIPLEADSPACES);
800 2938914 : int bStripEndSpaces = (nCSLTFlags & CSLT_STRIPENDSPACES);
801 :
802 2938914 : pszToken = (char *) CPLCalloc(10,1);
803 2938914 : nTokenMax = 10;
804 :
805 9444540 : while( pszString != NULL && *pszString != '\0' )
806 : {
807 3566712 : int bInString = FALSE;
808 3566712 : int bStartString = TRUE;
809 :
810 3566712 : nTokenLen = 0;
811 :
812 : /* Try to find the next delimeter, marking end of token */
813 25992732 : for( ; *pszString != '\0'; pszString++ )
814 : {
815 :
816 : /* End if this is a delimeter skip it and break. */
817 23082299 : if( !bInString && strchr(pszDelimiters, *pszString) != NULL )
818 : {
819 656279 : pszString++;
820 656279 : break;
821 : }
822 :
823 : /* If this is a quote, and we are honouring constant
824 : strings, then process the constant strings, with out delim
825 : but don't copy over the quotes */
826 22426020 : if( bHonourStrings && *pszString == '"' )
827 : {
828 3668 : if( nCSLTFlags & CSLT_PRESERVEQUOTES )
829 : {
830 404 : pszToken[nTokenLen] = *pszString;
831 404 : nTokenLen++;
832 : }
833 :
834 3668 : if( bInString )
835 : {
836 1784 : bInString = FALSE;
837 1784 : continue;
838 : }
839 : else
840 : {
841 1884 : bInString = TRUE;
842 1884 : continue;
843 : }
844 : }
845 :
846 : /*
847 : * Within string constants we allow for escaped quotes, but in
848 : * processing them we will unescape the quotes and \\ sequence
849 : * reduces to \
850 : */
851 22422352 : if( bInString && pszString[0] == '\\' )
852 : {
853 0 : if ( pszString[1] == '"' || pszString[1] == '\\' )
854 : {
855 0 : if( nCSLTFlags & CSLT_PRESERVEESCAPES )
856 : {
857 0 : pszToken[nTokenLen] = *pszString;
858 0 : nTokenLen++;
859 : }
860 :
861 0 : pszString++;
862 : }
863 : }
864 :
865 : /*
866 : * Strip spaces at the token start if requested.
867 : */
868 22422352 : if ( !bInString && bStripLeadSpaces
869 : && bStartString && isspace((unsigned char)*pszString) )
870 3578 : continue;
871 :
872 22418774 : bStartString = FALSE;
873 :
874 : /*
875 : * Extend token buffer if we are running close to its end.
876 : */
877 22418774 : if( nTokenLen >= nTokenMax-3 )
878 : {
879 633578 : nTokenMax = nTokenMax * 2 + 10;
880 633578 : pszToken = (char *) CPLRealloc( pszToken, nTokenMax );
881 : }
882 :
883 22418774 : pszToken[nTokenLen] = *pszString;
884 22418774 : nTokenLen++;
885 : }
886 :
887 : /*
888 : * Strip spaces at the token end if requested.
889 : */
890 3566712 : if ( !bInString && bStripEndSpaces )
891 : {
892 13296 : while ( nTokenLen && isspace((unsigned char)pszToken[nTokenLen - 1]) )
893 0 : nTokenLen--;
894 : }
895 :
896 3566712 : pszToken[nTokenLen] = '\0';
897 :
898 : /*
899 : * Add the token.
900 : */
901 3566712 : if( pszToken[0] != '\0' || bAllowEmptyTokens )
902 3499858 : oRetList.AddString( pszToken );
903 : }
904 :
905 : /*
906 : * If the last token was empty, then we need to capture
907 : * it now, as the loop would skip it.
908 : */
909 2938914 : if( *pszString == '\0' && bAllowEmptyTokens && oRetList.Count() > 0
910 : && strchr(pszDelimiters,*(pszString-1)) != NULL )
911 : {
912 34 : oRetList.AddString( "" );
913 : }
914 :
915 2938914 : CPLFree( pszToken );
916 :
917 2938914 : if( oRetList.List() == NULL )
918 : {
919 : // we prefer to return empty lists as a pointer to
920 : // a null pointer since some client code might depend on this.
921 23687 : oRetList.Assign( (char**) CPLCalloc(sizeof(char**),1) );
922 : }
923 :
924 2938914 : return oRetList.StealList();
925 : }
926 :
927 : /**********************************************************************
928 : * CPLSPrintf()
929 : *
930 : * My own version of CPLSPrintf() that works with 10 static buffer.
931 : *
932 : * It returns a ref. to a static buffer that should not be freed and
933 : * is valid only until the next call to CPLSPrintf().
934 : *
935 : * NOTE: This function should move to cpl_conv.cpp.
936 : **********************************************************************/
937 : /* For now, assume that a 8000 chars buffer will be enough.
938 : */
939 : #define CPLSPrintf_BUF_SIZE 8000
940 : #define CPLSPrintf_BUF_Count 10
941 :
942 45407186 : const char *CPLSPrintf(const char *fmt, ...)
943 : {
944 : va_list args;
945 :
946 : /* -------------------------------------------------------------------- */
947 : /* Get the thread local buffer ring data. */
948 : /* -------------------------------------------------------------------- */
949 45407186 : char *pachBufRingInfo = (char *) CPLGetTLS( CTLS_CPLSPRINTF );
950 :
951 45407186 : if( pachBufRingInfo == NULL )
952 : {
953 : pachBufRingInfo = (char *)
954 177 : CPLCalloc(1,sizeof(int)+CPLSPrintf_BUF_Count*CPLSPrintf_BUF_SIZE);
955 177 : CPLSetTLS( CTLS_CPLSPRINTF, pachBufRingInfo, TRUE );
956 : }
957 :
958 : /* -------------------------------------------------------------------- */
959 : /* Work out which string in the "ring" we want to use this */
960 : /* time. */
961 : /* -------------------------------------------------------------------- */
962 45407186 : int *pnBufIndex = (int *) pachBufRingInfo;
963 45407186 : int nOffset = sizeof(int) + *pnBufIndex * CPLSPrintf_BUF_SIZE;
964 45407186 : char *pachBuffer = pachBufRingInfo + nOffset;
965 :
966 45407186 : *pnBufIndex = (*pnBufIndex + 1) % CPLSPrintf_BUF_Count;
967 :
968 : /* -------------------------------------------------------------------- */
969 : /* Format the result. */
970 : /* -------------------------------------------------------------------- */
971 :
972 45407186 : va_start(args, fmt);
973 : #if defined(HAVE_VSNPRINTF)
974 45407186 : vsnprintf(pachBuffer, CPLSPrintf_BUF_SIZE-1, fmt, args);
975 : #else
976 : vsprintf(pachBuffer, fmt, args);
977 : #endif
978 45407186 : va_end(args);
979 :
980 45407186 : return pachBuffer;
981 : }
982 :
983 : /**********************************************************************
984 : * CSLAppendPrintf()
985 : *
986 : * Use CPLSPrintf() to append a new line at the end of a StringList.
987 : *
988 : * Returns the modified StringList.
989 : **********************************************************************/
990 0 : char **CSLAppendPrintf(char **papszStrList, const char *fmt, ...)
991 : {
992 0 : CPLString osWork;
993 : va_list args;
994 :
995 0 : va_start( args, fmt );
996 0 : osWork.vPrintf( fmt, args );
997 0 : va_end( args );
998 :
999 0 : return CSLAddString(papszStrList, osWork);
1000 : }
1001 :
1002 : /************************************************************************/
1003 : /* CPLVASPrintf() */
1004 : /* */
1005 : /* This is intended to serve as an easy to use C callabable */
1006 : /* vasprintf() alternative. Used in the geojson library for */
1007 : /* instance. */
1008 : /************************************************************************/
1009 :
1010 4048 : int CPLVASPrintf( char **buf, const char *fmt, va_list ap )
1011 :
1012 : {
1013 4048 : CPLString osWork;
1014 :
1015 4048 : osWork.vPrintf( fmt, ap );
1016 :
1017 4048 : if( buf )
1018 4048 : *buf = CPLStrdup(osWork.c_str());
1019 :
1020 4048 : return strlen(osWork);
1021 : }
1022 :
1023 : /************************************************************************/
1024 : /* CSLTestBoolean() */
1025 : /************************************************************************/
1026 :
1027 : /**
1028 : * Test what boolean value contained in the string.
1029 : *
1030 : * If pszValue is "NO", "FALSE", "OFF" or "0" will be returned FALSE.
1031 : * Otherwise, TRUE will be returned.
1032 : *
1033 : * @param pszValue the string should be tested.
1034 : *
1035 : * @return TRUE or FALSE.
1036 : */
1037 :
1038 1616380 : int CSLTestBoolean( const char *pszValue )
1039 : {
1040 1616380 : if( EQUAL(pszValue,"NO")
1041 : || EQUAL(pszValue,"FALSE")
1042 : || EQUAL(pszValue,"OFF")
1043 : || EQUAL(pszValue,"0") )
1044 1556022 : return FALSE;
1045 : else
1046 60358 : return TRUE;
1047 : }
1048 :
1049 : /**********************************************************************
1050 : * CSLFetchBoolean()
1051 : *
1052 : * Check for boolean key value.
1053 : *
1054 : * In a StringList of "Name=Value" pairs, look to see if there is a key
1055 : * with the given name, and if it can be interpreted as being TRUE. If
1056 : * the key appears without any "=Value" portion it will be considered true.
1057 : * If the value is NO, FALSE or 0 it will be considered FALSE otherwise
1058 : * if the key appears in the list it will be considered TRUE. If the key
1059 : * doesn't appear at all, the indicated default value will be returned.
1060 : *
1061 : * @param papszStrList the string list to search.
1062 : * @param pszKey the key value to look for (case insensitive).
1063 : * @param bDefault the value to return if the key isn't found at all.
1064 : *
1065 : * @return TRUE or FALSE
1066 : **********************************************************************/
1067 :
1068 41150 : int CSLFetchBoolean( char **papszStrList, const char *pszKey, int bDefault )
1069 :
1070 : {
1071 : const char *pszValue;
1072 :
1073 41150 : if( CSLFindString( papszStrList, pszKey ) != -1 )
1074 0 : return TRUE;
1075 :
1076 41150 : pszValue = CSLFetchNameValue(papszStrList, pszKey );
1077 41150 : if( pszValue == NULL )
1078 37878 : return bDefault;
1079 : else
1080 3272 : return CSLTestBoolean( pszValue );
1081 : }
1082 :
1083 : /************************************************************************/
1084 : /* CSLFetchNameValueDefaulted() */
1085 : /************************************************************************/
1086 :
1087 2206 : const char *CSLFetchNameValueDef( char **papszStrList,
1088 : const char *pszName,
1089 : const char *pszDefault )
1090 :
1091 : {
1092 2206 : const char *pszResult = CSLFetchNameValue( papszStrList, pszName );
1093 2206 : if( pszResult )
1094 226 : return pszResult;
1095 : else
1096 1980 : return pszDefault;
1097 : }
1098 :
1099 : /**********************************************************************
1100 : * CSLFetchNameValue()
1101 : *
1102 : * In a StringList of "Name=Value" pairs, look for the
1103 : * first value associated with the specified name. The search is not
1104 : * case sensitive.
1105 : * ("Name:Value" pairs are also supported for backward compatibility
1106 : * with older stuff.)
1107 : *
1108 : * Returns a reference to the value in the StringList that the caller
1109 : * should not attempt to free.
1110 : *
1111 : * Returns NULL if the name is not found.
1112 : **********************************************************************/
1113 3965593 : const char *CSLFetchNameValue(char **papszStrList, const char *pszName)
1114 : {
1115 : size_t nLen;
1116 :
1117 3965593 : if (papszStrList == NULL || pszName == NULL)
1118 225228 : return NULL;
1119 :
1120 3740365 : nLen = strlen(pszName);
1121 28572989 : while(*papszStrList != NULL)
1122 : {
1123 23860011 : if (EQUALN(*papszStrList, pszName, nLen)
1124 1383244 : && ( (*papszStrList)[nLen] == '=' ||
1125 1756 : (*papszStrList)[nLen] == ':' ) )
1126 : {
1127 1382752 : return (*papszStrList)+nLen+1;
1128 : }
1129 21092259 : papszStrList++;
1130 : }
1131 2357613 : return NULL;
1132 : }
1133 :
1134 : /************************************************************************/
1135 : /* CSLFindName() */
1136 : /************************************************************************/
1137 :
1138 : /**
1139 : * Find StringList entry with given key name.
1140 : *
1141 : * @param papszStrList the string list to search.
1142 : * @param pszName the key value to look for (case insensitive).
1143 : *
1144 : * @return -1 on failure or the list index of the first occurance
1145 : * matching the given key.
1146 : */
1147 :
1148 218 : int CSLFindName(char **papszStrList, const char *pszName)
1149 : {
1150 : size_t nLen;
1151 218 : int iIndex = 0;
1152 :
1153 218 : if (papszStrList == NULL || pszName == NULL)
1154 84 : return -1;
1155 :
1156 134 : nLen = strlen(pszName);
1157 426 : while(*papszStrList != NULL)
1158 : {
1159 214 : if (EQUALN(*papszStrList, pszName, nLen)
1160 28 : && ( (*papszStrList)[nLen] == '=' ||
1161 0 : (*papszStrList)[nLen] == ':' ) )
1162 : {
1163 28 : return iIndex;
1164 : }
1165 158 : iIndex++;
1166 158 : papszStrList++;
1167 : }
1168 106 : return -1;
1169 : }
1170 :
1171 : /**********************************************************************
1172 : * CPLParseNameValue()
1173 : **********************************************************************/
1174 :
1175 : /**
1176 : * Parse NAME=VALUE string into name and value components.
1177 : *
1178 : * Note that if ppszKey is non-NULL, the key (or name) portion will be
1179 : * allocated using VSIMalloc(), and returned in that pointer. It is the
1180 : * applications responsibility to free this string, but the application should
1181 : * not modify or free the returned value portion.
1182 : *
1183 : * This function also support "NAME:VALUE" strings and will strip white
1184 : * space from around the delimeter when forming name and value strings.
1185 : *
1186 : * Eventually CSLFetchNameValue() and friends may be modified to use
1187 : * CPLParseNameValue().
1188 : *
1189 : * @param pszNameValue string in "NAME=VALUE" format.
1190 : * @param ppszKey optional pointer though which to return the name
1191 : * portion.
1192 : * @return the value portion (pointing into original string).
1193 : */
1194 :
1195 21660 : const char *CPLParseNameValue(const char *pszNameValue, char **ppszKey )
1196 :
1197 : {
1198 : int i;
1199 : const char *pszValue;
1200 :
1201 283312 : for( i = 0; pszNameValue[i] != '\0'; i++ )
1202 : {
1203 282646 : if( pszNameValue[i] == '=' || pszNameValue[i] == ':' )
1204 : {
1205 20994 : pszValue = pszNameValue + i + 1;
1206 46236 : while( *pszValue == ' ' || *pszValue == '\t' )
1207 4248 : pszValue++;
1208 :
1209 20994 : if( ppszKey != NULL )
1210 : {
1211 20964 : *ppszKey = (char *) CPLMalloc(i+1);
1212 20964 : strncpy( *ppszKey, pszNameValue, i );
1213 20964 : (*ppszKey)[i] = '\0';
1214 83856 : while( i > 0 &&
1215 41928 : ( (*ppszKey)[i] == ' ' || (*ppszKey)[i] == '\t') )
1216 : {
1217 0 : (*ppszKey)[i] = '\0';
1218 0 : i--;
1219 : }
1220 : }
1221 :
1222 20994 : return pszValue;
1223 : }
1224 : }
1225 :
1226 666 : return NULL;
1227 : }
1228 :
1229 : /**********************************************************************
1230 : * CSLFetchNameValueMultiple()
1231 : *
1232 : * In a StringList of "Name=Value" pairs, look for all the
1233 : * values with the specified name. The search is not case
1234 : * sensitive.
1235 : * ("Name:Value" pairs are also supported for backward compatibility
1236 : * with older stuff.)
1237 : *
1238 : * Returns stringlist with one entry for each occurence of the
1239 : * specified name. The stringlist should eventually be destroyed
1240 : * by calling CSLDestroy().
1241 : *
1242 : * Returns NULL if the name is not found.
1243 : **********************************************************************/
1244 860 : char **CSLFetchNameValueMultiple(char **papszStrList, const char *pszName)
1245 : {
1246 : size_t nLen;
1247 860 : char **papszValues = NULL;
1248 :
1249 860 : if (papszStrList == NULL || pszName == NULL)
1250 616 : return NULL;
1251 :
1252 244 : nLen = strlen(pszName);
1253 948 : while(*papszStrList != NULL)
1254 : {
1255 504 : if (EQUALN(*papszStrList, pszName, nLen)
1256 44 : && ( (*papszStrList)[nLen] == '=' ||
1257 0 : (*papszStrList)[nLen] == ':' ) )
1258 : {
1259 : papszValues = CSLAddString(papszValues,
1260 44 : (*papszStrList)+nLen+1);
1261 : }
1262 460 : papszStrList++;
1263 : }
1264 :
1265 244 : return papszValues;
1266 : }
1267 :
1268 :
1269 : /**********************************************************************
1270 : * CSLAddNameValue()
1271 : *
1272 : * Add a new entry to a StringList of "Name=Value" pairs,
1273 : * ("Name:Value" pairs are also supported for backward compatibility
1274 : * with older stuff.)
1275 : *
1276 : * This function does not check if a "Name=Value" pair already exists
1277 : * for that name and can generate multiple entryes for the same name.
1278 : * Use CSLSetNameValue() if you want each name to have only one value.
1279 : *
1280 : * Returns the modified stringlist.
1281 : **********************************************************************/
1282 344034 : char **CSLAddNameValue(char **papszStrList,
1283 : const char *pszName, const char *pszValue)
1284 : {
1285 : char *pszLine;
1286 :
1287 344034 : if (pszName == NULL || pszValue==NULL)
1288 0 : return papszStrList;
1289 :
1290 344034 : pszLine = (char *) CPLMalloc(strlen(pszName)+strlen(pszValue)+2);
1291 344034 : sprintf( pszLine, "%s=%s", pszName, pszValue );
1292 344034 : papszStrList = CSLAddString(papszStrList, pszLine);
1293 344034 : CPLFree( pszLine );
1294 :
1295 344034 : return papszStrList;
1296 : }
1297 :
1298 : /************************************************************************/
1299 : /* CSLSetNameValue() */
1300 : /************************************************************************/
1301 :
1302 : /**
1303 : * Assign value to name in StringList.
1304 : *
1305 : * Set the value for a given name in a StringList of "Name=Value" pairs
1306 : * ("Name:Value" pairs are also supported for backward compatibility
1307 : * with older stuff.)
1308 : *
1309 : * If there is already a value for that name in the list then the value
1310 : * is changed, otherwise a new "Name=Value" pair is added.
1311 : *
1312 : * @param papszList the original list, the modified version is returned.
1313 : * @param pszName the name to be assigned a value. This should be a well
1314 : * formed token (no spaces or very special characters).
1315 : * @param pszValue the value to assign to the name. This should not contain
1316 : * any newlines (CR or LF) but is otherwise pretty much unconstrained. If
1317 : * NULL any corresponding value will be removed.
1318 : *
1319 : * @return modified stringlist.
1320 : */
1321 :
1322 332442 : char **CSLSetNameValue(char **papszList,
1323 : const char *pszName, const char *pszValue)
1324 : {
1325 : char **papszPtr;
1326 : size_t nLen;
1327 :
1328 332442 : if (pszName == NULL )
1329 636 : return papszList;
1330 :
1331 331806 : nLen = strlen(pszName);
1332 331806 : papszPtr = papszList;
1333 13243714 : while(papszPtr && *papszPtr != NULL)
1334 : {
1335 12589518 : if (EQUALN(*papszPtr, pszName, nLen)
1336 4542 : && ( (*papszPtr)[nLen] == '=' ||
1337 2950 : (*papszPtr)[nLen] == ':' ) )
1338 : {
1339 : /* Found it!
1340 : * Change the value... make sure to keep the ':' or '='
1341 : */
1342 : char cSep;
1343 1924 : cSep = (*papszPtr)[nLen];
1344 :
1345 1924 : CPLFree(*papszPtr);
1346 :
1347 : /*
1348 : * If the value is NULL, remove this entry completely/
1349 : */
1350 1924 : if( pszValue == NULL )
1351 : {
1352 492 : while( papszPtr[1] != NULL )
1353 : {
1354 60 : *papszPtr = papszPtr[1];
1355 60 : papszPtr++;
1356 : }
1357 216 : *papszPtr = NULL;
1358 : }
1359 :
1360 : /*
1361 : * Otherwise replace with new value.
1362 : */
1363 : else
1364 : {
1365 1708 : *papszPtr = (char *) CPLMalloc(strlen(pszName)+strlen(pszValue)+2);
1366 1708 : sprintf( *papszPtr, "%s%c%s", pszName, cSep, pszValue );
1367 : }
1368 1924 : return papszList;
1369 : }
1370 12580102 : papszPtr++;
1371 : }
1372 :
1373 329882 : if( pszValue == NULL )
1374 32 : return papszList;
1375 :
1376 : /* The name does not exist yet... create a new entry
1377 : */
1378 329850 : return CSLAddNameValue(papszList, pszName, pszValue);
1379 : }
1380 :
1381 : /************************************************************************/
1382 : /* CSLSetNameValueSeparator() */
1383 : /************************************************************************/
1384 :
1385 : /**
1386 : * Replace the default separator (":" or "=") with the passed separator
1387 : * in the given name/value list.
1388 : *
1389 : * Note that if a separator other than ":" or "=" is used, the resulting
1390 : * list will not be manipulatable by the CSL name/value functions any more.
1391 : *
1392 : * The CPLParseNameValue() function is used to break the existing lines,
1393 : * and it also strips white space from around the existing delimiter, thus
1394 : * the old separator, and any white space will be replaced by the new
1395 : * separator. For formatting purposes it may be desireable to include some
1396 : * white space in the new separator. eg. ": " or " = ".
1397 : *
1398 : * @param papszList the list to update. Component strings may be freed
1399 : * but the list array will remain at the same location.
1400 : *
1401 : * @param pszSeparator the new separator string to insert.
1402 : *
1403 : */
1404 :
1405 132 : void CSLSetNameValueSeparator( char ** papszList, const char *pszSeparator )
1406 :
1407 : {
1408 132 : int nLines = CSLCount(papszList), iLine;
1409 :
1410 2792 : for( iLine = 0; iLine < nLines; iLine++ )
1411 : {
1412 2660 : char *pszKey = NULL;
1413 : const char *pszValue;
1414 : char *pszNewLine;
1415 :
1416 2660 : pszValue = CPLParseNameValue( papszList[iLine], &pszKey );
1417 2660 : if( pszValue == NULL || pszKey == NULL )
1418 0 : continue;
1419 :
1420 : pszNewLine = (char *) CPLMalloc( strlen(pszValue) + strlen(pszKey)
1421 2660 : + strlen(pszSeparator) + 1 );
1422 2660 : strcpy( pszNewLine, pszKey );
1423 2660 : strcat( pszNewLine, pszSeparator );
1424 2660 : strcat( pszNewLine, pszValue );
1425 2660 : CPLFree( papszList[iLine] );
1426 2660 : papszList[iLine] = pszNewLine;
1427 2660 : CPLFree( pszKey );
1428 : }
1429 132 : }
1430 :
1431 : /************************************************************************/
1432 : /* CPLEscapeString() */
1433 : /************************************************************************/
1434 :
1435 : /**
1436 : * Apply escaping to string to preserve special characters.
1437 : *
1438 : * This function will "escape" a variety of special characters
1439 : * to make the string suitable to embed within a string constant
1440 : * or to write within a text stream but in a form that can be
1441 : * reconstitued to it's original form. The escaping will even preserve
1442 : * zero bytes allowing preservation of raw binary data.
1443 : *
1444 : * CPLES_BackslashQuotable(0): This scheme turns a binary string into
1445 : * a form suitable to be placed within double quotes as a string constant.
1446 : * The backslash, quote, '\\0' and newline characters are all escaped in
1447 : * the usual C style.
1448 : *
1449 : * CPLES_XML(1): This scheme converts the '<', '>', '"' and '&' characters into
1450 : * their XML/HTML equivelent (<, >, " and &) making a string safe
1451 : * to embed as CDATA within an XML element. The '\\0' is not escaped and
1452 : * should not be included in the input.
1453 : *
1454 : * CPLES_URL(2): Everything except alphanumerics and the underscore are
1455 : * converted to a percent followed by a two digit hex encoding of the character
1456 : * (leading zero supplied if needed). This is the mechanism used for encoding
1457 : * values to be passed in URLs.
1458 : *
1459 : * CPLES_SQL(3): All single quotes are replaced with two single quotes.
1460 : * Suitable for use when constructing literal values for SQL commands where
1461 : * the literal will be enclosed in single quotes.
1462 : *
1463 : * CPLES_CSV(4): If the values contains commas, semicolons, tabs, double quotes, or newlines it
1464 : * placed in double quotes, and double quotes in the value are doubled.
1465 : * Suitable for use when constructing field values for .csv files. Note that
1466 : * CPLUnescapeString() currently does not support this format, only
1467 : * CPLEscapeString(). See cpl_csv.cpp for csv parsing support.
1468 : *
1469 : * @param pszInput the string to escape.
1470 : * @param nLength The number of bytes of data to preserve. If this is -1
1471 : * the strlen(pszString) function will be used to compute the length.
1472 : * @param nScheme the encoding scheme to use.
1473 : *
1474 : * @return an escaped, zero terminated string that should be freed with
1475 : * CPLFree() when no longer needed.
1476 : */
1477 :
1478 99498 : char *CPLEscapeString( const char *pszInput, int nLength,
1479 : int nScheme )
1480 :
1481 : {
1482 : char *pszOutput;
1483 : char *pszShortOutput;
1484 :
1485 99498 : if( nLength == -1 )
1486 99400 : nLength = strlen(pszInput);
1487 :
1488 99498 : pszOutput = (char *) CPLMalloc( nLength * 6 + 1 );
1489 :
1490 99498 : if( nScheme == CPLES_BackslashQuotable )
1491 : {
1492 66 : int iOut = 0, iIn;
1493 :
1494 2459332 : for( iIn = 0; iIn < nLength; iIn++ )
1495 : {
1496 2459266 : if( pszInput[iIn] == '\0' )
1497 : {
1498 702836 : pszOutput[iOut++] = '\\';
1499 702836 : pszOutput[iOut++] = '0';
1500 : }
1501 1756430 : else if( pszInput[iIn] == '\n' )
1502 : {
1503 7574 : pszOutput[iOut++] = '\\';
1504 7574 : pszOutput[iOut++] = 'n';
1505 : }
1506 1748856 : else if( pszInput[iIn] == '"' )
1507 : {
1508 4938 : pszOutput[iOut++] = '\\';
1509 4938 : pszOutput[iOut++] = '\"';
1510 : }
1511 1743918 : else if( pszInput[iIn] == '\\' )
1512 : {
1513 5030 : pszOutput[iOut++] = '\\';
1514 5030 : pszOutput[iOut++] = '\\';
1515 : }
1516 : else
1517 1738888 : pszOutput[iOut++] = pszInput[iIn];
1518 : }
1519 66 : pszOutput[iOut] = '\0';
1520 : }
1521 99432 : else if( nScheme == CPLES_URL ) /* Untested at implementation */
1522 : {
1523 446 : int iOut = 0, iIn;
1524 :
1525 12834 : for( iIn = 0; iIn < nLength; iIn++ )
1526 : {
1527 34342 : if( (pszInput[iIn] >= 'a' && pszInput[iIn] <= 'z')
1528 3010 : || (pszInput[iIn] >= 'A' && pszInput[iIn] <= 'Z')
1529 3984 : || (pszInput[iIn] >= '0' && pszInput[iIn] <= '9')
1530 4172 : || pszInput[iIn] == '_' || pszInput[iIn] == '.' )
1531 : {
1532 10788 : pszOutput[iOut++] = pszInput[iIn];
1533 : }
1534 : else
1535 : {
1536 1600 : sprintf( pszOutput+iOut, "%%%02X", ((unsigned char*)pszInput)[iIn] );
1537 1600 : iOut += 3;
1538 : }
1539 : }
1540 446 : pszOutput[iOut] = '\0';
1541 : }
1542 197020 : else if( nScheme == CPLES_XML || nScheme == CPLES_XML_BUT_QUOTES )
1543 : {
1544 98034 : int iOut = 0, iIn;
1545 :
1546 2685658 : for( iIn = 0; iIn < nLength; iIn++ )
1547 : {
1548 2587624 : if( pszInput[iIn] == '<' )
1549 : {
1550 14 : pszOutput[iOut++] = '&';
1551 14 : pszOutput[iOut++] = 'l';
1552 14 : pszOutput[iOut++] = 't';
1553 14 : pszOutput[iOut++] = ';';
1554 : }
1555 2587610 : else if( pszInput[iIn] == '>' )
1556 : {
1557 14 : pszOutput[iOut++] = '&';
1558 14 : pszOutput[iOut++] = 'g';
1559 14 : pszOutput[iOut++] = 't';
1560 14 : pszOutput[iOut++] = ';';
1561 : }
1562 2587596 : else if( pszInput[iIn] == '&' )
1563 : {
1564 242 : pszOutput[iOut++] = '&';
1565 242 : pszOutput[iOut++] = 'a';
1566 242 : pszOutput[iOut++] = 'm';
1567 242 : pszOutput[iOut++] = 'p';
1568 242 : pszOutput[iOut++] = ';';
1569 : }
1570 2587534 : else if( pszInput[iIn] == '"' && nScheme != CPLES_XML_BUT_QUOTES )
1571 : {
1572 180 : pszOutput[iOut++] = '&';
1573 180 : pszOutput[iOut++] = 'q';
1574 180 : pszOutput[iOut++] = 'u';
1575 180 : pszOutput[iOut++] = 'o';
1576 180 : pszOutput[iOut++] = 't';
1577 180 : pszOutput[iOut++] = ';';
1578 : }
1579 2594964 : else if( ((GByte*)pszInput)[iIn] < 0x20
1580 4972 : && pszInput[iIn] != 0x9
1581 2818 : && pszInput[iIn] != 0xA
1582 0 : && pszInput[iIn] != 0xD )
1583 : {
1584 : // These control characters are unrepresentable in XML format,
1585 : // so we just drop them. #4117
1586 : }
1587 : else
1588 2587174 : pszOutput[iOut++] = pszInput[iIn];
1589 : }
1590 98034 : pszOutput[iOut] = '\0';
1591 : }
1592 952 : else if( nScheme == CPLES_SQL )
1593 : {
1594 32 : int iOut = 0, iIn;
1595 :
1596 156 : for( iIn = 0; iIn < nLength; iIn++ )
1597 : {
1598 124 : if( pszInput[iIn] == '\'' )
1599 : {
1600 0 : pszOutput[iOut++] = '\'';
1601 0 : pszOutput[iOut++] = '\'';
1602 : }
1603 : else
1604 124 : pszOutput[iOut++] = pszInput[iIn];
1605 : }
1606 32 : pszOutput[iOut] = '\0';
1607 : }
1608 920 : else if( nScheme == CPLES_CSV )
1609 : {
1610 1818 : if( strchr( pszInput, '\"' ) == NULL
1611 : && strchr( pszInput, ',') == NULL
1612 : && strchr( pszInput, ';') == NULL
1613 : && strchr( pszInput, '\t') == NULL
1614 : && strchr( pszInput, 10) == NULL
1615 : && strchr( pszInput, 13) == NULL )
1616 : {
1617 898 : strcpy( pszOutput, pszInput );
1618 : }
1619 : else
1620 : {
1621 22 : int iOut = 1, iIn;
1622 :
1623 22 : pszOutput[0] = '\"';
1624 :
1625 926 : for( iIn = 0; iIn < nLength; iIn++ )
1626 : {
1627 904 : if( pszInput[iIn] == '\"' )
1628 : {
1629 12 : pszOutput[iOut++] = '\"';
1630 12 : pszOutput[iOut++] = '\"';
1631 : }
1632 892 : else if( pszInput[iIn] == 13 )
1633 : /* drop DOS LF's in strings. */;
1634 : else
1635 892 : pszOutput[iOut++] = pszInput[iIn];
1636 : }
1637 22 : pszOutput[iOut++] = '\"';
1638 22 : pszOutput[iOut++] = '\0';
1639 : }
1640 : }
1641 : else
1642 : {
1643 0 : pszOutput[0] = '\0';
1644 : CPLError( CE_Failure, CPLE_AppDefined,
1645 : "Undefined escaping scheme (%d) in CPLEscapeString()",
1646 0 : nScheme );
1647 : }
1648 :
1649 99498 : pszShortOutput = CPLStrdup( pszOutput );
1650 99498 : CPLFree( pszOutput );
1651 :
1652 99498 : return pszShortOutput;
1653 : }
1654 :
1655 : /************************************************************************/
1656 : /* CPLUnescapeString() */
1657 : /************************************************************************/
1658 :
1659 : /**
1660 : * Unescape a string.
1661 : *
1662 : * This function does the opposite of CPLEscapeString(). Given a string
1663 : * with special values escaped according to some scheme, it will return a
1664 : * new copy of the string returned to it's original form.
1665 : *
1666 : * @param pszInput the input string. This is a zero terminated string.
1667 : * @param pnLength location to return the length of the unescaped string,
1668 : * which may in some cases include embedded '\\0' characters.
1669 : * @param nScheme the escaped scheme to undo (see CPLEscapeString() for a
1670 : * list).
1671 : *
1672 : * @return a copy of the unescaped string that should be freed by the
1673 : * application using CPLFree() when no longer needed.
1674 : */
1675 :
1676 7268 : char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
1677 :
1678 : {
1679 : char *pszOutput;
1680 7268 : int iOut=0, iIn;
1681 :
1682 7268 : pszOutput = (char *) CPLMalloc(4 * strlen(pszInput)+1);
1683 7268 : pszOutput[0] = '\0';
1684 :
1685 14222 : if( nScheme == CPLES_XML || nScheme == CPLES_XML_BUT_QUOTES )
1686 : {
1687 : char ch;
1688 247816 : for( iIn = 0; (ch = pszInput[iIn]) != '\0'; iIn++ )
1689 : {
1690 240862 : if( ch != '&' )
1691 : {
1692 229414 : pszOutput[iOut++] = ch;
1693 : }
1694 11448 : else if( EQUALN(pszInput+iIn,"<",4) )
1695 : {
1696 12 : pszOutput[iOut++] = '<';
1697 12 : iIn += 3;
1698 : }
1699 11436 : else if( EQUALN(pszInput+iIn,">",4) )
1700 : {
1701 12 : pszOutput[iOut++] = '>';
1702 12 : iIn += 3;
1703 : }
1704 11424 : else if( EQUALN(pszInput+iIn,"&",5) )
1705 : {
1706 536 : pszOutput[iOut++] = '&';
1707 536 : iIn += 4;
1708 : }
1709 10888 : else if( EQUALN(pszInput+iIn,"'",6) )
1710 : {
1711 0 : pszOutput[iOut++] = '\'';
1712 0 : iIn += 5;
1713 : }
1714 10888 : else if( EQUALN(pszInput+iIn,""",6) )
1715 : {
1716 10884 : pszOutput[iOut++] = '"';
1717 10884 : iIn += 5;
1718 : }
1719 4 : else if( EQUALN(pszInput+iIn,"&#x",3) )
1720 : {
1721 4 : wchar_t anVal[2] = {0 , 0};
1722 4 : iIn += 3;
1723 :
1724 8 : while(TRUE)
1725 : {
1726 12 : ch = pszInput[iIn ++];
1727 12 : if (ch >= 'a' && ch <= 'f')
1728 0 : anVal[0] = anVal[0] * 16 + ch - 'a' + 10;
1729 12 : else if (ch >= 'A' && ch <= 'A')
1730 0 : anVal[0] = anVal[0] * 16 + ch - 'A' + 10;
1731 20 : else if (ch >= '0' && ch <= '9')
1732 8 : anVal[0] = anVal[0] * 16 + ch - '0';
1733 : else
1734 : break;
1735 : }
1736 4 : if (ch != ';')
1737 0 : break;
1738 4 : iIn --;
1739 :
1740 4 : char * pszUTF8 = CPLRecodeFromWChar( anVal, "WCHAR_T", CPL_ENC_UTF8);
1741 4 : int nLen = strlen(pszUTF8);
1742 4 : memcpy(pszOutput + iOut, pszUTF8, nLen);
1743 4 : CPLFree(pszUTF8);
1744 4 : iOut += nLen;
1745 : }
1746 0 : else if( EQUALN(pszInput+iIn,"&#",2) )
1747 : {
1748 : char ch;
1749 0 : wchar_t anVal[2] = {0 , 0};
1750 0 : iIn += 2;
1751 :
1752 0 : while(TRUE)
1753 : {
1754 0 : ch = pszInput[iIn ++];
1755 0 : if (ch >= '0' && ch <= '9')
1756 0 : anVal[0] = anVal[0] * 10 + ch - '0';
1757 : else
1758 : break;
1759 : }
1760 0 : if (ch != ';')
1761 0 : break;
1762 0 : iIn --;
1763 :
1764 0 : char * pszUTF8 = CPLRecodeFromWChar( anVal, "WCHAR_T", CPL_ENC_UTF8);
1765 0 : int nLen = strlen(pszUTF8);
1766 0 : memcpy(pszOutput + iOut, pszUTF8, nLen);
1767 0 : CPLFree(pszUTF8);
1768 0 : iOut += nLen;
1769 : }
1770 : else
1771 : {
1772 : /* illegal escape sequence */
1773 : CPLDebug( "CPL",
1774 0 : "Error unescaping CPLES_XML text, '&' character followed by unhandled escape sequence." );
1775 0 : break;
1776 : }
1777 : }
1778 : }
1779 314 : else if( nScheme == CPLES_URL )
1780 : {
1781 304 : for( iIn = 0; pszInput[iIn] != '\0'; iIn++ )
1782 : {
1783 274 : if( pszInput[iIn] == '%'
1784 0 : && pszInput[iIn+1] != '\0'
1785 0 : && pszInput[iIn+2] != '\0' )
1786 : {
1787 0 : int nHexChar = 0;
1788 :
1789 0 : if( pszInput[iIn+1] >= 'A' && pszInput[iIn+1] <= 'F' )
1790 0 : nHexChar += 16 * (pszInput[iIn+1] - 'A' + 10);
1791 0 : else if( pszInput[iIn+1] >= 'a' && pszInput[iIn+1] <= 'f' )
1792 0 : nHexChar += 16 * (pszInput[iIn+1] - 'a' + 10);
1793 0 : else if( pszInput[iIn+1] >= '0' && pszInput[iIn+1] <= '9' )
1794 0 : nHexChar += 16 * (pszInput[iIn+1] - '0');
1795 : else
1796 : CPLDebug( "CPL",
1797 : "Error unescaping CPLES_URL text, percent not "
1798 0 : "followed by two hex digits." );
1799 :
1800 0 : if( pszInput[iIn+2] >= 'A' && pszInput[iIn+2] <= 'F' )
1801 0 : nHexChar += pszInput[iIn+2] - 'A' + 10;
1802 0 : else if( pszInput[iIn+2] >= 'a' && pszInput[iIn+2] <= 'f' )
1803 0 : nHexChar += pszInput[iIn+2] - 'a' + 10;
1804 0 : else if( pszInput[iIn+2] >= '0' && pszInput[iIn+2] <= '9' )
1805 0 : nHexChar += pszInput[iIn+2] - '0';
1806 : else
1807 : CPLDebug( "CPL",
1808 : "Error unescaping CPLES_URL text, percent not "
1809 0 : "followed by two hex digits." );
1810 :
1811 0 : pszOutput[iOut++] = (char) nHexChar;
1812 0 : iIn += 2;
1813 : }
1814 274 : else if( pszInput[iIn] == '+' )
1815 : {
1816 0 : pszOutput[iOut++] = ' ';
1817 : }
1818 : else
1819 : {
1820 274 : pszOutput[iOut++] = pszInput[iIn];
1821 : }
1822 : }
1823 : }
1824 284 : else if( nScheme == CPLES_SQL )
1825 : {
1826 0 : for( iIn = 0; pszInput[iIn] != '\0'; iIn++ )
1827 : {
1828 0 : if( pszInput[iIn] == '\'' && pszInput[iIn+1] == '\'' )
1829 : {
1830 0 : iIn++;
1831 0 : pszOutput[iOut++] = pszInput[iIn];
1832 : }
1833 : else
1834 : {
1835 0 : pszOutput[iOut++] = pszInput[iIn];
1836 : }
1837 : }
1838 : }
1839 : else /* if( nScheme == CPLES_BackslashQuoteable ) */
1840 : {
1841 410450 : for( iIn = 0; pszInput[iIn] != '\0'; iIn++ )
1842 : {
1843 410166 : if( pszInput[iIn] == '\\' )
1844 : {
1845 62 : iIn++;
1846 62 : if( pszInput[iIn] == 'n' )
1847 0 : pszOutput[iOut++] = '\n';
1848 62 : else if( pszInput[iIn] == '0' )
1849 2 : pszOutput[iOut++] = '\0';
1850 : else
1851 60 : pszOutput[iOut++] = pszInput[iIn];
1852 : }
1853 : else
1854 : {
1855 410104 : pszOutput[iOut++] = pszInput[iIn];
1856 : }
1857 : }
1858 : }
1859 :
1860 7268 : pszOutput[iOut] = '\0';
1861 :
1862 7268 : if( pnLength != NULL )
1863 662 : *pnLength = iOut;
1864 :
1865 7268 : return pszOutput;
1866 : }
1867 :
1868 : /************************************************************************/
1869 : /* CPLBinaryToHex() */
1870 : /************************************************************************/
1871 :
1872 : /**
1873 : * Binary to hexadecimal translation.
1874 : *
1875 : * @param nBytes number of bytes of binary data in pabyData.
1876 : * @param pabyData array of data bytes to translate.
1877 : *
1878 : * @return hexadecimal translation, zero terminated. Free with CPLFree().
1879 : */
1880 :
1881 998 : char *CPLBinaryToHex( int nBytes, const GByte *pabyData )
1882 :
1883 : {
1884 998 : char *pszHex = (char *) CPLMalloc(nBytes * 2 + 1 );
1885 : int i;
1886 : static const char achHex[] = "0123456789ABCDEF";
1887 :
1888 998 : pszHex[nBytes*2] = '\0';
1889 :
1890 115442 : for( i = 0; i < nBytes; i++ )
1891 : {
1892 114444 : int nLow = pabyData[i] & 0x0f;
1893 114444 : int nHigh = (pabyData[i] & 0xf0) >> 4;
1894 :
1895 114444 : pszHex[i*2] = achHex[nHigh];
1896 114444 : pszHex[i*2+1] = achHex[nLow];
1897 : }
1898 :
1899 998 : return pszHex;
1900 : }
1901 :
1902 :
1903 : /************************************************************************/
1904 : /* CPLHexToBinary() */
1905 : /************************************************************************/
1906 :
1907 : /**
1908 : * Hexadecimal to binary translation
1909 : *
1910 : * @param pszHex the input hex encoded string.
1911 : * @param pnBytes the returned count of decoded bytes placed here.
1912 : *
1913 : * @return returns binary buffer of data - free with CPLFree().
1914 : */
1915 :
1916 642 : GByte *CPLHexToBinary( const char *pszHex, int *pnBytes )
1917 :
1918 : {
1919 642 : int iSrc = 0, iDst = 0;
1920 642 : size_t nHexLen = strlen(pszHex);
1921 :
1922 : GByte *pabyWKB;
1923 :
1924 642 : pabyWKB = (GByte *) CPLMalloc(nHexLen / 2 + 2);
1925 :
1926 266304 : while( pszHex[iSrc] != '\0' )
1927 : {
1928 512292 : if( pszHex[iSrc] >= '0' && pszHex[iSrc] <= '9' )
1929 247272 : pabyWKB[iDst] = pszHex[iSrc] - '0';
1930 35496 : else if( pszHex[iSrc] >= 'A' && pszHex[iSrc] <= 'F' )
1931 17748 : pabyWKB[iDst] = pszHex[iSrc] - 'A' + 10;
1932 0 : else if( pszHex[iSrc] >= 'a' && pszHex[iSrc] <= 'f' )
1933 0 : pabyWKB[iDst] = pszHex[iSrc] - 'a' + 10;
1934 : else
1935 0 : break;
1936 :
1937 265020 : pabyWKB[iDst] *= 16;
1938 :
1939 265020 : iSrc++;
1940 :
1941 492718 : if( pszHex[iSrc] >= '0' && pszHex[iSrc] <= '9' )
1942 227698 : pabyWKB[iDst] += pszHex[iSrc] - '0';
1943 74644 : else if( pszHex[iSrc] >= 'A' && pszHex[iSrc] <= 'F' )
1944 37322 : pabyWKB[iDst] += pszHex[iSrc] - 'A' + 10;
1945 0 : else if( pszHex[iSrc] >= 'a' && pszHex[iSrc] <= 'f' )
1946 0 : pabyWKB[iDst] += pszHex[iSrc] - 'a' + 10;
1947 : else
1948 0 : break;
1949 :
1950 265020 : iSrc++;
1951 265020 : iDst++;
1952 : }
1953 :
1954 642 : pabyWKB[iDst] = 0;
1955 642 : *pnBytes = iDst;
1956 :
1957 642 : return pabyWKB;
1958 : }
1959 :
1960 :
1961 :
1962 : /************************************************************************/
1963 : /* CPLGetValueType() */
1964 : /************************************************************************/
1965 :
1966 : /**
1967 : * Detect the type of the value contained in a string, whether it is
1968 : * a real, an integer or a string
1969 : * Leading and trailing spaces are skipped in the analysis.
1970 : *
1971 : * Note: in the context of this function, integer must be understood in a
1972 : * broad sense. It does not mean that the value can fit into a 32 bit integer
1973 : * for example. It might be larger.
1974 : *
1975 : * @param pszValue the string to analyze
1976 : *
1977 : * @return returns the type of the value contained in the string.
1978 : */
1979 :
1980 7894 : CPLValueType CPLGetValueType(const char* pszValue)
1981 : {
1982 : /*
1983 : doubles : "+25.e+3", "-25.e-3", "25.e3", "25e3", " 25e3 "
1984 : not doubles: "25e 3", "25e.3", "-2-5e3", "2-5e3", "25.25.3"
1985 : */
1986 :
1987 7894 : int bFoundDot = FALSE;
1988 7894 : int bFoundExponent = FALSE;
1989 7894 : int bIsLastCharExponent = FALSE;
1990 7894 : int bIsReal = FALSE;
1991 :
1992 7894 : if (pszValue == NULL)
1993 0 : return CPL_VALUE_STRING;
1994 :
1995 : /* Skip leading + or - */
1996 7894 : if (*pszValue == '+' || *pszValue == '-')
1997 28 : pszValue ++;
1998 :
1999 : /* Skip leading spaces */
2000 15800 : while( isspace( (unsigned char)*pszValue ) )
2001 12 : pszValue ++;
2002 :
2003 27120 : for(; *pszValue != '\0'; pszValue++ )
2004 : {
2005 22620 : if( isdigit( *pszValue))
2006 : {
2007 18320 : bIsLastCharExponent = FALSE;
2008 : /* do nothing */
2009 : }
2010 4300 : else if ( isspace ((unsigned char)*pszValue) )
2011 : {
2012 8 : const char* pszTmp = pszValue;
2013 24 : while( isspace( (unsigned char)*pszTmp ) )
2014 8 : pszTmp ++;
2015 8 : if (*pszTmp == 0)
2016 0 : break;
2017 : else
2018 8 : return CPL_VALUE_STRING;
2019 : }
2020 4292 : else if ( *pszValue == '-' || *pszValue == '+' )
2021 : {
2022 14 : if (bIsLastCharExponent)
2023 : {
2024 : /* do nothing */
2025 : }
2026 : else
2027 14 : return CPL_VALUE_STRING;
2028 0 : bIsLastCharExponent = FALSE;
2029 : }
2030 4278 : else if ( *pszValue == '.')
2031 : {
2032 850 : bIsReal = TRUE;
2033 850 : if (!bFoundDot && bIsLastCharExponent == FALSE)
2034 850 : bFoundDot = TRUE;
2035 : else
2036 0 : return CPL_VALUE_STRING;
2037 850 : bIsLastCharExponent = FALSE;
2038 : }
2039 3484 : else if (*pszValue == 'D' || *pszValue == 'd'
2040 : || *pszValue == 'E' || *pszValue == 'e' )
2041 : {
2042 86 : bIsReal = TRUE;
2043 86 : if (!bFoundExponent)
2044 56 : bFoundExponent = TRUE;
2045 : else
2046 30 : return CPL_VALUE_STRING;
2047 56 : bIsLastCharExponent = TRUE;
2048 : }
2049 : else
2050 : {
2051 3342 : return CPL_VALUE_STRING;
2052 : }
2053 : }
2054 :
2055 4500 : return (bIsReal) ? CPL_VALUE_REAL : CPL_VALUE_INTEGER;
2056 : }
2057 :
2058 : /************************************************************************/
2059 : /* CPLStrlcpy() */
2060 : /************************************************************************/
2061 :
2062 : /**
2063 : * Copy source string to a destination buffer.
2064 : *
2065 : * This function ensures that the destination buffer is always NUL terminated
2066 : * (provided that its length is at least 1).
2067 : *
2068 : * This function is designed to be a safer, more consistent, and less error
2069 : * prone replacement for strncpy. Its contract is identical to libbsd's strlcpy.
2070 : *
2071 : * Truncation can be detected by testing if the return value of CPLStrlcpy
2072 : * is greater or equal to nDestSize.
2073 :
2074 : \verbatim
2075 : char szDest[5];
2076 : if (CPLStrlcpy(szDest, "abcde", sizeof(szDest)) >= sizeof(szDest))
2077 : fprintf(stderr, "truncation occured !\n");
2078 : \endverbatim
2079 :
2080 : * @param pszDest destination buffer
2081 : * @param pszSrc source string. Must be NUL terminated
2082 : * @param nDestSize size of destination buffer (including space for the NUL terminator character)
2083 : *
2084 : * @return the length of the source string (=strlen(pszSrc))
2085 : *
2086 : * @since GDAL 1.7.0
2087 : */
2088 1327108 : size_t CPLStrlcpy(char* pszDest, const char* pszSrc, size_t nDestSize)
2089 : {
2090 1327108 : char* pszDestIter = pszDest;
2091 1327108 : const char* pszSrcIter = pszSrc;
2092 :
2093 1327108 : if (nDestSize == 0)
2094 0 : return strlen(pszSrc);
2095 :
2096 1327108 : nDestSize --;
2097 11346013 : while(nDestSize != 0 && *pszSrcIter != '\0')
2098 : {
2099 8691797 : *pszDestIter = *pszSrcIter;
2100 8691797 : pszDestIter ++;
2101 8691797 : pszSrcIter ++;
2102 8691797 : nDestSize --;
2103 : }
2104 1327108 : *pszDestIter = '\0';
2105 1327108 : return pszSrcIter - pszSrc + strlen(pszSrcIter);
2106 : }
2107 :
2108 : /************************************************************************/
2109 : /* CPLStrlcat() */
2110 : /************************************************************************/
2111 :
2112 : /**
2113 : * Appends a source string to a destination buffer.
2114 : *
2115 : * This function ensures that the destination buffer is always NUL terminated
2116 : * (provided that its length is at least 1 and that there is at least one byte
2117 : * free in pszDest, that is to say strlen(pszDest_before) < nDestSize)
2118 : *
2119 : * This function is designed to be a safer, more consistent, and less error
2120 : * prone replacement for strncat. Its contract is identical to libbsd's strlcat.
2121 : *
2122 : * Truncation can be detected by testing if the return value of CPLStrlcat
2123 : * is greater or equal to nDestSize.
2124 :
2125 : \verbatim
2126 : char szDest[5];
2127 : CPLStrlcpy(szDest, "ab", sizeof(szDest));
2128 : if (CPLStrlcat(szDest, "cde", sizeof(szDest)) >= sizeof(szDest))
2129 : fprintf(stderr, "truncation occured !\n");
2130 : \endverbatim
2131 :
2132 : * @param pszDest destination buffer. Must be NUL terminated before running CPLStrlcat
2133 : * @param pszSrc source string. Must be NUL terminated
2134 : * @param nDestSize size of destination buffer (including space for the NUL terminator character)
2135 : *
2136 : * @return the thoretical length of the destination string after concatenation
2137 : * (=strlen(pszDest_before) + strlen(pszSrc)).
2138 : * If strlen(pszDest_before) >= nDestSize, then it returns nDestSize + strlen(pszSrc)
2139 : *
2140 : * @since GDAL 1.7.0
2141 : */
2142 364268 : size_t CPLStrlcat(char* pszDest, const char* pszSrc, size_t nDestSize)
2143 : {
2144 364268 : char* pszDestIter = pszDest;
2145 :
2146 8758418 : while(nDestSize != 0 && *pszDestIter != '\0')
2147 : {
2148 8029882 : pszDestIter ++;
2149 8029882 : nDestSize --;
2150 : }
2151 :
2152 364268 : return pszDestIter - pszDest + CPLStrlcpy(pszDestIter, pszSrc, nDestSize);
2153 : }
2154 :
2155 : /************************************************************************/
2156 : /* CPLStrnlen() */
2157 : /************************************************************************/
2158 :
2159 : /**
2160 : * Returns the length of a NUL terminated string by reading at most
2161 : * the specified number of bytes.
2162 : *
2163 : * The CPLStrnlen() function returns MIN(strlen(pszStr), nMaxLen).
2164 : * Only the first nMaxLen bytes of the string will be read. Usefull to
2165 : * test if a string contains at least nMaxLen characters without reading
2166 : * the full string up to the NUL terminating character.
2167 : *
2168 : * @param pszStr a NUL terminated string
2169 : * @param nMaxLen maximum number of bytes to read in pszStr
2170 : *
2171 : * @return strlen(pszStr) if the length is lesser than nMaxLen, otherwise
2172 : * nMaxLen if the NUL character has not been found in the first nMaxLen bytes.
2173 : *
2174 : * @since GDAL 1.7.0
2175 : */
2176 :
2177 5402 : size_t CPLStrnlen (const char *pszStr, size_t nMaxLen)
2178 : {
2179 5402 : size_t nLen = 0;
2180 82308 : while(nLen < nMaxLen && *pszStr != '\0')
2181 : {
2182 71504 : nLen ++;
2183 71504 : pszStr ++;
2184 : }
2185 5402 : return nLen;
2186 : }
|