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

Generated by: LCOV version 1.14