(file) Return to XmlParser.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

Diff for /pegasus/src/Pegasus/Common/XmlParser.cpp between version 1.1.1.1 and 1.43.2.4

version 1.1.1.1, 2001/01/14 19:53:23 version 1.43.2.4, 2008/03/12 23:40:26
Line 1 
Line 1 
 //BEGIN_LICENSE  //%2006////////////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000 The Open Group, BMC Software, Tivoli Systems, IBM  // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
   // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
   // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
   // IBM Corp.; EMC Corporation, The Open Group.
   // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
   // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
   // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
   // EMC Corporation; VERITAS Software Corporation; The Open Group.
   // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
   // EMC Corporation; Symantec Corporation; The Open Group.
   //
   // Permission is hereby granted, free of charge, to any person obtaining a copy
   // of this software and associated documentation files (the "Software"), to
   // deal in the Software without restriction, including without limitation the
   // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   // sell copies of the Software, and to permit persons to whom the Software is
   // furnished to do so, subject to the following conditions:
   //
   // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
   // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
   // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
   // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
   // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
   // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
   // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 // //
 // Permission is hereby granted, free of charge, to any person obtaining a  //==============================================================================
 // copy of this software and associated documentation files (the "Software"),  
 // to deal in the Software without restriction, including without limitation  
 // the rights to use, copy, modify, merge, publish, distribute, sublicense,  
 // and/or sell copies of the Software, and to permit persons to whom the  
 // Software is furnished to do so, subject to the following conditions:  
 // //
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  //%/////////////////////////////////////////////////////////////////////////////
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL  
 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER  
 // DEALINGS IN THE SOFTWARE.  
 //  
 //END_LICENSE  
 //BEGIN_HISTORY  
 //  
 // Author:  
 //  
 // $Log$  
 // Revision 1.1.1.1  2001/01/14 19:53:23  mike  
 // Pegasus import  
 //  
 //  
 //END_HISTORY  
  
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
 // //
Line 52 
Line 54 
 //              &quot - full quote //              &quot - full quote
 //              &apos - apostrophe //              &apos - apostrophe
 // //
   //             as well as character (numeric) references:
   //
   //              1 - decimal reference for character '1'
   //              1 - hexadecimal reference for character '1'
   //
 //          4. Element names and attribute names take the following form: //          4. Element names and attribute names take the following form:
 // //
 //              [A-Za-z_][A-Za-z_0-9-.:] //              [A-Za-z_][A-Za-z_0-9-.:]
Line 71 
Line 78 
 // //
 // TODO: // TODO:
 // //
 //      Handle <!DOCTYPE...> sections which are complicated (containing  //      ATTN: KS P1 4 Mar 2002. Review the following TODOs to see if there is
   //      work. Handle <!DOCTYPE...> sections which are complicated (containing
 //        rules rather than references to files). //        rules rather than references to files).
 // //
 //      Handle reference of this form: "&#913;"  
 //  
 //      Remove newlines from string literals: //      Remove newlines from string literals:
 // //
 //          Example: <xyz x="hello //          Example: <xyz x="hello
Line 83 
Line 89 
 // //
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
  
   #include <Pegasus/Common/Config.h>
 #include <cctype> #include <cctype>
 #include <cassert>  
 #include <cstdio> #include <cstdio>
 #include <cstdlib> #include <cstdlib>
 #include <cstring> #include <cstring>
 #include "XmlParser.h" #include "XmlParser.h"
   #include "Logger.h"
   #include "ExceptionRep.h"
   #include "CharSet.h"
  
 PEGASUS_NAMESPACE_BEGIN PEGASUS_NAMESPACE_BEGIN
  
Line 103 
Line 112 
     for (; *p; p++)     for (; *p; p++)
     {     {
         if (*p == '\n')         if (*p == '\n')
             std::cout << "\\n";              PEGASUS_STD(cout) << "\\n";
         else if (*p == '\r')         else if (*p == '\r')
             std::cout << "\\r";              PEGASUS_STD(cout) << "\\r";
         else if (*p == '\t')         else if (*p == '\t')
             std::cout << "\\t";              PEGASUS_STD(cout) << "\\t";
         else         else
             std::cout << *p;              PEGASUS_STD(cout) << *p;
     }     }
 } }
  
