1
/******************************************************************************
3
* Purpose: Implementation of the CPCIDSKVectorSegment class's
4
* ConsistencyCheck() method.
6
******************************************************************************
8
* PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
10
* Permission is hereby granted, free of charge, to any person obtaining a
11
* copy of this software and associated documentation files (the "Software"),
12
* to deal in the Software without restriction, including without limitation
13
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
14
* and/or sell copies of the Software, and to permit persons to whom the
15
* Software is furnished to do so, subject to the following conditions:
17
* The above copyright notice and this permission notice shall be included
18
* in all copies or substantial portions of the Software.
20
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26
* DEALINGS IN THE SOFTWARE.
27
****************************************************************************/
29
#include "pcidsk_file.h"
30
#include "pcidsk_exception.h"
31
#include "core/pcidsk_utils.h"
32
#include "segment/cpcidskvectorsegment.h"
36
using namespace PCIDSK;
38
/* -------------------------------------------------------------------- */
39
/* Size of a block in the record/vertice block tables. This is */
40
/* determined by the PCIDSK format and may not be changed. */
41
/* -------------------------------------------------------------------- */
42
static const int block_page_size = 8192;
44
/************************************************************************/
45
/* ==================================================================== */
48
/* Helper class to track space allocations. */
49
/* ==================================================================== */
50
/************************************************************************/
55
std::vector<uint32> offsets;
56
std::vector<uint32> sizes;
58
// binary search for the offset closes to our target or earlier.
59
uint32 FindPreceding( uint32 offset )
61
if( offsets.size() == 0 )
64
uint32 start=0, end=offsets.size()-1;
68
uint32 middle = (start+end+1) / 2;
69
if( offsets[middle] > offset )
71
else if( offsets[middle] < offset )
80
bool AddChunk( uint32 offset, uint32 size )
82
uint32 preceding = FindPreceding( offset );
84
// special case for empty
85
if( offsets.size() == 0 )
87
offsets.push_back( offset );
88
sizes.push_back( size );
92
// special case for before first.
93
if( offsets.size() > 0 && offset < offsets[0] )
95
if( offset+size > offsets[0] )
98
if( offset+size == offsets[0] )
105
offsets.insert( offsets.begin(), offset );
106
sizes.insert( sizes.begin(), size );
111
if( offsets[preceding] + sizes[preceding] > offset )
117
if( preceding+1 < offsets.size()
118
&& offsets[preceding+1] < offset+size )
124
// can we merge into preceding entry?
125
if( offsets[preceding] + sizes[preceding] == offset )
127
sizes[preceding] += size;
131
// can we merge into following entry?
132
if( preceding+1 < offsets.size()
133
&& offsets[preceding+1] == offset+size )
135
offsets[preceding+1] = offset;
136
sizes[preceding+1] += size;
140
// Insert after preceding.
141
offsets.insert( offsets.begin() + (preceding + 1), offset );
142
sizes.insert( sizes.begin() + (preceding + 1), size );
150
/************************************************************************/
151
/* ConsistencyCheck() */
152
/************************************************************************/
154
std::string CPCIDSKVectorSegment::ConsistencyCheck()
159
std::string report = CPCIDSKSegment::ConsistencyCheck();
161
report += ConsistencyCheck_Header();
162
report += ConsistencyCheck_DataIndices();
163
report += ConsistencyCheck_ShapeIndices();
166
fprintf( stderr, "ConsistencyCheck() Report:\n%s", report.c_str() );
171
/************************************************************************/
172
/* ConsistencyCheck_Header() */
174
/* Check that the header sections are non-overlapping and fit */
175
/* in the blocks indicated. */
177
/* Verify some "fixed" values. */
178
/************************************************************************/
180
std::string CPCIDSKVectorSegment::ConsistencyCheck_Header()
187
if( vh.header_blocks < 1 )
188
report += "less than one header_blocks\n";
190
if( vh.header_blocks * block_page_size > GetContentSize() )
191
report += "header blocks larger than segment size!";
197
for( i = 0; i < 4; i++ )
199
if( smap.AddChunk( vh.section_offsets[i], vh.section_sizes[i] ) )
200
report += "A header section overlaps another header section!\n";
202
if( vh.section_offsets[i] + vh.section_sizes[i]
203
> vh.header_blocks * block_page_size )
204
report += "A header section goes past end of header.\n";
210
/************************************************************************/
211
/* ConsistencyCheck_DataIndices() */
212
/************************************************************************/
214
std::string CPCIDSKVectorSegment::ConsistencyCheck_DataIndices()
218
unsigned int section;
222
smap.AddChunk( 0, vh.header_blocks );
224
for( section = 0; section < 2; section++ )
226
const std::vector<uint32> *map = di[section].GetIndex();
229
for( i = 0; i < map->size(); i++ )
231
if( smap.AddChunk( (*map)[i], 1 ) )
235
sprintf( msg, "Conflict for block %d, held by at least data index '%d'.\n",
236
(*map)[i], section );
242
if( di[section].bytes > di[section].block_count * block_page_size )
244
report += "bytes for data index to large for block count.\n";
251
/************************************************************************/
252
/* ConsistencyCheck_ShapeIndices() */
253
/************************************************************************/
255
std::string CPCIDSKVectorSegment::ConsistencyCheck_ShapeIndices()
260
std::map<ShapeId,uint32> id_map;
263
for( iShape = 0; iShape < shape_count; iShape++ )
265
AccessShapeByIndex( iShape );
267
unsigned int toff = iShape - shape_index_start;
269
if( id_map.count(shape_index_ids[toff]) > 0 )
273
sprintf( msg, "ShapeID %d is used for shape %d and %d!\n",
274
shape_index_ids[toff],
275
toff, id_map[shape_index_ids[toff]]);
279
id_map[shape_index_ids[toff]] = toff;
282
if( shape_index_vertex_off[toff] != 0xffffffff )
286
uint32 vert_off = shape_index_vertex_off[toff];
288
memcpy( &vertex_size, GetData( sec_vert, vert_off, NULL, 4 ), 4 );
289
memcpy( &vertex_count, GetData( sec_vert, vert_off+4, NULL, 4 ), 4 );
292
SwapData( &vertex_count, 4, 1 );
293
SwapData( &vertex_size, 4, 1 );
296
if( vertex_size < vertex_count * 24 + 8 )
298
report += "vertices for shape index seem larger than space allocated.\n";
301
if( vert_off + vertex_size > di[sec_vert].GetSectionEnd() )
303
report += "record overruns data index bytes.\n";
306
if( vmap.AddChunk( vert_off, vertex_size ) )
308
report += "vertex overlap detected!\n";
312
if( shape_index_record_off[toff] != 0xffffffff )
314
uint32 rec_off = shape_index_record_off[toff];
315
uint32 offset = rec_off;
316
uint32 record_size, i;
319
memcpy( &record_size, GetData( sec_record, rec_off, NULL, 4 ), 4 );
321
SwapData( &record_size, 4, 1 );
324
for( i = 0; i < vh.field_names.size(); i++ )
325
offset = ReadField( offset, wfld, vh.field_types[i],
328
if( offset - rec_off > record_size )
329
report += "record actually larger than declared record size.\n";
331
if( rec_off + record_size > di[sec_record].GetSectionEnd() )
333
report += "record overruns data index bytes.\n";
336
if( rmap.AddChunk( rec_off, record_size ) )
338
report += "record overlap detected!\n";