Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: NULL driver.
5 : * Author: Even Rouault, <even dot rouault at spatialys dot org>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2012-2017, Even Rouault, <even dot rouault at spatialys dot
9 : *org>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "gdal_priv.h"
15 : #include "ogrsf_frmts.h"
16 :
17 : extern "C" void GDALRegister_NULL();
18 :
19 : /************************************************************************/
20 : /* GDALNullDataset */
21 : /************************************************************************/
22 :
23 : class GDALNullDataset final : public GDALDataset
24 : {
25 : int m_nLayers;
26 : OGRLayer **m_papoLayers;
27 :
28 : public:
29 : GDALNullDataset();
30 : virtual ~GDALNullDataset();
31 :
32 0 : virtual int GetLayerCount() override
33 : {
34 0 : return m_nLayers;
35 : }
36 :
37 : virtual OGRLayer *GetLayer(int) override;
38 :
39 : OGRLayer *ICreateLayer(const char *pszName,
40 : const OGRGeomFieldDefn *poGeomFieldDefn,
41 : CSLConstList papszOptions) override;
42 :
43 : virtual int TestCapability(const char *) override;
44 :
45 : CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override;
46 :
47 : virtual CPLErr SetGeoTransform(double *) override;
48 :
49 : static GDALDataset *Open(GDALOpenInfo *poOpenInfo);
50 : static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize,
51 : int nBands, GDALDataType eType,
52 : char **papszOptions);
53 : };
54 :
55 : /************************************************************************/
56 : /* GDALNullLayer */
57 : /************************************************************************/
58 :
59 : class GDALNullRasterBand final : public GDALRasterBand
60 : {
61 : public:
62 : explicit GDALNullRasterBand(GDALDataType eDT);
63 :
64 : virtual CPLErr IReadBlock(int, int, void *) override;
65 : virtual CPLErr IWriteBlock(int, int, void *) override;
66 : virtual CPLErr IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
67 : int nXSize, int nYSize, void *pData, int nBufXSize,
68 : int nBufYSize, GDALDataType eBufType,
69 : GSpacing nPixelSpace, GSpacing nLineSpace,
70 : GDALRasterIOExtraArg *psExtraArg) override;
71 : };
72 :
73 : /************************************************************************/
74 : /* GDALNullLayer */
75 : /************************************************************************/
76 :
77 : class GDALNullLayer final : public OGRLayer
78 : {
79 : OGRFeatureDefn *poFeatureDefn;
80 : OGRSpatialReference *poSRS = nullptr;
81 :
82 : public:
83 : GDALNullLayer(const char *pszLayerName, const OGRSpatialReference *poSRS,
84 : OGRwkbGeometryType eType);
85 : virtual ~GDALNullLayer();
86 :
87 0 : virtual OGRFeatureDefn *GetLayerDefn() override
88 : {
89 0 : return poFeatureDefn;
90 : }
91 :
92 0 : virtual OGRSpatialReference *GetSpatialRef() override
93 : {
94 0 : return poSRS;
95 : }
96 :
97 0 : virtual void ResetReading() override
98 : {
99 0 : }
100 :
101 : virtual int TestCapability(const char *) override;
102 :
103 0 : virtual OGRFeature *GetNextFeature() override
104 : {
105 0 : return nullptr;
106 : }
107 :
108 0 : virtual OGRErr ICreateFeature(OGRFeature *) override
109 : {
110 0 : return OGRERR_NONE;
111 : }
112 :
113 : virtual OGRErr CreateField(const OGRFieldDefn *poField,
114 : int bApproxOK = TRUE) override;
115 : };
116 :
117 : /************************************************************************/
118 : /* GDALNullRasterBand() */
119 : /************************************************************************/
120 :
121 95 : GDALNullRasterBand::GDALNullRasterBand(GDALDataType eDT)
122 : {
123 95 : eDataType = eDT;
124 95 : nBlockXSize = 256;
125 95 : nBlockYSize = 256;
126 95 : }
127 :
128 : /************************************************************************/
129 : /* IRasterIO() */
130 : /************************************************************************/
131 :
132 26 : CPLErr GDALNullRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
133 : int nXSize, int nYSize, void *pData,
134 : int nBufXSize, int nBufYSize,
135 : GDALDataType eBufType,
136 : GSpacing nPixelSpace, GSpacing nLineSpace,
137 : GDALRasterIOExtraArg *psExtraArg)
138 : {
139 26 : if (eRWFlag == GF_Write)
140 26 : return CE_None;
141 0 : if (psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
142 0 : (nBufXSize != nXSize || nBufYSize != nYSize))
143 : {
144 0 : return GDALRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
145 : pData, nBufXSize, nBufYSize, eBufType,
146 0 : nPixelSpace, nLineSpace, psExtraArg);
147 : }
148 0 : if (nPixelSpace == GDALGetDataTypeSizeBytes(eBufType) &&
149 0 : nLineSpace == nPixelSpace * nBufXSize)
150 : {
151 0 : memset(pData, 0, static_cast<size_t>(nLineSpace) * nBufYSize);
152 : }
153 : else
154 : {
155 0 : for (int iY = 0; iY < nBufYSize; iY++)
156 : {
157 0 : double dfZero = 0;
158 0 : GDALCopyWords(&dfZero, GDT_Float64, 0,
159 0 : reinterpret_cast<GByte *>(pData) + iY * nLineSpace,
160 : eBufType, static_cast<int>(nPixelSpace), nBufXSize);
161 : }
162 : }
163 0 : return CE_None;
164 : }
165 :
166 : /************************************************************************/
167 : /* IReadBlock() */
168 : /************************************************************************/
169 :
170 0 : CPLErr GDALNullRasterBand::IReadBlock(int, int, void *pData)
171 : {
172 0 : memset(pData, 0,
173 0 : static_cast<size_t>(nBlockXSize) * nBlockYSize *
174 0 : GDALGetDataTypeSizeBytes(eDataType));
175 0 : return CE_None;
176 : }
177 :
178 : /************************************************************************/
179 : /* IWriteBlock() */
180 : /************************************************************************/
181 :
182 0 : CPLErr GDALNullRasterBand::IWriteBlock(int, int, void *)
183 : {
184 0 : return CE_None;
185 : }
186 :
187 : /************************************************************************/
188 : /* GDALNullDataset() */
189 : /************************************************************************/
190 :
191 51 : GDALNullDataset::GDALNullDataset() : m_nLayers(0), m_papoLayers(nullptr)
192 : {
193 51 : eAccess = GA_Update;
194 51 : }
195 :
196 : /************************************************************************/
197 : /* ~GDALNullDataset() */
198 : /************************************************************************/
199 :
200 102 : GDALNullDataset::~GDALNullDataset()
201 : {
202 51 : for (int i = 0; i < m_nLayers; i++)
203 0 : delete m_papoLayers[i];
204 51 : CPLFree(m_papoLayers);
205 102 : }
206 :
207 : /************************************************************************/
208 : /* ICreateLayer() */
209 : /************************************************************************/
210 :
211 0 : OGRLayer *GDALNullDataset::ICreateLayer(const char *pszLayerName,
212 : const OGRGeomFieldDefn *poGeomFieldDefn,
213 : CSLConstList /*papszOptions */)
214 : {
215 0 : const auto eType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
216 : const auto poSRS =
217 0 : poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr;
218 :
219 0 : m_papoLayers = static_cast<OGRLayer **>(
220 0 : CPLRealloc(m_papoLayers, sizeof(OGRLayer *) * (m_nLayers + 1)));
221 0 : m_papoLayers[m_nLayers] = new GDALNullLayer(pszLayerName, poSRS, eType);
222 0 : m_nLayers++;
223 0 : return m_papoLayers[m_nLayers - 1];
224 : }
225 :
226 : /************************************************************************/
227 : /* TestCapability() */
228 : /************************************************************************/
229 :
230 0 : int GDALNullDataset::TestCapability(const char *pszCap)
231 :
232 : {
233 0 : if (EQUAL(pszCap, ODsCCreateLayer))
234 0 : return TRUE;
235 0 : if (EQUAL(pszCap, ODsCRandomLayerWrite))
236 0 : return TRUE;
237 0 : return FALSE;
238 : }
239 :
240 : /************************************************************************/
241 : /* GetLayer() */
242 : /************************************************************************/
243 :
244 0 : OGRLayer *GDALNullDataset::GetLayer(int iLayer)
245 :
246 : {
247 0 : if (iLayer < 0 || iLayer >= m_nLayers)
248 0 : return nullptr;
249 : else
250 0 : return m_papoLayers[iLayer];
251 : }
252 :
253 : /************************************************************************/
254 : /* SetSpatialRef() */
255 : /************************************************************************/
256 :
257 51 : CPLErr GDALNullDataset::SetSpatialRef(const OGRSpatialReference *)
258 :
259 : {
260 51 : return CE_None;
261 : }
262 :
263 : /************************************************************************/
264 : /* SetGeoTransform() */
265 : /************************************************************************/
266 :
267 51 : CPLErr GDALNullDataset::SetGeoTransform(double *)
268 :
269 : {
270 51 : return CE_None;
271 : }
272 :
273 : /************************************************************************/
274 : /* Open() */
275 : /************************************************************************/
276 :
277 39270 : GDALDataset *GDALNullDataset::Open(GDALOpenInfo *poOpenInfo)
278 : {
279 39270 : if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "NULL:"))
280 39263 : return nullptr;
281 :
282 7 : const char *pszStr = poOpenInfo->pszFilename + strlen("NULL:");
283 7 : char **papszTokens = CSLTokenizeString2(pszStr, ",", 0);
284 0 : int nXSize = atoi(CSLFetchNameValueDef(papszTokens, "width", "512"));
285 0 : int nYSize = atoi(CSLFetchNameValueDef(papszTokens, "height", "512"));
286 0 : int nBands = atoi(CSLFetchNameValueDef(papszTokens, "bands", "1"));
287 0 : const char *pszDTName = CSLFetchNameValueDef(papszTokens, "type", "Byte");
288 0 : GDALDataType eDT = GDT_Byte;
289 0 : for (int iType = 1; iType < GDT_TypeCount; iType++)
290 : {
291 0 : if (GDALGetDataTypeName((GDALDataType)iType) != nullptr &&
292 0 : EQUAL(GDALGetDataTypeName((GDALDataType)iType), pszDTName))
293 : {
294 0 : eDT = (GDALDataType)iType;
295 0 : break;
296 : }
297 : }
298 0 : CSLDestroy(papszTokens);
299 :
300 0 : return Create("", nXSize, nYSize, nBands, eDT, nullptr);
301 : }
302 :
303 : /************************************************************************/
304 : /* Create() */
305 : /************************************************************************/
306 :
307 51 : GDALDataset *GDALNullDataset::Create(const char *, int nXSize, int nYSize,
308 : int nBandsIn, GDALDataType eType, char **)
309 : {
310 51 : GDALNullDataset *poDS = new GDALNullDataset();
311 51 : poDS->nRasterXSize = nXSize;
312 51 : poDS->nRasterYSize = nYSize;
313 146 : for (int i = 0; i < nBandsIn; i++)
314 95 : poDS->SetBand(i + 1, new GDALNullRasterBand(eType));
315 51 : return poDS;
316 : }
317 :
318 : /************************************************************************/
319 : /* GDALNullLayer() */
320 : /************************************************************************/
321 :
322 0 : GDALNullLayer::GDALNullLayer(const char *pszLayerName,
323 : const OGRSpatialReference *poSRSIn,
324 0 : OGRwkbGeometryType eType)
325 0 : : poFeatureDefn(new OGRFeatureDefn(pszLayerName))
326 : {
327 0 : SetDescription(poFeatureDefn->GetName());
328 0 : poFeatureDefn->SetGeomType(eType);
329 0 : poFeatureDefn->Reference();
330 :
331 0 : if (poSRSIn)
332 0 : poSRS = poSRSIn->Clone();
333 0 : }
334 :
335 : /************************************************************************/
336 : /* ~GDALNullLayer() */
337 : /************************************************************************/
338 :
339 0 : GDALNullLayer::~GDALNullLayer()
340 : {
341 0 : poFeatureDefn->Release();
342 :
343 0 : if (poSRS)
344 0 : poSRS->Release();
345 0 : }
346 :
347 : /************************************************************************/
348 : /* TestCapability() */
349 : /************************************************************************/
350 :
351 0 : int GDALNullLayer::TestCapability(const char *pszCap)
352 :
353 : {
354 0 : if (EQUAL(pszCap, OLCSequentialWrite))
355 0 : return TRUE;
356 0 : if (EQUAL(pszCap, OLCCreateField))
357 0 : return TRUE;
358 0 : return FALSE;
359 : }
360 :
361 : /************************************************************************/
362 : /* CreateField() */
363 : /************************************************************************/
364 :
365 0 : OGRErr GDALNullLayer::CreateField(const OGRFieldDefn *poField, int)
366 : {
367 0 : poFeatureDefn->AddFieldDefn(poField);
368 0 : return OGRERR_NONE;
369 : }
370 :
371 : /************************************************************************/
372 : /* GDALRegister_NULL() */
373 : /************************************************************************/
374 :
375 1595 : void GDALRegister_NULL()
376 :
377 : {
378 1595 : if (GDALGetDriverByName("NULL") != nullptr)
379 302 : return;
380 :
381 : GDALDriver *poDriver;
382 1293 : poDriver = new GDALDriver();
383 :
384 1293 : poDriver->SetDescription("NULL");
385 1293 : poDriver->SetMetadataItem(GDAL_DMD_CONNECTION_PREFIX, "NULL: ");
386 1293 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
387 1293 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
388 1293 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
389 1293 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
390 1293 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "NULL");
391 :
392 1293 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES,
393 : "Integer Integer64 Real String Date DateTime "
394 : "Binary IntegerList Integer64List "
395 1293 : "RealList StringList");
396 :
397 1293 : poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
398 :
399 1293 : poDriver->pfnOpen = GDALNullDataset::Open;
400 1293 : poDriver->pfnCreate = GDALNullDataset::Create;
401 :
402 1293 : GetGDALDriverManager()->RegisterDriver(poDriver);
403 : }
|