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

« back to all changes in this revision

Viewing changes to frmts/pcidsk/sdk/segment/cpcidskvectorsegment_consistencycheck.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 CPCIDSKVectorSegment class's 
 
4
 *           ConsistencyCheck() method.
 
5
 * 
 
6
 ******************************************************************************
 
7
 * Copyright (c) 2010
 
8
 * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
 
9
 *
 
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:
 
16
 *
 
17
 * The above copyright notice and this permission notice shall be included
 
18
 * in all copies or substantial portions of the Software.
 
19
 *
 
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
 ****************************************************************************/
 
28
 
 
29
#include "pcidsk_file.h"
 
30
#include "pcidsk_exception.h"
 
31
#include "core/pcidsk_utils.h"
 
32
#include "segment/cpcidskvectorsegment.h"
 
33
#include <cstring>
 
34
#include <cstdio>
 
35
 
 
36
using namespace PCIDSK;
 
37
 
 
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;  
 
43
 
 
44
/************************************************************************/
 
45
/* ==================================================================== */
 
46
/*                           SpaceMap                                   */
 
47
/*                                                                      */
 
48
/*    Helper class to track space allocations.                          */
 
49
/* ==================================================================== */
 
50
/************************************************************************/
 
51
 
 
52
class SpaceMap
 
53
{
 
54
public:
 
55
    std::vector<uint32>  offsets;
 
56
    std::vector<uint32>  sizes;
 
57
 
 
58
    // binary search for the offset closes to our target or earlier.
 
59
    uint32  FindPreceding( uint32 offset )
 
60
        {
 
61
            if( offsets.size() == 0 )
 
62
                return 0;
 
63
 
 
64
            uint32 start=0, end=offsets.size()-1;
 
65
 
 
66
            while( end > start )
 
67
            {
 
68
                uint32 middle = (start+end+1) / 2;
 
69
                if( offsets[middle] > offset )
 
70
                    end = middle-1;
 
71
                else if( offsets[middle] < offset )
 
72
                    start = middle;
 
73
                else
 
74
                    return middle;
 
75
            }
 
76
            
 
77
            return start;
 
78
        }
 
79
 
 
80
    bool    AddChunk( uint32 offset, uint32 size ) 
 
81
        {
 
82
            uint32 preceding = FindPreceding( offset );
 
83
 
 
84
            // special case for empty
 
85
            if( offsets.size() == 0 )
 
86
            {
 
87
                offsets.push_back( offset );
 
88
                sizes.push_back( size );
 
89
                return false;
 
90
            }
 
91
                    
 
92
            // special case for before first.
 
93
            if( offsets.size() > 0 && offset < offsets[0] )
 
94
            {
 
95
                if( offset+size > offsets[0] )
 
96
                    return true;
 
97
 
 
98
                if( offset+size == offsets[0] )
 
99
                {
 
100
                    offsets[0] = offset;
 
101
                    sizes[0] += size;
 
102
                }
 
103
                else
 
104
                {
 
105
                    offsets.insert( offsets.begin(), offset );
 
106
                    sizes.insert( sizes.begin(), size );
 
107
                }
 
108
                return false;
 
109
            }
 
110
 
 
111
            if( offsets[preceding] + sizes[preceding] > offset )
 
112
            {
 
113
                // conflict!
 
114
                return true;
 
115
            }
 
116
 
 
117
            if( preceding+1 < offsets.size()
 
118
                && offsets[preceding+1] < offset+size )
 
119
            {
 
120
                // conflict!
 
121
                return true;
 
122
            }
 
123
 
 
124
            // can we merge into preceding entry?
 
125
            if( offsets[preceding] + sizes[preceding] == offset )
 
126
            {
 
127
                sizes[preceding] += size;
 
128
                return false;
 
129
            }
 
130
 
 
131
            // can we merge into following entry?
 
132
            if( preceding+1 < offsets.size() 
 
133
                && offsets[preceding+1] == offset+size )
 
134
            {
 
135
                offsets[preceding+1] = offset;
 
136
                sizes[preceding+1] += size;
 
137
                return false;
 
138
            }
 
139
 
 
140
            // Insert after preceding.
 
141
            offsets.insert( offsets.begin() + (preceding + 1), offset );
 
142
            sizes.insert( sizes.begin() + (preceding + 1), size );
 
143
 
 
144
            return false;
 
145
        }
 
146
};
 
147
 
 
148
 
 
149
 
 
150
/************************************************************************/
 
151
/*                          ConsistencyCheck()                          */
 
152
/************************************************************************/
 
153
 
 
154
std::string CPCIDSKVectorSegment::ConsistencyCheck()
 
155
 
 
156
{
 
157
    Synchronize();
 
158
    
 
159
    std::string report = CPCIDSKSegment::ConsistencyCheck();
 
160
 
 
161
    report += ConsistencyCheck_Header();
 
162
    report += ConsistencyCheck_DataIndices();
 
163
    report += ConsistencyCheck_ShapeIndices();
 
164
 
 
165
    if( report != "" )
 
166
        fprintf( stderr, "ConsistencyCheck() Report:\n%s", report.c_str() );
 
167
 
 
168
    return report;
 
169
}
 
170
 
 
171
/************************************************************************/
 
172
/*                      ConsistencyCheck_Header()                       */
 
173
/*                                                                      */
 
174
/*      Check that the header sections are non-overlapping and fit      */
 
175
/*      in the blocks indicated.                                        */
 
176
/*                                                                      */
 
177
/*      Verify some "fixed" values.                                     */
 
178
/************************************************************************/
 
179
 
 
180
std::string CPCIDSKVectorSegment::ConsistencyCheck_Header()
 
