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