1 : /******************************************************************************
2 : * $Id: cpl_conv.cpp 18060 2009-11-21 20:26:25Z rouault $
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 18060 2009-11-21 20:26:25Z rouault $");
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 1040074 : void *CPLCalloc( size_t nCount, size_t nSize )
73 :
74 : {
75 : void *pReturn;
76 :
77 1040074 : if( nSize * nCount == 0 )
78 14902 : return NULL;
79 :
80 1025172 : pReturn = VSICalloc( nCount, nSize );
81 1025172 : 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 1025172 : 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 1078343 : void *CPLMalloc( size_t nSize )
111 :
112 : {
113 : void *pReturn;
114 :
115 1078343 : CPLVerifyConfiguration();
116 :
117 1078343 : if( nSize == 0 )
118 1035 : 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 1077308 : pReturn = VSIMalloc( nSize );
129 1077308 : 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 1077308 : 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 1427520 : void * CPLRealloc( void * pData, size_t nNewSize )
164 :
165 : {
166 : void *pReturn;
167 :
168 1427520 : if ( nNewSize == 0 )
169 : {
170 259 : VSIFree(pData);
171 259 : 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 1427261 : if( pData == NULL )
183 217219 : pReturn = VSIMalloc( nNewSize );
184 : else
185 1210042 : pReturn = VSIRealloc( pData, nNewSize );
186 :
187 1427261 : 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 1427261 : 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 2137802 : char *CPLStrdup( const char * pszString )
220 :
221 : {
222 : char *pszReturn;
223 :
224 2137802 : if( pszString == NULL )
225 94711 : pszString = "";
226 :
227 2137802 : pszReturn = VSIStrdup( pszString );
228 :
229 2137802 : 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 2137802 : 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 5 : char *CPLStrlwr( char *pszString )
255 :
256 : {
257 5 : if (pszString)
258 : {
259 5 : char *pszTemp = pszString;
260 :
261 25 : while (*pszTemp)
262 : {
263 15 : *pszTemp = (char) tolower (*pszTemp);
264 15 : pszTemp++;
265 : }
266 : }
267 :
268 5 : 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 197863 : char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
296 :
297 : {
298 : int nActuallyRead, nOriginalOffset;
299 :
300 197863 : 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 197863 : nOriginalOffset = VSIFTell( fp );
311 197863 : if( VSIFGets( pszBuffer, nBufferSize, fp ) == NULL )
312 148 : return NULL;
313 :
314 197715 : nActuallyRead = strlen(pszBuffer);
315 197715 : 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 293376 : if( nBufferSize == nActuallyRead+1
323 95661 : && 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 536060 : if( nActuallyRead > 1
339 197301 : && pszBuffer[nActuallyRead-1] == 10
340 101909 : && pszBuffer[nActuallyRead-2] == 13 )
341 : {
342 39135 : pszBuffer[nActuallyRead-2] = '\0';
343 : }
344 253972 : else if( pszBuffer[nActuallyRead-1] == 10
345 95392 : || pszBuffer[nActuallyRead-1] == 13 )
346 : {
347 63188 : 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 197715 : char *pszExtraNewline = strchr( pszBuffer, 13 );
356 :
357 197715 : 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 197715 : 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 323397 : static char *CPLReadLineBuffer( int nRequiredSize )
399 :
400 : {
401 :
402 : /* -------------------------------------------------------------------- */
403 : /* A required size of -1 means the buffer should be freed. */
404 : /* -------------------------------------------------------------------- */
405 323397 : if( nRequiredSize == -1 )
406 : {
407 353 : if( CPLGetTLS( CTLS_RLBUFFERINFO ) != NULL )
408 : {
409 353 : CPLFree( CPLGetTLS( CTLS_RLBUFFERINFO ) );
410 353 : CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
411 : }
412 353 : return NULL;
413 : }
414 :
415 : /* -------------------------------------------------------------------- */
416 : /* If the buffer doesn't exist yet, create it. */
417 : /* -------------------------------------------------------------------- */
418 323044 : GUInt32 *pnAlloc = (GUInt32 *) CPLGetTLS( CTLS_RLBUFFERINFO );
419 :
420 323044 : if( pnAlloc == NULL )
421 : {
422 406 : pnAlloc = (GUInt32 *) CPLMalloc(200);
423 406 : *pnAlloc = 196;
424 406 : CPLSetTLS( CTLS_RLBUFFERINFO, pnAlloc, TRUE );
425 : }
426 :
427 : /* -------------------------------------------------------------------- */
428 : /* If it is too small, grow it bigger. */
429 : /* -------------------------------------------------------------------- */
430 323044 : if( (int) *pnAlloc < nRequiredSize+1 )
431 : {
432 235 : int nNewSize = nRequiredSize + 4 + 500;
433 :
434 235 : GUInt32* pnAllocNew = (GUInt32 *) VSIRealloc(pnAlloc,nNewSize);
435 235 : if( pnAllocNew == NULL )
436 : {
437 0 : VSIFree( pnAlloc );
438 0 : CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
439 0 : return NULL;
440 : }
441 235 : pnAlloc = pnAllocNew;
442 :
443 235 : *pnAlloc = nNewSize - 4;
444 235 : CPLSetTLS( CTLS_RLBUFFERINFO, pnAlloc, TRUE );
445 : }
446 :
447 323044 : 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 102585 : const char *CPLReadLine( FILE * fp )
477 :
478 : {
479 102585 : char *pszRLBuffer = CPLReadLineBuffer(1);
480 102585 : int nReadSoFar = 0;
481 :
482 : /* -------------------------------------------------------------------- */
483 : /* Cleanup case. */
484 : /* -------------------------------------------------------------------- */
485 102585 : if( fp == NULL )
486 : {
487 106 : CPLReadLineBuffer( -1 );
488 106 : 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 388459 : 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 197854 : pszRLBuffer = CPLReadLineBuffer( nReadSoFar + 129 );
504 197854 : if( pszRLBuffer == NULL )
505 0 : return NULL;
506 :
507 : /* -------------------------------------------------------------------- */
508 : /* Do the actual read. */
509 : /* -------------------------------------------------------------------- */
510 197854 : if( CPLFGets( pszRLBuffer+nReadSoFar, 128, fp ) == NULL
511 : && nReadSoFar == 0 )
512 145 : return NULL;
513 :
514 197709 : nBytesReadThisTime = strlen(pszRLBuffer+nReadSoFar);
515 197709 : nReadSoFar += nBytesReadThisTime;
516 :
517 : } while( nBytesReadThisTime >= 127
518 95375 : && pszRLBuffer[nReadSoFar-1] != 13
519 95375 : && pszRLBuffer[nReadSoFar-1] != 10 );
520 :
521 102334 : 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 18741 : const char *CPLReadLineL( FILE * fp )
540 : {
541 18741 : 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 21046 : const char *CPLReadLine2L( FILE * fp, int nMaxCars, char** papszOptions )
565 :
566 : {
567 : /* -------------------------------------------------------------------- */
568 : /* Cleanup case. */
569 : /* -------------------------------------------------------------------- */
570 21046 : if( fp == NULL )
571 : {
572 247 : CPLReadLineBuffer( -1 );
573 247 : 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 20799 : const size_t nChunkSize = 40;
582 : char szChunk[nChunkSize];
583 20799 : size_t nChunkBytesRead = 0;
584 20799 : int nBufLength = 0;
585 20799 : size_t nChunkBytesConsumed = 0;
586 :
587 1806 : while( TRUE )
588 : {
589 : /* -------------------------------------------------------------------- */
590 : /* Read a chunk from the input file. */
591 : /* -------------------------------------------------------------------- */
592 22605 : pszRLBuffer = CPLReadLineBuffer( nBufLength + nChunkSize + 1 );
593 :
594 22605 : if( nChunkBytesRead == nChunkBytesConsumed + 1 )
595 : {
596 :
597 : // case where one character is left over from last read.
598 1806 : szChunk[0] = szChunk[nChunkBytesConsumed];
599 :
600 1806 : nChunkBytesConsumed = 0;
601 1806 : nChunkBytesRead = VSIFReadL( szChunk+1, 1, nChunkSize-1, fp ) + 1;
602 : }
603 : else
604 : {
605 20799 : nChunkBytesConsumed = 0;
606 :
607 : // fresh read.
608 20799 : nChunkBytesRead = VSIFReadL( szChunk, 1, nChunkSize, fp );
609 20799 : if( nChunkBytesRead == 0 )
610 : {
611 253 : if( nBufLength == 0 )
612 253 : return NULL;
613 : else
614 0 : break;
615 : }
616 : }
617 :
618 : /* -------------------------------------------------------------------- */
619 : /* copy over characters watching for end-of-line. */
620 : /* -------------------------------------------------------------------- */
621 22352 : int bBreak = FALSE;
622 375015 : while( nChunkBytesConsumed < nChunkBytesRead-1 && !bBreak )
623 : {
624 680662 : if( (szChunk[nChunkBytesConsumed] == 13
625 14295 : && szChunk[nChunkBytesConsumed+1] == 10)
626 316016 : || (szChunk[nChunkBytesConsumed] == 10
627 5745 : && szChunk[nChunkBytesConsumed+1] == 13) )
628 : {
629 14295 : nChunkBytesConsumed += 2;
630 14295 : bBreak = TRUE;
631 : }
632 632032 : else if( szChunk[nChunkBytesConsumed] == 10
633 310271 : || szChunk[nChunkBytesConsumed] == 13 )
634 : {
635 5745 : nChunkBytesConsumed += 1;
636 5745 : bBreak = TRUE;
637 : }
638 : else
639 : {
640 310271 : pszRLBuffer[nBufLength++] = szChunk[nChunkBytesConsumed++];
641 310271 : 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 22352 : if( bBreak )
651 20040 : 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 2312 : if( nChunkBytesConsumed == nChunkBytesRead-1
659 : && nChunkBytesRead < nChunkSize )
660 : {
661 661 : if( szChunk[nChunkBytesConsumed] == 10
662 155 : || szChunk[nChunkBytesConsumed] == 13 )
663 : {
664 351 : nChunkBytesConsumed++;
665 351 : break;
666 : }
667 :
668 155 : pszRLBuffer[nBufLength++] = szChunk[nChunkBytesConsumed++];
669 155 : 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 20546 : if( nChunkBytesConsumed < nChunkBytesRead )
678 : {
679 18907 : size_t nBytesToPush = nChunkBytesRead - nChunkBytesConsumed;
680 :
681 18907 : VSIFSeekL( fp, VSIFTellL( fp ) - nBytesToPush, SEEK_SET );
682 : }
683 :
684 20546 : pszRLBuffer[nBufLength] = '\0';
685 :
686 20546 : 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 225 : char *CPLScanString( const char *pszString, int nMaxLength,
714 : int bTrimSpaces, int bNormalize )
715 : {
716 : char *pszBuffer;
717 :
718 225 : if ( !pszString )
719 0 : return NULL;
720 :
721 225 : if ( !nMaxLength )
722 2 : return CPLStrdup( "" );
723 :
724 223 : pszBuffer = (char *)CPLMalloc( nMaxLength + 1 );
725 223 : if ( !pszBuffer )
726 0 : return NULL;
727 :
728 223 : strncpy( pszBuffer, pszString, nMaxLength );
729 223 : pszBuffer[nMaxLength] = '\0';
730 :
731 223 : if ( bTrimSpaces )
732 : {
733 223 : size_t i = strlen( pszBuffer );
734 1013 : while ( i-- > 0 && isspace((unsigned char)pszBuffer[i]) )
735 567 : pszBuffer[i] = '\0';
736 : }
737 :
738 223 : if ( bNormalize )
739 : {
740 162 : size_t i = strlen( pszBuffer );
741 1599 : while ( i-- > 0 )
742 : {
743 1275 : if ( pszBuffer[i] == ':' )
744 0 : pszBuffer[i] = '_';
745 : }
746 : }
747 :
748 223 : 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 2 : long CPLScanLong( const char *pszString, int nMaxLength )
770 : {
771 : long iValue;
772 2 : char *pszValue = (char *)CPLMalloc( nMaxLength + 1);
773 :
774 : /* -------------------------------------------------------------------- */
775 : /* Compute string into local buffer, and terminate it. */
776 : /* -------------------------------------------------------------------- */
777 2 : strncpy( pszValue, pszString, nMaxLength );
778 2 : pszValue[nMaxLength] = '\0';
779 :
780 : /* -------------------------------------------------------------------- */
781 : /* Use atol() to fetch out the result */
782 : /* -------------------------------------------------------------------- */
783 2 : iValue = atol( pszValue );
784 :
785 2 : CPLFree( pszValue );
786 2 : 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 7199 : GUIntBig CPLScanUIntBig( const char *pszString, int nMaxLength )
849 : {
850 : GUIntBig iValue;
851 7199 : char *pszValue = (char *)CPLMalloc( nMaxLength + 1);
852 :
853 : /* -------------------------------------------------------------------- */
854 : /* Compute string into local buffer, and terminate it. */
855 : /* -------------------------------------------------------------------- */
856 7199 : strncpy( pszValue, pszString, nMaxLength );
857 7199 : 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 7199 : iValue = atoll( pszValue );
866 : #else
867 : iValue = atol( pszValue );
868 : #endif
869 :
870 7199 : CPLFree( pszValue );
871 7199 : 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 22 : 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 22 : if( nMaxLength > (int) sizeof(szTemp)-1 )
903 0 : nMaxLength = sizeof(szTemp)-1;
904 :
905 22 : strncpy( szTemp, pszString, nMaxLength );
906 22 : szTemp[nMaxLength] = '\0';
907 :
908 : /* -------------------------------------------------------------------- */
909 : /* On MSVC we have to scanf pointer values without the 0x */
910 : /* prefix. */
911 : /* -------------------------------------------------------------------- */
912 22 : if( EQUALN(szTemp,"0x",2) )
913 : {
914 22 : pResult = NULL;
915 :
916 : #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
917 : sscanf( szTemp+2, "%p", &pResult );
918 : #else
919 22 : sscanf( szTemp, "%p", &pResult );
920 : #endif
921 : }
922 :
923 : else
924 : {
925 : #if SIZEOF_VOIDP == 8
926 : pResult = (void *) CPLScanUIntBig( szTemp, nMaxLength );
927 : #else
928 0 : pResult = (void *) CPLScanULong( szTemp, nMaxLength );
929 : #endif
930 : }
931 :
932 22 : 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 63 : int CPLPrintString( char *pszDest, const char *pszSrc, int nMaxLen )
1004 : {
1005 63 : char *pszTemp = pszDest;
1006 63 : int nChars = 0;
1007 :
1008 63 : if ( !pszDest )
1009 0 : return 0;
1010 :
1011 63 : if ( !pszSrc )
1012 : {
1013 0 : *pszDest = '\0';
1014 0 : return 1;
1015 : }
1016 :
1017 2785 : while ( nChars < nMaxLen && *pszSrc )
1018 : {
1019 2659 : *pszTemp++ = *pszSrc++;
1020 2659 : nChars++;
1021 : }
1022 :
1023 63 : 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 34 : int CPLPrintStringFill( char *pszDest, const char *pszSrc, int nMaxLen )
1048 : {
1049 34 : char *pszTemp = pszDest;
1050 :
1051 34 : if ( !pszDest )
1052 0 : return 0;
1053 :
1054 34 : if ( !pszSrc )
1055 : {
1056 0 : memset( pszDest, ' ', nMaxLen );
1057 0 : return nMaxLen;
1058 : }
1059 :
1060 262 : while ( nMaxLen && *pszSrc )
1061 : {
1062 194 : *pszTemp++ = *pszSrc++;
1063 194 : nMaxLen--;
1064 : }
1065 :
1066 34 : if ( nMaxLen )
1067 17 : memset( pszTemp, ' ', nMaxLen );
1068 :
1069 34 : 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 40 : int CPLPrintUIntBig( char *pszBuffer, GUIntBig iValue, int nMaxLen )
1132 : {
1133 : char szTemp[64];
1134 :
1135 40 : if ( !pszBuffer )
1136 0 : return 0;
1137 :
1138 40 : 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 40 : 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 40 : 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 22 : int CPLPrintPointer( char *pszBuffer, void *pValue, int nMaxLen )
1174 : {
1175 : char szTemp[64];
1176 :
1177 22 : if ( !pszBuffer )
1178 0 : return 0;
1179 :
1180 22 : if ( nMaxLen >= 64 )
1181 22 : nMaxLen = 63;
1182 :
1183 22 : 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 22 : if( !EQUALN(szTemp,"0x",2) )
1190 0 : sprintf( szTemp, "0x%p", pValue );
1191 :
1192 22 : 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 0 : int CPLPrintDouble( char *pszBuffer, const char *pszFormat,
1223 : 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 0 : int CPLPrintTime( char *pszBuffer, int nMaxLen, const char *pszFormat,
1313 : 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 1078343 : 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 1078343 : nTest = 1;
1375 :
1376 : #ifdef CPL_LSB
1377 1078343 : 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 1078343 : }
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()
1402 : */
1403 : const char * CPL_STDCALL
1404 730395 : CPLGetConfigOption( const char *pszKey, const char *pszDefault )
1405 :
1406 : {
1407 730395 : const char *pszResult = NULL;
1408 :
1409 730395 : char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
1410 730395 : if( papszTLConfigOptions != NULL )
1411 0 : pszResult = CSLFetchNameValue( papszTLConfigOptions, pszKey );
1412 :
1413 730395 : if( pszResult == NULL )
1414 : {
1415 730395 : CPLMutexHolderD( &hConfigMutex );
1416 :
1417 730395 : pszResult = CSLFetchNameValue( (char **) papszConfigOptions, pszKey );
1418 : }
1419 :
1420 : #if !defined(WIN32CE)
1421 730395 : if( pszResult == NULL )
1422 497648 : pszResult = getenv( pszKey );
1423 : #endif
1424 :
1425 730395 : if( pszResult == NULL )
1426 497016 : return pszDefault;
1427 : else
1428 233379 : 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 : void CPL_STDCALL
1456 124 : CPLSetConfigOption( const char *pszKey, const char *pszValue )
1457 :
1458 : {
1459 124 : CPLMutexHolderD( &hConfigMutex );
1460 :
1461 : papszConfigOptions = (volatile char **)
1462 124 : CSLSetNameValue( (char **) papszConfigOptions, pszKey, pszValue );
1463 124 : }
1464 :
1465 : /************************************************************************/
1466 : /* CPLSetThreadLocalConfigOption() */
1467 : /************************************************************************/
1468 :
1469 : /**
1470 : * Set a configuration option for GDAL/OGR use.
1471 : *
1472 : * Those options are defined as a (key, value) couple. The value corresponding
1473 : * to a key can be got later with the CPLGetConfigOption() method.
1474 : *
1475 : * This function sets the configuration option that only applies in the
1476 : * current thread, as opposed to CPLSetConfigOption() which sets an option
1477 : * that applies on all threads.
1478 : *
1479 : * @param pszKey the key of the option
1480 : * @param pszValue the value of the option
1481 : */
1482 :
1483 : void CPL_STDCALL
1484 0 : CPLSetThreadLocalConfigOption( const char *pszKey, const char *pszValue )
1485 :
1486 : {
1487 0 : char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
1488 :
1489 : papszTLConfigOptions =
1490 0 : CSLSetNameValue( papszTLConfigOptions, pszKey, pszValue );
1491 :
1492 0 : CPLSetTLS( CTLS_CONFIGOPTIONS, papszTLConfigOptions, FALSE );
1493 0 : }
1494 :
1495 : /************************************************************************/
1496 : /* CPLFreeConfig() */
1497 : /************************************************************************/
1498 :
1499 617 : void CPL_STDCALL CPLFreeConfig()
1500 :
1501 : {
1502 617 : CPLMutexHolderD( &hConfigMutex );
1503 :
1504 617 : CSLDestroy( (char **) papszConfigOptions);
1505 617 : papszConfigOptions = NULL;
1506 :
1507 617 : char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
1508 617 : if( papszTLConfigOptions != NULL )
1509 : {
1510 0 : CSLDestroy( papszTLConfigOptions );
1511 0 : CPLSetTLS( CTLS_CONFIGOPTIONS, NULL, FALSE );
1512 617 : }
1513 617 : }
1514 :
1515 : /************************************************************************/
1516 : /* CPLStat() */
1517 : /* */
1518 : /* Same as VSIStat() except it works on "C:" as if it were */
1519 : /* "C:\". */
1520 : /************************************************************************/
1521 :
1522 540 : int CPLStat( const char *pszPath, VSIStatBuf *psStatBuf )
1523 :
1524 : {
1525 540 : if( strlen(pszPath) == 2 && pszPath[1] == ':' )
1526 : {
1527 : char szAltPath[4];
1528 :
1529 0 : szAltPath[0] = pszPath[0];
1530 0 : szAltPath[1] = pszPath[1];
1531 0 : szAltPath[2] = '\\';
1532 0 : szAltPath[3] = '\0';
1533 0 : return VSIStat( szAltPath, psStatBuf );
1534 : }
1535 : else
1536 540 : return VSIStat( pszPath, psStatBuf );
1537 : }
1538 :
1539 : /************************************************************************/
1540 : /* proj_strtod() */
1541 : /************************************************************************/
1542 : static double
1543 86 : proj_strtod(char *nptr, char **endptr)
1544 :
1545 : {
1546 86 : char c, *cp = nptr;
1547 : double result;
1548 :
1549 : /*
1550 : * Scan for characters which cause problems with VC++ strtod()
1551 : */
1552 704 : while ((c = *cp) != '\0') {
1553 540 : if (c == 'd' || c == 'D') {
1554 :
1555 : /*
1556 : * Found one, so NUL it out, call strtod(),
1557 : * then restore it and return
1558 : */
1559 8 : *cp = '\0';
1560 8 : result = strtod(nptr, endptr);
1561 8 : *cp = c;
1562 8 : return result;
1563 : }
1564 532 : ++cp;
1565 : }
1566 :
1567 : /* no offending characters, just handle normally */
1568 :
1569 78 : return strtod(nptr, endptr);
1570 : }
1571 :
1572 : /************************************************************************/
1573 : /* CPLDMSToDec() */
1574 : /************************************************************************/
1575 :
1576 : static const char*sym = "NnEeSsWw";
1577 : static const double vm[] = { 1.0, 0.0166666666667, 0.00027777778 };
1578 :
1579 80 : double CPLDMSToDec( const char *is )
1580 :
1581 : {
1582 : int sign, n, nl;
1583 : char *p, *s, work[64];
1584 : double v, tv;
1585 :
1586 : /* copy sting into work space */
1587 80 : while (isspace((unsigned char)(sign = *is))) ++is;
1588 699 : for (n = sizeof(work), s = work, p = (char *)is; isgraph(*p) && --n ; )
1589 539 : *s++ = *p++;
1590 80 : *s = '\0';
1591 : /* it is possible that a really odd input (like lots of leading
1592 : zeros) could be truncated in copying into work. But ... */
1593 80 : sign = *(s = work);
1594 80 : if (sign == '+' || sign == '-') s++;
1595 73 : else sign = '+';
1596 166 : for (v = 0., nl = 0 ; nl < 3 ; nl = n + 1 ) {
1597 93 : if (!(isdigit(*s) || *s == '.')) break;
1598 86 : if ((tv = proj_strtod(s, &s)) == HUGE_VAL)
1599 0 : return tv;
1600 86 : switch (*s) {
1601 : case 'D': case 'd':
1602 8 : n = 0; break;
1603 : case '\'':
1604 5 : n = 1; break;
1605 : case '"':
1606 2 : n = 2; break;
1607 : case 'r': case 'R':
1608 0 : if (nl) {
1609 0 : return 0.0;
1610 : }
1611 0 : ++s;
1612 0 : v = tv;
1613 0 : goto skip;
1614 : default:
1615 71 : v += tv * vm[nl];
1616 71 : skip: n = 4;
1617 71 : continue;
1618 : }
1619 15 : if (n < nl) {
1620 0 : return 0.0;
1621 : }
1622 15 : v += tv * vm[n];
1623 15 : ++s;
1624 : }
1625 : /* postfix sign */
1626 80 : if (*s && (p = (char *) strchr(sym, *s))) {
1627 10 : sign = (p - sym) >= 4 ? '-' : '+';
1628 10 : ++s;
1629 : }
1630 80 : if (sign == '-')
1631 10 : v = -v;
1632 :
1633 80 : return v;
1634 : }
1635 :
1636 :
1637 : /************************************************************************/
1638 : /* CPLDecToDMS() */
1639 : /* */
1640 : /* Translate a decimal degrees value to a DMS string with */
1641 : /* hemisphere. */
1642 : /************************************************************************/
1643 :
1644 70 : const char *CPLDecToDMS( double dfAngle, const char * pszAxis,
1645 : int nPrecision )
1646 :
1647 : {
1648 70 : VALIDATE_POINTER1( pszAxis, "CPLDecToDMS", "" );
1649 :
1650 : int nDegrees, nMinutes;
1651 : double dfSeconds, dfABSAngle, dfEpsilon;
1652 : char szFormat[30];
1653 : const char *pszHemisphere;
1654 : static CPL_THREADLOCAL char szBuffer[50] = { 0 };
1655 :
1656 :
1657 70 : dfEpsilon = (0.5/3600.0) * pow(0.1,nPrecision);
1658 :
1659 70 : dfABSAngle = ABS(dfAngle) + dfEpsilon;
1660 70 : if (dfABSAngle > 361)
1661 : {
1662 0 : return "Invalid angle";
1663 : }
1664 :
1665 70 : nDegrees = (int) dfABSAngle;
1666 70 : nMinutes = (int) ((dfABSAngle - nDegrees) * 60);
1667 70 : dfSeconds = dfABSAngle * 3600 - nDegrees*3600 - nMinutes*60;
1668 :
1669 70 : if( dfSeconds > dfEpsilon * 3600.0 )
1670 70 : dfSeconds -= dfEpsilon * 3600.0;
1671 :
1672 100 : if( EQUAL(pszAxis,"Long") && dfAngle < 0.0 )
1673 30 : pszHemisphere = "W";
1674 40 : else if( EQUAL(pszAxis,"Long") )
1675 5 : pszHemisphere = "E";
1676 35 : else if( dfAngle < 0.0 )
1677 5 : pszHemisphere = "S";
1678 : else
1679 30 : pszHemisphere = "N";
1680 :
1681 70 : sprintf( szFormat, "%%3dd%%2d\'%%.%df\"%s", nPrecision, pszHemisphere );
1682 70 : sprintf( szBuffer, szFormat, nDegrees, nMinutes, dfSeconds );
1683 :
1684 70 : return( szBuffer );
1685 : }
1686 :
1687 : /************************************************************************/
1688 : /* CPLPackedDMSToDec() */
1689 : /************************************************************************/
1690 :
1691 : /**
1692 : * Convert a packed DMS value (DDDMMMSSS.SS) into decimal degrees.
1693 : *
1694 : * This function converts a packed DMS angle to seconds. The standard
1695 : * packed DMS format is:
1696 : *
1697 : * degrees * 1000000 + minutes * 1000 + seconds
1698 : *
1699 : * Example: ang = 120025045.25 yields
1700 : * deg = 120
1701 : * min = 25
1702 : * sec = 45.25
1703 : *
1704 : * The algorithm used for the conversion is as follows:
1705 : *
1706 : * 1. The absolute value of the angle is used.
1707 : *
1708 : * 2. The degrees are separated out:
1709 : * deg = ang/1000000 (fractional portion truncated)
1710 : *
1711 : * 3. The minutes are separated out:
1712 : * min = (ang - deg * 1000000) / 1000 (fractional portion truncated)
1713 : *
1714 : * 4. The seconds are then computed:
1715 : * sec = ang - deg * 1000000 - min * 1000
1716 : *
1717 : * 5. The total angle in seconds is computed:
1718 : * sec = deg * 3600.0 + min * 60.0 + sec
1719 : *
1720 : * 6. The sign of sec is set to that of the input angle.
1721 : *
1722 : * Packed DMS values used by the USGS GCTP package and probably by other
1723 : * software.
1724 : *
1725 : * NOTE: This code does not validate input value. If you give the wrong
1726 : * value, you will get the wrong result.
1727 : *
1728 : * @param dfPacked Angle in packed DMS format.
1729 : *
1730 : * @return Angle in decimal degrees.
1731 : *
1732 : */
1733 :
1734 14 : double CPLPackedDMSToDec( double dfPacked )
1735 : {
1736 : double dfDegrees, dfMinutes, dfSeconds, dfSign;
1737 :
1738 14 : dfSign = ( dfPacked < 0.0 )? -1 : 1;
1739 :
1740 14 : dfSeconds = ABS( dfPacked );
1741 14 : dfDegrees = floor(dfSeconds / 1000000.0);
1742 14 : dfSeconds = dfSeconds - dfDegrees * 1000000.0;
1743 14 : dfMinutes = floor(dfSeconds / 1000.0);
1744 14 : dfSeconds = dfSeconds - dfMinutes * 1000.0;
1745 14 : dfSeconds = dfSign * ( dfDegrees * 3600.0 + dfMinutes * 60.0 + dfSeconds);
1746 14 : dfDegrees = dfSeconds / 3600.0;
1747 :
1748 14 : return dfDegrees;
1749 : }
1750 :
1751 : /************************************************************************/
1752 : /* CPLDecToPackedDMS() */
1753 : /************************************************************************/
1754 : /**
1755 : * Convert decimal degrees into packed DMS value (DDDMMMSSS.SS).
1756 : *
1757 : * This function converts a value, specified in decimal degrees into
1758 : * packed DMS angle. The standard packed DMS format is:
1759 : *
1760 : * degrees * 1000000 + minutes * 1000 + seconds
1761 : *
1762 : * See also CPLPackedDMSToDec().
1763 : *
1764 : * @param dfDec Angle in decimal degrees.
1765 : *
1766 : * @return Angle in packed DMS format.
1767 : *
1768 : */
1769 :
1770 8 : double CPLDecToPackedDMS( double dfDec )
1771 : {
1772 : double dfDegrees, dfMinutes, dfSeconds, dfSign;
1773 :
1774 8 : dfSign = ( dfDec < 0.0 )? -1 : 1;
1775 :
1776 8 : dfDec = ABS( dfDec );
1777 8 : dfDegrees = floor( dfDec );
1778 8 : dfMinutes = floor( ( dfDec - dfDegrees ) * 60.0 );
1779 8 : dfSeconds = ( dfDec - dfDegrees ) * 3600.0 - dfMinutes * 60.0;
1780 :
1781 8 : return dfSign * (dfDegrees * 1000000.0 + dfMinutes * 1000.0 + dfSeconds);
1782 : }
1783 :
1784 : /************************************************************************/
1785 : /* CPLStringToComplex() */
1786 : /************************************************************************/
1787 :
1788 289 : void CPL_DLL CPLStringToComplex( const char *pszString,
1789 : double *pdfReal, double *pdfImag )
1790 :
1791 : {
1792 : int i;
1793 289 : int iPlus = -1, iImagEnd = -1;
1794 :
1795 578 : while( *pszString == ' ' )
1796 0 : pszString++;
1797 :
1798 289 : *pdfReal = atof(pszString);
1799 289 : *pdfImag = 0.0;
1800 :
1801 578 : for( i = 0; pszString[i] != '\0' && pszString[i] != ' ' && i < 100; i++ )
1802 : {
1803 289 : if( pszString[i] == '+' && i > 0 )
1804 0 : iPlus = i;
1805 289 : if( pszString[i] == '-' && i > 0 )
1806 0 : iPlus = i;
1807 289 : if( pszString[i] == 'i' )
1808 0 : iImagEnd = i;
1809 : }
1810 :
1811 289 : if( iPlus > -1 && iImagEnd > -1 && iPlus < iImagEnd )
1812 : {
1813 0 : *pdfImag = atof(pszString + iPlus);
1814 : }
1815 :
1816 : return;
1817 : }
1818 :
1819 : /************************************************************************/
1820 : /* CPLOpenShared() */
1821 : /************************************************************************/
1822 :
1823 : /**
1824 : * Open a shared file handle.
1825 : *
1826 : * Some operating systems have limits on the number of file handles that can
1827 : * be open at one time. This function attempts to maintain a registry of
1828 : * already open file handles, and reuse existing ones if the same file
1829 : * is requested by another part of the application.
1830 : *
1831 : * Note that access is only shared for access types "r", "rb", "r+" and
1832 : * "rb+". All others will just result in direct VSIOpen() calls. Keep in
1833 : * mind that a file is only reused if the file name is exactly the same.
1834 : * Different names referring to the same file will result in different
1835 : * handles.
1836 : *
1837 : * The VSIFOpen() or VSIFOpenL() function is used to actually open the file,
1838 : * when an existing file handle can't be shared.
1839 : *
1840 : * @param pszFilename the name of the file to open.
1841 : * @param pszAccess the normal fopen()/VSIFOpen() style access string.
1842 : * @param bLarge If TRUE VSIFOpenL() (for large files) will be used instead of
1843 : * VSIFOpen().
1844 : *
1845 : * @return a file handle or NULL if opening fails.
1846 : */
1847 :
1848 13 : FILE *CPLOpenShared( const char *pszFilename, const char *pszAccess,
1849 : int bLarge )
1850 :
1851 : {
1852 : int i;
1853 : int bReuse;
1854 13 : CPLMutexHolderD( &hSharedFileMutex );
1855 :
1856 : /* -------------------------------------------------------------------- */
1857 : /* Is there an existing file we can use? */
1858 : /* -------------------------------------------------------------------- */
1859 13 : bReuse = EQUAL(pszAccess,"rb") || EQUAL(pszAccess, "rb+");
1860 :
1861 15 : for( i = 0; bReuse && i < nSharedFileCount; i++ )
1862 : {
1863 17 : if( strcmp(pasSharedFileList[i].pszFilename,pszFilename) == 0
1864 5 : && !bLarge == !pasSharedFileList[i].bLarge
1865 5 : && EQUAL(pasSharedFileList[i].pszAccess,pszAccess) )
1866 : {
1867 5 : pasSharedFileList[i].nRefCount++;
1868 5 : return pasSharedFileList[i].fp;
1869 : }
1870 : }
1871 :
1872 : /* -------------------------------------------------------------------- */
1873 : /* Open the file. */
1874 : /* -------------------------------------------------------------------- */
1875 : FILE *fp;
1876 :
1877 8 : if( bLarge )
1878 8 : fp = VSIFOpenL( pszFilename, pszAccess );
1879 : else
1880 0 : fp = VSIFOpen( pszFilename, pszAccess );
1881 :
1882 8 : if( fp == NULL )
1883 0 : return NULL;
1884 :
1885 : /* -------------------------------------------------------------------- */
1886 : /* Add an entry to the list. */
1887 : /* -------------------------------------------------------------------- */
1888 8 : nSharedFileCount++;
1889 :
1890 : pasSharedFileList = (CPLSharedFileInfo *)
1891 : CPLRealloc( (void *) pasSharedFileList,
1892 8 : sizeof(CPLSharedFileInfo) * nSharedFileCount );
1893 :
1894 8 : pasSharedFileList[nSharedFileCount-1].fp = fp;
1895 8 : pasSharedFileList[nSharedFileCount-1].nRefCount = 1;
1896 8 : pasSharedFileList[nSharedFileCount-1].bLarge = bLarge;
1897 8 : pasSharedFileList[nSharedFileCount-1].pszFilename =CPLStrdup(pszFilename);
1898 8 : pasSharedFileList[nSharedFileCount-1].pszAccess = CPLStrdup(pszAccess);
1899 :
1900 8 : return fp;
1901 : }
1902 :
1903 : /************************************************************************/
1904 : /* CPLCloseShared() */
1905 : /************************************************************************/
1906 :
1907 : /**
1908 : * Close shared file.
1909 : *
1910 : * Dereferences the indicated file handle, and closes it if the reference
1911 : * count has dropped to zero. A CPLError() is issued if the file is not
1912 : * in the shared file list.
1913 : *
1914 : * @param fp file handle from CPLOpenShared() to deaccess.
1915 : */
1916 :
1917 13 : void CPLCloseShared( FILE * fp )
1918 :
1919 : {
1920 13 : CPLMutexHolderD( &hSharedFileMutex );
1921 : int i;
1922 :
1923 : /* -------------------------------------------------------------------- */
1924 : /* Search for matching information. */
1925 : /* -------------------------------------------------------------------- */
1926 13 : for( i = 0; i < nSharedFileCount && fp != pasSharedFileList[i].fp; i++ ){}
1927 :
1928 13 : if( i == nSharedFileCount )
1929 : {
1930 : CPLError( CE_Failure, CPLE_AppDefined,
1931 : "Unable to find file handle %p in CPLCloseShared().",
1932 0 : fp );
1933 : return;
1934 : }
1935 :
1936 : /* -------------------------------------------------------------------- */
1937 : /* Dereference and return if there are still some references. */
1938 : /* -------------------------------------------------------------------- */
1939 13 : if( --pasSharedFileList[i].nRefCount > 0 )
1940 : return;
1941 :
1942 : /* -------------------------------------------------------------------- */
1943 : /* Close the file, and remove the information. */
1944 : /* -------------------------------------------------------------------- */
1945 8 : if( pasSharedFileList[i].bLarge )
1946 8 : VSIFCloseL( pasSharedFileList[i].fp );
1947 : else
1948 0 : VSIFClose( pasSharedFileList[i].fp );
1949 :
1950 8 : CPLFree( pasSharedFileList[i].pszFilename );
1951 8 : CPLFree( pasSharedFileList[i].pszAccess );
1952 :
1953 : // pasSharedFileList[i] = pasSharedFileList[--nSharedFileCount];
1954 : memcpy( (void *) (pasSharedFileList + i),
1955 : (void *) (pasSharedFileList + --nSharedFileCount),
1956 8 : sizeof(CPLSharedFileInfo) );
1957 :
1958 8 : if( nSharedFileCount == 0 )
1959 : {
1960 7 : CPLFree( (void *) pasSharedFileList );
1961 7 : pasSharedFileList = NULL;
1962 0 : }
1963 : }
1964 :
1965 : /************************************************************************/
1966 : /* CPLGetSharedList() */
1967 : /************************************************************************/
1968 :
1969 : /**
1970 : * Fetch list of open shared files.
1971 : *
1972 : * @param pnCount place to put the count of entries.
1973 : *
1974 : * @return the pointer to the first in the array of shared file info
1975 : * structures.
1976 : */
1977 :
1978 0 : CPLSharedFileInfo *CPLGetSharedList( int *pnCount )
1979 :
1980 : {
1981 0 : if( pnCount != NULL )
1982 0 : *pnCount = nSharedFileCount;
1983 :
1984 0 : return (CPLSharedFileInfo *) pasSharedFileList;
1985 : }
1986 :
1987 : /************************************************************************/
1988 : /* CPLDumpSharedList() */
1989 : /************************************************************************/
1990 :
1991 : /**
1992 : * Report open shared files.
1993 : *
1994 : * Dumps all open shared files to the indicated file handle. If the
1995 : * file handle is NULL information is sent via the CPLDebug() call.
1996 : *
1997 : * @param fp File handle to write to.
1998 : */
1999 :
2000 9 : void CPLDumpSharedList( FILE *fp )
2001 :
2002 : {
2003 : int i;
2004 :
2005 9 : if( nSharedFileCount > 0 )
2006 : {
2007 0 : if( fp == NULL )
2008 0 : CPLDebug( "CPL", "%d Shared files open.", nSharedFileCount );
2009 : else
2010 0 : fprintf( fp, "%d Shared files open.", nSharedFileCount );
2011 : }
2012 :
2013 9 : for( i = 0; i < nSharedFileCount; i++ )
2014 : {
2015 0 : if( fp == NULL )
2016 : CPLDebug( "CPL",
2017 : "%2d %d %4s %s",
2018 0 : pasSharedFileList[i].nRefCount,
2019 0 : pasSharedFileList[i].bLarge,
2020 0 : pasSharedFileList[i].pszAccess,
2021 0 : pasSharedFileList[i].pszFilename );
2022 : else
2023 : fprintf( fp, "%2d %d %4s %s",
2024 0 : pasSharedFileList[i].nRefCount,
2025 0 : pasSharedFileList[i].bLarge,
2026 0 : pasSharedFileList[i].pszAccess,
2027 0 : pasSharedFileList[i].pszFilename );
2028 : }
2029 9 : }
2030 :
2031 : /************************************************************************/
2032 : /* CPLUnlinkTree() */
2033 : /************************************************************************/
2034 :
2035 : /**
2036 : * @return 0 on successful completion, -1 if function fails.
2037 : */
2038 :
2039 14 : int CPLUnlinkTree( const char *pszPath )
2040 :
2041 : {
2042 : /* -------------------------------------------------------------------- */
2043 : /* First, ensure there isn't any such file yet. */
2044 : /* -------------------------------------------------------------------- */
2045 : VSIStatBuf sStatBuf;
2046 :
2047 14 : if( VSIStat( pszPath, &sStatBuf ) != 0 )
2048 : {
2049 : CPLError( CE_Failure, CPLE_AppDefined,
2050 : "It seems no file system object called '%s' exists.",
2051 2 : pszPath );
2052 :
2053 2 : return -1;
2054 : }
2055 :
2056 : /* -------------------------------------------------------------------- */
2057 : /* If it's a simple file, just delete it. */
2058 : /* -------------------------------------------------------------------- */
2059 12 : if( VSI_ISREG( sStatBuf.st_mode ) )
2060 : {
2061 11 : if( VSIUnlink( pszPath ) != 0 )
2062 : {
2063 : CPLError( CE_Failure, CPLE_AppDefined, "Failed to unlink %s.",
2064 0 : pszPath );
2065 :
2066 0 : return -1;
2067 : }
2068 : else
2069 11 : return 0;
2070 : }
2071 :
2072 : /* -------------------------------------------------------------------- */
2073 : /* If it is a directory recurse then unlink the directory. */
2074 : /* -------------------------------------------------------------------- */
2075 1 : else if( VSI_ISDIR( sStatBuf.st_mode ) )
2076 : {
2077 1 : char **papszItems = CPLReadDir( pszPath );
2078 : int i;
2079 :
2080 14 : for( i = 0; papszItems != NULL && papszItems[i] != NULL; i++ )
2081 : {
2082 : char *pszSubPath;
2083 : int nErr;
2084 :
2085 13 : if( EQUAL(papszItems[i],".") || EQUAL(papszItems[i],"..") )
2086 2 : continue;
2087 :
2088 : pszSubPath = CPLStrdup(
2089 11 : CPLFormFilename( pszPath, papszItems[i], NULL ) );
2090 :
2091 11 : nErr = CPLUnlinkTree( pszSubPath );
2092 11 : CPLFree( pszSubPath );
2093 :
2094 11 : if( nErr != 0 )
2095 : {
2096 0 : CSLDestroy( papszItems );
2097 0 : return nErr;
2098 : }
2099 : }
2100 :
2101 1 : CSLDestroy( papszItems );
2102 :
2103 1 : if( VSIRmdir( pszPath ) != 0 )
2104 : {
2105 : CPLError( CE_Failure, CPLE_AppDefined, "Failed to unlink %s.",
2106 0 : pszPath );
2107 :
2108 0 : return -1;
2109 : }
2110 : else
2111 1 : return 0;
2112 : }
2113 :
2114 : /* -------------------------------------------------------------------- */
2115 : /* otherwise report an error. */
2116 : /* -------------------------------------------------------------------- */
2117 : else
2118 : {
2119 : CPLError( CE_Failure, CPLE_AppDefined,
2120 : "Failed to unlink %s.\nUnrecognised filesystem object.",
2121 0 : pszPath );
2122 0 : return 1000;
2123 : }
2124 : }
2125 :
2126 : /************************************************************************/
2127 : /* CPLCopyFile() */
2128 : /************************************************************************/
2129 :
2130 0 : int CPLCopyFile( const char *pszNewPath, const char *pszOldPath )
2131 :
2132 : {
2133 : FILE *fpOld, *fpNew;
2134 : GByte *pabyBuffer;
2135 : size_t nBufferSize;
2136 : size_t nBytesRead;
2137 0 : int nRet = 0;
2138 :
2139 : /* -------------------------------------------------------------------- */
2140 : /* Open old and new file. */
2141 : /* -------------------------------------------------------------------- */
2142 0 : fpOld = VSIFOpenL( pszOldPath, "rb" );
2143 0 : if( fpOld == NULL )
2144 0 : return -1;
2145 :
2146 0 : fpNew = VSIFOpenL( pszNewPath, "wb" );
2147 0 : if( fpNew == NULL )
2148 : {
2149 0 : VSIFCloseL( fpOld );
2150 0 : return -1;
2151 : }
2152 :
2153 : /* -------------------------------------------------------------------- */
2154 : /* Prepare buffer. */
2155 : /* -------------------------------------------------------------------- */
2156 0 : nBufferSize = 1024 * 1024;
2157 0 : pabyBuffer = (GByte *) CPLMalloc(nBufferSize);
2158 :
2159 : /* -------------------------------------------------------------------- */
2160 : /* Copy file over till we run out of stuff. */
2161 : /* -------------------------------------------------------------------- */
2162 0 : do {
2163 0 : nBytesRead = VSIFReadL( pabyBuffer, 1, nBufferSize, fpOld );
2164 : if( nBytesRead < 0 )
2165 : nRet = -1;
2166 :
2167 0 : if( nRet == 0
2168 : && VSIFWriteL( pabyBuffer, 1, nBytesRead, fpNew ) < nBytesRead )
2169 0 : nRet = -1;
2170 : } while( nRet == 0 && nBytesRead == nBufferSize );
2171 :
2172 : /* -------------------------------------------------------------------- */
2173 : /* Cleanup */
2174 : /* -------------------------------------------------------------------- */
2175 0 : VSIFCloseL( fpNew );
2176 0 : VSIFCloseL( fpOld );
2177 :
2178 0 : CPLFree( pabyBuffer );
2179 :
2180 0 : return nRet;
2181 : }
2182 :
2183 : /************************************************************************/
2184 : /* CPLMoveFile() */
2185 : /************************************************************************/
2186 :
2187 0 : int CPLMoveFile( const char *pszNewPath, const char *pszOldPath )
2188 :
2189 : {
2190 0 : if( VSIRename( pszNewPath, pszOldPath ) == 0 )
2191 0 : return 0;
2192 :
2193 0 : int nRet = CPLCopyFile( pszNewPath, pszOldPath );
2194 :
2195 0 : if( nRet == 0 )
2196 0 : VSIUnlink( pszOldPath );
2197 :
2198 0 : return nRet;
2199 : }
2200 :
2201 : /************************************************************************/
2202 : /* ==================================================================== */
2203 : /* CPLLocaleC */
2204 : /* ==================================================================== */
2205 : /************************************************************************/
2206 :
2207 : #include <locale.h>
2208 :
2209 : /************************************************************************/
2210 : /* CPLLocaleC() */
2211 : /************************************************************************/
2212 :
2213 32588 : CPLLocaleC::CPLLocaleC() : pszOldLocale(CPLStrdup(setlocale(LC_NUMERIC,NULL)))
2214 :
2215 : {
2216 32588 : if( setlocale(LC_NUMERIC,"C") == NULL )
2217 : {
2218 0 : CPLFree( pszOldLocale );
2219 0 : pszOldLocale = NULL;
2220 : }
2221 32588 : }
2222 :
2223 : /************************************************************************/
2224 : /* ~CPLLocaleC() */
2225 : /************************************************************************/
2226 :
2227 32588 : CPLLocaleC::~CPLLocaleC()
2228 :
2229 : {
2230 32588 : if( pszOldLocale != NULL )
2231 : {
2232 32588 : setlocale( LC_NUMERIC, pszOldLocale );
2233 32588 : CPLFree( pszOldLocale );
2234 : }
2235 32588 : }
2236 :
2237 : /************************************************************************/
2238 : /* CPLCheckForFile() */
2239 : /************************************************************************/
2240 :
2241 : /**
2242 : * Check for file existance.
2243 : *
2244 : * The function checks if a named file exists in the filesystem, hopefully
2245 : * in an efficient fashion if a sibling file list is available. It exists
2246 : * primarily to do faster file checking for functions like GDAL open methods
2247 : * that get a list of files from the target directory.
2248 : *
2249 : * If the sibling file list exists (is not NULL) it is assumed to be a list
2250 : * of files in the same directory as the target file, and it will be checked
2251 : * (case insensitively) for a match. If a match is found, pszFilename is
2252 : * updated with the correct case and TRUE is returned.
2253 : *
2254 : * If papszSiblingFiles is NULL, a VSIStatL() is used to test for the files
2255 : * existance, and no case insensitive testing is done.
2256 : *
2257 : * @param pszFilename name of file to check for - filename case updated in some cases.
2258 : * @param papszSiblingFiles a list of files in the same directory as
2259 : * pszFilename if available, or NULL. This list should have no path components.
2260 : *
2261 : * @return TRUE if a match is found, or FALSE if not.
2262 : */
2263 :
2264 5335 : int CPLCheckForFile( char *pszFilename, char **papszSiblingFiles )
2265 :
2266 : {
2267 : /* -------------------------------------------------------------------- */
2268 : /* Fallback case if we don't have a sibling file list. */
2269 : /* -------------------------------------------------------------------- */
2270 5335 : if( papszSiblingFiles == NULL )
2271 : {
2272 : VSIStatBufL sStatBuf;
2273 :
2274 5307 : return VSIStatL( pszFilename, &sStatBuf ) == 0;
2275 : }
2276 :
2277 : /* -------------------------------------------------------------------- */
2278 : /* We have sibling files, compare the non-path filename portion */
2279 : /* of pszFilename too all entries. */
2280 : /* -------------------------------------------------------------------- */
2281 28 : CPLString osFileOnly = CPLGetFilename( pszFilename );
2282 : int i;
2283 :
2284 2376 : for( i = 0; papszSiblingFiles[i] != NULL; i++ )
2285 : {
2286 2350 : if( EQUAL(papszSiblingFiles[i],osFileOnly) )
2287 : {
2288 : strcpy( pszFilename + strlen(pszFilename) - strlen(osFileOnly),
2289 2 : papszSiblingFiles[i] );
2290 2 : return TRUE;
2291 : }
2292 : }
2293 :
2294 26 : return FALSE;
2295 : }
|