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