LCOV - code coverage report
Current view: directory - frmts/iso8211 - ddffielddefn.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 320 159 49.7 %
Date: 2011-12-18 Functions: 17 10 58.8 %

       1                 : /******************************************************************************
       2                 :  * $Id: ddffielddefn.cpp 12706 2007-11-10 22:11:39Z rouault $
       3                 :  *
       4                 :  * Project:  ISO 8211 Access
       5                 :  * Purpose:  Implements the DDFFieldDefn class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1999, Frank Warmerdam
      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 "iso8211.h"
      31                 : #include "cpl_string.h"
      32                 : #include <ctype.h>
      33                 : 
      34                 : CPL_CVSID("$Id: ddffielddefn.cpp 12706 2007-11-10 22:11:39Z rouault $");
      35                 : 
      36                 : #define CPLE_DiscardedFormat   1301
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                            DDFFieldDefn()                            */
      40                 : /************************************************************************/
      41                 : 
      42             552 : DDFFieldDefn::DDFFieldDefn()
      43                 : 
      44                 : {
      45             552 :     poModule = NULL;
      46             552 :     pszTag = NULL;
      47             552 :     _fieldName = NULL;
      48             552 :     _arrayDescr = NULL;
      49             552 :     _formatControls = NULL;
      50             552 :     nSubfieldCount = 0;
      51             552 :     papoSubfields = NULL;
      52             552 :     bRepeatingSubfields = FALSE;
      53             552 :     nFixedWidth = 0;
      54             552 : }
      55                 : 
      56                 : /************************************************************************/
      57                 : /*                           ~DDFFieldDefn()                            */
      58                 : /************************************************************************/
      59                 : 
      60             552 : DDFFieldDefn::~DDFFieldDefn()
      61                 : 
      62                 : {
      63                 :     int   i;
      64                 : 
      65             552 :     CPLFree( pszTag );
      66             552 :     CPLFree( _fieldName );
      67             552 :     CPLFree( _arrayDescr );
      68             552 :     CPLFree( _formatControls );
      69                 : 
      70            3214 :     for( i = 0; i < nSubfieldCount; i++ )
      71            2662 :         delete papoSubfields[i];
      72             552 :     CPLFree( papoSubfields );
      73             552 : }
      74                 : 
      75                 : /************************************************************************/
      76                 : /*                            AddSubfield()                             */
      77                 : /************************************************************************/
      78                 : 
      79               0 : void DDFFieldDefn::AddSubfield( const char *pszName, 
      80                 :                                 const char *pszFormat )
      81                 : 
      82                 : {
      83               0 :     DDFSubfieldDefn *poSFDefn = new DDFSubfieldDefn;
      84                 : 
      85               0 :     poSFDefn->SetName( pszName );
      86               0 :     poSFDefn->SetFormat( pszFormat );
      87               0 :     AddSubfield( poSFDefn );
      88               0 : }
      89                 : 
      90                 : /************************************************************************/
      91                 : /*                            AddSubfield()                             */
      92                 : /************************************************************************/
      93                 : 
      94            2662 : void DDFFieldDefn::AddSubfield( DDFSubfieldDefn *poNewSFDefn,
      95                 :                                 int bDontAddToFormat )
      96                 : 
      97                 : {
      98            2662 :     nSubfieldCount++;
      99                 :     papoSubfields = (DDFSubfieldDefn ** )
     100            2662 :         CPLRealloc( papoSubfields, sizeof(void*) * nSubfieldCount );
     101            2662 :     papoSubfields[nSubfieldCount-1] = poNewSFDefn;
     102                 :     
     103            2662 :     if( bDontAddToFormat )
     104            2662 :         return;
     105                 : 
     106                 : /* -------------------------------------------------------------------- */
     107                 : /*      Add this format to the format list.  We don't bother            */
     108                 : /*      aggregating formats here.                                       */
     109                 : /* -------------------------------------------------------------------- */
     110               0 :     if( _formatControls == NULL || strlen(_formatControls) == 0 )
     111                 :     {
     112               0 :         CPLFree( _formatControls );
     113               0 :         _formatControls = CPLStrdup( "()" );
     114                 :     }
     115                 :     
     116               0 :     int nOldLen = strlen(_formatControls);
     117                 :     
     118                 :     char *pszNewFormatControls = (char *) 
     119               0 :         CPLMalloc(nOldLen+3+strlen(poNewSFDefn->GetFormat()));
     120                 :     
     121               0 :     strcpy( pszNewFormatControls, _formatControls );
     122               0 :     pszNewFormatControls[nOldLen-1] = '\0';
     123               0 :     if( pszNewFormatControls[nOldLen-2] != '(' )
     124               0 :         strcat( pszNewFormatControls, "," );
     125                 :     
     126               0 :     strcat( pszNewFormatControls, poNewSFDefn->GetFormat() );
     127               0 :     strcat( pszNewFormatControls, ")" );
     128                 :     
     129               0 :     CPLFree( _formatControls );
     130               0 :     _formatControls = pszNewFormatControls;
     131                 : 
     132                 : /* -------------------------------------------------------------------- */
     133                 : /*      Add the subfield name to the list.                              */
     134                 : /* -------------------------------------------------------------------- */
     135               0 :     if( _arrayDescr == NULL )
     136               0 :         _arrayDescr = CPLStrdup("");
     137                 : 
     138                 :     _arrayDescr = (char *) 
     139                 :         CPLRealloc(_arrayDescr, 
     140               0 :                    strlen(_arrayDescr)+strlen(poNewSFDefn->GetName())+2);
     141               0 :     if( strlen(_arrayDescr) > 0 )
     142               0 :         strcat( _arrayDescr, "!" );
     143               0 :     strcat( _arrayDescr, poNewSFDefn->GetName() );
     144                 : }
     145                 : 
     146                 : /************************************************************************/
     147                 : /*                               Create()                               */
     148                 : /*                                                                      */
     149                 : /*      Initialize a new field defn from application input, instead     */
     150                 : /*      of from an existing file.                                       */
     151                 : /************************************************************************/
     152                 : 
     153               0 : int DDFFieldDefn::Create( const char *pszTag, const char *pszFieldName, 
     154                 :                           const char *pszDescription, 
     155                 :                           DDF_data_struct_code eDataStructCode,
     156                 :                           DDF_data_type_code   eDataTypeCode,
     157                 :                           const char *pszFormat )
     158                 : 
     159                 : {
     160               0 :     CPLAssert( this->pszTag == NULL );
     161               0 :     poModule = NULL;
     162               0 :     this->pszTag = CPLStrdup( pszTag );
     163               0 :     _fieldName = CPLStrdup( pszFieldName );
     164               0 :     _arrayDescr = CPLStrdup( pszDescription );
     165               0 :     _formatControls = CPLStrdup( "" );
     166                 :     
     167               0 :     _data_struct_code = eDataStructCode;
     168               0 :     _data_type_code = eDataTypeCode;
     169                 : 
     170               0 :     if( pszFormat != NULL )
     171               0 :         _formatControls = CPLStrdup( pszFormat );
     172                 : 
     173               0 :     if( pszDescription != NULL && *pszDescription == '*' )
     174               0 :         bRepeatingSubfields = TRUE;
     175                 : 
     176               0 :     return TRUE;
     177                 : }
     178                 : 
     179                 : /************************************************************************/
     180                 : /*                          GenerateDDREntry()                          */
     181                 : /************************************************************************/
     182                 : 
     183               0 : int DDFFieldDefn::GenerateDDREntry( char **ppachData, 
     184                 :                                     int *pnLength )
     185                 : 
     186                 : {
     187                 :     *pnLength = 9 + strlen(_fieldName) + 1 
     188                 :         + strlen(_arrayDescr) + 1
     189               0 :         + strlen(_formatControls) + 1;
     190                 : 
     191               0 :     if( strlen(_formatControls) == 0 )
     192               0 :         *pnLength -= 1;
     193                 : 
     194               0 :     if( ppachData == NULL )
     195               0 :         return TRUE;
     196                 : 
     197               0 :     *ppachData = (char *) CPLMalloc( *pnLength+1 );
     198                 :     
     199               0 :     if( _data_struct_code == dsc_elementary )
     200               0 :         (*ppachData)[0] = '0';
     201               0 :     else if( _data_struct_code == dsc_vector )
     202               0 :         (*ppachData)[0] = '1';
     203               0 :     else if( _data_struct_code == dsc_array )
     204               0 :         (*ppachData)[0] = '2';
     205               0 :     else if( _data_struct_code == dsc_concatenated )
     206               0 :         (*ppachData)[0] = '3';
     207                 :     
     208               0 :     if( _data_type_code == dtc_char_string )
     209               0 :         (*ppachData)[1] = '0';
     210               0 :     else if( _data_type_code == dtc_implicit_point )
     211               0 :         (*ppachData)[1] = '1';
     212               0 :     else if( _data_type_code == dtc_explicit_point )
     213               0 :         (*ppachData)[1] = '2';
     214               0 :     else if( _data_type_code == dtc_explicit_point_scaled )
     215               0 :         (*ppachData)[1] = '3';
     216               0 :     else if( _data_type_code == dtc_char_bit_string )
     217               0 :         (*ppachData)[1] = '4';
     218               0 :     else if( _data_type_code == dtc_bit_string )
     219               0 :         (*ppachData)[1] = '5';
     220               0 :     else if( _data_type_code == dtc_mixed_data_type )
     221               0 :         (*ppachData)[1] = '6';
     222                 : 
     223               0 :     (*ppachData)[2] = '0';
     224               0 :     (*ppachData)[3] = '0';
     225               0 :     (*ppachData)[4] = ';';
     226               0 :     (*ppachData)[5] = '&';
     227               0 :     (*ppachData)[6] = ' ';
     228               0 :     (*ppachData)[7] = ' ';
     229               0 :     (*ppachData)[8] = ' ';
     230                 :     sprintf( *ppachData + 9, "%s%c%s", 
     231               0 :              _fieldName, DDF_UNIT_TERMINATOR, _arrayDescr );
     232                 : 
     233               0 :     if( strlen(_formatControls) > 0 )
     234                 :         sprintf( *ppachData + strlen(*ppachData), "%c%s",
     235               0 :                  DDF_UNIT_TERMINATOR, _formatControls );
     236               0 :     sprintf( *ppachData + strlen(*ppachData), "%c", DDF_FIELD_TERMINATOR );
     237                 : 
     238               0 :     return TRUE;
     239                 : }
     240                 : 
     241                 : /************************************************************************/
     242                 : /*                             Initialize()                             */
     243                 : /*                                                                      */
     244                 : /*      Initialize the field definition from the information in the     */
     245                 : /*      DDR record.  This is called by DDFModule::Open().               */
     246                 : /************************************************************************/
     247                 : 
     248             552 : int DDFFieldDefn::Initialize( DDFModule * poModuleIn,
     249                 :                               const char * pszTagIn, 
     250                 :                               int nFieldEntrySize,
     251                 :                               const char * pachFieldArea )
     252                 : 
     253                 : {
     254             552 :     int         iFDOffset = poModuleIn->GetFieldControlLength();
     255                 :     int         nCharsConsumed;
     256                 : 
     257             552 :     poModule = poModuleIn;
     258                 :     
     259             552 :     pszTag = CPLStrdup( pszTagIn );
     260                 : 
     261                 : /* -------------------------------------------------------------------- */
     262                 : /*      Set the data struct and type codes.                             */
     263                 : /* -------------------------------------------------------------------- */
     264             552 :     switch( pachFieldArea[0] )
     265                 :     {
     266                 :       case ' ': /* for ADRG, DIGEST USRP, DIGEST ASRP files */
     267                 :       case '0':
     268             101 :         _data_struct_code = dsc_elementary;
     269             101 :         break;
     270                 : 
     271                 :       case '1':
     272             327 :         _data_struct_code = dsc_vector;
     273             327 :         break;
     274                 : 
     275                 :       case '2':
     276             124 :         _data_struct_code = dsc_array;
     277             124 :         break;
     278                 : 
     279                 :       case '3':
     280               0 :         _data_struct_code = dsc_concatenated;
     281               0 :         break;
     282                 : 
     283                 :       default:
     284                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     285                 :                   "Unrecognised data_struct_code value %c.\n"
     286                 :                   "Field %s initialization incorrect.",
     287               0 :                   pachFieldArea[0], pszTag );
     288               0 :         _data_struct_code = dsc_elementary;
     289                 :     }
     290                 : 
     291             552 :     switch( pachFieldArea[1] )
     292                 :     {
     293                 :       case ' ': /* for ADRG, DIGEST USRP, DIGEST ASRP files */
     294                 :       case '0':
     295             150 :         _data_type_code = dtc_char_string;
     296             150 :         break;
     297                 :         
     298                 :       case '1':
     299              85 :         _data_type_code = dtc_implicit_point;
     300              85 :         break;
     301                 :         
     302                 :       case '2':
     303               6 :         _data_type_code = dtc_explicit_point;
     304               6 :         break;
     305                 :         
     306                 :       case '3':
     307               0 :         _data_type_code = dtc_explicit_point_scaled;
     308               0 :         break;
     309                 :         
     310                 :       case '4':
     311               0 :         _data_type_code = dtc_char_bit_string;
     312               0 :         break;
     313                 :         
     314                 :       case '5':
     315              15 :         _data_type_code = dtc_bit_string;
     316              15 :         break;
     317                 :         
     318                 :       case '6':
     319             296 :         _data_type_code = dtc_mixed_data_type;
     320             296 :         break;
     321                 : 
     322                 :       default:
     323                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     324                 :                   "Unrecognised data_type_code value %c.\n"
     325                 :                   "Field %s initialization incorrect.",
     326               0 :                   pachFieldArea[1], pszTag );
     327               0 :         _data_type_code = dtc_char_string;
     328                 :     }
     329                 :     
     330                 : /* -------------------------------------------------------------------- */
     331                 : /*      Capture the field name, description (sub field names), and      */
     332                 : /*      format statements.                                              */
     333                 : /* -------------------------------------------------------------------- */
     334                 : 
     335                 :     _fieldName =
     336                 :         DDFFetchVariable( pachFieldArea + iFDOffset,
     337                 :                           nFieldEntrySize - iFDOffset,
     338                 :                           DDF_UNIT_TERMINATOR, DDF_FIELD_TERMINATOR,
     339             552 :                           &nCharsConsumed );
     340             552 :     iFDOffset += nCharsConsumed;
     341                 :     
     342                 :     _arrayDescr =
     343                 :         DDFFetchVariable( pachFieldArea + iFDOffset,
     344                 :                           nFieldEntrySize - iFDOffset,
     345                 :                           DDF_UNIT_TERMINATOR, DDF_FIELD_TERMINATOR, 
     346             552 :                           &nCharsConsumed );
     347             552 :     iFDOffset += nCharsConsumed;
     348                 :     
     349                 :     _formatControls =
     350                 :         DDFFetchVariable( pachFieldArea + iFDOffset,
     351                 :                           nFieldEntrySize - iFDOffset,
     352                 :                           DDF_UNIT_TERMINATOR, DDF_FIELD_TERMINATOR, 
     353             552 :                           &nCharsConsumed );
     354                 :     
     355                 : /* -------------------------------------------------------------------- */
     356                 : /*      Parse the subfield info.                                        */
     357                 : /* -------------------------------------------------------------------- */
     358             552 :     if( _data_struct_code != dsc_elementary )
     359                 :     {
     360             451 :         if( !BuildSubfields() )
     361               0 :             return FALSE;
     362                 : 
     363             451 :         if( !ApplyFormats() )
     364               0 :             return FALSE;
     365                 :     }
     366                 :     
     367             552 :     return TRUE;
     368                 : }
     369                 : 
     370                 : /************************************************************************/
     371                 : /*                                Dump()                                */
     372                 : /************************************************************************/
     373                 : 
     374                 : /**
     375                 :  * Write out field definition info to debugging file.
     376                 :  *
     377                 :  * A variety of information about this field definition, and all it's
     378                 :  * subfields is written to the give debugging file handle.
     379                 :  *
     380                 :  * @param fp The standard io file handle to write to.  ie. stderr
     381                 :  */
     382                 : 
     383               0 : void DDFFieldDefn::Dump( FILE * fp )
     384                 : 
     385                 : {
     386               0 :     const char  *pszValue = "";
     387                 :     
     388               0 :     fprintf( fp, "  DDFFieldDefn:\n" );
     389               0 :     fprintf( fp, "      Tag = `%s'\n", pszTag );
     390               0 :     fprintf( fp, "      _fieldName = `%s'\n", _fieldName );
     391               0 :     fprintf( fp, "      _arrayDescr = `%s'\n", _arrayDescr );
     392               0 :     fprintf( fp, "      _formatControls = `%s'\n", _formatControls );
     393                 : 
     394               0 :     switch( _data_struct_code )
     395                 :     {
     396                 :       case dsc_elementary:
     397               0 :         pszValue = "elementary";
     398               0 :         break;
     399                 :         
     400                 :       case dsc_vector:
     401               0 :         pszValue = "vector";
     402               0 :         break;
     403                 :         
     404                 :       case dsc_array:
     405               0 :         pszValue = "array";
     406               0 :         break;
     407                 :         
     408                 :       case dsc_concatenated:
     409               0 :         pszValue = "concatenated";
     410               0 :         break;
     411                 :         
     412                 :       default:
     413               0 :         CPLAssert( FALSE );
     414               0 :         pszValue = "(unknown)";
     415                 :     }
     416                 : 
     417               0 :     fprintf( fp, "      _data_struct_code = %s\n", pszValue );
     418                 : 
     419               0 :     switch( _data_type_code )
     420                 :     {
     421                 :       case dtc_char_string:
     422               0 :         pszValue = "char_string";
     423               0 :         break;
     424                 :         
     425                 :       case dtc_implicit_point:
     426               0 :         pszValue = "implicit_point";
     427               0 :         break;
     428                 :         
     429                 :       case dtc_explicit_point:
     430               0 :         pszValue = "explicit_point";
     431               0 :         break;
     432                 :         
     433                 :       case dtc_explicit_point_scaled:
     434               0 :         pszValue = "explicit_point_scaled";
     435               0 :         break;
     436                 :         
     437                 :       case dtc_char_bit_string:
     438               0 :         pszValue = "char_bit_string";
     439               0 :         break;
     440                 :         
     441                 :       case dtc_bit_string:
     442               0 :         pszValue = "bit_string";
     443               0 :         break;
     444                 :         
     445                 :       case dtc_mixed_data_type:
     446               0 :         pszValue = "mixed_data_type";
     447               0 :         break;
     448                 : 
     449                 :       default:
     450               0 :         CPLAssert( FALSE );
     451               0 :         pszValue = "(unknown)";
     452                 :         break;
     453                 :     }
     454                 :     
     455               0 :     fprintf( fp, "      _data_type_code = %s\n", pszValue );
     456                 : 
     457               0 :     for( int i = 0; i < nSubfieldCount; i++ )
     458               0 :         papoSubfields[i]->Dump( fp );
     459               0 : }
     460                 : 
     461                 : /************************************************************************/
     462                 : /*                           BuildSubfields()                           */
     463                 : /*                                                                      */
     464                 : /*      Based on the _arrayDescr build a set of subfields.              */
     465                 : /************************************************************************/
     466                 : 
     467             451 : int DDFFieldDefn::BuildSubfields()
     468                 : 
     469                 : {
     470                 :     char        **papszSubfieldNames;
     471             451 :     const char  *pszSublist = _arrayDescr;
     472                 : 
     473                 : /* -------------------------------------------------------------------- */
     474                 : /*      It is valid to define a field with _arrayDesc                   */
     475                 : /*      '*STPT!CTPT!ENPT*YCOO!XCOO' and formatControls '(2b24)'.        */
     476                 : /*      This basically indicates that there are 3 (YCOO,XCOO)           */
     477                 : /*      structures named STPT, CTPT and ENPT.  But we can't handle      */
     478                 : /*      such a case gracefully here, so we just ignore the              */
     479                 : /*      "structure names" and treat such a thing as a repeating         */
     480                 : /*      YCOO/XCOO array.  This occurs with the AR2D field of some       */
     481                 : /*      AML S-57 files for instance.                                    */
     482                 : /*                                                                      */
     483                 : /*      We accomplish this by ignoring everything before the last       */
     484                 : /*      '*' in the subfield list.                                       */
     485                 : /* -------------------------------------------------------------------- */
     486             451 :     if( strrchr(pszSublist, '*') != NULL )
     487             128 :         pszSublist = strrchr(pszSublist,'*');
     488                 : 
     489                 : /* -------------------------------------------------------------------- */
     490                 : /*      Strip off the repeating marker, when it occurs, but mark our    */
     491                 : /*      field as repeating.                                             */
     492                 : /* -------------------------------------------------------------------- */
     493             451 :     if( pszSublist[0] == '*' )
     494                 :     {
     495             128 :         bRepeatingSubfields = TRUE;
     496             128 :         pszSublist++;
     497                 :     }
     498                 : 
     499                 : /* -------------------------------------------------------------------- */
     500                 : /*      split list of fields .                                          */
     501                 : /* -------------------------------------------------------------------- */
     502                 :     papszSubfieldNames = CSLTokenizeStringComplex( pszSublist, "!",
     503             451 :                                                    FALSE, FALSE );
     504                 : 
     505                 : /* -------------------------------------------------------------------- */
     506                 : /*      minimally initialize the subfields.  More will be done later.   */
     507                 : /* -------------------------------------------------------------------- */
     508             451 :     int nSFCount = CSLCount( papszSubfieldNames );
     509            6226 :     for( int iSF = 0; iSF < nSFCount; iSF++ )
     510                 :     {
     511            2662 :         DDFSubfieldDefn *poSFDefn = new DDFSubfieldDefn;
     512                 :         
     513            2662 :         poSFDefn->SetName( papszSubfieldNames[iSF] );
     514            2662 :         AddSubfield( poSFDefn, TRUE );
     515                 :     }
     516                 : 
     517             451 :     CSLDestroy( papszSubfieldNames );
     518                 : 
     519             451 :     return TRUE;
     520                 : }
     521                 : 
     522                 : /************************************************************************/
     523                 : /*                          ExtractSubstring()                          */
     524                 : /*                                                                      */
     525                 : /*      Extract a substring terminated by a comma (or end of            */
     526                 : /*      string).  Commas in brackets are ignored as terminated with     */
     527                 : /*      bracket nesting understood gracefully.  If the returned         */
     528                 : /*      string would being and end with a bracket then strip off the    */
     529                 : /*      brackets.                                                       */
     530                 : /*                                                                      */
     531                 : /*      Given a string like "(A,3(B,C),D),X,Y)" return "A,3(B,C),D".    */
     532                 : /*      Give a string like "3A,2C" return "3A".                         */
     533                 : /************************************************************************/
     534                 : 
     535             829 : char *DDFFieldDefn::ExtractSubstring( const char * pszSrc )
     536                 : 
     537                 : {
     538             829 :     int         nBracket=0, i;
     539                 :     char        *pszReturn;
     540                 : 
     541           25696 :     for( i = 0;
     542           13613 :          pszSrc[i] != '\0' && (nBracket > 0 || pszSrc[i] != ',');
     543                 :          i++ )
     544                 :     {
     545           11254 :         if( pszSrc[i] == '(' )
     546            2113 :             nBracket++;
     547            9141 :         else if( pszSrc[i] == ')' )
     548            2113 :             nBracket--;
     549                 :     }
     550                 : 
     551             829 :     if( pszSrc[0] == '(' )
     552                 :     {
     553             452 :         pszReturn = CPLStrdup( pszSrc + 1 );
     554             452 :         pszReturn[i-2] = '\0';
     555                 :     }
     556                 :     else
     557                 :     {
     558             377 :         pszReturn = CPLStrdup( pszSrc  );
     559             377 :         pszReturn[i] = '\0';
     560                 :     }
     561                 : 
     562             829 :     return pszReturn;
     563                 : }
     564                 : 
     565                 : /************************************************************************/
     566                 : /*                            ExpandFormat()                            */
     567                 : /************************************************************************/
     568                 : 
     569            1280 : char *DDFFieldDefn::ExpandFormat( const char * pszSrc )
     570                 : 
     571                 : {
     572            1280 :     int         nDestMax = 32;
     573            1280 :     char       *pszDest = (char *) CPLMalloc(nDestMax+1);
     574                 :     int         iSrc, iDst;
     575            1280 :     int         nRepeat = 0;
     576                 : 
     577            1280 :     iSrc = 0;
     578            1280 :     iDst = 0;
     579            1280 :     pszDest[0] = '\0';
     580                 : 
     581           12091 :     while( pszSrc[iSrc] != '\0' )
     582                 :     {
     583                 :         /* This is presumably an extra level of brackets around some
     584                 :            binary stuff related to rescaning which we don't care to do
     585                 :            (see 6.4.3.3 of the standard.  We just strip off the extra
     586                 :            layer of brackets */
     587            9983 :         if( (iSrc == 0 || pszSrc[iSrc-1] == ',') && pszSrc[iSrc] == '(' )
     588                 :         {
     589             452 :             char       *pszContents = ExtractSubstring( pszSrc+iSrc );
     590             452 :             char       *pszExpandedContents = ExpandFormat( pszContents );
     591                 : 
     592             452 :             if( (int) (strlen(pszExpandedContents) + strlen(pszDest) + 1)
     593                 :                 > nDestMax )
     594                 :             {
     595              96 :                 nDestMax = 2 * (strlen(pszExpandedContents) + strlen(pszDest));
     596              96 :                 pszDest = (char *) CPLRealloc(pszDest,nDestMax+1);
     597                 :             }
     598                 : 
     599             452 :             strcat( pszDest, pszExpandedContents );
     600             452 :             iDst = strlen(pszDest);
     601                 :             
     602             452 :             iSrc = iSrc + strlen(pszContents) + 2;
     603                 : 
     604             452 :             CPLFree( pszContents );
     605             452 :             CPLFree( pszExpandedContents );
     606                 :         }
     607                 : 
     608                 :         /* this is a repeated subclause */
     609           11707 :         else if( (iSrc == 0 || pszSrc[iSrc-1] == ',')
     610            2251 :                  && isdigit(pszSrc[iSrc]) )
     611                 :         {
     612                 :             const char *pszNext;
     613             377 :             nRepeat = atoi(pszSrc+iSrc);
     614                 :             
     615                 :             // skip over repeat count.
     616             757 :             for( pszNext = pszSrc+iSrc; isdigit(*pszNext); pszNext++ )
     617             380 :                 iSrc++;
     618                 : 
     619             377 :             char       *pszContents = ExtractSubstring( pszNext );
     620             377 :             char       *pszExpandedContents = ExpandFormat( pszContents );
     621                 :                 
     622            1542 :             for( int i = 0; i < nRepeat; i++ )
     623                 :             {
     624            1165 :                 if( (int) (strlen(pszExpandedContents) + strlen(pszDest) + 1)
     625                 :                     > nDestMax )
     626                 :                 {
     627                 :                     nDestMax = 
     628              45 :                         2 * (strlen(pszExpandedContents) + strlen(pszDest));
     629              45 :                     pszDest = (char *) CPLRealloc(pszDest,nDestMax+1);
     630                 :                 }
     631                 : 
     632            1165 :                 strcat( pszDest, pszExpandedContents );
     633            1165 :                 if( i < nRepeat-1 )
     634             788 :                     strcat( pszDest, "," );
     635                 :             }
     636                 : 
     637             377 :             iDst = strlen(pszDest);
     638                 :             
     639             377 :             if( pszNext[0] == '(' )
     640               0 :                 iSrc = iSrc + strlen(pszContents) + 2;
     641                 :             else
     642             377 :                 iSrc = iSrc + strlen(pszContents);
     643                 : 
     644             377 :             CPLFree( pszContents );
     645             377 :             CPLFree( pszExpandedContents );
     646                 :         }
     647                 :         else
     648                 :         {
     649            8702 :             if( iDst+1 >= nDestMax )
     650                 :             {
     651             115 :                 nDestMax = 2 * iDst;
     652             115 :                 pszDest = (char *) CPLRealloc(pszDest,nDestMax);
     653                 :             }
     654                 : 
     655            8702 :             pszDest[iDst++] = pszSrc[iSrc++];
     656            8702 :             pszDest[iDst] = '\0';
     657                 :         }
     658                 :     }
     659                 : 
     660            1280 :     return pszDest;
     661                 : }
     662                 :                                  
     663                 : /************************************************************************/
     664                 : /*                            ApplyFormats()                            */
     665                 : /*                                                                      */
     666                 : /*      This method parses the format string partially, and then        */
     667                 : /*      applies a subfield format string to each subfield object.       */
     668                 : /*      It in turn does final parsing of the subfield formats.          */
     669                 : /************************************************************************/
     670                 : 
     671             451 : int DDFFieldDefn::ApplyFormats()
     672                 : 
     673                 : {
     674                 :     char        *pszFormatList;
     675                 :     char        **papszFormatItems;
     676                 :     
     677                 : /* -------------------------------------------------------------------- */
     678                 : /*      Verify that the format string is contained within brackets.     */
     679                 : /* -------------------------------------------------------------------- */
     680            1353 :     if( strlen(_formatControls) < 2
     681             451 :         || _formatControls[0] != '('
     682             451 :         || _formatControls[strlen(_formatControls)-1] != ')' )
     683                 :     {
     684                 :         CPLError( CE_Warning, CPLE_DiscardedFormat,
     685                 :                   "Format controls for `%s' field missing brackets:%s",
     686               0 :                   pszTag, _formatControls );
     687                 :         
     688               0 :         return FALSE;
     689                 :     }
     690                 : 
     691                 : /* -------------------------------------------------------------------- */
     692                 : /*      Duplicate the string, and strip off the brackets.               */
     693                 : /* -------------------------------------------------------------------- */
     694                 : 
     695             451 :     pszFormatList = ExpandFormat( _formatControls );
     696                 : 
     697                 : /* -------------------------------------------------------------------- */
     698                 : /*      Tokenize based on commas.                                       */
     699                 : /* -------------------------------------------------------------------- */
     700                 :     papszFormatItems =
     701             451 :         CSLTokenizeStringComplex(pszFormatList, ",", FALSE, FALSE );
     702                 : 
     703             451 :     CPLFree( pszFormatList );
     704                 : 
     705                 : /* -------------------------------------------------------------------- */
     706                 : /*      Apply the format items to subfields.                            */
     707                 : /* -------------------------------------------------------------------- */
     708                 :     int iFormatItem;
     709                 :     
     710            6226 :     for( iFormatItem = 0;
     711            3113 :          papszFormatItems[iFormatItem] != NULL;
     712                 :          iFormatItem++ )
     713                 :     {
     714                 :         const char      *pszPastPrefix;
     715                 : 
     716            2662 :         pszPastPrefix = papszFormatItems[iFormatItem];
     717            5324 :         while( *pszPastPrefix >= '0' && *pszPastPrefix <= '9' )
     718               0 :             pszPastPrefix++;
     719                 : 
     720                 :         ///////////////////////////////////////////////////////////////
     721                 :         // Did we get too many formats for the subfields created
     722                 :         // by names?  This may be legal by the 8211 specification, but
     723                 :         // isn't encountered in any formats we care about so we just
     724                 :         // blow.
     725                 :         
     726            2662 :         if( iFormatItem >= nSubfieldCount )
     727                 :         {
     728                 :             CPLError( CE_Warning, CPLE_DiscardedFormat,
     729                 :                       "Got more formats than subfields for field `%s'.",
     730               0 :                       pszTag );
     731               0 :             break;
     732                 :         }
     733                 :         
     734            2662 :         if( !papoSubfields[iFormatItem]->SetFormat(pszPastPrefix) )
     735               0 :             return FALSE;
     736                 :     }
     737                 : 
     738                 : /* -------------------------------------------------------------------- */
     739                 : /*      Verify that we got enough formats, cleanup and return.          */
     740                 : /* -------------------------------------------------------------------- */
     741             451 :     CSLDestroy( papszFormatItems );
     742                 : 
     743             451 :     if( iFormatItem < nSubfieldCount )
     744                 :     {
     745                 :         CPLError( CE_Warning, CPLE_DiscardedFormat,
     746                 :                   "Got less formats than subfields for field `%s'.",
     747               0 :                   pszTag );
     748               0 :         return FALSE;
     749                 :     }
     750                 : 
     751                 : /* -------------------------------------------------------------------- */
     752                 : /*      If all the fields are fixed width, then we are fixed width      */
     753                 : /*      too.  This is important for repeating fields.                   */
     754                 : /* -------------------------------------------------------------------- */
     755             451 :     nFixedWidth = 0;
     756            2789 :     for( int i = 0; i < nSubfieldCount; i++ )
     757                 :     {
     758            2407 :         if( papoSubfields[i]->GetWidth() == 0 )
     759                 :         {
     760              69 :             nFixedWidth = 0;
     761              69 :             break;
     762                 :         }
     763                 :         else
     764            2338 :             nFixedWidth += papoSubfields[i]->GetWidth();
     765                 :     }
     766                 : 
     767             451 :     return TRUE;
     768                 : }
     769                 : 
     770                 : /************************************************************************/
     771                 : /*                          FindSubfieldDefn()                          */
     772                 : /************************************************************************/
     773                 : 
     774                 : /**
     775                 :  * Find a subfield definition by it's mnemonic tag.  
     776                 :  *
     777                 :  * @param pszMnemonic The name of the field.
     778                 :  *
     779                 :  * @return The subfield pointer, or NULL if there isn't any such subfield.
     780                 :  */
     781                 :  
     782                 : 
     783           49651 : DDFSubfieldDefn *DDFFieldDefn::FindSubfieldDefn( const char * pszMnemonic )
     784                 : 
     785                 : {
     786          109836 :     for( int i = 0; i < nSubfieldCount; i++ )
     787                 :     {
     788          109836 :         if( EQUAL(papoSubfields[i]->GetName(),pszMnemonic) )
     789           49651 :             return papoSubfields[i];
     790                 :     }
     791                 : 
     792               0 :     return NULL;
     793                 : }
     794                 : 
     795                 : /************************************************************************/
     796                 : /*                            GetSubfield()                             */
     797                 : /*                                                                      */
     798                 : /*      Fetch a subfield by it's index.                                 */
     799                 : /************************************************************************/
     800                 : 
     801                 : /**
     802                 :  * Fetch a subfield by index.
     803                 :  *
     804                 :  * @param i The index subfield index. (Between 0 and GetSubfieldCount()-1)
     805                 :  *
     806                 :  * @return The subfield pointer, or NULL if the index is out of range.
     807                 :  */
     808                 : 
     809          140278 : DDFSubfieldDefn *DDFFieldDefn::GetSubfield( int i )
     810                 : 
     811                 : {
     812          140278 :     if( i < 0 || i >= nSubfieldCount )
     813                 :     {
     814               0 :         CPLAssert( FALSE );
     815               0 :         return NULL;
     816                 :     }
     817                 :              
     818          140278 :     return papoSubfields[i];
     819                 : }
     820                 : 
     821                 : /************************************************************************/
     822                 : /*                          GetDefaultValue()                           */
     823                 : /************************************************************************/
     824                 : 
     825                 : /**
     826                 :  * Return default data for field instance.
     827                 :  */
     828                 : 
     829               0 : char *DDFFieldDefn::GetDefaultValue( int *pnSize )
     830                 : 
     831                 : {                                                                       
     832                 : /* -------------------------------------------------------------------- */
     833                 : /*      Loop once collecting the sum of the subfield lengths.           */
     834                 : /* -------------------------------------------------------------------- */
     835                 :     int iSubfield;
     836               0 :     int nTotalSize = 0;
     837                 : 
     838               0 :     for( iSubfield = 0; iSubfield < nSubfieldCount; iSubfield++ )
     839                 :     {
     840                 :         int nSubfieldSize;
     841                 : 
     842               0 :         if( !papoSubfields[iSubfield]->GetDefaultValue( NULL, 0, 
     843                 :                                                         &nSubfieldSize ) )
     844               0 :             return NULL;
     845               0 :         nTotalSize += nSubfieldSize;
     846                 :     }
     847                 : 
     848                 : /* -------------------------------------------------------------------- */
     849                 : /*      Allocate buffer.                                                */
     850                 : /* -------------------------------------------------------------------- */
     851               0 :     char *pachData = (char *) CPLMalloc( nTotalSize );
     852                 : 
     853               0 :     if( pnSize != NULL )
     854               0 :         *pnSize = nTotalSize;
     855                 : 
     856                 : /* -------------------------------------------------------------------- */
     857                 : /*      Loop again, collecting actual default values.                   */
     858                 : /* -------------------------------------------------------------------- */
     859               0 :     int nOffset = 0;
     860               0 :     for( iSubfield = 0; iSubfield < nSubfieldCount; iSubfield++ )
     861                 :     {
     862                 :         int nSubfieldSize;
     863                 : 
     864               0 :         if( !papoSubfields[iSubfield]->GetDefaultValue( 
     865                 :                 pachData + nOffset, nTotalSize - nOffset, &nSubfieldSize ) )
     866                 :         {
     867               0 :             CPLAssert( FALSE );
     868               0 :             return NULL;
     869                 :         }
     870                 : 
     871               0 :         nOffset += nSubfieldSize;
     872                 :     }
     873                 : 
     874               0 :     CPLAssert( nOffset == nTotalSize );
     875                 : 
     876               0 :     return pachData;
     877                 : }

Generated by: LCOV version 1.7