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: 2024-11-21 22:18:42 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          76 : CPCIDSKBlockFile::CPCIDSKBlockFile(PCIDSKFile * poFile)
      24          76 :     : mpoFile(dynamic_cast<CPCIDSKFile *>(poFile)),
      25          76 :       mnGrowingSegment(0)
      26             : {
      27          76 :     assert(mpoFile);
      28          76 : }
      29             : 
      30          37 : SysTileDir * CPCIDSKBlockFile::GetTileDir(void)
      31             : {
      32          16 :     SysTileDir * poTileDir = dynamic_cast<SysTileDir *>
      33          53 :         (mpoFile->GetSegment(SEG_SYS, "TileDir"));
      34             : 
      35          37 :     if (!poTileDir)
      36             :     {
      37           1 :         poTileDir = dynamic_cast<SysTileDir *>
      38          17 :             (mpoFile->GetSegment(SEG_SYS, "SysBMDir"));
      39             :     }
      40             : 
      41          37 :     return poTileDir;
      42             : }
      43             : 
      44           8 : SysTileDir * CPCIDSKBlockFile::CreateTileDir(void)
      45             : {
      46           8 :     SysTileDir * poTileDir = nullptr;
      47             : 
      48           8 :     std::string oFileOptions = GetFileOptions();
      49             : 
      50         100 :     for (char & chIter : oFileOptions)
      51          92 :         chIter = (char) toupper(static_cast<unsigned char>(chIter));
      52             : 
      53             :     // Check if we should create a TILEV1 or TILEV2 block directory.
      54           8 :     bool bTileV1 = oFileOptions.find("TILEV1") != std::string::npos;
      55           8 :     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          12 :     if (!bTileV2 && !bTileV1 &&
      60           4 :         GetImageFileSize() > (uint64) 549755813888ULL)
      61             :     {
      62           0 :         bTileV2 = true;
      63             :     }
      64             : 
      65             :     // We now use TILEV2 by default.
      66           8 :     if (bTileV2 || !bTileV1)
      67             :     {
      68           6 :         const char * pszDesc = "Block Tile Directory - Do not modify.";
      69             : 
      70           6 :         size_t nSegmentSize = BinaryTileDir::GetOptimizedDirSize(this);
      71             : 
      72             :         int nSegment =
      73           6 :             mpoFile->CreateSegment("TileDir", pszDesc, SEG_SYS,
      74           6 :                                    (int) ((nSegmentSize + 511) / 512));
      75             : 
      76           6 :         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           8 :     assert(poTileDir);
      93             : 
      94           8 :     poTileDir->CreateTileDir();
      95             : 
      96          16 :     return poTileDir;
      97             : }
      98             : 
      99           0 : std::string CPCIDSKBlockFile::GetFilename(void) const
     100             : {
     101           0 :     return mpoFile->GetFilename();
     102             : }
     103             : 
     104          16 : bool CPCIDSKBlockFile::GetUpdatable(void) const
     105             : {
     106          16 :     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           8 : uint32 CPCIDSKBlockFile::GetChannels(void) const
     120             : {
     121           8 :     return mpoFile->GetChannels();
     122             : }
     123             : 
     124          28 : std::string CPCIDSKBlockFile::GetFileOptions(void) const
     125             : {
     126          28 :     return mpoFile->GetMetadataValue("_DBLayout");
     127             : }
     128             : 
     129          20 : uint64 CPCIDSKBlockFile::GetImageFileSize(void) const
     130             : {
     131          20 :     uint64 nImageSize = 0;
     132             : 
     133          20 :     int nChanCount = mpoFile->GetChannels();
     134             : 
     135          40 :     for (int iChan = 1; iChan <= nChanCount; iChan++)
     136             :     {
     137          20 :         PCIDSKChannel * poChannel = mpoFile->GetChannel(iChan);
     138             : 
     139          20 :         nImageSize += DataTypeSize(poChannel->GetType());
     140             :     }
     141             : 
     142          20 :     return nImageSize * mpoFile->GetWidth() * mpoFile->GetHeight();
     143             : }
     144             : 
     145          58 : bool CPCIDSKBlockFile::IsValidFileOffset(uint64 nOffset) const
     146             : {
     147          58 :     return nOffset <= mpoFile->GetFileSize() * 512;
     148             : }
     149             : 
     150          46 : bool CPCIDSKBlockFile::IsCorruptedSegment(uint16 nSegment, uint64 nOffset, uint64 nSize) const
     151             : {
     152          46 :     PCIDSKSegment * poSegment = mpoFile->GetSegment(nSegment);
     153             : 
     154          46 :     return (!poSegment ||
     155          92 :             nOffset + nSize > poSegment->GetContentSize() ||
     156          92 :             !IsValidFileOffset(nOffset + nSize + poSegment->GetContentOffset()));
     157             : }
     158             : 
     159           8 : 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           8 :     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           8 :         mnGrowingSegment = 0;
     174             :     }
     175             : 
     176             :     // Try to find an extendable segment.
     177           8 :     if (mnGrowingSegment < 1)
     178             :     {
     179           8 :         int nSegment = 0;
     180             : 
     181             :         PCIDSKSegment * poSegment;
     182             : 
     183           0 :         while ((poSegment =
     184           8 :                 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           8 :     if (mnGrowingSegment < 1)
     198             :     {
     199           8 :         mnGrowingSegment =
     200           8 :             (uint16) mpoFile->CreateSegment(oName, oDesc, SEG_SYS, 0);
     201             :     }
     202             : 
     203           8 :     mpoFile->ExtendSegment(mnGrowingSegment, (nExtendSize + 511) / 512,
     204             :                            false, false);
     205             : 
     206           8 :     return mnGrowingSegment;
     207             : }
     208             : 
     209          16 : uint64 CPCIDSKBlockFile::GetSegmentSize(uint16 nSegment)
     210             : {
     211          16 :     PCIDSKSegment * poSegment = mpoFile->GetSegment(nSegment);
     212             : 
     213          16 :     return poSegment ? poSegment->GetContentSize() : 0;
     214             : }
     215             : 
     216          32 : void CPCIDSKBlockFile::WriteToSegment(uint16 nSegment, const void * pData,
     217             :                                       uint64 nOffset, uint64 nSize)
     218             : {
     219          32 :     PCIDSKSegment * poSegment = mpoFile->GetSegment(nSegment);
     220             : 
     221          32 :     if (!poSegment)
     222           0 :         return;
     223             : 
     224          32 :     poSegment->WriteToFile(pData, nOffset, nSize);
     225             : }
     226             : 
     227         105 : void CPCIDSKBlockFile::ReadFromSegment(uint16 nSegment, void * pData,
     228             :                                        uint64 nOffset, uint64 nSize)
     229             : {
     230         105 :     PCIDSKSegment * poSegment = mpoFile->GetSegment(nSegment);
     231             : 
     232         105 :     if (!poSegment)
     233           0 :         return;
     234             : 
     235         105 :     poSegment->ReadFromFile(pData, nOffset, nSize);
     236             : }

Generated by: LCOV version 1.14