LCOV - code coverage report
Current view: directory - frmts/pcidsk/sdk/segment - metadatasegment_p.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 79 76 96.2 %
Date: 2010-01-09 Functions: 9 7 77.8 %

       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                 : 
      39                 : using namespace PCIDSK;
      40                 : 
      41                 : /************************************************************************/
      42                 : /*                          MetadataSegment()                           */
      43                 : /************************************************************************/
      44                 : 
      45              25 : MetadataSegment::MetadataSegment( PCIDSKFile *file, int segment,
      46                 :                                   const char *segment_pointer )
      47              25 :         : CPCIDSKSegment( file, segment, segment_pointer )
      48                 : 
      49                 : {
      50              25 :     loaded = false;
      51              25 : }
      52                 : 
      53                 : /************************************************************************/
      54                 : /*                          ~MetadataSegment()                          */
      55                 : /************************************************************************/
      56                 : 
      57              50 : MetadataSegment::~MetadataSegment()
      58                 : 
      59                 : {
      60              25 :     if( loaded && update_list.size() > 0 )
      61              20 :         Save();
      62              50 : }
      63                 : 
      64                 : /************************************************************************/
      65                 : /*                                Load()                                */
      66                 : /************************************************************************/
      67                 : 
      68              35 : void MetadataSegment::Load()
      69                 : 
      70                 : {
      71              35 :     if( loaded )
      72              10 :         return;
      73                 : 
      74                 :     // TODO: this should likely be protected by a mutex. 
      75                 : 
      76                 : /* -------------------------------------------------------------------- */
      77                 : /*      Load the segment contents into a buffer.                        */
      78                 : /* -------------------------------------------------------------------- */
      79              25 :     seg_data.SetSize( data_size - 1024 );
      80                 : 
      81              25 :     ReadFromFile( seg_data.buffer, 0, data_size - 1024 );
      82                 : 
      83              25 :     loaded = true;
      84                 : }
      85                 : 
      86                 : /************************************************************************/
      87                 : /*                           FetchMetadata()                            */
      88                 : /************************************************************************/
      89                 : 
      90              11 : void MetadataSegment::FetchMetadata( const char *group, int id,
      91                 :                                      std::map<std::string,std::string> &md_set)
      92                 : 
      93                 : {
      94                 : /* -------------------------------------------------------------------- */
      95                 : /*      Load the metadata segment if not already loaded.                */
      96                 : /* -------------------------------------------------------------------- */
      97              11 :     Load();
      98                 : 
      99                 : /* -------------------------------------------------------------------- */
     100                 : /*      Establish the key prefix we are searching for.                  */
     101                 : /* -------------------------------------------------------------------- */
     102                 :     char key_prefix[200];
     103                 :     int  prefix_len;
     104                 : 
     105              11 :     sprintf( key_prefix, "METADATA_%s_%d_", group, id );
     106              11 :     prefix_len = strlen(key_prefix);
     107                 : 
     108                 : /* -------------------------------------------------------------------- */
     109                 : /*      Process all the metadata entries in this segment, searching     */
     110                 : /*      for those that match our prefix.                                */
     111                 : /* -------------------------------------------------------------------- */
     112                 :     const char *pszNext;
     113                 : 
     114              58 :     for( pszNext = (const char *) seg_data.buffer; *pszNext != '\0'; )
     115                 :     {
     116                 : /* -------------------------------------------------------------------- */
     117                 : /*      Identify the end of this line, and the split character (:).     */
     118                 : /* -------------------------------------------------------------------- */
     119              36 :         int i_split = -1, i;
     120                 : 
     121            4304 :         for( i=0; 
     122            3210 :              pszNext[i] != 10 && pszNext[i] != 12 && pszNext[i] != 0; 
     123                 :              i++) 
     124                 :         {
     125            1058 :             if( i_split == -1 && pszNext[i] == ':' )
     126              36 :                 i_split = i;
     127                 :         }
     128                 : 
     129              36 :         if( pszNext[i] == '\0' )
     130               0 :             break;
     131                 : 
     132                 : /* -------------------------------------------------------------------- */
     133                 : /*      If this matches our prefix, capture the key and value.          */
     134                 : /* -------------------------------------------------------------------- */
     135              36 :         if( i_split != -1 && strncmp(pszNext,key_prefix,prefix_len) == 0 )
     136                 :         {
     137              14 :             std::string key, value;
     138                 : 
     139              14 :             key.assign( pszNext+prefix_len, i_split-prefix_len );
     140                 : 
     141              14 :             if( pszNext[i_split+1] == ' ' )
     142              14 :                 value.assign( pszNext+i_split+2, i-i_split-2 );
     143                 :             else
     144               0 :                 value.assign( pszNext+i_split+1, i-i_split-1 );
     145                 : 
     146              14 :             md_set[key] = value;
     147                 :         }
     148                 : 
     149                 : /* -------------------------------------------------------------------- */
     150                 : /*      Advance to start of next line.                                  */
     151                 : /* -------------------------------------------------------------------- */
     152              36 :         pszNext = pszNext + i;
     153             108 :         while( *pszNext == 10 || *pszNext == 12 )
     154              36 :             pszNext++;
     155                 :     }
     156              11 : }
     157                 : 
     158                 : /************************************************************************/
     159                 : /*                          SetMetadataValue()                          */
     160                 : /************************************************************************/
     161                 : 
     162              24 : void MetadataSegment::SetMetadataValue( const char *group, int id,
     163                 :                                         const std::string& key, const std::string& value )
     164                 : 
     165                 : {
     166              24 :     Load();
     167                 : 
     168                 :     char key_prefix[200];
     169                 : 
     170              24 :     sprintf( key_prefix, "METADATA_%s_%d_", group, id );
     171                 : 
     172              24 :     std::string full_key;
     173                 : 
     174              24 :     full_key = key_prefix;
     175              24 :     full_key += key;
     176                 : 
     177              24 :     update_list[full_key] = value;
     178              24 : }
     179                 : 
     180                 : /************************************************************************/
     181                 : /*                                Save()                                */
     182                 : /*                                                                      */
     183                 : /*      When saving we first need to merge in any updates.  We put      */
     184                 : /*      this off since scanning and updating the metadata doc could     */
     185                 : /*      be epxensive if done for each item.                             */
     186                 : /************************************************************************/
     187                 : 
     188              20 : void MetadataSegment::Save()
     189                 : 
     190                 : {
     191              20 :     std::string new_data;
     192                 : 
     193                 : /* -------------------------------------------------------------------- */
     194                 : /*      Process all the metadata entries in this segment, searching     */
     195                 : /*      for those that match our prefix.                                */
     196                 : /* -------------------------------------------------------------------- */
     197                 :     const char *pszNext;
     198                 : 
     199              36 :     for( pszNext = (const char *) seg_data.buffer; *pszNext != '\0'; )
     200                 :     {
     201                 : /* -------------------------------------------------------------------- */
     202                 : /*      Identify the end of this line, and the split character (:).     */
     203                 : /* -------------------------------------------------------------------- */
     204              16 :         int i_split = -1, i;
     205                 : 
     206            1588 :         for( i=0; 
     207            1183 :              pszNext[i] != 10 && pszNext[i] != 12 && pszNext[i] != 0; 
     208                 :              i++) 
     209                 :         {
     210             389 :             if( i_split == -1 && pszNext[i] == ':' )
     211              16 :                 i_split = i;
     212                 :         }
     213                 : 
     214              16 :         if( pszNext[i] == '\0' )
     215               0 :             break;
     216                 : 
     217                 : /* -------------------------------------------------------------------- */
     218                 : /*      If we have a new value for this key, do not copy over the       */
     219                 : /*      old value.  Otherwise append the old value to our new image.    */
     220                 : /* -------------------------------------------------------------------- */
     221              16 :         std::string full_key;
     222                 : 
     223              16 :         full_key.assign( pszNext, i_split );
     224                 :         
     225              16 :         if( update_list.count(full_key) == 1 )
     226                 :             /* do not transfer - we will append later */;
     227                 :         else
     228              15 :             new_data.append( pszNext, i+1 );
     229                 : 
     230                 : /* -------------------------------------------------------------------- */
     231                 : /*      Advance to start of next line.                                  */
     232                 : /* -------------------------------------------------------------------- */
     233              16 :         pszNext = pszNext + i;
     234              48 :         while( *pszNext == 10 || *pszNext == 12 )
     235              16 :             pszNext++;
     236                 :     }
     237                 : 
     238                 : /* -------------------------------------------------------------------- */
     239                 : /*      Append all the update items with non-empty values.              */
     240                 : /* -------------------------------------------------------------------- */
     241              20 :     std::map<std::string,std::string>::iterator it;
     242                 : 
     243              43 :     for( it = update_list.begin(); it != update_list.end(); it++ )
     244                 :     {
     245              24 :         if( it->second.size() == 0 )
     246               1 :             continue;
     247                 : 
     248              23 :         std::string line;
     249                 : 
     250              23 :         line = it->first;
     251              23 :         line += ": ";
     252              23 :         line += it->second;
     253              23 :         line += "\n";
     254                 : 
     255              23 :         new_data += line;
     256                 :     }
     257                 : 
     258              20 :     update_list.clear();
     259                 : 
     260                 : /* -------------------------------------------------------------------- */
     261                 : /*      Move the new value into our buffer, and write to disk.          */
     262                 : /* -------------------------------------------------------------------- */
     263              20 :     if( new_data.size() % 512 != 0 ) // zero fill the last block.
     264                 :     {
     265                 :         new_data.resize( new_data.size() + (512 - (new_data.size() % 512)), 
     266              20 :                          '\0' );
     267                 :     }
     268                 : 
     269              20 :     seg_data.SetSize( new_data.size() );
     270              20 :     memcpy( seg_data.buffer, new_data.c_str(), new_data.size() );
     271                 : 
     272              20 :     WriteToFile( seg_data.buffer, 0, seg_data.buffer_size );
     273              20 : }

Generated by: LCOV version 1.7