1 : /******************************************************************************
2 : * $Id: ogrutils.cpp 23584 2011-12-17 09:43:03Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Utility functions for OGR classes, including some related to
6 : * parsing well known text format vectors.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 1999, Frank Warmerdam
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include <ctype.h>
32 :
33 : #include "ogr_geometry.h"
34 : #include "ogr_p.h"
35 :
36 : #ifdef OGR_ENABLED
37 : # include "ogrsf_frmts.h"
38 : #endif /* OGR_ENABLED */
39 :
40 : CPL_CVSID("$Id: ogrutils.cpp 23584 2011-12-17 09:43:03Z rouault $");
41 :
42 : /************************************************************************/
43 : /* OGRFormatDouble() */
44 : /************************************************************************/
45 :
46 8945 : void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal, char chDecimalSep, int nPrecision )
47 : {
48 : int i;
49 8945 : int bHasTruncated = FALSE;
50 : char szFormat[16];
51 8945 : sprintf(szFormat, "%%.%df", nPrecision);
52 :
53 8945 : int ret = snprintf(pszBuffer, nBufferLen, szFormat, dfVal);
54 : /* Windows CRT doesn't conform with C99 and return -1 when buffer is truncated */
55 8945 : if (ret >= nBufferLen || ret == -1)
56 2 : return;
57 :
58 24 : while(TRUE)
59 : {
60 8967 : i = 0;
61 8967 : int nCountBeforeDot = 0;
62 8967 : int iDotPos = -1;
63 204340 : while( pszBuffer[i] != '\0' )
64 : {
65 195373 : if ((pszBuffer[i] == '.' || pszBuffer[i] == ',') && chDecimalSep != '\0')
66 : {
67 8967 : iDotPos = i;
68 8967 : pszBuffer[i] = chDecimalSep;
69 : }
70 177439 : else if (iDotPos < 0 && pszBuffer[i] != '-')
71 48568 : nCountBeforeDot ++;
72 186406 : i++;
73 : }
74 :
75 : /* -------------------------------------------------------------------- */
76 : /* Trim trailing 00000x's as they are likely roundoff error. */
77 : /* -------------------------------------------------------------------- */
78 8967 : if( i > 10 && iDotPos >=0 )
79 : {
80 56245 : if (/* && pszBuffer[i-1] == '1' &&*/
81 8591 : pszBuffer[i-2] == '0'
82 7936 : && pszBuffer[i-3] == '0'
83 7860 : && pszBuffer[i-4] == '0'
84 7851 : && pszBuffer[i-5] == '0'
85 7851 : && pszBuffer[i-6] == '0' )
86 : {
87 7565 : pszBuffer[--i] = '\0';
88 : }
89 2973 : else if( i - 8 > iDotPos && /* pszBuffer[i-1] == '1' */
90 : /* && pszBuffer[i-2] == '0' && */
91 966 : (nCountBeforeDot >= 4 || pszBuffer[i-3] == '0')
92 327 : && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '0')
93 293 : && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '0')
94 319 : && (nCountBeforeDot >= 7 || pszBuffer[i-6] == '0')
95 22 : && (nCountBeforeDot >= 8 || pszBuffer[i-7] == '0')
96 10 : && pszBuffer[i-8] == '0'
97 10 : && pszBuffer[i-9] == '0')
98 : {
99 10 : i -= 8;
100 10 : pszBuffer[i] = '\0';
101 : }
102 : }
103 :
104 : /* -------------------------------------------------------------------- */
105 : /* Trim trailing zeros. */
106 : /* -------------------------------------------------------------------- */
107 104204 : while( i > 2 && pszBuffer[i-1] == '0' && pszBuffer[i-2] != '.' )
108 : {
109 86270 : pszBuffer[--i] = '\0';
110 : }
111 :
112 : /* -------------------------------------------------------------------- */
113 : /* Detect trailing 99999X's as they are likely roundoff error. */
114 : /* -------------------------------------------------------------------- */
115 8967 : if( !bHasTruncated &&
116 : i > 10 &&
117 : iDotPos >= 0 &&
118 : nPrecision >= 15)
119 : {
120 7686 : if (/*pszBuffer[i-1] == '9' && */
121 3721 : pszBuffer[i-2] == '9'
122 132 : && pszBuffer[i-3] == '9'
123 50 : && pszBuffer[i-4] == '9'
124 31 : && pszBuffer[i-5] == '9'
125 31 : && pszBuffer[i-6] == '9' )
126 : {
127 9 : snprintf(pszBuffer, nBufferLen, "%.9f", dfVal);
128 9 : bHasTruncated = TRUE;
129 9 : continue;
130 : }
131 4935 : else if (i - 9 > iDotPos && /*pszBuffer[i-1] == '9' && */
132 : /*pszBuffer[i-2] == '9' && */
133 956 : (nCountBeforeDot >= 4 || pszBuffer[i-3] == '9')
134 141 : && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '9')
135 22 : && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '9')
136 45 : && (nCountBeforeDot >= 7 || pszBuffer[i-6] == '9')
137 29 : && (nCountBeforeDot >= 8 || pszBuffer[i-7] == '9')
138 15 : && pszBuffer[i-8] == '9'
139 15 : && pszBuffer[i-9] == '9')
140 : {
141 15 : sprintf(szFormat, "%%.%df", MIN(5,12 - nCountBeforeDot));
142 15 : snprintf(pszBuffer, nBufferLen, szFormat, dfVal);
143 15 : bHasTruncated = TRUE;
144 15 : continue;
145 : }
146 : }
147 :
148 8943 : break;
149 : }
150 :
151 : }
152 :
153 : /************************************************************************/
154 : /* OGRMakeWktCoordinate() */
155 : /* */
156 : /* Format a well known text coordinate, trying to keep the */
157 : /* ASCII representation compact, but accurate. These rules */
158 : /* will have to tighten up in the future. */
159 : /* */
160 : /* Currently a new point should require no more than 64 */
161 : /* characters barring the X or Y value being extremely large. */
162 : /************************************************************************/
163 :
164 6970 : void OGRMakeWktCoordinate( char *pszTarget, double x, double y, double z,
165 : int nDimension )
166 :
167 : {
168 6970 : const size_t bufSize = 75;
169 6970 : const size_t maxTargetSize = 75; /* Assumed max length of the target buffer. */
170 :
171 : char szX[bufSize];
172 : char szY[bufSize];
173 : char szZ[bufSize];
174 :
175 6970 : szZ[0] = '\0';
176 :
177 : int nLenX, nLenY;
178 :
179 9776 : if( x == (int) x && y == (int) y )
180 : {
181 2806 : snprintf( szX, bufSize, "%d", (int) x );
182 2806 : snprintf( szY, bufSize, "%d", (int) y );
183 : }
184 : else
185 : {
186 4164 : OGRFormatDouble( szX, bufSize, x, '.' );
187 4164 : OGRFormatDouble( szY, bufSize, y, '.' );
188 : }
189 :
190 6970 : nLenX = strlen(szX);
191 6970 : nLenY = strlen(szY);
192 :
193 6970 : if( nDimension == 3 )
194 : {
195 1120 : if( z == (int) z )
196 : {
197 1113 : snprintf( szZ, bufSize, "%d", (int) z );
198 : }
199 : else
200 : {
201 7 : OGRFormatDouble( szZ, bufSize, z, '.' );
202 : }
203 : }
204 :
205 6970 : if( nLenX + 1 + nLenY + ((nDimension == 3) ? (1 + strlen(szZ)) : 0) >= maxTargetSize )
206 : {
207 : #ifdef DEBUG
208 : CPLDebug( "OGR",
209 : "Yow! Got this big result in OGRMakeWktCoordinate()\n"
210 : "%s %s %s",
211 1 : szX, szY, szZ );
212 : #endif
213 1 : if( nDimension == 3 )
214 1 : strcpy( pszTarget, "0 0 0");
215 : else
216 0 : strcpy( pszTarget, "0 0");
217 : }
218 : else
219 : {
220 6969 : memcpy( pszTarget, szX, nLenX );
221 6969 : pszTarget[nLenX] = ' ';
222 6969 : memcpy( pszTarget + nLenX + 1, szY, nLenY );
223 6969 : if (nDimension == 3)
224 : {
225 1119 : pszTarget[nLenX + 1 + nLenY] = ' ';
226 1119 : strcpy( pszTarget + nLenX + 1 + nLenY + 1, szZ );
227 : }
228 : else
229 : {
230 5850 : pszTarget[nLenX + 1 + nLenY] = '\0';
231 : }
232 : }
233 6970 : }
234 :
235 : /************************************************************************/
236 : /* OGRWktReadToken() */
237 : /* */
238 : /* Read one token or delimeter and put into token buffer. Pre */
239 : /* and post white space is swallowed. */
240 : /************************************************************************/
241 :
242 151510 : const char *OGRWktReadToken( const char * pszInput, char * pszToken )
243 :
244 : {
245 151510 : if( pszInput == NULL )
246 0 : return NULL;
247 :
248 : /* -------------------------------------------------------------------- */
249 : /* Swallow pre-white space. */
250 : /* -------------------------------------------------------------------- */
251 303020 : while( *pszInput == ' ' || *pszInput == '\t' )
252 0 : pszInput++;
253 :
254 : /* -------------------------------------------------------------------- */
255 : /* If this is a delimeter, read just one character. */
256 : /* -------------------------------------------------------------------- */
257 193037 : if( *pszInput == '(' || *pszInput == ')' || *pszInput == ',' )
258 : {
259 41527 : pszToken[0] = *pszInput;
260 41527 : pszToken[1] = '\0';
261 :
262 41527 : pszInput++;
263 : }
264 :
265 : /* -------------------------------------------------------------------- */
266 : /* Or if it alpha numeric read till we reach non-alpha numeric */
267 : /* text. */
268 : /* -------------------------------------------------------------------- */
269 : else
270 : {
271 109983 : int iChar = 0;
272 :
273 970218 : while( iChar < OGR_WKT_TOKEN_MAX-1
274 : && ((*pszInput >= 'a' && *pszInput <= 'z')
275 : || (*pszInput >= 'A' && *pszInput <= 'Z')
276 : || (*pszInput >= '0' && *pszInput <= '9')
277 : || *pszInput == '.'
278 : || *pszInput == '+'
279 : || *pszInput == '-') )
280 : {
281 750252 : pszToken[iChar++] = *(pszInput++);
282 : }
283 :
284 109983 : pszToken[iChar++] = '\0';
285 : }
286 :
287 : /* -------------------------------------------------------------------- */
288 : /* Eat any trailing white space. */
289 : /* -------------------------------------------------------------------- */
290 359788 : while( *pszInput == ' ' || *pszInput == '\t' )
291 56768 : pszInput++;
292 :
293 151510 : return( pszInput );
294 : }
295 :
296 : /************************************************************************/
297 : /* OGRWktReadPoints() */
298 : /* */
299 : /* Read a point string. The point list must be contained in */
300 : /* brackets and each point pair separated by a comma. */
301 : /************************************************************************/
302 :
303 16817 : const char * OGRWktReadPoints( const char * pszInput,
304 : OGRRawPoint ** ppaoPoints, double **ppadfZ,
305 : int * pnMaxPoints,
306 : int * pnPointsRead )
307 :
308 : {
309 16817 : const char *pszOrigInput = pszInput;
310 16817 : *pnPointsRead = 0;
311 :
312 16817 : if( pszInput == NULL )
313 0 : return NULL;
314 :
315 : /* -------------------------------------------------------------------- */
316 : /* Eat any leading white space. */
317 : /* -------------------------------------------------------------------- */
318 33634 : while( *pszInput == ' ' || *pszInput == '\t' )
319 0 : pszInput++;
320 :
321 : /* -------------------------------------------------------------------- */
322 : /* If this isn't an opening bracket then we have a problem! */
323 : /* -------------------------------------------------------------------- */
324 16817 : if( *pszInput != '(' )
325 : {
326 : CPLDebug( "OGR",
327 : "Expected '(', but got %s in OGRWktReadPoints().\n",
328 39 : pszInput );
329 :
330 39 : return pszInput;
331 : }
332 :
333 16778 : pszInput++;
334 :
335 : /* ==================================================================== */
336 : /* This loop reads a single point. It will continue till we */
337 : /* run out of well formed points, or a closing bracket is */
338 : /* encountered. */
339 : /* ==================================================================== */
340 : char szDelim[OGR_WKT_TOKEN_MAX];
341 :
342 21205 : do {
343 : /* -------------------------------------------------------------------- */
344 : /* Read the X and Y values, verify they are numeric. */
345 : /* -------------------------------------------------------------------- */
346 : char szTokenX[OGR_WKT_TOKEN_MAX];
347 : char szTokenY[OGR_WKT_TOKEN_MAX];
348 :
349 21253 : pszInput = OGRWktReadToken( pszInput, szTokenX );
350 21253 : pszInput = OGRWktReadToken( pszInput, szTokenY );
351 :
352 43695 : if( (!isdigit(szTokenX[0]) && szTokenX[0] != '-' && szTokenX[0] != '.' )
353 22442 : || (!isdigit(szTokenY[0]) && szTokenY[0] != '-' && szTokenY[0] != '.') )
354 38 : return NULL;
355 :
356 : /* -------------------------------------------------------------------- */
357 : /* Do we need to grow the point list to hold this point? */
358 : /* -------------------------------------------------------------------- */
359 21215 : if( *pnPointsRead == *pnMaxPoints )
360 : {
361 16510 : *pnMaxPoints = *pnMaxPoints * 2 + 10;
362 : *ppaoPoints = (OGRRawPoint *)
363 16510 : CPLRealloc(*ppaoPoints, sizeof(OGRRawPoint) * *pnMaxPoints);
364 :
365 16510 : if( *ppadfZ != NULL )
366 : {
367 : *ppadfZ = (double *)
368 12 : CPLRealloc(*ppadfZ, sizeof(double) * *pnMaxPoints);
369 : }
370 : }
371 :
372 : /* -------------------------------------------------------------------- */
373 : /* Add point to list. */
374 : /* -------------------------------------------------------------------- */
375 21215 : (*ppaoPoints)[*pnPointsRead].x = CPLAtof(szTokenX);
376 21215 : (*ppaoPoints)[*pnPointsRead].y = CPLAtof(szTokenY);
377 :
378 : /* -------------------------------------------------------------------- */
379 : /* Do we have a Z coordinate? */
380 : /* -------------------------------------------------------------------- */
381 21215 : pszInput = OGRWktReadToken( pszInput, szDelim );
382 :
383 36953 : if( isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.' )
384 : {
385 15738 : if( *ppadfZ == NULL )
386 : {
387 14936 : *ppadfZ = (double *) CPLCalloc(sizeof(double),*pnMaxPoints);
388 : }
389 :
390 15738 : (*ppadfZ)[*pnPointsRead] = CPLAtof(szDelim);
391 :
392 15738 : pszInput = OGRWktReadToken( pszInput, szDelim );
393 : }
394 5477 : else if ( *ppadfZ != NULL )
395 110 : (*ppadfZ)[*pnPointsRead] = 0.0;
396 :
397 21215 : (*pnPointsRead)++;
398 :
399 : /* -------------------------------------------------------------------- */
400 : /* Do we have a M coordinate? */
401 : /* If we do, just skip it. */
402 : /* -------------------------------------------------------------------- */
403 21215 : if( isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.' )
404 : {
405 54 : pszInput = OGRWktReadToken( pszInput, szDelim );
406 : }
407 :
408 : /* -------------------------------------------------------------------- */
409 : /* Read next delimeter ... it should be a comma if there are */
410 : /* more points. */
411 : /* -------------------------------------------------------------------- */
412 21215 : if( szDelim[0] != ')' && szDelim[0] != ',' )
413 : {
414 : CPLDebug( "OGR",
415 : "Corrupt input in OGRWktReadPoints()\n"
416 : "Got `%s' when expecting `,' or `)', near `%s' in %s.\n",
417 10 : szDelim, pszInput, pszOrigInput );
418 10 : return NULL;
419 : }
420 :
421 21205 : } while( szDelim[0] == ',' );
422 :
423 16730 : return pszInput;
424 : }
425 :
426 : /************************************************************************/
427 : /* OGRMalloc() */
428 : /* */
429 : /* Cover for CPLMalloc() */
430 : /************************************************************************/
431 :
432 0 : void *OGRMalloc( size_t size )
433 :
434 : {
435 0 : return CPLMalloc( size );
436 : }
437 :
438 : /************************************************************************/
439 : /* OGRCalloc() */
440 : /* */
441 : /* Cover for CPLCalloc() */
442 : /************************************************************************/
443 :
444 273412 : void * OGRCalloc( size_t count, size_t size )
445 :
446 : {
447 273412 : return CPLCalloc( count, size );
448 : }
449 :
450 : /************************************************************************/
451 : /* OGRRealloc() */
452 : /* */
453 : /* Cover for CPLRealloc() */
454 : /************************************************************************/
455 :
456 15711 : void *OGRRealloc( void * pOld, size_t size )
457 :
458 : {
459 15711 : return CPLRealloc( pOld, size );
460 : }
461 :
462 : /************************************************************************/
463 : /* OGRFree() */
464 : /* */
465 : /* Cover for CPLFree(). */
466 : /************************************************************************/
467 :
468 829333 : void OGRFree( void * pMemory )
469 :
470 : {
471 829333 : CPLFree( pMemory );
472 829333 : }
473 :
474 : /**
475 : * General utility option processing.
476 : *
477 : * This function is intended to provide a variety of generic commandline
478 : * options for all OGR commandline utilities. It takes care of the following
479 : * commandline options:
480 : *
481 : * --version: report version of GDAL in use.
482 : * --license: report GDAL license info.
483 : * --formats: report all format drivers configured.
484 : * --optfile filename: expand an option file into the argument list.
485 : * --config key value: set system configuration option.
486 : * --debug [on/off/value]: set debug level.
487 : * --pause: Pause for user input (allows time to attach debugger)
488 : * --locale [locale]: Install a locale using setlocale() (debugging)
489 : * --help-general: report detailed help on general options.
490 : *
491 : * The argument array is replaced "in place" and should be freed with
492 : * CSLDestroy() when no longer needed. The typical usage looks something
493 : * like the following. Note that the formats should be registered so that
494 : * the --formats option will work properly.
495 : *
496 : * int main( int argc, char ** argv )
497 : * {
498 : * OGRAllRegister();
499 : *
500 : * argc = OGRGeneralCmdLineProcessor( argc, &argv, 0 );
501 : * if( argc < 1 )
502 : * exit( -argc );
503 : *
504 : * @param nArgc number of values in the argument list.
505 : * @param Pointer to the argument list array (will be updated in place).
506 : *
507 : * @return updated nArgc argument count. Return of 0 requests terminate
508 : * without error, return of -1 requests exit with error code.
509 : */
510 :
511 160 : int OGRGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
512 :
513 : {
514 160 : char **papszReturn = NULL;
515 : int iArg;
516 160 : char **papszArgv = *ppapszArgv;
517 :
518 : (void) nOptions;
519 :
520 : /* -------------------------------------------------------------------- */
521 : /* Preserve the program name. */
522 : /* -------------------------------------------------------------------- */
523 160 : papszReturn = CSLAddString( papszReturn, papszArgv[0] );
524 :
525 : /* ==================================================================== */
526 : /* Loop over all arguments. */
527 : /* ==================================================================== */
528 801 : for( iArg = 1; iArg < nArgc; iArg++ )
529 : {
530 : /* -------------------------------------------------------------------- */
531 : /* --version */
532 : /* -------------------------------------------------------------------- */
533 641 : if( EQUAL(papszArgv[iArg],"--version") )
534 : {
535 0 : printf( "%s\n", GDALVersionInfo( "--version" ) );
536 0 : CSLDestroy( papszReturn );
537 0 : return 0;
538 : }
539 :
540 : /* -------------------------------------------------------------------- */
541 : /* --license */
542 : /* -------------------------------------------------------------------- */
543 641 : else if( EQUAL(papszArgv[iArg],"--license") )
544 : {
545 0 : printf( "%s\n", GDALVersionInfo( "LICENSE" ) );
546 0 : CSLDestroy( papszReturn );
547 0 : return 0;
548 : }
549 :
550 : /* -------------------------------------------------------------------- */
551 : /* --config */
552 : /* -------------------------------------------------------------------- */
553 641 : else if( EQUAL(papszArgv[iArg],"--config") )
554 : {
555 3 : if( iArg + 2 >= nArgc )
556 : {
557 : CPLError( CE_Failure, CPLE_AppDefined,
558 0 : "--config option given without a key and value argument." );
559 0 : CSLDestroy( papszReturn );
560 0 : return -1;
561 : }
562 :
563 3 : CPLSetConfigOption( papszArgv[iArg+1], papszArgv[iArg+2] );
564 :
565 3 : iArg += 2;
566 : }
567 :
568 : /* -------------------------------------------------------------------- */
569 : /* --mempreload */
570 : /* -------------------------------------------------------------------- */
571 638 : else if( EQUAL(papszArgv[iArg],"--mempreload") )
572 : {
573 : int i;
574 :
575 0 : if( iArg + 1 >= nArgc )
576 : {
577 : CPLError( CE_Failure, CPLE_AppDefined,
578 0 : "--mempreload option given without directory path.");
579 0 : CSLDestroy( papszReturn );
580 0 : return -1;
581 : }
582 :
583 0 : char **papszFiles = CPLReadDir( papszArgv[iArg+1] );
584 0 : if( CSLCount(papszFiles) == 0 )
585 : {
586 : CPLError( CE_Failure, CPLE_AppDefined,
587 0 : "--mempreload given invalid or empty directory.");
588 0 : CSLDestroy( papszReturn );
589 0 : return -1;
590 : }
591 :
592 0 : for( i = 0; papszFiles[i] != NULL; i++ )
593 : {
594 0 : CPLString osOldPath, osNewPath;
595 :
596 0 : if( EQUAL(papszFiles[i],".") || EQUAL(papszFiles[i],"..") )
597 0 : continue;
598 :
599 0 : osOldPath = CPLFormFilename( papszArgv[iArg+1],
600 0 : papszFiles[i], NULL );
601 0 : osNewPath.Printf( "/vsimem/%s", papszFiles[i] );
602 :
603 : CPLDebug( "VSI", "Preloading %s to %s.",
604 0 : osOldPath.c_str(), osNewPath.c_str() );
605 :
606 0 : if( CPLCopyFile( osNewPath, osOldPath ) != 0 )
607 0 : return -1;
608 : }
609 :
610 0 : CSLDestroy( papszFiles );
611 0 : iArg += 1;
612 : }
613 :
614 : /* -------------------------------------------------------------------- */
615 : /* --debug */
616 : /* -------------------------------------------------------------------- */
617 638 : else if( EQUAL(papszArgv[iArg],"--debug") )
618 : {
619 0 : if( iArg + 1 >= nArgc )
620 : {
621 : CPLError( CE_Failure, CPLE_AppDefined,
622 0 : "--debug option given without debug level." );
623 0 : CSLDestroy( papszReturn );
624 0 : return -1;
625 : }
626 :
627 0 : CPLSetConfigOption( "CPL_DEBUG", papszArgv[iArg+1] );
628 0 : iArg += 1;
629 : }
630 :
631 : /* -------------------------------------------------------------------- */
632 : /* --optfile */
633 : /* */
634 : /* Annoyingly the options inserted by --optfile will *not* be */
635 : /* processed properly if they are general options. */
636 : /* -------------------------------------------------------------------- */
637 638 : else if( EQUAL(papszArgv[iArg],"--optfile") )
638 : {
639 : const char *pszLine;
640 : FILE *fpOptFile;
641 :
642 0 : if( iArg + 1 >= nArgc )
643 : {
644 : CPLError( CE_Failure, CPLE_AppDefined,
645 0 : "--optfile option given without filename." );
646 0 : CSLDestroy( papszReturn );
647 0 : return -1;
648 : }
649 :
650 0 : fpOptFile = VSIFOpen( papszArgv[iArg+1], "rb" );
651 :
652 0 : if( fpOptFile == NULL )
653 : {
654 : CPLError( CE_Failure, CPLE_AppDefined,
655 : "Unable to open optfile '%s'.\n%s",
656 0 : papszArgv[iArg+1], VSIStrerror( errno ) );
657 0 : CSLDestroy( papszReturn );
658 0 : return -1;
659 : }
660 :
661 0 : while( (pszLine = CPLReadLine( fpOptFile )) != NULL )
662 : {
663 : char **papszTokens;
664 : int i;
665 :
666 0 : if( pszLine[0] == '#' || strlen(pszLine) == 0 )
667 0 : continue;
668 :
669 0 : papszTokens = CSLTokenizeString( pszLine );
670 0 : for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++)
671 0 : papszReturn = CSLAddString( papszReturn, papszTokens[i] );
672 0 : CSLDestroy( papszTokens );
673 : }
674 :
675 0 : VSIFClose( fpOptFile );
676 :
677 0 : iArg += 1;
678 : }
679 :
680 : /* -------------------------------------------------------------------- */
681 : /* --formats */
682 : /* -------------------------------------------------------------------- */
683 : #ifdef OGR_ENABLED
684 638 : else if( EQUAL(papszArgv[iArg], "--formats") )
685 : {
686 : int iDr;
687 :
688 0 : printf( "Supported Formats:\n" );
689 :
690 0 : OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
691 :
692 0 : for( iDr = 0; iDr < poR->GetDriverCount(); iDr++ )
693 : {
694 0 : OGRSFDriver *poDriver = poR->GetDriver(iDr);
695 :
696 0 : if( poDriver->TestCapability( ODrCCreateDataSource ) )
697 : printf( " -> \"%s\" (read/write)\n",
698 0 : poDriver->GetName() );
699 : else
700 : printf( " -> \"%s\" (readonly)\n",
701 0 : poDriver->GetName() );
702 : }
703 :
704 0 : CSLDestroy( papszReturn );
705 0 : return 0;
706 : }
707 : #endif /* OGR_ENABLED */
708 :
709 : /* -------------------------------------------------------------------- */
710 : /* --locale */
711 : /* -------------------------------------------------------------------- */
712 638 : else if( EQUAL(papszArgv[iArg],"--locale") && iArg < nArgc-1 )
713 : {
714 0 : setlocale( LC_ALL, papszArgv[++iArg] );
715 : }
716 :
717 : /* -------------------------------------------------------------------- */
718 : /* --pause - "hit enter" pause useful to connect a debugger. */
719 : /* -------------------------------------------------------------------- */
720 638 : else if( EQUAL(papszArgv[iArg],"--pause") )
721 : {
722 0 : printf( "Hit <ENTER> to Continue.\n" );
723 0 : CPLReadLine( stdin );
724 : }
725 :
726 : /* -------------------------------------------------------------------- */
727 : /* --help-general */
728 : /* -------------------------------------------------------------------- */
729 638 : else if( EQUAL(papszArgv[iArg],"--help-general") )
730 : {
731 0 : printf( "Generic GDAL/OGR utility command options:\n" );
732 0 : printf( " --version: report version of GDAL/OGR in use.\n" );
733 0 : printf( " --license: report GDAL/OGR license info.\n" );
734 : #ifdef OGR_ENABLED
735 0 : printf( " --formats: report all configured format drivers.\n" );
736 : #endif /* OGR_ENABLED */
737 0 : printf( " --optfile filename: expand an option file into the argument list.\n" );
738 0 : printf( " --config key value: set system configuration option.\n" );
739 0 : printf( " --debug [on/off/value]: set debug level.\n" );
740 0 : printf( " --pause: wait for user input, time to attach debugger\n" );
741 0 : printf( " --locale [locale]: install locale for debugging (ie. en_US.UTF-8)\n" );
742 0 : printf( " --help-general: report detailed help on general options.\n" );
743 0 : CSLDestroy( papszReturn );
744 0 : return 0;
745 : }
746 :
747 : /* -------------------------------------------------------------------- */
748 : /* carry through unrecognised options. */
749 : /* -------------------------------------------------------------------- */
750 : else
751 : {
752 638 : papszReturn = CSLAddString( papszReturn, papszArgv[iArg] );
753 : }
754 : }
755 :
756 160 : *ppapszArgv = papszReturn;
757 :
758 160 : return CSLCount( *ppapszArgv );
759 : }
760 :
761 : /************************************************************************/
762 : /* OGRParseDate() */
763 : /* */
764 : /* Parse a variety of text date formats into an OGRField. */
765 : /************************************************************************/
766 :
767 : /**
768 : * Parse date string.
769 : *
770 : * This function attempts to parse a date string in a variety of formats
771 : * into the OGRField.Date format suitable for use with OGR. Generally
772 : * speaking this function is expecting values like:
773 : *
774 : * YYYY-MM-DD HH:MM:SS+nn
775 : *
776 : * The seconds may also have a decimal portion (which is ignored). And
777 : * just dates (YYYY-MM-DD) or just times (HH:MM:SS) are also supported.
778 : * The date may also be in YYYY/MM/DD format. If the year is less than 100
779 : * and greater than 30 a "1900" century value will be set. If it is less than
780 : * 30 and greater than -1 then a "2000" century value will be set. In
781 : * the future this function may be generalized, and additional control
782 : * provided through nOptions, but an nOptions value of "0" should always do
783 : * a reasonable default form of processing.
784 : *
785 : * The value of psField will be indeterminate if the function fails (returns
786 : * FALSE).
787 : *
788 : * @param pszInput the input date string.
789 : * @param psField the OGRField that will be updated with the parsed result.
790 : * @param nOptions parsing options, for now always 0.
791 : *
792 : * @return TRUE if apparently successful or FALSE on failure.
793 : */
794 :
795 263 : int OGRParseDate( const char *pszInput, OGRField *psField, int nOptions )
796 :
797 : {
798 263 : int bGotSomething = FALSE;
799 :
800 263 : psField->Date.Year = 0;
801 263 : psField->Date.Month = 0;
802 263 : psField->Date.Day = 0;
803 263 : psField->Date.Hour = 0;
804 263 : psField->Date.Minute = 0;
805 263 : psField->Date.Second = 0;
806 263 : psField->Date.TZFlag = 0;
807 :
808 : /* -------------------------------------------------------------------- */
809 : /* Do we have a date? */
810 : /* -------------------------------------------------------------------- */
811 526 : while( *pszInput == ' ' )
812 0 : pszInput++;
813 :
814 263 : if( strstr(pszInput,"-") != NULL || strstr(pszInput,"/") != NULL )
815 : {
816 202 : psField->Date.Year = (GInt16)atoi(pszInput);
817 202 : if( psField->Date.Year < 100 && psField->Date.Year >= 30 )
818 0 : psField->Date.Year += 1900;
819 202 : else if( psField->Date.Year < 30 && psField->Date.Year >= 0 )
820 0 : psField->Date.Year += 2000;
821 :
822 1212 : while( *pszInput >= '0' && *pszInput <= '9' )
823 808 : pszInput++;
824 202 : if( *pszInput != '-' && *pszInput != '/' )
825 0 : return FALSE;
826 : else
827 202 : pszInput++;
828 :
829 202 : psField->Date.Month = (GByte)atoi(pszInput);
830 202 : if( psField->Date.Month > 12 )
831 0 : return FALSE;
832 :
833 808 : while( *pszInput >= '0' && *pszInput <= '9' )
834 404 : pszInput++;
835 202 : if( *pszInput != '-' && *pszInput != '/' )
836 0 : return FALSE;
837 : else
838 202 : pszInput++;
839 :
840 202 : psField->Date.Day = (GByte)atoi(pszInput);
841 202 : if( psField->Date.Day > 31 )
842 0 : return FALSE;
843 :
844 808 : while( *pszInput >= '0' && *pszInput <= '9' )
845 404 : pszInput++;
846 :
847 202 : bGotSomething = TRUE;
848 : }
849 :
850 : /* -------------------------------------------------------------------- */
851 : /* Do we have a time? */
852 : /* -------------------------------------------------------------------- */
853 658 : while( *pszInput == ' ' )
854 132 : pszInput++;
855 :
856 263 : if( strstr(pszInput,":") != NULL )
857 : {
858 183 : psField->Date.Hour = (GByte)atoi(pszInput);
859 183 : if( psField->Date.Hour > 23 )
860 0 : return FALSE;
861 :
862 729 : while( *pszInput >= '0' && *pszInput <= '9' )
863 363 : pszInput++;
864 183 : if( *pszInput != ':' )
865 1 : return FALSE;
866 : else
867 182 : pszInput++;
868 :
869 182 : psField->Date.Minute = (GByte)atoi(pszInput);
870 182 : if( psField->Date.Minute > 59 )
871 0 : return FALSE;
872 :
873 728 : while( *pszInput >= '0' && *pszInput <= '9' )
874 364 : pszInput++;
875 182 : if( *pszInput != ':' )
876 0 : return FALSE;
877 : else
878 182 : pszInput++;
879 :
880 182 : psField->Date.Second = (GByte)atoi(pszInput);
881 182 : if( psField->Date.Second > 59 )
882 0 : return FALSE;
883 :
884 728 : while( (*pszInput >= '0' && *pszInput <= '9')
885 : || *pszInput == '.' )
886 364 : pszInput++;
887 :
888 182 : bGotSomething = TRUE;
889 : }
890 :
891 : // No date or time!
892 262 : if( !bGotSomething )
893 3 : return FALSE;
894 :
895 : /* -------------------------------------------------------------------- */
896 : /* Do we have a timezone? */
897 : /* -------------------------------------------------------------------- */
898 518 : while( *pszInput == ' ' )
899 0 : pszInput++;
900 :
901 259 : if( *pszInput == '-' || *pszInput == '+' )
902 : {
903 : // +HH integral offset
904 51 : if( strlen(pszInput) <= 3 )
905 44 : psField->Date.TZFlag = (GByte)(100 + atoi(pszInput) * 4);
906 :
907 14 : else if( pszInput[3] == ':' // +HH:MM offset
908 : && atoi(pszInput+4) % 15 == 0 )
909 : {
910 : psField->Date.TZFlag = (GByte)(100
911 : + atoi(pszInput+1) * 4
912 7 : + (atoi(pszInput+4) / 15));
913 :
914 7 : if( pszInput[0] == '-' )
915 4 : psField->Date.TZFlag = -1 * (psField->Date.TZFlag - 100) + 100;
916 : }
917 0 : else if( isdigit(pszInput[3]) && isdigit(pszInput[4]) // +HHMM offset
918 : && atoi(pszInput+3) % 15 == 0 )
919 : {
920 : psField->Date.TZFlag = (GByte)(100
921 : + static_cast<GByte>(CPLScanLong(pszInput+1,2)) * 4
922 0 : + (atoi(pszInput+3) / 15));
923 :
924 0 : if( pszInput[0] == '-' )
925 0 : psField->Date.TZFlag = -1 * (psField->Date.TZFlag - 100) + 100;
926 : }
927 0 : else if( isdigit(pszInput[3]) && pszInput[4] == '\0' // +HMM offset
928 : && atoi(pszInput+2) % 15 == 0 )
929 : {
930 : psField->Date.TZFlag = (GByte)(100
931 : + static_cast<GByte>(CPLScanLong(pszInput+1,1)) * 4
932 0 : + (atoi(pszInput+2) / 15));
933 :
934 0 : if( pszInput[0] == '-' )
935 0 : psField->Date.TZFlag = -1 * (psField->Date.TZFlag - 100) + 100;
936 : }
937 : // otherwise ignore any timezone info.
938 : }
939 :
940 259 : return TRUE;
941 : }
942 :
943 :
944 : /************************************************************************/
945 : /* OGRParseXMLDateTime() */
946 : /************************************************************************/
947 :
948 27 : int OGRParseXMLDateTime( const char* pszXMLDateTime,
949 : int *pnYear, int *pnMonth, int *pnDay,
950 : int *pnHour, int *pnMinute, float* pfSecond, int *pnTZ)
951 : {
952 27 : int year = 0, month = 0, day = 0, hour = 0, minute = 0, TZHour, TZMinute;
953 27 : float second = 0;
954 : char c;
955 27 : int TZ = 0;
956 27 : int bRet = FALSE;
957 :
958 : /* Date is expressed as a UTC date */
959 27 : if (sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f%c",
960 : &year, &month, &day, &hour, &minute, &second, &c) == 7 && c == 'Z')
961 : {
962 4 : TZ = 100;
963 4 : bRet = TRUE;
964 : }
965 : /* Date is expressed as a UTC date, with a timezone */
966 23 : else if (sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f%c%02d:%02d",
967 : &year, &month, &day, &hour, &minute, &second, &c, &TZHour, &TZMinute) == 9 &&
968 : (c == '+' || c == '-'))
969 : {
970 23 : TZ = 100 + ((c == '+') ? 1 : -1) * ((TZHour * 60 + TZMinute) / 15);
971 23 : bRet = TRUE;
972 : }
973 : /* Date is expressed into an unknown timezone */
974 0 : else if (sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f",
975 : &year, &month, &day, &hour, &minute, &second) == 6)
976 : {
977 0 : TZ = 0;
978 0 : bRet = TRUE;
979 : }
980 27 : if (bRet)
981 : {
982 27 : if (pnYear) *pnYear = year;
983 27 : if (pnMonth) *pnMonth = month;
984 27 : if (pnDay) *pnDay = day;
985 27 : if (pnHour) *pnHour = hour;
986 27 : if (pnMinute) *pnMinute = minute;
987 27 : if (pfSecond) *pfSecond = second;
988 27 : if (pnTZ) *pnTZ = TZ;
989 : }
990 :
991 27 : return bRet;
992 : }
993 :
994 : /************************************************************************/
995 : /* OGRParseRFC822DateTime() */
996 : /************************************************************************/
997 :
998 : static const char* aszMonthStr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
999 : "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
1000 :
1001 25 : int OGRParseRFC822DateTime( const char* pszRFC822DateTime,
1002 : int *pnYear, int *pnMonth, int *pnDay,
1003 : int *pnHour, int *pnMinute, int *pnSecond, int *pnTZ)
1004 : {
1005 : /* Following http://asg.web.cmu.edu/rfc/rfc822.html#sec-5 : [Fri,] 28 Dec 2007 05:24[:17] GMT */
1006 25 : char** papszTokens = CSLTokenizeStringComplex( pszRFC822DateTime, " ,:", TRUE, FALSE );
1007 25 : char** papszVal = papszTokens;
1008 25 : int bRet = FALSE;
1009 25 : int nTokens = CSLCount(papszTokens);
1010 25 : if (nTokens >= 6)
1011 : {
1012 21 : if ( ! ((*papszVal)[0] >= '0' && (*papszVal)[0] <= '9') )
1013 : {
1014 : /* Ignore day of week */
1015 21 : papszVal ++;
1016 : }
1017 :
1018 21 : int day = atoi(*papszVal);
1019 21 : papszVal ++;
1020 :
1021 21 : int month = 0;
1022 :
1023 273 : for(int i = 0; i < 12; i++)
1024 : {
1025 252 : if (EQUAL(*papszVal, aszMonthStr[i]))
1026 21 : month = i + 1;
1027 : }
1028 21 : papszVal ++;
1029 :
1030 21 : int year = atoi(*papszVal);
1031 21 : papszVal ++;
1032 21 : if( year < 100 && year >= 30 )
1033 0 : year += 1900;
1034 21 : else if( year < 30 && year >= 0 )
1035 0 : year += 2000;
1036 :
1037 21 : int hour = atoi(*papszVal);
1038 21 : papszVal ++;
1039 :
1040 21 : int minute = atoi(*papszVal);
1041 21 : papszVal ++;
1042 :
1043 21 : int second = 0;
1044 21 : if (*papszVal != NULL && (*papszVal)[0] >= '0' && (*papszVal)[0] <= '9')
1045 : {
1046 21 : second = atoi(*papszVal);
1047 21 : papszVal ++;
1048 : }
1049 :
1050 21 : if (month != 0)
1051 : {
1052 21 : bRet = TRUE;
1053 21 : int TZ = 0;
1054 :
1055 21 : if (*papszVal == NULL)
1056 : {
1057 : }
1058 63 : else if (strlen(*papszVal) == 5 &&
1059 21 : ((*papszVal)[0] == '+' || (*papszVal)[0] == '-'))
1060 : {
1061 : char szBuf[3];
1062 21 : szBuf[0] = (*papszVal)[1];
1063 21 : szBuf[1] = (*papszVal)[2];
1064 21 : szBuf[2] = 0;
1065 21 : int TZHour = atoi(szBuf);
1066 21 : szBuf[0] = (*papszVal)[3];
1067 21 : szBuf[1] = (*papszVal)[4];
1068 21 : szBuf[2] = 0;
1069 21 : int TZMinute = atoi(szBuf);
1070 21 : TZ = 100 + (((*papszVal)[0] == '+') ? 1 : -1) * ((TZHour * 60 + TZMinute) / 15);
1071 : }
1072 : else
1073 : {
1074 0 : const char* aszTZStr[] = { "GMT", "UT", "Z", "EST", "EDT", "CST", "CDT", "MST", "MDT", "PST", "PDT" };
1075 0 : int anTZVal[] = { 0, 0, 0, -5, -4, -6, -5, -7, -6, -8, -7 };
1076 0 : for(int i = 0; i < 11; i++)
1077 : {
1078 0 : if (EQUAL(*papszVal, aszTZStr[i]))
1079 : {
1080 0 : TZ = 100 + anTZVal[i] * 4;
1081 0 : break;
1082 : }
1083 : }
1084 : }
1085 :
1086 21 : if (pnYear) *pnYear = year;
1087 21 : if (pnMonth) *pnMonth = month;
1088 21 : if (pnDay) *pnDay = day;
1089 21 : if (pnHour) *pnHour = hour;
1090 21 : if (pnMinute) *pnMinute = minute;
1091 21 : if (pnSecond) *pnSecond = second;
1092 21 : if (pnTZ) *pnTZ = TZ;
1093 : }
1094 : }
1095 25 : CSLDestroy(papszTokens);
1096 25 : return bRet;
1097 : }
1098 :
1099 :
1100 : /**
1101 : * Returns the day of the week in Gregorian calendar
1102 : *
1103 : * @param day : day of the month, between 1 and 31
1104 : * @param month : month of the year, between 1 (Jan) and 12 (Dec)
1105 : * @param year : year
1106 :
1107 : * @return day of the week : 0 for Monday, ... 6 for Sunday
1108 : */
1109 :
1110 12 : int OGRGetDayOfWeek(int day, int month, int year)
1111 : {
1112 : /* Reference: Zeller's congruence */
1113 12 : int q = day;
1114 : int m;
1115 12 : if (month >=3)
1116 12 : m = month;
1117 : else
1118 : {
1119 0 : m = month + 12;
1120 0 : year --;
1121 : }
1122 12 : int K = year % 100;
1123 12 : int J = year / 100;
1124 12 : int h = ( q + (((m+1)*26)/10) + K + K/4 + J/4 + 5 * J) % 7;
1125 12 : return ( h + 5 ) % 7;
1126 : }
1127 :
1128 :
1129 : /************************************************************************/
1130 : /* OGRGetRFC822DateTime() */
1131 : /************************************************************************/
1132 :
1133 12 : char* OGRGetRFC822DateTime(int year, int month, int day, int hour, int minute, int second, int TZFlag)
1134 : {
1135 12 : char* pszTZ = NULL;
1136 12 : const char* aszDayOfWeek[] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
1137 :
1138 12 : int dayofweek = OGRGetDayOfWeek(day, month, year);
1139 :
1140 12 : if (month < 1 || month > 12)
1141 0 : month = 1;
1142 :
1143 12 : if (TZFlag == 0 || TZFlag == 100)
1144 : {
1145 0 : pszTZ = CPLStrdup("GMT");
1146 : }
1147 : else
1148 : {
1149 12 : int TZOffset = ABS(TZFlag - 100) * 15;
1150 12 : int TZHour = TZOffset / 60;
1151 12 : int TZMinute = TZOffset - TZHour * 60;
1152 : pszTZ = CPLStrdup(CPLSPrintf("%c%02d%02d", TZFlag > 100 ? '+' : '-',
1153 12 : TZHour, TZMinute));
1154 : }
1155 : char* pszRet = CPLStrdup(CPLSPrintf("%s, %02d %s %04d %02d:%02d:%02d %s",
1156 12 : aszDayOfWeek[dayofweek], day, aszMonthStr[month - 1], year, hour, minute, second, pszTZ));
1157 12 : CPLFree(pszTZ);
1158 12 : return pszRet;
1159 : }
1160 :
1161 : /************************************************************************/
1162 : /* OGRGetXMLDateTime() */
1163 : /************************************************************************/
1164 :
1165 4 : char* OGRGetXMLDateTime(int year, int month, int day, int hour, int minute, int second, int TZFlag)
1166 : {
1167 : char* pszRet;
1168 6 : if (TZFlag == 0 || TZFlag == 100)
1169 : {
1170 : pszRet = CPLStrdup(CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02dZ",
1171 2 : year, month, day, hour, minute, second));
1172 : }
1173 : else
1174 : {
1175 2 : int TZOffset = ABS(TZFlag - 100) * 15;
1176 2 : int TZHour = TZOffset / 60;
1177 2 : int TZMinute = TZOffset - TZHour * 60;
1178 : pszRet = CPLStrdup(CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
1179 : year, month, day, hour, minute, second,
1180 2 : (TZFlag > 100) ? '+' : '-', TZHour, TZMinute));
1181 : }
1182 4 : return pszRet;
1183 : }
1184 :
1185 : /************************************************************************/
1186 : /* OGRGetXML_UTF8_EscapedString() */
1187 : /************************************************************************/
1188 :
1189 179 : char* OGRGetXML_UTF8_EscapedString(const char* pszString)
1190 : {
1191 : char *pszEscaped;
1192 179 : if (!CPLIsUTF8(pszString, -1) &&
1193 : CSLTestBoolean(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")))
1194 : {
1195 : static int bFirstTime = TRUE;
1196 1 : if (bFirstTime)
1197 : {
1198 1 : bFirstTime = FALSE;
1199 : CPLError(CE_Warning, CPLE_AppDefined,
1200 : "%s is not a valid UTF-8 string. Forcing it to ASCII.\n"
1201 : "If you still want the original string and change the XML file encoding\n"
1202 : "afterwards, you can define OGR_FORCE_ASCII=NO as configuration option.\n"
1203 1 : "This warning won't be issued anymore", pszString);
1204 : }
1205 : else
1206 : {
1207 : CPLDebug("OGR", "%s is not a valid UTF-8 string. Forcing it to ASCII",
1208 0 : pszString);
1209 : }
1210 1 : char* pszTemp = CPLForceToASCII(pszString, -1, '?');
1211 1 : pszEscaped = CPLEscapeString( pszTemp, -1, CPLES_XML );
1212 1 : CPLFree(pszTemp);
1213 : }
1214 : else
1215 178 : pszEscaped = CPLEscapeString( pszString, -1, CPLES_XML );
1216 179 : return pszEscaped;
1217 : }
1218 :
1219 : /************************************************************************/
1220 : /* OGRCompareDate() */
1221 : /************************************************************************/
1222 :
1223 1 : int OGRCompareDate( OGRField *psFirstTuple,
1224 : OGRField *psSecondTuple )
1225 : {
1226 : /* FIXME? : We ignore TZFlag */
1227 :
1228 1 : if (psFirstTuple->Date.Year < psSecondTuple->Date.Year)
1229 0 : return -1;
1230 1 : else if (psFirstTuple->Date.Year > psSecondTuple->Date.Year)
1231 0 : return 1;
1232 :
1233 1 : if (psFirstTuple->Date.Month < psSecondTuple->Date.Month)
1234 1 : return -1;
1235 0 : else if (psFirstTuple->Date.Month > psSecondTuple->Date.Month)
1236 0 : return 1;
1237 :
1238 0 : if (psFirstTuple->Date.Day < psSecondTuple->Date.Day)
1239 0 : return -1;
1240 0 : else if (psFirstTuple->Date.Day > psSecondTuple->Date.Day)
1241 0 : return 1;
1242 :
1243 0 : if (psFirstTuple->Date.Hour < psSecondTuple->Date.Hour)
1244 0 : return -1;
1245 0 : else if (psFirstTuple->Date.Hour > psSecondTuple->Date.Hour)
1246 0 : return 1;
1247 :
1248 0 : if (psFirstTuple->Date.Minute < psSecondTuple->Date.Minute)
1249 0 : return -1;
1250 0 : else if (psFirstTuple->Date.Minute > psSecondTuple->Date.Minute)
1251 0 : return 1;
1252 :
1253 0 : if (psFirstTuple->Date.Second < psSecondTuple->Date.Second)
1254 0 : return -1;
1255 0 : else if (psFirstTuple->Date.Second > psSecondTuple->Date.Second)
1256 0 : return 1;
1257 :
1258 0 : return 0;
1259 : }
1260 :
1261 : /************************************************************************/
1262 : /* OGRFastAtof() */
1263 : /************************************************************************/
1264 :
1265 : /* On Windows, atof() is very slow if the number */
1266 : /* is followed by other long content. */
1267 : /* So we just extract the number into a short string */
1268 : /* before calling atof() on it */
1269 : static
1270 0 : double OGRCallAtofOnShortString(const char* pszStr)
1271 : {
1272 : char szTemp[128];
1273 0 : int nCounter = 0;
1274 0 : const char* p = pszStr;
1275 0 : while(*p == ' ' || *p == '\t')
1276 0 : p++;
1277 0 : while(*p == '+' ||
1278 : *p == '-' ||
1279 : (*p >= '0' && *p <= '9') ||
1280 : *p == '.' ||
1281 : (*p == 'e' || *p == 'E' || *p == 'd' || *p == 'D'))
1282 : {
1283 0 : szTemp[nCounter++] = *(p++);
1284 0 : if (nCounter == 127)
1285 0 : return atof(pszStr);
1286 : }
1287 0 : szTemp[nCounter] = '\0';
1288 0 : return atof(szTemp);
1289 : }
1290 :
1291 : /** Same contract as CPLAtof, except than it doesn't always call the
1292 : * system atof() that may be slow on some platforms. For simple but
1293 : * common strings, it'll use a faster implementation (up to 20x faster
1294 : * than atof() on MS runtime libraries) that has no garanty to return
1295 : * exactly the same floating point number.
1296 : */
1297 :
1298 26822 : double OGRFastAtof(const char* pszStr)
1299 : {
1300 26822 : double dfVal = 0;
1301 26822 : double dfSign = 1.0;
1302 26822 : const char* p = pszStr;
1303 :
1304 : static const double adfTenPower[] =
1305 : {
1306 : 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10,
1307 : 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20,
1308 : 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31
1309 : };
1310 :
1311 53646 : while(*p == ' ' || *p == '\t')
1312 2 : p++;
1313 :
1314 26822 : if (*p == '+')
1315 9 : p++;
1316 26813 : else if (*p == '-')
1317 : {
1318 2926 : dfSign = -1.0;
1319 2926 : p++;
1320 : }
1321 :
1322 147100 : while(TRUE)
1323 : {
1324 173922 : if (*p >= '0' && *p <= '9')
1325 : {
1326 147100 : dfVal = dfVal * 10.0 + (*p - '0');
1327 147100 : p++;
1328 : }
1329 26822 : else if (*p == '.')
1330 : {
1331 23578 : p++;
1332 : break;
1333 : }
1334 3244 : else if (*p == 'e' || *p == 'E' || *p == 'd' || *p == 'D')
1335 0 : return OGRCallAtofOnShortString(pszStr);
1336 : else
1337 3244 : return dfSign * dfVal;
1338 : }
1339 :
1340 23578 : unsigned int countFractionnal = 0;
1341 94890 : while(TRUE)
1342 : {
1343 118468 : if (*p >= '0' && *p <= '9')
1344 : {
1345 94890 : dfVal = dfVal * 10.0 + (*p - '0');
1346 94890 : countFractionnal ++;
1347 94890 : p++;
1348 : }
1349 23578 : else if (*p == 'e' || *p == 'E' || *p == 'd' || *p == 'D')
1350 0 : return OGRCallAtofOnShortString(pszStr);
1351 : else
1352 : {
1353 23578 : if (countFractionnal < sizeof(adfTenPower) / sizeof(adfTenPower[0]))
1354 23578 : return dfSign * (dfVal / adfTenPower[countFractionnal]);
1355 : else
1356 0 : return OGRCallAtofOnShortString(pszStr);
1357 : }
1358 : }
1359 : }
1360 :
1361 : /**
1362 : * Check that panPermutation is a permutation of [0,nSize-1].
1363 : * @param panPermutation an array of nSize elements.
1364 : * @param nSize size of the array.
1365 : * @return OGRERR_NONE if panPermutation is a permutation of [0,nSize-1].
1366 : * @since OGR 1.9.0
1367 : */
1368 64 : OGRErr OGRCheckPermutation(int* panPermutation, int nSize)
1369 : {
1370 64 : OGRErr eErr = OGRERR_NONE;
1371 64 : int* panCheck = (int*)CPLCalloc(nSize, sizeof(int));
1372 : int i;
1373 319 : for(i=0;i<nSize;i++)
1374 : {
1375 259 : if (panPermutation[i] < 0 || panPermutation[i] >= nSize)
1376 : {
1377 : CPLError(CE_Failure, CPLE_IllegalArg,
1378 1 : "Bad value for element %d", i);
1379 1 : eErr = OGRERR_FAILURE;
1380 1 : break;
1381 : }
1382 258 : if (panCheck[panPermutation[i]] != 0)
1383 : {
1384 : CPLError(CE_Failure, CPLE_IllegalArg,
1385 : "Array is not a permutation of [0,%d]",
1386 3 : nSize - 1);
1387 3 : eErr = OGRERR_FAILURE;
1388 3 : break;
1389 : }
1390 255 : panCheck[panPermutation[i]] = 1;
1391 : }
1392 64 : CPLFree(panCheck);
1393 64 : return eErr;
1394 : }
|