LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/mitab - mitab_maptoolblock.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 103
Code covered: 59.2 % Executed lines: 61

       1                 : /**********************************************************************
       2                 :  * $Id: mitab_maptoolblock.cpp,v 1.7 2006/11/28 18:49:08 dmorissette Exp $
       3                 :  *
       4                 :  * Name:     mitab_maptoollock.cpp
       5                 :  * Project:  MapInfo TAB Read/Write library
       6                 :  * Language: C++
       7                 :  * Purpose:  Implementation of the TABMAPToolBlock class used to handle
       8                 :  *           reading/writing of the .MAP files' drawing tool blocks
       9                 :  * Author:   Daniel Morissette, dmorissette@dmsolutions.ca
      10                 :  *
      11                 :  **********************************************************************
      12                 :  * Copyright (c) 1999, 2000, Daniel Morissette
      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 OR
      25                 :  * 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                 :  * $Log: mitab_maptoolblock.cpp,v $
      34                 :  * Revision 1.7  2006/11/28 18:49:08  dmorissette
      35                 :  * Completed changes to split TABMAPObjectBlocks properly and produce an
      36                 :  * optimal spatial index (bug 1585)
      37                 :  *
      38                 :  * Revision 1.6  2004/06/30 20:29:04  dmorissette
      39                 :  * Fixed refs to old address danmo@videotron.ca
      40                 :  *
      41                 :  * Revision 1.5  2000/11/15 04:13:50  daniel
      42                 :  * Fixed writing of TABMAPToolBlock to allocate a new block when full
      43                 :  *
      44                 :  * Revision 1.4  2000/02/28 17:03:30  daniel
      45                 :  * Changed TABMAPBlockManager to TABBinBlockManager
      46                 :  *
      47                 :  * Revision 1.3  2000/01/15 22:30:44  daniel
      48                 :  * Switch to MIT/X-Consortium OpenSource license
      49                 :  *
      50                 :  * Revision 1.2  1999/09/26 14:59:37  daniel
      51                 :  * Implemented write support
      52                 :  *
      53                 :  * Revision 1.1  1999/09/16 02:39:17  daniel
      54                 :  * Completed read support for most feature types
      55                 :  *
      56                 :  **********************************************************************/
      57                 : 
      58                 : #include "mitab.h"
      59                 : 
      60                 : /*=====================================================================
      61                 :  *                      class TABMAPToolBlock
      62                 :  *====================================================================*/
      63                 : 
      64                 : #define MAP_TOOL_HEADER_SIZE   8
      65                 : 
      66                 : /**********************************************************************
      67                 :  *                   TABMAPToolBlock::TABMAPToolBlock()
      68                 :  *
      69                 :  * Constructor.
      70                 :  **********************************************************************/
      71               4 : TABMAPToolBlock::TABMAPToolBlock(TABAccess eAccessMode /*= TABRead*/):
      72               4 :     TABRawBinBlock(eAccessMode, TRUE)
      73                 : {
      74               4 :     m_nNextToolBlock = m_numDataBytes = 0;
      75                 : 
      76               4 :     m_numBlocksInChain = 1;  // Current block counts as 1
      77                 :  
      78               4 :     m_poBlockManagerRef = NULL;
      79               4 : }
      80                 : 
      81                 : /**********************************************************************
      82                 :  *                   TABMAPToolBlock::~TABMAPToolBlock()
      83                 :  *
      84                 :  * Destructor.
      85                 :  **********************************************************************/
      86               4 : TABMAPToolBlock::~TABMAPToolBlock()
      87                 : {
      88                 :    
      89               4 : }
      90                 : 
      91                 : 
      92                 : /**********************************************************************
      93                 :  *                   TABMAPToolBlock::EndOfChain()
      94                 :  *
      95                 :  * Return TRUE if we reached the end of the last block in the chain
      96                 :  * TABMAPToolBlocks, or FALSE if there is still data to be read from 
      97                 :  * this chain.
      98                 :  **********************************************************************/
      99               6 : GBool TABMAPToolBlock::EndOfChain()
     100                 : {
     101               6 :    if (m_pabyBuf && 
     102                 :        (m_nCurPos < (m_numDataBytes+MAP_TOOL_HEADER_SIZE) || 
     103                 :         m_nNextToolBlock > 0 ) )
     104                 :    {
     105               4 :        return FALSE;  // There is still data to be read.
     106                 :    }
     107                 : 
     108               2 :    return TRUE;
     109                 : }
     110                 : 
     111                 : /**********************************************************************
     112                 :  *                   TABMAPToolBlock::InitBlockFromData()
     113                 :  *
     114                 :  * Perform some initialization on the block after its binary data has
     115                 :  * been set or changed (or loaded from a file).
     116                 :  *
     117                 :  * Returns 0 if succesful or -1 if an error happened, in which case 
     118                 :  * CPLError() will have been called.
     119                 :  **********************************************************************/
     120                 : int     TABMAPToolBlock::InitBlockFromData(GByte *pabyBuf,
     121                 :                                            int nBlockSize, int nSizeUsed, 
     122                 :                                            GBool bMakeCopy /* = TRUE */,
     123                 :                                            FILE *fpSrc /* = NULL */, 
     124               2 :                                            int nOffset /* = 0 */)
     125                 : {
     126                 :     int nStatus;
     127                 : 
     128                 :     /*-----------------------------------------------------------------
     129                 :      * First of all, we must call the base class' InitBlockFromData()
     130                 :      *----------------------------------------------------------------*/
     131                 :     nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf, nBlockSize, nSizeUsed,
     132               2 :                                                 bMakeCopy, fpSrc, nOffset);
     133               2 :     if (nStatus != 0)   
     134               0 :         return nStatus;
     135                 : 
     136                 :     /*-----------------------------------------------------------------
     137                 :      * Validate block type
     138                 :      *----------------------------------------------------------------*/
     139               2 :     if (m_nBlockType != TABMAP_TOOL_BLOCK)
     140                 :     {
     141                 :         CPLError(CE_Failure, CPLE_FileIO,
     142                 :                  "InitBlockFromData(): Invalid Block Type: got %d expected %d",
     143               0 :                  m_nBlockType, TABMAP_TOOL_BLOCK);
     144               0 :         CPLFree(m_pabyBuf);
     145               0 :         m_pabyBuf = NULL;
     146               0 :         return -1;
     147                 :     }
     148                 : 
     149                 :     /*-----------------------------------------------------------------
     150                 :      * Init member variables
     151                 :      *----------------------------------------------------------------*/
     152               2 :     GotoByteInBlock(0x002);
     153               2 :     m_numDataBytes = ReadInt16();       /* Excluding 8 bytes header */
     154                 : 
     155               2 :     m_nNextToolBlock = ReadInt32();
     156                 : 
     157                 :     /*-----------------------------------------------------------------
     158                 :      * The read ptr is now located at the beginning of the data part.
     159                 :      *----------------------------------------------------------------*/
     160               2 :     GotoByteInBlock(MAP_TOOL_HEADER_SIZE);
     161                 : 
     162               2 :     return 0;
     163                 : }
     164                 : 
     165                 : /**********************************************************************
     166                 :  *                   TABMAPToolBlock::CommitToFile()
     167                 :  *
     168                 :  * Commit the current state of the binary block to the file to which 
     169                 :  * it has been previously attached.
     170                 :  *
     171                 :  * This method makes sure all values are properly set in the map object
     172                 :  * block header and then calls TABRawBinBlock::CommitToFile() to do
     173                 :  * the actual writing to disk.
     174                 :  *
     175                 :  * Returns 0 if succesful or -1 if an error happened, in which case 
     176                 :  * CPLError() will have been called.
     177                 :  **********************************************************************/
     178               2 : int     TABMAPToolBlock::CommitToFile()
     179                 : {
     180               2 :     int nStatus = 0;
     181                 : 
     182               2 :     if ( m_pabyBuf == NULL )
     183                 :     {
     184                 :         CPLError(CE_Failure, CPLE_AssertionFailed, 
     185               0 :                  "CommitToFile(): Block has not been initialized yet!");
     186               0 :         return -1;
     187                 :     }
     188                 : 
     189                 :     /*-----------------------------------------------------------------
     190                 :      * Make sure 8 bytes block header is up to date.
     191                 :      *----------------------------------------------------------------*/
     192               2 :     GotoByteInBlock(0x000);
     193                 : 
     194               2 :     WriteInt16(TABMAP_TOOL_BLOCK);    // Block type code
     195               2 :     WriteInt16(m_nSizeUsed - MAP_TOOL_HEADER_SIZE); // num. bytes used
     196               2 :     WriteInt32(m_nNextToolBlock);
     197                 : 
     198               2 :     nStatus = CPLGetLastErrorNo();
     199                 : 
     200                 :     /*-----------------------------------------------------------------
     201                 :      * OK, call the base class to write the block to disk.
     202                 :      *----------------------------------------------------------------*/
     203               2 :     if (nStatus == 0)
     204               2 :         nStatus = TABRawBinBlock::CommitToFile();
     205                 : 
     206               2 :     return nStatus;
     207                 : }
     208                 : 
     209                 : /**********************************************************************
     210                 :  *                   TABMAPToolBlock::InitNewBlock()
     211                 :  *
     212                 :  * Initialize a newly created block so that it knows to which file it
     213                 :  * is attached, its block size, etc . and then perform any specific 
     214                 :  * initialization for this block type, including writing a default 
     215                 :  * block header, etc. and leave the block ready to receive data.
     216                 :  *
     217                 :  * This is an alternative to calling ReadFromFile() or InitBlockFromData()
     218                 :  * that puts the block in a stable state without loading any initial
     219                 :  * data in it.
     220                 :  *
     221                 :  * Returns 0 if succesful or -1 if an error happened, in which case 
     222                 :  * CPLError() will have been called.
     223                 :  **********************************************************************/
     224                 : int     TABMAPToolBlock::InitNewBlock(FILE *fpSrc, int nBlockSize, 
     225               4 :                                         int nFileOffset /* = 0*/)
     226                 : {
     227                 :     /*-----------------------------------------------------------------
     228                 :      * Start with the default initialisation
     229                 :      *----------------------------------------------------------------*/
     230               4 :     if ( TABRawBinBlock::InitNewBlock(fpSrc, nBlockSize, nFileOffset) != 0)
     231               0 :         return -1;
     232                 : 
     233                 :     /*-----------------------------------------------------------------
     234                 :      * And then set default values for the block header.
     235                 :      *----------------------------------------------------------------*/
     236               4 :     m_nNextToolBlock = 0;
     237                 :  
     238               4 :     m_numDataBytes = 0;
     239                 : 
     240               4 :     GotoByteInBlock(0x000);
     241                 : 
     242               4 :     if (m_eAccess != TABRead)
     243                 :     {
     244               2 :         WriteInt16(TABMAP_TOOL_BLOCK); // Block type code
     245               2 :         WriteInt16(0);                 // num. bytes used, excluding header
     246               2 :         WriteInt32(0);                 // Pointer to next tool block
     247                 :     }
     248                 : 
     249               4 :     if (CPLGetLastErrorNo() != 0)
     250               0 :         return -1;
     251                 : 
     252               4 :     return 0;
     253                 : }
     254                 : 
     255                 : /**********************************************************************
     256                 :  *                   TABMAPToolBlock::SetNextToolBlock()
     257                 :  *
     258                 :  * Set the address (offset from beginning of file) of the drawing tool block
     259                 :  * that follows the current one.
     260                 :  **********************************************************************/
     261               0 : void     TABMAPToolBlock::SetNextToolBlock(GInt32 nNextToolBlockAddress)
     262                 : {
     263               0 :     m_nNextToolBlock = nNextToolBlockAddress;
     264               0 : }
     265                 : 
     266                 : /**********************************************************************
     267                 :  *                   TABMAPToolBlock::SetMAPBlockManagerRef()
     268                 :  *
     269                 :  * Pass a reference to the block manager object for the file this 
     270                 :  * block belongs to.  The block manager will be used by this object
     271                 :  * when it needs to automatically allocate a new block.
     272                 :  **********************************************************************/
     273               2 : void TABMAPToolBlock::SetMAPBlockManagerRef(TABBinBlockManager *poBlockMgr)
     274                 : {
     275               2 :     m_poBlockManagerRef = poBlockMgr;
     276               2 : };
     277                 : 
     278                 : 
     279                 : /**********************************************************************
     280                 :  *                   TABMAPToolBlock::ReadBytes()
     281                 :  *
     282                 :  * Cover function for TABRawBinBlock::ReadBytes() that will automagically
     283                 :  * load the next coordinate block in the chain before reading the 
     284                 :  * requested bytes if we are at the end of the current block and if
     285                 :  * m_nNextToolBlock is a valid block.
     286                 :  *
     287                 :  * Then the control is passed to TABRawBinBlock::ReadBytes() to finish the
     288                 :  * work:
     289                 :  * Copy the number of bytes from the data block's internal buffer to
     290                 :  * the user's buffer pointed by pabyDstBuf.
     291                 :  *
     292                 :  * Passing pabyDstBuf = NULL will only move the read pointer by the
     293                 :  * specified number of bytes as if the copy had happened... but it 
     294                 :  * won't crash.
     295                 :  *
     296                 :  * Returns 0 if succesful or -1 if an error happened, in which case 
     297                 :  * CPLError() will have been called.
     298                 :  **********************************************************************/
     299              40 : int     TABMAPToolBlock::ReadBytes(int numBytes, GByte *pabyDstBuf)
     300                 : {
     301                 :     int nStatus;
     302                 : 
     303              40 :     if (m_pabyBuf && 
     304                 :         m_nCurPos >= (m_numDataBytes+MAP_TOOL_HEADER_SIZE) && 
     305                 :         m_nNextToolBlock > 0)
     306                 :     {
     307               0 :         if ( (nStatus=GotoByteInFile(m_nNextToolBlock)) != 0)
     308                 :         {
     309                 :             // Failed.... an error has already been reported.
     310               0 :             return nStatus;
     311                 :         }
     312                 : 
     313               0 :         GotoByteInBlock(MAP_TOOL_HEADER_SIZE);  // Move pointer past header
     314               0 :         m_numBlocksInChain++;
     315                 :     }
     316                 : 
     317              40 :     return TABRawBinBlock::ReadBytes(numBytes, pabyDstBuf);
     318                 : }
     319                 : 
     320                 : /**********************************************************************
     321                 :  *                   TABMAPToolBlock::WriteBytes()
     322                 :  *
     323                 :  * Cover function for TABRawBinBlock::WriteBytes() that will automagically
     324                 :  * CommitToFile() the current block and create a new one if we are at 
     325                 :  * the end of the current block.
     326                 :  *
     327                 :  * Then the control is passed to TABRawBinBlock::WriteBytes() to finish the
     328                 :  * work.
     329                 :  *
     330                 :  * Passing pabySrcBuf = NULL will only move the write pointer by the
     331                 :  * specified number of bytes as if the copy had happened... but it 
     332                 :  * won't crash.
     333                 :  *
     334                 :  * Returns 0 if succesful or -1 if an error happened, in which case 
     335                 :  * CPLError() will have been called.
     336                 :  **********************************************************************/
     337              48 : int  TABMAPToolBlock::WriteBytes(int nBytesToWrite, GByte *pabySrcBuf)
     338                 : {
     339              48 :     if (m_eAccess == TABWrite && m_poBlockManagerRef &&
     340                 :         (m_nBlockSize - m_nCurPos) < nBytesToWrite)
     341                 :     {
     342               0 :         int nNewBlockOffset = m_poBlockManagerRef->AllocNewBlock();
     343               0 :         SetNextToolBlock(nNewBlockOffset);
     344                 : 
     345               0 :         if (CommitToFile() != 0 ||
     346                 :             InitNewBlock(m_fp, 512, nNewBlockOffset) != 0)
     347                 :         {
     348                 :             // An error message should have already been reported.
     349               0 :             return -1;
     350                 :         }
     351                 : 
     352               0 :         m_numBlocksInChain ++;
     353                 :     }
     354                 : 
     355              48 :     return TABRawBinBlock::WriteBytes(nBytesToWrite, pabySrcBuf);
     356                 : }
     357                 : 
     358                 : /**********************************************************************
     359                 :  *                   TABMAPToolBlock::CheckAvailableSpace()
     360                 :  *
     361                 :  * Check if an object of the specified type can fit in
     362                 :  * current block.  If it can't fit then force committing current block 
     363                 :  * and allocating a new one.
     364                 :  *
     365                 :  * Returns 0 if succesful or -1 if an error happened, in which case 
     366                 :  * CPLError() will have been called.
     367                 :  **********************************************************************/
     368               4 : int  TABMAPToolBlock::CheckAvailableSpace(int nToolType)
     369                 : {
     370               4 :     int nBytesToWrite = 0;
     371                 : 
     372               4 :     switch(nToolType)
     373                 :     {
     374                 :       case TABMAP_TOOL_PEN:
     375               2 :         nBytesToWrite = 11;
     376               2 :         break;
     377                 :       case TABMAP_TOOL_BRUSH:
     378               2 :         nBytesToWrite = 13;
     379               2 :         break;
     380                 :       case TABMAP_TOOL_FONT:
     381               0 :         nBytesToWrite = 37;
     382               0 :         break;
     383                 :       case TABMAP_TOOL_SYMBOL:
     384               0 :         nBytesToWrite = 13;
     385               0 :         break;
     386                 :       default:
     387               0 :         CPLAssert(FALSE);
     388                 :     }
     389                 : 
     390               4 :     if (GetNumUnusedBytes() < nBytesToWrite)
     391                 :     {
     392               0 :         int nNewBlockOffset = m_poBlockManagerRef->AllocNewBlock();
     393               0 :         SetNextToolBlock(nNewBlockOffset);
     394                 : 
     395               0 :         if (CommitToFile() != 0 ||
     396                 :             InitNewBlock(m_fp, 512, nNewBlockOffset) != 0)
     397                 :         {
     398                 :             // An error message should have already been reported.
     399               0 :             return -1;
     400                 :         }
     401                 : 
     402               0 :         m_numBlocksInChain ++;
     403                 :     }
     404                 : 
     405               4 :     return 0;
     406                 : }
     407                 : 
     408                 : 
     409                 : 
     410                 : 
     411                 : /**********************************************************************
     412                 :  *                   TABMAPToolBlock::Dump()
     413                 :  *
     414                 :  * Dump block contents... available only in DEBUG mode.
     415                 :  **********************************************************************/
     416                 : #ifdef DEBUG
     417                 : 
     418               0 : void TABMAPToolBlock::Dump(FILE *fpOut /*=NULL*/)
     419                 : {
     420               0 :     if (fpOut == NULL)
     421               0 :         fpOut = stdout;
     422                 : 
     423               0 :     fprintf(fpOut, "----- TABMAPToolBlock::Dump() -----\n");
     424               0 :     if (m_pabyBuf == NULL)
     425                 :     {
     426               0 :         fprintf(fpOut, "Block has not been initialized yet.");
     427                 :     }
     428                 :     else
     429                 :     {
     430                 :         fprintf(fpOut,"Coordinate Block (type %d) at offset %d.\n", 
     431               0 :                                                  m_nBlockType, m_nFileOffset);
     432               0 :         fprintf(fpOut,"  m_numDataBytes        = %d\n", m_numDataBytes);
     433               0 :         fprintf(fpOut,"  m_nNextToolBlock     = %d\n", m_nNextToolBlock);
     434                 :     }
     435                 : 
     436               0 :     fflush(fpOut);
     437               0 : }
     438                 : 
     439                 : #endif // DEBUG
     440                 : 
     441                 : 
     442                 : 

Generated by: LTP GCOV extension version 1.5