LCOV - code coverage report
Current view: directory - frmts/pcidsk/sdk/segment - vecsegdataindex.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 87 74 85.1 %
Date: 2012-04-28 Functions: 13 9 69.2 %

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Purpose:  Implementation of the VecSegIndex class.  
       4                 :  *
       5                 :  * This class is used to manage a vector segment data block index.  There
       6                 :  * will be two instances created, one for the record data (sec_record) and
       7                 :  * one for the vertices (sec_vert).  This class is exclusively a private
       8                 :  * helper class for VecSegHeader.
       9                 :  * 
      10                 :  ******************************************************************************
      11                 :  * Copyright (c) 2010
      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.h"
      34                 : #include "core/pcidsk_utils.h"
      35                 : #include "segment/cpcidskvectorsegment.h"
      36                 : #include <cassert>
      37                 : #include <cstring>
      38                 : #include <cstdio>
      39                 : 
      40                 : using namespace PCIDSK;
      41                 : 
      42                 : /* -------------------------------------------------------------------- */
      43                 : /*      Size of a block in the record/vertice block tables.  This is    */
      44                 : /*      determined by the PCIDSK format and may not be changed.         */
      45                 : /* -------------------------------------------------------------------- */
      46                 : static const int block_page_size = 8192;  
      47                 : 
      48                 : /************************************************************************/
      49                 : /*                          VecSegDataIndex()                           */
      50                 : /************************************************************************/
      51                 : 
      52             112 : VecSegDataIndex::VecSegDataIndex()
      53                 : 
      54                 : {
      55             112 :     block_initialized = false;
      56             112 :     vs = NULL;
      57             112 :     dirty = false;
      58             112 : }
      59                 : 
      60                 : /************************************************************************/
      61                 : /*                          ~VecSegDataIndex()                          */
      62                 : /************************************************************************/
      63                 : 
      64             112 : VecSegDataIndex::~VecSegDataIndex()
      65                 : 
      66                 : {
      67             112 : }
      68                 : 
      69                 : /************************************************************************/
      70                 : /*                             Initialize()                             */
      71                 : /************************************************************************/
      72                 : 
      73             108 : void VecSegDataIndex::Initialize( CPCIDSKVectorSegment *vs, int section )
      74                 : 
      75                 : {
      76             108 :     this->section = section;
      77             108 :     this->vs = vs;
      78                 : 
      79             108 :     if( section == sec_vert )
      80              54 :         offset_on_disk_within_section = 0;
      81                 :     else 
      82              54 :         offset_on_disk_within_section = vs->di[sec_vert].SerializedSize();
      83                 : 
      84                 :     uint32 offset = offset_on_disk_within_section 
      85             108 :         + vs->vh.section_offsets[hsec_shape];
      86                 : 
      87             108 :     memcpy( &block_count, vs->GetData(sec_raw,offset,NULL,4), 4);
      88             108 :     memcpy( &bytes, vs->GetData(sec_raw,offset+4,NULL,4), 4);
      89                 : 
      90             108 :     bool needs_swap = !BigEndianSystem();
      91                 : 
      92             108 :     if( needs_swap )
      93                 :     {
      94             108 :         SwapData( &block_count, 4, 1 );
      95             108 :         SwapData( &bytes, 4, 1 );
      96                 :     }
      97                 : 
      98             108 :     size_on_disk = block_count * 4 + 8;
      99             108 : }
     100                 : 
     101                 : /************************************************************************/
     102                 : /*                           SerializedSize()                           */
     103                 : /************************************************************************/
     104                 : 
     105             176 : uint32 VecSegDataIndex::SerializedSize()
     106                 : 
     107                 : {
     108             176 :     return 8 + 4 * block_count;
     109                 : }
     110                 : 
     111                 : /************************************************************************/
     112                 : /*                           GetBlockIndex()                            */
     113                 : /************************************************************************/
     114                 : 
     115            2038 : const std::vector<uint32> *VecSegDataIndex::GetIndex()
     116                 : 
     117                 : {
     118                 : /* -------------------------------------------------------------------- */
     119                 : /*      Load block map if needed.                                       */
     120                 : /* -------------------------------------------------------------------- */
     121            2038 :     if( !block_initialized )
     122                 :     {
     123              50 :         bool needs_swap = !BigEndianSystem();
     124                 : 
     125              50 :         block_index.resize( block_count );
     126              50 :         if( block_count > 0 )
     127                 :         {
     128                 :             vs->ReadFromFile( &(block_index[0]), 
     129                 :                               offset_on_disk_within_section
     130              36 :                               + vs->vh.section_offsets[hsec_shape] + 8, 
     131              72 :                               4 * block_count );
     132                 : 
     133              36 :             if( needs_swap )
     134              36 :                 SwapData( &(block_index[0]), 4, block_count );
     135                 :         }
     136                 : 
     137              50 :         block_initialized = true;
     138                 :     }
     139                 : 
     140            2038 :     return &block_index;
     141                 : }
     142                 :                              
     143                 : /************************************************************************/
     144                 : /*                               Flush()                                */
     145                 : /************************************************************************/
     146                 : 
     147             160 : void VecSegDataIndex::Flush()
     148                 : 
     149                 : {
     150             160 :     if( !dirty )
     151             146 :         return;
     152                 : 
     153              14 :     GetIndex(); // force loading if not already loaded!
     154                 : 
     155              14 :     PCIDSKBuffer wbuf( SerializedSize() );
     156                 : 
     157              14 :     memcpy( wbuf.buffer + 0, &block_count, 4 );
     158              14 :     memcpy( wbuf.buffer + 4, &bytes, 4 );
     159              14 :     memcpy( wbuf.buffer + 8, &(block_index[0]), 4*block_count );
     160                 : 
     161              14 :     bool needs_swap = !BigEndianSystem();
     162                 : 
     163              14 :     if( needs_swap )
     164              14 :         SwapData( wbuf.buffer, 4, block_count+2 );
     165                 : 
     166                 :     // Make sure this section of the header is large enough.
     167              14 :     int32 shift = (int32) wbuf.buffer_size - (int32) size_on_disk;
     168                 :     
     169              14 :     if( shift != 0 )
     170                 :     {
     171              14 :         uint32 old_section_size = vs->vh.section_sizes[hsec_shape];
     172                 : 
     173                 : //        fprintf( stderr, "Shifting section %d by %d bytes.\n",
     174                 : //                 section, shift );
     175                 : 
     176              14 :         vs->vh.GrowSection( hsec_shape, old_section_size + shift );
     177                 : 
     178              14 :         if( section == sec_vert )
     179                 :         {
     180                 :             // move record block index and shape index.
     181              12 :             vs->MoveData( vs->vh.section_offsets[hsec_shape]
     182                 :                           + vs->di[sec_vert].size_on_disk,
     183              12 :                           vs->vh.section_offsets[hsec_shape]
     184                 :                           + vs->di[sec_vert].size_on_disk + shift,
     185              36 :                           old_section_size - size_on_disk );
     186                 :         }
     187                 :         else
     188                 :         {
     189                 :             // only move shape index.
     190               2 :             vs->MoveData( vs->vh.section_offsets[hsec_shape]
     191                 :                           + vs->di[sec_vert].size_on_disk
     192                 :                           + vs->di[sec_record].size_on_disk,
     193               2 :                           vs->vh.section_offsets[hsec_shape]
     194                 :                           + vs->di[sec_vert].size_on_disk
     195                 :                           + vs->di[sec_record].size_on_disk 
     196                 :                           + shift,
     197                 :                           old_section_size 
     198                 :                           - vs->di[sec_vert].size_on_disk
     199               6 :                           - vs->di[sec_record].size_on_disk );
     200                 :         }
     201                 : 
     202              14 :         if( section == sec_vert )
     203              12 :             vs->di[sec_record].offset_on_disk_within_section += shift;
     204                 :     }
     205                 : 
     206                 :     // Actually write to disk.
     207                 :     vs->WriteToFile( wbuf.buffer, 
     208                 :                      offset_on_disk_within_section 
     209              14 :                      + vs->vh.section_offsets[hsec_shape], 
     210              28 :                      wbuf.buffer_size );
     211                 : 
     212              14 :     size_on_disk = wbuf.buffer_size;
     213              14 :     dirty = false;
     214                 : }
     215                 : 
     216                 : /************************************************************************/
     217                 : /*                           GetSectionEnd()                            */
     218                 : /************************************************************************/
     219                 : 
     220          276414 : uint32 VecSegDataIndex::GetSectionEnd()
     221                 : 
     222                 : {
     223          276414 :     return bytes;
     224                 : }
     225                 : 
     226                 : /************************************************************************/
     227                 : /*                           SetSectionEnd()                            */
     228                 : /************************************************************************/
     229                 : 
     230              18 : void VecSegDataIndex::SetSectionEnd( uint32 new_end )
     231                 : 
     232                 : {
     233                 :     // should we keep track of the need to write this back to disk?
     234              18 :     bytes = new_end;
     235              18 : }
     236                 : 
     237                 : /************************************************************************/
     238                 : /*                          AddBlockToIndex()                           */
     239                 : /************************************************************************/
     240                 : 
     241              14 : void VecSegDataIndex::AddBlockToIndex( uint32 block )
     242                 : 
     243                 : {
     244              14 :     GetIndex(); // force loading.
     245                 :         
     246              14 :     block_index.push_back( block );
     247              14 :     block_count++;
     248              14 :     dirty = true;
     249              14 : }
     250                 : 
     251                 : /************************************************************************/
     252                 : /*                              SetDirty()                              */
     253                 : /*                                                                      */
     254                 : /*      This method is primarily used to mark the need to write the     */
     255                 : /*      index when the location changes.                                */
     256                 : /************************************************************************/
     257                 : 
     258               0 : void VecSegDataIndex::SetDirty()
     259                 : 
     260                 : {
     261               0 :     dirty = true;
     262               0 : }
     263                 : 
     264                 : /************************************************************************/
     265                 : /*                          VacateBlockRange()                          */
     266                 : /*                                                                      */
     267                 : /*      Move any blocks in the indicated block range to the end of      */
     268                 : /*      the segment to make space for a growing header.                 */
     269                 : /************************************************************************/
     270                 : 
     271               0 : void VecSegDataIndex::VacateBlockRange( uint32 start, uint32 count )
     272                 : 
     273                 : {
     274               0 :     GetIndex(); // make sure loaded.
     275                 : 
     276                 :     unsigned int i;
     277               0 :     uint32  next_block = (uint32) (vs->GetContentSize() / block_page_size);
     278                 : 
     279               0 :     for( i = 0; i < block_count; i++ )
     280                 :     {
     281               0 :         if( block_index[i] >= start && block_index[i] < start+count )
     282                 :         {
     283                 :             vs->MoveData( block_index[i] * block_page_size,
     284                 :                           next_block * block_page_size, 
     285               0 :                           block_page_size );
     286               0 :             block_index[i] = next_block;
     287               0 :             dirty = true;
     288               0 :             next_block++;
     289                 :         }
     290                 :     }
     291               0 : }

Generated by: LCOV version 1.7