LCOV - code coverage report
Current view: directory - frmts/pcidsk/sdk/segment - metadatasegment_p.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 82 79 96.3 %
Date: 2011-12-18 Functions: 10 7 70.0 %

       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              43 : MetadataSegment::MetadataSegment( PCIDSKFile *file, int segment,
      47                 :                                   const char *segment_pointer )
      48              43 :         : CPCIDSKSegment( file, segment, segment_pointer )
      49                 : 
      50                 : {
      51              43 :     loaded = false;
      52              43 : }
      53                 : 
      54                 : /************************************************************************/
      55                 : /*                          ~MetadataSegment()                          */
      56                 : /************************************************************************/
      57                 : 
      58              43 : MetadataSegment::~MetadataSegment()
      59                 : 
      60                 : {
      61              43 :     Synchronize();
      62              43 : }
      63                 : 
      64                 : /************************************************************************/
      65                 : /*                            Synchronize()                             */
      66                 : /************************************************************************/
      67                 : 
      68              93 : void MetadataSegment::Synchronize()
      69                 : {
      70              93 :     if( loaded && update_list.size() > 0 )
      71              25 :         Save();
      72              93 : }
      73                 : 
      74                 : /************************************************************************/
      75                 : /*                                Load()                                */
      76                 : /************************************************************************/
      77                 : 
      78              98 : void MetadataSegment::Load()
      79                 : 
      80                 : {
      81              98 :     if( loaded )
      82              55 :         return;
      83                 : 
      84                 :     // TODO: this should likely be protected by a mutex. 
      85                 : 
      86                 : /* -------------------------------------------------------------------- */
      87                 : /*      Load the segment contents into a buffer.                        */
      88                 : /* -------------------------------------------------------------------- */
      89              43 :     seg_data.SetSize( (int) (data_size - 1024) );
      90                 : 
      91              43 :     ReadFromFile( seg_data.buffer, 0, data_size - 1024 );
      92                 : 
      93              43 :     loaded = true;
      94                 : }
      95                 : 
      96                 : /************************************************************************/
      97                 : /*                           FetchMetadata()                            */
      98                 : /************************************************************************/
      99                 : 
     100              60 : void MetadataSegment::FetchMetadata( const char *group, int id,
     101                 :                                      std::map<std::string,std::string> &md_set)
     102                 : 
     103                 : {
     104                 : /* -------------------------------------------------------------------- */
     105                 : /*      Load the metadata segment if not already loaded.                */
     106                 : /* -------------------------------------------------------------------- */
     107              60 :     Load();
     108                 : 
     109                 : /* -------------------------------------------------------------------- */
     110                 : /*      Establish the key prefix we are searching for.                  */
     111                 : /* -------------------------------------------------------------------- */
     112                 :     char key_prefix[200];
     113                 :     int  prefix_len;
     114                 : 
     115              60 :     std::sprintf( key_prefix, "METADATA_%s_%d_", group, id );
     116              60 :     prefix_len = std::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            2532 :     for( pszNext = (const char *) seg_data.buffer; *pszNext != '\0'; )
     125                 :     {
     126                 : /* -------------------------------------------------------------------- */
     127                 : /*      Identify the end of this line, and the split character (:).     */
     128                 : /* -------------------------------------------------------------------- */
     129            2412 :         int i_split = -1, i;
     130                 : 
     131          429704 :         for( i=0; 
     132          321072 :              pszNext[i] != 10 && pszNext[i] != 12 && pszNext[i] != 0; 
     133                 :              i++) 
     134                 :         {
     135          106220 :             if( i_split == -1 && pszNext[i] == ':' )
     136            2412 :                 i_split = i;
     137                 :         }
     138                 : 
     139            2412 :         if( pszNext[i] == '\0' )
     140               0 :             break;
     141                 : 
     142                 : /* -------------------------------------------------------------------- */
     143                 : /*      If this matches our prefix, capture the key and value.          */
     144                 : /* -------------------------------------------------------------------- */
     145            2412 :         if( i_split != -1 && std::strncmp(pszNext,key_prefix,prefix_len) == 0 )
     146                 :         {
     147             178 :             std::string key, value;
     148                 : 
     149             178 :             key.assign( pszNext+prefix_len, i_split-prefix_len );
     150                 : 
     151             178 :             if( pszNext[i_split+1] == ' ' )
     152             178 :                 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             178 :             md_set[key] = value;
     157                 :         }
     158                 : 
     159                 : /* -------------------------------------------------------------------- */
     160                 : /*      Advance to start of next line.                                  */
     161                 : /* -------------------------------------------------------------------- */
     162            2412 :         pszNext = pszNext + i;
     163            7236 :         while( *pszNext == 10 || *pszNext == 12 )
     164            2412 :             pszNext++;
     165                 :     }
     166              60 : }
     167                 : 
     168                 : /************************************************************************/
     169                 : /*                          SetMetadataValue()                          */
     170                 : /************************************************************************/
     171                 : 
     172              38 : void MetadataSegment::SetMetadataValue( const char *group, int id,
     173                 :                                         const std::string& key, const std::string& value )
     174                 : 
     175                 : {
     176              38 :     Load();
     177                 : 
     178                 :     char key_prefix[200];
     179                 : 
     180              38 :     std::sprintf( key_prefix, "METADATA_%s_%d_", group, id );
     181                 : 
     182              38 :     std::string full_key;
     183                 : 
     184              38 :     full_key = key_prefix;
     185              38 :     full_key += key;
     186                 : 
     187              38 :     update_list[full_key] = value;
     188              38 : }
     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              25 : void MetadataSegment::Save()
     199                 : 
     200                 : {
     201              25 :     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              41 :     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            1588 :         for( i=0; 
     217            1183 :              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              25 :     std::map<std::string,std::string>::iterator it;
     252                 : 
     253              60 :     for( it = update_list.begin(); it != update_list.end(); it++ )
     254                 :     {
     255              36 :         if( it->second.size() == 0 )
     256               1 :             continue;
     257                 : 
     258              35 :         std::string line;
     259                 : 
     260              35 :         line = it->first;
     261              35 :         line += ": ";
     262              35 :         line += it->second;
     263              35 :         line += "\n";
     264                 : 
     265              35 :         new_data += line;
     266                 :     }
     267                 : 
     268              25 :     update_list.clear();
     269                 : 
     270                 : /* -------------------------------------------------------------------- */
     271                 : /*      Move the new value into our buffer, and write to disk.          */
     272                 : /* -------------------------------------------------------------------- */
     273              25 :     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              25 :                          '\0' );
     277                 :     }
     278                 : 
     279              25 :     seg_data.SetSize( new_data.size() );
     280              25 :     std::memcpy( seg_data.buffer, new_data.c_str(), new_data.size() );
     281                 : 
     282              25 :     WriteToFile( seg_data.buffer, 0, seg_data.buffer_size );
     283              25 : }

Generated by: LCOV version 1.7