Sophie

Sophie

distrib > Mandriva > 9.1 > ppc > by-pkgid > dabb57319acb4393549d883bdd5bc220 > files > 55

libgdal0-devel-1.1.8-2mdk.ppc.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta name="robots" content="noindex">
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>cpl_minixml.cpp Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body bgcolor="#ffffff">
<!-- Generated by Doxygen 1.2.3-20001105 on Sat Dec 21 14:01:57 2002 -->
<center>
<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="hierarchy.html">Class Hierarchy</a> &nbsp; <a class="qindex" href="annotated.html">Compound List</a> &nbsp; <a class="qindex" href="files.html">File List</a> &nbsp; <a class="qindex" href="functions.html">Compound Members</a> &nbsp; <a class="qindex" href="globals.html">File Members</a> &nbsp; <a class="qindex" href="pages.html">Related Pages</a> &nbsp; </center>
<hr><h1>cpl_minixml.cpp</h1><div class="fragment"><pre>00001 <font class="comment">/**********************************************************************</font>
00002 <font class="comment"> * $Id: cpl_minixml_cpp-source.html,v 1.5 2002/12/21 19:13:12 warmerda Exp $</font>
00003 <font class="comment"> *</font>
00004 <font class="comment"> * Project:  CPL - Common Portability Library</font>
00005 <font class="comment"> * Purpose:  Implementation of MiniXML Parser and handling.</font>
00006 <font class="comment"> * Author:   Frank Warmerdam, warmerdam@pobox.com</font>
00007 <font class="comment"> *</font>
00008 <font class="comment"> **********************************************************************</font>
00009 <font class="comment"> * Copyright (c) 2001, Frank Warmerdam</font>
00010 <font class="comment"> *</font>
00011 <font class="comment"> * Permission is hereby granted, free of charge, to any person obtaining a</font>
00012 <font class="comment"> * copy of this software and associated documentation files (the "Software"),</font>
00013 <font class="comment"> * to deal in the Software without restriction, including without limitation</font>
00014 <font class="comment"> * the rights to use, copy, modify, merge, publish, distribute, sublicense,</font>
00015 <font class="comment"> * and/or sell copies of the Software, and to permit persons to whom the</font>
00016 <font class="comment"> * Software is furnished to do so, subject to the following conditions:</font>
00017 <font class="comment"> * </font>
00018 <font class="comment"> * The above copyright notice and this permission notice shall be included</font>
00019 <font class="comment"> * in all copies or substantial portions of the Software.</font>
00020 <font class="comment"> * </font>
00021 <font class="comment"> * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR</font>
00022 <font class="comment"> * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,</font>
00023 <font class="comment"> * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL</font>
00024 <font class="comment"> * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER</font>
00025 <font class="comment"> * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING</font>
00026 <font class="comment"> * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER </font>
00027 <font class="comment"> * DEALINGS IN THE SOFTWARE.</font>
00028 <font class="comment"> **********************************************************************</font>
00029 <font class="comment"> *</font>
00030 <font class="comment"> * $Log: cpl_minixml_cpp-source.html,v $
00030 <font class="comment"> * Revision 1.5  2002/12/21 19:13:12  warmerda
00030 <font class="comment"> * updated
00030 <font class="comment"> *</font>
00031 <font class="comment"> * Revision 1.16  2002/11/16 20:42:40  warmerda</font>
00032 <font class="comment"> * improved inline comments</font>
00033 <font class="comment"> *</font>
00034 <font class="comment"> * Revision 1.15  2002/11/16 20:38:34  warmerda</font>
00035 <font class="comment"> * added support for literals like DOCTYPE</font>
00036 <font class="comment"> *</font>
00037 <font class="comment"> * Revision 1.14  2002/07/16 15:06:26  warmerda</font>
00038 <font class="comment"> * ensure that attributes are serialized properly regardless of their order</font>
00039 <font class="comment"> *</font>
00040 <font class="comment"> * Revision 1.13  2002/07/09 20:25:25  warmerda</font>
00041 <font class="comment"> * expand tabs</font>
00042 <font class="comment"> *</font>
00043 <font class="comment"> * Revision 1.12  2002/05/28 18:54:05  warmerda</font>
00044 <font class="comment"> * added escaping/unescaping support</font>
00045 <font class="comment"> *</font>
00046 <font class="comment"> * Revision 1.11  2002/05/24 04:09:10  warmerda</font>
00047 <font class="comment"> * added clone and SetXMLValue functions</font>
00048 <font class="comment"> *</font>
00049 <font class="comment"> * Revision 1.10  2002/04/01 16:08:21  warmerda</font>
00050 <font class="comment"> * allow periods in tokens</font>
00051 <font class="comment"> *</font>
00052 <font class="comment"> * Revision 1.9  2002/03/07 22:19:20  warmerda</font>
00053 <font class="comment"> * don't do operations within CPLAssert(), in UnreadChar()</font>
00054 <font class="comment"> *</font>
00055 <font class="comment"> * Revision 1.8  2002/03/05 14:26:57  warmerda</font>
00056 <font class="comment"> * expanded tabs</font>
00057 <font class="comment"> *</font>
00058 <font class="comment"> * Revision 1.7  2002/01/23 20:45:05  warmerda</font>
00059 <font class="comment"> * handle &lt;?...?&gt; and comment elements</font>
00060 <font class="comment"> *</font>
00061 <font class="comment"> * Revision 1.6  2002/01/22 18:54:48  warmerda</font>
00062 <font class="comment"> * ensure text is property initialized when serializing</font>
00063 <font class="comment"> *</font>
00064 <font class="comment"> * Revision 1.5  2002/01/16 03:58:51  warmerda</font>
00065 <font class="comment"> * support single quotes as well as double quotes</font>
00066 <font class="comment"> *</font>
00067 <font class="comment"> * Revision 1.4  2001/12/06 18:13:49  warmerda</font>
00068 <font class="comment"> * added CPLAddXMLChild and CPLCreateElmentAndValue</font>
00069 <font class="comment"> *</font>
00070 <font class="comment"> * Revision 1.3  2001/11/16 21:20:16  warmerda</font>
00071 <font class="comment"> * fixed typo</font>
00072 <font class="comment"> *</font>
00073 <font class="comment"> * Revision 1.2  2001/11/16 20:29:58  warmerda</font>
00074 <font class="comment"> * fixed lost char in normal CString tokens</font>
00075 <font class="comment"> *</font>
00076 <font class="comment"> * Revision 1.1  2001/11/16 15:39:48  warmerda</font>
00077 <font class="comment"> * New</font>
00078 <font class="comment"> */</font>
00079 
00080 <font class="preprocessor">#include &lt;ctype.h&gt;</font>
00081 <font class="preprocessor">#include "cpl_minixml.h"</font>
00082 <font class="preprocessor">#include "<a class="code" href="cpl_error_h.html">cpl_error.h</a>"</font>
00083 <font class="preprocessor">#include "<a class="code" href="cpl_conv_h.html">cpl_conv.h</a>"</font>
00084 <font class="preprocessor">#include "cpl_string.h"</font>
00085 
00086 CPL_CVSID(<font class="stringliteral">"$Id: cpl_minixml_cpp-source.html,v 1.5 2002/12/21 19:13:12 warmerda Exp $"</font>);
00087 
00088 <font class="keyword">typedef</font> <font class="keyword">enum</font> {
00089     TNone,
00090     TString, 
00091     TOpen, 
00092     TClose,
00093     TEqual,
00094     TToken,
00095     TSlashClose,
00096     TQuestionClose,
00097     TComment,
00098     TLiteral
00099 } TokenType;
00100 
00101 <font class="keyword">typedef</font> <font class="keyword">struct </font>{
00102     <font class="keyword">const</font> <font class="keywordtype">char</font> *pszInput;
00103     <font class="keywordtype">int</font>        nInputOffset;
00104     <font class="keywordtype">int</font>        nInputLine;
00105 
00106     <font class="keywordtype">int</font>        bInElement;
00107     TokenType  eTokenType;
00108     <font class="keywordtype">char</font>       *pszToken;
00109     <font class="keywordtype">int</font>        nTokenMaxSize;
00110     <font class="keywordtype">int</font>        nTokenSize;
00111 
00112     <font class="keywordtype">int</font>        nStackMaxSize;
00113     <font class="keywordtype">int</font>        nStackSize;
00114     CPLXMLNode **papsStack;
00115 
00116     CPLXMLNode *psFirstNode;
00117 } ParseContext;
00118 
00119 <font class="comment">/************************************************************************/</font>
00120 <font class="comment">/*                              ReadChar()                              */</font>
00121 <font class="comment">/************************************************************************/</font>
00122 
00123 <font class="keyword">static</font> <font class="keywordtype">char</font> ReadChar( ParseContext *psContext )<font class="keyword"></font>
00124 <font class="keyword"></font>
00125 <font class="keyword"></font>{
00126     <font class="keywordtype">char</font>        chReturn;
00127 
00128     chReturn = psContext-&gt;pszInput[psContext-&gt;nInputOffset++];
00129 
00130     <font class="keywordflow">if</font>( chReturn == <font class="charliteral">'\0'</font> )
00131         psContext-&gt;nInputOffset--;
00132     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chReturn == 10 )
00133         psContext-&gt;nInputLine++;
00134     
00135     <font class="keywordflow">return</font> chReturn;
00136 }
00137 
00138 <font class="comment">/************************************************************************/</font>
00139 <font class="comment">/*                             UnreadChar()                             */</font>
00140 <font class="comment">/************************************************************************/</font>
00141 
00142 <font class="keyword">static</font> <font class="keywordtype">void</font> UnreadChar( ParseContext *psContext, <font class="keywordtype">char</font> chToUnread )<font class="keyword"></font>
00143 <font class="keyword"></font>
00144 <font class="keyword"></font>{
00145     <font class="keywordflow">if</font>( chToUnread == <font class="charliteral">'\0'</font> )
00146     {
00147         <font class="comment">/* do nothing */</font>
00148     }
00149     <font class="keywordflow">else</font>
00150     {
00151         CPLAssert( chToUnread 
00152                    == psContext-&gt;pszInput[psContext-&gt;nInputOffset-1] );
00153 
00154         psContext-&gt;nInputOffset--;
00155 
00156         <font class="keywordflow">if</font>( chToUnread == 10 )
00157             psContext-&gt;nInputLine--;
00158     }
00159 }
00160 
00161 <font class="comment">/************************************************************************/</font>
00162 <font class="comment">/*                             AddToToken()                             */</font>
00163 <font class="comment">/************************************************************************/</font>
00164 
00165 <font class="keyword">static</font> <font class="keywordtype">void</font> AddToToken( ParseContext *psContext, <font class="keywordtype">char</font> chNewChar )<font class="keyword"></font>
00166 <font class="keyword"></font>
00167 <font class="keyword"></font>{
00168     <font class="keywordflow">if</font>( psContext-&gt;pszToken == NULL )
00169     {
00170         psContext-&gt;nTokenMaxSize = 10;
00171         psContext-&gt;pszToken = (<font class="keywordtype">char</font> *) <a class="code" href="cpl_conv_h.html#a3">CPLMalloc</a>(psContext-&gt;nTokenMaxSize);
00172     }
00173     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psContext-&gt;nTokenSize &gt;= psContext-&gt;nTokenMaxSize - 2 )
00174     {
00175         psContext-&gt;nTokenMaxSize *= 2;
00176         psContext-&gt;pszToken = (<font class="keywordtype">char</font> *) 
00177             <a class="code" href="cpl_conv_h.html#a5">CPLRealloc</a>(psContext-&gt;pszToken,psContext-&gt;nTokenMaxSize);
00178     }
00179 
00180     psContext-&gt;pszToken[psContext-&gt;nTokenSize++] = chNewChar;
00181     psContext-&gt;pszToken[psContext-&gt;nTokenSize] = <font class="charliteral">'\0'</font>;
00182 }
00183 
00184 <font class="comment">/************************************************************************/</font>
00185 <font class="comment">/*                             ReadToken()                              */</font>
00186 <font class="comment">/************************************************************************/</font>
00187 
00188 <font class="keyword">static</font> TokenType ReadToken( ParseContext *psContext )<font class="keyword"></font>
00189 <font class="keyword"></font>
00190 <font class="keyword"></font>{
00191     <font class="keywordtype">char</font>        chNext;
00192 
00193     psContext-&gt;nTokenSize = 0;
00194     psContext-&gt;pszToken[0] = <font class="charliteral">'\0'</font>;
00195     
00196     chNext = ReadChar( psContext );
00197     <font class="keywordflow">while</font>( isspace(chNext) )
00198         chNext = ReadChar( psContext );
00199 
00200 <font class="comment">/* -------------------------------------------------------------------- */</font>
00201 <font class="comment">/*      Handle comments.                                                */</font>
00202 <font class="comment">/* -------------------------------------------------------------------- */</font>
00203     <font class="keywordflow">if</font>( chNext == <font class="charliteral">'&lt;'</font> 
00204         &amp;&amp; EQUALN(psContext-&gt;pszInput+psContext-&gt;nInputOffset,"!--",3) )
00205     {
00206         psContext-&gt;eTokenType = TComment;
00207 
00208         <font class="comment">// Skip "!--" characters</font>
00209         ReadChar(psContext);
00210         ReadChar(psContext);
00211         ReadChar(psContext);
00212 
00213         <font class="keywordflow">while</font>( !EQUALN(psContext-&gt;pszInput+psContext-&gt;nInputOffset,"--&gt;",3)
00214                &amp;&amp; (chNext = ReadChar(psContext)) != <font class="charliteral">'\0'</font> )
00215             AddToToken( psContext, chNext );
00216 
00217         <font class="comment">// Skip "--&gt;" characters</font>
00218         ReadChar(psContext);
00219         ReadChar(psContext);
00220         ReadChar(psContext);
00221     }
00222 <font class="comment">/* -------------------------------------------------------------------- */</font>
00223 <font class="comment">/*      Handle DOCTYPE or other literals.                               */</font>
00224 <font class="comment">/* -------------------------------------------------------------------- */</font>
00225     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chNext == <font class="charliteral">'&lt;'</font> 
00226           &amp;&amp; EQUALN(psContext-&gt;pszInput+psContext-&gt;nInputOffset,"!DOCTYPE",8) )
00227     {
00228         <font class="keywordtype">int</font>   bInQuotes = FALSE;
00229         psContext-&gt;eTokenType = TLiteral;
00230         
00231         AddToToken( psContext, <font class="charliteral">'&lt;'</font> );
00232         <font class="keywordflow">do</font> { 
00233             chNext = ReadChar(psContext);
00234             <font class="keywordflow">if</font>( chNext == <font class="charliteral">'\0'</font> )
00235             {
00236                 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00237                           <font class="stringliteral">"Parse error in DOCTYPE on or before line %d, reached end of file without '&gt;'."</font>, 
00238                           psContext-&gt;nInputLine );
00239                 
00240                 <font class="keywordflow">break</font>;
00241             }
00242 
00243             <font class="keywordflow">if</font>( chNext == <font class="charliteral">'\"'</font> )
00244                 bInQuotes = !bInQuotes;
00245 
00246             <font class="keywordflow">if</font>( chNext == <font class="charliteral">'&gt;'</font> &amp;&amp; !bInQuotes )
00247             {
00248                 AddToToken( psContext, <font class="charliteral">'&gt;'</font> );
00249                 <font class="keywordflow">break</font>;
00250             }
00251 
00252             AddToToken( psContext, chNext );
00253         } <font class="keywordflow">while</font>( TRUE );
00254     }
00255 <font class="comment">/* -------------------------------------------------------------------- */</font>
00256 <font class="comment">/*      Simple single tokens of interest.                               */</font>
00257 <font class="comment">/* -------------------------------------------------------------------- */</font>
00258     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chNext == <font class="charliteral">'&lt;'</font> &amp;&amp; !psContext-&gt;bInElement )
00259     {
00260         psContext-&gt;eTokenType = TOpen;
00261         psContext-&gt;bInElement = TRUE;
00262     }
00263     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chNext == <font class="charliteral">'&gt;'</font> &amp;&amp; psContext-&gt;bInElement )
00264     {
00265         psContext-&gt;eTokenType = TClose;
00266         psContext-&gt;bInElement = FALSE;
00267     }
00268     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chNext == <font class="charliteral">'='</font> &amp;&amp; psContext-&gt;bInElement )
00269     {
00270         psContext-&gt;eTokenType = TEqual;
00271     }
00272     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chNext == <font class="charliteral">'\0'</font> )
00273     {
00274         psContext-&gt;eTokenType = TNone;
00275     }
00276 <font class="comment">/* -------------------------------------------------------------------- */</font>
00277 <font class="comment">/*      Handle the /&gt; token terminator.                                 */</font>
00278 <font class="comment">/* -------------------------------------------------------------------- */</font>
00279     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chNext == <font class="charliteral">'/'</font> &amp;&amp; psContext-&gt;bInElement 
00280              &amp;&amp; psContext-&gt;pszInput[psContext-&gt;nInputOffset] == <font class="charliteral">'&gt;'</font> )
00281     {
00282         chNext = ReadChar( psContext );
00283         <font class="keywordflow">if</font>( chNext != <font class="charliteral">'&gt;'</font> )
00284         {
00285             psContext-&gt;eTokenType = TNone;
00286             <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00287                       <font class="stringliteral">"Parse error at '/' on line %d, expected '&gt;'."</font>, 
00288                       psContext-&gt;nInputLine );
00289         }
00290         <font class="keywordflow">else</font>
00291         {
00292             psContext-&gt;eTokenType = TSlashClose;
00293             psContext-&gt;bInElement = FALSE;
00294         }
00295     }
00296 <font class="comment">/* -------------------------------------------------------------------- */</font>
00297 <font class="comment">/*      Handle the ?&gt; token terminator.                                 */</font>
00298 <font class="comment">/* -------------------------------------------------------------------- */</font>
00299     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chNext == <font class="charliteral">'?'</font> &amp;&amp; psContext-&gt;bInElement 
00300              &amp;&amp; psContext-&gt;pszInput[psContext-&gt;nInputOffset] == <font class="charliteral">'&gt;'</font> )
00301     {
00302         chNext = ReadChar( psContext );
00303         <font class="keywordflow">if</font>( chNext != <font class="charliteral">'&gt;'</font> )
00304         {
00305             psContext-&gt;eTokenType = TNone;
00306             <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00307                       <font class="stringliteral">"Parse error at '?' on line %d, expected '&gt;'."</font>, 
00308                       psContext-&gt;nInputLine );
00309         }
00310         <font class="keywordflow">else</font>
00311         {
00312             psContext-&gt;eTokenType = TQuestionClose;
00313             psContext-&gt;bInElement = FALSE;
00314         }
00315     }
00316 
00317 <font class="comment">/* -------------------------------------------------------------------- */</font>
00318 <font class="comment">/*      Collect a quoted string.                                        */</font>
00319 <font class="comment">/* -------------------------------------------------------------------- */</font>
00320     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psContext-&gt;bInElement &amp;&amp; chNext == <font class="charliteral">'"'</font> )
00321     {
00322         psContext-&gt;eTokenType = TString;
00323 
00324         <font class="keywordflow">while</font>( (chNext = ReadChar(psContext)) != <font class="charliteral">'"'</font> 
00325                &amp;&amp; chNext != <font class="charliteral">'\0'</font> )
00326             AddToToken( psContext, chNext );
00327         
00328         <font class="keywordflow">if</font>( chNext != <font class="charliteral">'"'</font> )
00329         {
00330             psContext-&gt;eTokenType = TNone;
00331             <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00332                   <font class="stringliteral">"Parse error on line %d, reached EOF before closing quote."</font>, 
00333                       psContext-&gt;nInputLine );
00334         }
00335 
00336         <font class="comment">/* Do we need to unescape it? */</font>
00337         <font class="keywordflow">if</font>( strchr(psContext-&gt;pszToken,<font class="charliteral">'&amp;'</font>) != NULL )
00338         {
00339             <font class="keywordtype">int</font>  nLength;
00340             <font class="keywordtype">char</font> *pszUnescaped = CPLUnescapeString( psContext-&gt;pszToken, 
00341                                                     &amp;nLength, CPLES_XML );
00342             strcpy( psContext-&gt;pszToken, pszUnescaped );
00343             CPLFree( pszUnescaped );
00344             psContext-&gt;nTokenSize = strlen(psContext-&gt;pszToken );
00345         }
00346     }
00347 
00348     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psContext-&gt;bInElement &amp;&amp; chNext == <font class="charliteral">'\''</font> )
00349     {
00350         psContext-&gt;eTokenType = TString;
00351 
00352         <font class="keywordflow">while</font>( (chNext = ReadChar(psContext)) != <font class="charliteral">'\''</font> 
00353                &amp;&amp; chNext != <font class="charliteral">'\0'</font> )
00354             AddToToken( psContext, chNext );
00355         
00356         <font class="keywordflow">if</font>( chNext != <font class="charliteral">'\''</font> )
00357         {
00358             psContext-&gt;eTokenType = TNone;
00359             <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00360                   <font class="stringliteral">"Parse error on line %d, reached EOF before closing quote."</font>, 
00361                       psContext-&gt;nInputLine );
00362         }
00363     }
00364 
00365 <font class="comment">/* -------------------------------------------------------------------- */</font>
00366 <font class="comment">/*      Collect an unquoted string, terminated by a open angle          */</font>
00367 <font class="comment">/*      bracket.                                                        */</font>
00368 <font class="comment">/* -------------------------------------------------------------------- */</font>
00369     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( !psContext-&gt;bInElement )
00370     {
00371         psContext-&gt;eTokenType = TString;
00372 
00373         AddToToken( psContext, chNext );
00374         <font class="keywordflow">while</font>( (chNext = ReadChar(psContext)) != <font class="charliteral">'&lt;'</font> 
00375                &amp;&amp; chNext != <font class="charliteral">'\0'</font> )
00376             AddToToken( psContext, chNext );
00377         UnreadChar( psContext, chNext );
00378 
00379         <font class="comment">/* Do we need to unescape it? */</font>
00380         <font class="keywordflow">if</font>( strchr(psContext-&gt;pszToken,<font class="charliteral">'&amp;'</font>) != NULL )
00381         {
00382             <font class="keywordtype">int</font>  nLength;
00383             <font class="keywordtype">char</font> *pszUnescaped = CPLUnescapeString( psContext-&gt;pszToken, 
00384                                                     &amp;nLength, CPLES_XML );
00385             strcpy( psContext-&gt;pszToken, pszUnescaped );
00386             CPLFree( pszUnescaped );
00387             psContext-&gt;nTokenSize = strlen(psContext-&gt;pszToken );
00388         }
00389     }
00390     
00391 <font class="comment">/* -------------------------------------------------------------------- */</font>
00392 <font class="comment">/*      Collect a regular token terminated by white space, or           */</font>
00393 <font class="comment">/*      special character(s) like an equal sign.                        */</font>
00394 <font class="comment">/* -------------------------------------------------------------------- */</font>
00395     <font class="keywordflow">else</font>
00396     {
00397         psContext-&gt;eTokenType = TToken;
00398 
00399         <font class="comment">/* add the first character to the token regardless of what it is */</font>
00400         AddToToken( psContext, chNext );
00401 
00402         <font class="keywordflow">for</font>( chNext = ReadChar(psContext); 
00403              (chNext &gt;= <font class="charliteral">'A'</font> &amp;&amp; chNext &lt;= <font class="charliteral">'Z'</font>)
00404                  || (chNext &gt;= <font class="charliteral">'a'</font> &amp;&amp; chNext &lt;= <font class="charliteral">'z'</font>)
00405                  || chNext == <font class="charliteral">'_'</font>
00406                  || chNext == <font class="charliteral">'.'</font>
00407                  || chNext == <font class="charliteral">':'</font>
00408                  || (chNext &gt;= <font class="charliteral">'0'</font> &amp;&amp; chNext &lt;= <font class="charliteral">'9'</font>);
00409              chNext = ReadChar(psContext) ) 
00410         {
00411             AddToToken( psContext, chNext );
00412         }
00413 
00414         UnreadChar(psContext, chNext);
00415     }
00416     
00417     <font class="keywordflow">return</font> psContext-&gt;eTokenType;
00418 }
00419     
00420 <font class="comment">/************************************************************************/</font>
00421 <font class="comment">/*                              PushNode()                              */</font>
00422 <font class="comment">/************************************************************************/</font>
00423 
00424 <font class="keyword">static</font> <font class="keywordtype">void</font> PushNode( ParseContext *psContext, CPLXMLNode *psNode )<font class="keyword"></font>
00425 <font class="keyword"></font>
00426 <font class="keyword"></font>{
00427     <font class="keywordflow">if</font>( psContext-&gt;nStackMaxSize &lt;= psContext-&gt;nStackSize )
00428     {
00429         psContext-&gt;nStackMaxSize += 10;
00430         psContext-&gt;papsStack = (CPLXMLNode **)
00431             <a class="code" href="cpl_conv_h.html#a5">CPLRealloc</a>(psContext-&gt;papsStack, 
00432                        <font class="keyword">sizeof</font>(CPLXMLNode*) * psContext-&gt;nStackMaxSize);
00433     }
00434 
00435     psContext-&gt;papsStack[psContext-&gt;nStackSize++] = psNode;
00436 }
00437     
00438 <font class="comment">/************************************************************************/</font>
00439 <font class="comment">/*                             AttachNode()                             */</font>
00440 <font class="comment">/*                                                                      */</font>
00441 <font class="comment">/*      Attach the passed node as a child of the current node.          */</font>
00442 <font class="comment">/*      Special handling exists for adding siblings to psFirst if       */</font>
00443 <font class="comment">/*      there is nothing on the stack.                                  */</font>
00444 <font class="comment">/************************************************************************/</font>
00445 
00446 <font class="keyword">static</font> <font class="keywordtype">void</font> AttachNode( ParseContext *psContext, CPLXMLNode *psNode )<font class="keyword"></font>
00447 <font class="keyword"></font>
00448 <font class="keyword"></font>{
00449     <font class="keywordflow">if</font>( psContext-&gt;psFirstNode == NULL )
00450         psContext-&gt;psFirstNode = psNode;
00451     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psContext-&gt;nStackSize == 0 )
00452     {
00453         CPLXMLNode *psSibling;
00454 
00455         psSibling = psContext-&gt;psFirstNode;
00456         <font class="keywordflow">while</font>( psSibling-&gt;psNext != NULL )
00457             psSibling = psSibling-&gt;psNext;
00458         psSibling-&gt;psNext = psNode;
00459     }
00460     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psContext-&gt;papsStack[psContext-&gt;nStackSize-1]-&gt;psChild == NULL )
00461     {
00462         psContext-&gt;papsStack[psContext-&gt;nStackSize-1]-&gt;psChild = psNode;
00463     }
00464     <font class="keywordflow">else</font>
00465     {
00466         CPLXMLNode *psSibling;
00467 
00468         psSibling = psContext-&gt;papsStack[psContext-&gt;nStackSize-1]-&gt;psChild;
00469         <font class="keywordflow">while</font>( psSibling-&gt;psNext != NULL )
00470             psSibling = psSibling-&gt;psNext;
00471         psSibling-&gt;psNext = psNode;
00472     }
00473 }
00474 
00475 <font class="comment">/************************************************************************/</font>
00476 <font class="comment">/*                         CPLParseXMLString()                          */</font>
00477 <font class="comment">/************************************************************************/</font>
00478 
00479 CPLXMLNode *CPLParseXMLString( <font class="keyword">const</font> <font class="keywordtype">char</font> *pszString )<font class="keyword"></font>
00480 <font class="keyword"></font>
00481 <font class="keyword"></font>{
00482     ParseContext sContext;
00483 
00484     <a class="code" href="cpl_error_h.html#a19">CPLErrorReset</a>();
00485 
00486 <font class="comment">/* -------------------------------------------------------------------- */</font>
00487 <font class="comment">/*      Initialize parse context.                                       */</font>
00488 <font class="comment">/* -------------------------------------------------------------------- */</font>
00489     sContext.pszInput = pszString;
00490     sContext.nInputOffset = 0;
00491     sContext.nInputLine = 0;
00492     sContext.bInElement = FALSE;
00493     sContext.pszToken = NULL;
00494     sContext.nTokenMaxSize = 0;
00495     sContext.nTokenSize = 0;
00496     sContext.eTokenType = TNone;
00497     sContext.nStackMaxSize = 0;
00498     sContext.nStackSize = 0;
00499     sContext.papsStack = NULL;
00500     sContext.psFirstNode = NULL;
00501 
00502     <font class="comment">/* ensure token is initialized */</font>
00503     AddToToken( &amp;sContext, <font class="charliteral">' '</font> );
00504     
00505 <font class="comment">/* ==================================================================== */</font>
00506 <font class="comment">/*      Loop reading tokens.                                            */</font>
00507 <font class="comment">/* ==================================================================== */</font>
00508     <font class="keywordflow">while</font>( ReadToken( &amp;sContext ) != TNone )
00509     {
00510 <font class="comment">/* -------------------------------------------------------------------- */</font>
00511 <font class="comment">/*      Create a new element.                                           */</font>
00512 <font class="comment">/* -------------------------------------------------------------------- */</font>
00513         <font class="keywordflow">if</font>( sContext.eTokenType == TOpen )
00514         {
00515             CPLXMLNode *psElement;
00516 
00517             <font class="keywordflow">if</font>( ReadToken(&amp;sContext) != TToken )
00518             {
00519                 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00520                           <font class="stringliteral">"Line %d: Didn't find element token after open angle bracket."</font>,
00521                           sContext.nInputLine );
00522                 <font class="keywordflow">break</font>;
00523             }
00524 
00525             <font class="keywordflow">if</font>( sContext.pszToken[0] != <font class="charliteral">'/'</font> )
00526             {
00527                 psElement = CPLCreateXMLNode( NULL, CXT_Element,
00528                                               sContext.pszToken );
00529                 AttachNode( &amp;sContext, psElement );
00530                 PushNode( &amp;sContext, psElement );
00531             }
00532             <font class="keywordflow">else</font> 
00533             {
00534                 <font class="keywordflow">if</font>( sContext.nStackSize == 0
00535                     || !EQUAL(sContext.pszToken+1,
00536                          sContext.papsStack[sContext.nStackSize-1]-&gt;pszValue) )
00537                 {
00538                     <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00539                               <font class="stringliteral">"Line %d: &lt;%s&gt; doesn't have matching &lt;%s&gt;."</font>,
00540                               sContext.nInputLine,
00541                               sContext.pszToken, sContext.pszToken+1 );
00542                     <font class="keywordflow">break</font>;
00543                 }
00544                 <font class="keywordflow">else</font>
00545                 {
00546                     <font class="keywordflow">if</font>( ReadToken(&amp;sContext) != TClose )
00547                     {
00548                         <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00549                                   <font class="stringliteral">"Line %d: Missing close angle bracket after &lt;%s."</font>,
00550                                   sContext.nInputLine,
00551                                   sContext.pszToken );
00552                         <font class="keywordflow">break</font>;
00553                     }
00554 
00555                     <font class="comment">/* pop element off stack */</font>
00556                     sContext.nStackSize--;
00557                 }
00558             }
00559         }
00560 
00561 <font class="comment">/* -------------------------------------------------------------------- */</font>
00562 <font class="comment">/*      Add an attribute to a token.                                    */</font>
00563 <font class="comment">/* -------------------------------------------------------------------- */</font>
00564         <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.eTokenType == TToken )
00565         {
00566             CPLXMLNode *psAttr;
00567 
00568             psAttr = CPLCreateXMLNode(NULL, CXT_Attribute, sContext.pszToken);
00569             AttachNode( &amp;sContext, psAttr );
00570             
00571             <font class="keywordflow">if</font>( ReadToken(&amp;sContext) != TEqual )
00572             {
00573                 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00574                           <font class="stringliteral">"Line %d: Didn't find expected '=' for value of attribute '%s'."</font>,
00575                           sContext.nInputLine, psAttr-&gt;pszValue );
00576                 <font class="keywordflow">break</font>;
00577             }
00578 
00579             <font class="keywordflow">if</font>( ReadToken(&amp;sContext) != TString 
00580                 &amp;&amp; sContext.eTokenType != TToken )
00581             {
00582                 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00583                           <font class="stringliteral">"Line %d: Didn't find expected attribute value."</font>,
00584                           sContext.nInputLine );
00585                 <font class="keywordflow">break</font>;
00586             }
00587 
00588             CPLCreateXMLNode( psAttr, CXT_Text, sContext.pszToken );
00589         }
00590 
00591 <font class="comment">/* -------------------------------------------------------------------- */</font>
00592 <font class="comment">/*      Close the start section of an element.                          */</font>
00593 <font class="comment">/* -------------------------------------------------------------------- */</font>
00594         <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.eTokenType == TClose )
00595         {
00596             <font class="keywordflow">if</font>( sContext.nStackSize == 0 )
00597             {
00598                 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00599                           <font class="stringliteral">"Line %d: Found unbalanced '&gt;'."</font>,
00600                           sContext.nInputLine );
00601                 <font class="keywordflow">break</font>;
00602             }
00603         }
00604 
00605 <font class="comment">/* -------------------------------------------------------------------- */</font>
00606 <font class="comment">/*      Close the start section of an element, and pop it               */</font>
00607 <font class="comment">/*      immediately.                                                    */</font>
00608 <font class="comment">/* -------------------------------------------------------------------- */</font>
00609         <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.eTokenType == TSlashClose )
00610         {
00611             <font class="keywordflow">if</font>( sContext.nStackSize == 0 )
00612             {
00613                 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00614                           <font class="stringliteral">"Line %d: Found unbalanced '/&gt;'."</font>,
00615                           sContext.nInputLine );
00616                 <font class="keywordflow">break</font>;
00617             }
00618 
00619             sContext.nStackSize--;
00620         }
00621 
00622 <font class="comment">/* -------------------------------------------------------------------- */</font>
00623 <font class="comment">/*      Close the start section of a &lt;?...?&gt; element, and pop it        */</font>
00624 <font class="comment">/*      immediately.                                                    */</font>
00625 <font class="comment">/* -------------------------------------------------------------------- */</font>
00626         <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.eTokenType == TQuestionClose )
00627         {
00628             <font class="keywordflow">if</font>( sContext.nStackSize == 0 )
00629             {
00630                 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00631                           <font class="stringliteral">"Line %d: Found unbalanced '?&gt;'."</font>,
00632                           sContext.nInputLine );
00633                 <font class="keywordflow">break</font>;
00634             }
00635             <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.papsStack[sContext.nStackSize-1]-&gt;pszValue[0] != <font class="charliteral">'?'</font> )
00636             {
00637                 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00638                           <font class="stringliteral">"Line %d: Found '?&gt;' without matching '&lt;?'."</font>,
00639                           sContext.nInputLine );
00640                 <font class="keywordflow">break</font>;
00641             }
00642 
00643             sContext.nStackSize--;
00644         }
00645 
00646 <font class="comment">/* -------------------------------------------------------------------- */</font>
00647 <font class="comment">/*      Handle comments.  They are returned as a whole token with the     */</font>
00648 <font class="comment">/*      prefix and postfix omitted.  No processing of white space       */</font>
00649 <font class="comment">/*      will be done.                                                   */</font>
00650 <font class="comment">/* -------------------------------------------------------------------- */</font>
00651         <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.eTokenType == TComment )
00652         {
00653             CPLXMLNode *psValue;
00654 
00655             psValue = CPLCreateXMLNode(NULL, CXT_Comment, sContext.pszToken);
00656             AttachNode( &amp;sContext, psValue );
00657         }
00658 
00659 <font class="comment">/* -------------------------------------------------------------------- */</font>
00660 <font class="comment">/*      Handle literals.  They are returned without processing.         */</font>
00661 <font class="comment">/* -------------------------------------------------------------------- */</font>
00662         <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.eTokenType == TLiteral )
00663         {
00664             CPLXMLNode *psValue;
00665 
00666             psValue = CPLCreateXMLNode(NULL, CXT_Literal, sContext.pszToken);
00667             AttachNode( &amp;sContext, psValue );
00668         }
00669 
00670 <font class="comment">/* -------------------------------------------------------------------- */</font>
00671 <font class="comment">/*      Add a text value node as a child of the current element.        */</font>
00672 <font class="comment">/* -------------------------------------------------------------------- */</font>
00673         <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.eTokenType == TString &amp;&amp; !sContext.bInElement )
00674         {
00675             CPLXMLNode *psValue;
00676 
00677             psValue = CPLCreateXMLNode(NULL, CXT_Text, sContext.pszToken);
00678             AttachNode( &amp;sContext, psValue );
00679         }
00680 <font class="comment">/* -------------------------------------------------------------------- */</font>
00681 <font class="comment">/*      Anything else is an error.                                      */</font>
00682 <font class="comment">/* -------------------------------------------------------------------- */</font>
00683         <font class="keywordflow">else</font>
00684         {
00685             <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00686                       <font class="stringliteral">"Parse error at line %d, unexpected token:%s\n"</font>, 
00687                       sContext.nInputLine, sContext.pszToken );
00688             <font class="keywordflow">break</font>;
00689         }
00690     }
00691 
00692 <font class="comment">/* -------------------------------------------------------------------- */</font>
00693 <font class="comment">/*      Did we pop all the way out of our stack?                        */</font>
00694 <font class="comment">/* -------------------------------------------------------------------- */</font>
00695     <font class="keywordflow">if</font>( <a class="code" href="cpl_error_h.html#a21">CPLGetLastErrorType</a>() == CE_None &amp;&amp; sContext.nStackSize != 0 )
00696     {
00697         <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 
00698                   <font class="stringliteral">"Parse error at EOF, not all elements have been closed,\n"</font>
00699                   <font class="stringliteral">"starting with %s\n"</font>,
00700                   sContext.papsStack[sContext.nStackSize-1]-&gt;pszValue );
00701     }
00702 
00703 <font class="comment">/* -------------------------------------------------------------------- */</font>
00704 <font class="comment">/*      Cleanup                                                         */</font>
00705 <font class="comment">/* -------------------------------------------------------------------- */</font>
00706     CPLFree( sContext.pszToken );
00707     <font class="keywordflow">if</font>( sContext.papsStack != NULL )
00708         CPLFree( sContext.papsStack );
00709 
00710     <font class="keywordflow">if</font>( <a class="code" href="cpl_error_h.html#a21">CPLGetLastErrorType</a>() != CE_None )
00711     {
00712         CPLDestroyXMLNode( sContext.psFirstNode );
00713         sContext.psFirstNode = NULL;
00714     }
00715 
00716     <font class="keywordflow">return</font> sContext.psFirstNode;
00717 }
00718 
00719 <font class="comment">/************************************************************************/</font>
00720 <font class="comment">/*                            _GrowBuffer()                             */</font>
00721 <font class="comment">/************************************************************************/</font>
00722 
00723 <font class="keyword">static</font> <font class="keywordtype">void</font> _GrowBuffer( <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> nNeeded, 
00724                          <font class="keywordtype">char</font> **ppszText, <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> *pnMaxLength )<font class="keyword"></font>
00725 <font class="keyword"></font>
00726 <font class="keyword"></font>{
00727     <font class="keywordflow">if</font>( nNeeded+1 &gt;= *pnMaxLength )
00728     {
00729         *pnMaxLength = MAX(*pnMaxLength * 2,nNeeded+1);
00730         *ppszText = (<font class="keywordtype">char</font> *) <a class="code" href="cpl_conv_h.html#a5">CPLRealloc</a>(*ppszText, *pnMaxLength);
00731     }
00732 }
00733 
00734 <font class="comment">/************************************************************************/</font>
00735 <font class="comment">/*                        CPLSerializeXMLNode()                         */</font>
00736 <font class="comment">/************************************************************************/</font>
00737 
00738 <font class="keyword">static</font> <font class="keywordtype">void</font>
00739 CPLSerializeXMLNode( CPLXMLNode *psNode, <font class="keywordtype">int</font> nIndent, 
00740                      <font class="keywordtype">char</font> **ppszText, <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> *pnLength, 
00741                      <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> *pnMaxLength )<font class="keyword"></font>
00742 <font class="keyword"></font>
00743 <font class="keyword"></font>{
00744     <font class="keywordflow">if</font>( psNode == NULL )
00745         <font class="keywordflow">return</font>;
00746     
00747 <font class="comment">/* -------------------------------------------------------------------- */</font>
00748 <font class="comment">/*      Ensure the buffer is plenty large to hold this additional       */</font>
00749 <font class="comment">/*      string.                                                         */</font>
00750 <font class="comment">/* -------------------------------------------------------------------- */</font>
00751     *pnLength += strlen(*ppszText + *pnLength);
00752     <font class="keywordflow">if</font>(strlen(psNode-&gt;pszValue) + *pnLength + 40 + nIndent &gt; *pnMaxLength)
00753         _GrowBuffer( strlen(psNode-&gt;pszValue) + *pnLength + 40 + nIndent, 
00754                      ppszText, pnMaxLength );
00755     
00756 <font class="comment">/* -------------------------------------------------------------------- */</font>
00757 <font class="comment">/*      Text is just directly emitted.                                  */</font>
00758 <font class="comment">/* -------------------------------------------------------------------- */</font>
00759     <font class="keywordflow">if</font>( psNode-&gt;eType == CXT_Text )
00760     {
00761         <font class="keywordtype">char</font> *pszEscaped = CPLEscapeString( psNode-&gt;pszValue, -1, CPLES_XML );
00762 
00763         CPLAssert( psNode-&gt;psChild == NULL );
00764 
00765         strcat( *ppszText + *pnLength, pszEscaped );
00766 
00767         CPLFree( pszEscaped );
00768     }
00769 
00770 <font class="comment">/* -------------------------------------------------------------------- */</font>
00771 <font class="comment">/*      Attributes require a little formatting.                         */</font>
00772 <font class="comment">/* -------------------------------------------------------------------- */</font>
00773     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psNode-&gt;eType == CXT_Attribute )
00774     {
00775         CPLAssert( psNode-&gt;psChild != NULL 
00776                    &amp;&amp; psNode-&gt;psChild-&gt;eType == CXT_Text );
00777 
00778         sprintf( *ppszText + *pnLength, <font class="stringliteral">" %s=\""</font>, psNode-&gt;pszValue );
00779         CPLSerializeXMLNode( psNode-&gt;psChild, 0, ppszText, 
00780                              pnLength, pnMaxLength );
00781         strcat( *ppszText + *pnLength, <font class="stringliteral">"\""</font> );
00782     }
00783 
00784 <font class="comment">/* -------------------------------------------------------------------- */</font>
00785 <font class="comment">/*      Handle comment output.                                          */</font>
00786 <font class="comment">/* -------------------------------------------------------------------- */</font>
00787     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psNode-&gt;eType == CXT_Comment )
00788     {
00789         <font class="keywordtype">int</font>     i;
00790 
00791         CPLAssert( psNode-&gt;psChild == NULL );
00792 
00793         <font class="keywordflow">for</font>( i = 0; i &lt; nIndent; i++ )
00794             (*ppszText)[(*pnLength)++] = <font class="charliteral">' '</font>;
00795 
00796         sprintf( *ppszText + *pnLength, <font class="stringliteral">"&lt;!--%s--&gt;\n"</font>, 
00797                  psNode-&gt;pszValue );
00798     }
00799 
00800 <font class="comment">/* -------------------------------------------------------------------- */</font>
00801 <font class="comment">/*      Handle literal output (like &lt;!DOCTYPE...&gt;)                      */</font>
00802 <font class="comment">/* -------------------------------------------------------------------- */</font>
00803     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psNode-&gt;eType == CXT_Literal )
00804     {
00805         <font class="keywordtype">int</font>     i;
00806 
00807         CPLAssert( psNode-&gt;psChild == NULL );
00808 
00809         <font class="keywordflow">for</font>( i = 0; i &lt; nIndent; i++ )
00810             (*ppszText)[(*pnLength)++] = <font class="charliteral">' '</font>;
00811 
00812         strcpy( *ppszText + *pnLength, psNode-&gt;pszValue );
00813         strcat( *ppszText + *pnLength, <font class="stringliteral">"\n"</font> );
00814     }
00815 
00816 <font class="comment">/* -------------------------------------------------------------------- */</font>
00817 <font class="comment">/*      Elements actually have to deal with general children, and       */</font>
00818 <font class="comment">/*      various formatting issues.                                      */</font>
00819 <font class="comment">/* -------------------------------------------------------------------- */</font>
00820     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psNode-&gt;eType == CXT_Element )
00821     {
00822         <font class="keywordtype">int</font>             bHasNonAttributeChildren = FALSE;
00823         CPLXMLNode      *psChild;
00824         <font class="keywordtype">char</font> *pszIndent;
00825         
00826         pszIndent =  (<font class="keywordtype">char</font> *) <a class="code" href="cpl_conv_h.html#a4">CPLCalloc</a>(nIndent + 1,1);
00827         memset(pszIndent, <font class="charliteral">' '</font>, nIndent );
00828 
00829         strcat( *ppszText + *pnLength, pszIndent );
00830         *pnLength += nIndent;
00831         sprintf( *ppszText + *pnLength, <font class="stringliteral">"&lt;%s"</font>, psNode-&gt;pszValue );
00832 
00833         <font class="comment">/* Serialize *all* the attribute children, regardless of order */</font>
00834         <font class="keywordflow">for</font>( psChild = psNode-&gt;psChild; 
00835              psChild != NULL; 
00836              psChild = psChild-&gt;psNext )
00837         {
00838             <font class="keywordflow">if</font>( psChild-&gt;eType == CXT_Attribute )
00839                 CPLSerializeXMLNode( psChild, 0, ppszText, pnLength, 
00840                                      pnMaxLength );
00841             <font class="keywordflow">else</font>
00842                 bHasNonAttributeChildren = TRUE;
00843         }
00844         
00845         <font class="keywordflow">if</font>( !bHasNonAttributeChildren )
00846         {
00847             <font class="keywordflow">if</font>( psNode-&gt;pszValue[0] == <font class="charliteral">'?'</font> )
00848                 strcat( *ppszText + *pnLength, <font class="stringliteral">"?&gt;\n"</font> );
00849             <font class="keywordflow">else</font>
00850                 strcat( *ppszText + *pnLength, <font class="stringliteral">"/&gt;\n"</font> );
00851         }
00852         <font class="keywordflow">else</font>
00853         {
00854             <font class="keywordtype">int</font>         bJustText = TRUE;
00855 
00856             strcat( *ppszText + *pnLength, <font class="stringliteral">"&gt;"</font> );
00857 
00858             <font class="keywordflow">for</font>( psChild = psNode-&gt;psChild; 
00859                  psChild != NULL; 
00860                  psChild = psChild-&gt;psNext )
00861             {
00862                 <font class="keywordflow">if</font>( psChild-&gt;eType == CXT_Attribute )
00863                     <font class="keywordflow">continue</font>;
00864 
00865                 <font class="keywordflow">if</font>( psChild-&gt;eType != CXT_Text &amp;&amp; bJustText )
00866                 {
00867                     bJustText = FALSE;
00868                     strcat( *ppszText + *pnLength, <font class="stringliteral">"\n"</font> );
00869                 }
00870 
00871                 CPLSerializeXMLNode( psChild, nIndent + 2, ppszText, pnLength, 
00872                                      pnMaxLength );
00873             }
00874         
00875             <font class="keywordflow">if</font>( strlen(psNode-&gt;pszValue)+*pnLength+40+nIndent &gt; *pnMaxLength)
00876                 _GrowBuffer( strlen(psNode-&gt;pszValue)+*pnLength+40+nIndent, 
00877                              ppszText, pnMaxLength );
00878 
00879             <font class="keywordflow">if</font>( !bJustText )
00880                 strcat( *ppszText + *pnLength, pszIndent );
00881 
00882             *pnLength += strlen(*ppszText + *pnLength);
00883             sprintf( *ppszText + *pnLength, <font class="stringliteral">"&lt;/%s&gt;\n"</font>, psNode-&gt;pszValue );
00884         }
00885 
00886         CPLFree( pszIndent );
00887     }
00888 }
00889                                 
00890 <font class="comment">/************************************************************************/</font>
00891 <font class="comment">/*                        CPLSerializeXMLTree()                         */</font>
00892 <font class="comment">/************************************************************************/</font>
00893 
00894 <font class="keywordtype">char</font> *CPLSerializeXMLTree( CPLXMLNode *psNode )<font class="keyword"></font>
00895 <font class="keyword"></font>
00896 <font class="keyword"></font>{
00897     <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> nMaxLength = 10000, nLength = 0;
00898     <font class="keywordtype">char</font> *pszText = NULL;
00899     CPLXMLNode *psThis;
00900 
00901     pszText = (<font class="keywordtype">char</font> *) <a class="code" href="cpl_conv_h.html#a3">CPLMalloc</a>(nMaxLength);
00902     pszText[0] = <font class="charliteral">'\0'</font>;
00903 
00904     <font class="keywordflow">for</font>( psThis = psNode; psThis != NULL; psThis = psThis-&gt;psNext )
00905         CPLSerializeXMLNode( psThis, 0, &amp;pszText, &amp;nLength, &amp;nMaxLength );
00906 
00907     <font class="keywordflow">return</font> pszText;
00908 }
00909 
00910 <font class="comment">/************************************************************************/</font>
00911 <font class="comment">/*                          CPLCreateXMLNode()                          */</font>
00912 <font class="comment">/************************************************************************/</font>
00913 
00914 CPLXMLNode *CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType, 
00915                               <font class="keyword">const</font> <font class="keywordtype">char</font> *pszText )<font class="keyword"></font>
00916 <font class="keyword"></font>
00917 <font class="keyword"></font>{
00918     CPLXMLNode  *psNode;
00919 
00920 <font class="comment">/* -------------------------------------------------------------------- */</font>
00921 <font class="comment">/*      Create new node.                                                */</font>
00922 <font class="comment">/* -------------------------------------------------------------------- */</font>
00923     psNode = (CPLXMLNode *) <a class="code" href="cpl_conv_h.html#a4">CPLCalloc</a>(<font class="keyword">sizeof</font>(CPLXMLNode),1);
00924     
00925     psNode-&gt;eType = eType;
00926     psNode-&gt;pszValue = <a class="code" href="cpl_conv_h.html#a6">CPLStrdup</a>( pszText );
00927 
00928 <font class="comment">/* -------------------------------------------------------------------- */</font>
00929 <font class="comment">/*      Attach to parent, if provided.                                  */</font>
00930 <font class="comment">/* -------------------------------------------------------------------- */</font>
00931     <font class="keywordflow">if</font>( poParent != NULL )
00932     {
00933         <font class="keywordflow">if</font>( poParent-&gt;psChild == NULL )
00934             poParent-&gt;psChild = psNode;
00935         <font class="keywordflow">else</font>
00936         {
00937             CPLXMLNode  *psLink = poParent-&gt;psChild;
00938 
00939             <font class="keywordflow">while</font>( psLink-&gt;psNext != NULL )
00940                 psLink = psLink-&gt;psNext;
00941 
00942             psLink-&gt;psNext = psNode;
00943         }
00944     }
00945     
00946     <font class="keywordflow">return</font> psNode;
00947 }
00948 
00949 <font class="comment">/************************************************************************/</font>
00950 <font class="comment">/*                         CPLDestroyXMLNode()                          */</font>
00951 <font class="comment">/************************************************************************/</font>
00952 
00953 <font class="keywordtype">void</font> CPLDestroyXMLNode( CPLXMLNode *psNode )<font class="keyword"></font>
00954 <font class="keyword"></font>
00955 <font class="keyword"></font>{
00956     <font class="keywordflow">if</font>( psNode-&gt;psChild != NULL )
00957         CPLDestroyXMLNode( psNode-&gt;psChild );
00958     
00959     <font class="keywordflow">if</font>( psNode-&gt;psNext != NULL )
00960         CPLDestroyXMLNode( psNode-&gt;psNext );
00961 
00962     CPLFree( psNode-&gt;pszValue );
00963     CPLFree( psNode );
00964 }
00965 
00966 <font class="comment">/************************************************************************/</font>
00967 <font class="comment">/*                           CPLGetXMLNode()                            */</font>
00968 <font class="comment">/************************************************************************/</font>
00969 
00970 CPLXMLNode *CPLGetXMLNode( CPLXMLNode *poRoot, <font class="keyword">const</font> <font class="keywordtype">char</font> *pszPath )<font class="keyword"></font>
00971 <font class="keyword"></font>
00972 <font class="keyword"></font>{
00973     <font class="keywordtype">char</font>        **papszTokens;
00974     <font class="keywordtype">int</font>         iToken = 0;
00975 
00976     papszTokens = CSLTokenizeStringComplex( pszPath, <font class="stringliteral">"."</font>, FALSE, FALSE );
00977 
00978     <font class="keywordflow">while</font>( papszTokens[iToken] != NULL &amp;&amp; poRoot != NULL )
00979     {
00980         CPLXMLNode *psChild;
00981 
00982         <font class="keywordflow">for</font>( psChild = poRoot-&gt;psChild; psChild != NULL; 
00983              psChild = psChild-&gt;psNext ) 
00984         {
00985             <font class="keywordflow">if</font>( psChild-&gt;eType != CXT_Text 
00986                 &amp;&amp; EQUAL(papszTokens[iToken],psChild-&gt;pszValue) )
00987                 <font class="keywordflow">break</font>;
00988         }
00989 
00990         <font class="keywordflow">if</font>( psChild == NULL )
00991         {
00992             poRoot = NULL;
00993             <font class="keywordflow">break</font>;
00994         }
00995 
00996         poRoot = psChild;
00997         iToken++;
00998     }
00999 
01000     CSLDestroy( papszTokens );
01001     <font class="keywordflow">return</font> poRoot;
01002 }
01003 
01004 <font class="comment">/************************************************************************/</font>
01005 <font class="comment">/*                           CPLGetXMLValue()                           */</font>
01006 <font class="comment">/************************************************************************/</font>
01007 
01008 <font class="keyword">const</font> <font class="keywordtype">char</font> *CPLGetXMLValue( CPLXMLNode *poRoot, <font class="keyword">const</font> <font class="keywordtype">char</font> *pszPath, 
01009                             <font class="keyword">const</font> <font class="keywordtype">char</font> *pszDefault )<font class="keyword"></font>
01010 <font class="keyword"></font>
01011 <font class="keyword"></font>{
01012     CPLXMLNode  *psTarget;
01013 
01014     psTarget = CPLGetXMLNode( poRoot, pszPath );
01015     <font class="keywordflow">if</font>( psTarget == NULL )
01016         <font class="keywordflow">return</font> pszDefault;
01017 
01018     <font class="keywordflow">if</font>( psTarget-&gt;eType == CXT_Attribute )
01019     {
01020         CPLAssert( psTarget-&gt;psChild != NULL 
01021                    &amp;&amp; psTarget-&gt;psChild-&gt;eType == CXT_Text );
01022 
01023         <font class="keywordflow">return</font> psTarget-&gt;psChild-&gt;pszValue;
01024     }
01025 
01026     <font class="keywordflow">if</font>( psTarget-&gt;eType == CXT_Element 
01027         &amp;&amp; psTarget-&gt;psChild != NULL 
01028         &amp;&amp; psTarget-&gt;psChild-&gt;eType == CXT_Text
01029         &amp;&amp; psTarget-&gt;psChild-&gt;psNext == NULL )
01030     {
01031         <font class="keywordflow">return</font> psTarget-&gt;psChild-&gt;pszValue;
01032     }
01033         
01034     <font class="keywordflow">return</font> pszDefault;
01035 }
01036 
01037 <font class="comment">/************************************************************************/</font>
01038 <font class="comment">/*                           CPLAddXMLChild()                           */</font>
01039 <font class="comment">/*                                                                      */</font>
01040 <font class="comment">/*      Add a node as a child of another.                               */</font>
01041 <font class="comment">/************************************************************************/</font>
01042 
01043 <font class="keywordtype">void</font> CPLAddXMLChild( CPLXMLNode *psParent, CPLXMLNode *psChild )<font class="keyword"></font>
01044 <font class="keyword"></font>
01045 <font class="keyword"></font>{
01046     CPLXMLNode *psSib;
01047 
01048     CPLAssert( psChild-&gt;psNext == NULL );
01049     psChild-&gt;psNext = NULL;
01050 
01051     <font class="keywordflow">if</font>( psParent-&gt;psChild == NULL )
01052     {
01053         psParent-&gt;psChild = psChild;
01054         <font class="keywordflow">return</font>;
01055     }
01056 
01057     <font class="keywordflow">for</font>( psSib = psParent-&gt;psChild; 
01058          psSib-&gt;psNext != NULL; 
01059          psSib = psSib-&gt;psNext ) {}
01060 
01061     psSib-&gt;psNext = psChild;
01062 }
01063 
01064 <font class="comment">/************************************************************************/</font>
01065 <font class="comment">/*                    CPLCreateXMLElementAndValue()                     */</font>
01066 <font class="comment">/************************************************************************/</font>
01067 
01068 CPLXMLNode *CPLCreateXMLElementAndValue( CPLXMLNode *psParent, 
01069                                          <font class="keyword">const</font> <font class="keywordtype">char</font> *pszName, 
01070                                          <font class="keyword">const</font> <font class="keywordtype">char</font> *pszValue )<font class="keyword"></font>
01071 <font class="keyword"></font>
01072 <font class="keyword"></font>{
01073     <font class="keywordflow">return</font> CPLCreateXMLNode( 
01074         CPLCreateXMLNode( psParent, CXT_Element, pszName ),
01075         CXT_Text, pszValue );
01076 }
01077 
01078 <font class="comment">/************************************************************************/</font>
01079 <font class="comment">/*                          CPLCloneXMLTree()                           */</font>
01080 <font class="comment">/*                                                                      */</font>
01081 <font class="comment">/*      Clone an XML Tree.  We use recursion to handle children, but    */</font>
01082 <font class="comment">/*      we do siblings by looping.  This means we can handle very       */</font>
01083 <font class="comment">/*      long lists of elements, but great depth may cause stack         */</font>
01084 <font class="comment">/*      overflow problems on some systems.                              */</font>
01085 <font class="comment">/************************************************************************/</font>
01086 
01087 CPLXMLNode *CPLCloneXMLTree( CPLXMLNode *psTree )<font class="keyword"></font>
01088 <font class="keyword"></font>
01089 <font class="keyword"></font>{
01090     CPLXMLNode *psPrevious = NULL;
01091     CPLXMLNode *psReturn = NULL;
01092 
01093     <font class="keywordflow">while</font>( psTree != NULL )
01094     {
01095         CPLXMLNode *psCopy;
01096 
01097         psCopy = CPLCreateXMLNode( NULL, psTree-&gt;eType, psTree-&gt;pszValue );
01098         <font class="keywordflow">if</font>( psReturn == NULL )
01099             psReturn = psCopy;
01100         <font class="keywordflow">if</font>( psPrevious != NULL )
01101             psPrevious-&gt;psNext = psCopy;
01102 
01103         <font class="keywordflow">if</font>( psTree-&gt;psChild != NULL )
01104             psCopy-&gt;psChild = CPLCloneXMLTree( psTree-&gt;psChild );
01105 
01106         psPrevious = psCopy;
01107         psTree = psTree-&gt;psNext;
01108     }
01109 
01110     <font class="keywordflow">return</font> psReturn;
01111 }
01112 
01113 <font class="comment">/************************************************************************/</font>
01114 <font class="comment">/*                           CPLSetXMLValue()                           */</font>
01115 <font class="comment">/*                                                                      */</font>
01116 <font class="comment">/*      Set the text value of an XML element to the suggested           */</font>
01117 <font class="comment">/*      value.  Intermediate element nodes are created if               */</font>
01118 <font class="comment">/*      an existing component is missing.                               */</font>
01119 <font class="comment">/************************************************************************/</font>
01120 
01121 <font class="keywordtype">int</font> CPLSetXMLValue( CPLXMLNode *psRoot,  <font class="keyword">const</font> <font class="keywordtype">char</font> *pszPath,
01122                     <font class="keyword">const</font> <font class="keywordtype">char</font> *pszValue )<font class="keyword"></font>
01123 <font class="keyword"></font>
01124 <font class="keyword"></font>{
01125     <font class="keywordtype">char</font>        **papszTokens;
01126     <font class="keywordtype">int</font>         iToken = 0;
01127 
01128     papszTokens = CSLTokenizeStringComplex( pszPath, <font class="stringliteral">"."</font>, FALSE, FALSE );
01129 
01130     <font class="keywordflow">while</font>( papszTokens[iToken] != NULL &amp;&amp; psRoot != NULL )
01131     {
01132         CPLXMLNode *psChild;
01133         <font class="keywordtype">int</font>        bIsAttribute = FALSE;
01134         <font class="keyword">const</font> <font class="keywordtype">char</font> *pszName = papszTokens[iToken];
01135 
01136         <font class="keywordflow">if</font>( pszName[0] == <font class="charliteral">'#'</font> )
01137         {
01138             bIsAttribute = TRUE;
01139             pszName++;
01140         }
01141 
01142         <font class="keywordflow">if</font>( psRoot-&gt;eType != CXT_Element )
01143             <font class="keywordflow">return</font> FALSE;
01144 
01145         <font class="keywordflow">for</font>( psChild = psRoot-&gt;psChild; psChild != NULL; 
01146              psChild = psChild-&gt;psNext ) 
01147         {
01148             <font class="keywordflow">if</font>( psChild-&gt;eType != CXT_Text 
01149                 &amp;&amp; EQUAL(pszName,psChild-&gt;pszValue) )
01150                 <font class="keywordflow">break</font>;
01151         }
01152 
01153         <font class="keywordflow">if</font>( psChild == NULL )
01154         {
01155             <font class="keywordflow">if</font>( bIsAttribute )
01156                 psChild = CPLCreateXMLNode( psRoot, CXT_Attribute, pszName );
01157             <font class="keywordflow">else</font>
01158                 psChild = CPLCreateXMLNode( psRoot, CXT_Element, pszName );
01159         }
01160 
01161         psRoot = psChild;
01162         iToken++;
01163     }
01164 
01165     CSLDestroy( papszTokens );
01166 
01167 <font class="comment">/* -------------------------------------------------------------------- */</font>
01168 <font class="comment">/*      Now set a value node under this node.                           */</font>
01169 <font class="comment">/* -------------------------------------------------------------------- */</font>
01170     <font class="keywordflow">if</font>( psRoot-&gt;psChild == NULL )
01171         CPLCreateXMLNode( psRoot, CXT_Text, pszValue );
01172     <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psRoot-&gt;psChild-&gt;eType != CXT_Text )
01173         <font class="keywordflow">return</font> FALSE;
01174     <font class="keywordflow">else</font> 
01175     {
01176         CPLFree( psRoot-&gt;psChild-&gt;pszValue );
01177         psRoot-&gt;psChild-&gt;pszValue = <a class="code" href="cpl_conv_h.html#a6">CPLStrdup</a>( pszValue );
01178     }
01179 
01180     <font class="keywordflow">return</font> TRUE;
01181 }
01182 
</div></pre><hr><address><small>Generated at Sat Dec 21 14:01:57 2002 for GDAL by
<a href="http://www.stack.nl/~dimitri/doxygen/index.html">
<img src="doxygen.gif" alt="doxygen" align="middle" border=0 
width=110 height=53></a>1.2.3-20001105 written by <a href="mailto:dimitri@stack.nl">Dimitri van Heesch</a>,
 &copy;&nbsp;1997-2000</small></address>
</body>
</html>