Coverage Report

Created: 2026-02-14 09:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/frmts/pcidsk/sdk/blockdir/asciitilelayer.cpp
Line
Count
Source
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/asciitilelayer.h"
13
#include "blockdir/blockfile.h"
14
#include "core/pcidsk_scanint.h"
15
#include "pcidsk_exception.h"
16
#include "pcidsk_buffer.h"
17
#include <cstdlib>
18
#include <cstring>
19
#include <cstdio>
20
#include <algorithm>
21
#include <limits>
22
23
using namespace PCIDSK;
24
25
/************************************************************************/
26
/*                           AsciiTileLayer()                           */
27
/************************************************************************/
28
29
/**
30
 * Constructor.
31
 *
32
 * @param poBlockDir The associated block directory.
33
 * @param nLayer The index of the block layer.
34
 * @param psBlockLayer The block layer info.
35
 * @param psTileLayer The tile layer info.
36
 */
37
AsciiTileLayer::AsciiTileLayer(BlockDir * poBlockDir, uint32 nLayer,
38
                               BlockLayerInfo * psBlockLayer,
39
                               TileLayerInfo * psTileLayer)
40
262
    : BlockTileLayer(poBlockDir, nLayer, psBlockLayer, psTileLayer)
41
262
{
42
262
}
43
44
/************************************************************************/
45
/*                             ReadHeader()                             */
46
/************************************************************************/
47
48
/**
49
 * Reads the tile layer header from disk.
50
 */
51
void AsciiTileLayer::ReadHeader(void)
52
175
{
53
175
    uint8 abyHeader[128];
54
55
175
    uint8 * pabyHeaderIter = abyHeader;
56
57
175
    ReadFromLayer(abyHeader, 0, 128);
58
59
175
    mpsTileLayer->nXSize = ScanInt8(pabyHeaderIter);
60
175
    pabyHeaderIter += 8;
61
62
175
    mpsTileLayer->nYSize = ScanInt8(pabyHeaderIter);
63
175
    pabyHeaderIter += 8;
64
65
175
    mpsTileLayer->nTileXSize = ScanInt8(pabyHeaderIter);
66
175
    pabyHeaderIter += 8;
67
68
175
    mpsTileLayer->nTileYSize = ScanInt8(pabyHeaderIter);
69
175
    pabyHeaderIter += 8;
70
71
175
    memcpy(mpsTileLayer->szDataType, pabyHeaderIter, 4);
72
175
    pabyHeaderIter += 4;
73
/*
74
    std::string oNoDataValue((char *) pabyHeaderIter,
75
                             (char *) pabyHeaderIter + 18);
76
*/
77
175
    mpsTileLayer->bNoDataValid = false;
78
175
    mpsTileLayer->dfNoDataValue = 0.0;
79
175
    pabyHeaderIter += 18;
80
81
175
    memcpy(mpsTileLayer->szCompress, pabyHeaderIter, 8);
82
175
}
83
84
/************************************************************************/
85
/*                           WriteTileList()                            */
86
/************************************************************************/
87
88
/**
89
 * Writes the tile list to disk.
90
 */
