LCOV - code coverage report
Current view: directory - frmts/ers - ershdrnode.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 165 138 83.6 %
Date: 2012-12-26 Functions: 12 9 75.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ershdrnode.cpp 21814 2011-02-23 22:55:14Z warmerdam $
       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 21814 2011-02-23 22:55:14Z warmerdam $");
      35                 : 
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                             ERSHdrNode()                             */
      39                 : /************************************************************************/
      40                 : 
      41             232 : ERSHdrNode::ERSHdrNode()
      42                 : 
      43                 : {
      44             232 :     nItemMax = 0;
      45             232 :     nItemCount = 0;
      46             232 :     papszItemName = NULL;
      47             232 :     papszItemValue = NULL;
      48             232 :     papoItemChild = NULL;
      49             232 : }
      50                 : 
      51                 : /************************************************************************/
      52                 : /*                            ~ERSHdrNode()                             */
      53                 : /************************************************************************/
      54                 : 
      55             232 : ERSHdrNode::~ERSHdrNode()
      56                 : 
      57                 : {
      58                 :     int i;
      59                 : 
      60            1270 :     for( i = 0; i < nItemCount; i++ )
      61                 :     {
      62            1038 :         if( papoItemChild[i] != NULL )
      63             182 :             delete papoItemChild[i];
      64            1038 :         if( papszItemValue[i] != NULL )
      65             856 :             CPLFree( papszItemValue[i] );
      66            1038 :         CPLFree( papszItemName[i] );
      67                 :     }
      68                 : 
      69             232 :     CPLFree( papszItemName );
      70             232 :     CPLFree( papszItemValue );
      71             232 :     CPLFree( papoItemChild );
      72             232 : }
      73                 : 
      74                 : /************************************************************************/
      75                 : /*                             MakeSpace()                              */
      76                 : /*                                                                      */
      77                 : /*      Ensure we have room for at least one more entry in our item     */
      78                 : /*      lists.                                                          */
      79                 : /************************************************************************/
      80                 : 
      81            1038 : void ERSHdrNode::MakeSpace()
      82                 : 
      83                 : {
      84            1038 :     if( nItemCount == nItemMax )
      85                 :     {
      86             233 :         nItemMax = (int) (nItemMax * 1.3) + 10;
      87                 :         papszItemName = (char **) 
      88             233 :             CPLRealloc(papszItemName,sizeof(char *) * nItemMax);
      89                 :         papszItemValue = (char **) 
      90             233 :             CPLRealloc(papszItemValue,sizeof(char *) * nItemMax);
      91                 :         papoItemChild = (ERSHdrNode **) 
      92             233 :             CPLRealloc(papoItemChild,sizeof(void *) * nItemMax);
      93                 :     }
      94            1038 : }
      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             801 : int ERSHdrNode::ReadLine( VSILFILE * fp, CPLString &osLine )
     104                 : 
     105                 : {
     106                 :     int  nBracketLevel;
     107                 : 
     108             801 :     osLine = "";
     109                 : 
     110             811 :     do
     111                 :     {
     112             811 :         const char *pszNewLine = CPLReadLineL( fp );
     113                 :         
     114             811 :         if( pszNewLine == NULL )
     115               0 :             return FALSE;
     116                 : 
     117             811 :         osLine += pszNewLine;
     118                 : 
     119             811 :         int  bInQuote = FALSE;
     120                 :         size_t  i;
     121                 : 
     122             811 :         nBracketLevel = 0;
     123                 : 
     124           18380 :         for( i = 0; i < osLine.length(); i++ )
     125                 :         {
     126           17569 :             if( osLine[i] == '"' )
     127             338 :                 bInQuote = !bInQuote;
     128           17231 :             else if( osLine[i] == '{' && !bInQuote )
     129              12 :                 nBracketLevel++;
     130           17219 :             else if( osLine[i] == '}' && !bInQuote )
     131               2 :                 nBracketLevel--;
     132                 : 
     133                 :             // We have to ignore escaped quotes and backslashes in strings.
     134           17217 :             else if( osLine[i] == '\\' && osLine[i+1] == '"' && bInQuote )
     135               0 :                 i++;
     136           17217 :             else if( osLine[i] == '\\' && osLine[i+1] == '\\' && bInQuote )
     137               0 :                 i++;
     138                 :         }
     139                 :     } while( nBracketLevel > 0 );
     140                 : 
     141             801 :     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             801 : int ERSHdrNode::ParseChildren( VSILFILE * fp )
     157                 : 
     158                 : {
     159               0 :     while( TRUE )
     160                 :     { 
     161                 :         size_t iOff;
     162             801 :         CPLString osLine;
     163                 : 
     164                 : /* -------------------------------------------------------------------- */
     165                 : /*      Read the next line (or multi-line for bracketed value).         */
     166                 : /* -------------------------------------------------------------------- */
     167             801 :         if( !ReadLine( fp, osLine ) )
     168               0 :             return FALSE;
     169                 : 
     170                 : /* -------------------------------------------------------------------- */
     171                 : /*      Got a Name=Value.                                               */
     172                 : /* -------------------------------------------------------------------- */
     173             801 :         if( (iOff = osLine.find_first_of( '=' )) != std::string::npos )
     174                 :         {
     175             571 :             CPLString osName = osLine.substr(0,iOff-1);
     176             571 :             osName.Trim();
     177                 : 
     178             571 :             CPLString osValue = osLine.c_str() + iOff + 1;
     179             571 :             osValue.Trim();
     180                 : 
     181             571 :             MakeSpace();
     182             571 :             papszItemName[nItemCount] = CPLStrdup(osName);
     183             571 :             papszItemValue[nItemCount] = CPLStrdup(osValue);
     184             571 :             papoItemChild[nItemCount] = NULL;
     185                 : 
     186             571 :             nItemCount++;
     187                 :         }
     188                 : 
     189                 : /* -------------------------------------------------------------------- */
     190                 : /*      Got a Begin for an object.                                      */
     191                 : /* -------------------------------------------------------------------- */
     192             230 :         else if( (iOff = osLine.ifind( " Begin" )) != std::string::npos )
     193                 :         {
     194              89 :             CPLString osName = osLine.substr(0,iOff);
     195              89 :             osName.Trim();
     196                 :             
     197              89 :             MakeSpace();
     198              89 :             papszItemName[nItemCount] = CPLStrdup(osName);
     199              89 :             papszItemValue[nItemCount] = NULL;
     200              89 :             papoItemChild[nItemCount] = new ERSHdrNode();
     201                 : 
     202              89 :             nItemCount++;
     203                 :             
     204             178 :             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             141 :         else if( osLine.ifind( " End" ) != std::string::npos )
     213                 :         {
     214             139 :             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             159 : int ERSHdrNode::WriteSelf( VSILFILE * fp, int nIndent )
     237                 : 
     238                 : {
     239             159 :     CPLString oIndent;
     240                 :     int i;
     241                 : 
     242             159 :     oIndent.assign( nIndent, '\t' );
     243                 : 
     244             867 :     for( i = 0; i < nItemCount; i++ )
     245                 :     {
     246             708 :         if( papszItemValue[i] != NULL )
     247                 :         {
     248             582 :             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             126 :                          oIndent.c_str(), papszItemName[i] );
     258             126 :             if( !papoItemChild[i]->WriteSelf( fp, nIndent+1 ) )
     259               0 :                 return FALSE;
     260             126 :             if( VSIFPrintfL( fp, "%s%s End\n", 
     261                 :                              oIndent.c_str(), papszItemName[i] ) < 1 )
     262               0 :                 return FALSE;
     263                 :         }
     264                 :     }
     265                 : 
     266             159 :     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            1789 : 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            1789 :     if( strchr(pszPath,'.') == NULL )
     286                 :     {
     287            3291 :         for( i = 0; i < nItemCount; i++ )
     288                 :         {
     289            3040 :             if( EQUAL(pszPath,papszItemName[i]) )
     290                 :             {
     291             605 :                 if( papszItemValue[i] != NULL )
     292                 :                 {
     293             605 :                     if( papszItemValue[i][0] == '"' )
     294                 :                     {
     295                 :                         // strip off quotes. 
     296              43 :                         osTempReturn = papszItemValue[i];
     297                 :                         osTempReturn = 
     298              86 :                             osTempReturn.substr( 1, osTempReturn.length()-2 );
     299              43 :                         return osTempReturn;
     300                 :                     }
     301                 :                     else
     302             562 :                         return papszItemValue[i];
     303                 :                 }
     304                 :                 else
     305               0 :                     return pszDefault;
     306                 :             }
     307                 :         }
     308             251 :         return pszDefault;
     309                 :     }
     310                 : 
     311                 : /* -------------------------------------------------------------------- */
     312                 : /*      This is a dot path - extract the first element, find a match    */
     313                 : /*      and recurse.                                                    */
     314                 : /* -------------------------------------------------------------------- */
     315             933 :     CPLString osPathFirst, osPathRest, osPath = pszPath;
     316                 :     int iDot;
     317                 :     
     318             933 :     iDot = osPath.find_first_of('.');
     319             933 :     osPathFirst = osPath.substr(0,iDot);
     320             933 :     osPathRest = osPath.substr(iDot+1);
     321                 : 
     322            5810 :     for( i = 0; i < nItemCount; i++ )
     323                 :     {
     324            5606 :         if( EQUAL(osPathFirst,papszItemName[i]) )
     325                 :         {
     326             729 :             if( papoItemChild[i] != NULL )
     327             729 :                 return papoItemChild[i]->Find( osPathRest, pszDefault );
     328                 :             else
     329               0 :                 return pszDefault;
     330                 :         }
     331                 :     }
     332                 : 
     333             204 :     return pszDefault;
     334                 : }
     335                 : 
     336                 : /************************************************************************/
     337                 : /*                              FindElem()                              */
     338                 : /*                                                                      */
     339                 : /*      Find a particular element from an array valued item.            */
     340                 : /************************************************************************/
     341                 : 
     342               0 : const char *ERSHdrNode::FindElem( const char *pszPath, int iElem, 
     343                 :                                   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             574 : ERSHdrNode *ERSHdrNode::FindNode( const char *pszPath )
     375                 : 
     376                 : {
     377                 :     int i;
     378             574 :     CPLString osPathFirst, osPathRest, osPath = pszPath;
     379                 :     int iDot;
     380                 :     
     381             574 :     iDot = osPath.find_first_of('.');
     382             574 :     if( iDot == -1 )
     383                 :     {
     384             524 :         osPathFirst = osPath;
     385                 :     }
     386                 :     else
     387                 :     {
     388              50 :         osPathFirst = osPath.substr(0,iDot);
     389              50 :         osPathRest = osPath.substr(iDot+1);
     390                 :     }
     391                 : 
     392            3531 :     for( i = 0; i < nItemCount; i++ )
     393                 :     {
     394            3390 :         if( EQUAL(osPathFirst,papszItemName[i]) )
     395                 :         {
     396             433 :             if( papoItemChild[i] != NULL )
     397                 :             {
     398             433 :                 if( osPathRest.length() > 0 )
     399              50 :                     return papoItemChild[i]->FindNode( osPathRest );
     400                 :                 else
     401             383 :                     return papoItemChild[i];
     402                 :             }
     403                 :             else
     404               0 :                 return NULL;
     405                 :         }
     406                 :     }
     407                 : 
     408             141 :     return NULL;
     409                 : }
     410                 : 
     411                 : /************************************************************************/
     412                 : /*                                Set()                                 */
     413                 : /*                                                                      */
     414                 : /*      Set a value item.                                               */
     415                 : /************************************************************************/
     416                 : 
     417             714 : void ERSHdrNode::Set( const char *pszPath, const char *pszValue )
     418                 : 
     419                 : {
     420             714 :     CPLString  osPath = pszPath;
     421                 :     int iDot;
     422                 :     
     423             714 :     iDot = osPath.find_first_of('.');
     424                 : 
     425                 : /* -------------------------------------------------------------------- */
     426                 : /*      We have an intermediate node, find or create it and             */
     427                 : /*      recurse.                                                        */
     428                 : /* -------------------------------------------------------------------- */
     429             714 :     if( iDot != -1 )
     430                 :     {
     431             424 :         CPLString osPathFirst = osPath.substr(0,iDot);
     432             424 :         CPLString osPathRest = osPath.substr(iDot+1);
     433             424 :         ERSHdrNode *poFirst = FindNode( osPathFirst );
     434                 :         
     435             424 :         if( poFirst == NULL )
     436                 :         {
     437              93 :             poFirst = new ERSHdrNode();
     438                 :             
     439              93 :             MakeSpace();
     440              93 :             papszItemName[nItemCount] = CPLStrdup(osPathFirst);
     441              93 :             papszItemValue[nItemCount] = NULL;
     442              93 :             papoItemChild[nItemCount] = poFirst;
     443              93 :             nItemCount++;
     444                 :         }
     445                 : 
     446             424 :         poFirst->Set( osPathRest, pszValue );
     447             424 :         return;
     448                 :     }
     449                 : 
     450                 : /* -------------------------------------------------------------------- */
     451                 : /*      This is the final item name.  Find or create it.                */
     452                 : /* -------------------------------------------------------------------- */
     453                 :     int i;
     454                 : 
     455             691 :     for( i = 0; i < nItemCount; i++ )
     456                 :     {
     457             411 :         if( EQUAL(osPath,papszItemName[i]) 
     458               5 :             && papszItemValue[i] != NULL )
     459                 :         {
     460               5 :             CPLFree( papszItemValue[i] );
     461               5 :             papszItemValue[i] = CPLStrdup( pszValue );
     462                 :             return;
     463                 :         }
     464                 :     }
     465                 : 
     466             285 :     MakeSpace();
     467             285 :     papszItemName[nItemCount] = CPLStrdup(osPath);
     468             285 :     papszItemValue[nItemCount] = CPLStrdup(pszValue);
     469             285 :     papoItemChild[nItemCount] = NULL;
     470             285 :     nItemCount++;
     471                 : }

Generated by: LCOV version 1.7