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