PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/gdal-1.9.1-fedora/ogr/ogrutils.cpp

#
C++ | 1396 lines | 899 code | 191 blank | 306 comment | 423 complexity | d44f72d6dfd1440473bd339c147ebc74 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file