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