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-05-03 15:49:35 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      10             :  * copy of this software and associated documentation files (the "Software"),
      11             :  * to deal in the Software without restriction, including without limitation
      12             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      13             :  * and/or sell copies of the Software, and to permit persons to whom the
      14             :  * Software is furnished to do so, subject to the following conditions:
      15             :  *
      16             :  * The above copyright notice and this permission notice shall be included
      17             :  * in all copies or substantial portions of the Software.
      18             :  *
      19             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      20             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      21             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      22             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      23             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      24             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      25             :  * DEALINGS IN THE SOFTWARE.
      26             :  ****************************************************************************/
      27             : 
      28             : #include "core/cpcidskblockfile.h"
      29             : #include "core/cpcidskfile.h"
      30             : #include "segment/systiledir.h"
      31             : #include "blockdir/asciitiledir.h"
      32             : #include "blockdir/binarytiledir.h"
      33             : #include "pcidsk_channel.h"
      34             : #include <cassert>
      35             : #include <algorithm>
      36             : 
      37             : using namespace PCIDSK;
      38             : 
      39          76 : CPCIDSKBlockFile::CPCIDSKBlockFile(PCIDSKFile * poFile)
      40          76 :     : mpoFile(dynamic_cast<CPCIDSKFile *>(poFile)),
      41          76 :       mnGrowingSegment(0)
      42             : {
      43          76 :     assert(mpoFile);
      44          76 : }
      45             : 
      46          37 : SysTileDir * CPCIDSKBlockFile::GetTileDir(void)
      47             : {
      48          16 :     SysTileDir * poTileDir = dynamic_cast<SysTileDir *>
      49          53 :         (mpoFile->GetSegment(SEG_SYS, "TileDir"));
      50             : 
      51          37 :     if (!poTileDir)
      52             :     {
      53           1 :         poTileDir = dynamic_cast<SysTileDir *>
      54          17 :             (mpoFile->GetSegment(SEG_SYS, "SysBMDir"));
      55             :     }
      56             : 
      57          37 :     return poTileDir;
      58             : }
      59             : 
      60           8 : SysTileDir * CPCIDSKBlockFile::CreateTileDir(void)
      61             : {
      62           8 :     SysTileDir * poTileDir = nullptr;
      63             : 
      64           8 :     std::string oFileOptions = GetFileOptions();
      65             : 
      66         100 :     for (char & chIter : oFileOptions)
      67          92 :         chIter = (char) toupper(static_cast<unsigned char>(chIter));
      68             : 
      69             :     // Check if we should create a TILEV1 or TILEV2 block directory.
      70           8 :     bool bTileV1 = oFileOptions.find("TILEV1") != std::string::npos;
      71           8 :     bool bTileV2 = oFileOptions.find("TILEV2") != std::string::npos;
      72             : 
      73             :     // The TILEV1 block directory has a limit of 762GB, so default
      74             :     // to TILEV2 if the image file size exceed 512GB.
      75          12 :     if (!bTileV2 && !bTileV1 &&
      76           4 :         GetImageFileSize() > (uint64) 549755813888ULL)
      77             :     {
      78           0 :         bTileV2 = true;
      79             :     }
      80             : 
      81             :     // We now use TILEV2 by default.
      82           8 :     if (bTileV2 || !bTileV1)
      83             :     {
      84           6 :         const char * pszDesc = "Block Tile Directory - Do not modify.";
      85             : 
      86           6 :         size_t nSegmentSize = BinaryTileDir::GetOptimizedDirSize(this);
      87             : 
      88             :         int nSegment =
      89           6 :             mpoFile->CreateSegment("TileDir", pszDesc, SEG_SYS,
      90           6 :                                    (int) ((nSegmentSize + 511) / 512));
      91             : 
      92           6 :         poTileDir = dynamic_cast<SysTileDir *>(mpoFile->GetSegment(nSegment));
      93             :     }
      94             :     else
      95             :     {
      96           2 :         const char * pszDesc =
      97             :             "System Block Map Directory - Do not modify.";
      98             : 
      99           2 :         size_t nSegmentSize = AsciiTileDir::GetOptimizedDirSize(this);
     100             : 
     101             :         int nSegment =
     102           2 :             mpoFile->CreateSegment("SysBMDir", pszDesc, SEG_SYS,
     103           2 :                                    (int) ((nSegmentSize + 511) / 512));
     104             : 
     105           2 :         poTileDir = dynamic_cast<SysTileDir *>(mpoFile->GetSegment(nSegment));
     106             :     }
     107             : 
     108           8 :     assert(poTileDir);
     109             : 
     110           8 :     poTileDir->CreateTileDir();
     111             : 
     112          16 :     return poTileDir;
     113             : }
     114             : 
     115           0 : std::string CPCIDSKBlockFile::GetFilename(void) const
     116             : {
     117           0 :     return mpoFile->GetFilename();
     118             : }
     119             : 
     120          16 : bool CPCIDSKBlockFile::GetUpdatable(void) const
     121             : {
     122          16 :     return mpoFile->GetUpdatable();
     123             : }
     124             : 
     125           0 : uint32 CPCIDSKBlockFile::GetWidth(void) const
     126             : {
     127           0 :     return mpoFile->GetWidth();
     128             : }
     129             : 
     130           0 : uint32 CPCIDSKBlockFile::GetHeight(void) const
     131             : {
     132           0 :     return mpoFile->GetHeight();
     133             : }
     134             : 
     135           8 : uint32 CPCIDSKBlockFile::GetChannels(void) const
     136             : {
     137           8 :     return mpoFile->GetChannels();
     138             : }
     139             : 
     140          28 : std::string CPCIDSKBlockFile::GetFileOptions(void) const
     141             : {
     142          28 :     return mpoFile->GetMetadataValue("_DBLayout");
     143             : }
     144             : 
     145          20 : uint64 CPCIDSKBlockFile::GetImageFileSize(void) const
     146             : {
     147          20 :     uint64 nImageSize = 0;
     148             : 
     149          20 :     int nChanCount = mpoFile->GetChannels();
     150             : 
     151          40 :     for (int iChan = 1; iChan <= nChanCount; iChan++)
     152             :     {
     153          20 :         PCIDSKChannel * poChannel = mpoFile->GetChannel(iChan);
     154             : 
     155          20 :         nImageSize += DataTypeSize(poChannel->GetType());
     156             :     }
     157             : 
     158          20 :     return nImageSize * mpoFile->GetWidth() * mpoFile->GetHeight();
     159             : }
     160             : 
     161          58 : bool CPCIDSKBlockFile::IsValidFileOffset(uint64 nOffset) const
     162             : {
     163          58 :     return nOffset <= mpoFile->GetFileSize() * 512;
     164             : }
     165             : 
     166          46 : bool CPCIDSKBlockFile::IsCorruptedSegment(uint16 nSegment, uint64 nOffset, uint64 nSize) const
     167             : {
     168          46 :     PCIDSKSegment * poSegment = mpoFile->GetSegment(nSegment);
     169             : 
     170          46 :     return (!poSegment ||
     171          92 :             nOffset + nSize > poSegment->GetContentSize() ||
     172          92 :             !IsValidFileOffset(nOffset + nSize + poSegment->GetContentOffset()));
     173             : }
     174             : 
     175           8 : uint16 CPCIDSKBlockFile::ExtendSegment(const std::string & oName,
     176             :                                        const std::string & oDesc,
     177             :                                        uint64 nExtendSize)
     178             : {
     179             :     // Check to see if the cached growing segment is still valid.
     180           8 :     if (mnGrowingSegment > 0)
     181             :     {
     182           0 :         PCIDSKSegment * poSegment = mpoFile->GetSegment(mnGrowingSegment);
     183             : 
     184           0 :         if (!poSegment->IsAtEOF() || !poSegment->CanExtend(nExtendSize))
     185           0 :             mnGrowingSegment = 0;
     186             :     }
     187             :     else
     188             :     {
     189           8 :         mnGrowingSegment = 0;
     190             :     }
     191             : 
     192             :     // Try to find an extendable segment.
     193           8 :     if (mnGrowingSegment < 1)
     194             :     {
     195           8 :         int nSegment = 0;
     196             : 
     197             :         PCIDSKSegment * poSegment;
     198             : 
     199           0 :         while ((poSegment =
     200           8 :                 mpoFile->GetSegment(SEG_SYS, oName, nSegment)) != nullptr)
     201             :         {
     202           0 :             nSegment = poSegment->GetSegmentNumber();
     203             : 
     204           0 :             if (poSegment->IsAtEOF() && poSegment->CanExtend(nExtendSize))
     205             :             {
     206           0 :                 mnGrowingSegment = (uint16) nSegment;
     207           0 :                 break;
     208             :             }
     209             :         }
     210             :     }
     211             : 
     212             :     // Create a new segment if we could not found an extendable segment.
     213           8 :     if (mnGrowingSegment < 1)
     214             :     {
     215           8 :         mnGrowingSegment =
     216           8 :             (uint16) mpoFile->CreateSegment(oName, oDesc, SEG_SYS, 0);
     217             :     }
     218             : 
     219           8 :     mpoFile->ExtendSegment(mnGrowingSegment, (nExtendSize + 511) / 512,
     220             :                            false, false);
     221             : 
     222           8 :     return mnGrowingSegment;
     223             : }
     224             : 
     225          16 : uint64 CPCIDSKBlockFile::GetSegmentSize(uint16 nSegment)
     226             : {
     227          16 :     PCIDSKSegment * poSegment = mpoFile->GetSegment(nSegment);
     228             : 
     229          16 :     return poSegment ? poSegment->GetContentSize() : 0;
     230             : }
     231             : 
     232          32 : void CPCIDSKBlockFile::WriteToSegment(uint16 nSegment, const void * pData,
     233             :                                       uint64 nOffset, uint64 nSize)
     234             : {
     235          32 :     PCIDSKSegment * poSegment = mpoFile->GetSegment(nSegment);
     236             : 
     237          32 :     if (!poSegment)
     238           0 :         return;
     239             : 
     240          32 :     poSegment->WriteToFile(pData, nOffset, nSize);
     241             : }
     242             : 
     243         105 : void CPCIDSKBlockFile::ReadFromSegment(uint16 nSegment, void * pData,
     244             :                                        uint64 nOffset, uint64 nSize)
     245             : {
     246         105 :     PCIDSKSegment * poSegment = mpoFile->GetSegment(nSegment);
     247             : 
     248         105 :     if (!poSegment)
     249           0 :         return;
     250             : 
     251         105 :     poSegment->ReadFromFile(pData, nOffset, nSize);
     252             : }

Generated by: LCOV version 1.14