mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-19 09:42:11 +03:00
759 lines
24 KiB
Java
759 lines
24 KiB
Java
/* XMLUtil.java NanoXML/Java
|
|
*
|
|
* $Revision: 1.5 $
|
|
* $Date: 2002/02/03 21:19:38 $
|
|
* $Name: RELEASE_2_2_1 $
|
|
*
|
|
* This file is part of NanoXML 2 for Java.
|
|
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
|
|
*
|
|
* This software is provided 'as-is', without any express or implied warranty.
|
|
* In no event will the authors be held liable for any damages arising from the
|
|
* use of this software.
|
|
*
|
|
* Permission is granted to anyone to use this software for any purpose,
|
|
* including commercial applications, and to alter it and redistribute it
|
|
* freely, subject to the following restrictions:
|
|
*
|
|
* 1. The origin of this software must not be misrepresented; you must not
|
|
* claim that you wrote the original software. If you use this software in
|
|
* a product, an acknowledgment in the product documentation would be
|
|
* appreciated but is not required.
|
|
*
|
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
* misrepresented as being the original software.
|
|
*
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
|
*/
|
|
|
|
package processing.xml;
|
|
|
|
|
|
import java.io.IOException;
|
|
import java.io.Reader;
|
|
|
|
|
|
/**
|
|
* Utility methods for NanoXML.
|
|
*
|
|
* @author Marc De Scheemaecker
|
|
* @version $Name: RELEASE_2_2_1 $, $Revision: 1.5 $
|
|
*/
|
|
class XMLUtil
|
|
{
|
|
|
|
/**
|
|
* Skips the remainder of a comment.
|
|
* It is assumed that <!- is already read.
|
|
*
|
|
* @param reader the reader
|
|
*
|
|
* @throws java.io.IOException
|
|
* if an error occurred reading the data
|
|
*/
|
|
static void skipComment(StdXMLReader reader)
|
|
throws IOException,
|
|
XMLParseException
|
|
{
|
|
if (reader.read() != '-') {
|
|
XMLUtil.errorExpectedInput(reader.getSystemID(),
|
|
reader.getLineNr(),
|
|
"<!--");
|
|
}
|
|
|
|
int dashesRead = 0;
|
|
|
|
for (;;) {
|
|
char ch = reader.read();
|
|
|
|
switch (ch) {
|
|
case '-':
|
|
dashesRead++;
|
|
break;
|
|
|
|
case '>':
|
|
if (dashesRead == 2) {
|
|
return;
|
|
}
|
|
dashesRead = 0;
|
|
break;
|
|
|
|
default:
|
|
dashesRead = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Skips the remainder of the current XML tag.
|
|
*
|
|
* @param reader the reader
|
|
*
|
|
* @throws java.io.IOException
|
|
* if an error occurred reading the data
|
|
*/
|
|
static void skipTag(StdXMLReader reader)
|
|
throws IOException,
|
|
XMLParseException
|
|
{
|
|
int level = 1;
|
|
|
|
while (level > 0) {
|
|
char ch = reader.read();
|
|
|
|
switch (ch) {
|
|
case '<':
|
|
++level;
|
|
break;
|
|
|
|
case '>':
|
|
--level;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Scans a public ID.
|
|
*
|
|
* @param publicID will contain the public ID
|
|
* @param reader the reader
|
|
*
|
|
* @return the system ID
|
|
*
|
|
* @throws java.io.IOException
|
|
* if an error occurred reading the data
|
|
*/
|
|
static String scanPublicID(StringBuffer publicID,
|
|
StdXMLReader reader)
|
|
throws IOException,
|
|
XMLParseException
|
|
{
|
|
if (! XMLUtil.checkLiteral(reader, "UBLIC")) {
|
|
return null;
|
|
}
|
|
|
|
XMLUtil.skipWhitespace(reader, null);
|
|
publicID.append(XMLUtil.scanString(reader, '\0', null));
|
|
XMLUtil.skipWhitespace(reader, null);
|
|
return XMLUtil.scanString(reader, '\0', null);
|
|
}
|
|
|
|
|
|
/**
|
|
* Scans a system ID.
|
|
*
|
|
* @param reader the reader
|
|
*
|
|
* @return the system ID
|
|
*
|
|
* @throws java.io.IOException
|
|
* if an error occurred reading the data
|
|
*/
|
|
static String scanSystemID(StdXMLReader reader)
|
|
throws IOException,
|
|
XMLParseException
|
|
{
|
|
if (! XMLUtil.checkLiteral(reader, "YSTEM")) {
|
|
return null;
|
|
}
|
|
|
|
XMLUtil.skipWhitespace(reader, null);
|
|
return XMLUtil.scanString(reader, '\0', null);
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieves an identifier from the data.
|
|
*
|
|
* @param reader the reader
|
|
*
|
|
* @throws java.io.IOException
|
|
* if an error occurred reading the data
|
|
*/
|
|
static String scanIdentifier(StdXMLReader reader)
|
|
throws IOException,
|
|
XMLParseException
|
|
{
|
|
StringBuffer result = new StringBuffer();
|
|
|
|
for (;;) {
|
|
char ch = reader.read();
|
|
|
|
if ((ch == '_') || (ch == ':') || (ch == '-') || (ch == '.')
|
|
|| ((ch >= 'a') && (ch <= 'z'))
|
|
|| ((ch >= 'A') && (ch <= 'Z'))
|
|
|| ((ch >= '0') && (ch <= '9')) || (ch > '\u007E')) {
|
|
result.append(ch);
|
|
} else {
|
|
reader.unread(ch);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result.toString();
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieves a delimited string from the data.
|
|
*
|
|
* @param reader the reader
|
|
* @param entityChar the escape character (& or %)
|
|
* @param entityResolver the entity resolver
|
|
*
|
|
* @throws java.io.IOException
|
|
* if an error occurred reading the data
|
|
*/
|
|
static String scanString(StdXMLReader reader,
|
|
char entityChar,
|
|
XMLEntityResolver entityResolver)
|
|
throws IOException,
|
|
XMLParseException
|
|
{
|
|
StringBuffer result = new StringBuffer();
|
|
int startingLevel = reader.getStreamLevel();
|
|
char delim = reader.read();
|
|
|
|
if ((delim != '\'') && (delim != '"')) {
|
|
XMLUtil.errorExpectedInput(reader.getSystemID(),
|
|
reader.getLineNr(),
|
|
"delimited string");
|
|
}
|
|
|
|
for (;;) {
|
|
String str = XMLUtil.read(reader, entityChar);
|
|
char ch = str.charAt(0);
|
|
|
|
if (ch == entityChar) {
|
|
if (str.charAt(1) == '#') {
|
|
result.append(XMLUtil.processCharLiteral(str));
|
|
} else {
|
|
XMLUtil.processEntity(str, reader, entityResolver);
|
|
}
|
|
} else if (ch == '&') {
|
|
reader.unread(ch);
|
|
str = XMLUtil.read(reader, '&');
|
|
if (str.charAt(1) == '#') {
|
|
result.append(XMLUtil.processCharLiteral(str));
|
|
} else {
|
|
result.append(str);
|
|
}
|
|
} else if (reader.getStreamLevel() == startingLevel) {
|
|
if (ch == delim) {
|
|
break;
|
|
} else if ((ch == 9) || (ch == 10) || (ch == 13)) {
|
|
result.append(' ');
|
|
} else {
|
|
result.append(ch);
|
|
}
|
|
} else {
|
|
result.append(ch);
|
|
}
|
|
}
|
|
|
|
return result.toString();
|
|
}
|
|
|
|
|
|
/**
|
|
* Processes an entity.
|
|
*
|
|
* @param entity the entity
|
|
* @param reader the reader
|
|
* @param entityResolver the entity resolver
|
|
*
|
|
* @throws java.io.IOException
|
|
* if an error occurred reading the data
|
|
*/
|
|
static void processEntity(String entity,
|
|
StdXMLReader reader,
|
|
XMLEntityResolver entityResolver)
|
|
throws IOException,
|
|
XMLParseException
|
|
{
|
|
entity = entity.substring(1, entity.length() - 1);
|
|
Reader entityReader = entityResolver.getEntity(reader, entity);
|
|
|
|
if (entityReader == null) {
|
|
XMLUtil.errorInvalidEntity(reader.getSystemID(),
|
|
reader.getLineNr(),
|
|
entity);
|
|
}
|
|
|
|
boolean externalEntity = entityResolver.isExternalEntity(entity);
|
|
reader.startNewStream(entityReader, !externalEntity);
|
|
}
|
|
|
|
|
|
/**
|
|
* Processes a character literal.
|
|
*
|
|
* @param entity the entity
|
|
*
|
|
* @throws java.io.IOException
|
|
* if an error occurred reading the data
|
|
*/
|
|
static char processCharLiteral(String entity)
|
|
throws IOException,
|
|
XMLParseException
|
|
{
|
|
if (entity.charAt(2) == 'x') {
|
|
entity = entity.substring(3, entity.length() - 1);
|
|
return (char) Integer.parseInt(entity, 16);
|
|
} else {
|
|
entity = entity.substring(2, entity.length() - 1);
|
|
return (char) Integer.parseInt(entity, 10);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Skips whitespace from the reader.
|
|
*
|
|
* @param reader the reader
|
|
* @param buffer where to put the whitespace; null if the
|
|
* whitespace does not have to be stored.
|
|
*
|
|
* @throws java.io.IOException
|
|
* if an error occurred reading the data
|
|
*/
|
|
static void skipWhitespace(StdXMLReader reader,
|
|
StringBuffer buffer)
|
|
throws IOException
|
|
{
|
|
char ch;
|
|
|
|
if (buffer == null) {
|
|
do {
|
|
ch = reader.read();
|
|
} while ((ch == ' ') || (ch == '\t') || (ch == '\n'));
|
|
} else {
|
|
for (;;) {
|
|
ch = reader.read();
|
|
|
|
if ((ch != ' ') && (ch != '\t') && (ch != '\n')) {
|
|
break;
|
|
}
|
|
|
|
if (ch == '\n') {
|
|
buffer.append('\n');
|
|
} else {
|
|
buffer.append(' ');
|
|
}
|
|
}
|
|
}
|
|
|
|
reader.unread(ch);
|
|
}
|
|
|
|
|
|
/**
|
|
* Reads a character from the reader.
|
|
*
|
|
* @param reader the reader
|
|
* @param entityChar the escape character (& or %) used to indicate
|
|
* an entity
|
|
*
|
|
* @return the character, or an entity expression (like e.g. &lt;)
|
|
*
|
|
* @throws java.io.IOException
|
|
* if an error occurred reading the data
|
|
*/
|
|
static String read(StdXMLReader reader,
|
|
char entityChar) throws IOException, XMLParseException {
|
|
char ch = reader.read();
|
|
StringBuffer buf = new StringBuffer();
|
|
buf.append(ch);
|
|
|
|
if (ch == entityChar) {
|
|
while (ch != ';') {
|
|
ch = reader.read();
|
|
buf.append(ch);
|
|
}
|
|
}
|
|
|
|
return buf.toString();
|
|
}
|
|
|
|
|
|
/**
|
|
* Reads a character from the reader disallowing entities.
|
|
*
|
|
* @param reader the reader
|
|
* @param entityChar the escape character (& or %) used to indicate
|
|
* an entity
|
|
*/
|
|
static char readChar(StdXMLReader reader,
|
|
char entityChar) throws IOException, XMLParseException {
|
|
String str = XMLUtil.read(reader, entityChar);
|
|
char ch = str.charAt(0);
|
|
|
|
if (ch == entityChar) {
|
|
XMLUtil.errorUnexpectedEntity(reader.getSystemID(),
|
|
reader.getLineNr(),
|
|
str);
|
|
}
|
|
|
|
return ch;
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns true if the data starts with <I>literal</I>.
|
|
* Enough chars are read to determine this result.
|
|
*
|
|
* @param reader the reader
|
|
* @param literal the literal to check
|
|
*
|
|
* @throws java.io.IOException
|
|
* if an error occurred reading the data
|
|
*/
|
|
static boolean checkLiteral(StdXMLReader reader,
|
|
String literal)
|
|
throws IOException,
|
|
XMLParseException
|
|
{
|
|
for (int i = 0; i < literal.length(); i++) {
|
|
if (reader.read() != literal.charAt(i)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLParseException to indicate that an expected string is not
|
|
* encountered.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
* @param expectedString the string that is expected
|
|
*/
|
|
static void errorExpectedInput(String systemID,
|
|
int lineNr,
|
|
String expectedString)
|
|
throws XMLParseException
|
|
{
|
|
throw new XMLParseException(systemID, lineNr,
|
|
"Expected: " + expectedString);
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLParseException to indicate that an entity could not be
|
|
* resolved.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
* @param entity the name of the entity
|
|
*/
|
|
static void errorInvalidEntity(String systemID,
|
|
int lineNr,
|
|
String entity)
|
|
throws XMLParseException
|
|
{
|
|
throw new XMLParseException(systemID, lineNr,
|
|
"Invalid entity: `&" + entity + ";'");
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLParseException to indicate that an entity reference is
|
|
* unexpected at this point.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
* @param entity the name of the entity
|
|
*/
|
|
static void errorUnexpectedEntity(String systemID,
|
|
int lineNr,
|
|
String entity)
|
|
throws XMLParseException
|
|
{
|
|
throw new XMLParseException(systemID, lineNr,
|
|
"No entity reference is expected here ("
|
|
+ entity + ")");
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLParseException to indicate that a CDATA section is
|
|
* unexpected at this point.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
*/
|
|
static void errorUnexpectedCDATA(String systemID,
|
|
int lineNr)
|
|
throws XMLParseException
|
|
{
|
|
throw new XMLParseException(systemID, lineNr,
|
|
"No CDATA section is expected here");
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLParseException to indicate that a string is not expected
|
|
* at this point.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
* @param unexpectedString the string that is unexpected
|
|
*/
|
|
static void errorInvalidInput(String systemID,
|
|
int lineNr,
|
|
String unexpectedString)
|
|
throws XMLParseException
|
|
{
|
|
throw new XMLParseException(systemID, lineNr,
|
|
"Invalid input: " + unexpectedString);
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLParseException to indicate that the closing tag of an
|
|
* element does not match the opening tag.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
* @param expectedName the name of the opening tag
|
|
* @param wrongName the name of the closing tag
|
|
*/
|
|
static void errorWrongClosingTag(String systemID,
|
|
int lineNr,
|
|
String expectedName,
|
|
String wrongName)
|
|
throws XMLParseException
|
|
{
|
|
throw new XMLParseException(systemID, lineNr,
|
|
"Closing tag does not match opening tag: `"
|
|
+ wrongName + "' != `" + expectedName
|
|
+ "'");
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLParseException to indicate that extra data is encountered
|
|
* in a closing tag.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
*/
|
|
static void errorClosingTagNotEmpty(String systemID,
|
|
int lineNr)
|
|
throws XMLParseException
|
|
{
|
|
throw new XMLParseException(systemID, lineNr,
|
|
"Closing tag must be empty");
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLValidationException to indicate that an element is missing.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
* @param parentElementName the name of the parent element
|
|
* @param missingElementName the name of the missing element
|
|
*/
|
|
static void errorMissingElement(String systemID,
|
|
int lineNr,
|
|
String parentElementName,
|
|
String missingElementName)
|
|
throws XMLValidationException
|
|
{
|
|
throw new XMLValidationException(
|
|
XMLValidationException.MISSING_ELEMENT,
|
|
systemID, lineNr,
|
|
missingElementName,
|
|
/*attributeName*/ null,
|
|
/*attributeValue*/ null,
|
|
"Element " + parentElementName
|
|
+ " expects to have a " + missingElementName);
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLValidationException to indicate that an element is
|
|
* unexpected.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
* @param parentElementName the name of the parent element
|
|
* @param unexpectedElementName the name of the unexpected element
|
|
*/
|
|
static void errorUnexpectedElement(String systemID,
|
|
int lineNr,
|
|
String parentElementName,
|
|
String unexpectedElementName)
|
|
throws XMLValidationException
|
|
{
|
|
throw new XMLValidationException(
|
|
XMLValidationException.UNEXPECTED_ELEMENT,
|
|
systemID, lineNr,
|
|
unexpectedElementName,
|
|
/*attributeName*/ null,
|
|
/*attributeValue*/ null,
|
|
"Unexpected " + unexpectedElementName + " in a "
|
|
+ parentElementName);
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLValidationException to indicate that an attribute is
|
|
* missing.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
* @param elementName the name of the element
|
|
* @param attributeName the name of the missing attribute
|
|
*/
|
|
static void errorMissingAttribute(String systemID,
|
|
int lineNr,
|
|
String elementName,
|
|
String attributeName)
|
|
throws XMLValidationException
|
|
{
|
|
throw new XMLValidationException(
|
|
XMLValidationException.MISSING_ATTRIBUTE,
|
|
systemID, lineNr,
|
|
elementName,
|
|
attributeName,
|
|
/*attributeValue*/ null,
|
|
"Element " + elementName + " expects an attribute named "
|
|
+ attributeName);
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLValidationException to indicate that an attribute is
|
|
* unexpected.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
* @param elementName the name of the element
|
|
* @param attributeName the name of the unexpected attribute
|
|
*/
|
|
static void errorUnexpectedAttribute(String systemID,
|
|
int lineNr,
|
|
String elementName,
|
|
String attributeName)
|
|
throws XMLValidationException
|
|
{
|
|
throw new XMLValidationException(
|
|
XMLValidationException.UNEXPECTED_ATTRIBUTE,
|
|
systemID, lineNr,
|
|
elementName,
|
|
attributeName,
|
|
/*attributeValue*/ null,
|
|
"Element " + elementName + " did not expect an attribute "
|
|
+ "named " + attributeName);
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLValidationException to indicate that an attribute has an
|
|
* invalid value.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
* @param elementName the name of the element
|
|
* @param attributeName the name of the attribute
|
|
* @param attributeValue the value of that attribute
|
|
*/
|
|
static void errorInvalidAttributeValue(String systemID,
|
|
int lineNr,
|
|
String elementName,
|
|
String attributeName,
|
|
String attributeValue)
|
|
throws XMLValidationException
|
|
{
|
|
throw new XMLValidationException(
|
|
XMLValidationException.ATTRIBUTE_WITH_INVALID_VALUE,
|
|
systemID, lineNr,
|
|
elementName,
|
|
attributeName,
|
|
attributeValue,
|
|
"Invalid value for attribute " + attributeName);
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLValidationException to indicate that a #PCDATA element was
|
|
* missing.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
* @param parentElementName the name of the parent element
|
|
*/
|
|
static void errorMissingPCData(String systemID,
|
|
int lineNr,
|
|
String parentElementName)
|
|
throws XMLValidationException
|
|
{
|
|
throw new XMLValidationException(
|
|
XMLValidationException.MISSING_PCDATA,
|
|
systemID, lineNr,
|
|
/*elementName*/ null,
|
|
/*attributeName*/ null,
|
|
/*attributeValue*/ null,
|
|
"Missing #PCDATA in element " + parentElementName);
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLValidationException to indicate that a #PCDATA element was
|
|
* unexpected.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
* @param parentElementName the name of the parent element
|
|
*/
|
|
static void errorUnexpectedPCData(String systemID,
|
|
int lineNr,
|
|
String parentElementName)
|
|
throws XMLValidationException
|
|
{
|
|
throw new XMLValidationException(
|
|
XMLValidationException.UNEXPECTED_PCDATA,
|
|
systemID, lineNr,
|
|
/*elementName*/ null,
|
|
/*attributeName*/ null,
|
|
/*attributeValue*/ null,
|
|
"Unexpected #PCDATA in element " + parentElementName);
|
|
}
|
|
|
|
|
|
/**
|
|
* Throws an XMLValidationException.
|
|
*
|
|
* @param systemID the system ID of the data source
|
|
* @param lineNr the line number in the data source
|
|
* @param message the error message
|
|
* @param elementName the name of the element
|
|
* @param attributeName the name of the attribute
|
|
* @param attributeValue the value of that attribute
|
|
*/
|
|
static void validationError(String systemID,
|
|
int lineNr,
|
|
String message,
|
|
String elementName,
|
|
String attributeName,
|
|
String attributeValue)
|
|
throws XMLValidationException
|
|
{
|
|
throw new XMLValidationException(XMLValidationException.MISC_ERROR,
|
|
systemID, lineNr,
|
|
elementName,
|
|
attributeName,
|
|
attributeValue,
|
|
message);
|
|
}
|
|
|
|
}
|