LTP GCOV extension - code coverage report
Current view: directory - frmts/ers - ershdrnode.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 164
Code covered: 81.1 % Executed lines: 133

       1                 : /******************************************************************************
       2                 :  * $Id: ershdrnode.cpp 17867 2009-10-21 21:04:49Z rouault $
       3                 :  *
       4                 :  * Project:  ERMapper .ers Driver
       5                 :  * Purpose:  Implementation of ERSHdrNode class for parsing/accessing .ers hdr.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2007, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "cpl_conv.h"
      31                 : #include "cpl_string.h"
      32                 : #include "ershdrnode.h"
      33                 : 
      34                 : CPL_CVSID("$Id: ershdrnode.cpp 17867 2009-10-21 21:04:49Z rouault $");
      35                 : 
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                             ERSHdrNode()                             */
      39                 : /************************************************************************/
      40                 : 
      41             199 : ERSHdrNode::ERSHdrNode()
      42                 : 
      43                 : {
      44             199 :     nItemMax = 0;
      45             199 :     nItemCount = 0;
      46             199 :     papszItemName = NULL;
      47             199 :     papszItemValue = NULL;
      48             199 :     papoItemChild = NULL;
      49             199 : }
      50                 : 
      51                 : /************************************************************************/
      52                 : /*                            ~ERSHdrNode()                             */
      53                 : /************************************************************************/
      54                 : 
      55             199 : ERSHdrNode::~ERSHdrNode()
      56                 : 
      57                 : {
      58                 :     int i;
      59                 : 
      60            1065 :     for( i = 0; i < nItemCount; i++ )
      61                 :     {
      62             866 :         if( papoItemChild[i] != NULL )
      63             159 :             delete papoItemChild[i];
      64             866 :         if( papszItemValue[i] != NULL )
      65             707 :             CPLFree( papszItemValue[i] );
      66             866 :         CPLFree( papszItemName[i] );
      67                 :     }
      68                 : 
      69             199 :     CPLFree( papszItemName );
      70             199 :     CPLFree( papszItemValue );
      71             199 :     CPLFree( papoItemChild );
      72             199 : }
      73                 : 
      74                 : /************************************************************************/
      75                 : /*                             MakeSpace()                              */
      76                 : /*                                                                      */
      77                 : /*      Ensure we have room for at least one more entry in our item     */
      78                 : /*      lists.                                                          */
      79                 : /************************************************************************/
      80                 : 
      81             866 : void ERSHdrNode::MakeSpace()
      82                 : 
      83                 : {
      84             866 :     if( nItemCount == nItemMax )
      85                 :     {
      86             200 :         nItemMax = (int) (nItemMax * 1.3) + 10;
      87                 :         papszItemName = (char **) 
      88             200 :             CPLRealloc(papszItemName,sizeof(char *) * nItemMax);
      89                 :         papszItemValue = (char **) 
      90             200 :             CPLRealloc(papszItemValue,sizeof(char *) * nItemMax);
      91                 :         papoItemChild = (ERSHdrNode **) 
      92             200 :             CPLRealloc(papoItemChild,sizeof(void *) * nItemMax);
      93                 :     }
      94             866 : }
      95                 : 
      96                 : /************************************************************************/
      97                 : /*                              ReadLine()                              */
      98                 : /*                                                                      */
      99                 : /*      Read one virtual line from the input source.  Multiple lines    */
     100                 : /*      will be appended for objects enclosed in {}.                    */
     101                 : /************************************************************************/
     102                 : 
     103             617 : int ERSHdrNode::ReadLine( FILE * fp, CPLString &osLine )
     104                 : 
     105                 : {
     106                 :     int  nBracketLevel;
     107                 : 
     108             617 :     osLine = "";
     109                 : 
     110             617 :     do
     111                 :     {
     112             617 :         const char *pszNewLine = CPLReadLineL( fp );
     113                 :         
     114             617 :         if( pszNewLine == NULL )
     115               0 :             return FALSE;
     116                 : 
     117             617 :         osLine += pszNewLine;
     118                 : 
     119             617 :         int  bInQuote = FALSE;
     120                 :         size_t  i;
     121                 : 
     122             617 :         nBracketLevel = 0;
     123                 : 
     124           12827 :         for( i = 0; i < osLine.length(); i++ )
     125                 :         {
     126           12210 :             if( osLine[i] == '"' )
     127             208 :                 bInQuote = !bInQuote;
     128           12002 :             else if( osLine[i] == '{' && !bInQuote )
     129               0 :                 nBracketLevel++;
     130           12002 :             else if( osLine[i] == '}' && !bInQuote )
     131               0 :                 nBracketLevel--;
     132                 : 
     133                 :             // We have to ignore escaped quotes and backslashes in strings.
     134           12002 :             else if( osLine[i] == '\\' && osLine[i+1] == '"' && bInQuote )
     135               0 :                 i++;
     136           12002 :             else if( osLine[i] == '\\' && osLine[i+1] == '\\' && bInQuote )
     137               0 :                 i++;
     138                 :         }
     139                 :     } while( nBracketLevel > 0 );
     140                 : 
     141             617 :     return TRUE;
     142                 : }
     143                 : 
     144                 : /************************************************************************/
     145                 : /*                           ParseChildren()                            */
     146                 : /*                                                                      */
     147                 : /*      We receive the FILE * positioned after the "Object Begin"       */
     148                 : /*      line for this object, and are responsible for reading all       */
     149                 : /*      children.  We should return after consuming the                 */
     150                 : /*      corresponding End line for this object.  Really the first       */
     151                 : /*      unmatched End since we don't know what object we are.           */
     152                 : /*                                                                      */
     153                 : /*      This function is used recursively to read sub-objects.          */
     154                 : /************************************************************************/
     155                 : 
     156             617 : int ERSHdrNode::ParseChildren( FILE * fp )
     157                 : 
     158                 : {
     159               0 :     while( TRUE )
     160                 :     { 
     161                 :         size_t iOff;
     162             617 :         CPLString osLine;
     163                 : 
     164                 : /* -------------------------------------------------------------------- */
     165                 : /*      Read the next line (or multi-line for bracketed value).         */
     166                 : /* -------------------------------------------------------------------- */
     167             617 :         if( !ReadLine( fp, osLine ) )
     168               0 :             return FALSE;
     169                 : 
     170                 : /* -------------------------------------------------------------------- */
     171                 : /*      Got a Name=Value.                                               */
     172                 : /* -------------------------------------------------------------------- */
     173             617 :         if( (iOff = osLine.find_first_of( '=' )) != std::string::npos )
     174                 :         {
     175             437 :             CPLString osName = osLine.substr(0,iOff-1);
     176             437 :             osName.Trim();
     177                 : 
     178             437 :             CPLString osValue = osLine.c_str() + iOff + 1;
     179             437 :             osValue.Trim();
     180                 : 
     181             437 :             MakeSpace();
     182             437 :             papszItemName[nItemCount] = CPLStrdup(osName);
     183             437 :             papszItemValue[nItemCount] = CPLStrdup(osValue);
     184             437 :             papoItemChild[nItemCount] = NULL;
     185                 : 
     186             437 :             nItemCount++;
     187                 :         }
     188                 : 
     189                 : /* -------------------------------------------------------------------- */
     190                 : /*      Got a Begin for an object.                                      */
     191                 : /* -------------------------------------------------------------------- */
     192             180 :         else if( (iOff = osLine.find( " Begin" )) != std::string::npos )
     193                 :         {
     194              69 :             CPLString osName = osLine.substr(0,iOff);
     195              69 :             osName.Trim();
     196                 :             
     197              69 :             MakeSpace();
     198              69 :             papszItemName[nItemCount] = CPLStrdup(osName);
     199              69 :             papszItemValue[nItemCount] = NULL;
     200              69 :             papoItemChild[nItemCount] = new ERSHdrNode();
     201                 : 
     202              69 :             nItemCount++;
     203                 :             
     204             138 :             if( !papoItemChild[nItemCount-1]->ParseChildren( fp ) )
     205               0 :                 return FALSE;
     206                 :         }
     207                 : 
     208                 : /* -------------------------------------------------------------------- */
     209                 : /*      Got an End for our object.  Well, at least we *assume* it       */
     210                 : /*      must be for our object.                                         */
     211                 : /* -------------------------------------------------------------------- */
     212             111 :         else if( osLine.find( " End" ) != std::string::npos )
     213                 :         {
     214             109 :             return TRUE;
     215                 :         }
     216                 : 
     217                 : /* -------------------------------------------------------------------- */
     218                 : /*      Error?                                                          */
     219                 : /* -------------------------------------------------------------------- */
     220               2 :         else if( osLine.Trim().length() > 0 )
     221                 :         {
     222                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     223                 :                       "Unexpected line parsing .ecw:\n%s", 
     224               0 :                       osLine.c_str() );
     225               0 :             return FALSE;
     226                 :         }
     227                 :     }
     228                 : }
     229                 : 
     230                 : /************************************************************************/
     231                 : /*                             WriteSelf()                              */
     232                 : /*                                                                      */
     233                 : /*      Recursively write self and children to file.                    */
     234                 : /************************************************************************/
     235                 : 
     236             150 : int ERSHdrNode::WriteSelf( FILE * fp, int nIndent )
     237                 : 
     238                 : {
     239             150 :     CPLString oIndent;
     240                 :     int i;
     241                 : 
     242             150 :     oIndent.assign( nIndent, '\t' );
     243                 : 
     244             810 :     for( i = 0; i < nItemCount; i++ )
     245                 :     {
     246             660 :         if( papszItemValue[i] != NULL )
     247                 :         {
     248             540 :             if( VSIFPrintfL( fp, "%s%s\t= %s\n", 
     249                 :                              oIndent.c_str(), 
     250                 :                              papszItemName[i], 
     251                 :                              papszItemValue[i] ) < 1 )
     252               0 :                 return FALSE;
     253                 :         }
     254                 :         else
     255                 :         {
     256                 :             VSIFPrintfL( fp, "%s%s Begin\n", 
     257             120 :                          oIndent.c_str(), papszItemName[i] );
     258             120 :             if( !papoItemChild[i]->WriteSelf( fp, nIndent+1 ) )
     259               0 :                 return FALSE;
     260             120 :             if( VSIFPrintfL( fp, "%s%s End\n", 
     261                 :                              oIndent.c_str(), papszItemName[i] ) < 1 )
     262               0 :                 return FALSE;
     263                 :         }
     264                 :     }
     265                 : 
     266             150 :     return TRUE;
     267                 : }
     268                 : 
     269                 : /************************************************************************/
     270                 : /*                                Find()                                */
     271                 : /*                                                                      */
     272                 : /*      Find the desired entry value.  The input is a path with         */
     273                 : /*      components seperated by dots, relative to the current node.     */
     274                 : /************************************************************************/
     275                 : 
     276            1418 : const char *ERSHdrNode::Find( const char *pszPath, const char *pszDefault )
     277                 : 
     278                 : {
     279                 :     int i;
     280                 : 
     281                 : /* -------------------------------------------------------------------- */
     282                 : /*      If this is the final component of the path, search for a        */
     283                 : /*      matching child and return the value.                            */
     284                 : /* -------------------------------------------------------------------- */
     285            1418 :     if( strchr(pszPath,'.') == NULL )
     286                 :     {
     287            2601 :         for( i = 0; i < nItemCount; i++ )
     288                 :         {
     289            2402 :             if( EQUAL(pszPath,papszItemName[i]) )
     290                 :             {
     291             477 :                 if( papszItemValue[i] != NULL )
     292                 :                 {
     293             477 :                     if( papszItemValue[i][0] == '"' )
     294                 :                     {
     295                 :                         // strip off quotes. 
     296              25 :                         osTempReturn = papszItemValue[i];
     297                 :                         osTempReturn = 
     298              50 :                             osTempReturn.substr( 1, osTempReturn.length()-2 );
     299              25 :                         return osTempReturn;
     300                 :                     }
     301                 :                     else
     302             452 :                         return papszItemValue[i];
     303                 :                 }
     304                 :                 else
     305               0 :                     return pszDefault;
     306                 :             }
     307                 :         }
     308             199 :         return pszDefault;
     309                 :     }
     310                 : 
     311                 : /* -------------------------------------------------------------------- */
     312                 : /*      This is a dot path - extract the first element, find a match    */
     313                 : /*      and recurse.                                                    */
     314                 : /* -------------------------------------------------------------------- */
     315             742 :     CPLString osPathFirst, osPathRest, osPath = pszPath;
     316                 :     int iDot;
     317                 :     
     318             742 :     iDot = osPath.find_first_of('.');
     319             742 :     osPathFirst = osPath.substr(0,iDot);
     320             742 :     osPathRest = osPath.substr(iDot+1);
     321                 : 
     322            4616 :     for( i = 0; i < nItemCount; i++ )
     323                 :     {
     324            4451 :         if( EQUAL(osPathFirst,papszItemName[i]) )
     325                 :         {
     326             577 :             if( papoItemChild[i] != NULL )
     327            1319 :                 return papoItemChild[i]->Find( osPathRest, pszDefault );
     328                 :             else
     329               0 :                 return pszDefault;
     330                 :         }
     331                 :     }
     332                 : 
     333             165 :     return pszDefault;
     334                 : }
     335                 : 
     336                 : /************************************************************************/
     337                 : /*                              FindElem()                              */
     338                 : /*                                                                      */
     339                 : /*      Find a particular element from an array valued item.            */
     340                 : /************************************************************************/
     341                 : 
     342                 : const char *ERSHdrNode::FindElem( const char *pszPath, int iElem, 
     343               0 :                                   const char *pszDefault )
     344                 : 
     345                 : {
     346               0 :     const char *pszArray = Find( pszPath, NULL );
     347                 :     char **papszTokens;
     348               0 :     int  bDefault = TRUE;
     349                 : 
     350               0 :     if( pszArray == NULL )
     351               0 :         return pszDefault;
     352                 : 
     353               0 :     papszTokens = CSLTokenizeStringComplex( pszArray, "{ \t}", TRUE, FALSE );
     354               0 :     if( iElem >= 0 && iElem < CSLCount(papszTokens) )
     355                 :     {
     356               0 :         osTempReturn = papszTokens[iElem];
     357               0 :         bDefault = FALSE;
     358                 :     }
     359                 :     
     360               0 :     CSLDestroy( papszTokens );
     361                 : 
     362               0 :     if( bDefault )
     363               0 :         return pszDefault;
     364                 :     else
     365               0 :         return osTempReturn;
     366                 : }
     367                 : 
     368                 : /************************************************************************/
     369                 : /*                              FindNode()                              */
     370                 : /*                                                                      */
     371                 : /*      Find the desired node.                                          */
     372                 : /************************************************************************/
     373                 : 
     374             510 : ERSHdrNode *ERSHdrNode::FindNode( const char *pszPath )
     375                 : 
     376                 : {
     377                 :     int i;
     378             510 :     CPLString osPathFirst, osPathRest, osPath = pszPath;
     379                 :     int iDot;
     380                 :     
     381             510 :     iDot = osPath.find_first_of('.');
     382             510 :     if( iDot == -1 )
     383                 :     {
     384             470 :         osPathFirst = osPath;
     385                 :     }
     386                 :     else
     387                 :     {
     388              40 :         osPathFirst = osPath.substr(0,iDot);
     389              40 :         osPathRest = osPath.substr(iDot+1);
     390                 :     }
     391                 : 
     392            3157 :     for( i = 0; i < nItemCount; i++ )
     393                 :     {
     394            3027 :         if( EQUAL(osPathFirst,papszItemName[i]) )
     395                 :         {
     396             380 :             if( papoItemChild[i] != NULL )
     397                 :             {
     398             380 :                 if( osPathRest.length() > 0 )
     399              40 :                     return papoItemChild[i]->FindNode( osPathRest );
     400                 :                 else
     401             340 :                     return papoItemChild[i];
     402                 :             }
     403                 :             else
     404               0 :                 return NULL;
     405                 :         }
     406                 :     }
     407                 : 
     408             130 :     return NULL;
     409                 : }
     410                 : 
     411                 : /************************************************************************/
     412                 : /*                                Set()                                 */
     413                 : /*                                                                      */
     414                 : /*      Set a value item.                                               */
     415                 : /************************************************************************/
     416                 : 
     417             660 : void ERSHdrNode::Set( const char *pszPath, const char *pszValue )
     418                 : 
     419                 : {
     420             660 :     CPLString  osPath = pszPath;
     421                 :     int iDot;
     422                 :     
     423             660 :     iDot = osPath.find_first_of('.');
     424                 : 
     425                 : /* -------------------------------------------------------------------- */
     426                 : /*      We have an intermediate node, find or create it and             */
     427                 : /*      recurse.                                                        */
     428                 : /* -------------------------------------------------------------------- */
     429             660 :     if( iDot != -1 )
     430                 :     {
     431             390 :         CPLString osPathFirst = osPath.substr(0,iDot);
     432             390 :         CPLString osPathRest = osPath.substr(iDot+1);
     433             390 :         ERSHdrNode *poFirst = FindNode( osPathFirst );
     434                 :         
     435             390 :         if( poFirst == NULL )
     436                 :         {
     437              90 :             poFirst = new ERSHdrNode();
     438                 :             
     439              90 :             MakeSpace();
     440              90 :             papszItemName[nItemCount] = CPLStrdup(osPathFirst);
     441              90 :             papszItemValue[nItemCount] = NULL;
     442              90 :             papoItemChild[nItemCount] = poFirst;
     443              90 :             nItemCount++;
     444                 :         }
     445                 : 
     446             390 :         poFirst->Set( osPathRest, pszValue );
     447             780 :         return;
     448                 :     }
     449                 : 
     450                 : /* -------------------------------------------------------------------- */
     451                 : /*      This is the final item name.  Find or create it.                */
     452                 : /* -------------------------------------------------------------------- */
     453                 :     int i;
     454                 : 
     455             630 :     for( i = 0; i < nItemCount; i++ )
     456                 :     {
     457             360 :         if( EQUAL(osPath,papszItemName[i]) 
     458                 :             && papszItemValue[i] != NULL )
     459                 :         {
     460               0 :             CPLFree( papszItemValue[i] );
     461               0 :             papszItemValue[i] = CPLStrdup( pszValue );
     462                 :             return;
     463                 :         }
     464                 :     }
     465                 : 
     466             270 :     MakeSpace();
     467             270 :     papszItemName[nItemCount] = CPLStrdup(osPath);
     468             270 :     papszItemValue[nItemCount] = CPLStrdup(pszValue);
     469             270 :     papoItemChild[nItemCount] = NULL;
     470             270 :     nItemCount++;
     471                 : }

Generated by: LTP GCOV extension version 1.5