Line 120 
Line 129 
     char replacement;     char replacement;
 }; };
  
   // ATTN: Add support for more entity references
 static EntityReference _references[] = static EntityReference _references[] =
 { {
     { "&amp;", 5, '&' },     { "&amp;", 5, '&' },
Line 129 
Line 139 
     { "&apos;", 6, '\'' }     { "&apos;", 6, '\'' }
 }; };
  
 static Uint32 _REFERENCES_SIZE = (sizeof(_references) / sizeof(_references[0]));  
   
 // Remove all redundant spaces from the given string:  
   
 static void _normalize(char* text)  
 {  
     Uint32 length = strlen(text);  
     char* p = text;  
     char* end = p + length;  
   
     // Remove leading spaces:  
   
     while (isspace(*p))  
         p++;  
   
     if (p != text)  
         memmove(text, p, end - p + 1);  
   
     p = text;  
  
     // Look for sequences of more than one space and remove all but one.  // Implements a check for a whitespace character, without calling
   // isspace( ).  The isspace( ) function is locale-sensitive,
     for (;;)  // and incorrectly flags some chars above 0x7f as whitespace.  This
   // causes the XmlParser to incorrectly parse UTF-8 data.
   //
   // Section 2.3 of XML 1.0 Standard (http://www.w3.org/TR/REC-xml)
   // defines white space as:
   // S    ::=    (#x20 | #x9 | #xD | #xA)+
   static inline int _isspace(char c)
     {     {
         // Advance to the next space:      return CharSet::isXmlWhiteSpace((Uint8)c);
   
         while (*p && !isspace(*p))  
             p++;  
   
         if (!*p)  
             break;  
   
         // Advance to the next non-space:  
   
         char* q = p++;  
   
         while (isspace(*p))  
             p++;  
   
         // Discard trailing spaces (if we are at the end):  
   
         if (!*p)  
         {  
             *q = '\0';  
             break;  
         }         }
  
         // Remove the redundant spaces:  static Uint32 _REFERENCES_SIZE = (sizeof(_references) / sizeof(_references[0]));
   
         Uint32 n = p - q;  
   
         if (n > 1)  
         {  
             *q++ = ' ';  
             memmove(q, p, end - p + 1);  
             p = q;  
         }  
     }  
 }  
  
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
 // //
Line 195 
Line 161 
 // //
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
  
 static char* _xmlMessages[] =  static const char* _xmlMessages[] =
 { {
     "Bad opening element",     "Bad opening element",
     "Bad closing element",     "Bad closing element",
Line 213 
Line 179 
     "One or more tags are still open",     "One or more tags are still open",
     "More than one root element was encountered",     "More than one root element was encountered",
     "Validation error",     "Validation error",
     "Semantic error"      "Semantic error",
       "Malformed namespace declaration",
       "Namespace not supported",
       "Namespace not declared"
 }; };
  
 static String _formMessage(Uint32 code, Uint32 line, const String& message)  static const char* _xmlKeys[] =
 { {
     String result = _xmlMessages[Uint32(code) - 1];      "Common.XmlParser.BAD_START_TAG",
       "Common.XmlParser.BAD_END_TAG",
       "Common.XmlParser.BAD_ATTRIBUTE_NAME",
       "Common.XmlParser.EXPECTED_EQUAL_SIGN",
       "Common.XmlParser.BAD_ATTRIBUTE_VALUE",
       "Common.XmlParser.MINUS_MINUS_IN_COMMENT",
       "Common.XmlParser.UNTERMINATED_COMMENT",
       "Common.XmlParser.UNTERMINATED_CDATA",
       "Common.XmlParser.UNTERMINATED_DOCTYPE",
       "Common.XmlParser.TOO_MANY_ATTRIBUTES",
       "Common.XmlParser.MALFORMED_REFERENCE",
       "Common.XmlParser.EXPECTED_COMMENT_OR_CDATA",
       "Common.XmlParser.START_END_MISMATCH",
       "Common.XmlParser.UNCLOSED_TAGS",
       "Common.XmlParser.MULTIPLE_ROOTS",
       "Common.XmlParser.VALIDATION_ERROR",
       "Common.XmlParser.SEMANTIC_ERROR",
       "Common.XmlParser.MALFORMED_NAMESPACE_DECL",
       "Common.XmlParser.UNSUPPORTED_NAMESPACE",
       "Common.XmlParser.UNDECLARED_NAMESPACE"
   };
  
     char buffer[32];  
     sprintf(buffer, "%d", line);  
     result.append(": on line ");  
     result.append(buffer);  
  
     if (message.getLength())  static MessageLoaderParms _formMessage(
       Uint32 code,
       Uint32 line,
       const String& message)
     {     {
         result.append(": ");      String dftMsg = _xmlMessages[Uint32(code) - 1];
         result.append(message);      String key = _xmlKeys[Uint32(code) - 1];
           String msg = message;
   
       dftMsg.append(": on line $0");
       if (message.size())
       {
           msg = ": " + msg;
           dftMsg.append("$1");
     }     }
  
     return result;      return MessageLoaderParms(key, dftMsg, line ,msg);
 } }
  
   static MessageLoaderParms _formPartialMessage(Uint32 code, Uint32 line)
   {
       String dftMsg = _xmlMessages[Uint32(code) - 1];
       String key = _xmlKeys[Uint32(code) - 1];
   
       dftMsg.append(": on line $0");
   
       return MessageLoaderParms(key, dftMsg, line);
   }
   
   
 XmlException::XmlException( XmlException::XmlException(
     XmlException::Code code,     XmlException::Code code,
     Uint32 lineNumber,     Uint32 lineNumber,
Line 243 
Line 249 
  
 } }
  
   
   XmlException::XmlException(
       XmlException::Code code,
       Uint32 lineNumber,
       MessageLoaderParms& msgParms)
       : Exception(_formPartialMessage(code, lineNumber))
   {
           if (msgParms.default_msg.size())
       {
           msgParms.default_msg = ": " + msgParms.default_msg;
       }
           _rep->message.append(MessageLoader::getMessage(msgParms));
   }
   
   
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
 // //
 // XmlValidationError // XmlValidationError
