1 : /******************************************************************************
2 : * $Id: cpl_conv.cpp 25795 2013-03-24 13:16:52Z 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 25795 2013-03-24 13:16:52Z 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 9380794 : void *CPLCalloc( size_t nCount, size_t nSize )
83 :
84 : {
85 : void *pReturn;
86 :
87 9380794 : if( nSize * nCount == 0 )
88 49 : return NULL;
89 :
90 9380745 : pReturn = CPLMalloc( nCount * nSize );
91 9380745 : memset( pReturn, 0, nCount * nSize );
92 9380745 : 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 41664315 : void *CPLMalloc( size_t nSize )
115 :
116 : {
117 : void *pReturn;
118 :
119 41664315 : CPLVerifyConfiguration();
120 :
121 41664315 : if( nSize == 0 )
122 35256 : return NULL;
123 :
124 41629059 : 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 41629059 : pReturn = VSIMalloc( nSize );
133 41629060 : 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 41629060 : 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 13658080 : void * CPLRealloc( void * pData, size_t nNewSize )
178 :
179 : {
180 : void *pReturn;
181 :
182 13658080 : if ( nNewSize == 0 )
183 : {
184 0 : VSIFree(pData);
185 0 : return NULL;
186 : }
187 :
188 13658080 : 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 13658080 : if( pData == NULL )
197 1725416 : pReturn = VSIMalloc( nNewSize );
198 : else
199 11932664 : pReturn = VSIRealloc( pData, nNewSize );
200 :
201 13658679 : 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 13658674 : 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 25604072 : char *CPLStrdup( const char * pszString )
244 :
245 : {
246 : char *pszReturn;
247 :
248 25604072 : if( pszString == NULL )
249 816605 : pszString = "";
250 :
251 25604072 : pszReturn = (char *) CPLMalloc(strlen(pszString)+1);
252 25604073 : 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 25604073 : strcpy( pszReturn, pszString );
261 25604073 : 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 57 : char *CPLStrlwr( char *pszString )
279 :
280 : {
281 57 : if (pszString)
282 : {
283 57 : char *pszTemp = pszString;
284 :
285 168 : while (*pszTemp)
286 : {
287 54 : *pszTemp = (char) tolower (*pszTemp);
288 54 : pszTemp++;
289 : }
290 : }
291 :
292 57 : 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 1470374 : char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
320 :
321 : {
322 : int nActuallyRead, nOriginalOffset;
323 :
324 1470374 : 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 1470374 : nOriginalOffset = VSIFTell( fp );
335 1470374 : if( VSIFGets( pszBuffer, nBufferSize, fp ) == NULL )
336 1502 : return NULL;
337 :
338 1468872 : nActuallyRead = strlen(pszBuffer);
339 1468872 : 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 2441136 : if( nBufferSize == nActuallyRead+1
347 972264 : && 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 3504609 : if( nActuallyRead > 1
363 1463922 : && pszBuffer[nActuallyRead-1] == 10
364 493660 : && pszBuffer[nActuallyRead-2] == 13 )
365 : {
366 78155 : pszBuffer[nActuallyRead-2] = '\0';
367 : }
368 2360979 : else if( pszBuffer[nActuallyRead-1] == 10
369 970262 : || pszBuffer[nActuallyRead-1] == 13 )
370 : {
371 420471 : 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 1468872 : char *pszExtraNewline = strchr( pszBuffer, 13 );
380 :
381 1468872 : 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 1468872 : 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 2292899 : static char *CPLReadLineBuffer( int nRequiredSize )
426 :
427 : {
428 :
429 : /* -------------------------------------------------------------------- */
430 : /* A required size of -1 means the buffer should be freed. */
431 : /* -------------------------------------------------------------------- */
432 2292899 : if( nRequiredSize == -1 )
433 : {
434 929 : if( CPLGetTLS( CTLS_RLBUFFERINFO ) != NULL )
435 : {
436 929 : CPLFree( CPLGetTLS( CTLS_RLBUFFERINFO ) );
437 929 : CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
438 : }
439 929 : return NULL;
440 : }
441 :
442 : /* -------------------------------------------------------------------- */
443 : /* If the buffer doesn't exist yet, create it. */
444 : /* -------------------------------------------------------------------- */
445 2291970 : GUInt32 *pnAlloc = (GUInt32 *) CPLGetTLS( CTLS_RLBUFFERINFO );
446 :
447 2291970 : if( pnAlloc == NULL )
448 : {
449 1055 : pnAlloc = (GUInt32 *) CPLMalloc(200);
450 1055 : *pnAlloc = 196;
451 1055 : CPLSetTLS( CTLS_RLBUFFERINFO, pnAlloc, TRUE );
452 : }
453 :
454 : /* -------------------------------------------------------------------- */
455 : /* If it is too small, grow it bigger. */
456 : /* -------------------------------------------------------------------- */
457 2291970 : if( ((int) *pnAlloc) -1 < nRequiredSize )
458 : {
459 536 : int nNewSize = nRequiredSize + 4 + 500;
460 536 : 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 536 : GUInt32* pnAllocNew = (GUInt32 *) VSIRealloc(pnAlloc,nNewSize);
470 536 : 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 536 : pnAlloc = pnAllocNew;
480 :
481 536 : *pnAlloc = nNewSize - 4;
482 536 : CPLSetTLS( CTLS_RLBUFFERINFO, pnAlloc, TRUE );
483 : }
484 :
485 2291970 : 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 500476 : const char *CPLReadLine( FILE * fp )
515 :
516 : {
517 500476 : char *pszRLBuffer = CPLReadLineBuffer(1);
518 500476 : int nReadSoFar = 0;
519 :
520 : /* -------------------------------------------------------------------- */
521 : /* Cleanup case. */
522 : /* -------------------------------------------------------------------- */
523 500476 : 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 3409352 : 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 1470374 : if( nReadSoFar > 100 * 1024 * 1024 )
542 0 : return NULL; /* it is dubious that we need to read a line longer than 100 MB ! */
543 1470374 : pszRLBuffer = CPLReadLineBuffer( nReadSoFar + 129 );
544 1470374 : if( pszRLBuffer == NULL )
545 0 : return NULL;
546 :
547 : /* -------------------------------------------------------------------- */
548 : /* Do the actual read. */
549 : /* -------------------------------------------------------------------- */
550 1470374 : if( CPLFGets( pszRLBuffer+nReadSoFar, 128, fp ) == NULL
551 : && nReadSoFar == 0 )
552 1502 : return NULL;
553 :
554 1468872 : nBytesReadThisTime = strlen(pszRLBuffer+nReadSoFar);
555 1468872 : nReadSoFar += nBytesReadThisTime;
556 :
557 : } while( nBytesReadThisTime >= 127
558 970240 : && pszRLBuffer[nReadSoFar-1] != 13
559 970240 : && pszRLBuffer[nReadSoFar-1] != 10 );
560 :
561 498632 : 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 42125 : const char *CPLReadLineL( VSILFILE * fp )
580 : {
581 42125 : 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 303914 : const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars, char** papszOptions )
605 :
606 : {
607 : (void) papszOptions;
608 :
609 : /* -------------------------------------------------------------------- */
610 : /* Cleanup case. */
611 : /* -------------------------------------------------------------------- */
612 303914 : if( fp == NULL )
613 : {
614 587 : CPLReadLineBuffer( -1 );
615 587 : 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 303327 : const size_t nChunkSize = 40;
624 : char szChunk[nChunkSize];
625 303327 : size_t nChunkBytesRead = 0;
626 303327 : int nBufLength = 0;
627 303327 : size_t nChunkBytesConsumed = 0;
628 :
629 17793 : while( TRUE )
630 : {
631 : /* -------------------------------------------------------------------- */
632 : /* Read a chunk from the input file. */
633 : /* -------------------------------------------------------------------- */
634 321120 : if ( nBufLength > INT_MAX - (int)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 321120 : pszRLBuffer = CPLReadLineBuffer( nBufLength + nChunkSize + 1 );
643 321120 : if( pszRLBuffer == NULL )
644 0 : return NULL;
645 :
646 321120 : if( nChunkBytesRead == nChunkBytesConsumed + 1 )
647 : {
648 :
649 : // case where one character is left over from last read.
650 17793 : szChunk[0] = szChunk[nChunkBytesConsumed];
651 :
652 17793 : nChunkBytesConsumed = 0;
653 17793 : nChunkBytesRead = VSIFReadL( szChunk+1, 1, nChunkSize-1, fp ) + 1;
654 : }
655 : else
656 : {
657 303327 : nChunkBytesConsumed = 0;
658 :
659 : // fresh read.
660 303327 : nChunkBytesRead = VSIFReadL( szChunk, 1, nChunkSize, fp );
661 303327 : if( nChunkBytesRead == 0 )
662 : {
663 556 : if( nBufLength == 0 )
664 556 : return NULL;
665 : else
666 0 : break;
667 : }
668 : }
669 :
670 : /* -------------------------------------------------------------------- */
671 : /* copy over characters watching for end-of-line. */
672 : /* -------------------------------------------------------------------- */
673 320564 : int bBreak = FALSE;
674 9006427 : while( nChunkBytesConsumed < nChunkBytesRead-1 && !bBreak )
675 : {
676 17032193 : if( (szChunk[nChunkBytesConsumed] == 13
677 113492 : && szChunk[nChunkBytesConsumed+1] == 10)
678 8251838 : || (szChunk[nChunkBytesConsumed] == 10
679 188043 : && szChunk[nChunkBytesConsumed+1] == 13) )
680 : {
681 113491 : nChunkBytesConsumed += 2;
682 113491 : bBreak = TRUE;
683 : }
684 16503677 : else if( szChunk[nChunkBytesConsumed] == 10
685 8063795 : || szChunk[nChunkBytesConsumed] == 13 )
686 : {
687 188044 : nChunkBytesConsumed += 1;
688 188044 : bBreak = TRUE;
689 : }
690 : else
691 : {
692 8063794 : pszRLBuffer[nBufLength++] = szChunk[nChunkBytesConsumed++];
693 8063794 : 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 320534 : if( bBreak )
703 301535 : 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 18999 : if( nChunkBytesConsumed == nChunkBytesRead-1
711 : && nChunkBytesRead < nChunkSize )
712 : {
713 1629 : if( szChunk[nChunkBytesConsumed] == 10
714 423 : || szChunk[nChunkBytesConsumed] == 13 )
715 : {
716 783 : nChunkBytesConsumed++;
717 783 : break;
718 : }
719 :
720 423 : pszRLBuffer[nBufLength++] = szChunk[nChunkBytesConsumed++];
721 423 : 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 302741 : if( nChunkBytesConsumed < nChunkBytesRead )
730 : {
731 299373 : size_t nBytesToPush = nChunkBytesRead - nChunkBytesConsumed;
732 :
733 299373 : VSIFSeekL( fp, VSIFTellL( fp ) - nBytesToPush, SEEK_SET );
734 : }
735 :
736 302741 : pszRLBuffer[nBufLength] = '\0';
737 :
738 302741 : 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 4485 : char *CPLScanString( const char *pszString, int nMaxLength,
766 : int bTrimSpaces, int bNormalize )
767 : {
768 : char *pszBuffer;
769 :
770 4485 : if ( !pszString )
771 0 : return NULL;
772 :
773 4485 : if ( !nMaxLength )
774 2 : return CPLStrdup( "" );
775 :
776 4483 : pszBuffer = (char *)CPLMalloc( nMaxLength + 1 );
777 4483 : if ( !pszBuffer )
778 0 : return NULL;
779 :
780 4483 : strncpy( pszBuffer, pszString, nMaxLength );
781 4483 : pszBuffer[nMaxLength] = '\0';
782 :
783 4483 : if ( bTrimSpaces )
784 : {
785 4481 : size_t i = strlen( pszBuffer );
786 9529 : while ( i-- > 0 && isspace((unsigned char)pszBuffer[i]) )
787 567 : pszBuffer[i] = '\0';
788 : }
789 :
790 4483 : if ( bNormalize )
791 : {
792 4420 : size_t i = strlen( pszBuffer );
793 38592 : while ( i-- > 0 )
794 : {
795 29752 : if ( pszBuffer[i] == ':' )
796 0 : pszBuffer[i] = '_';
797 : }
798 : }
799 :
800 4483 : 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 7816 : GUIntBig CPLScanUIntBig( const char *pszString, int nMaxLength )
901 : {
902 : GUIntBig iValue;
903 7816 : char *pszValue = (char *)CPLMalloc( nMaxLength + 1);
904 :
905 : /* -------------------------------------------------------------------- */
906 : /* Compute string into local buffer, and terminate it. */
907 : /* -------------------------------------------------------------------- */
908 7816 : strncpy( pszValue, pszString, nMaxLength );
909 7816 : 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 7816 : iValue = atoll( pszValue );
918 : #else
919 : iValue = atol( pszValue );
920 : #endif
921 :
922 7816 : CPLFree( pszValue );
923 7816 : 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 2263 : int CPLPrintString( char *pszDest, const char *pszSrc, int nMaxLen )
1062 : {
1063 2263 : char *pszTemp = pszDest;
1064 2263 : int nChars = 0;
1065 :
1066 2263 : if ( !pszDest )
1067 0 : return 0;
1068 :
1069 2263 : if ( !pszSrc )
1070 : {
1071 0 : *pszDest = '\0';
1072 0 : return 1;
1073 : }
1074 :
1075 63792 : while ( nChars < nMaxLen && *pszSrc )
1076 : {
1077 59266 : *pszTemp++ = *pszSrc++;
1078 59266 : nChars++;
1079 : }
1080 :
1081 2263 : 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 41664315 : 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 41664315 : nTest = 1;
1433 :
1434 : #ifdef CPL_LSB
1435 41664315 : 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 41664315 : }
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 1171267 : CPLGetConfigOption( const char *pszKey, const char *pszDefault )
1544 :
1545 : {
1546 : #ifdef DEBUG_CONFIG_OPTIONS
1547 : CPLAccessConfigOption(pszKey, TRUE);
1548 : #endif
1549 :
1550 1171267 : const char *pszResult = NULL;
1551 :
1552 1171267 : char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
1553 1171267 : if( papszTLConfigOptions != NULL )
1554 1024958 : pszResult = CSLFetchNameValue( papszTLConfigOptions, pszKey );
1555 :
1556 1171267 : if( pszResult == NULL )
1557 : {
1558 1170061 : CPLMutexHolderD( &hConfigMutex );
1559 :
1560 1170061 : pszResult = CSLFetchNameValue( (char **) papszConfigOptions, pszKey );
1561 : }
1562 :
1563 : #if !defined(WIN32CE)
1564 1171267 : if( pszResult == NULL )
1565 491836 : pszResult = getenv( pszKey );
1566 : #endif
1567 :
1568 1171266 : if( pszResult == NULL )
1569 490210 : return pszDefault;
1570 : else
1571 681056 : 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 884 : CPLSetConfigOption( const char *pszKey, const char *pszValue )
1606 :
1607 : {
1608 : #ifdef DEBUG_CONFIG_OPTIONS
1609 : CPLAccessConfigOption(pszKey, FALSE);
1610 : #endif
1611 884 : CPLMutexHolderD( &hConfigMutex );
1612 :
1613 : papszConfigOptions = (volatile char **)
1614 884 : CSLSetNameValue( (char **) papszConfigOptions, pszKey, pszValue );
1615 884 : }
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 1306 : CPLSetThreadLocalConfigOption( const char *pszKey, const char *pszValue )
1641 :
1642 : {
1643 : #ifdef DEBUG_CONFIG_OPTIONS
1644 : CPLAccessConfigOption(pszKey, FALSE);
1645 : #endif
1646 :
1647 1306 : char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
1648 :
1649 : papszTLConfigOptions =
1650 1306 : CSLSetNameValue( papszTLConfigOptions, pszKey, pszValue );
1651 :
1652 1306 : CPLSetTLSWithFreeFunc( CTLS_CONFIGOPTIONS, papszTLConfigOptions, (CPLTLSFreeFunc)CSLDestroy );
1653 1306 : }
1654 :
1655 : /************************************************************************/
1656 : /* CPLFreeConfig() */
1657 : /************************************************************************/
1658 :
1659 1052 : void CPL_STDCALL CPLFreeConfig()
1660 :
1661 : {
1662 : {
1663 1052 : CPLMutexHolderD( &hConfigMutex );
1664 :
1665 1052 : CSLDestroy( (char **) papszConfigOptions);
1666 1052 : papszConfigOptions = NULL;
1667 :
1668 1052 : char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
1669 1052 : if( papszTLConfigOptions != NULL )
1670 : {
1671 4 : CSLDestroy( papszTLConfigOptions );
1672 4 : CPLSetTLS( CTLS_CONFIGOPTIONS, NULL, FALSE );
1673 1052 : }
1674 : }
1675 1052 : CPLDestroyMutex( hConfigMutex );
1676 1052 : hConfigMutex = NULL;
1677 1052 : }
1678 :
1679 : /************************************************************************/
1680 : /* CPLStat() */
1681 : /* */
1682 : /* Same as VSIStat() except it works on "C:" as if it were */
1683 : /* "C:\". */
1684 : /************************************************************************/
1685 :
1686 1298 : int CPLStat( const char *pszPath, VSIStatBuf *psStatBuf )
1687 :
1688 : {
1689 1298 : 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 1298 : 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 290 : const char *CPLDecToDMS( double dfAngle, const char * pszAxis,
1809 : int nPrecision )
1810 :
1811 : {
1812 290 : 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 290 : dfEpsilon = (0.5/3600.0) * pow(0.1,nPrecision);
1822 :
1823 290 : dfABSAngle = ABS(dfAngle) + dfEpsilon;
1824 290 : if (dfABSAngle > 361)
1825 : {
1826 0 : return "Invalid angle";
1827 : }
1828 :
1829 290 : nDegrees = (int) dfABSAngle;
1830 290 : nMinutes = (int) ((dfABSAngle - nDegrees) * 60);
1831 290 : dfSeconds = dfABSAngle * 3600 - nDegrees*3600 - nMinutes*60;
1832 :
1833 290 : if( dfSeconds > dfEpsilon * 3600.0 )
1834 290 : dfSeconds -= dfEpsilon * 3600.0;
1835 :
1836 405 : if( EQUAL(pszAxis,"Long") && dfAngle < 0.0 )
1837 115 : pszHemisphere = "W";
1838 175 : else if( EQUAL(pszAxis,"Long") )
1839 30 : pszHemisphere = "E";
1840 145 : else if( dfAngle < 0.0 )
1841 10 : pszHemisphere = "S";
1842 : else
1843 135 : pszHemisphere = "N";
1844 :
1845 290 : sprintf( szFormat, "%%3dd%%2d\'%%%d.%df\"%s", nPrecision+3, nPrecision, pszHemisphere );
1846 290 : sprintf( szBuffer, szFormat, nDegrees, nMinutes, dfSeconds );
1847 :
1848 290 : 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 14 : FILE *CPLOpenShared( const char *pszFilename, const char *pszAccess,
2013 : int bLarge )
2014 :
2015 : {
2016 : int i;
2017 : int bReuse;
2018 14 : CPLMutexHolderD( &hSharedFileMutex );
2019 14 : GIntBig nPID = CPLGetPID();
2020 :
2021 : /* -------------------------------------------------------------------- */
2022 : /* Is there an existing file we can use? */
2023 : /* -------------------------------------------------------------------- */
2024 14 : bReuse = EQUAL(pszAccess,"rb") || EQUAL(pszAccess, "rb+");
2025 :
2026 17 : for( i = 0; bReuse && i < nSharedFileCount; i++ )
2027 : {
2028 27 : if( strcmp(pasSharedFileList[i].pszFilename,pszFilename) == 0
2029 6 : && !bLarge == !pasSharedFileList[i].bLarge
2030 6 : && EQUAL(pasSharedFileList[i].pszAccess,pszAccess)
2031 6 : && nPID == pasSharedFileListExtra[i].nPID)
2032 : {
2033 6 : pasSharedFileList[i].nRefCount++;
2034 6 : 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 14 : void CPLCloseShared( FILE * fp )
2088 :
2089 : {
2090 14 : CPLMutexHolderD( &hSharedFileMutex );
2091 : int i;
2092 :
2093 : /* -------------------------------------------------------------------- */
2094 : /* Search for matching information. */
2095 : /* -------------------------------------------------------------------- */
2096 14 : for( i = 0; i < nSharedFileCount && fp != pasSharedFileList[i].fp; i++ ){}
2097 :
2098 14 : 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 14 : 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 : /************************************************************************/
2142 : /* CPLCleanupSharedFileMutex() */
2143 : /************************************************************************/
2144 :
2145 550 : void CPLCleanupSharedFileMutex()
2146 : {
2147 550 : if( hSharedFileMutex != NULL )
2148 : {
2149 1 : CPLDestroyMutex(hSharedFileMutex);
2150 1 : hSharedFileMutex = NULL;
2151 : }
2152 550 : }
2153 :
2154 : /************************************************************************/
2155 : /* CPLGetSharedList() */
2156 : /************************************************************************/
2157 :
2158 : /**
2159 : * Fetch list of open shared files.
2160 : *
2161 : * @param pnCount place to put the count of entries.
2162 : *
2163 : * @return the pointer to the first in the array of shared file info
2164 : * structures.
2165 : */
2166 :
2167 0 : CPLSharedFileInfo *CPLGetSharedList( int *pnCount )
2168 :
2169 : {
2170 0 : if( pnCount != NULL )
2171 0 : *pnCount = nSharedFileCount;
2172 :
2173 0 : return (CPLSharedFileInfo *) pasSharedFileList;
2174 : }
2175 :
2176 : /************************************************************************/
2177 : /* CPLDumpSharedList() */
2178 : /************************************************************************/
2179 :
2180 : /**
2181 : * Report open shared files.
2182 : *
2183 : * Dumps all open shared files to the indicated file handle. If the
2184 : * file handle is NULL information is sent via the CPLDebug() call.
2185 : *
2186 : * @param fp File handle to write to.
2187 : */
2188 :
2189 22 : void CPLDumpSharedList( FILE *fp )
2190 :
2191 : {
2192 : int i;
2193 :
2194 22 : if( nSharedFileCount > 0 )
2195 : {
2196 0 : if( fp == NULL )
2197 0 : CPLDebug( "CPL", "%d Shared files open.", nSharedFileCount );
2198 : else
2199 0 : fprintf( fp, "%d Shared files open.", nSharedFileCount );
2200 : }
2201 :
2202 22 : for( i = 0; i < nSharedFileCount; i++ )
2203 : {
2204 0 : if( fp == NULL )
2205 : CPLDebug( "CPL",
2206 : "%2d %d %4s %s",
2207 0 : pasSharedFileList[i].nRefCount,
2208 0 : pasSharedFileList[i].bLarge,
2209 0 : pasSharedFileList[i].pszAccess,
2210 0 : pasSharedFileList[i].pszFilename );
2211 : else
2212 : fprintf( fp, "%2d %d %4s %s",
2213 0 : pasSharedFileList[i].nRefCount,
2214 0 : pasSharedFileList[i].bLarge,
2215 0 : pasSharedFileList[i].pszAccess,
2216 0 : pasSharedFileList[i].pszFilename );
2217 : }
2218 22 : }
2219 :
2220 : /************************************************************************/
2221 : /* CPLUnlinkTree() */
2222 : /************************************************************************/
2223 :
2224 : /**
2225 : * @return 0 on successful completion, -1 if function fails.
2226 : */
2227 :
2228 20 : int CPLUnlinkTree( const char *pszPath )
2229 :
2230 : {
2231 : /* -------------------------------------------------------------------- */
2232 : /* First, ensure there isn't any such file yet. */
2233 : /* -------------------------------------------------------------------- */
2234 : VSIStatBuf sStatBuf;
2235 :
2236 20 : if( VSIStat( pszPath, &sStatBuf ) != 0 )
2237 : {
2238 : CPLError( CE_Failure, CPLE_AppDefined,
2239 : "It seems no file system object called '%s' exists.",
2240 2 : pszPath );
2241 :
2242 2 : return -1;
2243 : }
2244 :
2245 : /* -------------------------------------------------------------------- */
2246 : /* If it's a simple file, just delete it. */
2247 : /* -------------------------------------------------------------------- */
2248 18 : if( VSI_ISREG( sStatBuf.st_mode ) )
2249 : {
2250 17 : if( VSIUnlink( pszPath ) != 0 )
2251 : {
2252 : CPLError( CE_Failure, CPLE_AppDefined, "Failed to unlink %s.",
2253 0 : pszPath );
2254 :
2255 0 : return -1;
2256 : }
2257 : else
2258 17 : return 0;
2259 : }
2260 :
2261 : /* -------------------------------------------------------------------- */
2262 : /* If it is a directory recurse then unlink the directory. */
2263 : /* -------------------------------------------------------------------- */
2264 1 : else if( VSI_ISDIR( sStatBuf.st_mode ) )
2265 : {
2266 1 : char **papszItems = CPLReadDir( pszPath );
2267 : int i;
2268 :
2269 18 : for( i = 0; papszItems != NULL && papszItems[i] != NULL; i++ )
2270 : {
2271 : char *pszSubPath;
2272 : int nErr;
2273 :
2274 17 : if( EQUAL(papszItems[i],".") || EQUAL(papszItems[i],"..") )
2275 2 : continue;
2276 :
2277 : pszSubPath = CPLStrdup(
2278 15 : CPLFormFilename( pszPath, papszItems[i], NULL ) );
2279 :
2280 15 : nErr = CPLUnlinkTree( pszSubPath );
2281 15 : CPLFree( pszSubPath );
2282 :
2283 15 : if( nErr != 0 )
2284 : {
2285 0 : CSLDestroy( papszItems );
2286 0 : return nErr;
2287 : }
2288 : }
2289 :
2290 1 : CSLDestroy( papszItems );
2291 :
2292 1 : if( VSIRmdir( pszPath ) != 0 )
2293 : {
2294 : CPLError( CE_Failure, CPLE_AppDefined, "Failed to unlink %s.",
2295 0 : pszPath );
2296 :
2297 0 : return -1;
2298 : }
2299 : else
2300 1 : return 0;
2301 : }
2302 :
2303 : /* -------------------------------------------------------------------- */
2304 : /* otherwise report an error. */
2305 : /* -------------------------------------------------------------------- */
2306 : else
2307 : {
2308 : CPLError( CE_Failure, CPLE_AppDefined,
2309 : "Failed to unlink %s.\nUnrecognised filesystem object.",
2310 0 : pszPath );
2311 0 : return 1000;
2312 : }
2313 : }
2314 :
2315 : /************************************************************************/
2316 : /* CPLCopyFile() */
2317 : /************************************************************************/
2318 :
2319 462 : int CPLCopyFile( const char *pszNewPath, const char *pszOldPath )
2320 :
2321 : {
2322 : VSILFILE *fpOld, *fpNew;
2323 : GByte *pabyBuffer;
2324 : size_t nBufferSize;
2325 : size_t nBytesRead;
2326 462 : int nRet = 0;
2327 :
2328 : /* -------------------------------------------------------------------- */
2329 : /* Open old and new file. */
2330 : /* -------------------------------------------------------------------- */
2331 462 : fpOld = VSIFOpenL( pszOldPath, "rb" );
2332 462 : if( fpOld == NULL )
2333 0 : return -1;
2334 :
2335 462 : fpNew = VSIFOpenL( pszNewPath, "wb" );
2336 462 : if( fpNew == NULL )
2337 : {
2338 2 : VSIFCloseL( fpOld );
2339 2 : return -1;
2340 : }
2341 :
2342 : /* -------------------------------------------------------------------- */
2343 : /* Prepare buffer. */
2344 : /* -------------------------------------------------------------------- */
2345 460 : nBufferSize = 1024 * 1024;
2346 460 : pabyBuffer = (GByte *) CPLMalloc(nBufferSize);
2347 :
2348 : /* -------------------------------------------------------------------- */
2349 : /* Copy file over till we run out of stuff. */
2350 : /* -------------------------------------------------------------------- */
2351 460 : do {
2352 460 : nBytesRead = VSIFReadL( pabyBuffer, 1, nBufferSize, fpOld );
2353 460 : if( long(nBytesRead) < 0 )
2354 0 : nRet = -1;
2355 :
2356 460 : if( nRet == 0
2357 : && VSIFWriteL( pabyBuffer, 1, nBytesRead, fpNew ) < nBytesRead )
2358 0 : nRet = -1;
2359 : } while( nRet == 0 && nBytesRead == nBufferSize );
2360 :
2361 : /* -------------------------------------------------------------------- */
2362 : /* Cleanup */
2363 : /* -------------------------------------------------------------------- */
2364 460 : VSIFCloseL( fpNew );
2365 460 : VSIFCloseL( fpOld );
2366 :
2367 460 : CPLFree( pabyBuffer );
2368 :
2369 460 : return nRet;
2370 : }
2371 :
2372 : /************************************************************************/
2373 : /* CPLMoveFile() */
2374 : /************************************************************************/
2375 :
2376 4 : int CPLMoveFile( const char *pszNewPath, const char *pszOldPath )
2377 :
2378 : {
2379 4 : if( VSIRename( pszOldPath, pszNewPath ) == 0 )
2380 4 : return 0;
2381 :
2382 0 : int nRet = CPLCopyFile( pszNewPath, pszOldPath );
2383 :
2384 0 : if( nRet == 0 )
2385 0 : VSIUnlink( pszOldPath );
2386 :
2387 0 : return nRet;
2388 : }
2389 :
2390 : /************************************************************************/
2391 : /* ==================================================================== */
2392 : /* CPLLocaleC */
2393 : /* ==================================================================== */
2394 : /************************************************************************/
2395 :
2396 : #include <locale.h>
2397 :
2398 : /************************************************************************/
2399 : /* CPLLocaleC() */
2400 : /************************************************************************/
2401 :
2402 87555 : CPLLocaleC::CPLLocaleC() : pszOldLocale(CPLStrdup(setlocale(LC_NUMERIC,NULL)))
2403 :
2404 : {
2405 87555 : if( CSLTestBoolean(CPLGetConfigOption("GDAL_DISABLE_CPLLOCALEC","NO"))
2406 : || EQUAL(pszOldLocale,"C")
2407 : || EQUAL(pszOldLocale,"POSIX")
2408 : || setlocale(LC_NUMERIC,"C") == NULL )
2409 : {
2410 87555 : CPLFree( pszOldLocale );
2411 87555 : pszOldLocale = NULL;
2412 : }
2413 87555 : }
2414 :
2415 : /************************************************************************/
2416 : /* ~CPLLocaleC() */
2417 : /************************************************************************/
2418 :
2419 87555 : CPLLocaleC::~CPLLocaleC()
2420 :
2421 : {
2422 87555 : if( pszOldLocale != NULL )
2423 : {
2424 0 : setlocale( LC_NUMERIC, pszOldLocale );
2425 0 : CPLFree( pszOldLocale );
2426 : }
2427 87555 : }
2428 :
2429 : /************************************************************************/
2430 : /* CPLCheckForFile() */
2431 : /************************************************************************/
2432 :
2433 : /**
2434 : * Check for file existance.
2435 : *
2436 : * The function checks if a named file exists in the filesystem, hopefully
2437 : * in an efficient fashion if a sibling file list is available. It exists
2438 : * primarily to do faster file checking for functions like GDAL open methods
2439 : * that get a list of files from the target directory.
2440 : *
2441 : * If the sibling file list exists (is not NULL) it is assumed to be a list
2442 : * of files in the same directory as the target file, and it will be checked
2443 : * (case insensitively) for a match. If a match is found, pszFilename is
2444 : * updated with the correct case and TRUE is returned.
2445 : *
2446 : * If papszSiblingFiles is NULL, a VSIStatL() is used to test for the files
2447 : * existance, and no case insensitive testing is done.
2448 : *
2449 : * @param pszFilename name of file to check for - filename case updated in some cases.
2450 : * @param papszSiblingFiles a list of files in the same directory as
2451 : * pszFilename if available, or NULL. This list should have no path components.
2452 : *
2453 : * @return TRUE if a match is found, or FALSE if not.
2454 : */
2455 :
2456 7480 : int CPLCheckForFile( char *pszFilename, char **papszSiblingFiles )
2457 :
2458 : {
2459 : /* -------------------------------------------------------------------- */
2460 : /* Fallback case if we don't have a sibling file list. */
2461 : /* -------------------------------------------------------------------- */
2462 7480 : if( papszSiblingFiles == NULL )
2463 : {
2464 : VSIStatBufL sStatBuf;
2465 :
2466 3738 : return VSIStatL( pszFilename, &sStatBuf ) == 0;
2467 : }
2468 :
2469 : /* -------------------------------------------------------------------- */
2470 : /* We have sibling files, compare the non-path filename portion */
2471 : /* of pszFilename too all entries. */
2472 : /* -------------------------------------------------------------------- */
2473 3742 : CPLString osFileOnly = CPLGetFilename( pszFilename );
2474 : int i;
2475 :
2476 198941 : for( i = 0; papszSiblingFiles[i] != NULL; i++ )
2477 : {
2478 195302 : if( EQUAL(papszSiblingFiles[i],osFileOnly) )
2479 : {
2480 : strcpy( pszFilename + strlen(pszFilename) - strlen(osFileOnly),
2481 103 : papszSiblingFiles[i] );
2482 103 : return TRUE;
2483 : }
2484 : }
2485 :
2486 3639 : return FALSE;
2487 : }
2488 :
2489 : /************************************************************************/
2490 : /* Stub implementation of zip services if we don't have libz. */
2491 : /************************************************************************/
2492 :
2493 : #if !defined(HAVE_LIBZ)
2494 :
2495 : void *CPLCreateZip( const char *pszZipFilename, char **papszOptions )
2496 :
2497 : {
2498 : CPLError( CE_Failure, CPLE_NotSupported,
2499 : "This GDAL/OGR build does not include zlib and zip services." );
2500 : return NULL;
2501 : }
2502 :
2503 : CPLErr CPLCreateFileInZip( void *hZip, const char *pszFilename,
2504 : char **papszOptions )
2505 :
2506 : {
2507 : return CE_Failure;
2508 : }
2509 :
2510 : CPLErr CPLWriteFileInZip( void *hZip, const void *pBuffer, int nBufferSize )
2511 :
2512 : {
2513 : return CE_Failure;
2514 : }
2515 :
2516 : CPLErr CPLCloseFileInZip( void *hZip )
2517 :
2518 : {
2519 : return CE_Failure;
2520 : }
2521 :
2522 : CPLErr CPLCloseZip( void *hZip )
2523 :
2524 : {
2525 : return CE_Failure;
2526 : }
2527 :
2528 : void* CPLZLibDeflate( const void* ptr, size_t nBytes, int nLevel,
2529 : void* outptr, size_t nOutAvailableBytes,
2530 : size_t* pnOutBytes )
2531 : {
2532 : if( pnOutBytes != NULL )
2533 : *pnOutBytes = 0;
2534 : return NULL;
2535 : }
2536 :
2537 : void* CPLZLibInflate( const void* ptr, size_t nBytes,
2538 : void* outptr, size_t nOutAvailableBytes,
2539 : size_t* pnOutBytes )
2540 : {
2541 : if( pnOutBytes != NULL )
2542 : *pnOutBytes = 0;
2543 : return NULL;
2544 : }
2545 :
2546 : #endif /* !defined(HAVE_LIBZ) */
|