1 /*
2  *  Copyright (C) 2005-2007  MakeHuman Project
3  *
4  *  This program is free software; you  can  redistribute  it  and/or
5  *  modify  it  under  the terms of the GNU General Public License as
6  *  published by the Free Software Foundation; either  version  3  of
7  *  the License, or (at your option) any later version.
8  *
9  *  This  program  is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the  implied  warranty  of
11  *  MERCHANTABILITY  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  *  General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software Foun-
16  *  dation, Inc., 59 Temple Place, Suite 330, Boston,  MA  02111-1307
17  *  USA
18  *
19  *  File: xmlParser.h
20  *  Project: MakeHuman <info@makehuman.org>, http://www.makehuman.org/
21  *  Library: ANIMORPH
22  *
23  *  For individual developers look into the AUTHORS file.
24  *
25  */
26 /**
27  ****************************************************************************
28  * <P> XML.c - implementation file for basic XML parser written in ANSI C++
29  * for portability. It works by using recursion and a node tree for breaking
30  * down the elements of an XML document.  </P>
31  *
32  * @version     V2.16
33  * @author      Frank Vanden Berghen
34  *
35  * BSD license:
36  * Copyright (c) 2002, Frank Vanden Berghen
37  * All rights reserved.
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions are met:
40  *
41  *     * Redistributions of source code must retain the above copyright
42  *       notice, this list of conditions and the following disclaimer.
43  *     * Redistributions in binary form must reproduce the above copyright
44  *       notice, this list of conditions and the following disclaimer in the
45  *       documentation and/or other materials provided with the distribution.
46  *     * Neither the name of the Frank Vanden Berghen nor the
47  *       names of its contributors may be used to endorse or promote products
48  *       derived from this software without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
51  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
52  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
54  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
55  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
56  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
57  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
59  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60  *
61  ****************************************************************************
62  */
63 #ifndef __INCLUDE_XML_NODE__
64 #define __INCLUDE_XML_NODE__
65 
66 #include <stdlib.h>
67 
68 #ifdef WIN32
69 #include <tchar.h>
70 #else
71 #include <wchar.h> // to have 'wcsrtombs' for ANSI version
72                    // to have 'mbsrtowcs' for UNICODE version
73 #endif
74 
75 #ifdef _UNICODE
76 // If you comment the next "define" line then the library will never "switch to" _UNICODE (wchar_t*) mode (16/32 bits per characters).
77 // This is useful when you get error messages like:
78 //    'XMLNode::openFileHelper' : cannot convert parameter 2 from 'const char [5]' to 'const wchar_t *'
79 // The _XMLUNICODE preprocessor variable force the XMLParser library into either utf16/32-mode (the proprocessor variable
80 // must be defined) or utf8-mode(the variable must be undefined).
81 #define _XMLUNICODE
82 #endif
83 
84 // Some common types for char set portable code
85 #ifdef _XMLUNICODE
86     #ifndef _T
87         #define _T(c) L ## c
88     #endif
89     #define XMLCSTR const wchar_t *
90     #define XMLSTR  wchar_t *
91     #define XMLCHAR wchar_t
92 #else
93     #ifndef _T
94         #define _T(c) c
95     #endif
96     #define XMLCSTR const char *
97     #define XMLSTR  char *
98     #define XMLCHAR char
99 #endif
100 #ifndef FALSE
101     #define FALSE 0
102 #endif /* FALSE */
103 #ifndef TRUE
104     #define TRUE 1
105 #endif /* TRUE */
106 
107 
108 // Enumeration for XML parse errors.
109 typedef enum XMLError
110 {
111     eXMLErrorNone = 0,
112     eXMLErrorMissingEndTag,
113     eXMLErrorEmpty,
114     eXMLErrorFirstNotStartTag,
115     eXMLErrorMissingTagName,
116     eXMLErrorMissingEndTagName,
117     eXMLErrorNoMatchingQuote,
118     eXMLErrorUnmatchedEndTag,
119     eXMLErrorUnmatchedEndClearTag,
120     eXMLErrorUnexpectedToken,
121     eXMLErrorInvalidTag,
122     eXMLErrorNoElements,
123     eXMLErrorFileNotFound,
124     eXMLErrorFirstTagNotFound,
125     eXMLErrorUnknownEscapeSequence,
126     eXMLErrorCharConversionError,
127     eXMLErrorCannotOpenWriteFile,
128     eXMLErrorCannotWriteFile,
129 
130     eXMLErrorBase64DataSizeIsNotMultipleOf4,
131     eXMLErrorBase64DecodeIllegalCharacter,
132     eXMLErrorBase64DecodeTruncatedData,
133     eXMLErrorBase64DecodeBufferTooSmall
134 } XMLError;
135 
136 // Enumeration used to manage type of data. Use in conjunction with structure XMLNodeContents
137 typedef enum XMLElementType
138 {
139     eNodeChild=0,
140     eNodeAttribute=1,
141     eNodeText=2,
142     eNodeClear=3,
143     eNodeNULL=4
144 } XMLElementType;
145 
146 // Structure used to obtain error details if the parse fails.
147 typedef struct XMLResults
148 {
149     enum XMLError error;
150     int  nLine,nColumn;
151 } XMLResults;
152 
153 // Structure for XML clear (unformatted) node (usually comments)
154 typedef struct {
155     XMLCSTR lpszValue; XMLCSTR lpszOpenTag; XMLCSTR lpszCloseTag;
156 } XMLClear;
157 
158 // Structure for XML attribute.
159 typedef struct {
160     XMLCSTR lpszName; XMLCSTR lpszValue;
161 } XMLAttribute;
162 
163 // The variable XMLClearTags below contains the clearTags recognized by the library
164 // You can modify the initialization of this variable inside the "xmlParser.cpp" file
165 // to change the clearTags that are currently recognized.
166 typedef struct {
167     XMLCSTR lpszOpen; int openTagLen; XMLCSTR lpszClose;
168 } ALLXMLClearTag;
169 extern ALLXMLClearTag XMLClearTags[];
170 
171 struct XMLNodeContents;
172 
173 typedef struct XMLNode
174 {
175   private:
176 
177     struct XMLNodeDataTag;
178 
179     // protected constructors: use one of these four methods to get your first instance of XMLNode:
180     //  - parseString
181     //  - parseFile
182     //  - openFileHelper
183     //  - createXMLTopNode
184     XMLNode(struct XMLNodeDataTag *pParent, XMLCSTR lpszName, int isDeclaration);
185     XMLNode(struct XMLNodeDataTag *p);
186 
187   public:
188 
189     // You can create your first instance of XMLNode with these 4 functions:
190     // (see complete explanation of parameters below)
191 
192     static XMLNode createXMLTopNode(XMLCSTR lpszName, int isDeclaration=FALSE);
193     static XMLNode parseString   (XMLCSTR  lpXMLString, XMLCSTR tag=NULL, XMLResults *pResults=NULL);
194     static XMLNode parseFile     (XMLCSTR     filename, XMLCSTR tag=NULL, XMLResults *pResults=NULL);
195     static XMLNode openFileHelper(XMLCSTR     filename, XMLCSTR tag=NULL                           );
196 
197     // The tag parameter should be the name of the first tag inside the XML file.
198     // If the tag parameter is omitted, the 3 functions return a node that represents
199     // the head of the xml document including the declaration term (<? ... ?>).
200 
201     // The "openFileHelper" reports to the screen all the warnings & errors that occurred during
202     // parsing of the XML file. Since each application has its own way to report and deal with errors,
203     // you should rather use the "parseFile" function to parse XML files and program yourself thereafter
204     // an "error reporting" tailored for your needs (instead of using the very crude "error reporting"
205     // mechanism included inside the "openFileHelper" function).
206 
207     // If the XML document is corrupted:
208     //   * The "openFileHelper" method will:
209     //         - display an error message on the console (or inside a messageBox for windows).
210     //         - stop execution (exit).
211     //   * The 2 other methods will initialize the "pResults" variable with some information that
212     //     can be used to trace the error.
213     //   * If you still want to parse the file, you can use the APPROXIMATE_PARSING option as
214     //     explained inside the note at the beginning of the "xmlParser.cpp" file.
215     // You can have a user-friendly explanation of the parsing error with this function:
216     static XMLCSTR getError(XMLError error);
217 
218     XMLCSTR getName();                                               // name of the node
219     XMLCSTR getText(int i=0);                                        // return ith text field
220     int nText();                                                     // nbr of text field
221     XMLNode getParentNode();                                         // return the parent node
222     XMLNode getChildNode(int i=0);                                   // return ith child node
223     XMLNode getChildNode(XMLCSTR name, int i);                       // return ith child node with specific name
224                                                                      //     (return an empty node if failing)
225     XMLNode getChildNode(XMLCSTR name, int *i=NULL);                 // return next child node with specific name
226                                                                      //     (return an empty node if failing)
227     XMLNode getChildNodeWithAttribute(XMLCSTR tagName,               // return child node with specific name/attribute
228                                       XMLCSTR attributeName,         //     (return an empty node if failing)
229                                       XMLCSTR attributeValue=NULL,   //
230                                       int *i=NULL);                  //
231     int nChildNode(XMLCSTR name);                                    // return the number of child node with specific name
232     int nChildNode();                                                // nbr of child node
233     XMLAttribute getAttribute(int i=0);                              // return ith attribute
234     XMLCSTR      getAttributeName(int i=0);                          // return ith attribute name
235     XMLCSTR      getAttributeValue(int i=0);                         // return ith attribute value
236     char  isAttributeSet(XMLCSTR name);                              // test if an attribute with a specific name is given
237     XMLCSTR getAttribute(XMLCSTR name, int i);                       // return ith attribute content with specific name
238                                                                      //     (return a NULL if failing)
239     XMLCSTR getAttribute(XMLCSTR name, int *i=NULL);                 // return next attribute content with specific name
240                                                                      //     (return a NULL if failing)
241     int nAttribute();                                                // nbr of attribute
242     XMLClear getClear(int i=0);                                      // return ith clear field (comments)
243     int nClear();                                                    // nbr of clear field
244     XMLSTR createXMLString(int nFormat=1, int *pnSize=NULL);         // create XML string starting from current XMLNode
245                                                                      // if nFormat==0, no formatting is required
246                                                                      // otherwise this returns an user friendly XML string from a
247                                                                      // given element with appropriate white spaces and carriage returns.
248                                                                      // if pnSize is given it returns the size in character of the string.
249     XMLError writeToFile(XMLCSTR filename, const char *encoding=NULL, char nFormat=1);
250                                                                      // save the content of an xmlNode inside a file.
251                                                                      // the nFormat parameter has the same meaning as in the
252                                                                      // createXMLString function. If "strictUTF8Parsing=1", the
253                                                                      // the encoding parameter is ignored and always set to
254                                                                      // "utf-8". If "_XMLUNICODE=1", the encoding parameter is
255                                                                      // ignored and always set to "utf-16".
256     XMLNodeContents enumContents(int i);                             // enumerate all the different contents (attribute,child,text,
257                                                                      //     clear) of the current XMLNode. The order is reflecting
258                                                                      //     the order of the original file/string.
259                                                                      //     NOTE: 0 <= i < nElement();
260     int nElement();                                                  // nbr of different contents for current node
261     char isEmpty();                                                  // is this node Empty?
262     char isDeclaration();                                            // is this node a declaration <? .... ?>
263 
264 // to allow shallow/fast copy:
265     ~XMLNode();
266     XMLNode(const XMLNode &A);
267     XMLNode& operator=( const XMLNode& A );
268 
XMLNodeXMLNode269     XMLNode(): d(NULL){};
270     static XMLNode emptyXMLNode;
271     static XMLClear emptyXMLClear;
272     static XMLAttribute emptyXMLAttribute;
273 
274     // The following functions allows you to create from scratch (or update) a XMLNode structure
275     // Start by creating your top node with the "createXMLTopNode" function and then add new nodes with the "addChild" function.
276     // The parameter 'pos' gives the position where the childNode, the text or the XMLClearTag will be inserted.
277     // The default value (pos=-1) inserts at the end. The value (pos=0) insert at the beginning (Insertion at the beginning is slower than at the end).
278     // REMARK: 0 <= pos < nChild()+nText()+nClear()
279     XMLNode       addChild(XMLCSTR lpszName, int isDeclaration=FALSE, int pos=-1);
280     XMLAttribute *addAttribute(XMLCSTR lpszName, XMLCSTR lpszValuev);
281     XMLCSTR       addText(XMLCSTR lpszValue, int pos=-1);
282     XMLClear     *addClear(XMLCSTR lpszValue, XMLCSTR lpszOpen=XMLClearTags[0].lpszOpen, XMLCSTR lpszClose=XMLClearTags[0].lpszClose, int pos=-1);
283     XMLNode       addChild(XMLNode nodeToAdd, int pos=-1);          // If the "nodeToAdd" has some parents, it will be detached
284                                                                     // from it's parents before being attached to the current XMLNode
285     // Some update functions:
286     XMLCSTR       updateName(XMLCSTR lpszName);                                                    // change node's name
287     XMLAttribute *updateAttribute(XMLAttribute *newAttribute, XMLAttribute *oldAttribute);         // if the attribute to update is missing, a new one will be added
288     XMLAttribute *updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName=NULL,int i=0);         // if the attribute to update is missing, a new one will be added
289     XMLAttribute *updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName);  // set lpszNewName=NULL if you don't want to change the name of the attribute
290                                                                                                    // if the attribute to update is missing, a new one will be added
291     XMLCSTR       updateText(XMLCSTR lpszNewValue, int i=0);                                       // if the text to update is missing, a new one will be added
292     XMLCSTR       updateText(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue);                          // if the text to update is missing, a new one will be added
293     XMLClear     *updateClear(XMLCSTR lpszNewContent, int i=0);                                    // if the clearTag to update is missing, a new one will be added
294     XMLClear     *updateClear(XMLClear *newP,XMLClear *oldP);                                      // if the clearTag to update is missing, a new one will be added
295     XMLClear     *updateClear(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue);                         // if the clearTag to update is missing, a new one will be added
296 
297     // Some deletion functions:
298     void deleteNodeContent(char force=0);  // delete the content of this XMLNode and the subtree.
299                                            // if force=0, while (references to this node still exist), no memory free occurs
300                                            // if force=1, always delete the content of this XMLNode and the subtree and free associated memory
301     void deleteAttribute(XMLCSTR lpszName);
302     void deleteAttribute(int i=0);
303     void deleteAttribute(XMLAttribute *anAttribute);
304     void deleteText(int i=0);
305     void deleteText(XMLCSTR lpszValue);
306     void deleteClear(int i=0);
307     void deleteClear(XMLClear *p);
308     void deleteClear(XMLCSTR lpszValue);
309 
310     // The strings given as parameters for the following add and update methods (all these methods have
311     // a name with the postfix "_WOSD" that means "WithOut String Duplication" ) will be free'd by the
312     // XMLNode class. For example, it means that this is incorrect:
313     //    xNode.addText_WOSD("foo");
314     //    xNode.updateAttribute_WOSD("#newcolor" ,NULL,"color");
315     // In opposition, this is correct:
316     //    xNode.addText("foo");
317     //    xNode.addText_WOSD(stringDup("foo"));
318     //    xNode.updateAttribute("#newcolor" ,NULL,"color");
319     //    xNode.updateAttribute_WOSD(stringDup("#newcolor"),NULL,"color");
320     // Typically, you will never do:
321     //    char *b=(char*)malloc(...);
322     //    xNode.addText(b);
323     //    free(b);
324     // ... but rather:
325     //    char *b=(char*)malloc(...);
326     //    xNode.addText_WOSD(b);
327     //    ('free(b)' is performed by the XMLNode class)
328 
329     static XMLNode createXMLTopNode_WOSD(XMLCSTR lpszName, int isDeclaration=FALSE);
330     XMLNode        addChild_WOSD(XMLCSTR lpszName, int isDeclaration=FALSE, int pos=-1);
331     XMLAttribute  *addAttribute_WOSD(XMLCSTR lpszName, XMLCSTR lpszValue);
332     XMLCSTR        addText_WOSD(XMLCSTR lpszValue, int pos=-1);
333     XMLClear      *addClear_WOSD(XMLCSTR lpszValue, XMLCSTR lpszOpen=XMLClearTags[0].lpszOpen, XMLCSTR lpszClose=XMLClearTags[0].lpszClose, int pos=-1);
334 
335     XMLCSTR        updateName_WOSD(XMLCSTR lpszName);
336     XMLAttribute  *updateAttribute_WOSD(XMLAttribute *newAttribute, XMLAttribute *oldAttribute);
337     XMLAttribute  *updateAttribute_WOSD(XMLCSTR lpszNewValue, XMLCSTR lpszNewName=NULL,int i=0);
338     XMLAttribute  *updateAttribute_WOSD(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName);
339     XMLCSTR        updateText_WOSD(XMLCSTR lpszNewValue, int i=0);
340     XMLCSTR        updateText_WOSD(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue);
341     XMLClear      *updateClear_WOSD(XMLCSTR lpszNewContent, int i=0);
342     XMLClear      *updateClear_WOSD(XMLClear *newP,XMLClear *oldP);
343     XMLClear      *updateClear_WOSD(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue);
344 
345     // These are some useful functions when you want to insert a childNode, a text or a XMLClearTag in the
346     // middle (at a specified position) of a XMLNode tree already constructed. The value returned by these
347     // methods is to be used as last parameter (parameter 'pos') of addChild, addText or addClear.
348     int positionOfText(int i=0);
349     int positionOfText(XMLCSTR lpszValue);
350     int positionOfClear(int i=0);
351     int positionOfClear(XMLCSTR lpszValue);
352     int positionOfClear(XMLClear *a);
353     int positionOfChildNode(int i=0);
354     int positionOfChildNode(XMLNode x);
355     int positionOfChildNode(XMLCSTR name, int i=0); // return the position of the ith childNode with the specified name
356                                                     // if (name==NULL) return the position of the ith childNode
357 
358     // The setGlobalOptions function allows you to change two global parameters that affect string&file
359     // parsing. First of all, you most-probably will never have to change these 2 global parameters.
360     // About the "guessUnicodeChars" parameter:
361     //     If "guessUnicodeChars=1" and if this library is compiled in UNICODE mode, then the
362     //     "parseFile" and "openFileHelper" functions will test if the file contains ASCII
363     //     characters. If this is the case, then the file will be loaded and converted in memory to
364     //     UNICODE before being parsed. If "guessUnicodeChars=0", no conversion will
365     //     be performed.
366     //
367     //     If "guessUnicodeChars=1" and if this library is compiled in ASCII/UTF8 mode, then the
368     //     "parseFile" and "openFileHelper" functions will test if the file contains UNICODE
369     //     characters. If this is the case, then the file will be loaded and converted in memory to
370     //     ASCII/UTF8 before being parsed. If "guessUnicodeChars=0", no conversion will
371     //     be performed
372     //
373     //     Sometime, it's useful to set "guessUnicodeChars=0" to disable any conversion
374     //     because the test to detect the file-type (ASCII/UTF8 or UNICODE) may fail (rarely).
375     //
376     // About the "strictUTF8Parsing" parameter:
377     //     If "strictUTF8Parsing=0" then we assume that all characters have the same length of 1 byte.
378     //     If "strictUTF8Parsing=1" then the characters have different lengths (from 1 byte to 4 bytes)
379     //     depending on the content of the first byte of the character.
380 
381     static void setGlobalOptions(char guessUnicodeChars=1, char strictUTF8Parsing=1);
382 
383     // The next function try to guess if the character encoding is UTF-8. You most-probably will never
384     // have to use this function. It then returns the appropriate value of the global parameter
385     // "strictUTF8Parsing" described above. The guess is based on the content of a buffer of length
386     // "bufLen" bytes that contains the first bytes (minimum 25 bytes; 200 bytes is a good value) of the
387     // file to be parsed. The "openFileHelper" function is using this function to automatically compute
388     // the value of the "strictUTF8Parsing" global parameter. There are several heuristics used to do the
389     // guess. One of the heuristic is based on the "encoding" attribute. The original XML specifications
390     // forbids to use this attribute to do the guess but you can still use it if you set
391     // "useXMLEncodingAttribute" to 1 (this is the default behavior).
392 
393     static char guessUTF8ParsingParameterValue(void *buffer, int bufLen, char useXMLEncodingAttribute=1);
394 
395   private:
396 
397 // these are functions and structures used internally by the XMLNode class (don't bother about them):
398 
399       typedef struct XMLNodeDataTag // to allow shallow copy and "intelligent/smart" pointers (automatic delete):
400       {
401           XMLCSTR                lpszName;        // Element name (=NULL if root)
402           int                    nChild,          // Number of child nodes
403                                  nText,           // Number of text fields
404                                  nClear,          // Number of Clear fields (comments)
405                                  nAttribute,      // Number of attributes
406                                  isDeclaration;   // Whether node is an XML declaration - '<?xml ?>'
407           struct XMLNodeDataTag  *pParent;        // Pointer to parent element (=NULL if root)
408           XMLNode                *pChild;         // Array of child nodes
409           XMLCSTR                *pText;          // Array of text fields
410           XMLClear               *pClear;         // Array of clear fields
411           XMLAttribute           *pAttribute;     // Array of attributes
412           int                    *pOrder;         // order of the child_nodes,text_fields,clear_fields
413           int                    ref_count;       // for garbage collection (smart pointers)
414       } XMLNodeData;
415       XMLNodeData *d;
416 
417       int ParseClearTag(void *pXML, void *pClear);
418       int ParseXMLElement(void *pXML);
419       void *addToOrder(int *_pos, int nc, void *p, int size, XMLElementType xtype);
420       int indexText(XMLCSTR lpszValue);
421       int indexClear(XMLCSTR lpszValue);
422       static inline int findPosition(XMLNodeData *d, int index, XMLElementType xtype);
423       static int CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker, int nFormat);
424       static void removeOrderElement(XMLNodeData *d, XMLElementType t, int index);
425       static void exactMemory(XMLNodeData *d);
426       static void detachFromParent(XMLNodeData *d);
427 } XMLNode;
428 
429 // This structure is given by the function "enumContents".
430 typedef struct XMLNodeContents
431 {
432     // This dictates what's the content of the XMLNodeContent
433     enum XMLElementType type;
434     // should be an union to access the appropriate data.
435     // compiler does not allow union of object with constructor... too bad.
436     XMLNode child;
437     XMLAttribute attrib;
438     XMLCSTR text;
439     XMLClear clear;
440 
441 } XMLNodeContents;
442 
443 // Duplicate (copy in a new allocated buffer) the source string. This is
444 // a very handy function when used with all the "XMLNode::*_WOSD" functions.
445 // (If (cbData!=0) then cbData is the number of chars to duplicate)
446 XMLSTR stringDup(XMLCSTR source, int cbData=0);
447 
448 // The 3 following functions are processing strings so that all the characters
449 // &,",',<,> are replaced by their XML equivalent: &amp;, &quot;, &apos;, &lt;, &gt;.
450 // These 3 functions are useful when creating from scratch an XML file using the
451 // "printf", "fprintf", "cout",... functions. If you are creating from scratch an
452 // XML file using the provided XMLNode class you cannot use these functions (the
453 // XMLNode class does the processing job for you during rendering). The second
454 // function ("toXMLStringFast") allows you to re-use the same output buffer
455 // for all the conversions so that only a few memory allocations are performed.
456 // If the output buffer is too small to contain the resulting string, it will
457 // be enlarged.
458 XMLSTR toXMLString(XMLCSTR source);
459 XMLSTR toXMLStringFast(XMLSTR *destBuffer,int *destSz, XMLCSTR source);
460 
461 // you should not use this one (there is a possibility of "destination-buffer-overflow"):
462 XMLSTR toXMLString(XMLSTR dest,XMLCSTR source);
463 
464 // Below is a class that allows you to include any binary data (images, sounds,...)
465 // into an XML document using "Base64 encoding". This class is completely
466 // separated from the rest of the xmlParser library and can be removed without any problem.
467 // To include some binary data into an XML file, you must convert the binary data into
468 // standard text (using "encode"). To retrieve the original binary data from the
469 // b64-encoded text included inside the XML file use "decode". Alternatively, these
470 // functions can also be used to "encrypt/decrypt" some critical data contained inside
471 // the XML.
472 
473 class XMLParserBase64Tool
474 {
475 public:
XMLParserBase64Tool()476     XMLParserBase64Tool(): buf(NULL),buflen(0){}
477     ~XMLParserBase64Tool();
478 
479     void freeBuffer();
480 
481     // returns the length of the base64 string that encodes inbuf.
482     // If "formatted" parameter is true, some space will be reserved for a carriage-return every 72 chars.
483     static int encodeLength(unsigned char *inbuf, int inBufLen, char formatted=0);
484 
485     // The "base64Encode" function returns a string containing the base64 encoding of "inByteLen" bytes
486     // from "inByteBuf". If "formatted" parameter is true, then there will be a carriage-return every 72 chars.
487     // The string will be free'd when the XMLParserBase64Tool object is deleted.
488     // All returned strings are sharing the same memory space.
489     XMLSTR encode(unsigned char *inByteBuf, unsigned int inByteLen, char formatted=0);
490 
491     // returns the number of bytes which will be decoded from "inString".
492     static unsigned int decodeSize(XMLCSTR inString, XMLError *xe=NULL);
493 
494     // returns a pointer to a buffer containing the binary data decoded from "inString"
495     // If "inString" is malformed NULL will be returned
496     // The output buffer will be free'd when the XMLParserBase64Tool object is deleted.
497     // All output buffer are sharing the same memory space.
498     unsigned char* decode(XMLCSTR inString, int *outByteLen=NULL, XMLError *xe=NULL);
499 
500     // The next function is deprecated.
501     // decodes data from "inString" to "outByteBuf". You need to provide the size (in byte) of "outByteBuf"
502     // in "inMaxByteOutBuflen". If "outByteBuf" is not large enough or if data is malformed, then "FALSE"
503     // will be returned; otherwise "TRUE".
504     static unsigned char decode(XMLCSTR inString, unsigned char *outByteBuf, int inMaxByteOutBuflen, XMLError *xe=NULL);
505 
506 private:
507     void *buf;
508     int buflen;
509     void alloc(int newsize);
510 };
511 
512 
513 #endif
514