1 /******************************************************************************
2  *
3  * Project:  GDAL Core
4  * Purpose:  Base class for objects with metadata, etc.
5  * Author:   Frank Warmerdam, warmerdam@pobox.com
6  *
7  ******************************************************************************
8  * Copyright (c) 2000, Frank Warmerdam
9  * Copyright (c) 2009-2013, Even Rouault <even dot rouault at spatialys.com>
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 "cpl_port.h"
31 #include "gdal_priv.h"
32 
33 #include <cstdarg>
34 #include <cstddef>
35 
36 #include "cpl_error.h"
37 #include "cpl_string.h"
38 #include "gdal.h"
39 
40 CPL_CVSID("$Id: gdalmajorobject.cpp b1c9c12ad373e40b955162b45d704070d4ebf7b0 2019-06-19 16:50:15 +0200 Even Rouault $")
41 
42 /************************************************************************/
43 /*                          GDALMajorObject()                           */
44 /************************************************************************/
45 
GDALMajorObject()46 GDALMajorObject::GDALMajorObject() :
47     nFlags(GMO_VALID)
48 {}
49 
50 /************************************************************************/
51 /*                          ~GDALMajorObject()                          */
52 /************************************************************************/
53 
~GDALMajorObject()54 GDALMajorObject::~GDALMajorObject()
55 
56 {
57     if( (nFlags & GMO_VALID) == 0 )
58         CPLDebug( "GDAL", "In ~GDALMajorObject on invalid object" );
59 
60     nFlags &= ~GMO_VALID;
61 }
62 
63 /************************************************************************/
64 /*                           GetDescription()                           */
65 /************************************************************************/
66 
67 /**
68  * \brief Fetch object description.
69  *
70  * The semantics of the returned description are specific to the derived
71  * type.  For GDALDatasets it is the dataset name.  For GDALRasterBands
72  * it is actually a description (if supported) or "".
73  *
74  * This method is the same as the C function GDALGetDescription().
75  *
76  * @return non-null pointer to internal description string.
77  */
78 
GetDescription() const79 const char *GDALMajorObject::GetDescription() const
80 
81 {
82     return sDescription.c_str();
83 }
84 
85 /************************************************************************/
86 /*                         GDALGetDescription()                         */
87 /************************************************************************/
88 
89 /**
90  * \brief Fetch object description.
91  *
92  * @see GDALMajorObject::GetDescription()
93  */
94 
GDALGetDescription(GDALMajorObjectH hObject)95 const char * CPL_STDCALL GDALGetDescription( GDALMajorObjectH hObject )
96 
97 {
98     VALIDATE_POINTER1( hObject, "GDALGetDescription", nullptr );
99 
100     return GDALMajorObject::FromHandle(hObject)->GetDescription();
101 }
102 
103 /************************************************************************/
104 /*                           SetDescription()                           */
105 /************************************************************************/
106 
107 /**
108  * \brief Set object description.
109  *
110  * The semantics of the description are specific to the derived
111  * type.  For GDALDatasets it is the dataset name.  For GDALRasterBands
112  * it is actually a description (if supported) or "".
113  *
114  * Normally application code should not set the "description" for
115  * GDALDatasets.  It is handled internally.
116  *
117  * This method is the same as the C function GDALSetDescription().
118  */
119 
SetDescription(const char * pszNewDesc)120 void GDALMajorObject::SetDescription( const char * pszNewDesc )
121 
122 {
123     sDescription = pszNewDesc;
124 }
125 
126 /************************************************************************/
127 /*                         GDALSetDescription()                         */
128 /************************************************************************/
129 
130 /**
131  * \brief Set object description.
132  *
133  * @see GDALMajorObject::SetDescription()
134  */
135 
GDALSetDescription(GDALMajorObjectH hObject,const char * pszNewDesc)136 void CPL_STDCALL GDALSetDescription( GDALMajorObjectH hObject,
137                                      const char *pszNewDesc )
138 
139 {
140     VALIDATE_POINTER0( hObject, "GDALSetDescription" );
141 
142     GDALMajorObject::FromHandle(hObject)->SetDescription( pszNewDesc );
143 }
144 
145 /************************************************************************/
146 /*                      GetMetadataDomainList()                         */
147 /************************************************************************/
148 
149 /**
150  * \brief Fetch list of metadata domains.
151  *
152  * The returned string list is the list of (non-empty) metadata domains.
153  *
154  * This method does the same thing as the C function GDALGetMetadataDomainList().
155  *
156  * @return NULL or a string list. Must be freed with CSLDestroy()
157  *
158  * @since GDAL 1.11
159  */
160 
GetMetadataDomainList()161 char **GDALMajorObject::GetMetadataDomainList()
162 {
163     return CSLDuplicate(oMDMD.GetDomainList());
164 }
165 
166 /************************************************************************/
167 /*                      BuildMetadataDomainList()                       */
168 /************************************************************************/
169 
170 /**
171  * \brief Helper function for custom implementations of GetMetadataDomainList()
172  *
173  *
174  * @param papszList initial list of domains. May be NULL. Will become invalid
175  *                  after function call (use return value)
176  * @param bCheckNonEmpty if TRUE, each candidate domain will be tested to be non
177  *                       empty
178  * @param ... NULL terminated variadic list of candidate domains.
179  *
180  * @return NULL or a string list. Must be freed with CSLDestroy()
181  *
182  * @since GDAL 1.11
183  */
184 
BuildMetadataDomainList(char ** papszList,int bCheckNonEmpty,...)185 char **GDALMajorObject::BuildMetadataDomainList( char** papszList,
186                                                  int bCheckNonEmpty, ... )
187 {
188     va_list args;
189     const char* pszDomain = nullptr;
190     va_start(args, bCheckNonEmpty);
191 
192     while( (pszDomain = va_arg(args, const char*)) != nullptr )
193     {
194         if( CSLFindString(papszList, pszDomain) < 0 &&
195             (!bCheckNonEmpty || GetMetadata(pszDomain) != nullptr) )
196         {
197             papszList = CSLAddString(papszList, pszDomain);
198         }
199     }
200 
201     va_end(args);
202 
203     return papszList;
204 }
205 
206 /************************************************************************/
207 /*                    GDALGetMetadataDomainList()                       */
208 /************************************************************************/
209 
210 /**
211  * \brief Fetch list of metadata domains.
212  *
213  * @see GDALMajorObject::GetMetadataDomainList()
214  *
215  * @since GDAL 1.11
216  */
217 
218 char ** CPL_STDCALL
GDALGetMetadataDomainList(GDALMajorObjectH hObject)219 GDALGetMetadataDomainList( GDALMajorObjectH hObject )
220 
221 {
222     VALIDATE_POINTER1( hObject, "GetMetadataDomainList", nullptr );
223 
224     return GDALMajorObject::FromHandle(hObject)->GetMetadataDomainList();
225 }
226 
227 /************************************************************************/
228 /*                            GetMetadata()                             */
229 /************************************************************************/
230 
231 /**
232  * \brief Fetch metadata.
233  *
234  * The returned string list is owned by the object, and may change at
235  * any time.  It is formatted as a "Name=value" list with the last pointer
236  * value being NULL.  Use the CPL StringList functions such as
237  * CSLFetchNameValue() to manipulate it.
238  *
239  * Note that relatively few formats return any metadata at this time.
240  *
241  * This method does the same thing as the C function GDALGetMetadata().
242  *
243  * @param pszDomain the domain of interest.  Use "" or NULL for the default
244  * domain.
245  *
246  * @return NULL or a string list.
247  */
248 
GetMetadata(const char * pszDomain)249 char **GDALMajorObject::GetMetadata( const char * pszDomain )
250 
251 {
252     return oMDMD.GetMetadata( pszDomain );
253 }
254 
255 /************************************************************************/
256 /*                          GDALGetMetadata()                           */
257 /************************************************************************/
258 
259 /**
260  * \brief Fetch metadata.
261  *
262  * @see GDALMajorObject::GetMetadata()
263  */
264 
265 char ** CPL_STDCALL
GDALGetMetadata(GDALMajorObjectH hObject,const char * pszDomain)266 GDALGetMetadata( GDALMajorObjectH hObject, const char * pszDomain )
267 
268 {
269     VALIDATE_POINTER1( hObject, "GDALGetMetadata", nullptr );
270 
271     return GDALMajorObject::FromHandle(hObject)->GetMetadata(pszDomain);
272 }
273 
274 /************************************************************************/
275 /*                            SetMetadata()                             */
276 /************************************************************************/
277 
278 /**
279  * \brief Set metadata.
280  *
281  * The C function GDALSetMetadata() does the same thing as this method.
282  *
283  * @param papszMetadataIn the metadata in name=value string list format to
284  * apply.
285  * @param pszDomain the domain of interest.  Use "" or NULL for the default
286  * domain.
287  * @return CE_None on success, CE_Failure on failure and CE_Warning if the
288  * metadata has been accepted, but is likely not maintained persistently
289  * by the underlying object between sessions.
290  */
291 
SetMetadata(char ** papszMetadataIn,const char * pszDomain)292 CPLErr GDALMajorObject::SetMetadata( char ** papszMetadataIn,
293                                      const char * pszDomain )
294 
295 {
296     nFlags |= GMO_MD_DIRTY;
297     return oMDMD.SetMetadata( papszMetadataIn, pszDomain );
298 }
299 
300 /************************************************************************/
301 /*                          GDALSetMetadata()                           */
302 /************************************************************************/
303 
304 /**
305  * \brief Set metadata.
306  *
307  * CAUTION: when using this function on a GDALDatasetH or GDALRasterBandH,
308  * depending on the format, older values of the updated information might
309  * still be found in the file in a "ghost" state, even if no longer accessible
310  * through the GDAL API. This is for example the case of the GTiff format (this is
311  * not a exhaustive list)
312  *
313  * @see GDALMajorObject::SetMetadata(), GDALDataset::SetMetadata(),
314  *      GDALRasterBand::SetMetadata()
315  */
316 
317 CPLErr CPL_STDCALL
GDALSetMetadata(GDALMajorObjectH hObject,CSLConstList papszMD,const char * pszDomain)318 GDALSetMetadata( GDALMajorObjectH hObject, CSLConstList papszMD,
319                  const char *pszDomain )
320 
321 {
322     VALIDATE_POINTER1( hObject, "GDALSetMetadata", CE_Failure );
323 
324     return GDALMajorObject::FromHandle(hObject)->
325         SetMetadata( const_cast<char**>(papszMD), pszDomain );
326 }
327 
328 /************************************************************************/
329 /*                          GetMetadataItem()                           */
330 /************************************************************************/
331 
332 /**
333  * \brief Fetch single metadata item.
334  *
335  * The C function GDALGetMetadataItem() does the same thing as this method.
336  *
337  * @param pszName the key for the metadata item to fetch.
338  * @param pszDomain the domain to fetch for, use NULL for the default domain.
339  *
340  * @return NULL on failure to find the key, or a pointer to an internal
341  * copy of the value string on success.
342  */
343 
GetMetadataItem(const char * pszName,const char * pszDomain)344 const char *GDALMajorObject::GetMetadataItem( const char * pszName,
345                                               const char * pszDomain )
346 
347 {
348     return oMDMD.GetMetadataItem( pszName, pszDomain );
349 }
350 
351 /************************************************************************/
352 /*                        GDALGetMetadataItem()                         */
353 /************************************************************************/
354 
355 /**
356  * \brief Fetch single metadata item.
357  *
358  * @see GDALMajorObject::GetMetadataItem()
359  */
360 
GDALGetMetadataItem(GDALMajorObjectH hObject,const char * pszName,const char * pszDomain)361 const char * CPL_STDCALL GDALGetMetadataItem( GDALMajorObjectH hObject,
362                                               const char *pszName,
363                                               const char *pszDomain )
364 
365 {
366     VALIDATE_POINTER1( hObject, "GDALGetMetadataItem", nullptr );
367 
368     return GDALMajorObject::FromHandle(hObject)->
369         GetMetadataItem( pszName, pszDomain);
370 }
371 
372 /************************************************************************/
373 /*                          SetMetadataItem()                           */
374 /************************************************************************/
375 
376 /**
377  * \brief Set single metadata item.
378  *
379  * The C function GDALSetMetadataItem() does the same thing as this method.
380  *
381  * @param pszName the key for the metadata item to fetch.
382  * @param pszValue the value to assign to the key.
383  * @param pszDomain the domain to set within, use NULL for the default domain.
384  *
385  * @return CE_None on success, or an error code on failure.
386  */
387 
SetMetadataItem(const char * pszName,const char * pszValue,const char * pszDomain)388 CPLErr GDALMajorObject::SetMetadataItem( const char * pszName,
389                                          const char * pszValue,
390                                          const char * pszDomain )
391 
392 {
393     nFlags |= GMO_MD_DIRTY;
394     return oMDMD.SetMetadataItem( pszName, pszValue,  pszDomain );
395 }
396 
397 /************************************************************************/
398 /*                        GDALSetMetadataItem()                         */
399 /************************************************************************/
400 
401 /**
402  * \brief Set single metadata item.
403  *
404  * CAUTION: when using this function on a GDALDatasetH or GDALRasterBandH,
405  * depending on the format, older values of the updated information might
406  * still be found in the file in a "ghost" state, even if no longer accessible
407  * through the GDAL API. This is for example the case of the GTiff format (this is
408  * not a exhaustive list)
409  *
410  * @see GDALMajorObject::SetMetadataItem(), GDALDataset::SetMetadataItem(),
411  *      GDALRasterBand::SetMetadataItem()
412  */
413 
414 CPLErr CPL_STDCALL
GDALSetMetadataItem(GDALMajorObjectH hObject,const char * pszName,const char * pszValue,const char * pszDomain)415 GDALSetMetadataItem( GDALMajorObjectH hObject,
416                      const char *pszName, const char *pszValue,
417                      const char *pszDomain )
418 
419 {
420     VALIDATE_POINTER1( hObject, "GDALSetMetadataItem", CE_Failure );
421 
422     return GDALMajorObject::FromHandle(hObject)->
423         SetMetadataItem( pszName, pszValue, pszDomain );
424 }
425 
426 /************************************************************************/
427 /*                             GetMOFlags()                             */
428 /************************************************************************/
429 
430 /** Returns the GMO_ flags.
431  * @return flags
432  */
GetMOFlags() const433 int GDALMajorObject::GetMOFlags() const
434 
435 {
436     return nFlags;
437 }
438 
439 /************************************************************************/
440 /*                             SetMOFlags()                             */
441 /************************************************************************/
442 
443 /** Assign GMO_flags.
444  * @param nNewFlags new flags.
445  */
SetMOFlags(int nNewFlags)446 void GDALMajorObject::SetMOFlags( int nNewFlags )
447 
448 {
449     nFlags = nNewFlags;
450 }
451