LTP GCOV extension - code coverage report
Current view: directory - gcore - gdal_rpcimdio.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 243
Code covered: 49.0 % Executed lines: 119

       1                 : /******************************************************************************
       2                 :  * $Id: gdal_rpcimdio.cpp 19883 2010-06-17 21:26:06Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL Core
       5                 :  * Purpose:  Functions for reading RPC and IMD formats, and normalizing.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) HER MAJESTY THE QUEEN IN RIGHT OF CANADA (2008)
      10                 :  * as represented by the Canadian Nuclear Safety Commission
      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 "gdal.h"
      32                 : #include "cpl_string.h"
      33                 : #include "cplkeywordparser.h"
      34                 : 
      35                 : CPL_CVSID("$Id: gdal_rpcimdio.cpp 19883 2010-06-17 21:26:06Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                          GDALLoadRPBFile()                           */
      39                 : /************************************************************************/
      40                 : 
      41                 : static const char *apszRPBMap[] = {
      42                 :     "LINE_OFF",       "IMAGE.lineOffset",
      43                 :     "SAMP_OFF",       "IMAGE.sampOffset",
      44                 :     "LAT_OFF",        "IMAGE.latOffset",
      45                 :     "LONG_OFF",       "IMAGE.longOffset",
      46                 :     "HEIGHT_OFF",     "IMAGE.heightOffset",
      47                 :     "LINE_SCALE",     "IMAGE.lineScale",
      48                 :     "SAMP_SCALE",     "IMAGE.sampScale",
      49                 :     "LAT_SCALE",      "IMAGE.latScale",
      50                 :     "LONG_SCALE",     "IMAGE.longScale",
      51                 :     "HEIGHT_SCALE",   "IMAGE.heightScale",
      52                 :     "LINE_NUM_COEFF", "IMAGE.lineNumCoef",
      53                 :     "LINE_DEN_COEFF", "IMAGE.lineDenCoef",
      54                 :     "SAMP_NUM_COEFF", "IMAGE.sampNumCoef",
      55                 :     "SAMP_DEN_COEFF", "IMAGE.sampDenCoef",
      56                 :     NULL,             NULL };
      57                 : 
      58                 : char **CPL_STDCALL GDALLoadRPBFile( const char *pszFilename,
      59               4 :                                     char **papszSiblingFiles )
      60                 : 
      61                 : {
      62                 : /* -------------------------------------------------------------------- */
      63                 : /*      Try to identify the RPB file in upper or lower case.            */
      64                 : /* -------------------------------------------------------------------- */
      65               4 :     CPLString osTarget = CPLResetExtension( pszFilename, "RPB" );
      66                 : 
      67                 :     /* Is this already a RPB file ? */
      68               4 :     if (EQUAL(CPLGetExtension(pszFilename), "RPB"))
      69               3 :         osTarget = pszFilename;
      70               1 :     else if( papszSiblingFiles == NULL )
      71                 :     {
      72                 :         VSIStatBufL sStatBuf;
      73                 :         
      74               0 :         if( VSIStatL( osTarget, &sStatBuf ) != 0 )
      75                 :         {
      76               0 :             osTarget = CPLResetExtension( pszFilename, "rpb" );
      77                 : 
      78               0 :             if( VSIStatL( osTarget, &sStatBuf ) != 0 )
      79               0 :                 return NULL;
      80                 :         }
      81                 :     }
      82                 :     else
      83                 :     {
      84                 :         int iSibling = CSLFindString( papszSiblingFiles, 
      85               1 :                                       CPLGetFilename(osTarget) );
      86               1 :         if( iSibling < 0 )
      87               1 :             return NULL;
      88                 : 
      89               0 :         osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling]));
      90               0 :         osTarget += papszSiblingFiles[iSibling];
      91                 :     }
      92                 : 
      93                 : /* -------------------------------------------------------------------- */
      94                 : /*      Read file and parse.                                            */
      95                 : /* -------------------------------------------------------------------- */
      96               3 :     CPLKeywordParser oParser;
      97                 : 
      98               3 :     FILE *fp = VSIFOpenL( osTarget, "r" );
      99                 : 
     100               3 :     if( fp == NULL )
     101               0 :         return NULL;
     102                 :     
     103               3 :     if( !oParser.Ingest( fp ) )
     104                 :     {
     105               0 :         VSIFCloseL( fp );
     106               0 :         return NULL;
     107                 :     }
     108                 : 
     109               3 :     VSIFCloseL( fp );
     110                 : 
     111                 : /* -------------------------------------------------------------------- */
     112                 : /*      Extract RPC information, in a GDAL "standard" metadata format.  */
     113                 : /* -------------------------------------------------------------------- */
     114                 :     int i;
     115               3 :     char **papszMD = NULL;
     116               3 :     for( i = 0; apszRPBMap[i] != NULL; i += 2 )
     117                 :     {
     118              42 :         const char *pszRPBVal = oParser.GetKeyword( apszRPBMap[i+1] );
     119              42 :         CPLString osAdjVal;
     120                 : 
     121              42 :         if( pszRPBVal == NULL )
     122                 :         {
     123                 :             CPLError( CE_Failure, CPLE_AppDefined,
     124                 :                       "%s file found, but missing %s field (and possibly others).",
     125               0 :                       osTarget.c_str(), apszRPBMap[i+1] );
     126               0 :             CSLDestroy( papszMD );
     127               0 :             return NULL;
     128                 :         }
     129                 : 
     130              42 :         if( strchr(pszRPBVal,',') == NULL )
     131              30 :             osAdjVal = pszRPBVal;
     132                 :         else
     133                 :         {
     134                 :             // strip out commas and turn newlines into spaces.
     135                 :             int j;
     136                 : 
     137            3384 :             for( j = 0; pszRPBVal[j] != '\0'; j++ )
     138                 :             {
     139            3372 :                 switch( pszRPBVal[j] ) 
     140                 :                 {
     141                 :                   case ',':
     142                 :                   case '\n':
     143                 :                   case '\r':
     144             228 :                     osAdjVal += ' ';
     145             228 :                     break;
     146                 :                     
     147                 :                   case '(':
     148                 :                   case ')':
     149              24 :                     break;
     150                 : 
     151                 :                   default:
     152            3120 :                     osAdjVal += pszRPBVal[j];
     153                 :                 }
     154                 :             }
     155                 :         }
     156                 : 
     157              42 :         papszMD = CSLSetNameValue( papszMD, apszRPBMap[i], osAdjVal );
     158                 :     }
     159                 : 
     160               3 :     return papszMD;
     161                 : }
     162                 : 
     163                 : /************************************************************************/
     164                 : /*                          GDALLoadRPCFile()                           */
     165                 : /************************************************************************/
     166                 : 
     167                 : /* Load a GeoEye _rpc.txt file. See ticket http://trac.osgeo.org/gdal/ticket/3639 */
     168                 : 
     169                 : char **CPL_STDCALL GDALLoadRPCFile( const char *pszFilename,
     170               0 :                                     char **papszSiblingFiles )
     171                 : 
     172                 : {
     173                 : /* -------------------------------------------------------------------- */
     174                 : /*      Try to identify the RPC file in upper or lower case.            */
     175                 : /* -------------------------------------------------------------------- */
     176               0 :     CPLString osTarget; 
     177                 : 
     178                 :     /* Is this already a _RPC.TXT file ? */
     179               0 :     if (strlen(pszFilename) > 8 && EQUAL(pszFilename + strlen(pszFilename) - 8, "_RPC.TXT"))
     180               0 :         osTarget = pszFilename;
     181                 :     else
     182                 :     {
     183               0 :         CPLString osSrcPath = pszFilename;
     184               0 :         CPLString soPt(".");
     185               0 :         size_t found = osSrcPath.rfind(soPt);
     186               0 :         if (found == CPLString::npos)
     187               0 :             return NULL;
     188               0 :         osSrcPath.replace (found, osSrcPath.size() - found, "_rpc.txt");
     189               0 :         CPLString osTarget = osSrcPath; 
     190                 : 
     191               0 :         if( papszSiblingFiles == NULL )
     192                 :         {
     193                 :             VSIStatBufL sStatBuf;
     194                 : 
     195               0 :             if( VSIStatL( osTarget, &sStatBuf ) != 0 )
     196                 :             {
     197               0 :                 osSrcPath = pszFilename;
     198               0 :                 osSrcPath.replace (found, osSrcPath.size() - found, "_RPC.TXT");
     199               0 :                 osTarget = osSrcPath; 
     200                 : 
     201               0 :                 if( VSIStatL( osTarget, &sStatBuf ) != 0 )
     202                 :                 {
     203               0 :                     osSrcPath = pszFilename;
     204               0 :                     osSrcPath.replace (found, osSrcPath.size() - found, "_rpc.TXT");
     205               0 :                     osTarget = osSrcPath; 
     206                 : 
     207               0 :                     if( VSIStatL( osTarget, &sStatBuf ) != 0 )
     208                 :                     {
     209               0 :                         return NULL;
     210                 :                     }
     211                 :                 }
     212                 :             }
     213                 :         }
     214                 :         else
     215                 :         {
     216                 :             int iSibling = CSLFindString( papszSiblingFiles, 
     217               0 :                                         CPLGetFilename(osTarget) );
     218               0 :             if( iSibling < 0 )
     219               0 :                 return NULL;
     220                 : 
     221               0 :             osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling]));
     222               0 :             osTarget += papszSiblingFiles[iSibling];
     223               0 :         }
     224                 :     }
     225                 : 
     226                 : /* -------------------------------------------------------------------- */
     227                 : /*      Read file and parse.                                            */
     228                 : /* -------------------------------------------------------------------- */
     229               0 :     char **papszLines = CSLLoad2( osTarget, 100, 100, NULL );
     230               0 :     if(!papszLines)
     231               0 :         return NULL;
     232                 : 
     233               0 :     char **papszMD = NULL;
     234                 : 
     235                 :     /* From LINE_OFF to HEIGHT_SCALE */
     236               0 :     for(size_t i = 0; i < 19; i += 2 )
     237                 :     {
     238               0 :         const char *pszRPBVal = CSLFetchNameValue(papszLines, apszRPBMap[i] );
     239               0 :         if( pszRPBVal == NULL )
     240                 :         {
     241                 :             CPLError( CE_Failure, CPLE_AppDefined,
     242                 :                 "%s file found, but missing %s field (and possibly others).",
     243               0 :                 osTarget.c_str(), apszRPBMap[i]);
     244               0 :             CSLDestroy( papszMD );
     245               0 :             CSLDestroy( papszLines );
     246               0 :             return NULL;
     247                 :         }
     248                 :         else
     249                 :         {
     250               0 :             papszMD = CSLSetNameValue( papszMD, apszRPBMap[i], pszRPBVal );
     251                 :         }
     252                 :     }
     253                 :        
     254                 :     /* For LINE_NUM_COEFF, LINE_DEN_COEFF, SAMP_NUM_COEFF, SAMP_DEN_COEFF */
     255                 :     /* parameters that have 20 values each */
     256               0 :     for(size_t i = 20; apszRPBMap[i] != NULL; i += 2 )
     257                 :     {
     258               0 :         CPLString soVal;
     259               0 :         for(int j = 1; j <= 20; j++)
     260                 :         {
     261               0 :             CPLString soRPBMapItem;
     262               0 :             soRPBMapItem.Printf("%s_%d", apszRPBMap[i], j);
     263               0 :             const char *pszRPBVal = CSLFetchNameValue(papszLines, soRPBMapItem.c_str() );
     264               0 :             if( pszRPBVal == NULL )
     265                 :             {
     266                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     267                 :                     "%s file found, but missing %s field (and possibly others).",
     268               0 :                     osTarget.c_str(), soRPBMapItem.c_str() );
     269               0 :                 CSLDestroy( papszMD );
     270               0 :                 CSLDestroy( papszLines );
     271               0 :                 return NULL;
     272                 :             }
     273                 :             else
     274                 :             {
     275               0 :                 soVal += pszRPBVal;
     276               0 :                 soVal += " ";
     277                 :             }
     278                 :         }
     279               0 :         papszMD = CSLSetNameValue( papszMD, apszRPBMap[i], soVal.c_str() );
     280                 :     }
     281                 : 
     282               0 :     CSLDestroy( papszLines );
     283               0 :     return papszMD;
     284                 : }
     285                 : 
     286                 : /************************************************************************/
     287                 : /*                          GDALWriteRPBFile()                          */
     288                 : /************************************************************************/
     289                 : 
     290               1 : CPLErr CPL_STDCALL GDALWriteRPBFile( const char *pszFilename, char **papszMD )
     291                 : 
     292                 : {
     293               1 :     CPLString osRPBFilename = CPLResetExtension( pszFilename, "RPB" );
     294                 :     
     295                 : 
     296                 : /* -------------------------------------------------------------------- */
     297                 : /*      Read file and parse.                                            */
     298                 : /* -------------------------------------------------------------------- */
     299               1 :     FILE *fp = VSIFOpenL( osRPBFilename, "w" );
     300                 : 
     301               1 :     if( fp == NULL )
     302                 :     {
     303                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     304                 :                   "Unable to create %s for writing.\n%s", 
     305               0 :                   osRPBFilename.c_str(), CPLGetLastErrorMsg() );
     306               0 :         return CE_Failure;
     307                 :     }
     308                 :     
     309                 : /* -------------------------------------------------------------------- */
     310                 : /*      Write the prefix information.                                   */
     311                 : /* -------------------------------------------------------------------- */
     312               1 :     VSIFPrintfL( fp, "%s", "satId = \"QB02\";\n" );
     313               1 :     VSIFPrintfL( fp, "%s", "bandId = \"P\";\n" );
     314               1 :     VSIFPrintfL( fp, "%s", "SpecId = \"RPC00B\";\n" );
     315               1 :     VSIFPrintfL( fp, "%s", "BEGIN_GROUP = IMAGE\n" );
     316               1 :     VSIFPrintfL( fp, "%s", "\terrBias = 0.0;\n" );
     317               1 :     VSIFPrintfL( fp, "%s", "\terrRand = 0.0;\n" );
     318                 : 
     319                 : /* -------------------------------------------------------------------- */
     320                 : /*      Write RPC values from our RPC metadata.                         */
     321                 : /* -------------------------------------------------------------------- */
     322                 :     int i;
     323                 : 
     324              15 :     for( i = 0; apszRPBMap[i] != NULL; i += 2 )
     325                 :     {
     326              14 :         const char *pszRPBVal = CSLFetchNameValue( papszMD, apszRPBMap[i] );
     327                 :         const char *pszRPBTag;
     328                 : 
     329              14 :         if( pszRPBVal == NULL )
     330                 :         {
     331                 :             CPLError( CE_Failure, CPLE_AppDefined,
     332                 :                       "%s field missing in metadata, %s file not written.",
     333               0 :                       apszRPBMap[i], osRPBFilename.c_str() );
     334               0 :             VSIFCloseL( fp );
     335               0 :             VSIUnlink( osRPBFilename );
     336               0 :             return CE_Failure;
     337                 :         }
     338                 : 
     339              14 :         pszRPBTag = apszRPBMap[i+1];
     340              14 :         if( EQUALN(pszRPBTag,"IMAGE.",6) )
     341              14 :             pszRPBTag += 6;
     342                 : 
     343              14 :         if( strstr(apszRPBMap[i], "COEF" ) == NULL )
     344                 :         {
     345              10 :             VSIFPrintfL( fp, "\t%s = %s;\n", pszRPBTag, pszRPBVal );
     346                 :         }
     347                 :         else
     348                 :         {
     349                 :             // Reformat in brackets with commas over multiple lines.
     350                 : 
     351               4 :             VSIFPrintfL( fp, "\t%s = (\n", pszRPBTag );
     352                 : 
     353                 :             char **papszItems = CSLTokenizeStringComplex( pszRPBVal, " ,", 
     354               4 :                                                           FALSE, FALSE );
     355                 : 
     356               4 :             if( CSLCount(papszItems) != 20 )
     357                 :             {
     358                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     359                 :                           "%s field is corrupt (not 20 values), %s file not written.\n%s = %s",
     360                 :                           apszRPBMap[i], osRPBFilename.c_str(),
     361               0 :                           apszRPBMap[i], pszRPBVal );
     362               0 :                 VSIFCloseL( fp );
     363               0 :                 VSIUnlink( osRPBFilename );
     364               0 :                 return CE_Failure;
     365                 :             }
     366                 : 
     367                 :             int j;
     368                 : 
     369              84 :             for( j = 0; j < 20; j++ )
     370                 :             {
     371              80 :                 if( j < 19 )
     372              76 :                     VSIFPrintfL( fp, "\t\t\t%s,\n", papszItems[j] );
     373                 :                 else
     374               4 :                     VSIFPrintfL( fp, "\t\t\t%s);\n", papszItems[j] );
     375                 :             }
     376               4 :             CSLDestroy( papszItems );
     377                 :         }
     378                 :     }
     379                 : 
     380                 : /* -------------------------------------------------------------------- */
     381                 : /*      Write end part                                                  */
     382                 : /* -------------------------------------------------------------------- */
     383               1 :     VSIFPrintfL( fp, "%s", "END_GROUP = IMAGE\n" );
     384               1 :     VSIFPrintfL( fp, "END;\n" );
     385               1 :     VSIFCloseL( fp );
     386                 :     
     387               1 :     return CE_None;
     388                 : }
     389                 : 
     390                 : /************************************************************************/
     391                 : /*                           GDAL_IMD_AA2R()                            */
     392                 : /*                                                                      */
     393                 : /*      Translate AA version IMD file to R version.                     */
     394                 : /************************************************************************/
     395                 : 
     396               0 : static int GDAL_IMD_AA2R( char ***ppapszIMD )
     397                 : 
     398                 : {
     399               0 :     char **papszIMD = *ppapszIMD;
     400                 : 
     401                 : /* -------------------------------------------------------------------- */
     402                 : /*      Verify that we have a new format file.                          */
     403                 : /* -------------------------------------------------------------------- */
     404               0 :     const char *pszValue = CSLFetchNameValue( papszIMD, "version" );
     405                 :     
     406               0 :     if( pszValue == NULL )
     407               0 :         return FALSE;
     408                 :     
     409               0 :     if( EQUAL(pszValue,"\"R\"") )
     410               0 :         return TRUE;
     411                 : 
     412               0 :     if( !EQUAL(pszValue,"\"AA\"") )
     413                 :     {
     414               0 :         CPLDebug( "IMD", "The file is not the expected 'version = \"AA\"' format.\nProceeding, but file may be corrupted." );
     415                 :     }
     416                 : 
     417                 : /* -------------------------------------------------------------------- */
     418                 : /*      Fix the version line.                                           */
     419                 : /* -------------------------------------------------------------------- */
     420               0 :     papszIMD = CSLSetNameValue( papszIMD, "version", "\"R\"" );
     421                 : 
     422                 : /* -------------------------------------------------------------------- */
     423                 : /*      remove a bunch of fields.                                       */
     424                 : /* -------------------------------------------------------------------- */
     425                 :     int iKey;
     426                 : 
     427                 :     static const char *apszToRemove[] = {
     428                 :         "productCatalogId",
     429                 :         "childCatalogId",
     430                 :         "productType",
     431                 :         "numberOfLooks",
     432                 :         "effectiveBandwidth",
     433                 :         "mode",
     434                 :         "scanDirection",
     435                 :         "cloudCover",
     436                 :         "productGSD",
     437                 :         NULL };
     438                 : 
     439               0 :     for( iKey = 0; apszToRemove[iKey] != NULL; iKey++ )
     440                 :     {
     441               0 :         int iTarget = CSLFindName( papszIMD, apszToRemove[iKey] );
     442               0 :         if( iTarget != -1 )
     443               0 :             papszIMD = CSLRemoveStrings( papszIMD, iTarget, 1, NULL );
     444                 :     }
     445                 : 
     446                 : /* -------------------------------------------------------------------- */
     447                 : /*      Replace various min/mean/max with just the mean.                */
     448                 : /* -------------------------------------------------------------------- */
     449                 :     static const char *keylist[] = { 
     450                 :         "CollectedRowGSD",
     451                 :         "CollectedColGSD",
     452                 :         "SunAz",
     453                 :         "SunEl",
     454                 :         "SatAz",
     455                 :         "SatEl",
     456                 :         "InTrackViewAngle",
     457                 :         "CrossTrackViewAngle",
     458                 :         "OffNadirViewAngle",
     459                 :         NULL };
     460                 : 
     461               0 :     for( iKey = 0; keylist[iKey] != NULL; iKey++ )
     462                 :     {
     463               0 :         CPLString osTarget;
     464                 :         int       iTarget;
     465                 : 
     466               0 :         osTarget.Printf( "IMAGE_1.min%s", keylist[iKey] );
     467               0 :         iTarget = CSLFindName( papszIMD, osTarget );
     468               0 :         if( iTarget != -1 )
     469               0 :             papszIMD = CSLRemoveStrings( papszIMD, iTarget, 1, NULL );
     470                 : 
     471               0 :         osTarget.Printf( "IMAGE_1.max%s", keylist[iKey] );
     472               0 :         iTarget = CSLFindName( papszIMD, osTarget );
     473               0 :         if( iTarget != -1 )
     474               0 :             papszIMD = CSLRemoveStrings( papszIMD, iTarget, 1, NULL );
     475                 : 
     476               0 :         osTarget.Printf( "IMAGE_1.mean%s", keylist[iKey] );
     477               0 :         iTarget = CSLFindName( papszIMD, osTarget );
     478               0 :         if( iTarget != -1 )
     479                 :         {
     480               0 :             CPLString osValue = CSLFetchNameValue( papszIMD, osTarget );
     481               0 :             CPLString osLine;
     482                 :             
     483                 :             osTarget.Printf( "IMAGE_1.%c%s", 
     484                 :                              tolower(keylist[iKey][0]), 
     485               0 :                              keylist[iKey]+1 );
     486                 : 
     487               0 :             osLine = osTarget + "=" + osValue;
     488                 : 
     489               0 :             CPLFree( papszIMD[iTarget] );
     490               0 :             papszIMD[iTarget] = CPLStrdup(osLine);
     491                 :         }
     492                 :     }
     493                 : 
     494               0 :     *ppapszIMD = papszIMD;
     495               0 :     return TRUE;
     496                 : }
     497                 : 
     498                 : /************************************************************************/
     499                 : /*                          GDALLoadIMDFile()                           */
     500                 : /************************************************************************/
     501                 : 
     502                 : char ** CPL_STDCALL GDALLoadIMDFile( const char *pszFilename,
     503               7 :                                      char **papszSiblingFiles )
     504                 : 
     505                 : {
     506                 : /* -------------------------------------------------------------------- */
     507                 : /*      Try to identify the IMD file in upper or lower case.            */
     508                 : /* -------------------------------------------------------------------- */
     509               7 :     CPLString osTarget = CPLResetExtension( pszFilename, "IMD" );
     510                 : 
     511                 :     /* Is this already a IMD file ? */
     512               7 :     if (EQUAL(CPLGetExtension(pszFilename), "IMD"))
     513               6 :         osTarget = pszFilename;
     514               1 :     else if( papszSiblingFiles == NULL )
     515                 :     {
     516                 :         VSIStatBufL sStatBuf;
     517                 :         
     518               0 :         if( VSIStatL( osTarget, &sStatBuf ) != 0 )
     519                 :         {
     520               0 :             osTarget = CPLResetExtension( pszFilename, "imd" );
     521                 : 
     522               0 :             if( VSIStatL( osTarget, &sStatBuf ) != 0 )
     523               0 :                 return NULL;
     524                 :         }
     525                 :     }
     526                 :     else
     527                 :     {
     528                 :         int iSibling = CSLFindString( papszSiblingFiles, 
     529               1 :                                       CPLGetFilename(osTarget) );
     530               1 :         if( iSibling < 0 )
     531               0 :             return NULL;
     532                 : 
     533               1 :         osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling]));
     534               1 :         osTarget += papszSiblingFiles[iSibling];
     535                 :     }
     536                 : 
     537                 : /* -------------------------------------------------------------------- */
     538                 : /*      Read file and parse.                                            */
     539                 : /* -------------------------------------------------------------------- */
     540               7 :     CPLKeywordParser oParser;
     541                 : 
     542               7 :     FILE *fp = VSIFOpenL( osTarget, "r" );
     543                 : 
     544               7 :     if( fp == NULL )
     545               0 :         return NULL;
     546                 :     
     547               7 :     if( !oParser.Ingest( fp ) )
     548                 :     {
     549               0 :         VSIFCloseL( fp );
     550               0 :         return NULL;
     551                 :     }
     552                 : 
     553               7 :     VSIFCloseL( fp );
     554                 : 
     555                 : /* -------------------------------------------------------------------- */
     556                 : /*      Consider version changing.                                      */
     557                 : /* -------------------------------------------------------------------- */
     558               7 :     char **papszIMD = CSLDuplicate( oParser.GetAllKeywords() );
     559               7 :     const char *pszVersion = CSLFetchNameValue( papszIMD, "version" );
     560                 : 
     561               7 :     if( pszVersion == NULL )
     562                 :     {
     563                 :         /* ? */;
     564                 :     }
     565               6 :     else if( EQUAL(pszVersion,"\"AA\"") )
     566                 :     {
     567               0 :         GDAL_IMD_AA2R( &papszIMD );
     568                 :     }
     569                 : 
     570               7 :     return papszIMD;
     571                 : }
     572                 : 
     573                 : /************************************************************************/
     574                 : /*                       GDALWriteIMDMultiLine()                        */
     575                 : /*                                                                      */
     576                 : /*      Write a value that is split over multiple lines.                */
     577                 : /************************************************************************/
     578                 :  
     579               4 : static void GDALWriteIMDMultiLine( FILE *fp, const char *pszValue )
     580                 : 
     581                 : {
     582                 :     char **papszItems = CSLTokenizeStringComplex( pszValue, "(,) ", 
     583               4 :                                                   FALSE, FALSE );
     584               4 :     int nItemCount = CSLCount(papszItems);
     585                 :     int i;
     586                 : 
     587               4 :     VSIFPrintfL( fp, "(\n" );
     588                 : 
     589              40 :     for( i = 0; i < nItemCount; i++ )
     590                 :     {
     591              36 :         if( i == nItemCount-1 )
     592               4 :             VSIFPrintfL( fp, "\t%s );\n", papszItems[i] );
     593                 :         else
     594              32 :             VSIFPrintfL( fp, "\t%s,\n", papszItems[i] );
     595                 :     }
     596               4 :     CSLDestroy( papszItems );
     597               4 : }
     598                 : 
     599                 : /************************************************************************/
     600                 : /*                          GDALWriteIMDFile()                          */
     601                 : /************************************************************************/
     602                 : 
     603               2 : CPLErr CPL_STDCALL GDALWriteIMDFile( const char *pszFilename, char **papszMD )
     604                 : 
     605                 : {
     606               2 :     CPLString osRPBFilename = CPLResetExtension( pszFilename, "IMD" );
     607                 :     
     608                 : 
     609                 : /* -------------------------------------------------------------------- */
     610                 : /*      Read file and parse.                                            */
     611                 : /* -------------------------------------------------------------------- */
     612               2 :     FILE *fp = VSIFOpenL( osRPBFilename, "w" );
     613                 : 
     614               2 :     if( fp == NULL )
     615                 :     {
     616                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     617                 :                   "Unable to create %s for writing.\n%s", 
     618               0 :                   osRPBFilename.c_str(), CPLGetLastErrorMsg() );
     619               0 :         return CE_Failure;
     620                 :     }
     621                 : 
     622                 : /* ==================================================================== */
     623                 : /* -------------------------------------------------------------------- */
     624                 : /*      Loop through all values writing.                                */
     625                 : /* -------------------------------------------------------------------- */
     626                 : /* ==================================================================== */
     627                 :     int iKey;
     628               2 :     CPLString osCurSection;
     629                 : 
     630             176 :     for( iKey = 0; papszMD[iKey] != NULL; iKey++ )
     631                 :     {
     632             174 :         char *pszRawKey = NULL;
     633             174 :         const char *pszValue = CPLParseNameValue( papszMD[iKey], &pszRawKey );
     634             174 :         CPLString osKeySection, osKeyItem;
     635             174 :         char *pszDot = strchr(pszRawKey,'.');
     636                 : 
     637                 : /* -------------------------------------------------------------------- */
     638                 : /*      Split stuff like BAND_P.ULLon into section and item.            */
     639                 : /* -------------------------------------------------------------------- */
     640             174 :         if( pszDot == NULL )
     641                 :         {
     642              28 :             osKeyItem = pszRawKey;
     643                 :         }
     644                 :         else
     645                 :         {
     646             146 :             osKeyItem = pszDot+1;
     647             146 :             *pszDot = '\0';
     648             146 :             osKeySection = pszRawKey;
     649                 :         }
     650             174 :         CPLFree( pszRawKey );
     651                 : 
     652                 : /* -------------------------------------------------------------------- */
     653                 : /*      Close and/or start sections as needed.                          */
     654                 : /* -------------------------------------------------------------------- */
     655             174 :         if( osCurSection.size() && !EQUAL(osCurSection,osKeySection) )
     656               4 :             VSIFPrintfL( fp, "END_GROUP = %s\n", osCurSection.c_str() );
     657                 : 
     658             174 :         if( osKeySection.size() && !EQUAL(osCurSection,osKeySection) )
     659               6 :             VSIFPrintfL( fp, "BEGIN_GROUP = %s\n", osKeySection.c_str() );
     660                 : 
     661             174 :         osCurSection = osKeySection;
     662                 : 
     663                 : /* -------------------------------------------------------------------- */
     664                 : /*      Print out simple item.                                          */
     665                 : /* -------------------------------------------------------------------- */
     666             174 :         if( osCurSection.size() )
     667             146 :             VSIFPrintfL( fp, "\t%s = ", osKeyItem.c_str() );
     668                 :         else
     669              28 :             VSIFPrintfL( fp, "%s = ", osKeyItem.c_str() );
     670                 : 
     671             174 :         if( pszValue[0] != '(' )
     672             170 :             VSIFPrintfL( fp, "%s;\n", pszValue );
     673                 :         else
     674               4 :             GDALWriteIMDMultiLine( fp, pszValue );
     675                 :     }
     676                 : 
     677                 : /* -------------------------------------------------------------------- */
     678                 : /*      Close off.                                                      */
     679                 : /* -------------------------------------------------------------------- */
     680               2 :     if( osCurSection.size() )
     681               2 :         VSIFPrintfL( fp, "END_GROUP = %s\n", osCurSection.c_str() );
     682                 :     
     683               2 :     VSIFPrintfL( fp, "END;\n" );
     684                 :     
     685               2 :     VSIFCloseL( fp );
     686                 :     
     687               2 :     return CE_None;
     688                 : }

Generated by: LTP GCOV extension version 1.5