1 : /******************************************************************************
2 : * $Id: cpl_conv.cpp 18894 2010-02-23 19:26:15Z warmerdam $
3 : *
4 : * Project: CPL - Common Portability Library
5 : * Purpose: Convenience functions.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1998, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 : #ifdef MSVC_USE_VLD
30 : #include <vld.h>
31 : #endif
32 : #include "cpl_conv.h"
33 : #include "cpl_string.h"
34 : #include "cpl_vsi.h"
35 : #include "cpl_multiproc.h"
36 :
37 : CPL_CVSID("$Id: cpl_conv.cpp 18894 2010-02-23 19:26:15Z warmerdam $");
38 :
39 : #if defined(WIN32CE)
40 : # include "cpl_wince.h"
41 : #endif
42 :
43 : static void *hConfigMutex = NULL;
44 : static volatile char **papszConfigOptions = NULL;
45 :
46 : static void *hSharedFileMutex = NULL;
47 : static volatile int nSharedFileCount = 0;
48 : static volatile CPLSharedFileInfo *pasSharedFileList = NULL;
49 :
50 :
51 : /************************************************************************/
52 : /* CPLCalloc() */
53 : /************************************************************************/
54 :
55 : /**
56 : * Safe version of calloc().
57 : *
58 : * This function is like the C library calloc(), but raises a CE_Fatal
59 : * error with CPLError() if it fails to allocate the desired memory. It
60 : * should be used for small memory allocations that are unlikely to fail
61 : * and for which the application is unwilling to test for out of memory
62 : * conditions. It uses VSICalloc() to get the memory, so any hooking of
63 : * VSICalloc() will apply to CPLCalloc() as well. CPLFree() or VSIFree()
64 : * can be used free memory allocated by CPLCalloc().
65 : *
66 : * @param nCount number of objects to allocate.
67 : * @param nSize size (in bytes) of object to allocate.
68 : * @return pointer to newly allocated memory, only NULL if nSize * nCount is
69 : * NULL.
70 : */
71 :
72 1668853 : void *CPLCalloc( size_t nCount, size_t nSize )
73 :
74 : {
75 : void *pReturn;
76 :
77 1668853 : if( nSize * nCount == 0 )
78 15188 : return NULL;
79 :
80 1653665 : pReturn = VSICalloc( nCount, nSize );
81 1653665 : if( pReturn == NULL )
82 : {
83 : CPLError( CE_Fatal, CPLE_OutOfMemory,
84 : "CPLCalloc(): Out of memory allocating %ld bytes.\n",
85 0 : (long) (nSize * nCount) );
86 : }
87 :
88 1653665 : return pReturn;
89 : }
90 :
91 : /************************************************************************/
92 : /* CPLMalloc() */
93 : /************************************************************************/
94 :
95 : /**
96 : * Safe version of malloc().
97 : *
98 : * This function is like the C library malloc(), but raises a CE_Fatal
99 : * error with CPLError() if it fails to allocate the desired memory. It
100 : * should be used for small memory allocations that are unlikely to fail
101 : * and for which the application is unwilling to test for out of memory
102 : * conditions. It uses VSIMalloc() to get the memory, so any hooking of
103 : * VSIMalloc() will apply to CPLMalloc() as well. CPLFree() or VSIFree()
104 : * can be used free memory allocated by CPLMalloc().
105 : *
106 : * @param nSize size (in bytes) of memory block to allocate.
107 : * @return pointer to newly allocated memory, only NULL if nSize is zero.
108 : */
109 :
110 1548005 : void *CPLMalloc( size_t nSize )
111 :
112 : {
113 : void *pReturn;
114 :
115 1548005 : CPLVerifyConfiguration();
116 :
117 1548005 : if( nSize == 0 )
118 1031 : return NULL;
119 :
120 : if( nSize < 0 )
121 : {
122 : CPLError( CE_Failure, CPLE_AppDefined,
123 : "CPLMalloc(%ld): Silly size requested.\n",
124 : (long) nSize );
125 : return NULL;
126 : }
127 :
128 1546974 : pReturn = VSIMalloc( nSize );
129 1546974 : if( pReturn == NULL )
130 : {
131 : CPLError( CE_Fatal, CPLE_OutOfMemory,
132 : "CPLMalloc(): Out of memory allocating %ld bytes.\n",
133 0 : (long) nSize );
134 : }
135 :
136 1546974 : return pReturn;
137 : }
138 :
139 : /************************************************************************/
140 : /* CPLRealloc() */
141 : /************************************************************************/
142 :
143 : /**
144 : * Safe version of realloc().
145 : *
146 : * This function is like the C library realloc(), but raises a CE_Fatal
147 : * error with CPLError() if it fails to allocate the desired memory. It
148 : * should be used for small memory allocations that are unlikely to fail
149 : * and for which the application is unwilling to test for out of memory
150 : * conditions. It uses VSIRealloc() to get the memory, so any hooking of
151 : * VSIRealloc() will apply to CPLRealloc() as well. CPLFree() or VSIFree()
152 : * can be used free memory allocated by CPLRealloc().
153 : *
154 : * It is also safe to pass NULL in as the existing memory block for
155 : * CPLRealloc(), in which case it uses VSIMalloc() to allocate a new block.
156 : *
157 : * @param pData existing memory block which should be copied to the new block.
158 : * @param nNewSize new size (in bytes) of memory block to allocate.
159 : * @return pointer to allocated memory, only NULL if nNewSize is zero.
160 : */
161 :
162 :
163 6596090 : void * CPLRealloc( void * pData, size_t nNewSize )
164 :
165 : {
166 : void *pReturn;
167 :
168 6596090 : if ( nNewSize == 0 )
169 : {
170 73397 : VSIFree(pData);
171 73397 : return NULL;
172 : }
173 :
174 : if( nNewSize < 0 )
175 : {
176 : CPLError( CE_Failure, CPLE_AppDefined,
177 : "CPLRealloc(%ld): Silly size requested.\n",
178 : (long) nNewSize );
179 : return NULL;
180 : }
181 :
182 6522693 : if( pData == NULL )
183 838853 : pReturn = VSIMalloc( nNewSize );
184 : else
185 5683840 : pReturn = VSIRealloc( pData, nNewSize );
186 :
187 6522693 : if( pReturn == NULL )
188 : {
189 : CPLError( CE_Fatal, CPLE_OutOfMemory,
190 : "CPLRealloc(): Out of memory allocating %ld bytes.\n",
191 0 : (long)nNewSize );
192 : }
193 :
194 6522693 : return pReturn;
195 : }
196 :
197 : /************************************************************************/
198 : /* CPLStrdup() */
199 : /************************************************************************/
200 :
201 : /**
202 : * Safe version of strdup() function.
203 : *
204 : * This function is similar to the C library strdup() function, but if
205 : * the memory allocation fails it will issue a CE_Fatal error with
206 : * CPLError() instead of returning NULL. It uses VSIStrdup(), so any
207 : * hooking of that function will apply to CPLStrdup() as well. Memory
208 : * allocated with CPLStrdup() can be freed with CPLFree() or VSIFree().
209 : *
210 : * It is also safe to pass a NULL string into CPLStrdup(). CPLStrdup()
211 : * will allocate and return a zero length string (as opposed to a NULL
212 : * string).
213 : *
214 : * @param pszString input string to be duplicated. May be NULL.
215 : * @return pointer to a newly allocated copy of the string. Free with
216 : * CPLFree() or VSIFree().
217 : */
218 :
219 6222982 : char *CPLStrdup( const char * pszString )
220 :
221 : {
222 : char *pszReturn;
223 :
224 6222982 : if( pszString == NULL )
225 122183 : pszString = "";
226 :
227 6222982 : pszReturn = VSIStrdup( pszString );
228 :
229 6222982 : if( pszReturn == NULL )
230 : {
231 : CPLError( CE_Fatal, CPLE_OutOfMemory,
232 : "CPLStrdup(): Out of memory allocating %ld bytes.\n",
233 0 : (long) strlen(pszString) );
234 :
235 : }
236 :
237 6222982 : return( pszReturn );
238 : }
239 :
240 : /************************************************************************/
241 : /* CPLStrlwr() */
242 : /************************************************************************/
243 :
244 : /**
245 : * Convert each characters of the string to lower case.
246 : *
247 : * For example, "ABcdE" will be converted to "abcde".
248 : * This function is locale dependent.
249 : *
250 : * @param pszString input string to be converted.
251 : * @return pointer to the same string, pszString.
252 : */
253 :
254 7 : char *CPLStrlwr( char *pszString )
255 :
256 : {
257 7 : if (pszString)
258 : {
259 7 : char *pszTemp = pszString;
260 :
261 35 : while (*pszTemp)
262 : {
263 21 : *pszTemp = (char) tolower (*pszTemp);
264 21 : pszTemp++;
265 : }
266 : }
267 :
268 7 : return pszString;
269 : }
270 :
271 : /************************************************************************/
272 : /* CPLFGets() */
273 : /* */
274 : /* Note: CR = \r = ASCII 13 */
275 : /* LF = \n = ASCII 10 */
276 : /************************************************************************/
277 :
278 : /**
279 : * Reads in at most one less than nBufferSize characters from the fp
280 : * stream and stores them into the buffer pointed to by pszBuffer.
281 : * Reading stops after an EOF or a newline. If a newline is read, it
282 : * is _not_ stored into the buffer. A '\\0' is stored after the last
283 : * character in the buffer. All three types of newline terminators
284 : * recognized by the CPLFGets(): single '\\r' and '\\n' and '\\r\\n'
285 : * combination.
286 : *
287 : * @param pszBuffer pointer to the targeting character buffer.
288 : * @param nBufferSize maximum size of the string to read (not including
289 : * termonating '\\0').
290 : * @param fp file pointer to read from.
291 : * @return pointer to the pszBuffer containing a string read
292 : * from the file or NULL if the error or end of file was encountered.
293 : */
294 :
295 443538 : char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
296 :
297 : {
298 : int nActuallyRead, nOriginalOffset;
299 :
300 443538 : if ( nBufferSize == 0 || pszBuffer == NULL || fp == NULL )
301 0 : return NULL;
302 :
303 : /* -------------------------------------------------------------------- */
304 : /* Let the OS level call read what it things is one line. This */
305 : /* will include the newline. On windows, if the file happens */
306 : /* to be in text mode, the CRLF will have been converted to */
307 : /* just the newline (LF). If it is in binary mode it may well */
308 : /* have both. */
309 : /* -------------------------------------------------------------------- */
310 443538 : nOriginalOffset = VSIFTell( fp );
311 443538 : if( VSIFGets( pszBuffer, nBufferSize, fp ) == NULL )
312 422 : return NULL;
313 :
314 443116 : nActuallyRead = strlen(pszBuffer);
315 443116 : if ( nActuallyRead == 0 )
316 0 : return NULL;
317 :
318 : /* -------------------------------------------------------------------- */
319 : /* If we found \r and out buffer is full, it is possible there */
320 : /* is also a pending \n. Check for it. */
321 : /* -------------------------------------------------------------------- */
322 443116 : if( nBufferSize == nActuallyRead+1
323 : && pszBuffer[nActuallyRead-1] == 13 )
324 : {
325 : int chCheck;
326 0 : chCheck = fgetc( fp );
327 0 : if( chCheck != 10 )
328 : {
329 : // unget the character.
330 0 : VSIFSeek( fp, nOriginalOffset+nActuallyRead, SEEK_SET );
331 : }
332 : }
333 :
334 : /* -------------------------------------------------------------------- */
335 : /* Trim off \n, \r or \r\n if it appears at the end. We don't */
336 : /* need to do any "seeking" since we want the newline eaten. */
337 : /* -------------------------------------------------------------------- */
338 482384 : if( nActuallyRead > 1
339 : && pszBuffer[nActuallyRead-1] == 10
340 : && pszBuffer[nActuallyRead-2] == 13 )
341 : {
342 39268 : pszBuffer[nActuallyRead-2] = '\0';
343 : }
344 403848 : else if( pszBuffer[nActuallyRead-1] == 10
345 : || pszBuffer[nActuallyRead-1] == 13 )
346 : {
347 141924 : pszBuffer[nActuallyRead-1] = '\0';
348 : }
349 :
350 : /* -------------------------------------------------------------------- */
351 : /* Search within the string for a \r (MacOS convention */
352 : /* apparently), and if we find it we need to trim the string, */
353 : /* and seek back. */
354 : /* -------------------------------------------------------------------- */
355 443116 : char *pszExtraNewline = strchr( pszBuffer, 13 );
356 :
357 443116 : if( pszExtraNewline != NULL )
358 : {
359 : int chCheck;
360 :
361 0 : nActuallyRead = pszExtraNewline - pszBuffer + 1;
362 :
363 0 : *pszExtraNewline = '\0';
364 0 : VSIFSeek( fp, nOriginalOffset + nActuallyRead - 1, SEEK_SET );
365 :
366 : /*
367 : * This hackery is necessary to try and find our correct
368 : * spot on win32 systems with text mode line translation going
369 : * on. Sometimes the fseek back overshoots, but it doesn't
370 : * "realize it" till a character has been read. Try to read till
371 : * we get to the right spot and get our CR.
372 : */
373 0 : chCheck = fgetc( fp );
374 0 : while( (chCheck != 13 && chCheck != EOF)
375 : || VSIFTell(fp) < nOriginalOffset + nActuallyRead )
376 : {
377 : static volatile int bWarned = FALSE;
378 :
379 0 : if( !bWarned )
380 : {
381 0 : bWarned = TRUE;
382 0 : CPLDebug( "CPL", "CPLFGets() correcting for DOS text mode translation seek problem." );
383 : }
384 0 : chCheck = fgetc( fp );
385 : }
386 : }
387 :
388 443116 : return pszBuffer;
389 : }
390 :
391 : /************************************************************************/
392 : /* CPLReadLineBuffer() */
393 : /* */
394 : /* Fetch readline buffer, and ensure it is the desired size, */
395 : /* reallocating if needed. Manages TLS (thread local storage) */
396 : /* issues for the buffer. */
397 : /************************************************************************/
398 867601 : static char *CPLReadLineBuffer( int nRequiredSize )
399 :
400 : {
401 :
402 : /* -------------------------------------------------------------------- */
403 : /* A required size of -1 means the buffer should be freed. */
404 : /* -------------------------------------------------------------------- */
405 867601 : if( nRequiredSize == -1 )
406 : {
407 589 : if( CPLGetTLS( CTLS_RLBUFFERINFO ) != NULL )
408 : {
409 589 : CPLFree( CPLGetTLS( CTLS_RLBUFFERINFO ) );
410 589 : CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
411 : }
412 589 : return NULL;
413 : }
414 :
415 : /* -------------------------------------------------------------------- */
416 : /* If the buffer doesn't exist yet, create it. */
417 : /* -------------------------------------------------------------------- */
418 867012 : GUInt32 *pnAlloc = (GUInt32 *) CPLGetTLS( CTLS_RLBUFFERINFO );
419 :
420 867012 : if( pnAlloc == NULL )
421 : {
422 651 : pnAlloc = (GUInt32 *) CPLMalloc(200);
423 651 : *pnAlloc = 196;
424 651 : CPLSetTLS( CTLS_RLBUFFERINFO, pnAlloc, TRUE );
425 : }
426 :
427 : /* -------------------------------------------------------------------- */
428 : /* If it is too small, grow it bigger. */
429 : /* -------------------------------------------------------------------- */
430 867012 : if( (int) *pnAlloc < nRequiredSize+1 )
431 : {
432 342 : int nNewSize = nRequiredSize + 4 + 500;
433 :
434 342 : GUInt32* pnAllocNew = (GUInt32 *) VSIRealloc(pnAlloc,nNewSize);
435 342 : if( pnAllocNew == NULL )
436 : {
437 0 : VSIFree( pnAlloc );
438 0 : CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
439 0 : return NULL;
440 : }
441 342 : pnAlloc = pnAllocNew;
442 :
443 342 : *pnAlloc = nNewSize - 4;
444 342 : CPLSetTLS( CTLS_RLBUFFERINFO, pnAlloc, TRUE );
445 : }
446 :
447 867012 : return (char *) (pnAlloc+1);
448 : }
449 :
450 : /************************************************************************/
451 : /* CPLReadLine() */
452 : /************************************************************************/
453 :
454 : /**
455 : * Simplified line reading from text file.
456 : *
457 : * Read a line of text from the given file handle, taking care
458 : * to capture CR and/or LF and strip off ... equivelent of
459 : * DKReadLine(). Pointer to an internal buffer is returned.
460 : * The application shouldn't free it, or depend on it's value
461 : * past the next call to CPLReadLine().
462 : *
463 : * Note that CPLReadLine() uses VSIFGets(), so any hooking of VSI file
464 : * services should apply to CPLReadLine() as well.
465 : *
466 : * CPLReadLine() maintains an internal buffer, which will appear as a
467 : * single block memory leak in some circumstances. CPLReadLine() may
468 : * be called with a NULL FILE * at any time to free this working buffer.
469 : *
470 : * @param fp file pointer opened with VSIFOpen().
471 : *
472 : * @return pointer to an internal buffer containing a line of text read
473 : * from the file or NULL if the end of file was encountered.
474 : */
475 :
476 181803 : const char *CPLReadLine( FILE * fp )
477 :
478 : {
479 181803 : char *pszRLBuffer = CPLReadLineBuffer(1);
480 181803 : int nReadSoFar = 0;
481 :
482 : /* -------------------------------------------------------------------- */
483 : /* Cleanup case. */
484 : /* -------------------------------------------------------------------- */
485 181803 : if( fp == NULL )
486 : {
487 178 : CPLReadLineBuffer( -1 );
488 178 : return NULL;
489 : }
490 :
491 : /* -------------------------------------------------------------------- */
492 : /* Loop reading chunks of the line till we get to the end of */
493 : /* the line. */
494 : /* -------------------------------------------------------------------- */
495 : int nBytesReadThisTime;
496 :
497 443112 : do {
498 : /* -------------------------------------------------------------------- */
499 : /* Grow the working buffer if we have it nearly full. Fail out */
500 : /* of read line if we can't reallocate it big enough (for */
501 : /* instance for a _very large_ file with no newlines). */
502 : /* -------------------------------------------------------------------- */
503 443532 : pszRLBuffer = CPLReadLineBuffer( nReadSoFar + 129 );
504 443532 : if( pszRLBuffer == NULL )
505 0 : return NULL;
506 :
507 : /* -------------------------------------------------------------------- */
508 : /* Do the actual read. */
509 : /* -------------------------------------------------------------------- */
510 443532 : if( CPLFGets( pszRLBuffer+nReadSoFar, 128, fp ) == NULL
511 : && nReadSoFar == 0 )
512 420 : return NULL;
513 :
514 443112 : nBytesReadThisTime = strlen(pszRLBuffer+nReadSoFar);
515 443112 : nReadSoFar += nBytesReadThisTime;
516 :
517 : } while( nBytesReadThisTime >= 127
518 : && pszRLBuffer[nReadSoFar-1] != 13
519 : && pszRLBuffer[nReadSoFar-1] != 10 );
520 :
521 181205 : return( pszRLBuffer );
522 : }
523 :
524 : /************************************************************************/
525 : /* CPLReadLineL() */
526 : /************************************************************************/
527 :
528 : /**
529 : * Simplified line reading from text file.
530 : *
531 : * Similar to CPLReadLine(), but reading from a large file API handle.
532 : *
533 : * @param fp file pointer opened with VSIFOpenL().
534 : *
535 : * @return pointer to an internal buffer containing a line of text read
536 : * from the file or NULL if the end of file was encountered.
537 : */
538 :
539 29671 : const char *CPLReadLineL( FILE * fp )
540 : {
541 29671 : return CPLReadLine2L( fp, -1, NULL );
542 : }
543 :
544 : /************************************************************************/
545 : /* CPLReadLine2L() */
546 : /************************************************************************/
547 :
548 : /**
549 : * Simplified line reading from text file.
550 : *
551 : * Similar to CPLReadLine(), but reading from a large file API handle.
552 : *
553 : * @param fp file pointer opened with VSIFOpenL().
554 : * @param nMaxCars maximum number of characters allowed, or -1 for no limit.
555 : * @param papszOptions NULL-terminated array of options. Unused for now.
556 :
557 : * @return pointer to an internal buffer containing a line of text read
558 : * from the file or NULL if the end of file was encountered or the maximum
559 : * number of characters allowed readched.
560 : *
561 : * @since GDAL 1.7.0
562 : */
563 :
564 238371 : const char *CPLReadLine2L( FILE * fp, int nMaxCars, char** papszOptions )
565 :
566 : {
567 : /* -------------------------------------------------------------------- */
568 : /* Cleanup case. */
569 : /* -------------------------------------------------------------------- */
570 238371 : if( fp == NULL )
571 : {
572 411 : CPLReadLineBuffer( -1 );
573 411 : return NULL;
574 : }
575 :
576 : /* -------------------------------------------------------------------- */
577 : /* Loop reading chunks of the line till we get to the end of */
578 : /* the line. */
579 : /* -------------------------------------------------------------------- */
580 : char *pszRLBuffer;
581 237960 : const size_t nChunkSize = 40;
582 : char szChunk[nChunkSize];
583 237960 : size_t nChunkBytesRead = 0;
584 237960 : int nBufLength = 0;
585 237960 : size_t nChunkBytesConsumed = 0;
586 :
587 3717 : while( TRUE )
588 : {
589 : /* -------------------------------------------------------------------- */
590 : /* Read a chunk from the input file. */
591 : /* -------------------------------------------------------------------- */
592 241677 : pszRLBuffer = CPLReadLineBuffer( nBufLength + nChunkSize + 1 );
593 :
594 241677 : if( nChunkBytesRead == nChunkBytesConsumed + 1 )
595 : {
596 :
597 : // case where one character is left over from last read.
598 3717 : szChunk[0] = szChunk[nChunkBytesConsumed];
599 :
600 3717 : nChunkBytesConsumed = 0;
601 3717 : nChunkBytesRead = VSIFReadL( szChunk+1, 1, nChunkSize-1, fp ) + 1;
602 : }
603 : else
604 : {
605 237960 : nChunkBytesConsumed = 0;
606 :
607 : // fresh read.
608 237960 : nChunkBytesRead = VSIFReadL( szChunk, 1, nChunkSize, fp );
609 237960 : if( nChunkBytesRead == 0 )
610 : {
611 357 : if( nBufLength == 0 )
612 357 : return NULL;
613 : else
614 0 : break;
615 : }
616 : }
617 :
618 : /* -------------------------------------------------------------------- */
619 : /* copy over characters watching for end-of-line. */
620 : /* -------------------------------------------------------------------- */
621 241320 : int bBreak = FALSE;
622 7815611 : while( nChunkBytesConsumed < nChunkBytesRead-1 && !bBreak )
623 : {
624 7353819 : if( (szChunk[nChunkBytesConsumed] == 13
625 : && szChunk[nChunkBytesConsumed+1] == 10)
626 : || (szChunk[nChunkBytesConsumed] == 10
627 : && szChunk[nChunkBytesConsumed+1] == 13) )
628 : {
629 20848 : nChunkBytesConsumed += 2;
630 20848 : bBreak = TRUE;
631 : }
632 7528104 : else if( szChunk[nChunkBytesConsumed] == 10
633 : || szChunk[nChunkBytesConsumed] == 13 )
634 : {
635 215981 : nChunkBytesConsumed += 1;
636 215981 : bBreak = TRUE;
637 : }
638 : else
639 : {
640 7096142 : pszRLBuffer[nBufLength++] = szChunk[nChunkBytesConsumed++];
641 7096142 : if (nMaxCars >= 0 && nBufLength == nMaxCars)
642 : {
643 : CPLError( CE_Failure, CPLE_AppDefined,
644 0 : "Maximum number of characters allowed reached.");
645 0 : return NULL;
646 : }
647 : }
648 : }
649 :
650 241320 : if( bBreak )
651 236829 : break;
652 :
653 : /* -------------------------------------------------------------------- */
654 : /* If there is a remaining character and it is not a newline */
655 : /* consume it. If it is a newline, but we are clearly at the */
656 : /* end of the file then consume it. */
657 : /* -------------------------------------------------------------------- */
658 4491 : if( nChunkBytesConsumed == nChunkBytesRead-1
659 : && nChunkBytesRead < nChunkSize )
660 : {
661 774 : if( szChunk[nChunkBytesConsumed] == 10
662 : || szChunk[nChunkBytesConsumed] == 13 )
663 : {
664 514 : nChunkBytesConsumed++;
665 514 : break;
666 : }
667 :
668 260 : pszRLBuffer[nBufLength++] = szChunk[nChunkBytesConsumed++];
669 260 : break;
670 : }
671 : }
672 :
673 : /* -------------------------------------------------------------------- */
674 : /* If we have left over bytes after breaking out, seek back to */
675 : /* ensure they remain to be read next time. */
676 : /* -------------------------------------------------------------------- */
677 237603 : if( nChunkBytesConsumed < nChunkBytesRead )
678 : {
679 235119 : size_t nBytesToPush = nChunkBytesRead - nChunkBytesConsumed;
680 :
681 235119 : VSIFSeekL( fp, VSIFTellL( fp ) - nBytesToPush, SEEK_SET );
682 : }
683 :
684 237603 : pszRLBuffer[nBufLength] = '\0';
685 :
686 237603 : return( pszRLBuffer );
687 : }
688 :
689 : /************************************************************************/
690 : /* CPLScanString() */
691 : /************************************************************************/
692 :
693 : /**
694 : * Scan up to a maximum number of characters from a given string,
695 : * allocate a buffer for a new string and fill it with scanned characters.
696 : *
697 : * @param pszString String containing characters to be scanned. It may be
698 : * terminated with a null character.
699 : *
700 : * @param nMaxLength The maximum number of character to read. Less
701 : * characters will be read if a null character is encountered.
702 : *
703 : * @param bTrimSpaces If TRUE, trim ending spaces from the input string.
704 : * Character considered as empty using isspace(3) function.
705 : *
706 : * @param bNormalize If TRUE, replace ':' symbol with the '_'. It is needed if
707 : * resulting string will be used in CPL dictionaries.
708 : *
709 : * @return Pointer to the resulting string buffer. Caller responsible to free
710 : * this buffer with CPLFree().
711 : */
712 :
713 : char *CPLScanString( const char *pszString, int nMaxLength,
714 307 : int bTrimSpaces, int bNormalize )
715 : {
716 : char *pszBuffer;
717 :
718 307 : if ( !pszString )
719 0 : return NULL;
720 :
721 307 : if ( !nMaxLength )
722 2 : return CPLStrdup( "" );
723 :
724 305 : pszBuffer = (char *)CPLMalloc( nMaxLength + 1 );
725 305 : if ( !pszBuffer )
726 0 : return NULL;
727 :
728 305 : strncpy( pszBuffer, pszString, nMaxLength );
729 305 : pszBuffer[nMaxLength] = '\0';
730 :
731 305 : if ( bTrimSpaces )
732 : {
733 305 : size_t i = strlen( pszBuffer );
734 1177 : while ( i-- > 0 && isspace((unsigned char)pszBuffer[i]) )
735 567 : pszBuffer[i] = '\0';
736 : }
737 :
738 305 : if ( bNormalize )
739 : {
740 244 : size_t i = strlen( pszBuffer );
741 2191 : while ( i-- > 0 )
742 : {
743 1703 : if ( pszBuffer[i] == ':' )
744 0 : pszBuffer[i] = '_';
745 : }
746 : }
747 :
748 305 : return pszBuffer;
749 : }
750 :
751 : /************************************************************************/
752 : /* CPLScanLong() */
753 : /************************************************************************/
754 :
755 : /**
756 : * Scan up to a maximum number of characters from a string and convert
757 : * the result to a long.
758 : *
759 : * @param pszString String containing characters to be scanned. It may be
760 : * terminated with a null character.
761 : *
762 : * @param nMaxLength The maximum number of character to consider as part
763 : * of the number. Less characters will be considered if a null character
764 : * is encountered.
765 : *
766 : * @return Long value, converted from its ASCII form.
767 : */
768 :
769 5 : long CPLScanLong( const char *pszString, int nMaxLength )
770 : {
771 : long iValue;
772 5 : char *pszValue = (char *)CPLMalloc( nMaxLength + 1);
773 :
774 : /* -------------------------------------------------------------------- */
775 : /* Compute string into local buffer, and terminate it. */
776 : /* -------------------------------------------------------------------- */
777 5 : strncpy( pszValue, pszString, nMaxLength );
778 5 : pszValue[nMaxLength] = '\0';
779 :
780 : /* -------------------------------------------------------------------- */
781 : /* Use atol() to fetch out the result */
782 : /* -------------------------------------------------------------------- */
783 5 : iValue = atol( pszValue );
784 :
785 5 : CPLFree( pszValue );
786 5 : return iValue;
787 : }
788 :
789 :
790 : /************************************************************************/
791 : /* CPLScanULong() */
792 : /************************************************************************/
793 :
794 : /**
795 : * Scan up to a maximum number of characters from a string and convert
796 : * the result to a unsigned long.
797 : *
798 : * @param pszString String containing characters to be scanned. It may be
799 : * terminated with a null character.
800 : *
801 : * @param nMaxLength The maximum number of character to consider as part
802 : * of the number. Less characters will be considered if a null character
803 : * is encountered.
804 : *
805 : * @return Unsigned long value, converted from its ASCII form.
806 : */
807 :
808 0 : unsigned long CPLScanULong( const char *pszString, int nMaxLength )
809 : {
810 : unsigned long uValue;
811 0 : char *pszValue = (char *)CPLMalloc( nMaxLength + 1);
812 :
813 : /* -------------------------------------------------------------------- */
814 : /* Compute string into local buffer, and terminate it. */
815 : /* -------------------------------------------------------------------- */
816 0 : strncpy( pszValue, pszString, nMaxLength );
817 0 : pszValue[nMaxLength] = '\0';
818 :
819 : /* -------------------------------------------------------------------- */
820 : /* Use strtoul() to fetch out the result */
821 : /* -------------------------------------------------------------------- */
822 0 : uValue = strtoul( pszValue, NULL, 10 );
823 :
824 0 : CPLFree( pszValue );
825 0 : return uValue;
826 : }
827 :
828 : /************************************************************************/
829 : /* CPLScanUIntBig() */
830 : /************************************************************************/
831 :
832 : /**
833 : * Extract big integer from string.
834 : *
835 : * Scan up to a maximum number of characters from a string and convert
836 : * the result to a GUIntBig.
837 : *
838 : * @param pszString String containing characters to be scanned. It may be
839 : * terminated with a null character.
840 : *
841 : * @param nMaxLength The maximum number of character to consider as part
842 : * of the number. Less characters will be considered if a null character
843 : * is encountered.
844 : *
845 : * @return GUIntBig value, converted from its ASCII form.
846 : */
847 :
848 7324 : GUIntBig CPLScanUIntBig( const char *pszString, int nMaxLength )
849 : {
850 : GUIntBig iValue;
851 7324 : char *pszValue = (char *)CPLMalloc( nMaxLength + 1);
852 :
853 : /* -------------------------------------------------------------------- */
854 : /* Compute string into local buffer, and terminate it. */
855 : /* -------------------------------------------------------------------- */
856 7324 : strncpy( pszValue, pszString, nMaxLength );
857 7324 : pszValue[nMaxLength] = '\0';
858 :
859 : /* -------------------------------------------------------------------- */
860 : /* Fetch out the result */
861 : /* -------------------------------------------------------------------- */
862 : #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
863 : iValue = (GUIntBig)_atoi64( pszValue );
864 : # elif HAVE_ATOLL
865 7324 : iValue = atoll( pszValue );
866 : #else
867 : iValue = atol( pszValue );
868 : #endif
869 :
870 7324 : CPLFree( pszValue );
871 7324 : return iValue;
872 : }
873 :
874 : /************************************************************************/
875 : /* CPLScanPointer() */
876 : /************************************************************************/
877 :
878 : /**
879 : * Extract pointer from string.
880 : *
881 : * Scan up to a maximum number of characters from a string and convert
882 : * the result to a pointer.
883 : *
884 : * @param pszString String containing characters to be scanned. It may be
885 : * terminated with a null character.
886 : *
887 : * @param nMaxLength The maximum number of character to consider as part
888 : * of the number. Less characters will be considered if a null character
889 : * is encountered.
890 : *
891 : * @return pointer value, converted from its ASCII form.
892 : */
893 :
894 54 : void *CPLScanPointer( const char *pszString, int nMaxLength )
895 : {
896 : void *pResult;
897 : char szTemp[128];
898 :
899 : /* -------------------------------------------------------------------- */
900 : /* Compute string into local buffer, and terminate it. */
901 : /* -------------------------------------------------------------------- */
902 54 : if( nMaxLength > (int) sizeof(szTemp)-1 )
903 0 : nMaxLength = sizeof(szTemp)-1;
904 :
905 54 : strncpy( szTemp, pszString, nMaxLength );
906 54 : szTemp[nMaxLength] = '\0';
907 :
908 : /* -------------------------------------------------------------------- */
909 : /* On MSVC we have to scanf pointer values without the 0x */
910 : /* prefix. */
911 : /* -------------------------------------------------------------------- */
912 54 : if( EQUALN(szTemp,"0x",2) )
913 : {
914 54 : pResult = NULL;
915 :
916 : #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
917 : sscanf( szTemp+2, "%p", &pResult );
918 : #else
919 54 : sscanf( szTemp, "%p", &pResult );
920 : #endif
921 : }
922 :
923 : else
924 : {
925 : #if SIZEOF_VOIDP == 8
926 0 : pResult = (void *) CPLScanUIntBig( szTemp, nMaxLength );
927 : #else
928 : pResult = (void *) CPLScanULong( szTemp, nMaxLength );
929 : #endif
930 : }
931 :
932 54 : return pResult;
933 : }
934 :
935 : /************************************************************************/
936 : /* CPLScanDouble() */
937 : /************************************************************************/
938 :
939 : /**
940 : * Extract double from string.
941 : *
942 : * Scan up to a maximum number of characters from a string and convert the
943 : * result to a double. This function uses CPLAtof() to convert string to
944 : * double value, so it uses a comma as a decimal delimiter.
945 : *
946 : * @param pszString String containing characters to be scanned. It may be
947 : * terminated with a null character.
948 : *
949 : * @param nMaxLength The maximum number of character to consider as part
950 : * of the number. Less characters will be considered if a null character
951 : * is encountered.
952 : *
953 : * @return Double value, converted from its ASCII form.
954 : */
955 :
956 161 : double CPLScanDouble( const char *pszString, int nMaxLength )
957 : {
958 : int i;
959 : double dfValue;
960 161 : char *pszValue = (char *)CPLMalloc( nMaxLength + 1);
961 :
962 : /* -------------------------------------------------------------------- */
963 : /* Compute string into local buffer, and terminate it. */
964 : /* -------------------------------------------------------------------- */
965 161 : strncpy( pszValue, pszString, nMaxLength );
966 161 : pszValue[nMaxLength] = '\0';
967 :
968 : /* -------------------------------------------------------------------- */
969 : /* Make a pass through converting 'D's to 'E's. */
970 : /* -------------------------------------------------------------------- */
971 3409 : for( i = 0; i < nMaxLength; i++ )
972 3248 : if ( pszValue[i] == 'd' || pszValue[i] == 'D' )
973 30 : pszValue[i] = 'E';
974 :
975 : /* -------------------------------------------------------------------- */
976 : /* The conversion itself. */
977 : /* -------------------------------------------------------------------- */
978 161 : dfValue = CPLAtof( pszValue );
979 :
980 161 : CPLFree( pszValue );
981 161 : return dfValue;
982 : }
983 :
984 : /************************************************************************/
985 : /* CPLPrintString() */
986 : /************************************************************************/
987 :
988 : /**
989 : * Copy the string pointed to by pszSrc, NOT including the terminating
990 : * `\\0' character, to the array pointed to by pszDest.
991 : *
992 : * @param pszDest Pointer to the destination string buffer. Should be
993 : * large enough to hold the resulting string.
994 : *
995 : * @param pszSrc Pointer to the source buffer.
996 : *
997 : * @param nMaxLen Maximum length of the resulting string. If string length
998 : * is greater than nMaxLen, it will be truncated.
999 : *
1000 : * @return Number of characters printed.
1001 : */
1002 :
1003 130 : int CPLPrintString( char *pszDest, const char *pszSrc, int nMaxLen )
1004 : {
1005 130 : char *pszTemp = pszDest;
1006 130 : int nChars = 0;
1007 :
1008 130 : if ( !pszDest )
1009 0 : return 0;
1010 :
1011 130 : if ( !pszSrc )
1012 : {
1013 0 : *pszDest = '\0';
1014 0 : return 1;
1015 : }
1016 :
1017 4482 : while ( nChars < nMaxLen && *pszSrc )
1018 : {
1019 4222 : *pszTemp++ = *pszSrc++;
1020 4222 : nChars++;
1021 : }
1022 :
1023 130 : return nChars;
1024 : }
1025 :
1026 : /************************************************************************/
1027 : /* CPLPrintStringFill() */
1028 : /************************************************************************/
1029 :
1030 : /**
1031 : * Copy the string pointed to by pszSrc, NOT including the terminating
1032 : * `\\0' character, to the array pointed to by pszDest. Remainder of the
1033 : * destination string will be filled with space characters. This is only
1034 : * difference from the PrintString().
1035 : *
1036 : * @param pszDest Pointer to the destination string buffer. Should be
1037 : * large enough to hold the resulting string.
1038 : *
1039 : * @param pszSrc Pointer to the source buffer.
1040 : *
1041 : * @param nMaxLen Maximum length of the resulting string. If string length
1042 : * is greater than nMaxLen, it will be truncated.
1043 : *
1044 : * @return Number of characters printed.
1045 : */
1046 :
1047 86 : int CPLPrintStringFill( char *pszDest, const char *pszSrc, int nMaxLen )
1048 : {
1049 86 : char *pszTemp = pszDest;
1050 :
1051 86 : if ( !pszDest )
1052 0 : return 0;
1053 :
1054 86 : if ( !pszSrc )
1055 : {
1056 0 : memset( pszDest, ' ', nMaxLen );
1057 0 : return nMaxLen;
1058 : }
1059 :
1060 678 : while ( nMaxLen && *pszSrc )
1061 : {
1062 506 : *pszTemp++ = *pszSrc++;
1063 506 : nMaxLen--;
1064 : }
1065 :
1066 86 : if ( nMaxLen )
1067 43 : memset( pszTemp, ' ', nMaxLen );
1068 :
1069 86 : return nMaxLen;
1070 : }
1071 :
1072 : /************************************************************************/
1073 : /* CPLPrintInt32() */
1074 : /************************************************************************/
1075 :
1076 : /**
1077 : * Print GInt32 value into specified string buffer. This string will not
1078 : * be NULL-terminated.
1079 : *
1080 : * @param pszBuffer Pointer to the destination string buffer. Should be
1081 : * large enough to hold the resulting string. Note, that the string will
1082 : * not be NULL-terminated, so user should do this himself, if needed.
1083 : *
1084 : * @param iValue Numerical value to print.
1085 : *
1086 : * @param nMaxLen Maximum length of the resulting string. If string length
1087 : * is greater than nMaxLen, it will be truncated.
1088 : *
1089 : * @return Number of characters printed.
1090 : */
1091 :
1092 1 : int CPLPrintInt32( char *pszBuffer, GInt32 iValue, int nMaxLen )
1093 : {
1094 : char szTemp[64];
1095 :
1096 1 : if ( !pszBuffer )
1097 0 : return 0;
1098 :
1099 1 : if ( nMaxLen >= 64 )
1100 0 : nMaxLen = 63;
1101 :
1102 : #if UINT_MAX == 65535
1103 : sprintf( szTemp, "%*ld", nMaxLen, iValue );
1104 : #else
1105 1 : sprintf( szTemp, "%*d", nMaxLen, iValue );
1106 : #endif
1107 :
1108 1 : return CPLPrintString( pszBuffer, szTemp, nMaxLen );
1109 : }
1110 :
1111 : /************************************************************************/
1112 : /* CPLPrintUIntBig() */
1113 : /************************************************************************/
1114 :
1115 : /**
1116 : * Print GUIntBig value into specified string buffer. This string will not
1117 : * be NULL-terminated.
1118 : *
1119 : * @param pszBuffer Pointer to the destination string buffer. Should be
1120 : * large enough to hold the resulting string. Note, that the string will
1121 : * not be NULL-terminated, so user should do this himself, if needed.
1122 : *
1123 : * @param iValue Numerical value to print.
1124 : *
1125 : * @param nMaxLen Maximum length of the resulting string. If string length
1126 : * is greater than nMaxLen, it will be truncated.
1127 : *
1128 : * @return Number of characters printed.
1129 : */
1130 :
1131 51 : int CPLPrintUIntBig( char *pszBuffer, GUIntBig iValue, int nMaxLen )
1132 : {
1133 : char szTemp[64];
1134 :
1135 51 : if ( !pszBuffer )
1136 0 : return 0;
1137 :
1138 51 : if ( nMaxLen >= 64 )
1139 0 : nMaxLen = 63;
1140 :
1141 : #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
1142 : sprintf( szTemp, "%*I64d", nMaxLen, iValue );
1143 : # elif HAVE_LONG_LONG
1144 51 : sprintf( szTemp, "%*lld", nMaxLen, (long long) iValue );
1145 : // sprintf( szTemp, "%*Ld", nMaxLen, (long long) iValue );
1146 : #else
1147 : sprintf( szTemp, "%*ld", nMaxLen, iValue );
1148 : #endif
1149 :
1150 51 : return CPLPrintString( pszBuffer, szTemp, nMaxLen );
1151 : }
1152 :
1153 : /************************************************************************/
1154 : /* CPLPrintPointer() */
1155 : /************************************************************************/
1156 :
1157 : /**
1158 : * Print pointer value into specified string buffer. This string will not
1159 : * be NULL-terminated.
1160 : *
1161 : * @param pszBuffer Pointer to the destination string buffer. Should be
1162 : * large enough to hold the resulting string. Note, that the string will
1163 : * not be NULL-terminated, so user should do this himself, if needed.
1164 : *
1165 : * @param pValue Pointer to ASCII encode.
1166 : *
1167 : * @param nMaxLen Maximum length of the resulting string. If string length
1168 : * is greater than nMaxLen, it will be truncated.
1169 : *
1170 : * @return Number of characters printed.
1171 : */
1172 :
1173 54 : int CPLPrintPointer( char *pszBuffer, void *pValue, int nMaxLen )
1174 : {
1175 : char szTemp[64];
1176 :
1177 54 : if ( !pszBuffer )
1178 0 : return 0;
1179 :
1180 54 : if ( nMaxLen >= 64 )
1181 54 : nMaxLen = 63;
1182 :
1183 54 : sprintf( szTemp, "%p", pValue );
1184 :
1185 : // On windows, and possibly some other platforms the sprintf("%p")
1186 : // does not prefix things with 0x so it is hard to know later if the
1187 : // value is hex encoded. Fix this up here.
1188 :
1189 54 : if( !EQUALN(szTemp,"0x",2) )
1190 0 : sprintf( szTemp, "0x%p", pValue );
1191 :
1192 54 : return CPLPrintString( pszBuffer, szTemp, nMaxLen );
1193 : }
1194 :
1195 : /************************************************************************/
1196 : /* CPLPrintDouble() */
1197 : /************************************************************************/
1198 :
1199 : /**
1200 : * Print double value into specified string buffer. Exponential character
1201 : * flag 'E' (or 'e') will be replaced with 'D', as in Fortran. Resulting
1202 : * string will not to be NULL-terminated.
1203 : *
1204 : * @param pszBuffer Pointer to the destination string buffer. Should be
1205 : * large enough to hold the resulting string. Note, that the string will
1206 : * not be NULL-terminated, so user should do this himself, if needed.
1207 : *
1208 : * @param pszFormat Format specifier (for example, "%16.9E").
1209 : *
1210 : * @param dfValue Numerical value to print.
1211 : *
1212 : * @param pszLocale Pointer to a character string containing locale name
1213 : * ("C", "POSIX", "us_US", "ru_RU.KOI8-R" etc.). If NULL we will not
1214 : * manipulate with locale settings and current process locale will be used for
1215 : * printing. With the pszLocale option we can control what exact locale
1216 : * will be used for printing a numeric value to the string (in most cases
1217 : * it should be C/POSIX).
1218 : *
1219 : * @return Number of characters printed.
1220 : */
1221 :
1222 : int CPLPrintDouble( char *pszBuffer, const char *pszFormat,
1223 0 : double dfValue, const char *pszLocale )
1224 : {
1225 :
1226 : #define DOUBLE_BUFFER_SIZE 64
1227 :
1228 : char szTemp[DOUBLE_BUFFER_SIZE];
1229 : int i;
1230 :
1231 0 : if ( !pszBuffer )
1232 0 : return 0;
1233 :
1234 : #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
1235 : char *pszCurLocale = NULL;
1236 :
1237 : if ( pszLocale || EQUAL( pszLocale, "" ) )
1238 : {
1239 : // Save the current locale
1240 : pszCurLocale = setlocale(LC_ALL, NULL );
1241 : // Set locale to the specified value
1242 : setlocale( LC_ALL, pszLocale );
1243 : }
1244 : #else
1245 : (void) pszLocale;
1246 : #endif
1247 :
1248 : #if defined(HAVE_SNPRINTF)
1249 0 : snprintf( szTemp, DOUBLE_BUFFER_SIZE, pszFormat, dfValue );
1250 : #else
1251 : sprintf( szTemp, pszFormat, dfValue );
1252 : #endif
1253 0 : szTemp[DOUBLE_BUFFER_SIZE - 1] = '\0';
1254 :
1255 0 : for( i = 0; szTemp[i] != '\0'; i++ )
1256 : {
1257 0 : if( szTemp[i] == 'E' || szTemp[i] == 'e' )
1258 0 : szTemp[i] = 'D';
1259 : }
1260 :
1261 : #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
1262 : // Restore stored locale back
1263 : if ( pszCurLocale )
1264 : setlocale( LC_ALL, pszCurLocale );
1265 : #endif
1266 :
1267 0 : return CPLPrintString( pszBuffer, szTemp, 64 );
1268 :
1269 : #undef DOUBLE_BUFFER_SIZE
1270 :
1271 : }
1272 :
1273 : /************************************************************************/
1274 : /* CPLPrintTime() */
1275 : /************************************************************************/
1276 :
1277 : /**
1278 : * Print specified time value accordingly to the format options and
1279 : * specified locale name. This function does following:
1280 : *
1281 : * - if locale parameter is not NULL, the current locale setting will be
1282 : * stored and replaced with the specified one;
1283 : * - format time value with the strftime(3) function;
1284 : * - restore back current locale, if was saved.
1285 : *
1286 : * @param pszBuffer Pointer to the destination string buffer. Should be
1287 : * large enough to hold the resulting string. Note, that the string will
1288 : * not be NULL-terminated, so user should do this himself, if needed.
1289 : *
1290 : * @param nMaxLen Maximum length of the resulting string. If string length is
1291 : * greater than nMaxLen, it will be truncated.
1292 : *
1293 : * @param pszFormat Controls the output format. Options are the same as
1294 : * for strftime(3) function.
1295 : *
1296 : * @param poBrokenTime Pointer to the broken-down time structure. May be
1297 : * requested with the VSIGMTime() and VSILocalTime() functions.
1298 : *
1299 : * @param pszLocale Pointer to a character string containing locale name
1300 : * ("C", "POSIX", "us_US", "ru_RU.KOI8-R" etc.). If NULL we will not
1301 : * manipulate with locale settings and current process locale will be used for
1302 : * printing. Be aware that it may be unsuitable to use current locale for
1303 : * printing time, because all names will be printed in your native language,
1304 : * as well as time format settings also may be ajusted differently from the
1305 : * C/POSIX defaults. To solve these problems this option was introdiced.
1306 : *
1307 : * @return Number of characters printed.
1308 : */
1309 :
1310 : #ifndef WIN32CE /* XXX - mloskot - strftime is not available yet. */
1311 :
1312 : int CPLPrintTime( char *pszBuffer, int nMaxLen, const char *pszFormat,
1313 0 : const struct tm *poBrokenTime, const char *pszLocale )
1314 : {
1315 0 : char *pszTemp = (char *)CPLMalloc( (nMaxLen + 1) * sizeof(char) );
1316 : int nChars;
1317 :
1318 : #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
1319 : char *pszCurLocale = NULL;
1320 :
1321 : if ( pszLocale || EQUAL( pszLocale, "" ) )
1322 : {
1323 : // Save the current locale
1324 : pszCurLocale = setlocale(LC_ALL, NULL );
1325 : // Set locale to the specified value
1326 : setlocale( LC_ALL, pszLocale );
1327 : }
1328 : #else
1329 : (void) pszLocale;
1330 : #endif
1331 :
1332 0 : if ( !strftime( pszTemp, nMaxLen + 1, pszFormat, poBrokenTime ) )
1333 0 : memset( pszTemp, 0, nMaxLen + 1);
1334 :
1335 : #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
1336 : // Restore stored locale back
1337 : if ( pszCurLocale )
1338 : setlocale( LC_ALL, pszCurLocale );
1339 : #endif
1340 :
1341 0 : nChars = CPLPrintString( pszBuffer, pszTemp, nMaxLen );
1342 :
1343 0 : CPLFree( pszTemp );
1344 :
1345 0 : return nChars;
1346 : }
1347 :
1348 : #endif
1349 :
1350 : /************************************************************************/
1351 : /* CPLVerifyConfiguration() */
1352 : /************************************************************************/
1353 :
1354 1548005 : void CPLVerifyConfiguration()
1355 :
1356 : {
1357 : /* -------------------------------------------------------------------- */
1358 : /* Verify data types. */
1359 : /* -------------------------------------------------------------------- */
1360 : CPLAssert( sizeof(GInt32) == 4 );
1361 : CPLAssert( sizeof(GInt16) == 2 );
1362 : CPLAssert( sizeof(GByte) == 1 );
1363 :
1364 : if( sizeof(GInt32) != 4 )
1365 : CPLError( CE_Fatal, CPLE_AppDefined,
1366 : "sizeof(GInt32) == %d ... yow!\n",
1367 : (int) sizeof(GInt32) );
1368 :
1369 : /* -------------------------------------------------------------------- */
1370 : /* Verify byte order */
1371 : /* -------------------------------------------------------------------- */
1372 : GInt32 nTest;
1373 :
1374 1548005 : nTest = 1;
1375 :
1376 : #ifdef CPL_LSB
1377 1548005 : if( ((GByte *) &nTest)[0] != 1 )
1378 : #endif
1379 : #ifdef CPL_MSB
1380 : if( ((GByte *) &nTest)[3] != 1 )
1381 : #endif
1382 : CPLError( CE_Fatal, CPLE_AppDefined,
1383 0 : "CPLVerifyConfiguration(): byte order set wrong.\n" );
1384 1548005 : }
1385 :
1386 : /************************************************************************/
1387 : /* CPLGetConfigOption() */
1388 : /************************************************************************/
1389 :
1390 : /**
1391 : * Get the value of a configuration option.
1392 : *
1393 : * The value is the value of a (key, value) option set with CPLSetConfigOption().
1394 : * If the given option was no defined with CPLSetConfigOption(), it tries to find
1395 : * it in environment variables.
1396 : *
1397 : * @param pszKey the key of the option to retrieve
1398 : * @param pszDefault a default value if the key does not match existing defined options (may be NULL)
1399 : * @return the value associated to the key, or the default value if not found
1400 : *
1401 : * @see CPLSetConfigOption(), http://trac.osgeo.org/gdal/wiki/ConfigOptions
1402 : */
1403 : const char * CPL_STDCALL
1404 780724 : CPLGetConfigOption( const char *pszKey, const char *pszDefault )
1405 :
1406 : {
1407 780724 : const char *pszResult = NULL;
1408 :
1409 780724 : char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
1410 780724 : if( papszTLConfigOptions != NULL )
1411 0 : pszResult = CSLFetchNameValue( papszTLConfigOptions, pszKey );
1412 :
1413 780724 : if( pszResult == NULL )
1414 : {
1415 780724 : CPLMutexHolderD( &hConfigMutex );
1416 :
1417 780724 : pszResult = CSLFetchNameValue( (char **) papszConfigOptions, pszKey );
1418 : }
1419 :
1420 : #if !defined(WIN32CE)
1421 780724 : if( pszResult == NULL )
1422 531459 : pszResult = getenv( pszKey );
1423 : #endif
1424 :
1425 780724 : if( pszResult == NULL )
1426 530192 : return pszDefault;
1427 : else
1428 250532 : return pszResult;
1429 : }
1430 :
1431 : /************************************************************************/
1432 : /* CPLSetConfigOption() */
1433 : /************************************************************************/
1434 :
1435 : /**
1436 : * Set a configuration option for GDAL/OGR use.
1437 : *
1438 : * Those options are defined as a (key, value) couple. The value corresponding
1439 : * to a key can be got later with the CPLGetConfigOption() method.
1440 : *
1441 : * This mechanism is similar to environment variables, but options set with
1442 : * CPLSetConfigOption() overrides, for CPLGetConfigOption() point of view,
1443 : * values defined in the environment.
1444 : *
1445 : * If CPLSetConfigOption() is called several times with the same key, the
1446 : * value provided during the last call will be used.
1447 : *
1448 : * Options can also be passed on the command line of most GDAL utilities
1449 : * with the with '--config KEY VALUE'. For example,
1450 : * ogrinfo --config CPL_DEBUG ON ~/data/test/point.shp
1451 : *
1452 : * @param pszKey the key of the option
1453 : * @param pszValue the value of the option
1454 : *
1455 : * @see http://trac.osgeo.org/gdal/wiki/ConfigOptions
1456 : */
1457 : void CPL_STDCALL
1458 264 : CPLSetConfigOption( const char *pszKey, const char *pszValue )
1459 :
1460 : {
1461 264 : CPLMutexHolderD( &hConfigMutex );
1462 :
1463 : papszConfigOptions = (volatile char **)
1464 264 : CSLSetNameValue( (char **) papszConfigOptions, pszKey, pszValue );
1465 264 : }
1466 :
1467 : /************************************************************************/
1468 : /* CPLSetThreadLocalConfigOption() */
1469 : /************************************************************************/
1470 :
1471 : /**
1472 : * Set a configuration option for GDAL/OGR use.
1473 : *
1474 : * Those options are defined as a (key, value) couple. The value corresponding
1475 : * to a key can be got later with the CPLGetConfigOption() method.
1476 : *
1477 : * This function sets the configuration option that only applies in the
1478 : * current thread, as opposed to CPLSetConfigOption() which sets an option
1479 : * that applies on all threads.
1480 : *
1481 : * @param pszKey the key of the option
1482 : * @param pszValue the value of the option
1483 : */
1484 :
1485 : void CPL_STDCALL
1486 0 : CPLSetThreadLocalConfigOption( const char *pszKey, const char *pszValue )
1487 :
1488 : {
1489 0 : char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
1490 :
1491 : papszTLConfigOptions =
1492 0 : CSLSetNameValue( papszTLConfigOptions, pszKey, pszValue );
1493 :
1494 0 : CPLSetTLS( CTLS_CONFIGOPTIONS, papszTLConfigOptions, FALSE );
1495 0 : }
1496 :
1497 : /************************************************************************/
1498 : /* CPLFreeConfig() */
1499 : /************************************************************************/
1500 :
1501 719 : void CPL_STDCALL CPLFreeConfig()
1502 :
1503 : {
1504 719 : CPLMutexHolderD( &hConfigMutex );
1505 :
1506 719 : CSLDestroy( (char **) papszConfigOptions);
1507 719 : papszConfigOptions = NULL;
1508 :
1509 719 : char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
1510 719 : if( papszTLConfigOptions != NULL )
1511 : {
1512 0 : CSLDestroy( papszTLConfigOptions );
1513 0 : CPLSetTLS( CTLS_CONFIGOPTIONS, NULL, FALSE );
1514 719 : }
1515 719 : }
1516 :
1517 : /************************************************************************/
1518 : /* CPLStat() */
1519 : /* */
1520 : /* Same as VSIStat() except it works on "C:" as if it were */
1521 : /* "C:\". */
1522 : /************************************************************************/
1523 :
1524 767 : int CPLStat( const char *pszPath, VSIStatBuf *psStatBuf )
1525 :
1526 : {
1527 767 : if( strlen(pszPath) == 2 && pszPath[1] == ':' )
1528 : {
1529 : char szAltPath[4];
1530 :
1531 0 : szAltPath[0] = pszPath[0];
1532 0 : szAltPath[1] = pszPath[1];
1533 0 : szAltPath[2] = '\\';
1534 0 : szAltPath[3] = '\0';
1535 0 : return VSIStat( szAltPath, psStatBuf );
1536 : }
1537 : else
1538 767 : return VSIStat( pszPath, psStatBuf );
1539 : }
1540 :
1541 : /************************************************************************/
1542 : /* proj_strtod() */
1543 : /************************************************************************/
1544 : static double
1545 242 : proj_strtod(char *nptr, char **endptr)
1546 :
1547 : {
1548 242 : char c, *cp = nptr;
1549 : double result;
1550 :
1551 : /*
1552 : * Scan for characters which cause problems with VC++ strtod()
1553 : */
1554 1651 : while ((c = *cp) != '\0') {
1555 1205 : if (c == 'd' || c == 'D') {
1556 :
1557 : /*
1558 : * Found one, so NUL it out, call strtod(),
1559 : * then restore it and return
1560 : */
1561 38 : *cp = '\0';
1562 38 : result = strtod(nptr, endptr);
1563 38 : *cp = c;
1564 38 : return result;
1565 : }
1566 1167 : ++cp;
1567 : }
1568 :
1569 : /* no offending characters, just handle normally */
1570 :
1571 204 : return strtod(nptr, endptr);
1572 : }
1573 :
1574 : /************************************************************************/
1575 : /* CPLDMSToDec() */
1576 : /************************************************************************/
1577 :
1578 : static const char*sym = "NnEeSsWw";
1579 : static const double vm[] = { 1.0, 0.0166666666667, 0.00027777778 };
1580 :
1581 184 : double CPLDMSToDec( const char *is )
1582 :
1583 : {
1584 : int sign, n, nl;
1585 : char *p, *s, work[64];
1586 : double v, tv;
1587 :
1588 : /* copy sting into work space */
1589 184 : while (isspace((unsigned char)(sign = *is))) ++is;
1590 1409 : for (n = sizeof(work), s = work, p = (char *)is; isgraph(*p) && --n ; )
1591 1041 : *s++ = *p++;
1592 184 : *s = '\0';
1593 : /* it is possible that a really odd input (like lots of leading
1594 : zeros) could be truncated in copying into work. But ... */
1595 184 : sign = *(s = work);
1596 184 : if (sign == '+' || sign == '-') s++;
1597 173 : else sign = '+';
1598 426 : for (v = 0., nl = 0 ; nl < 3 ; nl = n + 1 ) {
1599 254 : if (!(isdigit(*s) || *s == '.')) break;
1600 242 : if ((tv = proj_strtod(s, &s)) == HUGE_VAL)
1601 0 : return tv;
1602 242 : switch (*s) {
1603 : case 'D': case 'd':
1604 38 : n = 0; break;
1605 : case '\'':
1606 32 : n = 1; break;
1607 : case '"':
1608 27 : n = 2; break;
1609 : case 'r': case 'R':
1610 0 : if (nl) {
1611 0 : return 0.0;
1612 : }
1613 0 : ++s;
1614 0 : v = tv;
1615 0 : goto skip;
1616 : default:
1617 145 : v += tv * vm[nl];
1618 145 : skip: n = 4;
1619 145 : continue;
1620 : }
1621 97 : if (n < nl) {
1622 0 : return 0.0;
1623 : }
1624 97 : v += tv * vm[n];
1625 97 : ++s;
1626 : }
1627 : /* postfix sign */
1628 184 : if (*s && (p = (char *) strchr(sym, *s))) {
1629 40 : sign = (p - sym) >= 4 ? '-' : '+';
1630 40 : ++s;
1631 : }
1632 184 : if (sign == '-')
1633 23 : v = -v;
1634 :
1635 184 : return v;
1636 : }
1637 :
1638 :
1639 : /************************************************************************/
1640 : /* CPLDecToDMS() */
1641 : /* */
1642 : /* Translate a decimal degrees value to a DMS string with */
1643 : /* hemisphere. */
1644 : /************************************************************************/
1645 :
1646 : const char *CPLDecToDMS( double dfAngle, const char * pszAxis,
1647 260 : int nPrecision )
1648 :
1649 : {
1650 260 : VALIDATE_POINTER1( pszAxis, "CPLDecToDMS", "" );
1651 :
1652 : int nDegrees, nMinutes;
1653 : double dfSeconds, dfABSAngle, dfEpsilon;
1654 : char szFormat[30];
1655 : const char *pszHemisphere;
1656 : static CPL_THREADLOCAL char szBuffer[50] = { 0 };
1657 :
1658 :
1659 260 : dfEpsilon = (0.5/3600.0) * pow(0.1,nPrecision);
1660 :
1661 260 : dfABSAngle = ABS(dfAngle) + dfEpsilon;
1662 260 : if (dfABSAngle > 361)
1663 : {
1664 0 : return "Invalid angle";
1665 : }
1666 :
1667 260 : nDegrees = (int) dfABSAngle;
1668 260 : nMinutes = (int) ((dfABSAngle - nDegrees) * 60);
1669 260 : dfSeconds = dfABSAngle * 3600 - nDegrees*3600 - nMinutes*60;
1670 :
1671 260 : if( dfSeconds > dfEpsilon * 3600.0 )
1672 260 : dfSeconds -= dfEpsilon * 3600.0;
1673 :
1674 360 : if( EQUAL(pszAxis,"Long") && dfAngle < 0.0 )
1675 100 : pszHemisphere = "W";
1676 160 : else if( EQUAL(pszAxis,"Long") )
1677 30 : pszHemisphere = "E";
1678 130 : else if( dfAngle < 0.0 )
1679 10 : pszHemisphere = "S";
1680 : else
1681 120 : pszHemisphere = "N";
1682 :
1683 260 : sprintf( szFormat, "%%3dd%%2d\'%%.%df\"%s", nPrecision, pszHemisphere );
1684 260 : sprintf( szBuffer, szFormat, nDegrees, nMinutes, dfSeconds );
1685 :
1686 260 : return( szBuffer );
1687 : }
1688 :
1689 : /************************************************************************/
1690 : /* CPLPackedDMSToDec() */
1691 : /************************************************************************/
1692 :
1693 : /**
1694 : * Convert a packed DMS value (DDDMMMSSS.SS) into decimal degrees.
1695 : *
1696 : * This function converts a packed DMS angle to seconds. The standard
1697 : * packed DMS format is:
1698 : *
1699 : * degrees * 1000000 + minutes * 1000 + seconds
1700 : *
1701 : * Example: ang = 120025045.25 yields
1702 : * deg = 120
1703 : * min = 25
1704 : * sec = 45.25
1705 : *
1706 : * The algorithm used for the conversion is as follows:
1707 : *
1708 : * 1. The absolute value of the angle is used.
1709 : *
1710 : * 2. The degrees are separated out:
1711 : * deg = ang/1000000 (fractional portion truncated)
1712 : *
1713 : * 3. The minutes are separated out:
1714 : * min = (ang - deg * 1000000) / 1000 (fractional portion truncated)
1715 : *
1716 : * 4. The seconds are then computed:
1717 : * sec = ang - deg * 1000000 - min * 1000
1718 : *
1719 : * 5. The total angle in seconds is computed:
1720 : * sec = deg * 3600.0 + min * 60.0 + sec
1721 : *
1722 : * 6. The sign of sec is set to that of the input angle.
1723 : *
1724 : * Packed DMS values used by the USGS GCTP package and probably by other
1725 : * software.
1726 : *
1727 : * NOTE: This code does not validate input value. If you give the wrong
1728 : * value, you will get the wrong result.
1729 : *
1730 : * @param dfPacked Angle in packed DMS format.
1731 : *
1732 : * @return Angle in decimal degrees.
1733 : *
1734 : */
1735 :
1736 32 : double CPLPackedDMSToDec( double dfPacked )
1737 : {
1738 : double dfDegrees, dfMinutes, dfSeconds, dfSign;
1739 :
1740 32 : dfSign = ( dfPacked < 0.0 )? -1 : 1;
1741 :
1742 32 : dfSeconds = ABS( dfPacked );
1743 32 : dfDegrees = floor(dfSeconds / 1000000.0);
1744 32 : dfSeconds = dfSeconds - dfDegrees * 1000000.0;
1745 32 : dfMinutes = floor(dfSeconds / 1000.0);
1746 32 : dfSeconds = dfSeconds - dfMinutes * 1000.0;
1747 32 : dfSeconds = dfSign * ( dfDegrees * 3600.0 + dfMinutes * 60.0 + dfSeconds);
1748 32 : dfDegrees = dfSeconds / 3600.0;
1749 :
1750 32 : return dfDegrees;
1751 : }
1752 :
1753 : /************************************************************************/
1754 : /* CPLDecToPackedDMS() */
1755 : /************************************************************************/
1756 : /**
1757 : * Convert decimal degrees into packed DMS value (DDDMMMSSS.SS).
1758 : *
1759 : * This function converts a value, specified in decimal degrees into
1760 : * packed DMS angle. The standard packed DMS format is:
1761 : *
1762 : * degrees * 1000000 + minutes * 1000 + seconds
1763 : *
1764 : * See also CPLPackedDMSToDec().
1765 : *
1766 : * @param dfDec Angle in decimal degrees.
1767 : *
1768 : * @return Angle in packed DMS format.
1769 : *
1770 : */
1771 :
1772 8 : double CPLDecToPackedDMS( double dfDec )
1773 : {
1774 : double dfDegrees, dfMinutes, dfSeconds, dfSign;
1775 :
1776 8 : dfSign = ( dfDec < 0.0 )? -1 : 1;
1777 :
1778 8 : dfDec = ABS( dfDec );
1779 8 : dfDegrees = floor( dfDec );
1780 8 : dfMinutes = floor( ( dfDec - dfDegrees ) * 60.0 );
1781 8 : dfSeconds = ( dfDec - dfDegrees ) * 3600.0 - dfMinutes * 60.0;
1782 :
1783 8 : return dfSign * (dfDegrees * 1000000.0 + dfMinutes * 1000.0 + dfSeconds);
1784 : }
1785 :
1786 : /************************************************************************/
1787 : /* CPLStringToComplex() */
1788 : /************************************************************************/
1789 :
1790 : void CPL_DLL CPLStringToComplex( const char *pszString,
1791 515 : double *pdfReal, double *pdfImag )
1792 :
1793 : {
1794 : int i;
1795 515 : int iPlus = -1, iImagEnd = -1;
1796 :
1797 1030 : while( *pszString == ' ' )
1798 0 : pszString++;
1799 :
1800 515 : *pdfReal = atof(pszString);
1801 515 : *pdfImag = 0.0;
1802 :
1803 1036 : for( i = 0; pszString[i] != '\0' && pszString[i] != ' ' && i < 100; i++ )
1804 : {
1805 521 : if( pszString[i] == '+' && i > 0 )
1806 0 : iPlus = i;
1807 521 : if( pszString[i] == '-' && i > 0 )
1808 0 : iPlus = i;
1809 521 : if( pszString[i] == 'i' )
1810 0 : iImagEnd = i;
1811 : }
1812 :
1813 515 : if( iPlus > -1 && iImagEnd > -1 && iPlus < iImagEnd )
1814 : {
1815 0 : *pdfImag = atof(pszString + iPlus);
1816 : }
1817 :
1818 : return;
1819 : }
1820 :
1821 : /************************************************************************/
1822 : /* CPLOpenShared() */
1823 : /************************************************************************/
1824 :
1825 : /**
1826 : * Open a shared file handle.
1827 : *
1828 : * Some operating systems have limits on the number of file handles that can
1829 : * be open at one time. This function attempts to maintain a registry of
1830 : * already open file handles, and reuse existing ones if the same file
1831 : * is requested by another part of the application.
1832 : *
1833 : * Note that access is only shared for access types "r", "rb", "r+" and
1834 : * "rb+". All others will just result in direct VSIOpen() calls. Keep in
1835 : * mind that a file is only reused if the file name is exactly the same.
1836 : * Different names referring to the same file will result in different
1837 : * handles.
1838 : *
1839 : * The VSIFOpen() or VSIFOpenL() function is used to actually open the file,
1840 : * when an existing file handle can't be shared.
1841 : *
1842 : * @param pszFilename the name of the file to open.
1843 : * @param pszAccess the normal fopen()/VSIFOpen() style access string.
1844 : * @param bLarge If TRUE VSIFOpenL() (for large files) will be used instead of
1845 : * VSIFOpen().
1846 : *
1847 : * @return a file handle or NULL if opening fails.
1848 : */
1849 :
1850 : FILE *CPLOpenShared( const char *pszFilename, const char *pszAccess,
1851 9 : int bLarge )
1852 :
1853 : {
1854 : int i;
1855 : int bReuse;
1856 9 : CPLMutexHolderD( &hSharedFileMutex );
1857 :
1858 : /* -------------------------------------------------------------------- */
1859 : /* Is there an existing file we can use? */
1860 : /* -------------------------------------------------------------------- */
1861 9 : bReuse = EQUAL(pszAccess,"rb") || EQUAL(pszAccess, "rb+");
1862 :
1863 11 : for( i = 0; bReuse && i < nSharedFileCount; i++ )
1864 : {
1865 5 : if( strcmp(pasSharedFileList[i].pszFilename,pszFilename) == 0
1866 : && !bLarge == !pasSharedFileList[i].bLarge
1867 : && EQUAL(pasSharedFileList[i].pszAccess,pszAccess) )
1868 : {
1869 3 : pasSharedFileList[i].nRefCount++;
1870 3 : return pasSharedFileList[i].fp;
1871 : }
1872 : }
1873 :
1874 : /* -------------------------------------------------------------------- */
1875 : /* Open the file. */
1876 : /* -------------------------------------------------------------------- */
1877 : FILE *fp;
1878 :
1879 6 : if( bLarge )
1880 6 : fp = VSIFOpenL( pszFilename, pszAccess );
1881 : else
1882 0 : fp = VSIFOpen( pszFilename, pszAccess );
1883 :
1884 6 : if( fp == NULL )
1885 0 : return NULL;
1886 :
1887 : /* -------------------------------------------------------------------- */
1888 : /* Add an entry to the list. */
1889 : /* -------------------------------------------------------------------- */
1890 6 : nSharedFileCount++;
1891 :
1892 : pasSharedFileList = (CPLSharedFileInfo *)
1893 : CPLRealloc( (void *) pasSharedFileList,
1894 6 : sizeof(CPLSharedFileInfo) * nSharedFileCount );
1895 :
1896 6 : pasSharedFileList[nSharedFileCount-1].fp = fp;
1897 6 : pasSharedFileList[nSharedFileCount-1].nRefCount = 1;
1898 6 : pasSharedFileList[nSharedFileCount-1].bLarge = bLarge;
1899 6 : pasSharedFileList[nSharedFileCount-1].pszFilename =CPLStrdup(pszFilename);
1900 6 : pasSharedFileList[nSharedFileCount-1].pszAccess = CPLStrdup(pszAccess);
1901 :
1902 6 : return fp;
1903 : }
1904 :
1905 : /************************************************************************/
1906 : /* CPLCloseShared() */
1907 : /************************************************************************/
1908 :
1909 : /**
1910 : * Close shared file.
1911 : *
1912 : * Dereferences the indicated file handle, and closes it if the reference
1913 : * count has dropped to zero. A CPLError() is issued if the file is not
1914 : * in the shared file list.
1915 : *
1916 : * @param fp file handle from CPLOpenShared() to deaccess.
1917 : */
1918 :
1919 9 : void CPLCloseShared( FILE * fp )
1920 :
1921 : {
1922 9 : CPLMutexHolderD( &hSharedFileMutex );
1923 : int i;
1924 :
1925 : /* -------------------------------------------------------------------- */
1926 : /* Search for matching information. */
1927 : /* -------------------------------------------------------------------- */
1928 9 : for( i = 0; i < nSharedFileCount && fp != pasSharedFileList[i].fp; i++ ){}
1929 :
1930 9 : if( i == nSharedFileCount )
1931 : {
1932 : CPLError( CE_Failure, CPLE_AppDefined,
1933 : "Unable to find file handle %p in CPLCloseShared().",
1934 0 : fp );
1935 3 : return;
1936 : }
1937 :
1938 : /* -------------------------------------------------------------------- */
1939 : /* Dereference and return if there are still some references. */
1940 : /* -------------------------------------------------------------------- */
1941 9 : if( --pasSharedFileList[i].nRefCount > 0 )
1942 : return;
1943 :
1944 : /* -------------------------------------------------------------------- */
1945 : /* Close the file, and remove the information. */
1946 : /* -------------------------------------------------------------------- */
1947 6 : if( pasSharedFileList[i].bLarge )
1948 6 : VSIFCloseL( pasSharedFileList[i].fp );
1949 : else
1950 0 : VSIFClose( pasSharedFileList[i].fp );
1951 :
1952 6 : CPLFree( pasSharedFileList[i].pszFilename );
1953 6 : CPLFree( pasSharedFileList[i].pszAccess );
1954 :
1955 : // pasSharedFileList[i] = pasSharedFileList[--nSharedFileCount];
1956 : memcpy( (void *) (pasSharedFileList + i),
1957 : (void *) (pasSharedFileList + --nSharedFileCount),
1958 6 : sizeof(CPLSharedFileInfo) );
1959 :
1960 6 : if( nSharedFileCount == 0 )
1961 : {
1962 5 : CPLFree( (void *) pasSharedFileList );
1963 5 : pasSharedFileList = NULL;
1964 0 : }
1965 : }
1966 :
1967 : /************************************************************************/
1968 : /* CPLGetSharedList() */
1969 : /************************************************************************/
1970 :
1971 : /**
1972 : * Fetch list of open shared files.
1973 : *
1974 : * @param pnCount place to put the count of entries.
1975 : *
1976 : * @return the pointer to the first in the array of shared file info
1977 : * structures.
1978 : */
1979 :
1980 0 : CPLSharedFileInfo *CPLGetSharedList( int *pnCount )
1981 :
1982 : {
1983 0 : if( pnCount != NULL )
1984 0 : *pnCount = nSharedFileCount;
1985 :
1986 0 : return (CPLSharedFileInfo *) pasSharedFileList;
1987 : }
1988 :
1989 : /************************************************************************/
1990 : /* CPLDumpSharedList() */
1991 : /************************************************************************/
1992 :
1993 : /**
1994 : * Report open shared files.
1995 : *
1996 : * Dumps all open shared files to the indicated file handle. If the
1997 : * file handle is NULL information is sent via the CPLDebug() call.
1998 : *
1999 : * @param fp File handle to write to.
2000 : */
2001 :
2002 17 : void CPLDumpSharedList( FILE *fp )
2003 :
2004 : {
2005 : int i;
2006 :
2007 17 : if( nSharedFileCount > 0 )
2008 : {
2009 0 : if( fp == NULL )
2010 0 : CPLDebug( "CPL", "%d Shared files open.", nSharedFileCount );
2011 : else
2012 0 : fprintf( fp, "%d Shared files open.", nSharedFileCount );
2013 : }
2014 :
2015 17 : for( i = 0; i < nSharedFileCount; i++ )
2016 : {
2017 0 : if( fp == NULL )
2018 : CPLDebug( "CPL",
2019 : "%2d %d %4s %s",
2020 : pasSharedFileList[i].nRefCount,
2021 : pasSharedFileList[i].bLarge,
2022 : pasSharedFileList[i].pszAccess,
2023 0 : pasSharedFileList[i].pszFilename );
2024 : else
2025 : fprintf( fp, "%2d %d %4s %s",
2026 : pasSharedFileList[i].nRefCount,
2027 : pasSharedFileList[i].bLarge,
2028 : pasSharedFileList[i].pszAccess,
2029 0 : pasSharedFileList[i].pszFilename );
2030 : }
2031 17 : }
2032 :
2033 : /************************************************************************/
2034 : /* CPLUnlinkTree() */
2035 : /************************************************************************/
2036 :
2037 : /**
2038 : * @return 0 on successful completion, -1 if function fails.
2039 : */
2040 :
2041 14 : int CPLUnlinkTree( const char *pszPath )
2042 :
2043 : {
2044 : /* -------------------------------------------------------------------- */
2045 : /* First, ensure there isn't any such file yet. */
2046 : /* -------------------------------------------------------------------- */
2047 : VSIStatBuf sStatBuf;
2048 :
2049 14 : if( VSIStat( pszPath, &sStatBuf ) != 0 )
2050 : {
2051 : CPLError( CE_Failure, CPLE_AppDefined,
2052 : "It seems no file system object called '%s' exists.",
2053 2 : pszPath );
2054 :
2055 2 : return -1;
2056 : }
2057 :
2058 : /* -------------------------------------------------------------------- */
2059 : /* If it's a simple file, just delete it. */
2060 : /* -------------------------------------------------------------------- */
2061 12 : if( VSI_ISREG( sStatBuf.st_mode ) )
2062 : {
2063 11 : if( VSIUnlink( pszPath ) != 0 )
2064 : {
2065 : CPLError( CE_Failure, CPLE_AppDefined, "Failed to unlink %s.",
2066 0 : pszPath );
2067 :
2068 0 : return -1;
2069 : }
2070 : else
2071 11 : return 0;
2072 : }
2073 :
2074 : /* -------------------------------------------------------------------- */
2075 : /* If it is a directory recurse then unlink the directory. */
2076 : /* -------------------------------------------------------------------- */
2077 1 : else if( VSI_ISDIR( sStatBuf.st_mode ) )
2078 : {
2079 1 : char **papszItems = CPLReadDir( pszPath );
2080 : int i;
2081 :
2082 14 : for( i = 0; papszItems != NULL && papszItems[i] != NULL; i++ )
2083 : {
2084 : char *pszSubPath;
2085 : int nErr;
2086 :
2087 13 : if( EQUAL(papszItems[i],".") || EQUAL(papszItems[i],"..") )
2088 2 : continue;
2089 :
2090 : pszSubPath = CPLStrdup(
2091 11 : CPLFormFilename( pszPath, papszItems[i], NULL ) );
2092 :
2093 11 : nErr = CPLUnlinkTree( pszSubPath );
2094 11 : CPLFree( pszSubPath );
2095 :
2096 11 : if( nErr != 0 )
2097 : {
2098 0 : CSLDestroy( papszItems );
2099 0 : return nErr;
2100 : }
2101 : }
2102 :
2103 1 : CSLDestroy( papszItems );
2104 :
2105 1 : if( VSIRmdir( pszPath ) != 0 )
2106 : {
2107 : CPLError( CE_Failure, CPLE_AppDefined, "Failed to unlink %s.",
2108 0 : pszPath );
2109 :
2110 0 : return -1;
2111 : }
2112 : else
2113 1 : return 0;
2114 : }
2115 :
2116 : /* -------------------------------------------------------------------- */
2117 : /* otherwise report an error. */
2118 : /* -------------------------------------------------------------------- */
2119 : else
2120 : {
2121 : CPLError( CE_Failure, CPLE_AppDefined,
2122 : "Failed to unlink %s.\nUnrecognised filesystem object.",
2123 0 : pszPath );
2124 0 : return 1000;
2125 : }
2126 : }
2127 :
2128 : /************************************************************************/
2129 : /* CPLCopyFile() */
2130 : /************************************************************************/
2131 :
2132 0 : int CPLCopyFile( const char *pszNewPath, const char *pszOldPath )
2133 :
2134 : {
2135 : FILE *fpOld, *fpNew;
2136 : GByte *pabyBuffer;
2137 : size_t nBufferSize;
2138 : size_t nBytesRead;
2139 0 : int nRet = 0;
2140 :
2141 : /* -------------------------------------------------------------------- */
2142 : /* Open old and new file. */
2143 : /* -------------------------------------------------------------------- */
2144 0 : fpOld = VSIFOpenL( pszOldPath, "rb" );
2145 0 : if( fpOld == NULL )
2146 0 : return -1;
2147 :
2148 0 : fpNew = VSIFOpenL( pszNewPath, "wb" );
2149 0 : if( fpNew == NULL )
2150 : {
2151 0 : VSIFCloseL( fpOld );
2152 0 : return -1;
2153 : }
2154 :
2155 : /* -------------------------------------------------------------------- */
2156 : /* Prepare buffer. */
2157 : /* -------------------------------------------------------------------- */
2158 0 : nBufferSize = 1024 * 1024;
2159 0 : pabyBuffer = (GByte *) CPLMalloc(nBufferSize);
2160 :
2161 : /* -------------------------------------------------------------------- */
2162 : /* Copy file over till we run out of stuff. */
2163 : /* -------------------------------------------------------------------- */
2164 0 : do {
2165 0 : nBytesRead = VSIFReadL( pabyBuffer, 1, nBufferSize, fpOld );
2166 : if( nBytesRead < 0 )
2167 : nRet = -1;
2168 :
2169 0 : if( nRet == 0
2170 : && VSIFWriteL( pabyBuffer, 1, nBytesRead, fpNew ) < nBytesRead )
2171 0 : nRet = -1;
2172 : } while( nRet == 0 && nBytesRead == nBufferSize );
2173 :
2174 : /* -------------------------------------------------------------------- */
2175 : /* Cleanup */
2176 : /* -------------------------------------------------------------------- */
2177 0 : VSIFCloseL( fpNew );
2178 0 : VSIFCloseL( fpOld );
2179 :
2180 0 : CPLFree( pabyBuffer );
2181 :
2182 0 : return nRet;
2183 : }
2184 :
2185 : /************************************************************************/
2186 : /* CPLMoveFile() */
2187 : /************************************************************************/
2188 :
2189 0 : int CPLMoveFile( const char *pszNewPath, const char *pszOldPath )
2190 :
2191 : {
2192 0 : if( VSIRename( pszNewPath, pszOldPath ) == 0 )
2193 0 : return 0;
2194 :
2195 0 : int nRet = CPLCopyFile( pszNewPath, pszOldPath );
2196 :
2197 0 : if( nRet == 0 )
2198 0 : VSIUnlink( pszOldPath );
2199 :
2200 0 : return nRet;
2201 : }
2202 :
2203 : /************************************************************************/
2204 : /* ==================================================================== */
2205 : /* CPLLocaleC */
2206 : /* ==================================================================== */
2207 : /************************************************************************/
2208 :
2209 : #include <locale.h>
2210 :
2211 : /************************************************************************/
2212 : /* CPLLocaleC() */
2213 : /************************************************************************/
2214 :
2215 41322 : CPLLocaleC::CPLLocaleC() : pszOldLocale(CPLStrdup(setlocale(LC_NUMERIC,NULL)))
2216 :
2217 : {
2218 41322 : if( setlocale(LC_NUMERIC,"C") == NULL )
2219 : {
2220 0 : CPLFree( pszOldLocale );
2221 0 : pszOldLocale = NULL;
2222 : }
2223 41322 : }
2224 :
2225 : /************************************************************************/
2226 : /* ~CPLLocaleC() */
2227 : /************************************************************************/
2228 :
2229 41322 : CPLLocaleC::~CPLLocaleC()
2230 :
2231 : {
2232 41322 : if( pszOldLocale != NULL )
2233 : {
2234 41322 : setlocale( LC_NUMERIC, pszOldLocale );
2235 41322 : CPLFree( pszOldLocale );
2236 : }
2237 41322 : }
2238 :
2239 : /************************************************************************/
2240 : /* CPLCheckForFile() */
2241 : /************************************************************************/
2242 :
2243 : /**
2244 : * Check for file existance.
2245 : *
2246 : * The function checks if a named file exists in the filesystem, hopefully
2247 : * in an efficient fashion if a sibling file list is available. It exists
2248 : * primarily to do faster file checking for functions like GDAL open methods
2249 : * that get a list of files from the target directory.
2250 : *
2251 : * If the sibling file list exists (is not NULL) it is assumed to be a list
2252 : * of files in the same directory as the target file, and it will be checked
2253 : * (case insensitively) for a match. If a match is found, pszFilename is
2254 : * updated with the correct case and TRUE is returned.
2255 : *
2256 : * If papszSiblingFiles is NULL, a VSIStatL() is used to test for the files
2257 : * existance, and no case insensitive testing is done.
2258 : *
2259 : * @param pszFilename name of file to check for - filename case updated in some cases.
2260 : * @param papszSiblingFiles a list of files in the same directory as
2261 : * pszFilename if available, or NULL. This list should have no path components.
2262 : *
2263 : * @return TRUE if a match is found, or FALSE if not.
2264 : */
2265 :
2266 6690 : int CPLCheckForFile( char *pszFilename, char **papszSiblingFiles )
2267 :
2268 : {
2269 : /* -------------------------------------------------------------------- */
2270 : /* Fallback case if we don't have a sibling file list. */
2271 : /* -------------------------------------------------------------------- */
2272 6690 : if( papszSiblingFiles == NULL )
2273 : {
2274 : VSIStatBufL sStatBuf;
2275 :
2276 6662 : return VSIStatL( pszFilename, &sStatBuf ) == 0;
2277 : }
2278 :
2279 : /* -------------------------------------------------------------------- */
2280 : /* We have sibling files, compare the non-path filename portion */
2281 : /* of pszFilename too all entries. */
2282 : /* -------------------------------------------------------------------- */
2283 28 : CPLString osFileOnly = CPLGetFilename( pszFilename );
2284 : int i;
2285 :
2286 2532 : for( i = 0; papszSiblingFiles[i] != NULL; i++ )
2287 : {
2288 2506 : if( EQUAL(papszSiblingFiles[i],osFileOnly) )
2289 : {
2290 : strcpy( pszFilename + strlen(pszFilename) - strlen(osFileOnly),
2291 2 : papszSiblingFiles[i] );
2292 30 : return TRUE;
2293 : }
2294 : }
2295 :
2296 26 : return FALSE;
2297 : }
|