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