LCOV - code coverage report
Current view: directory - frmts/envisat - EnvisatFile.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 459 204 44.4 %
Date: 2011-12-18 Functions: 25 12 48.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: EnvisatFile.c 22619 2011-06-29 20:54:01Z rouault $
       3                 :  *
       4                 :  * Project:  APP ENVISAT Support
       5                 :  * Purpose:  Low Level Envisat file access (read/write) API.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2001, Atlantis Scientific, Inc.
      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                 : #ifndef APP_BUILD
      31                 : #  define GDAL_BUILD
      32                 : #  include "cpl_conv.h"
      33                 : #  include "EnvisatFile.h"
      34                 : 
      35                 : CPL_CVSID("$Id: EnvisatFile.c 22619 2011-06-29 20:54:01Z rouault $");
      36                 : 
      37                 : #else
      38                 : #  include "APP/app.h"
      39                 : #  include "util/Files/EnvisatFile.h"
      40                 : #endif
      41                 : 
      42                 : typedef struct 
      43                 : {
      44                 :     char  *ds_name;
      45                 :     char  *ds_type;
      46                 :     char  *filename;
      47                 :     int   ds_offset;
      48                 :     int   ds_size;
      49                 :     int   num_dsr;
      50                 :     int   dsr_size;
      51                 : } EnvisatDatasetInfo;
      52                 : 
      53                 : typedef struct
      54                 : {
      55                 :     char  *key;
      56                 :     char  *value;
      57                 :     char  *units;
      58                 :     char  *literal_line;
      59                 :     int         value_offset;
      60                 : } EnvisatNameValue;
      61                 : 
      62                 : struct EnvisatFile_tag
      63                 : {
      64                 :     FILE  *fp;
      65                 :     char        *filename;
      66                 :     int   updatable;
      67                 :     int         header_dirty;
      68                 :     int   dsd_offset;
      69                 : 
      70                 :     int   mph_count;
      71                 :     EnvisatNameValue **mph_entries;
      72                 : 
      73                 :     int   sph_count;
      74                 :     EnvisatNameValue **sph_entries;
      75                 : 
      76                 :     int   ds_count;
      77                 :     EnvisatDatasetInfo **ds_info;
      78                 :     
      79                 : };
      80                 : 
      81                 : #ifdef GDAL_BUILD
      82                 : #  define SUCCESS 0
      83                 : #  define FAILURE 1
      84                 : #  define SendError( text )   CPLError( CE_Failure, CPLE_AppDefined, "%s", text )
      85                 : #endif
      86                 : 
      87                 : #define MPH_SIZE 1247
      88                 : 
      89                 : /*
      90                 :  * API For handling name/value lists.
      91                 :  */
      92                 : int S_NameValueList_Parse( const char *text, int text_offset, 
      93                 :                            int *entry_count, 
      94                 :                            EnvisatNameValue ***entries );
      95                 : void S_NameValueList_Destroy( int *entry_count, 
      96                 :                              EnvisatNameValue ***entries );
      97                 : int S_NameValueList_FindKey( const char *key,
      98                 :                              int entry_count, 
      99                 :                              EnvisatNameValue **entries );
     100                 : const char *S_NameValueList_FindValue( const char *key,
     101                 :                                        int entry_count, 
     102                 :                                        EnvisatNameValue **entries,
     103                 :                                        const char * default_value );
     104                 : 
     105                 : int S_NameValueList_Rewrite( FILE *fp, int entry_count, 
     106                 :                              EnvisatNameValue **entries );
     107                 : 
     108                 : EnvisatNameValue *
     109                 :     S_EnivsatFile_FindNameValue( EnvisatFile *self,
     110                 :                                  EnvisatFile_HeaderFlag mph_or_sph,
     111                 :                                  const char * key );
     112                 : 
     113                 : 
     114                 : 
     115                 : 
     116                 : /*-----------------------------------------------------------------------------
     117                 : 
     118                 : Name:
     119                 :     Envisat_SetupLevel0
     120                 : 
     121                 : Purpose:
     122                 :     Patch up missing information about SPH, and datasets for incomplete 
     123                 :     level 0 signal datasets.
     124                 : 
     125                 : Description:
     126                 : 
     127                 : Inputs:
     128                 :     self -- Envisat file handle.
     129                 : 
     130                 : Outputs:
     131                 : 
     132                 : Returns:
     133                 :     SUCCESS or FAILURE
     134                 : 
     135                 : -----------------------------------------------------------------------------*/
     136                 : 
     137               0 : static int EnvisatFile_SetupLevel0( EnvisatFile *self )
     138                 : 
     139                 : {
     140                 :     int file_length;
     141                 :     unsigned char header[68];
     142                 :     EnvisatDatasetInfo *ds_info;
     143                 : 
     144               0 :     self->dsd_offset = 0;
     145               0 :     self->ds_count = 1;
     146               0 :     self->ds_info = (EnvisatDatasetInfo **) 
     147               0 :         calloc(sizeof(EnvisatDatasetInfo*),self->ds_count);
     148                 : 
     149               0 :     if( self->ds_info == NULL )
     150               0 :         return FAILURE;
     151                 : 
     152                 :     /*
     153                 :      * Figure out how long the file is. 
     154                 :      */
     155                 : 
     156               0 :     fseek( self->fp, 0, SEEK_END );
     157               0 :     file_length = (int) ftell( self->fp );
     158                 :     
     159                 :     /* 
     160                 :      * Read the first record header, and verify the well known values.
     161                 :      */
     162               0 :     fseek( self->fp, 3203, SEEK_SET );
     163               0 :     fread( header, 68, 1, self->fp );
     164                 : 
     165               0 :     if( header[38] != 0 || header[39] != 0x1d
     166               0 :         || header[40] != 0 || header[41] != 0x54 )
     167                 :     {
     168               0 :         SendError( "Didn't get expected Data Field Header Length, or Mode ID\n"
     169                 :                    "values for the first data record." );
     170               0 :         return FAILURE;
     171                 :     }
     172                 : 
     173                 :     /* 
     174                 :      * Then build the dataset into structure from that. 
     175                 :      */
     176               0 :     ds_info = (EnvisatDatasetInfo *) calloc(sizeof(EnvisatDatasetInfo),1);
     177                 :     
     178               0 :     ds_info->ds_name = strdup( "ASAR SOURCE PACKETS         " );
     179               0 :     ds_info->ds_type = strdup( "M" );
     180               0 :     ds_info->filename = strdup( "                                                              " );
     181               0 :     ds_info->ds_offset = 3203;
     182               0 :     ds_info->dsr_size = -1;
     183               0 :     ds_info->num_dsr = 0;
     184               0 :     ds_info->ds_size = file_length - ds_info->ds_offset;
     185                 :     
     186               0 :     self->ds_info[0] = ds_info;
     187                 : 
     188               0 :     return SUCCESS;
     189                 : }
     190                 : 
     191                 : /*-----------------------------------------------------------------------------
     192                 : 
     193                 : Name:
     194                 :     Envisat_Open
     195                 : 
     196                 : Purpose:
     197                 :     Open an ENVISAT formatted file, and read all headers.
     198                 : 
     199                 : Description:
     200                 : 
     201                 : Inputs:
     202                 :     filename -- name of Envisat file.
     203                 :     mode -- either "r" for read access, or "r+" for read/write access.
     204                 : 
     205                 : Outputs:
     206                 :     self -- file handle, NULL on FAILURE.
     207                 : 
     208                 : Returns:
     209                 :     SUCCESS or FAILURE
     210                 : 
     211                 : -----------------------------------------------------------------------------*/
     212                 : 
     213              13 : int EnvisatFile_Open( EnvisatFile **self_ptr, 
     214                 :                       const char *filename, 
     215                 :                       const char *mode )
     216                 : 
     217                 : {
     218                 :     FILE  *fp;
     219                 :     EnvisatFile *self;
     220                 :     char  mph_data[1248];
     221                 :     char  *sph_data, *ds_data;
     222                 :     int   sph_size, num_dsd, dsd_size, i;
     223                 : 
     224              13 :     *self_ptr = NULL;
     225                 : 
     226                 :     /*
     227                 :      * Check for legal mode argument.  Force to be binary for correct
     228                 :      * operation on DOS file systems.
     229                 :      */
     230              13 :     if( strcmp(mode,"r") == 0 )
     231              13 :         mode = "rb";
     232               0 :     else if( strcmp(mode,"r+") == 0 )
     233               0 :         mode = "rb+";
     234                 :     else
     235                 :     {
     236               0 :         SendError( "Illegal mode value used in EnvisatFile_Open(), only "
     237                 :                    "\"r\" and \"r+\" are supported." );
     238               0 :         return FAILURE;
     239                 :     }
     240                 : 
     241                 :     /*
     242                 :      * Try to open the file, and report failure. 
     243                 :      */
     244                 : 
     245              13 :     fp = fopen( filename, mode );
     246                 : 
     247              13 :     if( fp == NULL )
     248                 :     {
     249                 :         char  error_buf[2048];
     250                 : 
     251               0 :         sprintf( error_buf, 
     252                 :                  "Unable to open file \"%s\" in EnvisatFile_Open().", 
     253                 :                  filename );
     254                 : 
     255               0 :         SendError( error_buf );
     256               0 :         return FAILURE;
     257                 :     }
     258                 : 
     259                 :     /*
     260                 :      * Create, and initialize the EnvisatFile structure. 
     261                 :      */
     262              13 :     self = (EnvisatFile *) calloc(sizeof(EnvisatFile),1);
     263              13 :     if( self == NULL )
     264               0 :         return FAILURE;
     265                 : 
     266              13 :     self->fp = fp;
     267              13 :     self->filename = strdup( filename );
     268              13 :     self->header_dirty = 0;
     269              13 :     self->updatable = (strcmp(mode,"rb+") == 0);
     270                 : 
     271                 :     /*
     272                 :      * Read the MPH, and process it as a group of name/value pairs. 
     273                 :      */
     274                 : 
     275              13 :     if( fread( mph_data, 1, MPH_SIZE, fp ) != MPH_SIZE )
     276                 :     {
     277               0 :         free( self );
     278               0 :         SendError( "fread() for mph failed." );
     279               0 :         return FAILURE;
     280                 :     }
     281                 : 
     282              13 :     mph_data[MPH_SIZE] = '\0';
     283              13 :     if( S_NameValueList_Parse( mph_data, 0, 
     284                 :                                &(self->mph_count), 
     285                 :                                &(self->mph_entries) ) == FAILURE )
     286               0 :         return FAILURE;
     287                 : 
     288                 :     /*
     289                 :      * Is this an incomplete level 0 file?
     290                 :      */
     291              13 :     if( EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", -1 ) == 0 
     292              13 :         && strncmp(EnvisatFile_GetKeyValueAsString( self, MPH, "PRODUCT", ""),
     293               0 :                    "ASA_IM__0P", 10) == 0 )
     294                 :     {
     295                 : 
     296               0 :         if( EnvisatFile_SetupLevel0( self ) == FAILURE )
     297                 :         {
     298               0 :             EnvisatFile_Close( self );
     299               0 :             return FAILURE;
     300                 :         }
     301                 :         else
     302                 :         {
     303               0 :             *self_ptr = self;
     304               0 :             return SUCCESS;
     305                 :         }
     306                 :     }
     307                 : 
     308                 :     /*
     309                 :      * Read the SPH, and process it as a group of name/value pairs.  
     310                 :      */
     311              13 :     sph_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", 0 );
     312                 : 
     313              13 :     if( sph_size == 0 )             
     314                 :     {
     315               0 :         SendError( "File does not appear to have SPH,"
     316                 :                    " SPH_SIZE not set, or zero." );
     317               0 :         return FAILURE;
     318                 :     }
     319                 : 
     320              13 :     sph_data = (char *) malloc(sph_size + 1 );
     321              13 :     if( sph_data == NULL )
     322               0 :         return FAILURE;
     323                 : 
     324              13 :     if( (int) fread( sph_data, 1, sph_size, fp ) != sph_size )
     325                 :     {
     326               0 :         free( self );
     327               0 :         SendError( "fread() for sph failed." );
     328               0 :         return FAILURE;
     329                 :     }
     330                 : 
     331              13 :     sph_data[sph_size] = '\0';
     332              13 :     ds_data = strstr(sph_data,"DS_NAME");
     333              13 :     if( ds_data != NULL )
     334                 :     {
     335              13 :         self->dsd_offset = (int) (ds_data - sph_data) + MPH_SIZE;
     336              13 :         *(ds_data-1) = '\0';
     337                 :     }
     338                 : 
     339              13 :     if( S_NameValueList_Parse( sph_data, MPH_SIZE,
     340                 :                                &(self->sph_count), 
     341                 :                                &(self->sph_entries) ) == FAILURE )
     342               0 :         return FAILURE;
     343                 : 
     344                 :     /*
     345                 :      * Parse the Dataset Definitions.
     346                 :      */
     347              13 :     num_dsd = EnvisatFile_GetKeyValueAsInt( self, MPH, "NUM_DSD", 0 );
     348              13 :     dsd_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "DSD_SIZE", 0 );
     349                 :     
     350              13 :     if( num_dsd > 0 && ds_data == NULL )
     351                 :     {
     352               0 :         SendError( "DSDs indicated in MPH, but not found in SPH." );
     353               0 :         return FAILURE;
     354                 :     }
     355                 : 
     356              13 :     self->ds_info = (EnvisatDatasetInfo **) 
     357                 :         calloc(sizeof(EnvisatDatasetInfo*),num_dsd);
     358              13 :     if( self->ds_info == NULL )
     359               0 :         return FAILURE;
     360                 : 
     361             373 :     for( i = 0; i < num_dsd; i++ )
     362                 :     {
     363             360 :         int dsdh_count = 0;
     364             360 :         EnvisatNameValue **dsdh_entries = NULL;
     365                 :         char  *dsd_data;
     366                 :         EnvisatDatasetInfo *ds_info;
     367                 : 
     368                 :         /*
     369                 :          * We parse each DSD grouping into a name/value list. 
     370                 :          */
     371             360 :         dsd_data = ds_data + i * dsd_size;
     372             360 :         dsd_data[dsd_size-1] = '\0';
     373                 :         
     374             360 :         if( S_NameValueList_Parse( dsd_data, 0, 
     375                 :                                    &dsdh_count, &dsdh_entries ) == FAILURE )
     376               0 :             return FAILURE;
     377                 : 
     378                 :         /* 
     379                 :          * Then build the dataset into structure from that. 
     380                 :          */
     381             360 :         ds_info = (EnvisatDatasetInfo *) calloc(sizeof(EnvisatDatasetInfo),1);
     382                 : 
     383             360 :         ds_info->ds_name = strdup( 
     384                 :             S_NameValueList_FindValue( "DS_NAME", 
     385                 :                                        dsdh_count, dsdh_entries, "" ));
     386             360 :         ds_info->ds_type = strdup( 
     387                 :             S_NameValueList_FindValue( "DS_TYPE", 
     388                 :                                        dsdh_count, dsdh_entries, "" ));
     389             360 :         ds_info->filename = strdup( 
     390                 :             S_NameValueList_FindValue( "FILENAME", 
     391                 :                                        dsdh_count, dsdh_entries, "" ));
     392             360 :         ds_info->ds_offset = atoi(
     393                 :             S_NameValueList_FindValue( "DS_OFFSET", 
     394                 :                                        dsdh_count, dsdh_entries, "0" ));
     395             360 :         ds_info->ds_size = atoi(
     396                 :             S_NameValueList_FindValue( "DS_SIZE", 
     397                 :                                        dsdh_count, dsdh_entries, "0" ));
     398             360 :         ds_info->num_dsr = atoi(
     399                 :             S_NameValueList_FindValue( "NUM_DSR", 
     400                 :                                        dsdh_count, dsdh_entries, "0" ));
     401             360 :         ds_info->dsr_size = atoi(
     402                 :             S_NameValueList_FindValue( "DSR_SIZE", 
     403                 :                                        dsdh_count, dsdh_entries, "0" ));
     404                 : 
     405             360 :         S_NameValueList_Destroy( &dsdh_count, &dsdh_entries );
     406                 : 
     407             360 :         self->ds_info[i] = ds_info;
     408             360 :         self->ds_count++;
     409                 :     }
     410                 :     
     411              13 :     free( sph_data );
     412                 : 
     413                 :     /*
     414                 :      * Return successfully.
     415                 :      */
     416              13 :     *self_ptr = self;
     417                 : 
     418              13 :     return SUCCESS;
     419                 : }
     420                 : 
     421                 : /*-----------------------------------------------------------------------------
     422                 : 
     423                 : Name:
     424                 :     EnvisatFile_Create
     425                 : 
     426                 : Purpose:
     427                 :     Create a new ENVISAT formatted file based on a template file.
     428                 : 
     429                 : Description:
     430                 : 
     431                 : Inputs:
     432                 :     filename -- name of Envisat file.
     433                 :     template_file -- name of envisat file header to utilize as template. 
     434                 : 
     435                 : Outputs:
     436                 :     self -- file handle, NULL on FAILURE.
     437                 : 
     438                 : Returns:
     439                 :     SUCCESS or FAILURE
     440                 : 
     441                 : -----------------------------------------------------------------------------*/
     442                 : 
     443               0 : int EnvisatFile_Create( EnvisatFile **self_ptr, 
     444                 :                         const char *filename, 
     445                 :                         const char *template_file )
     446                 : 
     447                 : {
     448                 :     int   template_size;
     449                 :     char  *template_data;
     450                 :     FILE  *fp;
     451                 : 
     452                 :     /*
     453                 :      * Try to open the template file, and read it into memory.
     454                 :      */
     455                 : 
     456               0 :     fp = fopen( template_file, "rb" );
     457                 : 
     458               0 :     if( fp == NULL )
     459                 :     {
     460                 :         char  error_buf[2048];
     461                 : 
     462               0 :         sprintf( error_buf, 
     463                 :                  "Unable to open file \"%s\" in EnvisatFile_Create().", 
     464                 :                  template_file );
     465                 : 
     466               0 :         SendError( error_buf );
     467               0 :         return FAILURE;
     468                 :     }
     469                 : 
     470               0 :     fseek( fp, 0, SEEK_END );
     471               0 :     template_size = (int) ftell( fp );
     472                 : 
     473               0 :     template_data = (char *) malloc(template_size);
     474                 :     
     475               0 :     fseek( fp, 0, SEEK_SET );
     476               0 :     fread( template_data, template_size, 1, fp );
     477               0 :     fclose( fp );
     478                 : 
     479                 :     /*
     480                 :      * Try to write the template out to the new filename. 
     481                 :      */
     482                 :     
     483               0 :     fp = fopen( filename, "wb" );
     484               0 :     if( fp == NULL )
     485                 :     {
     486                 :         char  error_buf[2048];
     487                 : 
     488               0 :         sprintf( error_buf, 
     489                 :                  "Unable to open file \"%s\" in EnvisatFile_Create().", 
     490                 :                  filename );
     491                 : 
     492               0 :         SendError( error_buf );
     493               0 :         return FAILURE;
     494                 :     }
     495                 : 
     496               0 :     fwrite( template_data, template_size, 1, fp );
     497               0 :     fclose( fp );
     498                 : 
     499               0 :     free( template_data );
     500                 : 
     501                 :     /*
     502                 :      * Now just open the file normally. 
     503                 :      */
     504                 :     
     505               0 :     return EnvisatFile_Open( self_ptr, filename, "r+" );
     506                 : }
     507                 : 
     508                 : /*-----------------------------------------------------------------------------
     509                 : 
     510                 : Name:
     511                 :     EnvisatFile_GetCurrentLength
     512                 : 
     513                 : Purpose:
     514                 :     Fetch the current file length.
     515                 : 
     516                 : Description:
     517                 :     The length is computed by scanning the dataset definitions, not the
     518                 :     physical file length.  
     519                 : 
     520                 : Inputs:
     521                 :     self -- the file to operate on. 
     522                 : 
     523                 : Outputs:
     524                 : 
     525                 : Returns:
     526                 :     Returns length or -1 on failure.
     527                 : 
     528                 : -----------------------------------------------------------------------------*/
     529                 : 
     530               0 : int EnvisatFile_GetCurrentLength( EnvisatFile *self )
     531                 : 
     532                 : {
     533                 :     int   length;
     534                 :     int   ds;
     535                 :     int   ds_offset;
     536                 :     int         ds_size;
     537                 : 
     538               0 :     length = MPH_SIZE 
     539                 :         + EnvisatFile_GetKeyValueAsInt( self, MPH, "SPH_SIZE", 0 );
     540                 : 
     541               0 :     for( ds = 0; 
     542               0 :          EnvisatFile_GetDatasetInfo( self, ds, NULL, NULL, NULL, 
     543                 :                                      &ds_offset, &ds_size, NULL, NULL )
     544                 :              != FAILURE; 
     545               0 :          ds++ )
     546                 :     {
     547               0 :         if( ds_offset != 0 && (ds_offset+ds_size) > length )
     548               0 :             length = ds_offset + ds_size;
     549                 :     }
     550                 : 
     551               0 :     return length;
     552                 : }
     553                 : 
     554                 : /*-----------------------------------------------------------------------------
     555                 : 
     556                 : Name:
     557                 :     EnvisatFile_RewriteHeader
     558                 : 
     559                 : Purpose:
     560                 :     Update the envisat file header on disk to match the in-memory image.
     561                 : 
     562                 : Description:
     563                 : 
     564                 : Inputs:
     565                 :     self -- handle for file to close.
     566                 : 
     567                 : Outputs:
     568                 : 
     569                 : Returns:
     570                 :     SUCCESS or FAILURE.
     571                 : 
     572                 : -----------------------------------------------------------------------------*/
     573                 : 
     574               0 : static int EnvisatFile_RewriteHeader( EnvisatFile *self )
     575                 : 
     576                 : {
     577                 :     int   dsd, dsd_size;
     578                 : 
     579                 :     /* 
     580                 :      * Rewrite MPH and SPH headers.
     581                 :      */
     582               0 :     if( S_NameValueList_Rewrite( self->fp, 
     583                 :                         self->mph_count, self->mph_entries ) == FAILURE )
     584               0 :         return FAILURE;
     585                 : 
     586               0 :     if( S_NameValueList_Rewrite( self->fp, 
     587                 :                         self->sph_count, self->sph_entries ) == FAILURE )
     588               0 :         return FAILURE;
     589                 : 
     590                 :     /*
     591                 :      * Rewrite DSDs.  We actually have to read each, and reparse to set
     592                 :      * the individual parameters properly.
     593                 :      */
     594               0 :     dsd_size = EnvisatFile_GetKeyValueAsInt( self, MPH, "DSD_SIZE", 0 );
     595               0 :     if( dsd_size == 0 )
     596               0 :         return FAILURE;
     597                 : 
     598               0 :     for( dsd = 0; dsd < self->ds_count; dsd++ )
     599                 :     {
     600                 :         char  *dsd_text;
     601               0 :         int dsdh_count = 0, key_index;
     602               0 :         EnvisatNameValue **dsdh_entries = NULL;
     603                 : 
     604               0 :         dsd_text = (char *) calloc(1,dsd_size+1);
     605               0 :         if( fseek( self->fp, self->dsd_offset + dsd * dsd_size, 
     606                 :                    SEEK_SET ) != 0 )
     607                 :         {
     608               0 :             SendError( "fseek() failed in EnvisatFile_RewriteHeader()" );
     609               0 :             return FAILURE;
     610                 :         }
     611                 :         
     612               0 :         if( (int) fread( dsd_text, 1, dsd_size, self->fp ) != dsd_size )
     613                 :         {
     614               0 :             SendError( "fread() failed in EnvisatFile_RewriteHeader()" );
     615               0 :             return FAILURE;
     616                 :         }
     617                 : 
     618               0 :         if( S_NameValueList_Parse( dsd_text, self->dsd_offset + dsd*dsd_size, 
     619                 :                                    &dsdh_count, &dsdh_entries ) == FAILURE )
     620               0 :             return FAILURE;
     621                 : 
     622               0 :         free( dsd_text );
     623                 : 
     624               0 :         key_index = S_NameValueList_FindKey( "DS_OFFSET", 
     625                 :                                              dsdh_count, dsdh_entries );
     626               0 :         if( key_index == -1 )
     627               0 :             continue;
     628                 : 
     629               0 :         sprintf( dsdh_entries[key_index]->value, "%+021d", 
     630               0 :                  self->ds_info[dsd]->ds_offset );
     631                 : 
     632               0 :         key_index = S_NameValueList_FindKey( "DS_SIZE", 
     633                 :                                              dsdh_count, dsdh_entries );
     634               0 :         sprintf( dsdh_entries[key_index]->value, "%+021d", 
     635               0 :                  self->ds_info[dsd]->ds_size );
     636                 : 
     637               0 :         key_index = S_NameValueList_FindKey( "NUM_DSR", 
     638                 :                                              dsdh_count, dsdh_entries );
     639               0 :         sprintf( dsdh_entries[key_index]->value, "%+011d", 
     640               0 :                  self->ds_info[dsd]->num_dsr );
     641                 : 
     642               0 :         key_index = S_NameValueList_FindKey( "DSR_SIZE", 
     643                 :                                              dsdh_count, dsdh_entries );
     644               0 :         sprintf( dsdh_entries[key_index]->value, "%+011d", 
     645               0 :                  self->ds_info[dsd]->dsr_size );
     646                 : 
     647               0 :         if( S_NameValueList_Rewrite( self->fp, dsdh_count, dsdh_entries )
     648                 :             == FAILURE )
     649               0 :             return FAILURE;
     650                 : 
     651               0 :         S_NameValueList_Destroy( &dsdh_count, &dsdh_entries );
     652                 :     }
     653                 : 
     654               0 :     self->header_dirty = 0;
     655                 : 
     656               0 :     return SUCCESS;
     657                 : }
     658                 : 
     659                 : /*-----------------------------------------------------------------------------
     660                 : 
     661                 : Name:
     662                 :     EnvisatFile_Close
     663                 : 
     664                 : Purpose:
     665                 :     Close an ENVISAT formatted file, releasing all associated resources.
     666                 : 
     667                 : Description:
     668                 : 
     669                 : Inputs:
     670                 :     self -- handle for file to close.
     671                 : 
     672                 : Outputs:
     673                 : 
     674                 : Returns:
     675                 : 
     676                 : 
     677                 : -----------------------------------------------------------------------------*/
     678                 : 
     679              13 : void EnvisatFile_Close( EnvisatFile *self )
     680                 : 
     681                 : {
     682                 :     int   i;
     683                 : 
     684                 :     /*
     685                 :      * Do we need to write out the header information?
     686                 :      */
     687              13 :     if( self->header_dirty )
     688               0 :         EnvisatFile_RewriteHeader( self );
     689                 : 
     690                 :     /*
     691                 :      * Close file. 
     692                 :      */
     693              13 :     if( self->fp != NULL )
     694              13 :         fclose( self->fp );
     695                 : 
     696                 :     /*
     697                 :      * Clean up data structures. 
     698                 :      */
     699              13 :     S_NameValueList_Destroy( &(self->mph_count), &(self->mph_entries) );
     700              13 :     S_NameValueList_Destroy( &(self->sph_count), &(self->sph_entries) );
     701                 : 
     702             373 :     for( i = 0; i < self->ds_count; i++ )
     703                 :     {
     704             360 :         if( self->ds_info != NULL && self->ds_info[i] != NULL )
     705                 :         {
     706             360 :             free( self->ds_info[i]->ds_name );
     707             360 :             free( self->ds_info[i]->ds_type );
     708             360 :             free( self->ds_info[i]->filename );
     709             360 :             free( self->ds_info[i] );
     710                 :         }
     711                 :     }
     712              13 :     if( self->ds_info != NULL )
     713              13 :         free( self->ds_info );
     714              13 :     if( self->filename != NULL )
     715              13 :         free( self->filename );
     716                 : 
     717              13 :     free( self );
     718              13 : }
     719                 : 
     720                 : /*-----------------------------------------------------------------------------
     721                 : 
     722                 : Name:
     723                 :     EnvisatFile_GetFilename
     724                 : 
     725                 : Purpose:
     726                 :     Fetch name of this Envisat file.
     727                 : 
     728                 : Description:
     729                 : 
     730                 : Inputs:
     731                 :     self -- handle for file to get name of.
     732                 : 
     733                 : Outputs:
     734                 : 
     735                 : Returns:
     736                 :     const pointer to internal copy of the filename.  Do not alter or free.
     737                 : 
     738                 : 
     739                 : -----------------------------------------------------------------------------*/
     740                 : 
     741               0 : const char *EnvisatFile_GetFilename( EnvisatFile *self )
     742                 : 
     743                 : {
     744               0 :     return self->filename;
     745                 : }
     746                 : 
     747                 : /*-----------------------------------------------------------------------------
     748                 : 
     749                 : Name:
     750                 :     EnvisatFile_GetKeyByIndex()
     751                 : 
     752                 : Purpose:
     753                 :     Fetch the key with the indicated index.
     754                 : 
     755                 : Description:
     756                 :     This function can be used to "discover" the set of available keys by
     757                 :     by scanning with index values starting at zero and ending when a NULL
     758                 :     is returned.
     759                 : 
     760                 : Inputs:
     761                 :     self -- the file to be searched.
     762                 :     mph_or_sph -- Either MPH or SPH depending on the header to be searched.
     763                 :     key_index -- key index, from zero to number of keys-1.
     764                 : 
     765                 : Outputs:
     766                 : 
     767                 : Returns:
     768                 :     pointer to key name or NULL on failure.
     769                 : 
     770                 : -----------------------------------------------------------------------------*/
     771                 : 
     772             926 : const char *EnvisatFile_GetKeyByIndex( EnvisatFile *self, 
     773                 :                                        EnvisatFile_HeaderFlag mph_or_sph,
     774                 :                                        int key_index )
     775                 : 
     776                 : {
     777                 :     int entry_count;
     778                 :     EnvisatNameValue **entries;
     779                 : 
     780                 :     /*
     781                 :      * Select source list. 
     782                 :      */
     783             926 :     if( mph_or_sph == MPH )
     784                 :     {
     785             455 :         entry_count = self->mph_count;
     786             455 :         entries = self->mph_entries;
     787                 :     }
     788                 :     else
     789                 :     {
     790             471 :         entry_count = self->sph_count;
     791             471 :         entries = self->sph_entries;
     792                 :     }
     793                 : 
     794             926 :     if( key_index < 0 || key_index >= entry_count )
     795              26 :         return NULL;
     796                 :     else
     797             900 :         return entries[key_index]->key;
     798                 : }
     799                 : 
     800                 : /*-----------------------------------------------------------------------------
     801                 : 
     802                 : Name:
     803                 :     EnvisatFile_GetKeyValueAsString()
     804                 : 
     805                 : Purpose:
     806                 :     Fetch the value associated with the indicated key as a string.
     807                 : 
     808                 : Description:
     809                 : 
     810                 : Inputs:
     811                 :     self -- the file to be searched.
     812                 :     mph_or_sph -- Either MPH or SPH depending on the header to be searched.
     813                 :     key -- the key (name) to be searched for.
     814                 :     default_value -- the value to return if the key is not found.
     815                 : 
     816                 : Outputs:
     817                 : 
     818                 : Returns:
     819                 :     pointer to value string, or default_value if not found.
     820                 : 
     821                 : -----------------------------------------------------------------------------*/
     822                 : 
     823             952 : const char *EnvisatFile_GetKeyValueAsString( EnvisatFile *self, 
     824                 :                                              EnvisatFile_HeaderFlag mph_or_sph,
     825                 :                                              const char *key,
     826                 :                                              const char *default_value )
     827                 : 
     828                 : {
     829                 :     int entry_count, key_index;
     830                 :     EnvisatNameValue **entries;
     831                 : 
     832                 :     /*
     833                 :      * Select source list. 
     834                 :      */
     835             952 :     if( mph_or_sph == MPH )
     836                 :     {
     837             468 :         entry_count = self->mph_count;
     838             468 :         entries = self->mph_entries;
     839                 :     }
     840                 :     else
     841                 :     {
     842             484 :         entry_count = self->sph_count;
     843             484 :         entries = self->sph_entries;
     844                 :     }
     845                 : 
     846                 :     /*
     847                 :      * Find and return the value.
     848                 :      */
     849             952 :     key_index = S_NameValueList_FindKey( key, entry_count, entries );
     850             952 :     if( key_index == -1 )
     851              14 :         return default_value;
     852                 :     else
     853             938 :         return entries[key_index]->value;
     854                 : }
     855                 : 
     856                 : /*-----------------------------------------------------------------------------
     857                 : 
     858                 : Name:
     859                 :     EnvisatFile_SetKeyValueAsString()
     860                 : 
     861                 : Purpose:
     862                 :     Set the value associated with the indicated key as a string.
     863                 : 
     864                 : Description:
     865                 : 
     866                 : Inputs:
     867                 :     self -- the file to be searched.
     868                 :     mph_or_sph -- Either MPH or SPH depending on the header to be searched.
     869                 :     key -- the key (name) to be searched for.
     870                 :     value -- the value to assign.
     871                 : 
     872                 : Outputs:
     873                 : 
     874                 : Returns:
     875                 :     SUCCESS or FAILURE.
     876                 : 
     877                 : -----------------------------------------------------------------------------*/
     878                 : 
     879               0 : int EnvisatFile_SetKeyValueAsString( EnvisatFile *self, 
     880                 :                                      EnvisatFile_HeaderFlag mph_or_sph,
     881                 :                                      const char *key,
     882                 :                                      const char *value )
     883                 : 
     884                 : {
     885                 :     int entry_count, key_index;
     886                 :     EnvisatNameValue **entries;
     887                 : 
     888               0 :     if( !self->updatable )
     889                 :     {
     890               0 :         SendError( "File not opened for update access." );
     891               0 :         return FAILURE;
     892                 :     }
     893                 : 
     894                 :     /*
     895                 :      * Select source list. 
     896                 :      */
     897               0 :     if( mph_or_sph == MPH )
     898                 :     {
     899               0 :         entry_count = self->mph_count;
     900               0 :         entries = self->mph_entries;
     901                 :     }
     902                 :     else
     903                 :     {
     904               0 :         entry_count = self->sph_count;
     905               0 :         entries = self->sph_entries;
     906                 :     }
     907                 : 
     908                 :     /*
     909                 :      * Find and return the value.
     910                 :      */
     911               0 :     key_index = S_NameValueList_FindKey( key, entry_count, entries );
     912               0 :     if( key_index == -1 )
     913                 :     {
     914                 :         char  error_buf[2048];
     915                 : 
     916               0 :         sprintf( error_buf, 
     917                 :                  "Unable to set header field \"%s\", field not found.", 
     918                 :                  key );
     919                 : 
     920               0 :         SendError( error_buf );
     921               0 :         return FAILURE;
     922                 :     }
     923                 : 
     924               0 :     self->header_dirty = 1;
     925               0 :     if( strlen(value) > strlen(entries[key_index]->value) )
     926                 :     {
     927               0 :         strncpy( entries[key_index]->value, value, 
     928               0 :                  strlen(entries[key_index]->value) );
     929                 :     }
     930                 :     else
     931                 :     {
     932               0 :         memset( entries[key_index]->value, ' ', 
     933               0 :                 strlen(entries[key_index]->value) );
     934               0 :         strncpy( entries[key_index]->value, value, strlen(value) );
     935                 :     }
     936                 : 
     937               0 :     return SUCCESS;
     938                 : }
     939                 : 
     940                 : /*-----------------------------------------------------------------------------
     941                 : 
     942                 : Name:
     943                 :     EnvisatFile_GetKeyValueAsInt()
     944                 : 
     945                 : Purpose:
     946                 :     Fetch the value associated with the indicated key as an integer.
     947                 : 
     948                 : Description:
     949                 : 
     950                 : Inputs:
     951                 :     self -- the file to be searched.
     952                 :     mph_or_sph -- Either MPH or SPH depending on the header to be searched.
     953                 :     key -- the key (name) to be searched for.
     954                 :     default_value -- the value to return if the key is not found.
     955                 : 
     956                 : Outputs:
     957                 : 
     958                 : Returns:
     959                 :     key value, or default_value if key not found.
     960                 : 
     961                 : -----------------------------------------------------------------------------*/
     962                 : 
     963              79 : int EnvisatFile_GetKeyValueAsInt( EnvisatFile *self, 
     964                 :                                   EnvisatFile_HeaderFlag mph_or_sph,
     965                 :                                   const char *key,
     966                 :                                   int default_value )
     967                 : 
     968                 : {
     969                 :     int entry_count, key_index;
     970                 :     EnvisatNameValue **entries;
     971                 : 
     972                 :     /*
     973                 :      * Select source list. 
     974                 :      */
     975              79 :     if( mph_or_sph == MPH )
     976                 :     {
     977              52 :         entry_count = self->mph_count;
     978              52 :         entries = self->mph_entries;
     979                 :     }
     980                 :     else
     981                 :     {
     982              27 :         entry_count = self->sph_count;
     983              27 :         entries = self->sph_entries;
     984                 :     }
     985                 : 
     986                 :     /*
     987                 :      * Find and return the value.
     988                 :      */
     989              79 :     key_index = S_NameValueList_FindKey( key, entry_count, entries );
     990              79 :     if( key_index == -1 )
     991               0 :         return default_value;
     992                 :     else
     993              79 :         return atoi(entries[key_index]->value);
     994                 : }
     995                 : 
     996                 : /*-----------------------------------------------------------------------------
     997                 : 
     998                 : Name:
     999                 :     EnvisatFile_SetKeyValueAsInt()
    1000                 : 
    1001                 : Purpose:
    1002                 :     Set the value associated with the indicated key as an integer.
    1003                 : 
    1004                 : Description:
    1005                 : 
    1006                 : Inputs:
    1007                 :     self -- the file to be searched.
    1008                 :     mph_or_sph -- Either MPH or SPH depending on the header to be searched.
    1009                 :     key -- the key (name) to be searched for.
    1010                 :     value -- the value to assign.
    1011                 : 
    1012                 : Outputs:
    1013                 : 
    1014                 : Returns:
    1015                 :     SUCCESS or FAILURE.
    1016                 : 
    1017                 : -----------------------------------------------------------------------------*/
    1018                 : 
    1019               0 : int EnvisatFile_SetKeyValueAsInt( EnvisatFile *self, 
    1020                 :                                   EnvisatFile_HeaderFlag mph_or_sph,
    1021                 :                                   const char *key,
    1022                 :                                   int value )
    1023                 : 
    1024                 : {
    1025                 :     char format[32], string_value[128];
    1026                 :     const char *prototype_value;
    1027                 : 
    1028                 : 
    1029               0 :     prototype_value = EnvisatFile_GetKeyValueAsString( self, mph_or_sph, key, NULL);
    1030               0 :     if( prototype_value == NULL )
    1031                 :     {
    1032                 :         char  error_buf[2048];
    1033                 : 
    1034               0 :         sprintf( error_buf, 
    1035                 :                  "Unable to set header field \"%s\", field not found.", 
    1036                 :                  key );
    1037                 : 
    1038               0 :         SendError( error_buf );
    1039               0 :         return FAILURE;
    1040                 :     }
    1041                 : 
    1042               0 :     sprintf( format, "%%+0%dd", (int) strlen(prototype_value) );
    1043               0 :     sprintf( string_value, format, value );
    1044                 : 
    1045               0 :     return EnvisatFile_SetKeyValueAsString( self, mph_or_sph, key, string_value );
    1046                 : }
    1047                 : 
    1048                 : /*-----------------------------------------------------------------------------
    1049                 : 
    1050                 : Name:
    1051                 :     EnvisatFile_GetKeyValueAsDouble()
    1052                 : 
    1053                 : Purpose:
    1054                 :     Fetch the value associated with the indicated key as a double.
    1055                 : 
    1056                 : Description:
    1057                 : 
    1058                 : Inputs:
    1059                 :     self -- the file to be searched.
    1060                 :     mph_or_sph -- Either MPH or SPH depending on the header to be searched.
    1061                 :     key -- the key (name) to be searched for.
    1062                 :     default_value -- the value to return if the key is not found.
    1063                 : 
    1064                 : Outputs:
    1065                 : 
    1066                 : Returns:
    1067                 :     key value, or default_value if key not found.
    1068                 : 
    1069                 : -----------------------------------------------------------------------------*/
    1070                 : 
    1071               0 : double EnvisatFile_GetKeyValueAsDouble( EnvisatFile *self, 
    1072                 :                                         EnvisatFile_HeaderFlag mph_or_sph,
    1073                 :                                         const char *key,
    1074                 :                                         double default_value )
    1075                 : 
    1076                 : {
    1077                 :     int entry_count, key_index;
    1078                 :     EnvisatNameValue **entries;
    1079                 : 
    1080                 :     /*
    1081                 :      * Select source list. 
    1082                 :      */
    1083               0 :     if( mph_or_sph == MPH )
    1084                 :     {
    1085               0 :         entry_count = self->mph_count;
    1086               0 :         entries = self->mph_entries;
    1087                 :     }
    1088                 :     else
    1089                 :     {
    1090               0 :         entry_count = self->sph_count;
    1091               0 :         entries = self->sph_entries;
    1092                 :     }
    1093                 : 
    1094                 :     /*
    1095                 :      * Find and return the value.
    1096                 :      */
    1097               0 :     key_index = S_NameValueList_FindKey( key, entry_count, entries );
    1098               0 :     if( key_index == -1 )
    1099               0 :         return default_value;
    1100                 :     else
    1101               0 :         return atof(entries[key_index]->value);
    1102                 : }
    1103                 : 
    1104                 : /*-----------------------------------------------------------------------------
    1105                 : 
    1106                 : Name:
    1107                 :     EnvisatFile_SetKeyValueAsDouble()
    1108                 : 
    1109                 : Purpose:
    1110                 :     Set the value associated with the indicated key as a double.
    1111                 : 
    1112                 : Description:
    1113                 :     Note that this function attempts to format the new value similarly to
    1114                 :     the previous value.  In some cases (expecially exponential values) this 
    1115                 :     may not work out well.  In case of problems the caller is encourage to
    1116                 :     format the value themselves, and use the EnvisatFile_SetKeyValueAsString
    1117                 :     function, but taking extreme care about the string length.
    1118                 : 
    1119                 : Inputs:
    1120                 :     self -- the file to be searched.
    1121                 :     mph_or_sph -- Either MPH or SPH depending on the header to be searched.
    1122                 :     key -- the key (name) to be searched for.
    1123                 :     value -- the value to assign.
    1124                 : 
    1125                 : Outputs:
    1126                 : 
    1127                 : Returns:
    1128                 :     SUCCESS or FAILURE.
    1129                 : 
    1130                 : -----------------------------------------------------------------------------*/
    1131                 : 
    1132               0 : int EnvisatFile_SetKeyValueAsDouble( EnvisatFile *self, 
    1133                 :                                      EnvisatFile_HeaderFlag mph_or_sph,
    1134                 :                                      const char *key,
    1135                 :                                      double value )
    1136                 : 
    1137                 : {
    1138                 :     char format[32], string_value[128];
    1139                 :     const char *prototype_value;
    1140                 :     int   length;
    1141                 : 
    1142               0 :     prototype_value = EnvisatFile_GetKeyValueAsString( self, mph_or_sph, key, NULL);
    1143               0 :     if( prototype_value == NULL )
    1144                 :     {
    1145                 :         char  error_buf[2048];
    1146                 : 
    1147               0 :         sprintf( error_buf, 
    1148                 :                  "Unable to set header field \"%s\", field not found.", 
    1149                 :                  key );
    1150                 : 
    1151               0 :         SendError( error_buf );
    1152               0 :         return FAILURE;
    1153                 :     }
    1154                 : 
    1155               0 :     length = strlen(prototype_value);
    1156               0 :     if( prototype_value[length-4] == 'E' )
    1157                 :     {
    1158               0 :         sprintf( format, "%%+%dE", length-4 );
    1159               0 :         sprintf( string_value, format, value );
    1160                 :     }
    1161                 :     else
    1162                 :     {
    1163               0 :         int decimals = 0, i;
    1164               0 :         for( i = length-1; i > 0; i-- )
    1165                 :         {
    1166               0 :             if( prototype_value[i] == '.' )
    1167               0 :                 break;
    1168                 :             
    1169               0 :             decimals++;
    1170                 :         }
    1171                 : 
    1172               0 :         sprintf( format, "%%+0%d.%df", length, decimals );
    1173               0 :         sprintf( string_value, format, value );
    1174                 : 
    1175               0 :         if( (int)strlen(string_value) > length )
    1176               0 :             string_value[length] = '\0';
    1177                 :     }
    1178                 : 
    1179               0 :     return EnvisatFile_SetKeyValueAsString( self, mph_or_sph, key, string_value );
    1180                 : }
    1181                 : 
    1182                 : /*-----------------------------------------------------------------------------
    1183                 : 
    1184                 : Name:
    1185                 :     EnvisatFile_GetDatasetIndex()
    1186                 : 
    1187                 : Purpose:
    1188                 :     Fetch the datasat index give a dataset name.
    1189                 : 
    1190                 : Description:
    1191                 :     The provided name is extended with spaces, so it isn't necessary for the
    1192                 :     application to pass all the passing spaces.
    1193                 : 
    1194                 : Inputs:
    1195                 :     self -- the file to be searched.
    1196                 :     ds_name -- the name (DS_NAME) of the dataset to find.
    1197                 : 
    1198                 : Outputs:
    1199                 : 
    1200                 : Returns:
    1201                 :     Dataset index that matches, or -1 if none found.
    1202                 : 
    1203                 : -----------------------------------------------------------------------------*/
    1204                 : 
    1205              13 : int EnvisatFile_GetDatasetIndex( EnvisatFile *self, const char *ds_name )
    1206                 : 
    1207                 : {
    1208                 :     int   i;
    1209                 :     char  padded_ds_name[100];
    1210                 : 
    1211                 :     /* 
    1212                 :      * Padd the name.  While the normal product spec says the DS_NAME will
    1213                 :      * be 28 characters, I try to pad more than this incase the specification
    1214                 :      * is changed. 
    1215                 :      */
    1216              13 :     strncpy( padded_ds_name, ds_name, sizeof(padded_ds_name) );
    1217              13 :     padded_ds_name[sizeof(padded_ds_name)-1] = 0;
    1218            1082 :     for( i = strlen(padded_ds_name); i < sizeof(padded_ds_name)-1; i++ )
    1219                 :     {
    1220            1069 :         padded_ds_name[i] = ' ';
    1221                 :     }
    1222              13 :     padded_ds_name[i] = '\0';
    1223                 : 
    1224                 :     /* 
    1225                 :      * Compare only for the full length of DS_NAME we have saved.
    1226                 :      */
    1227              75 :     for( i = 0; i < self->ds_count; i++ )
    1228                 :     {
    1229              75 :         if( strncmp( padded_ds_name, self->ds_info[i]->ds_name, 
    1230              75 :                      strlen(self->ds_info[i]->ds_name) ) == 0 )
    1231                 :         {
    1232              13 :             return i;
    1233                 :         }
    1234                 :     }
    1235                 : 
    1236               0 :     return -1;
    1237                 : }
    1238                 : 
    1239                 : /*-----------------------------------------------------------------------------
    1240                 : 
    1241                 : Name:
    1242                 :     EnvisatFile_GetDatasetInfo()
    1243                 : 
    1244                 : Purpose:
    1245                 :     Fetch the information associated with a dataset definition.
    1246                 : 
    1247                 : Description:
    1248                 :     The returned strings are pointers to internal copies, and should not be
    1249                 :     modified, or freed.  Note, any of the "output" parameters can safely be
    1250                 :     NULL if it is not needed.
    1251                 : 
    1252                 : Inputs:
    1253                 :     self -- the file to be searched.
    1254                 :     ds_index -- the dataset index to fetch
    1255                 : 
    1256                 : Outputs:
    1257                 :     ds_name -- the dataset symbolic name, ie 'MDS1 SQ ADS              '.
    1258                 :     ds_type -- the dataset type, ie. 'A', not sure of valid values.
    1259                 :     filename -- dataset filename, normally spaces, or 'NOT USED          '.
    1260                 :     ds_offset -- the byte offset in the whole file to the first byte of 
    1261                 :                  dataset data.  This is 0 for unused datasets.
    1262                 :     ds_size -- the size, in bytes, of the whole dataset.
    1263                 :     num_dsr -- the number of records in the dataset.
    1264                 :     dsr_size -- the size of one record in the dataset in bytes, -1 if
    1265                 :                 records are variable sized.
    1266                 : 
    1267                 : Returns:
    1268                 :     SUCCESS if dataset exists, or FAILURE if ds_index is out of range.
    1269                 : 
    1270                 : -----------------------------------------------------------------------------*/
    1271                 : 
    1272            1239 : int EnvisatFile_GetDatasetInfo( EnvisatFile *self, 
    1273                 :                                 int ds_index, 
    1274                 :                                 char **ds_name, 
    1275                 :                                 char **ds_type,
    1276                 :                                 char **filename,
    1277                 :                                 int  *ds_offset,
    1278                 :                                 int  *ds_size,
    1279                 :                                 int  *num_dsr,
    1280                 :                                 int  *dsr_size )
    1281                 : 
    1282                 : {
    1283            1239 :     if( ds_index < 0 || ds_index >= self->ds_count )
    1284              39 :         return FAILURE;
    1285                 : 
    1286            1200 :     if( ds_name != NULL )
    1287            1080 :         *ds_name = self->ds_info[ds_index]->ds_name;
    1288            1200 :     if( ds_type != NULL )
    1289             454 :         *ds_type = self->ds_info[ds_index]->ds_type;
    1290            1200 :     if( filename != NULL )
    1291             720 :         *filename = self->ds_info[ds_index]->filename;
    1292            1200 :     if( ds_offset != NULL )
    1293             467 :         *ds_offset = self->ds_info[ds_index]->ds_offset;
    1294            1200 :     if( ds_size != NULL )
    1295               0 :         *ds_size = self->ds_info[ds_index]->ds_size;
    1296            1200 :     if( num_dsr != NULL )
    1297             840 :         *num_dsr = self->ds_info[ds_index]->num_dsr;
    1298            1200 :     if( dsr_size != NULL )
    1299             840 :         *dsr_size = self->ds_info[ds_index]->dsr_size;
    1300                 : 
    1301            1200 :     return SUCCESS;
    1302                 : }
    1303                 : 
    1304                 : /*-----------------------------------------------------------------------------
    1305                 : 
    1306                 : Name:
    1307                 :     EnvisatFile_SetDatasetInfo()
    1308                 : 
    1309                 : Purpose:
    1310                 :     Update the information associated with a dataset definition.
    1311                 : 
    1312                 : Description:
    1313                 : 
    1314                 : Inputs:
    1315                 :     self -- the file to be searched.
    1316                 :     ds_index -- the dataset index to fetch
    1317                 :     ds_offset -- the byte offset in the whole file to the first byte of 
    1318                 :                  dataset data.  This is 0 for unused datasets.
    1319                 :     ds_size -- the size, in bytes, of the whole dataset.
    1320                 :     num_dsr -- the number of records in the dataset.
    1321                 :     dsr_size -- the size of one record in the dataset in bytes, -1 if
    1322                 :                 records are variable sized.
    1323                 : 
    1324                 : Outputs:
    1325                 : 
    1326                 : Returns:
    1327                 :     SUCCESS or FAILURE.
    1328                 : 
    1329                 : -----------------------------------------------------------------------------*/
    1330                 : 
    1331               0 : int EnvisatFile_SetDatasetInfo( EnvisatFile *self, 
    1332                 :                                 int ds_index, 
    1333                 :                                 int ds_offset,
    1334                 :                                 int ds_size,
    1335                 :                                 int num_dsr,
    1336                 :                                 int dsr_size )
    1337                 : 
    1338                 : {
    1339               0 :     if( ds_index < 0 || ds_index >= self->ds_count )
    1340               0 :         return FAILURE;
    1341                 : 
    1342               0 :     self->ds_info[ds_index]->ds_offset = ds_offset;
    1343               0 :     self->ds_info[ds_index]->ds_size = ds_size;
    1344               0 :     self->ds_info[ds_index]->num_dsr = num_dsr;
    1345               0 :     self->ds_info[ds_index]->dsr_size = dsr_size;
    1346               0 :     self->header_dirty = 1;
    1347                 : 
    1348               0 :     return SUCCESS;
    1349                 : }
    1350                 : 
    1351                 : 
    1352                 : /*-----------------------------------------------------------------------------
    1353                 : 
    1354                 : Name:
    1355                 :     EnvisatFile_ReadDatasetChunk()
    1356                 : 
    1357                 : Purpose:
    1358                 :     Read an arbitrary chunk of a dataset.
    1359                 : 
    1360                 : Description:
    1361                 :     Note that no range checking is made on offset and size, and data may be
    1362                 :     read from outside the dataset if they are inappropriate.
    1363                 : 
    1364                 : Inputs:
    1365                 :     self -- the file to be searched.
    1366                 :     ds_index -- the index of dataset to access.
    1367                 :     offset -- byte offset within database to read.
    1368                 :     size -- size of buffer to fill in bytes.
    1369                 :     buffer -- buffer to load data into
    1370                 : 
    1371                 : Outputs:
    1372                 :     buffer is updated on SUCCESS.
    1373                 : 
    1374                 : Returns:
    1375                 :     SUCCESS or FAILURE
    1376                 : 
    1377                 : -----------------------------------------------------------------------------*/
    1378                 : 
    1379               0 : int EnvisatFile_ReadDatasetChunk( EnvisatFile *self, 
    1380                 :                                   int ds_index,
    1381                 :                                   int offset,
    1382                 :                                   int size,
    1383                 :                                   void * buffer )
    1384                 : 
    1385                 : {
    1386               0 :     if( ds_index < 0 || ds_index >= self->ds_count )
    1387                 :     {
    1388               0 :         SendError( "Attempt to read non-existant dataset in "
    1389                 :                    "EnvisatFile_ReadDatasetChunk()" );
    1390               0 :         return FAILURE;
    1391                 :     }
    1392                 : 
    1393               0 :     if( offset < 0 
    1394               0 :         || offset + size > self->ds_info[ds_index]->ds_size )
    1395                 :     {
    1396               0 :         SendError( "Attempt to read beyond end of dataset in "
    1397                 :                    "EnvisatFile_ReadDatasetChunk()" );
    1398               0 :         return FAILURE;
    1399                 :     }
    1400                 : 
    1401               0 :     if( fseek( self->fp, self->ds_info[ds_index]->ds_offset+offset, SEEK_SET )
    1402                 :         != 0 )
    1403                 :     {
    1404               0 :         SendError( "seek failed in EnvisatFile_ReadChunk()" );
    1405               0 :         return FAILURE;
    1406                 :     }
    1407                 : 
    1408               0 :     if( (int) fread( buffer, 1, size, self->fp ) != size )
    1409                 :     {
    1410               0 :         SendError( "read failed in EnvisatFile_ReadChunk()" );
    1411               0 :         return FAILURE;
    1412                 :     }
    1413                 : 
    1414               0 :     return SUCCESS;
    1415                 : }
    1416                 : 
    1417                 : /*-----------------------------------------------------------------------------
    1418                 : 
    1419                 : Name:
    1420                 :     EnvisatFile_WriteDatasetRecord()
    1421                 : 
    1422                 : Purpose:
    1423                 :     Write an arbitrary dataset record.
    1424                 : 
    1425                 : Description:
    1426                 :     Note that no range checking is made on offset and size, and data may be
    1427                 :     read from outside the dataset if they are inappropriate.
    1428                 : 
    1429                 : Inputs:
    1430                 :     self -- the file to be searched.
    1431                 :     ds_index -- the index of dataset to access.
    1432                 :     record_index -- the record to write.
    1433                 :     record_buffer -- buffer to load data into
    1434                 : 
    1435                 : Outputs:
    1436                 : 
    1437                 : Returns:
    1438                 :     SUCCESS or FAILURE
    1439                 : 
    1440                 : -----------------------------------------------------------------------------*/
    1441                 : 
    1442               0 : int EnvisatFile_WriteDatasetRecord( EnvisatFile *self, 
    1443                 :                                     int ds_index,
    1444                 :                                     int record_index,
    1445                 :                                     void *buffer )
    1446                 : 
    1447                 : {
    1448                 :     int   absolute_offset;
    1449                 :     int         result;
    1450                 : 
    1451               0 :     if( ds_index < 0 || ds_index >= self->ds_count )
    1452                 :     {
    1453               0 :         SendError( "Attempt to write non-existant dataset in "
    1454                 :                    "EnvisatFile_WriteDatasetRecord()" );
    1455               0 :         return FAILURE;
    1456                 :     }
    1457                 : 
    1458               0 :     if( record_index < 0
    1459               0 :         || record_index >=  self->ds_info[ds_index]->num_dsr )
    1460                 :     {
    1461               0 :         SendError( "Attempt to write beyond end of dataset in "
    1462                 :                    "EnvisatFile_WriteDatasetRecord()" );
    1463               0 :         return FAILURE;
    1464                 :     }
    1465                 : 
    1466               0 :     absolute_offset = self->ds_info[ds_index]->ds_offset
    1467               0 :         + record_index * self->ds_info[ds_index]->dsr_size;
    1468                 : 
    1469               0 :     if( fseek( self->fp, absolute_offset, SEEK_SET ) != 0 )
    1470                 :     {
    1471               0 :         SendError( "seek failed in EnvisatFile_WriteDatasetRecord()" );
    1472               0 :         return FAILURE;
    1473                 :     }
    1474                 : 
    1475               0 :     result = fwrite( buffer, 1, self->ds_info[ds_index]->dsr_size, self->fp );
    1476               0 :     if( result != self->ds_info[ds_index]->dsr_size )
    1477                 :     {
    1478               0 :         SendError( "write failed in EnvisatFile_WriteDatasetRecord()" );
    1479               0 :         return FAILURE;
    1480                 :     }
    1481                 : 
    1482               0 :     return SUCCESS;
    1483                 : }
    1484                 : 
    1485                 : /*-----------------------------------------------------------------------------
    1486                 : 
    1487                 : Name:
    1488                 :     EnvisatFile_ReadDatasetRecord()
    1489                 : 
    1490                 : Purpose:
    1491                 :     Read an arbitrary dataset record.
    1492                 : 
    1493                 : Description:
    1494                 :     Note that no range checking is made on offset and size, and data may be
    1495                 :     read from outside the dataset if they are inappropriate.
    1496                 : 
    1497                 : Inputs:
    1498                 :     self -- the file to be searched.
    1499                 :     ds_index -- the index of dataset to access.
    1500                 :     record_index -- the record to write.
    1501                 :     record_buffer -- buffer to load data into
    1502                 : 
    1503                 : Outputs:
    1504                 : 
    1505                 : Returns:
    1506                 :     SUCCESS or FAILURE
    1507                 : 
    1508                 : -----------------------------------------------------------------------------*/
    1509                 : 
    1510             622 : int EnvisatFile_ReadDatasetRecord( EnvisatFile *self, 
    1511                 :                                     int ds_index,
    1512                 :                                     int record_index,
    1513                 :                                     void *buffer )
    1514                 : 
    1515                 : {
    1516                 :     int   absolute_offset;
    1517                 :     int         result;
    1518                 : 
    1519             622 :     if( ds_index < 0 || ds_index >= self->ds_count )
    1520                 :     {
    1521               0 :         SendError( "Attempt to write non-existant dataset in "
    1522                 :                    "EnvisatFile_WriteDatasetRecord()" );
    1523               0 :         return FAILURE;
    1524                 :     }
    1525                 : 
    1526            1244 :     if( record_index < 0
    1527             622 :         || record_index >=  self->ds_info[ds_index]->num_dsr )
    1528                 :     {
    1529               0 :         SendError( "Attempt to write beyond end of dataset in "
    1530                 :                    "EnvisatFile_WriteDatasetRecord()" );
    1531               0 :         return FAILURE;
    1532                 :     }
    1533                 : 
    1534            1244 :     absolute_offset = self->ds_info[ds_index]->ds_offset
    1535             622 :         + record_index * self->ds_info[ds_index]->dsr_size;
    1536                 : 
    1537             622 :     if( fseek( self->fp, absolute_offset, SEEK_SET ) != 0 )
    1538                 :     {
    1539               0 :         SendError( "seek failed in EnvisatFile_WriteDatasetRecord()" );
    1540               0 :         return FAILURE;
    1541                 :     }
    1542                 : 
    1543             622 :     result = fread( buffer, 1, self->ds_info[ds_index]->dsr_size, self->fp );
    1544             622 :     if( result != self->ds_info[ds_index]->dsr_size )
    1545                 :     {
    1546               0 :         SendError( "read failed in EnvisatFile_ReadDatasetRecord()" );
    1547               0 :         return FAILURE;
    1548                 :     }
    1549                 : 
    1550             622 :     return SUCCESS;
    1551                 : }
    1552                 : 
    1553                 : /*-----------------------------------------------------------------------------
    1554                 : 
    1555                 : Name:
    1556                 :     S_NameValueList_FindKey()
    1557                 : 
    1558                 : Purpose:
    1559                 :     Search for given key in list of name/value pairs. 
    1560                 : 
    1561                 : Description:
    1562                 :     Scans list looking for index of EnvisatNameValue where the key matches
    1563                 :     (case sensitive) the passed in name. 
    1564                 : 
    1565                 : Inputs:
    1566                 :     key -- the key, such as "SLICE_POSITION" being searched for. 
    1567                 :     entry_count -- the number of items in the entries array.
    1568                 :     entries -- array of name/value structures to search. 
    1569                 : 
    1570                 : Outputs:
    1571                 : 
    1572                 : Returns:
    1573                 :     array index into entries, or -1 on failure. 
    1574                 : 
    1575                 : -----------------------------------------------------------------------------*/
    1576                 : 
    1577            3551 : int S_NameValueList_FindKey( const char *key, 
    1578                 :                              int entry_count, 
    1579                 :                              EnvisatNameValue **entries )
    1580                 : 
    1581                 : {
    1582                 :     int   i;
    1583                 : 
    1584           27007 :     for( i = 0; i < entry_count; i++ )
    1585                 :     {
    1586           26111 :         if( strcmp(entries[i]->key,key) == 0 )
    1587            2655 :             return i;
    1588                 :     }
    1589                 :     
    1590             896 :     return -1;
    1591                 : }
    1592                 : 
    1593                 : /*-----------------------------------------------------------------------------
    1594                 : 
    1595                 : Name:
    1596                 :     S_NameValueList_FindValue()
    1597                 : 
    1598                 : Purpose:
    1599                 :     Search for given key in list of name/value pairs, and return value.
    1600                 : 
    1601                 : Description:
    1602                 :     Returns value string or default if key not found.
    1603                 : 
    1604                 : Inputs:
    1605                 :     key -- the key, such as "SLICE_POSITION" being searched for. 
    1606                 :     entry_count -- the number of items in the entries array.
    1607                 :     entries -- array of name/value structures to search. 
    1608                 :     default_value -- value to use if key not found.
    1609                 : 
    1610                 : Outputs:
    1611                 : 
    1612                 : Returns:
    1613                 :     value string, or default if key not found.
    1614                 : 
    1615                 : -----------------------------------------------------------------------------*/
    1616                 : 
    1617            2520 : const char *S_NameValueList_FindValue( const char *key, 
    1618                 :                                        int entry_count, 
    1619                 :                                        EnvisatNameValue **entries,
    1620                 :                                        const char *default_value )
    1621                 : 
    1622                 : {
    1623                 :     int   i;
    1624                 : 
    1625            2520 :     i = S_NameValueList_FindKey( key, entry_count, entries );
    1626            2520 :     if( i == -1 )
    1627             882 :         return default_value;
    1628                 :     else
    1629            1638 :         return entries[i]->value;
    1630                 : }
    1631                 : 
    1632                 : /*-----------------------------------------------------------------------------
    1633                 : 
    1634                 : Name:
    1635                 :     S_NameValueList_Parse()
    1636                 : 
    1637                 : Purpose:
    1638                 :     Parse a block of envisat style name/value pairs into an
    1639                 :     EnvisatNameValue structure list. 
    1640                 : 
    1641                 : Description:
    1642                 :     The passed in text block should be zero terminated.  The entry_count, 
    1643                 :     and entries should be pre-initialized (normally to 0 and NULL).
    1644                 : 
    1645                 : Inputs:
    1646                 :     text -- the block of text, multiple lines, to be processed.
    1647                 : 
    1648                 : Outputs:
    1649                 :     entry_count -- returns with the updated number of entries in the
    1650                 :                    entries array.
    1651                 :     entries -- returns with updated array info structures. 
    1652                 : 
    1653                 : Returns:
    1654                 :     SUCCESS or FAILURE
    1655                 : 
    1656                 : -----------------------------------------------------------------------------*/
    1657                 : 
    1658             386 : int S_NameValueList_Parse( const char *text, int text_offset, 
    1659                 :                            int *entry_count, 
    1660                 :                            EnvisatNameValue ***entries )
    1661                 : 
    1662                 : {
    1663             386 :     const char  *next_text = text;
    1664                 : 
    1665                 :     /*
    1666                 :      * Loop over each input line in the text block.
    1667                 :      */
    1668            3794 :     while( *next_text != '\0' )
    1669                 :     {
    1670                 :         char  line[1024];
    1671            3022 :         int     line_len = 0, equal_index, src_char, line_offset;
    1672                 :         EnvisatNameValue *entry;
    1673                 : 
    1674                 :         /*
    1675                 :          * Extract one line of text into the "line" buffer, and remove the
    1676                 :          * newline character.  Eat leading spaces.
    1677                 :          */
    1678           53887 :         while( *next_text == ' ' ) 
    1679                 :         {
    1680           47843 :             next_text++;
    1681                 :         }
    1682            3022 :         line_offset = (int) (next_text - text) + text_offset;
    1683           89338 :         while( *next_text != '\0' && *next_text != '\n' )
    1684                 :         {
    1685           83294 :             if( line_len > sizeof(line)-1 )
    1686                 :             {
    1687               0 :                 SendError( "S_NameValueList_Parse(): "
    1688                 :                            "Corrupt line, longer than 1024 characters." );
    1689               0 :                 return FAILURE;
    1690                 :             }
    1691                 : 
    1692           83294 :             line[line_len++] = *(next_text++);
    1693                 :         }
    1694                 : 
    1695            3022 :         line[line_len] = '\0';
    1696            3022 :         if( *next_text == '\n' )
    1697            2649 :             next_text++;
    1698                 : 
    1699                 :         /*
    1700                 :          * Blank lines are permitted.  We will skip processing of any line
    1701                 :          * that doesn't have an equal sign, under the assumption it is
    1702                 :          * white space.
    1703                 :          */
    1704            3022 :         if( strstr( line, "=") == NULL )
    1705             484 :             continue;
    1706                 : 
    1707                 :         /*
    1708                 :          * Create the name/value info structure. 
    1709                 :          */
    1710            2538 :         entry = (EnvisatNameValue *) calloc(sizeof(EnvisatNameValue),1);
    1711            2538 :         entry->literal_line = strdup(line);
    1712                 : 
    1713                 :         /*
    1714                 :          * Capture the key.  We take everything up to the equal sign.  There
    1715                 :          * shouldn't be any white space, but if so, we take it as part of the
    1716                 :          * key.
    1717                 :          */
    1718            2538 :         equal_index = strstr(line, "=") - line;
    1719            2538 :         entry->key = (char *) malloc(equal_index+1);
    1720            2538 :         strncpy( entry->key, line, equal_index );
    1721            2538 :         entry->key[equal_index] = '\0';
    1722            2538 :         entry->value_offset = line_offset + equal_index + 1;
    1723                 : 
    1724                 :         /*
    1725                 :          * If the next character after the equal sign is a double quote, then
    1726                 :          * the value is a string.  Suck out the text between the double quotes.
    1727                 :          */
    1728            2538 :         if( line[equal_index+1] == '"' )
    1729                 :         {
    1730           54427 :             for( src_char = equal_index + 2;
    1731           53716 :                  line[src_char] != '\0' && line[src_char] != '"';
    1732           26147 :                  src_char++ ) {}
    1733                 : 
    1734             711 :             line[src_char] = '\0';
    1735             711 :             entry->value = strdup( line + equal_index + 2 );
    1736             711 :             entry->value_offset += 1;
    1737                 :         }
    1738                 : 
    1739                 :         /*
    1740                 :          * The value is numeric, and may include a units field.
    1741                 :          */
    1742                 :         else
    1743                 :         {
    1744           72241 :             for( src_char = equal_index + 1; 
    1745           47912 :                  line[src_char] != '\0' && line[src_char] != '<' 
    1746           46085 :                      && line[src_char] != ' ';
    1747           22502 :                  src_char++ ) {}
    1748                 : 
    1749                 :             /* capture units */
    1750            1827 :             if( line[src_char] == '<' )
    1751                 :             {
    1752                 :                 int dst_char;
    1753                 : 
    1754           13054 :                 for( dst_char = src_char+1; 
    1755           11973 :                      line[dst_char] != '>' && line[dst_char] != '\0';
    1756            5446 :                      dst_char++ ) {}
    1757                 : 
    1758            1081 :                 line[dst_char] = '\0';
    1759            1081 :                 entry->units = strdup( line + src_char + 1 );
    1760                 :             }
    1761                 : 
    1762            1827 :             line[src_char] = '\0';
    1763            1827 :             entry->value = strdup( line + equal_index + 1 );
    1764                 :         }
    1765                 : 
    1766                 :         /*
    1767                 :          * Add the entry to the name/value list. 
    1768                 :          */
    1769            2538 :         (*entry_count)++;
    1770            5076 :         *entries = (EnvisatNameValue **)
    1771            5076 :             realloc( *entries, *entry_count * sizeof(EnvisatNameValue*) );
    1772                 : 
    1773            2538 :         if( *entries == NULL )
    1774                 :         {
    1775               0 :             *entry_count = 0;
    1776               0 :             return FAILURE;
    1777                 :         }
    1778                 : 
    1779            2538 :         (*entries)[*entry_count-1] = entry;
    1780                 :     }
    1781                 :     
    1782             386 :     return SUCCESS;
    1783                 : }
    1784                 : 
    1785                 : /*-----------------------------------------------------------------------------
    1786                 : 
    1787                 : Name:
    1788                 :     S_NameValueList_Rewrite()
    1789                 : 
    1790                 : Purpose:
    1791                 :     Rewrite the values of a name/value list in the file.
    1792                 : 
    1793                 : Description:
    1794                 : 
    1795                 : Inputs:
    1796                 :     fp -- the FILE to operate on.
    1797                 :     entry_count -- number of entries to write.
    1798                 :     entries -- array of entry descriptions.
    1799                 : 
    1800                 : Returns:
    1801                 :     SUCCESS or FAILURE
    1802                 : 
    1803                 : 
    1804                 : -----------------------------------------------------------------------------*/
    1805                 : 
    1806               0 : int S_NameValueList_Rewrite( FILE * fp, int entry_count, 
    1807                 :                               EnvisatNameValue **entries )        
    1808                 : 
    1809                 : {
    1810                 :     int   i;
    1811                 : 
    1812               0 :     for( i = 0; i < entry_count; i++ )
    1813                 :     {
    1814               0 :         EnvisatNameValue  *entry = entries[i];
    1815                 : 
    1816               0 :         if( fseek( fp, entry->value_offset, SEEK_SET ) != 0 )
    1817                 :         {
    1818               0 :             SendError( "fseek() failed writing name/value list." );
    1819               0 :             return FAILURE;
    1820                 :         }
    1821                 : 
    1822               0 :         if( fwrite( entry->value, 1, strlen(entry->value), fp ) != 
    1823               0 :             strlen(entry->value) )
    1824                 :         {
    1825               0 :             SendError( "fwrite() failed writing name/value list." );
    1826               0 :             return FAILURE;
    1827                 :         }
    1828                 :     }
    1829                 : 
    1830               0 :     return SUCCESS;
    1831                 : }
    1832                 : 
    1833                 : 
    1834                 : /*-----------------------------------------------------------------------------
    1835                 : 
    1836                 : Name:
    1837                 :     S_NameValueList_Destroy()
    1838                 : 
    1839                 : Purpose:
    1840                 :     Free resources associated with a name/value list.
    1841                 : 
    1842                 : Description:
    1843                 :     The count, and name/value list pointers are set to 0/NULL on completion.
    1844                 : 
    1845                 : Inputs:
    1846                 :     entry_count -- returns with the updated number of entries in the
    1847                 :                    entries array.
    1848                 :     entries -- returns with updated array info structures. 
    1849                 : 
    1850                 : Outputs:
    1851                 :     entry_count -- Set to zero.
    1852                 :     entries -- Sett o NULL.
    1853                 : 
    1854                 : Returns:
    1855                 : 
    1856                 : 
    1857                 : -----------------------------------------------------------------------------*/
    1858                 : 
    1859             386 : void S_NameValueList_Destroy( int *entry_count, 
    1860                 :                               EnvisatNameValue ***entries )       
    1861                 : 
    1862                 : {
    1863                 :     int   i;
    1864                 : 
    1865            2924 :     for( i = 0; i < *entry_count; i++ )
    1866                 :     {
    1867            2538 :         free( (*entries)[i]->key );
    1868            2538 :         free( (*entries)[i]->value );
    1869            2538 :         free( (*entries)[i]->units );
    1870            2538 :         free( (*entries)[i]->literal_line );
    1871            2538 :         free( (*entries)[i] );
    1872                 :     }
    1873                 : 
    1874             386 :     free( *entries );
    1875                 :     
    1876             386 :     *entry_count = 0;
    1877             386 :     *entries = NULL;
    1878             386 : }
    1879                 : 
    1880                 : /* EOF */
    1881                 : 

Generated by: LCOV version 1.7