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