181
 
 
182
{
 
183
    std::string report;
 
184
 
 
185
    LoadHeader();
 
186
 
 
187
    if( vh.header_blocks < 1 )
 
188
        report += "less than one header_blocks\n";
 
189
 
 
190
    if( vh.header_blocks * block_page_size > GetContentSize() )
 
191
        report += "header blocks larger than segment size!";
 
192
 
 
193
 
 
194
    SpaceMap smap;
 
195
    int i;
 
196
 
 
197
    for( i = 0; i < 4; i++ )
 
198
    {
 
199
        if( smap.AddChunk( vh.section_offsets[i], vh.section_sizes[i] ) )
 
200
            report += "A header section overlaps another header section!\n";
 
201
 
 
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";
 
205
    }
 
206
 
 
207
    return report;
 
208
}
 
209
 
 
210
/************************************************************************/
 
211
/*                    ConsistencyCheck_DataIndices()                    */
 
212
/************************************************************************/
 
213
 
 
214
std::string CPCIDSKVectorSegment::ConsistencyCheck_DataIndices()
 
215
 
 
216
{
 
217
    std::string report;
 
218
    unsigned int section;
 
219
 
 
220
    SpaceMap smap;
 
221
 
 
222
    smap.AddChunk( 0, vh.header_blocks );
 
223
 
 
224
    for( section = 0; section < 2; section++ )
 
225
    {
 
226
        const std::vector<uint32> *map = di[section].GetIndex();
 
227
        unsigned int i;
 
228
 
 
229
        for( i = 0; i < map->size(); i++ )
 
230
        {
 
231
            if( smap.AddChunk( (*map)[i], 1 ) )
 
232
            {
 
233
                char msg[100];
 
234
 
 
235
                sprintf( msg, "Conflict for block %d, held by at least data index '%d'.\n",
 
236
                         (*map)[i], section );
 
237
 
 
238
                report += msg;
 
239
            }
 
240
        }
 
241
 
 
242
        if( di[section].bytes > di[section].block_count * block_page_size )
 
243
        {
 
244
            report += "bytes for data index to large for block count.\n";
 
245
        }
 
246
    }
 
247
 
 
248
    return report;
 
249
}
 
250
 
 
251
/************************************************************************/
 
252
/*                   ConsistencyCheck_ShapeIndices()                    */
 
253
/************************************************************************/
 
254
 
 
255
std::string CPCIDSKVectorSegment::ConsistencyCheck_ShapeIndices()
 
256
 
 
257
{
 
258
    std::string report;
 
259
    SpaceMap  vmap, rmap;
 
260
    std::map<ShapeId,uint32> id_map;
 
261
    int iShape;
 
262
 
 
263
    for( iShape = 0; iShape < shape_count; iShape++ )
 
264
    {
 
265
        AccessShapeByIndex( iShape );
 
266
 
 
267
        unsigned int toff = iShape - shape_index_start;
 
268
 
 
269
        if( id_map.count(shape_index_ids[toff]) > 0 )
 
270
        {
 
271
            char msg[100];
 
272
 
 
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]]);
 
276
            report += msg;
 
277
        }
 
278
 
 
279
        id_map[shape_index_ids[toff]] = toff;
 
280
 
 
281
 
 
282
        if( shape_index_vertex_off[toff] != 0xffffffff )
 
283
        {
 
284
            uint32 vertex_count;
 
285
            uint32 vertex_size;
 
286
            uint32 vert_off = shape_index_vertex_off[toff];
 
287
 
 
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 );
 
290
            if( needs_swap )
 
291
            {
 
292
                SwapData( &vertex_count, 4, 1 );
 
293
                SwapData( &vertex_size, 4, 1 );
 
294
            }
 
295
            
 
296
            if( vertex_size < vertex_count * 24 + 8 )
 
297
            {
 
298
                report += "vertices for shape index seem larger than space allocated.\n";
 
299
            }
 
300
 
 
301
            if( vert_off + vertex_size > di[sec_vert].GetSectionEnd() )
 
302
            {
 
303
                report += "record overruns data index bytes.\n";
 
304
            }
 
305
 
 
306
            if( vmap.AddChunk( vert_off, vertex_size ) )
 
307
            {
 
308
                report += "vertex overlap detected!\n";
 
309
            }
 
310
        }
 
311
 
 
312
        if( shape_index_record_off[toff] != 0xffffffff )
 
313
        {
 
314
            uint32 rec_off = shape_index_record_off[toff];
 
315
            uint32 offset = rec_off;
 
316
            uint32 record_size, i;
 
317
            ShapeField wfld;
 
318
 
 
319
            memcpy( &record_size, GetData( sec_record, rec_off, NULL, 4 ), 4 );
 
320
            if( needs_swap )
 
321
                SwapData( &record_size, 4, 1 );
 
322
 
 
323
            offset += 4;
 
324
            for( i = 0; i < vh.field_names.size(); i++ )
 
325
                offset = ReadField( offset, wfld, vh.field_types[i], 
 
326
                                    sec_record );
 
327
 
 
328
            if( offset - rec_off > record_size )
 
329
                report += "record actually larger than declared record size.\n";
 
330
            
 
331
            if( rec_off + record_size > di[sec_record].GetSectionEnd() )
 
332
            {
 
333
                report += "record overruns data index bytes.\n";
 
334
            }
 
335
            
 
336
            if( rmap.AddChunk( rec_off, record_size ) )
 
337
            {
 
338
                report += "record overlap detected!\n";
 
339
            }
 
340
        }
 
341
    }
 
342
 
 
343
    return report;
 
344
}