/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 | } |