110152Satgutier@umich.edu/**
210152Satgutier@umich.edu ****************************************************************************
310152Satgutier@umich.edu * <P> XML.c - implementation file for basic XML parser written in ANSI C++
410152Satgutier@umich.edu * for portability. It works by using recursion and a node tree for breaking
510152Satgutier@umich.edu * down the elements of an XML document.  </P>
610152Satgutier@umich.edu *
710152Satgutier@umich.edu * @version     V2.41
810152Satgutier@umich.edu * @author      Frank Vanden Berghen
910152Satgutier@umich.edu *
1010152Satgutier@umich.edu * NOTE:
1110152Satgutier@umich.edu *
1210152Satgutier@umich.edu *   If you add "#define STRICT_PARSING", on the first line of this file
1310152Satgutier@umich.edu *   the parser will see the following XML-stream:
1410152Satgutier@umich.edu *      <a><b>some text</b><b>other text    </a>
1510152Satgutier@umich.edu *   as an error. Otherwise, this tring will be equivalent to:
1610152Satgutier@umich.edu *      <a><b>some text</b><b>other text</b></a>
1710152Satgutier@umich.edu *
1810152Satgutier@umich.edu * NOTE:
1910152Satgutier@umich.edu *
2010152Satgutier@umich.edu *   If you add "#define APPROXIMATE_PARSING" on the first line of this file
2110152Satgutier@umich.edu *   the parser will see the following XML-stream:
2210152Satgutier@umich.edu *     <data name="n1">
2310152Satgutier@umich.edu *     <data name="n2">
2410152Satgutier@umich.edu *     <data name="n3" />
2510152Satgutier@umich.edu *   as equivalent to the following XML-stream:
2610152Satgutier@umich.edu *     <data name="n1" />
2710152Satgutier@umich.edu *     <data name="n2" />
2810152Satgutier@umich.edu *     <data name="n3" />
2910152Satgutier@umich.edu *   This can be useful for badly-formed XML-streams but prevent the use
3010152Satgutier@umich.edu *   of the following XML-stream (problem is: tags at contiguous levels
3110152Satgutier@umich.edu *   have the same names):
3210152Satgutier@umich.edu *     <data name="n1">
3310152Satgutier@umich.edu *        <data name="n2">
3410152Satgutier@umich.edu *            <data name="n3" />
3510152Satgutier@umich.edu *        </data>
3610152Satgutier@umich.edu *     </data>
3710152Satgutier@umich.edu *
3810152Satgutier@umich.edu * NOTE:
3910152Satgutier@umich.edu *
4010152Satgutier@umich.edu *   If you add "#define _XMLPARSER_NO_MESSAGEBOX_" on the first line of this file
4110152Satgutier@umich.edu *   the "openFileHelper" function will always display error messages inside the
4210152Satgutier@umich.edu *   console instead of inside a message-box-window. Message-box-windows are
4310152Satgutier@umich.edu *   available on windows 9x/NT/2000/XP/Vista only.
4410152Satgutier@umich.edu *
4510152Satgutier@umich.edu * The following license terms for the "XMLParser library from Business-Insight" apply to projects
4610152Satgutier@umich.edu * that are in some way related to
4710152Satgutier@umich.edu * the "mcpat project", including applications
4810152Satgutier@umich.edu * using "mcpat project" and tools developed
4910152Satgutier@umich.edu * for enhancing "mcpat project". All other projects
5010152Satgutier@umich.edu * (not related to "mcpat project") have to use the "XMLParser library from Business-Insight"
5110152Satgutier@umich.edu * code under the Aladdin Free Public License (AFPL)
5210152Satgutier@umich.edu * See the file "AFPL-license.txt" for more informations about the AFPL license.
5310152Satgutier@umich.edu * (see http://www.artifex.com/downloads/doc/Public.htm for detailed AFPL terms)
5410152Satgutier@umich.edu *
5510152Satgutier@umich.edu * Redistribution and use of the "XMLParser library from Business-Insight" in source and binary forms, with or without
5610152Satgutier@umich.edu * modification, are permitted provided that the following conditions are met:
5710152Satgutier@umich.edu *     * Redistributions of source code must retain the above copyright
5810152Satgutier@umich.edu *       notice, this list of conditions and the following disclaimer.
5910152Satgutier@umich.edu *     * Redistributions in binary form must reproduce the above copyright
6010152Satgutier@umich.edu *       notice, this list of conditions and the following disclaimer in the
6110152Satgutier@umich.edu *       documentation and/or other materials provided with the distribution.
6210152Satgutier@umich.edu *     * Neither the name of Frank Vanden Berghen nor the
6310152Satgutier@umich.edu *       names of its contributors may be used to endorse or promote products
6410152Satgutier@umich.edu *       derived from this software without specific prior written permission.
6510152Satgutier@umich.edu *
6610152Satgutier@umich.edu * THIS SOFTWARE IS PROVIDED BY Business-Insight ``AS IS'' AND ANY
6710152Satgutier@umich.edu * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
6810152Satgutier@umich.edu * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
6910152Satgutier@umich.edu * DISCLAIMED. IN NO EVENT SHALL Business-Insight BE LIABLE FOR ANY
7010152Satgutier@umich.edu * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
7110152Satgutier@umich.edu * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
7210152Satgutier@umich.edu * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
7310152Satgutier@umich.edu * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7410152Satgutier@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
7510152Satgutier@umich.edu * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7610152Satgutier@umich.edu *
7710152Satgutier@umich.edu * Copyright (c) 2002, Business-Insight
7810234Syasuko.eckert@amd.com * Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
7910152Satgutier@umich.edu * <a href="http://www.Business-Insight.com">Business-Insight</a>
8010152Satgutier@umich.edu * All rights reserved.
8110152Satgutier@umich.edu *
8210152Satgutier@umich.edu ****************************************************************************
8310152Satgutier@umich.edu */
8410152Satgutier@umich.edu#ifndef _CRT_SECURE_NO_DEPRECATE
8510152Satgutier@umich.edu#define _CRT_SECURE_NO_DEPRECATE
8610152Satgutier@umich.edu#endif
8710152Satgutier@umich.edu#include "xmlParser.h"
8810152Satgutier@umich.edu#ifdef _XMLWINDOWS
8910152Satgutier@umich.edu//#ifdef _DEBUG
9010152Satgutier@umich.edu//#define _CRTDBG_MAP_ALLOC
9110152Satgutier@umich.edu//#include <crtdbg.h>
9210152Satgutier@umich.edu//#endif
9310152Satgutier@umich.edu#define WIN32_LEAN_AND_MEAN
9410152Satgutier@umich.edu#include <Windows.h> // to have IsTextUnicode, MultiByteToWideChar, WideCharToMultiByte to handle unicode files
9510234Syasuko.eckert@amd.com// to have "MessageBoxA" to display error messages for openFilHelper
9610152Satgutier@umich.edu#endif
9710152Satgutier@umich.edu
9810152Satgutier@umich.edu#include <memory.h>
9910152Satgutier@umich.edu
10010152Satgutier@umich.edu#include <cassert>
10110152Satgutier@umich.edu#include <cstdio>
10210152Satgutier@umich.edu#include <cstdlib>
10310152Satgutier@umich.edu#include <cstring>
10410152Satgutier@umich.edu
10510234Syasuko.eckert@amd.comXMLCSTR XMLNode::getVersion() {
10610234Syasuko.eckert@amd.com    return _CXML("v2.39");
10710234Syasuko.eckert@amd.com}
10810234Syasuko.eckert@amd.comvoid freeXMLString(XMLSTR t) {
10910234Syasuko.eckert@amd.com    if (t)free(t);
11010234Syasuko.eckert@amd.com}
11110152Satgutier@umich.edu
11210152Satgutier@umich.edustatic XMLNode::XMLCharEncoding characterEncoding=XMLNode::char_encoding_UTF8;
11310152Satgutier@umich.edustatic char guessWideCharChars=1, dropWhiteSpace=1, removeCommentsInMiddleOfText=1;
11410152Satgutier@umich.edu
11510234Syasuko.eckert@amd.cominline int mmin( const int t1, const int t2 ) {
11610234Syasuko.eckert@amd.com    return t1 < t2 ? t1 : t2;
11710234Syasuko.eckert@amd.com}
11810152Satgutier@umich.edu
11910152Satgutier@umich.edu// You can modify the initialization of the variable "XMLClearTags" below
12010152Satgutier@umich.edu// to change the clearTags that are currently recognized by the library.
12110152Satgutier@umich.edu// The number on the second columns is the length of the string inside the
12210152Satgutier@umich.edu// first column. The "<!DOCTYPE" declaration must be the second in the list.
12310152Satgutier@umich.edu// The "<!--" declaration must be the third in the list.
12410234Syasuko.eckert@amd.comtypedef struct {
12510234Syasuko.eckert@amd.com    XMLCSTR lpszOpen;
12610234Syasuko.eckert@amd.com    int openTagLen;
12710234Syasuko.eckert@amd.com    XMLCSTR lpszClose;
12810234Syasuko.eckert@amd.com} ALLXMLClearTag;
12910234Syasuko.eckert@amd.comstatic ALLXMLClearTag XMLClearTags[] = {
13010234Syasuko.eckert@amd.com    {    _CXML("<![CDATA["), 9,  _CXML("]]>")      },
13110234Syasuko.eckert@amd.com    {    _CXML("<!DOCTYPE"), 9,  _CXML(">")        },
13210234Syasuko.eckert@amd.com    {    _CXML("<!--")     , 4,  _CXML("-->")      },
13310234Syasuko.eckert@amd.com    {    _CXML("<PRE>")    , 5,  _CXML("</PRE>")   },
13410152Satgutier@umich.edu//  {    _CXML("<Script>") ,8,  _CXML("</Script>")},
13510234Syasuko.eckert@amd.com    {    NULL              , 0,  NULL           }
13610152Satgutier@umich.edu};
13710152Satgutier@umich.edu
13810152Satgutier@umich.edu// You can modify the initialization of the variable "XMLEntities" below
13910152Satgutier@umich.edu// to change the character entities that are currently recognized by the library.
14010152Satgutier@umich.edu// The number on the second columns is the length of the string inside the
14110152Satgutier@umich.edu// first column. Additionally, the syntaxes "&#xA0;" and "&#160;" are recognized.
14210234Syasuko.eckert@amd.comtypedef struct {
14310234Syasuko.eckert@amd.com    XMLCSTR s;
14410234Syasuko.eckert@amd.com    int l;
14510234Syasuko.eckert@amd.com    XMLCHAR c;
14610234Syasuko.eckert@amd.com} XMLCharacterEntity;
14710234Syasuko.eckert@amd.comstatic XMLCharacterEntity XMLEntities[] = {
14810152Satgutier@umich.edu    { _CXML("&amp;" ), 5, _CXML('&' )},
14910152Satgutier@umich.edu    { _CXML("&lt;"  ), 4, _CXML('<' )},
15010152Satgutier@umich.edu    { _CXML("&gt;"  ), 4, _CXML('>' )},
15110152Satgutier@umich.edu    { _CXML("&quot;"), 6, _CXML('\"')},
15210152Satgutier@umich.edu    { _CXML("&apos;"), 6, _CXML('\'')},
15310152Satgutier@umich.edu    { NULL           , 0, '\0'    }
15410152Satgutier@umich.edu};
15510152Satgutier@umich.edu
15610152Satgutier@umich.edu// When rendering the XMLNode to a string (using the "createXMLString" function),
15710152Satgutier@umich.edu// you can ask for a beautiful formatting. This formatting is using the
15810152Satgutier@umich.edu// following indentation character:
15910152Satgutier@umich.edu#define INDENTCHAR _CXML('\t')
16010152Satgutier@umich.edu
16110152Satgutier@umich.edu// The following function parses the XML errors into a user friendly string.
16210152Satgutier@umich.edu// You can edit this to change the output language of the library to something else.
16310234Syasuko.eckert@amd.comXMLCSTR XMLNode::getError(XMLError xerror) {
16410234Syasuko.eckert@amd.com    switch (xerror) {
16510234Syasuko.eckert@amd.com    case eXMLErrorNone:
16610234Syasuko.eckert@amd.com        return _CXML("No error");
16710234Syasuko.eckert@amd.com    case eXMLErrorMissingEndTag:
16810234Syasuko.eckert@amd.com        return _CXML("Warning: Unmatched end tag");
16910234Syasuko.eckert@amd.com    case eXMLErrorNoXMLTagFound:
17010234Syasuko.eckert@amd.com        return _CXML("Warning: No XML tag found");
17110234Syasuko.eckert@amd.com    case eXMLErrorEmpty:
17210234Syasuko.eckert@amd.com        return _CXML("Error: No XML data");
17310234Syasuko.eckert@amd.com    case eXMLErrorMissingTagName:
17410234Syasuko.eckert@amd.com        return _CXML("Error: Missing start tag name");
17510234Syasuko.eckert@amd.com    case eXMLErrorMissingEndTagName:
17610234Syasuko.eckert@amd.com        return _CXML("Error: Missing end tag name");
17710234Syasuko.eckert@amd.com    case eXMLErrorUnmatchedEndTag:
17810234Syasuko.eckert@amd.com        return _CXML("Error: Unmatched end tag");
17910234Syasuko.eckert@amd.com    case eXMLErrorUnmatchedEndClearTag:
18010234Syasuko.eckert@amd.com        return _CXML("Error: Unmatched clear tag end");
18110234Syasuko.eckert@amd.com    case eXMLErrorUnexpectedToken:
18210234Syasuko.eckert@amd.com        return _CXML("Error: Unexpected token found");
18310234Syasuko.eckert@amd.com    case eXMLErrorNoElements:
18410234Syasuko.eckert@amd.com        return _CXML("Error: No elements found");
18510234Syasuko.eckert@amd.com    case eXMLErrorFileNotFound:
18610234Syasuko.eckert@amd.com        return _CXML("Error: File not found");
18710234Syasuko.eckert@amd.com    case eXMLErrorFirstTagNotFound:
18810234Syasuko.eckert@amd.com        return _CXML("Error: First Tag not found");
18910234Syasuko.eckert@amd.com    case eXMLErrorUnknownCharacterEntity:
19010234Syasuko.eckert@amd.com        return _CXML("Error: Unknown character entity");
19110234Syasuko.eckert@amd.com    case eXMLErrorCharacterCodeAbove255:
19210234Syasuko.eckert@amd.com        return _CXML("Error: Character code above 255 is forbidden in MultiByte char mode.");
19310234Syasuko.eckert@amd.com    case eXMLErrorCharConversionError:
19410234Syasuko.eckert@amd.com        return _CXML("Error: unable to convert between WideChar and MultiByte chars");
19510234Syasuko.eckert@amd.com    case eXMLErrorCannotOpenWriteFile:
19610234Syasuko.eckert@amd.com        return _CXML("Error: unable to open file for writing");
19710234Syasuko.eckert@amd.com    case eXMLErrorCannotWriteFile:
19810234Syasuko.eckert@amd.com        return _CXML("Error: cannot write into file");
19910152Satgutier@umich.edu
20010234Syasuko.eckert@amd.com    case eXMLErrorBase64DataSizeIsNotMultipleOf4:
20110234Syasuko.eckert@amd.com        return _CXML("Warning: Base64-string length is not a multiple of 4");
20210234Syasuko.eckert@amd.com    case eXMLErrorBase64DecodeTruncatedData:
20310234Syasuko.eckert@amd.com        return _CXML("Warning: Base64-string is truncated");
20410234Syasuko.eckert@amd.com    case eXMLErrorBase64DecodeIllegalCharacter:
20510234Syasuko.eckert@amd.com        return _CXML("Error: Base64-string contains an illegal character");
20610234Syasuko.eckert@amd.com    case eXMLErrorBase64DecodeBufferTooSmall:
20710234Syasuko.eckert@amd.com        return _CXML("Error: Base64 decode output buffer is too small");
20810152Satgutier@umich.edu    };
20910152Satgutier@umich.edu    return _CXML("Unknown");
21010152Satgutier@umich.edu}
21110152Satgutier@umich.edu
21210152Satgutier@umich.edu/////////////////////////////////////////////////////////////////////////
21310152Satgutier@umich.edu//      Here start the abstraction layer to be OS-independent          //
21410152Satgutier@umich.edu/////////////////////////////////////////////////////////////////////////
21510152Satgutier@umich.edu
21610152Satgutier@umich.edu// Here is an abstraction layer to access some common string manipulation functions.
21710152Satgutier@umich.edu// The abstraction layer is currently working for gcc, Microsoft Visual Studio 6.0,
21810152Satgutier@umich.edu// Microsoft Visual Studio .NET, CC (sun compiler) and Borland C++.
21910152Satgutier@umich.edu// If you plan to "port" the library to a new system/compiler, all you have to do is
22010152Satgutier@umich.edu// to edit the following lines.
22110152Satgutier@umich.edu#ifdef XML_NO_WIDE_CHAR
22210234Syasuko.eckert@amd.comchar myIsTextWideChar(const void *b, int len) {
22310234Syasuko.eckert@amd.com    return FALSE;
22410234Syasuko.eckert@amd.com}
22510152Satgutier@umich.edu#else
22610234Syasuko.eckert@amd.com#if defined (UNDER_CE) || !defined(_XMLWINDOWS)
22710234Syasuko.eckert@amd.com// inspired by the Wine API: RtlIsTextUnicode
22810234Syasuko.eckert@amd.comchar myIsTextWideChar(const void *b, int len) {
22910152Satgutier@umich.edu#ifdef sun
23010234Syasuko.eckert@amd.com    // for SPARC processors: wchar_t* buffers must always be alligned, otherwise it's a char* buffer.
23110234Syasuko.eckert@amd.com    if ((((unsigned long)b)%sizeof(wchar_t))!=0) return FALSE;
23210152Satgutier@umich.edu#endif
23310234Syasuko.eckert@amd.com    const wchar_t *s = (const wchar_t*)b;
23410152Satgutier@umich.edu
23510234Syasuko.eckert@amd.com    // buffer too small:
23610234Syasuko.eckert@amd.com    if (len < (int)sizeof(wchar_t)) return FALSE;
23710152Satgutier@umich.edu
23810234Syasuko.eckert@amd.com    // odd length test
23910234Syasuko.eckert@amd.com    if (len&1) return FALSE;
24010152Satgutier@umich.edu
24110234Syasuko.eckert@amd.com    /* only checks the first 256 characters */
24210234Syasuko.eckert@amd.com    len = mmin(256, len / sizeof(wchar_t));
24310152Satgutier@umich.edu
24410234Syasuko.eckert@amd.com    // Check for the special byte order:
24510234Syasuko.eckert@amd.com    if (*((unsigned short*)s) == 0xFFFE) return TRUE;     // IS_TEXT_UNICODE_REVERSE_SIGNATURE;
24610234Syasuko.eckert@amd.com    if (*((unsigned short*)s) == 0xFEFF) return TRUE;      // IS_TEXT_UNICODE_SIGNATURE
24710152Satgutier@umich.edu
24810234Syasuko.eckert@amd.com    // checks for ASCII characters in the UNICODE stream
24910234Syasuko.eckert@amd.com    int i, stats=0;
25010234Syasuko.eckert@amd.com    for (i=0; i<len; i++) if (s[i]<=(unsigned short)255) stats++;
25110234Syasuko.eckert@amd.com    if (stats>len/2) return TRUE;
25210152Satgutier@umich.edu
25310234Syasuko.eckert@amd.com    // Check for UNICODE NULL chars
25410234Syasuko.eckert@amd.com    for (i=0; i<len; i++) if (!s[i]) return TRUE;
25510152Satgutier@umich.edu
25610234Syasuko.eckert@amd.com    return FALSE;
25710234Syasuko.eckert@amd.com}
25810234Syasuko.eckert@amd.com#else
25910234Syasuko.eckert@amd.comchar myIsTextWideChar(const void *b, int l) {
26010234Syasuko.eckert@amd.com    return (char)IsTextUnicode((CONST LPVOID)b, l, NULL);
26110234Syasuko.eckert@amd.com};
26210234Syasuko.eckert@amd.com#endif
26310152Satgutier@umich.edu#endif
26410152Satgutier@umich.edu
26510152Satgutier@umich.edu#ifdef _XMLWINDOWS
26610152Satgutier@umich.edu// for Microsoft Visual Studio 6.0 and Microsoft Visual Studio .NET and Borland C++ Builder 6.0
26710234Syasuko.eckert@amd.com#ifdef _XMLWIDECHAR
26810234Syasuko.eckert@amd.comwchar_t *myMultiByteToWideChar(const char *s, XMLNode::XMLCharEncoding ce) {
26910234Syasuko.eckert@amd.com    int i;
27010234Syasuko.eckert@amd.com    if (ce == XMLNode::char_encoding_UTF8) {
27110234Syasuko.eckert@amd.com        i = (int)MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0);
27210234Syasuko.eckert@amd.com    } else {
27310234Syasuko.eckert@amd.com        i = (int)MultiByteToWideChar(CP_ACP , MB_PRECOMPOSED, s, -1, NULL, 0);
27410234Syasuko.eckert@amd.com    }
27510234Syasuko.eckert@amd.com    if (i < 0) {
27610234Syasuko.eckert@amd.com        return NULL;
27710234Syasuko.eckert@amd.com    }
27810234Syasuko.eckert@amd.com    wchar_t *d = (wchar_t *)malloc((i + 1) * sizeof(XMLCHAR));
27910234Syasuko.eckert@amd.com    if (ce == XMLNode::char_encoding_UTF8) {
28010234Syasuko.eckert@amd.com        i = (int)MultiByteToWideChar(CP_UTF8, 0, s, -1, d, i);
28110234Syasuko.eckert@amd.com    } else {
28210234Syasuko.eckert@amd.com        i = (int)MultiByteToWideChar(CP_ACP , MB_PRECOMPOSED, s, -1, d, i);
28310234Syasuko.eckert@amd.com    }
28410234Syasuko.eckert@amd.com    d[i] = 0;
28510234Syasuko.eckert@amd.com    return d;
28610234Syasuko.eckert@amd.com}
28710234Syasuko.eckert@amd.comstatic inline FILE *xfopen(XMLCSTR filename, XMLCSTR mode) {
28810234Syasuko.eckert@amd.com    return _wfopen(filename, mode);
28910234Syasuko.eckert@amd.com}
29010234Syasuko.eckert@amd.comstatic inline int xstrlen(XMLCSTR c)   {
29110234Syasuko.eckert@amd.com    return (int)wcslen(c);
29210234Syasuko.eckert@amd.com}
29310234Syasuko.eckert@amd.comstatic inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) {
29410234Syasuko.eckert@amd.com    return _wcsnicmp(c1, c2, l);
29510234Syasuko.eckert@amd.com}
29610234Syasuko.eckert@amd.comstatic inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) {
29710234Syasuko.eckert@amd.com    return wcsncmp(c1, c2, l);
29810234Syasuko.eckert@amd.com}
29910234Syasuko.eckert@amd.comstatic inline int xstricmp(XMLCSTR c1, XMLCSTR c2) {
30010234Syasuko.eckert@amd.com    return _wcsicmp(c1, c2);
30110234Syasuko.eckert@amd.com}
30210234Syasuko.eckert@amd.comstatic inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) {
30310234Syasuko.eckert@amd.com    return (XMLSTR)wcsstr(c1, c2);
30410234Syasuko.eckert@amd.com}
30510234Syasuko.eckert@amd.comstatic inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) {
30610234Syasuko.eckert@amd.com    return (XMLSTR)wcscpy(c1, c2);
30710234Syasuko.eckert@amd.com}
30810234Syasuko.eckert@amd.com#else
30910234Syasuko.eckert@amd.comchar *myWideCharToMultiByte(const wchar_t *s) {
31010234Syasuko.eckert@amd.com    UINT codePage = CP_ACP;
31110234Syasuko.eckert@amd.com    if (characterEncoding == XMLNode::char_encoding_UTF8) codePage = CP_UTF8;
31210234Syasuko.eckert@amd.com    int i = (int)WideCharToMultiByte(codePage,  // code page
31310234Syasuko.eckert@amd.com                                     0,                       // performance and mapping flags
31410234Syasuko.eckert@amd.com                                     s,                       // wide-character string
31510234Syasuko.eckert@amd.com                                     -1,                       // number of chars in string
31610234Syasuko.eckert@amd.com                                     NULL,                       // buffer for new string
31710234Syasuko.eckert@amd.com                                     0,                       // size of buffer
31810234Syasuko.eckert@amd.com                                     NULL,                    // default for unmappable chars
31910234Syasuko.eckert@amd.com                                     NULL                     // set when default char used
32010234Syasuko.eckert@amd.com                                    );
32110234Syasuko.eckert@amd.com    if (i<0) return NULL;
32210234Syasuko.eckert@amd.com    char *d=(char*)malloc(i+1);
32310234Syasuko.eckert@amd.com    WideCharToMultiByte(codePage,  // code page
32410234Syasuko.eckert@amd.com                        0,                       // performance and mapping flags
32510234Syasuko.eckert@amd.com                        s,                       // wide-character string
32610234Syasuko.eckert@amd.com                        -1,                       // number of chars in string
32710234Syasuko.eckert@amd.com                        d,                       // buffer for new string
32810234Syasuko.eckert@amd.com                        i,                       // size of buffer
32910234Syasuko.eckert@amd.com                        NULL,                    // default for unmappable chars
33010234Syasuko.eckert@amd.com                        NULL                     // set when default char used
33110234Syasuko.eckert@amd.com                       );
33210234Syasuko.eckert@amd.com    d[i] = 0;
33310234Syasuko.eckert@amd.com    return d;
33410234Syasuko.eckert@amd.com}
33510234Syasuko.eckert@amd.comstatic inline FILE *xfopen(XMLCSTR filename, XMLCSTR mode) {
33610234Syasuko.eckert@amd.com    return fopen(filename, mode);
33710234Syasuko.eckert@amd.com}
33810234Syasuko.eckert@amd.comstatic inline int xstrlen(XMLCSTR c)   {
33910234Syasuko.eckert@amd.com    return (int)strlen(c);
34010234Syasuko.eckert@amd.com}
34110234Syasuko.eckert@amd.com#ifdef __BORLANDC__
34210234Syasuko.eckert@amd.comstatic inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) {
34310234Syasuko.eckert@amd.com    return strnicmp(c1, c2, l);
34410234Syasuko.eckert@amd.com}
34510234Syasuko.eckert@amd.comstatic inline int xstricmp(XMLCSTR c1, XMLCSTR c2) {
34610234Syasuko.eckert@amd.com    return stricmp(c1, c2);
34710234Syasuko.eckert@amd.com}
34810234Syasuko.eckert@amd.com#else
34910234Syasuko.eckert@amd.comstatic inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) {
35010234Syasuko.eckert@amd.com    return _strnicmp(c1, c2, l);
35110234Syasuko.eckert@amd.com}
35210234Syasuko.eckert@amd.comstatic inline int xstricmp(XMLCSTR c1, XMLCSTR c2) {
35310234Syasuko.eckert@amd.com    return _stricmp(c1, c2);
35410234Syasuko.eckert@amd.com}
35510234Syasuko.eckert@amd.com#endif
35610234Syasuko.eckert@amd.comstatic inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) {
35710234Syasuko.eckert@amd.com    return strncmp(c1, c2, l);
35810234Syasuko.eckert@amd.com}
35910234Syasuko.eckert@amd.comstatic inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) {
36010234Syasuko.eckert@amd.com    return (XMLSTR)strstr(c1, c2);
36110234Syasuko.eckert@amd.com}
36210234Syasuko.eckert@amd.comstatic inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) {
36310234Syasuko.eckert@amd.com    return (XMLSTR)strcpy(c1, c2);
36410234Syasuko.eckert@amd.com}
36510234Syasuko.eckert@amd.com#endif
36610152Satgutier@umich.edu#else
36710152Satgutier@umich.edu// for gcc and CC
36810234Syasuko.eckert@amd.com#ifdef XML_NO_WIDE_CHAR
36910234Syasuko.eckert@amd.comchar *myWideCharToMultiByte(const wchar_t *s) {
37010234Syasuko.eckert@amd.com    return NULL;
37110234Syasuko.eckert@amd.com}
37210234Syasuko.eckert@amd.com#else
37310234Syasuko.eckert@amd.comchar *myWideCharToMultiByte(const wchar_t *s) {
37410234Syasuko.eckert@amd.com    const wchar_t *ss = s;
37510234Syasuko.eckert@amd.com    int i = (int)wcsrtombs(NULL, &ss, 0, NULL);
37610234Syasuko.eckert@amd.com    if (i < 0) return NULL;
37710234Syasuko.eckert@amd.com    char *d = (char *)malloc(i + 1);
37810234Syasuko.eckert@amd.com    wcsrtombs(d, &s, i, NULL);
37910234Syasuko.eckert@amd.com    d[i] = 0;
38010234Syasuko.eckert@amd.com    return d;
38110234Syasuko.eckert@amd.com}
38210234Syasuko.eckert@amd.com#endif
38310234Syasuko.eckert@amd.com#ifdef _XMLWIDECHAR
38410234Syasuko.eckert@amd.comwchar_t *myMultiByteToWideChar(const char *s, XMLNode::XMLCharEncoding ce) {
38510234Syasuko.eckert@amd.com    const char *ss = s;
38610234Syasuko.eckert@amd.com    int i = (int)mbsrtowcs(NULL, &ss, 0, NULL);
38710234Syasuko.eckert@amd.com    if (i < 0) return NULL;
38810234Syasuko.eckert@amd.com    wchar_t *d = (wchar_t *)malloc((i + 1) * sizeof(wchar_t));
38910234Syasuko.eckert@amd.com    mbsrtowcs(d, &s, i, NULL);
39010234Syasuko.eckert@amd.com    d[i] = 0;
39110234Syasuko.eckert@amd.com    return d;
39210234Syasuko.eckert@amd.com}
39310234Syasuko.eckert@amd.comint xstrlen(XMLCSTR c)   {
39410234Syasuko.eckert@amd.com    return wcslen(c);
39510234Syasuko.eckert@amd.com}
39610234Syasuko.eckert@amd.com#ifdef sun
39710234Syasuko.eckert@amd.com// for CC
39810234Syasuko.eckert@amd.com#include <widec.h>
39910234Syasuko.eckert@amd.comstatic inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) {
40010234Syasuko.eckert@amd.com    return wsncasecmp(c1, c2, l);
40110234Syasuko.eckert@amd.com}
40210234Syasuko.eckert@amd.comstatic inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) {
40310234Syasuko.eckert@amd.com    return wsncmp(c1, c2, l);
40410234Syasuko.eckert@amd.com}
40510234Syasuko.eckert@amd.comstatic inline int xstricmp(XMLCSTR c1, XMLCSTR c2) {
40610234Syasuko.eckert@amd.com    return wscasecmp(c1, c2);
40710234Syasuko.eckert@amd.com}
40810234Syasuko.eckert@amd.com#else
40910234Syasuko.eckert@amd.com// for gcc
41010234Syasuko.eckert@amd.comstatic inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) {
41110234Syasuko.eckert@amd.com    return wcsncasecmp(c1, c2, l);
41210234Syasuko.eckert@amd.com}
41310234Syasuko.eckert@amd.comstatic inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) {
41410234Syasuko.eckert@amd.com    return wcsncmp(c1, c2, l);
41510234Syasuko.eckert@amd.com}
41610234Syasuko.eckert@amd.comstatic inline int xstricmp(XMLCSTR c1, XMLCSTR c2) {
41710234Syasuko.eckert@amd.com    return wcscasecmp(c1, c2);
41810234Syasuko.eckert@amd.com}
41910234Syasuko.eckert@amd.com#endif
42010234Syasuko.eckert@amd.comstatic inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) {
42110234Syasuko.eckert@amd.com    return (XMLSTR)wcsstr(c1, c2);
42210234Syasuko.eckert@amd.com}
42310234Syasuko.eckert@amd.comstatic inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) {
42410234Syasuko.eckert@amd.com    return (XMLSTR)wcscpy(c1, c2);
42510234Syasuko.eckert@amd.com}
42610234Syasuko.eckert@amd.comstatic inline FILE *xfopen(XMLCSTR filename, XMLCSTR mode) {
42710234Syasuko.eckert@amd.com    char *filenameAscii = myWideCharToMultiByte(filename);
42810234Syasuko.eckert@amd.com    FILE *f;
42910234Syasuko.eckert@amd.com    if (mode[0] == _CXML('r')) f = fopen(filenameAscii, "rb");
43010234Syasuko.eckert@amd.com    else                     f = fopen(filenameAscii, "wb");
43110234Syasuko.eckert@amd.com    free(filenameAscii);
43210234Syasuko.eckert@amd.com    return f;
43310234Syasuko.eckert@amd.com}
43410234Syasuko.eckert@amd.com#else
43510234Syasuko.eckert@amd.comstatic inline FILE *xfopen(XMLCSTR filename, XMLCSTR mode) {
43610234Syasuko.eckert@amd.com    return fopen(filename, mode);
43710234Syasuko.eckert@amd.com}
43810234Syasuko.eckert@amd.comstatic inline int xstrlen(XMLCSTR c)   {
43910234Syasuko.eckert@amd.com    return strlen(c);
44010234Syasuko.eckert@amd.com}
44110234Syasuko.eckert@amd.comstatic inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) {
44210234Syasuko.eckert@amd.com    return strncasecmp(c1, c2, l);
44310234Syasuko.eckert@amd.com}
44410234Syasuko.eckert@amd.comstatic inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) {
44510234Syasuko.eckert@amd.com    return strncmp(c1, c2, l);
44610234Syasuko.eckert@amd.com}
44710234Syasuko.eckert@amd.comstatic inline int xstricmp(XMLCSTR c1, XMLCSTR c2) {
44810234Syasuko.eckert@amd.com    return strcasecmp(c1, c2);
44910234Syasuko.eckert@amd.com}
45010234Syasuko.eckert@amd.comstatic inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) {
45110234Syasuko.eckert@amd.com    return (XMLSTR)strstr(c1, c2);
45210234Syasuko.eckert@amd.com}
45310234Syasuko.eckert@amd.comstatic inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) {
45410234Syasuko.eckert@amd.com    return (XMLSTR)strcpy(c1, c2);
45510234Syasuko.eckert@amd.com}
45610234Syasuko.eckert@amd.com#endif
45710234Syasuko.eckert@amd.comstatic inline int _strnicmp(const char *c1, const char *c2, int l) {
45810234Syasuko.eckert@amd.com    return strncasecmp(c1, c2, l);
45910234Syasuko.eckert@amd.com}
46010152Satgutier@umich.edu#endif
46110152Satgutier@umich.edu
46210152Satgutier@umich.edu
46310152Satgutier@umich.edu///////////////////////////////////////////////////////////////////////////////
46410152Satgutier@umich.edu//            the "xmltoc,xmltob,xmltoi,xmltol,xmltof,xmltoa" functions      //
46510152Satgutier@umich.edu///////////////////////////////////////////////////////////////////////////////
46610152Satgutier@umich.edu// These 6 functions are not used inside the XMLparser.
46710152Satgutier@umich.edu// There are only here as "convenience" functions for the user.
46810152Satgutier@umich.edu// If you don't need them, you can delete them without any trouble.
46910152Satgutier@umich.edu#ifdef _XMLWIDECHAR
47010234Syasuko.eckert@amd.com#ifdef _XMLWINDOWS
47110234Syasuko.eckert@amd.com// for Microsoft Visual Studio 6.0 and Microsoft Visual Studio .NET and Borland C++ Builder 6.0
47210234Syasuko.eckert@amd.comchar    xmltob(XMLCSTR t, int     v) {
47310234Syasuko.eckert@amd.com    if (t && (*t)) return (char)_wtoi(t);
47410234Syasuko.eckert@amd.com    return v;
47510234Syasuko.eckert@amd.com}
47610234Syasuko.eckert@amd.comint     xmltoi(XMLCSTR t, int     v) {
47710234Syasuko.eckert@amd.com    if (t && (*t)) return _wtoi(t);
47810234Syasuko.eckert@amd.com    return v;
47910234Syasuko.eckert@amd.com}
48010234Syasuko.eckert@amd.comlong    xmltol(XMLCSTR t, long    v) {
48110234Syasuko.eckert@amd.com    if (t && (*t)) return _wtol(t);
48210234Syasuko.eckert@amd.com    return v;
48310234Syasuko.eckert@amd.com}
48410234Syasuko.eckert@amd.comdouble  xmltof(XMLCSTR t, double  v) {
48510234Syasuko.eckert@amd.com    if (t && (*t)) wscanf(t, "%f", &v); /*v=_wtof(t);*/
48610234Syasuko.eckert@amd.com    return v;
48710234Syasuko.eckert@amd.com}
48810152Satgutier@umich.edu#else
48910234Syasuko.eckert@amd.com#ifdef sun
49010234Syasuko.eckert@amd.com// for CC
49110234Syasuko.eckert@amd.com#include <widec.h>
49210234Syasuko.eckert@amd.comchar    xmltob(XMLCSTR t, int     v) {
49310234Syasuko.eckert@amd.com    if (t) return (char)wstol(t, NULL, 10);
49410234Syasuko.eckert@amd.com    return v;
49510234Syasuko.eckert@amd.com}
49610234Syasuko.eckert@amd.comint     xmltoi(XMLCSTR t, int     v) {
49710234Syasuko.eckert@amd.com    if (t) return (int)wstol(t, NULL, 10);
49810234Syasuko.eckert@amd.com    return v;
49910234Syasuko.eckert@amd.com}
50010234Syasuko.eckert@amd.comlong    xmltol(XMLCSTR t, long    v) {
50110234Syasuko.eckert@amd.com    if (t) return wstol(t, NULL, 10);
50210234Syasuko.eckert@amd.com    return v;
50310234Syasuko.eckert@amd.com}
50410234Syasuko.eckert@amd.com#else
50510234Syasuko.eckert@amd.com// for gcc
50610234Syasuko.eckert@amd.comchar    xmltob(XMLCSTR t, int     v) {
50710234Syasuko.eckert@amd.com    if (t) return (char)wcstol(t, NULL, 10);
50810234Syasuko.eckert@amd.com    return v;
50910234Syasuko.eckert@amd.com}
51010234Syasuko.eckert@amd.comint     xmltoi(XMLCSTR t, int     v) {
51110234Syasuko.eckert@amd.com    if (t) return (int)wcstol(t, NULL, 10);
51210234Syasuko.eckert@amd.com    return v;
51310234Syasuko.eckert@amd.com}
51410234Syasuko.eckert@amd.comlong    xmltol(XMLCSTR t, long    v) {
51510234Syasuko.eckert@amd.com    if (t) return wcstol(t, NULL, 10);
51610234Syasuko.eckert@amd.com    return v;
51710234Syasuko.eckert@amd.com}
51810152Satgutier@umich.edu#endif
51910234Syasuko.eckert@amd.comdouble  xmltof(XMLCSTR t, double  v) {
52010234Syasuko.eckert@amd.com    if (t && (*t)) wscanf(t, "%f", &v); /*v=_wtof(t);*/
52110234Syasuko.eckert@amd.com    return v;
52210234Syasuko.eckert@amd.com}
52310234Syasuko.eckert@amd.com#endif
52410234Syasuko.eckert@amd.com#else
52510234Syasuko.eckert@amd.comchar    xmltob(XMLCSTR t, char    v) {
52610234Syasuko.eckert@amd.com    if (t && (*t)) return (char)atoi(t);
52710234Syasuko.eckert@amd.com    return v;
52810234Syasuko.eckert@amd.com}
52910234Syasuko.eckert@amd.comint     xmltoi(XMLCSTR t, int     v) {
53010234Syasuko.eckert@amd.com    if (t && (*t)) return atoi(t);
53110234Syasuko.eckert@amd.com    return v;
53210234Syasuko.eckert@amd.com}
53310234Syasuko.eckert@amd.comlong    xmltol(XMLCSTR t, long    v) {
53410234Syasuko.eckert@amd.com    if (t && (*t)) return atol(t);
53510234Syasuko.eckert@amd.com    return v;
53610234Syasuko.eckert@amd.com}
53710234Syasuko.eckert@amd.comdouble  xmltof(XMLCSTR t, double  v) {
53810234Syasuko.eckert@amd.com    if (t && (*t)) return atof(t);
53910234Syasuko.eckert@amd.com    return v;
54010234Syasuko.eckert@amd.com}
54110234Syasuko.eckert@amd.com#endif
54210234Syasuko.eckert@amd.comXMLCSTR xmltoa(XMLCSTR t, XMLCSTR v) {
54310234Syasuko.eckert@amd.com    if (t)       return  t;
54410234Syasuko.eckert@amd.com    return v;
54510234Syasuko.eckert@amd.com}
54610234Syasuko.eckert@amd.comXMLCHAR xmltoc(XMLCSTR t, XMLCHAR v) {
54710234Syasuko.eckert@amd.com    if (t && (*t)) return *t;
54810234Syasuko.eckert@amd.com    return v;
54910234Syasuko.eckert@amd.com}
55010152Satgutier@umich.edu
55110152Satgutier@umich.edu/////////////////////////////////////////////////////////////////////////
55210152Satgutier@umich.edu//                    the "openFileHelper" function                    //
55310152Satgutier@umich.edu/////////////////////////////////////////////////////////////////////////
55410152Satgutier@umich.edu
55510152Satgutier@umich.edu// Since each application has its own way to report and deal with errors, you should modify & rewrite
55610152Satgutier@umich.edu// the following "openFileHelper" function to get an "error reporting mechanism" tailored to your needs.
55710234Syasuko.eckert@amd.comXMLNode XMLNode::openFileHelper(XMLCSTR filename, XMLCSTR tag) {
55810152Satgutier@umich.edu    // guess the value of the global parameter "characterEncoding"
55910152Satgutier@umich.edu    // (the guess is based on the first 200 bytes of the file).
56010234Syasuko.eckert@amd.com    FILE *f = xfopen(filename, _CXML("rb"));
56110234Syasuko.eckert@amd.com    if (f) {
56210152Satgutier@umich.edu        char bb[205];
56310234Syasuko.eckert@amd.com        int l = (int)fread(bb, 1, 200, f);
56410234Syasuko.eckert@amd.com        setGlobalOptions(guessCharEncoding(bb, l), guessWideCharChars,
56510234Syasuko.eckert@amd.com                         dropWhiteSpace, removeCommentsInMiddleOfText);
56610152Satgutier@umich.edu        fclose(f);
56710152Satgutier@umich.edu    }
56810152Satgutier@umich.edu
56910152Satgutier@umich.edu    // parse the file
57010152Satgutier@umich.edu    XMLResults pResults;
57110234Syasuko.eckert@amd.com    XMLNode xnode = XMLNode::parseFile(filename, tag, &pResults);
57210152Satgutier@umich.edu
57310152Satgutier@umich.edu    // display error message (if any)
57410234Syasuko.eckert@amd.com    if (pResults.error != eXMLErrorNone) {
57510152Satgutier@umich.edu        // create message
57610234Syasuko.eckert@amd.com        char message[2000], *s1 = (char*)"", *s3 = (char*)"";
57710234Syasuko.eckert@amd.com        XMLCSTR s2 = _CXML("");
57810234Syasuko.eckert@amd.com        if (pResults.error == eXMLErrorFirstTagNotFound) {
57910234Syasuko.eckert@amd.com            s1 = (char*)"First Tag should be '";
58010234Syasuko.eckert@amd.com            s2 = tag;
58110234Syasuko.eckert@amd.com            s3 = (char*)"'.\n";
58210234Syasuko.eckert@amd.com        }
58310152Satgutier@umich.edu        sprintf(message,
58410152Satgutier@umich.edu#ifdef _XMLWIDECHAR
58510234Syasuko.eckert@amd.com                "XML Parsing error inside file '%S'.\n%S\nAt line %i, column %i.\n%s%S%s"
58610152Satgutier@umich.edu#else
58710234Syasuko.eckert@amd.com                "XML Parsing error inside file '%s'.\n%s\nAt line %i, column %i.\n%s%s%s"
58810152Satgutier@umich.edu#endif
58910234Syasuko.eckert@amd.com                , filename, XMLNode::getError(pResults.error), pResults.nLine,
59010234Syasuko.eckert@amd.com                pResults.nColumn, s1, s2, s3);
59110152Satgutier@umich.edu
59210152Satgutier@umich.edu        // display message
59310152Satgutier@umich.edu#if defined(_XMLWINDOWS) && !defined(UNDER_CE) && !defined(_XMLPARSER_NO_MESSAGEBOX_)
59410234Syasuko.eckert@amd.com        MessageBoxA(NULL, message, "XML Parsing error", MB_OK | MB_ICONERROR |
59510234Syasuko.eckert@amd.com                    MB_TOPMOST);
59610152Satgutier@umich.edu#else
59710234Syasuko.eckert@amd.com        printf("%s", message);
59810152Satgutier@umich.edu#endif
59910152Satgutier@umich.edu        exit(255);
60010152Satgutier@umich.edu    }
60110152Satgutier@umich.edu    return xnode;
60210152Satgutier@umich.edu}
60310152Satgutier@umich.edu
60410152Satgutier@umich.edu/////////////////////////////////////////////////////////////////////////
60510152Satgutier@umich.edu//      Here start the core implementation of the XMLParser library    //
60610152Satgutier@umich.edu/////////////////////////////////////////////////////////////////////////
60710152Satgutier@umich.edu
60810152Satgutier@umich.edu// You should normally not change anything below this point.
60910152Satgutier@umich.edu
61010152Satgutier@umich.edu#ifndef _XMLWIDECHAR
61110152Satgutier@umich.edu// If "characterEncoding=ascii" then we assume that all characters have the same length of 1 byte.
61210152Satgutier@umich.edu// If "characterEncoding=UTF8" then the characters have different lengths (from 1 byte to 4 bytes).
61310152Satgutier@umich.edu// If "characterEncoding=ShiftJIS" then the characters have different lengths (from 1 byte to 2 bytes).
61410152Satgutier@umich.edu// This table is used as lookup-table to know the length of a character (in byte) based on the
61510152Satgutier@umich.edu// content of the first byte of the character.
61610152Satgutier@umich.edu// (note: if you modify this, you must always have XML_utf8ByteTable[0]=0 ).
61710234Syasuko.eckert@amd.comstatic const char XML_utf8ByteTable[256] = {
61810152Satgutier@umich.edu    //  0 1 2 3 4 5 6 7 8 9 a b c d e f
61910234Syasuko.eckert@amd.com    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x00
62010234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x10
62110234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x20
62210234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x30
62310234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x40
62410234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x50
62510234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x60
62610234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x70 End of ASCII range
62710234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x80 0x80 to 0xc1 invalid
62810234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x90
62910234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0xa0
63010234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0xb0
63110234Syasuko.eckert@amd.com    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xc0 0xc2 to 0xdf 2 byte
63210234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xd0
63310234Syasuko.eckert@amd.com    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,// 0xe0 0xe0 to 0xef 3 byte
63410234Syasuko.eckert@amd.com    4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
63510152Satgutier@umich.edu};
63610234Syasuko.eckert@amd.comstatic const char XML_legacyByteTable[256] = {
63710234Syasuko.eckert@amd.com    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
63810234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
63910234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
64010234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
64110234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
64210234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
64310152Satgutier@umich.edu};
64410234Syasuko.eckert@amd.comstatic const char XML_sjisByteTable[256] = {
64510152Satgutier@umich.edu    //  0 1 2 3 4 5 6 7 8 9 a b c d e f
64610234Syasuko.eckert@amd.com    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x00
64710234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x10
64810234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x20
64910234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x30
65010234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x40
65110234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x50
65210234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x60
65310234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x70
65410234Syasuko.eckert@amd.com    1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0x80 0x81 to 0x9F 2 bytes
65510234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0x90
65610234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0xa0
65710234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0xb0
65810234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0xc0
65910234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0xd0
66010234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xe0 0xe0 to 0xef 2 bytes
66110234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0
66210152Satgutier@umich.edu};
66310234Syasuko.eckert@amd.comstatic const char XML_gb2312ByteTable[256] = {
66410152Satgutier@umich.edu//  0 1 2 3 4 5 6 7 8 9 a b c d e f
66510234Syasuko.eckert@amd.com    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x00
66610234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x10
66710234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x20
66810234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x30
66910234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x40
67010234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x50
67110234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x60
67210234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x70
67310234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x80
67410234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x90
67510234Syasuko.eckert@amd.com    1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xa0 0xa1 to 0xf7 2 bytes
67610234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xb0
67710234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xc0
67810234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xd0
67910234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xe0
68010234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0
68110152Satgutier@umich.edu};
68210234Syasuko.eckert@amd.comstatic const char XML_gbk_big5_ByteTable[256] = {
68310152Satgutier@umich.edu    //  0 1 2 3 4 5 6 7 8 9 a b c d e f
68410234Syasuko.eckert@amd.com    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x00
68510234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x10
68610234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x20
68710234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x30
68810234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x40
68910234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x50
69010234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x60
69110234Syasuko.eckert@amd.com    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x70
69210234Syasuko.eckert@amd.com    1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0x80 0x81 to 0xfe 2 bytes
69310234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0x90
69410234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xa0
69510234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xb0
69610234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xc0
69710234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xd0
69810234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xe0
69910234Syasuko.eckert@amd.com    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 // 0xf0
70010152Satgutier@umich.edu};
70110234Syasuko.eckert@amd.com// the default is "characterEncoding=XMLNode::encoding_UTF8"
70210234Syasuko.eckert@amd.comstatic const char *XML_ByteTable = (const char *)XML_utf8ByteTable;
70310152Satgutier@umich.edu#endif
70410152Satgutier@umich.edu
70510152Satgutier@umich.edu
70610152Satgutier@umich.eduXMLNode XMLNode::emptyXMLNode;
70710234Syasuko.eckert@amd.comXMLClear XMLNode::emptyXMLClear = { NULL, NULL, NULL};
70810234Syasuko.eckert@amd.comXMLAttribute XMLNode::emptyXMLAttribute = { NULL, NULL};
70910152Satgutier@umich.edu
71010152Satgutier@umich.edu// Enumeration used to decipher what type a token is
71110234Syasuko.eckert@amd.comtypedef enum XMLTokenTypeTag {
71210152Satgutier@umich.edu    eTokenText = 0,
71310152Satgutier@umich.edu    eTokenQuotedText,
71410152Satgutier@umich.edu    eTokenTagStart,         /* "<"            */
71510152Satgutier@umich.edu    eTokenTagEnd,           /* "</"           */
71610152Satgutier@umich.edu    eTokenCloseTag,         /* ">"            */
71710152Satgutier@umich.edu    eTokenEquals,           /* "="            */
71810152Satgutier@umich.edu    eTokenDeclaration,      /* "<?"           */
71910152Satgutier@umich.edu    eTokenShortHandClose,   /* "/>"           */
72010152Satgutier@umich.edu    eTokenClear,
72110152Satgutier@umich.edu    eTokenError
72210152Satgutier@umich.edu} XMLTokenType;
72310152Satgutier@umich.edu
72410152Satgutier@umich.edu// Main structure used for parsing XML
72510234Syasuko.eckert@amd.comtypedef struct XML {
72610152Satgutier@umich.edu    XMLCSTR                lpXML;
72710152Satgutier@umich.edu    XMLCSTR                lpszText;
72810152Satgutier@umich.edu    int                    nIndex,nIndexMissigEndTag;
72910152Satgutier@umich.edu    enum XMLError          error;
73010152Satgutier@umich.edu    XMLCSTR                lpEndTag;
73110152Satgutier@umich.edu    int                    cbEndTag;
73210152Satgutier@umich.edu    XMLCSTR                lpNewElement;
73310152Satgutier@umich.edu    int                    cbNewElement;
73410152Satgutier@umich.edu    int                    nFirst;
73510152Satgutier@umich.edu} XML;
73610152Satgutier@umich.edu
73710234Syasuko.eckert@amd.comtypedef struct {
73810152Satgutier@umich.edu    ALLXMLClearTag *pClr;
73910152Satgutier@umich.edu    XMLCSTR     pStr;
74010152Satgutier@umich.edu} NextToken;
74110152Satgutier@umich.edu
74210152Satgutier@umich.edu// Enumeration used when parsing attributes
74310234Syasuko.eckert@amd.comtypedef enum Attrib {
74410152Satgutier@umich.edu    eAttribName = 0,
74510152Satgutier@umich.edu    eAttribEquals,
74610152Satgutier@umich.edu    eAttribValue
74710152Satgutier@umich.edu} Attrib;
74810152Satgutier@umich.edu
74910152Satgutier@umich.edu// Enumeration used when parsing elements to dictate whether we are currently
75010152Satgutier@umich.edu// inside a tag
75110234Syasuko.eckert@amd.comtypedef enum Status {
75210152Satgutier@umich.edu    eInsideTag = 0,
75310152Satgutier@umich.edu    eOutsideTag
75410152Satgutier@umich.edu} Status;
75510152Satgutier@umich.edu
75610234Syasuko.eckert@amd.comXMLError XMLNode::writeToFile(XMLCSTR filename, const char *encoding, char nFormat) const {
75710152Satgutier@umich.edu    if (!d) return eXMLErrorNone;
75810234Syasuko.eckert@amd.com    FILE *f = xfopen(filename, _CXML("wb"));
75910152Satgutier@umich.edu    if (!f) return eXMLErrorCannotOpenWriteFile;
76010152Satgutier@umich.edu#ifdef _XMLWIDECHAR
76110234Syasuko.eckert@amd.com    unsigned char h[2] = { 0xFF, 0xFE };
76210234Syasuko.eckert@amd.com    if (!fwrite(h, 2, 1, f)) return eXMLErrorCannotWriteFile;
76310234Syasuko.eckert@amd.com    if ((!isDeclaration()) && ((d->lpszName) ||
76410234Syasuko.eckert@amd.com                               (!getChildNode().isDeclaration()))) {
76510234Syasuko.eckert@amd.com        if (!fwrite(L"<?xml version=\"1.0\" encoding=\"utf-16\"?>\n",
76610234Syasuko.eckert@amd.com                    sizeof(wchar_t)*40, 1, f))
76710152Satgutier@umich.edu            return eXMLErrorCannotWriteFile;
76810152Satgutier@umich.edu    }
76910152Satgutier@umich.edu#else
77010234Syasuko.eckert@amd.com    if ((!isDeclaration()) && ((d->lpszName) ||
77110234Syasuko.eckert@amd.com                               (!getChildNode().isDeclaration()))) {
77210234Syasuko.eckert@amd.com        if (characterEncoding == char_encoding_UTF8) {
77310152Satgutier@umich.edu            // header so that windows recognize the file as UTF-8:
77410234Syasuko.eckert@amd.com            unsigned char h[3] = {0xEF, 0xBB, 0xBF};
77510234Syasuko.eckert@amd.com            if (!fwrite(h, 3, 1, f)) return eXMLErrorCannotWriteFile;
77610234Syasuko.eckert@amd.com            encoding = "utf-8";
77710234Syasuko.eckert@amd.com        } else if (characterEncoding == char_encoding_ShiftJIS)
77810234Syasuko.eckert@amd.com            encoding = "SHIFT-JIS";
77910152Satgutier@umich.edu
78010234Syasuko.eckert@amd.com        if (!encoding) encoding = "ISO-8859-1";
78110234Syasuko.eckert@amd.com        if (fprintf(f, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", encoding)
78210234Syasuko.eckert@amd.com            < 0)
78310234Syasuko.eckert@amd.com            return eXMLErrorCannotWriteFile;
78410234Syasuko.eckert@amd.com    } else {
78510234Syasuko.eckert@amd.com        if (characterEncoding == char_encoding_UTF8) {
78610234Syasuko.eckert@amd.com            unsigned char h[3] = {0xEF, 0xBB, 0xBF};
78710234Syasuko.eckert@amd.com            if (!fwrite(h, 3, 1, f)) return eXMLErrorCannotWriteFile;
78810152Satgutier@umich.edu        }
78910152Satgutier@umich.edu    }
79010152Satgutier@umich.edu#endif
79110152Satgutier@umich.edu    int i;
79210234Syasuko.eckert@amd.com    XMLSTR t = createXMLString(nFormat, &i);
79310234Syasuko.eckert@amd.com    if (!fwrite(t, sizeof(XMLCHAR)*i, 1, f)) return eXMLErrorCannotWriteFile;
79410234Syasuko.eckert@amd.com    if (fclose(f) != 0) return eXMLErrorCannotWriteFile;
79510152Satgutier@umich.edu    free(t);
79610152Satgutier@umich.edu    return eXMLErrorNone;
79710152Satgutier@umich.edu}
79810152Satgutier@umich.edu
79910152Satgutier@umich.edu// Duplicate a given string.
80010234Syasuko.eckert@amd.comXMLSTR stringDup(XMLCSTR lpszData, int cbData) {
80110234Syasuko.eckert@amd.com    if (lpszData == NULL) return NULL;
80210152Satgutier@umich.edu
80310152Satgutier@umich.edu    XMLSTR lpszNew;
80410234Syasuko.eckert@amd.com    if (cbData == -1) cbData = (int)xstrlen(lpszData);
80510234Syasuko.eckert@amd.com    lpszNew = (XMLSTR)malloc((cbData + 1) * sizeof(XMLCHAR));
80610234Syasuko.eckert@amd.com    if (lpszNew) {
80710152Satgutier@umich.edu        memcpy(lpszNew, lpszData, (cbData) * sizeof(XMLCHAR));
80810152Satgutier@umich.edu        lpszNew[cbData] = (XMLCHAR)NULL;
80910152Satgutier@umich.edu    }
81010152Satgutier@umich.edu    return lpszNew;
81110152Satgutier@umich.edu}
81210152Satgutier@umich.edu
81310234Syasuko.eckert@amd.comXMLSTR ToXMLStringTool::toXMLUnSafe(XMLSTR dest, XMLCSTR source) {
81410234Syasuko.eckert@amd.com    XMLSTR dd = dest;
81510152Satgutier@umich.edu    XMLCHAR ch;
81610152Satgutier@umich.edu    XMLCharacterEntity *entity;
81710234Syasuko.eckert@amd.com    while ((ch = *source)) {
81810234Syasuko.eckert@amd.com        entity = XMLEntities;
81910234Syasuko.eckert@amd.com        do {
82010234Syasuko.eckert@amd.com            if (ch == entity->c) {
82110234Syasuko.eckert@amd.com                xstrcpy(dest, entity->s);
82210234Syasuko.eckert@amd.com                dest += entity->l;
82310234Syasuko.eckert@amd.com                source++;
82410234Syasuko.eckert@amd.com                goto out_of_loop1;
82510234Syasuko.eckert@amd.com            }
82610152Satgutier@umich.edu            entity++;
82710234Syasuko.eckert@amd.com        } while (entity->s);
82810152Satgutier@umich.edu#ifdef _XMLWIDECHAR
82910234Syasuko.eckert@amd.com        *(dest++) = *(source++);
83010152Satgutier@umich.edu#else
83110234Syasuko.eckert@amd.com        switch (XML_ByteTable[(unsigned char)ch]) {
83210234Syasuko.eckert@amd.com        case 4:
83310234Syasuko.eckert@amd.com            *(dest++) = *(source++);
83410234Syasuko.eckert@amd.com        case 3:
83510234Syasuko.eckert@amd.com            *(dest++) = *(source++);
83610234Syasuko.eckert@amd.com        case 2:
83710234Syasuko.eckert@amd.com            *(dest++) = *(source++);
83810234Syasuko.eckert@amd.com        case 1:
83910234Syasuko.eckert@amd.com            *(dest++) = *(source++);
84010152Satgutier@umich.edu        }
84110152Satgutier@umich.edu#endif
84210152Satgutier@umich.eduout_of_loop1:
84310152Satgutier@umich.edu        ;
84410152Satgutier@umich.edu    }
84510234Syasuko.eckert@amd.com    *dest = 0;
84610152Satgutier@umich.edu    return dd;
84710152Satgutier@umich.edu}
84810152Satgutier@umich.edu
84910152Satgutier@umich.edu// private (used while rendering):
85010234Syasuko.eckert@amd.comint ToXMLStringTool::lengthXMLString(XMLCSTR source) {
85110234Syasuko.eckert@amd.com    int r = 0;
85210152Satgutier@umich.edu    XMLCharacterEntity *entity;
85310152Satgutier@umich.edu    XMLCHAR ch;
85410234Syasuko.eckert@amd.com    while ((ch = *source)) {
85510234Syasuko.eckert@amd.com        entity = XMLEntities;
85610234Syasuko.eckert@amd.com        do {
85710234Syasuko.eckert@amd.com            if (ch == entity->c) {
85810234Syasuko.eckert@amd.com                r += entity->l;
85910234Syasuko.eckert@amd.com                source++;
86010234Syasuko.eckert@amd.com                goto out_of_loop1;
86110234Syasuko.eckert@amd.com            }
86210152Satgutier@umich.edu            entity++;
86310234Syasuko.eckert@amd.com        } while (entity->s);
86410152Satgutier@umich.edu#ifdef _XMLWIDECHAR
86510234Syasuko.eckert@amd.com        r++;
86610234Syasuko.eckert@amd.com        source++;
86710152Satgutier@umich.edu#else
86810234Syasuko.eckert@amd.com        ch = XML_ByteTable[(unsigned char)ch];
86910234Syasuko.eckert@amd.com        r += ch;
87010234Syasuko.eckert@amd.com        source += ch;
87110152Satgutier@umich.edu#endif
87210152Satgutier@umich.eduout_of_loop1:
87310152Satgutier@umich.edu        ;
87410152Satgutier@umich.edu    }
87510152Satgutier@umich.edu    return r;
87610152Satgutier@umich.edu}
87710152Satgutier@umich.edu
87810234Syasuko.eckert@amd.comToXMLStringTool::~ToXMLStringTool() {
87910234Syasuko.eckert@amd.com    freeBuffer();
88010234Syasuko.eckert@amd.com}
88110234Syasuko.eckert@amd.comvoid ToXMLStringTool::freeBuffer() {
88210234Syasuko.eckert@amd.com    if (buf) free(buf);
88310234Syasuko.eckert@amd.com    buf = NULL;
88410234Syasuko.eckert@amd.com    buflen = 0;
88510234Syasuko.eckert@amd.com}
88610234Syasuko.eckert@amd.comXMLSTR ToXMLStringTool::toXML(XMLCSTR source) {
88710234Syasuko.eckert@amd.com    int l = lengthXMLString(source) + 1;
88810234Syasuko.eckert@amd.com    if (l > buflen) {
88910234Syasuko.eckert@amd.com        buflen = l;
89010234Syasuko.eckert@amd.com        buf = (XMLSTR)realloc(buf, l * sizeof(XMLCHAR));
89110234Syasuko.eckert@amd.com    }
89210234Syasuko.eckert@amd.com    return toXMLUnSafe(buf, source);
89310152Satgutier@umich.edu}
89410152Satgutier@umich.edu
89510152Satgutier@umich.edu// private:
89610234Syasuko.eckert@amd.comXMLSTR fromXMLString(XMLCSTR s, int lo, XML *pXML) {
89710152Satgutier@umich.edu    // This function is the opposite of the function "toXMLString". It decodes the escape
89810152Satgutier@umich.edu    // sequences &amp;, &quot;, &apos;, &lt;, &gt; and replace them by the characters
89910152Satgutier@umich.edu    // &,",',<,>. This function is used internally by the XML Parser. All the calls to
90010152Satgutier@umich.edu    // the XML library will always gives you back "decoded" strings.
90110152Satgutier@umich.edu    //
90210152Satgutier@umich.edu    // in: string (s) and length (lo) of string
90310152Satgutier@umich.edu    // out:  new allocated string converted from xml
90410152Satgutier@umich.edu    if (!s) return NULL;
90510152Satgutier@umich.edu
90610234Syasuko.eckert@amd.com    int ll = 0, j;
90710152Satgutier@umich.edu    XMLSTR d;
90810234Syasuko.eckert@amd.com    XMLCSTR ss = s;
90910152Satgutier@umich.edu    XMLCharacterEntity *entity;
91010234Syasuko.eckert@amd.com    while ((lo > 0) && (*s)) {
91110234Syasuko.eckert@amd.com        if (*s == _CXML('&')) {
91210234Syasuko.eckert@amd.com            if ((lo > 2) && (s[1] == _CXML('#'))) {
91310234Syasuko.eckert@amd.com                s += 2;
91410234Syasuko.eckert@amd.com                lo -= 2;
91510234Syasuko.eckert@amd.com                if ((*s == _CXML('X')) || (*s == _CXML('x'))) {
91610234Syasuko.eckert@amd.com                    s++;
91710234Syasuko.eckert@amd.com                    lo--;
91810234Syasuko.eckert@amd.com                }
91910234Syasuko.eckert@amd.com                while ((*s) && (*s != _CXML(';')) && ((lo--) > 0)) {
92010234Syasuko.eckert@amd.com                    s++;
92110234Syasuko.eckert@amd.com                }
92210234Syasuko.eckert@amd.com                if (*s != _CXML(';')) {
92310234Syasuko.eckert@amd.com                    pXML->error = eXMLErrorUnknownCharacterEntity;
92410152Satgutier@umich.edu                    return NULL;
92510152Satgutier@umich.edu                }
92610234Syasuko.eckert@amd.com                s++;
92710234Syasuko.eckert@amd.com                lo--;
92810234Syasuko.eckert@amd.com            } else {
92910234Syasuko.eckert@amd.com                entity = XMLEntities;
93010234Syasuko.eckert@amd.com                do {
93110234Syasuko.eckert@amd.com                    if ((lo >= entity->l) &&
93210234Syasuko.eckert@amd.com                        (xstrnicmp(s, entity->s, entity->l) == 0)) {
93310234Syasuko.eckert@amd.com                        s += entity->l;
93410234Syasuko.eckert@amd.com                        lo -= entity->l;
93510234Syasuko.eckert@amd.com                        break;
93610234Syasuko.eckert@amd.com                    }
93710152Satgutier@umich.edu                    entity++;
93810234Syasuko.eckert@amd.com                } while (entity->s);
93910234Syasuko.eckert@amd.com                if (!entity->s) {
94010234Syasuko.eckert@amd.com                    pXML->error = eXMLErrorUnknownCharacterEntity;
94110152Satgutier@umich.edu                    return NULL;
94210152Satgutier@umich.edu                }
94310152Satgutier@umich.edu            }
94410234Syasuko.eckert@amd.com        } else {
94510152Satgutier@umich.edu#ifdef _XMLWIDECHAR
94610234Syasuko.eckert@amd.com            s++;
94710234Syasuko.eckert@amd.com            lo--;
94810152Satgutier@umich.edu#else
94910234Syasuko.eckert@amd.com            j = XML_ByteTable[(unsigned char)*s];
95010234Syasuko.eckert@amd.com            s += j;
95110234Syasuko.eckert@amd.com            lo -= j;
95210234Syasuko.eckert@amd.com            ll += j - 1;
95310152Satgutier@umich.edu#endif
95410152Satgutier@umich.edu        }
95510152Satgutier@umich.edu        ll++;
95610152Satgutier@umich.edu    }
95710152Satgutier@umich.edu
95810234Syasuko.eckert@amd.com    d = (XMLSTR)malloc((ll + 1) * sizeof(XMLCHAR));
95910234Syasuko.eckert@amd.com    s = d;
96010234Syasuko.eckert@amd.com    while (ll-- > 0) {
96110234Syasuko.eckert@amd.com        if (*ss == _CXML('&')) {
96210234Syasuko.eckert@amd.com            if (ss[1] == _CXML('#')) {
96310234Syasuko.eckert@amd.com                ss += 2;
96410234Syasuko.eckert@amd.com                j = 0;
96510234Syasuko.eckert@amd.com                if ((*ss == _CXML('X')) || (*ss == _CXML('x'))) {
96610152Satgutier@umich.edu                    ss++;
96710234Syasuko.eckert@amd.com                    while (*ss != _CXML(';')) {
96810234Syasuko.eckert@amd.com                        if ((*ss >= _CXML('0')) && (*ss <= _CXML('9'))) {
96910234Syasuko.eckert@amd.com                            j = (j << 4) + *ss - _CXML('0');
97010234Syasuko.eckert@amd.com                        } else if ((*ss >= _CXML('A')) && (*ss <= _CXML('F'))) {
97110234Syasuko.eckert@amd.com                            j = (j << 4) + *ss - _CXML('A') + 10;
97210234Syasuko.eckert@amd.com                        } else if ((*ss >= _CXML('a')) && (*ss <= _CXML('f'))) {
97310234Syasuko.eckert@amd.com                            j = (j << 4) + *ss - _CXML('a') + 10;
97410234Syasuko.eckert@amd.com                        } else {
97510234Syasuko.eckert@amd.com                            free((void*)s);
97610234Syasuko.eckert@amd.com                            pXML->error = eXMLErrorUnknownCharacterEntity;
97710234Syasuko.eckert@amd.com                            return NULL;
97810234Syasuko.eckert@amd.com                        }
97910152Satgutier@umich.edu                        ss++;
98010152Satgutier@umich.edu                    }
98110234Syasuko.eckert@amd.com                } else {
98210234Syasuko.eckert@amd.com                    while (*ss != _CXML(';')) {
98310234Syasuko.eckert@amd.com                        if ((*ss >= _CXML('0')) && (*ss <= _CXML('9'))) {
98410234Syasuko.eckert@amd.com                            j = (j * 10) + *ss - _CXML('0');
98510234Syasuko.eckert@amd.com                        } else {
98610234Syasuko.eckert@amd.com                            free((void*)s);
98710234Syasuko.eckert@amd.com                            pXML->error = eXMLErrorUnknownCharacterEntity;
98810234Syasuko.eckert@amd.com                            return NULL;
98910234Syasuko.eckert@amd.com                        }
99010152Satgutier@umich.edu                        ss++;
99110152Satgutier@umich.edu                    }
99210152Satgutier@umich.edu                }
99310152Satgutier@umich.edu#ifndef _XMLWIDECHAR
99410234Syasuko.eckert@amd.com                if (j > 255) {
99510234Syasuko.eckert@amd.com                    free((void*)s);
99610234Syasuko.eckert@amd.com                    pXML->error = eXMLErrorCharacterCodeAbove255;
99710234Syasuko.eckert@amd.com                    return NULL;
99810234Syasuko.eckert@amd.com                }
99910152Satgutier@umich.edu#endif
100010234Syasuko.eckert@amd.com                (*d++) = (XMLCHAR)j;
100110234Syasuko.eckert@amd.com                ss++;
100210234Syasuko.eckert@amd.com            } else {
100310234Syasuko.eckert@amd.com                entity = XMLEntities;
100410234Syasuko.eckert@amd.com                do {
100510234Syasuko.eckert@amd.com                    if (xstrnicmp(ss, entity->s, entity->l) == 0) {
100610234Syasuko.eckert@amd.com                        *(d++) = entity->c;
100710234Syasuko.eckert@amd.com                        ss += entity->l;
100810234Syasuko.eckert@amd.com                        break;
100910234Syasuko.eckert@amd.com                    }
101010152Satgutier@umich.edu                    entity++;
101110234Syasuko.eckert@amd.com                } while (entity->s);
101210152Satgutier@umich.edu            }
101310234Syasuko.eckert@amd.com        } else {
101410152Satgutier@umich.edu#ifdef _XMLWIDECHAR
101510234Syasuko.eckert@amd.com            *(d++) = *(ss++);
101610152Satgutier@umich.edu#else
101710234Syasuko.eckert@amd.com            switch (XML_ByteTable[(unsigned char)*ss]) {
101810234Syasuko.eckert@amd.com            case 4:
101910234Syasuko.eckert@amd.com                *(d++) = *(ss++);
102010234Syasuko.eckert@amd.com                ll--;
102110234Syasuko.eckert@amd.com            case 3:
102210234Syasuko.eckert@amd.com                *(d++) = *(ss++);
102310234Syasuko.eckert@amd.com                ll--;
102410234Syasuko.eckert@amd.com            case 2:
102510234Syasuko.eckert@amd.com                *(d++) = *(ss++);
102610234Syasuko.eckert@amd.com                ll--;
102710234Syasuko.eckert@amd.com            case 1:
102810234Syasuko.eckert@amd.com                *(d++) = *(ss++);
102910152Satgutier@umich.edu            }
103010152Satgutier@umich.edu#endif
103110152Satgutier@umich.edu        }
103210152Satgutier@umich.edu    }
103310234Syasuko.eckert@amd.com    *d = 0;
103410152Satgutier@umich.edu    return (XMLSTR)s;
103510152Satgutier@umich.edu}
103610152Satgutier@umich.edu
103710152Satgutier@umich.edu#define XML_isSPACECHAR(ch) ((ch==_CXML('\n'))||(ch==_CXML(' '))||(ch== _CXML('\t'))||(ch==_CXML('\r')))
103810152Satgutier@umich.edu
103910152Satgutier@umich.edu// private:
104010152Satgutier@umich.educhar myTagCompare(XMLCSTR cclose, XMLCSTR copen)
104110152Satgutier@umich.edu// !!!! WARNING strange convention&:
104210152Satgutier@umich.edu// return 0 if equals
104310152Satgutier@umich.edu// return 1 if different
104410152Satgutier@umich.edu{
104510152Satgutier@umich.edu    if (!cclose) return 1;
104610234Syasuko.eckert@amd.com    int l = (int)xstrlen(cclose);
104710234Syasuko.eckert@amd.com    if (xstrnicmp(cclose, copen, l) != 0) return 1;
104810234Syasuko.eckert@amd.com    const XMLCHAR c = copen[l];
104910234Syasuko.eckert@amd.com    if (XML_isSPACECHAR(c) ||
105010234Syasuko.eckert@amd.com            (c == _CXML('/' )) ||
105110234Syasuko.eckert@amd.com            (c == _CXML('<' )) ||
105210234Syasuko.eckert@amd.com            (c == _CXML('>' )) ||
105310234Syasuko.eckert@amd.com            (c == _CXML('=' ))) return 0;
105410152Satgutier@umich.edu    return 1;
105510152Satgutier@umich.edu}
105610152Satgutier@umich.edu
105710152Satgutier@umich.edu// Obtain the next character from the string.
105810234Syasuko.eckert@amd.comstatic inline XMLCHAR getNextChar(XML *pXML) {
105910152Satgutier@umich.edu    XMLCHAR ch = pXML->lpXML[pXML->nIndex];
106010152Satgutier@umich.edu#ifdef _XMLWIDECHAR
106110234Syasuko.eckert@amd.com    if (ch != 0) pXML->nIndex++;
106210152Satgutier@umich.edu#else
106310234Syasuko.eckert@amd.com    pXML->nIndex += XML_ByteTable[(unsigned char)ch];
106410152Satgutier@umich.edu#endif
106510152Satgutier@umich.edu    return ch;
106610152Satgutier@umich.edu}
106710152Satgutier@umich.edu
106810152Satgutier@umich.edu// Find the next token in a string.
106910152Satgutier@umich.edu// pcbToken contains the number of characters that have been read.
107010234Syasuko.eckert@amd.comstatic NextToken GetNextToken(XML *pXML, int *pcbToken,
107110234Syasuko.eckert@amd.com                              enum XMLTokenTypeTag *pType) {
107210152Satgutier@umich.edu    NextToken        result;
107310152Satgutier@umich.edu    XMLCHAR            ch;
107410152Satgutier@umich.edu    XMLCHAR            chTemp;
107510234Syasuko.eckert@amd.com    int              indexStart, nFoundMatch, nIsText = FALSE;
107610234Syasuko.eckert@amd.com    result.pClr = NULL; // prevent warning
107710152Satgutier@umich.edu
107810152Satgutier@umich.edu    // Find next non-white space character
107910234Syasuko.eckert@amd.com    do {
108010234Syasuko.eckert@amd.com        indexStart = pXML->nIndex;
108110234Syasuko.eckert@amd.com        ch = getNextChar(pXML);
108210234Syasuko.eckert@amd.com    } while XML_isSPACECHAR(ch);
108310152Satgutier@umich.edu
108410234Syasuko.eckert@amd.com    if (ch) {
108510152Satgutier@umich.edu        // Cache the current string pointer
108610152Satgutier@umich.edu        result.pStr = &pXML->lpXML[indexStart];
108710152Satgutier@umich.edu
108810152Satgutier@umich.edu        // First check whether the token is in the clear tag list (meaning it
108910152Satgutier@umich.edu        // does not need formatting).
109010234Syasuko.eckert@amd.com        ALLXMLClearTag *ctag = XMLClearTags;
109110234Syasuko.eckert@amd.com        do {
109210234Syasuko.eckert@amd.com            if (xstrncmp(ctag->lpszOpen, result.pStr, ctag->openTagLen) == 0) {
109310234Syasuko.eckert@amd.com                result.pClr = ctag;
109410234Syasuko.eckert@amd.com                pXML->nIndex += ctag->openTagLen - 1;
109510234Syasuko.eckert@amd.com                *pType = eTokenClear;
109610152Satgutier@umich.edu                return result;
109710152Satgutier@umich.edu            }
109810152Satgutier@umich.edu            ctag++;
109910234Syasuko.eckert@amd.com        } while (ctag->lpszOpen);
110010152Satgutier@umich.edu
110110152Satgutier@umich.edu        // If we didn't find a clear tag then check for standard tokens
110210234Syasuko.eckert@amd.com        switch (ch) {
110310234Syasuko.eckert@amd.com            // Check for quotes
110410152Satgutier@umich.edu        case _CXML('\''):
110510152Satgutier@umich.edu        case _CXML('\"'):
110610152Satgutier@umich.edu            // Type of token
110710152Satgutier@umich.edu            *pType = eTokenQuotedText;
110810152Satgutier@umich.edu            chTemp = ch;
110910152Satgutier@umich.edu
111010152Satgutier@umich.edu            // Set the size
111110152Satgutier@umich.edu            nFoundMatch = FALSE;
111210152Satgutier@umich.edu
111310152Satgutier@umich.edu            // Search through the string to find a matching quote
111410234Syasuko.eckert@amd.com            while ((ch = getNextChar(pXML))) {
111510234Syasuko.eckert@amd.com                if (ch == chTemp) {
111610234Syasuko.eckert@amd.com                    nFoundMatch = TRUE;
111710234Syasuko.eckert@amd.com                    break;
111810234Syasuko.eckert@amd.com                }
111910234Syasuko.eckert@amd.com                if (ch == _CXML('<')) {
112010234Syasuko.eckert@amd.com                    break;
112110234Syasuko.eckert@amd.com                }
112210152Satgutier@umich.edu            }
112310152Satgutier@umich.edu
112410152Satgutier@umich.edu            // If we failed to find a matching quote
112510234Syasuko.eckert@amd.com            if (nFoundMatch == FALSE) {
112610234Syasuko.eckert@amd.com                pXML->nIndex = indexStart + 1;
112710234Syasuko.eckert@amd.com                nIsText = TRUE;
112810152Satgutier@umich.edu                break;
112910152Satgutier@umich.edu            }
113010152Satgutier@umich.edu
113110152Satgutier@umich.edu//  4.02.2002
113210152Satgutier@umich.edu//            if (FindNonWhiteSpace(pXML)) pXML->nIndex--;
113310152Satgutier@umich.edu
113410152Satgutier@umich.edu            break;
113510152Satgutier@umich.edu
113610234Syasuko.eckert@amd.com            // Equals (used with attribute values)
113710152Satgutier@umich.edu        case _CXML('='):
113810152Satgutier@umich.edu            *pType = eTokenEquals;
113910152Satgutier@umich.edu            break;
114010152Satgutier@umich.edu
114110234Syasuko.eckert@amd.com            // Close tag
114210152Satgutier@umich.edu        case _CXML('>'):
114310152Satgutier@umich.edu            *pType = eTokenCloseTag;
114410152Satgutier@umich.edu            break;
114510152Satgutier@umich.edu
114610234Syasuko.eckert@amd.com            // Check for tag start and tag end
114710152Satgutier@umich.edu        case _CXML('<'):
114810152Satgutier@umich.edu
114910152Satgutier@umich.edu            // Peek at the next character to see if we have an end tag '</',
115010152Satgutier@umich.edu            // or an xml declaration '<?'
115110152Satgutier@umich.edu            chTemp = pXML->lpXML[pXML->nIndex];
115210152Satgutier@umich.edu
115310152Satgutier@umich.edu            // If we have a tag end...
115410234Syasuko.eckert@amd.com            if (chTemp == _CXML('/')) {
115510152Satgutier@umich.edu                // Set the type and ensure we point at the next character
115610152Satgutier@umich.edu                getNextChar(pXML);
115710152Satgutier@umich.edu                *pType = eTokenTagEnd;
115810152Satgutier@umich.edu            }
115910152Satgutier@umich.edu
116010152Satgutier@umich.edu            // If we have an XML declaration tag
116110234Syasuko.eckert@amd.com            else if (chTemp == _CXML('?')) {
116210152Satgutier@umich.edu
116310152Satgutier@umich.edu                // Set the type and ensure we point at the next character
116410152Satgutier@umich.edu                getNextChar(pXML);
116510152Satgutier@umich.edu                *pType = eTokenDeclaration;
116610152Satgutier@umich.edu            }
116710152Satgutier@umich.edu
116810152Satgutier@umich.edu            // Otherwise we must have a start tag
116910234Syasuko.eckert@amd.com            else {
117010152Satgutier@umich.edu                *pType = eTokenTagStart;
117110152Satgutier@umich.edu            }
117210152Satgutier@umich.edu            break;
117310152Satgutier@umich.edu
117410234Syasuko.eckert@amd.com            // Check to see if we have a short hand type end tag ('/>').
117510152Satgutier@umich.edu        case _CXML('/'):
117610152Satgutier@umich.edu
117710152Satgutier@umich.edu            // Peek at the next character to see if we have a short end tag '/>'
117810152Satgutier@umich.edu            chTemp = pXML->lpXML[pXML->nIndex];
117910152Satgutier@umich.edu
118010152Satgutier@umich.edu            // If we have a short hand end tag...
118110234Syasuko.eckert@amd.com            if (chTemp == _CXML('>')) {
118210152Satgutier@umich.edu                // Set the type and ensure we point at the next character
118310152Satgutier@umich.edu                getNextChar(pXML);
118410152Satgutier@umich.edu                *pType = eTokenShortHandClose;
118510152Satgutier@umich.edu                break;
118610152Satgutier@umich.edu            }
118710152Satgutier@umich.edu
118810152Satgutier@umich.edu            // If we haven't found a short hand closing tag then drop into the
118910152Satgutier@umich.edu            // text process
119010152Satgutier@umich.edu
119110234Syasuko.eckert@amd.com            // Other characters
119210152Satgutier@umich.edu        default:
119310152Satgutier@umich.edu            nIsText = TRUE;
119410152Satgutier@umich.edu        }
119510152Satgutier@umich.edu
119610152Satgutier@umich.edu        // If this is a TEXT node
119710234Syasuko.eckert@amd.com        if (nIsText) {
119810152Satgutier@umich.edu            // Indicate we are dealing with text
119910152Satgutier@umich.edu            *pType = eTokenText;
120010234Syasuko.eckert@amd.com            while ((ch = getNextChar(pXML))) {
120110234Syasuko.eckert@amd.com                if XML_isSPACECHAR(ch) {
120210234Syasuko.eckert@amd.com                    indexStart++;
120310234Syasuko.eckert@amd.com                    break;
120410152Satgutier@umich.edu
120510234Syasuko.eckert@amd.com                } else if (ch == _CXML('/')) {
120610152Satgutier@umich.edu                    // If we find a slash then this maybe text or a short hand end tag
120710152Satgutier@umich.edu                    // Peek at the next character to see it we have short hand end tag
120810234Syasuko.eckert@amd.com                    ch = pXML->lpXML[pXML->nIndex];
120910152Satgutier@umich.edu                    // If we found a short hand end tag then we need to exit the loop
121010234Syasuko.eckert@amd.com                    if (ch == _CXML('>')) {
121110234Syasuko.eckert@amd.com                        pXML->nIndex--;
121210234Syasuko.eckert@amd.com                        break;
121310234Syasuko.eckert@amd.com                    }
121410152Satgutier@umich.edu
121510234Syasuko.eckert@amd.com                } else if ((ch == _CXML('<')) || (ch == _CXML('>')) ||
121610234Syasuko.eckert@amd.com                           (ch == _CXML('='))) {
121710234Syasuko.eckert@amd.com                    pXML->nIndex--;
121810234Syasuko.eckert@amd.com                    break;
121910152Satgutier@umich.edu                }
122010152Satgutier@umich.edu            }
122110152Satgutier@umich.edu        }
122210234Syasuko.eckert@amd.com        *pcbToken = pXML->nIndex - indexStart;
122310234Syasuko.eckert@amd.com    } else {
122410152Satgutier@umich.edu        // If we failed to obtain a valid character
122510152Satgutier@umich.edu        *pcbToken = 0;
122610152Satgutier@umich.edu        *pType = eTokenError;
122710234Syasuko.eckert@amd.com        result.pStr = NULL;
122810152Satgutier@umich.edu    }
122910152Satgutier@umich.edu
123010152Satgutier@umich.edu    return result;
123110152Satgutier@umich.edu}
123210152Satgutier@umich.edu
123310234Syasuko.eckert@amd.comXMLCSTR XMLNode::updateName_WOSD(XMLSTR lpszName) {
123410234Syasuko.eckert@amd.com    if (!d) {
123510234Syasuko.eckert@amd.com        free(lpszName);
123610234Syasuko.eckert@amd.com        return NULL;
123710234Syasuko.eckert@amd.com    }
123810234Syasuko.eckert@amd.com    if (d->lpszName && (lpszName != d->lpszName)) free((void*)d->lpszName);
123910234Syasuko.eckert@amd.com    d->lpszName = lpszName;
124010152Satgutier@umich.edu    return lpszName;
124110152Satgutier@umich.edu}
124210152Satgutier@umich.edu
124310152Satgutier@umich.edu// private:
124410234Syasuko.eckert@amd.comXMLNode::XMLNode(struct XMLNodeDataTag *p) {
124510234Syasuko.eckert@amd.com    d = p;
124610234Syasuko.eckert@amd.com    (p->ref_count)++;
124710234Syasuko.eckert@amd.com}
124810234Syasuko.eckert@amd.comXMLNode::XMLNode(XMLNodeData *pParent, XMLSTR lpszName, char isDeclaration) {
124910234Syasuko.eckert@amd.com    d = (XMLNodeData*)malloc(sizeof(XMLNodeData));
125010234Syasuko.eckert@amd.com    d->ref_count = 1;
125110152Satgutier@umich.edu
125210234Syasuko.eckert@amd.com    d->lpszName = NULL;
125310234Syasuko.eckert@amd.com    d->nChild = 0;
125410152Satgutier@umich.edu    d->nText = 0;
125510152Satgutier@umich.edu    d->nClear = 0;
125610152Satgutier@umich.edu    d->nAttribute = 0;
125710152Satgutier@umich.edu
125810152Satgutier@umich.edu    d->isDeclaration = isDeclaration;
125910152Satgutier@umich.edu
126010152Satgutier@umich.edu    d->pParent = pParent;
126110234Syasuko.eckert@amd.com    d->pChild = NULL;
126210234Syasuko.eckert@amd.com    d->pText = NULL;
126310234Syasuko.eckert@amd.com    d->pClear = NULL;
126410234Syasuko.eckert@amd.com    d->pAttribute = NULL;
126510234Syasuko.eckert@amd.com    d->pOrder = NULL;
126610152Satgutier@umich.edu
126710152Satgutier@umich.edu    updateName_WOSD(lpszName);
126810152Satgutier@umich.edu}
126910152Satgutier@umich.edu
127010234Syasuko.eckert@amd.comXMLNode XMLNode::createXMLTopNode_WOSD(XMLSTR lpszName, char isDeclaration) {
127110234Syasuko.eckert@amd.com    return XMLNode(NULL, lpszName, isDeclaration);
127210234Syasuko.eckert@amd.com}
127310234Syasuko.eckert@amd.comXMLNode XMLNode::createXMLTopNode(XMLCSTR lpszName, char isDeclaration) {
127410234Syasuko.eckert@amd.com    return XMLNode(NULL, stringDup(lpszName), isDeclaration);
127510234Syasuko.eckert@amd.com}
127610152Satgutier@umich.edu
127710152Satgutier@umich.edu#define MEMORYINCREASE 50
127810152Satgutier@umich.edu
127910234Syasuko.eckert@amd.comstatic inline void myFree(void *p) {
128010234Syasuko.eckert@amd.com    if (p) free(p);
128110234Syasuko.eckert@amd.com}
128210234Syasuko.eckert@amd.comstatic inline void *myRealloc(void *p, int newsize, int memInc, int sizeofElem) {
128310234Syasuko.eckert@amd.com    if (p == NULL) {
128410234Syasuko.eckert@amd.com        if (memInc) return malloc(memInc*sizeofElem);
128510234Syasuko.eckert@amd.com        return malloc(sizeofElem);
128610234Syasuko.eckert@amd.com    }
128710234Syasuko.eckert@amd.com    if ((memInc == 0) || ((newsize % memInc) == 0)) {
128810234Syasuko.eckert@amd.com        p = realloc(p, (newsize + memInc) * sizeofElem);
128910234Syasuko.eckert@amd.com    }
129010152Satgutier@umich.edu//    if (!p)
129110152Satgutier@umich.edu//    {
129210152Satgutier@umich.edu//        printf("XMLParser Error: Not enough memory! Aborting...\n"); exit(220);
129310152Satgutier@umich.edu//    }
129410152Satgutier@umich.edu    return p;
129510152Satgutier@umich.edu}
129610152Satgutier@umich.edu
129710152Satgutier@umich.edu// private:
129810234Syasuko.eckert@amd.comXMLElementPosition XMLNode::findPosition(XMLNodeData *d, int index,
129910234Syasuko.eckert@amd.com                                         XMLElementType xxtype) {
130010234Syasuko.eckert@amd.com    if (index < 0) return -1;
130110234Syasuko.eckert@amd.com    int i = 0, j = (int)((index << 2) + xxtype), *o = d->pOrder;
130210234Syasuko.eckert@amd.com    while (o[i] != j) i++;
130310234Syasuko.eckert@amd.com    return i;
130410152Satgutier@umich.edu}
130510152Satgutier@umich.edu
130610152Satgutier@umich.edu// private:
130710152Satgutier@umich.edu// update "order" information when deleting a content of a XMLNode
130810234Syasuko.eckert@amd.comint XMLNode::removeOrderElement(XMLNodeData *d, XMLElementType t, int index) {
130910234Syasuko.eckert@amd.com    int n = d->nChild + d->nText + d->nClear;
131010234Syasuko.eckert@amd.com    int *o = d->pOrder;
131110234Syasuko.eckert@amd.com    int i = findPosition(d, index, t);
131210234Syasuko.eckert@amd.com    memmove(o + i, o + i + 1, (n - i)*sizeof(int));
131310234Syasuko.eckert@amd.com    for (; i < n; i++)
131410234Syasuko.eckert@amd.com        if ((o[i]&3) == (int)t) o[i] -= 4;
131510152Satgutier@umich.edu    // We should normally do:
131610152Satgutier@umich.edu    // d->pOrder=(int)realloc(d->pOrder,n*sizeof(int));
131710152Satgutier@umich.edu    // but we skip reallocation because it's too time consuming.
131810152Satgutier@umich.edu    // Anyway, at the end, it will be free'd completely at once.
131910152Satgutier@umich.edu    return i;
132010152Satgutier@umich.edu}
132110152Satgutier@umich.edu
132210234Syasuko.eckert@amd.comvoid *XMLNode::addToOrder(int memoryIncrease, int *_pos, int nc, void *p,
132310234Syasuko.eckert@amd.com                          int size, XMLElementType xtype) {
132410152Satgutier@umich.edu    //  in: *_pos is the position inside d->pOrder ("-1" means "EndOf")
132510152Satgutier@umich.edu    // out: *_pos is the index inside p
132610234Syasuko.eckert@amd.com    p = myRealloc(p, (nc + 1), memoryIncrease, size);
132710234Syasuko.eckert@amd.com    int n = d->nChild + d->nText + d->nClear;
132810234Syasuko.eckert@amd.com    d->pOrder = (int*)myRealloc(d->pOrder, n + 1, memoryIncrease * 3,
132910234Syasuko.eckert@amd.com                                sizeof(int));
133010234Syasuko.eckert@amd.com    int pos = *_pos, *o = d->pOrder;
133110152Satgutier@umich.edu
133210234Syasuko.eckert@amd.com    if ((pos < 0) || (pos >= n)) {
133310234Syasuko.eckert@amd.com        *_pos = nc;
133410234Syasuko.eckert@amd.com        o[n] = (int)((nc << 2) + xtype);
133510234Syasuko.eckert@amd.com        return p;
133610234Syasuko.eckert@amd.com    }
133710152Satgutier@umich.edu
133810234Syasuko.eckert@amd.com    int i = pos;
133910234Syasuko.eckert@amd.com    memmove(o + i + 1, o + i, (n - i)*sizeof(int));
134010152Satgutier@umich.edu
134110234Syasuko.eckert@amd.com    while ((pos < n) && ((o[pos]&3) != (int)xtype)) pos++;
134210234Syasuko.eckert@amd.com    if (pos == n) {
134310234Syasuko.eckert@amd.com        *_pos = nc;
134410234Syasuko.eckert@amd.com        o[n] = (int)((nc << 2) + xtype);
134510234Syasuko.eckert@amd.com        return p;
134610234Syasuko.eckert@amd.com    }
134710152Satgutier@umich.edu
134810234Syasuko.eckert@amd.com    o[i] = o[pos];
134910234Syasuko.eckert@amd.com    for (i = pos + 1; i <= n; i++) if ((o[i]&3) == (int)xtype) o[i] += 4;
135010152Satgutier@umich.edu
135110234Syasuko.eckert@amd.com    *_pos = pos = o[pos] >> 2;
135210234Syasuko.eckert@amd.com    memmove(((char*)p) + (pos + 1)*size, ((char*)p) + pos*size, (nc - pos)*size);
135310152Satgutier@umich.edu
135410152Satgutier@umich.edu    return p;
135510152Satgutier@umich.edu}
135610152Satgutier@umich.edu
135710152Satgutier@umich.edu// Add a child node to the given element.
135810234Syasuko.eckert@amd.comXMLNode XMLNode::addChild_priv(int memoryIncrease, XMLSTR lpszName,
135910234Syasuko.eckert@amd.com                               char isDeclaration, int pos) {
136010152Satgutier@umich.edu    if (!lpszName) return emptyXMLNode;
136110234Syasuko.eckert@amd.com    d->pChild = (XMLNode*)addToOrder(memoryIncrease, &pos, d->nChild,
136210234Syasuko.eckert@amd.com                                     d->pChild, sizeof(XMLNode), eNodeChild);
136310234Syasuko.eckert@amd.com    d->pChild[pos].d = NULL;
136410234Syasuko.eckert@amd.com    d->pChild[pos] = XMLNode(d, lpszName, isDeclaration);
136510152Satgutier@umich.edu    d->nChild++;
136610152Satgutier@umich.edu    return d->pChild[pos];
136710152Satgutier@umich.edu}
136810152Satgutier@umich.edu
136910152Satgutier@umich.edu// Add an attribute to an element.
137010234Syasuko.eckert@amd.comXMLAttribute *XMLNode::addAttribute_priv(int memoryIncrease, XMLSTR lpszName,
137110234Syasuko.eckert@amd.com                                         XMLSTR lpszValuev) {
137210152Satgutier@umich.edu    if (!lpszName) return &emptyXMLAttribute;
137310234Syasuko.eckert@amd.com    if (!d) {
137410234Syasuko.eckert@amd.com        myFree(lpszName);
137510234Syasuko.eckert@amd.com        myFree(lpszValuev);
137610234Syasuko.eckert@amd.com        return &emptyXMLAttribute;
137710234Syasuko.eckert@amd.com    }
137810234Syasuko.eckert@amd.com    int nc = d->nAttribute;
137910234Syasuko.eckert@amd.com    d->pAttribute = (XMLAttribute*)myRealloc(d->pAttribute, (nc + 1),
138010234Syasuko.eckert@amd.com                                             memoryIncrease,
138110234Syasuko.eckert@amd.com                                             sizeof(XMLAttribute));
138210234Syasuko.eckert@amd.com    XMLAttribute *pAttr = d->pAttribute + nc;
138310152Satgutier@umich.edu    pAttr->lpszName = lpszName;
138410152Satgutier@umich.edu    pAttr->lpszValue = lpszValuev;
138510152Satgutier@umich.edu    d->nAttribute++;
138610152Satgutier@umich.edu    return pAttr;
138710152Satgutier@umich.edu}
138810152Satgutier@umich.edu
138910152Satgutier@umich.edu// Add text to the element.
139010234Syasuko.eckert@amd.comXMLCSTR XMLNode::addText_priv(int memoryIncrease, XMLSTR lpszValue, int pos) {
139110152Satgutier@umich.edu    if (!lpszValue) return NULL;
139210234Syasuko.eckert@amd.com    if (!d) {
139310234Syasuko.eckert@amd.com        myFree(lpszValue);
139410234Syasuko.eckert@amd.com        return NULL;
139510234Syasuko.eckert@amd.com    }
139610234Syasuko.eckert@amd.com    d->pText = (XMLCSTR*)addToOrder(memoryIncrease, &pos, d->nText, d->pText,
139710234Syasuko.eckert@amd.com                                    sizeof(XMLSTR), eNodeText);
139810234Syasuko.eckert@amd.com    d->pText[pos] = lpszValue;
139910152Satgutier@umich.edu    d->nText++;
140010152Satgutier@umich.edu    return lpszValue;
140110152Satgutier@umich.edu}
140210152Satgutier@umich.edu
140310152Satgutier@umich.edu// Add clear (unformatted) text to the element.
140410234Syasuko.eckert@amd.comXMLClear *XMLNode::addClear_priv(int memoryIncrease, XMLSTR lpszValue,
140510234Syasuko.eckert@amd.com                                 XMLCSTR lpszOpen, XMLCSTR lpszClose,
140610234Syasuko.eckert@amd.com                                 int pos) {
140710152Satgutier@umich.edu    if (!lpszValue) return &emptyXMLClear;
140810234Syasuko.eckert@amd.com    if (!d) {
140910234Syasuko.eckert@amd.com        myFree(lpszValue);
141010234Syasuko.eckert@amd.com        return &emptyXMLClear;
141110234Syasuko.eckert@amd.com    }
141210234Syasuko.eckert@amd.com    d->pClear = (XMLClear *)addToOrder(memoryIncrease, &pos, d->nClear,
141310234Syasuko.eckert@amd.com                                       d->pClear, sizeof(XMLClear),
141410234Syasuko.eckert@amd.com                                       eNodeClear);
141510234Syasuko.eckert@amd.com    XMLClear *pNewClear = d->pClear + pos;
141610152Satgutier@umich.edu    pNewClear->lpszValue = lpszValue;
141710234Syasuko.eckert@amd.com    if (!lpszOpen) lpszOpen = XMLClearTags->lpszOpen;
141810234Syasuko.eckert@amd.com    if (!lpszClose) lpszClose = XMLClearTags->lpszClose;
141910152Satgutier@umich.edu    pNewClear->lpszOpenTag = lpszOpen;
142010152Satgutier@umich.edu    pNewClear->lpszCloseTag = lpszClose;
142110152Satgutier@umich.edu    d->nClear++;
142210152Satgutier@umich.edu    return pNewClear;
142310152Satgutier@umich.edu}
142410152Satgutier@umich.edu
142510152Satgutier@umich.edu// private:
142610152Satgutier@umich.edu// Parse a clear (unformatted) type node.
142710234Syasuko.eckert@amd.comchar XMLNode::parseClearTag(void *px, void *_pClear) {
142810234Syasuko.eckert@amd.com    XML *pXML = (XML *)px;
142910234Syasuko.eckert@amd.com    ALLXMLClearTag pClear = *((ALLXMLClearTag*)_pClear);
143010234Syasuko.eckert@amd.com    int cbTemp = 0;
143110234Syasuko.eckert@amd.com    XMLCSTR lpszTemp = NULL;
143210234Syasuko.eckert@amd.com    XMLCSTR lpXML = &pXML->lpXML[pXML->nIndex];
143310234Syasuko.eckert@amd.com    static XMLCSTR docTypeEnd = _CXML("]>");
143410152Satgutier@umich.edu
143510152Satgutier@umich.edu    // Find the closing tag
143610152Satgutier@umich.edu    // Seems the <!DOCTYPE need a better treatment so lets handle it
143710234Syasuko.eckert@amd.com    if (pClear.lpszOpen == XMLClearTags[1].lpszOpen) {
143810234Syasuko.eckert@amd.com        XMLCSTR pCh = lpXML;
143910234Syasuko.eckert@amd.com        while (*pCh) {
144010234Syasuko.eckert@amd.com            if (*pCh == _CXML('<')) {
144110234Syasuko.eckert@amd.com                pClear.lpszClose = docTypeEnd;
144210234Syasuko.eckert@amd.com                lpszTemp = xstrstr(lpXML, docTypeEnd);
144310234Syasuko.eckert@amd.com                break;
144410234Syasuko.eckert@amd.com            } else if (*pCh == _CXML('>')) {
144510234Syasuko.eckert@amd.com                lpszTemp = pCh;
144610234Syasuko.eckert@amd.com                break;
144710234Syasuko.eckert@amd.com            }
144810152Satgutier@umich.edu#ifdef _XMLWIDECHAR
144910152Satgutier@umich.edu            pCh++;
145010152Satgutier@umich.edu#else
145110234Syasuko.eckert@amd.com            pCh += XML_ByteTable[(unsigned char)(*pCh)];
145210152Satgutier@umich.edu#endif
145310152Satgutier@umich.edu        }
145410234Syasuko.eckert@amd.com    } else lpszTemp = xstrstr(lpXML, pClear.lpszClose);
145510152Satgutier@umich.edu
145610234Syasuko.eckert@amd.com    if (lpszTemp) {
145710152Satgutier@umich.edu        // Cache the size and increment the index
145810152Satgutier@umich.edu        cbTemp = (int)(lpszTemp - lpXML);
145910152Satgutier@umich.edu
146010234Syasuko.eckert@amd.com        pXML->nIndex += cbTemp + (int)xstrlen(pClear.lpszClose);
146110152Satgutier@umich.edu
146210152Satgutier@umich.edu        // Add the clear node to the current element
146310234Syasuko.eckert@amd.com        addClear_priv(MEMORYINCREASE, stringDup(lpXML, cbTemp),
146410234Syasuko.eckert@amd.com                      pClear.lpszOpen, pClear.lpszClose, -1);
146510152Satgutier@umich.edu        return 0;
146610152Satgutier@umich.edu    }
146710152Satgutier@umich.edu
146810152Satgutier@umich.edu    // If we failed to find the end tag
146910152Satgutier@umich.edu    pXML->error = eXMLErrorUnmatchedEndClearTag;
147010152Satgutier@umich.edu    return 1;
147110152Satgutier@umich.edu}
147210152Satgutier@umich.edu
147310234Syasuko.eckert@amd.comvoid XMLNode::exactMemory(XMLNodeData *d) {
147410234Syasuko.eckert@amd.com    if (d->pOrder) {
147510234Syasuko.eckert@amd.com        d->pOrder = (int*)realloc(d->pOrder, (d->nChild + d->nText + d->nClear)
147610234Syasuko.eckert@amd.com                                  * sizeof(int));
147710234Syasuko.eckert@amd.com    }
147810234Syasuko.eckert@amd.com    if (d->pChild) {
147910234Syasuko.eckert@amd.com        d->pChild = (XMLNode*)realloc(d->pChild, d->nChild * sizeof(XMLNode));
148010234Syasuko.eckert@amd.com    }
148110234Syasuko.eckert@amd.com    if (d->pAttribute) {
148210234Syasuko.eckert@amd.com        d->pAttribute = (XMLAttribute*)realloc(d->pAttribute, d->nAttribute *
148310234Syasuko.eckert@amd.com                                               sizeof(XMLAttribute));
148410234Syasuko.eckert@amd.com    }
148510234Syasuko.eckert@amd.com    if (d->pText) {
148610234Syasuko.eckert@amd.com        d->pText = (XMLCSTR*)realloc(d->pText, d->nText * sizeof(XMLSTR));
148710234Syasuko.eckert@amd.com    }
148810234Syasuko.eckert@amd.com    if (d->pClear) {
148910234Syasuko.eckert@amd.com        d->pClear = (XMLClear *)realloc(d->pClear, d->nClear * sizeof(XMLClear));
149010234Syasuko.eckert@amd.com    }
149110152Satgutier@umich.edu}
149210152Satgutier@umich.edu
149310234Syasuko.eckert@amd.comchar XMLNode::maybeAddTxT(void *pa, XMLCSTR tokenPStr) {
149410234Syasuko.eckert@amd.com    XML *pXML = (XML *)pa;
149510234Syasuko.eckert@amd.com    XMLCSTR lpszText = pXML->lpszText;
149610152Satgutier@umich.edu    if (!lpszText) return 0;
149710234Syasuko.eckert@amd.com    if (dropWhiteSpace) while (XML_isSPACECHAR(*lpszText) &&
149810234Syasuko.eckert@amd.com                               (lpszText != tokenPStr)) lpszText++;
149910152Satgutier@umich.edu    int cbText = (int)(tokenPStr - lpszText);
150010234Syasuko.eckert@amd.com    if (!cbText) {
150110234Syasuko.eckert@amd.com        pXML->lpszText = NULL;
150210234Syasuko.eckert@amd.com        return 0;
150310234Syasuko.eckert@amd.com    }
150410234Syasuko.eckert@amd.com    if (dropWhiteSpace) {
150510234Syasuko.eckert@amd.com        cbText--;
150610234Syasuko.eckert@amd.com        while ((cbText) && XML_isSPACECHAR(lpszText[cbText])) cbText--;
150710234Syasuko.eckert@amd.com        cbText++;
150810234Syasuko.eckert@amd.com    }
150910234Syasuko.eckert@amd.com    if (!cbText) {
151010234Syasuko.eckert@amd.com        pXML->lpszText = NULL;
151110234Syasuko.eckert@amd.com        return 0;
151210234Syasuko.eckert@amd.com    }
151310234Syasuko.eckert@amd.com    XMLSTR lpt = fromXMLString(lpszText, cbText, pXML);
151410152Satgutier@umich.edu    if (!lpt) return 1;
151510234Syasuko.eckert@amd.com    pXML->lpszText = NULL;
151610234Syasuko.eckert@amd.com    if (removeCommentsInMiddleOfText && d->nText && d->nClear) {
151710152Satgutier@umich.edu        // if the previous insertion was a comment (<!-- -->) AND
151810152Satgutier@umich.edu        // if the previous previous insertion was a text then, delete the comment and append the text
151910234Syasuko.eckert@amd.com        int n = d->nChild + d->nText + d->nClear - 1, *o = d->pOrder;
152010234Syasuko.eckert@amd.com        if (((o[n]&3) == eNodeClear) && ((o[n-1]&3) == eNodeText)) {
152110234Syasuko.eckert@amd.com            int i = o[n] >> 2;
152210234Syasuko.eckert@amd.com            if (d->pClear[i].lpszOpenTag == XMLClearTags[2].lpszOpen) {
152310152Satgutier@umich.edu                deleteClear(i);
152410234Syasuko.eckert@amd.com                i = o[n-1] >> 2;
152510234Syasuko.eckert@amd.com                n = xstrlen(d->pText[i]);
152610234Syasuko.eckert@amd.com                int n2 = xstrlen(lpt) + 1;
152710234Syasuko.eckert@amd.com                d->pText[i] = (XMLSTR)realloc((void*)d->pText[i], (n + n2) *
152810234Syasuko.eckert@amd.com                                              sizeof(XMLCHAR));
152910152Satgutier@umich.edu                if (!d->pText[i]) return 1;
153010234Syasuko.eckert@amd.com                memcpy((void*)(d->pText[i] + n), lpt, n2*sizeof(XMLCHAR));
153110152Satgutier@umich.edu                free(lpt);
153210152Satgutier@umich.edu                return 0;
153310152Satgutier@umich.edu            }
153410152Satgutier@umich.edu        }
153510152Satgutier@umich.edu    }
153610234Syasuko.eckert@amd.com    addText_priv(MEMORYINCREASE, lpt, -1);
153710152Satgutier@umich.edu    return 0;
153810152Satgutier@umich.edu}
153910152Satgutier@umich.edu// private:
154010152Satgutier@umich.edu// Recursively parse an XML element.
154110234Syasuko.eckert@amd.comint XMLNode::ParseXMLElement(void *pa) {
154210234Syasuko.eckert@amd.com    XML *pXML = (XML *)pa;
154310152Satgutier@umich.edu    int cbToken;
154410152Satgutier@umich.edu    enum XMLTokenTypeTag xtype;
154510152Satgutier@umich.edu    NextToken token;
154610234Syasuko.eckert@amd.com    XMLCSTR lpszTemp = NULL;
154710234Syasuko.eckert@amd.com    int cbTemp = 0;
154810152Satgutier@umich.edu    char nDeclaration;
154910152Satgutier@umich.edu    XMLNode pNew;
155010152Satgutier@umich.edu    enum Status status; // inside or outside a tag
155110152Satgutier@umich.edu    enum Attrib attrib = eAttribName;
155210152Satgutier@umich.edu
155310152Satgutier@umich.edu    assert(pXML);
155410152Satgutier@umich.edu
155510152Satgutier@umich.edu    // If this is the first call to the function
155610234Syasuko.eckert@amd.com    if (pXML->nFirst) {
155710152Satgutier@umich.edu        // Assume we are outside of a tag definition
155810152Satgutier@umich.edu        pXML->nFirst = FALSE;
155910152Satgutier@umich.edu        status = eOutsideTag;
156010234Syasuko.eckert@amd.com    } else {
156110152Satgutier@umich.edu        // If this is not the first call then we should only be called when inside a tag.
156210152Satgutier@umich.edu        status = eInsideTag;
156310152Satgutier@umich.edu    }
156410152Satgutier@umich.edu
156510152Satgutier@umich.edu    // Iterate through the tokens in the document
156610234Syasuko.eckert@amd.com    for (;;) {
156710152Satgutier@umich.edu        // Obtain the next token
156810152Satgutier@umich.edu        token = GetNextToken(pXML, &cbToken, &xtype);
156910152Satgutier@umich.edu
157010234Syasuko.eckert@amd.com        if (xtype != eTokenError) {
157110152Satgutier@umich.edu            // Check the current status
157210234Syasuko.eckert@amd.com            switch (status) {
157310152Satgutier@umich.edu
157410234Syasuko.eckert@amd.com                // If we are outside of a tag definition
157510152Satgutier@umich.edu            case eOutsideTag:
157610152Satgutier@umich.edu
157710152Satgutier@umich.edu                // Check what type of token we obtained
157810234Syasuko.eckert@amd.com                switch (xtype) {
157910234Syasuko.eckert@amd.com                    // If we have found text or quoted text
158010152Satgutier@umich.edu                case eTokenText:
158110152Satgutier@umich.edu                case eTokenCloseTag:          /* '>'         */
158210152Satgutier@umich.edu                case eTokenShortHandClose:    /* '/>'        */
158310152Satgutier@umich.edu                case eTokenQuotedText:
158410152Satgutier@umich.edu                case eTokenEquals:
158510152Satgutier@umich.edu                    break;
158610152Satgutier@umich.edu
158710234Syasuko.eckert@amd.com                    // If we found a start tag '<' and declarations '<?'
158810152Satgutier@umich.edu                case eTokenTagStart:
158910152Satgutier@umich.edu                case eTokenDeclaration:
159010152Satgutier@umich.edu
159110152Satgutier@umich.edu                    // Cache whether this new element is a declaration or not
159210152Satgutier@umich.edu                    nDeclaration = (xtype == eTokenDeclaration);
159310152Satgutier@umich.edu
159410152Satgutier@umich.edu                    // If we have node text then add this to the element
159510234Syasuko.eckert@amd.com                    if (maybeAddTxT(pXML, token.pStr)) return FALSE;
159610152Satgutier@umich.edu
159710152Satgutier@umich.edu                    // Find the name of the tag
159810152Satgutier@umich.edu                    token = GetNextToken(pXML, &cbToken, &xtype);
159910152Satgutier@umich.edu
160010152Satgutier@umich.edu                    // Return an error if we couldn't obtain the next token or
160110152Satgutier@umich.edu                    // it wasnt text
160210234Syasuko.eckert@amd.com                    if (xtype != eTokenText) {
160310152Satgutier@umich.edu                        pXML->error = eXMLErrorMissingTagName;
160410152Satgutier@umich.edu                        return FALSE;
160510152Satgutier@umich.edu                    }
160610152Satgutier@umich.edu
160710152Satgutier@umich.edu                    // If we found a new element which is the same as this
160810152Satgutier@umich.edu                    // element then we need to pass this back to the caller..
160910152Satgutier@umich.edu
161010152Satgutier@umich.edu#ifdef APPROXIMATE_PARSING
161110152Satgutier@umich.edu                    if (d->lpszName &&
161210234Syasuko.eckert@amd.com                            myTagCompare(d->lpszName, token.pStr) == 0) {
161310152Satgutier@umich.edu                        // Indicate to the caller that it needs to create a
161410152Satgutier@umich.edu                        // new element.
161510152Satgutier@umich.edu                        pXML->lpNewElement = token.pStr;
161610152Satgutier@umich.edu                        pXML->cbNewElement = cbToken;
161710152Satgutier@umich.edu                        return TRUE;
161810152Satgutier@umich.edu                    } else
161910152Satgutier@umich.edu#endif
162010152Satgutier@umich.edu                    {
162110152Satgutier@umich.edu                        // If the name of the new element differs from the name of
162210152Satgutier@umich.edu                        // the current element we need to add the new element to
162310152Satgutier@umich.edu                        // the current one and recurse
162410234Syasuko.eckert@amd.com                        pNew = addChild_priv(MEMORYINCREASE,
162510234Syasuko.eckert@amd.com                                             stringDup(token.pStr, cbToken),
162610234Syasuko.eckert@amd.com                                             nDeclaration, -1);
162710152Satgutier@umich.edu
162810234Syasuko.eckert@amd.com                        while (!pNew.isEmpty()) {
162910152Satgutier@umich.edu                            // Callself to process the new node.  If we return
163010152Satgutier@umich.edu                            // FALSE this means we dont have any more
163110152Satgutier@umich.edu                            // processing to do...
163210152Satgutier@umich.edu
163310152Satgutier@umich.edu                            if (!pNew.ParseXMLElement(pXML)) return FALSE;
163410234Syasuko.eckert@amd.com                            else {
163510152Satgutier@umich.edu                                // If the call to recurse this function
163610152Satgutier@umich.edu                                // evented in a end tag specified in XML then
163710152Satgutier@umich.edu                                // we need to unwind the calls to this
163810152Satgutier@umich.edu                                // function until we find the appropriate node
163910152Satgutier@umich.edu                                // (the element name and end tag name must
164010152Satgutier@umich.edu                                // match)
164110234Syasuko.eckert@amd.com                                if (pXML->cbEndTag) {
164210152Satgutier@umich.edu                                    // If we are back at the root node then we
164310152Satgutier@umich.edu                                    // have an unmatched end tag
164410234Syasuko.eckert@amd.com                                    if (!d->lpszName) {
164510234Syasuko.eckert@amd.com                                        pXML->error = eXMLErrorUnmatchedEndTag;
164610152Satgutier@umich.edu                                        return FALSE;
164710152Satgutier@umich.edu                                    }
164810152Satgutier@umich.edu
164910152Satgutier@umich.edu                                    // If the end tag matches the name of this
165010152Satgutier@umich.edu                                    // element then we only need to unwind
165110152Satgutier@umich.edu                                    // once more...
165210152Satgutier@umich.edu
165310234Syasuko.eckert@amd.com                                    if (myTagCompare(d->lpszName,
165410234Syasuko.eckert@amd.com                                                     pXML->lpEndTag) == 0) {
165510152Satgutier@umich.edu                                        pXML->cbEndTag = 0;
165610152Satgutier@umich.edu                                    }
165710152Satgutier@umich.edu
165810152Satgutier@umich.edu                                    return TRUE;
165910234Syasuko.eckert@amd.com                                } else if (pXML->cbNewElement) {
166010234Syasuko.eckert@amd.com                                    // If the call indicated a new element is to
166110234Syasuko.eckert@amd.com                                    // be created on THIS element.
166210152Satgutier@umich.edu
166310234Syasuko.eckert@amd.com                                    // If the name of this element matches the
166410234Syasuko.eckert@amd.com                                    // name of the element we need to create
166510234Syasuko.eckert@amd.com                                    // then we need to return to the caller
166610234Syasuko.eckert@amd.com                                    // and let it process the element.
166710152Satgutier@umich.edu
166810234Syasuko.eckert@amd.com                                    if (myTagCompare(d->lpszName,
166910234Syasuko.eckert@amd.com                                                     pXML->lpNewElement) == 0) {
167010234Syasuko.eckert@amd.com                                        return TRUE;
167110234Syasuko.eckert@amd.com                                    }
167210152Satgutier@umich.edu
167310234Syasuko.eckert@amd.com                                    // Add the new element and recurse
167410234Syasuko.eckert@amd.com                                    pNew =
167510234Syasuko.eckert@amd.com                                        addChild_priv(MEMORYINCREASE,
167610234Syasuko.eckert@amd.com                                                      stringDup(pXML->
167710234Syasuko.eckert@amd.com                                                                lpNewElement,
167810234Syasuko.eckert@amd.com                                                                pXML->
167910234Syasuko.eckert@amd.com                                                                cbNewElement),
168010234Syasuko.eckert@amd.com                                                      0, -1);
168110234Syasuko.eckert@amd.com                                    pXML->cbNewElement = 0;
168210234Syasuko.eckert@amd.com                                } else {
168310234Syasuko.eckert@amd.com                                    // If we didn't have a new element to create
168410234Syasuko.eckert@amd.com                                    pNew = emptyXMLNode;
168510152Satgutier@umich.edu
168610234Syasuko.eckert@amd.com                                }
168710152Satgutier@umich.edu                            }
168810152Satgutier@umich.edu                        }
168910152Satgutier@umich.edu                    }
169010152Satgutier@umich.edu                    break;
169110152Satgutier@umich.edu
169210234Syasuko.eckert@amd.com                    // If we found an end tag
169310152Satgutier@umich.edu                case eTokenTagEnd:
169410152Satgutier@umich.edu
169510152Satgutier@umich.edu                    // If we have node text then add this to the element
169610234Syasuko.eckert@amd.com                    if (maybeAddTxT(pXML, token.pStr)) return FALSE;
169710152Satgutier@umich.edu
169810152Satgutier@umich.edu                    // Find the name of the end tag
169910152Satgutier@umich.edu                    token = GetNextToken(pXML, &cbTemp, &xtype);
170010152Satgutier@umich.edu
170110152Satgutier@umich.edu                    // The end tag should be text
170210234Syasuko.eckert@amd.com                    if (xtype != eTokenText) {
170310152Satgutier@umich.edu                        pXML->error = eXMLErrorMissingEndTagName;
170410152Satgutier@umich.edu                        return FALSE;
170510152Satgutier@umich.edu                    }
170610152Satgutier@umich.edu                    lpszTemp = token.pStr;
170710152Satgutier@umich.edu
170810152Satgutier@umich.edu                    // After the end tag we should find a closing tag
170910152Satgutier@umich.edu                    token = GetNextToken(pXML, &cbToken, &xtype);
171010234Syasuko.eckert@amd.com                    if (xtype != eTokenCloseTag) {
171110152Satgutier@umich.edu                        pXML->error = eXMLErrorMissingEndTagName;
171210152Satgutier@umich.edu                        return FALSE;
171310152Satgutier@umich.edu                    }
171410234Syasuko.eckert@amd.com                    pXML->lpszText = pXML->lpXML + pXML->nIndex;
171510152Satgutier@umich.edu
171610152Satgutier@umich.edu                    // We need to return to the previous caller.  If the name
171710152Satgutier@umich.edu                    // of the tag cannot be found we need to keep returning to
171810152Satgutier@umich.edu                    // caller until we find a match
171910152Satgutier@umich.edu                    if (myTagCompare(d->lpszName, lpszTemp) != 0)
172010152Satgutier@umich.edu#ifdef STRICT_PARSING
172110152Satgutier@umich.edu                    {
172210234Syasuko.eckert@amd.com                        pXML->error = eXMLErrorUnmatchedEndTag;
172310234Syasuko.eckert@amd.com                        pXML->nIndexMissigEndTag = pXML->nIndex;
172410152Satgutier@umich.edu                        return FALSE;
172510152Satgutier@umich.edu                    }
172610152Satgutier@umich.edu#else
172710152Satgutier@umich.edu                    {
172810234Syasuko.eckert@amd.com                        pXML->error = eXMLErrorMissingEndTag;
172910234Syasuko.eckert@amd.com                        pXML->nIndexMissigEndTag = pXML->nIndex;
173010152Satgutier@umich.edu                        pXML->lpEndTag = lpszTemp;
173110152Satgutier@umich.edu                        pXML->cbEndTag = cbTemp;
173210152Satgutier@umich.edu                    }
173310152Satgutier@umich.edu#endif
173410152Satgutier@umich.edu
173510152Satgutier@umich.edu                    // Return to the caller
173610152Satgutier@umich.edu                    exactMemory(d);
173710152Satgutier@umich.edu                    return TRUE;
173810152Satgutier@umich.edu
173910234Syasuko.eckert@amd.com                    // If we found a clear (unformatted) token
174010152Satgutier@umich.edu                case eTokenClear:
174110152Satgutier@umich.edu                    // If we have node text then add this to the element
174210234Syasuko.eckert@amd.com                    if (maybeAddTxT(pXML, token.pStr)) return FALSE;
174310152Satgutier@umich.edu                    if (parseClearTag(pXML, token.pClr)) return FALSE;
174410234Syasuko.eckert@amd.com                    pXML->lpszText = pXML->lpXML + pXML->nIndex;
174510152Satgutier@umich.edu                    break;
174610152Satgutier@umich.edu
174710152Satgutier@umich.edu                default:
174810152Satgutier@umich.edu                    break;
174910152Satgutier@umich.edu                }
175010152Satgutier@umich.edu                break;
175110152Satgutier@umich.edu
175210234Syasuko.eckert@amd.com                // If we are inside a tag definition we need to search for attributes
175310152Satgutier@umich.edu            case eInsideTag:
175410152Satgutier@umich.edu
175510152Satgutier@umich.edu                // Check what part of the attribute (name, equals, value) we
175610152Satgutier@umich.edu                // are looking for.
175710234Syasuko.eckert@amd.com                switch (attrib) {
175810234Syasuko.eckert@amd.com                    // If we are looking for a new attribute
175910152Satgutier@umich.edu                case eAttribName:
176010152Satgutier@umich.edu
176110152Satgutier@umich.edu                    // Check what the current token type is
176210234Syasuko.eckert@amd.com                    switch (xtype) {
176310234Syasuko.eckert@amd.com                        // If the current type is text...
176410234Syasuko.eckert@amd.com                        // Eg.  'attribute'
176510152Satgutier@umich.edu                    case eTokenText:
176610152Satgutier@umich.edu                        // Cache the token then indicate that we are next to
176710152Satgutier@umich.edu                        // look for the equals
176810152Satgutier@umich.edu                        lpszTemp = token.pStr;
176910152Satgutier@umich.edu                        cbTemp = cbToken;
177010152Satgutier@umich.edu                        attrib = eAttribEquals;
177110152Satgutier@umich.edu                        break;
177210152Satgutier@umich.edu
177310234Syasuko.eckert@amd.com                        // If we found a closing tag...
177410234Syasuko.eckert@amd.com                        // Eg.  '>'
177510152Satgutier@umich.edu                    case eTokenCloseTag:
177610152Satgutier@umich.edu                        // We are now outside the tag
177710152Satgutier@umich.edu                        status = eOutsideTag;
177810234Syasuko.eckert@amd.com                        pXML->lpszText = pXML->lpXML + pXML->nIndex;
177910152Satgutier@umich.edu                        break;
178010152Satgutier@umich.edu
178110234Syasuko.eckert@amd.com                        // If we found a short hand '/>' closing tag then we can
178210234Syasuko.eckert@amd.com                        // return to the caller
178310152Satgutier@umich.edu                    case eTokenShortHandClose:
178410152Satgutier@umich.edu                        exactMemory(d);
178510234Syasuko.eckert@amd.com                        pXML->lpszText = pXML->lpXML + pXML->nIndex;
178610152Satgutier@umich.edu                        return TRUE;
178710152Satgutier@umich.edu
178810234Syasuko.eckert@amd.com                        // Errors...
178910152Satgutier@umich.edu                    case eTokenQuotedText:    /* '"SomeText"'   */
179010152Satgutier@umich.edu                    case eTokenTagStart:      /* '<'            */
179110152Satgutier@umich.edu                    case eTokenTagEnd:        /* '</'           */
179210152Satgutier@umich.edu                    case eTokenEquals:        /* '='            */
179310152Satgutier@umich.edu                    case eTokenDeclaration:   /* '<?'           */
179410152Satgutier@umich.edu                    case eTokenClear:
179510152Satgutier@umich.edu                        pXML->error = eXMLErrorUnexpectedToken;
179610152Satgutier@umich.edu                        return FALSE;
179710234Syasuko.eckert@amd.com                    default:
179810234Syasuko.eckert@amd.com                        break;
179910152Satgutier@umich.edu                    }
180010152Satgutier@umich.edu                    break;
180110152Satgutier@umich.edu
180210234Syasuko.eckert@amd.com                    // If we are looking for an equals
180310152Satgutier@umich.edu                case eAttribEquals:
180410152Satgutier@umich.edu                    // Check what the current token type is
180510234Syasuko.eckert@amd.com                    switch (xtype) {
180610234Syasuko.eckert@amd.com                        // If the current type is text...
180710234Syasuko.eckert@amd.com                        // Eg.  'Attribute AnotherAttribute'
180810152Satgutier@umich.edu                    case eTokenText:
180910152Satgutier@umich.edu                        // Add the unvalued attribute to the list
181010234Syasuko.eckert@amd.com                        addAttribute_priv(MEMORYINCREASE,
181110234Syasuko.eckert@amd.com                                          stringDup(lpszTemp, cbTemp), NULL);
181210152Satgutier@umich.edu                        // Cache the token then indicate.  We are next to
181310152Satgutier@umich.edu                        // look for the equals attribute
181410152Satgutier@umich.edu                        lpszTemp = token.pStr;
181510152Satgutier@umich.edu                        cbTemp = cbToken;
181610152Satgutier@umich.edu                        break;
181710152Satgutier@umich.edu
181810234Syasuko.eckert@amd.com                        // If we found a closing tag 'Attribute >' or a short hand
181910234Syasuko.eckert@amd.com                        // closing tag 'Attribute />'
182010152Satgutier@umich.edu                    case eTokenShortHandClose:
182110152Satgutier@umich.edu                    case eTokenCloseTag:
182210152Satgutier@umich.edu                        // If we are a declaration element '<?' then we need
182310152Satgutier@umich.edu                        // to remove extra closing '?' if it exists
182410234Syasuko.eckert@amd.com                        pXML->lpszText = pXML->lpXML + pXML->nIndex;
182510152Satgutier@umich.edu
182610152Satgutier@umich.edu                        if (d->isDeclaration &&
182710234Syasuko.eckert@amd.com                                (lpszTemp[cbTemp-1]) == _CXML('?')) {
182810152Satgutier@umich.edu                            cbTemp--;
182910234Syasuko.eckert@amd.com                            if (d->pParent && d->pParent->pParent) {
183010234Syasuko.eckert@amd.com                                xtype = eTokenShortHandClose;
183110234Syasuko.eckert@amd.com                            }
183210152Satgutier@umich.edu                        }
183310152Satgutier@umich.edu
183410234Syasuko.eckert@amd.com                        if (cbTemp) {
183510152Satgutier@umich.edu                            // Add the unvalued attribute to the list
183610234Syasuko.eckert@amd.com                            addAttribute_priv(MEMORYINCREASE,
183710234Syasuko.eckert@amd.com                                              stringDup(lpszTemp, cbTemp), NULL);
183810152Satgutier@umich.edu                        }
183910152Satgutier@umich.edu
184010152Satgutier@umich.edu                        // If this is the end of the tag then return to the caller
184110234Syasuko.eckert@amd.com                        if (xtype == eTokenShortHandClose) {
184210152Satgutier@umich.edu                            exactMemory(d);
184310152Satgutier@umich.edu                            return TRUE;
184410152Satgutier@umich.edu                        }
184510152Satgutier@umich.edu
184610152Satgutier@umich.edu                        // We are now outside the tag
184710152Satgutier@umich.edu                        status = eOutsideTag;
184810152Satgutier@umich.edu                        break;
184910152Satgutier@umich.edu
185010234Syasuko.eckert@amd.com                        // If we found the equals token...
185110234Syasuko.eckert@amd.com                        // Eg.  'Attribute ='
185210152Satgutier@umich.edu                    case eTokenEquals:
185310152Satgutier@umich.edu                        // Indicate that we next need to search for the value
185410152Satgutier@umich.edu                        // for the attribute
185510152Satgutier@umich.edu                        attrib = eAttribValue;
185610152Satgutier@umich.edu                        break;
185710152Satgutier@umich.edu
185810234Syasuko.eckert@amd.com                        // Errors...
185910152Satgutier@umich.edu                    case eTokenQuotedText:    /* 'Attribute "InvalidAttr"'*/
186010152Satgutier@umich.edu                    case eTokenTagStart:      /* 'Attribute <'            */
186110152Satgutier@umich.edu                    case eTokenTagEnd:        /* 'Attribute </'           */
186210152Satgutier@umich.edu                    case eTokenDeclaration:   /* 'Attribute <?'           */
186310152Satgutier@umich.edu                    case eTokenClear:
186410152Satgutier@umich.edu                        pXML->error = eXMLErrorUnexpectedToken;
186510152Satgutier@umich.edu                        return FALSE;
186610234Syasuko.eckert@amd.com                    default:
186710234Syasuko.eckert@amd.com                        break;
186810152Satgutier@umich.edu                    }
186910152Satgutier@umich.edu                    break;
187010152Satgutier@umich.edu
187110234Syasuko.eckert@amd.com                    // If we are looking for an attribute value
187210152Satgutier@umich.edu                case eAttribValue:
187310152Satgutier@umich.edu                    // Check what the current token type is
187410234Syasuko.eckert@amd.com                    switch (xtype) {
187510234Syasuko.eckert@amd.com                        // If the current type is text or quoted text...
187610234Syasuko.eckert@amd.com                        // Eg.  'Attribute = "Value"' or 'Attribute = Value' or
187710234Syasuko.eckert@amd.com                        // 'Attribute = 'Value''.
187810152Satgutier@umich.edu                    case eTokenText:
187910152Satgutier@umich.edu                    case eTokenQuotedText:
188010152Satgutier@umich.edu                        // If we are a declaration element '<?' then we need
188110152Satgutier@umich.edu                        // to remove extra closing '?' if it exists
188210152Satgutier@umich.edu                        if (d->isDeclaration &&
188310234Syasuko.eckert@amd.com                                (token.pStr[cbToken-1]) == _CXML('?')) {
188410152Satgutier@umich.edu                            cbToken--;
188510152Satgutier@umich.edu                        }
188610152Satgutier@umich.edu
188710234Syasuko.eckert@amd.com                        if (cbTemp) {
188810152Satgutier@umich.edu                            // Add the valued attribute to the list
188910234Syasuko.eckert@amd.com                            if (xtype == eTokenQuotedText) {
189010234Syasuko.eckert@amd.com                                token.pStr++;
189110234Syasuko.eckert@amd.com                                cbToken -= 2;
189210234Syasuko.eckert@amd.com                            }
189310234Syasuko.eckert@amd.com                            XMLSTR attrVal = (XMLSTR)token.pStr;
189410234Syasuko.eckert@amd.com                            if (attrVal) {
189510234Syasuko.eckert@amd.com                                attrVal = fromXMLString(attrVal, cbToken, pXML);
189610152Satgutier@umich.edu                                if (!attrVal) return FALSE;
189710152Satgutier@umich.edu                            }
189810234Syasuko.eckert@amd.com                            addAttribute_priv(MEMORYINCREASE,
189910234Syasuko.eckert@amd.com                                              stringDup(lpszTemp, cbTemp),
190010234Syasuko.eckert@amd.com                                              attrVal);
190110152Satgutier@umich.edu                        }
190210152Satgutier@umich.edu
190310152Satgutier@umich.edu                        // Indicate we are searching for a new attribute
190410152Satgutier@umich.edu                        attrib = eAttribName;
190510152Satgutier@umich.edu                        break;
190610152Satgutier@umich.edu
190710234Syasuko.eckert@amd.com                        // Errors...
190810152Satgutier@umich.edu                    case eTokenTagStart:        /* 'Attr = <'          */
190910152Satgutier@umich.edu                    case eTokenTagEnd:          /* 'Attr = </'         */
191010152Satgutier@umich.edu                    case eTokenCloseTag:        /* 'Attr = >'          */
191110152Satgutier@umich.edu                    case eTokenShortHandClose:  /* "Attr = />"         */
191210152Satgutier@umich.edu                    case eTokenEquals:          /* 'Attr = ='          */
191310152Satgutier@umich.edu                    case eTokenDeclaration:     /* 'Attr = <?'         */
191410152Satgutier@umich.edu                    case eTokenClear:
191510152Satgutier@umich.edu                        pXML->error = eXMLErrorUnexpectedToken;
191610152Satgutier@umich.edu                        return FALSE;
191710152Satgutier@umich.edu                        break;
191810234Syasuko.eckert@amd.com                    default:
191910234Syasuko.eckert@amd.com                        break;
192010152Satgutier@umich.edu                    }
192110152Satgutier@umich.edu                }
192210152Satgutier@umich.edu            }
192310152Satgutier@umich.edu        }
192410152Satgutier@umich.edu        // If we failed to obtain the next token
192510234Syasuko.eckert@amd.com        else {
192610234Syasuko.eckert@amd.com            if ((!d->isDeclaration) && (d->pParent)) {
192710152Satgutier@umich.edu#ifdef STRICT_PARSING
192810234Syasuko.eckert@amd.com                pXML->error = eXMLErrorUnmatchedEndTag;
192910152Satgutier@umich.edu#else
193010234Syasuko.eckert@amd.com                pXML->error = eXMLErrorMissingEndTag;
193110152Satgutier@umich.edu#endif
193210234Syasuko.eckert@amd.com                pXML->nIndexMissigEndTag = pXML->nIndex;
193310152Satgutier@umich.edu            }
193410234Syasuko.eckert@amd.com            maybeAddTxT(pXML, pXML->lpXML + pXML->nIndex);
193510152Satgutier@umich.edu            return FALSE;
193610152Satgutier@umich.edu        }
193710152Satgutier@umich.edu    }
193810152Satgutier@umich.edu}
193910152Satgutier@umich.edu
194010152Satgutier@umich.edu// Count the number of lines and columns in an XML string.
194110234Syasuko.eckert@amd.comstatic void CountLinesAndColumns(XMLCSTR lpXML, int nUpto,
194210234Syasuko.eckert@amd.com                                 XMLResults *pResults) {
194310152Satgutier@umich.edu    XMLCHAR ch;
194410152Satgutier@umich.edu    assert(lpXML);
194510152Satgutier@umich.edu    assert(pResults);
194610152Satgutier@umich.edu
194710234Syasuko.eckert@amd.com    struct XML xml = { lpXML, lpXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0,
194810234Syasuko.eckert@amd.com                       TRUE };
194910152Satgutier@umich.edu
195010152Satgutier@umich.edu    pResults->nLine = 1;
195110152Satgutier@umich.edu    pResults->nColumn = 1;
195210234Syasuko.eckert@amd.com    while (xml.nIndex < nUpto) {
195310152Satgutier@umich.edu        ch = getNextChar(&xml);
195410152Satgutier@umich.edu        if (ch != _CXML('\n')) pResults->nColumn++;
195510234Syasuko.eckert@amd.com        else {
195610152Satgutier@umich.edu            pResults->nLine++;
195710234Syasuko.eckert@amd.com            pResults->nColumn = 1;
195810152Satgutier@umich.edu        }
195910152Satgutier@umich.edu    }
196010152Satgutier@umich.edu}
196110152Satgutier@umich.edu
196210152Satgutier@umich.edu// Parse XML and return the root element.
196310234Syasuko.eckert@amd.comXMLNode XMLNode::parseString(XMLCSTR lpszXML, XMLCSTR tag,
196410234Syasuko.eckert@amd.com                             XMLResults *pResults) {
196510234Syasuko.eckert@amd.com    if (!lpszXML) {
196610234Syasuko.eckert@amd.com        if (pResults) {
196710234Syasuko.eckert@amd.com            pResults->error = eXMLErrorNoElements;
196810234Syasuko.eckert@amd.com            pResults->nLine = 0;
196910234Syasuko.eckert@amd.com            pResults->nColumn = 0;
197010152Satgutier@umich.edu        }
197110152Satgutier@umich.edu        return emptyXMLNode;
197210152Satgutier@umich.edu    }
197310152Satgutier@umich.edu
197410234Syasuko.eckert@amd.com    XMLNode xnode(NULL, NULL, FALSE);
197510234Syasuko.eckert@amd.com    struct XML xml = { lpszXML, lpszXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0,
197610234Syasuko.eckert@amd.com                       TRUE };
197710152Satgutier@umich.edu
197810152Satgutier@umich.edu    // Create header element
197910152Satgutier@umich.edu    xnode.ParseXMLElement(&xml);
198010152Satgutier@umich.edu    enum XMLError error = xml.error;
198110234Syasuko.eckert@amd.com    if (!xnode.nChildNode()) error = eXMLErrorNoXMLTagFound;
198210234Syasuko.eckert@amd.com    if ((xnode.nChildNode() == 1) && (xnode.nElement() == 1)) {
198310234Syasuko.eckert@amd.com        xnode = xnode.getChildNode(); // skip the empty node
198410234Syasuko.eckert@amd.com    }
198510152Satgutier@umich.edu
198610152Satgutier@umich.edu    // If no error occurred
198710234Syasuko.eckert@amd.com    if ((error == eXMLErrorNone) || (error == eXMLErrorMissingEndTag) ||
198810234Syasuko.eckert@amd.com        (error == eXMLErrorNoXMLTagFound)) {
198910234Syasuko.eckert@amd.com        XMLCSTR name = xnode.getName();
199010234Syasuko.eckert@amd.com        if (tag && (*tag) && ((!name) || (xstricmp(name, tag)))) {
199110234Syasuko.eckert@amd.com            xnode = xnode.getChildNode(tag);
199210234Syasuko.eckert@amd.com            if (xnode.isEmpty()) {
199310234Syasuko.eckert@amd.com                if (pResults) {
199410234Syasuko.eckert@amd.com                    pResults->error = eXMLErrorFirstTagNotFound;
199510234Syasuko.eckert@amd.com                    pResults->nLine = 0;
199610234Syasuko.eckert@amd.com                    pResults->nColumn = 0;
199710152Satgutier@umich.edu                }
199810152Satgutier@umich.edu                return emptyXMLNode;
199910152Satgutier@umich.edu            }
200010152Satgutier@umich.edu        }
200110234Syasuko.eckert@amd.com    } else {
200210152Satgutier@umich.edu        // Cleanup: this will destroy all the nodes
200310152Satgutier@umich.edu        xnode = emptyXMLNode;
200410152Satgutier@umich.edu    }
200510152Satgutier@umich.edu
200610152Satgutier@umich.edu
200710152Satgutier@umich.edu    // If we have been given somewhere to place results
200810234Syasuko.eckert@amd.com    if (pResults) {
200910152Satgutier@umich.edu        pResults->error = error;
201010152Satgutier@umich.edu
201110152Satgutier@umich.edu        // If we have an error
201210234Syasuko.eckert@amd.com        if (error != eXMLErrorNone) {
201310234Syasuko.eckert@amd.com            if (error == eXMLErrorMissingEndTag) {
201410234Syasuko.eckert@amd.com                xml.nIndex = xml.nIndexMissigEndTag;
201510234Syasuko.eckert@amd.com            }
201610152Satgutier@umich.edu            // Find which line and column it starts on.
201710152Satgutier@umich.edu            CountLinesAndColumns(xml.lpXML, xml.nIndex, pResults);
201810152Satgutier@umich.edu        }
201910152Satgutier@umich.edu    }
202010152Satgutier@umich.edu    return xnode;
202110152Satgutier@umich.edu}
202210152Satgutier@umich.edu
202310234Syasuko.eckert@amd.comXMLNode XMLNode::parseFile(XMLCSTR filename, XMLCSTR tag, XMLResults *pResults) {
202410234Syasuko.eckert@amd.com    if (pResults) {
202510234Syasuko.eckert@amd.com        pResults->nLine = 0;
202610234Syasuko.eckert@amd.com        pResults->nColumn = 0;
202710234Syasuko.eckert@amd.com    }
202810234Syasuko.eckert@amd.com    FILE *f = xfopen(filename, _CXML("rb"));
202910234Syasuko.eckert@amd.com    if (f == NULL) {
203010234Syasuko.eckert@amd.com        if (pResults) pResults->error = eXMLErrorFileNotFound;
203110234Syasuko.eckert@amd.com        return emptyXMLNode;
203210234Syasuko.eckert@amd.com    }
203310234Syasuko.eckert@amd.com    fseek(f, 0, SEEK_END);
203410234Syasuko.eckert@amd.com    int l = ftell(f), headerSz = 0;
203510234Syasuko.eckert@amd.com    if (!l) {
203610234Syasuko.eckert@amd.com        if (pResults) pResults->error = eXMLErrorEmpty;
203710234Syasuko.eckert@amd.com        fclose(f);
203810234Syasuko.eckert@amd.com        return emptyXMLNode;
203910234Syasuko.eckert@amd.com    }
204010234Syasuko.eckert@amd.com    fseek(f, 0, SEEK_SET);
204110234Syasuko.eckert@amd.com    unsigned char *buf = (unsigned char*)malloc(l + 4);
204210234Syasuko.eckert@amd.com    l = fread(buf, 1, l, f);
204310152Satgutier@umich.edu    fclose(f);
204410234Syasuko.eckert@amd.com    buf[l] = 0;
204510234Syasuko.eckert@amd.com    buf[l+1] = 0;
204610234Syasuko.eckert@amd.com    buf[l+2] = 0;
204710234Syasuko.eckert@amd.com    buf[l+3] = 0;
204810152Satgutier@umich.edu#ifdef _XMLWIDECHAR
204910234Syasuko.eckert@amd.com    if (guessWideCharChars) {
205010234Syasuko.eckert@amd.com        if (!myIsTextWideChar(buf, l)) {
205110234Syasuko.eckert@amd.com            XMLNode::XMLCharEncoding ce = XMLNode::char_encoding_legacy;
205210234Syasuko.eckert@amd.com            if ((buf[0] == 0xef) && (buf[1] == 0xbb) && (buf[2] == 0xbf)) {
205310234Syasuko.eckert@amd.com                headerSz = 3;
205410234Syasuko.eckert@amd.com                ce = XMLNode::char_encoding_UTF8;
205510234Syasuko.eckert@amd.com            }
205610234Syasuko.eckert@amd.com            XMLSTR b2 = myMultiByteToWideChar((const char*)(buf + headerSz), ce);
205710234Syasuko.eckert@amd.com            free(buf);
205810234Syasuko.eckert@amd.com            buf = (unsigned char*)b2;
205910234Syasuko.eckert@amd.com            headerSz = 0;
206010234Syasuko.eckert@amd.com        } else {
206110234Syasuko.eckert@amd.com            if ((buf[0] == 0xef) && (buf[1] == 0xff)) headerSz = 2;
206210234Syasuko.eckert@amd.com            if ((buf[0] == 0xff) && (buf[1] == 0xfe)) headerSz = 2;
206310152Satgutier@umich.edu        }
206410152Satgutier@umich.edu    }
206510152Satgutier@umich.edu#else
206610234Syasuko.eckert@amd.com    if (guessWideCharChars) {
206710234Syasuko.eckert@amd.com        if (myIsTextWideChar(buf, l)) {
206810234Syasuko.eckert@amd.com            if ((buf[0] == 0xef) && (buf[1] == 0xff)) headerSz = 2;
206910234Syasuko.eckert@amd.com            if ((buf[0] == 0xff) && (buf[1] == 0xfe)) headerSz = 2;
207010234Syasuko.eckert@amd.com            char *b2 = myWideCharToMultiByte((const wchar_t*)(buf + headerSz));
207110234Syasuko.eckert@amd.com            free(buf);
207210234Syasuko.eckert@amd.com            buf = (unsigned char*)b2;
207310234Syasuko.eckert@amd.com            headerSz = 0;
207410234Syasuko.eckert@amd.com        } else {
207510234Syasuko.eckert@amd.com            if ((buf[0] == 0xef) && (buf[1] == 0xbb) && (buf[2] == 0xbf)) {
207610234Syasuko.eckert@amd.com                headerSz = 3;
207710234Syasuko.eckert@amd.com            }
207810152Satgutier@umich.edu        }
207910152Satgutier@umich.edu    }
208010152Satgutier@umich.edu#endif
208110152Satgutier@umich.edu
208210234Syasuko.eckert@amd.com    if (!buf) {
208310234Syasuko.eckert@amd.com        if (pResults) pResults->error = eXMLErrorCharConversionError;
208410234Syasuko.eckert@amd.com        return emptyXMLNode;
208510234Syasuko.eckert@amd.com    }
208610234Syasuko.eckert@amd.com    XMLNode x = parseString((XMLSTR)(buf + headerSz), tag, pResults);
208710152Satgutier@umich.edu    free(buf);
208810152Satgutier@umich.edu    return x;
208910152Satgutier@umich.edu}
209010152Satgutier@umich.edu
209110234Syasuko.eckert@amd.comstatic inline void charmemset(XMLSTR dest, XMLCHAR c, int l) {
209210234Syasuko.eckert@amd.com    while (l--) *(dest++) = c;
209310234Syasuko.eckert@amd.com}
209410152Satgutier@umich.edu// private:
209510152Satgutier@umich.edu// Creates an user friendly XML string from a given element with
209610152Satgutier@umich.edu// appropriate white space and carriage returns.
209710152Satgutier@umich.edu//
209810152Satgutier@umich.edu// This recurses through all subnodes then adds contents of the nodes to the
209910152Satgutier@umich.edu// string.
210010234Syasuko.eckert@amd.comint XMLNode::CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker,
210110234Syasuko.eckert@amd.com                              int nFormat) {
210210152Satgutier@umich.edu    int nResult = 0;
210310234Syasuko.eckert@amd.com    int cb = nFormat < 0 ? 0 : nFormat;
210410152Satgutier@umich.edu    int cbElement;
210510234Syasuko.eckert@amd.com    int nChildFormat = -1;
210610234Syasuko.eckert@amd.com    int nElementI = pEntry->nChild + pEntry->nText + pEntry->nClear;
210710234Syasuko.eckert@amd.com    int i, j;
210810234Syasuko.eckert@amd.com    if ((nFormat >= 0) && (nElementI == 1) && (pEntry->nText == 1) &&
210910234Syasuko.eckert@amd.com        (!pEntry->isDeclaration)) {
211010234Syasuko.eckert@amd.com        nFormat = -2;
211110234Syasuko.eckert@amd.com    }
211210152Satgutier@umich.edu
211310152Satgutier@umich.edu    assert(pEntry);
211410152Satgutier@umich.edu
211510152Satgutier@umich.edu#define LENSTR(lpsz) (lpsz ? xstrlen(lpsz) : 0)
211610152Satgutier@umich.edu
211710152Satgutier@umich.edu    // If the element has no name then assume this is the head node.
211810152Satgutier@umich.edu    cbElement = (int)LENSTR(pEntry->lpszName);
211910152Satgutier@umich.edu
212010234Syasuko.eckert@amd.com    if (cbElement) {
212110152Satgutier@umich.edu        // "<elementname "
212210234Syasuko.eckert@amd.com        if (lpszMarker) {
212310152Satgutier@umich.edu            if (cb) charmemset(lpszMarker, INDENTCHAR, cb);
212410152Satgutier@umich.edu            nResult = cb;
212510234Syasuko.eckert@amd.com            lpszMarker[nResult++] = _CXML('<');
212610234Syasuko.eckert@amd.com            if (pEntry->isDeclaration) lpszMarker[nResult++] = _CXML('?');
212710152Satgutier@umich.edu            xstrcpy(&lpszMarker[nResult], pEntry->lpszName);
212810234Syasuko.eckert@amd.com            nResult += cbElement;
212910234Syasuko.eckert@amd.com            lpszMarker[nResult++] = _CXML(' ');
213010152Satgutier@umich.edu
213110234Syasuko.eckert@amd.com        } else {
213210234Syasuko.eckert@amd.com            nResult += cbElement + 2 + cb;
213310152Satgutier@umich.edu            if (pEntry->isDeclaration) nResult++;
213410152Satgutier@umich.edu        }
213510152Satgutier@umich.edu
213610152Satgutier@umich.edu        // Enumerate attributes and add them to the string
213710234Syasuko.eckert@amd.com        XMLAttribute *pAttr = pEntry->pAttribute;
213810234Syasuko.eckert@amd.com        for (i = 0; i < pEntry->nAttribute; i++) {
213910152Satgutier@umich.edu            // "Attrib
214010152Satgutier@umich.edu            cb = (int)LENSTR(pAttr->lpszName);
214110234Syasuko.eckert@amd.com            if (cb) {
214210152Satgutier@umich.edu                if (lpszMarker) xstrcpy(&lpszMarker[nResult], pAttr->lpszName);
214310152Satgutier@umich.edu                nResult += cb;
214410152Satgutier@umich.edu                // "Attrib=Value "
214510234Syasuko.eckert@amd.com                if (pAttr->lpszValue) {
214610234Syasuko.eckert@amd.com                    cb = (int)ToXMLStringTool::lengthXMLString(pAttr->lpszValue);
214710234Syasuko.eckert@amd.com                    if (lpszMarker) {
214810234Syasuko.eckert@amd.com                        lpszMarker[nResult] = _CXML('=');
214910234Syasuko.eckert@amd.com                        lpszMarker[nResult+1] = _CXML('"');
215010234Syasuko.eckert@amd.com                        if (cb) {
215110234Syasuko.eckert@amd.com                            ToXMLStringTool::toXMLUnSafe(&lpszMarker[nResult+2],
215210234Syasuko.eckert@amd.com                                                         pAttr->lpszValue);
215310234Syasuko.eckert@amd.com                        }
215410234Syasuko.eckert@amd.com                        lpszMarker[nResult+cb+2] = _CXML('"');
215510152Satgutier@umich.edu                    }
215610234Syasuko.eckert@amd.com                    nResult += cb + 3;
215710152Satgutier@umich.edu                }
215810152Satgutier@umich.edu                if (lpszMarker) lpszMarker[nResult] = _CXML(' ');
215910152Satgutier@umich.edu                nResult++;
216010152Satgutier@umich.edu            }
216110152Satgutier@umich.edu            pAttr++;
216210152Satgutier@umich.edu        }
216310152Satgutier@umich.edu
216410234Syasuko.eckert@amd.com        if (pEntry->isDeclaration) {
216510234Syasuko.eckert@amd.com            if (lpszMarker) {
216610234Syasuko.eckert@amd.com                lpszMarker[nResult-1] = _CXML('?');
216710234Syasuko.eckert@amd.com                lpszMarker[nResult] = _CXML('>');
216810152Satgutier@umich.edu            }
216910152Satgutier@umich.edu            nResult++;
217010234Syasuko.eckert@amd.com            if (nFormat != -1) {
217110234Syasuko.eckert@amd.com                if (lpszMarker) lpszMarker[nResult] = _CXML('\n');
217210152Satgutier@umich.edu                nResult++;
217310152Satgutier@umich.edu            }
217410152Satgutier@umich.edu        } else
217510152Satgutier@umich.edu            // If there are child nodes we need to terminate the start tag
217610234Syasuko.eckert@amd.com            if (nElementI) {
217710234Syasuko.eckert@amd.com                if (lpszMarker) lpszMarker[nResult-1] = _CXML('>');
217810234Syasuko.eckert@amd.com                if (nFormat >= 0) {
217910234Syasuko.eckert@amd.com                    if (lpszMarker) lpszMarker[nResult] = _CXML('\n');
218010152Satgutier@umich.edu                    nResult++;
218110152Satgutier@umich.edu                }
218210152Satgutier@umich.edu            } else nResult--;
218310152Satgutier@umich.edu    }
218410152Satgutier@umich.edu
218510152Satgutier@umich.edu    // Calculate the child format for when we recurse.  This is used to
218610152Satgutier@umich.edu    // determine the number of spaces used for prefixes.
218710234Syasuko.eckert@amd.com    if (nFormat != -1) {
218810234Syasuko.eckert@amd.com        if (cbElement && (!pEntry->isDeclaration)) nChildFormat = nFormat + 1;
218910234Syasuko.eckert@amd.com        else nChildFormat = nFormat;
219010152Satgutier@umich.edu    }
219110152Satgutier@umich.edu
219210152Satgutier@umich.edu    // Enumerate through remaining children
219310234Syasuko.eckert@amd.com    for (i = 0; i < nElementI; i++) {
219410234Syasuko.eckert@amd.com        j = pEntry->pOrder[i];
219510234Syasuko.eckert@amd.com        switch ((XMLElementType)(j&3)) {
219610234Syasuko.eckert@amd.com            // Text nodes
219710234Syasuko.eckert@amd.com        case eNodeText: {
219810234Syasuko.eckert@amd.com            // "Text"
219910234Syasuko.eckert@amd.com            XMLCSTR pChild = pEntry->pText[j>>2];
220010234Syasuko.eckert@amd.com            cb = (int)ToXMLStringTool::lengthXMLString(pChild);
220110234Syasuko.eckert@amd.com            if (cb) {
220210234Syasuko.eckert@amd.com                if (nFormat >= 0) {
220310234Syasuko.eckert@amd.com                    if (lpszMarker) {
220410234Syasuko.eckert@amd.com                        charmemset(&lpszMarker[nResult], INDENTCHAR,
220510234Syasuko.eckert@amd.com                                   nFormat + 1);
220610234Syasuko.eckert@amd.com                        ToXMLStringTool::toXMLUnSafe(
220710234Syasuko.eckert@amd.com                            &lpszMarker[nResult+nFormat+1], pChild);
220810234Syasuko.eckert@amd.com                        lpszMarker[nResult+nFormat+1+cb] = _CXML('\n');
220910152Satgutier@umich.edu                    }
221010234Syasuko.eckert@amd.com                    nResult += cb + nFormat + 2;
221110234Syasuko.eckert@amd.com                } else {
221210234Syasuko.eckert@amd.com                    if (lpszMarker) {
221310234Syasuko.eckert@amd.com                        ToXMLStringTool::toXMLUnSafe(&lpszMarker[nResult],
221410234Syasuko.eckert@amd.com                                                     pChild);
221510234Syasuko.eckert@amd.com                    }
221610234Syasuko.eckert@amd.com                    nResult += cb;
221710152Satgutier@umich.edu                }
221810234Syasuko.eckert@amd.com            }
221910234Syasuko.eckert@amd.com            break;
222010234Syasuko.eckert@amd.com        }
222110234Syasuko.eckert@amd.com
222210234Syasuko.eckert@amd.com        // Clear type nodes
222310234Syasuko.eckert@amd.com        case eNodeClear: {
222410234Syasuko.eckert@amd.com            XMLClear *pChild = pEntry->pClear + (j >> 2);
222510234Syasuko.eckert@amd.com            // "OpenTag"
222610234Syasuko.eckert@amd.com            cb = (int)LENSTR(pChild->lpszOpenTag);
222710234Syasuko.eckert@amd.com            if (cb) {
222810234Syasuko.eckert@amd.com                if (nFormat != -1) {
222910234Syasuko.eckert@amd.com                    if (lpszMarker) {
223010234Syasuko.eckert@amd.com                        charmemset(&lpszMarker[nResult], INDENTCHAR,
223110234Syasuko.eckert@amd.com                                   nFormat + 1);
223210234Syasuko.eckert@amd.com                        xstrcpy(&lpszMarker[nResult+nFormat+1],
223310234Syasuko.eckert@amd.com                                pChild->lpszOpenTag);
223410234Syasuko.eckert@amd.com                    }
223510234Syasuko.eckert@amd.com                    nResult += cb + nFormat + 1;
223610234Syasuko.eckert@amd.com                } else {
223710234Syasuko.eckert@amd.com                    if (lpszMarker) {
223810234Syasuko.eckert@amd.com                        xstrcpy(&lpszMarker[nResult], pChild->lpszOpenTag);
223910234Syasuko.eckert@amd.com                    }
224010234Syasuko.eckert@amd.com                    nResult += cb;
224110234Syasuko.eckert@amd.com                }
224210152Satgutier@umich.edu            }
224310152Satgutier@umich.edu
224410234Syasuko.eckert@amd.com            // "OpenTag Value"
224510234Syasuko.eckert@amd.com            cb = (int)LENSTR(pChild->lpszValue);
224610234Syasuko.eckert@amd.com            if (cb) {
224710234Syasuko.eckert@amd.com                if (lpszMarker) {
224810234Syasuko.eckert@amd.com                    xstrcpy(&lpszMarker[nResult], pChild->lpszValue);
224910152Satgutier@umich.edu                }
225010234Syasuko.eckert@amd.com                nResult += cb;
225110152Satgutier@umich.edu            }
225210152Satgutier@umich.edu
225310234Syasuko.eckert@amd.com            // "OpenTag Value CloseTag"
225410234Syasuko.eckert@amd.com            cb = (int)LENSTR(pChild->lpszCloseTag);
225510234Syasuko.eckert@amd.com            if (cb) {
225610234Syasuko.eckert@amd.com                if (lpszMarker) {
225710234Syasuko.eckert@amd.com                    xstrcpy(&lpszMarker[nResult], pChild->lpszCloseTag);
225810234Syasuko.eckert@amd.com                }
225910234Syasuko.eckert@amd.com                nResult += cb;
226010234Syasuko.eckert@amd.com            }
226110234Syasuko.eckert@amd.com
226210234Syasuko.eckert@amd.com            if (nFormat != -1) {
226310234Syasuko.eckert@amd.com                if (lpszMarker) lpszMarker[nResult] = _CXML('\n');
226410234Syasuko.eckert@amd.com                nResult++;
226510234Syasuko.eckert@amd.com            }
226610234Syasuko.eckert@amd.com            break;
226710234Syasuko.eckert@amd.com        }
226810234Syasuko.eckert@amd.com
226910152Satgutier@umich.edu        // Element nodes
227010234Syasuko.eckert@amd.com        case eNodeChild: {
227110234Syasuko.eckert@amd.com            // Recursively add child nodes
227210234Syasuko.eckert@amd.com            nResult += CreateXMLStringR(pEntry->pChild[j>>2].d,
227310234Syasuko.eckert@amd.com                                        lpszMarker ? lpszMarker + nResult : 0,
227410234Syasuko.eckert@amd.com                                        nChildFormat);
227510234Syasuko.eckert@amd.com            break;
227610234Syasuko.eckert@amd.com        }
227710234Syasuko.eckert@amd.com        default:
227810234Syasuko.eckert@amd.com            break;
227910152Satgutier@umich.edu        }
228010152Satgutier@umich.edu    }
228110152Satgutier@umich.edu
228210234Syasuko.eckert@amd.com    if ((cbElement) && (!pEntry->isDeclaration)) {
228310152Satgutier@umich.edu        // If we have child entries we need to use long XML notation for
228410152Satgutier@umich.edu        // closing the element - "<elementname>blah blah blah</elementname>"
228510234Syasuko.eckert@amd.com        if (nElementI) {
228610152Satgutier@umich.edu            // "</elementname>\0"
228710234Syasuko.eckert@amd.com            if (lpszMarker) {
228810234Syasuko.eckert@amd.com                if (nFormat >= 0) {
228910234Syasuko.eckert@amd.com                    charmemset(&lpszMarker[nResult], INDENTCHAR, nFormat);
229010234Syasuko.eckert@amd.com                    nResult += nFormat;
229110152Satgutier@umich.edu                }
229210152Satgutier@umich.edu
229310234Syasuko.eckert@amd.com                lpszMarker[nResult] = _CXML('<');
229410234Syasuko.eckert@amd.com                lpszMarker[nResult+1] = _CXML('/');
229510152Satgutier@umich.edu                nResult += 2;
229610152Satgutier@umich.edu                xstrcpy(&lpszMarker[nResult], pEntry->lpszName);
229710152Satgutier@umich.edu                nResult += cbElement;
229810152Satgutier@umich.edu
229910234Syasuko.eckert@amd.com                lpszMarker[nResult] = _CXML('>');
230010152Satgutier@umich.edu                if (nFormat == -1) nResult++;
230110234Syasuko.eckert@amd.com                else {
230210234Syasuko.eckert@amd.com                    lpszMarker[nResult+1] = _CXML('\n');
230310234Syasuko.eckert@amd.com                    nResult += 2;
230410152Satgutier@umich.edu                }
230510234Syasuko.eckert@amd.com            } else {
230610234Syasuko.eckert@amd.com                if (nFormat >= 0) nResult += cbElement + 4 + nFormat;
230710234Syasuko.eckert@amd.com                else if (nFormat == -1) nResult += cbElement + 3;
230810234Syasuko.eckert@amd.com                else nResult += cbElement + 4;
230910152Satgutier@umich.edu            }
231010234Syasuko.eckert@amd.com        } else {
231110152Satgutier@umich.edu            // If there are no children we can use shorthand XML notation -
231210152Satgutier@umich.edu            // "<elementname/>"
231310152Satgutier@umich.edu            // "/>\0"
231410234Syasuko.eckert@amd.com            if (lpszMarker) {
231510234Syasuko.eckert@amd.com                lpszMarker[nResult] = _CXML('/');
231610234Syasuko.eckert@amd.com                lpszMarker[nResult+1] = _CXML('>');
231710234Syasuko.eckert@amd.com                if (nFormat != -1) lpszMarker[nResult+2] = _CXML('\n');
231810152Satgutier@umich.edu            }
231910152Satgutier@umich.edu            nResult += nFormat == -1 ? 2 : 3;
232010152Satgutier@umich.edu        }
232110152Satgutier@umich.edu    }
232210152Satgutier@umich.edu
232310152Satgutier@umich.edu    return nResult;
232410152Satgutier@umich.edu}
232510152Satgutier@umich.edu
232610152Satgutier@umich.edu#undef LENSTR
232710152Satgutier@umich.edu
232810152Satgutier@umich.edu// Create an XML string
232910152Satgutier@umich.edu// @param       int nFormat             - 0 if no formatting is required
233010152Satgutier@umich.edu//                                        otherwise nonzero for formatted text
233110152Satgutier@umich.edu//                                        with carriage returns and indentation.
233210152Satgutier@umich.edu// @param       int *pnSize             - [out] pointer to the size of the
233310152Satgutier@umich.edu//                                        returned string not including the
233410152Satgutier@umich.edu//                                        NULL terminator.
233510152Satgutier@umich.edu// @return      XMLSTR                  - Allocated XML string, you must free
233610152Satgutier@umich.edu//                                        this with free().
233710234Syasuko.eckert@amd.comXMLSTR XMLNode::createXMLString(int nFormat, int *pnSize) const {
233810234Syasuko.eckert@amd.com    if (!d) {
233910234Syasuko.eckert@amd.com        if (pnSize) *pnSize = 0;
234010234Syasuko.eckert@amd.com        return NULL;
234110234Syasuko.eckert@amd.com    }
234210152Satgutier@umich.edu
234310152Satgutier@umich.edu    XMLSTR lpszResult = NULL;
234410152Satgutier@umich.edu    int cbStr;
234510152Satgutier@umich.edu
234610152Satgutier@umich.edu    // Recursively Calculate the size of the XML string
234710234Syasuko.eckert@amd.com    if (!dropWhiteSpace) nFormat = 0;
234810152Satgutier@umich.edu    nFormat = nFormat ? 0 : -1;
234910152Satgutier@umich.edu    cbStr = CreateXMLStringR(d, 0, nFormat);
235010152Satgutier@umich.edu    // Alllocate memory for the XML string + the NULL terminator and
235110152Satgutier@umich.edu    // create the recursively XML string.
235210234Syasuko.eckert@amd.com    lpszResult = (XMLSTR)malloc((cbStr + 1) * sizeof(XMLCHAR));
235310152Satgutier@umich.edu    CreateXMLStringR(d, lpszResult, nFormat);
235410234Syasuko.eckert@amd.com    lpszResult[cbStr] = _CXML('\0');
235510152Satgutier@umich.edu    if (pnSize) *pnSize = cbStr;
235610152Satgutier@umich.edu    return lpszResult;
235710152Satgutier@umich.edu}
235810152Satgutier@umich.edu
235910234Syasuko.eckert@amd.comint XMLNode::detachFromParent(XMLNodeData *d) {
236010234Syasuko.eckert@amd.com    XMLNode *pa = d->pParent->pChild;
236110234Syasuko.eckert@amd.com    int i = 0;
236210234Syasuko.eckert@amd.com    while (((void*)(pa[i].d)) != ((void*)d)) i++;
236310152Satgutier@umich.edu    d->pParent->nChild--;
236410234Syasuko.eckert@amd.com    if (d->pParent->nChild) {
236510234Syasuko.eckert@amd.com        memmove(pa + i, pa + i + 1, (d->pParent->nChild - i)*sizeof(XMLNode));
236610234Syasuko.eckert@amd.com    } else {
236710234Syasuko.eckert@amd.com        free(pa);
236810234Syasuko.eckert@amd.com        d->pParent->pChild = NULL;
236910234Syasuko.eckert@amd.com    }
237010234Syasuko.eckert@amd.com    return removeOrderElement(d->pParent, eNodeChild, i);
237110152Satgutier@umich.edu}
237210152Satgutier@umich.edu
237310234Syasuko.eckert@amd.comXMLNode::~XMLNode() {
237410152Satgutier@umich.edu    if (!d) return;
237510152Satgutier@umich.edu    d->ref_count--;
237610152Satgutier@umich.edu    emptyTheNode(0);
237710152Satgutier@umich.edu}
237810234Syasuko.eckert@amd.comvoid XMLNode::deleteNodeContent() {
237910152Satgutier@umich.edu    if (!d) return;
238010234Syasuko.eckert@amd.com    if (d->pParent) {
238110234Syasuko.eckert@amd.com        detachFromParent(d);
238210234Syasuko.eckert@amd.com        d->pParent = NULL;
238310234Syasuko.eckert@amd.com        d->ref_count--;
238410234Syasuko.eckert@amd.com    }
238510152Satgutier@umich.edu    emptyTheNode(1);
238610152Satgutier@umich.edu}
238710234Syasuko.eckert@amd.comvoid XMLNode::emptyTheNode(char force) {
238810234Syasuko.eckert@amd.com    XMLNodeData *dd = d; // warning: must stay this way!
238910234Syasuko.eckert@amd.com    if ((dd->ref_count == 0) || force) {
239010152Satgutier@umich.edu        if (d->pParent) detachFromParent(d);
239110152Satgutier@umich.edu        int i;
239210152Satgutier@umich.edu        XMLNode *pc;
239310234Syasuko.eckert@amd.com        for (i = 0; i < dd->nChild; i++) {
239410234Syasuko.eckert@amd.com            pc = dd->pChild + i;
239510234Syasuko.eckert@amd.com            pc->d->pParent = NULL;
239610152Satgutier@umich.edu            pc->d->ref_count--;
239710152Satgutier@umich.edu            pc->emptyTheNode(force);
239810152Satgutier@umich.edu        }
239910152Satgutier@umich.edu        myFree(dd->pChild);
240010234Syasuko.eckert@amd.com        for (i = 0; i < dd->nText; i++) free((void*)dd->pText[i]);
240110152Satgutier@umich.edu        myFree(dd->pText);
240210234Syasuko.eckert@amd.com        for (i = 0; i < dd->nClear; i++) free((void*)dd->pClear[i].lpszValue);
240310152Satgutier@umich.edu        myFree(dd->pClear);
240410234Syasuko.eckert@amd.com        for (i = 0; i < dd->nAttribute; i++) {
240510152Satgutier@umich.edu            free((void*)dd->pAttribute[i].lpszName);
240610234Syasuko.eckert@amd.com            if (dd->pAttribute[i].lpszValue) {
240710234Syasuko.eckert@amd.com                free((void*)dd->pAttribute[i].lpszValue);
240810234Syasuko.eckert@amd.com            }
240910152Satgutier@umich.edu        }
241010152Satgutier@umich.edu        myFree(dd->pAttribute);
241110152Satgutier@umich.edu        myFree(dd->pOrder);
241210152Satgutier@umich.edu        myFree((void*)dd->lpszName);
241310234Syasuko.eckert@amd.com        dd->nChild = 0;
241410234Syasuko.eckert@amd.com        dd->nText = 0;
241510234Syasuko.eckert@amd.com        dd->nClear = 0;
241610234Syasuko.eckert@amd.com        dd->nAttribute = 0;
241710234Syasuko.eckert@amd.com        dd->pChild = NULL;
241810234Syasuko.eckert@amd.com        dd->pText = NULL;
241910234Syasuko.eckert@amd.com        dd->pClear = NULL;
242010234Syasuko.eckert@amd.com        dd->pAttribute = NULL;
242110234Syasuko.eckert@amd.com        dd->pOrder = NULL;
242210234Syasuko.eckert@amd.com        dd->lpszName = NULL;
242310234Syasuko.eckert@amd.com        dd->pParent = NULL;
242410152Satgutier@umich.edu    }
242510234Syasuko.eckert@amd.com    if (dd->ref_count == 0) {
242610152Satgutier@umich.edu        free(dd);
242710234Syasuko.eckert@amd.com        d = NULL;
242810152Satgutier@umich.edu    }
242910152Satgutier@umich.edu}
243010152Satgutier@umich.edu
243110234Syasuko.eckert@amd.comXMLNode& XMLNode::operator=( const XMLNode & A ) {
243210152Satgutier@umich.edu    // shallow copy
243310234Syasuko.eckert@amd.com    if (this != &A) {
243410234Syasuko.eckert@amd.com        if (d) {
243510234Syasuko.eckert@amd.com            d->ref_count--;
243610234Syasuko.eckert@amd.com            emptyTheNode(0);
243710234Syasuko.eckert@amd.com        }
243810234Syasuko.eckert@amd.com        d = A.d;
243910152Satgutier@umich.edu        if (d) (d->ref_count) ++ ;
244010152Satgutier@umich.edu    }
244110152Satgutier@umich.edu    return *this;
244210152Satgutier@umich.edu}
244310152Satgutier@umich.edu
244410234Syasuko.eckert@amd.comXMLNode::XMLNode(const XMLNode &A) {
244510152Satgutier@umich.edu    // shallow copy
244610234Syasuko.eckert@amd.com    d = A.d;
244710152Satgutier@umich.edu    if (d) (d->ref_count)++ ;
244810152Satgutier@umich.edu}
244910152Satgutier@umich.edu
245010234Syasuko.eckert@amd.comXMLNode XMLNode::deepCopy() const {
245110152Satgutier@umich.edu    if (!d) return XMLNode::emptyXMLNode;
245210234Syasuko.eckert@amd.com    XMLNode x(NULL, stringDup(d->lpszName), d->isDeclaration);
245310234Syasuko.eckert@amd.com    XMLNodeData *p = x.d;
245410234Syasuko.eckert@amd.com    int n = d->nAttribute;
245510234Syasuko.eckert@amd.com    if (n) {
245610234Syasuko.eckert@amd.com        p->nAttribute = n;
245710234Syasuko.eckert@amd.com        p->pAttribute = (XMLAttribute*)malloc(n * sizeof(XMLAttribute));
245810234Syasuko.eckert@amd.com        while (n--) {
245910234Syasuko.eckert@amd.com            p->pAttribute[n].lpszName = stringDup(d->pAttribute[n].lpszName);
246010234Syasuko.eckert@amd.com            p->pAttribute[n].lpszValue = stringDup(d->pAttribute[n].lpszValue);
246110152Satgutier@umich.edu        }
246210152Satgutier@umich.edu    }
246310234Syasuko.eckert@amd.com    if (d->pOrder) {
246410234Syasuko.eckert@amd.com        n = (d->nChild + d->nText + d->nClear) * sizeof(int);
246510234Syasuko.eckert@amd.com        p->pOrder = (int*)malloc(n);
246610234Syasuko.eckert@amd.com        memcpy(p->pOrder, d->pOrder, n);
246710152Satgutier@umich.edu    }
246810234Syasuko.eckert@amd.com    n = d->nText;
246910234Syasuko.eckert@amd.com    if (n) {
247010234Syasuko.eckert@amd.com        p->nText = n;
247110234Syasuko.eckert@amd.com        p->pText = (XMLCSTR*)malloc(n * sizeof(XMLCSTR));
247210234Syasuko.eckert@amd.com        while (n--) p->pText[n] = stringDup(d->pText[n]);
247310152Satgutier@umich.edu    }
247410234Syasuko.eckert@amd.com    n = d->nClear;
247510234Syasuko.eckert@amd.com    if (n) {
247610234Syasuko.eckert@amd.com        p->nClear = n;
247710234Syasuko.eckert@amd.com        p->pClear = (XMLClear*)malloc(n * sizeof(XMLClear));
247810234Syasuko.eckert@amd.com        while (n--) {
247910234Syasuko.eckert@amd.com            p->pClear[n].lpszCloseTag = d->pClear[n].lpszCloseTag;
248010234Syasuko.eckert@amd.com            p->pClear[n].lpszOpenTag = d->pClear[n].lpszOpenTag;
248110234Syasuko.eckert@amd.com            p->pClear[n].lpszValue = stringDup(d->pClear[n].lpszValue);
248210152Satgutier@umich.edu        }
248310152Satgutier@umich.edu    }
248410234Syasuko.eckert@amd.com    n = d->nChild;
248510234Syasuko.eckert@amd.com    if (n) {
248610234Syasuko.eckert@amd.com        p->nChild = n;
248710234Syasuko.eckert@amd.com        p->pChild = (XMLNode*)malloc(n * sizeof(XMLNode));
248810234Syasuko.eckert@amd.com        while (n--) {
248910234Syasuko.eckert@amd.com            p->pChild[n].d = NULL;
249010234Syasuko.eckert@amd.com            p->pChild[n] = d->pChild[n].deepCopy();
249110234Syasuko.eckert@amd.com            p->pChild[n].d->pParent = p;
249210152Satgutier@umich.edu        }
249310152Satgutier@umich.edu    }
249410152Satgutier@umich.edu    return x;
249510152Satgutier@umich.edu}
249610152Satgutier@umich.edu
249710234Syasuko.eckert@amd.comXMLNode XMLNode::addChild(XMLNode childNode, int pos) {
249810234Syasuko.eckert@amd.com    XMLNodeData *dc = childNode.d;
249910234Syasuko.eckert@amd.com    if ((!dc) || (!d)) return childNode;
250010234Syasuko.eckert@amd.com    if (!dc->lpszName) {
250110152Satgutier@umich.edu        // this is a root node: todo: correct fix
250210234Syasuko.eckert@amd.com        int j = pos;
250310234Syasuko.eckert@amd.com        while (dc->nChild) {
250410234Syasuko.eckert@amd.com            addChild(dc->pChild[0], j);
250510234Syasuko.eckert@amd.com            if (pos >= 0) j++;
250610152Satgutier@umich.edu        }
250710152Satgutier@umich.edu        return childNode;
250810152Satgutier@umich.edu    }
250910234Syasuko.eckert@amd.com    if (dc->pParent) {
251010234Syasuko.eckert@amd.com        if ((detachFromParent(dc) <= pos) && (dc->pParent == d)) pos--;
251110234Syasuko.eckert@amd.com    } else dc->ref_count++;
251210234Syasuko.eckert@amd.com    dc->pParent = d;
251310152Satgutier@umich.edu//     int nc=d->nChild;
251410152Satgutier@umich.edu//     d->pChild=(XMLNode*)myRealloc(d->pChild,(nc+1),memoryIncrease,sizeof(XMLNode));
251510234Syasuko.eckert@amd.com    d->pChild = (XMLNode*)addToOrder(0, &pos, d->nChild, d->pChild,
251610234Syasuko.eckert@amd.com                                     sizeof(XMLNode), eNodeChild);
251710234Syasuko.eckert@amd.com    d->pChild[pos].d = dc;
251810152Satgutier@umich.edu    d->nChild++;
251910152Satgutier@umich.edu    return childNode;
252010152Satgutier@umich.edu}
252110152Satgutier@umich.edu
252210234Syasuko.eckert@amd.comvoid XMLNode::deleteAttribute(int i) {
252310234Syasuko.eckert@amd.com    if ((!d) || (i < 0) || (i >= d->nAttribute)) return;
252410152Satgutier@umich.edu    d->nAttribute--;
252510234Syasuko.eckert@amd.com    XMLAttribute *p = d->pAttribute + i;
252610152Satgutier@umich.edu    free((void*)p->lpszName);
252710152Satgutier@umich.edu    if (p->lpszValue) free((void*)p->lpszValue);
252810234Syasuko.eckert@amd.com    if (d->nAttribute) {
252910234Syasuko.eckert@amd.com        memmove(p, p + 1, (d->nAttribute - i)*sizeof(XMLAttribute));
253010234Syasuko.eckert@amd.com    }
253110234Syasuko.eckert@amd.com    else {
253210234Syasuko.eckert@amd.com        free(p);
253310234Syasuko.eckert@amd.com        d->pAttribute = NULL;
253410234Syasuko.eckert@amd.com    }
253510152Satgutier@umich.edu}
253610152Satgutier@umich.edu
253710234Syasuko.eckert@amd.comvoid XMLNode::deleteAttribute(XMLAttribute *a) {
253810234Syasuko.eckert@amd.com    if (a) deleteAttribute(a->lpszName);
253910234Syasuko.eckert@amd.com}
254010234Syasuko.eckert@amd.comvoid XMLNode::deleteAttribute(XMLCSTR lpszName) {
254110234Syasuko.eckert@amd.com    int j = 0;
254210234Syasuko.eckert@amd.com    getAttribute(lpszName, &j);
254310234Syasuko.eckert@amd.com    if (j) deleteAttribute(j - 1);
254410152Satgutier@umich.edu}
254510152Satgutier@umich.edu
254610234Syasuko.eckert@amd.comXMLAttribute *XMLNode::updateAttribute_WOSD(XMLSTR lpszNewValue,
254710234Syasuko.eckert@amd.com                                            XMLSTR lpszNewName, int i) {
254810234Syasuko.eckert@amd.com    if (!d) {
254910234Syasuko.eckert@amd.com        if (lpszNewValue) free(lpszNewValue);
255010234Syasuko.eckert@amd.com        if (lpszNewName) free(lpszNewName);
255110152Satgutier@umich.edu        return NULL;
255210152Satgutier@umich.edu    }
255310234Syasuko.eckert@amd.com    if (i >= d->nAttribute) {
255410234Syasuko.eckert@amd.com        if (lpszNewName) return addAttribute_WOSD(lpszNewName, lpszNewValue);
255510234Syasuko.eckert@amd.com        return NULL;
255610234Syasuko.eckert@amd.com    }
255710234Syasuko.eckert@amd.com    XMLAttribute *p = d->pAttribute + i;
255810234Syasuko.eckert@amd.com    if (p->lpszValue && p->lpszValue != lpszNewValue) {
255910234Syasuko.eckert@amd.com        free((void*)p->lpszValue);
256010234Syasuko.eckert@amd.com    }
256110234Syasuko.eckert@amd.com    p->lpszValue = lpszNewValue;
256210234Syasuko.eckert@amd.com    if (lpszNewName && p->lpszName != lpszNewName) {
256310234Syasuko.eckert@amd.com        free((void*)p->lpszName);
256410234Syasuko.eckert@amd.com        p->lpszName = lpszNewName;
256510234Syasuko.eckert@amd.com    };
256610152Satgutier@umich.edu    return p;
256710152Satgutier@umich.edu}
256810152Satgutier@umich.edu
256910234Syasuko.eckert@amd.comXMLAttribute *XMLNode::updateAttribute_WOSD(XMLAttribute *newAttribute,
257010234Syasuko.eckert@amd.com                                            XMLAttribute *oldAttribute) {
257110234Syasuko.eckert@amd.com    if (oldAttribute) {
257210234Syasuko.eckert@amd.com        return updateAttribute_WOSD((XMLSTR)newAttribute->lpszValue,
257310234Syasuko.eckert@amd.com                                    (XMLSTR)newAttribute->lpszName,
257410234Syasuko.eckert@amd.com                                    oldAttribute->lpszName);
257510234Syasuko.eckert@amd.com    }
257610234Syasuko.eckert@amd.com    return addAttribute_WOSD((XMLSTR)newAttribute->lpszName,
257710234Syasuko.eckert@amd.com                             (XMLSTR)newAttribute->lpszValue);
257810152Satgutier@umich.edu}
257910152Satgutier@umich.edu
258010234Syasuko.eckert@amd.comXMLAttribute *XMLNode::updateAttribute_WOSD(XMLSTR lpszNewValue,
258110234Syasuko.eckert@amd.com                                            XMLSTR lpszNewName,
258210234Syasuko.eckert@amd.com                                            XMLCSTR lpszOldName) {
258310234Syasuko.eckert@amd.com    int j = 0;
258410234Syasuko.eckert@amd.com    getAttribute(lpszOldName, &j);
258510234Syasuko.eckert@amd.com    if (j) return updateAttribute_WOSD(lpszNewValue, lpszNewName, j - 1);
258610234Syasuko.eckert@amd.com    else {
258710234Syasuko.eckert@amd.com        if (lpszNewName) {
258810234Syasuko.eckert@amd.com            return addAttribute_WOSD(lpszNewName, lpszNewValue);
258910234Syasuko.eckert@amd.com        } else {
259010234Syasuko.eckert@amd.com            return addAttribute_WOSD(stringDup(lpszOldName), lpszNewValue);
259110234Syasuko.eckert@amd.com        }
259210152Satgutier@umich.edu    }
259310152Satgutier@umich.edu}
259410152Satgutier@umich.edu
259510234Syasuko.eckert@amd.comint XMLNode::indexText(XMLCSTR lpszValue) const {
259610152Satgutier@umich.edu    if (!d) return -1;
259710234Syasuko.eckert@amd.com    int i, l = d->nText;
259810234Syasuko.eckert@amd.com    if (!lpszValue) {
259910234Syasuko.eckert@amd.com        if (l) return 0;
260010234Syasuko.eckert@amd.com        return -1;
260110234Syasuko.eckert@amd.com    }
260210234Syasuko.eckert@amd.com    XMLCSTR *p = d->pText;
260310234Syasuko.eckert@amd.com    for (i = 0; i < l; i++) if (lpszValue == p[i]) return i;
260410152Satgutier@umich.edu    return -1;
260510152Satgutier@umich.edu}
260610152Satgutier@umich.edu
260710234Syasuko.eckert@amd.comvoid XMLNode::deleteText(int i) {
260810234Syasuko.eckert@amd.com    if ((!d) || (i < 0) || (i >= d->nText)) return;
260910152Satgutier@umich.edu    d->nText--;
261010234Syasuko.eckert@amd.com    XMLCSTR *p = d->pText + i;
261110152Satgutier@umich.edu    free((void*)*p);
261210234Syasuko.eckert@amd.com    if (d->nText) memmove(p, p + 1, (d->nText - i)*sizeof(XMLCSTR));
261310234Syasuko.eckert@amd.com    else {
261410234Syasuko.eckert@amd.com        free(p);
261510234Syasuko.eckert@amd.com        d->pText = NULL;
261610234Syasuko.eckert@amd.com    }
261710234Syasuko.eckert@amd.com    removeOrderElement(d, eNodeText, i);
261810152Satgutier@umich.edu}
261910152Satgutier@umich.edu
262010234Syasuko.eckert@amd.comvoid XMLNode::deleteText(XMLCSTR lpszValue) {
262110234Syasuko.eckert@amd.com    deleteText(indexText(lpszValue));
262210234Syasuko.eckert@amd.com}
262310152Satgutier@umich.edu
262410234Syasuko.eckert@amd.comXMLCSTR XMLNode::updateText_WOSD(XMLSTR lpszNewValue, int i) {
262510234Syasuko.eckert@amd.com    if (!d) {
262610234Syasuko.eckert@amd.com        if (lpszNewValue) free(lpszNewValue);
262710234Syasuko.eckert@amd.com        return NULL;
262810234Syasuko.eckert@amd.com    }
262910234Syasuko.eckert@amd.com    if (i >= d->nText) return addText_WOSD(lpszNewValue);
263010234Syasuko.eckert@amd.com    XMLCSTR *p = d->pText + i;
263110234Syasuko.eckert@amd.com    if (*p != lpszNewValue) {
263210234Syasuko.eckert@amd.com        free((void*)*p);
263310234Syasuko.eckert@amd.com        *p = lpszNewValue;
263410234Syasuko.eckert@amd.com    }
263510152Satgutier@umich.edu    return lpszNewValue;
263610152Satgutier@umich.edu}
263710152Satgutier@umich.edu
263810234Syasuko.eckert@amd.comXMLCSTR XMLNode::updateText_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue) {
263910234Syasuko.eckert@amd.com    if (!d) {
264010234Syasuko.eckert@amd.com        if (lpszNewValue) free(lpszNewValue);
264110234Syasuko.eckert@amd.com        return NULL;
264210234Syasuko.eckert@amd.com    }
264310234Syasuko.eckert@amd.com    int i = indexText(lpszOldValue);
264410234Syasuko.eckert@amd.com    if (i >= 0) return updateText_WOSD(lpszNewValue, i);
264510152Satgutier@umich.edu    return addText_WOSD(lpszNewValue);
264610152Satgutier@umich.edu}
264710152Satgutier@umich.edu
264810234Syasuko.eckert@amd.comvoid XMLNode::deleteClear(int i) {
264910234Syasuko.eckert@amd.com    if ((!d) || (i < 0) || (i >= d->nClear)) return;
265010152Satgutier@umich.edu    d->nClear--;
265110234Syasuko.eckert@amd.com    XMLClear *p = d->pClear + i;
265210152Satgutier@umich.edu    free((void*)p->lpszValue);
265310234Syasuko.eckert@amd.com    if (d->nClear) memmove(p, p + 1, (d->nClear - i)*sizeof(XMLClear));
265410234Syasuko.eckert@amd.com    else {
265510234Syasuko.eckert@amd.com        free(p);
265610234Syasuko.eckert@amd.com        d->pClear = NULL;
265710234Syasuko.eckert@amd.com    }
265810234Syasuko.eckert@amd.com    removeOrderElement(d, eNodeClear, i);
265910152Satgutier@umich.edu}
266010152Satgutier@umich.edu
266110234Syasuko.eckert@amd.comint XMLNode::indexClear(XMLCSTR lpszValue) const {
266210152Satgutier@umich.edu    if (!d) return -1;
266310234Syasuko.eckert@amd.com    int i, l = d->nClear;
266410234Syasuko.eckert@amd.com    if (!lpszValue) {
266510234Syasuko.eckert@amd.com        if (l) return 0;
266610234Syasuko.eckert@amd.com        return -1;
266710234Syasuko.eckert@amd.com    }
266810234Syasuko.eckert@amd.com    XMLClear *p = d->pClear;
266910234Syasuko.eckert@amd.com    for (i = 0; i < l; i++) if (lpszValue == p[i].lpszValue) return i;
267010152Satgutier@umich.edu    return -1;
267110152Satgutier@umich.edu}
267210152Satgutier@umich.edu
267310234Syasuko.eckert@amd.comvoid XMLNode::deleteClear(XMLCSTR lpszValue) {
267410234Syasuko.eckert@amd.com    deleteClear(indexClear(lpszValue));
267510234Syasuko.eckert@amd.com}
267610234Syasuko.eckert@amd.comvoid XMLNode::deleteClear(XMLClear *a) {
267710234Syasuko.eckert@amd.com    if (a) deleteClear(a->lpszValue);
267810234Syasuko.eckert@amd.com}
267910152Satgutier@umich.edu
268010234Syasuko.eckert@amd.comXMLClear *XMLNode::updateClear_WOSD(XMLSTR lpszNewContent, int i) {
268110234Syasuko.eckert@amd.com    if (!d) {
268210234Syasuko.eckert@amd.com        if (lpszNewContent) free(lpszNewContent);
268310234Syasuko.eckert@amd.com        return NULL;
268410234Syasuko.eckert@amd.com    }
268510234Syasuko.eckert@amd.com    if (i >= d->nClear) return addClear_WOSD(lpszNewContent);
268610234Syasuko.eckert@amd.com    XMLClear *p = d->pClear + i;
268710234Syasuko.eckert@amd.com    if (lpszNewContent != p->lpszValue) {
268810234Syasuko.eckert@amd.com        free((void*)p->lpszValue);
268910234Syasuko.eckert@amd.com        p->lpszValue = lpszNewContent;
269010234Syasuko.eckert@amd.com    }
269110152Satgutier@umich.edu    return p;
269210152Satgutier@umich.edu}
269310152Satgutier@umich.edu
269410234Syasuko.eckert@amd.comXMLClear *XMLNode::updateClear_WOSD(XMLSTR lpszNewContent,
269510234Syasuko.eckert@amd.com                                    XMLCSTR lpszOldValue) {
269610234Syasuko.eckert@amd.com    if (!d) {
269710234Syasuko.eckert@amd.com        if (lpszNewContent) free(lpszNewContent);
269810234Syasuko.eckert@amd.com        return NULL;
269910234Syasuko.eckert@amd.com    }
270010234Syasuko.eckert@amd.com    int i = indexClear(lpszOldValue);
270110234Syasuko.eckert@amd.com    if (i >= 0) return updateClear_WOSD(lpszNewContent, i);
270210152Satgutier@umich.edu    return addClear_WOSD(lpszNewContent);
270310152Satgutier@umich.edu}
270410152Satgutier@umich.edu
270510234Syasuko.eckert@amd.comXMLClear *XMLNode::updateClear_WOSD(XMLClear *newP, XMLClear *oldP) {
270610234Syasuko.eckert@amd.com    if (oldP) {
270710234Syasuko.eckert@amd.com        return updateClear_WOSD((XMLSTR)newP->lpszValue,
270810234Syasuko.eckert@amd.com                                (XMLSTR)oldP->lpszValue);
270910234Syasuko.eckert@amd.com    }
271010152Satgutier@umich.edu    return NULL;
271110152Satgutier@umich.edu}
271210152Satgutier@umich.edu
271310234Syasuko.eckert@amd.comint XMLNode::nChildNode(XMLCSTR name) const {
271410152Satgutier@umich.edu    if (!d) return 0;
271510234Syasuko.eckert@amd.com    int i, j = 0, n = d->nChild;
271610234Syasuko.eckert@amd.com    XMLNode *pc = d->pChild;
271710234Syasuko.eckert@amd.com    for (i = 0; i < n; i++) {
271810234Syasuko.eckert@amd.com        if (xstricmp(pc->d->lpszName, name) == 0) j++;
271910152Satgutier@umich.edu        pc++;
272010152Satgutier@umich.edu    }
272110152Satgutier@umich.edu    return j;
272210152Satgutier@umich.edu}
272310152Satgutier@umich.edu
272410234Syasuko.eckert@amd.comXMLNode XMLNode::getChildNode(XMLCSTR name, int *j) const {
272510152Satgutier@umich.edu    if (!d) return emptyXMLNode;
272610234Syasuko.eckert@amd.com    int i = 0, n = d->nChild;
272710234Syasuko.eckert@amd.com    if (j) i = *j;
272810234Syasuko.eckert@amd.com    XMLNode *pc = d->pChild + i;
272910234Syasuko.eckert@amd.com    for (; i < n; i++) {
273010234Syasuko.eckert@amd.com        if (!xstricmp(pc->d->lpszName, name)) {
273110234Syasuko.eckert@amd.com            if (j) *j = i + 1;
273210152Satgutier@umich.edu            return *pc;
273310152Satgutier@umich.edu        }
273410152Satgutier@umich.edu        pc++;
273510152Satgutier@umich.edu    }
273610152Satgutier@umich.edu    return emptyXMLNode;
273710152Satgutier@umich.edu}
273810152Satgutier@umich.edu
273910234Syasuko.eckert@amd.comXMLNode XMLNode::getChildNode(XMLCSTR name, int j) const {
274010152Satgutier@umich.edu    if (!d) return emptyXMLNode;
274110234Syasuko.eckert@amd.com    if (j >= 0) {
274210234Syasuko.eckert@amd.com        int i = 0;
274310234Syasuko.eckert@amd.com        while (j-- > 0) getChildNode(name, &i);
274410234Syasuko.eckert@amd.com        return getChildNode(name, &i);
274510152Satgutier@umich.edu    }
274610234Syasuko.eckert@amd.com    int i = d->nChild;
274710234Syasuko.eckert@amd.com    while (i--) if (!xstricmp(name, d->pChild[i].d->lpszName)) break;
274810234Syasuko.eckert@amd.com    if (i < 0) return emptyXMLNode;
274910152Satgutier@umich.edu    return getChildNode(i);
275010152Satgutier@umich.edu}
275110152Satgutier@umich.edu
275210234Syasuko.eckert@amd.comXMLNode* XMLNode::getChildNodePtr(XMLCSTR name, int *j) const {
275310234Syasuko.eckert@amd.com    if (!d) return &emptyXMLNode;
275410234Syasuko.eckert@amd.com    int i = 0, n = d->nChild;
275510234Syasuko.eckert@amd.com    int foundIndex = 0;
275610234Syasuko.eckert@amd.com    XMLNode *pc = d->pChild + i;
275710234Syasuko.eckert@amd.com    for (; i < n; i++) {
275810234Syasuko.eckert@amd.com        if (!xstricmp(pc->d->lpszName, name)) {
275910234Syasuko.eckert@amd.com            if (*j == foundIndex) return pc;
276010234Syasuko.eckert@amd.com            foundIndex++;
276110234Syasuko.eckert@amd.com        }
276210234Syasuko.eckert@amd.com        pc++;
276310234Syasuko.eckert@amd.com    }
276410234Syasuko.eckert@amd.com    return &emptyXMLNode;
276510234Syasuko.eckert@amd.com}
276610234Syasuko.eckert@amd.com
276710234Syasuko.eckert@amd.comXMLNode XMLNode::getChildNodeByPath(XMLCSTR _path, char createMissing,
276810234Syasuko.eckert@amd.com                                    XMLCHAR sep) {
276910234Syasuko.eckert@amd.com    XMLSTR path = stringDup(_path);
277010234Syasuko.eckert@amd.com    XMLNode x = getChildNodeByPathNonConst(path, createMissing, sep);
277110152Satgutier@umich.edu    if (path) free(path);
277210152Satgutier@umich.edu    return x;
277310152Satgutier@umich.edu}
277410152Satgutier@umich.edu
277510234Syasuko.eckert@amd.comXMLNode XMLNode::getChildNodeByPathNonConst(XMLSTR path,
277610234Syasuko.eckert@amd.com                                            char createIfMissing, XMLCHAR sep) {
277710234Syasuko.eckert@amd.com    if ((!path) || (!(*path))) return *this;
277810234Syasuko.eckert@amd.com    XMLNode xn, xbase = *this;
277910234Syasuko.eckert@amd.com    XMLCHAR *tend1, sepString[2];
278010234Syasuko.eckert@amd.com    sepString[0] = sep;
278110234Syasuko.eckert@amd.com    sepString[1] = 0;
278210234Syasuko.eckert@amd.com    tend1 = xstrstr(path, sepString);
278310234Syasuko.eckert@amd.com    while (tend1) {
278410234Syasuko.eckert@amd.com        *tend1 = 0;
278510234Syasuko.eckert@amd.com        xn = xbase.getChildNode(path);
278610234Syasuko.eckert@amd.com        if (xn.isEmpty()) {
278710234Syasuko.eckert@amd.com            if (createIfMissing) xn = xbase.addChild(path);
278810234Syasuko.eckert@amd.com            else {
278910234Syasuko.eckert@amd.com                *tend1 = sep;
279010234Syasuko.eckert@amd.com                return XMLNode::emptyXMLNode;
279110234Syasuko.eckert@amd.com            }
279210152Satgutier@umich.edu        }
279310234Syasuko.eckert@amd.com        *tend1 = sep;
279410234Syasuko.eckert@amd.com        xbase = xn;
279510234Syasuko.eckert@amd.com        path = tend1 + 1;
279610234Syasuko.eckert@amd.com        tend1 = xstrstr(path, sepString);
279710152Satgutier@umich.edu    }
279810234Syasuko.eckert@amd.com    xn = xbase.getChildNode(path);
279910234Syasuko.eckert@amd.com    if (xn.isEmpty() && createIfMissing) xn = xbase.addChild(path);
280010152Satgutier@umich.edu    return xn;
280110152Satgutier@umich.edu}
280210152Satgutier@umich.edu
280310234Syasuko.eckert@amd.comXMLElementPosition XMLNode::positionOfText     (int i) const {
280410234Syasuko.eckert@amd.com    if (i >= d->nText ) i = d->nText - 1;
280510234Syasuko.eckert@amd.com    return findPosition(d, i, eNodeText );
280610234Syasuko.eckert@amd.com}
280710234Syasuko.eckert@amd.comXMLElementPosition XMLNode::positionOfClear    (int i) const {
280810234Syasuko.eckert@amd.com    if (i >= d->nClear) i = d->nClear - 1;
280910234Syasuko.eckert@amd.com    return findPosition(d, i, eNodeClear);
281010234Syasuko.eckert@amd.com}
281110234Syasuko.eckert@amd.comXMLElementPosition XMLNode::positionOfChildNode(int i) const {
281210234Syasuko.eckert@amd.com    if (i >= d->nChild) i = d->nChild - 1;
281310234Syasuko.eckert@amd.com    return findPosition(d, i, eNodeChild);
281410234Syasuko.eckert@amd.com}
281510234Syasuko.eckert@amd.comXMLElementPosition XMLNode::positionOfText (XMLCSTR lpszValue) const {
281610234Syasuko.eckert@amd.com    return positionOfText (indexText (lpszValue));
281710234Syasuko.eckert@amd.com}
281810234Syasuko.eckert@amd.comXMLElementPosition XMLNode::positionOfClear(XMLCSTR lpszValue) const {
281910234Syasuko.eckert@amd.com    return positionOfClear(indexClear(lpszValue));
282010234Syasuko.eckert@amd.com}
282110234Syasuko.eckert@amd.comXMLElementPosition XMLNode::positionOfClear(XMLClear *a) const {
282210234Syasuko.eckert@amd.com    if (a) return positionOfClear(a->lpszValue);
282310234Syasuko.eckert@amd.com    return positionOfClear();
282410234Syasuko.eckert@amd.com}
282510234Syasuko.eckert@amd.comXMLElementPosition XMLNode::positionOfChildNode(XMLNode x)  const {
282610234Syasuko.eckert@amd.com    if ((!d) || (!x.d)) return -1;
282710234Syasuko.eckert@amd.com    XMLNodeData *dd = x.d;
282810234Syasuko.eckert@amd.com    XMLNode *pc = d->pChild;
282910234Syasuko.eckert@amd.com    int i = d->nChild;
283010234Syasuko.eckert@amd.com    while (i--) if (pc[i].d == dd) return findPosition(d, i, eNodeChild);
283110152Satgutier@umich.edu    return -1;
283210152Satgutier@umich.edu}
283310234Syasuko.eckert@amd.comXMLElementPosition XMLNode::positionOfChildNode(XMLCSTR name, int count) const {
283410152Satgutier@umich.edu    if (!name) return positionOfChildNode(count);
283510234Syasuko.eckert@amd.com    int j = 0;
283610234Syasuko.eckert@amd.com    do {
283710234Syasuko.eckert@amd.com        getChildNode(name, &j);
283810234Syasuko.eckert@amd.com        if (j < 0) return -1;
283910234Syasuko.eckert@amd.com    } while (count--);
284010234Syasuko.eckert@amd.com    return findPosition(d, j - 1, eNodeChild);
284110152Satgutier@umich.edu}
284210152Satgutier@umich.edu
284310234Syasuko.eckert@amd.comXMLNode XMLNode::getChildNodeWithAttribute(XMLCSTR name, XMLCSTR attributeName,
284410234Syasuko.eckert@amd.com                                           XMLCSTR attributeValue,
284510234Syasuko.eckert@amd.com                                           int *k) const {
284610234Syasuko.eckert@amd.com    int i = 0, j;
284710234Syasuko.eckert@amd.com    if (k) i = *k;
284810234Syasuko.eckert@amd.com    XMLNode x;
284910234Syasuko.eckert@amd.com    XMLCSTR t;
285010234Syasuko.eckert@amd.com    do {
285110234Syasuko.eckert@amd.com        x = getChildNode(name, &i);
285210234Syasuko.eckert@amd.com        if (!x.isEmpty()) {
285310234Syasuko.eckert@amd.com            if (attributeValue) {
285410234Syasuko.eckert@amd.com                j = 0;
285510234Syasuko.eckert@amd.com                do {
285610234Syasuko.eckert@amd.com                    t = x.getAttribute(attributeName, &j);
285710234Syasuko.eckert@amd.com                    if (t && (xstricmp(attributeValue, t) == 0)) {
285810234Syasuko.eckert@amd.com                        if (k) *k = i;
285910234Syasuko.eckert@amd.com                        return x;
286010234Syasuko.eckert@amd.com                    }
286110234Syasuko.eckert@amd.com                } while (t);
286210234Syasuko.eckert@amd.com            } else {
286310234Syasuko.eckert@amd.com                if (x.isAttributeSet(attributeName)) {
286410234Syasuko.eckert@amd.com                    if (k) *k = i;
286510234Syasuko.eckert@amd.com                    return x;
286610234Syasuko.eckert@amd.com                }
286710234Syasuko.eckert@amd.com            }
286810234Syasuko.eckert@amd.com        }
286910234Syasuko.eckert@amd.com    } while (!x.isEmpty());
287010234Syasuko.eckert@amd.com    return emptyXMLNode;
287110152Satgutier@umich.edu}
287210152Satgutier@umich.edu
287310152Satgutier@umich.edu// Find an attribute on an node.
287410234Syasuko.eckert@amd.comXMLCSTR XMLNode::getAttribute(XMLCSTR lpszAttrib, int *j) const {
287510152Satgutier@umich.edu    if (!d) return NULL;
287610234Syasuko.eckert@amd.com    int i = 0, n = d->nAttribute;
287710234Syasuko.eckert@amd.com    if (j) i = *j;
287810234Syasuko.eckert@amd.com    XMLAttribute *pAttr = d->pAttribute + i;
287910234Syasuko.eckert@amd.com    for (; i < n; i++) {
288010234Syasuko.eckert@amd.com        if (xstricmp(pAttr->lpszName, lpszAttrib) == 0) {
288110234Syasuko.eckert@amd.com            if (j) *j = i + 1;
288210152Satgutier@umich.edu            return pAttr->lpszValue;
288310152Satgutier@umich.edu        }
288410152Satgutier@umich.edu        pAttr++;
288510152Satgutier@umich.edu    }
288610152Satgutier@umich.edu    return NULL;
288710152Satgutier@umich.edu}
288810152Satgutier@umich.edu
288910234Syasuko.eckert@amd.comchar XMLNode::isAttributeSet(XMLCSTR lpszAttrib) const {
289010152Satgutier@umich.edu    if (!d) return FALSE;
289110234Syasuko.eckert@amd.com    int i, n = d->nAttribute;
289210234Syasuko.eckert@amd.com    XMLAttribute *pAttr = d->pAttribute;
289310234Syasuko.eckert@amd.com    for (i = 0; i < n; i++) {
289410234Syasuko.eckert@amd.com        if (xstricmp(pAttr->lpszName, lpszAttrib) == 0) {
289510152Satgutier@umich.edu            return TRUE;
289610152Satgutier@umich.edu        }
289710152Satgutier@umich.edu        pAttr++;
289810152Satgutier@umich.edu    }
289910152Satgutier@umich.edu    return FALSE;
290010152Satgutier@umich.edu}
290110152Satgutier@umich.edu
290210234Syasuko.eckert@amd.comXMLCSTR XMLNode::getAttribute(XMLCSTR name, int j) const {
290310152Satgutier@umich.edu    if (!d) return NULL;
290410234Syasuko.eckert@amd.com    int i = 0;
290510234Syasuko.eckert@amd.com    while (j-- > 0) getAttribute(name, &i);
290610234Syasuko.eckert@amd.com    return getAttribute(name, &i);
290710152Satgutier@umich.edu}
290810152Satgutier@umich.edu
290910234Syasuko.eckert@amd.comXMLNodeContents XMLNode::enumContents(int i) const {
291010152Satgutier@umich.edu    XMLNodeContents c;
291110234Syasuko.eckert@amd.com    if (!d) {
291210234Syasuko.eckert@amd.com        c.etype = eNodeNULL;
291310152Satgutier@umich.edu        return c;
291410152Satgutier@umich.edu    }
291510234Syasuko.eckert@amd.com    if (i < d->nAttribute) {
291610234Syasuko.eckert@amd.com        c.etype = eNodeAttribute;
291710234Syasuko.eckert@amd.com        c.attrib = d->pAttribute[i];
291810234Syasuko.eckert@amd.com        return c;
291910234Syasuko.eckert@amd.com    }
292010234Syasuko.eckert@amd.com    i -= d->nAttribute;
292110234Syasuko.eckert@amd.com    c.etype = (XMLElementType)(d->pOrder[i] & 3);
292210234Syasuko.eckert@amd.com    i = (d->pOrder[i]) >> 2;
292310234Syasuko.eckert@amd.com    switch (c.etype) {
292410234Syasuko.eckert@amd.com    case eNodeChild:
292510234Syasuko.eckert@amd.com        c.child = d->pChild[i];
292610234Syasuko.eckert@amd.com        break;
292710234Syasuko.eckert@amd.com    case eNodeText:
292810234Syasuko.eckert@amd.com        c.text  = d->pText[i];
292910234Syasuko.eckert@amd.com        break;
293010234Syasuko.eckert@amd.com    case eNodeClear:
293110234Syasuko.eckert@amd.com        c.clear = d->pClear[i];
293210234Syasuko.eckert@amd.com        break;
293310234Syasuko.eckert@amd.com    default:
293410234Syasuko.eckert@amd.com        break;
293510152Satgutier@umich.edu    }
293610152Satgutier@umich.edu    return c;
293710152Satgutier@umich.edu}
293810152Satgutier@umich.edu
293910234Syasuko.eckert@amd.comXMLCSTR XMLNode::getName() const {
294010234Syasuko.eckert@amd.com    if (!d) return NULL;
294110234Syasuko.eckert@amd.com    return d->lpszName;
294210234Syasuko.eckert@amd.com}
294310234Syasuko.eckert@amd.comint XMLNode::nText()       const {
294410234Syasuko.eckert@amd.com    if (!d) return 0;
294510234Syasuko.eckert@amd.com    return d->nText;
294610234Syasuko.eckert@amd.com}
294710234Syasuko.eckert@amd.comint XMLNode::nChildNode()  const {
294810234Syasuko.eckert@amd.com    if (!d) return 0;
294910234Syasuko.eckert@amd.com    return d->nChild;
295010234Syasuko.eckert@amd.com}
295110234Syasuko.eckert@amd.comint XMLNode::nAttribute()  const {
295210234Syasuko.eckert@amd.com    if (!d) return 0;
295310234Syasuko.eckert@amd.com    return d->nAttribute;
295410234Syasuko.eckert@amd.com}
295510234Syasuko.eckert@amd.comint XMLNode::nClear()      const {
295610234Syasuko.eckert@amd.com    if (!d) return 0;
295710234Syasuko.eckert@amd.com    return d->nClear;
295810234Syasuko.eckert@amd.com}
295910234Syasuko.eckert@amd.comint XMLNode::nElement()    const {
296010234Syasuko.eckert@amd.com    if (!d) return 0;
296110234Syasuko.eckert@amd.com    return d->nAttribute + d->nChild + d->nText + d->nClear;
296210234Syasuko.eckert@amd.com}
296310234Syasuko.eckert@amd.comXMLClear     XMLNode::getClear         (int i) const {
296410234Syasuko.eckert@amd.com    if ((!d) || (i >= d->nClear    )) return emptyXMLClear;
296510234Syasuko.eckert@amd.com    return d->pClear[i];
296610234Syasuko.eckert@amd.com}
296710234Syasuko.eckert@amd.comXMLAttribute XMLNode::getAttribute     (int i) const {
296810234Syasuko.eckert@amd.com    if ((!d) || (i >= d->nAttribute)) return emptyXMLAttribute;
296910234Syasuko.eckert@amd.com    return d->pAttribute[i];
297010234Syasuko.eckert@amd.com}
297110234Syasuko.eckert@amd.comXMLCSTR      XMLNode::getAttributeName (int i) const {
297210234Syasuko.eckert@amd.com    if ((!d) || (i >= d->nAttribute)) return NULL;
297310234Syasuko.eckert@amd.com    return d->pAttribute[i].lpszName;
297410234Syasuko.eckert@amd.com}
297510234Syasuko.eckert@amd.comXMLCSTR      XMLNode::getAttributeValue(int i) const {
297610234Syasuko.eckert@amd.com    if ((!d) || (i >= d->nAttribute)) return NULL;
297710234Syasuko.eckert@amd.com    return d->pAttribute[i].lpszValue;
297810234Syasuko.eckert@amd.com}
297910234Syasuko.eckert@amd.comXMLCSTR      XMLNode::getText          (int i) const {
298010234Syasuko.eckert@amd.com    if ((!d) || (i >= d->nText     )) return NULL;
298110234Syasuko.eckert@amd.com    return d->pText[i];
298210234Syasuko.eckert@amd.com}
298310234Syasuko.eckert@amd.comXMLNode      XMLNode::getChildNode     (int i) const {
298410234Syasuko.eckert@amd.com    if ((!d) || (i >= d->nChild    )) return emptyXMLNode;
298510234Syasuko.eckert@amd.com    return d->pChild[i];
298610234Syasuko.eckert@amd.com}
298710234Syasuko.eckert@amd.comXMLNode      XMLNode::getParentNode    (     ) const {
298810234Syasuko.eckert@amd.com    if ((!d) || (!d->pParent     )) return emptyXMLNode;
298910234Syasuko.eckert@amd.com    return XMLNode(d->pParent);
299010234Syasuko.eckert@amd.com}
299110234Syasuko.eckert@amd.comchar         XMLNode::isDeclaration    (     ) const {
299210234Syasuko.eckert@amd.com    if (!d) return 0;
299310234Syasuko.eckert@amd.com    return d->isDeclaration;
299410234Syasuko.eckert@amd.com}
299510234Syasuko.eckert@amd.comchar         XMLNode::isEmpty          (     ) const {
299610234Syasuko.eckert@amd.com    return (d == NULL);
299710234Syasuko.eckert@amd.com}
299810234Syasuko.eckert@amd.comXMLNode       XMLNode::emptyNode       (     )       {
299910234Syasuko.eckert@amd.com    return XMLNode::emptyXMLNode;
300010234Syasuko.eckert@amd.com}
300110152Satgutier@umich.edu
300210234Syasuko.eckert@amd.comXMLNode XMLNode::addChild(XMLCSTR lpszName, char isDeclaration,
300310234Syasuko.eckert@amd.com                          XMLElementPosition pos) {
300410234Syasuko.eckert@amd.com    return addChild_priv(0, stringDup(lpszName), isDeclaration, pos);
300510234Syasuko.eckert@amd.com}
300610234Syasuko.eckert@amd.comXMLNode XMLNode::addChild_WOSD(XMLSTR lpszName, char isDeclaration,
300710234Syasuko.eckert@amd.com                               XMLElementPosition pos) {
300810234Syasuko.eckert@amd.com    return addChild_priv(0, lpszName, isDeclaration, pos);
300910234Syasuko.eckert@amd.com}
301010234Syasuko.eckert@amd.comXMLAttribute *XMLNode::addAttribute(XMLCSTR lpszName, XMLCSTR lpszValue) {
301110234Syasuko.eckert@amd.com    return addAttribute_priv(0, stringDup(lpszName), stringDup(lpszValue));
301210234Syasuko.eckert@amd.com}
301310234Syasuko.eckert@amd.comXMLAttribute *XMLNode::addAttribute_WOSD(XMLSTR lpszName, XMLSTR lpszValuev) {
301410234Syasuko.eckert@amd.com    return addAttribute_priv(0, lpszName, lpszValuev);
301510234Syasuko.eckert@amd.com}
301610234Syasuko.eckert@amd.comXMLCSTR XMLNode::addText(XMLCSTR lpszValue, XMLElementPosition pos) {
301710234Syasuko.eckert@amd.com    return addText_priv(0, stringDup(lpszValue), pos);
301810234Syasuko.eckert@amd.com}
301910234Syasuko.eckert@amd.comXMLCSTR XMLNode::addText_WOSD(XMLSTR lpszValue, XMLElementPosition pos) {
302010234Syasuko.eckert@amd.com    return addText_priv(0, lpszValue, pos);
302110234Syasuko.eckert@amd.com}
302210234Syasuko.eckert@amd.comXMLClear *XMLNode::addClear(XMLCSTR lpszValue, XMLCSTR lpszOpen,
302310234Syasuko.eckert@amd.com                            XMLCSTR lpszClose, XMLElementPosition pos) {
302410234Syasuko.eckert@amd.com    return addClear_priv(0, stringDup(lpszValue), lpszOpen, lpszClose, pos);
302510234Syasuko.eckert@amd.com}
302610234Syasuko.eckert@amd.comXMLClear *XMLNode::addClear_WOSD(XMLSTR lpszValue, XMLCSTR lpszOpen,
302710234Syasuko.eckert@amd.com                                 XMLCSTR lpszClose, XMLElementPosition pos) {
302810234Syasuko.eckert@amd.com    return addClear_priv(0, lpszValue, lpszOpen, lpszClose, pos);
302910234Syasuko.eckert@amd.com}
303010234Syasuko.eckert@amd.comXMLCSTR XMLNode::updateName(XMLCSTR lpszName) {
303110234Syasuko.eckert@amd.com    return updateName_WOSD(stringDup(lpszName));
303210234Syasuko.eckert@amd.com}
303310234Syasuko.eckert@amd.comXMLAttribute *XMLNode::updateAttribute(XMLAttribute *newAttribute,
303410234Syasuko.eckert@amd.com                                       XMLAttribute *oldAttribute) {
303510234Syasuko.eckert@amd.com    return updateAttribute_WOSD(stringDup(newAttribute->lpszValue),
303610234Syasuko.eckert@amd.com                                stringDup(newAttribute->lpszName),
303710234Syasuko.eckert@amd.com                                oldAttribute->lpszName);
303810234Syasuko.eckert@amd.com}
303910234Syasuko.eckert@amd.comXMLAttribute *XMLNode::updateAttribute(XMLCSTR lpszNewValue,
304010234Syasuko.eckert@amd.com                                       XMLCSTR lpszNewName, int i) {
304110234Syasuko.eckert@amd.com    return updateAttribute_WOSD(stringDup(lpszNewValue),
304210234Syasuko.eckert@amd.com                                stringDup(lpszNewName), i);
304310234Syasuko.eckert@amd.com}
304410234Syasuko.eckert@amd.comXMLAttribute *XMLNode::updateAttribute(XMLCSTR lpszNewValue,
304510234Syasuko.eckert@amd.com                                       XMLCSTR lpszNewName,
304610234Syasuko.eckert@amd.com                                       XMLCSTR lpszOldName) {
304710234Syasuko.eckert@amd.com    return updateAttribute_WOSD(stringDup(lpszNewValue),
304810234Syasuko.eckert@amd.com                                stringDup(lpszNewName), lpszOldName);
304910234Syasuko.eckert@amd.com}
305010234Syasuko.eckert@amd.comXMLCSTR XMLNode::updateText(XMLCSTR lpszNewValue, int i) {
305110234Syasuko.eckert@amd.com    return updateText_WOSD(stringDup(lpszNewValue), i);
305210234Syasuko.eckert@amd.com}
305310234Syasuko.eckert@amd.comXMLCSTR XMLNode::updateText(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue) {
305410234Syasuko.eckert@amd.com    return updateText_WOSD(stringDup(lpszNewValue), lpszOldValue);
305510234Syasuko.eckert@amd.com}
305610234Syasuko.eckert@amd.comXMLClear *XMLNode::updateClear(XMLCSTR lpszNewContent, int i) {
305710234Syasuko.eckert@amd.com    return updateClear_WOSD(stringDup(lpszNewContent), i);
305810234Syasuko.eckert@amd.com}
305910234Syasuko.eckert@amd.comXMLClear *XMLNode::updateClear(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue) {
306010234Syasuko.eckert@amd.com    return updateClear_WOSD(stringDup(lpszNewValue), lpszOldValue);
306110234Syasuko.eckert@amd.com}
306210234Syasuko.eckert@amd.comXMLClear     *XMLNode::updateClear(XMLClear *newP, XMLClear *oldP) {
306310234Syasuko.eckert@amd.com    return updateClear_WOSD(stringDup(newP->lpszValue), oldP->lpszValue);
306410234Syasuko.eckert@amd.com}
306510152Satgutier@umich.edu
306610234Syasuko.eckert@amd.comchar XMLNode::setGlobalOptions(XMLCharEncoding _characterEncoding,
306710234Syasuko.eckert@amd.com                               char _guessWideCharChars,
306810234Syasuko.eckert@amd.com                               char _dropWhiteSpace,
306910234Syasuko.eckert@amd.com                               char _removeCommentsInMiddleOfText) {
307010234Syasuko.eckert@amd.com    guessWideCharChars = _guessWideCharChars;
307110234Syasuko.eckert@amd.com    dropWhiteSpace = _dropWhiteSpace;
307210234Syasuko.eckert@amd.com    removeCommentsInMiddleOfText = _removeCommentsInMiddleOfText;
307310152Satgutier@umich.edu#ifdef _XMLWIDECHAR
307410234Syasuko.eckert@amd.com    if (_characterEncoding) characterEncoding = _characterEncoding;
307510152Satgutier@umich.edu#else
307610234Syasuko.eckert@amd.com    switch (_characterEncoding) {
307710234Syasuko.eckert@amd.com    case char_encoding_UTF8:
307810234Syasuko.eckert@amd.com        characterEncoding = _characterEncoding;
307910234Syasuko.eckert@amd.com        XML_ByteTable = XML_utf8ByteTable;
308010234Syasuko.eckert@amd.com        break;
308110234Syasuko.eckert@amd.com    case char_encoding_legacy:
308210234Syasuko.eckert@amd.com        characterEncoding = _characterEncoding;
308310234Syasuko.eckert@amd.com        XML_ByteTable = XML_legacyByteTable;
308410234Syasuko.eckert@amd.com        break;
308510234Syasuko.eckert@amd.com    case char_encoding_ShiftJIS:
308610234Syasuko.eckert@amd.com        characterEncoding = _characterEncoding;
308710234Syasuko.eckert@amd.com        XML_ByteTable = XML_sjisByteTable;
308810234Syasuko.eckert@amd.com        break;
308910234Syasuko.eckert@amd.com    case char_encoding_GB2312:
309010234Syasuko.eckert@amd.com        characterEncoding = _characterEncoding;
309110234Syasuko.eckert@amd.com        XML_ByteTable = XML_gb2312ByteTable;
309210234Syasuko.eckert@amd.com        break;
309310152Satgutier@umich.edu    case char_encoding_Big5:
309410234Syasuko.eckert@amd.com    case char_encoding_GBK:
309510234Syasuko.eckert@amd.com        characterEncoding = _characterEncoding;
309610234Syasuko.eckert@amd.com        XML_ByteTable = XML_gbk_big5_ByteTable;
309710234Syasuko.eckert@amd.com        break;
309810234Syasuko.eckert@amd.com    default:
309910234Syasuko.eckert@amd.com        return 1;
310010152Satgutier@umich.edu    }
310110152Satgutier@umich.edu#endif
310210152Satgutier@umich.edu    return 0;
310310152Satgutier@umich.edu}
310410152Satgutier@umich.edu
310510234Syasuko.eckert@amd.comXMLNode::XMLCharEncoding XMLNode::guessCharEncoding(void *buf, int l,
310610234Syasuko.eckert@amd.com                                                    char useXMLEncodingAttribute) {
310710152Satgutier@umich.edu#ifdef _XMLWIDECHAR
310810152Satgutier@umich.edu    return (XMLCharEncoding)0;
310910152Satgutier@umich.edu#else
311010234Syasuko.eckert@amd.com    if (l < 25) return (XMLCharEncoding)0;
311110234Syasuko.eckert@amd.com    if (guessWideCharChars && (myIsTextWideChar(buf, l))) {
311210234Syasuko.eckert@amd.com        return (XMLCharEncoding)0;
311310234Syasuko.eckert@amd.com    }
311410234Syasuko.eckert@amd.com    unsigned char *b = (unsigned char*)buf;
311510234Syasuko.eckert@amd.com    if ((b[0] == 0xef) && (b[1] == 0xbb) && (b[2] == 0xbf)) {
311610234Syasuko.eckert@amd.com        return char_encoding_UTF8;
311710234Syasuko.eckert@amd.com    }
311810152Satgutier@umich.edu
311910152Satgutier@umich.edu    // Match utf-8 model ?
312010234Syasuko.eckert@amd.com    XMLCharEncoding bestGuess = char_encoding_UTF8;
312110234Syasuko.eckert@amd.com    int i = 0;
312210234Syasuko.eckert@amd.com    while (i < l)
312310234Syasuko.eckert@amd.com        switch (XML_utf8ByteTable[b[i]]) {
312410234Syasuko.eckert@amd.com        case 4:
312510234Syasuko.eckert@amd.com            i++;
312610234Syasuko.eckert@amd.com            if ((i < l) && (b[i]& 0xC0) != 0x80) {
312710234Syasuko.eckert@amd.com                bestGuess = char_encoding_legacy;    // 10bbbbbb ?
312810234Syasuko.eckert@amd.com                i = l;
312910234Syasuko.eckert@amd.com            }
313010234Syasuko.eckert@amd.com        case 3:
313110234Syasuko.eckert@amd.com            i++;
313210234Syasuko.eckert@amd.com            if ((i < l) && (b[i]& 0xC0) != 0x80) {
313310234Syasuko.eckert@amd.com                bestGuess = char_encoding_legacy;    // 10bbbbbb ?
313410234Syasuko.eckert@amd.com                i = l;
313510234Syasuko.eckert@amd.com            }
313610234Syasuko.eckert@amd.com        case 2:
313710234Syasuko.eckert@amd.com            i++;
313810234Syasuko.eckert@amd.com            if ((i < l) && (b[i]& 0xC0) != 0x80) {
313910234Syasuko.eckert@amd.com                bestGuess = char_encoding_legacy;    // 10bbbbbb ?
314010234Syasuko.eckert@amd.com                i = l;
314110234Syasuko.eckert@amd.com            }
314210234Syasuko.eckert@amd.com        case 1:
314310234Syasuko.eckert@amd.com            i++;
314410234Syasuko.eckert@amd.com            break;
314510234Syasuko.eckert@amd.com        case 0:
314610234Syasuko.eckert@amd.com            i = l;
314710152Satgutier@umich.edu        }
314810152Satgutier@umich.edu    if (!useXMLEncodingAttribute) return bestGuess;
314910152Satgutier@umich.edu    // if encoding is specified and different from utf-8 than it's non-utf8
315010152Satgutier@umich.edu    // otherwise it's utf-8
315110152Satgutier@umich.edu    char bb[201];
315210234Syasuko.eckert@amd.com    l = mmin(l, 200);
315310234Syasuko.eckert@amd.com    memcpy(bb, buf, l); // copy buf into bb to be able to do "bb[l]=0"
315410234Syasuko.eckert@amd.com    bb[l] = 0;
315510234Syasuko.eckert@amd.com    b = (unsigned char*)strstr(bb, "encoding");
315610152Satgutier@umich.edu    if (!b) return bestGuess;
315710234Syasuko.eckert@amd.com    b += 8;
315810234Syasuko.eckert@amd.com    while XML_isSPACECHAR(*b) b++;
315910234Syasuko.eckert@amd.com    if (*b != '=') return bestGuess;
316010234Syasuko.eckert@amd.com    b++;
316110234Syasuko.eckert@amd.com    while XML_isSPACECHAR(*b) b++;
316210234Syasuko.eckert@amd.com    if ((*b != '\'') && (*b != '"')) return bestGuess;
316310234Syasuko.eckert@amd.com    b++;
316410234Syasuko.eckert@amd.com    while XML_isSPACECHAR(*b) b++;
316510152Satgutier@umich.edu
316610234Syasuko.eckert@amd.com    if ((xstrnicmp((char*)b, "utf-8", 5) == 0) ||
316710234Syasuko.eckert@amd.com            (xstrnicmp((char*)b, "utf8", 4) == 0)) {
316810234Syasuko.eckert@amd.com        if (bestGuess == char_encoding_legacy) return char_encoding_error;
316910152Satgutier@umich.edu        return char_encoding_UTF8;
317010152Satgutier@umich.edu    }
317110152Satgutier@umich.edu
317210234Syasuko.eckert@amd.com    if ((xstrnicmp((char*)b, "shiftjis", 8) == 0) ||
317310234Syasuko.eckert@amd.com            (xstrnicmp((char*)b, "shift-jis", 9) == 0) ||
317410234Syasuko.eckert@amd.com            (xstrnicmp((char*)b, "sjis", 4) == 0)) return char_encoding_ShiftJIS;
317510152Satgutier@umich.edu
317610234Syasuko.eckert@amd.com    if (xstrnicmp((char*)b, "GB2312", 6) == 0) return char_encoding_GB2312;
317710234Syasuko.eckert@amd.com    if (xstrnicmp((char*)b, "Big5", 4) == 0) return char_encoding_Big5;
317810234Syasuko.eckert@amd.com    if (xstrnicmp((char*)b, "GBK", 3) == 0) return char_encoding_GBK;
317910152Satgutier@umich.edu
318010152Satgutier@umich.edu    return char_encoding_legacy;
318110152Satgutier@umich.edu#endif
318210152Satgutier@umich.edu}
318310152Satgutier@umich.edu#undef XML_isSPACECHAR
318410152Satgutier@umich.edu
318510152Satgutier@umich.edu//////////////////////////////////////////////////////////
318610152Satgutier@umich.edu//      Here starts the base64 conversion functions.    //
318710152Satgutier@umich.edu//////////////////////////////////////////////////////////
318810152Satgutier@umich.edu
318910234Syasuko.eckert@amd.com// used to mark partial words at the end
319010234Syasuko.eckert@amd.comstatic const char base64Fillchar = _CXML('=');
319110152Satgutier@umich.edu
319210152Satgutier@umich.edu// this lookup table defines the base64 encoding
319310234Syasuko.eckert@amd.comXMLCSTR base64EncodeTable = _CXML("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
319410152Satgutier@umich.edu
319510152Satgutier@umich.edu// Decode Table gives the index of any valid base64 character in the Base64 table]
319610152Satgutier@umich.edu// 96: '='  -   97: space char   -   98: illegal char   -   99: end of string
319710152Satgutier@umich.educonst unsigned char base64DecodeTable[] = {
319810234Syasuko.eckert@amd.com    99, 98, 98, 98, 98, 98, 98, 98, 98, 97,  97, 98, 98, 97, 98, 98, 98, 98, 98, 98,  98, 98, 98, 98, 98, 98, 98, 98, 98, 98,  //00 -29
319910234Syasuko.eckert@amd.com    98, 98, 97, 98, 98, 98, 98, 98, 98, 98,  98, 98, 98, 62, 98, 98, 98, 63, 52, 53,  54, 55, 56, 57, 58, 59, 60, 61, 98, 98,  //30 -59
320010234Syasuko.eckert@amd.com    98, 96, 98, 98, 98, 0, 1, 2, 3, 4,   5, 6, 7, 8, 9, 10, 11, 12, 13, 14,  15, 16, 17, 18, 19, 20, 21, 22, 23, 24,  //60 -89
320110234Syasuko.eckert@amd.com    25, 98, 98, 98, 98, 98, 98, 26, 27, 28,  29, 30, 31, 32, 33, 34, 35, 36, 37, 38,  39, 40, 41, 42, 43, 44, 45, 46, 47, 48,  //90 -119
320210234Syasuko.eckert@amd.com    49, 50, 51, 98, 98, 98, 98, 98, 98, 98,  98, 98, 98, 98, 98, 98, 98, 98, 98, 98,  98, 98, 98, 98, 98, 98, 98, 98, 98, 98,  //120 -149
320310234Syasuko.eckert@amd.com    98, 98, 98, 98, 98, 98, 98, 98, 98, 98,  98, 98, 98, 98, 98, 98, 98, 98, 98, 98,  98, 98, 98, 98, 98, 98, 98, 98, 98, 98,  //150 -179
320410234Syasuko.eckert@amd.com    98, 98, 98, 98, 98, 98, 98, 98, 98, 98,  98, 98, 98, 98, 98, 98, 98, 98, 98, 98,  98, 98, 98, 98, 98, 98, 98, 98, 98, 98,  //180 -209
320510234Syasuko.eckert@amd.com    98, 98, 98, 98, 98, 98, 98, 98, 98, 98,  98, 98, 98, 98, 98, 98, 98, 98, 98, 98,  98, 98, 98, 98, 98, 98, 98, 98, 98, 98,  //210 -239
320610234Syasuko.eckert@amd.com    98, 98, 98, 98, 98, 98, 98, 98, 98, 98,  98, 98, 98, 98, 98, 98                                 //240 -255
320710152Satgutier@umich.edu};
320810152Satgutier@umich.edu
320910234Syasuko.eckert@amd.comXMLParserBase64Tool::~XMLParserBase64Tool() {
321010234Syasuko.eckert@amd.com    freeBuffer();
321110234Syasuko.eckert@amd.com}
321210152Satgutier@umich.edu
321310234Syasuko.eckert@amd.comvoid XMLParserBase64Tool::freeBuffer() {
321410234Syasuko.eckert@amd.com    if (buf) free(buf);
321510234Syasuko.eckert@amd.com    buf = NULL;
321610234Syasuko.eckert@amd.com    buflen = 0;
321710234Syasuko.eckert@amd.com}
321810152Satgutier@umich.edu
321910234Syasuko.eckert@amd.comint XMLParserBase64Tool::encodeLength(int inlen, char formatted) {
322010234Syasuko.eckert@amd.com    unsigned int i = ((inlen - 1) / 3 * 4 + 4 + 1);
322110234Syasuko.eckert@amd.com    if (formatted) i += inlen / 54;
322210152Satgutier@umich.edu    return i;
322310152Satgutier@umich.edu}
322410152Satgutier@umich.edu
322510234Syasuko.eckert@amd.comXMLSTR XMLParserBase64Tool::encode(unsigned char *inbuf, unsigned int inlen,
322610234Syasuko.eckert@amd.com                                   char formatted) {
322710234Syasuko.eckert@amd.com    int i = encodeLength(inlen, formatted), k = 17, eLen = inlen / 3, j;
322810152Satgutier@umich.edu    alloc(i*sizeof(XMLCHAR));
322910234Syasuko.eckert@amd.com    XMLSTR curr = (XMLSTR)buf;
323010234Syasuko.eckert@amd.com    for (i = 0; i < eLen; i++) {
323110152Satgutier@umich.edu        // Copy next three bytes into lower 24 bits of int, paying attention to sign.
323210234Syasuko.eckert@amd.com        j = (inbuf[0] << 16) | (inbuf[1] << 8) | inbuf[2];
323310234Syasuko.eckert@amd.com        inbuf += 3;
323410152Satgutier@umich.edu        // Encode the int into four chars
323510234Syasuko.eckert@amd.com        *(curr++) = base64EncodeTable[ j>>18      ];
323610234Syasuko.eckert@amd.com        *(curr++) = base64EncodeTable[(j>>12)&0x3f];
323710234Syasuko.eckert@amd.com        *(curr++) = base64EncodeTable[(j>> 6)&0x3f];
323810234Syasuko.eckert@amd.com        *(curr++) = base64EncodeTable[(j    )&0x3f];
323910234Syasuko.eckert@amd.com        if (formatted) {
324010234Syasuko.eckert@amd.com            if (!k) {
324110234Syasuko.eckert@amd.com                *(curr++) = _CXML('\n');
324210234Syasuko.eckert@amd.com                k = 18;
324310234Syasuko.eckert@amd.com            }
324410234Syasuko.eckert@amd.com            k--;
324510234Syasuko.eckert@amd.com        }
324610152Satgutier@umich.edu    }
324710234Syasuko.eckert@amd.com    eLen = inlen - eLen * 3; // 0 - 2.
324810234Syasuko.eckert@amd.com    if (eLen == 1) {
324910234Syasuko.eckert@amd.com        *(curr++) = base64EncodeTable[ inbuf[0] >> 2      ];
325010234Syasuko.eckert@amd.com        *(curr++) = base64EncodeTable[(inbuf[0] << 4) & 0x3F];
325110234Syasuko.eckert@amd.com        *(curr++) = base64Fillchar;
325210234Syasuko.eckert@amd.com        *(curr++) = base64Fillchar;
325310234Syasuko.eckert@amd.com    } else if (eLen == 2) {
325410234Syasuko.eckert@amd.com        j = (inbuf[0] << 8) | inbuf[1];
325510234Syasuko.eckert@amd.com        *(curr++) = base64EncodeTable[ j>>10      ];
325610234Syasuko.eckert@amd.com        *(curr++) = base64EncodeTable[(j>> 4)&0x3f];
325710234Syasuko.eckert@amd.com        *(curr++) = base64EncodeTable[(j<< 2)&0x3f];
325810234Syasuko.eckert@amd.com        *(curr++) = base64Fillchar;
325910152Satgutier@umich.edu    }
326010234Syasuko.eckert@amd.com    *(curr++) = 0;
326110152Satgutier@umich.edu    return (XMLSTR)buf;
326210152Satgutier@umich.edu}
326310152Satgutier@umich.edu
326410234Syasuko.eckert@amd.comunsigned int XMLParserBase64Tool::decodeSize(XMLCSTR data, XMLError *xe) {
326510234Syasuko.eckert@amd.com    if (xe) *xe = eXMLErrorNone;
326610234Syasuko.eckert@amd.com    int size = 0;
326710152Satgutier@umich.edu    unsigned char c;
326810152Satgutier@umich.edu    //skip any extra characters (e.g. newlines or spaces)
326910234Syasuko.eckert@amd.com    while (*data) {
327010152Satgutier@umich.edu#ifdef _XMLWIDECHAR
327110234Syasuko.eckert@amd.com        if (*data > 255) {
327210234Syasuko.eckert@amd.com            if (xe) *xe = eXMLErrorBase64DecodeIllegalCharacter;
327310234Syasuko.eckert@amd.com            return 0;
327410234Syasuko.eckert@amd.com        }
327510152Satgutier@umich.edu#endif
327610234Syasuko.eckert@amd.com        c = base64DecodeTable[(unsigned char)(*data)];
327710234Syasuko.eckert@amd.com        if (c < 97) size++;
327810234Syasuko.eckert@amd.com        else if (c == 98) {
327910234Syasuko.eckert@amd.com            if (xe) *xe = eXMLErrorBase64DecodeIllegalCharacter;
328010234Syasuko.eckert@amd.com            return 0;
328110234Syasuko.eckert@amd.com        }
328210152Satgutier@umich.edu        data++;
328310152Satgutier@umich.edu    }
328410234Syasuko.eckert@amd.com    if (xe && (size % 4 != 0)) *xe = eXMLErrorBase64DataSizeIsNotMultipleOf4;
328510234Syasuko.eckert@amd.com    if (size == 0) return 0;
328610234Syasuko.eckert@amd.com    do {
328710234Syasuko.eckert@amd.com        data--;
328810234Syasuko.eckert@amd.com        size--;
328910234Syasuko.eckert@amd.com    } while (*data == base64Fillchar);
329010234Syasuko.eckert@amd.com    size++;
329110234Syasuko.eckert@amd.com    return (unsigned int)((size*3) / 4);
329210152Satgutier@umich.edu}
329310152Satgutier@umich.edu
329410234Syasuko.eckert@amd.comunsigned char XMLParserBase64Tool::decode(XMLCSTR data, unsigned char *buf,
329510234Syasuko.eckert@amd.com                                          int len, XMLError *xe) {
329610234Syasuko.eckert@amd.com    if (xe) *xe = eXMLErrorNone;
329710234Syasuko.eckert@amd.com    int i = 0, p = 0;
329810234Syasuko.eckert@amd.com    unsigned char d, c;
329910234Syasuko.eckert@amd.com    for (;;) {
330010152Satgutier@umich.edu
330110152Satgutier@umich.edu#ifdef _XMLWIDECHAR
330210152Satgutier@umich.edu#define BASE64DECODE_READ_NEXT_CHAR(c)                                              \
330310152Satgutier@umich.edu        do {                                                                        \
330410152Satgutier@umich.edu            if (data[i]>255){ c=98; break; }                                        \
330510152Satgutier@umich.edu            c=base64DecodeTable[(unsigned char)data[i++]];                       \
330610152Satgutier@umich.edu        }while (c==97);                                                             \
330710152Satgutier@umich.edu        if(c==98){ if(xe)*xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
330810152Satgutier@umich.edu#else
330910152Satgutier@umich.edu#define BASE64DECODE_READ_NEXT_CHAR(c)                                           \
331010152Satgutier@umich.edu        do { c=base64DecodeTable[(unsigned char)data[i++]]; }while (c==97);   \
331110152Satgutier@umich.edu        if(c==98){ if(xe)*xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
331210152Satgutier@umich.edu#endif
331310152Satgutier@umich.edu
331410152Satgutier@umich.edu        BASE64DECODE_READ_NEXT_CHAR(c)
331510234Syasuko.eckert@amd.com        if (c == 99) {
331610234Syasuko.eckert@amd.com            return 2;
331710234Syasuko.eckert@amd.com        }
331810234Syasuko.eckert@amd.com        if (c == 96) {
331910234Syasuko.eckert@amd.com            if (p == (int)len) return 2;
332010234Syasuko.eckert@amd.com            if (xe) *xe = eXMLErrorBase64DecodeTruncatedData;
332110152Satgutier@umich.edu            return 1;
332210152Satgutier@umich.edu        }
332310152Satgutier@umich.edu
332410152Satgutier@umich.edu        BASE64DECODE_READ_NEXT_CHAR(d)
332510234Syasuko.eckert@amd.com        if ((d == 99) || (d == 96)) {
332610234Syasuko.eckert@amd.com            if (xe) *xe = eXMLErrorBase64DecodeTruncatedData;
332710234Syasuko.eckert@amd.com            return 1;
332810234Syasuko.eckert@amd.com        }
332910234Syasuko.eckert@amd.com        if (p == (int)len) {
333010234Syasuko.eckert@amd.com            if (xe) *xe = eXMLErrorBase64DecodeBufferTooSmall;
333110234Syasuko.eckert@amd.com            return 0;
333210234Syasuko.eckert@amd.com        }
333310234Syasuko.eckert@amd.com        buf[p++] = (unsigned char)((c << 2) | ((d >> 4) & 0x3));
333410152Satgutier@umich.edu
333510152Satgutier@umich.edu        BASE64DECODE_READ_NEXT_CHAR(c)
333610234Syasuko.eckert@amd.com        if (c == 99) {
333710234Syasuko.eckert@amd.com            if (xe) *xe = eXMLErrorBase64DecodeTruncatedData;
333810234Syasuko.eckert@amd.com            return 1;
333910234Syasuko.eckert@amd.com        }
334010234Syasuko.eckert@amd.com        if (p == (int)len) {
334110234Syasuko.eckert@amd.com            if (c == 96) return 2;
334210234Syasuko.eckert@amd.com            if (xe) *xe = eXMLErrorBase64DecodeBufferTooSmall;
334310152Satgutier@umich.edu            return 0;
334410152Satgutier@umich.edu        }
334510234Syasuko.eckert@amd.com        if (c == 96) {
334610234Syasuko.eckert@amd.com            if (xe) *xe = eXMLErrorBase64DecodeTruncatedData;
334710234Syasuko.eckert@amd.com            return 1;
334810234Syasuko.eckert@amd.com        }
334910234Syasuko.eckert@amd.com        buf[p++] = (unsigned char)(((d << 4) & 0xf0) | ((c >> 2) & 0xf));
335010152Satgutier@umich.edu
335110152Satgutier@umich.edu        BASE64DECODE_READ_NEXT_CHAR(d)
335210234Syasuko.eckert@amd.com        if (d == 99 ) {
335310234Syasuko.eckert@amd.com            if (xe) *xe = eXMLErrorBase64DecodeTruncatedData;
335410234Syasuko.eckert@amd.com            return 1;
335510234Syasuko.eckert@amd.com        }
335610234Syasuko.eckert@amd.com        if (p == (int)len) {
335710234Syasuko.eckert@amd.com            if (d == 96) return 2;
335810234Syasuko.eckert@amd.com            if (xe) *xe = eXMLErrorBase64DecodeBufferTooSmall;
335910152Satgutier@umich.edu            return 0;
336010152Satgutier@umich.edu        }
336110234Syasuko.eckert@amd.com        if (d == 96) {
336210234Syasuko.eckert@amd.com            if (xe) *xe = eXMLErrorBase64DecodeTruncatedData;
336310234Syasuko.eckert@amd.com            return 1;
336410234Syasuko.eckert@amd.com        }
336510234Syasuko.eckert@amd.com        buf[p++] = (unsigned char)(((c << 6) & 0xc0) | d);
336610152Satgutier@umich.edu    }
336710152Satgutier@umich.edu}
336810152Satgutier@umich.edu#undef BASE64DECODE_READ_NEXT_CHAR
336910152Satgutier@umich.edu
337010234Syasuko.eckert@amd.comvoid XMLParserBase64Tool::alloc(int newsize) {
337110234Syasuko.eckert@amd.com    if ((!buf) && (newsize)) {
337210234Syasuko.eckert@amd.com        buf = malloc(newsize);
337310234Syasuko.eckert@amd.com        buflen = newsize;
337410234Syasuko.eckert@amd.com        return;
337510234Syasuko.eckert@amd.com    }
337610234Syasuko.eckert@amd.com    if (newsize > buflen) {
337710234Syasuko.eckert@amd.com        buf = realloc(buf, newsize);
337810234Syasuko.eckert@amd.com        buflen = newsize;
337910234Syasuko.eckert@amd.com    }
338010152Satgutier@umich.edu}
338110152Satgutier@umich.edu
338210234Syasuko.eckert@amd.comunsigned char *XMLParserBase64Tool::decode(XMLCSTR data, int *outlen, XMLError *xe) {
338310234Syasuko.eckert@amd.com    if (xe) *xe = eXMLErrorNone;
338410234Syasuko.eckert@amd.com    unsigned int len = decodeSize(data, xe);
338510234Syasuko.eckert@amd.com    if (outlen) *outlen = len;
338610152Satgutier@umich.edu    if (!len) return NULL;
338710234Syasuko.eckert@amd.com    alloc(len + 1);
338810234Syasuko.eckert@amd.com    if (!decode(data, (unsigned char*)buf, len, xe)) {
338910234Syasuko.eckert@amd.com        return NULL;
339010234Syasuko.eckert@amd.com    }
339110152Satgutier@umich.edu    return (unsigned char*)buf;
339210152Satgutier@umich.edu}
339310152Satgutier@umich.edu
3394