LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/mitab - mitab_maptoolblock.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 105 61 58.1 %
Date: 2012-04-28 Functions: 15 10 66.7 %

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

Generated by: LCOV version 1.7