LTP GCOV extension - code coverage report
Current view: directory - frmts/pcidsk/sdk/segment - metadatasegment_p.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 80
Code covered: 96.2 % Executed lines: 77

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Purpose:  Implementation of the MetadataSegment class.
       4                 :  *
       5                 :  * This class is used to manage access to the SYS METADATA segment.  This
       6                 :  * segment holds all the metadata for objects in the PCIDSK file.
       7                 :  *
       8                 :  * This class is closely partnered with the MetadataSet class. 
       9                 :  * 
      10                 :  ******************************************************************************
      11                 :  * Copyright (c) 2009
      12                 :  * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
      13                 :  *
      14                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      15                 :  * copy of this software and associated documentation files (the "Software"),
      16                 :  * to deal in the Software without restriction, including without limitation
      17                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      18                 :  * and/or sell copies of the Software, and to permit persons to whom the
      19                 :  * Software is furnished to do so, subject to the following conditions:
      20                 :  *
      21                 :  * The above copyright notice and this permission notice shall be included
      22                 :  * in all copies or substantial portions of the Software.
      23                 :  *
      24                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      25                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      27                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      28                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      29                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      30                 :  * DEALINGS IN THE SOFTWARE.
      31                 :  ****************************************************************************/
      32                 : 
      33                 : #include "pcidsk_file.h"
      34                 : #include "segment/metadatasegment.h"
      35                 : #include <cassert>
      36                 : #include <cstring>
      37                 : #include <cstdio>
      38                 : #include <map>
      39                 : 
      40                 : using namespace PCIDSK;
      41                 : 
      42                 : /************************************************************************/
      43                 : /*                          MetadataSegment()                           */
      44                 : /************************************************************************/
      45                 : 
      46                 : MetadataSegment::MetadataSegment( PCIDSKFile *file, int segment,
      47              25 :                                   const char *segment_pointer )
      48              25 :         : CPCIDSKSegment( file, segment, segment_pointer )
      49                 : 
      50                 : {
      51              25 :     loaded = false;
      52              25 : }
      53                 : 
      54                 : /************************************************************************/
      55                 : /*                          ~MetadataSegment()                          */
      56                 : /************************************************************************/
      57                 : 
      58              25 : MetadataSegment::~MetadataSegment()
      59                 : 
      60                 : {
      61              25 :     Synchronize();
      62              25 : }
      63                 : 
      64                 : /************************************************************************/
      65                 : /*                            Synchronize()                             */
      66                 : /************************************************************************/
      67                 : 
      68              65 : void MetadataSegment::Synchronize()
      69                 : {
      70              65 :     if( loaded && update_list.size() > 0 )
      71              20 :         Save();
      72              65 : }
      73                 : 
      74                 : /************************************************************************/
      75                 : /*                                Load()                                */
      76                 : /************************************************************************/
      77                 : 
      78              35 : void MetadataSegment::Load()
      79                 : 
      80                 : {
      81              35 :     if( loaded )
      82              10 :         return;
      83                 : 
      84                 :     // TODO: this should likely be protected by a mutex. 
      85                 : 
      86                 : /* -------------------------------------------------------------------- */
      87                 : /*      Load the segment contents into a buffer.                        */
      88                 : /* -------------------------------------------------------------------- */
      89              25 :     seg_data.SetSize( data_size - 1024 );
      90                 : 
      91              25 :     ReadFromFile( seg_data.buffer, 0, data_size - 1024 );
      92                 : 
      93              25 :     loaded = true;
      94                 : }
      95                 : 
      96                 : /************************************************************************/
      97                 : /*                           FetchMetadata()                            */
      98                 : /************************************************************************/
      99                 : 
     100                 : void MetadataSegment::FetchMetadata( const char *group, int id,
     101              11 :                                      std::map<std::string,std::string> &md_set)
     102                 : 
     103                 : {
     104                 : /* -------------------------------------------------------------------- */
     105                 : /*      Load the metadata segment if not already loaded.                */
     106                 : /* -------------------------------------------------------------------- */
     107              11 :     Load();
     108                 : 
     109                 : /* -------------------------------------------------------------------- */
     110                 : /*      Establish the key prefix we are searching for.                  */
     111                 : /* -------------------------------------------------------------------- */
     112                 :     char key_prefix[200];
     113                 :     int  prefix_len;
     114                 : 
     115              11 :     sprintf( key_prefix, "METADATA_%s_%d_", group, id );
     116              11 :     prefix_len = strlen(key_prefix);
     117                 : 
     118                 : /* -------------------------------------------------------------------- */
     119                 : /*      Process all the metadata entries in this segment, searching     */
     120                 : /*      for those that match our prefix.                                */
     121                 : /* -------------------------------------------------------------------- */
     122                 :     const char *pszNext;
     123                 : 
     124              58 :     for( pszNext = (const char *) seg_data.buffer; *pszNext != '\0'; )
     125                 :     {
     126                 : /* -------------------------------------------------------------------- */
     127                 : /*      Identify the end of this line, and the split character (:).     */
     128                 : /* -------------------------------------------------------------------- */
     129              36 :         int i_split = -1, i;
     130                 : 
     131            1094 :         for( i=0; 
     132                 :              pszNext[i] != 10 && pszNext[i] != 12 && pszNext[i] != 0; 
     133                 :              i++) 
     134                 :         {
     135            1058 :             if( i_split == -1 && pszNext[i] == ':' )
     136              36 :                 i_split = i;
     137                 :         }
     138                 : 
     139              36 :         if( pszNext[i] == '\0' )
     140               0 :             break;
     141                 : 
     142                 : /* -------------------------------------------------------------------- */
     143                 : /*      If this matches our prefix, capture the key and value.          */
     144                 : /* -------------------------------------------------------------------- */
     145              36 :         if( i_split != -1 && strncmp(pszNext,key_prefix,prefix_len) == 0 )
     146                 :         {
     147              14 :             std::string key, value;
     148                 : 
     149              14 :             key.assign( pszNext+prefix_len, i_split-prefix_len );
     150                 : 
     151              14 :             if( pszNext[i_split+1] == ' ' )
     152              14 :                 value.assign( pszNext+i_split+2, i-i_split-2 );
     153                 :             else
     154               0 :                 value.assign( pszNext+i_split+1, i-i_split-1 );
     155                 : 
     156              14 :             md_set[key] = value;
     157                 :         }
     158                 : 
     159                 : /* -------------------------------------------------------------------- */
     160                 : /*      Advance to start of next line.                                  */
     161                 : /* -------------------------------------------------------------------- */
     162              36 :         pszNext = pszNext + i;
     163             108 :         while( *pszNext == 10 || *pszNext == 12 )
     164              36 :             pszNext++;
     165                 :     }
     166              11 : }
     167                 : 
     168                 : /************************************************************************/
     169                 : /*                          SetMetadataValue()                          */
     170                 : /************************************************************************/
     171                 : 
     172                 : void MetadataSegment::SetMetadataValue( const char *group, int id,
     173              24 :                                         const std::string& key, const std::string& value )
     174                 : 
     175                 : {
     176              24 :     Load();
     177                 : 
     178                 :     char key_prefix[200];
     179                 : 
     180              24 :     sprintf( key_prefix, "METADATA_%s_%d_", group, id );
     181                 : 
     182              24 :     std::string full_key;
     183                 : 
     184              24 :     full_key = key_prefix;
     185              24 :     full_key += key;
     186                 : 
     187              24 :     update_list[full_key] = value;
     188              24 : }
     189                 : 
     190                 : /************************************************************************/
     191                 : /*                                Save()                                */
     192                 : /*                                                                      */
     193                 : /*      When saving we first need to merge in any updates.  We put      */
     194                 : /*      this off since scanning and updating the metadata doc could     */
     195                 : /*      be epxensive if done for each item.                             */
     196                 : /************************************************************************/
     197                 : 
     198              20 : void MetadataSegment::Save()
     199                 : 
     200                 : {
     201              20 :     std::string new_data;
     202                 : 
     203                 : /* -------------------------------------------------------------------- */
     204                 : /*      Process all the metadata entries in this segment, searching     */
     205                 : /*      for those that match our prefix.                                */
     206                 : /* -------------------------------------------------------------------- */
     207                 :     const char *pszNext;
     208                 : 
     209              36 :     for( pszNext = (const char *) seg_data.buffer; *pszNext != '\0'; )
     210                 :     {
     211                 : /* -------------------------------------------------------------------- */
     212                 : /*      Identify the end of this line, and the split character (:).     */
     213                 : /* -------------------------------------------------------------------- */
     214              16 :         int i_split = -1, i;
     215                 : 
     216             405 :         for( i=0; 
     217                 :              pszNext[i] != 10 && pszNext[i] != 12 && pszNext[i] != 0; 
     218                 :              i++) 
     219                 :         {
     220             389 :             if( i_split == -1 && pszNext[i] == ':' )
     221              16 :                 i_split = i;
     222                 :         }
     223                 : 
     224              16 :         if( pszNext[i] == '\0' )
     225               0 :             break;
     226                 : 
     227                 : /* -------------------------------------------------------------------- */
     228                 : /*      If we have a new value for this key, do not copy over the       */
     229                 : /*      old value.  Otherwise append the old value to our new image.    */
     230                 : /* -------------------------------------------------------------------- */
     231              16 :         std::string full_key;
     232                 : 
     233              16 :         full_key.assign( pszNext, i_split );
     234                 :         
     235              16 :         if( update_list.count(full_key) == 1 )
     236                 :             /* do not transfer - we will append later */;
     237                 :         else
     238              15 :             new_data.append( pszNext, i+1 );
     239                 : 
     240                 : /* -------------------------------------------------------------------- */
     241                 : /*      Advance to start of next line.                                  */
     242                 : /* -------------------------------------------------------------------- */
     243              16 :         pszNext = pszNext + i;
     244              48 :         while( *pszNext == 10 || *pszNext == 12 )
     245              16 :             pszNext++;
     246                 :     }
     247                 : 
     248                 : /* -------------------------------------------------------------------- */
     249                 : /*      Append all the update items with non-empty values.              */
     250                 : /* -------------------------------------------------------------------- */
     251              20 :     std::map<std::string,std::string>::iterator it;
     252                 : 
     253              67 :     for( it = update_list.begin(); it != update_list.end(); it++ )
     254                 :     {
     255              24 :         if( it->second.size() == 0 )
     256               1 :             continue;
     257                 : 
     258              23 :         std::string line;
     259                 : 
     260              23 :         line = it->first;
     261              23 :         line += ": ";
     262              23 :         line += it->second;
     263              23 :         line += "\n";
     264                 : 
     265              23 :         new_data += line;
     266                 :     }
     267                 : 
     268              20 :     update_list.clear();
     269                 : 
     270                 : /* -------------------------------------------------------------------- */
     271                 : /*      Move the new value into our buffer, and write to disk.          */
     272                 : /* -------------------------------------------------------------------- */
     273              20 :     if( new_data.size() % 512 != 0 ) // zero fill the last block.
     274                 :     {
     275                 :         new_data.resize( new_data.size() + (512 - (new_data.size() % 512)), 
     276              20 :                          '\0' );
     277                 :     }
     278                 : 
     279              20 :     seg_data.SetSize( new_data.size() );
     280              20 :     memcpy( seg_data.buffer, new_data.c_str(), new_data.size() );
     281                 : 
     282              20 :     WriteToFile( seg_data.buffer, 0, seg_data.buffer_size );
     283              20 : }

Generated by: LTP GCOV extension version 1.5