xmlParser.cc revision 10152
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 7810152Satgutier@umich.edu * <a href="http://www.Business-Insight.com">Business-Insight</a> 7910152Satgutier@umich.edu * All rights reserved. 8010152Satgutier@umich.edu * 8110152Satgutier@umich.edu **************************************************************************** 8210152Satgutier@umich.edu */ 8310152Satgutier@umich.edu#ifndef _CRT_SECURE_NO_DEPRECATE 8410152Satgutier@umich.edu#define _CRT_SECURE_NO_DEPRECATE 8510152Satgutier@umich.edu#endif 8610152Satgutier@umich.edu#include "xmlParser.h" 8710152Satgutier@umich.edu#ifdef _XMLWINDOWS 8810152Satgutier@umich.edu//#ifdef _DEBUG 8910152Satgutier@umich.edu//#define _CRTDBG_MAP_ALLOC 9010152Satgutier@umich.edu//#include <crtdbg.h> 9110152Satgutier@umich.edu//#endif 9210152Satgutier@umich.edu#define WIN32_LEAN_AND_MEAN 9310152Satgutier@umich.edu#include <Windows.h> // to have IsTextUnicode, MultiByteToWideChar, WideCharToMultiByte to handle unicode files 9410152Satgutier@umich.edu // to have "MessageBoxA" to display error messages for openFilHelper 9510152Satgutier@umich.edu#endif 9610152Satgutier@umich.edu 9710152Satgutier@umich.edu#include <memory.h> 9810152Satgutier@umich.edu 9910152Satgutier@umich.edu#include <cassert> 10010152Satgutier@umich.edu#include <cstdio> 10110152Satgutier@umich.edu#include <cstdlib> 10210152Satgutier@umich.edu#include <cstring> 10310152Satgutier@umich.edu 10410152Satgutier@umich.eduXMLCSTR XMLNode::getVersion() { return _CXML("v2.39"); } 10510152Satgutier@umich.eduvoid freeXMLString(XMLSTR t){if(t)free(t);} 10610152Satgutier@umich.edu 10710152Satgutier@umich.edustatic XMLNode::XMLCharEncoding characterEncoding=XMLNode::char_encoding_UTF8; 10810152Satgutier@umich.edustatic char guessWideCharChars=1, dropWhiteSpace=1, removeCommentsInMiddleOfText=1; 10910152Satgutier@umich.edu 11010152Satgutier@umich.eduinline int mmin( const int t1, const int t2 ) { return t1 < t2 ? t1 : t2; } 11110152Satgutier@umich.edu 11210152Satgutier@umich.edu// You can modify the initialization of the variable "XMLClearTags" below 11310152Satgutier@umich.edu// to change the clearTags that are currently recognized by the library. 11410152Satgutier@umich.edu// The number on the second columns is the length of the string inside the 11510152Satgutier@umich.edu// first column. The "<!DOCTYPE" declaration must be the second in the list. 11610152Satgutier@umich.edu// The "<!--" declaration must be the third in the list. 11710152Satgutier@umich.edutypedef struct { XMLCSTR lpszOpen; int openTagLen; XMLCSTR lpszClose;} ALLXMLClearTag; 11810152Satgutier@umich.edustatic ALLXMLClearTag XMLClearTags[] = 11910152Satgutier@umich.edu{ 12010152Satgutier@umich.edu { _CXML("<![CDATA["),9, _CXML("]]>") }, 12110152Satgutier@umich.edu { _CXML("<!DOCTYPE"),9, _CXML(">") }, 12210152Satgutier@umich.edu { _CXML("<!--") ,4, _CXML("-->") }, 12310152Satgutier@umich.edu { _CXML("<PRE>") ,5, _CXML("</PRE>") }, 12410152Satgutier@umich.edu// { _CXML("<Script>") ,8, _CXML("</Script>")}, 12510152Satgutier@umich.edu { NULL ,0, NULL } 12610152Satgutier@umich.edu}; 12710152Satgutier@umich.edu 12810152Satgutier@umich.edu// You can modify the initialization of the variable "XMLEntities" below 12910152Satgutier@umich.edu// to change the character entities that are currently recognized by the library. 13010152Satgutier@umich.edu// The number on the second columns is the length of the string inside the 13110152Satgutier@umich.edu// first column. Additionally, the syntaxes " " and " " are recognized. 13210152Satgutier@umich.edutypedef struct { XMLCSTR s; int l; XMLCHAR c;} XMLCharacterEntity; 13310152Satgutier@umich.edustatic XMLCharacterEntity XMLEntities[] = 13410152Satgutier@umich.edu{ 13510152Satgutier@umich.edu { _CXML("&" ), 5, _CXML('&' )}, 13610152Satgutier@umich.edu { _CXML("<" ), 4, _CXML('<' )}, 13710152Satgutier@umich.edu { _CXML(">" ), 4, _CXML('>' )}, 13810152Satgutier@umich.edu { _CXML("""), 6, _CXML('\"')}, 13910152Satgutier@umich.edu { _CXML("'"), 6, _CXML('\'')}, 14010152Satgutier@umich.edu { NULL , 0, '\0' } 14110152Satgutier@umich.edu}; 14210152Satgutier@umich.edu 14310152Satgutier@umich.edu// When rendering the XMLNode to a string (using the "createXMLString" function), 14410152Satgutier@umich.edu// you can ask for a beautiful formatting. This formatting is using the 14510152Satgutier@umich.edu// following indentation character: 14610152Satgutier@umich.edu#define INDENTCHAR _CXML('\t') 14710152Satgutier@umich.edu 14810152Satgutier@umich.edu// The following function parses the XML errors into a user friendly string. 14910152Satgutier@umich.edu// You can edit this to change the output language of the library to something else. 15010152Satgutier@umich.eduXMLCSTR XMLNode::getError(XMLError xerror) 15110152Satgutier@umich.edu{ 15210152Satgutier@umich.edu switch (xerror) 15310152Satgutier@umich.edu { 15410152Satgutier@umich.edu case eXMLErrorNone: return _CXML("No error"); 15510152Satgutier@umich.edu case eXMLErrorMissingEndTag: return _CXML("Warning: Unmatched end tag"); 15610152Satgutier@umich.edu case eXMLErrorNoXMLTagFound: return _CXML("Warning: No XML tag found"); 15710152Satgutier@umich.edu case eXMLErrorEmpty: return _CXML("Error: No XML data"); 15810152Satgutier@umich.edu case eXMLErrorMissingTagName: return _CXML("Error: Missing start tag name"); 15910152Satgutier@umich.edu case eXMLErrorMissingEndTagName: return _CXML("Error: Missing end tag name"); 16010152Satgutier@umich.edu case eXMLErrorUnmatchedEndTag: return _CXML("Error: Unmatched end tag"); 16110152Satgutier@umich.edu case eXMLErrorUnmatchedEndClearTag: return _CXML("Error: Unmatched clear tag end"); 16210152Satgutier@umich.edu case eXMLErrorUnexpectedToken: return _CXML("Error: Unexpected token found"); 16310152Satgutier@umich.edu case eXMLErrorNoElements: return _CXML("Error: No elements found"); 16410152Satgutier@umich.edu case eXMLErrorFileNotFound: return _CXML("Error: File not found"); 16510152Satgutier@umich.edu case eXMLErrorFirstTagNotFound: return _CXML("Error: First Tag not found"); 16610152Satgutier@umich.edu case eXMLErrorUnknownCharacterEntity:return _CXML("Error: Unknown character entity"); 16710152Satgutier@umich.edu case eXMLErrorCharacterCodeAbove255: return _CXML("Error: Character code above 255 is forbidden in MultiByte char mode."); 16810152Satgutier@umich.edu case eXMLErrorCharConversionError: return _CXML("Error: unable to convert between WideChar and MultiByte chars"); 16910152Satgutier@umich.edu case eXMLErrorCannotOpenWriteFile: return _CXML("Error: unable to open file for writing"); 17010152Satgutier@umich.edu case eXMLErrorCannotWriteFile: return _CXML("Error: cannot write into file"); 17110152Satgutier@umich.edu 17210152Satgutier@umich.edu case eXMLErrorBase64DataSizeIsNotMultipleOf4: return _CXML("Warning: Base64-string length is not a multiple of 4"); 17310152Satgutier@umich.edu case eXMLErrorBase64DecodeTruncatedData: return _CXML("Warning: Base64-string is truncated"); 17410152Satgutier@umich.edu case eXMLErrorBase64DecodeIllegalCharacter: return _CXML("Error: Base64-string contains an illegal character"); 17510152Satgutier@umich.edu case eXMLErrorBase64DecodeBufferTooSmall: return _CXML("Error: Base64 decode output buffer is too small"); 17610152Satgutier@umich.edu }; 17710152Satgutier@umich.edu return _CXML("Unknown"); 17810152Satgutier@umich.edu} 17910152Satgutier@umich.edu 18010152Satgutier@umich.edu///////////////////////////////////////////////////////////////////////// 18110152Satgutier@umich.edu// Here start the abstraction layer to be OS-independent // 18210152Satgutier@umich.edu///////////////////////////////////////////////////////////////////////// 18310152Satgutier@umich.edu 18410152Satgutier@umich.edu// Here is an abstraction layer to access some common string manipulation functions. 18510152Satgutier@umich.edu// The abstraction layer is currently working for gcc, Microsoft Visual Studio 6.0, 18610152Satgutier@umich.edu// Microsoft Visual Studio .NET, CC (sun compiler) and Borland C++. 18710152Satgutier@umich.edu// If you plan to "port" the library to a new system/compiler, all you have to do is 18810152Satgutier@umich.edu// to edit the following lines. 18910152Satgutier@umich.edu#ifdef XML_NO_WIDE_CHAR 19010152Satgutier@umich.educhar myIsTextWideChar(const void *b, int len) { return FALSE; } 19110152Satgutier@umich.edu#else 19210152Satgutier@umich.edu #if defined (UNDER_CE) || !defined(_XMLWINDOWS) 19310152Satgutier@umich.edu char myIsTextWideChar(const void *b, int len) // inspired by the Wine API: RtlIsTextUnicode 19410152Satgutier@umich.edu { 19510152Satgutier@umich.edu#ifdef sun 19610152Satgutier@umich.edu // for SPARC processors: wchar_t* buffers must always be alligned, otherwise it's a char* buffer. 19710152Satgutier@umich.edu if ((((unsigned long)b)%sizeof(wchar_t))!=0) return FALSE; 19810152Satgutier@umich.edu#endif 19910152Satgutier@umich.edu const wchar_t *s=(const wchar_t*)b; 20010152Satgutier@umich.edu 20110152Satgutier@umich.edu // buffer too small: 20210152Satgutier@umich.edu if (len<(int)sizeof(wchar_t)) return FALSE; 20310152Satgutier@umich.edu 20410152Satgutier@umich.edu // odd length test 20510152Satgutier@umich.edu if (len&1) return FALSE; 20610152Satgutier@umich.edu 20710152Satgutier@umich.edu /* only checks the first 256 characters */ 20810152Satgutier@umich.edu len=mmin(256,len/sizeof(wchar_t)); 20910152Satgutier@umich.edu 21010152Satgutier@umich.edu // Check for the special byte order: 21110152Satgutier@umich.edu if (*((unsigned short*)s) == 0xFFFE) return TRUE; // IS_TEXT_UNICODE_REVERSE_SIGNATURE; 21210152Satgutier@umich.edu if (*((unsigned short*)s) == 0xFEFF) return TRUE; // IS_TEXT_UNICODE_SIGNATURE 21310152Satgutier@umich.edu 21410152Satgutier@umich.edu // checks for ASCII characters in the UNICODE stream 21510152Satgutier@umich.edu int i,stats=0; 21610152Satgutier@umich.edu for (i=0; i<len; i++) if (s[i]<=(unsigned short)255) stats++; 21710152Satgutier@umich.edu if (stats>len/2) return TRUE; 21810152Satgutier@umich.edu 21910152Satgutier@umich.edu // Check for UNICODE NULL chars 22010152Satgutier@umich.edu for (i=0; i<len; i++) if (!s[i]) return TRUE; 22110152Satgutier@umich.edu 22210152Satgutier@umich.edu return FALSE; 22310152Satgutier@umich.edu } 22410152Satgutier@umich.edu #else 22510152Satgutier@umich.edu char myIsTextWideChar(const void *b,int l) { return (char)IsTextUnicode((CONST LPVOID)b,l,NULL); }; 22610152Satgutier@umich.edu #endif 22710152Satgutier@umich.edu#endif 22810152Satgutier@umich.edu 22910152Satgutier@umich.edu#ifdef _XMLWINDOWS 23010152Satgutier@umich.edu// for Microsoft Visual Studio 6.0 and Microsoft Visual Studio .NET and Borland C++ Builder 6.0 23110152Satgutier@umich.edu #ifdef _XMLWIDECHAR 23210152Satgutier@umich.edu wchar_t *myMultiByteToWideChar(const char *s, XMLNode::XMLCharEncoding ce) 23310152Satgutier@umich.edu { 23410152Satgutier@umich.edu int i; 23510152Satgutier@umich.edu if (ce==XMLNode::char_encoding_UTF8) i=(int)MultiByteToWideChar(CP_UTF8,0 ,s,-1,NULL,0); 23610152Satgutier@umich.edu else i=(int)MultiByteToWideChar(CP_ACP ,MB_PRECOMPOSED,s,-1,NULL,0); 23710152Satgutier@umich.edu if (i<0) return NULL; 23810152Satgutier@umich.edu wchar_t *d=(wchar_t *)malloc((i+1)*sizeof(XMLCHAR)); 23910152Satgutier@umich.edu if (ce==XMLNode::char_encoding_UTF8) i=(int)MultiByteToWideChar(CP_UTF8,0 ,s,-1,d,i); 24010152Satgutier@umich.edu else i=(int)MultiByteToWideChar(CP_ACP ,MB_PRECOMPOSED,s,-1,d,i); 24110152Satgutier@umich.edu d[i]=0; 24210152Satgutier@umich.edu return d; 24310152Satgutier@umich.edu } 24410152Satgutier@umich.edu static inline FILE *xfopen(XMLCSTR filename,XMLCSTR mode) { return _wfopen(filename,mode); } 24510152Satgutier@umich.edu static inline int xstrlen(XMLCSTR c) { return (int)wcslen(c); } 24610152Satgutier@umich.edu static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return _wcsnicmp(c1,c2,l);} 24710152Satgutier@umich.edu static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return wcsncmp(c1,c2,l);} 24810152Satgutier@umich.edu static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return _wcsicmp(c1,c2); } 24910152Satgutier@umich.edu static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)wcsstr(c1,c2); } 25010152Satgutier@umich.edu static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) { return (XMLSTR)wcscpy(c1,c2); } 25110152Satgutier@umich.edu #else 25210152Satgutier@umich.edu char *myWideCharToMultiByte(const wchar_t *s) 25310152Satgutier@umich.edu { 25410152Satgutier@umich.edu UINT codePage=CP_ACP; if (characterEncoding==XMLNode::char_encoding_UTF8) codePage=CP_UTF8; 25510152Satgutier@umich.edu int i=(int)WideCharToMultiByte(codePage, // code page 25610152Satgutier@umich.edu 0, // performance and mapping flags 25710152Satgutier@umich.edu s, // wide-character string 25810152Satgutier@umich.edu -1, // number of chars in string 25910152Satgutier@umich.edu NULL, // buffer for new string 26010152Satgutier@umich.edu 0, // size of buffer 26110152Satgutier@umich.edu NULL, // default for unmappable chars 26210152Satgutier@umich.edu NULL // set when default char used 26310152Satgutier@umich.edu ); 26410152Satgutier@umich.edu if (i<0) return NULL; 26510152Satgutier@umich.edu char *d=(char*)malloc(i+1); 26610152Satgutier@umich.edu WideCharToMultiByte(codePage, // code page 26710152Satgutier@umich.edu 0, // performance and mapping flags 26810152Satgutier@umich.edu s, // wide-character string 26910152Satgutier@umich.edu -1, // number of chars in string 27010152Satgutier@umich.edu d, // buffer for new string 27110152Satgutier@umich.edu i, // size of buffer 27210152Satgutier@umich.edu NULL, // default for unmappable chars 27310152Satgutier@umich.edu NULL // set when default char used 27410152Satgutier@umich.edu ); 27510152Satgutier@umich.edu d[i]=0; 27610152Satgutier@umich.edu return d; 27710152Satgutier@umich.edu } 27810152Satgutier@umich.edu static inline FILE *xfopen(XMLCSTR filename,XMLCSTR mode) { return fopen(filename,mode); } 27910152Satgutier@umich.edu static inline int xstrlen(XMLCSTR c) { return (int)strlen(c); } 28010152Satgutier@umich.edu #ifdef __BORLANDC__ 28110152Satgutier@umich.edu static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return strnicmp(c1,c2,l);} 28210152Satgutier@umich.edu static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return stricmp(c1,c2); } 28310152Satgutier@umich.edu #else 28410152Satgutier@umich.edu static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return _strnicmp(c1,c2,l);} 28510152Satgutier@umich.edu static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return _stricmp(c1,c2); } 28610152Satgutier@umich.edu #endif 28710152Satgutier@umich.edu static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return strncmp(c1,c2,l);} 28810152Satgutier@umich.edu static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)strstr(c1,c2); } 28910152Satgutier@umich.edu static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) { return (XMLSTR)strcpy(c1,c2); } 29010152Satgutier@umich.edu #endif 29110152Satgutier@umich.edu#else 29210152Satgutier@umich.edu// for gcc and CC 29310152Satgutier@umich.edu #ifdef XML_NO_WIDE_CHAR 29410152Satgutier@umich.edu char *myWideCharToMultiByte(const wchar_t *s) { return NULL; } 29510152Satgutier@umich.edu #else 29610152Satgutier@umich.edu char *myWideCharToMultiByte(const wchar_t *s) 29710152Satgutier@umich.edu { 29810152Satgutier@umich.edu const wchar_t *ss=s; 29910152Satgutier@umich.edu int i=(int)wcsrtombs(NULL,&ss,0,NULL); 30010152Satgutier@umich.edu if (i<0) return NULL; 30110152Satgutier@umich.edu char *d=(char *)malloc(i+1); 30210152Satgutier@umich.edu wcsrtombs(d,&s,i,NULL); 30310152Satgutier@umich.edu d[i]=0; 30410152Satgutier@umich.edu return d; 30510152Satgutier@umich.edu } 30610152Satgutier@umich.edu #endif 30710152Satgutier@umich.edu #ifdef _XMLWIDECHAR 30810152Satgutier@umich.edu wchar_t *myMultiByteToWideChar(const char *s, XMLNode::XMLCharEncoding ce) 30910152Satgutier@umich.edu { 31010152Satgutier@umich.edu const char *ss=s; 31110152Satgutier@umich.edu int i=(int)mbsrtowcs(NULL,&ss,0,NULL); 31210152Satgutier@umich.edu if (i<0) return NULL; 31310152Satgutier@umich.edu wchar_t *d=(wchar_t *)malloc((i+1)*sizeof(wchar_t)); 31410152Satgutier@umich.edu mbsrtowcs(d,&s,i,NULL); 31510152Satgutier@umich.edu d[i]=0; 31610152Satgutier@umich.edu return d; 31710152Satgutier@umich.edu } 31810152Satgutier@umich.edu int xstrlen(XMLCSTR c) { return wcslen(c); } 31910152Satgutier@umich.edu #ifdef sun 32010152Satgutier@umich.edu // for CC 32110152Satgutier@umich.edu #include <widec.h> 32210152Satgutier@umich.edu static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return wsncasecmp(c1,c2,l);} 32310152Satgutier@umich.edu static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return wsncmp(c1,c2,l);} 32410152Satgutier@umich.edu static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return wscasecmp(c1,c2); } 32510152Satgutier@umich.edu #else 32610152Satgutier@umich.edu // for gcc 32710152Satgutier@umich.edu static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return wcsncasecmp(c1,c2,l);} 32810152Satgutier@umich.edu static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return wcsncmp(c1,c2,l);} 32910152Satgutier@umich.edu static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return wcscasecmp(c1,c2); } 33010152Satgutier@umich.edu #endif 33110152Satgutier@umich.edu static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)wcsstr(c1,c2); } 33210152Satgutier@umich.edu static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) { return (XMLSTR)wcscpy(c1,c2); } 33310152Satgutier@umich.edu static inline FILE *xfopen(XMLCSTR filename,XMLCSTR mode) 33410152Satgutier@umich.edu { 33510152Satgutier@umich.edu char *filenameAscii=myWideCharToMultiByte(filename); 33610152Satgutier@umich.edu FILE *f; 33710152Satgutier@umich.edu if (mode[0]==_CXML('r')) f=fopen(filenameAscii,"rb"); 33810152Satgutier@umich.edu else f=fopen(filenameAscii,"wb"); 33910152Satgutier@umich.edu free(filenameAscii); 34010152Satgutier@umich.edu return f; 34110152Satgutier@umich.edu } 34210152Satgutier@umich.edu #else 34310152Satgutier@umich.edu static inline FILE *xfopen(XMLCSTR filename,XMLCSTR mode) { return fopen(filename,mode); } 34410152Satgutier@umich.edu static inline int xstrlen(XMLCSTR c) { return strlen(c); } 34510152Satgutier@umich.edu static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return strncasecmp(c1,c2,l);} 34610152Satgutier@umich.edu static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return strncmp(c1,c2,l);} 34710152Satgutier@umich.edu static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return strcasecmp(c1,c2); } 34810152Satgutier@umich.edu static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)strstr(c1,c2); } 34910152Satgutier@umich.edu static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) { return (XMLSTR)strcpy(c1,c2); } 35010152Satgutier@umich.edu #endif 35110152Satgutier@umich.edu static inline int _strnicmp(const char *c1,const char *c2, int l) { return strncasecmp(c1,c2,l);} 35210152Satgutier@umich.edu#endif 35310152Satgutier@umich.edu 35410152Satgutier@umich.edu 35510152Satgutier@umich.edu/////////////////////////////////////////////////////////////////////////////// 35610152Satgutier@umich.edu// the "xmltoc,xmltob,xmltoi,xmltol,xmltof,xmltoa" functions // 35710152Satgutier@umich.edu/////////////////////////////////////////////////////////////////////////////// 35810152Satgutier@umich.edu// These 6 functions are not used inside the XMLparser. 35910152Satgutier@umich.edu// There are only here as "convenience" functions for the user. 36010152Satgutier@umich.edu// If you don't need them, you can delete them without any trouble. 36110152Satgutier@umich.edu#ifdef _XMLWIDECHAR 36210152Satgutier@umich.edu #ifdef _XMLWINDOWS 36310152Satgutier@umich.edu // for Microsoft Visual Studio 6.0 and Microsoft Visual Studio .NET and Borland C++ Builder 6.0 36410152Satgutier@umich.edu char xmltob(XMLCSTR t,int v){ if (t&&(*t)) return (char)_wtoi(t); return v; } 36510152Satgutier@umich.edu int xmltoi(XMLCSTR t,int v){ if (t&&(*t)) return _wtoi(t); return v; } 36610152Satgutier@umich.edu long xmltol(XMLCSTR t,long v){ if (t&&(*t)) return _wtol(t); return v; } 36710152Satgutier@umich.edu double xmltof(XMLCSTR t,double v){ if (t&&(*t)) wscanf(t, "%f", &v); /*v=_wtof(t);*/ return v; } 36810152Satgutier@umich.edu #else 36910152Satgutier@umich.edu #ifdef sun 37010152Satgutier@umich.edu // for CC 37110152Satgutier@umich.edu #include <widec.h> 37210152Satgutier@umich.edu char xmltob(XMLCSTR t,int v){ if (t) return (char)wstol(t,NULL,10); return v; } 37310152Satgutier@umich.edu int xmltoi(XMLCSTR t,int v){ if (t) return (int)wstol(t,NULL,10); return v; } 37410152Satgutier@umich.edu long xmltol(XMLCSTR t,long v){ if (t) return wstol(t,NULL,10); return v; } 37510152Satgutier@umich.edu #else 37610152Satgutier@umich.edu // for gcc 37710152Satgutier@umich.edu char xmltob(XMLCSTR t,int v){ if (t) return (char)wcstol(t,NULL,10); return v; } 37810152Satgutier@umich.edu int xmltoi(XMLCSTR t,int v){ if (t) return (int)wcstol(t,NULL,10); return v; } 37910152Satgutier@umich.edu long xmltol(XMLCSTR t,long v){ if (t) return wcstol(t,NULL,10); return v; } 38010152Satgutier@umich.edu #endif 38110152Satgutier@umich.edu double xmltof(XMLCSTR t,double v){ if (t&&(*t)) wscanf(t, "%f", &v); /*v=_wtof(t);*/ return v; } 38210152Satgutier@umich.edu #endif 38310152Satgutier@umich.edu#else 38410152Satgutier@umich.edu char xmltob(XMLCSTR t,char v){ if (t&&(*t)) return (char)atoi(t); return v; } 38510152Satgutier@umich.edu int xmltoi(XMLCSTR t,int v){ if (t&&(*t)) return atoi(t); return v; } 38610152Satgutier@umich.edu long xmltol(XMLCSTR t,long v){ if (t&&(*t)) return atol(t); return v; } 38710152Satgutier@umich.edu double xmltof(XMLCSTR t,double v){ if (t&&(*t)) return atof(t); return v; } 38810152Satgutier@umich.edu#endif 38910152Satgutier@umich.eduXMLCSTR xmltoa(XMLCSTR t,XMLCSTR v){ if (t) return t; return v; } 39010152Satgutier@umich.eduXMLCHAR xmltoc(XMLCSTR t,XMLCHAR v){ if (t&&(*t)) return *t; return v; } 39110152Satgutier@umich.edu 39210152Satgutier@umich.edu///////////////////////////////////////////////////////////////////////// 39310152Satgutier@umich.edu// the "openFileHelper" function // 39410152Satgutier@umich.edu///////////////////////////////////////////////////////////////////////// 39510152Satgutier@umich.edu 39610152Satgutier@umich.edu// Since each application has its own way to report and deal with errors, you should modify & rewrite 39710152Satgutier@umich.edu// the following "openFileHelper" function to get an "error reporting mechanism" tailored to your needs. 39810152Satgutier@umich.eduXMLNode XMLNode::openFileHelper(XMLCSTR filename, XMLCSTR tag) 39910152Satgutier@umich.edu{ 40010152Satgutier@umich.edu // guess the value of the global parameter "characterEncoding" 40110152Satgutier@umich.edu // (the guess is based on the first 200 bytes of the file). 40210152Satgutier@umich.edu FILE *f=xfopen(filename,_CXML("rb")); 40310152Satgutier@umich.edu if (f) 40410152Satgutier@umich.edu { 40510152Satgutier@umich.edu char bb[205]; 40610152Satgutier@umich.edu int l=(int)fread(bb,1,200,f); 40710152Satgutier@umich.edu setGlobalOptions(guessCharEncoding(bb,l),guessWideCharChars,dropWhiteSpace,removeCommentsInMiddleOfText); 40810152Satgutier@umich.edu fclose(f); 40910152Satgutier@umich.edu } 41010152Satgutier@umich.edu 41110152Satgutier@umich.edu // parse the file 41210152Satgutier@umich.edu XMLResults pResults; 41310152Satgutier@umich.edu XMLNode xnode=XMLNode::parseFile(filename,tag,&pResults); 41410152Satgutier@umich.edu 41510152Satgutier@umich.edu // display error message (if any) 41610152Satgutier@umich.edu if (pResults.error != eXMLErrorNone) 41710152Satgutier@umich.edu { 41810152Satgutier@umich.edu // create message 41910152Satgutier@umich.edu char message[2000],*s1=(char*)"",*s3=(char*)""; XMLCSTR s2=_CXML(""); 42010152Satgutier@umich.edu if (pResults.error==eXMLErrorFirstTagNotFound) { s1=(char*)"First Tag should be '"; s2=tag; s3=(char*)"'.\n"; } 42110152Satgutier@umich.edu sprintf(message, 42210152Satgutier@umich.edu#ifdef _XMLWIDECHAR 42310152Satgutier@umich.edu "XML Parsing error inside file '%S'.\n%S\nAt line %i, column %i.\n%s%S%s" 42410152Satgutier@umich.edu#else 42510152Satgutier@umich.edu "XML Parsing error inside file '%s'.\n%s\nAt line %i, column %i.\n%s%s%s" 42610152Satgutier@umich.edu#endif 42710152Satgutier@umich.edu ,filename,XMLNode::getError(pResults.error),pResults.nLine,pResults.nColumn,s1,s2,s3); 42810152Satgutier@umich.edu 42910152Satgutier@umich.edu // display message 43010152Satgutier@umich.edu#if defined(_XMLWINDOWS) && !defined(UNDER_CE) && !defined(_XMLPARSER_NO_MESSAGEBOX_) 43110152Satgutier@umich.edu MessageBoxA(NULL,message,"XML Parsing error",MB_OK|MB_ICONERROR|MB_TOPMOST); 43210152Satgutier@umich.edu#else 43310152Satgutier@umich.edu printf("%s",message); 43410152Satgutier@umich.edu#endif 43510152Satgutier@umich.edu exit(255); 43610152Satgutier@umich.edu } 43710152Satgutier@umich.edu return xnode; 43810152Satgutier@umich.edu} 43910152Satgutier@umich.edu 44010152Satgutier@umich.edu///////////////////////////////////////////////////////////////////////// 44110152Satgutier@umich.edu// Here start the core implementation of the XMLParser library // 44210152Satgutier@umich.edu///////////////////////////////////////////////////////////////////////// 44310152Satgutier@umich.edu 44410152Satgutier@umich.edu// You should normally not change anything below this point. 44510152Satgutier@umich.edu 44610152Satgutier@umich.edu#ifndef _XMLWIDECHAR 44710152Satgutier@umich.edu// If "characterEncoding=ascii" then we assume that all characters have the same length of 1 byte. 44810152Satgutier@umich.edu// If "characterEncoding=UTF8" then the characters have different lengths (from 1 byte to 4 bytes). 44910152Satgutier@umich.edu// If "characterEncoding=ShiftJIS" then the characters have different lengths (from 1 byte to 2 bytes). 45010152Satgutier@umich.edu// This table is used as lookup-table to know the length of a character (in byte) based on the 45110152Satgutier@umich.edu// content of the first byte of the character. 45210152Satgutier@umich.edu// (note: if you modify this, you must always have XML_utf8ByteTable[0]=0 ). 45310152Satgutier@umich.edustatic const char XML_utf8ByteTable[256] = 45410152Satgutier@umich.edu{ 45510152Satgutier@umich.edu // 0 1 2 3 4 5 6 7 8 9 a b c d e f 45610152Satgutier@umich.edu 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00 45710152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10 45810152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20 45910152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30 46010152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40 46110152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50 46210152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60 46310152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70 End of ASCII range 46410152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x80 0x80 to 0xc1 invalid 46510152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x90 46610152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xa0 46710152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xb0 46810152Satgutier@umich.edu 1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xc0 0xc2 to 0xdf 2 byte 46910152Satgutier@umich.edu 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xd0 47010152Satgutier@umich.edu 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,// 0xe0 0xe0 to 0xef 3 byte 47110152Satgutier@umich.edu 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 47210152Satgutier@umich.edu}; 47310152Satgutier@umich.edustatic const char XML_legacyByteTable[256] = 47410152Satgutier@umich.edu{ 47510152Satgutier@umich.edu 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, 47610152Satgutier@umich.edu 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, 47710152Satgutier@umich.edu 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, 47810152Satgutier@umich.edu 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, 47910152Satgutier@umich.edu 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, 48010152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 48110152Satgutier@umich.edu}; 48210152Satgutier@umich.edustatic const char XML_sjisByteTable[256] = 48310152Satgutier@umich.edu{ 48410152Satgutier@umich.edu // 0 1 2 3 4 5 6 7 8 9 a b c d e f 48510152Satgutier@umich.edu 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00 48610152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10 48710152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20 48810152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30 48910152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40 49010152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50 49110152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60 49210152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70 49310152Satgutier@umich.edu 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0x80 0x81 to 0x9F 2 bytes 49410152Satgutier@umich.edu 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0x90 49510152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xa0 49610152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xb0 49710152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xc0 49810152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xd0 49910152Satgutier@umich.edu 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xe0 0xe0 to 0xef 2 bytes 50010152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 // 0xf0 50110152Satgutier@umich.edu}; 50210152Satgutier@umich.edustatic const char XML_gb2312ByteTable[256] = 50310152Satgutier@umich.edu{ 50410152Satgutier@umich.edu// 0 1 2 3 4 5 6 7 8 9 a b c d e f 50510152Satgutier@umich.edu 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00 50610152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10 50710152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20 50810152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30 50910152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40 51010152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50 51110152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60 51210152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70 51310152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x80 51410152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x90 51510152Satgutier@umich.edu 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xa0 0xa1 to 0xf7 2 bytes 51610152Satgutier@umich.edu 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xb0 51710152Satgutier@umich.edu 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xc0 51810152Satgutier@umich.edu 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xd0 51910152Satgutier@umich.edu 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xe0 52010152Satgutier@umich.edu 2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1 // 0xf0 52110152Satgutier@umich.edu}; 52210152Satgutier@umich.edustatic const char XML_gbk_big5_ByteTable[256] = 52310152Satgutier@umich.edu{ 52410152Satgutier@umich.edu // 0 1 2 3 4 5 6 7 8 9 a b c d e f 52510152Satgutier@umich.edu 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00 52610152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10 52710152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20 52810152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30 52910152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40 53010152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50 53110152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60 53210152Satgutier@umich.edu 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70 53310152Satgutier@umich.edu 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0x80 0x81 to 0xfe 2 bytes 53410152Satgutier@umich.edu 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0x90 53510152Satgutier@umich.edu 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xa0 53610152Satgutier@umich.edu 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xb0 53710152Satgutier@umich.edu 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xc0 53810152Satgutier@umich.edu 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xd0 53910152Satgutier@umich.edu 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xe0 54010152Satgutier@umich.edu 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1 // 0xf0 54110152Satgutier@umich.edu}; 54210152Satgutier@umich.edustatic const char *XML_ByteTable=(const char *)XML_utf8ByteTable; // the default is "characterEncoding=XMLNode::encoding_UTF8" 54310152Satgutier@umich.edu#endif 54410152Satgutier@umich.edu 54510152Satgutier@umich.edu 54610152Satgutier@umich.eduXMLNode XMLNode::emptyXMLNode; 54710152Satgutier@umich.eduXMLClear XMLNode::emptyXMLClear={ NULL, NULL, NULL}; 54810152Satgutier@umich.eduXMLAttribute XMLNode::emptyXMLAttribute={ NULL, NULL}; 54910152Satgutier@umich.edu 55010152Satgutier@umich.edu// Enumeration used to decipher what type a token is 55110152Satgutier@umich.edutypedef enum XMLTokenTypeTag 55210152Satgutier@umich.edu{ 55310152Satgutier@umich.edu eTokenText = 0, 55410152Satgutier@umich.edu eTokenQuotedText, 55510152Satgutier@umich.edu eTokenTagStart, /* "<" */ 55610152Satgutier@umich.edu eTokenTagEnd, /* "</" */ 55710152Satgutier@umich.edu eTokenCloseTag, /* ">" */ 55810152Satgutier@umich.edu eTokenEquals, /* "=" */ 55910152Satgutier@umich.edu eTokenDeclaration, /* "<?" */ 56010152Satgutier@umich.edu eTokenShortHandClose, /* "/>" */ 56110152Satgutier@umich.edu eTokenClear, 56210152Satgutier@umich.edu eTokenError 56310152Satgutier@umich.edu} XMLTokenType; 56410152Satgutier@umich.edu 56510152Satgutier@umich.edu// Main structure used for parsing XML 56610152Satgutier@umich.edutypedef struct XML 56710152Satgutier@umich.edu{ 56810152Satgutier@umich.edu XMLCSTR lpXML; 56910152Satgutier@umich.edu XMLCSTR lpszText; 57010152Satgutier@umich.edu int nIndex,nIndexMissigEndTag; 57110152Satgutier@umich.edu enum XMLError error; 57210152Satgutier@umich.edu XMLCSTR lpEndTag; 57310152Satgutier@umich.edu int cbEndTag; 57410152Satgutier@umich.edu XMLCSTR lpNewElement; 57510152Satgutier@umich.edu int cbNewElement; 57610152Satgutier@umich.edu int nFirst; 57710152Satgutier@umich.edu} XML; 57810152Satgutier@umich.edu 57910152Satgutier@umich.edutypedef struct 58010152Satgutier@umich.edu{ 58110152Satgutier@umich.edu ALLXMLClearTag *pClr; 58210152Satgutier@umich.edu XMLCSTR pStr; 58310152Satgutier@umich.edu} NextToken; 58410152Satgutier@umich.edu 58510152Satgutier@umich.edu// Enumeration used when parsing attributes 58610152Satgutier@umich.edutypedef enum Attrib 58710152Satgutier@umich.edu{ 58810152Satgutier@umich.edu eAttribName = 0, 58910152Satgutier@umich.edu eAttribEquals, 59010152Satgutier@umich.edu eAttribValue 59110152Satgutier@umich.edu} Attrib; 59210152Satgutier@umich.edu 59310152Satgutier@umich.edu// Enumeration used when parsing elements to dictate whether we are currently 59410152Satgutier@umich.edu// inside a tag 59510152Satgutier@umich.edutypedef enum Status 59610152Satgutier@umich.edu{ 59710152Satgutier@umich.edu eInsideTag = 0, 59810152Satgutier@umich.edu eOutsideTag 59910152Satgutier@umich.edu} Status; 60010152Satgutier@umich.edu 60110152Satgutier@umich.eduXMLError XMLNode::writeToFile(XMLCSTR filename, const char *encoding, char nFormat) const 60210152Satgutier@umich.edu{ 60310152Satgutier@umich.edu if (!d) return eXMLErrorNone; 60410152Satgutier@umich.edu FILE *f=xfopen(filename,_CXML("wb")); 60510152Satgutier@umich.edu if (!f) return eXMLErrorCannotOpenWriteFile; 60610152Satgutier@umich.edu#ifdef _XMLWIDECHAR 60710152Satgutier@umich.edu unsigned char h[2]={ 0xFF, 0xFE }; 60810152Satgutier@umich.edu if (!fwrite(h,2,1,f)) return eXMLErrorCannotWriteFile; 60910152Satgutier@umich.edu if ((!isDeclaration())&&((d->lpszName)||(!getChildNode().isDeclaration()))) 61010152Satgutier@umich.edu { 61110152Satgutier@umich.edu if (!fwrite(L"<?xml version=\"1.0\" encoding=\"utf-16\"?>\n",sizeof(wchar_t)*40,1,f)) 61210152Satgutier@umich.edu return eXMLErrorCannotWriteFile; 61310152Satgutier@umich.edu } 61410152Satgutier@umich.edu#else 61510152Satgutier@umich.edu if ((!isDeclaration())&&((d->lpszName)||(!getChildNode().isDeclaration()))) 61610152Satgutier@umich.edu { 61710152Satgutier@umich.edu if (characterEncoding==char_encoding_UTF8) 61810152Satgutier@umich.edu { 61910152Satgutier@umich.edu // header so that windows recognize the file as UTF-8: 62010152Satgutier@umich.edu unsigned char h[3]={0xEF,0xBB,0xBF}; if (!fwrite(h,3,1,f)) return eXMLErrorCannotWriteFile; 62110152Satgutier@umich.edu encoding="utf-8"; 62210152Satgutier@umich.edu } else if (characterEncoding==char_encoding_ShiftJIS) encoding="SHIFT-JIS"; 62310152Satgutier@umich.edu 62410152Satgutier@umich.edu if (!encoding) encoding="ISO-8859-1"; 62510152Satgutier@umich.edu if (fprintf(f,"<?xml version=\"1.0\" encoding=\"%s\"?>\n",encoding)<0) return eXMLErrorCannotWriteFile; 62610152Satgutier@umich.edu } else 62710152Satgutier@umich.edu { 62810152Satgutier@umich.edu if (characterEncoding==char_encoding_UTF8) 62910152Satgutier@umich.edu { 63010152Satgutier@umich.edu unsigned char h[3]={0xEF,0xBB,0xBF}; if (!fwrite(h,3,1,f)) return eXMLErrorCannotWriteFile; 63110152Satgutier@umich.edu } 63210152Satgutier@umich.edu } 63310152Satgutier@umich.edu#endif 63410152Satgutier@umich.edu int i; 63510152Satgutier@umich.edu XMLSTR t=createXMLString(nFormat,&i); 63610152Satgutier@umich.edu if (!fwrite(t,sizeof(XMLCHAR)*i,1,f)) return eXMLErrorCannotWriteFile; 63710152Satgutier@umich.edu if (fclose(f)!=0) return eXMLErrorCannotWriteFile; 63810152Satgutier@umich.edu free(t); 63910152Satgutier@umich.edu return eXMLErrorNone; 64010152Satgutier@umich.edu} 64110152Satgutier@umich.edu 64210152Satgutier@umich.edu// Duplicate a given string. 64310152Satgutier@umich.eduXMLSTR stringDup(XMLCSTR lpszData, int cbData) 64410152Satgutier@umich.edu{ 64510152Satgutier@umich.edu if (lpszData==NULL) return NULL; 64610152Satgutier@umich.edu 64710152Satgutier@umich.edu XMLSTR lpszNew; 64810152Satgutier@umich.edu if (cbData==-1) cbData=(int)xstrlen(lpszData); 64910152Satgutier@umich.edu lpszNew = (XMLSTR)malloc((cbData+1) * sizeof(XMLCHAR)); 65010152Satgutier@umich.edu if (lpszNew) 65110152Satgutier@umich.edu { 65210152Satgutier@umich.edu memcpy(lpszNew, lpszData, (cbData) * sizeof(XMLCHAR)); 65310152Satgutier@umich.edu lpszNew[cbData] = (XMLCHAR)NULL; 65410152Satgutier@umich.edu } 65510152Satgutier@umich.edu return lpszNew; 65610152Satgutier@umich.edu} 65710152Satgutier@umich.edu 65810152Satgutier@umich.eduXMLSTR ToXMLStringTool::toXMLUnSafe(XMLSTR dest,XMLCSTR source) 65910152Satgutier@umich.edu{ 66010152Satgutier@umich.edu XMLSTR dd=dest; 66110152Satgutier@umich.edu XMLCHAR ch; 66210152Satgutier@umich.edu XMLCharacterEntity *entity; 66310152Satgutier@umich.edu while ((ch=*source)) 66410152Satgutier@umich.edu { 66510152Satgutier@umich.edu entity=XMLEntities; 66610152Satgutier@umich.edu do 66710152Satgutier@umich.edu { 66810152Satgutier@umich.edu if (ch==entity->c) {xstrcpy(dest,entity->s); dest+=entity->l; source++; goto out_of_loop1; } 66910152Satgutier@umich.edu entity++; 67010152Satgutier@umich.edu } while(entity->s); 67110152Satgutier@umich.edu#ifdef _XMLWIDECHAR 67210152Satgutier@umich.edu *(dest++)=*(source++); 67310152Satgutier@umich.edu#else 67410152Satgutier@umich.edu switch(XML_ByteTable[(unsigned char)ch]) 67510152Satgutier@umich.edu { 67610152Satgutier@umich.edu case 4: *(dest++)=*(source++); 67710152Satgutier@umich.edu case 3: *(dest++)=*(source++); 67810152Satgutier@umich.edu case 2: *(dest++)=*(source++); 67910152Satgutier@umich.edu case 1: *(dest++)=*(source++); 68010152Satgutier@umich.edu } 68110152Satgutier@umich.edu#endif 68210152Satgutier@umich.eduout_of_loop1: 68310152Satgutier@umich.edu ; 68410152Satgutier@umich.edu } 68510152Satgutier@umich.edu *dest=0; 68610152Satgutier@umich.edu return dd; 68710152Satgutier@umich.edu} 68810152Satgutier@umich.edu 68910152Satgutier@umich.edu// private (used while rendering): 69010152Satgutier@umich.eduint ToXMLStringTool::lengthXMLString(XMLCSTR source) 69110152Satgutier@umich.edu{ 69210152Satgutier@umich.edu int r=0; 69310152Satgutier@umich.edu XMLCharacterEntity *entity; 69410152Satgutier@umich.edu XMLCHAR ch; 69510152Satgutier@umich.edu while ((ch=*source)) 69610152Satgutier@umich.edu { 69710152Satgutier@umich.edu entity=XMLEntities; 69810152Satgutier@umich.edu do 69910152Satgutier@umich.edu { 70010152Satgutier@umich.edu if (ch==entity->c) { r+=entity->l; source++; goto out_of_loop1; } 70110152Satgutier@umich.edu entity++; 70210152Satgutier@umich.edu } while(entity->s); 70310152Satgutier@umich.edu#ifdef _XMLWIDECHAR 70410152Satgutier@umich.edu r++; source++; 70510152Satgutier@umich.edu#else 70610152Satgutier@umich.edu ch=XML_ByteTable[(unsigned char)ch]; r+=ch; source+=ch; 70710152Satgutier@umich.edu#endif 70810152Satgutier@umich.eduout_of_loop1: 70910152Satgutier@umich.edu ; 71010152Satgutier@umich.edu } 71110152Satgutier@umich.edu return r; 71210152Satgutier@umich.edu} 71310152Satgutier@umich.edu 71410152Satgutier@umich.eduToXMLStringTool::~ToXMLStringTool(){ freeBuffer(); } 71510152Satgutier@umich.eduvoid ToXMLStringTool::freeBuffer(){ if (buf) free(buf); buf=NULL; buflen=0; } 71610152Satgutier@umich.eduXMLSTR ToXMLStringTool::toXML(XMLCSTR source) 71710152Satgutier@umich.edu{ 71810152Satgutier@umich.edu int l=lengthXMLString(source)+1; 71910152Satgutier@umich.edu if (l>buflen) { buflen=l; buf=(XMLSTR)realloc(buf,l*sizeof(XMLCHAR)); } 72010152Satgutier@umich.edu return toXMLUnSafe(buf,source); 72110152Satgutier@umich.edu} 72210152Satgutier@umich.edu 72310152Satgutier@umich.edu// private: 72410152Satgutier@umich.eduXMLSTR fromXMLString(XMLCSTR s, int lo, XML *pXML) 72510152Satgutier@umich.edu{ 72610152Satgutier@umich.edu // This function is the opposite of the function "toXMLString". It decodes the escape 72710152Satgutier@umich.edu // sequences &, ", ', <, > and replace them by the characters 72810152Satgutier@umich.edu // &,",',<,>. This function is used internally by the XML Parser. All the calls to 72910152Satgutier@umich.edu // the XML library will always gives you back "decoded" strings. 73010152Satgutier@umich.edu // 73110152Satgutier@umich.edu // in: string (s) and length (lo) of string 73210152Satgutier@umich.edu // out: new allocated string converted from xml 73310152Satgutier@umich.edu if (!s) return NULL; 73410152Satgutier@umich.edu 73510152Satgutier@umich.edu int ll=0,j; 73610152Satgutier@umich.edu XMLSTR d; 73710152Satgutier@umich.edu XMLCSTR ss=s; 73810152Satgutier@umich.edu XMLCharacterEntity *entity; 73910152Satgutier@umich.edu while ((lo>0)&&(*s)) 74010152Satgutier@umich.edu { 74110152Satgutier@umich.edu if (*s==_CXML('&')) 74210152Satgutier@umich.edu { 74310152Satgutier@umich.edu if ((lo>2)&&(s[1]==_CXML('#'))) 74410152Satgutier@umich.edu { 74510152Satgutier@umich.edu s+=2; lo-=2; 74610152Satgutier@umich.edu if ((*s==_CXML('X'))||(*s==_CXML('x'))) { s++; lo--; } 74710152Satgutier@umich.edu while ((*s)&&(*s!=_CXML(';'))&&((lo--)>0)) s++; 74810152Satgutier@umich.edu if (*s!=_CXML(';')) 74910152Satgutier@umich.edu { 75010152Satgutier@umich.edu pXML->error=eXMLErrorUnknownCharacterEntity; 75110152Satgutier@umich.edu return NULL; 75210152Satgutier@umich.edu } 75310152Satgutier@umich.edu s++; lo--; 75410152Satgutier@umich.edu } else 75510152Satgutier@umich.edu { 75610152Satgutier@umich.edu entity=XMLEntities; 75710152Satgutier@umich.edu do 75810152Satgutier@umich.edu { 75910152Satgutier@umich.edu if ((lo>=entity->l)&&(xstrnicmp(s,entity->s,entity->l)==0)) { s+=entity->l; lo-=entity->l; break; } 76010152Satgutier@umich.edu entity++; 76110152Satgutier@umich.edu } while(entity->s); 76210152Satgutier@umich.edu if (!entity->s) 76310152Satgutier@umich.edu { 76410152Satgutier@umich.edu pXML->error=eXMLErrorUnknownCharacterEntity; 76510152Satgutier@umich.edu return NULL; 76610152Satgutier@umich.edu } 76710152Satgutier@umich.edu } 76810152Satgutier@umich.edu } else 76910152Satgutier@umich.edu { 77010152Satgutier@umich.edu#ifdef _XMLWIDECHAR 77110152Satgutier@umich.edu s++; lo--; 77210152Satgutier@umich.edu#else 77310152Satgutier@umich.edu j=XML_ByteTable[(unsigned char)*s]; s+=j; lo-=j; ll+=j-1; 77410152Satgutier@umich.edu#endif 77510152Satgutier@umich.edu } 77610152Satgutier@umich.edu ll++; 77710152Satgutier@umich.edu } 77810152Satgutier@umich.edu 77910152Satgutier@umich.edu d=(XMLSTR)malloc((ll+1)*sizeof(XMLCHAR)); 78010152Satgutier@umich.edu s=d; 78110152Satgutier@umich.edu while (ll-->0) 78210152Satgutier@umich.edu { 78310152Satgutier@umich.edu if (*ss==_CXML('&')) 78410152Satgutier@umich.edu { 78510152Satgutier@umich.edu if (ss[1]==_CXML('#')) 78610152Satgutier@umich.edu { 78710152Satgutier@umich.edu ss+=2; j=0; 78810152Satgutier@umich.edu if ((*ss==_CXML('X'))||(*ss==_CXML('x'))) 78910152Satgutier@umich.edu { 79010152Satgutier@umich.edu ss++; 79110152Satgutier@umich.edu while (*ss!=_CXML(';')) 79210152Satgutier@umich.edu { 79310152Satgutier@umich.edu if ((*ss>=_CXML('0'))&&(*ss<=_CXML('9'))) j=(j<<4)+*ss-_CXML('0'); 79410152Satgutier@umich.edu else if ((*ss>=_CXML('A'))&&(*ss<=_CXML('F'))) j=(j<<4)+*ss-_CXML('A')+10; 79510152Satgutier@umich.edu else if ((*ss>=_CXML('a'))&&(*ss<=_CXML('f'))) j=(j<<4)+*ss-_CXML('a')+10; 79610152Satgutier@umich.edu else { free((void*)s); pXML->error=eXMLErrorUnknownCharacterEntity;return NULL;} 79710152Satgutier@umich.edu ss++; 79810152Satgutier@umich.edu } 79910152Satgutier@umich.edu } else 80010152Satgutier@umich.edu { 80110152Satgutier@umich.edu while (*ss!=_CXML(';')) 80210152Satgutier@umich.edu { 80310152Satgutier@umich.edu if ((*ss>=_CXML('0'))&&(*ss<=_CXML('9'))) j=(j*10)+*ss-_CXML('0'); 80410152Satgutier@umich.edu else { free((void*)s); pXML->error=eXMLErrorUnknownCharacterEntity;return NULL;} 80510152Satgutier@umich.edu ss++; 80610152Satgutier@umich.edu } 80710152Satgutier@umich.edu } 80810152Satgutier@umich.edu#ifndef _XMLWIDECHAR 80910152Satgutier@umich.edu if (j>255) { free((void*)s); pXML->error=eXMLErrorCharacterCodeAbove255;return NULL;} 81010152Satgutier@umich.edu#endif 81110152Satgutier@umich.edu (*d++)=(XMLCHAR)j; ss++; 81210152Satgutier@umich.edu } else 81310152Satgutier@umich.edu { 81410152Satgutier@umich.edu entity=XMLEntities; 81510152Satgutier@umich.edu do 81610152Satgutier@umich.edu { 81710152Satgutier@umich.edu if (xstrnicmp(ss,entity->s,entity->l)==0) { *(d++)=entity->c; ss+=entity->l; break; } 81810152Satgutier@umich.edu entity++; 81910152Satgutier@umich.edu } while(entity->s); 82010152Satgutier@umich.edu } 82110152Satgutier@umich.edu } else 82210152Satgutier@umich.edu { 82310152Satgutier@umich.edu#ifdef _XMLWIDECHAR 82410152Satgutier@umich.edu *(d++)=*(ss++); 82510152Satgutier@umich.edu#else 82610152Satgutier@umich.edu switch(XML_ByteTable[(unsigned char)*ss]) 82710152Satgutier@umich.edu { 82810152Satgutier@umich.edu case 4: *(d++)=*(ss++); ll--; 82910152Satgutier@umich.edu case 3: *(d++)=*(ss++); ll--; 83010152Satgutier@umich.edu case 2: *(d++)=*(ss++); ll--; 83110152Satgutier@umich.edu case 1: *(d++)=*(ss++); 83210152Satgutier@umich.edu } 83310152Satgutier@umich.edu#endif 83410152Satgutier@umich.edu } 83510152Satgutier@umich.edu } 83610152Satgutier@umich.edu *d=0; 83710152Satgutier@umich.edu return (XMLSTR)s; 83810152Satgutier@umich.edu} 83910152Satgutier@umich.edu 84010152Satgutier@umich.edu#define XML_isSPACECHAR(ch) ((ch==_CXML('\n'))||(ch==_CXML(' '))||(ch== _CXML('\t'))||(ch==_CXML('\r'))) 84110152Satgutier@umich.edu 84210152Satgutier@umich.edu// private: 84310152Satgutier@umich.educhar myTagCompare(XMLCSTR cclose, XMLCSTR copen) 84410152Satgutier@umich.edu// !!!! WARNING strange convention&: 84510152Satgutier@umich.edu// return 0 if equals 84610152Satgutier@umich.edu// return 1 if different 84710152Satgutier@umich.edu{ 84810152Satgutier@umich.edu if (!cclose) return 1; 84910152Satgutier@umich.edu int l=(int)xstrlen(cclose); 85010152Satgutier@umich.edu if (xstrnicmp(cclose, copen, l)!=0) return 1; 85110152Satgutier@umich.edu const XMLCHAR c=copen[l]; 85210152Satgutier@umich.edu if (XML_isSPACECHAR(c)|| 85310152Satgutier@umich.edu (c==_CXML('/' ))|| 85410152Satgutier@umich.edu (c==_CXML('<' ))|| 85510152Satgutier@umich.edu (c==_CXML('>' ))|| 85610152Satgutier@umich.edu (c==_CXML('=' ))) return 0; 85710152Satgutier@umich.edu return 1; 85810152Satgutier@umich.edu} 85910152Satgutier@umich.edu 86010152Satgutier@umich.edu// Obtain the next character from the string. 86110152Satgutier@umich.edustatic inline XMLCHAR getNextChar(XML *pXML) 86210152Satgutier@umich.edu{ 86310152Satgutier@umich.edu XMLCHAR ch = pXML->lpXML[pXML->nIndex]; 86410152Satgutier@umich.edu#ifdef _XMLWIDECHAR 86510152Satgutier@umich.edu if (ch!=0) pXML->nIndex++; 86610152Satgutier@umich.edu#else 86710152Satgutier@umich.edu pXML->nIndex+=XML_ByteTable[(unsigned char)ch]; 86810152Satgutier@umich.edu#endif 86910152Satgutier@umich.edu return ch; 87010152Satgutier@umich.edu} 87110152Satgutier@umich.edu 87210152Satgutier@umich.edu// Find the next token in a string. 87310152Satgutier@umich.edu// pcbToken contains the number of characters that have been read. 87410152Satgutier@umich.edustatic NextToken GetNextToken(XML *pXML, int *pcbToken, enum XMLTokenTypeTag *pType) 87510152Satgutier@umich.edu{ 87610152Satgutier@umich.edu NextToken result; 87710152Satgutier@umich.edu XMLCHAR ch; 87810152Satgutier@umich.edu XMLCHAR chTemp; 87910152Satgutier@umich.edu int indexStart,nFoundMatch,nIsText=FALSE; 88010152Satgutier@umich.edu result.pClr=NULL; // prevent warning 88110152Satgutier@umich.edu 88210152Satgutier@umich.edu // Find next non-white space character 88310152Satgutier@umich.edu do { indexStart=pXML->nIndex; ch=getNextChar(pXML); } while XML_isSPACECHAR(ch); 88410152Satgutier@umich.edu 88510152Satgutier@umich.edu if (ch) 88610152Satgutier@umich.edu { 88710152Satgutier@umich.edu // Cache the current string pointer 88810152Satgutier@umich.edu result.pStr = &pXML->lpXML[indexStart]; 88910152Satgutier@umich.edu 89010152Satgutier@umich.edu // First check whether the token is in the clear tag list (meaning it 89110152Satgutier@umich.edu // does not need formatting). 89210152Satgutier@umich.edu ALLXMLClearTag *ctag=XMLClearTags; 89310152Satgutier@umich.edu do 89410152Satgutier@umich.edu { 89510152Satgutier@umich.edu if (xstrncmp(ctag->lpszOpen, result.pStr, ctag->openTagLen)==0) 89610152Satgutier@umich.edu { 89710152Satgutier@umich.edu result.pClr=ctag; 89810152Satgutier@umich.edu pXML->nIndex+=ctag->openTagLen-1; 89910152Satgutier@umich.edu *pType=eTokenClear; 90010152Satgutier@umich.edu return result; 90110152Satgutier@umich.edu } 90210152Satgutier@umich.edu ctag++; 90310152Satgutier@umich.edu } while(ctag->lpszOpen); 90410152Satgutier@umich.edu 90510152Satgutier@umich.edu // If we didn't find a clear tag then check for standard tokens 90610152Satgutier@umich.edu switch(ch) 90710152Satgutier@umich.edu { 90810152Satgutier@umich.edu // Check for quotes 90910152Satgutier@umich.edu case _CXML('\''): 91010152Satgutier@umich.edu case _CXML('\"'): 91110152Satgutier@umich.edu // Type of token 91210152Satgutier@umich.edu *pType = eTokenQuotedText; 91310152Satgutier@umich.edu chTemp = ch; 91410152Satgutier@umich.edu 91510152Satgutier@umich.edu // Set the size 91610152Satgutier@umich.edu nFoundMatch = FALSE; 91710152Satgutier@umich.edu 91810152Satgutier@umich.edu // Search through the string to find a matching quote 91910152Satgutier@umich.edu while((ch = getNextChar(pXML))) 92010152Satgutier@umich.edu { 92110152Satgutier@umich.edu if (ch==chTemp) { nFoundMatch = TRUE; break; } 92210152Satgutier@umich.edu if (ch==_CXML('<')) break; 92310152Satgutier@umich.edu } 92410152Satgutier@umich.edu 92510152Satgutier@umich.edu // If we failed to find a matching quote 92610152Satgutier@umich.edu if (nFoundMatch == FALSE) 92710152Satgutier@umich.edu { 92810152Satgutier@umich.edu pXML->nIndex=indexStart+1; 92910152Satgutier@umich.edu nIsText=TRUE; 93010152Satgutier@umich.edu break; 93110152Satgutier@umich.edu } 93210152Satgutier@umich.edu 93310152Satgutier@umich.edu// 4.02.2002 93410152Satgutier@umich.edu// if (FindNonWhiteSpace(pXML)) pXML->nIndex--; 93510152Satgutier@umich.edu 93610152Satgutier@umich.edu break; 93710152Satgutier@umich.edu 93810152Satgutier@umich.edu // Equals (used with attribute values) 93910152Satgutier@umich.edu case _CXML('='): 94010152Satgutier@umich.edu *pType = eTokenEquals; 94110152Satgutier@umich.edu break; 94210152Satgutier@umich.edu 94310152Satgutier@umich.edu // Close tag 94410152Satgutier@umich.edu case _CXML('>'): 94510152Satgutier@umich.edu *pType = eTokenCloseTag; 94610152Satgutier@umich.edu break; 94710152Satgutier@umich.edu 94810152Satgutier@umich.edu // Check for tag start and tag end 94910152Satgutier@umich.edu case _CXML('<'): 95010152Satgutier@umich.edu 95110152Satgutier@umich.edu // Peek at the next character to see if we have an end tag '</', 95210152Satgutier@umich.edu // or an xml declaration '<?' 95310152Satgutier@umich.edu chTemp = pXML->lpXML[pXML->nIndex]; 95410152Satgutier@umich.edu 95510152Satgutier@umich.edu // If we have a tag end... 95610152Satgutier@umich.edu if (chTemp == _CXML('/')) 95710152Satgutier@umich.edu { 95810152Satgutier@umich.edu // Set the type and ensure we point at the next character 95910152Satgutier@umich.edu getNextChar(pXML); 96010152Satgutier@umich.edu *pType = eTokenTagEnd; 96110152Satgutier@umich.edu } 96210152Satgutier@umich.edu 96310152Satgutier@umich.edu // If we have an XML declaration tag 96410152Satgutier@umich.edu else if (chTemp == _CXML('?')) 96510152Satgutier@umich.edu { 96610152Satgutier@umich.edu 96710152Satgutier@umich.edu // Set the type and ensure we point at the next character 96810152Satgutier@umich.edu getNextChar(pXML); 96910152Satgutier@umich.edu *pType = eTokenDeclaration; 97010152Satgutier@umich.edu } 97110152Satgutier@umich.edu 97210152Satgutier@umich.edu // Otherwise we must have a start tag 97310152Satgutier@umich.edu else 97410152Satgutier@umich.edu { 97510152Satgutier@umich.edu *pType = eTokenTagStart; 97610152Satgutier@umich.edu } 97710152Satgutier@umich.edu break; 97810152Satgutier@umich.edu 97910152Satgutier@umich.edu // Check to see if we have a short hand type end tag ('/>'). 98010152Satgutier@umich.edu case _CXML('/'): 98110152Satgutier@umich.edu 98210152Satgutier@umich.edu // Peek at the next character to see if we have a short end tag '/>' 98310152Satgutier@umich.edu chTemp = pXML->lpXML[pXML->nIndex]; 98410152Satgutier@umich.edu 98510152Satgutier@umich.edu // If we have a short hand end tag... 98610152Satgutier@umich.edu if (chTemp == _CXML('>')) 98710152Satgutier@umich.edu { 98810152Satgutier@umich.edu // Set the type and ensure we point at the next character 98910152Satgutier@umich.edu getNextChar(pXML); 99010152Satgutier@umich.edu *pType = eTokenShortHandClose; 99110152Satgutier@umich.edu break; 99210152Satgutier@umich.edu } 99310152Satgutier@umich.edu 99410152Satgutier@umich.edu // If we haven't found a short hand closing tag then drop into the 99510152Satgutier@umich.edu // text process 99610152Satgutier@umich.edu 99710152Satgutier@umich.edu // Other characters 99810152Satgutier@umich.edu default: 99910152Satgutier@umich.edu nIsText = TRUE; 100010152Satgutier@umich.edu } 100110152Satgutier@umich.edu 100210152Satgutier@umich.edu // If this is a TEXT node 100310152Satgutier@umich.edu if (nIsText) 100410152Satgutier@umich.edu { 100510152Satgutier@umich.edu // Indicate we are dealing with text 100610152Satgutier@umich.edu *pType = eTokenText; 100710152Satgutier@umich.edu while((ch = getNextChar(pXML))) 100810152Satgutier@umich.edu { 100910152Satgutier@umich.edu if XML_isSPACECHAR(ch) 101010152Satgutier@umich.edu { 101110152Satgutier@umich.edu indexStart++; break; 101210152Satgutier@umich.edu 101310152Satgutier@umich.edu } else if (ch==_CXML('/')) 101410152Satgutier@umich.edu { 101510152Satgutier@umich.edu // If we find a slash then this maybe text or a short hand end tag 101610152Satgutier@umich.edu // Peek at the next character to see it we have short hand end tag 101710152Satgutier@umich.edu ch=pXML->lpXML[pXML->nIndex]; 101810152Satgutier@umich.edu // If we found a short hand end tag then we need to exit the loop 101910152Satgutier@umich.edu if (ch==_CXML('>')) { pXML->nIndex--; break; } 102010152Satgutier@umich.edu 102110152Satgutier@umich.edu } else if ((ch==_CXML('<'))||(ch==_CXML('>'))||(ch==_CXML('='))) 102210152Satgutier@umich.edu { 102310152Satgutier@umich.edu pXML->nIndex--; break; 102410152Satgutier@umich.edu } 102510152Satgutier@umich.edu } 102610152Satgutier@umich.edu } 102710152Satgutier@umich.edu *pcbToken = pXML->nIndex-indexStart; 102810152Satgutier@umich.edu } else 102910152Satgutier@umich.edu { 103010152Satgutier@umich.edu // If we failed to obtain a valid character 103110152Satgutier@umich.edu *pcbToken = 0; 103210152Satgutier@umich.edu *pType = eTokenError; 103310152Satgutier@umich.edu result.pStr=NULL; 103410152Satgutier@umich.edu } 103510152Satgutier@umich.edu 103610152Satgutier@umich.edu return result; 103710152Satgutier@umich.edu} 103810152Satgutier@umich.edu 103910152Satgutier@umich.eduXMLCSTR XMLNode::updateName_WOSD(XMLSTR lpszName) 104010152Satgutier@umich.edu{ 104110152Satgutier@umich.edu if (!d) { free(lpszName); return NULL; } 104210152Satgutier@umich.edu if (d->lpszName&&(lpszName!=d->lpszName)) free((void*)d->lpszName); 104310152Satgutier@umich.edu d->lpszName=lpszName; 104410152Satgutier@umich.edu return lpszName; 104510152Satgutier@umich.edu} 104610152Satgutier@umich.edu 104710152Satgutier@umich.edu// private: 104810152Satgutier@umich.eduXMLNode::XMLNode(struct XMLNodeDataTag *p){ d=p; (p->ref_count)++; } 104910152Satgutier@umich.eduXMLNode::XMLNode(XMLNodeData *pParent, XMLSTR lpszName, char isDeclaration) 105010152Satgutier@umich.edu{ 105110152Satgutier@umich.edu d=(XMLNodeData*)malloc(sizeof(XMLNodeData)); 105210152Satgutier@umich.edu d->ref_count=1; 105310152Satgutier@umich.edu 105410152Satgutier@umich.edu d->lpszName=NULL; 105510152Satgutier@umich.edu d->nChild= 0; 105610152Satgutier@umich.edu d->nText = 0; 105710152Satgutier@umich.edu d->nClear = 0; 105810152Satgutier@umich.edu d->nAttribute = 0; 105910152Satgutier@umich.edu 106010152Satgutier@umich.edu d->isDeclaration = isDeclaration; 106110152Satgutier@umich.edu 106210152Satgutier@umich.edu d->pParent = pParent; 106310152Satgutier@umich.edu d->pChild= NULL; 106410152Satgutier@umich.edu d->pText= NULL; 106510152Satgutier@umich.edu d->pClear= NULL; 106610152Satgutier@umich.edu d->pAttribute= NULL; 106710152Satgutier@umich.edu d->pOrder= NULL; 106810152Satgutier@umich.edu 106910152Satgutier@umich.edu updateName_WOSD(lpszName); 107010152Satgutier@umich.edu} 107110152Satgutier@umich.edu 107210152Satgutier@umich.eduXMLNode XMLNode::createXMLTopNode_WOSD(XMLSTR lpszName, char isDeclaration) { return XMLNode(NULL,lpszName,isDeclaration); } 107310152Satgutier@umich.eduXMLNode XMLNode::createXMLTopNode(XMLCSTR lpszName, char isDeclaration) { return XMLNode(NULL,stringDup(lpszName),isDeclaration); } 107410152Satgutier@umich.edu 107510152Satgutier@umich.edu#define MEMORYINCREASE 50 107610152Satgutier@umich.edu 107710152Satgutier@umich.edustatic inline void myFree(void *p) { if (p) free(p); } 107810152Satgutier@umich.edustatic inline void *myRealloc(void *p, int newsize, int memInc, int sizeofElem) 107910152Satgutier@umich.edu{ 108010152Satgutier@umich.edu if (p==NULL) { if (memInc) return malloc(memInc*sizeofElem); return malloc(sizeofElem); } 108110152Satgutier@umich.edu if ((memInc==0)||((newsize%memInc)==0)) p=realloc(p,(newsize+memInc)*sizeofElem); 108210152Satgutier@umich.edu// if (!p) 108310152Satgutier@umich.edu// { 108410152Satgutier@umich.edu// printf("XMLParser Error: Not enough memory! Aborting...\n"); exit(220); 108510152Satgutier@umich.edu// } 108610152Satgutier@umich.edu return p; 108710152Satgutier@umich.edu} 108810152Satgutier@umich.edu 108910152Satgutier@umich.edu// private: 109010152Satgutier@umich.eduXMLElementPosition XMLNode::findPosition(XMLNodeData *d, int index, XMLElementType xxtype) 109110152Satgutier@umich.edu{ 109210152Satgutier@umich.edu if (index<0) return -1; 109310152Satgutier@umich.edu int i=0,j=(int)((index<<2)+xxtype),*o=d->pOrder; while (o[i]!=j) i++; return i; 109410152Satgutier@umich.edu} 109510152Satgutier@umich.edu 109610152Satgutier@umich.edu// private: 109710152Satgutier@umich.edu// update "order" information when deleting a content of a XMLNode 109810152Satgutier@umich.eduint XMLNode::removeOrderElement(XMLNodeData *d, XMLElementType t, int index) 109910152Satgutier@umich.edu{ 110010152Satgutier@umich.edu int n=d->nChild+d->nText+d->nClear, *o=d->pOrder,i=findPosition(d,index,t); 110110152Satgutier@umich.edu memmove(o+i, o+i+1, (n-i)*sizeof(int)); 110210152Satgutier@umich.edu for (;i<n;i++) 110310152Satgutier@umich.edu if ((o[i]&3)==(int)t) o[i]-=4; 110410152Satgutier@umich.edu // We should normally do: 110510152Satgutier@umich.edu // d->pOrder=(int)realloc(d->pOrder,n*sizeof(int)); 110610152Satgutier@umich.edu // but we skip reallocation because it's too time consuming. 110710152Satgutier@umich.edu // Anyway, at the end, it will be free'd completely at once. 110810152Satgutier@umich.edu return i; 110910152Satgutier@umich.edu} 111010152Satgutier@umich.edu 111110152Satgutier@umich.eduvoid *XMLNode::addToOrder(int memoryIncrease,int *_pos, int nc, void *p, int size, XMLElementType xtype) 111210152Satgutier@umich.edu{ 111310152Satgutier@umich.edu // in: *_pos is the position inside d->pOrder ("-1" means "EndOf") 111410152Satgutier@umich.edu // out: *_pos is the index inside p 111510152Satgutier@umich.edu p=myRealloc(p,(nc+1),memoryIncrease,size); 111610152Satgutier@umich.edu int n=d->nChild+d->nText+d->nClear; 111710152Satgutier@umich.edu d->pOrder=(int*)myRealloc(d->pOrder,n+1,memoryIncrease*3,sizeof(int)); 111810152Satgutier@umich.edu int pos=*_pos,*o=d->pOrder; 111910152Satgutier@umich.edu 112010152Satgutier@umich.edu if ((pos<0)||(pos>=n)) { *_pos=nc; o[n]=(int)((nc<<2)+xtype); return p; } 112110152Satgutier@umich.edu 112210152Satgutier@umich.edu int i=pos; 112310152Satgutier@umich.edu memmove(o+i+1, o+i, (n-i)*sizeof(int)); 112410152Satgutier@umich.edu 112510152Satgutier@umich.edu while ((pos<n)&&((o[pos]&3)!=(int)xtype)) pos++; 112610152Satgutier@umich.edu if (pos==n) { *_pos=nc; o[n]=(int)((nc<<2)+xtype); return p; } 112710152Satgutier@umich.edu 112810152Satgutier@umich.edu o[i]=o[pos]; 112910152Satgutier@umich.edu for (i=pos+1;i<=n;i++) if ((o[i]&3)==(int)xtype) o[i]+=4; 113010152Satgutier@umich.edu 113110152Satgutier@umich.edu *_pos=pos=o[pos]>>2; 113210152Satgutier@umich.edu memmove(((char*)p)+(pos+1)*size,((char*)p)+pos*size,(nc-pos)*size); 113310152Satgutier@umich.edu 113410152Satgutier@umich.edu return p; 113510152Satgutier@umich.edu} 113610152Satgutier@umich.edu 113710152Satgutier@umich.edu// Add a child node to the given element. 113810152Satgutier@umich.eduXMLNode XMLNode::addChild_priv(int memoryIncrease, XMLSTR lpszName, char isDeclaration, int pos) 113910152Satgutier@umich.edu{ 114010152Satgutier@umich.edu if (!lpszName) return emptyXMLNode; 114110152Satgutier@umich.edu d->pChild=(XMLNode*)addToOrder(memoryIncrease,&pos,d->nChild,d->pChild,sizeof(XMLNode),eNodeChild); 114210152Satgutier@umich.edu d->pChild[pos].d=NULL; 114310152Satgutier@umich.edu d->pChild[pos]=XMLNode(d,lpszName,isDeclaration); 114410152Satgutier@umich.edu d->nChild++; 114510152Satgutier@umich.edu return d->pChild[pos]; 114610152Satgutier@umich.edu} 114710152Satgutier@umich.edu 114810152Satgutier@umich.edu// Add an attribute to an element. 114910152Satgutier@umich.eduXMLAttribute *XMLNode::addAttribute_priv(int memoryIncrease,XMLSTR lpszName, XMLSTR lpszValuev) 115010152Satgutier@umich.edu{ 115110152Satgutier@umich.edu if (!lpszName) return &emptyXMLAttribute; 115210152Satgutier@umich.edu if (!d) { myFree(lpszName); myFree(lpszValuev); return &emptyXMLAttribute; } 115310152Satgutier@umich.edu int nc=d->nAttribute; 115410152Satgutier@umich.edu d->pAttribute=(XMLAttribute*)myRealloc(d->pAttribute,(nc+1),memoryIncrease,sizeof(XMLAttribute)); 115510152Satgutier@umich.edu XMLAttribute *pAttr=d->pAttribute+nc; 115610152Satgutier@umich.edu pAttr->lpszName = lpszName; 115710152Satgutier@umich.edu pAttr->lpszValue = lpszValuev; 115810152Satgutier@umich.edu d->nAttribute++; 115910152Satgutier@umich.edu return pAttr; 116010152Satgutier@umich.edu} 116110152Satgutier@umich.edu 116210152Satgutier@umich.edu// Add text to the element. 116310152Satgutier@umich.eduXMLCSTR XMLNode::addText_priv(int memoryIncrease, XMLSTR lpszValue, int pos) 116410152Satgutier@umich.edu{ 116510152Satgutier@umich.edu if (!lpszValue) return NULL; 116610152Satgutier@umich.edu if (!d) { myFree(lpszValue); return NULL; } 116710152Satgutier@umich.edu d->pText=(XMLCSTR*)addToOrder(memoryIncrease,&pos,d->nText,d->pText,sizeof(XMLSTR),eNodeText); 116810152Satgutier@umich.edu d->pText[pos]=lpszValue; 116910152Satgutier@umich.edu d->nText++; 117010152Satgutier@umich.edu return lpszValue; 117110152Satgutier@umich.edu} 117210152Satgutier@umich.edu 117310152Satgutier@umich.edu// Add clear (unformatted) text to the element. 117410152Satgutier@umich.eduXMLClear *XMLNode::addClear_priv(int memoryIncrease, XMLSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, int pos) 117510152Satgutier@umich.edu{ 117610152Satgutier@umich.edu if (!lpszValue) return &emptyXMLClear; 117710152Satgutier@umich.edu if (!d) { myFree(lpszValue); return &emptyXMLClear; } 117810152Satgutier@umich.edu d->pClear=(XMLClear *)addToOrder(memoryIncrease,&pos,d->nClear,d->pClear,sizeof(XMLClear),eNodeClear); 117910152Satgutier@umich.edu XMLClear *pNewClear=d->pClear+pos; 118010152Satgutier@umich.edu pNewClear->lpszValue = lpszValue; 118110152Satgutier@umich.edu if (!lpszOpen) lpszOpen=XMLClearTags->lpszOpen; 118210152Satgutier@umich.edu if (!lpszClose) lpszClose=XMLClearTags->lpszClose; 118310152Satgutier@umich.edu pNewClear->lpszOpenTag = lpszOpen; 118410152Satgutier@umich.edu pNewClear->lpszCloseTag = lpszClose; 118510152Satgutier@umich.edu d->nClear++; 118610152Satgutier@umich.edu return pNewClear; 118710152Satgutier@umich.edu} 118810152Satgutier@umich.edu 118910152Satgutier@umich.edu// private: 119010152Satgutier@umich.edu// Parse a clear (unformatted) type node. 119110152Satgutier@umich.educhar XMLNode::parseClearTag(void *px, void *_pClear) 119210152Satgutier@umich.edu{ 119310152Satgutier@umich.edu XML *pXML=(XML *)px; 119410152Satgutier@umich.edu ALLXMLClearTag pClear=*((ALLXMLClearTag*)_pClear); 119510152Satgutier@umich.edu int cbTemp=0; 119610152Satgutier@umich.edu XMLCSTR lpszTemp=NULL; 119710152Satgutier@umich.edu XMLCSTR lpXML=&pXML->lpXML[pXML->nIndex]; 119810152Satgutier@umich.edu static XMLCSTR docTypeEnd=_CXML("]>"); 119910152Satgutier@umich.edu 120010152Satgutier@umich.edu // Find the closing tag 120110152Satgutier@umich.edu // Seems the <!DOCTYPE need a better treatment so lets handle it 120210152Satgutier@umich.edu if (pClear.lpszOpen==XMLClearTags[1].lpszOpen) 120310152Satgutier@umich.edu { 120410152Satgutier@umich.edu XMLCSTR pCh=lpXML; 120510152Satgutier@umich.edu while (*pCh) 120610152Satgutier@umich.edu { 120710152Satgutier@umich.edu if (*pCh==_CXML('<')) { pClear.lpszClose=docTypeEnd; lpszTemp=xstrstr(lpXML,docTypeEnd); break; } 120810152Satgutier@umich.edu else if (*pCh==_CXML('>')) { lpszTemp=pCh; break; } 120910152Satgutier@umich.edu#ifdef _XMLWIDECHAR 121010152Satgutier@umich.edu pCh++; 121110152Satgutier@umich.edu#else 121210152Satgutier@umich.edu pCh+=XML_ByteTable[(unsigned char)(*pCh)]; 121310152Satgutier@umich.edu#endif 121410152Satgutier@umich.edu } 121510152Satgutier@umich.edu } else lpszTemp=xstrstr(lpXML, pClear.lpszClose); 121610152Satgutier@umich.edu 121710152Satgutier@umich.edu if (lpszTemp) 121810152Satgutier@umich.edu { 121910152Satgutier@umich.edu // Cache the size and increment the index 122010152Satgutier@umich.edu cbTemp = (int)(lpszTemp - lpXML); 122110152Satgutier@umich.edu 122210152Satgutier@umich.edu pXML->nIndex += cbTemp+(int)xstrlen(pClear.lpszClose); 122310152Satgutier@umich.edu 122410152Satgutier@umich.edu // Add the clear node to the current element 122510152Satgutier@umich.edu addClear_priv(MEMORYINCREASE,stringDup(lpXML,cbTemp), pClear.lpszOpen, pClear.lpszClose,-1); 122610152Satgutier@umich.edu return 0; 122710152Satgutier@umich.edu } 122810152Satgutier@umich.edu 122910152Satgutier@umich.edu // If we failed to find the end tag 123010152Satgutier@umich.edu pXML->error = eXMLErrorUnmatchedEndClearTag; 123110152Satgutier@umich.edu return 1; 123210152Satgutier@umich.edu} 123310152Satgutier@umich.edu 123410152Satgutier@umich.eduvoid XMLNode::exactMemory(XMLNodeData *d) 123510152Satgutier@umich.edu{ 123610152Satgutier@umich.edu if (d->pOrder) d->pOrder=(int*)realloc(d->pOrder,(d->nChild+d->nText+d->nClear)*sizeof(int)); 123710152Satgutier@umich.edu if (d->pChild) d->pChild=(XMLNode*)realloc(d->pChild,d->nChild*sizeof(XMLNode)); 123810152Satgutier@umich.edu if (d->pAttribute) d->pAttribute=(XMLAttribute*)realloc(d->pAttribute,d->nAttribute*sizeof(XMLAttribute)); 123910152Satgutier@umich.edu if (d->pText) d->pText=(XMLCSTR*)realloc(d->pText,d->nText*sizeof(XMLSTR)); 124010152Satgutier@umich.edu if (d->pClear) d->pClear=(XMLClear *)realloc(d->pClear,d->nClear*sizeof(XMLClear)); 124110152Satgutier@umich.edu} 124210152Satgutier@umich.edu 124310152Satgutier@umich.educhar XMLNode::maybeAddTxT(void *pa, XMLCSTR tokenPStr) 124410152Satgutier@umich.edu{ 124510152Satgutier@umich.edu XML *pXML=(XML *)pa; 124610152Satgutier@umich.edu XMLCSTR lpszText=pXML->lpszText; 124710152Satgutier@umich.edu if (!lpszText) return 0; 124810152Satgutier@umich.edu if (dropWhiteSpace) while (XML_isSPACECHAR(*lpszText)&&(lpszText!=tokenPStr)) lpszText++; 124910152Satgutier@umich.edu int cbText = (int)(tokenPStr - lpszText); 125010152Satgutier@umich.edu if (!cbText) { pXML->lpszText=NULL; return 0; } 125110152Satgutier@umich.edu if (dropWhiteSpace) { cbText--; while ((cbText)&&XML_isSPACECHAR(lpszText[cbText])) cbText--; cbText++; } 125210152Satgutier@umich.edu if (!cbText) { pXML->lpszText=NULL; return 0; } 125310152Satgutier@umich.edu XMLSTR lpt=fromXMLString(lpszText,cbText,pXML); 125410152Satgutier@umich.edu if (!lpt) return 1; 125510152Satgutier@umich.edu pXML->lpszText=NULL; 125610152Satgutier@umich.edu if (removeCommentsInMiddleOfText && d->nText && d->nClear) 125710152Satgutier@umich.edu { 125810152Satgutier@umich.edu // if the previous insertion was a comment (<!-- -->) AND 125910152Satgutier@umich.edu // if the previous previous insertion was a text then, delete the comment and append the text 126010152Satgutier@umich.edu int n=d->nChild+d->nText+d->nClear-1,*o=d->pOrder; 126110152Satgutier@umich.edu if (((o[n]&3)==eNodeClear)&&((o[n-1]&3)==eNodeText)) 126210152Satgutier@umich.edu { 126310152Satgutier@umich.edu int i=o[n]>>2; 126410152Satgutier@umich.edu if (d->pClear[i].lpszOpenTag==XMLClearTags[2].lpszOpen) 126510152Satgutier@umich.edu { 126610152Satgutier@umich.edu deleteClear(i); 126710152Satgutier@umich.edu i=o[n-1]>>2; 126810152Satgutier@umich.edu n=xstrlen(d->pText[i]); 126910152Satgutier@umich.edu int n2=xstrlen(lpt)+1; 127010152Satgutier@umich.edu d->pText[i]=(XMLSTR)realloc((void*)d->pText[i],(n+n2)*sizeof(XMLCHAR)); 127110152Satgutier@umich.edu if (!d->pText[i]) return 1; 127210152Satgutier@umich.edu memcpy((void*)(d->pText[i]+n),lpt,n2*sizeof(XMLCHAR)); 127310152Satgutier@umich.edu free(lpt); 127410152Satgutier@umich.edu return 0; 127510152Satgutier@umich.edu } 127610152Satgutier@umich.edu } 127710152Satgutier@umich.edu } 127810152Satgutier@umich.edu addText_priv(MEMORYINCREASE,lpt,-1); 127910152Satgutier@umich.edu return 0; 128010152Satgutier@umich.edu} 128110152Satgutier@umich.edu// private: 128210152Satgutier@umich.edu// Recursively parse an XML element. 128310152Satgutier@umich.eduint XMLNode::ParseXMLElement(void *pa) 128410152Satgutier@umich.edu{ 128510152Satgutier@umich.edu XML *pXML=(XML *)pa; 128610152Satgutier@umich.edu int cbToken; 128710152Satgutier@umich.edu enum XMLTokenTypeTag xtype; 128810152Satgutier@umich.edu NextToken token; 128910152Satgutier@umich.edu XMLCSTR lpszTemp=NULL; 129010152Satgutier@umich.edu int cbTemp=0; 129110152Satgutier@umich.edu char nDeclaration; 129210152Satgutier@umich.edu XMLNode pNew; 129310152Satgutier@umich.edu enum Status status; // inside or outside a tag 129410152Satgutier@umich.edu enum Attrib attrib = eAttribName; 129510152Satgutier@umich.edu 129610152Satgutier@umich.edu assert(pXML); 129710152Satgutier@umich.edu 129810152Satgutier@umich.edu // If this is the first call to the function 129910152Satgutier@umich.edu if (pXML->nFirst) 130010152Satgutier@umich.edu { 130110152Satgutier@umich.edu // Assume we are outside of a tag definition 130210152Satgutier@umich.edu pXML->nFirst = FALSE; 130310152Satgutier@umich.edu status = eOutsideTag; 130410152Satgutier@umich.edu } else 130510152Satgutier@umich.edu { 130610152Satgutier@umich.edu // If this is not the first call then we should only be called when inside a tag. 130710152Satgutier@umich.edu status = eInsideTag; 130810152Satgutier@umich.edu } 130910152Satgutier@umich.edu 131010152Satgutier@umich.edu // Iterate through the tokens in the document 131110152Satgutier@umich.edu for(;;) 131210152Satgutier@umich.edu { 131310152Satgutier@umich.edu // Obtain the next token 131410152Satgutier@umich.edu token = GetNextToken(pXML, &cbToken, &xtype); 131510152Satgutier@umich.edu 131610152Satgutier@umich.edu if (xtype != eTokenError) 131710152Satgutier@umich.edu { 131810152Satgutier@umich.edu // Check the current status 131910152Satgutier@umich.edu switch(status) 132010152Satgutier@umich.edu { 132110152Satgutier@umich.edu 132210152Satgutier@umich.edu // If we are outside of a tag definition 132310152Satgutier@umich.edu case eOutsideTag: 132410152Satgutier@umich.edu 132510152Satgutier@umich.edu // Check what type of token we obtained 132610152Satgutier@umich.edu switch(xtype) 132710152Satgutier@umich.edu { 132810152Satgutier@umich.edu // If we have found text or quoted text 132910152Satgutier@umich.edu case eTokenText: 133010152Satgutier@umich.edu case eTokenCloseTag: /* '>' */ 133110152Satgutier@umich.edu case eTokenShortHandClose: /* '/>' */ 133210152Satgutier@umich.edu case eTokenQuotedText: 133310152Satgutier@umich.edu case eTokenEquals: 133410152Satgutier@umich.edu break; 133510152Satgutier@umich.edu 133610152Satgutier@umich.edu // If we found a start tag '<' and declarations '<?' 133710152Satgutier@umich.edu case eTokenTagStart: 133810152Satgutier@umich.edu case eTokenDeclaration: 133910152Satgutier@umich.edu 134010152Satgutier@umich.edu // Cache whether this new element is a declaration or not 134110152Satgutier@umich.edu nDeclaration = (xtype == eTokenDeclaration); 134210152Satgutier@umich.edu 134310152Satgutier@umich.edu // If we have node text then add this to the element 134410152Satgutier@umich.edu if (maybeAddTxT(pXML,token.pStr)) return FALSE; 134510152Satgutier@umich.edu 134610152Satgutier@umich.edu // Find the name of the tag 134710152Satgutier@umich.edu token = GetNextToken(pXML, &cbToken, &xtype); 134810152Satgutier@umich.edu 134910152Satgutier@umich.edu // Return an error if we couldn't obtain the next token or 135010152Satgutier@umich.edu // it wasnt text 135110152Satgutier@umich.edu if (xtype != eTokenText) 135210152Satgutier@umich.edu { 135310152Satgutier@umich.edu pXML->error = eXMLErrorMissingTagName; 135410152Satgutier@umich.edu return FALSE; 135510152Satgutier@umich.edu } 135610152Satgutier@umich.edu 135710152Satgutier@umich.edu // If we found a new element which is the same as this 135810152Satgutier@umich.edu // element then we need to pass this back to the caller.. 135910152Satgutier@umich.edu 136010152Satgutier@umich.edu#ifdef APPROXIMATE_PARSING 136110152Satgutier@umich.edu if (d->lpszName && 136210152Satgutier@umich.edu myTagCompare(d->lpszName, token.pStr) == 0) 136310152Satgutier@umich.edu { 136410152Satgutier@umich.edu // Indicate to the caller that it needs to create a 136510152Satgutier@umich.edu // new element. 136610152Satgutier@umich.edu pXML->lpNewElement = token.pStr; 136710152Satgutier@umich.edu pXML->cbNewElement = cbToken; 136810152Satgutier@umich.edu return TRUE; 136910152Satgutier@umich.edu } else 137010152Satgutier@umich.edu#endif 137110152Satgutier@umich.edu { 137210152Satgutier@umich.edu // If the name of the new element differs from the name of 137310152Satgutier@umich.edu // the current element we need to add the new element to 137410152Satgutier@umich.edu // the current one and recurse 137510152Satgutier@umich.edu pNew = addChild_priv(MEMORYINCREASE,stringDup(token.pStr,cbToken), nDeclaration,-1); 137610152Satgutier@umich.edu 137710152Satgutier@umich.edu while (!pNew.isEmpty()) 137810152Satgutier@umich.edu { 137910152Satgutier@umich.edu // Callself to process the new node. If we return 138010152Satgutier@umich.edu // FALSE this means we dont have any more 138110152Satgutier@umich.edu // processing to do... 138210152Satgutier@umich.edu 138310152Satgutier@umich.edu if (!pNew.ParseXMLElement(pXML)) return FALSE; 138410152Satgutier@umich.edu else 138510152Satgutier@umich.edu { 138610152Satgutier@umich.edu // If the call to recurse this function 138710152Satgutier@umich.edu // evented in a end tag specified in XML then 138810152Satgutier@umich.edu // we need to unwind the calls to this 138910152Satgutier@umich.edu // function until we find the appropriate node 139010152Satgutier@umich.edu // (the element name and end tag name must 139110152Satgutier@umich.edu // match) 139210152Satgutier@umich.edu if (pXML->cbEndTag) 139310152Satgutier@umich.edu { 139410152Satgutier@umich.edu // If we are back at the root node then we 139510152Satgutier@umich.edu // have an unmatched end tag 139610152Satgutier@umich.edu if (!d->lpszName) 139710152Satgutier@umich.edu { 139810152Satgutier@umich.edu pXML->error=eXMLErrorUnmatchedEndTag; 139910152Satgutier@umich.edu return FALSE; 140010152Satgutier@umich.edu } 140110152Satgutier@umich.edu 140210152Satgutier@umich.edu // If the end tag matches the name of this 140310152Satgutier@umich.edu // element then we only need to unwind 140410152Satgutier@umich.edu // once more... 140510152Satgutier@umich.edu 140610152Satgutier@umich.edu if (myTagCompare(d->lpszName, pXML->lpEndTag)==0) 140710152Satgutier@umich.edu { 140810152Satgutier@umich.edu pXML->cbEndTag = 0; 140910152Satgutier@umich.edu } 141010152Satgutier@umich.edu 141110152Satgutier@umich.edu return TRUE; 141210152Satgutier@umich.edu } else 141310152Satgutier@umich.edu if (pXML->cbNewElement) 141410152Satgutier@umich.edu { 141510152Satgutier@umich.edu // If the call indicated a new element is to 141610152Satgutier@umich.edu // be created on THIS element. 141710152Satgutier@umich.edu 141810152Satgutier@umich.edu // If the name of this element matches the 141910152Satgutier@umich.edu // name of the element we need to create 142010152Satgutier@umich.edu // then we need to return to the caller 142110152Satgutier@umich.edu // and let it process the element. 142210152Satgutier@umich.edu 142310152Satgutier@umich.edu if (myTagCompare(d->lpszName, pXML->lpNewElement)==0) 142410152Satgutier@umich.edu { 142510152Satgutier@umich.edu return TRUE; 142610152Satgutier@umich.edu } 142710152Satgutier@umich.edu 142810152Satgutier@umich.edu // Add the new element and recurse 142910152Satgutier@umich.edu pNew = addChild_priv(MEMORYINCREASE,stringDup(pXML->lpNewElement,pXML->cbNewElement),0,-1); 143010152Satgutier@umich.edu pXML->cbNewElement = 0; 143110152Satgutier@umich.edu } 143210152Satgutier@umich.edu else 143310152Satgutier@umich.edu { 143410152Satgutier@umich.edu // If we didn't have a new element to create 143510152Satgutier@umich.edu pNew = emptyXMLNode; 143610152Satgutier@umich.edu 143710152Satgutier@umich.edu } 143810152Satgutier@umich.edu } 143910152Satgutier@umich.edu } 144010152Satgutier@umich.edu } 144110152Satgutier@umich.edu break; 144210152Satgutier@umich.edu 144310152Satgutier@umich.edu // If we found an end tag 144410152Satgutier@umich.edu case eTokenTagEnd: 144510152Satgutier@umich.edu 144610152Satgutier@umich.edu // If we have node text then add this to the element 144710152Satgutier@umich.edu if (maybeAddTxT(pXML,token.pStr)) return FALSE; 144810152Satgutier@umich.edu 144910152Satgutier@umich.edu // Find the name of the end tag 145010152Satgutier@umich.edu token = GetNextToken(pXML, &cbTemp, &xtype); 145110152Satgutier@umich.edu 145210152Satgutier@umich.edu // The end tag should be text 145310152Satgutier@umich.edu if (xtype != eTokenText) 145410152Satgutier@umich.edu { 145510152Satgutier@umich.edu pXML->error = eXMLErrorMissingEndTagName; 145610152Satgutier@umich.edu return FALSE; 145710152Satgutier@umich.edu } 145810152Satgutier@umich.edu lpszTemp = token.pStr; 145910152Satgutier@umich.edu 146010152Satgutier@umich.edu // After the end tag we should find a closing tag 146110152Satgutier@umich.edu token = GetNextToken(pXML, &cbToken, &xtype); 146210152Satgutier@umich.edu if (xtype != eTokenCloseTag) 146310152Satgutier@umich.edu { 146410152Satgutier@umich.edu pXML->error = eXMLErrorMissingEndTagName; 146510152Satgutier@umich.edu return FALSE; 146610152Satgutier@umich.edu } 146710152Satgutier@umich.edu pXML->lpszText=pXML->lpXML+pXML->nIndex; 146810152Satgutier@umich.edu 146910152Satgutier@umich.edu // We need to return to the previous caller. If the name 147010152Satgutier@umich.edu // of the tag cannot be found we need to keep returning to 147110152Satgutier@umich.edu // caller until we find a match 147210152Satgutier@umich.edu if (myTagCompare(d->lpszName, lpszTemp) != 0) 147310152Satgutier@umich.edu#ifdef STRICT_PARSING 147410152Satgutier@umich.edu { 147510152Satgutier@umich.edu pXML->error=eXMLErrorUnmatchedEndTag; 147610152Satgutier@umich.edu pXML->nIndexMissigEndTag=pXML->nIndex; 147710152Satgutier@umich.edu return FALSE; 147810152Satgutier@umich.edu } 147910152Satgutier@umich.edu#else 148010152Satgutier@umich.edu { 148110152Satgutier@umich.edu pXML->error=eXMLErrorMissingEndTag; 148210152Satgutier@umich.edu pXML->nIndexMissigEndTag=pXML->nIndex; 148310152Satgutier@umich.edu pXML->lpEndTag = lpszTemp; 148410152Satgutier@umich.edu pXML->cbEndTag = cbTemp; 148510152Satgutier@umich.edu } 148610152Satgutier@umich.edu#endif 148710152Satgutier@umich.edu 148810152Satgutier@umich.edu // Return to the caller 148910152Satgutier@umich.edu exactMemory(d); 149010152Satgutier@umich.edu return TRUE; 149110152Satgutier@umich.edu 149210152Satgutier@umich.edu // If we found a clear (unformatted) token 149310152Satgutier@umich.edu case eTokenClear: 149410152Satgutier@umich.edu // If we have node text then add this to the element 149510152Satgutier@umich.edu if (maybeAddTxT(pXML,token.pStr)) return FALSE; 149610152Satgutier@umich.edu if (parseClearTag(pXML, token.pClr)) return FALSE; 149710152Satgutier@umich.edu pXML->lpszText=pXML->lpXML+pXML->nIndex; 149810152Satgutier@umich.edu break; 149910152Satgutier@umich.edu 150010152Satgutier@umich.edu default: 150110152Satgutier@umich.edu break; 150210152Satgutier@umich.edu } 150310152Satgutier@umich.edu break; 150410152Satgutier@umich.edu 150510152Satgutier@umich.edu // If we are inside a tag definition we need to search for attributes 150610152Satgutier@umich.edu case eInsideTag: 150710152Satgutier@umich.edu 150810152Satgutier@umich.edu // Check what part of the attribute (name, equals, value) we 150910152Satgutier@umich.edu // are looking for. 151010152Satgutier@umich.edu switch(attrib) 151110152Satgutier@umich.edu { 151210152Satgutier@umich.edu // If we are looking for a new attribute 151310152Satgutier@umich.edu case eAttribName: 151410152Satgutier@umich.edu 151510152Satgutier@umich.edu // Check what the current token type is 151610152Satgutier@umich.edu switch(xtype) 151710152Satgutier@umich.edu { 151810152Satgutier@umich.edu // If the current type is text... 151910152Satgutier@umich.edu // Eg. 'attribute' 152010152Satgutier@umich.edu case eTokenText: 152110152Satgutier@umich.edu // Cache the token then indicate that we are next to 152210152Satgutier@umich.edu // look for the equals 152310152Satgutier@umich.edu lpszTemp = token.pStr; 152410152Satgutier@umich.edu cbTemp = cbToken; 152510152Satgutier@umich.edu attrib = eAttribEquals; 152610152Satgutier@umich.edu break; 152710152Satgutier@umich.edu 152810152Satgutier@umich.edu // If we found a closing tag... 152910152Satgutier@umich.edu // Eg. '>' 153010152Satgutier@umich.edu case eTokenCloseTag: 153110152Satgutier@umich.edu // We are now outside the tag 153210152Satgutier@umich.edu status = eOutsideTag; 153310152Satgutier@umich.edu pXML->lpszText=pXML->lpXML+pXML->nIndex; 153410152Satgutier@umich.edu break; 153510152Satgutier@umich.edu 153610152Satgutier@umich.edu // If we found a short hand '/>' closing tag then we can 153710152Satgutier@umich.edu // return to the caller 153810152Satgutier@umich.edu case eTokenShortHandClose: 153910152Satgutier@umich.edu exactMemory(d); 154010152Satgutier@umich.edu pXML->lpszText=pXML->lpXML+pXML->nIndex; 154110152Satgutier@umich.edu return TRUE; 154210152Satgutier@umich.edu 154310152Satgutier@umich.edu // Errors... 154410152Satgutier@umich.edu case eTokenQuotedText: /* '"SomeText"' */ 154510152Satgutier@umich.edu case eTokenTagStart: /* '<' */ 154610152Satgutier@umich.edu case eTokenTagEnd: /* '</' */ 154710152Satgutier@umich.edu case eTokenEquals: /* '=' */ 154810152Satgutier@umich.edu case eTokenDeclaration: /* '<?' */ 154910152Satgutier@umich.edu case eTokenClear: 155010152Satgutier@umich.edu pXML->error = eXMLErrorUnexpectedToken; 155110152Satgutier@umich.edu return FALSE; 155210152Satgutier@umich.edu default: break; 155310152Satgutier@umich.edu } 155410152Satgutier@umich.edu break; 155510152Satgutier@umich.edu 155610152Satgutier@umich.edu // If we are looking for an equals 155710152Satgutier@umich.edu case eAttribEquals: 155810152Satgutier@umich.edu // Check what the current token type is 155910152Satgutier@umich.edu switch(xtype) 156010152Satgutier@umich.edu { 156110152Satgutier@umich.edu // If the current type is text... 156210152Satgutier@umich.edu // Eg. 'Attribute AnotherAttribute' 156310152Satgutier@umich.edu case eTokenText: 156410152Satgutier@umich.edu // Add the unvalued attribute to the list 156510152Satgutier@umich.edu addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp), NULL); 156610152Satgutier@umich.edu // Cache the token then indicate. We are next to 156710152Satgutier@umich.edu // look for the equals attribute 156810152Satgutier@umich.edu lpszTemp = token.pStr; 156910152Satgutier@umich.edu cbTemp = cbToken; 157010152Satgutier@umich.edu break; 157110152Satgutier@umich.edu 157210152Satgutier@umich.edu // If we found a closing tag 'Attribute >' or a short hand 157310152Satgutier@umich.edu // closing tag 'Attribute />' 157410152Satgutier@umich.edu case eTokenShortHandClose: 157510152Satgutier@umich.edu case eTokenCloseTag: 157610152Satgutier@umich.edu // If we are a declaration element '<?' then we need 157710152Satgutier@umich.edu // to remove extra closing '?' if it exists 157810152Satgutier@umich.edu pXML->lpszText=pXML->lpXML+pXML->nIndex; 157910152Satgutier@umich.edu 158010152Satgutier@umich.edu if (d->isDeclaration && 158110152Satgutier@umich.edu (lpszTemp[cbTemp-1]) == _CXML('?')) 158210152Satgutier@umich.edu { 158310152Satgutier@umich.edu cbTemp--; 158410152Satgutier@umich.edu if (d->pParent && d->pParent->pParent) xtype = eTokenShortHandClose; 158510152Satgutier@umich.edu } 158610152Satgutier@umich.edu 158710152Satgutier@umich.edu if (cbTemp) 158810152Satgutier@umich.edu { 158910152Satgutier@umich.edu // Add the unvalued attribute to the list 159010152Satgutier@umich.edu addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp), NULL); 159110152Satgutier@umich.edu } 159210152Satgutier@umich.edu 159310152Satgutier@umich.edu // If this is the end of the tag then return to the caller 159410152Satgutier@umich.edu if (xtype == eTokenShortHandClose) 159510152Satgutier@umich.edu { 159610152Satgutier@umich.edu exactMemory(d); 159710152Satgutier@umich.edu return TRUE; 159810152Satgutier@umich.edu } 159910152Satgutier@umich.edu 160010152Satgutier@umich.edu // We are now outside the tag 160110152Satgutier@umich.edu status = eOutsideTag; 160210152Satgutier@umich.edu break; 160310152Satgutier@umich.edu 160410152Satgutier@umich.edu // If we found the equals token... 160510152Satgutier@umich.edu // Eg. 'Attribute =' 160610152Satgutier@umich.edu case eTokenEquals: 160710152Satgutier@umich.edu // Indicate that we next need to search for the value 160810152Satgutier@umich.edu // for the attribute 160910152Satgutier@umich.edu attrib = eAttribValue; 161010152Satgutier@umich.edu break; 161110152Satgutier@umich.edu 161210152Satgutier@umich.edu // Errors... 161310152Satgutier@umich.edu case eTokenQuotedText: /* 'Attribute "InvalidAttr"'*/ 161410152Satgutier@umich.edu case eTokenTagStart: /* 'Attribute <' */ 161510152Satgutier@umich.edu case eTokenTagEnd: /* 'Attribute </' */ 161610152Satgutier@umich.edu case eTokenDeclaration: /* 'Attribute <?' */ 161710152Satgutier@umich.edu case eTokenClear: 161810152Satgutier@umich.edu pXML->error = eXMLErrorUnexpectedToken; 161910152Satgutier@umich.edu return FALSE; 162010152Satgutier@umich.edu default: break; 162110152Satgutier@umich.edu } 162210152Satgutier@umich.edu break; 162310152Satgutier@umich.edu 162410152Satgutier@umich.edu // If we are looking for an attribute value 162510152Satgutier@umich.edu case eAttribValue: 162610152Satgutier@umich.edu // Check what the current token type is 162710152Satgutier@umich.edu switch(xtype) 162810152Satgutier@umich.edu { 162910152Satgutier@umich.edu // If the current type is text or quoted text... 163010152Satgutier@umich.edu // Eg. 'Attribute = "Value"' or 'Attribute = Value' or 163110152Satgutier@umich.edu // 'Attribute = 'Value''. 163210152Satgutier@umich.edu case eTokenText: 163310152Satgutier@umich.edu case eTokenQuotedText: 163410152Satgutier@umich.edu // If we are a declaration element '<?' then we need 163510152Satgutier@umich.edu // to remove extra closing '?' if it exists 163610152Satgutier@umich.edu if (d->isDeclaration && 163710152Satgutier@umich.edu (token.pStr[cbToken-1]) == _CXML('?')) 163810152Satgutier@umich.edu { 163910152Satgutier@umich.edu cbToken--; 164010152Satgutier@umich.edu } 164110152Satgutier@umich.edu 164210152Satgutier@umich.edu if (cbTemp) 164310152Satgutier@umich.edu { 164410152Satgutier@umich.edu // Add the valued attribute to the list 164510152Satgutier@umich.edu if (xtype==eTokenQuotedText) { token.pStr++; cbToken-=2; } 164610152Satgutier@umich.edu XMLSTR attrVal=(XMLSTR)token.pStr; 164710152Satgutier@umich.edu if (attrVal) 164810152Satgutier@umich.edu { 164910152Satgutier@umich.edu attrVal=fromXMLString(attrVal,cbToken,pXML); 165010152Satgutier@umich.edu if (!attrVal) return FALSE; 165110152Satgutier@umich.edu } 165210152Satgutier@umich.edu addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp),attrVal); 165310152Satgutier@umich.edu } 165410152Satgutier@umich.edu 165510152Satgutier@umich.edu // Indicate we are searching for a new attribute 165610152Satgutier@umich.edu attrib = eAttribName; 165710152Satgutier@umich.edu break; 165810152Satgutier@umich.edu 165910152Satgutier@umich.edu // Errors... 166010152Satgutier@umich.edu case eTokenTagStart: /* 'Attr = <' */ 166110152Satgutier@umich.edu case eTokenTagEnd: /* 'Attr = </' */ 166210152Satgutier@umich.edu case eTokenCloseTag: /* 'Attr = >' */ 166310152Satgutier@umich.edu case eTokenShortHandClose: /* "Attr = />" */ 166410152Satgutier@umich.edu case eTokenEquals: /* 'Attr = =' */ 166510152Satgutier@umich.edu case eTokenDeclaration: /* 'Attr = <?' */ 166610152Satgutier@umich.edu case eTokenClear: 166710152Satgutier@umich.edu pXML->error = eXMLErrorUnexpectedToken; 166810152Satgutier@umich.edu return FALSE; 166910152Satgutier@umich.edu break; 167010152Satgutier@umich.edu default: break; 167110152Satgutier@umich.edu } 167210152Satgutier@umich.edu } 167310152Satgutier@umich.edu } 167410152Satgutier@umich.edu } 167510152Satgutier@umich.edu // If we failed to obtain the next token 167610152Satgutier@umich.edu else 167710152Satgutier@umich.edu { 167810152Satgutier@umich.edu if ((!d->isDeclaration)&&(d->pParent)) 167910152Satgutier@umich.edu { 168010152Satgutier@umich.edu#ifdef STRICT_PARSING 168110152Satgutier@umich.edu pXML->error=eXMLErrorUnmatchedEndTag; 168210152Satgutier@umich.edu#else 168310152Satgutier@umich.edu pXML->error=eXMLErrorMissingEndTag; 168410152Satgutier@umich.edu#endif 168510152Satgutier@umich.edu pXML->nIndexMissigEndTag=pXML->nIndex; 168610152Satgutier@umich.edu } 168710152Satgutier@umich.edu maybeAddTxT(pXML,pXML->lpXML+pXML->nIndex); 168810152Satgutier@umich.edu return FALSE; 168910152Satgutier@umich.edu } 169010152Satgutier@umich.edu } 169110152Satgutier@umich.edu} 169210152Satgutier@umich.edu 169310152Satgutier@umich.edu// Count the number of lines and columns in an XML string. 169410152Satgutier@umich.edustatic void CountLinesAndColumns(XMLCSTR lpXML, int nUpto, XMLResults *pResults) 169510152Satgutier@umich.edu{ 169610152Satgutier@umich.edu XMLCHAR ch; 169710152Satgutier@umich.edu assert(lpXML); 169810152Satgutier@umich.edu assert(pResults); 169910152Satgutier@umich.edu 170010152Satgutier@umich.edu struct XML xml={ lpXML,lpXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0, TRUE }; 170110152Satgutier@umich.edu 170210152Satgutier@umich.edu pResults->nLine = 1; 170310152Satgutier@umich.edu pResults->nColumn = 1; 170410152Satgutier@umich.edu while (xml.nIndex<nUpto) 170510152Satgutier@umich.edu { 170610152Satgutier@umich.edu ch = getNextChar(&xml); 170710152Satgutier@umich.edu if (ch != _CXML('\n')) pResults->nColumn++; 170810152Satgutier@umich.edu else 170910152Satgutier@umich.edu { 171010152Satgutier@umich.edu pResults->nLine++; 171110152Satgutier@umich.edu pResults->nColumn=1; 171210152Satgutier@umich.edu } 171310152Satgutier@umich.edu } 171410152Satgutier@umich.edu} 171510152Satgutier@umich.edu 171610152Satgutier@umich.edu// Parse XML and return the root element. 171710152Satgutier@umich.eduXMLNode XMLNode::parseString(XMLCSTR lpszXML, XMLCSTR tag, XMLResults *pResults) 171810152Satgutier@umich.edu{ 171910152Satgutier@umich.edu if (!lpszXML) 172010152Satgutier@umich.edu { 172110152Satgutier@umich.edu if (pResults) 172210152Satgutier@umich.edu { 172310152Satgutier@umich.edu pResults->error=eXMLErrorNoElements; 172410152Satgutier@umich.edu pResults->nLine=0; 172510152Satgutier@umich.edu pResults->nColumn=0; 172610152Satgutier@umich.edu } 172710152Satgutier@umich.edu return emptyXMLNode; 172810152Satgutier@umich.edu } 172910152Satgutier@umich.edu 173010152Satgutier@umich.edu XMLNode xnode(NULL,NULL,FALSE); 173110152Satgutier@umich.edu struct XML xml={ lpszXML, lpszXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0, TRUE }; 173210152Satgutier@umich.edu 173310152Satgutier@umich.edu // Create header element 173410152Satgutier@umich.edu xnode.ParseXMLElement(&xml); 173510152Satgutier@umich.edu enum XMLError error = xml.error; 173610152Satgutier@umich.edu if (!xnode.nChildNode()) error=eXMLErrorNoXMLTagFound; 173710152Satgutier@umich.edu if ((xnode.nChildNode()==1)&&(xnode.nElement()==1)) xnode=xnode.getChildNode(); // skip the empty node 173810152Satgutier@umich.edu 173910152Satgutier@umich.edu // If no error occurred 174010152Satgutier@umich.edu if ((error==eXMLErrorNone)||(error==eXMLErrorMissingEndTag)||(error==eXMLErrorNoXMLTagFound)) 174110152Satgutier@umich.edu { 174210152Satgutier@umich.edu XMLCSTR name=xnode.getName(); 174310152Satgutier@umich.edu if (tag&&(*tag)&&((!name)||(xstricmp(name,tag)))) 174410152Satgutier@umich.edu { 174510152Satgutier@umich.edu xnode=xnode.getChildNode(tag); 174610152Satgutier@umich.edu if (xnode.isEmpty()) 174710152Satgutier@umich.edu { 174810152Satgutier@umich.edu if (pResults) 174910152Satgutier@umich.edu { 175010152Satgutier@umich.edu pResults->error=eXMLErrorFirstTagNotFound; 175110152Satgutier@umich.edu pResults->nLine=0; 175210152Satgutier@umich.edu pResults->nColumn=0; 175310152Satgutier@umich.edu } 175410152Satgutier@umich.edu return emptyXMLNode; 175510152Satgutier@umich.edu } 175610152Satgutier@umich.edu } 175710152Satgutier@umich.edu } else 175810152Satgutier@umich.edu { 175910152Satgutier@umich.edu // Cleanup: this will destroy all the nodes 176010152Satgutier@umich.edu xnode = emptyXMLNode; 176110152Satgutier@umich.edu } 176210152Satgutier@umich.edu 176310152Satgutier@umich.edu 176410152Satgutier@umich.edu // If we have been given somewhere to place results 176510152Satgutier@umich.edu if (pResults) 176610152Satgutier@umich.edu { 176710152Satgutier@umich.edu pResults->error = error; 176810152Satgutier@umich.edu 176910152Satgutier@umich.edu // If we have an error 177010152Satgutier@umich.edu if (error!=eXMLErrorNone) 177110152Satgutier@umich.edu { 177210152Satgutier@umich.edu if (error==eXMLErrorMissingEndTag) xml.nIndex=xml.nIndexMissigEndTag; 177310152Satgutier@umich.edu // Find which line and column it starts on. 177410152Satgutier@umich.edu CountLinesAndColumns(xml.lpXML, xml.nIndex, pResults); 177510152Satgutier@umich.edu } 177610152Satgutier@umich.edu } 177710152Satgutier@umich.edu return xnode; 177810152Satgutier@umich.edu} 177910152Satgutier@umich.edu 178010152Satgutier@umich.eduXMLNode XMLNode::parseFile(XMLCSTR filename, XMLCSTR tag, XMLResults *pResults) 178110152Satgutier@umich.edu{ 178210152Satgutier@umich.edu if (pResults) { pResults->nLine=0; pResults->nColumn=0; } 178310152Satgutier@umich.edu FILE *f=xfopen(filename,_CXML("rb")); 178410152Satgutier@umich.edu if (f==NULL) { if (pResults) pResults->error=eXMLErrorFileNotFound; return emptyXMLNode; } 178510152Satgutier@umich.edu fseek(f,0,SEEK_END); 178610152Satgutier@umich.edu int l=ftell(f),headerSz=0; 178710152Satgutier@umich.edu if (!l) { if (pResults) pResults->error=eXMLErrorEmpty; fclose(f); return emptyXMLNode; } 178810152Satgutier@umich.edu fseek(f,0,SEEK_SET); 178910152Satgutier@umich.edu unsigned char *buf=(unsigned char*)malloc(l+4); 179010152Satgutier@umich.edu l=fread(buf,1,l,f); 179110152Satgutier@umich.edu fclose(f); 179210152Satgutier@umich.edu buf[l]=0;buf[l+1]=0;buf[l+2]=0;buf[l+3]=0; 179310152Satgutier@umich.edu#ifdef _XMLWIDECHAR 179410152Satgutier@umich.edu if (guessWideCharChars) 179510152Satgutier@umich.edu { 179610152Satgutier@umich.edu if (!myIsTextWideChar(buf,l)) 179710152Satgutier@umich.edu { 179810152Satgutier@umich.edu XMLNode::XMLCharEncoding ce=XMLNode::char_encoding_legacy; 179910152Satgutier@umich.edu if ((buf[0]==0xef)&&(buf[1]==0xbb)&&(buf[2]==0xbf)) { headerSz=3; ce=XMLNode::char_encoding_UTF8; } 180010152Satgutier@umich.edu XMLSTR b2=myMultiByteToWideChar((const char*)(buf+headerSz),ce); 180110152Satgutier@umich.edu free(buf); buf=(unsigned char*)b2; headerSz=0; 180210152Satgutier@umich.edu } else 180310152Satgutier@umich.edu { 180410152Satgutier@umich.edu if ((buf[0]==0xef)&&(buf[1]==0xff)) headerSz=2; 180510152Satgutier@umich.edu if ((buf[0]==0xff)&&(buf[1]==0xfe)) headerSz=2; 180610152Satgutier@umich.edu } 180710152Satgutier@umich.edu } 180810152Satgutier@umich.edu#else 180910152Satgutier@umich.edu if (guessWideCharChars) 181010152Satgutier@umich.edu { 181110152Satgutier@umich.edu if (myIsTextWideChar(buf,l)) 181210152Satgutier@umich.edu { 181310152Satgutier@umich.edu if ((buf[0]==0xef)&&(buf[1]==0xff)) headerSz=2; 181410152Satgutier@umich.edu if ((buf[0]==0xff)&&(buf[1]==0xfe)) headerSz=2; 181510152Satgutier@umich.edu char *b2=myWideCharToMultiByte((const wchar_t*)(buf+headerSz)); 181610152Satgutier@umich.edu free(buf); buf=(unsigned char*)b2; headerSz=0; 181710152Satgutier@umich.edu } else 181810152Satgutier@umich.edu { 181910152Satgutier@umich.edu if ((buf[0]==0xef)&&(buf[1]==0xbb)&&(buf[2]==0xbf)) headerSz=3; 182010152Satgutier@umich.edu } 182110152Satgutier@umich.edu } 182210152Satgutier@umich.edu#endif 182310152Satgutier@umich.edu 182410152Satgutier@umich.edu if (!buf) { if (pResults) pResults->error=eXMLErrorCharConversionError; return emptyXMLNode; } 182510152Satgutier@umich.edu XMLNode x=parseString((XMLSTR)(buf+headerSz),tag,pResults); 182610152Satgutier@umich.edu free(buf); 182710152Satgutier@umich.edu return x; 182810152Satgutier@umich.edu} 182910152Satgutier@umich.edu 183010152Satgutier@umich.edustatic inline void charmemset(XMLSTR dest,XMLCHAR c,int l) { while (l--) *(dest++)=c; } 183110152Satgutier@umich.edu// private: 183210152Satgutier@umich.edu// Creates an user friendly XML string from a given element with 183310152Satgutier@umich.edu// appropriate white space and carriage returns. 183410152Satgutier@umich.edu// 183510152Satgutier@umich.edu// This recurses through all subnodes then adds contents of the nodes to the 183610152Satgutier@umich.edu// string. 183710152Satgutier@umich.eduint XMLNode::CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker, int nFormat) 183810152Satgutier@umich.edu{ 183910152Satgutier@umich.edu int nResult = 0; 184010152Satgutier@umich.edu int cb=nFormat<0?0:nFormat; 184110152Satgutier@umich.edu int cbElement; 184210152Satgutier@umich.edu int nChildFormat=-1; 184310152Satgutier@umich.edu int nElementI=pEntry->nChild+pEntry->nText+pEntry->nClear; 184410152Satgutier@umich.edu int i,j; 184510152Satgutier@umich.edu if ((nFormat>=0)&&(nElementI==1)&&(pEntry->nText==1)&&(!pEntry->isDeclaration)) nFormat=-2; 184610152Satgutier@umich.edu 184710152Satgutier@umich.edu assert(pEntry); 184810152Satgutier@umich.edu 184910152Satgutier@umich.edu#define LENSTR(lpsz) (lpsz ? xstrlen(lpsz) : 0) 185010152Satgutier@umich.edu 185110152Satgutier@umich.edu // If the element has no name then assume this is the head node. 185210152Satgutier@umich.edu cbElement = (int)LENSTR(pEntry->lpszName); 185310152Satgutier@umich.edu 185410152Satgutier@umich.edu if (cbElement) 185510152Satgutier@umich.edu { 185610152Satgutier@umich.edu // "<elementname " 185710152Satgutier@umich.edu if (lpszMarker) 185810152Satgutier@umich.edu { 185910152Satgutier@umich.edu if (cb) charmemset(lpszMarker, INDENTCHAR, cb); 186010152Satgutier@umich.edu nResult = cb; 186110152Satgutier@umich.edu lpszMarker[nResult++]=_CXML('<'); 186210152Satgutier@umich.edu if (pEntry->isDeclaration) lpszMarker[nResult++]=_CXML('?'); 186310152Satgutier@umich.edu xstrcpy(&lpszMarker[nResult], pEntry->lpszName); 186410152Satgutier@umich.edu nResult+=cbElement; 186510152Satgutier@umich.edu lpszMarker[nResult++]=_CXML(' '); 186610152Satgutier@umich.edu 186710152Satgutier@umich.edu } else 186810152Satgutier@umich.edu { 186910152Satgutier@umich.edu nResult+=cbElement+2+cb; 187010152Satgutier@umich.edu if (pEntry->isDeclaration) nResult++; 187110152Satgutier@umich.edu } 187210152Satgutier@umich.edu 187310152Satgutier@umich.edu // Enumerate attributes and add them to the string 187410152Satgutier@umich.edu XMLAttribute *pAttr=pEntry->pAttribute; 187510152Satgutier@umich.edu for (i=0; i<pEntry->nAttribute; i++) 187610152Satgutier@umich.edu { 187710152Satgutier@umich.edu // "Attrib 187810152Satgutier@umich.edu cb = (int)LENSTR(pAttr->lpszName); 187910152Satgutier@umich.edu if (cb) 188010152Satgutier@umich.edu { 188110152Satgutier@umich.edu if (lpszMarker) xstrcpy(&lpszMarker[nResult], pAttr->lpszName); 188210152Satgutier@umich.edu nResult += cb; 188310152Satgutier@umich.edu // "Attrib=Value " 188410152Satgutier@umich.edu if (pAttr->lpszValue) 188510152Satgutier@umich.edu { 188610152Satgutier@umich.edu cb=(int)ToXMLStringTool::lengthXMLString(pAttr->lpszValue); 188710152Satgutier@umich.edu if (lpszMarker) 188810152Satgutier@umich.edu { 188910152Satgutier@umich.edu lpszMarker[nResult]=_CXML('='); 189010152Satgutier@umich.edu lpszMarker[nResult+1]=_CXML('"'); 189110152Satgutier@umich.edu if (cb) ToXMLStringTool::toXMLUnSafe(&lpszMarker[nResult+2],pAttr->lpszValue); 189210152Satgutier@umich.edu lpszMarker[nResult+cb+2]=_CXML('"'); 189310152Satgutier@umich.edu } 189410152Satgutier@umich.edu nResult+=cb+3; 189510152Satgutier@umich.edu } 189610152Satgutier@umich.edu if (lpszMarker) lpszMarker[nResult] = _CXML(' '); 189710152Satgutier@umich.edu nResult++; 189810152Satgutier@umich.edu } 189910152Satgutier@umich.edu pAttr++; 190010152Satgutier@umich.edu } 190110152Satgutier@umich.edu 190210152Satgutier@umich.edu if (pEntry->isDeclaration) 190310152Satgutier@umich.edu { 190410152Satgutier@umich.edu if (lpszMarker) 190510152Satgutier@umich.edu { 190610152Satgutier@umich.edu lpszMarker[nResult-1]=_CXML('?'); 190710152Satgutier@umich.edu lpszMarker[nResult]=_CXML('>'); 190810152Satgutier@umich.edu } 190910152Satgutier@umich.edu nResult++; 191010152Satgutier@umich.edu if (nFormat!=-1) 191110152Satgutier@umich.edu { 191210152Satgutier@umich.edu if (lpszMarker) lpszMarker[nResult]=_CXML('\n'); 191310152Satgutier@umich.edu nResult++; 191410152Satgutier@umich.edu } 191510152Satgutier@umich.edu } else 191610152Satgutier@umich.edu // If there are child nodes we need to terminate the start tag 191710152Satgutier@umich.edu if (nElementI) 191810152Satgutier@umich.edu { 191910152Satgutier@umich.edu if (lpszMarker) lpszMarker[nResult-1]=_CXML('>'); 192010152Satgutier@umich.edu if (nFormat>=0) 192110152Satgutier@umich.edu { 192210152Satgutier@umich.edu if (lpszMarker) lpszMarker[nResult]=_CXML('\n'); 192310152Satgutier@umich.edu nResult++; 192410152Satgutier@umich.edu } 192510152Satgutier@umich.edu } else nResult--; 192610152Satgutier@umich.edu } 192710152Satgutier@umich.edu 192810152Satgutier@umich.edu // Calculate the child format for when we recurse. This is used to 192910152Satgutier@umich.edu // determine the number of spaces used for prefixes. 193010152Satgutier@umich.edu if (nFormat!=-1) 193110152Satgutier@umich.edu { 193210152Satgutier@umich.edu if (cbElement&&(!pEntry->isDeclaration)) nChildFormat=nFormat+1; 193310152Satgutier@umich.edu else nChildFormat=nFormat; 193410152Satgutier@umich.edu } 193510152Satgutier@umich.edu 193610152Satgutier@umich.edu // Enumerate through remaining children 193710152Satgutier@umich.edu for (i=0; i<nElementI; i++) 193810152Satgutier@umich.edu { 193910152Satgutier@umich.edu j=pEntry->pOrder[i]; 194010152Satgutier@umich.edu switch((XMLElementType)(j&3)) 194110152Satgutier@umich.edu { 194210152Satgutier@umich.edu // Text nodes 194310152Satgutier@umich.edu case eNodeText: 194410152Satgutier@umich.edu { 194510152Satgutier@umich.edu // "Text" 194610152Satgutier@umich.edu XMLCSTR pChild=pEntry->pText[j>>2]; 194710152Satgutier@umich.edu cb = (int)ToXMLStringTool::lengthXMLString(pChild); 194810152Satgutier@umich.edu if (cb) 194910152Satgutier@umich.edu { 195010152Satgutier@umich.edu if (nFormat>=0) 195110152Satgutier@umich.edu { 195210152Satgutier@umich.edu if (lpszMarker) 195310152Satgutier@umich.edu { 195410152Satgutier@umich.edu charmemset(&lpszMarker[nResult],INDENTCHAR,nFormat+1); 195510152Satgutier@umich.edu ToXMLStringTool::toXMLUnSafe(&lpszMarker[nResult+nFormat+1],pChild); 195610152Satgutier@umich.edu lpszMarker[nResult+nFormat+1+cb]=_CXML('\n'); 195710152Satgutier@umich.edu } 195810152Satgutier@umich.edu nResult+=cb+nFormat+2; 195910152Satgutier@umich.edu } else 196010152Satgutier@umich.edu { 196110152Satgutier@umich.edu if (lpszMarker) ToXMLStringTool::toXMLUnSafe(&lpszMarker[nResult], pChild); 196210152Satgutier@umich.edu nResult += cb; 196310152Satgutier@umich.edu } 196410152Satgutier@umich.edu } 196510152Satgutier@umich.edu break; 196610152Satgutier@umich.edu } 196710152Satgutier@umich.edu 196810152Satgutier@umich.edu // Clear type nodes 196910152Satgutier@umich.edu case eNodeClear: 197010152Satgutier@umich.edu { 197110152Satgutier@umich.edu XMLClear *pChild=pEntry->pClear+(j>>2); 197210152Satgutier@umich.edu // "OpenTag" 197310152Satgutier@umich.edu cb = (int)LENSTR(pChild->lpszOpenTag); 197410152Satgutier@umich.edu if (cb) 197510152Satgutier@umich.edu { 197610152Satgutier@umich.edu if (nFormat!=-1) 197710152Satgutier@umich.edu { 197810152Satgutier@umich.edu if (lpszMarker) 197910152Satgutier@umich.edu { 198010152Satgutier@umich.edu charmemset(&lpszMarker[nResult], INDENTCHAR, nFormat+1); 198110152Satgutier@umich.edu xstrcpy(&lpszMarker[nResult+nFormat+1], pChild->lpszOpenTag); 198210152Satgutier@umich.edu } 198310152Satgutier@umich.edu nResult+=cb+nFormat+1; 198410152Satgutier@umich.edu } 198510152Satgutier@umich.edu else 198610152Satgutier@umich.edu { 198710152Satgutier@umich.edu if (lpszMarker)xstrcpy(&lpszMarker[nResult], pChild->lpszOpenTag); 198810152Satgutier@umich.edu nResult += cb; 198910152Satgutier@umich.edu } 199010152Satgutier@umich.edu } 199110152Satgutier@umich.edu 199210152Satgutier@umich.edu // "OpenTag Value" 199310152Satgutier@umich.edu cb = (int)LENSTR(pChild->lpszValue); 199410152Satgutier@umich.edu if (cb) 199510152Satgutier@umich.edu { 199610152Satgutier@umich.edu if (lpszMarker) xstrcpy(&lpszMarker[nResult], pChild->lpszValue); 199710152Satgutier@umich.edu nResult += cb; 199810152Satgutier@umich.edu } 199910152Satgutier@umich.edu 200010152Satgutier@umich.edu // "OpenTag Value CloseTag" 200110152Satgutier@umich.edu cb = (int)LENSTR(pChild->lpszCloseTag); 200210152Satgutier@umich.edu if (cb) 200310152Satgutier@umich.edu { 200410152Satgutier@umich.edu if (lpszMarker) xstrcpy(&lpszMarker[nResult], pChild->lpszCloseTag); 200510152Satgutier@umich.edu nResult += cb; 200610152Satgutier@umich.edu } 200710152Satgutier@umich.edu 200810152Satgutier@umich.edu if (nFormat!=-1) 200910152Satgutier@umich.edu { 201010152Satgutier@umich.edu if (lpszMarker) lpszMarker[nResult] = _CXML('\n'); 201110152Satgutier@umich.edu nResult++; 201210152Satgutier@umich.edu } 201310152Satgutier@umich.edu break; 201410152Satgutier@umich.edu } 201510152Satgutier@umich.edu 201610152Satgutier@umich.edu // Element nodes 201710152Satgutier@umich.edu case eNodeChild: 201810152Satgutier@umich.edu { 201910152Satgutier@umich.edu // Recursively add child nodes 202010152Satgutier@umich.edu nResult += CreateXMLStringR(pEntry->pChild[j>>2].d, lpszMarker ? lpszMarker + nResult : 0, nChildFormat); 202110152Satgutier@umich.edu break; 202210152Satgutier@umich.edu } 202310152Satgutier@umich.edu default: break; 202410152Satgutier@umich.edu } 202510152Satgutier@umich.edu } 202610152Satgutier@umich.edu 202710152Satgutier@umich.edu if ((cbElement)&&(!pEntry->isDeclaration)) 202810152Satgutier@umich.edu { 202910152Satgutier@umich.edu // If we have child entries we need to use long XML notation for 203010152Satgutier@umich.edu // closing the element - "<elementname>blah blah blah</elementname>" 203110152Satgutier@umich.edu if (nElementI) 203210152Satgutier@umich.edu { 203310152Satgutier@umich.edu // "</elementname>\0" 203410152Satgutier@umich.edu if (lpszMarker) 203510152Satgutier@umich.edu { 203610152Satgutier@umich.edu if (nFormat >=0) 203710152Satgutier@umich.edu { 203810152Satgutier@umich.edu charmemset(&lpszMarker[nResult], INDENTCHAR,nFormat); 203910152Satgutier@umich.edu nResult+=nFormat; 204010152Satgutier@umich.edu } 204110152Satgutier@umich.edu 204210152Satgutier@umich.edu lpszMarker[nResult]=_CXML('<'); lpszMarker[nResult+1]=_CXML('/'); 204310152Satgutier@umich.edu nResult += 2; 204410152Satgutier@umich.edu xstrcpy(&lpszMarker[nResult], pEntry->lpszName); 204510152Satgutier@umich.edu nResult += cbElement; 204610152Satgutier@umich.edu 204710152Satgutier@umich.edu lpszMarker[nResult]=_CXML('>'); 204810152Satgutier@umich.edu if (nFormat == -1) nResult++; 204910152Satgutier@umich.edu else 205010152Satgutier@umich.edu { 205110152Satgutier@umich.edu lpszMarker[nResult+1]=_CXML('\n'); 205210152Satgutier@umich.edu nResult+=2; 205310152Satgutier@umich.edu } 205410152Satgutier@umich.edu } else 205510152Satgutier@umich.edu { 205610152Satgutier@umich.edu if (nFormat>=0) nResult+=cbElement+4+nFormat; 205710152Satgutier@umich.edu else if (nFormat==-1) nResult+=cbElement+3; 205810152Satgutier@umich.edu else nResult+=cbElement+4; 205910152Satgutier@umich.edu } 206010152Satgutier@umich.edu } else 206110152Satgutier@umich.edu { 206210152Satgutier@umich.edu // If there are no children we can use shorthand XML notation - 206310152Satgutier@umich.edu // "<elementname/>" 206410152Satgutier@umich.edu // "/>\0" 206510152Satgutier@umich.edu if (lpszMarker) 206610152Satgutier@umich.edu { 206710152Satgutier@umich.edu lpszMarker[nResult]=_CXML('/'); lpszMarker[nResult+1]=_CXML('>'); 206810152Satgutier@umich.edu if (nFormat != -1) lpszMarker[nResult+2]=_CXML('\n'); 206910152Satgutier@umich.edu } 207010152Satgutier@umich.edu nResult += nFormat == -1 ? 2 : 3; 207110152Satgutier@umich.edu } 207210152Satgutier@umich.edu } 207310152Satgutier@umich.edu 207410152Satgutier@umich.edu return nResult; 207510152Satgutier@umich.edu} 207610152Satgutier@umich.edu 207710152Satgutier@umich.edu#undef LENSTR 207810152Satgutier@umich.edu 207910152Satgutier@umich.edu// Create an XML string 208010152Satgutier@umich.edu// @param int nFormat - 0 if no formatting is required 208110152Satgutier@umich.edu// otherwise nonzero for formatted text 208210152Satgutier@umich.edu// with carriage returns and indentation. 208310152Satgutier@umich.edu// @param int *pnSize - [out] pointer to the size of the 208410152Satgutier@umich.edu// returned string not including the 208510152Satgutier@umich.edu// NULL terminator. 208610152Satgutier@umich.edu// @return XMLSTR - Allocated XML string, you must free 208710152Satgutier@umich.edu// this with free(). 208810152Satgutier@umich.eduXMLSTR XMLNode::createXMLString(int nFormat, int *pnSize) const 208910152Satgutier@umich.edu{ 209010152Satgutier@umich.edu if (!d) { if (pnSize) *pnSize=0; return NULL; } 209110152Satgutier@umich.edu 209210152Satgutier@umich.edu XMLSTR lpszResult = NULL; 209310152Satgutier@umich.edu int cbStr; 209410152Satgutier@umich.edu 209510152Satgutier@umich.edu // Recursively Calculate the size of the XML string 209610152Satgutier@umich.edu if (!dropWhiteSpace) nFormat=0; 209710152Satgutier@umich.edu nFormat = nFormat ? 0 : -1; 209810152Satgutier@umich.edu cbStr = CreateXMLStringR(d, 0, nFormat); 209910152Satgutier@umich.edu // Alllocate memory for the XML string + the NULL terminator and 210010152Satgutier@umich.edu // create the recursively XML string. 210110152Satgutier@umich.edu lpszResult=(XMLSTR)malloc((cbStr+1)*sizeof(XMLCHAR)); 210210152Satgutier@umich.edu CreateXMLStringR(d, lpszResult, nFormat); 210310152Satgutier@umich.edu lpszResult[cbStr]=_CXML('\0'); 210410152Satgutier@umich.edu if (pnSize) *pnSize = cbStr; 210510152Satgutier@umich.edu return lpszResult; 210610152Satgutier@umich.edu} 210710152Satgutier@umich.edu 210810152Satgutier@umich.eduint XMLNode::detachFromParent(XMLNodeData *d) 210910152Satgutier@umich.edu{ 211010152Satgutier@umich.edu XMLNode *pa=d->pParent->pChild; 211110152Satgutier@umich.edu int i=0; 211210152Satgutier@umich.edu while (((void*)(pa[i].d))!=((void*)d)) i++; 211310152Satgutier@umich.edu d->pParent->nChild--; 211410152Satgutier@umich.edu if (d->pParent->nChild) memmove(pa+i,pa+i+1,(d->pParent->nChild-i)*sizeof(XMLNode)); 211510152Satgutier@umich.edu else { free(pa); d->pParent->pChild=NULL; } 211610152Satgutier@umich.edu return removeOrderElement(d->pParent,eNodeChild,i); 211710152Satgutier@umich.edu} 211810152Satgutier@umich.edu 211910152Satgutier@umich.eduXMLNode::~XMLNode() 212010152Satgutier@umich.edu{ 212110152Satgutier@umich.edu if (!d) return; 212210152Satgutier@umich.edu d->ref_count--; 212310152Satgutier@umich.edu emptyTheNode(0); 212410152Satgutier@umich.edu} 212510152Satgutier@umich.eduvoid XMLNode::deleteNodeContent() 212610152Satgutier@umich.edu{ 212710152Satgutier@umich.edu if (!d) return; 212810152Satgutier@umich.edu if (d->pParent) { detachFromParent(d); d->pParent=NULL; d->ref_count--; } 212910152Satgutier@umich.edu emptyTheNode(1); 213010152Satgutier@umich.edu} 213110152Satgutier@umich.eduvoid XMLNode::emptyTheNode(char force) 213210152Satgutier@umich.edu{ 213310152Satgutier@umich.edu XMLNodeData *dd=d; // warning: must stay this way! 213410152Satgutier@umich.edu if ((dd->ref_count==0)||force) 213510152Satgutier@umich.edu { 213610152Satgutier@umich.edu if (d->pParent) detachFromParent(d); 213710152Satgutier@umich.edu int i; 213810152Satgutier@umich.edu XMLNode *pc; 213910152Satgutier@umich.edu for(i=0; i<dd->nChild; i++) 214010152Satgutier@umich.edu { 214110152Satgutier@umich.edu pc=dd->pChild+i; 214210152Satgutier@umich.edu pc->d->pParent=NULL; 214310152Satgutier@umich.edu pc->d->ref_count--; 214410152Satgutier@umich.edu pc->emptyTheNode(force); 214510152Satgutier@umich.edu } 214610152Satgutier@umich.edu myFree(dd->pChild); 214710152Satgutier@umich.edu for(i=0; i<dd->nText; i++) free((void*)dd->pText[i]); 214810152Satgutier@umich.edu myFree(dd->pText); 214910152Satgutier@umich.edu for(i=0; i<dd->nClear; i++) free((void*)dd->pClear[i].lpszValue); 215010152Satgutier@umich.edu myFree(dd->pClear); 215110152Satgutier@umich.edu for(i=0; i<dd->nAttribute; i++) 215210152Satgutier@umich.edu { 215310152Satgutier@umich.edu free((void*)dd->pAttribute[i].lpszName); 215410152Satgutier@umich.edu if (dd->pAttribute[i].lpszValue) free((void*)dd->pAttribute[i].lpszValue); 215510152Satgutier@umich.edu } 215610152Satgutier@umich.edu myFree(dd->pAttribute); 215710152Satgutier@umich.edu myFree(dd->pOrder); 215810152Satgutier@umich.edu myFree((void*)dd->lpszName); 215910152Satgutier@umich.edu dd->nChild=0; dd->nText=0; dd->nClear=0; dd->nAttribute=0; 216010152Satgutier@umich.edu dd->pChild=NULL; dd->pText=NULL; dd->pClear=NULL; dd->pAttribute=NULL; 216110152Satgutier@umich.edu dd->pOrder=NULL; dd->lpszName=NULL; dd->pParent=NULL; 216210152Satgutier@umich.edu } 216310152Satgutier@umich.edu if (dd->ref_count==0) 216410152Satgutier@umich.edu { 216510152Satgutier@umich.edu free(dd); 216610152Satgutier@umich.edu d=NULL; 216710152Satgutier@umich.edu } 216810152Satgutier@umich.edu} 216910152Satgutier@umich.edu 217010152Satgutier@umich.eduXMLNode& XMLNode::operator=( const XMLNode& A ) 217110152Satgutier@umich.edu{ 217210152Satgutier@umich.edu // shallow copy 217310152Satgutier@umich.edu if (this != &A) 217410152Satgutier@umich.edu { 217510152Satgutier@umich.edu if (d) { d->ref_count--; emptyTheNode(0); } 217610152Satgutier@umich.edu d=A.d; 217710152Satgutier@umich.edu if (d) (d->ref_count) ++ ; 217810152Satgutier@umich.edu } 217910152Satgutier@umich.edu return *this; 218010152Satgutier@umich.edu} 218110152Satgutier@umich.edu 218210152Satgutier@umich.eduXMLNode::XMLNode(const XMLNode &A) 218310152Satgutier@umich.edu{ 218410152Satgutier@umich.edu // shallow copy 218510152Satgutier@umich.edu d=A.d; 218610152Satgutier@umich.edu if (d) (d->ref_count)++ ; 218710152Satgutier@umich.edu} 218810152Satgutier@umich.edu 218910152Satgutier@umich.eduXMLNode XMLNode::deepCopy() const 219010152Satgutier@umich.edu{ 219110152Satgutier@umich.edu if (!d) return XMLNode::emptyXMLNode; 219210152Satgutier@umich.edu XMLNode x(NULL,stringDup(d->lpszName),d->isDeclaration); 219310152Satgutier@umich.edu XMLNodeData *p=x.d; 219410152Satgutier@umich.edu int n=d->nAttribute; 219510152Satgutier@umich.edu if (n) 219610152Satgutier@umich.edu { 219710152Satgutier@umich.edu p->nAttribute=n; p->pAttribute=(XMLAttribute*)malloc(n*sizeof(XMLAttribute)); 219810152Satgutier@umich.edu while (n--) 219910152Satgutier@umich.edu { 220010152Satgutier@umich.edu p->pAttribute[n].lpszName=stringDup(d->pAttribute[n].lpszName); 220110152Satgutier@umich.edu p->pAttribute[n].lpszValue=stringDup(d->pAttribute[n].lpszValue); 220210152Satgutier@umich.edu } 220310152Satgutier@umich.edu } 220410152Satgutier@umich.edu if (d->pOrder) 220510152Satgutier@umich.edu { 220610152Satgutier@umich.edu n=(d->nChild+d->nText+d->nClear)*sizeof(int); p->pOrder=(int*)malloc(n); memcpy(p->pOrder,d->pOrder,n); 220710152Satgutier@umich.edu } 220810152Satgutier@umich.edu n=d->nText; 220910152Satgutier@umich.edu if (n) 221010152Satgutier@umich.edu { 221110152Satgutier@umich.edu p->nText=n; p->pText=(XMLCSTR*)malloc(n*sizeof(XMLCSTR)); 221210152Satgutier@umich.edu while(n--) p->pText[n]=stringDup(d->pText[n]); 221310152Satgutier@umich.edu } 221410152Satgutier@umich.edu n=d->nClear; 221510152Satgutier@umich.edu if (n) 221610152Satgutier@umich.edu { 221710152Satgutier@umich.edu p->nClear=n; p->pClear=(XMLClear*)malloc(n*sizeof(XMLClear)); 221810152Satgutier@umich.edu while (n--) 221910152Satgutier@umich.edu { 222010152Satgutier@umich.edu p->pClear[n].lpszCloseTag=d->pClear[n].lpszCloseTag; 222110152Satgutier@umich.edu p->pClear[n].lpszOpenTag=d->pClear[n].lpszOpenTag; 222210152Satgutier@umich.edu p->pClear[n].lpszValue=stringDup(d->pClear[n].lpszValue); 222310152Satgutier@umich.edu } 222410152Satgutier@umich.edu } 222510152Satgutier@umich.edu n=d->nChild; 222610152Satgutier@umich.edu if (n) 222710152Satgutier@umich.edu { 222810152Satgutier@umich.edu p->nChild=n; p->pChild=(XMLNode*)malloc(n*sizeof(XMLNode)); 222910152Satgutier@umich.edu while (n--) 223010152Satgutier@umich.edu { 223110152Satgutier@umich.edu p->pChild[n].d=NULL; 223210152Satgutier@umich.edu p->pChild[n]=d->pChild[n].deepCopy(); 223310152Satgutier@umich.edu p->pChild[n].d->pParent=p; 223410152Satgutier@umich.edu } 223510152Satgutier@umich.edu } 223610152Satgutier@umich.edu return x; 223710152Satgutier@umich.edu} 223810152Satgutier@umich.edu 223910152Satgutier@umich.eduXMLNode XMLNode::addChild(XMLNode childNode, int pos) 224010152Satgutier@umich.edu{ 224110152Satgutier@umich.edu XMLNodeData *dc=childNode.d; 224210152Satgutier@umich.edu if ((!dc)||(!d)) return childNode; 224310152Satgutier@umich.edu if (!dc->lpszName) 224410152Satgutier@umich.edu { 224510152Satgutier@umich.edu // this is a root node: todo: correct fix 224610152Satgutier@umich.edu int j=pos; 224710152Satgutier@umich.edu while (dc->nChild) 224810152Satgutier@umich.edu { 224910152Satgutier@umich.edu addChild(dc->pChild[0],j); 225010152Satgutier@umich.edu if (pos>=0) j++; 225110152Satgutier@umich.edu } 225210152Satgutier@umich.edu return childNode; 225310152Satgutier@umich.edu } 225410152Satgutier@umich.edu if (dc->pParent) { if ((detachFromParent(dc)<=pos)&&(dc->pParent==d)) pos--; } else dc->ref_count++; 225510152Satgutier@umich.edu dc->pParent=d; 225610152Satgutier@umich.edu// int nc=d->nChild; 225710152Satgutier@umich.edu// d->pChild=(XMLNode*)myRealloc(d->pChild,(nc+1),memoryIncrease,sizeof(XMLNode)); 225810152Satgutier@umich.edu d->pChild=(XMLNode*)addToOrder(0,&pos,d->nChild,d->pChild,sizeof(XMLNode),eNodeChild); 225910152Satgutier@umich.edu d->pChild[pos].d=dc; 226010152Satgutier@umich.edu d->nChild++; 226110152Satgutier@umich.edu return childNode; 226210152Satgutier@umich.edu} 226310152Satgutier@umich.edu 226410152Satgutier@umich.eduvoid XMLNode::deleteAttribute(int i) 226510152Satgutier@umich.edu{ 226610152Satgutier@umich.edu if ((!d)||(i<0)||(i>=d->nAttribute)) return; 226710152Satgutier@umich.edu d->nAttribute--; 226810152Satgutier@umich.edu XMLAttribute *p=d->pAttribute+i; 226910152Satgutier@umich.edu free((void*)p->lpszName); 227010152Satgutier@umich.edu if (p->lpszValue) free((void*)p->lpszValue); 227110152Satgutier@umich.edu if (d->nAttribute) memmove(p,p+1,(d->nAttribute-i)*sizeof(XMLAttribute)); else { free(p); d->pAttribute=NULL; } 227210152Satgutier@umich.edu} 227310152Satgutier@umich.edu 227410152Satgutier@umich.eduvoid XMLNode::deleteAttribute(XMLAttribute *a){ if (a) deleteAttribute(a->lpszName); } 227510152Satgutier@umich.eduvoid XMLNode::deleteAttribute(XMLCSTR lpszName) 227610152Satgutier@umich.edu{ 227710152Satgutier@umich.edu int j=0; 227810152Satgutier@umich.edu getAttribute(lpszName,&j); 227910152Satgutier@umich.edu if (j) deleteAttribute(j-1); 228010152Satgutier@umich.edu} 228110152Satgutier@umich.edu 228210152Satgutier@umich.eduXMLAttribute *XMLNode::updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName,int i) 228310152Satgutier@umich.edu{ 228410152Satgutier@umich.edu if (!d) { if (lpszNewValue) free(lpszNewValue); if (lpszNewName) free(lpszNewName); return NULL; } 228510152Satgutier@umich.edu if (i>=d->nAttribute) 228610152Satgutier@umich.edu { 228710152Satgutier@umich.edu if (lpszNewName) return addAttribute_WOSD(lpszNewName,lpszNewValue); 228810152Satgutier@umich.edu return NULL; 228910152Satgutier@umich.edu } 229010152Satgutier@umich.edu XMLAttribute *p=d->pAttribute+i; 229110152Satgutier@umich.edu if (p->lpszValue&&p->lpszValue!=lpszNewValue) free((void*)p->lpszValue); 229210152Satgutier@umich.edu p->lpszValue=lpszNewValue; 229310152Satgutier@umich.edu if (lpszNewName&&p->lpszName!=lpszNewName) { free((void*)p->lpszName); p->lpszName=lpszNewName; }; 229410152Satgutier@umich.edu return p; 229510152Satgutier@umich.edu} 229610152Satgutier@umich.edu 229710152Satgutier@umich.eduXMLAttribute *XMLNode::updateAttribute_WOSD(XMLAttribute *newAttribute, XMLAttribute *oldAttribute) 229810152Satgutier@umich.edu{ 229910152Satgutier@umich.edu if (oldAttribute) return updateAttribute_WOSD((XMLSTR)newAttribute->lpszValue,(XMLSTR)newAttribute->lpszName,oldAttribute->lpszName); 230010152Satgutier@umich.edu return addAttribute_WOSD((XMLSTR)newAttribute->lpszName,(XMLSTR)newAttribute->lpszValue); 230110152Satgutier@umich.edu} 230210152Satgutier@umich.edu 230310152Satgutier@umich.eduXMLAttribute *XMLNode::updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName,XMLCSTR lpszOldName) 230410152Satgutier@umich.edu{ 230510152Satgutier@umich.edu int j=0; 230610152Satgutier@umich.edu getAttribute(lpszOldName,&j); 230710152Satgutier@umich.edu if (j) return updateAttribute_WOSD(lpszNewValue,lpszNewName,j-1); 230810152Satgutier@umich.edu else 230910152Satgutier@umich.edu { 231010152Satgutier@umich.edu if (lpszNewName) return addAttribute_WOSD(lpszNewName,lpszNewValue); 231110152Satgutier@umich.edu else return addAttribute_WOSD(stringDup(lpszOldName),lpszNewValue); 231210152Satgutier@umich.edu } 231310152Satgutier@umich.edu} 231410152Satgutier@umich.edu 231510152Satgutier@umich.eduint XMLNode::indexText(XMLCSTR lpszValue) const 231610152Satgutier@umich.edu{ 231710152Satgutier@umich.edu if (!d) return -1; 231810152Satgutier@umich.edu int i,l=d->nText; 231910152Satgutier@umich.edu if (!lpszValue) { if (l) return 0; return -1; } 232010152Satgutier@umich.edu XMLCSTR *p=d->pText; 232110152Satgutier@umich.edu for (i=0; i<l; i++) if (lpszValue==p[i]) return i; 232210152Satgutier@umich.edu return -1; 232310152Satgutier@umich.edu} 232410152Satgutier@umich.edu 232510152Satgutier@umich.eduvoid XMLNode::deleteText(int i) 232610152Satgutier@umich.edu{ 232710152Satgutier@umich.edu if ((!d)||(i<0)||(i>=d->nText)) return; 232810152Satgutier@umich.edu d->nText--; 232910152Satgutier@umich.edu XMLCSTR *p=d->pText+i; 233010152Satgutier@umich.edu free((void*)*p); 233110152Satgutier@umich.edu if (d->nText) memmove(p,p+1,(d->nText-i)*sizeof(XMLCSTR)); else { free(p); d->pText=NULL; } 233210152Satgutier@umich.edu removeOrderElement(d,eNodeText,i); 233310152Satgutier@umich.edu} 233410152Satgutier@umich.edu 233510152Satgutier@umich.eduvoid XMLNode::deleteText(XMLCSTR lpszValue) { deleteText(indexText(lpszValue)); } 233610152Satgutier@umich.edu 233710152Satgutier@umich.eduXMLCSTR XMLNode::updateText_WOSD(XMLSTR lpszNewValue, int i) 233810152Satgutier@umich.edu{ 233910152Satgutier@umich.edu if (!d) { if (lpszNewValue) free(lpszNewValue); return NULL; } 234010152Satgutier@umich.edu if (i>=d->nText) return addText_WOSD(lpszNewValue); 234110152Satgutier@umich.edu XMLCSTR *p=d->pText+i; 234210152Satgutier@umich.edu if (*p!=lpszNewValue) { free((void*)*p); *p=lpszNewValue; } 234310152Satgutier@umich.edu return lpszNewValue; 234410152Satgutier@umich.edu} 234510152Satgutier@umich.edu 234610152Satgutier@umich.eduXMLCSTR XMLNode::updateText_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue) 234710152Satgutier@umich.edu{ 234810152Satgutier@umich.edu if (!d) { if (lpszNewValue) free(lpszNewValue); return NULL; } 234910152Satgutier@umich.edu int i=indexText(lpszOldValue); 235010152Satgutier@umich.edu if (i>=0) return updateText_WOSD(lpszNewValue,i); 235110152Satgutier@umich.edu return addText_WOSD(lpszNewValue); 235210152Satgutier@umich.edu} 235310152Satgutier@umich.edu 235410152Satgutier@umich.eduvoid XMLNode::deleteClear(int i) 235510152Satgutier@umich.edu{ 235610152Satgutier@umich.edu if ((!d)||(i<0)||(i>=d->nClear)) return; 235710152Satgutier@umich.edu d->nClear--; 235810152Satgutier@umich.edu XMLClear *p=d->pClear+i; 235910152Satgutier@umich.edu free((void*)p->lpszValue); 236010152Satgutier@umich.edu if (d->nClear) memmove(p,p+1,(d->nClear-i)*sizeof(XMLClear)); else { free(p); d->pClear=NULL; } 236110152Satgutier@umich.edu removeOrderElement(d,eNodeClear,i); 236210152Satgutier@umich.edu} 236310152Satgutier@umich.edu 236410152Satgutier@umich.eduint XMLNode::indexClear(XMLCSTR lpszValue) const 236510152Satgutier@umich.edu{ 236610152Satgutier@umich.edu if (!d) return -1; 236710152Satgutier@umich.edu int i,l=d->nClear; 236810152Satgutier@umich.edu if (!lpszValue) { if (l) return 0; return -1; } 236910152Satgutier@umich.edu XMLClear *p=d->pClear; 237010152Satgutier@umich.edu for (i=0; i<l; i++) if (lpszValue==p[i].lpszValue) return i; 237110152Satgutier@umich.edu return -1; 237210152Satgutier@umich.edu} 237310152Satgutier@umich.edu 237410152Satgutier@umich.eduvoid XMLNode::deleteClear(XMLCSTR lpszValue) { deleteClear(indexClear(lpszValue)); } 237510152Satgutier@umich.eduvoid XMLNode::deleteClear(XMLClear *a) { if (a) deleteClear(a->lpszValue); } 237610152Satgutier@umich.edu 237710152Satgutier@umich.eduXMLClear *XMLNode::updateClear_WOSD(XMLSTR lpszNewContent, int i) 237810152Satgutier@umich.edu{ 237910152Satgutier@umich.edu if (!d) { if (lpszNewContent) free(lpszNewContent); return NULL; } 238010152Satgutier@umich.edu if (i>=d->nClear) return addClear_WOSD(lpszNewContent); 238110152Satgutier@umich.edu XMLClear *p=d->pClear+i; 238210152Satgutier@umich.edu if (lpszNewContent!=p->lpszValue) { free((void*)p->lpszValue); p->lpszValue=lpszNewContent; } 238310152Satgutier@umich.edu return p; 238410152Satgutier@umich.edu} 238510152Satgutier@umich.edu 238610152Satgutier@umich.eduXMLClear *XMLNode::updateClear_WOSD(XMLSTR lpszNewContent, XMLCSTR lpszOldValue) 238710152Satgutier@umich.edu{ 238810152Satgutier@umich.edu if (!d) { if (lpszNewContent) free(lpszNewContent); return NULL; } 238910152Satgutier@umich.edu int i=indexClear(lpszOldValue); 239010152Satgutier@umich.edu if (i>=0) return updateClear_WOSD(lpszNewContent,i); 239110152Satgutier@umich.edu return addClear_WOSD(lpszNewContent); 239210152Satgutier@umich.edu} 239310152Satgutier@umich.edu 239410152Satgutier@umich.eduXMLClear *XMLNode::updateClear_WOSD(XMLClear *newP,XMLClear *oldP) 239510152Satgutier@umich.edu{ 239610152Satgutier@umich.edu if (oldP) return updateClear_WOSD((XMLSTR)newP->lpszValue,(XMLSTR)oldP->lpszValue); 239710152Satgutier@umich.edu return NULL; 239810152Satgutier@umich.edu} 239910152Satgutier@umich.edu 240010152Satgutier@umich.eduint XMLNode::nChildNode(XMLCSTR name) const 240110152Satgutier@umich.edu{ 240210152Satgutier@umich.edu if (!d) return 0; 240310152Satgutier@umich.edu int i,j=0,n=d->nChild; 240410152Satgutier@umich.edu XMLNode *pc=d->pChild; 240510152Satgutier@umich.edu for (i=0; i<n; i++) 240610152Satgutier@umich.edu { 240710152Satgutier@umich.edu if (xstricmp(pc->d->lpszName, name)==0) j++; 240810152Satgutier@umich.edu pc++; 240910152Satgutier@umich.edu } 241010152Satgutier@umich.edu return j; 241110152Satgutier@umich.edu} 241210152Satgutier@umich.edu 241310152Satgutier@umich.eduXMLNode XMLNode::getChildNode(XMLCSTR name, int *j) const 241410152Satgutier@umich.edu{ 241510152Satgutier@umich.edu if (!d) return emptyXMLNode; 241610152Satgutier@umich.edu int i=0,n=d->nChild; 241710152Satgutier@umich.edu if (j) i=*j; 241810152Satgutier@umich.edu XMLNode *pc=d->pChild+i; 241910152Satgutier@umich.edu for (; i<n; i++) 242010152Satgutier@umich.edu { 242110152Satgutier@umich.edu if (!xstricmp(pc->d->lpszName, name)) 242210152Satgutier@umich.edu { 242310152Satgutier@umich.edu if (j) *j=i+1; 242410152Satgutier@umich.edu return *pc; 242510152Satgutier@umich.edu } 242610152Satgutier@umich.edu pc++; 242710152Satgutier@umich.edu } 242810152Satgutier@umich.edu return emptyXMLNode; 242910152Satgutier@umich.edu} 243010152Satgutier@umich.edu 243110152Satgutier@umich.eduXMLNode XMLNode::getChildNode(XMLCSTR name, int j) const 243210152Satgutier@umich.edu{ 243310152Satgutier@umich.edu if (!d) return emptyXMLNode; 243410152Satgutier@umich.edu if (j>=0) 243510152Satgutier@umich.edu { 243610152Satgutier@umich.edu int i=0; 243710152Satgutier@umich.edu while (j-->0) getChildNode(name,&i); 243810152Satgutier@umich.edu return getChildNode(name,&i); 243910152Satgutier@umich.edu } 244010152Satgutier@umich.edu int i=d->nChild; 244110152Satgutier@umich.edu while (i--) if (!xstricmp(name,d->pChild[i].d->lpszName)) break; 244210152Satgutier@umich.edu if (i<0) return emptyXMLNode; 244310152Satgutier@umich.edu return getChildNode(i); 244410152Satgutier@umich.edu} 244510152Satgutier@umich.edu 244610152Satgutier@umich.eduXMLNode XMLNode::getChildNodeByPath(XMLCSTR _path, char createMissing, XMLCHAR sep) 244710152Satgutier@umich.edu{ 244810152Satgutier@umich.edu XMLSTR path=stringDup(_path); 244910152Satgutier@umich.edu XMLNode x=getChildNodeByPathNonConst(path,createMissing,sep); 245010152Satgutier@umich.edu if (path) free(path); 245110152Satgutier@umich.edu return x; 245210152Satgutier@umich.edu} 245310152Satgutier@umich.edu 245410152Satgutier@umich.eduXMLNode XMLNode::getChildNodeByPathNonConst(XMLSTR path, char createIfMissing, XMLCHAR sep) 245510152Satgutier@umich.edu{ 245610152Satgutier@umich.edu if ((!path)||(!(*path))) return *this; 245710152Satgutier@umich.edu XMLNode xn,xbase=*this; 245810152Satgutier@umich.edu XMLCHAR *tend1,sepString[2]; sepString[0]=sep; sepString[1]=0; 245910152Satgutier@umich.edu tend1=xstrstr(path,sepString); 246010152Satgutier@umich.edu while(tend1) 246110152Satgutier@umich.edu { 246210152Satgutier@umich.edu *tend1=0; 246310152Satgutier@umich.edu xn=xbase.getChildNode(path); 246410152Satgutier@umich.edu if (xn.isEmpty()) 246510152Satgutier@umich.edu { 246610152Satgutier@umich.edu if (createIfMissing) xn=xbase.addChild(path); 246710152Satgutier@umich.edu else { *tend1=sep; return XMLNode::emptyXMLNode; } 246810152Satgutier@umich.edu } 246910152Satgutier@umich.edu *tend1=sep; 247010152Satgutier@umich.edu xbase=xn; 247110152Satgutier@umich.edu path=tend1+1; 247210152Satgutier@umich.edu tend1=xstrstr(path,sepString); 247310152Satgutier@umich.edu } 247410152Satgutier@umich.edu xn=xbase.getChildNode(path); 247510152Satgutier@umich.edu if (xn.isEmpty()&&createIfMissing) xn=xbase.addChild(path); 247610152Satgutier@umich.edu return xn; 247710152Satgutier@umich.edu} 247810152Satgutier@umich.edu 247910152Satgutier@umich.eduXMLElementPosition XMLNode::positionOfText (int i) const { if (i>=d->nText ) i=d->nText-1; return findPosition(d,i,eNodeText ); } 248010152Satgutier@umich.eduXMLElementPosition XMLNode::positionOfClear (int i) const { if (i>=d->nClear) i=d->nClear-1; return findPosition(d,i,eNodeClear); } 248110152Satgutier@umich.eduXMLElementPosition XMLNode::positionOfChildNode(int i) const { if (i>=d->nChild) i=d->nChild-1; return findPosition(d,i,eNodeChild); } 248210152Satgutier@umich.eduXMLElementPosition XMLNode::positionOfText (XMLCSTR lpszValue) const { return positionOfText (indexText (lpszValue)); } 248310152Satgutier@umich.eduXMLElementPosition XMLNode::positionOfClear(XMLCSTR lpszValue) const { return positionOfClear(indexClear(lpszValue)); } 248410152Satgutier@umich.eduXMLElementPosition XMLNode::positionOfClear(XMLClear *a) const { if (a) return positionOfClear(a->lpszValue); return positionOfClear(); } 248510152Satgutier@umich.eduXMLElementPosition XMLNode::positionOfChildNode(XMLNode x) const 248610152Satgutier@umich.edu{ 248710152Satgutier@umich.edu if ((!d)||(!x.d)) return -1; 248810152Satgutier@umich.edu XMLNodeData *dd=x.d; 248910152Satgutier@umich.edu XMLNode *pc=d->pChild; 249010152Satgutier@umich.edu int i=d->nChild; 249110152Satgutier@umich.edu while (i--) if (pc[i].d==dd) return findPosition(d,i,eNodeChild); 249210152Satgutier@umich.edu return -1; 249310152Satgutier@umich.edu} 249410152Satgutier@umich.eduXMLElementPosition XMLNode::positionOfChildNode(XMLCSTR name, int count) const 249510152Satgutier@umich.edu{ 249610152Satgutier@umich.edu if (!name) return positionOfChildNode(count); 249710152Satgutier@umich.edu int j=0; 249810152Satgutier@umich.edu do { getChildNode(name,&j); if (j<0) return -1; } while (count--); 249910152Satgutier@umich.edu return findPosition(d,j-1,eNodeChild); 250010152Satgutier@umich.edu} 250110152Satgutier@umich.edu 250210152Satgutier@umich.eduXMLNode XMLNode::getChildNodeWithAttribute(XMLCSTR name,XMLCSTR attributeName,XMLCSTR attributeValue, int *k) const 250310152Satgutier@umich.edu{ 250410152Satgutier@umich.edu int i=0,j; 250510152Satgutier@umich.edu if (k) i=*k; 250610152Satgutier@umich.edu XMLNode x; 250710152Satgutier@umich.edu XMLCSTR t; 250810152Satgutier@umich.edu do 250910152Satgutier@umich.edu { 251010152Satgutier@umich.edu x=getChildNode(name,&i); 251110152Satgutier@umich.edu if (!x.isEmpty()) 251210152Satgutier@umich.edu { 251310152Satgutier@umich.edu if (attributeValue) 251410152Satgutier@umich.edu { 251510152Satgutier@umich.edu j=0; 251610152Satgutier@umich.edu do 251710152Satgutier@umich.edu { 251810152Satgutier@umich.edu t=x.getAttribute(attributeName,&j); 251910152Satgutier@umich.edu if (t&&(xstricmp(attributeValue,t)==0)) { if (k) *k=i; return x; } 252010152Satgutier@umich.edu } while (t); 252110152Satgutier@umich.edu } else 252210152Satgutier@umich.edu { 252310152Satgutier@umich.edu if (x.isAttributeSet(attributeName)) { if (k) *k=i; return x; } 252410152Satgutier@umich.edu } 252510152Satgutier@umich.edu } 252610152Satgutier@umich.edu } while (!x.isEmpty()); 252710152Satgutier@umich.edu return emptyXMLNode; 252810152Satgutier@umich.edu} 252910152Satgutier@umich.edu 253010152Satgutier@umich.edu// Find an attribute on an node. 253110152Satgutier@umich.eduXMLCSTR XMLNode::getAttribute(XMLCSTR lpszAttrib, int *j) const 253210152Satgutier@umich.edu{ 253310152Satgutier@umich.edu if (!d) return NULL; 253410152Satgutier@umich.edu int i=0,n=d->nAttribute; 253510152Satgutier@umich.edu if (j) i=*j; 253610152Satgutier@umich.edu XMLAttribute *pAttr=d->pAttribute+i; 253710152Satgutier@umich.edu for (; i<n; i++) 253810152Satgutier@umich.edu { 253910152Satgutier@umich.edu if (xstricmp(pAttr->lpszName, lpszAttrib)==0) 254010152Satgutier@umich.edu { 254110152Satgutier@umich.edu if (j) *j=i+1; 254210152Satgutier@umich.edu return pAttr->lpszValue; 254310152Satgutier@umich.edu } 254410152Satgutier@umich.edu pAttr++; 254510152Satgutier@umich.edu } 254610152Satgutier@umich.edu return NULL; 254710152Satgutier@umich.edu} 254810152Satgutier@umich.edu 254910152Satgutier@umich.educhar XMLNode::isAttributeSet(XMLCSTR lpszAttrib) const 255010152Satgutier@umich.edu{ 255110152Satgutier@umich.edu if (!d) return FALSE; 255210152Satgutier@umich.edu int i,n=d->nAttribute; 255310152Satgutier@umich.edu XMLAttribute *pAttr=d->pAttribute; 255410152Satgutier@umich.edu for (i=0; i<n; i++) 255510152Satgutier@umich.edu { 255610152Satgutier@umich.edu if (xstricmp(pAttr->lpszName, lpszAttrib)==0) 255710152Satgutier@umich.edu { 255810152Satgutier@umich.edu return TRUE; 255910152Satgutier@umich.edu } 256010152Satgutier@umich.edu pAttr++; 256110152Satgutier@umich.edu } 256210152Satgutier@umich.edu return FALSE; 256310152Satgutier@umich.edu} 256410152Satgutier@umich.edu 256510152Satgutier@umich.eduXMLCSTR XMLNode::getAttribute(XMLCSTR name, int j) const 256610152Satgutier@umich.edu{ 256710152Satgutier@umich.edu if (!d) return NULL; 256810152Satgutier@umich.edu int i=0; 256910152Satgutier@umich.edu while (j-->0) getAttribute(name,&i); 257010152Satgutier@umich.edu return getAttribute(name,&i); 257110152Satgutier@umich.edu} 257210152Satgutier@umich.edu 257310152Satgutier@umich.eduXMLNodeContents XMLNode::enumContents(int i) const 257410152Satgutier@umich.edu{ 257510152Satgutier@umich.edu XMLNodeContents c; 257610152Satgutier@umich.edu if (!d) { c.etype=eNodeNULL; return c; } 257710152Satgutier@umich.edu if (i<d->nAttribute) 257810152Satgutier@umich.edu { 257910152Satgutier@umich.edu c.etype=eNodeAttribute; 258010152Satgutier@umich.edu c.attrib=d->pAttribute[i]; 258110152Satgutier@umich.edu return c; 258210152Satgutier@umich.edu } 258310152Satgutier@umich.edu i-=d->nAttribute; 258410152Satgutier@umich.edu c.etype=(XMLElementType)(d->pOrder[i]&3); 258510152Satgutier@umich.edu i=(d->pOrder[i])>>2; 258610152Satgutier@umich.edu switch (c.etype) 258710152Satgutier@umich.edu { 258810152Satgutier@umich.edu case eNodeChild: c.child = d->pChild[i]; break; 258910152Satgutier@umich.edu case eNodeText: c.text = d->pText[i]; break; 259010152Satgutier@umich.edu case eNodeClear: c.clear = d->pClear[i]; break; 259110152Satgutier@umich.edu default: break; 259210152Satgutier@umich.edu } 259310152Satgutier@umich.edu return c; 259410152Satgutier@umich.edu} 259510152Satgutier@umich.edu 259610152Satgutier@umich.eduXMLCSTR XMLNode::getName() const { if (!d) return NULL; return d->lpszName; } 259710152Satgutier@umich.eduint XMLNode::nText() const { if (!d) return 0; return d->nText; } 259810152Satgutier@umich.eduint XMLNode::nChildNode() const { if (!d) return 0; return d->nChild; } 259910152Satgutier@umich.eduint XMLNode::nAttribute() const { if (!d) return 0; return d->nAttribute; } 260010152Satgutier@umich.eduint XMLNode::nClear() const { if (!d) return 0; return d->nClear; } 260110152Satgutier@umich.eduint XMLNode::nElement() const { if (!d) return 0; return d->nAttribute+d->nChild+d->nText+d->nClear; } 260210152Satgutier@umich.eduXMLClear XMLNode::getClear (int i) const { if ((!d)||(i>=d->nClear )) return emptyXMLClear; return d->pClear[i]; } 260310152Satgutier@umich.eduXMLAttribute XMLNode::getAttribute (int i) const { if ((!d)||(i>=d->nAttribute)) return emptyXMLAttribute; return d->pAttribute[i]; } 260410152Satgutier@umich.eduXMLCSTR XMLNode::getAttributeName (int i) const { if ((!d)||(i>=d->nAttribute)) return NULL; return d->pAttribute[i].lpszName; } 260510152Satgutier@umich.eduXMLCSTR XMLNode::getAttributeValue(int i) const { if ((!d)||(i>=d->nAttribute)) return NULL; return d->pAttribute[i].lpszValue; } 260610152Satgutier@umich.eduXMLCSTR XMLNode::getText (int i) const { if ((!d)||(i>=d->nText )) return NULL; return d->pText[i]; } 260710152Satgutier@umich.eduXMLNode XMLNode::getChildNode (int i) const { if ((!d)||(i>=d->nChild )) return emptyXMLNode; return d->pChild[i]; } 260810152Satgutier@umich.eduXMLNode XMLNode::getParentNode ( ) const { if ((!d)||(!d->pParent )) return emptyXMLNode; return XMLNode(d->pParent); } 260910152Satgutier@umich.educhar XMLNode::isDeclaration ( ) const { if (!d) return 0; return d->isDeclaration; } 261010152Satgutier@umich.educhar XMLNode::isEmpty ( ) const { return (d==NULL); } 261110152Satgutier@umich.eduXMLNode XMLNode::emptyNode ( ) { return XMLNode::emptyXMLNode; } 261210152Satgutier@umich.edu 261310152Satgutier@umich.eduXMLNode XMLNode::addChild(XMLCSTR lpszName, char isDeclaration, XMLElementPosition pos) 261410152Satgutier@umich.edu { return addChild_priv(0,stringDup(lpszName),isDeclaration,pos); } 261510152Satgutier@umich.eduXMLNode XMLNode::addChild_WOSD(XMLSTR lpszName, char isDeclaration, XMLElementPosition pos) 261610152Satgutier@umich.edu { return addChild_priv(0,lpszName,isDeclaration,pos); } 261710152Satgutier@umich.eduXMLAttribute *XMLNode::addAttribute(XMLCSTR lpszName, XMLCSTR lpszValue) 261810152Satgutier@umich.edu { return addAttribute_priv(0,stringDup(lpszName),stringDup(lpszValue)); } 261910152Satgutier@umich.eduXMLAttribute *XMLNode::addAttribute_WOSD(XMLSTR lpszName, XMLSTR lpszValuev) 262010152Satgutier@umich.edu { return addAttribute_priv(0,lpszName,lpszValuev); } 262110152Satgutier@umich.eduXMLCSTR XMLNode::addText(XMLCSTR lpszValue, XMLElementPosition pos) 262210152Satgutier@umich.edu { return addText_priv(0,stringDup(lpszValue),pos); } 262310152Satgutier@umich.eduXMLCSTR XMLNode::addText_WOSD(XMLSTR lpszValue, XMLElementPosition pos) 262410152Satgutier@umich.edu { return addText_priv(0,lpszValue,pos); } 262510152Satgutier@umich.eduXMLClear *XMLNode::addClear(XMLCSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, XMLElementPosition pos) 262610152Satgutier@umich.edu { return addClear_priv(0,stringDup(lpszValue),lpszOpen,lpszClose,pos); } 262710152Satgutier@umich.eduXMLClear *XMLNode::addClear_WOSD(XMLSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, XMLElementPosition pos) 262810152Satgutier@umich.edu { return addClear_priv(0,lpszValue,lpszOpen,lpszClose,pos); } 262910152Satgutier@umich.eduXMLCSTR XMLNode::updateName(XMLCSTR lpszName) 263010152Satgutier@umich.edu { return updateName_WOSD(stringDup(lpszName)); } 263110152Satgutier@umich.eduXMLAttribute *XMLNode::updateAttribute(XMLAttribute *newAttribute, XMLAttribute *oldAttribute) 263210152Satgutier@umich.edu { return updateAttribute_WOSD(stringDup(newAttribute->lpszValue),stringDup(newAttribute->lpszName),oldAttribute->lpszName); } 263310152Satgutier@umich.eduXMLAttribute *XMLNode::updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,int i) 263410152Satgutier@umich.edu { return updateAttribute_WOSD(stringDup(lpszNewValue),stringDup(lpszNewName),i); } 263510152Satgutier@umich.eduXMLAttribute *XMLNode::updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName) 263610152Satgutier@umich.edu { return updateAttribute_WOSD(stringDup(lpszNewValue),stringDup(lpszNewName),lpszOldName); } 263710152Satgutier@umich.eduXMLCSTR XMLNode::updateText(XMLCSTR lpszNewValue, int i) 263810152Satgutier@umich.edu { return updateText_WOSD(stringDup(lpszNewValue),i); } 263910152Satgutier@umich.eduXMLCSTR XMLNode::updateText(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue) 264010152Satgutier@umich.edu { return updateText_WOSD(stringDup(lpszNewValue),lpszOldValue); } 264110152Satgutier@umich.eduXMLClear *XMLNode::updateClear(XMLCSTR lpszNewContent, int i) 264210152Satgutier@umich.edu { return updateClear_WOSD(stringDup(lpszNewContent),i); } 264310152Satgutier@umich.eduXMLClear *XMLNode::updateClear(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue) 264410152Satgutier@umich.edu { return updateClear_WOSD(stringDup(lpszNewValue),lpszOldValue); } 264510152Satgutier@umich.eduXMLClear *XMLNode::updateClear(XMLClear *newP,XMLClear *oldP) 264610152Satgutier@umich.edu { return updateClear_WOSD(stringDup(newP->lpszValue),oldP->lpszValue); } 264710152Satgutier@umich.edu 264810152Satgutier@umich.educhar XMLNode::setGlobalOptions(XMLCharEncoding _characterEncoding, char _guessWideCharChars, 264910152Satgutier@umich.edu char _dropWhiteSpace, char _removeCommentsInMiddleOfText) 265010152Satgutier@umich.edu{ 265110152Satgutier@umich.edu guessWideCharChars=_guessWideCharChars; dropWhiteSpace=_dropWhiteSpace; removeCommentsInMiddleOfText=_removeCommentsInMiddleOfText; 265210152Satgutier@umich.edu#ifdef _XMLWIDECHAR 265310152Satgutier@umich.edu if (_characterEncoding) characterEncoding=_characterEncoding; 265410152Satgutier@umich.edu#else 265510152Satgutier@umich.edu switch(_characterEncoding) 265610152Satgutier@umich.edu { 265710152Satgutier@umich.edu case char_encoding_UTF8: characterEncoding=_characterEncoding; XML_ByteTable=XML_utf8ByteTable; break; 265810152Satgutier@umich.edu case char_encoding_legacy: characterEncoding=_characterEncoding; XML_ByteTable=XML_legacyByteTable; break; 265910152Satgutier@umich.edu case char_encoding_ShiftJIS: characterEncoding=_characterEncoding; XML_ByteTable=XML_sjisByteTable; break; 266010152Satgutier@umich.edu case char_encoding_GB2312: characterEncoding=_characterEncoding; XML_ByteTable=XML_gb2312ByteTable; break; 266110152Satgutier@umich.edu case char_encoding_Big5: 266210152Satgutier@umich.edu case char_encoding_GBK: characterEncoding=_characterEncoding; XML_ByteTable=XML_gbk_big5_ByteTable; break; 266310152Satgutier@umich.edu default: return 1; 266410152Satgutier@umich.edu } 266510152Satgutier@umich.edu#endif 266610152Satgutier@umich.edu return 0; 266710152Satgutier@umich.edu} 266810152Satgutier@umich.edu 266910152Satgutier@umich.eduXMLNode::XMLCharEncoding XMLNode::guessCharEncoding(void *buf,int l, char useXMLEncodingAttribute) 267010152Satgutier@umich.edu{ 267110152Satgutier@umich.edu#ifdef _XMLWIDECHAR 267210152Satgutier@umich.edu return (XMLCharEncoding)0; 267310152Satgutier@umich.edu#else 267410152Satgutier@umich.edu if (l<25) return (XMLCharEncoding)0; 267510152Satgutier@umich.edu if (guessWideCharChars&&(myIsTextWideChar(buf,l))) return (XMLCharEncoding)0; 267610152Satgutier@umich.edu unsigned char *b=(unsigned char*)buf; 267710152Satgutier@umich.edu if ((b[0]==0xef)&&(b[1]==0xbb)&&(b[2]==0xbf)) return char_encoding_UTF8; 267810152Satgutier@umich.edu 267910152Satgutier@umich.edu // Match utf-8 model ? 268010152Satgutier@umich.edu XMLCharEncoding bestGuess=char_encoding_UTF8; 268110152Satgutier@umich.edu int i=0; 268210152Satgutier@umich.edu while (i<l) 268310152Satgutier@umich.edu switch (XML_utf8ByteTable[b[i]]) 268410152Satgutier@umich.edu { 268510152Satgutier@umich.edu case 4: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) { bestGuess=char_encoding_legacy; i=l; } // 10bbbbbb ? 268610152Satgutier@umich.edu case 3: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) { bestGuess=char_encoding_legacy; i=l; } // 10bbbbbb ? 268710152Satgutier@umich.edu case 2: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) { bestGuess=char_encoding_legacy; i=l; } // 10bbbbbb ? 268810152Satgutier@umich.edu case 1: i++; break; 268910152Satgutier@umich.edu case 0: i=l; 269010152Satgutier@umich.edu } 269110152Satgutier@umich.edu if (!useXMLEncodingAttribute) return bestGuess; 269210152Satgutier@umich.edu // if encoding is specified and different from utf-8 than it's non-utf8 269310152Satgutier@umich.edu // otherwise it's utf-8 269410152Satgutier@umich.edu char bb[201]; 269510152Satgutier@umich.edu l=mmin(l,200); 269610152Satgutier@umich.edu memcpy(bb,buf,l); // copy buf into bb to be able to do "bb[l]=0" 269710152Satgutier@umich.edu bb[l]=0; 269810152Satgutier@umich.edu b=(unsigned char*)strstr(bb,"encoding"); 269910152Satgutier@umich.edu if (!b) return bestGuess; 270010152Satgutier@umich.edu b+=8; while XML_isSPACECHAR(*b) b++; if (*b!='=') return bestGuess; 270110152Satgutier@umich.edu b++; while XML_isSPACECHAR(*b) b++; if ((*b!='\'')&&(*b!='"')) return bestGuess; 270210152Satgutier@umich.edu b++; while XML_isSPACECHAR(*b) b++; 270310152Satgutier@umich.edu 270410152Satgutier@umich.edu if ((xstrnicmp((char*)b,"utf-8",5)==0)|| 270510152Satgutier@umich.edu (xstrnicmp((char*)b,"utf8",4)==0)) 270610152Satgutier@umich.edu { 270710152Satgutier@umich.edu if (bestGuess==char_encoding_legacy) return char_encoding_error; 270810152Satgutier@umich.edu return char_encoding_UTF8; 270910152Satgutier@umich.edu } 271010152Satgutier@umich.edu 271110152Satgutier@umich.edu if ((xstrnicmp((char*)b,"shiftjis",8)==0)|| 271210152Satgutier@umich.edu (xstrnicmp((char*)b,"shift-jis",9)==0)|| 271310152Satgutier@umich.edu (xstrnicmp((char*)b,"sjis",4)==0)) return char_encoding_ShiftJIS; 271410152Satgutier@umich.edu 271510152Satgutier@umich.edu if (xstrnicmp((char*)b,"GB2312",6)==0) return char_encoding_GB2312; 271610152Satgutier@umich.edu if (xstrnicmp((char*)b,"Big5",4)==0) return char_encoding_Big5; 271710152Satgutier@umich.edu if (xstrnicmp((char*)b,"GBK",3)==0) return char_encoding_GBK; 271810152Satgutier@umich.edu 271910152Satgutier@umich.edu return char_encoding_legacy; 272010152Satgutier@umich.edu#endif 272110152Satgutier@umich.edu} 272210152Satgutier@umich.edu#undef XML_isSPACECHAR 272310152Satgutier@umich.edu 272410152Satgutier@umich.edu////////////////////////////////////////////////////////// 272510152Satgutier@umich.edu// Here starts the base64 conversion functions. // 272610152Satgutier@umich.edu////////////////////////////////////////////////////////// 272710152Satgutier@umich.edu 272810152Satgutier@umich.edustatic const char base64Fillchar = _CXML('='); // used to mark partial words at the end 272910152Satgutier@umich.edu 273010152Satgutier@umich.edu// this lookup table defines the base64 encoding 273110152Satgutier@umich.eduXMLCSTR base64EncodeTable=_CXML("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); 273210152Satgutier@umich.edu 273310152Satgutier@umich.edu// Decode Table gives the index of any valid base64 character in the Base64 table] 273410152Satgutier@umich.edu// 96: '=' - 97: space char - 98: illegal char - 99: end of string 273510152Satgutier@umich.educonst unsigned char base64DecodeTable[] = { 273610152Satgutier@umich.edu 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 273710152Satgutier@umich.edu 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 273810152Satgutier@umich.edu 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 273910152Satgutier@umich.edu 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 274010152Satgutier@umich.edu 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 274110152Satgutier@umich.edu 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 274210152Satgutier@umich.edu 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 274310152Satgutier@umich.edu 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 274410152Satgutier@umich.edu 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98 //240 -255 274510152Satgutier@umich.edu}; 274610152Satgutier@umich.edu 274710152Satgutier@umich.eduXMLParserBase64Tool::~XMLParserBase64Tool(){ freeBuffer(); } 274810152Satgutier@umich.edu 274910152Satgutier@umich.eduvoid XMLParserBase64Tool::freeBuffer(){ if (buf) free(buf); buf=NULL; buflen=0; } 275010152Satgutier@umich.edu 275110152Satgutier@umich.eduint XMLParserBase64Tool::encodeLength(int inlen, char formatted) 275210152Satgutier@umich.edu{ 275310152Satgutier@umich.edu unsigned int i=((inlen-1)/3*4+4+1); 275410152Satgutier@umich.edu if (formatted) i+=inlen/54; 275510152Satgutier@umich.edu return i; 275610152Satgutier@umich.edu} 275710152Satgutier@umich.edu 275810152Satgutier@umich.eduXMLSTR XMLParserBase64Tool::encode(unsigned char *inbuf, unsigned int inlen, char formatted) 275910152Satgutier@umich.edu{ 276010152Satgutier@umich.edu int i=encodeLength(inlen,formatted),k=17,eLen=inlen/3,j; 276110152Satgutier@umich.edu alloc(i*sizeof(XMLCHAR)); 276210152Satgutier@umich.edu XMLSTR curr=(XMLSTR)buf; 276310152Satgutier@umich.edu for(i=0;i<eLen;i++) 276410152Satgutier@umich.edu { 276510152Satgutier@umich.edu // Copy next three bytes into lower 24 bits of int, paying attention to sign. 276610152Satgutier@umich.edu j=(inbuf[0]<<16)|(inbuf[1]<<8)|inbuf[2]; inbuf+=3; 276710152Satgutier@umich.edu // Encode the int into four chars 276810152Satgutier@umich.edu *(curr++)=base64EncodeTable[ j>>18 ]; 276910152Satgutier@umich.edu *(curr++)=base64EncodeTable[(j>>12)&0x3f]; 277010152Satgutier@umich.edu *(curr++)=base64EncodeTable[(j>> 6)&0x3f]; 277110152Satgutier@umich.edu *(curr++)=base64EncodeTable[(j )&0x3f]; 277210152Satgutier@umich.edu if (formatted) { if (!k) { *(curr++)=_CXML('\n'); k=18; } k--; } 277310152Satgutier@umich.edu } 277410152Satgutier@umich.edu eLen=inlen-eLen*3; // 0 - 2. 277510152Satgutier@umich.edu if (eLen==1) 277610152Satgutier@umich.edu { 277710152Satgutier@umich.edu *(curr++)=base64EncodeTable[ inbuf[0]>>2 ]; 277810152Satgutier@umich.edu *(curr++)=base64EncodeTable[(inbuf[0]<<4)&0x3F]; 277910152Satgutier@umich.edu *(curr++)=base64Fillchar; 278010152Satgutier@umich.edu *(curr++)=base64Fillchar; 278110152Satgutier@umich.edu } else if (eLen==2) 278210152Satgutier@umich.edu { 278310152Satgutier@umich.edu j=(inbuf[0]<<8)|inbuf[1]; 278410152Satgutier@umich.edu *(curr++)=base64EncodeTable[ j>>10 ]; 278510152Satgutier@umich.edu *(curr++)=base64EncodeTable[(j>> 4)&0x3f]; 278610152Satgutier@umich.edu *(curr++)=base64EncodeTable[(j<< 2)&0x3f]; 278710152Satgutier@umich.edu *(curr++)=base64Fillchar; 278810152Satgutier@umich.edu } 278910152Satgutier@umich.edu *(curr++)=0; 279010152Satgutier@umich.edu return (XMLSTR)buf; 279110152Satgutier@umich.edu} 279210152Satgutier@umich.edu 279310152Satgutier@umich.eduunsigned int XMLParserBase64Tool::decodeSize(XMLCSTR data,XMLError *xe) 279410152Satgutier@umich.edu{ 279510152Satgutier@umich.edu if (xe) *xe=eXMLErrorNone; 279610152Satgutier@umich.edu int size=0; 279710152Satgutier@umich.edu unsigned char c; 279810152Satgutier@umich.edu //skip any extra characters (e.g. newlines or spaces) 279910152Satgutier@umich.edu while (*data) 280010152Satgutier@umich.edu { 280110152Satgutier@umich.edu#ifdef _XMLWIDECHAR 280210152Satgutier@umich.edu if (*data>255) { if (xe) *xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; } 280310152Satgutier@umich.edu#endif 280410152Satgutier@umich.edu c=base64DecodeTable[(unsigned char)(*data)]; 280510152Satgutier@umich.edu if (c<97) size++; 280610152Satgutier@umich.edu else if (c==98) { if (xe) *xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; } 280710152Satgutier@umich.edu data++; 280810152Satgutier@umich.edu } 280910152Satgutier@umich.edu if (xe&&(size%4!=0)) *xe=eXMLErrorBase64DataSizeIsNotMultipleOf4; 281010152Satgutier@umich.edu if (size==0) return 0; 281110152Satgutier@umich.edu do { data--; size--; } while(*data==base64Fillchar); size++; 281210152Satgutier@umich.edu return (unsigned int)((size*3)/4); 281310152Satgutier@umich.edu} 281410152Satgutier@umich.edu 281510152Satgutier@umich.eduunsigned char XMLParserBase64Tool::decode(XMLCSTR data, unsigned char *buf, int len, XMLError *xe) 281610152Satgutier@umich.edu{ 281710152Satgutier@umich.edu if (xe) *xe=eXMLErrorNone; 281810152Satgutier@umich.edu int i=0,p=0; 281910152Satgutier@umich.edu unsigned char d,c; 282010152Satgutier@umich.edu for(;;) 282110152Satgutier@umich.edu { 282210152Satgutier@umich.edu 282310152Satgutier@umich.edu#ifdef _XMLWIDECHAR 282410152Satgutier@umich.edu#define BASE64DECODE_READ_NEXT_CHAR(c) \ 282510152Satgutier@umich.edu do { \ 282610152Satgutier@umich.edu if (data[i]>255){ c=98; break; } \ 282710152Satgutier@umich.edu c=base64DecodeTable[(unsigned char)data[i++]]; \ 282810152Satgutier@umich.edu }while (c==97); \ 282910152Satgutier@umich.edu if(c==98){ if(xe)*xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; } 283010152Satgutier@umich.edu#else 283110152Satgutier@umich.edu#define BASE64DECODE_READ_NEXT_CHAR(c) \ 283210152Satgutier@umich.edu do { c=base64DecodeTable[(unsigned char)data[i++]]; }while (c==97); \ 283310152Satgutier@umich.edu if(c==98){ if(xe)*xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; } 283410152Satgutier@umich.edu#endif 283510152Satgutier@umich.edu 283610152Satgutier@umich.edu BASE64DECODE_READ_NEXT_CHAR(c) 283710152Satgutier@umich.edu if (c==99) { return 2; } 283810152Satgutier@umich.edu if (c==96) 283910152Satgutier@umich.edu { 284010152Satgutier@umich.edu if (p==(int)len) return 2; 284110152Satgutier@umich.edu if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; 284210152Satgutier@umich.edu return 1; 284310152Satgutier@umich.edu } 284410152Satgutier@umich.edu 284510152Satgutier@umich.edu BASE64DECODE_READ_NEXT_CHAR(d) 284610152Satgutier@umich.edu if ((d==99)||(d==96)) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; } 284710152Satgutier@umich.edu if (p==(int)len) { if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall; return 0; } 284810152Satgutier@umich.edu buf[p++]=(unsigned char)((c<<2)|((d>>4)&0x3)); 284910152Satgutier@umich.edu 285010152Satgutier@umich.edu BASE64DECODE_READ_NEXT_CHAR(c) 285110152Satgutier@umich.edu if (c==99) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; } 285210152Satgutier@umich.edu if (p==(int)len) 285310152Satgutier@umich.edu { 285410152Satgutier@umich.edu if (c==96) return 2; 285510152Satgutier@umich.edu if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall; 285610152Satgutier@umich.edu return 0; 285710152Satgutier@umich.edu } 285810152Satgutier@umich.edu if (c==96) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; } 285910152Satgutier@umich.edu buf[p++]=(unsigned char)(((d<<4)&0xf0)|((c>>2)&0xf)); 286010152Satgutier@umich.edu 286110152Satgutier@umich.edu BASE64DECODE_READ_NEXT_CHAR(d) 286210152Satgutier@umich.edu if (d==99 ) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; } 286310152Satgutier@umich.edu if (p==(int)len) 286410152Satgutier@umich.edu { 286510152Satgutier@umich.edu if (d==96) return 2; 286610152Satgutier@umich.edu if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall; 286710152Satgutier@umich.edu return 0; 286810152Satgutier@umich.edu } 286910152Satgutier@umich.edu if (d==96) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; } 287010152Satgutier@umich.edu buf[p++]=(unsigned char)(((c<<6)&0xc0)|d); 287110152Satgutier@umich.edu } 287210152Satgutier@umich.edu} 287310152Satgutier@umich.edu#undef BASE64DECODE_READ_NEXT_CHAR 287410152Satgutier@umich.edu 287510152Satgutier@umich.eduvoid XMLParserBase64Tool::alloc(int newsize) 287610152Satgutier@umich.edu{ 287710152Satgutier@umich.edu if ((!buf)&&(newsize)) { buf=malloc(newsize); buflen=newsize; return; } 287810152Satgutier@umich.edu if (newsize>buflen) { buf=realloc(buf,newsize); buflen=newsize; } 287910152Satgutier@umich.edu} 288010152Satgutier@umich.edu 288110152Satgutier@umich.eduunsigned char *XMLParserBase64Tool::decode(XMLCSTR data, int *outlen, XMLError *xe) 288210152Satgutier@umich.edu{ 288310152Satgutier@umich.edu if (xe) *xe=eXMLErrorNone; 288410152Satgutier@umich.edu unsigned int len=decodeSize(data,xe); 288510152Satgutier@umich.edu if (outlen) *outlen=len; 288610152Satgutier@umich.edu if (!len) return NULL; 288710152Satgutier@umich.edu alloc(len+1); 288810152Satgutier@umich.edu if(!decode(data,(unsigned char*)buf,len,xe)){ return NULL; } 288910152Satgutier@umich.edu return (unsigned char*)buf; 289010152Satgutier@umich.edu} 289110152Satgutier@umich.edu 2892