/* Copyright (C) 2000-2004 Code contributed by Greg Collecutt, Joseph Hope and Paul Cochrane This file is part of xmds. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* $Id: xmlbasics.cc,v 1.11 2004/07/13 05:29:38 paultcochrane Exp $ */ /*! @file xmlbasics.cc @brief Basic xml parsing classes and methods More detailed explanation... */ #include extern bool xmlDebugFlag; //#define DEBUG 0 // ****************************************************************************** // ****************************************************************************** // XMLException // ****************************************************************************** // ****************************************************************************** long nXMLExceptions=0; //!< The number of XML exceptions // ****************************************************************************** XMLException::XMLException() { if(xmlDebugFlag) { nXMLExceptions++; printf("XMLException::XMLException()\n"); printf("nXMLExceptions=%li\n",nXMLExceptions); } code=UNKNOWN_ERR; }; // ****************************************************************************** XMLException::XMLException( const unsigned short& error) { if(xmlDebugFlag) { nXMLExceptions++; printf("XMLException::XMLException(unsigned short error)\n"); printf("nXMLExceptions=%li\n",nXMLExceptions); } code=error; }; // ****************************************************************************** XMLException::~XMLException() { if(xmlDebugFlag) { nXMLExceptions--; printf("XMLException::~XMLException()\n"); printf("nXMLExceptions=%li\n",nXMLExceptions); } }; // ****************************************************************************** const char* XMLException::getError() const { switch(code) { case UNKNOWN_ENCODING_ERR : return "XMLException::UNKNOWN_ENCODING_ERR\n"; break; case UNEXPECTED_EOF_ERR : return "XMLException::UNEXPECTED_EOF_ERR\n"; break; case RANGE_ERR : return "XMLException::RANGE_ERR\n"; break; case INVALID_CHAR_ERR : return "XMLException::INVALID_CHAR_ERR\n"; break; default : return "XMLException::UNKNOWN_ERR\n"; } }; // ****************************************************************************** // ****************************************************************************** // XMLChar // ****************************************************************************** // ****************************************************************************** // ********************************************************************** bool XMLChar::isChar( const char& ch) { if(ch>=0x0020) { return 1; } if(isWhiteSpace(ch)) { return 1; } return 0; }; // ********************************************************************** bool XMLChar::isCharData( const char& ch) { if((ch=='<')|(ch=='&')) { return 0; } return isChar(ch); }; // ********************************************************************** bool XMLChar::isWhiteSpace( const char& ch) { return ((ch==0x20)|(ch==0x09)|(ch==0x0D)|(ch==0x0A)); }; // ********************************************************************** bool XMLChar::isLatinLetter( const char& ch) { return (((ch>='A')&(ch<='Z'))|((ch>='a')&(ch<='z'))); }; // ********************************************************************** bool XMLChar::isLatinDigit( const char& ch) { return ((ch>='0')&(ch<='9')); }; // ********************************************************************** bool XMLChar::isLatinHexDigit( const char& ch) { return (((ch>='0')&(ch<='9')) |((ch>='A')&(ch<='F')) |((ch>='a')&(ch<='f'))); }; // ********************************************************************** bool XMLChar::isLetter( const char& ch) { return isBaseChar(ch); }; // ********************************************************************** bool XMLChar::isBaseChar( const char& ch) { return isLatinLetter(ch); }; // ********************************************************************** bool XMLChar::isDigit( const char& ch) { return isLatinDigit(ch); }; // ********************************************************************** bool XMLChar::isNameChar( const char& ch) { if (isNCNameChar(ch)) { return 1; } if (ch==':') { return 1; } return 0; }; // ********************************************************************** bool XMLChar::isNCNameChar( const char& ch) { if (isLetter(ch)) { return 1; } if (isDigit(ch)) { return 1; } if ((ch=='.')|(ch=='-')|(ch=='_')) { return 1; } return 0; }; // ********************************************************************** bool XMLChar::isPubidChar( const char& ch) { if (isLatinLetter(ch)) { return 1; } if (isLatinDigit(ch)) { return 1; } if ((ch==0x20)|(ch==0x0D)|(ch==0x0A)) { return 1; } if ((ch=='-')|(ch==0x27)|(ch=='(')) { return 1; } if ((ch==')')|(ch=='+')|(ch==',')) { return 1; } if ((ch=='.')|(ch=='/')|(ch==':')) { return 1; } if ((ch=='=')|(ch=='?')|(ch==';')) { return 1; } if ((ch=='!')|(ch=='*')|(ch=='#')) { return 1; } if ((ch=='@')|(ch=='$')|(ch=='_')|(ch=='%')) { return 1; } return 0; }; // ****************************************************************************** // ****************************************************************************** // XMLString // ****************************************************************************** // ****************************************************************************** long nXMLStrings=0; //!< The number of XML strings // ****************************************************************************** // XMLString default constructor XMLString::XMLString() { if(xmlDebugFlag) { nXMLStrings++; printf("XMLString::XMLString()\n"); printf("nXMLStrings=%li\n",nXMLStrings); } _length=0; _c_str_valid=0; }; // ********************************************************************** // XMLString construction from C-style string XMLString::XMLString( const char* s) { if(xmlDebugFlag) { nXMLStrings++; printf("XMLString::XMLString(const char* s) = %s\n",s); printf("nXMLStrings=%li\n",nXMLStrings); } _length=0; while(s[_length]) { _length++; } _data = new char[_length]; for(unsigned long i=0;i<_length;i++) { _data[i] = s[i]; } _c_str_valid=0; }; // ********************************************************************** // XMLString construction from another XMLString XMLString::XMLString( const XMLString& s) { if(xmlDebugFlag) { nXMLStrings++; printf("XMLString::XMLString(const XMLString& s) = %s\n",s.c_str()); printf("nXMLStrings=%li\n",nXMLStrings); } _length=s._length; _data = new char[_length]; for(unsigned long i=0;i<_length;i++) { _data[i] = s._data[i]; } _c_str_valid=0; }; // ********************************************************************** // XMLString default destructor XMLString::~XMLString() { if(xmlDebugFlag) { nXMLStrings--; printf("XMLString::~XMLString()\n"); printf("nXMLStrings=%li\n",nXMLStrings); } if(_length) { delete _data; } if(_c_str_valid) { delete _c_str; } }; // ********************************************************************** XMLString& XMLString::operator=( const XMLString& s) { if(this != &s) { // so as to never copy itself! if (_length) { delete _data; } if(_c_str_valid) { delete _c_str; } _length=s.length(); _data = new char[_length]; for(unsigned long i=0;i<_length;i++) { _data[i] = s._data[i]; } _c_str_valid=0; } return *this; }; // ********************************************************************** XMLString& XMLString::operator=( const char* s) { if(_length) { delete _data; } if(_c_str_valid) { delete _c_str; } _length=0; while(!(s[_length]==0)) { _length++; } _data = new char[_length+1]; for(unsigned long i=0;i<=_length;i++){ _data[i] = s[i]; } _c_str_valid=0; return *this; }; // ********************************************************************** unsigned long XMLString::length() const { return _length; }; // ********************************************************************** const char* XMLString::c_str() const { if(!_c_str_valid) { _c_str = new char[_length+1]; for(unsigned long i=0;i<_length;i++) { _c_str[i]=(char) _data[i]; } _c_str[_length]=0; _c_str_valid=1; } return _c_str; }; // ********************************************************************** char XMLString::data( const unsigned long& index) const { if(index>=_length) { throw XMLException(XMLException::RANGE_ERR); } return _data[index]; }; // ********************************************************************** bool XMLString::operator==( const XMLString& s) const { if(&s==this) { return 1; } if(s.length()!=_length){ return 0; } bool result=1; for(unsigned long i=0;i<_length;i++) { result = result&(s._data[i]==_data[i]); } return result; }; // ********************************************************************** bool XMLString::operator!=( const XMLString& s) const { return !((*this)==s); }; // ********************************************************************** XMLString& XMLString::operator+=( const XMLString& s) { unsigned long newLength = _length + s._length; char* newData = new char[newLength]; unsigned long i; for(i = 0; i < _length; i++) { newData[i] = _data[i]; } for(i = _length; i < newLength; i++) { newData[i] = s._data[i-_length]; } if(_length) { delete _data; } _data = newData; _length = newLength; if(_c_str_valid) { delete _c_str; } _c_str_valid = 0; return *this; }; // ********************************************************************** long XMLString::loadFromFile( FILE* infile) { if(_length) { delete _data; } if(_c_str_valid) { delete _c_str; } fseek(infile,0,SEEK_END); _length = ftell(infile); fseek(infile,0,SEEK_SET); _data = new char[_length]; for(unsigned long i=0;i<_length;i++) { _data[i] = fgetc(infile); } _c_str_valid=0; return _length; }; // ********************************************************************** void XMLString::insertString( const unsigned long& offset, const XMLString& s) { if(offset > _length) { return; } unsigned long newLength = _length + s._length; char* newData = new char[newLength]; unsigned long i; for(i = 0; i < offset; i++) { newData[i] = _data[i]; } for(i = 0; i < s._length; i++) { newData[offset + i] = s._data[i]; } for(i = offset; i < _length; i++) { newData[offset + s._length + i] = _data[i]; } if(_length) { delete _data; } _data = newData; _length = newLength; if(_c_str_valid) { delete _c_str; } _c_str_valid = 0; }; // ********************************************************************** void XMLString::deleteData( const unsigned long& offset, const unsigned long& count) { unsigned long i = offset + count; while(i < _length) { _data[i - count] = _data[i]; } if(offset + count > _length) { _length = offset; } else { _length -= count; } if(_c_str_valid) { delete _c_str; } _c_str_valid = 0; }; // ********************************************************************** void XMLString::replaceData( const unsigned long& offset, unsigned long count, const XMLString& s) { if(offset > _length) { *this += s; } if(offset + count > _length) { count = _length - offset; } unsigned long newLength = _length + s._length - count; char* newData = new char[newLength]; unsigned long i; for(i = 0; i < offset; i++) { newData[i] = _data[i]; } for(i = offset; i < offset+s._length; i++) { newData[i] = s._data[i-offset]; } for(i = offset+s._length; i < newLength; i++) { newData[i] = _data[i-s._length+count]; } if(_length) { delete _data; } _data = newData; _length = newLength; if(_c_str_valid) { delete _c_str; } _c_str_valid = 0; }; // ********************************************************************** void XMLString::subString( XMLString& subS, const unsigned long& begin, const unsigned long& end_plus_one) const { if(end_plus_one>_length) { throw XMLException(XMLException::RANGE_ERR); } if(end_plus_one<=begin) { subS=""; return; } if(subS._length) { delete subS._data; } if(subS._c_str_valid) { delete subS._c_str; } subS._c_str_valid=0; subS._data = new char[end_plus_one-begin]; for(unsigned long i=begin;i