LCOV - code coverage report
Current view: top level - frmts/pcidsk/sdk/core - cpcidskblockfile.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 77 94 81.9 %
Date: 2026-08-22 15:37:05 Functions: 13 16 81.2 %

          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 "core/cpcidskblockfile.h"
      13             : #include "core/cpcidskfile.h"
      14             : #include "segment/systiledir.h"
      15             : #include "blockdir/asciitiledir.h"
      16             : #include "blockdir/binarytiledir.h"
      17             : #include "pcidsk_channel.h"
      18             : #include <cassert>
      19             : #include <algorithm>
      20             : 
      21             : using namespace PCIDSK;
      22             : 
      23          81 : CPCIDSKBlockFile::CPCIDSKBlockFile(PCIDSKFile * poFile)
      24          81 :     : mpoFile(dynamic_cast<CPCIDSKFile *>(poFile)),
      25          81 :       mnGrowingSegment(0)
      26             : {
      27          81 :     assert(mpoFile);
      28          81 : }
      29             : 
      30          39 : SysTileDir * CPCIDSKBlockFile::GetTileDir(void)
      31             : {
      32          16 :     SysTileDir * poTileDir = dynamic_cast<SysTileDir *>
      33          55 :         (mpoFile->GetSegment(SEG_SYS, "TileDir"));
      34             : 
      35          39 :     if (!poTileDir)
      36             :     {
      37           1 :         poTileDir = dynamic_cast<SysTileDir *>
      38          17 :             (mpoFile->GetSegment(SEG_SYS, "SysBMDir"));
      39             :     }
      40             : 
      41          39 :     return poTileDir;
      42             : }
      43             : 
      44           9 : SysTileDir * CPCIDSKBlockFile::CreateTileDir(void)
      45             : {
      46           9 :     SysTileDir * poTileDir = nullptr;
      47             : 
      48           9 :     std::string oFileOptions = GetFileOptions();
      49             : 
      50         108 :     for (char & chIter : oFileOptions)
      51          99 :         chIter = (char) toupper(static_cast<unsigned char>(chIter));
      52             : 
      53             :     // Check if we should create a TILEV1 or TILEV2 block directory.
      54           9 :     bool bTileV1 = oFileOptions.find("TILEV1") != std::string::npos;
      55           9 :     bool bTileV2 = oFileOptions.find("TILEV2") != std::string::npos;
      56             : 
      57             :     // The TILEV1 block directory has a limit of 762GB, so default
      58             :     // to TILEV2 if the image file size exceed 512GB.
      59          14 :     if (!bTileV2 && !bTileV1 &&
      60           5 :         GetImageFileSize() > (uint64) 549755813888ULL)
      61             :     {
      62           0 :         bTileV2 = true;
      63             :     }
      64             : 
      65             :     // We now use TILEV2 by default.
      66           9 :     if (bTileV2 || !bTileV1)
      67             :     {
      68           7 :         const char * pszDesc = "Block Tile Directory - Do not modify.";
      69             : 
      70           7 :         size_t nSegmentSize = BinaryTileDir::GetOptimizedDirSize(this);
      71             : 
      72             :         int nSegment =
      73           7 :             mpoFile->CreateSegment("TileDir", pszDesc, SEG_SYS,
      74           7 :                                    (int) ((nSegmentSize + 511) / 512));
      75             : 
      76           7 :         poTileDir = dynamic_cast<SysTileDir *>(mpoFile->GetSegment(nSegment));
      77             :     }
      78             :     else
      79             :     {
      80           2 :         const char * pszDesc =
      81             :             "System Block Map Directory - Do not modify.";
      82             : 
      83           2 :         size_t nSegmentSize = AsciiTileDir::GetOptimizedDirSize(this);
      84             : 
      85             :         int nSegment =
      86           2 :             mpoFile->CreateSegment("SysBMDir", pszDesc, SEG_SYS,
      87           2 :                                    (int) ((nSegmentSize + 511) / 512));
      88             : 
      89           2 :         poTileDir = dynamic_cast<SysTileDir *>(mpoFile->GetSegment(nSegment));
      90             :     }
      91             : 
      92           9 :     assert(poTileDir);
      93             : 
      94           9 :     poTileDir->CreateTileDir();
      95             : 
      96          18 :     return poTileDir;
      97             : }
      98             : 
      99           0 : std::string CPCIDSKBlockFile::GetFilename(void) const
     100             : {
     101           0 :     return mpoFile->GetFilename();
     102             : }
     103             : 
     104          18 : bool CPCIDSKBlockFile::GetUpdatable(void) const
     105             : {
     106          18 :     return mpoFile->GetUpdatable();
     107             : }
     108             : 
     109           0 : uint32 CPCIDSKBlockFile::GetWidth(void) const
     110             : {
     111           0 :     return mpoFile->GetWidth();
     112             : }
     113             : 
     114           0 : uint32 CPCIDSKBlockFile::GetHeight(void) const
     115             : {
     116           0 :     return mpoFile->GetHeight();
     117             : }
     118             : 
     119           9 : uint32 CPCIDSKBlockFile::GetChannels(void) const
     120             : {
     121           9 :     return mpoFile->GetChannels();
     122             : }
     123             : 
     124          32 : std::string CPCIDSKBlockFile::GetFileOptions(void) const
     125             : {
     126          32 :     return mpoFile->GetMetadataValue("_DBLayout");
     127             : }
     128             : 
     129          23 : uint64 CPCIDSKBlockFile::GetImageFileSize(void) const
     130             : {
     131          23 :     uint64 nImageSize = 0;
     132             : 
     133          23 :     int nChanCount = mpoFile->GetChannels();
     134             : 
     135          46 :     for (int iChan = 1; iChan <= nChanCount; iChan++)
     136             :     {
     137          23 :         PCIDSKChannel * poChannel = mpoFile->GetChannel(iChan);
     138             : 
     139          23 :         nImageSize += DataTypeSize(poChannel->GetType());
     140             :     }
     141             : 
     142          23 :     return nImageSize * mpoFile->GetWidth() * mpoFile->GetHeight();
     143             : }
     144             : 
     145          59 : bool CPCIDSKBlockFile::IsValidFileOffset(uint64 nOffset) const
     146             : {
     147          59 :     return nOffset <= mpoFile->GetFileSize() * 512;
     148             : }
     149             : 
     150          47 : bool CPCIDSKBlockFile::IsCorruptedSegment(uint16 nSegment, uint64 nOffset, uint64 nSize) const
     151             : {
     152          47 :     PCIDSKSegment * poSegment = mpoFile->GetSegment(nSegment);
     153             : 
     154          47 :     return (!poSegment ||
     155          94 :             nOffset + nSize > poSegment->GetContentSize() ||
     156          94 :             !IsValidFileOffset(nOffset + nSize + poSegment->GetContentOffset()));
     157             : }
     158             : 
     159           9 : uint16 CPCIDSKBlockFile::ExtendSegment(const std::string & oName,
     160             :                                        const std::string & oDesc,
     161             :                                        uint64 nExtendSize)
     162             : {
     163             :     // Check to see if the cached growing segment is still valid.
     164           9 :     if (mnGrowingSegment > 0)
     165             :     {
     166           0 :         PCIDSKSegment * poSegment = mpoFile->GetSegment(mnGrowingSegment);
     167             : 
     168           0 :         if (!poSegment->IsAtEOF() || !poSegment->CanExtend(nExtendSize))
     169           0 :             mnGrowingSegment = 0;
     170             :     }
     171             :     else
     172             :     {
     173           9 :         mnGrowingSegment = 0;
     174             :     }
     175             : 
     176             :     // Try to find an extendable segment.
     177           9 :     if (mnGrowingSegment < 1)
     178             :     {
     179           9 :         int nSegment = 0;
     180             : 
     181             :         PCIDSKSegment * poSegment;
     182             : 
     183           0 :         while ((poSegment =
     184           9 :                 mpoFile->GetSegment(SEG_SYS, oName, nSegment)) != nullptr)
     185             :         {
     186           0 :             nSegment = poSegment->GetSegmentNumber();
     187             : 
     188           0 :             if (poSegment->IsAtEOF() && poSegment->CanExtend(nExtendSize))
     189             :             {
     190           0 :                 mnGrowingSegment = (uint16) nSegment;
     191           0 :                 break;
     192             :             }
     193             :         }
     194             :     }
     195             : 
     196             :     // Create a new segment if we could not found an extendable segment.
     197           9 :     if (mnGrowingSegment < 1)
     198             :     {
     199           9 :         mnGrowingSegment =
     200           9 :             (uint16) mpoFile->CreateSegment(oName, oDesc, SEG_SYS, 0);
     201             :     }
     202             : 
     203           9 :     mpoFile->ExtendSegment(mnGrowingSegment, (nExtendSize + 511) / 512,
     204             :                            false, false);
     205             : 
     206           9 :     return mnGrowingSegment;
     207             : }
     208             : 
     209          18 : uint64 CPCIDSKBlockFile::GetSegmentSize(uint16 nSegment)
     210             : {
     211          18 :     PCIDSKSegment * poSegment = mpoFile->GetSegment(nSegment);
     212             : 
     213          18 :     return poSegment ? poSegment->GetContentSize() : 0;
     214             : }
     215             : 
     216          39 : void CPCIDSKBlockFile::WriteToSegment(uint16 nSegment, const void * pData,
     217             :                                       uint64 nOffset, uint64 nSize)
     218             : {
     219          39 :     PCIDSKSegment * poSegment = mpoFile->GetSegment(nSegment);
     220             : 
     221          39 :     if (!poSegment)
     222           0 :         return;
     223             : 
     224          39 :     poSegment->WriteToFile(pData, nOffset, nSize);
     225             : }
     226             : 
     227         107 : void CPCIDSKBlockFile::ReadFromSegment(uint16 nSegment, void * pData,
     228             :                                        uint64 nOffset, uint64 nSize)
     229             : {
     230         107 :     PCIDSKSegment * poSegment = mpoFile->GetSegment(nSegment);
     231             : 
     232         107 :     if (!poSegment)
     233           0 :         return;
     234             : 
     235         107 :     poSegment->ReadFromFile(pData, nOffset, nSize);
     236             : }

Generated by: LCOV version 1.14