LCOV - code coverage report
Current view: directory - gcore - gdal_rpcimdio.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 184 116 63.0 %
Date: 2010-01-09 Functions: 6 5 83.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdal_rpcimdio.cpp 18063 2009-11-21 21:11:49Z warmerdam $
       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 18063 2009-11-21 21:11:49Z warmerdam $");
      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            2850 : char **CPL_STDCALL GDALLoadRPBFile( const char *pszFilename,
      59                 :                                     char **papszSiblingFiles )
      60                 : 
      61                 : {
      62                 : /* -------------------------------------------------------------------- */
      63                 : /*      Try to identify the RPB file in upper or lower case.            */
      64                 : /* -------------------------------------------------------------------- */
      65            2850 :     CPLString osTarget = CPLResetExtension( pszFilename, "RPB" );
      66                 :     
      67            2850 :     if( papszSiblingFiles == NULL )
      68                 :     {
      69                 :         VSIStatBufL sStatBuf;
      70                 :         
      71            2850 :         if( VSIStatL( osTarget, &sStatBuf ) != 0 )
      72                 :         {
      73            2847 :             osTarget = CPLResetExtension( pszFilename, "rpb" );
      74                 : 
      75            2847 :             if( VSIStatL( osTarget, &sStatBuf ) != 0 )
      76            2847 :                 return NULL;
      77                 :         }
      78                 :     }
      79                 :     else
      80                 :     {
      81                 :         int iSibling = CSLFindString( papszSiblingFiles, 
      82               0 :                                       CPLGetFilename(osTarget) );
      83               0 :         if( iSibling < 0 )
      84               0 :             return NULL;
      85                 : 
      86               0 :         osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling]));
      87               0 :         osTarget += papszSiblingFiles[iSibling];
      88                 :     }
      89                 : 
      90                 : /* -------------------------------------------------------------------- */
      91                 : /*      Read file and parse.                                            */
      92                 : /* -------------------------------------------------------------------- */
      93               3 :     CPLKeywordParser oParser;
      94                 : 
      95               3 :     FILE *fp = VSIFOpenL( osTarget, "r" );
      96                 : 
      97               3 :     if( fp == NULL )
      98               0 :         return NULL;
      99                 :     
     100               3 :     if( !oParser.Ingest( fp ) )
     101                 :     {
     102               0 :         VSIFCloseL( fp );
     103               0 :         return NULL;
     104                 :     }
     105                 : 
     106               3 :     VSIFCloseL( fp );
     107                 : 
     108                 : /* -------------------------------------------------------------------- */
     109                 : /*      Extract RPC information, in a GDAL "standard" metadata format.  */
     110                 : /* -------------------------------------------------------------------- */
     111                 :     int i;
     112               3 :     char **papszMD = NULL;
     113               3 :     for( i = 0; apszRPBMap[i] != NULL; i += 2 )
     114                 :     {
     115              42 :         const char *pszRPBVal = oParser.GetKeyword( apszRPBMap[i+1] );
     116              42 :         CPLString osAdjVal;
     117                 : 
     118              42 :         if( pszRPBVal == NULL )
     119                 :         {
     120                 :             CPLError( CE_Failure, CPLE_AppDefined,
     121                 :                       "%s file found, but missing %s field (and possibly others).",
     122               0 :                       osTarget.c_str(), apszRPBMap[i+1] );
     123               0 :             CSLDestroy( papszMD );
     124               0 :             return NULL;
     125                 :         }
     126                 : 
     127              42 :         if( strchr(pszRPBVal,',') == NULL )
     128              30 :             osAdjVal = pszRPBVal;
     129                 :         else
     130                 :         {
     131                 :             // strip out commas and turn newlines into spaces.
     132                 :             int j;
     133                 : 
     134            3384 :             for( j = 0; pszRPBVal[j] != '\0'; j++ )
     135                 :             {
     136            3372 :                 switch( pszRPBVal[j] ) 
     137                 :                 {
     138                 :                   case ',':
     139                 :                   case '\n':
     140                 :                   case '\r':
     141             228 :                     osAdjVal += ' ';
     142             228 :                     break;
     143                 :                     
     144                 :                   case '(':
     145                 :                   case ')':
     146              24 :                     break;
     147                 : 
     148                 :                   default:
     149            3120 :                     osAdjVal += pszRPBVal[j];
     150                 :                 }
     151                 :             }
     152                 :         }
     153                 : 
     154              42 :         papszMD = CSLSetNameValue( papszMD, apszRPBMap[i], osAdjVal );
     155                 :     }
     156                 : 
     157               3 :     return papszMD;
     158                 : }
     159                 : 
     160                 : /************************************************************************/
     161                 : /*                          GDALWriteRPBFile()                          */
     162                 : /************************************************************************/
     163                 : 
     164               1 : CPLErr CPL_STDCALL GDALWriteRPBFile( const char *pszFilename, char **papszMD )
     165                 : 
     166                 : {
     167               1 :     CPLString osRPBFilename = CPLResetExtension( pszFilename, "RPB" );
     168                 :     
     169                 : 
     170                 : /* -------------------------------------------------------------------- */
     171                 : /*      Read file and parse.                                            */
     172                 : /* -------------------------------------------------------------------- */
     173               1 :     FILE *fp = VSIFOpenL( osRPBFilename, "w" );
     174                 : 
     175               1 :     if( fp == NULL )
     176                 :     {
     177                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     178                 :                   "Unable to create %s for writing.\n%s", 
     179               0 :                   osRPBFilename.c_str(), CPLGetLastErrorMsg() );
     180               0 :         return CE_Failure;
     181                 :     }
     182                 :     
     183                 : /* -------------------------------------------------------------------- */
     184                 : /*      Write the prefix information.                                   */
     185                 : /* -------------------------------------------------------------------- */
     186               1 :     VSIFPrintfL( fp, "%s", "satId = \"QB02\";\n" );
     187               1 :     VSIFPrintfL( fp, "%s", "bandId = \"P\";\n" );
     188               1 :     VSIFPrintfL( fp, "%s", "SpecId = \"RPC00B\";\n" );
     189               1 :     VSIFPrintfL( fp, "%s", "BEGIN_GROUP = IMAGE\n" );
     190               1 :     VSIFPrintfL( fp, "%s", "\terrBias = 0.0;\n" );
     191               1 :     VSIFPrintfL( fp, "%s", "\terrRand = 0.0;\n" );
     192                 : 
     193                 : /* -------------------------------------------------------------------- */
     194                 : /*      Write RPC values from our RPC metadata.                         */
     195                 : /* -------------------------------------------------------------------- */
     196                 :     int i;
     197                 : 
     198              15 :     for( i = 0; apszRPBMap[i] != NULL; i += 2 )
     199                 :     {
     200              14 :         const char *pszRPBVal = CSLFetchNameValue( papszMD, apszRPBMap[i] );
     201                 :         const char *pszRPBTag;
     202                 : 
     203              14 :         if( pszRPBVal == NULL )
     204                 :         {
     205                 :             CPLError( CE_Failure, CPLE_AppDefined,
     206                 :                       "%s field missing in metadata, %s file not written.",
     207               0 :                       apszRPBMap[i], osRPBFilename.c_str() );
     208               0 :             VSIFCloseL( fp );
     209               0 :             VSIUnlink( osRPBFilename );
     210               0 :             return CE_Failure;
     211                 :         }
     212                 : 
     213              14 :         pszRPBTag = apszRPBMap[i+1];
     214              14 :         if( EQUALN(pszRPBTag,"IMAGE.",6) )
     215              14 :             pszRPBTag += 6;
     216                 : 
     217              14 :         if( strstr(apszRPBMap[i], "COEF" ) == NULL )
     218                 :         {
     219              10 :             VSIFPrintfL( fp, "\t%s = %s;\n", pszRPBTag, pszRPBVal );
     220                 :         }
     221                 :         else
     222                 :         {
     223                 :             // Reformat in brackets with commas over multiple lines.
     224                 : 
     225               4 :             VSIFPrintfL( fp, "\t%s = (\n", pszRPBTag );
     226                 : 
     227                 :             char **papszItems = CSLTokenizeStringComplex( pszRPBVal, " ,", 
     228               4 :                                                           FALSE, FALSE );
     229                 : 
     230               4 :             if( CSLCount(papszItems) != 20 )
     231                 :             {
     232                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     233                 :                           "%s field is corrupt (not 20 values), %s file not written.\n%s = %s",
     234                 :                           apszRPBMap[i], osRPBFilename.c_str(),
     235               0 :                           apszRPBMap[i], pszRPBVal );
     236               0 :                 VSIFCloseL( fp );
     237               0 :                 VSIUnlink( osRPBFilename );
     238               0 :                 return CE_Failure;
     239                 :             }
     240                 : 
     241                 :             int j;
     242                 : 
     243              84 :             for( j = 0; j < 20; j++ )
     244                 :             {
     245              80 :                 if( j < 19 )
     246              76 :                     VSIFPrintfL( fp, "\t\t\t%s,\n", papszItems[j] );
     247                 :                 else
     248               4 :                     VSIFPrintfL( fp, "\t\t\t%s);\n", papszItems[j] );
     249                 :             }
     250               4 :             CSLDestroy( papszItems );
     251                 :         }
     252                 :     }
     253                 : 
     254                 : /* -------------------------------------------------------------------- */
     255                 : /*      Write end part                                                  */
     256                 : /* -------------------------------------------------------------------- */
     257               1 :     VSIFPrintfL( fp, "%s", "END_GROUP = IMAGE\n" );
     258               1 :     VSIFPrintfL( fp, "END;\n" );
     259               1 :     VSIFCloseL( fp );
     260                 :     
     261               1 :     return CE_None;
     262                 : }
     263                 : 
     264                 : /************************************************************************/
     265                 : /*                           GDAL_IMD_AA2R()                            */
     266                 : /*                                                                      */
     267                 : /*      Translate AA version IMD file to R version.                     */
     268                 : /************************************************************************/
     269                 : 
     270               0 : static int GDAL_IMD_AA2R( char ***ppapszIMD )
     271                 : 
     272                 : {
     273               0 :     char **papszIMD = *ppapszIMD;
     274                 : 
     275                 : /* -------------------------------------------------------------------- */
     276                 : /*      Verify that we have a new format file.                          */
     277                 : /* -------------------------------------------------------------------- */
     278               0 :     const char *pszValue = CSLFetchNameValue( papszIMD, "version" );
     279                 :     
     280               0 :     if( pszValue == NULL )
     281               0 :         return FALSE;
     282                 :     
     283               0 :     if( EQUAL(pszValue,"\"R\"") )
     284               0 :         return TRUE;
     285                 : 
     286               0 :     if( !EQUAL(pszValue,"\"AA\"") )
     287                 :     {
     288               0 :         CPLDebug( "IMD", "The file is not the expected 'version = \"AA\"' format.\nProceeding, but file may be corrupted." );
     289                 :     }
     290                 : 
     291                 : /* -------------------------------------------------------------------- */
     292                 : /*      Fix the version line.                                           */
     293                 : /* -------------------------------------------------------------------- */
     294               0 :     papszIMD = CSLSetNameValue( papszIMD, "version", "\"R\"" );
     295                 : 
     296                 : /* -------------------------------------------------------------------- */
     297                 : /*      remove a bunch of fields.                                       */
     298                 : /* -------------------------------------------------------------------- */
     299                 :     int iKey;
     300                 : 
     301                 :     static const char *apszToRemove[] = {
     302                 :         "productCatalogId",
     303                 :         "childCatalogId",
     304                 :         "productType",
     305                 :         "numberOfLooks",
     306                 :         "effectiveBandwidth",
     307                 :         "mode",
     308                 :         "scanDirection",
     309                 :         "cloudCover",
     310                 :         "productGSD",
     311                 :         NULL };
     312                 : 
     313               0 :     for( iKey = 0; apszToRemove[iKey] != NULL; iKey++ )
     314                 :     {
     315               0 :         int iTarget = CSLFindName( papszIMD, apszToRemove[iKey] );
     316               0 :         if( iTarget != -1 )
     317               0 :             papszIMD = CSLRemoveStrings( papszIMD, iTarget, 1, NULL );
     318                 :     }
     319                 : 
     320                 : /* -------------------------------------------------------------------- */
     321                 : /*      Replace various min/mean/max with just the mean.                */
     322                 : /* -------------------------------------------------------------------- */
     323                 :     static const char *keylist[] = { 
     324                 :         "CollectedRowGSD",
     325                 :         "CollectedColGSD",
     326                 :         "SunAz",
     327                 :         "SunEl",
     328                 :         "SatAz",
     329                 :         "SatEl",
     330                 :         "InTrackViewAngle",
     331                 :         "CrossTrackViewAngle",
     332                 :         "OffNadirViewAngle",
     333                 :         NULL };
     334                 : 
     335               0 :     for( iKey = 0; keylist[iKey] != NULL; iKey++ )
     336                 :     {
     337               0 :         CPLString osTarget;
     338                 :         int       iTarget;
     339                 : 
     340               0 :         osTarget.Printf( "IMAGE_1.min%s", keylist[iKey] );
     341               0 :         iTarget = CSLFindName( papszIMD, osTarget );
     342               0 :         if( iTarget != -1 )
     343               0 :             papszIMD = CSLRemoveStrings( papszIMD, iTarget, 1, NULL );
     344                 : 
     345               0 :         osTarget.Printf( "IMAGE_1.max%s", keylist[iKey] );
     346               0 :         iTarget = CSLFindName( papszIMD, osTarget );
     347               0 :         if( iTarget != -1 )
     348               0 :             papszIMD = CSLRemoveStrings( papszIMD, iTarget, 1, NULL );
     349                 : 
     350               0 :         osTarget.Printf( "IMAGE_1.mean%s", keylist[iKey] );
     351               0 :         iTarget = CSLFindName( papszIMD, osTarget );
     352               0 :         if( iTarget != -1 )
     353                 :         {
     354               0 :             CPLString osValue = CSLFetchNameValue( papszIMD, osTarget );
     355               0 :             CPLString osLine;
     356                 :             
     357                 :             osTarget.Printf( "IMAGE_1.%c%s", 
     358               0 :                              tolower(keylist[iKey][0]), 
     359               0 :                              keylist[iKey]+1 );
     360                 : 
     361               0 :             osLine = osTarget + "=" + osValue;
     362                 : 
     363               0 :             CPLFree( papszIMD[iTarget] );
     364               0 :             papszIMD[iTarget] = CPLStrdup(osLine);
     365                 :         }
     366                 :     }
     367                 : 
     368               0 :     *ppapszIMD = papszIMD;
     369               0 :     return TRUE;
     370                 : }
     371                 : 
     372                 : /************************************************************************/
     373                 : /*                          GDALLoadIMDFile()                           */
     374                 : /************************************************************************/
     375                 : 
     376            2850 : char ** CPL_STDCALL GDALLoadIMDFile( const char *pszFilename,
     377                 :                                      char **papszSiblingFiles )
     378                 : 
     379                 : {
     380                 : /* -------------------------------------------------------------------- */
     381                 : /*      Try to identify the RPB file in upper or lower case.            */
     382                 : /* -------------------------------------------------------------------- */
     383            2850 :     CPLString osTarget = CPLResetExtension( pszFilename, "IMD" );
     384                 :     
     385            2850 :     if( papszSiblingFiles == NULL )
     386                 :     {
     387                 :         VSIStatBufL sStatBuf;
     388                 :         
     389            2850 :         if( VSIStatL( osTarget, &sStatBuf ) != 0 )
     390                 :         {
     391            2844 :             osTarget = CPLResetExtension( pszFilename, "imd" );
     392                 : 
     393            2844 :             if( VSIStatL( osTarget, &sStatBuf ) != 0 )
     394            2844 :                 return NULL;
     395                 :         }
     396                 :     }
     397                 :     else
     398                 :     {
     399                 :         int iSibling = CSLFindString( papszSiblingFiles, 
     400               0 :                                       CPLGetFilename(osTarget) );
     401               0 :         if( iSibling < 0 )
     402               0 :             return NULL;
     403                 : 
     404               0 :         osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling]));
     405               0 :         osTarget += papszSiblingFiles[iSibling];
     406                 :     }
     407                 : 
     408                 : /* -------------------------------------------------------------------- */
     409                 : /*      Read file and parse.                                            */
     410                 : /* -------------------------------------------------------------------- */
     411               6 :     CPLKeywordParser oParser;
     412                 : 
     413               6 :     FILE *fp = VSIFOpenL( osTarget, "r" );
     414                 : 
     415               6 :     if( fp == NULL )
     416               0 :         return NULL;
     417                 :     
     418               6 :     if( !oParser.Ingest( fp ) )
     419                 :     {
     420               0 :         VSIFCloseL( fp );
     421               0 :         return NULL;
     422                 :     }
     423                 : 
     424               6 :     VSIFCloseL( fp );
     425                 : 
     426                 : /* -------------------------------------------------------------------- */
     427                 : /*      Consider version changing.                                      */
     428                 : /* -------------------------------------------------------------------- */
     429               6 :     char **papszIMD = CSLDuplicate( oParser.GetAllKeywords() );
     430               6 :     const char *pszVersion = CSLFetchNameValue( papszIMD, "version" );
     431                 : 
     432               6 :     if( pszVersion == NULL )
     433                 :     {
     434                 :         /* ? */;
     435                 :     }
     436               6 :     else if( EQUAL(pszVersion,"\"AA\"") )
     437                 :     {
     438               0 :         GDAL_IMD_AA2R( &papszIMD );
     439                 :     }
     440                 : 
     441               6 :     return papszIMD;
     442                 : }
     443                 : 
     444                 : /************************************************************************/
     445                 : /*                       GDALWriteIMDMultiLine()                        */
     446                 : /*                                                                      */
     447                 : /*      Write a value that is split over multiple lines.                */
     448                 : /************************************************************************/
     449                 :  
     450               4 : static void GDALWriteIMDMultiLine( FILE *fp, const char *pszValue )
     451                 : 
     452                 : {
     453                 :     char **papszItems = CSLTokenizeStringComplex( pszValue, "(,) ", 
     454               4 :                                                   FALSE, FALSE );
     455               4 :     int nItemCount = CSLCount(papszItems);
     456                 :     int i;
     457                 : 
     458               4 :     VSIFPrintfL( fp, "(\n" );
     459                 : 
     460              40 :     for( i = 0; i < nItemCount; i++ )
     461                 :     {
     462              36 :         if( i == nItemCount-1 )
     463               4 :             VSIFPrintfL( fp, "\t%s );\n", papszItems[i] );
     464                 :         else
     465              32 :             VSIFPrintfL( fp, "\t%s,\n", papszItems[i] );
     466                 :     }
     467               4 :     CSLDestroy( papszItems );
     468               4 : }
     469                 : 
     470                 : /************************************************************************/
     471                 : /*                          GDALWriteIMDFile()                          */
     472                 : /************************************************************************/
     473                 : 
     474               2 : CPLErr CPL_STDCALL GDALWriteIMDFile( const char *pszFilename, char **papszMD )
     475                 : 
     476                 : {
     477               2 :     CPLString osRPBFilename = CPLResetExtension( pszFilename, "IMD" );
     478                 :     
     479                 : 
     480                 : /* -------------------------------------------------------------------- */
     481                 : /*      Read file and parse.                                            */
     482                 : /* -------------------------------------------------------------------- */
     483               2 :     FILE *fp = VSIFOpenL( osRPBFilename, "w" );
     484                 : 
     485               2 :     if( fp == NULL )
     486                 :     {
     487                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     488                 :                   "Unable to create %s for writing.\n%s", 
     489               0 :                   osRPBFilename.c_str(), CPLGetLastErrorMsg() );
     490               0 :         return CE_Failure;
     491                 :     }
     492                 : 
     493                 : /* ==================================================================== */
     494                 : /* -------------------------------------------------------------------- */
     495                 : /*      Loop through all values writing.                                */
     496                 : /* -------------------------------------------------------------------- */
     497                 : /* ==================================================================== */
     498                 :     int iKey;
     499               2 :     CPLString osCurSection;
     500                 : 
     501             176 :     for( iKey = 0; papszMD[iKey] != NULL; iKey++ )
     502                 :     {
     503             174 :         char *pszRawKey = NULL;
     504             174 :         const char *pszValue = CPLParseNameValue( papszMD[iKey], &pszRawKey );
     505             174 :         CPLString osKeySection, osKeyItem;
     506             174 :         char *pszDot = strchr(pszRawKey,'.');
     507                 : 
     508                 : /* -------------------------------------------------------------------- */
     509                 : /*      Split stuff like BAND_P.ULLon into section and item.            */
     510                 : /* -------------------------------------------------------------------- */
     511             174 :         if( pszDot == NULL )
     512                 :         {
     513              28 :             osKeyItem = pszRawKey;
     514                 :         }
     515                 :         else
     516                 :         {
     517             146 :             osKeyItem = pszDot+1;
     518             146 :             *pszDot = '\0';
     519             146 :             osKeySection = pszRawKey;
     520                 :         }
     521             174 :         CPLFree( pszRawKey );
     522                 : 
     523                 : /* -------------------------------------------------------------------- */
     524                 : /*      Close and/or start sections as needed.                          */
     525                 : /* -------------------------------------------------------------------- */
     526             174 :         if( osCurSection.size() && !EQUAL(osCurSection,osKeySection) )
     527               4 :             VSIFPrintfL( fp, "END_GROUP = %s\n", osCurSection.c_str() );
     528                 : 
     529             174 :         if( osKeySection.size() && !EQUAL(osCurSection,osKeySection) )
     530               6 :             VSIFPrintfL( fp, "BEGIN_GROUP = %s\n", osKeySection.c_str() );
     531                 : 
     532             174 :         osCurSection = osKeySection;
     533                 : 
     534                 : /* -------------------------------------------------------------------- */
     535                 : /*      Print out simple item.                                          */
     536                 : /* -------------------------------------------------------------------- */
     537             174 :         if( osCurSection.size() )
     538             146 :             VSIFPrintfL( fp, "\t%s = ", osKeyItem.c_str() );
     539                 :         else
     540              28 :             VSIFPrintfL( fp, "%s = ", osKeyItem.c_str() );
     541                 : 
     542             174 :         if( pszValue[0] != '(' )
     543             170 :             VSIFPrintfL( fp, "%s;\n", pszValue );
     544                 :         else
     545               4 :             GDALWriteIMDMultiLine( fp, pszValue );
     546                 :     }
     547                 : 
     548                 : /* -------------------------------------------------------------------- */
     549                 : /*      Close off.                                                      */
     550                 : /* -------------------------------------------------------------------- */
     551               2 :     if( osCurSection.size() )
     552               2 :         VSIFPrintfL( fp, "END_GROUP = %s\n", osCurSection.c_str() );
     553                 :     
     554               2 :     VSIFPrintfL( fp, "END;\n" );
     555                 :     
     556               2 :     VSIFCloseL( fp );
     557                 :     
     558               2 :     return CE_None;
     559                 : }

Generated by: LCOV version 1.7