Line 254 
Line 275 
     const String& message)     const String& message)
     : XmlException(XmlException::VALIDATION_ERROR, lineNumber, message)     : XmlException(XmlException::VALIDATION_ERROR, lineNumber, message)
 { {
   }
  
   
   XmlValidationError::XmlValidationError(
       Uint32 lineNumber,
       MessageLoaderParms& msgParms)
       : XmlException(XmlException::VALIDATION_ERROR, lineNumber, msgParms)
   {
 } }
  
   
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
 // //
 // XmlSemanticError // XmlSemanticError
Line 266 
Line 295 
 XmlSemanticError::XmlSemanticError( XmlSemanticError::XmlSemanticError(
     Uint32 lineNumber,     Uint32 lineNumber,
     const String& message)     const String& message)
     : XmlException(XmlException::VALIDATION_ERROR, lineNumber, message)      : XmlException(XmlException::SEMANTIC_ERROR, lineNumber, message)
 { {
   }
   
  
   XmlSemanticError::XmlSemanticError(
       Uint32 lineNumber,
       MessageLoaderParms& msgParms)
       : XmlException(XmlException::SEMANTIC_ERROR, lineNumber, msgParms)
   {
 } }
  
   
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
 // //
 // XmlParser // XmlParser
 // //
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
  
 XmlParser::XmlParser(char* text) : _line(1), _text(text), _current(text),  XmlParser::XmlParser(char* text, XmlNamespace* ns)
     _restoreChar('\0'), _foundRoot(false)      : _line(1),
         _current(text),
         _restoreChar('\0'),
         _foundRoot(false),
         _scopeLevel(0),
         _supportedNamespaces(ns)
 { {
   }
  
   inline void _skipWhitespace(Uint32& line, char*& p)
   {
       while (*p && _isspace(*p))
       {
           if (*p == '\n')
               line++;
   
           p++;
       }
   }
   
   #if defined(PEGASUS_PLATFORM_WIN64_IA64_MSVC) || \
       defined(PEGASUS_PLATFORM_WIN64_X86_64_MSVC)
   #pragma optimize( "", off )
   #endif
   static int _getEntityRef(char*& p)
   {
       if ((p[0] == 'g') && (p[1] == 't') && (p[2] == ';'))
       {
           p += 3;
           return '>';
 } }
  
 Boolean XmlParser::next(XmlEntry& entry)      if ((p[0] == 'l') && (p[1] == 't') && (p[2] == ';'))
 { {
           p += 3;
           return '<';
       }
   
       if ((p[0] == 'a') && (p[1] == 'p') && (p[2] == 'o') && (p[3] == 's') &&
           (p[4] == ';'))
       {
           p += 5;
           return '\'';
       }
   
       if ((p[0] == 'q') && (p[1] == 'u') && (p[2] == 'o') && (p[3] == 't') &&
           (p[4] == ';'))
       {
           p += 5;
           return '"';
       }
   
       if ((p[0] == 'a') && (p[1] == 'm') && (p[2] == 'p') && (p[3] == ';'))
       {
           p += 4;
           return '&';
       }
   
       return -1;
   }
   #if defined(PEGASUS_PLATFORM_WIN64_IA64_MSVC) || \
       defined(PEGASUS_PLATFORM_WIN64_X86_64_MSVC)
   #pragma optimize( "", on )
   #endif
   
   static inline int _getCharRef(char*& p, bool hex)
   {
       char* end;
       unsigned long ch;
   
       if (hex)
       {
           ch = strtoul(p, &end, 16);
       }
       else
       {
           ch = strtoul(p, &end, 10);
       }
   
       if ((end == p) || (*end != ';') || (ch > 255))
       {
           return -1;
       }
   
       if ((hex && (end - p > 4)) || (!hex && (end - p > 5)))
       {
           return -1;
       }
   
       p = end + 1;
   
       return ch;
   }
   
   static void _normalize(Uint32& line, char*& p, char end_char, char*& start)
   {
       // Skip over leading whitespace:
   
       _skipWhitespace(line, p);
       start = p;
   
       // Process one character at a time:
   
       char* q = p;
   
       while (*p && (*p != end_char))
       {
           if (_isspace(*p))
           {
               // Compress sequences of whitespace characters to a single space
               // character. Update line number when newlines encountered.
   
               if (*p++ == '\n')
               {
                   line++;
               }
   
               *q++ = ' ';
   
               _skipWhitespace(line, p);
           }
           else if (*p == '&')
           {
               // Process entity characters and entity references:
   
               p++;
               int ch;
   
               if (*p == '#')
               {
                   *p++;
   
                   if (*p == 'x')
                   {
                       p++;
                       ch = _getCharRef(p, true);
                   }
                   else
                   {
                       ch = _getCharRef(p, false);
                   }
               }
               else
               {
                   ch = _getEntityRef(p);
               }
   
               if (ch == -1)
               {
                   throw XmlException(XmlException::MALFORMED_REFERENCE, line);
               }
   
               *q++ = ch;
           }
           else
           {
               *q++ = *p++;
           }
       }
   
       // We encountered a the end_char or a zero-terminator.
   
       *q = *p;
   
       // Remove single trailing whitespace (consecutive whitespaces already
       // compressed above).  Since p >= q, we can tell if we need to strip a
       // trailing space from q by looking at the end of p.  We must not look at
       // the last character of p, though, if p is an empty string.
   
       if ((p != start) && _isspace(p[-1]))
       {
           q--;
       }
   
       // If q got behind p, it is safe and necessary to null-terminate q
   
       if (q != p)
       {
           *q = '\0';
       }
   }
   
   Boolean XmlParser::next(
       XmlEntry& entry,
       Boolean includeComment)
   {
       entry.attributes.clear();
   
     if (!_putBackStack.isEmpty())     if (!_putBackStack.isEmpty())
     {     {
         entry = _putBackStack.top();         entry = _putBackStack.top();
Line 305 
Line 523 
         _restoreChar = '\0';         _restoreChar = '\0';
     }     }
  
       // Loop until we are done with comments if includeComment is false.
       do
       {
     // Skip over any whitespace:     // Skip over any whitespace:
           _skipWhitespace(_line, _current);
     _skipWhitespace(_current);  
  
     if (!*_current)     if (!*_current)
     {     {
Line 348 
Line 568 
  
             _stack.pop();             _stack.pop();
         }         }
   
         return true;  
     }     }
     else     else
     {     {
               // Normalize the content:
   
               char* start;
               _normalize(_line, _current, '<', start);
   
               // Get the content:
   
         entry.type = XmlEntry::CONTENT;         entry.type = XmlEntry::CONTENT;
         entry.text = _current;              entry.text = start;
         _getContent(_current);  
               // Overwrite '<' with a null character (temporarily).
   
         _restoreChar = *_current;         _restoreChar = *_current;
         *_current = '\0';         *_current = '\0';
  
         if (nullTerminator)         if (nullTerminator)
             *nullTerminator = '\0';             *nullTerminator = '\0';
           }
       } while (!includeComment && entry.type == XmlEntry::COMMENT);
   
       if (_supportedNamespaces &&
           (entry.type == XmlEntry::START_TAG ||
            entry.type == XmlEntry::EMPTY_TAG ||
            entry.type == XmlEntry::END_TAG))
       {
           // Process attributes and enter namespaces into the table
           if (entry.type == XmlEntry::START_TAG ||
               entry.type == XmlEntry::EMPTY_TAG)
           {
               _scopeLevel++;
               for (unsigned int i = 0; i < entry.attributes.size(); i++)
               {
                   XmlAttribute& attr = entry.attributes[i];
                   if (strncmp(attr.name, "xmlns", 5) == 0)
                   {
                       XmlNamespace ns;
                       if (attr.name[5] == ':')
                       {
                           ns.localName = attr.name + 6;
   
                           // Check if we have malformed XML of the form:
                           // "xmlns:=URI". In this case attr.name will be set
                           // to "xmlns:" and ns.localName will point to '\0'
                           if (ns.localName[0] == '\0')
                           {
                               throw XmlException(
                                   XmlException::MALFORMED_NAMESPACE_DECL,
                                   _line);
                           }
                       }
                       else
                       {
                           // Default name space has no local name
                           ns.localName = 0;
                       }
                       ns.extendedName = attr.value;
                       ns.scopeLevel = _scopeLevel;
                       ns.type = getSupportedNamespaceType(ns.extendedName);
   
                       // Even unsupported namespaces get pushed onto the stack.
                       // We will throw an exception of there is an attempt to
                       // reference an unsupported namespace later.
                       _nameSpaces.push(ns);
                   }
                   else
                   {
                       // Attribute names may also be namespace qualified.
                       attr.nsType = _getNamespaceType(attr.name);
                   }
               }
           }
  
         _substituteReferences((char*)entry.text);          // Get the namespace type for this tag.
         _normalize((char*)entry.text);          entry.nsType = _getNamespaceType(entry.text);
   
           if (entry.type == XmlEntry::END_TAG ||
               entry.type == XmlEntry::EMPTY_TAG)
           {
               // Remove any namespaces of the current scope level from
               // the scope stack.
               while (!_nameSpaces.isEmpty() &&
                      _scopeLevel <= _nameSpaces.top().scopeLevel)
               {
                   _nameSpaces.pop();
               }
   
               PEGASUS_ASSERT(_scopeLevel > 0);
               _scopeLevel--;
           }
       }
       else
       {
           entry.nsType = -1;
       }
  
         return true;         return true;
     }     }
   
   // Get the namespace type of the given tag
   int XmlParser::_getNamespaceType(const char* tag)
   {
       const char* pos = strchr(tag, ':');
   
       // If ":" is not found, the tag is not namespace qualified and we
       // need to look for the default name space.
   
       // Search the namespace stack from the top
       for (int i = _nameSpaces.size() - 1; i >=0; i--)
       {
           // If ":" is found, look for the name space with the matching
           // local name...
           if ((pos && _nameSpaces[i].localName &&
                !strncmp(_nameSpaces[i].localName, tag, pos - tag)) ||
               // ... otherwise look for the default name space. It's the
               // one with localName set to NULL
               (!pos && !_nameSpaces[i].localName))
           {
               // If it's a reference to an unsupported namespace,
               // throw an exception
               if (_nameSpaces[i].type == -1)
               {
                   throw XmlException(XmlException::UNSUPPORTED_NAMESPACE, _line);
               }
               return _nameSpaces[i].type;
           }
 } }
  
 void XmlParser::putBack(XmlEntry& entry)      // If the tag is namespace qualified, but the name space has not been
       // declared, it's malformed XML and we must throw an exception
       if (pos)
 { {
     _putBackStack.push(entry);          throw XmlException(XmlException::UNDECLARED_NAMESPACE, _line);
 } }
  
 XmlParser::~XmlParser()      // Otherwise it's OK not to have a name space.
       return -1;
   }
   
   // Gived the extended namespace name, find it in the table of supported
   // namespaces and return its type.
   int XmlParser::getSupportedNamespaceType(const char* extendedName)
 { {
     // Nothing to do!      for (int i = 0;
            _supportedNamespaces[i].localName != 0;
            i++)
       {
           PEGASUS_ASSERT(_supportedNamespaces[i].type == i);
           if (!strcmp(_supportedNamespaces[i].extendedName, extendedName))
           {
               return _supportedNamespaces[i].type;
           }
       }
       return -1;
 } }
  
 void XmlParser::_skipWhitespace(char*& p)  XmlNamespace* XmlParser::getNamespace(int nsType)
 { {
     while (*p && isspace(*p))      for (int i = _nameSpaces.size() - 1; i >=0; i--)
     {     {
         if (*p == '\n')          if (_nameSpaces[i].type == nsType)
             _line++;          {
               return &_nameSpaces[i];
           }
       }
       return 0;
   }
  
         p++;  void XmlParser::putBack(XmlEntry& entry)
   {
       _putBackStack.push(entry);
     }     }
   
   XmlParser::~XmlParser()
   {
       // Nothing to do!
 } }
  
 Boolean XmlParser::_getElementName(char*& p)  // A-Za-z0-9_-:.
   static unsigned char _isInnerElementChar[] =
 { {
     if (!isalpha(*p) && *p != '_')      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
       0,0,0,0,0,0,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,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,0,0,0,0,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
   };
   
   Boolean XmlParser::_getElementName(char*& p)
     {     {
         std::cout << __LINE__ << std::endl;      if (!CharSet::isAlNumUnder(Uint8(*p)))
         throw XmlException(XmlException::BAD_START_TAG, _line);         throw XmlException(XmlException::BAD_START_TAG, _line);
     }  
  
     while (*p &&      p++;
         (isalnum(*p) || *p == '_' || *p == '-' || *p == ':' || *p == '.'))  
       while (*p && _isInnerElementChar[Uint8(*p)])
         p++;         p++;
  
     // The next character must be a space:     // The next character must be a space:
  
     if (isspace(*p))      if (_isspace(*p))
     {     {
         *p++ = '\0';         *p++ = '\0';
         _skipWhitespace(p);          _skipWhitespace(_line, p);
     }     }
  
     if (*p == '>')     if (*p == '>')
Line 423 
Line 791 
 { {
     openCloseElement = false;     openCloseElement = false;
  
     if (!isalpha(*p) && *p != '_')      if (!CharSet::isAlNumUnder(Uint8(*p)))
     {  
         std::cout << __LINE__ << std::endl;  
         throw XmlException(XmlException::BAD_START_TAG, _line);         throw XmlException(XmlException::BAD_START_TAG, _line);
     }  
  
     while (*p &&      p++;
         (isalnum(*p) || *p == '_' || *p == '-' || *p == ':' || *p == '.'))  
       while (*p && _isInnerElementChar[Uint8(*p)])
         p++;         p++;
  
     // The next character must be a space:     // The next character must be a space:
  
     if (isspace(*p))      if (_isspace(*p))
     {     {
         *p++ = '\0';         *p++ = '\0';
         _skipWhitespace(p);          _skipWhitespace(_line, p);
     }     }
  
     if (*p == '>')     if (*p == '>')
Line 460 
Line 826 
  
 void XmlParser::_getAttributeNameAndEqual(char*& p) void XmlParser::_getAttributeNameAndEqual(char*& p)
 { {
     if (!isalpha(*p) && *p != '_')      if (!CharSet::isAlNumUnder((Uint8)*p))
     {  
         std::cout << __LINE__ << std::endl;  
         throw XmlException(XmlException::BAD_ATTRIBUTE_NAME, _line);         throw XmlException(XmlException::BAD_ATTRIBUTE_NAME, _line);
     }  
  
     while (*p &&      p++;
         (isalnum(*p) || *p == '_' || *p == '-' || *p == ':' || *p == '.'))  
       while (*p && _isInnerElementChar[Uint8(*p)])
         p++;         p++;
  
     char* term = p;     char* term = p;
  
     _skipWhitespace(p);      _skipWhitespace(_line, p);
  
     if (*p != '=')     if (*p != '=')
     {  
         std::cout << __LINE__ << std::endl;  
         throw XmlException(XmlException::BAD_ATTRIBUTE_NAME, _line);         throw XmlException(XmlException::BAD_ATTRIBUTE_NAME, _line);
     }  
  
     p++;     p++;
  
     _skipWhitespace(p);      _skipWhitespace(_line, p);
  
     *term = '\0';     *term = '\0';
 } }
  
 void XmlParser::_getAttributeValue(char*& p)  
 {  
     // ATTN-B: handle values contained in semiquotes:  
   
     if (*p != '"' && *p != '\'')  
     {  
         std::cout << __LINE__ << std::endl;  
         throw XmlException(XmlException::BAD_ATTRIBUTE_VALUE, _line);  
     }  
   
     char startChar = *p++;  
   
     while (*p && *p != startChar)  
         p++;  
   
     if (*p != startChar)  
     {  
         std::cout << __LINE__ << std::endl;  
         throw XmlException(XmlException::BAD_ATTRIBUTE_VALUE, _line);  
     }  
   
     *p++ = '\0';  
 }  
   
 void XmlParser::_getComment(char*& p) void XmlParser::_getComment(char*& p)
 { {
     // Now p points to first non-whitespace character beyond "<--" sequence:     // Now p points to first non-whitespace character beyond "<--" sequence:
Line 575 
Line 912 
     p++;     p++;
 } }
  
 void XmlParser::_getContent(char*& p)  
 {  
     while (*p && *p != '<')  
     {  
         if (*p == '\n')  
             _line++;  
   
         p++;  
     }  
 }  
   
 void XmlParser::_substituteReferences(char* text)  
 {  
     Uint32 rem = strlen(text);  
   
     for (char* p = text; *p; p++, rem--)  
     {  
         if (*p == '&')  
         {  
             // Look for predefined entity reference:  
   
             Boolean found = false;  
   
             for (Uint32 i = 0; i < _REFERENCES_SIZE; i++)  
             {  
                 Uint32 length = _references[i].length;  
                 const char* match = _references[i].match;  
   
                 if (strncmp(p, _references[i].match, length) == 0)  
                 {  
                     found = true;  
                     *p = _references[i].replacement;  
                     char* q = p + length;  
                     rem = rem - length + 1;  
                     memmove(p + 1, q, rem);  
                 }  
             }  
   
             // If not found, then at least make sure it is well formed:  
   
             if (!found)  
             {  
                 char* start = p;  
                 p++;  
   
                 XmlException::Code code = XmlException::MALFORMED_REFERENCE;  
   
                 if (isalpha(*p) || *p == '_')  
                 {  
                     for (p++; *p && *p != ';'; p++)  
                     {  
                         if (!isalnum(*p) && *p != '_')  
                             throw XmlException(code, _line);  
                     }  
                 }  
                 else if (*p == '#')  
                 {  
                     for (p++ ; *p && *p != ';'; p++)  
                     {  
                         if (!isdigit(*p))  
                             throw XmlException(code, _line);  
                     }  
                 }  
   
                 if (*p != ';')  
                     throw XmlException(code, _line);  
   
                 rem -= p - start;  
             }  
         }  
     }  
 }  
   
 static const char _EMPTY_STRING[] = "";  
   
 void XmlParser::_getElement(char*& p, XmlEntry& entry) void XmlParser::_getElement(char*& p, XmlEntry& entry)
 { {
     entry.attributeCount = 0;  
   
     //--------------------------------------------------------------------------     //--------------------------------------------------------------------------
     // Get the element name (expect one of these: '?', '!', [A-Za-z_])     // Get the element name (expect one of these: '?', '!', [A-Za-z_])
     //--------------------------------------------------------------------------     //--------------------------------------------------------------------------
Line 693 
Line 953 
         else if (memcmp(p, "DOCTYPE", 7) == 0)         else if (memcmp(p, "DOCTYPE", 7) == 0)
         {         {
             entry.type = XmlEntry::DOCTYPE;             entry.type = XmlEntry::DOCTYPE;
             entry.text = _EMPTY_STRING;              entry.text = "";
             _getDocType(p);             _getDocType(p);
             return;             return;
         }         }
Line 705 
Line 965 
         entry.text = ++p;         entry.text = ++p;
  
         if (!_getElementName(p))         if (!_getElementName(p))
         {  
             std::cout << __LINE__ << std::endl;  
             throw(XmlException(XmlException::BAD_END_TAG, _line));             throw(XmlException(XmlException::BAD_END_TAG, _line));
         }  
  
         return;         return;
     }     }
     else if (isalpha(*p) || *p == '_')      else if ((((*p >= 'A') && (*p <= 'Z')) ||
                 ((*p >= 'a') && (*p <= 'z')) ||
                 (*p == '_')))
     {     {
         entry.type = XmlEntry::START_TAG;         entry.type = XmlEntry::START_TAG;
         entry.text = p;         entry.text = p;
Line 727 
Line 986 
         }         }
     }     }
     else     else
     {  
         std::cout << __LINE__ << std::endl;  
         throw XmlException(XmlException::BAD_START_TAG, _line);         throw XmlException(XmlException::BAD_START_TAG, _line);
     }  
  
     //--------------------------------------------------------------------------     //--------------------------------------------------------------------------
     // Grab all the attributes:     // Grab all the attributes:
Line 759 
Line 1015 
         }         }
  
         XmlAttribute attr;         XmlAttribute attr;
           attr.nsType = -1;
         attr.name = p;         attr.name = p;
         _getAttributeNameAndEqual(p);         _getAttributeNameAndEqual(p);
  
         if (*p != '"' && *p != '\'')          // Get the attribute value (e.g., "some value")
           {
               if ((*p != '"') && (*p != '\''))
         {         {
             std::cout << __LINE__ << std::endl;  
             throw XmlException(XmlException::BAD_ATTRIBUTE_VALUE, _line);             throw XmlException(XmlException::BAD_ATTRIBUTE_VALUE, _line);
         }         }
  
         attr.value = p + 1;              char quote = *p++;
         _getAttributeValue(p);  
               char* start;
               _normalize(_line, p, quote, start);
               attr.value = start;
   
               if (*p != quote)
               {
                   throw XmlException(XmlException::BAD_ATTRIBUTE_VALUE, _line);
               }
   
               // Overwrite the closing quote with a null-terminator:
   
               *p++ = '\0';
           }
  
         if (entry.type == XmlEntry::XML_DECLARATION)         if (entry.type == XmlEntry::XML_DECLARATION)
         {         {
             // The next thing must a space or a "?>":             // The next thing must a space or a "?>":
  
             if (!(p[0] == '?' && p[1] == '>') && !isspace(*p))              if (!(p[0] == '?' && p[1] == '>') && !_isspace(*p))
             {             {
                 std::cout << __LINE__ << std::endl;  
                 throw XmlException(                 throw XmlException(
                     XmlException::BAD_ATTRIBUTE_VALUE, _line);                     XmlException::BAD_ATTRIBUTE_VALUE, _line);
             }             }
         }         }
         else if (!(*p == '>' || (p[0] == '/' && p[1] == '>') || isspace(*p)))          else if (!(*p == '>' || (p[0] == '/' && p[1] == '>') || _isspace(*p)))
         {         {
             // The next thing must be a space or a '>':             // The next thing must be a space or a '>':
  
             std::cout << __LINE__ << std::endl;  
             throw XmlException(XmlException::BAD_ATTRIBUTE_VALUE, _line);             throw XmlException(XmlException::BAD_ATTRIBUTE_VALUE, _line);
         }         }
  
         _skipWhitespace(p);          _skipWhitespace(_line, p);
  
         if (entry.attributeCount == XmlEntry::MAX_ATTRIBUTES)          entry.attributes.append(attr);
             throw XmlException(XmlException::TOO_MANY_ATTRIBUTES, _line);  
   
         _substituteReferences((char*)attr.value);  
         entry.attributes[entry.attributeCount++] = attr;  
     }     }
 } }
  
