(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.10 and 1.36

version 1.10, 2001/06/16 17:30:38 version 1.36, 2006/01/06 20:49:18
Line 1 
Line 1 
 //%/////////////////////////////////////////////////////////////////////////////  //%2005////////////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000, 2001 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.
 // //
 // Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to // of this software and associated documentation files (the "Software"), to
Line 22 
Line 29 
 // //
 // Author: Mike Brasher (mbrasher@bmc.com) // Author: Mike Brasher (mbrasher@bmc.com)
 // //
 // Modified By:  // Modified By: David Dillard, VERITAS Software Corp.
   //                  (david.dillard@veritas.com)
 // //
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
Line 49 
Line 57 
 //              &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 68 
Line 81 
 // //
 // 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 80 
Line 92 
 // //
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
  
   #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 "Logger.h"
   #include "ExceptionRep.h"
   #include "CharSet.h"
  
 PEGASUS_NAMESPACE_BEGIN PEGASUS_NAMESPACE_BEGIN
  
Line 123 
Line 137 
     char replacement;     char replacement;
 }; };
  
   // ATTN: Add support for more entity references
 static EntityReference _references[] = static EntityReference _references[] =
 { {
     { "&amp;", 5, '&' },     { "&amp;", 5, '&' },
Line 132 
Line 147 
     { "&apos;", 6, '\'' }     { "&apos;", 6, '\'' }
 }; };
  
   
   // Implements a check for a whitespace character, without calling
   // isspace( ).  The isspace( ) function is locale-sensitive,
   // 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)
   {
       return CharSet::isXmlWhiteSpace((Uint8)c);
   }
   
 static Uint32 _REFERENCES_SIZE = (sizeof(_references) / sizeof(_references[0])); static Uint32 _REFERENCES_SIZE = (sizeof(_references) / sizeof(_references[0]));
  
 // Remove all redundant spaces from the given string: // Remove all redundant spaces from the given string:
  
 static void _normalize(char* text) static void _normalize(char* text)
 { {
     Uint32 length = strlen(text);  
     char* p = text;     char* p = text;
     char* end = p + length;      char* end = p + strlen(text);
  
     // Remove leading spaces:     // Remove leading spaces:
  
     while (isspace(*p))      while (_isspace(*p))
         p++;         p++;
  
     if (p != text)     if (p != text)
Line 158 
Line 186 
     {     {
         // Advance to the next space:         // Advance to the next space:
  
         while (*p && !isspace(*p))          while (*p && !_isspace(*p))
             p++;             p++;
  
         if (!*p)         if (!*p)
Line 168 
Line 196 
  
         char* q = p++;         char* q = p++;
  
         while (isspace(*p))          while (_isspace(*p))
             p++;             p++;
  
         // Discard trailing spaces (if we are at the end):         // Discard trailing spaces (if we are at the end):
Line 181 
Line 209 
  
         // Remove the redundant spaces:         // Remove the redundant spaces:
  
         Uint32 n = p - q;          const size_t n = p - q;
  
         if (n > 1)         if (n > 1)
         {         {
Line 219 
Line 247 
     "Semantic error"     "Semantic error"
 }; };
  
   static const char* _xmlKeys[] =
   {
       "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"
   };
   
   // l10n replace _formMessage (comment out the old one)
   /*
 static String _formMessage(Uint32 code, Uint32 line, const String& message) static String _formMessage(Uint32 code, Uint32 line, const String& message)
 { {
     String result = _xmlMessages[Uint32(code) - 1];     String result = _xmlMessages[Uint32(code) - 1];
Line 236 
Line 287 
  
     return result;     return result;
 } }
   */
   
   static MessageLoaderParms _formMessage(Uint32 code, Uint32 line, const String& message)
   {
       String dftMsg = _xmlMessages[Uint32(code) - 1];
       String key = _xmlKeys[Uint32(code) - 1];
           String msg = message;
   
       dftMsg.append(": on line $0");
       if (message.size())
       {
           msg = ": " + msg;
           dftMsg.append("$1");
       }
   
       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,
Line 246 
Line 325 
  
 } }
  
   
   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 260 
Line 354 
  
 } }
  
   
   XmlValidationError::XmlValidationError(
       Uint32 lineNumber,
       MessageLoaderParms& msgParms)
       : XmlException(XmlException::VALIDATION_ERROR, lineNumber, msgParms)
   {
   
   }
   
   
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
 // //
 // XmlSemanticError // XmlSemanticError
Line 274 
Line 378 
  
 } }
  
   
   XmlSemanticError::XmlSemanticError(
       Uint32 lineNumber,
       MessageLoaderParms& msgParms)
       : XmlException(XmlException::SEMANTIC_ERROR, lineNumber, msgParms)
   {
   
   }
   
   
 //////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
 // //
 // XmlParser // XmlParser
