~ubuntu-branches/debian/sid/gdal/sid

« back to all changes in this revision

Viewing changes to frmts/pcidsk/sdk/segment/vecsegdataindex.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-05-07 15:04:42 UTC
  • mfrom: (5.5.16 experimental)
  • Revision ID: package-import@ubuntu.com-20120507150442-2eks97loeh6rq005
Tags: 1.9.0-1
* Ready for sid, starting transition.
* All symfiles updated to latest builds.
* Added dh_numpy call in debian/rules to depend on numpy ABI.
* Policy bumped to 3.9.3, no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
VecSegDataIndex::VecSegDataIndex()
 
53
 
 
54
{
 
55
    block_initialized = false;
 
56
    vs = NULL;
 
57
    dirty = false;
 
58
}
 
59
 
 
60
/************************************************************************/
 
61
/*                          ~VecSegDataIndex()                          */
 
62
/************************************************************************/
 
63
 
 
64
VecSegDataIndex::~VecSegDataIndex()
 
65
 
 
66
{
 
67
}
 
68
 
 
69
/************************************************************************/
 
70
/*                             Initialize()                             */
 
71
/************************************************************************/
 
72
 
 
73
void VecSegDataIndex::Initialize( CPCIDSKVectorSegment *vs, int section )
 
74
 
 
75
{
 
76
    this->section = section;
 
77
    this->vs = vs;
 
78
 
 
79
    if( section == sec_vert )
 
80
        offset_on_disk_within_section = 0;
 
81
    else 
 
82
        offset_on_disk_within_section = vs->di[sec_vert].SerializedSize();
 
83
 
 
84
    uint32 offset = offset_on_disk_within_section 
 
85
        + vs->vh.section_offsets[hsec_shape];
 
86
 
 
87
    memcpy( &block_count, vs->GetData(sec_raw,offset,NULL,4), 4);
 
88
    memcpy( &bytes, vs->GetData(sec_raw,offset+4,NULL,4), 4);
 
89
 
 
90
    bool needs_swap = !BigEndianSystem();
 
91
 
 
92
    if( needs_swap )
 
93
    {
 
94
        SwapData( &block_count, 4, 1 );
 
95
        SwapData( &bytes, 4, 1 );
 
96
    }
 
97
 
 
98
    size_on_disk = block_count * 4 + 8;
 
99
}
 
100
 
 
101
/************************************************************************/
 
102
/*                           SerializedSize()                           */
 
103
/************************************************************************/
 
104
 
 
105
uint32 VecSegDataIndex::SerializedSize()
 
106
 
 
107
{
 
108
    return 8 + 4 * block_count;
 
109
}
 
110
 
 
111
/************************************************************************/
 
112
/*                           GetBlockIndex()                            */
 
113
/************************************************************************/
 
114
 
 
115
const std::vector<uint32> *VecSegDataIndex::GetIndex()
 
116
 
 
117
{
 
118
/* -------------------------------------------------------------------- */
 
119
/*      Load block map if needed.                                       */
 
120
/* -------------------------------------------------------------------- */
 
121
    if( !block_initialized )
 
122
    {
 
123
        bool needs_swap = !BigEndianSystem();
 
124
 
 
125
        block_index.resize( block_count );
 
126
        if( block_count > 0 )
 
127
        {
 
128
            vs->ReadFromFile( &(block_index[0]), 
 
129
                              offset_on_disk_within_section
 
130
                              + vs->vh.section_offsets[hsec_shape] + 8, 
 
131
                              4 * block_count );
 
132
 
 
133
            if( needs_swap )
 
134
                SwapData( &(block_index[0]), 4, block_count );
 
135
        }
 
136
 
 
137
        block_initialized = true;
 
138
    }
 
139
 
 
140
    return &block_index;
 
141
}
 
142
                             
 
143
/************************************************************************/
 
144
/*                               Flush()                                */
 