Line 814 
Line 1079 
  
 void XmlEntry::print() const void XmlEntry::print() const
 { {
     std::cout << "=== " << _typeStrings[type] << " ";      PEGASUS_STD(cout) << "=== " << _typeStrings[type] << " ";
  
     Boolean needQuotes = type == XmlEntry::CDATA || type == XmlEntry::CONTENT;     Boolean needQuotes = type == XmlEntry::CDATA || type == XmlEntry::CONTENT;
  
     if (needQuotes)     if (needQuotes)
         std::cout << "\"";          PEGASUS_STD(cout) << "\"";
  
     _printValue(text);     _printValue(text);
  
     if (needQuotes)     if (needQuotes)
         std::cout << "\"";          PEGASUS_STD(cout) << "\"";
  
     std::cout << '\n';      PEGASUS_STD(cout) << '\n';
  
     for (Uint32 i = 0; i < attributeCount; i++)      for (Uint32 i = 0; i < attributes.size(); i++)
     {     {
         std::cout << "    " << attributes[i].name << "=\"";          PEGASUS_STD(cout) << "    " << attributes[i].name << "=\"";
         _printValue(attributes[i].value);         _printValue(attributes[i].value);
         std::cout << "\"" << std::endl;          PEGASUS_STD(cout) << "\"" << PEGASUS_STD(endl);
     }     }
 } }
  
 const XmlAttribute* XmlEntry::findAttribute( const XmlAttribute* XmlEntry::findAttribute(
     const char* name) const     const char* name) const
 { {
     for (Uint32 i = 0; i < attributeCount; i++)      for (Uint32 i = 0; i < attributes.size(); i++)
     {     {
         if (strcmp(attributes[i].name, name) == 0)         if (strcmp(attributes[i].name, name) == 0)
             return &attributes[i];             return &attributes[i];
Line 863 
Line 1128 
 { {
     first = str;     first = str;
  
     while (isspace(*first))      while (_isspace(*first))
         first++;         first++;
  
     if (!*first)     if (!*first)
Line 874 
Line 1139 
  
     last = first + strlen(first);     last = first + strlen(first);
  
     while (last != first && isspace(last[-1]))      while (last != first && _isspace(last[-1]))
         last--;         last--;
 } }
  
Line 920 
Line 1185 
     if (!end || end != last)     if (!end || end != last)
         return false;         return false;
  
     value = Uint32(tmp);      value = static_cast<Real32>(tmp);
     return true;     return true;
 } }
  
Line 944 
Line 1209 
     if (!getAttributeValue(name, tmp))     if (!getAttributeValue(name, tmp))
         return false;         return false;
  
     value = tmp;      value = String(tmp);
     return true;     return true;
 } }
  
   void XmlAppendCString(Buffer& out, const char* str)
   {
       out.append(str, static_cast<Uint32>(strlen(str)));
   }
   
 PEGASUS_NAMESPACE_END PEGASUS_NAMESPACE_END


Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.43.2.4

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2