Line 286 
Line 400 
  
 } }
  
   inline void _skipWhitespace(Uint32& line, char*& p)
   {
       while (*p && _isspace(*p))
       {
           if (*p == '\n')
               line++;
   
           p++;
       }
   }
   
 Boolean XmlParser::next(XmlEntry& entry) Boolean XmlParser::next(XmlEntry& entry)
 { {
     if (!_putBackStack.isEmpty())     if (!_putBackStack.isEmpty())
Line 310 
Line 435 
  
     // Skip over any whitespace:     // Skip over any whitespace:
  
     _skipWhitespace(_current);      _skipWhitespace(_line, _current);
  
     if (!*_current)     if (!*_current)
     {     {
Line 382 
Line 507 
     // Nothing to do!     // Nothing to do!
 } }
  
 void XmlParser::_skipWhitespace(char*& p)  // A-Za-z0-9_-:.
   static unsigned char _isInnerElementChar[] =
 { {
     while (*p && isspace(*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,
         if (*p == '\n')      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,
             _line++;      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,
         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,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) Boolean XmlParser::_getElementName(char*& p)
 { {
     if (!isalpha(*p) && *p != '_')      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 550 
 { {
     openCloseElement = false;     openCloseElement = false;
  
     if (!isalpha(*p) && *p != '_')      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 457 
Line 585 
  
 void XmlParser::_getAttributeNameAndEqual(char*& p) void XmlParser::_getAttributeNameAndEqual(char*& p)
 { {
     if (!isalpha(*p) && *p != '_')      if (!CharSet::isAlNumUnder((Uint8)*p))
         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 != '=')
         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';
 } }
Line 573 
Line 702 
  
 void XmlParser::_substituteReferences(char* text) void XmlParser::_substituteReferences(char* text)
 { {
     Uint32 rem = strlen(text);      size_t rem = strlen(text);
  
     for (char* p = text; *p; p++, rem--)     for (char* p = text; *p; p++, rem--)
     {     {
         if (*p == '&')         if (*p == '&')
         {         {
             // Look for predefined entity reference:              // Process character or entity reference
  
             Boolean found = false;              Uint16 referenceChar = 0;
               Uint32 referenceLength = 0;
               XmlException::Code code = XmlException::MALFORMED_REFERENCE;
  
             for (Uint32 i = 0; i < _REFERENCES_SIZE; i++)              if (*(p+1) == '#')
             {             {
                 Uint32 length = _references[i].length;                  // Found a character (numeric) reference
                 const char* match = _references[i].match;                  // Determine whether it is decimal or hex
                   if (*(p+2) == 'x')
                   {
                       // Decode a hexadecimal character reference
                       char* q = p+3;
  
                 if (strncmp(p, _references[i].match, length) == 0)                      // At most four digits are allowed, plus trailing ';'
                       Uint32 numDigits;
                       for (numDigits = 0; numDigits < 5; numDigits++, q++)
                 {                 {
                     found = true;                          if (isdigit(*q))
                     *p = _references[i].replacement;                          {
                     char* q = p + length;                              referenceChar = (referenceChar << 4);
                     rem = rem - length + 1;                              referenceChar += (*q - '0');
                     memmove(p + 1, q, rem);                          }
                           else if ((*q >= 'A') && (*q <= 'F'))
                           {
                               referenceChar = (referenceChar << 4);
                               referenceChar += (*q - 'A' + 10);
                           }
                           else if ((*q >= 'a') && (*q <= 'f'))
                           {
                               referenceChar = (referenceChar << 4);
                               referenceChar += (*q - 'a' + 10);
                           }
                           else if (*q == ';')
                           {
                               break;
                           }
                           else
                           {
                               throw XmlException(code, _line);
                 }                 }
             }             }
  
             // If not found, then at least make sure it is well formed:                      // Hex number must be 1 - 4 digits
                       if ((numDigits == 0) || (numDigits > 4))
                       {
                           throw XmlException(code, _line);
                       }
  
             if (!found)                      // ATTN: Currently do not support 16-bit characters
                       if (referenceChar > 0xff)
             {             {
                 char* start = p;                          // ATTN: Is there a good way to say "unsupported"?
                 p++;                          throw XmlException(code, _line);
                       }
  
                 XmlException::Code code = XmlException::MALFORMED_REFERENCE;                      referenceLength = numDigits + 4;
                   }
                   else
                   {
                       // Decode a decimal character reference
                       Uint32 newChar = 0;
                       char* q = p+2;
  
                 if (isalpha(*p) || *p == '_')                      // At most five digits are allowed, plus trailing ';'
                       Uint32 numDigits;
                       for (numDigits = 0; numDigits < 6; numDigits++, q++)
                       {
                           if (isdigit(*q))
                 {                 {
                     for (p++; *p && *p != ';'; p++)                              newChar = (newChar * 10);
                               newChar += (*q - '0');
                           }
                           else if (*q == ';')
                           {
                               break;
                           }
                           else
                     {                     {
                         if (!isalnum(*p) && *p != '_')  
                             throw XmlException(code, _line);                             throw XmlException(code, _line);
                     }                     }
                 }                 }
                 else if (*p == '#')  
                       // Decimal number must be 1 - 5 digits and fit in 16 bits
                       if ((numDigits == 0) || (numDigits > 5) ||
                           (newChar > 0xffff))
                 {                 {
                     for (p++ ; *p && *p != ';'; p++)                          throw XmlException(code, _line);
                       }
   
                       // ATTN: Currently do not support 16-bit characters
                       if (newChar > 0xff)
                     {                     {
                         if (!isdigit(*p))                          // ATTN: Is there a good way to say "unsupported"?
                             throw XmlException(code, _line);                             throw XmlException(code, _line);
                     }                     }
   
                       referenceChar = Uint16(newChar);
                       referenceLength = numDigits + 3;
                   }
               }
               else
               {
                   // Check for entity reference
                   // ATTN: Inefficient if many entity references are supported
                   Uint32 i;
                   for (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)
                       {
                           referenceChar = _references[i].replacement;
                           referenceLength = length;
                           break;
                       }
                 }                 }
  
                 if (*p != ';')                  if (i == _REFERENCES_SIZE)
                   {
                       // Didn't recognize the entity reference
                       // ATTN: Is there a good way to say "unsupported"?
                     throw XmlException(code, _line);                     throw XmlException(code, _line);
   
                 rem -= p - start;  
             }             }
         }         }
   
               // Replace the reference with the correct character
               *p = (char)referenceChar;
               char* q = p + referenceLength;
               rem = rem - referenceLength + 1;
               memmove(p + 1, q, rem);
           }
     }     }
 } }
  
Line 694 
Line 906 
  
         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 751 
Line 965 
         {         {
             // 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))
             {             {
                 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 '>':
  
             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)         if (entry.attributeCount == XmlEntry::MAX_ATTRIBUTES)
             throw XmlException(XmlException::TOO_MANY_ATTRIBUTES, _line);             throw XmlException(XmlException::TOO_MANY_ATTRIBUTES, _line);
Line 837 
Line 1051 
 { {
     first = str;     first = str;
  
     while (isspace(*first))      while (_isspace(*first))
         first++;         first++;
  
     if (!*first)     if (!*first)
Line 848 
Line 1062 
  
     last = first + strlen(first);     last = first + strlen(first);
  
     while (last != first && isspace(last[-1]))      while (last != first && _isspace(last[-1]))
         last--;         last--;
 } }
  
Line 894 
Line 1108 
     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 918 
Line 1132 
     if (!getAttributeValue(name, tmp))     if (!getAttributeValue(name, tmp))
         return false;         return false;
  
     value = tmp;      value = String(tmp);
     return true;     return true;
 } }
  
 void XmlAppendCString(Array<Sint8>& out, const char* str)  void XmlAppendCString(Buffer& out, const char* str)
 { {
     out.append(str, strlen(str));      out.append(str, static_cast<Uint32>(strlen(str)));
 } }
  
 PEGASUS_NAMESPACE_END PEGASUS_NAMESPACE_END


Legend:
Removed from v.1.10  
changed lines
  Added in v.1.36

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2