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