1 : /******************************************************************************
2 : * $Id: gdaldriver.cpp 25606 2013-02-06 19:22:07Z rouault $
3 : *
4 : * Project: GDAL Core
5 : * Purpose: Implementation of GDALDriver class (and C wrappers)
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1998, 2000, Frank Warmerdam
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 :
32 : CPL_CVSID("$Id: gdaldriver.cpp 25606 2013-02-06 19:22:07Z rouault $");
33 :
34 : CPL_C_START
35 : const char* GDALClientDatasetGetFilename(const char* pszFilename);
36 : CPL_C_END
37 :
38 : /************************************************************************/
39 : /* GDALDriver() */
40 : /************************************************************************/
41 :
42 76429 : GDALDriver::GDALDriver()
43 :
44 : {
45 76429 : pfnOpen = NULL;
46 76429 : pfnCreate = NULL;
47 76429 : pfnDelete = NULL;
48 76429 : pfnCreateCopy = NULL;
49 76429 : pfnUnloadDriver = NULL;
50 76429 : pDriverData = NULL;
51 76429 : pfnIdentify = NULL;
52 76429 : pfnRename = NULL;
53 76429 : pfnCopyFiles = NULL;
54 76429 : }
55 :
56 : /************************************************************************/
57 : /* ~GDALDriver() */
58 : /************************************************************************/
59 :
60 71521 : GDALDriver::~GDALDriver()
61 :
62 : {
63 71521 : if( pfnUnloadDriver != NULL )
64 4400 : pfnUnloadDriver( this );
65 71521 : }
66 :
67 : /************************************************************************/
68 : /* GDALDestroyDriver() */
69 : /************************************************************************/
70 :
71 : /**
72 : * \brief Destroy a GDALDriver.
73 : *
74 : * This is roughly equivelent to deleting the driver, but is guaranteed
75 : * to take place in the GDAL heap. It is important this that function
76 : * not be called on a driver that is registered with the GDALDriverManager.
77 : *
78 : * @param hDriver the driver to destroy.
79 : */
80 :
81 0 : void CPL_STDCALL GDALDestroyDriver( GDALDriverH hDriver )
82 :
83 : {
84 0 : VALIDATE_POINTER0( hDriver, "GDALDestroyDriver" );
85 :
86 0 : delete ((GDALDriver *) hDriver);
87 : }
88 :
89 : /************************************************************************/
90 : /* Create() */
91 : /************************************************************************/
92 :
93 : /**
94 : * \brief Create a new dataset with this driver.
95 : *
96 : * What argument values are legal for particular drivers is driver specific,
97 : * and there is no way to query in advance to establish legal values.
98 : *
99 : * That function will try to validate the creation option list passed to the driver
100 : * with the GDALValidateCreationOptions() method. This check can be disabled
101 : * by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS=NO.
102 : *
103 : * After you have finished working with the returned dataset, it is <b>required</b>
104 : * to close it with GDALClose(). This does not only close the file handle, but
105 : * also ensures that all the data and metadata has been written to the dataset
106 : * (GDALFlushCache() is not sufficient for that purpose).
107 : *
108 : * In some situations, the new dataset can be created in another process through the
109 : * \ref gdal_api_proxy mechanism.
110 : *
111 : * Equivelent of the C function GDALCreate().
112 : *
113 : * @param pszFilename the name of the dataset to create. UTF-8 encoded.
114 : * @param nXSize width of created raster in pixels.
115 : * @param nYSize height of created raster in pixels.
116 : * @param nBands number of bands.
117 : * @param eType type of raster.
118 : * @param papszOptions list of driver specific control parameters.
119 : *
120 : * @return NULL on failure, or a new GDALDataset.
121 : */
122 :
123 8091 : GDALDataset * GDALDriver::Create( const char * pszFilename,
124 : int nXSize, int nYSize, int nBands,
125 : GDALDataType eType, char ** papszOptions )
126 :
127 : {
128 8091 : CPLLocaleC oLocaleForcer;
129 :
130 : /* -------------------------------------------------------------------- */
131 : /* Does this format support creation. */
132 : /* -------------------------------------------------------------------- */
133 8091 : if( pfnCreate == NULL )
134 : {
135 : CPLError( CE_Failure, CPLE_NotSupported,
136 : "GDALDriver::Create() ... no create method implemented"
137 0 : " for this format.\n" );
138 :
139 0 : return NULL;
140 : }
141 : /* -------------------------------------------------------------------- */
142 : /* Do some rudimentary argument checking. */
143 : /* -------------------------------------------------------------------- */
144 8091 : if (nBands < 0)
145 : {
146 : CPLError( CE_Failure, CPLE_AppDefined,
147 : "Attempt to create dataset with %d bands is illegal,"
148 : "Must be >= 0.",
149 1 : nBands );
150 1 : return NULL;
151 : }
152 :
153 8090 : if( nXSize < 1 || nYSize < 1 )
154 : {
155 : CPLError( CE_Failure, CPLE_AppDefined,
156 : "Attempt to create %dx%d dataset is illegal,"
157 : "sizes must be larger than zero.",
158 1 : nXSize, nYSize );
159 1 : return NULL;
160 : }
161 :
162 8089 : const char* pszClientFilename = GDALClientDatasetGetFilename(pszFilename);
163 8092 : if( pszClientFilename != NULL && !EQUAL(GetDescription(), "MEM") &&
164 3 : !EQUAL(GetDescription(), "VRT") )
165 : {
166 3 : GDALDriver* poAPIPROXYDriver = GDALGetAPIPROXYDriver();
167 3 : if( poAPIPROXYDriver != this )
168 : {
169 3 : if( poAPIPROXYDriver == NULL || poAPIPROXYDriver->pfnCreate == NULL )
170 0 : return NULL;
171 3 : char** papszOptionsDup = CSLDuplicate(papszOptions);
172 : papszOptionsDup = CSLAddNameValue(papszOptionsDup, "SERVER_DRIVER",
173 3 : GetDescription());
174 : GDALDataset* poDstDS = poAPIPROXYDriver->pfnCreate(
175 : pszClientFilename, nXSize, nYSize, nBands,
176 3 : eType, papszOptionsDup);
177 :
178 3 : CSLDestroy(papszOptionsDup);
179 :
180 3 : if( poDstDS != NULL )
181 : {
182 6 : if( poDstDS->GetDescription() == NULL
183 3 : || strlen(poDstDS->GetDescription()) == 0 )
184 0 : poDstDS->SetDescription( pszFilename );
185 :
186 3 : if( poDstDS->poDriver == NULL )
187 0 : poDstDS->poDriver = poAPIPROXYDriver;
188 : }
189 :
190 3 : return poDstDS;
191 : }
192 : }
193 :
194 : /* -------------------------------------------------------------------- */
195 : /* Make sure we cleanup if there is an existing dataset of this */
196 : /* name. But even if that seems to fail we will continue since */
197 : /* it might just be a corrupt file or something. */
198 : /* -------------------------------------------------------------------- */
199 8086 : if( !CSLFetchBoolean(papszOptions, "APPEND_SUBDATASET", FALSE) )
200 8086 : QuietDelete( pszFilename );
201 :
202 : /* -------------------------------------------------------------------- */
203 : /* Validate creation options. */
204 : /* -------------------------------------------------------------------- */
205 8086 : if (CSLTestBoolean(CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
206 8086 : GDALValidateCreationOptions( this, papszOptions );
207 :
208 : /* -------------------------------------------------------------------- */
209 : /* Proceed with creation. */
210 : /* -------------------------------------------------------------------- */
211 : GDALDataset *poDS;
212 :
213 : CPLDebug( "GDAL", "GDALDriver::Create(%s,%s,%d,%d,%d,%s,%p)",
214 8086 : GetDescription(), pszFilename, nXSize, nYSize, nBands,
215 : GDALGetDataTypeName( eType ),
216 16172 : papszOptions );
217 :
218 : poDS = pfnCreate( pszFilename, nXSize, nYSize, nBands, eType,
219 8086 : papszOptions );
220 :
221 8086 : if( poDS != NULL )
222 : {
223 14380 : if( poDS->GetDescription() == NULL
224 7190 : || strlen(poDS->GetDescription()) == 0 )
225 6461 : poDS->SetDescription( pszFilename );
226 :
227 7190 : if( poDS->poDriver == NULL )
228 6593 : poDS->poDriver = this;
229 : }
230 :
231 8086 : return poDS;
232 : }
233 :
234 : /************************************************************************/
235 : /* GDALCreate() */
236 : /************************************************************************/
237 :
238 : /**
239 : * \brief Create a new dataset with this driver.
240 : *
241 : * @see GDALDriver::Create()
242 : */
243 :
244 : GDALDatasetH CPL_DLL CPL_STDCALL
245 7438 : GDALCreate( GDALDriverH hDriver, const char * pszFilename,
246 : int nXSize, int nYSize, int nBands, GDALDataType eBandType,
247 : char ** papszOptions )
248 :
249 : {
250 7438 : VALIDATE_POINTER1( hDriver, "GDALCreate", NULL );
251 :
252 : return( ((GDALDriver *) hDriver)->Create( pszFilename,
253 : nXSize, nYSize, nBands,
254 7438 : eBandType, papszOptions ) );
255 : }
256 :
257 : /************************************************************************/
258 : /* DefaultCopyMasks() */
259 : /************************************************************************/
260 :
261 804 : CPLErr GDALDriver::DefaultCopyMasks( GDALDataset *poSrcDS,
262 : GDALDataset *poDstDS,
263 : int bStrict )
264 :
265 : {
266 804 : CPLErr eErr = CE_None;
267 :
268 804 : int nBands = poSrcDS->GetRasterCount();
269 804 : if (nBands == 0)
270 1 : return CE_None;
271 :
272 803 : const char* papszOptions[2] = { "COMPRESSED=YES", NULL };
273 :
274 : /* -------------------------------------------------------------------- */
275 : /* Try to copy mask if it seems appropriate. */
276 : /* -------------------------------------------------------------------- */
277 2075 : for( int iBand = 0;
278 : eErr == CE_None && iBand < nBands;
279 : iBand++ )
280 : {
281 1272 : GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
282 :
283 1272 : int nMaskFlags = poSrcBand->GetMaskFlags();
284 1272 : if( eErr == CE_None
285 : && !(nMaskFlags & (GMF_ALL_VALID|GMF_PER_DATASET|GMF_ALPHA|GMF_NODATA) ) )
286 : {
287 0 : GDALRasterBand *poDstBand = poDstDS->GetRasterBand( iBand+1 );
288 0 : if (poDstBand != NULL)
289 : {
290 0 : eErr = poDstBand->CreateMaskBand( nMaskFlags );
291 0 : if( eErr == CE_None )
292 : {
293 : eErr = GDALRasterBandCopyWholeRaster(
294 0 : poSrcBand->GetMaskBand(),
295 0 : poDstBand->GetMaskBand(),
296 : (char**)papszOptions,
297 0 : GDALDummyProgress, NULL);
298 : }
299 0 : else if( !bStrict )
300 0 : eErr = CE_None;
301 : }
302 : }
303 : }
304 :
305 : /* -------------------------------------------------------------------- */
306 : /* Try to copy a per-dataset mask if we have one. */
307 : /* -------------------------------------------------------------------- */
308 803 : int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
309 803 : if( eErr == CE_None
310 : && !(nMaskFlags & (GMF_ALL_VALID|GMF_ALPHA|GMF_NODATA) )
311 : && (nMaskFlags & GMF_PER_DATASET) )
312 : {
313 1 : eErr = poDstDS->CreateMaskBand( nMaskFlags );
314 1 : if( eErr == CE_None )
315 : {
316 : eErr = GDALRasterBandCopyWholeRaster(
317 1 : poSrcDS->GetRasterBand(1)->GetMaskBand(),
318 1 : poDstDS->GetRasterBand(1)->GetMaskBand(),
319 : (char**)papszOptions,
320 3 : GDALDummyProgress, NULL);
321 : }
322 0 : else if( !bStrict )
323 0 : eErr = CE_None;
324 : }
325 :
326 803 : return eErr;
327 : }
328 :
329 : /************************************************************************/
330 : /* DefaultCreateCopy() */
331 : /************************************************************************/
332 :
333 613 : GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
334 : GDALDataset * poSrcDS,
335 : int bStrict, char ** papszOptions,
336 : GDALProgressFunc pfnProgress,
337 : void * pProgressData )
338 :
339 : {
340 613 : if( pfnProgress == NULL )
341 0 : pfnProgress = GDALDummyProgress;
342 :
343 613 : CPLErrorReset();
344 :
345 613 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
346 : {
347 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
348 0 : return NULL;
349 : }
350 :
351 : /* -------------------------------------------------------------------- */
352 : /* Validate that we can create the output as requested. */
353 : /* -------------------------------------------------------------------- */
354 613 : int nXSize = poSrcDS->GetRasterXSize();
355 613 : int nYSize = poSrcDS->GetRasterYSize();
356 613 : int nBands = poSrcDS->GetRasterCount();
357 :
358 613 : CPLDebug( "GDAL", "Using default GDALDriver::CreateCopy implementation." );
359 :
360 613 : if (nBands == 0)
361 : {
362 : CPLError( CE_Failure, CPLE_NotSupported,
363 22 : "GDALDriver::DefaultCreateCopy does not support zero band" );
364 22 : return NULL;
365 : }
366 :
367 : /* -------------------------------------------------------------------- */
368 : /* Propogate some specific structural metadata as options if it */
369 : /* appears to be supported by the target driver and the caller */
370 : /* didn't provide values. */
371 : /* -------------------------------------------------------------------- */
372 591 : char **papszCreateOptions = CSLDuplicate( papszOptions );
373 : int iOptItem;
374 : static const char *apszOptItems[] = {
375 : "NBITS", "IMAGE_STRUCTURE",
376 : "PIXELTYPE", "IMAGE_STRUCTURE",
377 : NULL };
378 :
379 1773 : for( iOptItem = 0; apszOptItems[iOptItem] != NULL; iOptItem += 2 )
380 : {
381 : // does the source have this metadata item on the first band?
382 : const char *pszValue =
383 : poSrcDS->GetRasterBand(1)->GetMetadataItem(
384 1182 : apszOptItems[iOptItem], apszOptItems[iOptItem+1] );
385 :
386 1182 : if( pszValue == NULL )
387 1180 : continue;
388 :
389 : // do not override provided value.
390 2 : if( CSLFetchNameValue( papszCreateOptions, pszValue ) != NULL )
391 0 : continue;
392 :
393 : // Does this appear to be a supported creation option on this driver?
394 : const char *pszOptionList =
395 2 : GetMetadataItem( GDAL_DMD_CREATIONDATATYPES );
396 :
397 2 : if( pszOptionList == NULL
398 : || strstr(pszOptionList,apszOptItems[iOptItem]) != NULL )
399 0 : continue;
400 :
401 : papszCreateOptions = CSLSetNameValue( papszCreateOptions,
402 : apszOptItems[iOptItem],
403 2 : pszValue );
404 : }
405 :
406 : /* -------------------------------------------------------------------- */
407 : /* Create destination dataset. */
408 : /* -------------------------------------------------------------------- */
409 : GDALDataset *poDstDS;
410 : GDALDataType eType;
411 591 : CPLErr eErr = CE_None;
412 :
413 591 : eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
414 : poDstDS = Create( pszFilename, nXSize, nYSize,
415 591 : nBands, eType, papszCreateOptions );
416 :
417 591 : CSLDestroy(papszCreateOptions);
418 :
419 591 : if( poDstDS == NULL )
420 371 : return NULL;
421 :
422 : /* -------------------------------------------------------------------- */
423 : /* Try setting the projection and geotransform if it seems */
424 : /* suitable. */
425 : /* -------------------------------------------------------------------- */
426 : double adfGeoTransform[6];
427 :
428 654 : if( eErr == CE_None
429 220 : && poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
430 214 : && (adfGeoTransform[0] != 0.0
431 0 : || adfGeoTransform[1] != 1.0
432 0 : || adfGeoTransform[2] != 0.0
433 0 : || adfGeoTransform[3] != 0.0
434 0 : || adfGeoTransform[4] != 0.0
435 0 : || adfGeoTransform[5] != 1.0) )
436 : {
437 214 : eErr = poDstDS->SetGeoTransform( adfGeoTransform );
438 214 : if( !bStrict )
439 42 : eErr = CE_None;
440 : }
441 :
442 660 : if( eErr == CE_None
443 220 : && poSrcDS->GetProjectionRef() != NULL
444 220 : && strlen(poSrcDS->GetProjectionRef()) > 0 )
445 : {
446 210 : eErr = poDstDS->SetProjection( poSrcDS->GetProjectionRef() );
447 210 : if( !bStrict )
448 41 : eErr = CE_None;
449 : }
450 :
451 : /* -------------------------------------------------------------------- */
452 : /* Copy GCPs. */
453 : /* -------------------------------------------------------------------- */
454 220 : if( poSrcDS->GetGCPCount() > 0 && eErr == CE_None )
455 : {
456 1 : eErr = poDstDS->SetGCPs( poSrcDS->GetGCPCount(),
457 1 : poSrcDS->GetGCPs(),
458 3 : poSrcDS->GetGCPProjection() );
459 1 : if( !bStrict )
460 0 : eErr = CE_None;
461 : }
462 :
463 : /* -------------------------------------------------------------------- */
464 : /* Copy metadata. */
465 : /* -------------------------------------------------------------------- */
466 220 : if( poSrcDS->GetMetadata() != NULL )
467 204 : poDstDS->SetMetadata( poSrcDS->GetMetadata() );
468 :
469 : /* -------------------------------------------------------------------- */
470 : /* Copy transportable special domain metadata (RPCs). It would */
471 : /* be nice to copy geolocation, but is is pretty fragile. */
472 : /* -------------------------------------------------------------------- */
473 220 : char **papszMD = poSrcDS->GetMetadata( "RPC" );
474 220 : if( papszMD )
475 1 : poDstDS->SetMetadata( papszMD, "RPC" );
476 :
477 : /* -------------------------------------------------------------------- */
478 : /* Loop copying bands. */
479 : /* -------------------------------------------------------------------- */
480 597 : for( int iBand = 0;
481 : eErr == CE_None && iBand < nBands;
482 : iBand++ )
483 : {
484 377 : GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
485 377 : GDALRasterBand *poDstBand = poDstDS->GetRasterBand( iBand+1 );
486 :
487 : /* -------------------------------------------------------------------- */
488 : /* Do we need to copy a colortable. */
489 : /* -------------------------------------------------------------------- */
490 : GDALColorTable *poCT;
491 : int bSuccess;
492 : double dfValue;
493 :
494 377 : poCT = poSrcBand->GetColorTable();
495 377 : if( poCT != NULL )
496 4 : poDstBand->SetColorTable( poCT );
497 :
498 : /* -------------------------------------------------------------------- */
499 : /* Do we need to copy other metadata? Most of this is */
500 : /* non-critical, so lets not bother folks if it fails are we */
501 : /* are not in strict mode. */
502 : /* -------------------------------------------------------------------- */
503 377 : if( !bStrict )
504 51 : CPLPushErrorHandler( CPLQuietErrorHandler );
505 :
506 377 : if( strlen(poSrcBand->GetDescription()) > 0 )
507 12 : poDstBand->SetDescription( poSrcBand->GetDescription() );
508 :
509 377 : if( CSLCount(poSrcBand->GetMetadata()) > 0 )
510 72 : poDstBand->SetMetadata( poSrcBand->GetMetadata() );
511 :
512 377 : dfValue = poSrcBand->GetOffset( &bSuccess );
513 377 : if( bSuccess && dfValue != 0.0 )
514 0 : poDstBand->SetOffset( dfValue );
515 :
516 377 : dfValue = poSrcBand->GetScale( &bSuccess );
517 377 : if( bSuccess && dfValue != 1.0 )
518 1 : poDstBand->SetScale( dfValue );
519 :
520 377 : dfValue = poSrcBand->GetNoDataValue( &bSuccess );
521 377 : if( bSuccess )
522 10 : poDstBand->SetNoDataValue( dfValue );
523 :
524 967 : if( poSrcBand->GetColorInterpretation() != GCI_Undefined
525 295 : && poSrcBand->GetColorInterpretation()
526 295 : != poDstBand->GetColorInterpretation() )
527 : poDstBand->SetColorInterpretation(
528 220 : poSrcBand->GetColorInterpretation() );
529 :
530 : char** papszCatNames;
531 377 : papszCatNames = poSrcBand->GetCategoryNames();
532 377 : if (0 != papszCatNames)
533 1 : poDstBand->SetCategoryNames( papszCatNames );
534 :
535 377 : if( !bStrict )
536 : {
537 51 : CPLPopErrorHandler();
538 51 : CPLErrorReset();
539 : }
540 : else
541 326 : eErr = CPLGetLastErrorType();
542 : }
543 :
544 : /* -------------------------------------------------------------------- */
545 : /* Copy image data. */
546 : /* -------------------------------------------------------------------- */
547 220 : if( eErr == CE_None )
548 : eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS,
549 : (GDALDatasetH) poDstDS,
550 219 : NULL, pfnProgress, pProgressData );
551 :
552 : /* -------------------------------------------------------------------- */
553 : /* Should we copy some masks over? */
554 : /* -------------------------------------------------------------------- */
555 220 : if( eErr == CE_None )
556 201 : eErr = DefaultCopyMasks( poSrcDS, poDstDS, eErr );
557 :
558 : /* -------------------------------------------------------------------- */
559 : /* Try to cleanup the output dataset if the translation failed. */
560 : /* -------------------------------------------------------------------- */
561 220 : if( eErr != CE_None )
562 : {
563 19 : delete poDstDS;
564 19 : Delete( pszFilename );
565 19 : return NULL;
566 : }
567 : else
568 201 : CPLErrorReset();
569 :
570 201 : return poDstDS;
571 : }
572 :
573 : /************************************************************************/
574 : /* CreateCopy() */
575 : /************************************************************************/
576 :
577 : /**
578 : * \brief Create a copy of a dataset.
579 : *
580 : * This method will attempt to create a copy of a raster dataset with the
581 : * indicated filename, and in this drivers format. Band number, size,
582 : * type, projection, geotransform and so forth are all to be copied from
583 : * the provided template dataset.
584 : *
585 : * Note that many sequential write once formats (such as JPEG and PNG) don't
586 : * implement the Create() method but do implement this CreateCopy() method.
587 : * If the driver doesn't implement CreateCopy(), but does implement Create()
588 : * then the default CreateCopy() mechanism built on calling Create() will
589 : * be used.
590 : *
591 : * It is intended that CreateCopy() will often be used with a source dataset
592 : * which is a virtual dataset allowing configuration of band types, and
593 : * other information without actually duplicating raster data (see the VRT driver).
594 : * This is what is done by the gdal_translate utility for example.
595 : *
596 : * That function will try to validate the creation option list passed to the driver
597 : * with the GDALValidateCreationOptions() method. This check can be disabled
598 : * by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS=NO.
599 : *
600 : * After you have finished working with the returned dataset, it is <b>required</b>
601 : * to close it with GDALClose(). This does not only close the file handle, but
602 : * also ensures that all the data and metadata has been written to the dataset
603 : * (GDALFlushCache() is not sufficient for that purpose).
604 : *
605 : * In some situations, the new dataset can be created in another process through the
606 : * \ref gdal_api_proxy mechanism.
607 : *
608 : * @param pszFilename the name for the new dataset. UTF-8 encoded.
609 : * @param poSrcDS the dataset being duplicated.
610 : * @param bStrict TRUE if the copy must be strictly equivelent, or more
611 : * normally FALSE indicating that the copy may adapt as needed for the
612 : * output format.
613 : * @param papszOptions additional format dependent options controlling
614 : * creation of the output file.
615 : * @param pfnProgress a function to be used to report progress of the copy.
616 : * @param pProgressData application data passed into progress function.
617 : *
618 : * @return a pointer to the newly created dataset (may be read-only access).
619 : */
620 :
621 2270 : GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
622 : GDALDataset * poSrcDS,
623 : int bStrict, char ** papszOptions,
624 : GDALProgressFunc pfnProgress,
625 : void * pProgressData )
626 :
627 : {
628 2270 : CPLLocaleC oLocaleForcer;
629 :
630 2270 : if( pfnProgress == NULL )
631 1755 : pfnProgress = GDALDummyProgress;
632 :
633 2270 : const char* pszClientFilename = GDALClientDatasetGetFilename(pszFilename);
634 2273 : if( pszClientFilename != NULL && !EQUAL(GetDescription(), "MEM") &&
635 3 : !EQUAL(GetDescription(), "VRT") )
636 : {
637 3 : GDALDriver* poAPIPROXYDriver = GDALGetAPIPROXYDriver();
638 3 : if( poAPIPROXYDriver != this )
639 : {
640 3 : if( poAPIPROXYDriver->pfnCreateCopy == NULL )
641 0 : return NULL;
642 3 : char** papszOptionsDup = CSLDuplicate(papszOptions);
643 : papszOptionsDup = CSLAddNameValue(papszOptionsDup, "SERVER_DRIVER",
644 3 : GetDescription());
645 : GDALDataset* poDstDS = poAPIPROXYDriver->pfnCreateCopy(
646 : pszClientFilename, poSrcDS, bStrict, papszOptionsDup,
647 3 : pfnProgress, pProgressData);
648 3 : if( poDstDS != NULL )
649 : {
650 6 : if( poDstDS->GetDescription() == NULL
651 3 : || strlen(poDstDS->GetDescription()) == 0 )
652 0 : poDstDS->SetDescription( pszFilename );
653 :
654 3 : if( poDstDS->poDriver == NULL )
655 0 : poDstDS->poDriver = poAPIPROXYDriver;
656 : }
657 :
658 3 : CSLDestroy(papszOptionsDup);
659 3 : return poDstDS;
660 : }
661 : }
662 :
663 : /* -------------------------------------------------------------------- */
664 : /* Make sure we cleanup if there is an existing dataset of this */
665 : /* name. But even if that seems to fail we will continue since */
666 : /* it might just be a corrupt file or something. */
667 : /* -------------------------------------------------------------------- */
668 2267 : if( !CSLFetchBoolean(papszOptions, "APPEND_SUBDATASET", FALSE) )
669 2267 : QuietDelete( pszFilename );
670 :
671 : /* -------------------------------------------------------------------- */
672 : /* Validate creation options. */
673 : /* -------------------------------------------------------------------- */
674 2267 : if (CSLTestBoolean(CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
675 2267 : GDALValidateCreationOptions( this, papszOptions);
676 :
677 : /* -------------------------------------------------------------------- */
678 : /* If the format provides a CreateCopy() method use that, */
679 : /* otherwise fallback to the internal implementation using the */
680 : /* Create() method. */
681 : /* -------------------------------------------------------------------- */
682 2267 : if( pfnCreateCopy != NULL )
683 : {
684 : GDALDataset *poDstDS;
685 :
686 : poDstDS = pfnCreateCopy( pszFilename, poSrcDS, bStrict, papszOptions,
687 1688 : pfnProgress, pProgressData );
688 1688 : if( poDstDS != NULL )
689 : {
690 1940 : if( poDstDS->GetDescription() == NULL
691 970 : || strlen(poDstDS->GetDescription()) == 0 )
692 21 : poDstDS->SetDescription( pszFilename );
693 :
694 970 : if( poDstDS->poDriver == NULL )
695 350 : poDstDS->poDriver = this;
696 : }
697 :
698 1688 : return poDstDS;
699 : }
700 : else
701 : return DefaultCreateCopy( pszFilename, poSrcDS, bStrict,
702 579 : papszOptions, pfnProgress, pProgressData );
703 : }
704 :
705 : /************************************************************************/
706 : /* GDALCreateCopy() */
707 : /************************************************************************/
708 :
709 : /**
710 : * \brief Create a copy of a dataset.
711 : *
712 : * @see GDALDriver::CreateCopy()
713 : */
714 :
715 2227 : GDALDatasetH CPL_STDCALL GDALCreateCopy( GDALDriverH hDriver,
716 : const char * pszFilename,
717 : GDALDatasetH hSrcDS,
718 : int bStrict, char ** papszOptions,
719 : GDALProgressFunc pfnProgress,
720 : void * pProgressData )
721 :
722 : {
723 2227 : VALIDATE_POINTER1( hDriver, "GDALCreateCopy", NULL );
724 2227 : VALIDATE_POINTER1( hSrcDS, "GDALCreateCopy", NULL );
725 :
726 : return (GDALDatasetH) ((GDALDriver *) hDriver)->
727 : CreateCopy( pszFilename, (GDALDataset *) hSrcDS, bStrict, papszOptions,
728 2227 : pfnProgress, pProgressData );
729 : }
730 :
731 : /************************************************************************/
732 : /* QuietDelete() */
733 : /************************************************************************/
734 :
735 : /**
736 : * \brief Delete dataset if found.
737 : *
738 : * This is a helper method primarily used by Create() and
739 : * CreateCopy() to predelete any dataset of the name soon to be
740 : * created. It will attempt to delete the named dataset if
741 : * one is found, otherwise it does nothing. An error is only
742 : * returned if the dataset is found but the delete fails.
743 : *
744 : * This is a static method and it doesn't matter what driver instance
745 : * it is invoked on. It will attempt to discover the correct driver
746 : * using Identify().
747 : *
748 : * @param pszName the dataset name to try and delete.
749 : * @return CE_None if the dataset does not exist, or is deleted without issues.
750 : */
751 :
752 10357 : CPLErr GDALDriver::QuietDelete( const char *pszName )
753 :
754 : {
755 10357 : GDALDriver *poDriver = (GDALDriver*) GDALIdentifyDriver( pszName, NULL );
756 :
757 10357 : if( poDriver == NULL )
758 10099 : return CE_None;
759 :
760 258 : CPLDebug( "GDAL", "QuietDelete(%s) invoking Delete()", pszName );
761 :
762 258 : return poDriver->Delete( pszName );
763 : }
764 :
765 : /************************************************************************/
766 : /* Delete() */
767 : /************************************************************************/
768 :
769 : /**
770 : * \brief Delete named dataset.
771 : *
772 : * The driver will attempt to delete the named dataset in a driver specific
773 : * fashion. Full featured drivers will delete all associated files,
774 : * database objects, or whatever is appropriate. The default behaviour when
775 : * no driver specific behaviour is provided is to attempt to delete the
776 : * passed name as a single file.
777 : *
778 : * It is unwise to have open dataset handles on this dataset when it is
779 : * deleted.
780 : *
781 : * Equivelent of the C function GDALDeleteDataset().
782 : *
783 : * @param pszFilename name of dataset to delete.
784 : *
785 : * @return CE_None on success, or CE_Failure if the operation fails.
786 : */
787 :
788 1611 : CPLErr GDALDriver::Delete( const char * pszFilename )
789 :
790 : {
791 1611 : if( pfnDelete != NULL )
792 169 : return pfnDelete( pszFilename );
793 :
794 : /* -------------------------------------------------------------------- */
795 : /* Collect file list. */
796 : /* -------------------------------------------------------------------- */
797 1442 : GDALDatasetH hDS = (GDALDataset *) GDALOpen(pszFilename,GA_ReadOnly);
798 :
799 1442 : if( hDS == NULL )
800 : {
801 8 : if( CPLGetLastErrorNo() == 0 )
802 : CPLError( CE_Failure, CPLE_OpenFailed,
803 0 : "Unable to open %s to obtain file list.", pszFilename );
804 :
805 8 : return CE_Failure;
806 : }
807 :
808 1434 : char **papszFileList = GDALGetFileList( hDS );
809 :
810 1434 : GDALClose( hDS );
811 :
812 1434 : if( CSLCount( papszFileList ) == 0 )
813 : {
814 : CPLError( CE_Failure, CPLE_NotSupported,
815 : "Unable to determine files associated with %s,\n"
816 0 : "delete fails.", pszFilename );
817 :
818 0 : return CE_Failure;
819 : }
820 :
821 : /* -------------------------------------------------------------------- */
822 : /* Delete all files. */
823 : /* -------------------------------------------------------------------- */
824 : int i;
825 :
826 3245 : for( i = 0; papszFileList[i] != NULL; i++ )
827 : {
828 1811 : if( VSIUnlink( papszFileList[i] ) != 0 )
829 : {
830 : CPLError( CE_Failure, CPLE_AppDefined,
831 : "Deleting %s failed:\n%s",
832 : papszFileList[i],
833 0 : VSIStrerror(errno) );
834 0 : CSLDestroy( papszFileList );
835 0 : return CE_Failure;
836 : }
837 : }
838 :
839 1434 : CSLDestroy( papszFileList );
840 :
841 1434 : return CE_None;
842 : }
843 :
844 : /************************************************************************/
845 : /* GDALDeleteDataset() */
846 : /************************************************************************/
847 :
848 : /**
849 : * \brief Delete named dataset.
850 : *
851 : * @see GDALDriver::Delete()
852 : */
853 :
854 1328 : CPLErr CPL_STDCALL GDALDeleteDataset( GDALDriverH hDriver, const char * pszFilename )
855 :
856 : {
857 1328 : if( hDriver == NULL )
858 0 : hDriver = GDALIdentifyDriver( pszFilename, NULL );
859 :
860 1328 : if( hDriver == NULL )
861 : {
862 : CPLError( CE_Failure, CPLE_AppDefined,
863 : "No identifiable driver for %s.",
864 0 : pszFilename );
865 0 : return CE_Failure;
866 : }
867 :
868 1328 : return ((GDALDriver *) hDriver)->Delete( pszFilename );
869 : }
870 :
871 : /************************************************************************/
872 : /* DefaultRename() */
873 : /* */
874 : /* The generic implementation based on the file list used when */
875 : /* there is no format specific implementation. */
876 : /************************************************************************/
877 :
878 1 : CPLErr GDALDriver::DefaultRename( const char * pszNewName,
879 : const char *pszOldName )
880 :
881 : {
882 : /* -------------------------------------------------------------------- */
883 : /* Collect file list. */
884 : /* -------------------------------------------------------------------- */
885 1 : GDALDatasetH hDS = (GDALDataset *) GDALOpen(pszOldName,GA_ReadOnly);
886 :
887 1 : if( hDS == NULL )
888 : {
889 0 : if( CPLGetLastErrorNo() == 0 )
890 : CPLError( CE_Failure, CPLE_OpenFailed,
891 0 : "Unable to open %s to obtain file list.", pszOldName );
892 :
893 0 : return CE_Failure;
894 : }
895 :
896 1 : char **papszFileList = GDALGetFileList( hDS );
897 :
898 1 : GDALClose( hDS );
899 :
900 1 : if( CSLCount( papszFileList ) == 0 )
901 : {
902 : CPLError( CE_Failure, CPLE_NotSupported,
903 : "Unable to determine files associated with %s,\n"
904 0 : "rename fails.", pszOldName );
905 :
906 0 : return CE_Failure;
907 : }
908 :
909 : /* -------------------------------------------------------------------- */
910 : /* Produce a list of new filenames that correspond to the old */
911 : /* names. */
912 : /* -------------------------------------------------------------------- */
913 1 : CPLErr eErr = CE_None;
914 : int i;
915 : char **papszNewFileList =
916 1 : CPLCorrespondingPaths( pszOldName, pszNewName, papszFileList );
917 :
918 1 : if( papszNewFileList == NULL )
919 0 : return CE_Failure;
920 :
921 5 : for( i = 0; papszFileList[i] != NULL; i++ )
922 : {
923 4 : if( CPLMoveFile( papszNewFileList[i], papszFileList[i] ) != 0 )
924 : {
925 0 : eErr = CE_Failure;
926 : // Try to put the ones we moved back.
927 0 : for( --i; i >= 0; i-- )
928 0 : CPLMoveFile( papszFileList[i], papszNewFileList[i] );
929 0 : break;
930 : }
931 : }
932 :
933 1 : CSLDestroy( papszNewFileList );
934 1 : CSLDestroy( papszFileList );
935 :
936 1 : return eErr;
937 : }
938 :
939 : /************************************************************************/
940 : /* Rename() */
941 : /************************************************************************/
942 :
943 : /**
944 : * \brief Rename a dataset.
945 : *
946 : * Rename a dataset. This may including moving the dataset to a new directory
947 : * or even a new filesystem.
948 : *
949 : * It is unwise to have open dataset handles on this dataset when it is
950 : * being renamed.
951 : *
952 : * Equivelent of the C function GDALRenameDataset().
953 : *
954 : * @param pszNewName new name for the dataset.
955 : * @param pszOldName old name for the dataset.
956 : *
957 : * @return CE_None on success, or CE_Failure if the operation fails.
958 : */
959 :
960 1 : CPLErr GDALDriver::Rename( const char * pszNewName, const char *pszOldName )
961 :
962 : {
963 1 : if( pfnRename != NULL )
964 1 : return pfnRename( pszNewName, pszOldName );
965 : else
966 0 : return DefaultRename( pszNewName, pszOldName );
967 : }
968 :
969 : /************************************************************************/
970 : /* GDALRenameDataset() */
971 : /************************************************************************/
972 :
973 : /**
974 : * \brief Rename a dataset.
975 : *
976 : * @see GDALDriver::Rename()
977 : */
978 :
979 1 : CPLErr CPL_STDCALL GDALRenameDataset( GDALDriverH hDriver,
980 : const char * pszNewName,
981 : const char * pszOldName )
982 :
983 : {
984 1 : if( hDriver == NULL )
985 0 : hDriver = GDALIdentifyDriver( pszOldName, NULL );
986 :
987 1 : if( hDriver == NULL )
988 : {
989 : CPLError( CE_Failure, CPLE_AppDefined,
990 : "No identifiable driver for %s.",
991 0 : pszOldName );
992 0 : return CE_Failure;
993 : }
994 :
995 1 : return ((GDALDriver *) hDriver)->Rename( pszNewName, pszOldName );
996 : }
997 :
998 : /************************************************************************/
999 : /* DefaultCopyFiles() */
1000 : /* */
1001 : /* The default implementation based on file lists used when */
1002 : /* there is no format specific implementation. */
1003 : /************************************************************************/
1004 :
1005 1 : CPLErr GDALDriver::DefaultCopyFiles( const char * pszNewName,
1006 : const char *pszOldName )
1007 :
1008 : {
1009 : /* -------------------------------------------------------------------- */
1010 : /* Collect file list. */
1011 : /* -------------------------------------------------------------------- */
1012 1 : GDALDatasetH hDS = (GDALDataset *) GDALOpen(pszOldName,GA_ReadOnly);
1013 :
1014 1 : if( hDS == NULL )
1015 : {
1016 0 : if( CPLGetLastErrorNo() == 0 )
1017 : CPLError( CE_Failure, CPLE_OpenFailed,
1018 0 : "Unable to open %s to obtain file list.", pszOldName );
1019 :
1020 0 : return CE_Failure;
1021 : }
1022 :
1023 1 : char **papszFileList = GDALGetFileList( hDS );
1024 :
1025 1 : GDALClose( hDS );
1026 :
1027 1 : if( CSLCount( papszFileList ) == 0 )
1028 : {
1029 : CPLError( CE_Failure, CPLE_NotSupported,
1030 : "Unable to determine files associated with %s,\n"
1031 0 : "rename fails.", pszOldName );
1032 :
1033 0 : return CE_Failure;
1034 : }
1035 :
1036 : /* -------------------------------------------------------------------- */
1037 : /* Produce a list of new filenames that correspond to the old */
1038 : /* names. */
1039 : /* -------------------------------------------------------------------- */
1040 1 : CPLErr eErr = CE_None;
1041 : int i;
1042 : char **papszNewFileList =
1043 1 : CPLCorrespondingPaths( pszOldName, pszNewName, papszFileList );
1044 :
1045 1 : if( papszNewFileList == NULL )
1046 0 : return CE_Failure;
1047 :
1048 5 : for( i = 0; papszFileList[i] != NULL; i++ )
1049 : {
1050 4 : if( CPLCopyFile( papszNewFileList[i], papszFileList[i] ) != 0 )
1051 : {
1052 0 : eErr = CE_Failure;
1053 : // Try to put the ones we moved back.
1054 0 : for( --i; i >= 0; i-- )
1055 0 : VSIUnlink( papszNewFileList[i] );
1056 0 : break;
1057 : }
1058 : }
1059 :
1060 1 : CSLDestroy( papszNewFileList );
1061 1 : CSLDestroy( papszFileList );
1062 :
1063 1 : return eErr;
1064 : }
1065 :
1066 : /************************************************************************/
1067 : /* CopyFiles() */
1068 : /************************************************************************/
1069 :
1070 : /**
1071 : * \brief Copy the files of a dataset.
1072 : *
1073 : * Copy all the files associated with a dataset.
1074 : *
1075 : * Equivelent of the C function GDALCopyDatasetFiles().
1076 : *
1077 : * @param pszNewName new name for the dataset.
1078 : * @param pszOldName old name for the dataset.
1079 : *
1080 : * @return CE_None on success, or CE_Failure if the operation fails.
1081 : */
1082 :
1083 1 : CPLErr GDALDriver::CopyFiles( const char * pszNewName, const char *pszOldName )
1084 :
1085 : {
1086 1 : if( pfnCopyFiles != NULL )
1087 1 : return pfnCopyFiles( pszNewName, pszOldName );
1088 : else
1089 0 : return DefaultCopyFiles( pszNewName, pszOldName );
1090 : }
1091 :
1092 : /************************************************************************/
1093 : /* GDALCopyDatasetFiles() */
1094 : /************************************************************************/
1095 :
1096 : /**
1097 : * \brief Copy the files of a dataset.
1098 : *
1099 : * @see GDALDriver::CopyFiles()
1100 : */
1101 :
1102 1 : CPLErr CPL_STDCALL GDALCopyDatasetFiles( GDALDriverH hDriver,
1103 : const char * pszNewName,
1104 : const char * pszOldName )
1105 :
1106 : {
1107 1 : if( hDriver == NULL )
1108 0 : hDriver = GDALIdentifyDriver( pszOldName, NULL );
1109 :
1110 1 : if( hDriver == NULL )
1111 : {
1112 : CPLError( CE_Failure, CPLE_AppDefined,
1113 : "No identifiable driver for %s.",
1114 0 : pszOldName );
1115 0 : return CE_Failure;
1116 : }
1117 :
1118 1 : return ((GDALDriver *) hDriver)->CopyFiles( pszNewName, pszOldName );
1119 : }
1120 :
1121 : /************************************************************************/
1122 : /* GDALGetDriverShortName() */
1123 : /************************************************************************/
1124 :
1125 : /**
1126 : * \brief Return the short name of a driver
1127 : *
1128 : * This is the string that can be
1129 : * passed to the GDALGetDriverByName() function.
1130 : *
1131 : * For the GeoTIFF driver, this is "GTiff"
1132 : *
1133 : * @param hDriver the handle of the driver
1134 : * @return the short name of the driver. The
1135 : * returned string should not be freed and is owned by the driver.
1136 : */
1137 :
1138 26505 : const char * CPL_STDCALL GDALGetDriverShortName( GDALDriverH hDriver )
1139 :
1140 : {
1141 26505 : VALIDATE_POINTER1( hDriver, "GDALGetDriverShortName", NULL );
1142 :
1143 26505 : return ((GDALDriver *) hDriver)->GetDescription();
1144 : }
1145 :
1146 : /************************************************************************/
1147 : /* GDALGetDriverLongName() */
1148 : /************************************************************************/
1149 :
1150 : /**
1151 : * \brief Return the long name of a driver
1152 : *
1153 : * For the GeoTIFF driver, this is "GeoTIFF"
1154 : *
1155 : * @param hDriver the handle of the driver
1156 : * @return the long name of the driver or empty string. The
1157 : * returned string should not be freed and is owned by the driver.
1158 : */
1159 :
1160 169 : const char * CPL_STDCALL GDALGetDriverLongName( GDALDriverH hDriver )
1161 :
1162 : {
1163 169 : VALIDATE_POINTER1( hDriver, "GDALGetDriverLongName", NULL );
1164 :
1165 : const char *pszLongName =
1166 169 : ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_LONGNAME );
1167 :
1168 169 : if( pszLongName == NULL )
1169 0 : return "";
1170 : else
1171 169 : return pszLongName;
1172 : }
1173 :
1174 : /************************************************************************/
1175 : /* GDALGetDriverHelpTopic() */
1176 : /************************************************************************/
1177 :
1178 : /**
1179 : * \brief Return the URL to the help that describes the driver
1180 : *
1181 : * That URL is relative to the GDAL documentation directory.
1182 : *
1183 : * For the GeoTIFF driver, this is "frmt_gtiff.html"
1184 : *
1185 : * @param hDriver the handle of the driver
1186 : * @return the URL to the help that describes the driver or NULL. The
1187 : * returned string should not be freed and is owned by the driver.
1188 : */
1189 :
1190 0 : const char * CPL_STDCALL GDALGetDriverHelpTopic( GDALDriverH hDriver )
1191 :
1192 : {
1193 0 : VALIDATE_POINTER1( hDriver, "GDALGetDriverHelpTopic", NULL );
1194 :
1195 0 : return ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_HELPTOPIC );
1196 : }
1197 :
1198 : /************************************************************************/
1199 : /* GDALGetDriverCreationOptionList() */
1200 : /************************************************************************/
1201 :
1202 : /**
1203 : * \brief Return the list of creation options of the driver
1204 : *
1205 : * Return the list of creation options of the driver used by Create() and
1206 : * CreateCopy() as an XML string
1207 : *
1208 : * @param hDriver the handle of the driver
1209 : * @return an XML string that describes the list of creation options or
1210 : * empty string. The returned string should not be freed and is
1211 : * owned by the driver.
1212 : */
1213 :
1214 0 : const char * CPL_STDCALL GDALGetDriverCreationOptionList( GDALDriverH hDriver )
1215 :
1216 : {
1217 0 : VALIDATE_POINTER1( hDriver, "GDALGetDriverCreationOptionList", NULL );
1218 :
1219 : const char *pszOptionList =
1220 0 : ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST );
1221 :
1222 0 : if( pszOptionList == NULL )
1223 0 : return "";
1224 : else
1225 0 : return pszOptionList;
1226 : }
1227 :
1228 : /************************************************************************/
1229 : /* GDALValidateCreationOptions() */
1230 : /************************************************************************/
1231 :
1232 : /**
1233 : * \brief Validate the list of creation options that are handled by a driver
1234 : *
1235 : * This is a helper method primarily used by Create() and
1236 : * CreateCopy() to validate that the passed in list of creation options
1237 : * is compatible with the GDAL_DMD_CREATIONOPTIONLIST metadata item defined
1238 : * by some drivers. @see GDALGetDriverCreationOptionList()
1239 : *
1240 : * If the GDAL_DMD_CREATIONOPTIONLIST metadata item is not defined, this
1241 : * function will return TRUE. Otherwise it will check that the keys and values
1242 : * in the list of creation options are compatible with the capabilities declared
1243 : * by the GDAL_DMD_CREATIONOPTIONLIST metadata item. In case of incompatibility
1244 : * a (non fatal) warning will be emited and FALSE will be returned.
1245 : *
1246 : * @param hDriver the handle of the driver with whom the lists of creation option
1247 : * must be validated
1248 : * @param papszCreationOptions the list of creation options. An array of strings,
1249 : * whose last element is a NULL pointer
1250 : * @return TRUE if the list of creation options is compatible with the Create()
1251 : * and CreateCopy() method of the driver, FALSE otherwise.
1252 : */
1253 :
1254 10355 : int CPL_STDCALL GDALValidateCreationOptions( GDALDriverH hDriver,
1255 : char** papszCreationOptions)
1256 : {
1257 10355 : int bRet = TRUE;
1258 10355 : VALIDATE_POINTER1( hDriver, "GDALValidateCreationOptions", FALSE );
1259 :
1260 : const char *pszOptionList =
1261 10355 : ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST );
1262 :
1263 10355 : if( papszCreationOptions == NULL || *papszCreationOptions == NULL)
1264 9844 : return TRUE;
1265 511 : if( pszOptionList == NULL )
1266 23 : return TRUE;
1267 :
1268 488 : CPLXMLNode* psNode = CPLParseXMLString(pszOptionList);
1269 488 : if (psNode == NULL)
1270 : {
1271 : CPLError(CE_Warning, CPLE_AppDefined,
1272 : "Could not parse creation option list of driver %s. Assuming creation options are valid.",
1273 0 : ((GDALDriver *) hDriver)->GetDescription());
1274 0 : return TRUE;
1275 : }
1276 :
1277 1753 : while(*papszCreationOptions)
1278 : {
1279 777 : char* pszKey = NULL;
1280 777 : const char* pszValue = CPLParseNameValue(*papszCreationOptions, &pszKey);
1281 777 : if (pszKey == NULL)
1282 : {
1283 : CPLError(CE_Warning, CPLE_NotSupported,
1284 : "Creation option '%s' is not formatted with the key=value format",
1285 0 : *papszCreationOptions);
1286 0 : bRet = FALSE;
1287 :
1288 0 : papszCreationOptions ++;
1289 0 : continue;
1290 : }
1291 :
1292 777 : CPLXMLNode* psChildNode = psNode->psChild;
1293 8348 : while(psChildNode)
1294 : {
1295 7566 : if (EQUAL(psChildNode->pszValue, "OPTION"))
1296 : {
1297 7566 : const char* pszOptionName = CPLGetXMLValue(psChildNode, "name", "");
1298 : /* For option names terminated by wildcard (NITF BLOCKA option names for example) */
1299 15132 : if (strlen(pszOptionName) > 0 &&
1300 7566 : pszOptionName[strlen(pszOptionName) - 1] == '*' &&
1301 : EQUALN(pszOptionName, pszKey, strlen(pszOptionName) - 1))
1302 : {
1303 7 : break;
1304 : }
1305 :
1306 7559 : if (EQUAL(pszOptionName, pszKey) ||
1307 : EQUAL(CPLGetXMLValue(psChildNode, "alias", ""), pszKey))
1308 : {
1309 765 : break;
1310 : }
1311 : }
1312 6794 : psChildNode = psChildNode->psNext;
1313 : }
1314 777 : if (psChildNode == NULL)
1315 : {
1316 : CPLError(CE_Warning, CPLE_NotSupported,
1317 : "Driver %s does not support %s creation option",
1318 5 : ((GDALDriver *) hDriver)->GetDescription(),
1319 10 : pszKey);
1320 5 : CPLFree(pszKey);
1321 5 : bRet = FALSE;
1322 :
1323 5 : papszCreationOptions ++;
1324 5 : continue;
1325 : }
1326 772 : const char* pszType = CPLGetXMLValue(psChildNode, "type", NULL);
1327 772 : if (pszType != NULL)
1328 : {
1329 1046 : if (EQUAL(pszType, "INT") || EQUAL(pszType, "INTEGER"))
1330 : {
1331 274 : const char* pszValueIter = pszValue;
1332 971 : while (*pszValueIter)
1333 : {
1334 423 : if (!((*pszValueIter >= '0' && *pszValueIter <= '9') ||
1335 : *pszValueIter == '+' || *pszValueIter == '-'))
1336 : {
1337 : CPLError(CE_Warning, CPLE_NotSupported,
1338 : "'%s' is an unexpected value for %s creation option of type int.",
1339 0 : pszValue, pszKey);
1340 0 : bRet = FALSE;
1341 0 : break;
1342 : }
1343 423 : pszValueIter++;
1344 : }
1345 : }
1346 498 : else if (EQUAL(pszType, "UNSIGNED INT"))
1347 : {
1348 0 : const char* pszValueIter = pszValue;
1349 0 : while (*pszValueIter)
1350 : {
1351 0 : if (!((*pszValueIter >= '0' && *pszValueIter <= '9') ||
1352 : *pszValueIter == '+'))
1353 : {
1354 : CPLError(CE_Warning, CPLE_NotSupported,
1355 : "'%s' is an unexpected value for %s creation option of type unsigned int.",
1356 0 : pszValue, pszKey);
1357 0 : bRet = FALSE;
1358 0 : break;
1359 : }
1360 0 : pszValueIter++;
1361 : }
1362 : }
1363 498 : else if (EQUAL(pszType, "FLOAT"))
1364 : {
1365 23 : char* endPtr = NULL;
1366 23 : CPLStrtod(pszValue, &endPtr);
1367 23 : if ( !(endPtr == NULL || *endPtr == '\0') )
1368 : {
1369 : CPLError(CE_Warning, CPLE_NotSupported,
1370 : "'%s' is an unexpected value for %s creation option of type float.",
1371 0 : pszValue, pszKey);
1372 0 : bRet = FALSE;
1373 : }
1374 : }
1375 475 : else if (EQUAL(pszType, "BOOLEAN"))
1376 : {
1377 120 : if (!(EQUAL(pszValue, "ON") || EQUAL(pszValue, "TRUE") || EQUAL(pszValue, "YES") ||
1378 : EQUAL(pszValue, "OFF") || EQUAL(pszValue, "FALSE") || EQUAL(pszValue, "NO")))
1379 : {
1380 : CPLError(CE_Warning, CPLE_NotSupported,
1381 : "'%s' is an unexpected value for %s creation option of type boolean.",
1382 0 : pszValue, pszKey);
1383 0 : bRet = FALSE;
1384 : }
1385 : }
1386 355 : else if (EQUAL(pszType, "STRING-SELECT"))
1387 : {
1388 253 : int bMatchFound = FALSE;
1389 253 : CPLXMLNode* psStringSelect = psChildNode->psChild;
1390 1813 : while(psStringSelect)
1391 : {
1392 1559 : if (psStringSelect->eType == CXT_Element &&
1393 : EQUAL(psStringSelect->pszValue, "Value"))
1394 : {
1395 866 : CPLXMLNode* psOptionNode = psStringSelect->psChild;
1396 2347 : while(psOptionNode)
1397 : {
1398 867 : if (psOptionNode->eType == CXT_Text &&
1399 : EQUAL(psOptionNode->pszValue, pszValue))
1400 : {
1401 252 : bMatchFound = TRUE;
1402 252 : break;
1403 : }
1404 615 : psOptionNode = psOptionNode->psNext;
1405 : }
1406 866 : if (bMatchFound)
1407 252 : break;
1408 : }
1409 1307 : psStringSelect = psStringSelect->psNext;
1410 : }
1411 253 : if (!bMatchFound)
1412 : {
1413 : CPLError(CE_Warning, CPLE_NotSupported,
1414 : "'%s' is an unexpected value for %s creation option of type string-select.",
1415 1 : pszValue, pszKey);
1416 1 : bRet = FALSE;
1417 : }
1418 : }
1419 102 : else if (EQUAL(pszType, "STRING"))
1420 : {
1421 102 : const char* pszMaxSize = CPLGetXMLValue(psChildNode, "maxsize", NULL);
1422 102 : if (pszMaxSize != NULL)
1423 : {
1424 8 : if ((int)strlen(pszValue) > atoi(pszMaxSize))
1425 : {
1426 : CPLError(CE_Warning, CPLE_NotSupported,
1427 : "'%s' is of size %d, whereas maximum size for %s creation option is %d.",
1428 1 : pszValue, (int)strlen(pszValue), pszKey, atoi(pszMaxSize));
1429 1 : bRet = FALSE;
1430 : }
1431 : }
1432 : }
1433 : else
1434 : {
1435 : /* Driver error */
1436 : CPLError(CE_Warning, CPLE_NotSupported,
1437 : "Driver %s : type '%s' for %s creation option is not recognized.",
1438 0 : ((GDALDriver *) hDriver)->GetDescription(),
1439 : pszType,
1440 0 : pszKey);
1441 : }
1442 : }
1443 : else
1444 : {
1445 : /* Driver error */
1446 : CPLError(CE_Warning, CPLE_NotSupported,
1447 : "Driver %s : no type for %s creation option.",
1448 0 : ((GDALDriver *) hDriver)->GetDescription(),
1449 0 : pszKey);
1450 : }
1451 772 : CPLFree(pszKey);
1452 772 : papszCreationOptions++;
1453 : }
1454 :
1455 488 : CPLDestroyXMLNode(psNode);
1456 488 : return bRet;
1457 : }
1458 :
1459 : /************************************************************************/
1460 : /* GDALIdentifyDriver() */
1461 : /************************************************************************/
1462 :
1463 : /**
1464 : * \brief Identify the driver that can open a raster file.
1465 : *
1466 : * This function will try to identify the driver that can open the passed file
1467 : * name by invoking the Identify method of each registered GDALDriver in turn.
1468 : * The first driver that successful identifies the file name will be returned.
1469 : * If all drivers fail then NULL is returned.
1470 : *
1471 : * In order to reduce the need for such searches touch the operating system
1472 : * file system machinery, it is possible to give an optional list of files.
1473 : * This is the list of all files at the same level in the file system as the
1474 : * target file, including the target file. The filenames will not include any
1475 : * path components, are an essentially just the output of CPLReadDir() on the
1476 : * parent directory. If the target object does not have filesystem semantics
1477 : * then the file list should be NULL.
1478 : *
1479 : * @param pszFilename the name of the file to access. In the case of
1480 : * exotic drivers this may not refer to a physical file, but instead contain
1481 : * information for the driver on how to access a dataset.
1482 : *
1483 : * @param papszFileList an array of strings, whose last element is the NULL pointer.
1484 : * These strings are filenames that are auxiliary to the main filename. The passed
1485 : * value may be NULL.
1486 : *
1487 : * @return A GDALDriverH handle or NULL on failure. For C++ applications
1488 : * this handle can be cast to a GDALDriver *.
1489 : */
1490 :
1491 :
1492 : GDALDriverH CPL_STDCALL
1493 10388 : GDALIdentifyDriver( const char * pszFilename,
1494 : char **papszFileList )
1495 :
1496 : {
1497 : int iDriver;
1498 10388 : GDALDriverManager *poDM = GetGDALDriverManager();
1499 10388 : GDALOpenInfo oOpenInfo( pszFilename, GA_ReadOnly, papszFileList );
1500 10388 : CPLLocaleC oLocaleForcer;
1501 :
1502 10388 : CPLErrorReset();
1503 10388 : CPLAssert( NULL != poDM );
1504 :
1505 1339566 : for( iDriver = -1; iDriver < poDM->GetDriverCount(); iDriver++ )
1506 : {
1507 : GDALDriver *poDriver;
1508 : GDALDataset *poDS;
1509 :
1510 1329464 : if( iDriver < 0 )
1511 10388 : poDriver = GDALGetAPIPROXYDriver();
1512 : else
1513 1319076 : poDriver = poDM->GetDriver( iDriver );
1514 :
1515 1329464 : VALIDATE_POINTER1( poDriver, "GDALIdentifyDriver", NULL );
1516 :
1517 1329464 : if( poDriver->pfnIdentify != NULL )
1518 : {
1519 802159 : if( poDriver->pfnIdentify( &oOpenInfo ) )
1520 268 : return (GDALDriverH) poDriver;
1521 : }
1522 527305 : else if( poDriver->pfnOpen != NULL )
1523 : {
1524 517050 : poDS = poDriver->pfnOpen( &oOpenInfo );
1525 517050 : if( poDS != NULL )
1526 : {
1527 18 : delete poDS;
1528 18 : return (GDALDriverH) poDriver;
1529 : }
1530 :
1531 517032 : if( CPLGetLastErrorNo() != 0 )
1532 0 : return NULL;
1533 : }
1534 : }
1535 :
1536 10102 : return NULL;
1537 : }
|