LCOV - code coverage report
Current view: top level - frmts/pcidsk/sdk/blockdir - blocktilelayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 144 234 61.5 %
Date: 2024-05-13 13:33:37 Functions: 17 22 77.3 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Purpose:  Block directory API.
       4             :  *
       5             :  ******************************************************************************
       6             :  * Copyright (c) 2011
       7             :  * PCI Geomatics, 90 Allstate Parkway, Markham, Ontario, Canada.
       8             :  *
       9             :  * Permission is hereby granted, free of charge, to any person obtaining a
      10             :  * copy of this software and associated documentation files (the "Software"),
      11             :  * to deal in the Software without restriction, including without limitation
      12             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      13             :  * and/or sell copies of the Software, and to permit persons to whom the
      14             :  * Software is furnished to do so, subject to the following conditions:
      15             :  *
      16             :  * The above copyright notice and this permission notice shall be included
      17             :  * in all copies or substantial portions of the Software.
      18             :  *
      19             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      20             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      21             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      22             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      23             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      24             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      25             :  * DEALINGS IN THE SOFTWARE.
      26             :  ****************************************************************************/
      27             : 
      28             : #include "blockdir/blocktilelayer.h"
      29             : #include "blockdir/blockdir.h"
      30             : #include "blockdir/blockfile.h"
      31             : #include "blockdir/asciitiledir.h"
      32             : #include "blockdir/binarytiledir.h"
      33             : #include "core/mutexholder.h"
      34             : #include "pcidsk_types.h"
      35             : #include "pcidsk_exception.h"
      36             : #include <cstdlib>
      37             : #include <cstring>
      38             : #include <cassert>
      39             : #include <algorithm>
      40             : #include <limits>
      41             : 
      42             : #ifdef PCIMAJORVERSION
      43             : #include "raster/memcmp.hh"
      44             : #include "raster/memset.hh"
      45             : #endif
      46             : 
      47             : namespace PCIDSK
      48             : {
      49             : 
      50             : /************************************************************************/
      51             : /*                             BlockTileLayer()                         */
      52             : /************************************************************************/
      53             : 
      54             : /**
      55             :  * Constructor.
      56             :  *
      57             :  * @param poBlockDir The associated block directory.
      58             :  * @param nLayer The index of the block layer.
      59             :  * @param psBlockLayer The block layer info.
      60             :  * @param psTileLayer The tile layer info.
      61             :  */
      62          49 : BlockTileLayer::BlockTileLayer(BlockDir * poBlockDir, uint32 nLayer,
      63             :                                BlockLayerInfo * psBlockLayer,
      64          49 :                                TileLayerInfo * psTileLayer)
      65             :     : BlockLayer(poBlockDir, nLayer),
      66             :       mpsBlockLayer(psBlockLayer),
      67             :       mpsTileLayer(psTileLayer),
      68          49 :       mbModified(false)
      69             : {
      70          49 :     memset(mszDataType, 0, sizeof(mszDataType));
      71          49 :     memset(mszCompress, 0, sizeof(mszCompress));
      72             : 
      73          49 :     mpoTileListMutex = DefaultCreateMutex();
      74          49 : }
      75             : 
      76             : /************************************************************************/
      77             : /*                            ~BlockTileLayer()                         */
      78             : /************************************************************************/
      79             : 
      80             : /**
      81             :  * Destructor.
      82             :  */
      83          49 : BlockTileLayer::~BlockTileLayer(void)
      84             : {
      85          49 :     delete mpoTileListMutex;
      86          49 : }
      87             : 
      88             : /************************************************************************/
      89             : /*                              GetTileInfo()                           */
      90             : /************************************************************************/
      91             : 
      92             : /**
      93             :  * Gets the tile at the specified index.
      94             :  *
      95             :  * @param nCol The column of the tile.
      96             :  * @param nRow The row of the tile.
      97             :  *
      98             :  * @return The tile at the specified index.
      99             :  */
     100             : BlockTileLayer::BlockTileInfo *
     101          70 : BlockTileLayer::GetTileInfo(uint32 nCol, uint32 nRow)
     102             : {
     103          70 :     if (!IsValid())
     104           0 :         return nullptr;
     105             : 
     106          70 :     uint32 nTilesPerRow = GetTilePerRow();
     107             : 
     108          70 :     uint32 iTile = nRow * nTilesPerRow + nCol;
     109             : 
     110          70 :     MutexHolder oLock(mpoTileListMutex);
     111             : 
     112          70 :     if (moTileList.empty())
     113          12 :         ReadTileList();
     114             : 
     115          70 :     return &moTileList.at(iTile);
     116             : }
     117             : 
     118             : /************************************************************************/
     119             : /*                                  Sync()                              */
     120             : /************************************************************************/
     121             : 
     122             : /**
     123             :  * Synchronizes the block tile layer to disk.
     124             :  */
     125          50 : void BlockTileLayer::Sync(void)
     126             : {
     127          50 :     if (!mbModified)
     128          42 :         return;
     129             : 
     130             :     try
     131             :     {
     132           8 :         if (!GetFile()->GetUpdatable())
     133           0 :             return;
     134             :     }
     135           0 :     catch (...)
     136             :     {
     137           0 :         return;
     138             :     }
     139             : 
     140           8 :     MutexHolder oLock(mpoTileListMutex);
     141             : 
     142           8 :     if (!mbModified)
     143           0 :         return;
     144             : 
     145           8 :     WriteTileList();
     146             : 
     147           8 :     mbModified = false;
     148             : }
     149             : 
     150             : /************************************************************************/
     151             : /*                              IsCorrupted()                           */
     152             : /************************************************************************/
     153          28 : bool BlockTileLayer::IsCorrupted(void) const
     154             : {
     155             :     // Dead layers have a tile size of 0, but it should be considered valid.
     156          28 :     if (GetLayerType() == BLTDead)
     157           0 :         return false;
     158             : 
     159             :     // The tile layer is corrupted when the image size is 0.
     160          28 :     if (GetXSize() == 0 || GetYSize() == 0)
     161           0 :         return true;
     162             : 
     163             :     uint64 nTileSize =
     164          28 :         static_cast<uint64>(GetTileXSize()) * GetTileYSize() * GetDataTypeSize();
     165             : 
     166          28 :     return nTileSize == 0 || nTileSize > std::numeric_limits<uint32>::max();
     167             : }
     168             : 
     169             : /************************************************************************/
     170             : /*                              GetTileCount()                          */
     171             : /************************************************************************/
     172             : 
     173             : /**
     174             :  * Gets the number of tiles in the tile layer.
     175             :  *
     176             :  * @return The number of tiles in the tile layer.
     177             :  */
     178          61 : uint32 BlockTileLayer::GetTileCount(void) const
     179             : {
     180          61 :     return (uint32) (((static_cast<uint64>(GetXSize()) + GetTileXSize() - 1) / GetTileXSize()) *
     181          61 :                      ((static_cast<uint64>(GetYSize()) + GetTileYSize() - 1) / GetTileYSize()));
     182             : }
     183             : 
     184             : /************************************************************************/
     185             : /*                             GetTilePerRow()                          */
     186             : /************************************************************************/
     187             : 
     188             : /**
     189             :  * Gets the number of tiles per row in the tile layer.
     190             :  *
     191             :  * @return The number of tiles per row in the tile layer.
     192             :  */
     193         107 : uint32 BlockTileLayer::GetTilePerRow(void) const
     194             : {
     195         107 :     return (uint32) (static_cast<uint64>(GetXSize()) + GetTileXSize() - 1) / GetTileXSize();
     196             : }
     197             : 
     198             : /************************************************************************/
     199             : /*                             GetTilePerCol()                          */
     200             : /************************************************************************/
     201             : 
     202             : /**
     203             :  * Gets the number of tiles per column in the tile layer.
     204             :  *
     205             :  * @return The number of tiles per column in the tile layer.
     206             :  */
     207           0 : uint32 BlockTileLayer::GetTilePerCol(void) const
     208             : {
     209           0 :     return (uint32) (static_cast<uint64>(GetYSize()) + GetTileYSize() - 1) / GetTileYSize();
     210             : }
     211             : 
     212             : /************************************************************************/
     213             : /*                              GetTileSize()                           */
     214             : /************************************************************************/
     215             : 
     216             : /**
     217             :  * Gets the size in bytes of a tile.
     218             :  *
     219             :  * @return The size in bytes of a tile.
     220             :  */
     221          45 : uint32 BlockTileLayer::GetTileSize(void) const
     222             : {
     223          45 :     return GetTileXSize() * GetTileYSize() * GetDataTypeSize();
     224             : }
     225             : 
     226             : /************************************************************************/
     227             : /*                            GetDataTypeSize()                         */
     228             : /************************************************************************/
     229             : 
     230             : /**
     231             :  * Gets the data type size in bytes.
     232             :  *
     233             :  * @return The data type size in bytes.
     234             :  */
     235          73 : uint32 BlockTileLayer::GetDataTypeSize(void) const
     236             : {
     237          73 :     return DataTypeSize(GetDataTypeFromName(GetDataType()));
     238             : }
     239             : 
     240             : /************************************************************************/
     241             : /*                              IsTileValid()                           */
     242             : /************************************************************************/
     243             : 
     244             : /**
     245             :  * Checks if the specified tile is valid.
     246             :  *
     247             :  * @param nCol The column of the tile.
     248             :  * @param nRow The row of the tile.
     249             :  *
     250             :  * @return If the specified tile is valid.
     251             :  */
     252           0 : bool BlockTileLayer::IsTileValid(uint32 nCol, uint32 nRow)
     253             : {
     254           0 :     BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
     255             : 
     256           0 :     return (psTile && psTile->nOffset != INVALID_OFFSET && psTile->nSize != 0 &&
     257           0 :             AreBlocksAllocated(psTile->nOffset, psTile->nSize));
     258             : }
     259             : 
     260             : /************************************************************************/
     261             : /*                            GetTileDataSize()                         */
     262             : /************************************************************************/
     263             : 
     264             : /**
     265             :  * Gets the size in bytes of the specified tile.
     266             :  *
     267             :  * @param nCol The column of the tile.
     268             :  * @param nRow The row of the tile.
     269             :  *
     270             :  * @return The size in bytes of the specified tile.
     271             :  */
     272           4 : uint32 BlockTileLayer::GetTileDataSize(uint32 nCol, uint32 nRow)
     273             : {
     274           4 :     BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
     275             : 
     276           4 :     return psTile ? psTile->nSize : 0;
     277             : }
     278             : 
     279             : /************************************************************************/
     280             : /*                            WriteSparseTile()                         */
     281             : /************************************************************************/
     282             : 
     283             : /**
     284             :  * Writes the specified tile only if the data is sparse.
     285             :  *
     286             :  * @param pData The data of the tile.
     287             :  * @param nCol The column of the tile.
     288             :  * @param nRow The row of the tile.
     289             :  *
     290             :  * @return If the specified tile data is sparse.
     291             :  */
     292           8 : bool BlockTileLayer::WriteSparseTile(const void * pData,
     293             :                                      uint32 nCol, uint32 nRow)
     294             : {
     295           8 :     MutexHolder oLock(mpoTileListMutex);
     296             : 
     297           8 :     uint32 nValue = 0;
     298             : 
     299           8 :     bool bIsSparse = true;
     300             : 
     301           8 :     uint32 nTileSize = GetTileSize();
     302             : 
     303             :     // Check if we can use a sparse tile with a 4 byte value.
     304           8 :     if (dynamic_cast<BinaryTileDir *>(mpoBlockDir) && nTileSize % 4 == 0)
     305             :     {
     306           6 :         uint32 * pnIter = (uint32 *) pData;
     307             : 
     308           6 :         nValue = *pnIter;
     309             : 
     310             : #ifdef PCIMAJORVERSION
     311             :         bIsSparse = raster::memcmp32(pnIter, nValue,
     312             :                                      nTileSize / sizeof(uint32));
     313             : #else
     314           6 :         uint32 * pnEnd = pnIter + nTileSize / sizeof(uint32);
     315         364 :         for (; pnIter < pnEnd; ++pnIter)
     316             :         {
     317         364 :             if (*pnIter != nValue)
     318             :             {
     319           6 :                 bIsSparse = false;
     320           6 :                 break;
     321             :             }
     322             :         }
     323             : #endif
     324             :     }
     325             :     // Check if we can use a sparse tile with a value of 0.
     326             :     else
     327             :     {
     328           2 :         nValue = 0;
     329             : 
     330             : #ifdef PCIMAJORVERSION
     331             :         bIsSparse = raster::memcmp8((uchar *) pData, 0, nTileSize);
     332             : #else
     333           2 :         uchar * pnIter = (uchar *) pData;
     334           2 :         uchar * pnEnd = pnIter + nTileSize;
     335         718 :         for (; pnIter < pnEnd; ++pnIter)
     336             :         {
     337         718 :             if (*pnIter != nValue)
     338             :             {
     339           2 :                 bIsSparse = false;
     340           2 :                 break;
     341             :             }
     342             :         }
     343             : #endif
     344             :     }
     345             : 
     346             :     // If the tile data is sparse store the sparse value in the nSize member
     347             :     // of the BlockTileInfo structure.
     348           8 :     if (bIsSparse)
     349             :     {
     350           0 :         BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
     351           0 :         if( psTile != nullptr ) // TODO: what if it is null
     352             :         {
     353             :             // Free the blocks used by the tile.
     354           0 :             if (psTile->nOffset != INVALID_OFFSET)
     355           0 :                 FreeBlocks(psTile->nOffset, psTile->nSize);
     356             : 
     357           0 :             psTile->nOffset = INVALID_OFFSET;
     358             : 
     359           0 :             psTile->nSize = nValue;
     360             : 
     361           0 :             mbModified = true;
     362             :         }
     363             :     }
     364             : 
     365          16 :     return bIsSparse;
     366             : }
     367             : 
     368             : /************************************************************************/
     369             : /*                               WriteTile()                            */
     370             : /************************************************************************/
     371             : 
     372             : /**
     373             :  * Writes the specified tile.
     374             :  *
     375             :  * @param pData The data of the tile.
     376             :  * @param nCol The column of the tile.
     377             :  * @param nRow The row of the tile.
     378             :  * @param nSize The size of the tile.
     379             :  */
     380           8 : void BlockTileLayer::WriteTile(const void * pData,
     381             :                                uint32 nCol, uint32 nRow, uint32 nSize)
     382             : {
     383           8 :     MutexHolder oLock(mpoTileListMutex);
     384             : 
     385           8 :     if (!IsValid())
     386           0 :         return;
     387             : 
     388           8 :     BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
     389             : 
     390           8 :     if (!psTile)
     391           0 :         return;
     392             : 
     393           8 :     if (nSize == 0)
     394           4 :         nSize = GetTileSize();
     395             : 
     396           8 :     if (psTile->nOffset == INVALID_OFFSET)
     397             :     {
     398           8 :         psTile->nOffset = GetLayerSize();
     399             : 
     400           8 :         psTile->nSize = nSize;
     401             : 
     402           8 :         mbModified = true;
     403             :     }
     404             : 
     405           8 :     if (psTile->nSize < nSize)
     406             :     {
     407           0 :         psTile->nOffset = GetLayerSize();
     408             : 
     409           0 :         psTile->nSize = nSize;
     410             : 
     411           0 :         mbModified = true;
     412             :     }
     413           8 :     else if (psTile->nSize > nSize)
     414             :     {
     415           0 :         psTile->nSize = nSize;
     416             : 
     417           0 :         mbModified = true;
     418             :     }
     419             : 
     420           8 :     WriteToLayer(pData, psTile->nOffset, psTile->nSize);
     421             : }
     422             : 
     423             : /************************************************************************/
     424             : /*                             ReadSparseTile()                         */
     425             : /************************************************************************/
     426             : 
     427             : /**
     428             :  * Reads the specified tile only if the data is sparse.
     429             :  *
     430             :  * @param pData The data of the tile.
     431             :  * @param nCol The column of the tile.
     432             :  * @param nRow The row of the tile.
     433             :  *
     434             :  * @return If the specified tile data is sparse.
     435             :  */
     436          29 : bool BlockTileLayer::ReadSparseTile(void * pData, uint32 nCol, uint32 nRow)
     437             : {
     438          29 :     if (!IsValid())
     439           0 :         return false;
     440             : 
     441          29 :     BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
     442             : 
     443          29 :     if (!psTile)
     444           0 :         return false;
     445             : 
     446          29 :     if (psTile->nOffset != INVALID_OFFSET)
     447          29 :         return false;
     448             : 
     449           0 :     uint32 nTileSize = GetTileSize();
     450             : 
     451             :     // Check if we can use a sparse tile with a 4 byte value.
     452           0 :     if (dynamic_cast<BinaryTileDir *>(mpoBlockDir) && nTileSize % 4 == 0)
     453             :     {
     454             : #ifdef PCIMAJORVERSION
     455             :         raster::memset32((uint32 *) pData, psTile->nSize,
     456             :                          nTileSize / sizeof(uint32));
     457             : #else
     458           0 :         uint32 * pnIter = (uint32 *) pData;
     459           0 :         uint32 * pnEnd = pnIter + nTileSize / sizeof(uint32);
     460           0 :         for (; pnIter < pnEnd; ++pnIter)
     461           0 :             *pnIter = psTile->nSize;
     462             : #endif
     463             :     }
     464             :     // Check if we can use a sparse tile with a value of 0.
     465             :     else
     466             :     {
     467           0 :         memset(pData, 0, nTileSize);
     468             :     }
     469             : 
     470           0 :     return true;
     471             : }
     472             : 
     473             : /************************************************************************/
     474             : /*                                ReadTile()                            */
     475             : /************************************************************************/
     476             : 
     477             : /**
     478             :  * Reads the specified tile.
     479             :  *
     480             :  * @param pData The data of the tile.
     481             :  * @param nCol The column of the tile.
     482             :  * @param nRow The row of the tile.
     483             :  * @param nSize The buffer size.
     484             :  *
     485             :  * @return The size of the tile.
     486             :  */
     487          29 : uint32 BlockTileLayer::ReadTile(void * pData, uint32 nCol, uint32 nRow, uint32 nSize)
     488             : {
     489          29 :     if (!IsValid())
     490           0 :         return 0;
     491             : 
     492          29 :     BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
     493             : 
     494          29 :     if (!psTile)
     495           0 :         return 0;
     496             : 
     497          29 :     if (psTile->nOffset == INVALID_OFFSET)
     498           0 :         return 0;
     499             : 
     500          29 :     if (psTile->nSize == 0)
     501           0 :         return 0;
     502             : 
     503          29 :     uint32 nReadSize = std::min(nSize, psTile->nSize);
     504             : 
     505             : #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
     506          29 :     assert(psTile->nSize == nSize);
     507             : #endif
     508             : 
     509          29 :     if (!ReadFromLayer(pData, psTile->nOffset, nReadSize))
     510           0 :         return 0;
     511             : 
     512          29 :     return nReadSize;
     513             : }
     514             : 
     515             : /************************************************************************/
     516             : /*                         ReadPartialSparseTile()                      */
     517             : /************************************************************************/
     518             : 
     519             : /**
     520             :  * Reads the specified tile only if the data is sparse.
     521             :  *
     522             :  * @param pData The data of the tile.
     523             :  * @param nCol The column of the tile.
     524             :  * @param nRow The row of the tile.
     525             :  * @param nOffset The offset of the data.
     526             :  * @param nSize The size of the data.
     527             :  *
     528             :  * @return If the specified tile data is sparse.
     529             :  */
     530           0 : bool BlockTileLayer::ReadPartialSparseTile(void * pData,
     531             :                                            uint32 nCol, uint32 nRow,
     532             :                                            uint32 nOffset, uint32 nSize)
     533             : {
     534           0 :     if (!IsValid())
     535           0 :         return false;
     536             : 
     537           0 :     BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
     538             : 
     539           0 :     if (!psTile)
     540           0 :         return false;
     541             : 
     542           0 :     if (psTile->nOffset != INVALID_OFFSET)
     543           0 :         return false;
     544             : 
     545           0 :     uint32 nTileSize = GetTileSize();
     546             : 
     547             :     // Check if we can use a sparse tile with a 4 byte value.
     548           0 :     if (dynamic_cast<BinaryTileDir *>(mpoBlockDir) && nTileSize % 4 == 0)
     549             :     {
     550           0 :         uint32 nValue = psTile->nSize;
     551             : 
     552             :         // We need to bitwise shift the value if the offset isn't aligned.
     553           0 :         uint32 nByteOffset = nOffset % 4;
     554             : 
     555           0 :         if (nByteOffset != 0)
     556             :         {
     557           0 :             uint32 nBitOffset = nByteOffset * 8;
     558             : 
     559           0 :             nValue = (nValue << nBitOffset) | (nValue >> (32 - nBitOffset));
     560             :         }
     561             : 
     562           0 :         uint32 nAlign = nSize / sizeof(uint32);
     563             : 
     564             : #ifdef PCIMAJORVERSION
     565             :         raster::memset32((uint32 *) pData, nValue, nAlign);
     566             : #else
     567           0 :         uint32 * pnIter = (uint32 *) pData;
     568           0 :         uint32 * pnEnd = pnIter + nAlign;
     569           0 :         for (; pnIter < pnEnd; ++pnIter)
     570           0 :             *pnIter = nValue;
     571             : #endif
     572             : 
     573           0 :         uint32 nRemaining = nSize % 4;
     574             : 
     575           0 :         if (nRemaining != 0)
     576             :         {
     577           0 :             uchar * pbyIter = (uchar *) pData + nAlign * 4;
     578             : 
     579           0 :             do
     580             :             {
     581           0 :                 nValue = (nValue << 8) | (nValue >> 24);
     582             : 
     583           0 :                 *pbyIter++ = (uchar) nValue;
     584             :             }
     585           0 :             while (--nRemaining);
     586             :         }
     587             :     }
     588             :     // Check if we can use a sparse tile with a value of 0.
     589             :     else
     590             :     {
     591           0 :         memset(pData, 0, nSize);
     592             :     }
     593             : 
     594           0 :     return true;
     595             : }
     596             : 
     597             : /************************************************************************/
     598             : /*                            ReadPartialTile()                         */
     599             : /************************************************************************/
     600             : 
     601             : /**
     602             :  * Reads the specified tile.
     603             :  *
     604             :  * @param pData The data of the tile.
     605             :  * @param nCol The column of the tile.
     606             :  * @param nRow The row of the tile.
     607             :  * @param nOffset The offset of the data.
     608             :  * @param nSize The size of the data.
     609             :  *
     610             :  * @return If the read was successful.
     611             :  */
     612           0 : bool BlockTileLayer::ReadPartialTile(void * pData, uint32 nCol, uint32 nRow,
     613             :                                      uint32 nOffset, uint32 nSize)
     614             : {
     615           0 :     if (!IsValid())
     616           0 :         return false;
     617             : 
     618           0 :     BlockTileInfo * psTile = GetTileInfo(nCol, nRow);
     619             : 
     620           0 :     if (!psTile)
     621           0 :         return false;
     622             : 
     623           0 :     if (psTile->nOffset == INVALID_OFFSET)
     624           0 :         return false;
     625             : 
     626           0 :     if (psTile->nSize == 0 || psTile->nSize < nOffset + nSize)
     627           0 :         return false;
     628             : 
     629           0 :     if (!ReadFromLayer(pData, psTile->nOffset + nOffset, nSize))
     630           0 :         return false;
     631             : 
     632           0 :     return true;
     633             : }
     634             : 
     635             : /************************************************************************/
     636             : /*                            SetTileLayerInfo()                        */
     637             : /************************************************************************/
     638             : 
     639             : /**
     640             :  * Sets the tile layer information.
     641             :  *
     642             :  * @param nXSize The width of the tile layer.
     643             :  * @param nYSize The height of the tile layer.
     644             :  * @param nTileXSize The width of a tile.
     645             :  * @param nTileYSize The height of a tile.
     646             :  * @param oDataType The data type of the tile layer.
     647             :  * @param oCompress The compress type of the tile layer.
     648             :  * @param bNoDataValid If the NoData value is valid.
     649             :  * @param dfNoDataValue The NoData value of the tile layer.
     650             :  */
     651           8 : void BlockTileLayer::SetTileLayerInfo(uint32 nXSize, uint32 nYSize,
     652             :                                       uint32 nTileXSize, uint32 nTileYSize,
     653             :                                       const std::string & oDataType,
     654             :                                       const std::string & oCompress,
     655             :                                       bool bNoDataValid, double dfNoDataValue)
     656             : {
     657             :     uint64 nTileSize =
     658           8 :         static_cast<uint64>(nTileXSize) * nTileYSize *
     659           8 :         DataTypeSize(GetDataTypeFromName(oDataType.c_str()));
     660             : 
     661           8 :     if (nTileSize == 0 || nTileSize > std::numeric_limits<uint32>::max())
     662             :     {
     663           0 :         return ThrowPCIDSKException("Invalid tile dimensions: %d x %d",
     664           0 :                                     nTileXSize, nTileYSize);
     665             :     }
     666             : 
     667           8 :     if (nXSize == 0 || nYSize == 0)
     668             :     {
     669           0 :         return ThrowPCIDSKException("Invalid tile layer dimensions: %d x %d",
     670           0 :                                     nXSize, nYSize);
     671             :     }
     672             : 
     673           8 :     mpsTileLayer->nXSize = nXSize;
     674           8 :     mpsTileLayer->nYSize = nYSize;
     675           8 :     mpsTileLayer->nTileXSize = nTileXSize;
     676           8 :     mpsTileLayer->nTileYSize = nTileYSize;
     677           8 :     mpsTileLayer->bNoDataValid = bNoDataValid;
     678           8 :     mpsTileLayer->dfNoDataValue = dfNoDataValue;
     679             : 
     680           8 :     memset(mpsTileLayer->szDataType, ' ', 4);
     681           8 :     memcpy(mpsTileLayer->szDataType, oDataType.data(), oDataType.size());
     682             : 
     683           8 :     memset(mpsTileLayer->szCompress, ' ', 8);
     684           8 :     memcpy(mpsTileLayer->szCompress, oCompress.data(), oCompress.size());
     685             : 
     686             :     // Invalidate the cache variables.
     687           8 :     *mszDataType = 0;
     688           8 :     *mszCompress = 0;
     689             : 
     690             :     // Initialize the tile list.
     691           8 :     uint32 nTileCount = GetTileCount();
     692             : 
     693           8 :     MutexHolder oLock(mpoTileListMutex);
     694             : 
     695             :     try
     696             :     {
     697           8 :         moTileList.resize(nTileCount);
     698             :     }
     699           0 :     catch (const std::exception & ex)
     700             :     {
     701           0 :         return ThrowPCIDSKException("Out of memory in BlockTileLayer::SetTileLayerInfo(): %s", ex.what());
     702             :     }
     703             : 
     704          16 :     for (uint32 iTile = 0; iTile < nTileCount; iTile++)
     705             :     {
     706           8 :         BlockTileInfo * psTile = &moTileList[iTile];
     707             : 
     708           8 :         psTile->nOffset = INVALID_OFFSET;
     709           8 :         psTile->nSize = 0;
     710             :     }
     711             : 
     712             :     // Write the tile list to disk.
     713           8 :     WriteTileList();
     714             : 
     715           8 :     mbModified = false;
     716             : 
     717           8 :     oLock.Release();
     718             : 
     719             :     // Make sure that the first tile starts on a block boundary.
     720           8 :     uint64 nLayerSize = GetLayerSize();
     721           8 :     uint32 nBlockSize = mpoBlockDir->GetBlockSize();
     722             : 
     723           8 :     if (nLayerSize % nBlockSize != 0)
     724           8 :         Resize((nLayerSize / nBlockSize + 1) * nBlockSize);
     725             : }
     726             : 
     727             : /************************************************************************/
     728             : /*                              GetDataType()                           */
     729             : /************************************************************************/
     730             : 
     731             : /**
     732             :  * Gets the data type of the tile layer.
     733             :  *
     734             :  * @return The data type of the tile layer.
     735             :  */
     736         140 : const char * BlockTileLayer::GetDataType(void) const
     737             : {
     738         280 :     MutexHolder oLock(mpoTileListMutex);
     739             : 
     740         140 :     if (*mszDataType)
     741         104 :         return mszDataType;
     742             : 
     743          36 :     memcpy(mszDataType, mpsTileLayer->szDataType, 4);
     744             : 
     745          36 :     int nIter = 3;
     746             : 
     747          90 :     while (nIter > 0 && mszDataType[nIter] == ' ')
     748          54 :         mszDataType[nIter--] = '\0';
     749             : 
     750          36 :     return mszDataType;
     751             : }
     752             : 
     753             : /************************************************************************/
     754             : /*                            GetCompressType()                         */
     755             : /************************************************************************/
     756             : 
     757             : /**
     758             :  * Gets the compress type of the tile layer.
     759             :  *
     760             :  * @return The compress type of the tile layer.
     761             :  */
     762          38 : const char * BlockTileLayer::GetCompressType(void) const
     763             : {
     764          76 :     MutexHolder oLock(mpoTileListMutex);
     765             : 
     766          38 :     if (*mszCompress)
     767          18 :         return mszCompress;
     768             : 
     769          20 :     memcpy(mszCompress, mpsTileLayer->szCompress, 8);
     770             : 
     771          20 :     int nIter = 7;
     772             : 
     773         106 :     while (nIter > 0 && mszCompress[nIter] == ' ')
     774          86 :         mszCompress[nIter--] = '\0';
     775             : 
     776          20 :     return mszCompress;
     777             : }
     778             : 
     779             : } // namespace PCIDSK

Generated by: LCOV version 1.14