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

Generated by: LCOV version 1.14