root/tags/gdal_1_3_2/gcore/gdalmultidomainmetadata.cpp

Revision 9670, 12.0 kB (checked in by fwarmerdam, 3 years ago)

fixed memory leak in SetMetadata?

  • 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 GDALMultiDomainMetadata class.  This class
6  *           manages metadata items for a variable list of domains.
7  * Author:   Frank Warmerdam, warmerdam@pobox.com
8  *
9  ******************************************************************************
10  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
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.7  2006/05/01 13:45:18  fwarmerdam
33  * fixed memory leak in SetMetadata
34  *
35  * Revision 1.6  2005/10/13 01:19:57  fwarmerdam
36  * moved GDALMultiDomainMetadata into GDALMajorObject
37  *
38  * Revision 1.5  2005/09/11 18:03:05  fwarmerdam
39  * added clear() method
40  *
41  * Revision 1.4  2005/06/28 22:13:43  fwarmerdam
42  * Removed debug printf()
43  *
44  * Revision 1.3  2005/06/28 20:22:40  fwarmerdam
45  * treat xml: domains as a special inline XML format
46  *
47  * Revision 1.2  2005/05/23 06:45:59  fwarmerdam
48  * fixed flaw in walking papszMD
49  *
50  * Revision 1.1  2005/05/22 08:13:53  fwarmerdam
51  * New
52  *
53  */
54
55 #include "gdal_pam.h"
56 #include "cpl_string.h"
57
58 CPL_CVSID("$Id$");
59
60 /************************************************************************/
61 /*                      GDALMultiDomainMetadata()                       */
62 /************************************************************************/
63
64 GDALMultiDomainMetadata::GDALMultiDomainMetadata()
65
66 {
67     papszDomainList = NULL;
68     papapszMetadataLists = NULL;
69 }
70
71 /************************************************************************/
72 /*                      ~GDALMultiDomainMetadata()                      */
73 /************************************************************************/
74
75 GDALMultiDomainMetadata::~GDALMultiDomainMetadata()
76
77 {
78     Clear();
79 }
80
81 /************************************************************************/
82 /*                               Clear()                                */
83 /************************************************************************/
84
85 void GDALMultiDomainMetadata::Clear()
86
87 {
88     int i;
89
90     CSLDestroy( papszDomainList );
91     papszDomainList = NULL;
92
93     for( i = 0; papapszMetadataLists != NULL
94                 && papapszMetadataLists[i] != NULL; i++ )
95     {
96         CSLDestroy( papapszMetadataLists[i] );
97     }
98     CPLFree( papapszMetadataLists );
99     papapszMetadataLists = NULL;
100 }
101
102
103 /************************************************************************/
104 /*                            GetMetadata()                             */
105 /************************************************************************/
106
107 char **GDALMultiDomainMetadata::GetMetadata( const char *pszDomain )
108
109 {
110     if( pszDomain == NULL )
111         pszDomain = "";
112
113     int iDomain = CSLFindString( papszDomainList, pszDomain );
114
115     if( iDomain == -1 )
116         return NULL;
117     else
118         return papapszMetadataLists[iDomain];
119 }
120
121 /************************************************************************/
122 /*                            SetMetadata()                             */
123 /************************************************************************/
124
125 CPLErr GDALMultiDomainMetadata::SetMetadata( char **papszMetadata,
126                                              const char *pszDomain )
127
128 {
129     if( pszDomain == NULL )
130         pszDomain = "";
131
132     int iDomain = CSLFindString( papszDomainList, pszDomain );
133
134     if( iDomain == -1 )
135     {
136         int nDomainCount;
137
138         papszDomainList = CSLAddString( papszDomainList, pszDomain );
139         nDomainCount = CSLCount( papszDomainList );
140
141         papapszMetadataLists = (char ***)
142             CPLRealloc( papapszMetadataLists, sizeof(char*)*(nDomainCount+1) );
143         papapszMetadataLists[nDomainCount] = NULL;
144         papapszMetadataLists[nDomainCount-1] = CSLDuplicate( papszMetadata );
145     }
146     else
147     {
148         CSLDestroy( papapszMetadataLists[iDomain] );
149         papapszMetadataLists[iDomain] = CSLDuplicate( papszMetadata );
150     }
151
152     return CE_None;
153 }
154
155 /************************************************************************/
156 /*                          GetMetadataItem()                           */
157 /************************************************************************/
158
159 const char *GDALMultiDomainMetadata::GetMetadataItem( const char *pszName,
160                                                       const char *pszDomain )
161
162 {
163     char **papszMD = GetMetadata( pszDomain );
164     if( papszMD != NULL )
165         return CSLFetchNameValue( papszMD, pszName );
166     else
167         return NULL;
168 }
169
170 /************************************************************************/
171 /*                          SetMetadataItem()                           */
172 /************************************************************************/
173
174 CPLErr GDALMultiDomainMetadata::SetMetadataItem( const char *pszName,
175                                                  const char *pszValue,
176                                                  const char *pszDomain )
177
178 {
179     if( pszDomain == NULL )
180         pszDomain = "";
181
182     int iDomain = CSLFindString( papszDomainList, pszDomain );
183
184     if( iDomain == -1 )
185     {
186         int nDomainCount;
187
188         papszDomainList = CSLAddString( papszDomainList, pszDomain );
189         nDomainCount = CSLCount( papszDomainList );
190
191         papapszMetadataLists = (char ***)
192             CPLRealloc( papapszMetadataLists, sizeof(char*)*(nDomainCount+1) );
193         papapszMetadataLists[nDomainCount] = NULL;
194         papapszMetadataLists[nDomainCount-1] =
195             CSLSetNameValue( NULL, pszName, pszValue );
196     }
197     else
198     {
199         papapszMetadataLists[iDomain] =
200             CSLSetNameValue( papapszMetadataLists[iDomain],
201                              pszName, pszValue );
202     }
203
204     return CE_None;
205 }
206
207 /************************************************************************/
208 /*                              XMLInit()                               */
209 /*                                                                      */
210 /*      This method should be invoked on the parent of the              */
211 /*      <Metadata> elements.                                            */
212 /************************************************************************/
213
214 int GDALMultiDomainMetadata::XMLInit( CPLXMLNode *psTree, int bMerge )
215
216 {
217     CPLXMLNode *psMetadata;
218
219 /* ==================================================================== */
220 /*      Process all <Metadata> elements, each for one domain.           */
221 /* ==================================================================== */
222     for( psMetadata = psTree->psChild;
223          psMetadata != NULL; psMetadata = psMetadata->psNext )
224     {
225         char **papszMD = NULL;
226         CPLXMLNode *psMDI;
227         const char *pszDomain, *pszFormat;
228
229         if( psMetadata->eType != CXT_Element
230             || !EQUAL(psMetadata->pszValue,"Metadata") )
231             continue;
232
233         pszDomain = CPLGetXMLValue( psMetadata, "domain", "" );
234         pszFormat = CPLGetXMLValue( psMetadata, "format", "" );
235
236 /* -------------------------------------------------------------------- */
237 /*      XML format subdocuments.                                        */
238 /* -------------------------------------------------------------------- */
239         if( EQUAL(pszFormat,"xml") )
240         {
241             CPLXMLNode *psSubDoc;
242
243             /* find first non-attribute child of current element */
244             psSubDoc = psMetadata->psChild;
245             while( psSubDoc != NULL && psSubDoc->eType == CXT_Attribute )
246                 psSubDoc = psSubDoc->psNext;
247            
248             char *pszDoc = CPLSerializeXMLTree( psSubDoc );
249
250             papszMD = (char **) CPLCalloc(sizeof(char*),2);
251             papszMD[0] = pszDoc;
252         }
253
254 /* -------------------------------------------------------------------- */
255 /*      Name value format.                                              */
256 /*      <MDI key="...">value_Text</MDI>                                 */
257 /* -------------------------------------------------------------------- */
258         else
259         {
260             if( bMerge )
261             {
262                 papszMD = GetMetadata( pszDomain );
263                 if( papszMD != NULL )
264                     papszMD = CSLDuplicate( papszMD );
265             }
266            
267             for( psMDI = psMetadata->psChild; psMDI != NULL;
268                  psMDI = psMDI->psNext )
269             {
270                 if( !EQUAL(psMDI->pszValue,"MDI")
271                     || psMDI->eType != CXT_Element
272                     || psMDI->psChild == NULL
273                     || psMDI->psChild->psNext == NULL
274                     || psMDI->psChild->eType != CXT_Attribute
275                     || psMDI->psChild->psChild == NULL )
276                     continue;
277                
278                 papszMD =
279                     CSLSetNameValue( papszMD,
280                                      psMDI->psChild->psChild->pszValue,
281                                      psMDI->psChild->psNext->pszValue );
282             }
283         }
284
285         SetMetadata( papszMD, pszDomain );
286         CSLDestroy( papszMD );
287     }
288
289     return CSLCount(papszDomainList) != 0;
290 }
291
292 /************************************************************************/
293 /*                             Serialize()                              */
294 /************************************************************************/
295
296 CPLXMLNode *GDALMultiDomainMetadata::Serialize()
297
298 {
299     CPLXMLNode *psFirst = NULL;
300
301     for( int iDomain = 0;
302          papszDomainList != NULL && papszDomainList[iDomain] != NULL;
303          iDomain++)
304     {
305         char **papszMD = papapszMetadataLists[iDomain];
306         CPLXMLNode *psMD;
307         int bFormatXML = FALSE;
308        
309         psMD = CPLCreateXMLNode( NULL, CXT_Element, "Metadata" );
310
311         if( strlen( papszDomainList[iDomain] ) > 0 )
312             CPLCreateXMLNode(
313                 CPLCreateXMLNode( psMD, CXT_Attribute, "domain" ),
314                 CXT_Text, papszDomainList[iDomain] );
315
316         if( EQUALN(papszDomainList[iDomain],"xml:",4)
317             && CSLCount(papszMD) == 1 )
318         {
319             CPLXMLNode *psValueAsXML = CPLParseXMLString( papszMD[0] );
320             if( psValueAsXML != NULL )
321             {
322                 bFormatXML = TRUE;
323
324                 CPLCreateXMLNode(
325                     CPLCreateXMLNode( psMD, CXT_Attribute, "format" ),
326                     CXT_Text, "xml" );
327                
328                 CPLAddXMLChild( psMD, psValueAsXML );
329             }
330         }
331
332         if( !bFormatXML )
333         {
334             for( int i = 0; papszMD != NULL && papszMD[i] != NULL; i++ )
335             {
336                 const char *pszRawValue;
337                 char *pszKey;
338                 CPLXMLNode *psMDI;
339                
340                 pszRawValue = CPLParseNameValue( papszMD[i], &pszKey );
341                
342                 psMDI = CPLCreateXMLNode( psMD, CXT_Element, "MDI" );
343                 CPLSetXMLValue( psMDI, "#key", pszKey );
344                 CPLCreateXMLNode( psMDI, CXT_Text, pszRawValue );
345                
346                 CPLFree( pszKey );
347             }
348         }
349            
350         if( psFirst == NULL )
351             psFirst = psMD;
352         else
353             CPLAddXMLSibling( psFirst, psMD );
354     }
355
356     return psFirst;
357 }
358
Note: See TracBrowser for help on using the browser.