145
/************************************************************************/
 
146
 
 
147
void VecSegDataIndex::Flush()
 
148
 
 
149
{
 
150
    if( !dirty )
 
151
        return;
 
152
 
 
153
    GetIndex(); // force loading if not already loaded!
 
154
 
 
155
    PCIDSKBuffer wbuf( SerializedSize() );
 
156
 
 
157
    memcpy( wbuf.buffer + 0, &block_count, 4 );
 
158
    memcpy( wbuf.buffer + 4, &bytes, 4 );
 
159
    memcpy( wbuf.buffer + 8, &(block_index[0]), 4*block_count );
 
160
 
 
161
    bool needs_swap = !BigEndianSystem();
 
162
 
 
163
    if( needs_swap )
 
164
        SwapData( wbuf.buffer, 4, block_count+2 );
 
165
 
 
166
    // Make sure this section of the header is large enough.
 
167
    int32 shift = (int32) wbuf.buffer_size - (int32) size_on_disk;
 
168
    
 
169
    if( shift != 0 )
 
170
    {
 
171
        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
        vs->vh.GrowSection( hsec_shape, old_section_size + shift );
 
177
 
 
178
        if( section == sec_vert )
 
179
        {
 
180
            // move record block index and shape index.
 
181
            vs->MoveData( vs->vh.section_offsets[hsec_shape]
 
182
                          + vs->di[sec_vert].size_on_disk,
 
183
                          vs->vh.section_offsets[hsec_shape]
 
184
                          + vs->di[sec_vert].size_on_disk + shift,
 
185
                          old_section_size - size_on_disk );
 
186
        }
 
187
        else
 
188
        {
 
189
            // only move shape index.
 
190
            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
                          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
                          - vs->di[sec_record].size_on_disk );
 
200
        }
 
201
 
 
202
        if( section == sec_vert )
 
203
            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
                     + vs->vh.section_offsets[hsec_shape], 
 
210
                     wbuf.buffer_size );
 
211
 
 
212
    size_on_disk = wbuf.buffer_size;
 
213
    dirty = false;
 
214
}
 
215
 
 
216
/************************************************************************/
 
217
/*                           GetSectionEnd()                            */
 
218
/************************************************************************/
 
219
 
 
220
uint32 VecSegDataIndex::GetSectionEnd()
 
221
 
 
222
{
 
223
    return bytes;
 
224
}
 
225
 
 
226
/************************************************************************/
 
227
/*                           SetSectionEnd()                            */
 
228
/************************************************************************/
 
229
 
 
230
void VecSegDataIndex::SetSectionEnd( uint32 new_end )
 
231
 
 
232
{
 
233
    // should we keep track of the need to write this back to disk?
 
234
    bytes = new_end;
 
235
}
 
236
 
 
237
/************************************************************************/
 
238
/*                          AddBlockToIndex()                           */
 
239
/************************************************************************/
 
240
 
 
241
void VecSegDataIndex::AddBlockToIndex( uint32 block )
 
242
 
 
243
{
 
244
    GetIndex(); // force loading.
 
245
        
 
246
    block_index.push_back( block );
 
247
    block_count++;
 
248
    dirty = true;
 
249
}
 
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
void VecSegDataIndex::SetDirty()
 
259
 
 
260
{
 
261
    dirty = true;
 
262
}
 
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
void VecSegDataIndex::VacateBlockRange( uint32 start, uint32 count )
 
272
 
 
273
{
 
274
    GetIndex(); // make sure loaded.
 
275
 
 
276
    unsigned int i;
 
277
    uint32  next_block = (uint32) (vs->GetContentSize() / block_page_size);
 
278
 
 
279
    for( i = 0; i < block_count; i++ )
 
280
    {
 
281
        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
                          block_page_size );
 
286
            block_index[i] = next_block;
 
287
            dirty = true;
 
288
            next_block++;
 
289
        }
 
290
    }
 
291
}