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 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "gdal_priv.h"
31 : #include "ogrsf_frmts.h"
32 :
33 : extern "C" void GDALRegister_NULL();
34 :
35 : /************************************************************************/
36 : /* GDALNullDataset */
37 : /************************************************************************/
38 :
39 : class GDALNullDataset final : public GDALDataset
40 : {
41 : int m_nLayers;
42 : OGRLayer **m_papoLayers;
43 :
44 : public:
45 : GDALNullDataset();
46 : virtual ~GDALNullDataset();
47 :
48 0 : virtual int GetLayerCount() override
49 : {
50 0 : return m_nLayers;
51 : }
52 :
53 : virtual OGRLayer *GetLayer(int) override;
54 :
55 : OGRLayer *ICreateLayer(const char *pszName,
56 : const OGRGeomFieldDefn *poGeomFieldDefn,
57 : CSLConstList papszOptions) override;
58 :
59 : virtual int TestCapability(const char *) override;
60 :
61 : CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override;
62 :
63 : virtual CPLErr SetGeoTransform(double *) override;
64 :
65 : static GDALDataset *Open(GDALOpenInfo *poOpenInfo);
66 : static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize,
67 : int nBands, GDALDataType eType,
68 : char **papszOptions);
69 : };
70 :
71 : /************************************************************************/
72 : /* GDALNullLayer */
73 : /************************************************************************/
74 :
75 : class GDALNullRasterBand final : public GDALRasterBand
76 : {
77 : public:
78 : explicit GDALNullRasterBand(GDALDataType eDT);
79 :
80 : virtual CPLErr IReadBlock(int, int, void *) override;
81 : virtual CPLErr IWriteBlock(int, int, void *) override;
82 : virtual CPLErr IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
83 : int nXSize, int nYSize, void *pData, int nBufXSize,
84 : int nBufYSize, GDALDataType eBufType,
85 : GSpacing nPixelSpace, GSpacing nLineSpace,
86 : GDALRasterIOExtraArg *psExtraArg) override;
87 : };
88 :
89 : /************************************************************************/
90 : /* GDALNullLayer */
91 : /************************************************************************/
92 :
93 : class GDALNullLayer final : public OGRLayer
94 : {
95 : OGRFeatureDefn *poFeatureDefn;
96 : OGRSpatialReference *poSRS = nullptr;
97 :
98 : public:
99 : GDALNullLayer(const char *pszLayerName, const OGRSpatialReference *poSRS,
100 : OGRwkbGeometryType eType);
101 : virtual ~GDALNullLayer();
102 :
103 0 : virtual OGRFeatureDefn *GetLayerDefn() override
104 : {
105 0 : return poFeatureDefn;
106 : }
107 :
108 0 : virtual OGRSpatialReference *GetSpatialRef() override
109 : {
110 0 : return poSRS;
111 : }
112 :
113 0 : virtual void ResetReading() override
114 : {
115 0 : }
116 :
117 : virtual int TestCapability(const char *) override;
118 :
119 0 : virtual OGRFeature *GetNextFeature() override
120 : {
121 0 : return nullptr;
122 : }
123 :
124 0 : virtual OGRErr ICreateFeature(OGRFeature *) override
125 : {
126 0 : return OGRERR_NONE;
127 : }
128 :
129 : virtual OGRErr CreateField(const OGRFieldDefn *poField,
130 : int bApproxOK = TRUE) override;
131 : };
132 :
133 : /************************************************************************/
134 : /* GDALNullRasterBand() */
135 : /************************************************************************/
136 :
137 95 : GDALNullRasterBand::GDALNullRasterBand(GDALDataType eDT)
138 : {
139 95 : eDataType = eDT;
140 95 : nBlockXSize = 256;
141 95 : nBlockYSize = 256;
142 95 : }
143 :
144 : /************************************************************************/
145 : /* IRasterIO() */
146 : /************************************************************************/
147 :
148 26 : CPLErr GDALNullRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
149 : int nXSize, int nYSize, void *pData,
150 : int nBufXSize, int nBufYSize,
151 : GDALDataType eBufType,
152 : GSpacing nPixelSpace, GSpacing nLineSpace,
153 : GDALRasterIOExtraArg *psExtraArg)
154 : {
155 26 : if (eRWFlag == GF_Write)
156 26 : return CE_None;
157 0 : if (psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
158 0 : (nBufXSize != nXSize || nBufYSize != nYSize))
159 : {
160 0 : return GDALRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
161 : pData, nBufXSize, nBufYSize, eBufType,
162 0 : nPixelSpace, nLineSpace, psExtraArg);
163 : }
164 0 : if (nPixelSpace == GDALGetDataTypeSizeBytes(eBufType) &&
165 0 : nLineSpace == nPixelSpace * nBufXSize)
166 : {
167 0 : memset(pData, 0, nLineSpace * nBufYSize);
168 : }
169 : else
170 : {
171 0 : for (int iY = 0; iY < nBufYSize; iY++)
172 : {
173 0 : double dfZero = 0;
174 0 : GDALCopyWords(&dfZero, GDT_Float64, 0,
175 0 : reinterpret_cast<GByte *>(pData) + iY * nLineSpace,
176 : eBufType, static_cast<int>(nPixelSpace), nBufXSize);
177 : }
178 : }
179 0 : return CE_None;
180 : }
181 :
182 : /************************************************************************/
183 : /* IReadBlock() */
184 : /************************************************************************/
185 :
186 0 : CPLErr GDALNullRasterBand::IReadBlock(int, int, void *pData)
187 : {
188 0 : memset(pData, 0,
189 0 : nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eDataType));
190 0 : return CE_None;
191 : }
192 :
193 : /************************************************************************/
194 : /* IWriteBlock() */
195 : /************************************************************************/
196 :
197 0 : CPLErr GDALNullRasterBand::IWriteBlock(int, int, void *)
198 : {
199 0 : return CE_None;
200 : }
201 :
202 : /************************************************************************/
203 : /* GDALNullDataset() */
204 : /************************************************************************/
205 :
206 51 : GDALNullDataset::GDALNullDataset() : m_nLayers(0), m_papoLayers(nullptr)
207 : {
208 51 : eAccess = GA_Update;
209 51 : }
210 :
211 : /************************************************************************/
212 : /* ~GDALNullDataset() */
213 : /************************************************************************/
214 :
215 102 : GDALNullDataset::~GDALNullDataset()
216 : {
217 51 : for (int i = 0; i < m_nLayers; i++)
218 0 : delete m_papoLayers[i];
219 51 : CPLFree(m_papoLayers);
220 102 : }
221 :
222 : /************************************************************************/
223 : /* ICreateLayer() */
224 : /************************************************************************/
225 :
226 0 : OGRLayer *GDALNullDataset::ICreateLayer(const char *pszLayerName,
227 : const OGRGeomFieldDefn *poGeomFieldDefn,
228 : CSLConstList /*papszOptions */)
229 : {
230 0 : const auto eType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
231 : const auto poSRS =
232 0 : poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr;
233 :
234 0 : m_papoLayers = static_cast<OGRLayer **>(
235 0 : CPLRealloc(m_papoLayers, sizeof(OGRLayer *) * (m_nLayers + 1)));
236 0 : m_papoLayers[m_nLayers] = new GDALNullLayer(pszLayerName, poSRS, eType);
237 0 : m_nLayers++;
238 0 : return m_papoLayers[m_nLayers - 1];
239 : }
240 :
241 : /************************************************************************/
242 : /* TestCapability() */
243 : /************************************************************************/
244 :
245 0 : int GDALNullDataset::TestCapability(const char *pszCap)
246 :
247 : {
248 0 : if (EQUAL(pszCap, ODsCCreateLayer))
249 0 : return TRUE;
250 0 : if (EQUAL(pszCap, ODsCRandomLayerWrite))
251 0 : return TRUE;
252 0 : return FALSE;
253 : }
254 :
255 : /************************************************************************/
256 : /* GetLayer() */
257 : /************************************************************************/
258 :
259 0 : OGRLayer *GDALNullDataset::GetLayer(int iLayer)
260 :
261 : {
262 0 : if (iLayer < 0 || iLayer >= m_nLayers)
263 0 : return nullptr;
264 : else
265 0 : return m_papoLayers[iLayer];
266 : }
267 :
268 : /************************************************************************/
269 : /* SetSpatialRef() */
270 : /************************************************************************/
271 :
272 51 : CPLErr GDALNullDataset::SetSpatialRef(const OGRSpatialReference *)
273 :
274 : {
275 51 : return CE_None;
276 : }
277 :
278 : /************************************************************************/
279 : /* SetGeoTransform() */
280 : /************************************************************************/
281 :
282 51 : CPLErr GDALNullDataset::SetGeoTransform(double *)
283 :
284 : {
285 51 : return CE_None;
286 : }
287 :
288 : /************************************************************************/
289 : /* Open() */
290 : /************************************************************************/
291 :
292 37187 : GDALDataset *GDALNullDataset::Open(GDALOpenInfo *poOpenInfo)
293 : {
294 37187 : if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "NULL:"))
295 37182 : return nullptr;
296 :
297 5 : const char *pszStr = poOpenInfo->pszFilename + strlen("NULL:");
298 5 : char **papszTokens = CSLTokenizeString2(pszStr, ",", 0);
299 0 : int nXSize = atoi(CSLFetchNameValueDef(papszTokens, "width", "512"));
300 0 : int nYSize = atoi(CSLFetchNameValueDef(papszTokens, "height", "512"));
301 0 : int nBands = atoi(CSLFetchNameValueDef(papszTokens, "bands", "1"));
302 0 : const char *pszDTName = CSLFetchNameValueDef(papszTokens, "type", "Byte");
303 0 : GDALDataType eDT = GDT_Byte;
304 0 : for (int iType = 1; iType < GDT_TypeCount; iType++)
305 : {
306 0 : if (GDALGetDataTypeName((GDALDataType)iType) != nullptr &&
307 0 : EQUAL(GDALGetDataTypeName((GDALDataType)iType), pszDTName))
308 : {
309 0 : eDT = (GDALDataType)iType;
310 0 : break;
311 : }
312 : }
313 0 : CSLDestroy(papszTokens);
314 :
315 0 : return Create("", nXSize, nYSize, nBands, eDT, nullptr);
316 : }
317 :
318 : /************************************************************************/
319 : /* Create() */
320 : /************************************************************************/
321 :
322 51 : GDALDataset *GDALNullDataset::Create(const char *, int nXSize, int nYSize,
323 : int nBandsIn, GDALDataType eType, char **)
324 : {
325 51 : GDALNullDataset *poDS = new GDALNullDataset();
326 51 : poDS->nRasterXSize = nXSize;
327 51 : poDS->nRasterYSize = nYSize;
328 146 : for (int i = 0; i < nBandsIn; i++)
329 95 : poDS->SetBand(i + 1, new GDALNullRasterBand(eType));
330 51 : return poDS;
331 : }
332 :
333 : /************************************************************************/
334 : /* GDALNullLayer() */
335 : /************************************************************************/
336 :
337 0 : GDALNullLayer::GDALNullLayer(const char *pszLayerName,
338 : const OGRSpatialReference *poSRSIn,
339 0 : OGRwkbGeometryType eType)
340 0 : : poFeatureDefn(new OGRFeatureDefn(pszLayerName))
341 : {
342 0 : SetDescription(poFeatureDefn->GetName());
343 0 : poFeatureDefn->SetGeomType(eType);
344 0 : poFeatureDefn->Reference();
345 :
346 0 : if (poSRSIn)
347 0 : poSRS = poSRSIn->Clone();
348 0 : }
349 :
350 : /************************************************************************/
351 : /* ~GDALNullLayer() */
352 : /************************************************************************/
353 :
354 0 : GDALNullLayer::~GDALNullLayer()
355 : {
356 0 : poFeatureDefn->Release();
357 :
358 0 : if (poSRS)
359 0 : poSRS->Release();
360 0 : }
361 :
362 : /************************************************************************/
363 : /* TestCapability() */
364 : /************************************************************************/
365 :
366 0 : int GDALNullLayer::TestCapability(const char *pszCap)
367 :
368 : {
369 0 : if (EQUAL(pszCap, OLCSequentialWrite))
370 0 : return TRUE;
371 0 : if (EQUAL(pszCap, OLCCreateField))
372 0 : return TRUE;
373 0 : return FALSE;
374 : }
375 :
376 : /************************************************************************/
377 : /* CreateField() */
378 : /************************************************************************/
379 :
380 0 : OGRErr GDALNullLayer::CreateField(const OGRFieldDefn *poField, int)
381 : {
382 0 : poFeatureDefn->AddFieldDefn(poField);
383 0 : return OGRERR_NONE;
384 : }
385 :
386 : /************************************************************************/
387 : /* GDALRegister_NULL() */
388 : /************************************************************************/
389 :
390 1509 : void GDALRegister_NULL()
391 :
392 : {
393 1509 : if (GDALGetDriverByName("NULL") != nullptr)
394 295 : return;
395 :
396 : GDALDriver *poDriver;
397 1214 : poDriver = new GDALDriver();
398 :
399 1214 : poDriver->SetDescription("NULL");
400 1214 : poDriver->SetMetadataItem(GDAL_DMD_CONNECTION_PREFIX, "NULL: ");
401 1214 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
402 1214 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
403 1214 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
404 1214 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
405 1214 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "NULL");
406 :
407 1214 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES,
408 : "Integer Integer64 Real String Date DateTime "
409 : "Binary IntegerList Integer64List "
410 1214 : "RealList StringList");
411 :
412 1214 : poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
413 :
414 1214 : poDriver->pfnOpen = GDALNullDataset::Open;
415 1214 : poDriver->pfnCreate = GDALNullDataset::Create;
416 :
417 1214 : GetGDALDriverManager()->RegisterDriver(poDriver);
418 : }
|