1 : /******************************************************************************
2 : * $Id: gdaldataset.cpp 25340 2012-12-21 20:30:21Z rouault $
3 : *
4 : * Project: GDAL Core
5 : * Purpose: Base class for raster file formats.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1998, 2003, 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 : #include "cpl_string.h"
32 : #include "cpl_hash_set.h"
33 : #include "cpl_multiproc.h"
34 : #include <map>
35 :
36 : CPL_CVSID("$Id: gdaldataset.cpp 25340 2012-12-21 20:30:21Z rouault $");
37 :
38 : CPL_C_START
39 : GDALAsyncReader *
40 : GDALGetDefaultAsyncReader( GDALDataset *poDS,
41 : int nXOff, int nYOff,
42 : int nXSize, int nYSize,
43 : void *pBuf,
44 : int nBufXSize, int nBufYSize,
45 : GDALDataType eBufType,
46 : int nBandCount, int* panBandMap,
47 : int nPixelSpace, int nLineSpace,
48 : int nBandSpace, char **papszOptions);
49 : CPL_C_END
50 :
51 : typedef struct
52 : {
53 : /* PID of the thread that mark the dataset as shared */
54 : /* This may not be the actual PID, but the responsiblePID */
55 : GIntBig nPID;
56 : char *pszDescription;
57 : GDALAccess eAccess;
58 :
59 : GDALDataset *poDS;
60 : } SharedDatasetCtxt;
61 :
62 : typedef struct
63 : {
64 : GDALDataset *poDS;
65 : /* In the case of a shared dataset, memorize the PID of the thread */
66 : /* that marked the dataset as shared, so that we can remove it from */
67 : /* the phSharedDatasetSet in the destructor of the dataset, even */
68 : /* if GDALClose is called from a different thread */
69 : /* Ideally, this should be stored in the GDALDataset object itself */
70 : /* but this is inconvenient to change the object size at that time */
71 : GIntBig nPIDCreatorForShared;
72 : } DatasetCtxt;
73 :
74 : /* Set of datasets opened as shared datasets (with GDALOpenShared) */
75 : /* The values in the set are of type SharedDatasetCtxt */
76 : static CPLHashSet* phSharedDatasetSet = NULL;
77 :
78 : /* Set of all datasets created in the constructor of GDALDataset */
79 : /* The values in the set are of type DatasetCtxt */
80 : static CPLHashSet* phAllDatasetSet = NULL;
81 : static void *hDLMutex = NULL;
82 :
83 : /* Static array of all datasets. Used by GDALGetOpenDatasets */
84 : /* Not thread-safe. See GDALGetOpenDatasets */
85 : static GDALDataset** ppDatasets = NULL;
86 :
87 6797 : static unsigned long GDALSharedDatasetHashFunc(const void* elt)
88 : {
89 6797 : SharedDatasetCtxt* psStruct = (SharedDatasetCtxt*) elt;
90 6797 : return (unsigned long) (CPLHashSetHashStr(psStruct->pszDescription) ^ psStruct->eAccess ^ psStruct->nPID);
91 : }
92 :
93 5643 : static int GDALSharedDatasetEqualFunc(const void* elt1, const void* elt2)
94 : {
95 5643 : SharedDatasetCtxt* psStruct1 = (SharedDatasetCtxt*) elt1;
96 5643 : SharedDatasetCtxt* psStruct2 = (SharedDatasetCtxt*) elt2;
97 : return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
98 : psStruct1->nPID == psStruct2->nPID &&
99 5643 : psStruct1->eAccess == psStruct2->eAccess;
100 : }
101 :
102 293 : static void GDALSharedDatasetFreeFunc(void* elt)
103 : {
104 293 : SharedDatasetCtxt* psStruct = (SharedDatasetCtxt*) elt;
105 293 : CPLFree(psStruct->pszDescription);
106 293 : CPLFree(psStruct);
107 293 : }
108 :
109 86358 : static unsigned long GDALDatasetHashFunc(const void* elt)
110 : {
111 86358 : DatasetCtxt* psStruct = (DatasetCtxt*) elt;
112 86358 : return (unsigned long)(GUIntBig) psStruct->poDS;
113 : }
114 :
115 37986 : static int GDALDatasetEqualFunc(const void* elt1, const void* elt2)
116 : {
117 37986 : DatasetCtxt* psStruct1 = (DatasetCtxt*) elt1;
118 37986 : DatasetCtxt* psStruct2 = (DatasetCtxt*) elt2;
119 37986 : return psStruct1->poDS == psStruct2->poDS ;
120 : }
121 :
122 16633 : static void GDALDatasetFreeFunc(void* elt)
123 : {
124 16633 : DatasetCtxt* psStruct = (DatasetCtxt*) elt;
125 16633 : CPLFree(psStruct);
126 16633 : }
127 :
128 : /************************************************************************/
129 : /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
130 : /************************************************************************/
131 :
132 : void** GDALGetphDLMutex();
133 : void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID);
134 : GIntBig GDALGetResponsiblePIDForCurrentThread();
135 :
136 : /* The open-shared mutex must be used by the ProxyPool too */
137 30766 : void** GDALGetphDLMutex()
138 : {
139 30766 : return &hDLMutex;
140 : }
141 :
142 : /* The current thread will act in the behalf of the thread of PID responsiblePID */
143 29317 : void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
144 : {
145 29317 : GIntBig* pResponsiblePID = (GIntBig*) CPLGetTLS(CTLS_RESPONSIBLEPID);
146 29317 : if (pResponsiblePID == NULL)
147 : {
148 93 : pResponsiblePID = (GIntBig*) CPLMalloc(sizeof(GIntBig));
149 93 : CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
150 : }
151 29317 : *pResponsiblePID = responsiblePID;
152 29317 : }
153 :
154 : /* Get the PID of the thread that the current thread will act in the behalf of */
155 : /* By default : the current thread acts in the behalf of itself */
156 58951 : GIntBig GDALGetResponsiblePIDForCurrentThread()
157 : {
158 58951 : GIntBig* pResponsiblePID = (GIntBig*) CPLGetTLS(CTLS_RESPONSIBLEPID);
159 58951 : if (pResponsiblePID == NULL)
160 2239 : return CPLGetPID();
161 56712 : return *pResponsiblePID;
162 : }
163 :
164 :
165 : /************************************************************************/
166 : /* ==================================================================== */
167 : /* GDALDataset */
168 : /* ==================================================================== */
169 : /************************************************************************/
170 :
171 : /**
172 : * \class GDALDataset "gdal_priv.h"
173 : *
174 : * A dataset encapsulating one or more raster bands. Details are
175 : * further discussed in the <a href="gdal_datamodel.html#GDALDataset">GDAL
176 : * Data Model</a>.
177 : *
178 : * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
179 : * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
180 : * dataset.
181 : */
182 :
183 : /************************************************************************/
184 : /* GDALDataset() */
185 : /************************************************************************/
186 :
187 16633 : GDALDataset::GDALDataset()
188 :
189 : {
190 16633 : poDriver = NULL;
191 16633 : eAccess = GA_ReadOnly;
192 16633 : nRasterXSize = 512;
193 16633 : nRasterYSize = 512;
194 16633 : nBands = 0;
195 16633 : papoBands = NULL;
196 16633 : nRefCount = 1;
197 16633 : bShared = FALSE;
198 :
199 : /* -------------------------------------------------------------------- */
200 : /* Add this dataset to the open dataset list. */
201 : /* -------------------------------------------------------------------- */
202 : {
203 16633 : CPLMutexHolderD( &hDLMutex );
204 :
205 16633 : if (phAllDatasetSet == NULL)
206 622 : phAllDatasetSet = CPLHashSetNew(GDALDatasetHashFunc, GDALDatasetEqualFunc, GDALDatasetFreeFunc);
207 16633 : DatasetCtxt* ctxt = (DatasetCtxt*)CPLMalloc(sizeof(DatasetCtxt));
208 16633 : ctxt->poDS = this;
209 16633 : ctxt->nPIDCreatorForShared = -1;
210 16633 : CPLHashSetInsert(phAllDatasetSet, ctxt);
211 : }
212 :
213 : /* -------------------------------------------------------------------- */
214 : /* Set forced caching flag. */
215 : /* -------------------------------------------------------------------- */
216 : bForceCachedIO = CSLTestBoolean(
217 16633 : CPLGetConfigOption( "GDAL_FORCE_CACHING", "NO") );
218 16633 : }
219 :
220 :
221 : /************************************************************************/
222 : /* ~GDALDataset() */
223 : /************************************************************************/
224 :
225 : /**
226 : * \brief Destroy an open GDALDataset.
227 : *
228 : * This is the accepted method of closing a GDAL dataset and deallocating
229 : * all resources associated with it.
230 : *
231 : * Equivelent of the C callable GDALClose(). Except that GDALClose() first
232 : * decrements the reference count, and then closes only if it has dropped to
233 : * zero.
234 : *
235 : * For Windows users, it is not recommanded using the delete operator on the
236 : * dataset object because of known issues when allocating and freeing memory across
237 : * module boundaries. Calling GDALClose() is then a better option.
238 : */
239 :
240 16633 : GDALDataset::~GDALDataset()
241 :
242 : {
243 : int i;
244 :
245 : // we don't want to report destruction of datasets that
246 : // were never really open.
247 16633 : if( nBands != 0 || !EQUAL(GetDescription(),"") )
248 : {
249 16109 : if( CPLGetPID() != GDALGetResponsiblePIDForCurrentThread() )
250 : CPLDebug( "GDAL",
251 : "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)", GetDescription(), this,
252 : (int)CPLGetPID(),
253 0 : (int)GDALGetResponsiblePIDForCurrentThread() );
254 : else
255 : CPLDebug( "GDAL",
256 16109 : "GDALClose(%s, this=%p)", GetDescription(), this );
257 : }
258 :
259 : /* -------------------------------------------------------------------- */
260 : /* Remove dataset from the "open" dataset list. */
261 : /* -------------------------------------------------------------------- */
262 : {
263 16633 : CPLMutexHolderD( &hDLMutex );
264 :
265 : DatasetCtxt sStruct;
266 16633 : sStruct.poDS = this;
267 16633 : DatasetCtxt* psStruct = (DatasetCtxt*) CPLHashSetLookup(phAllDatasetSet, &sStruct);
268 16633 : GIntBig nPIDCreatorForShared = psStruct->nPIDCreatorForShared;
269 16633 : CPLHashSetRemove(phAllDatasetSet, psStruct);
270 :
271 16633 : if (bShared && phSharedDatasetSet != NULL)
272 : {
273 : SharedDatasetCtxt* psStruct;
274 : SharedDatasetCtxt sStruct;
275 293 : sStruct.nPID = nPIDCreatorForShared;
276 293 : sStruct.eAccess = eAccess;
277 293 : sStruct.pszDescription = (char*) GetDescription();
278 293 : psStruct = (SharedDatasetCtxt*) CPLHashSetLookup(phSharedDatasetSet, &sStruct);
279 586 : if (psStruct && psStruct->poDS == this)
280 : {
281 293 : CPLHashSetRemove(phSharedDatasetSet, psStruct);
282 : }
283 : else
284 : {
285 0 : CPLDebug("GDAL", "Should not happen. Cannot find %s, this=%p in phSharedDatasetSet", GetDescription(), this);
286 : }
287 : }
288 :
289 16633 : if (CPLHashSetSize(phAllDatasetSet) == 0)
290 : {
291 622 : CPLHashSetDestroy(phAllDatasetSet);
292 622 : phAllDatasetSet = NULL;
293 622 : if (phSharedDatasetSet)
294 : {
295 151 : CPLHashSetDestroy(phSharedDatasetSet);
296 : }
297 622 : phSharedDatasetSet = NULL;
298 622 : CPLFree(ppDatasets);
299 622 : ppDatasets = NULL;
300 16633 : }
301 : }
302 :
303 : /* -------------------------------------------------------------------- */
304 : /* Destroy the raster bands if they exist. */
305 : /* -------------------------------------------------------------------- */
306 430649 : for( i = 0; i < nBands && papoBands != NULL; i++ )
307 : {
308 414016 : if( papoBands[i] != NULL )
309 414016 : delete papoBands[i];
310 : }
311 :
312 16633 : CPLFree( papoBands );
313 16633 : }
314 :
315 : /************************************************************************/
316 : /* FlushCache() */
317 : /************************************************************************/
318 :
319 : /**
320 : * \brief Flush all write cached data to disk.
321 : *
322 : * Any raster (or other GDAL) data written via GDAL calls, but buffered
323 : * internally will be written to disk.
324 : *
325 : * Using this method does not prevent use from calling GDALClose()
326 : * to properly close a dataset and ensure that important data not addressed
327 : * by FlushCache() is written in the file.
328 : *
329 : * This method is the same as the C function GDALFlushCache().
330 : */
331 :
332 22142 : void GDALDataset::FlushCache()
333 :
334 : {
335 : int i;
336 :
337 : // This sometimes happens if a dataset is destroyed before completely
338 : // built.
339 :
340 22142 : if( papoBands == NULL )
341 529 : return;
342 :
343 1046997 : for( i = 0; i < nBands; i++ )
344 : {
345 1025384 : if( papoBands[i] != NULL )
346 1025384 : papoBands[i]->FlushCache();
347 : }
348 : }
349 :
350 : /************************************************************************/
351 : /* GDALFlushCache() */
352 : /************************************************************************/
353 :
354 : /**
355 : * \brief Flush all write cached data to disk.
356 : *
357 : * @see GDALDataset::FlushCache().
358 : */
359 :
360 337 : void CPL_STDCALL GDALFlushCache( GDALDatasetH hDS )
361 :
362 : {
363 337 : VALIDATE_POINTER0( hDS, "GDALFlushCache" );
364 :
365 337 : ((GDALDataset *) hDS)->FlushCache();
366 : }
367 :
368 : /************************************************************************/
369 : /* BlockBasedFlushCache() */
370 : /* */
371 : /* This helper method can be called by the */
372 : /* GDALDataset::FlushCache() for particular drivers to ensure */
373 : /* that buffers will be flushed in a manner suitable for pixel */
374 : /* interleaved (by block) IO. That is, if all the bands have */
375 : /* the same size blocks then a given block will be flushed for */
376 : /* all bands before proceeding to the next block. */
377 : /************************************************************************/
378 :
379 29 : void GDALDataset::BlockBasedFlushCache()
380 :
381 : {
382 : GDALRasterBand *poBand1;
383 : int nBlockXSize, nBlockYSize, iBand;
384 :
385 29 : poBand1 = GetRasterBand( 1 );
386 29 : if( poBand1 == NULL )
387 : {
388 1 : GDALDataset::FlushCache();
389 1 : return;
390 : }
391 :
392 28 : poBand1->GetBlockSize( &nBlockXSize, &nBlockYSize );
393 :
394 : /* -------------------------------------------------------------------- */
395 : /* Verify that all bands match. */
396 : /* -------------------------------------------------------------------- */
397 62 : for( iBand = 1; iBand < nBands; iBand++ )
398 : {
399 : int nThisBlockXSize, nThisBlockYSize;
400 34 : GDALRasterBand *poBand = GetRasterBand( iBand+1 );
401 :
402 34 : poBand->GetBlockSize( &nThisBlockXSize, &nThisBlockYSize );
403 34 : if( nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize )
404 : {
405 0 : GDALDataset::FlushCache();
406 0 : return;
407 : }
408 : }
409 :
410 : /* -------------------------------------------------------------------- */
411 : /* Now flush writable data. */
412 : /* -------------------------------------------------------------------- */
413 328 : for( int iY = 0; iY < poBand1->nBlocksPerColumn; iY++ )
414 : {
415 600 : for( int iX = 0; iX < poBand1->nBlocksPerRow; iX++ )
416 : {
417 1000 : for( iBand = 0; iBand < nBands; iBand++ )
418 : {
419 700 : GDALRasterBand *poBand = GetRasterBand( iBand+1 );
420 :
421 700 : if( poBand->papoBlocks[iX + iY*poBand1->nBlocksPerRow] != NULL)
422 : {
423 : CPLErr eErr;
424 :
425 400 : eErr = poBand->FlushBlock( iX, iY );
426 :
427 400 : if( eErr != CE_None )
428 0 : return;
429 : }
430 : }
431 : }
432 : }
433 : }
434 :
435 : /************************************************************************/
436 : /* RasterInitialize() */
437 : /* */
438 : /* Initialize raster size */
439 : /************************************************************************/
440 :
441 0 : void GDALDataset::RasterInitialize( int nXSize, int nYSize )
442 :
443 : {
444 0 : CPLAssert( nXSize > 0 && nYSize > 0 );
445 :
446 0 : nRasterXSize = nXSize;
447 0 : nRasterYSize = nYSize;
448 0 : }
449 :
450 : /************************************************************************/
451 : /* AddBand() */
452 : /************************************************************************/
453 :
454 : /**
455 : * \brief Add a band to a dataset.
456 : *
457 : * This method will add a new band to the dataset if the underlying format
458 : * supports this action. Most formats do not.
459 : *
460 : * Note that the new GDALRasterBand is not returned. It may be fetched
461 : * after successful completion of the method by calling
462 : * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest
463 : * band will always be the last band.
464 : *
465 : * @param eType the data type of the pixels in the new band.
466 : *
467 : * @param papszOptions a list of NAME=VALUE option strings. The supported
468 : * options are format specific. NULL may be passed by default.
469 : *
470 : * @return CE_None on success or CE_Failure on failure.
471 : */
472 :
473 0 : CPLErr GDALDataset::AddBand( GDALDataType eType, char ** papszOptions )
474 :
475 : {
476 : (void) eType;
477 : (void) papszOptions;
478 :
479 : ReportError( CE_Failure, CPLE_NotSupported,
480 0 : "Dataset does not support the AddBand() method." );
481 :
482 0 : return CE_Failure;
483 : }
484 :
485 : /************************************************************************/
486 : /* GDALAddBand() */
487 : /************************************************************************/
488 :
489 : /**
490 : * \brief Add a band to a dataset.
491 : *
492 : * @see GDALDataset::AddBand().
493 : */
494 :
495 283 : CPLErr CPL_STDCALL GDALAddBand( GDALDatasetH hDataset,
496 : GDALDataType eType, char **papszOptions )
497 :
498 : {
499 283 : VALIDATE_POINTER1( hDataset, "GDALAddBand", CE_Failure );
500 :
501 283 : return ((GDALDataset *) hDataset)->AddBand( eType, papszOptions );
502 : }
503 :
504 : /************************************************************************/
505 : /* SetBand() */
506 : /* */
507 : /* Set a band in the band array, updating the band count, and */
508 : /* array size appropriately. */
509 : /************************************************************************/
510 :
511 625404 : void GDALDataset::SetBand( int nNewBand, GDALRasterBand * poBand )
512 :
513 : {
514 : /* -------------------------------------------------------------------- */
515 : /* Do we need to grow the bands list? */
516 : /* -------------------------------------------------------------------- */
517 625404 : if( nBands < nNewBand || papoBands == NULL ) {
518 : int i;
519 : GDALRasterBand** papoNewBands;
520 :
521 360596 : if( papoBands == NULL )
522 : papoNewBands = (GDALRasterBand **)
523 16058 : VSICalloc(sizeof(GDALRasterBand*), MAX(nNewBand,nBands));
524 : else
525 : papoNewBands = (GDALRasterBand **)
526 : VSIRealloc(papoBands, sizeof(GDALRasterBand*) *
527 344538 : MAX(nNewBand,nBands));
528 360596 : if (papoNewBands == NULL)
529 : {
530 : ReportError(CE_Failure, CPLE_OutOfMemory,
531 0 : "Cannot allocate band array");
532 0 : return;
533 : }
534 360596 : papoBands = papoNewBands;
535 :
536 714952 : for( i = nBands; i < nNewBand; i++ )
537 354356 : papoBands[i] = NULL;
538 :
539 360596 : nBands = MAX(nBands,nNewBand);
540 : }
541 :
542 : /* -------------------------------------------------------------------- */
543 : /* Set the band. Resetting the band is currently not permitted. */
544 : /* -------------------------------------------------------------------- */
545 625404 : if( papoBands[nNewBand-1] != NULL )
546 : {
547 : ReportError(CE_Failure, CPLE_NotSupported,
548 0 : "Cannot set band %d as it is already set", nNewBand);
549 0 : return;
550 : }
551 :
552 625404 : papoBands[nNewBand-1] = poBand;
553 :
554 : /* -------------------------------------------------------------------- */
555 : /* Set back reference information on the raster band. Note */
556 : /* that the GDALDataset is a friend of the GDALRasterBand */
557 : /* specifically to allow this. */
558 : /* -------------------------------------------------------------------- */
559 625404 : poBand->nBand = nNewBand;
560 625404 : poBand->poDS = this;
561 625404 : poBand->nRasterXSize = nRasterXSize;
562 625404 : poBand->nRasterYSize = nRasterYSize;
563 625404 : poBand->eAccess = eAccess; /* default access to be same as dataset */
564 : }
565 :
566 : /************************************************************************/
567 : /* GetRasterXSize() */
568 : /************************************************************************/
569 :
570 : /**
571 :
572 : \brief Fetch raster width in pixels.
573 :
574 : Equivelent of the C function GDALGetRasterXSize().
575 :
576 : @return the width in pixels of raster bands in this GDALDataset.
577 :
578 : */
579 :
580 399124 : int GDALDataset::GetRasterXSize()
581 :
582 : {
583 399124 : return nRasterXSize;
584 : }
585 :
586 : /************************************************************************/
587 : /* GDALGetRasterXSize() */
588 : /************************************************************************/
589 :
590 : /**
591 : * \brief Fetch raster width in pixels.
592 : *
593 : * @see GDALDataset::GetRasterXSize().
594 : */
595 :
596 5463 : int CPL_STDCALL GDALGetRasterXSize( GDALDatasetH hDataset )
597 :
598 : {
599 5463 : VALIDATE_POINTER1( hDataset, "GDALGetRasterXSize", 0 );
600 :
601 5463 : return ((GDALDataset *) hDataset)->GetRasterXSize();
602 : }
603 :
604 :
605 : /************************************************************************/
606 : /* GetRasterYSize() */
607 : /************************************************************************/
608 :
609 : /**
610 :
611 : \brief Fetch raster height in pixels.
612 :
613 : Equivelent of the C function GDALGetRasterYSize().
614 :
615 : @return the height in pixels of raster bands in this GDALDataset.
616 :
617 : */
618 :
619 162388 : int GDALDataset::GetRasterYSize()
620 :
621 : {
622 162388 : return nRasterYSize;
623 : }
624 :
625 : /************************************************************************/
626 : /* GDALGetRasterYSize() */
627 : /************************************************************************/
628 :
629 : /**
630 : * \brief Fetch raster height in pixels.
631 : *
632 : * @see GDALDataset::GetRasterYSize().
633 : */
634 :
635 13762 : int CPL_STDCALL GDALGetRasterYSize( GDALDatasetH hDataset )
636 :
637 : {
638 13762 : VALIDATE_POINTER1( hDataset, "GDALGetRasterYSize", 0 );
639 :
640 13762 : return ((GDALDataset *) hDataset)->GetRasterYSize();
641 : }
642 :
643 : /************************************************************************/
644 : /* GetRasterBand() */
645 : /************************************************************************/
646 :
647 : /**
648 :
649 : \brief Fetch a band object for a dataset.
650 :
651 : Equivalent of the C function GDALGetRasterBand().
652 :
653 : @param nBandId the index number of the band to fetch, from 1 to
654 : GetRasterCount().
655 :
656 : @return the nBandId th band object
657 :
658 : */
659 :
660 2375533 : GDALRasterBand * GDALDataset::GetRasterBand( int nBandId )
661 :
662 : {
663 2375533 : if ( papoBands )
664 : {
665 2375532 : if( nBandId < 1 || nBandId > nBands )
666 : {
667 : ReportError( CE_Failure, CPLE_IllegalArg,
668 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
669 0 : nBandId );
670 0 : return NULL;
671 : }
672 : else
673 2375532 : return( papoBands[nBandId-1] );
674 : }
675 1 : return NULL;
676 : }
677 :
678 : /************************************************************************/
679 : /* GDALGetRasterBand() */
680 : /************************************************************************/
681 :
682 : /**
683 : * \brief Fetch a band object for a dataset.
684 : * @see GDALDataset::GetRasterBand().
685 : */
686 :
687 180541 : GDALRasterBandH CPL_STDCALL GDALGetRasterBand( GDALDatasetH hDS, int nBandId )
688 :
689 : {
690 180541 : VALIDATE_POINTER1( hDS, "GDALGetRasterBand", NULL );
691 :
692 180541 : return( (GDALRasterBandH) ((GDALDataset *) hDS)->GetRasterBand(nBandId) );
693 : }
694 :
695 : /************************************************************************/
696 : /* GetRasterCount() */
697 : /************************************************************************/
698 :
699 : /**
700 : * \brief Fetch the number of raster bands on this dataset.
701 : *
702 : * Same as the C function GDALGetRasterCount().
703 : *
704 : * @return the number of raster bands.
705 : */
706 :
707 1851722 : int GDALDataset::GetRasterCount()
708 :
709 : {
710 1851722 : return papoBands ? nBands : 0;
711 : }
712 :
713 : /************************************************************************/
714 : /* GDALGetRasterCount() */
715 : /************************************************************************/
716 :
717 : /**
718 : * \brief Fetch the number of raster bands on this dataset.
719 : *
720 : * @see GDALDataset::GetRasterCount().
721 : */
722 :
723 339684 : int CPL_STDCALL GDALGetRasterCount( GDALDatasetH hDS )
724 :
725 : {
726 339684 : VALIDATE_POINTER1( hDS, "GDALGetRasterCount", 0 );
727 :
728 339684 : return( ((GDALDataset *) hDS)->GetRasterCount() );
729 : }
730 :
731 : /************************************************************************/
732 : /* GetProjectionRef() */
733 : /************************************************************************/
734 :
735 : /**
736 : * \brief Fetch the projection definition string for this dataset.
737 : *
738 : * Same as the C function GDALGetProjectionRef().
739 : *
740 : * The returned string defines the projection coordinate system of the
741 : * image in OpenGIS WKT format. It should be suitable for use with the
742 : * OGRSpatialReference class.
743 : *
744 : * When a projection definition is not available an empty (but not NULL)
745 : * string is returned.
746 : *
747 : * @return a pointer to an internal projection reference string. It should
748 : * not be altered, freed or expected to last for long.
749 : *
750 : * @see http://www.gdal.org/ogr/osr_tutorial.html
751 : */
752 :
753 4525 : const char *GDALDataset::GetProjectionRef()
754 :
755 : {
756 4525 : return( "" );
757 : }
758 :
759 : /************************************************************************/
760 : /* GDALGetProjectionRef() */
761 : /************************************************************************/
762 :
763 : /**
764 : * \brief Fetch the projection definition string for this dataset.
765 : *
766 : * @see GDALDataset::GetProjectionRef()
767 : */
768 :
769 1875 : const char * CPL_STDCALL GDALGetProjectionRef( GDALDatasetH hDS )
770 :
771 : {
772 1875 : VALIDATE_POINTER1( hDS, "GDALGetProjectionRef", NULL );
773 :
774 1875 : return( ((GDALDataset *) hDS)->GetProjectionRef() );
775 : }
776 :
777 : /************************************************************************/
778 : /* SetProjection() */
779 : /************************************************************************/
780 :
781 : /**
782 : * \brief Set the projection reference string for this dataset.
783 : *
784 : * The string should be in OGC WKT or PROJ.4 format. An error may occur
785 : * because of incorrectly specified projection strings, because the dataset
786 : * is not writable, or because the dataset does not support the indicated
787 : * projection. Many formats do not support writing projections.
788 : *
789 : * This method is the same as the C GDALSetProjection() function.
790 : *
791 : * @param pszProjection projection reference string.
792 : *
793 : * @return CE_Failure if an error occurs, otherwise CE_None.
794 : */
795 :
796 5 : CPLErr GDALDataset::SetProjection( const char * pszProjection )
797 :
798 : {
799 5 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
800 : ReportError( CE_Failure, CPLE_NotSupported,
801 0 : "Dataset does not support the SetProjection() method." );
802 5 : return CE_Failure;
803 : }
804 :
805 : /************************************************************************/
806 : /* GDALSetProjection() */
807 : /************************************************************************/
808 :
809 : /**
810 : * \brief Set the projection reference string for this dataset.
811 : *
812 : * @see GDALDataset::SetProjection()
813 : */
814 :
815 1259 : CPLErr CPL_STDCALL GDALSetProjection( GDALDatasetH hDS, const char * pszProjection )
816 :
817 : {
818 1259 : VALIDATE_POINTER1( hDS, "GDALSetProjection", CE_Failure );
819 :
820 1259 : return( ((GDALDataset *) hDS)->SetProjection(pszProjection) );
821 : }
822 :
823 : /************************************************************************/
824 : /* GetGeoTransform() */
825 : /************************************************************************/
826 :
827 : /**
828 : * \brief Fetch the affine transformation coefficients.
829 : *
830 : * Fetches the coefficients for transforming between pixel/line (P,L) raster
831 : * space, and projection coordinates (Xp,Yp) space.
832 : *
833 : * \code
834 : * Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
835 : * Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
836 : * \endcode
837 : *
838 : * In a north up image, padfTransform[1] is the pixel width, and
839 : * padfTransform[5] is the pixel height. The upper left corner of the
840 : * upper left pixel is at position (padfTransform[0],padfTransform[3]).
841 : *
842 : * The default transform is (0,1,0,0,0,1) and should be returned even when
843 : * a CE_Failure error is returned, such as for formats that don't support
844 : * transformation to projection coordinates.
845 : *
846 : * NOTE: GetGeoTransform() isn't expressive enough to handle the variety of
847 : * OGC Grid Coverages pixel/line to projection transformation schemes.
848 : * Eventually this method will be depreciated in favour of a more general
849 : * scheme.
850 : *
851 : * This method does the same thing as the C GDALGetGeoTransform() function.
852 : *
853 : * @param padfTransform an existing six double buffer into which the
854 : * transformation will be placed.
855 : *
856 : * @return CE_None on success, or CE_Failure if no transform can be fetched.
857 : */
858 :
859 4131 : CPLErr GDALDataset::GetGeoTransform( double * padfTransform )
860 :
861 : {
862 4131 : CPLAssert( padfTransform != NULL );
863 :
864 4131 : padfTransform[0] = 0.0; /* X Origin (top left corner) */
865 4131 : padfTransform[1] = 1.0; /* X Pixel size */
866 4131 : padfTransform[2] = 0.0;
867 :
868 4131 : padfTransform[3] = 0.0; /* Y Origin (top left corner) */
869 4131 : padfTransform[4] = 0.0;
870 4131 : padfTransform[5] = 1.0; /* Y Pixel Size */
871 :
872 4131 : return( CE_Failure );
873 : }
874 :
875 : /************************************************************************/
876 : /* GDALGetGeoTransform() */
877 : /************************************************************************/
878 :
879 : /**
880 : * \brief Fetch the affine transformation coefficients.
881 : *
882 : * @see GDALDataset::GetGeoTransform()
883 : */
884 :
885 1771 : CPLErr CPL_STDCALL GDALGetGeoTransform( GDALDatasetH hDS, double * padfTransform )
886 :
887 : {
888 1771 : VALIDATE_POINTER1( hDS, "GDALGetGeoTransform", CE_Failure );
889 :
890 1771 : return( ((GDALDataset *) hDS)->GetGeoTransform(padfTransform) );
891 : }
892 :
893 : /************************************************************************/
894 : /* SetGeoTransform() */
895 : /************************************************************************/
896 :
897 : /**
898 : * \brief Set the affine transformation coefficients.
899 : *
900 : * See GetGeoTransform() for details on the meaning of the padfTransform
901 : * coefficients.
902 : *
903 : * This method does the same thing as the C GDALSetGeoTransform() function.
904 : *
905 : * @param padfTransform a six double buffer containing the transformation
906 : * coefficients to be written with the dataset.
907 : *
908 : * @return CE_None on success, or CE_Failure if this transform cannot be
909 : * written.
910 : */
911 :
912 5 : CPLErr GDALDataset::SetGeoTransform( double * padfTransform )
913 :
914 : {
915 5 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
916 : ReportError( CE_Failure, CPLE_NotSupported,
917 0 : "SetGeoTransform() not supported for this dataset." );
918 :
919 5 : return( CE_Failure );
920 : }
921 :
922 : /************************************************************************/
923 : /* GDALSetGeoTransform() */
924 : /************************************************************************/
925 :
926 : /**
927 : * \brief Set the affine transformation coefficients.
928 : *
929 : * @see GDALDataset::SetGeoTransform()
930 : */
931 :
932 : CPLErr CPL_STDCALL
933 1236 : GDALSetGeoTransform( GDALDatasetH hDS, double * padfTransform )
934 :
935 : {
936 1236 : VALIDATE_POINTER1( hDS, "GDALSetGeoTransform", CE_Failure );
937 :
938 1236 : return( ((GDALDataset *) hDS)->SetGeoTransform(padfTransform) );
939 : }
940 :
941 : /************************************************************************/
942 : /* GetInternalHandle() */
943 : /************************************************************************/
944 :
945 : /**
946 : * \brief Fetch a format specific internally meaningful handle.
947 : *
948 : * This method is the same as the C GDALGetInternalHandle() method.
949 : *
950 : * @param pszHandleName the handle name desired. The meaningful names
951 : * will be specific to the file format.
952 : *
953 : * @return the desired handle value, or NULL if not recognised/supported.
954 : */
955 :
956 0 : void *GDALDataset::GetInternalHandle( const char * pszHandleName )
957 :
958 : {
959 0 : return( NULL );
960 : }
961 :
962 : /************************************************************************/
963 : /* GDALGetInternalHandle() */
964 : /************************************************************************/
965 :
966 : /**
967 : * \brief Fetch a format specific internally meaningful handle.
968 : *
969 : * @see GDALDataset::GetInternalHandle()
970 : */
971 :
972 : void * CPL_STDCALL
973 0 : GDALGetInternalHandle( GDALDatasetH hDS, const char * pszRequest )
974 :
975 : {
976 0 : VALIDATE_POINTER1( hDS, "GDALGetInternalHandle", NULL );
977 :
978 0 : return( ((GDALDataset *) hDS)->GetInternalHandle(pszRequest) );
979 : }
980 :
981 : /************************************************************************/
982 : /* GetDriver() */
983 : /************************************************************************/
984 :
985 : /**
986 : * \brief Fetch the driver to which this dataset relates.
987 : *
988 : * This method is the same as the C GDALGetDatasetDriver() function.
989 : *
990 : * @return the driver on which the dataset was created with GDALOpen() or
991 : * GDALCreate().
992 : */
993 :
994 2388 : GDALDriver * GDALDataset::GetDriver()
995 :
996 : {
997 2388 : return poDriver;
998 : }
999 :
1000 : /************************************************************************/
1001 : /* GDALGetDatasetDriver() */
1002 : /************************************************************************/
1003 :
1004 : /**
1005 : * \brief Fetch the driver to which this dataset relates.
1006 : *
1007 : * @see GDALDataset::GetDriver()
1008 : */
1009 :
1010 606 : GDALDriverH CPL_STDCALL GDALGetDatasetDriver( GDALDatasetH hDataset )
1011 :
1012 : {
1013 606 : VALIDATE_POINTER1( hDataset, "GDALGetDatasetDriver", NULL );
1014 :
1015 606 : return (GDALDriverH) ((GDALDataset *) hDataset)->GetDriver();
1016 : }
1017 :
1018 : /************************************************************************/
1019 : /* Reference() */
1020 : /************************************************************************/
1021 :
1022 : /**
1023 : * \brief Add one to dataset reference count.
1024 : *
1025 : * The reference is one after instantiation.
1026 : *
1027 : * This method is the same as the C GDALReferenceDataset() function.
1028 : *
1029 : * @return the post-increment reference count.
1030 : */
1031 :
1032 11031 : int GDALDataset::Reference()
1033 :
1034 : {
1035 11031 : return ++nRefCount;
1036 : }
1037 :
1038 : /************************************************************************/
1039 : /* GDALReferenceDataset() */
1040 : /************************************************************************/
1041 :
1042 : /**
1043 : * \brief Add one to dataset reference count.
1044 : *
1045 : * @see GDALDataset::Reference()
1046 : */
1047 :
1048 69 : int CPL_STDCALL GDALReferenceDataset( GDALDatasetH hDataset )
1049 :
1050 : {
1051 69 : VALIDATE_POINTER1( hDataset, "GDALReferenceDataset", 0 );
1052 :
1053 69 : return ((GDALDataset *) hDataset)->Reference();
1054 : }
1055 :
1056 : /************************************************************************/
1057 : /* Dereference() */
1058 : /************************************************************************/
1059 :
1060 : /**
1061 : * \brief Subtract one from dataset reference count.
1062 : *
1063 : * The reference is one after instantiation. Generally when the reference
1064 : * count has dropped to zero the dataset may be safely deleted (closed).
1065 : *
1066 : * This method is the same as the C GDALDereferenceDataset() function.
1067 : *
1068 : * @return the post-decrement reference count.
1069 : */
1070 :
1071 22903 : int GDALDataset::Dereference()
1072 :
1073 : {
1074 22903 : return --nRefCount;
1075 : }
1076 :
1077 : /************************************************************************/
1078 : /* GDALDereferenceDataset() */
1079 : /************************************************************************/
1080 :
1081 : /**
1082 : * \brief Subtract one from dataset reference count.
1083 : *
1084 : * @see GDALDataset::Dereference()
1085 : */
1086 :
1087 16392 : int CPL_STDCALL GDALDereferenceDataset( GDALDatasetH hDataset )
1088 :
1089 : {
1090 16392 : VALIDATE_POINTER1( hDataset, "GDALDereferenceDataset", 0 );
1091 :
1092 16392 : return ((GDALDataset *) hDataset)->Dereference();
1093 : }
1094 :
1095 : /************************************************************************/
1096 : /* GetShared() */
1097 : /************************************************************************/
1098 :
1099 : /**
1100 : * \brief Returns shared flag.
1101 : *
1102 : * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
1103 : */
1104 :
1105 23652 : int GDALDataset::GetShared()
1106 :
1107 : {
1108 23652 : return bShared;
1109 : }
1110 :
1111 : /************************************************************************/
1112 : /* MarkAsShared() */
1113 : /************************************************************************/
1114 :
1115 : /**
1116 : * \brief Mark this dataset as available for sharing.
1117 : */
1118 :
1119 293 : void GDALDataset::MarkAsShared()
1120 :
1121 : {
1122 293 : CPLAssert( !bShared );
1123 :
1124 293 : bShared = TRUE;
1125 :
1126 293 : GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1127 : SharedDatasetCtxt* psStruct;
1128 :
1129 : /* Insert the dataset in the set of shared opened datasets */
1130 293 : CPLMutexHolderD( &hDLMutex );
1131 293 : if (phSharedDatasetSet == NULL)
1132 151 : phSharedDatasetSet = CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc, GDALSharedDatasetFreeFunc);
1133 :
1134 293 : psStruct = (SharedDatasetCtxt*)CPLMalloc(sizeof(SharedDatasetCtxt));
1135 293 : psStruct->poDS = this;
1136 293 : psStruct->nPID = nPID;
1137 293 : psStruct->eAccess = eAccess;
1138 293 : psStruct->pszDescription = CPLStrdup(GetDescription());
1139 293 : if(CPLHashSetLookup(phSharedDatasetSet, psStruct) != NULL)
1140 : {
1141 0 : CPLFree(psStruct);
1142 : ReportError(CE_Failure, CPLE_AppDefined,
1143 0 : "An existing shared dataset has already this description. This should not happen");
1144 : }
1145 : else
1146 : {
1147 293 : CPLHashSetInsert(phSharedDatasetSet, psStruct);
1148 :
1149 : DatasetCtxt sStruct;
1150 293 : sStruct.poDS = this;
1151 293 : DatasetCtxt* psStruct = (DatasetCtxt*) CPLHashSetLookup(phAllDatasetSet, &sStruct);
1152 293 : psStruct->nPIDCreatorForShared = nPID;
1153 293 : }
1154 293 : }
1155 :
1156 : /************************************************************************/
1157 : /* GetGCPCount() */
1158 : /************************************************************************/
1159 :
1160 : /**
1161 : * \brief Get number of GCPs.
1162 : *
1163 : * This method is the same as the C function GDALGetGCPCount().
1164 : *
1165 : * @return number of GCPs for this dataset. Zero if there are none.
1166 : */
1167 :
1168 4011 : int GDALDataset::GetGCPCount()
1169 :
1170 : {
1171 4011 : return 0;
1172 : }
1173 :
1174 : /************************************************************************/
1175 : /* GDALGetGCPCount() */
1176 : /************************************************************************/
1177 :
1178 : /**
1179 : * \brief Get number of GCPs.
1180 : *
1181 : * @see GDALDataset::GetGCPCount()
1182 : */
1183 :
1184 202 : int CPL_STDCALL GDALGetGCPCount( GDALDatasetH hDS )
1185 :
1186 : {
1187 202 : VALIDATE_POINTER1( hDS, "GDALGetGCPCount", 0 );
1188 :
1189 202 : return ((GDALDataset *) hDS)->GetGCPCount();
1190 : }
1191 :
1192 : /************************************************************************/
1193 : /* GetGCPProjection() */
1194 : /************************************************************************/
1195 :
1196 : /**
1197 : * \brief Get output projection for GCPs.
1198 : *
1199 : * This method is the same as the C function GDALGetGCPProjection().
1200 : *
1201 : * The projection string follows the normal rules from GetProjectionRef().
1202 : *
1203 : * @return internal projection string or "" if there are no GCPs.
1204 : * It should not be altered, freed or expected to last for long.
1205 : */
1206 :
1207 2 : const char *GDALDataset::GetGCPProjection()
1208 :
1209 : {
1210 2 : return "";
1211 : }
1212 :
1213 : /************************************************************************/
1214 : /* GDALGetGCPProjection() */
1215 : /************************************************************************/
1216 :
1217 : /**
1218 : * \brief Get output projection for GCPs.
1219 : *
1220 : * @see GDALDataset::GetGCPProjection()
1221 : */
1222 :
1223 94 : const char * CPL_STDCALL GDALGetGCPProjection( GDALDatasetH hDS )
1224 :
1225 : {
1226 94 : VALIDATE_POINTER1( hDS, "GDALGetGCPProjection", NULL );
1227 :
1228 94 : return ((GDALDataset *) hDS)->GetGCPProjection();
1229 : }
1230 :
1231 : /************************************************************************/
1232 : /* GetGCPs() */
1233 : /************************************************************************/
1234 :
1235 : /**
1236 : * \brief Fetch GCPs.
1237 : *
1238 : * This method is the same as the C function GDALGetGCPs().
1239 : *
1240 : * @return pointer to internal GCP structure list. It should not be modified,
1241 : * and may change on the next GDAL call.
1242 : */
1243 :
1244 1 : const GDAL_GCP *GDALDataset::GetGCPs()
1245 :
1246 : {
1247 1 : return NULL;
1248 : }
1249 :
1250 : /************************************************************************/
1251 : /* GDALGetGCPs() */
1252 : /************************************************************************/
1253 :
1254 : /**
1255 : * \brief Fetch GCPs.
1256 : *
1257 : * @see GDALDataset::GetGCPs()
1258 : */
1259 :
1260 66 : const GDAL_GCP * CPL_STDCALL GDALGetGCPs( GDALDatasetH hDS )
1261 :
1262 : {
1263 66 : VALIDATE_POINTER1( hDS, "GDALGetGCPs", NULL );
1264 :
1265 66 : return ((GDALDataset *) hDS)->GetGCPs();
1266 : }
1267 :
1268 :
1269 : /************************************************************************/
1270 : /* SetGCPs() */
1271 : /************************************************************************/
1272 :
1273 : /**
1274 : * \brief Assign GCPs.
1275 : *
1276 : * This method is the same as the C function GDALSetGCPs().
1277 : *
1278 : * This method assigns the passed set of GCPs to this dataset, as well as
1279 : * setting their coordinate system. Internally copies are made of the
1280 : * coordinate system and list of points, so the caller remains resposible for
1281 : * deallocating these arguments if appropriate.
1282 : *
1283 : * Most formats do not support setting of GCPs, even foramts that can
1284 : * handle GCPs. These formats will return CE_Failure.
1285 : *
1286 : * @param nGCPCount number of GCPs being assigned.
1287 : *
1288 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
1289 : *
1290 : * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
1291 : * GCP output coordinates. This parameter should be "" if no output coordinate
1292 : * system is known.
1293 : *
1294 : * @return CE_None on success, CE_Failure on failure (including if action is
1295 : * not supported for this format).
1296 : */
1297 :
1298 0 : CPLErr GDALDataset::SetGCPs( int nGCPCount,
1299 : const GDAL_GCP *pasGCPList,
1300 : const char * pszGCPProjection )
1301 :
1302 : {
1303 : (void) nGCPCount;
1304 : (void) pasGCPList;
1305 : (void) pszGCPProjection;
1306 :
1307 0 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1308 : ReportError( CE_Failure, CPLE_NotSupported,
1309 0 : "Dataset does not support the SetGCPs() method." );
1310 :
1311 0 : return CE_Failure;
1312 : }
1313 :
1314 : /************************************************************************/
1315 : /* GDALSetGCPs() */
1316 : /************************************************************************/
1317 :
1318 : /**
1319 : * \brief Assign GCPs.
1320 : *
1321 : * @see GDALDataset::SetGCPs()
1322 : */
1323 :
1324 11 : CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount,
1325 : const GDAL_GCP *pasGCPList,
1326 : const char *pszGCPProjection )
1327 :
1328 : {
1329 11 : VALIDATE_POINTER1( hDS, "GDALSetGCPs", CE_Failure );
1330 :
1331 : return ((GDALDataset *) hDS)->SetGCPs( nGCPCount, pasGCPList,
1332 11 : pszGCPProjection );
1333 : }
1334 :
1335 : /************************************************************************/
1336 : /* BuildOverviews() */
1337 : /************************************************************************/
1338 :
1339 : /**
1340 : * \brief Build raster overview(s)
1341 : *
1342 : * If the operation is unsupported for the indicated dataset, then
1343 : * CE_Failure is returned, and CPLGetLastErrorNo() will return
1344 : * CPLE_NotSupported.
1345 : *
1346 : * This method is the same as the C function GDALBuildOverviews().
1347 : *
1348 : * @param pszResampling one of "NEAREST", "GAUSS", "CUBIC", "AVERAGE", "MODE",
1349 : * "AVERAGE_MAGPHASE" or "NONE" controlling the downsampling method applied.
1350 : * @param nOverviews number of overviews to build.
1351 : * @param panOverviewList the list of overview decimation factors to build.
1352 : * @param nListBands number of bands to build overviews for in panBandList. Build
1353 : * for all bands if this is 0.
1354 : * @param panBandList list of band numbers.
1355 : * @param pfnProgress a function to call to report progress, or NULL.
1356 : * @param pProgressData application data to pass to the progress function.
1357 : *
1358 : * @return CE_None on success or CE_Failure if the operation doesn't work.
1359 : *
1360 : * For example, to build overview level 2, 4 and 8 on all bands the following
1361 : * call could be made:
1362 : * <pre>
1363 : * int anOverviewList[3] = { 2, 4, 8 };
1364 : *
1365 : * poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, NULL,
1366 : * GDALDummyProgress, NULL );
1367 : * </pre>
1368 : *
1369 : * @see GDALRegenerateOverviews()
1370 : */
1371 :
1372 188 : CPLErr GDALDataset::BuildOverviews( const char *pszResampling,
1373 : int nOverviews, int *panOverviewList,
1374 : int nListBands, int *panBandList,
1375 : GDALProgressFunc pfnProgress,
1376 : void * pProgressData )
1377 :
1378 : {
1379 : CPLErr eErr;
1380 188 : int *panAllBandList = NULL;
1381 :
1382 188 : if( nListBands == 0 )
1383 : {
1384 184 : nListBands = GetRasterCount();
1385 184 : panAllBandList = (int *) CPLMalloc(sizeof(int) * nListBands);
1386 468 : for( int i = 0; i < nListBands; i++ )
1387 284 : panAllBandList[i] = i+1;
1388 :
1389 184 : panBandList = panAllBandList;
1390 : }
1391 :
1392 188 : if( pfnProgress == NULL )
1393 178 : pfnProgress = GDALDummyProgress;
1394 :
1395 : eErr = IBuildOverviews( pszResampling, nOverviews, panOverviewList,
1396 188 : nListBands, panBandList, pfnProgress, pProgressData );
1397 :
1398 188 : if( panAllBandList != NULL )
1399 184 : CPLFree( panAllBandList );
1400 :
1401 188 : return eErr;
1402 : }
1403 :
1404 : /************************************************************************/
1405 : /* GDALBuildOverviews() */
1406 : /************************************************************************/
1407 :
1408 : /**
1409 : * \brief Build raster overview(s)
1410 : *
1411 : * @see GDALDataset::BuildOverviews()
1412 : */
1413 :
1414 182 : CPLErr CPL_STDCALL GDALBuildOverviews( GDALDatasetH hDataset,
1415 : const char *pszResampling,
1416 : int nOverviews, int *panOverviewList,
1417 : int nListBands, int *panBandList,
1418 : GDALProgressFunc pfnProgress,
1419 : void * pProgressData )
1420 :
1421 : {
1422 182 : VALIDATE_POINTER1( hDataset, "GDALBuildOverviews", CE_Failure );
1423 :
1424 : return ((GDALDataset *) hDataset)->BuildOverviews(
1425 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
1426 182 : pfnProgress, pProgressData );
1427 : }
1428 :
1429 : /************************************************************************/
1430 : /* IBuildOverviews() */
1431 : /* */
1432 : /* Default implementation. */
1433 : /************************************************************************/
1434 :
1435 85 : CPLErr GDALDataset::IBuildOverviews( const char *pszResampling,
1436 : int nOverviews, int *panOverviewList,
1437 : int nListBands, int *panBandList,
1438 : GDALProgressFunc pfnProgress,
1439 : void * pProgressData )
1440 :
1441 : {
1442 85 : if( oOvManager.IsInitialized() )
1443 : return oOvManager.BuildOverviews( NULL, pszResampling,
1444 : nOverviews, panOverviewList,
1445 : nListBands, panBandList,
1446 85 : pfnProgress, pProgressData );
1447 : else
1448 : {
1449 : ReportError( CE_Failure, CPLE_NotSupported,
1450 0 : "BuildOverviews() not supported for this dataset." );
1451 :
1452 0 : return( CE_Failure );
1453 : }
1454 : }
1455 :
1456 : /************************************************************************/
1457 : /* IRasterIO() */
1458 : /* */
1459 : /* The default implementation of IRasterIO() is to pass the */
1460 : /* request off to each band objects rasterio methods with */
1461 : /* appropriate arguments. */
1462 : /************************************************************************/
1463 :
1464 362380 : CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
1465 : int nXOff, int nYOff, int nXSize, int nYSize,
1466 : void * pData, int nBufXSize, int nBufYSize,
1467 : GDALDataType eBufType,
1468 : int nBandCount, int *panBandMap,
1469 : int nPixelSpace, int nLineSpace, int nBandSpace)
1470 :
1471 : {
1472 : int iBandIndex;
1473 362380 : CPLErr eErr = CE_None;
1474 362380 : const char* pszInterleave = NULL;
1475 :
1476 362380 : CPLAssert( NULL != pData );
1477 :
1478 393706 : if (nXSize == nBufXSize && nYSize == nBufYSize &&
1479 31326 : (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) != NULL &&
1480 : EQUAL(pszInterleave, "PIXEL"))
1481 : {
1482 : return BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
1483 : pData, nBufXSize, nBufYSize,
1484 : eBufType, nBandCount, panBandMap,
1485 1506 : nPixelSpace, nLineSpace, nBandSpace );
1486 : }
1487 :
1488 748358 : for( iBandIndex = 0;
1489 : iBandIndex < nBandCount && eErr == CE_None;
1490 : iBandIndex++ )
1491 : {
1492 387484 : GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
1493 : GByte *pabyBandData;
1494 :
1495 387484 : if (poBand == NULL)
1496 : {
1497 0 : eErr = CE_Failure;
1498 0 : break;
1499 : }
1500 :
1501 387484 : pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
1502 :
1503 : eErr = poBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
1504 : (void *) pabyBandData, nBufXSize, nBufYSize,
1505 387484 : eBufType, nPixelSpace, nLineSpace );
1506 : }
1507 :
1508 360874 : return eErr;
1509 : }
1510 :
1511 :
1512 : /************************************************************************/
1513 : /* RasterIO() */
1514 : /************************************************************************/
1515 :
1516 : /**
1517 : * \brief Read/write a region of image data from multiple bands.
1518 : *
1519 : * This method allows reading a region of one or more GDALRasterBands from
1520 : * this dataset into a buffer, or writing data from a buffer into a region
1521 : * of the GDALRasterBands. It automatically takes care of data type
1522 : * translation if the data type (eBufType) of the buffer is different than
1523 : * that of the GDALRasterBand.
1524 : * The method also takes care of image decimation / replication if the
1525 : * buffer size (nBufXSize x nBufYSize) is different than the size of the
1526 : * region being accessed (nXSize x nYSize).
1527 : *
1528 : * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
1529 : * writing from various organization of buffers.
1530 : *
1531 : * For highest performance full resolution data access, read and write
1532 : * on "block boundaries" as returned by GetBlockSize(), or use the
1533 : * ReadBlock() and WriteBlock() methods.
1534 : *
1535 : * This method is the same as the C GDALDatasetRasterIO() function.
1536 : *
1537 : * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
1538 : * write a region of data.
1539 : *
1540 : * @param nXOff The pixel offset to the top left corner of the region
1541 : * of the band to be accessed. This would be zero to start from the left side.
1542 : *
1543 : * @param nYOff The line offset to the top left corner of the region
1544 : * of the band to be accessed. This would be zero to start from the top.
1545 : *
1546 : * @param nXSize The width of the region of the band to be accessed in pixels.
1547 : *
1548 : * @param nYSize The height of the region of the band to be accessed in lines.
1549 : *
1550 : * @param pData The buffer into which the data should be read, or from which
1551 : * it should be written. This buffer must contain at least
1552 : * nBufXSize * nBufYSize * nBandCount words of type eBufType. It is organized
1553 : * in left to right,top to bottom pixel order. Spacing is controlled by the
1554 : * nPixelSpace, and nLineSpace parameters.
1555 : *
1556 : * @param nBufXSize the width of the buffer image into which the desired region
1557 : * is to be read, or from which it is to be written.
1558 : *
1559 : * @param nBufYSize the height of the buffer image into which the desired
1560 : * region is to be read, or from which it is to be written.
1561 : *
1562 : * @param eBufType the type of the pixel values in the pData data buffer. The
1563 : * pixel values will automatically be translated to/from the GDALRasterBand
1564 : * data type as needed.
1565 : *
1566 : * @param nBandCount the number of bands being read or written.
1567 : *
1568 : * @param panBandMap the list of nBandCount band numbers being read/written.
1569 : * Note band numbers are 1 based. This may be NULL to select the first
1570 : * nBandCount bands.
1571 : *
1572 : * @param nPixelSpace The byte offset from the start of one pixel value in
1573 : * pData to the start of the next pixel value within a scanline. If defaulted
1574 : * (0) the size of the datatype eBufType is used.
1575 : *
1576 : * @param nLineSpace The byte offset from the start of one scanline in
1577 : * pData to the start of the next. If defaulted (0) the size of the datatype
1578 : * eBufType * nBufXSize is used.
1579 : *
1580 : * @param nBandSpace the byte offset from the start of one bands data to the
1581 : * start of the next. If defaulted (0) the value will be
1582 : * nLineSpace * nBufYSize implying band sequential organization
1583 : * of the data buffer.
1584 : *
1585 : * @return CE_Failure if the access fails, otherwise CE_None.
1586 : */
1587 :
1588 363014 : CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
1589 : int nXOff, int nYOff, int nXSize, int nYSize,
1590 : void * pData, int nBufXSize, int nBufYSize,
1591 : GDALDataType eBufType,
1592 : int nBandCount, int *panBandMap,
1593 : int nPixelSpace, int nLineSpace, int nBandSpace )
1594 :
1595 : {
1596 363014 : int i = 0;
1597 363014 : int bNeedToFreeBandMap = FALSE;
1598 363014 : CPLErr eErr = CE_None;
1599 :
1600 363014 : if( NULL == pData )
1601 : {
1602 : ReportError( CE_Failure, CPLE_AppDefined,
1603 0 : "The buffer into which the data should be read is null" );
1604 0 : return CE_Failure;
1605 : }
1606 :
1607 : /* -------------------------------------------------------------------- */
1608 : /* Some size values are "noop". Lets just return to avoid */
1609 : /* stressing lower level functions. */
1610 : /* -------------------------------------------------------------------- */
1611 363014 : if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
1612 : {
1613 : CPLDebug( "GDAL",
1614 : "RasterIO() skipped for odd window or buffer size.\n"
1615 : " Window = (%d,%d)x%dx%d\n"
1616 : " Buffer = %dx%d\n",
1617 : nXOff, nYOff, nXSize, nYSize,
1618 0 : nBufXSize, nBufYSize );
1619 :
1620 0 : return CE_None;
1621 : }
1622 :
1623 : /* -------------------------------------------------------------------- */
1624 : /* If pixel and line spaceing are defaulted assign reasonable */
1625 : /* value assuming a packed buffer. */
1626 : /* -------------------------------------------------------------------- */
1627 363014 : if( nPixelSpace == 0 )
1628 339734 : nPixelSpace = GDALGetDataTypeSize( eBufType ) / 8;
1629 :
1630 363014 : if( nLineSpace == 0 )
1631 : {
1632 356839 : if (nPixelSpace > INT_MAX / nBufXSize)
1633 : {
1634 : ReportError( CE_Failure, CPLE_AppDefined,
1635 0 : "Int overflow : %d x %d", nPixelSpace, nBufXSize );
1636 0 : return CE_Failure;
1637 : }
1638 356839 : nLineSpace = nPixelSpace * nBufXSize;
1639 : }
1640 :
1641 : /* The nBandCount > 1 test is necessary to allow reading only */
1642 : /* one band, even if the nLineSpace would overflow, but as it */
1643 : /* is not used in that case, it can be left to 0 (#3481) */
1644 363014 : if( nBandSpace == 0 && nBandCount > 1 )
1645 : {
1646 1084 : if (nLineSpace > INT_MAX / nBufYSize)
1647 : {
1648 : ReportError( CE_Failure, CPLE_AppDefined,
1649 0 : "Int overflow : %d x %d", nLineSpace, nBufYSize );
1650 0 : return CE_Failure;
1651 : }
1652 1084 : nBandSpace = nLineSpace * nBufYSize;
1653 : }
1654 :
1655 363014 : if( panBandMap == NULL )
1656 : {
1657 21579 : if (nBandCount > GetRasterCount())
1658 : {
1659 : ReportError( CE_Failure, CPLE_IllegalArg,
1660 : "nBandCount cannot be greater than %d",
1661 0 : GetRasterCount() );
1662 0 : return CE_Failure;
1663 : }
1664 21579 : panBandMap = (int *) VSIMalloc2(sizeof(int), nBandCount);
1665 21579 : if (panBandMap == NULL)
1666 : {
1667 : ReportError( CE_Failure, CPLE_OutOfMemory,
1668 0 : "Out of memory while allocating band map array" );
1669 0 : return CE_Failure;
1670 : }
1671 70533 : for( i = 0; i < nBandCount; i++ )
1672 48954 : panBandMap[i] = i+1;
1673 :
1674 21579 : bNeedToFreeBandMap = TRUE;
1675 : }
1676 :
1677 : /* -------------------------------------------------------------------- */
1678 : /* Do some validation of parameters. */
1679 : /* -------------------------------------------------------------------- */
1680 363014 : if( nXOff < 0 || nXOff > INT_MAX - nXSize || nXOff + nXSize > nRasterXSize
1681 : || nYOff < 0 || nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize )
1682 : {
1683 : ReportError( CE_Failure, CPLE_IllegalArg,
1684 : "Access window out of range in RasterIO(). Requested\n"
1685 : "(%d,%d) of size %dx%d on raster of %dx%d.",
1686 2 : nXOff, nYOff, nXSize, nYSize, nRasterXSize, nRasterYSize );
1687 2 : eErr = CE_Failure;
1688 : }
1689 :
1690 363014 : if( eRWFlag != GF_Read && eRWFlag != GF_Write )
1691 : {
1692 : ReportError( CE_Failure, CPLE_IllegalArg,
1693 : "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
1694 0 : eRWFlag );
1695 0 : eErr = CE_Failure;
1696 : }
1697 :
1698 756966 : for( i = 0; i < nBandCount && eErr == CE_None; i++ )
1699 : {
1700 393952 : if( panBandMap[i] < 1 || panBandMap[i] > GetRasterCount() )
1701 : {
1702 : ReportError( CE_Failure, CPLE_IllegalArg,
1703 : "panBandMap[%d] = %d, this band does not exist on dataset.",
1704 0 : i, panBandMap[i] );
1705 0 : eErr = CE_Failure;
1706 : }
1707 :
1708 393952 : if( eErr == CE_None && GetRasterBand( panBandMap[i] ) == NULL )
1709 : {
1710 : ReportError( CE_Failure, CPLE_IllegalArg,
1711 : "panBandMap[%d]=%d, this band should exist but is NULL!",
1712 0 : i, panBandMap[i] );
1713 0 : eErr = CE_Failure;
1714 : }
1715 : }
1716 :
1717 : /* -------------------------------------------------------------------- */
1718 : /* We are being forced to use cached IO instead of a driver */
1719 : /* specific implementation. */
1720 : /* -------------------------------------------------------------------- */
1721 363014 : if( bForceCachedIO )
1722 : {
1723 : eErr =
1724 : BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
1725 : pData, nBufXSize, nBufYSize, eBufType,
1726 : nBandCount, panBandMap,
1727 6 : nPixelSpace, nLineSpace, nBandSpace );
1728 : }
1729 :
1730 : /* -------------------------------------------------------------------- */
1731 : /* Call the format specific function. */
1732 : /* -------------------------------------------------------------------- */
1733 363008 : else if( eErr == CE_None )
1734 : {
1735 : eErr =
1736 : IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
1737 : pData, nBufXSize, nBufYSize, eBufType,
1738 : nBandCount, panBandMap,
1739 363006 : nPixelSpace, nLineSpace, nBandSpace );
1740 : }
1741 :
1742 : /* -------------------------------------------------------------------- */
1743 : /* Cleanup */
1744 : /* -------------------------------------------------------------------- */
1745 363014 : if( bNeedToFreeBandMap )
1746 21579 : CPLFree( panBandMap );
1747 :
1748 363014 : return eErr;
1749 : }
1750 :
1751 : /************************************************************************/
1752 : /* GDALDatasetRasterIO() */
1753 : /************************************************************************/
1754 :
1755 : /**
1756 : * \brief Read/write a region of image data from multiple bands.
1757 : *
1758 : * @see GDALDataset::RasterIO()
1759 : */
1760 :
1761 : CPLErr CPL_STDCALL
1762 339210 : GDALDatasetRasterIO( GDALDatasetH hDS, GDALRWFlag eRWFlag,
1763 : int nXOff, int nYOff, int nXSize, int nYSize,
1764 : void * pData, int nBufXSize, int nBufYSize,
1765 : GDALDataType eBufType,
1766 : int nBandCount, int *panBandMap,
1767 : int nPixelSpace, int nLineSpace, int nBandSpace )
1768 :
1769 : {
1770 339210 : VALIDATE_POINTER1( hDS, "GDALDatasetRasterIO", CE_Failure );
1771 :
1772 339210 : GDALDataset *poDS = (GDALDataset *) hDS;
1773 :
1774 : return( poDS->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
1775 : pData, nBufXSize, nBufYSize, eBufType,
1776 : nBandCount, panBandMap,
1777 339210 : nPixelSpace, nLineSpace, nBandSpace ) );
1778 : }
1779 :
1780 : /************************************************************************/
1781 : /* GetOpenDatasets() */
1782 : /************************************************************************/
1783 :
1784 14 : static int GDALGetOpenDatasetsForeach(void* elt, void* user_data)
1785 : {
1786 14 : int* pnIndex = (int*) user_data;
1787 14 : DatasetCtxt* psStruct = (DatasetCtxt*) elt;
1788 :
1789 14 : ppDatasets[*pnIndex] = psStruct->poDS;
1790 :
1791 14 : (*pnIndex) ++;
1792 :
1793 14 : return TRUE;
1794 : }
1795 :
1796 : /**
1797 : * \brief Fetch all open GDAL dataset handles.
1798 : *
1799 : * This method is the same as the C function GDALGetOpenDatasets().
1800 : *
1801 : * NOTE: This method is not thread safe. The returned list may change
1802 : * at any time and it should not be freed.
1803 : *
1804 : * @param pnCount integer into which to place the count of dataset pointers
1805 : * being returned.
1806 : *
1807 : * @return a pointer to an array of dataset handles.
1808 : */
1809 :
1810 1084 : GDALDataset **GDALDataset::GetOpenDatasets( int *pnCount )
1811 :
1812 : {
1813 1084 : CPLMutexHolderD( &hDLMutex );
1814 :
1815 1084 : if (phAllDatasetSet != NULL)
1816 : {
1817 2 : int nIndex = 0;
1818 2 : *pnCount = CPLHashSetSize(phAllDatasetSet);
1819 2 : ppDatasets = (GDALDataset**) CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset*));
1820 2 : CPLHashSetForeach(phAllDatasetSet, GDALGetOpenDatasetsForeach, &nIndex);
1821 2 : return ppDatasets;
1822 : }
1823 : else
1824 : {
1825 1082 : *pnCount = 0;
1826 1082 : return NULL;
1827 0 : }
1828 : }
1829 :
1830 : /************************************************************************/
1831 : /* GDALGetOpenDatasets() */
1832 : /************************************************************************/
1833 :
1834 : /**
1835 : * \brief Fetch all open GDAL dataset handles.
1836 : *
1837 : * @see GDALDataset::GetOpenDatasets()
1838 : */
1839 :
1840 0 : void CPL_STDCALL GDALGetOpenDatasets( GDALDatasetH **ppahDSList, int *pnCount )
1841 :
1842 : {
1843 0 : VALIDATE_POINTER0( ppahDSList, "GDALGetOpenDatasets" );
1844 0 : VALIDATE_POINTER0( pnCount, "GDALGetOpenDatasets" );
1845 :
1846 0 : *ppahDSList = (GDALDatasetH *) GDALDataset::GetOpenDatasets( pnCount);
1847 : }
1848 :
1849 : /************************************************************************/
1850 : /* GDALGetAccess() */
1851 : /************************************************************************/
1852 :
1853 : /**
1854 : * \brief Return access flag
1855 : *
1856 : * @see GDALDataset::GetAccess()
1857 : */
1858 :
1859 0 : int CPL_STDCALL GDALGetAccess( GDALDatasetH hDS )
1860 : {
1861 0 : VALIDATE_POINTER1( hDS, "GDALGetAccess", 0 );
1862 :
1863 0 : return ((GDALDataset *) hDS)->GetAccess();
1864 : }
1865 :
1866 : /************************************************************************/
1867 : /* AdviseRead() */
1868 : /************************************************************************/
1869 :
1870 : /**
1871 : * \brief Advise driver of upcoming read requests.
1872 : *
1873 : * Some GDAL drivers operate more efficiently if they know in advance what
1874 : * set of upcoming read requests will be made. The AdviseRead() method allows
1875 : * an application to notify the driver of the region and bands of interest,
1876 : * and at what resolution the region will be read.
1877 : *
1878 : * Many drivers just ignore the AdviseRead() call, but it can dramatically
1879 : * accelerate access via some drivers.
1880 : *
1881 : * @param nXOff The pixel offset to the top left corner of the region
1882 : * of the band to be accessed. This would be zero to start from the left side.
1883 : *
1884 : * @param nYOff The line offset to the top left corner of the region
1885 : * of the band to be accessed. This would be zero to start from the top.
1886 : *
1887 : * @param nXSize The width of the region of the band to be accessed in pixels.
1888 : *
1889 : * @param nYSize The height of the region of the band to be accessed in lines.
1890 : *
1891 : * @param nBufXSize the width of the buffer image into which the desired region
1892 : * is to be read, or from which it is to be written.
1893 : *
1894 : * @param nBufYSize the height of the buffer image into which the desired
1895 : * region is to be read, or from which it is to be written.
1896 : *
1897 : * @param eBufType the type of the pixel values in the pData data buffer. The
1898 : * pixel values will automatically be translated to/from the GDALRasterBand
1899 : * data type as needed.
1900 : *
1901 : * @param nBandCount the number of bands being read or written.
1902 : *
1903 : * @param panBandMap the list of nBandCount band numbers being read/written.
1904 : * Note band numbers are 1 based. This may be NULL to select the first
1905 : * nBandCount bands.
1906 : *
1907 : * @param papszOptions a list of name=value strings with special control
1908 : * options. Normally this is NULL.
1909 : *
1910 : * @return CE_Failure if the request is invalid and CE_None if it works or
1911 : * is ignored.
1912 : */
1913 :
1914 0 : CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
1915 : int nBufXSize, int nBufYSize,
1916 : GDALDataType eBufType,
1917 : int nBandCount, int *panBandMap,
1918 : char **papszOptions )
1919 :
1920 : {
1921 : int iBand;
1922 :
1923 0 : for( iBand = 0; iBand < nBandCount; iBand++ )
1924 : {
1925 : CPLErr eErr;
1926 : GDALRasterBand *poBand;
1927 :
1928 0 : if( panBandMap == NULL )
1929 0 : poBand = GetRasterBand(iBand+1);
1930 : else
1931 0 : poBand = GetRasterBand(panBandMap[iBand]);
1932 :
1933 : eErr = poBand->AdviseRead( nXOff, nYOff, nXSize, nYSize,
1934 0 : nBufXSize, nBufYSize, eBufType, papszOptions );
1935 :
1936 0 : if( eErr != CE_None )
1937 0 : return eErr;
1938 : }
1939 :
1940 0 : return CE_None;
1941 : }
1942 :
1943 : /************************************************************************/
1944 : /* GDALDatasetAdviseRead() */
1945 : /************************************************************************/
1946 :
1947 : /**
1948 : * \brief Advise driver of upcoming read requests.
1949 : *
1950 : * @see GDALDataset::AdviseRead()
1951 : */
1952 : CPLErr CPL_STDCALL
1953 0 : GDALDatasetAdviseRead( GDALDatasetH hDS,
1954 : int nXOff, int nYOff, int nXSize, int nYSize,
1955 : int nBufXSize, int nBufYSize, GDALDataType eDT,
1956 : int nBandCount, int *panBandMap,char **papszOptions )
1957 :
1958 : {
1959 0 : VALIDATE_POINTER1( hDS, "GDALDatasetAdviseRead", CE_Failure );
1960 :
1961 : return ((GDALDataset *) hDS)->AdviseRead( nXOff, nYOff, nXSize, nYSize,
1962 : nBufXSize, nBufYSize, eDT,
1963 : nBandCount, panBandMap,
1964 0 : papszOptions );
1965 : }
1966 :
1967 : /************************************************************************/
1968 : /* GetFileList() */
1969 : /************************************************************************/
1970 :
1971 : /**
1972 : * \brief Fetch files forming dataset.
1973 : *
1974 : * Returns a list of files believed to be part of this dataset. If it returns
1975 : * an empty list of files it means there is believed to be no local file
1976 : * system files associated with the dataset (for instance a virtual dataset).
1977 : * The returned file list is owned by the caller and should be deallocated
1978 : * with CSLDestroy().
1979 : *
1980 : * The returned filenames will normally be relative or absolute paths
1981 : * depending on the path used to originally open the dataset. The strings
1982 : * will be UTF-8 encoded.
1983 : *
1984 : * This method is the same as the C GDALGetFileList() function.
1985 : *
1986 : * @return NULL or a NULL terminated array of file names.
1987 : */
1988 :
1989 1575 : char **GDALDataset::GetFileList()
1990 :
1991 : {
1992 1575 : CPLString osMainFilename = GetDescription();
1993 : int bMainFileReal;
1994 : VSIStatBufL sStat;
1995 :
1996 : /* -------------------------------------------------------------------- */
1997 : /* Is the main filename even a real filesystem object? */
1998 : /* -------------------------------------------------------------------- */
1999 1575 : bMainFileReal = VSIStatExL( osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG ) == 0;
2000 :
2001 : /* -------------------------------------------------------------------- */
2002 : /* Form new list. */
2003 : /* -------------------------------------------------------------------- */
2004 1575 : char **papszList = NULL;
2005 :
2006 1575 : if( bMainFileReal )
2007 1568 : papszList = CSLAddString( papszList, osMainFilename );
2008 :
2009 : /* -------------------------------------------------------------------- */
2010 : /* Do we have a known overview file? */
2011 : /* -------------------------------------------------------------------- */
2012 1575 : if( oOvManager.IsInitialized() && oOvManager.poODS != NULL )
2013 : {
2014 66 : char **papszOvrList = oOvManager.poODS->GetFileList();
2015 66 : papszList = CSLInsertStrings( papszList, -1, papszOvrList );
2016 66 : CSLDestroy( papszOvrList );
2017 : }
2018 :
2019 : /* -------------------------------------------------------------------- */
2020 : /* Do we have a known overview file? */
2021 : /* -------------------------------------------------------------------- */
2022 1575 : if( oOvManager.HaveMaskFile() )
2023 : {
2024 5 : char **papszMskList = oOvManager.poMaskDS->GetFileList();
2025 5 : papszList = CSLInsertStrings( papszList, -1, papszMskList );
2026 5 : CSLDestroy( papszMskList );
2027 : }
2028 :
2029 : /* -------------------------------------------------------------------- */
2030 : /* Do we have a world file? */
2031 : /* -------------------------------------------------------------------- */
2032 1575 : if( bMainFileReal )
2033 : {
2034 1568 : const char* pszExtension = CPLGetExtension( osMainFilename );
2035 1568 : if( strlen(pszExtension) > 2 )
2036 : {
2037 : // first + last + 'w'
2038 : char szDerivedExtension[4];
2039 1560 : szDerivedExtension[0] = pszExtension[0];
2040 1560 : szDerivedExtension[1] = pszExtension[strlen(pszExtension)-1];
2041 1560 : szDerivedExtension[2] = 'w';
2042 1560 : szDerivedExtension[3] = '\0';
2043 1560 : CPLString osWorldFilename = CPLResetExtension( osMainFilename, szDerivedExtension );
2044 :
2045 1560 : if (oOvManager.papszInitSiblingFiles)
2046 : {
2047 : int iSibling = CSLFindString(oOvManager.papszInitSiblingFiles,
2048 1038 : CPLGetFilename(osWorldFilename));
2049 1038 : if (iSibling >= 0)
2050 : {
2051 : osWorldFilename.resize(strlen(osWorldFilename) -
2052 2 : strlen(oOvManager.papszInitSiblingFiles[iSibling]));
2053 2 : osWorldFilename += oOvManager.papszInitSiblingFiles[iSibling];
2054 2 : papszList = CSLAddString( papszList, osWorldFilename );
2055 : }
2056 : }
2057 522 : else if( VSIStatExL( osWorldFilename, &sStat, VSI_STAT_EXISTS_FLAG ) == 0 )
2058 1 : papszList = CSLAddString( papszList, osWorldFilename );
2059 : }
2060 : }
2061 :
2062 1575 : return papszList;
2063 : }
2064 :
2065 : /************************************************************************/
2066 : /* GDALGetFileList() */
2067 : /************************************************************************/
2068 :
2069 : /**
2070 : * \brief Fetch files forming dataset.
2071 : *
2072 : * @see GDALDataset::GetFileList()
2073 : */
2074 :
2075 1483 : char ** CPL_STDCALL GDALGetFileList( GDALDatasetH hDS )
2076 :
2077 : {
2078 1483 : VALIDATE_POINTER1( hDS, "GDALGetFileList", NULL );
2079 :
2080 1483 : return ((GDALDataset *) hDS)->GetFileList();
2081 : }
2082 :
2083 : /************************************************************************/
2084 : /* CreateMaskBand() */
2085 : /************************************************************************/
2086 :
2087 : /**
2088 : * \brief Adds a mask band to the dataset
2089 : *
2090 : * The default implementation of the CreateMaskBand() method is implemented
2091 : * based on similar rules to the .ovr handling implemented using the
2092 : * GDALDefaultOverviews object. A TIFF file with the extension .msk will
2093 : * be created with the same basename as the original file, and it will have
2094 : * one band.
2095 : * The mask images will be deflate compressed tiled images with the same
2096 : * block size as the original image if possible.
2097 : *
2098 : * Note that if you got a mask band with a previous call to GetMaskBand(),
2099 : * it might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
2100 : * again.
2101 : *
2102 : * @since GDAL 1.5.0
2103 : *
2104 : * @param nFlags ignored. GMF_PER_DATASET will be assumed.
2105 : * @return CE_None on success or CE_Failure on an error.
2106 : *
2107 : * @see http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask
2108 : *
2109 : */
2110 5 : CPLErr GDALDataset::CreateMaskBand( int nFlags )
2111 :
2112 : {
2113 5 : if( oOvManager.IsInitialized() )
2114 : {
2115 5 : CPLErr eErr = oOvManager.CreateMaskBand( nFlags, -1 );
2116 5 : if (eErr != CE_None)
2117 0 : return eErr;
2118 :
2119 : /* Invalidate existing raster band masks */
2120 : int i;
2121 16 : for(i=0;i<nBands;i++)
2122 : {
2123 11 : GDALRasterBand* poBand = papoBands[i];
2124 11 : if (poBand->bOwnMask)
2125 1 : delete poBand->poMask;
2126 11 : poBand->bOwnMask = false;
2127 11 : poBand->poMask = NULL;
2128 : }
2129 :
2130 5 : return CE_None;
2131 : }
2132 :
2133 : ReportError( CE_Failure, CPLE_NotSupported,
2134 0 : "CreateMaskBand() not supported for this dataset." );
2135 :
2136 0 : return( CE_Failure );
2137 : }
2138 :
2139 : /************************************************************************/
2140 : /* GDALCreateDatasetMaskBand() */
2141 : /************************************************************************/
2142 :
2143 : /**
2144 : * \brief Adds a mask band to the dataset
2145 : * @see GDALDataset::CreateMaskBand()
2146 : */
2147 19 : CPLErr CPL_STDCALL GDALCreateDatasetMaskBand( GDALDatasetH hDS, int nFlags )
2148 :
2149 : {
2150 19 : VALIDATE_POINTER1( hDS, "GDALCreateDatasetMaskBand", CE_Failure );
2151 :
2152 19 : return ((GDALDataset *) hDS)->CreateMaskBand( nFlags );
2153 : }
2154 :
2155 : /************************************************************************/
2156 : /* GDALOpen() */
2157 : /************************************************************************/
2158 :
2159 : /**
2160 : * \brief Open a raster file as a GDALDataset.
2161 : *
2162 : * This function will try to open the passed file, or virtual dataset
2163 : * name by invoking the Open method of each registered GDALDriver in turn.
2164 : * The first successful open will result in a returned dataset. If all
2165 : * drivers fail then NULL is returned and an error is issued.
2166 : *
2167 : * Several recommandations :
2168 : * <ul>
2169 : * <li>If you open a dataset object with GA_Update access, it is not recommanded
2170 : * to open a new dataset on the same underlying file.</li>
2171 : * <li>The returned dataset should only be accessed by one thread at a time. If you
2172 : * want to use it from different threads, you must add all necessary code (mutexes, etc.)
2173 : * to avoid concurrent use of the object. (Some drivers, such as GeoTIFF, maintain internal
2174 : * state variables that are updated each time a new block is read, thus preventing concurrent
2175 : * use.) </li>
2176 : * </ul>
2177 : *
2178 : * For drivers supporting the VSI virtual file API, it is possible to open
2179 : * a file in a .zip archive (see VSIInstallZipFileHandler()), in a .tar/.tar.gz/.tgz archive
2180 : * (see VSIInstallTarFileHandler()) or on a HTTP / FTP server (see VSIInstallCurlFileHandler())
2181 : *
2182 : * \sa GDALOpenShared()
2183 : *
2184 : * @param pszFilename the name of the file to access. In the case of
2185 : * exotic drivers this may not refer to a physical file, but instead contain
2186 : * information for the driver on how to access a dataset. It should be in UTF-8
2187 : * encoding.
2188 : *
2189 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
2190 : * drivers support only read only access.
2191 : *
2192 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
2193 : * this handle can be cast to a GDALDataset *.
2194 : */
2195 :
2196 : GDALDatasetH CPL_STDCALL
2197 9048 : GDALOpen( const char * pszFilename, GDALAccess eAccess )
2198 :
2199 : {
2200 9048 : return GDALOpenInternal(pszFilename, eAccess, NULL);
2201 : }
2202 :
2203 : /* The drivers listed in papszAllowedDrivers can be in any order */
2204 : /* Only the order of registration will be taken into account */
2205 9076 : GDALDatasetH GDALOpenInternal( const char * pszFilename, GDALAccess eAccess,
2206 : const char* const * papszAllowedDrivers)
2207 : {
2208 9076 : GDALOpenInfo oOpenInfo( pszFilename, eAccess );
2209 9076 : return GDALOpenInternal(oOpenInfo, papszAllowedDrivers);
2210 : }
2211 :
2212 713 : static std::map<GIntBig, int> oRecProtectorMap;
2213 :
2214 9192 : GDALDatasetH GDALOpenInternal( GDALOpenInfo& oOpenInfo,
2215 : const char* const * papszAllowedDrivers)
2216 : {
2217 :
2218 9192 : VALIDATE_POINTER1( oOpenInfo.pszFilename, "GDALOpen", NULL );
2219 :
2220 9192 : GIntBig nPID = CPLGetPID();
2221 : {
2222 9192 : CPLMutexHolderD( &hDLMutex );
2223 9192 : if( oRecProtectorMap[nPID] == 100 )
2224 : {
2225 : CPLError(CE_Failure, CPLE_AppDefined,
2226 1 : "GDALOpen() called with too many recursion levels");
2227 1 : return NULL;
2228 : }
2229 9191 : oRecProtectorMap[nPID] ++;
2230 : }
2231 :
2232 : int iDriver;
2233 9191 : GDALDriverManager *poDM = GetGDALDriverManager();
2234 9191 : CPLLocaleC oLocaleForcer;
2235 :
2236 9191 : CPLErrorReset();
2237 9191 : CPLAssert( NULL != poDM );
2238 :
2239 346208 : for( iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++ )
2240 : {
2241 344995 : GDALDriver *poDriver = poDM->GetDriver( iDriver );
2242 : GDALDataset *poDS;
2243 :
2244 344995 : if (papszAllowedDrivers != NULL &&
2245 : CSLFindString((char**)papszAllowedDrivers, GDALGetDriverShortName(poDriver)) == -1)
2246 2858 : continue;
2247 :
2248 342137 : if ( poDriver->pfnOpen == NULL )
2249 0 : continue;
2250 :
2251 342137 : poDS = poDriver->pfnOpen( &oOpenInfo );
2252 342137 : if( poDS != NULL )
2253 : {
2254 7814 : if( strlen(poDS->GetDescription()) == 0 )
2255 583 : poDS->SetDescription( oOpenInfo.pszFilename );
2256 :
2257 7814 : if( poDS->poDriver == NULL )
2258 6793 : poDS->poDriver = poDriver;
2259 :
2260 :
2261 7814 : if( CPLGetPID() != GDALGetResponsiblePIDForCurrentThread() )
2262 : CPLDebug( "GDAL", "GDALOpen(%s, this=%p) succeeds as %s (pid=%d, responsiblePID=%d).",
2263 0 : oOpenInfo.pszFilename, poDS, poDriver->GetDescription(),
2264 0 : (int)CPLGetPID(), (int)GDALGetResponsiblePIDForCurrentThread() );
2265 : else
2266 : CPLDebug( "GDAL", "GDALOpen(%s, this=%p) succeeds as %s.",
2267 7814 : oOpenInfo.pszFilename, poDS, poDriver->GetDescription() );
2268 :
2269 : {
2270 7814 : CPLMutexHolderD( &hDLMutex );
2271 7814 : oRecProtectorMap[nPID] --;
2272 : }
2273 7814 : return (GDALDatasetH) poDS;
2274 : }
2275 :
2276 334323 : if( CPLGetLastErrorNo() != 0 )
2277 : {
2278 : {
2279 164 : CPLMutexHolderD( &hDLMutex );
2280 164 : oRecProtectorMap[nPID] --;
2281 : }
2282 164 : return NULL;
2283 : }
2284 : }
2285 :
2286 1213 : if( oOpenInfo.bStatOK )
2287 : CPLError( CE_Failure, CPLE_OpenFailed,
2288 : "`%s' not recognised as a supported file format.\n",
2289 72 : oOpenInfo.pszFilename );
2290 : else
2291 : CPLError( CE_Failure, CPLE_OpenFailed,
2292 : "`%s' does not exist in the file system,\n"
2293 : "and is not recognised as a supported dataset name.\n",
2294 1141 : oOpenInfo.pszFilename );
2295 :
2296 : {
2297 1213 : CPLMutexHolderD( &hDLMutex );
2298 1213 : oRecProtectorMap[nPID] --;
2299 : }
2300 1213 : return NULL;
2301 : }
2302 :
2303 : /************************************************************************/
2304 : /* GDALOpenShared() */
2305 : /************************************************************************/
2306 :
2307 : /**
2308 : * \brief Open a raster file as a GDALDataset.
2309 : *
2310 : * This function works the same as GDALOpen(), but allows the sharing of
2311 : * GDALDataset handles for a dataset with other callers to GDALOpenShared().
2312 : *
2313 : * In particular, GDALOpenShared() will first consult it's list of currently
2314 : * open and shared GDALDataset's, and if the GetDescription() name for one
2315 : * exactly matches the pszFilename passed to GDALOpenShared() it will be
2316 : * referenced and returned.
2317 : *
2318 : * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same pszFilename
2319 : * from two different threads, a different GDALDataset object will be returned as
2320 : * it is not safe to use the same dataset from different threads, unless the user
2321 : * does explicitely use mutexes in its code.
2322 : *
2323 : * For drivers supporting the VSI virtual file API, it is possible to open
2324 : * a file in a .zip archive (see VSIInstallZipFileHandler()), in a .tar/.tar.gz/.tgz archive
2325 : * (see VSIInstallTarFileHandler()) or on a HTTP / FTP server (see VSIInstallCurlFileHandler())
2326 : *
2327 : * \sa GDALOpen()
2328 : *
2329 : * @param pszFilename the name of the file to access. In the case of
2330 : * exotic drivers this may not refer to a physical file, but instead contain
2331 : * information for the driver on how to access a dataset. It should be in
2332 : * UTF-8 encoding.
2333 : *
2334 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
2335 : * drivers support only read only access.
2336 : *
2337 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
2338 : * this handle can be cast to a GDALDataset *.
2339 : */
2340 :
2341 : GDALDatasetH CPL_STDCALL
2342 5448 : GDALOpenShared( const char *pszFilename, GDALAccess eAccess )
2343 :
2344 : {
2345 5448 : VALIDATE_POINTER1( pszFilename, "GDALOpenShared", NULL );
2346 :
2347 : /* -------------------------------------------------------------------- */
2348 : /* First scan the existing list to see if it could already */
2349 : /* contain the requested dataset. */
2350 : /* -------------------------------------------------------------------- */
2351 : {
2352 5448 : CPLMutexHolderD( &hDLMutex );
2353 :
2354 5448 : if (phSharedDatasetSet != NULL)
2355 : {
2356 5194 : GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
2357 : SharedDatasetCtxt* psStruct;
2358 : SharedDatasetCtxt sStruct;
2359 :
2360 5194 : sStruct.nPID = nThisPID;
2361 5194 : sStruct.pszDescription = (char*) pszFilename;
2362 5194 : sStruct.eAccess = eAccess;
2363 5194 : psStruct = (SharedDatasetCtxt*) CPLHashSetLookup(phSharedDatasetSet, &sStruct);
2364 5194 : if (psStruct == NULL && eAccess == GA_ReadOnly)
2365 : {
2366 138 : sStruct.eAccess = GA_Update;
2367 138 : psStruct = (SharedDatasetCtxt*) CPLHashSetLookup(phSharedDatasetSet, &sStruct);
2368 : }
2369 5194 : if (psStruct)
2370 : {
2371 5056 : psStruct->poDS->Reference();
2372 5056 : return psStruct->poDS;
2373 : }
2374 0 : }
2375 : }
2376 :
2377 : /* -------------------------------------------------------------------- */
2378 : /* Try opening the the requested dataset. */
2379 : /* -------------------------------------------------------------------- */
2380 : GDALDataset *poDataset;
2381 :
2382 392 : poDataset = (GDALDataset *) GDALOpen( pszFilename, eAccess );
2383 392 : if( poDataset != NULL )
2384 : {
2385 291 : if (strcmp(pszFilename, poDataset->GetDescription()) != 0)
2386 : {
2387 : CPLError(CE_Warning, CPLE_NotSupported,
2388 : "A dataset opened by GDALOpenShared should have the same filename (%s) "
2389 : "and description (%s)",
2390 2 : pszFilename, poDataset->GetDescription());
2391 : }
2392 : else
2393 : {
2394 289 : poDataset->MarkAsShared();
2395 : }
2396 : }
2397 :
2398 392 : return (GDALDatasetH) poDataset;
2399 : }
2400 :
2401 : /************************************************************************/
2402 : /* GDALClose() */
2403 : /************************************************************************/
2404 :
2405 : /**
2406 : * \brief Close GDAL dataset.
2407 : *
2408 : * For non-shared datasets (opened with GDALOpen()) the dataset is closed
2409 : * using the C++ "delete" operator, recovering all dataset related resources.
2410 : * For shared datasets (opened with GDALOpenShared()) the dataset is
2411 : * dereferenced, and closed only if the referenced count has dropped below 1.
2412 : *
2413 : * @param hDS The dataset to close. May be cast from a "GDALDataset *".
2414 : */
2415 :
2416 18181 : void CPL_STDCALL GDALClose( GDALDatasetH hDS )
2417 :
2418 : {
2419 18181 : VALIDATE_POINTER0( hDS, "GDALClose" );
2420 :
2421 18181 : GDALDataset *poDS = (GDALDataset *) hDS;
2422 18181 : CPLMutexHolderD( &hDLMutex );
2423 18181 : CPLLocaleC oLocaleForcer;
2424 :
2425 18181 : if (poDS->GetShared())
2426 : {
2427 : /* -------------------------------------------------------------------- */
2428 : /* If this file is in the shared dataset list then dereference */
2429 : /* it, and only delete/remote it if the reference count has */
2430 : /* dropped to zero. */
2431 : /* -------------------------------------------------------------------- */
2432 3980 : if( poDS->Dereference() > 0 )
2433 : return;
2434 :
2435 594 : delete poDS;
2436 : return;
2437 : }
2438 :
2439 : /* -------------------------------------------------------------------- */
2440 : /* This is not shared dataset, so directly delete it. */
2441 : /* -------------------------------------------------------------------- */
2442 14201 : delete poDS;
2443 : }
2444 :
2445 : /************************************************************************/
2446 : /* GDALDumpOpenDataset() */
2447 : /************************************************************************/
2448 :
2449 0 : static int GDALDumpOpenSharedDatasetsForeach(void* elt, void* user_data)
2450 : {
2451 0 : SharedDatasetCtxt* psStruct = (SharedDatasetCtxt*) elt;
2452 0 : FILE *fp = (FILE*) user_data;
2453 : const char *pszDriverName;
2454 0 : GDALDataset *poDS = psStruct->poDS;
2455 :
2456 0 : if( poDS->GetDriver() == NULL )
2457 0 : pszDriverName = "DriverIsNULL";
2458 : else
2459 0 : pszDriverName = poDS->GetDriver()->GetDescription();
2460 :
2461 0 : poDS->Reference();
2462 : VSIFPrintf( fp, " %d %c %-6s %7d %dx%dx%d %s\n",
2463 : poDS->Dereference(),
2464 : poDS->GetShared() ? 'S' : 'N',
2465 : pszDriverName,
2466 : (int)psStruct->nPID,
2467 : poDS->GetRasterXSize(),
2468 : poDS->GetRasterYSize(),
2469 : poDS->GetRasterCount(),
2470 0 : poDS->GetDescription() );
2471 :
2472 0 : return TRUE;
2473 : }
2474 :
2475 :
2476 0 : static int GDALDumpOpenDatasetsForeach(void* elt, void* user_data)
2477 : {
2478 0 : DatasetCtxt* psStruct = (DatasetCtxt*) elt;
2479 0 : FILE *fp = (FILE*) user_data;
2480 : const char *pszDriverName;
2481 0 : GDALDataset *poDS = psStruct->poDS;
2482 :
2483 : /* Don't list shared datasets. They have already been listed by */
2484 : /* GDALDumpOpenSharedDatasetsForeach */
2485 0 : if (poDS->GetShared())
2486 0 : return TRUE;
2487 :
2488 0 : if( poDS->GetDriver() == NULL )
2489 0 : pszDriverName = "DriverIsNULL";
2490 : else
2491 0 : pszDriverName = poDS->GetDriver()->GetDescription();
2492 :
2493 0 : poDS->Reference();
2494 : VSIFPrintf( fp, " %d %c %-6s %7d %dx%dx%d %s\n",
2495 : poDS->Dereference(),
2496 : poDS->GetShared() ? 'S' : 'N',
2497 : pszDriverName,
2498 : -1,
2499 : poDS->GetRasterXSize(),
2500 : poDS->GetRasterYSize(),
2501 : poDS->GetRasterCount(),
2502 0 : poDS->GetDescription() );
2503 :
2504 0 : return TRUE;
2505 : }
2506 :
2507 : /**
2508 : * \brief List open datasets.
2509 : *
2510 : * Dumps a list of all open datasets (shared or not) to the indicated
2511 : * text file (may be stdout or stderr). This function is primariliy intended
2512 : * to assist in debugging "dataset leaks" and reference counting issues.
2513 : * The information reported includes the dataset name, referenced count,
2514 : * shared status, driver name, size, and band count.
2515 : */
2516 :
2517 458 : int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp )
2518 :
2519 : {
2520 458 : VALIDATE_POINTER1( fp, "GDALDumpOpenDatasets", 0 );
2521 :
2522 458 : CPLMutexHolderD( &hDLMutex );
2523 :
2524 458 : if (phAllDatasetSet != NULL)
2525 : {
2526 0 : VSIFPrintf( fp, "Open GDAL Datasets:\n" );
2527 0 : CPLHashSetForeach(phAllDatasetSet, GDALDumpOpenDatasetsForeach, fp);
2528 0 : if (phSharedDatasetSet != NULL)
2529 : {
2530 0 : CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach, fp);
2531 : }
2532 0 : return CPLHashSetSize(phAllDatasetSet);
2533 : }
2534 : else
2535 : {
2536 458 : return 0;
2537 0 : }
2538 : }
2539 :
2540 : /************************************************************************/
2541 : /* BeginAsyncReader() */
2542 : /************************************************************************/
2543 :
2544 : /**
2545 : * \brief Sets up an asynchronous data request
2546 : *
2547 : * This method establish an asynchronous raster read request for the
2548 : * indicated window on the dataset into the indicated buffer. The parameters
2549 : * for windowing, buffer size, buffer type and buffer organization are similar
2550 : * to those for GDALDataset::RasterIO(); however, this call only launches
2551 : * the request and filling the buffer is accomplished via calls to
2552 : * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
2553 : *
2554 : * Once all processing for the created session is complete, or if no further
2555 : * refinement of the request is required, the GDALAsyncReader object should
2556 : * be destroyed with the GDALDataset::EndAsyncReader() method.
2557 : *
2558 : * Note that the data buffer (pData) will potentially continue to be
2559 : * updated as long as the session lives, but it is not deallocated when
2560 : * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It
2561 : * should be deallocated by the application at that point.
2562 : *
2563 : * Additional information on asynchronous IO in GDAL may be found at:
2564 : * http://trac.osgeo.org/gdal/wiki/rfc24_progressive_data_support
2565 : *
2566 : * This method is the same as the C GDALBeginAsyncReader() function.
2567 : *
2568 : * @param nXOff The pixel offset to the top left corner of the region
2569 : * of the band to be accessed. This would be zero to start from the left side.
2570 : *
2571 : * @param nYOff The line offset to the top left corner of the region
2572 : * of the band to be accessed. This would be zero to start from the top.
2573 : *
2574 : * @param nXSize The width of the region of the band to be accessed in pixels.
2575 : *
2576 : * @param nYSize The height of the region of the band to be accessed in lines.
2577 : *
2578 : * @param pBuf The buffer into which the data should be read. This buffer must
2579 : * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
2580 : * It is organized in left to right,top to bottom pixel order. Spacing is
2581 : * controlled by the nPixelSpace, and nLineSpace parameters.
2582 : *
2583 : * @param nBufXSize the width of the buffer image into which the desired region
2584 : * is to be read, or from which it is to be written.
2585 : *
2586 : * @param nBufYSize the height of the buffer image into which the desired
2587 : * region is to be read, or from which it is to be written.
2588 : *
2589 : * @param eBufType the type of the pixel values in the pData data buffer. The
2590 : * pixel values will automatically be translated to/from the GDALRasterBand
2591 : * data type as needed.
2592 : *
2593 : * @param nBandCount the number of bands being read or written.
2594 : *
2595 : * @param panBandMap the list of nBandCount band numbers being read/written.
2596 : * Note band numbers are 1 based. This may be NULL to select the first
2597 : * nBandCount bands.
2598 : *
2599 : * @param nPixelSpace The byte offset from the start of one pixel value in
2600 : * pData to the start of the next pixel value within a scanline. If defaulted
2601 : * (0) the size of the datatype eBufType is used.
2602 : *
2603 : * @param nLineSpace The byte offset from the start of one scanline in
2604 : * pData to the start of the next. If defaulted the size of the datatype
2605 : * eBufType * nBufXSize is used.
2606 : *
2607 : * @param nBandSpace the byte offset from the start of one bands data to the
2608 : * start of the next. If defaulted (zero) the value will be
2609 : * nLineSpace * nBufYSize implying band sequential organization
2610 : * of the data buffer.
2611 : *
2612 : * @param papszOptions Driver specific control options in a string list or NULL.
2613 : * Consult driver documentation for options supported.
2614 : *
2615 : * @return The GDALAsyncReader object representing the request.
2616 : */
2617 :
2618 : GDALAsyncReader*
2619 1 : GDALDataset::BeginAsyncReader(int nXOff, int nYOff,
2620 : int nXSize, int nYSize,
2621 : void *pBuf,
2622 : int nBufXSize, int nBufYSize,
2623 : GDALDataType eBufType,
2624 : int nBandCount, int* panBandMap,
2625 : int nPixelSpace, int nLineSpace,
2626 : int nBandSpace, char **papszOptions)
2627 : {
2628 : // See gdaldefaultasync.cpp
2629 :
2630 : return
2631 : GDALGetDefaultAsyncReader( this,
2632 : nXOff, nYOff, nXSize, nYSize,
2633 : pBuf, nBufXSize, nBufYSize, eBufType,
2634 : nBandCount, panBandMap,
2635 : nPixelSpace, nLineSpace, nBandSpace,
2636 1 : papszOptions );
2637 : }
2638 :
2639 : /************************************************************************/
2640 : /* GDALBeginAsyncReader() */
2641 : /************************************************************************/
2642 :
2643 : GDALAsyncReaderH CPL_STDCALL
2644 1 : GDALBeginAsyncReader(GDALDatasetH hDS, int xOff, int yOff,
2645 : int xSize, int ySize,
2646 : void *pBuf,
2647 : int bufXSize, int bufYSize,
2648 : GDALDataType bufType,
2649 : int nBandCount, int* bandMap,
2650 : int nPixelSpace, int nLineSpace,
2651 : int nBandSpace,
2652 : char **papszOptions)
2653 :
2654 : {
2655 1 : VALIDATE_POINTER1( hDS, "GDALDataset", NULL );
2656 : return (GDALAsyncReaderH)((GDALDataset *) hDS)->
2657 : BeginAsyncReader(xOff, yOff,
2658 : xSize, ySize,
2659 : pBuf, bufXSize, bufYSize,
2660 : bufType, nBandCount, bandMap,
2661 : nPixelSpace, nLineSpace,
2662 1 : nBandSpace, papszOptions);
2663 : }
2664 :
2665 : /************************************************************************/
2666 : /* EndAsyncReader() */
2667 : /************************************************************************/
2668 :
2669 : /**
2670 : * End asynchronous request.
2671 : *
2672 : * This method destroys an asynchronous io request and recovers all
2673 : * resources associated with it.
2674 : *
2675 : * This method is the same as the C function GDALEndAsyncReader().
2676 : *
2677 : * @param poARIO pointer to a GDALAsyncReader
2678 : */
2679 :
2680 1 : void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO )
2681 : {
2682 1 : delete poARIO;
2683 1 : }
2684 :
2685 : /************************************************************************/
2686 : /* GDALEndAsyncReader() */
2687 : /************************************************************************/
2688 1 : void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS, GDALAsyncReaderH hAsyncReaderH)
2689 : {
2690 1 : VALIDATE_POINTER0( hDS, "GDALDataset" );
2691 1 : VALIDATE_POINTER0( hAsyncReaderH, "GDALAsyncReader" );
2692 1 : ((GDALDataset *) hDS) -> EndAsyncReader((GDALAsyncReader *)hAsyncReaderH);
2693 : }
2694 :
2695 : /************************************************************************/
2696 : /* CloseDependentDatasets() */
2697 : /************************************************************************/
2698 :
2699 : /**
2700 : * Drop references to any other datasets referenced by this dataset.
2701 : *
2702 : * This method should release any reference to other datasets (e.g. a VRT
2703 : * dataset to its sources), but not close the current dataset itself.
2704 : *
2705 : * If at least, one reference to a dependant dataset has been dropped,
2706 : * this method should return TRUE. Otherwise it *should* return FALSE.
2707 : * (Failure to return the proper value might result in infinite loop)
2708 : *
2709 : * This method can be called several times on a given dataset. After
2710 : * the first time, it should not do anything and return FALSE.
2711 : *
2712 : * The driver implementation may choose to destroy its raster bands,
2713 : * so be careful not to call any method on the raster bands afterwards.
2714 : *
2715 : * Basically the only safe action you can do after calling CloseDependantDatasets()
2716 : * is to call the destructor.
2717 : *
2718 : * Note: the only legitimate caller of CloseDependantDatasets() is
2719 : * GDALDriverManager::~GDALDriverManager()
2720 : *
2721 : * @return TRUE if at least one reference to another dataset has been dropped.
2722 : */
2723 1170 : int GDALDataset::CloseDependentDatasets()
2724 : {
2725 1170 : return oOvManager.CloseDependentDatasets();
2726 : }
2727 :
2728 : /************************************************************************/
2729 : /* ReportError() */
2730 : /************************************************************************/
2731 :
2732 : /**
2733 : * \brief Emits an error related to a dataset.
2734 : *
2735 : * This function is a wrapper for regular CPLError(). The only difference
2736 : * with CPLError() is that it prepends the error message with the dataset
2737 : * name.
2738 : *
2739 : * @param eErrClass one of CE_Warning, CE_Failure or CE_Fatal.
2740 : * @param err_no the error number (CPLE_*) from cpl_error.h.
2741 : * @param fmt a printf() style format string. Any additional arguments
2742 : * will be treated as arguments to fill in this format in a manner
2743 : * similar to printf().
2744 : *
2745 : * @since GDAL 1.9.0
2746 : */
2747 :
2748 2 : void GDALDataset::ReportError(CPLErr eErrClass, int err_no, const char *fmt, ...)
2749 : {
2750 : va_list args;
2751 :
2752 2 : va_start(args, fmt);
2753 :
2754 : char szNewFmt[256];
2755 2 : const char* pszDSName = GetDescription();
2756 2 : if (strlen(fmt) + strlen(pszDSName) + 3 >= sizeof(szNewFmt) - 1)
2757 0 : pszDSName = CPLGetFilename(pszDSName);
2758 3 : if (pszDSName[0] != '\0' &&
2759 : strlen(fmt) + strlen(pszDSName) + 3 < sizeof(szNewFmt) - 1)
2760 : {
2761 : snprintf(szNewFmt, sizeof(szNewFmt), "%s: %s",
2762 1 : pszDSName, fmt);
2763 1 : CPLErrorV( eErrClass, err_no, szNewFmt, args );
2764 : }
2765 : else
2766 : {
2767 1 : CPLErrorV( eErrClass, err_no, fmt, args );
2768 : }
2769 2 : va_end(args);
2770 2141 : }
|