LCOV - code coverage report
Current view: directory - frmts/pcidsk/sdk/segment - cpcidskvectorsegment_consistencycheck.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 120 0 0.0 %
Date: 2012-04-28 Functions: 8 0 0.0 %

       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               0 : {
      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               0 :     uint32  FindPreceding( uint32 offset )
      60                 :         {
      61               0 :             if( offsets.size() == 0 )
      62               0 :                 return 0;
      63                 : 
      64               0 :             uint32 start=0, end=offsets.size()-1;
      65                 : 
      66               0 :             while( end > start )
      67                 :             {
      68               0 :                 uint32 middle = (start+end+1) / 2;
      69               0 :                 if( offsets[middle] > offset )
      70               0 :                     end = middle-1;
      71               0 :                 else if( offsets[middle] < offset )
      72               0 :                     start = middle;
      73                 :                 else
      74               0 :                     return middle;
      75                 :             }
      76                 :             
      77               0 :             return start;
      78                 :         }
      79                 : 
      80               0 :     bool    AddChunk( uint32 offset, uint32 size ) 
      81                 :         {
      82               0 :             uint32 preceding = FindPreceding( offset );
      83                 : 
      84                 :             // special case for empty
      85               0 :             if( offsets.size() == 0 )
      86                 :             {
      87               0 :                 offsets.push_back( offset );
      88               0 :                 sizes.push_back( size );
      89               0 :                 return false;
      90                 :             }
      91                 :                     
      92                 :             // special case for before first.
      93               0 :             if( offsets.size() > 0 && offset < offsets[0] )
      94                 :             {
      95               0 :                 if( offset+size > offsets[0] )
      96               0 :                     return true;
      97                 : 
      98               0 :                 if( offset+size == offsets[0] )
      99                 :                 {
     100               0 :                     offsets[0] = offset;
     101               0 :                     sizes[0] += size;
     102                 :                 }
     103                 :                 else
     104                 :                 {
     105               0 :                     offsets.insert( offsets.begin(), offset );
     106               0 :                     sizes.insert( sizes.begin(), size );
     107                 :                 }
     108               0 :                 return false;
     109                 :             }
     110                 : 
     111               0 :             if( offsets[preceding] + sizes[preceding] > offset )
     112                 :             {
     113                 :                 // conflict!
     114               0 :                 return true;
     115                 :             }
     116                 : 
     117               0 :             if( preceding+1 < offsets.size()
     118                 :                 && offsets[preceding+1] < offset+size )
     119                 :             {
     120                 :                 // conflict!
     121               0 :                 return true;
     122                 :             }
     123                 : 
     124                 :             // can we merge into preceding entry?
     125               0 :             if( offsets[preceding] + sizes[preceding] == offset )
     126                 :             {
     127               0 :                 sizes[preceding] += size;
     128               0 :                 return false;
     129                 :             }
     130                 : 
     131                 :             // can we merge into following entry?
     132               0 :             if( preceding+1 < offsets.size() 
     133                 :                 && offsets[preceding+1] == offset+size )
     134                 :             {
     135               0 :                 offsets[preceding+1] = offset;
     136               0 :                 sizes[preceding+1] += size;
     137               0 :                 return false;
     138                 :             }
     139                 : 
     140                 :             // Insert after preceding.
     141               0 :             offsets.insert( offsets.begin() + (preceding + 1), offset );
     142               0 :             sizes.insert( sizes.begin() + (preceding + 1), size );
     143                 : 
     144               0 :             return false;
     145                 :         }
     146                 : };
     147                 : 
     148                 : 
     149                 : 
     150                 : /************************************************************************/
     151                 : /*                          ConsistencyCheck()                          */
     152                 : /************************************************************************/
     153                 : 
     154               0 : std::string CPCIDSKVectorSegment::ConsistencyCheck()
     155                 : 
     156                 : {
     157               0 :     Synchronize();
     158                 :     
     159               0 :     std::string report = CPCIDSKSegment::ConsistencyCheck();
     160                 : 
     161               0 :     report += ConsistencyCheck_Header();
     162               0 :     report += ConsistencyCheck_DataIndices();
     163               0 :     report += ConsistencyCheck_ShapeIndices();
     164                 : 
     165               0 :     if( report != "" )
     166               0 :         fprintf( stderr, "ConsistencyCheck() Report:\n%s", report.c_str() );
     167                 : 
     168               0 :     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               0 : std::string CPCIDSKVectorSegment::ConsistencyCheck_Header()
     181                 : 
     182                 : {
     183               0 :     std::string report;
     184                 : 
     185               0 :     LoadHeader();
     186                 : 
     187               0 :     if( vh.header_blocks < 1 )
     188               0 :         report += "less than one header_blocks\n";
     189                 : 
     190               0 :     if( vh.header_blocks * block_page_size > GetContentSize() )
     191               0 :         report += "header blocks larger than segment size!";
     192                 : 
     193                 : 
     194               0 :     SpaceMap smap;
     195                 :     int i;
     196                 : 
     197               0 :     for( i = 0; i < 4; i++ )
     198                 :     {
     199               0 :         if( smap.AddChunk( vh.section_offsets[i], vh.section_sizes[i] ) )
     200               0 :             report += "A header section overlaps another header section!\n";
     201                 : 
     202               0 :         if( vh.section_offsets[i] + vh.section_sizes[i] 
     203                 :             > vh.header_blocks * block_page_size )
     204               0 :             report += "A header section goes past end of header.\n";
     205                 :     }
     206                 : 
     207               0 :     return report;
     208                 : }
     209                 : 
     210                 : /************************************************************************/
     211                 : /*                    ConsistencyCheck_DataIndices()                    */
     212                 : /************************************************************************/
     213                 : 
     214               0 : std::string CPCIDSKVectorSegment::ConsistencyCheck_DataIndices()
     215                 : 
     216                 : {
     217               0 :     std::string report;
     218                 :     unsigned int section;
     219                 : 
     220               0 :     SpaceMap smap;
     221                 : 
     222               0 :     smap.AddChunk( 0, vh.header_blocks );
     223                 : 
     224               0 :     for( section = 0; section < 2; section++ )
     225                 :     {
     226               0 :         const std::vector<uint32> *map = di[section].GetIndex();
     227                 :         unsigned int i;
     228                 : 
     229               0 :         for( i = 0; i < map->size(); i++ )
     230                 :         {
     231               0 :             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               0 :                          (*map)[i], section );
     237                 : 
     238               0 :                 report += msg;
     239                 :             }
     240                 :         }
     241                 : 
     242               0 :         if( di[section].bytes > di[section].block_count * block_page_size )
     243                 :         {
     244               0 :             report += "bytes for data index to large for block count.\n";
     245                 :         }
     246                 :     }
     247                 : 
     248               0 :     return report;
     249                 : }
     250                 : 
     251                 : /************************************************************************/
     252                 : /*                   ConsistencyCheck_ShapeIndices()                    */
     253                 : /************************************************************************/
     254                 : 
     255               0 : std::string CPCIDSKVectorSegment::ConsistencyCheck_ShapeIndices()
     256                 : 
     257                 : {
     258               0 :     std::string report;
     259               0 :     SpaceMap  vmap, rmap;
     260               0 :     std::map<ShapeId,uint32> id_map;
     261                 :     int iShape;
     262                 : 
     263               0 :     for( iShape = 0; iShape < shape_count; iShape++ )
     264                 :     {
     265               0 :         AccessShapeByIndex( iShape );
     266                 : 
     267               0 :         unsigned int toff = iShape - shape_index_start;
     268                 : 
     269               0 :         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               0 :                      toff, id_map[shape_index_ids[toff]]);
     276               0 :             report += msg;
     277                 :         }
     278                 : 
     279               0 :         id_map[shape_index_ids[toff]] = toff;
     280                 : 
     281                 : 
     282               0 :         if( shape_index_vertex_off[toff] != 0xffffffff )
     283                 :         {
     284                 :             uint32 vertex_count;
     285                 :             uint32 vertex_size;
     286               0 :             uint32 vert_off = shape_index_vertex_off[toff];
     287                 : 
     288               0 :             memcpy( &vertex_size, GetData( sec_vert, vert_off, NULL, 4 ), 4 );
     289               0 :             memcpy( &vertex_count, GetData( sec_vert, vert_off+4, NULL, 4 ), 4 );
     290               0 :             if( needs_swap )
     291                 :             {
     292               0 :                 SwapData( &vertex_count, 4, 1 );
     293               0 :                 SwapData( &vertex_size, 4, 1 );
     294                 :             }
     295                 :             
     296               0 :             if( vertex_size < vertex_count * 24 + 8 )
     297                 :             {
     298               0 :                 report += "vertices for shape index seem larger than space allocated.\n";
     299                 :             }
     300                 : 
     301               0 :             if( vert_off + vertex_size > di[sec_vert].GetSectionEnd() )
     302                 :             {
     303               0 :                 report += "record overruns data index bytes.\n";
     304                 :             }
     305                 : 
     306               0 :             if( vmap.AddChunk( vert_off, vertex_size ) )
     307                 :             {
     308               0 :                 report += "vertex overlap detected!\n";
     309                 :             }
     310                 :         }
     311                 : 
     312               0 :         if( shape_index_record_off[toff] != 0xffffffff )
     313                 :         {
     314               0 :             uint32 rec_off = shape_index_record_off[toff];
     315               0 :             uint32 offset = rec_off;
     316                 :             uint32 record_size, i;
     317               0 :             ShapeField wfld;
     318                 : 
     319               0 :             memcpy( &record_size, GetData( sec_record, rec_off, NULL, 4 ), 4 );
     320               0 :             if( needs_swap )
     321               0 :                 SwapData( &record_size, 4, 1 );
     322                 : 
     323               0 :             offset += 4;
     324               0 :             for( i = 0; i < vh.field_names.size(); i++ )
     325                 :                 offset = ReadField( offset, wfld, vh.field_types[i], 
     326               0 :                                     sec_record );
     327                 : 
     328               0 :             if( offset - rec_off > record_size )
     329               0 :                 report += "record actually larger than declared record size.\n";
     330                 :             
     331               0 :             if( rec_off + record_size > di[sec_record].GetSectionEnd() )
     332                 :             {
     333               0 :                 report += "record overruns data index bytes.\n";
     334                 :             }
     335                 :             
     336               0 :             if( rmap.AddChunk( rec_off, record_size ) )
     337                 :             {
     338               0 :                 report += "record overlap detected!\n";
     339               0 :             }
     340                 :         }
     341                 :     }
     342                 : 
     343               0 :     return report;
     344                 : }

Generated by: LCOV version 1.7