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