root/tags/gdal_1_2_3/gcore/gdalopen.cpp

Revision 5930, 14.2 kB (checked in by warmerda, 5 years ago)

Avoid size_t casting warnings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /******************************************************************************
2  * $Id$
3  *
4  * Project:  GDAL Core
5  * Purpose:  Implementation of GDALOpen(), GDALOpenShared(), GDALOpenInfo and
6  *           related services.
7  * Author:   Frank Warmerdam, warmerdam@pobox.com
8  *
9  **********************************************************************
10  * Copyright (c) 2002, Frank Warmerdam
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included
20  * in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  * DEALINGS IN THE SOFTWARE.
29  ******************************************************************************
30  *
31  * $Log$
32  * Revision 1.20  2004/03/10 18:06:11  warmerda
33  * Avoid size_t casting warnings.
34  *
35  * Revision 1.19  2003/04/30 17:13:48  warmerda
36  * added docs for many C functions
37  *
38  * Revision 1.18  2003/02/03 05:09:31  warmerda
39  * populate GDALOpenInfo header data using large file API if needed
40  *
41  * Revision 1.17  2002/07/09 20:33:12  warmerda
42  * expand tabs
43  *
44  * Revision 1.16  2002/06/19 18:20:21  warmerda
45  * use VSIStatL() so it works on large files, dont keep stat in openinfo.
46  *
47  * Revision 1.15  2002/06/15 00:07:23  aubin
48  * mods to enable 64bit file i/o
49  *
50  * Revision 1.14  2002/06/12 21:13:27  warmerda
51  * use metadata based driver info
52  *
53  * Revision 1.13  2002/05/28 18:56:22  warmerda
54  * added shared dataset concept
55  *
56  * Revision 1.12  2001/12/12 17:21:21  warmerda
57  * Use CPLStat instead of VSIStat().
58  *
59  * Revision 1.11  2001/08/20 13:40:28  warmerda
60  * modified message on failure to open if not a file
61  *
62  * Revision 1.10  2001/07/18 04:04:30  warmerda
63  * added CPL_CVSID
64  *
65  * Revision 1.9  2001/01/03 05:32:20  warmerda
66  * avoid depending on VSIStatBuf file size for 2GB issues
67  *
68  * Revision 1.8  2000/04/21 21:55:53  warmerda
69  * set filename as description of GDALDatasets.
70  *
71  * Revision 1.7  2000/01/10 15:43:06  warmerda
72  * Fixed debug statement.
73  *
74  * Revision 1.6  2000/01/10 15:31:02  warmerda
75  * Added debug statement in GDALOpen.
76  *
77  * Revision 1.5  1999/11/11 21:59:07  warmerda
78  * added GetDriver() for datasets
79  *
80  * Revision 1.4  1999/10/01 14:44:02  warmerda
81  * added documentation
82  *
83  * Revision 1.3  1999/04/21 04:00:34  warmerda
84  * Initialize fp to NULL.
85  *
86  * Revision 1.2  1998/12/31 18:52:45  warmerda
87  * Use CPL memory functions (they are safe), and fixed up header reading.
88  *
89  * Revision 1.1  1998/12/03 18:31:45  warmerda
90  * New
91  *
92  */
93
94 #include "gdal_priv.h"
95 #include "cpl_conv.h"
96
97 CPL_CVSID("$Id$");
98
99 /************************************************************************/
100 /* ==================================================================== */
101 /*                             GDALOpenInfo                             */
102 /* ==================================================================== */
103 /************************************************************************/
104
105 /************************************************************************/
106 /*                            GDALOpenInfo()                            */
107 /************************************************************************/
108
109 GDALOpenInfo::GDALOpenInfo( const char * pszFilenameIn, GDALAccess eAccessIn )
110
111 {
112 /* -------------------------------------------------------------------- */
113 /*      Ensure that C: is treated as C:\ so we can stat it on           */
114 /*      Windows.  Similar to what is done in CPLStat().                 */
115 /* -------------------------------------------------------------------- */
116 #ifdef WIN32
117     if( strlen(pszFilenameIn) == 2 && pszFilenameIn[1] == ':' )
118     {
119         char    szAltPath[10];
120        
121         strcpy( szAltPath, pszFilenameIn );
122         strcat( szAltPath, "\\" );
123         pszFilename = CPLStrdup( szAltPath );
124     }
125     else
126 #endif
127         pszFilename = CPLStrdup( pszFilenameIn );
128
129 /* -------------------------------------------------------------------- */
130 /*      Initialize.                                                     */
131 /* -------------------------------------------------------------------- */
132
133     nHeaderBytes = 0;
134     pabyHeader = NULL;
135     bIsDirectory = FALSE;
136     bStatOK = FALSE;
137     eAccess = eAccessIn;
138     fp = NULL;
139    
140 /* -------------------------------------------------------------------- */
141 /*      Collect information about the file.                             */
142 /* -------------------------------------------------------------------- */
143     VSIStatBufL  sStat;
144
145     if( VSIStatL( pszFilename, &sStat ) == 0 )
146     {
147         bStatOK = TRUE;
148
149         if( VSI_ISREG( sStat.st_mode ) )
150         {
151             pabyHeader = (GByte *) CPLCalloc(1025,1);
152
153             fp = VSIFOpen( pszFilename, "rb" );
154
155             if( fp != NULL )
156             {
157                 nHeaderBytes = (int) VSIFRead( pabyHeader, 1, 1024, fp );
158
159                 VSIRewind( fp );
160             }
161             else if( errno == 27 /* "File to large" */ )
162             {
163                 fp = VSIFOpenL( pszFilename, "rb" );
164                 if( fp != NULL )
165                 {
166                     nHeaderBytes = (int) VSIFRead( pabyHeader, 1, 1024, fp );
167                     VSIFCloseL( fp );
168                     fp = NULL;
169                 }
170             }
171         }
172         else if( VSI_ISDIR( sStat.st_mode ) )
173             bIsDirectory = TRUE;
174     }
175 }
176
177 /************************************************************************/
178 /*                           ~GDALOpenInfo()                            */
179 /************************************************************************/
180
181 GDALOpenInfo::~GDALOpenInfo()
182
183 {
184     VSIFree( pabyHeader );
185     CPLFree( pszFilename );
186
187     if( fp != NULL )
188         VSIFClose( fp );
189 }
190
191 /************************************************************************/
192 /*                              GDALOpen()                              */
193 /************************************************************************/
194
195 /**
196  * \fn GDALDatasetH GDALOpen( const char * pszFilename, GDALAccess eAccess );
197  *
198  * Open a raster file as a GDALDataset.
199  *
200  * See Also: GDALOpenShared()
201  *
202  * @param pszFilename the name of the file to access.  In the case of
203  * exotic drivers this may not refer to a physical file, but instead contain
204  * information for the driver on how to access a dataset.
205  *
206  * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
207  * drivers support only read only access.
208  *
209  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
210  * this handle can be cast to a GDALDataset *.
211  */
212  
213
214 GDALDatasetH GDALOpen( const char * pszFilename, GDALAccess eAccess )
215
216 {
217     int         iDriver;
218     GDALDriverManager *poDM = GetGDALDriverManager();
219     GDALOpenInfo oOpenInfo( pszFilename, eAccess );
220
221     CPLErrorReset();
222    
223     for( iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++ )
224     {
225         GDALDriver      *poDriver = poDM->GetDriver( iDriver );
226         GDALDataset     *poDS;
227
228         poDS = poDriver->pfnOpen( &oOpenInfo );
229         if( poDS != NULL )
230         {
231             poDS->SetDescription( pszFilename );
232
233             if( poDS->poDriver == NULL )
234                 poDS->poDriver = poDriver;
235
236            
237             CPLDebug( "GDAL", "GDALOpen(%s) succeeds as %s.\n",
238                       pszFilename, poDriver->GetDescription() );
239
240             return (GDALDatasetH) poDS;
241         }
242
243         if( CPLGetLastErrorNo() != 0 )
244             return NULL;
245     }
246
247     if( oOpenInfo.bStatOK )
248         CPLError( CE_Failure, CPLE_OpenFailed,
249                   "`%s' not recognised as a supported file format.\n",
250                   pszFilename );
251     else
252         CPLError( CE_Failure, CPLE_OpenFailed,
253                   "`%s' does not exist in the file system,\n"
254                   "and is not recognised as a supported dataset name.\n",
255                   pszFilename );
256              
257     return NULL;
258 }
259
260 /************************************************************************/
261 /*                           GDALOpenShared()                           */
262 /************************************************************************/
263
264 /**
265  * Open a raster file as a GDALDataset.
266  *
267  * This function works the same as GDALOpen(), but allows the sharing of
268  * GDALDataset handles for a dataset with other callers to GDALOpenShared().
269  *
270  * In particular, GDALOpenShared() will first consult it's list of currently
271  * open and shared GDALDataset's, and if the GetDescription() name for one
272  * exactly matches the pszFilename passed to GDALOpenShared() it
273
274  * @param pszFilename the name of the file to access.  In the case of
275  * exotic drivers this may not refer to a physical file, but instead contain
276  * information for the driver on how to access a dataset.
277  *
278  * @param eAccess the desired access, either GA_Update or GA_ReadOnly.  Many
279  * drivers support only read only access.
280  *
281  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
282  * this handle can be cast to a GDALDataset *.
283  */
284  
285 GDALDatasetH GDALOpenShared( const char *pszFilename, GDALAccess eAccess )
286
287 {
288 /* -------------------------------------------------------------------- */
289 /*      First scan the existing list to see if it could already         */
290 /*      contain the requested dataset.                                  */
291 /* -------------------------------------------------------------------- */
292     int         i, nSharedDatasetCount;
293     GDALDataset **papoSharedDatasets
294                         = GDALDataset::GetOpenDatasets(&nSharedDatasetCount);
295    
296     for( i = 0; i < nSharedDatasetCount; i++ )
297     {
298         if( strcmp(pszFilename,papoSharedDatasets[i]->GetDescription()) == 0
299             && (eAccess == GA_ReadOnly
300                 || papoSharedDatasets[i]->GetAccess() == eAccess ) )
301            
302         {
303             papoSharedDatasets[i]->Reference();
304             return papoSharedDatasets[i];
305         }
306     }
307
308 /* -------------------------------------------------------------------- */
309 /*      Try opening the the requested dataset.                          */
310 /* -------------------------------------------------------------------- */
311     GDALDataset *poDataset;
312
313     poDataset = (GDALDataset *) GDALOpen( pszFilename, eAccess );
314     if( poDataset != NULL )
315         poDataset->MarkAsShared();
316    
317     return (GDALDatasetH) poDataset;
318 }
319
320 /************************************************************************/
321 /*                             GDALClose()                              */
322 /************************************************************************/
323
324 /**
325  * Close GDAL dataset.
326  *
327  * For non-shared datasets (opened with GDALOpen()) the dataset is closed
328  * using the C++ "delete" operator, recovering all dataset related resources. 
329  * For shared datasets (opened with GDALOpenShared()) the dataset is
330  * dereferenced, and closed only if the referenced count has dropped below 1.
331  *
332  * @param hDS The dataset to close.  May be cast from a "GDALDataset *".
333  */
334
335 void GDALClose( GDALDatasetH hDS )
336
337 {
338     GDALDataset *poDS = (GDALDataset *) hDS;
339     int         i, nSharedDatasetCount;
340     GDALDataset **papoSharedDatasets
341                         = GDALDataset::GetOpenDatasets(&nSharedDatasetCount);
342
343 /* -------------------------------------------------------------------- */
344 /*      If this file is in the shared dataset list then dereference     */
345 /*      it, and only delete/remote it if the reference count has        */
346 /*      dropped to zero.                                                */
347 /* -------------------------------------------------------------------- */
348     for( i = 0; i < nSharedDatasetCount; i++ )
349     {
350         if( papoSharedDatasets[i] == poDS )
351         {
352             if( poDS->Dereference() > 0 )
353                 return;
354
355             delete poDS;
356             return;
357         }
358     }
359
360 /* -------------------------------------------------------------------- */
361 /*      This is not shared dataset, so directly delete it.              */
362 /* -------------------------------------------------------------------- */
363     delete poDS;
364 }
365
366 /************************************************************************/
367 /*                        GDALDumpOpenDataset()                         */
368 /************************************************************************/
369
370 /**
371  * List open datasets.
372  *
373  * Dumps a list of all open datasets (shared or not) to the indicated
374  * text file (may be stdout or stderr).   This function is primariliy intended
375  * to assist in debugging "dataset leaks" and reference counting issues.
376  * The information reported includes the dataset name, referenced count,
377  * shared status, driver name, size, and band count.
378  */
379
380 int GDALDumpOpenDatasets( FILE *fp )
381    
382 {
383     int         i, nSharedDatasetCount;
384     GDALDataset **papoSharedDatasets
385                         = GDALDataset::GetOpenDatasets(&nSharedDatasetCount);
386
387     if( nSharedDatasetCount > 0 )
388         VSIFPrintf( fp, "Open GDAL Datasets:\n" );
389    
390     for( i = 0; i < nSharedDatasetCount; i++ )
391     {
392         const char *pszDriverName;
393         GDALDataset *poDS = papoSharedDatasets[i];
394        
395         if( poDS->GetDriver() == NULL )
396             pszDriverName = "DriverIsNULL";
397         else
398             pszDriverName = poDS->GetDriver()->GetDescription();
399
400         poDS->Reference();
401         VSIFPrintf( fp, "  %d %c %-6s %dx%dx%d %s\n",
402                     poDS->Dereference(),
403                     poDS->GetShared() ? 'S' : 'N',
404                     pszDriverName,
405                     poDS->GetRasterXSize(),
406                     poDS->GetRasterYSize(),
407                     poDS->GetRasterCount(),
408                     poDS->GetDescription() );
409     }
410    
411     return nSharedDatasetCount;
412 }
Note: See TracBrowser for help on using the browser.