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

Generated by: LCOV version 1.14