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