91
void AsciiTileLayer::WriteTileList(void)
92
0
{
93
0
    uint32 nTileCount = GetTileCount();
94
95
0
    size_t nSize = 128 + nTileCount * 20;
96
97
0
    char * pabyTileLayer = (char *) malloc(nSize + 1); // +1 for '\0'.
98
99
0
    if (!pabyTileLayer)
100
0
        return ThrowPCIDSKException("Out of memory in AsciiTileLayer::WriteTileList().");
101
102
0
    PCIDSKBuffer oTileLayerAutoPtr;
103
0
    oTileLayerAutoPtr.buffer = pabyTileLayer;
104
105
    // Write the tile layer header to disk.
106
0
    char * pabyHeaderIter = pabyTileLayer;
107
108
0
    memset(pabyTileLayer, ' ', 128);
109
110
0
    snprintf(pabyHeaderIter, 9, "%8d", mpsTileLayer->nXSize);
111
0
    pabyHeaderIter += 8;
112
113
0
    snprintf(pabyHeaderIter, 9, "%8d", mpsTileLayer->nYSize);
114
0
    pabyHeaderIter += 8;
115
116
0
    snprintf(pabyHeaderIter, 9, "%8d", mpsTileLayer->nTileXSize);
117
0
    pabyHeaderIter += 8;
118
119
0
    snprintf(pabyHeaderIter, 9, "%8d", mpsTileLayer->nTileYSize);
120
0
    pabyHeaderIter += 8;
121
122
0
    memcpy(pabyHeaderIter, mpsTileLayer->szDataType, 4);
123
0
    pabyHeaderIter += 4;
124
125
0
    if (mpsTileLayer->bNoDataValid)
126
0
        snprintf(pabyHeaderIter, 19, "%18.10E", mpsTileLayer->dfNoDataValue);
127
0
    pabyHeaderIter += 18;
128
129
0
    memcpy(pabyHeaderIter, mpsTileLayer->szCompress, 8);
130
131
    // Write the tile list to disk.
132
0
    char * pabyTileListIter = pabyTileLayer + 128;
133
134
0
    for (uint32 iTile = 0; iTile < nTileCount; iTile++)
135
0
    {
136
0
        BlockTileInfo * psTile = &moTileList[iTile];
137
138
0
        snprintf(pabyTileListIter, 13, "%12" PCIDSK_FRMT_64_WITHOUT_PREFIX "d", psTile->nOffset);
139
0
        pabyTileListIter += 12;
140
0
    }
141
142
    // We cannot write the offset and the size at the same time because
143
    // snprintf() inserts a '\0' in the first character of the first size.
144
0
    for (uint32 iTile = 0; iTile < nTileCount; iTile++)
145
0
    {
146
0
        BlockTileInfo * psTile = &moTileList[iTile];
147
148
0
        snprintf(pabyTileListIter, 9, "%8d", psTile->nSize);
149
0
        pabyTileListIter += 8;
150
0
    }
151
152
0
    WriteToLayer(pabyTileLayer, 0, nSize);
153
0
}
154
155
/************************************************************************/
156
/*                            ReadTileList()                            */
157
/************************************************************************/
158
159
/**
160
 * Reads the tile list from disk.
161
 */
162
void AsciiTileLayer::ReadTileList(void)
163
19
{
164
19
    uint32 nTileCount = GetTileCount();
165
166
19
    uint64 nSize = static_cast<uint64>(nTileCount) * 20;
167
168
19
    if (128 + nSize > GetLayerSize() || !GetFile()->IsValidFileOffset(128 + nSize))
169
1
        return ThrowPCIDSKException("The tile layer is corrupted.");
170
171
#if SIZEOF_VOIDP < 8
172
    if (nSize > std::numeric_limits<size_t>::max())
173
        return ThrowPCIDSKException("Unable to open extremely large tile layer on 32-bit system.");
174
#endif
175
176
18
    uint8 * pabyTileList = (uint8 *) malloc(static_cast<size_t>(nSize));
177
178
18
    if (!pabyTileList)
179
0
        return ThrowPCIDSKException("Out of memory in AsciiTileLayer::ReadTileList().");
180
181
18
    PCIDSKBuffer oTileListAutoPtr;
182
18
    oTileListAutoPtr.buffer = reinterpret_cast<char *>(pabyTileList);
183
184
18
    ReadFromLayer(pabyTileList, 128, nSize);
185
186
18
    uint8 * pabyTileOffsetIter = pabyTileList;
187
18
    uint8 * pabyTileSizeIter = pabyTileList + nTileCount * 12;
188
189
18
    try
190
18
    {
191
18
        moTileList.resize(nTileCount);
192
18
    }
193
18
    catch (const std::exception & ex)
194
18
    {
195
0
        return ThrowPCIDSKException("Out of memory in AsciiTileLayer::ReadTileList(): %s", ex.what());
196
0
    }
197
198
180
    for (uint32 iTile = 0; iTile < nTileCount; iTile++)
199
162
    {
200
162
        BlockTileInfo * psTile = &moTileList[iTile];
201
202
162
        psTile->nOffset = ScanInt12(pabyTileOffsetIter);
203
162
        pabyTileOffsetIter += 12;
204
205
162
        psTile->nSize = ScanInt8(pabyTileSizeIter);
206
162
        pabyTileSizeIter += 8;
207
162
    }
208
18
}