blob: 3bbcebe62be29711ea545bf1dfaef7e040692606 [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999,2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.xerces.readers;
import org.apache.xerces.framework.XMLErrorReporter;
import org.apache.xerces.utils.QName;
import org.apache.xerces.utils.StringPool;
import org.apache.xerces.utils.XMLCharacterProperties;
import org.xml.sax.Locator;
import org.xml.sax.InputSource;
import java.io.IOException;
/**
* Reader for processing internal entity replacement text.
* <p>
* This reader processes data contained within strings kept
* in the string pool. It provides the support for both
* general and parameter entities. The location support
* as we are processing the replacement text is somewhat
* poor and needs to be updated when "nested locations"
* have been implemented.
* <p>
* For efficiency, we return instances of this class to a
* free list and reuse those instances to process other
* strings.
*
* @version $id$
*/
final class StringReader extends XMLEntityReader {
/**
* Allocate a string reader
*
* @param entityHandler The current entity handler.
* @param errorReporter The current error reporter.
* @param sendCharDataAsCharArray true if char data should be reported using
* char arrays instead of string handles.
* @param lineNumber The line number to return as our position.
* @param columnNumber The column number to return as our position.
* @param stringHandle The StringPool handle for the data to process.
* @param stringPool The string pool.
* @param addEnclosingSpaces If true, treat the data to process as if
* there were a leading and trailing space
* character enclosing the string data.
* @return The reader that will process the string data.
*/
public static StringReader createStringReader(XMLEntityHandler entityHandler,
XMLErrorReporter errorReporter,
boolean sendCharDataAsCharArray,
int lineNumber,
int columnNumber,
int stringHandle,
StringPool stringPool,
boolean addEnclosingSpaces)
{
StringReader reader = null;
synchronized (StringReader.class) {
reader = fgFreeReaders;
if (reader == null) {
return new StringReader(entityHandler, errorReporter, sendCharDataAsCharArray, lineNumber, columnNumber,
stringHandle, stringPool, addEnclosingSpaces);
}
fgFreeReaders = reader.fNextFreeReader;
}
reader.init(entityHandler, errorReporter, sendCharDataAsCharArray, lineNumber, columnNumber,
stringHandle, stringPool, addEnclosingSpaces);
return reader;
}
//
//
//
private StringReader(XMLEntityHandler entityHandler, XMLErrorReporter errorReporter,
boolean sendCharDataAsCharArray, int lineNumber, int columnNumber,
int stringHandle, StringPool stringPool, boolean addEnclosingSpaces)
{
super(entityHandler, errorReporter, sendCharDataAsCharArray, lineNumber, columnNumber);
fStringPool = stringPool;
fData = fStringPool.toString(stringHandle);
fCurrentOffset = 0;
fEndOffset = fData.length();
if (addEnclosingSpaces) {
fMostRecentChar = ' ';
fCurrentOffset--;
oweTrailingSpace = hadTrailingSpace = true;
} else {
fMostRecentChar = fEndOffset == 0 ? -1 : fData.charAt(0);
}
}
private void init(XMLEntityHandler entityHandler, XMLErrorReporter errorReporter,
boolean sendCharDataAsCharArray, int lineNumber, int columnNumber,
int stringHandle, StringPool stringPool, boolean addEnclosingSpaces)
{
super.init(entityHandler, errorReporter, sendCharDataAsCharArray, lineNumber, columnNumber);
fStringPool = stringPool;
fData = fStringPool.toString(stringHandle);
fCurrentOffset = 0;
fEndOffset = fData.length();
fNextFreeReader = null;
if (addEnclosingSpaces) {
fMostRecentChar = ' ';
fCurrentOffset--;
oweTrailingSpace = hadTrailingSpace = true;
} else {
fMostRecentChar = fEndOffset == 0 ? -1 : fData.charAt(0);
oweTrailingSpace = hadTrailingSpace = false;
}
}
//
//
//
public int addString(int offset, int length) {
if (length == 0)
return 0;
return fStringPool.addString(fData.substring(offset, offset + length));
}
//
//
//
public int addSymbol(int offset, int length) {
if (length == 0)
return 0;
return fStringPool.addSymbol(fData.substring(offset, offset + length));
}
//
//
//
public void append(XMLEntityHandler.CharBuffer charBuffer, int offset, int length) {
boolean addSpace = false;
for (int i = 0; i < length; i++) {
try {
charBuffer.append(fData.charAt(offset++));
} catch (StringIndexOutOfBoundsException ex) {
if (offset == fEndOffset + 1 && hadTrailingSpace) {
charBuffer.append(' ');
} else {
System.err.println("StringReader.append()");
throw ex;
}
}
}
}
//
//
//
private int loadNextChar() {
if (++fCurrentOffset >= fEndOffset) {
if (oweTrailingSpace) {
oweTrailingSpace = false;
fMostRecentChar = ' ';
} else {
fMostRecentChar = -1;
}
} else {
fMostRecentChar = fData.charAt(fCurrentOffset);
}
return fMostRecentChar;
}
//
//
//
public XMLEntityHandler.EntityReader changeReaders() throws Exception {
XMLEntityHandler.EntityReader nextReader = super.changeReaders();
synchronized (StringReader.class) {
fNextFreeReader = fgFreeReaders;
fgFreeReaders = this;
}
return nextReader;
}
//
//
//
public boolean lookingAtChar(char chr, boolean skipPastChar) throws Exception {
int ch = fMostRecentChar;
if (ch != chr) {
if (ch == -1) {
return changeReaders().lookingAtChar(chr, skipPastChar);
}
return false;
}
if (skipPastChar) {
if (++fCurrentOffset >= fEndOffset) {
if (oweTrailingSpace) {
oweTrailingSpace = false;
fMostRecentChar = ' ';
} else {
fMostRecentChar = -1;
}
} else {
fMostRecentChar = fData.charAt(fCurrentOffset);
}
}
return true;
}
//
//
//
public boolean lookingAtValidChar(boolean skipPastChar) throws Exception {
int ch = fMostRecentChar;
if (ch < 0xD800) {
if (ch < 0x20 && ch != 0x09 && ch != 0x0A && ch != 0x0D) {
if (ch == -1)
return changeReaders().lookingAtValidChar(skipPastChar);
return false;
}
if (skipPastChar) {
if (++fCurrentOffset >= fEndOffset) {
if (oweTrailingSpace) {
oweTrailingSpace = false;
fMostRecentChar = ' ';
} else {
fMostRecentChar = -1;
}
} else {
fMostRecentChar = fData.charAt(fCurrentOffset);
}
}
return true;
}
if (ch > 0xFFFD) {
return false;
}
if (ch < 0xDC00) {
if (fCurrentOffset + 1 >= fEndOffset) {
return false;
}
ch = fData.charAt(fCurrentOffset + 1);
if (ch < 0xDC00 || ch >= 0xE000) {
return false;
} else if (!skipPastChar) {
return true;
} else {
fCurrentOffset++;
}
} else if (ch < 0xE000) {
return false;
}
if (skipPastChar) {
if (++fCurrentOffset >= fEndOffset) {
if (oweTrailingSpace) {
oweTrailingSpace = false;
fMostRecentChar = ' ';
} else {
fMostRecentChar = -1;
}
} else {
fMostRecentChar = fData.charAt(fCurrentOffset);
}
}
return true;
}
//
//
//
public boolean lookingAtSpace(boolean skipPastChar) throws Exception {
int ch = fMostRecentChar;
if (ch > 0x20)
return false;
if (ch == 0x20 || ch == 0x0A || ch == 0x0D || ch == 0x09) {
if (skipPastChar) {
loadNextChar();
}
return true;
}
if (ch == -1) {
return changeReaders().lookingAtSpace(skipPastChar);
}
return false;
}
//
//
//
public void skipToChar(char chr) throws Exception {
//
// REVISIT - this will skip invalid characters without reporting them.
//
int ch = fMostRecentChar;
while (true) {
if (ch == chr)
return;
if (ch == -1) {
changeReaders().skipToChar(chr);
return;
}
ch = loadNextChar();
}
}
//
//
//
public void skipPastSpaces() throws Exception {
int ch = fMostRecentChar;
if (ch == -1) {
changeReaders().skipPastSpaces();
return;
}
while (true) {
if (ch > 0x20 || (ch != 0x20 && ch != 0x0A && ch != 0x09 && ch != 0x0D)) {
fMostRecentChar = ch;
return;
}
if (++fCurrentOffset >= fEndOffset) {
changeReaders().skipPastSpaces();
return;
}
ch = fData.charAt(fCurrentOffset);
}
}
//
//
//
public void skipPastName(char fastcheck) throws Exception {
int ch = fMostRecentChar;
if (ch < 0x80) {
if (ch == -1 || XMLCharacterProperties.fgAsciiInitialNameChar[ch] == 0)
return;
} else {
if (!fCalledCharPropInit) {
XMLCharacterProperties.initCharFlags();
fCalledCharPropInit = true;
}
if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_InitialNameCharFlag) == 0)
return;
}
while (true) {
ch = loadNextChar();
if (fastcheck == ch)
return;
if (ch < 0x80) {
if (ch == -1 || XMLCharacterProperties.fgAsciiNameChar[ch] == 0)
return;
} else {
if (!fCalledCharPropInit) {
XMLCharacterProperties.initCharFlags();
fCalledCharPropInit = true;
}
if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_NameCharFlag) == 0)
return;
}
}
}
//
//
//
public void skipPastNmtoken(char fastcheck) throws Exception {
int ch = fMostRecentChar;
while (true) {
if (fastcheck == ch)
return;
if (ch < 0x80) {
if (ch == -1 || XMLCharacterProperties.fgAsciiNameChar[ch] == 0)
return;
} else {
if (!fCalledCharPropInit) {
XMLCharacterProperties.initCharFlags();
fCalledCharPropInit = true;
}
if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_NameCharFlag) == 0)
return;
}
ch = loadNextChar();
}
}
//
//
//
public boolean skippedString(char[] s) throws Exception {
int ch = fMostRecentChar;
if (ch != s[0]) {
if (ch == -1)
return changeReaders().skippedString(s);
return false;
}
if (fCurrentOffset + s.length > fEndOffset)
return false;
for (int i = 1; i < s.length; i++) {
if (fData.charAt(fCurrentOffset + i) != s[i])
return false;
}
fCurrentOffset += (s.length - 1);
loadNextChar();
return true;
}
//
//
//
public int scanInvalidChar() throws Exception {
int ch = fMostRecentChar;
if (ch == -1)
return changeReaders().scanInvalidChar();
loadNextChar();
return ch;
}
//
//
//
public int scanCharRef(boolean hex) throws Exception {
int ch = fMostRecentChar;
if (ch == -1)
return changeReaders().scanCharRef(hex);
int num = 0;
if (hex) {
if (ch > 'f' || XMLCharacterProperties.fgAsciiXDigitChar[ch] == 0)
return XMLEntityHandler.CHARREF_RESULT_INVALID_CHAR;
num = ch - (ch < 'A' ? '0' : (ch < 'a' ? 'A' : 'a') - 10);
} else {
if (ch < '0' || ch > '9')
return XMLEntityHandler.CHARREF_RESULT_INVALID_CHAR;
num = ch - '0';
}
boolean toobig = false;
while (true) {
ch = loadNextChar();
if (ch == -1)
return XMLEntityHandler.CHARREF_RESULT_SEMICOLON_REQUIRED;
if (hex) {
if (ch > 'f' || XMLCharacterProperties.fgAsciiXDigitChar[ch] == 0)
break;
} else {
if (ch < '0' || ch > '9')
break;
}
if (hex) {
int dig = ch - (ch < 'A' ? '0' : (ch < 'a' ? 'A' : 'a') - 10);
num = (num << 4) + dig;
} else {
int dig = ch - '0';
num = (num * 10) + dig;
}
if (num > 0x10FFFF) {
toobig = true;
num = 0;
}
}
if (ch != ';')
return XMLEntityHandler.CHARREF_RESULT_SEMICOLON_REQUIRED;
loadNextChar();
if (toobig)
return XMLEntityHandler.CHARREF_RESULT_OUT_OF_RANGE;
return num;
}
//
//
//
public int scanStringLiteral() throws Exception {
boolean single;
if (!(single = lookingAtChar('\'', true)) && !lookingAtChar('\"', true)) {
return XMLEntityHandler.STRINGLIT_RESULT_QUOTE_REQUIRED;
}
int offset = fCurrentOffset;
char qchar = single ? '\'' : '\"';
while (!lookingAtChar(qchar, false)) {
if (!lookingAtValidChar(true)) {
return XMLEntityHandler.STRINGLIT_RESULT_INVALID_CHAR;
}
}
int stringIndex = addString(offset, fCurrentOffset - offset);
lookingAtChar(qchar, true); // move past qchar
return stringIndex;
}
//
// [10] AttValue ::= '"' ([^<&"] | Reference)* '"'
// | "'" ([^<&'] | Reference)* "'"
//
public int scanAttValue(char qchar, boolean asSymbol) throws Exception
{
int offset = fCurrentOffset;
while (true) {
if (lookingAtChar(qchar, false)) {
break;
}
if (lookingAtChar(' ', true)) {
continue;
}
if (lookingAtSpace(false)) {
return XMLEntityHandler.ATTVALUE_RESULT_COMPLEX;
}
if (lookingAtChar('&', false)) {
return XMLEntityHandler.ATTVALUE_RESULT_COMPLEX;
}
if (lookingAtChar('<', false)) {
return XMLEntityHandler.ATTVALUE_RESULT_LESSTHAN;
}
if (!lookingAtValidChar(true)) {
return XMLEntityHandler.ATTVALUE_RESULT_INVALID_CHAR;
}
}
int result = asSymbol ? addSymbol(offset, fCurrentOffset - offset) : addString(offset, fCurrentOffset - offset);
lookingAtChar(qchar, true);
return result;
}
//
// [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"'
// | "'" ([^%&'] | PEReference | Reference)* "'"
//
// The values in the following table are defined as:
//
// 0 - not special
// 1 - quote character
// 2 - reference
// 3 - peref
// 4 - invalid
//
public static final byte fgAsciiEntityValueChar[] = {
4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4, 0, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 1, 0, 0, 3, 2, 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
};
public int scanEntityValue(int qchar, boolean createString) throws Exception
{
int offset = fCurrentOffset;
int ch = fMostRecentChar;
while (true) {
if (ch == -1) {
changeReaders(); // do not call next reader, our caller may need to change the parameters
return XMLEntityHandler.ENTITYVALUE_RESULT_END_OF_INPUT;
}
if (ch < 0x80) {
switch (fgAsciiEntityValueChar[ch]) {
case 1: // quote char
if (ch == qchar) {
if (!createString)
return XMLEntityHandler.ENTITYVALUE_RESULT_FINISHED;
int length = fCurrentOffset - offset;
int result = length == 0 ? StringPool.EMPTY_STRING : addString(offset, length);
loadNextChar();
return result;
}
// the other quote character is not special
// fall through
case 0: // non-special char
if (++fCurrentOffset >= fEndOffset) {
if (oweTrailingSpace) {
oweTrailingSpace = false;
ch = fMostRecentChar = ' ';
} else {
ch = fMostRecentChar = -1;
}
} else {
ch = fMostRecentChar = fData.charAt(fCurrentOffset);
}
continue;
case 2: // reference
return XMLEntityHandler.ENTITYVALUE_RESULT_REFERENCE;
case 3: // peref
return XMLEntityHandler.ENTITYVALUE_RESULT_PEREF;
case 4: // invalid
return XMLEntityHandler.ENTITYVALUE_RESULT_INVALID_CHAR;
}
} else if (ch < 0xD800) {
ch = loadNextChar();
} else if (ch >= 0xE000 && (ch <= 0xFFFD || (ch >= 0x10000 && ch <= 0x10FFFF))) {
//
// REVISIT - needs more code to check surrogates.
//
ch = loadNextChar();
} else {
return XMLEntityHandler.ENTITYVALUE_RESULT_INVALID_CHAR;
}
}
}
//
//
//
public boolean scanExpectedName(char fastcheck, StringPool.CharArrayRange expectedName) throws Exception {
int ch = fMostRecentChar;
if (ch == -1) {
return changeReaders().scanExpectedName(fastcheck, expectedName);
}
if (!fCalledCharPropInit) {
XMLCharacterProperties.initCharFlags();
fCalledCharPropInit = true;
}
int nameOffset = fCurrentOffset;
if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_InitialNameCharFlag) == 0)
return false;
while (true) {
ch = loadNextChar();
if (fastcheck == ch)
break;
if (ch == -1)
break;
if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_NameCharFlag) == 0)
break;
}
int nameIndex = fStringPool.addSymbol(fData.substring(nameOffset, fCurrentOffset));
// DEFECT !! check name against expected name
return true;
}
//
//
//
public void scanQName(char fastcheck, QName qname) throws Exception {
int ch = fMostRecentChar;
if (ch == -1) {
changeReaders().scanQName(fastcheck, qname);
return;
}
if (!fCalledCharPropInit) {
XMLCharacterProperties.initCharFlags();
fCalledCharPropInit = true;
}
int nameOffset = fCurrentOffset;
if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_InitialNameCharFlag) == 0) {
qname.clear();
return;
}
while (true) {
ch = loadNextChar();
if (fastcheck == ch)
break;
if (ch == -1)
break;
if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_NameCharFlag) == 0)
break;
}
qname.clear();
qname.rawname = fStringPool.addSymbol(fData.substring(nameOffset, fCurrentOffset));
int index = fData.indexOf(':', nameOffset);
if (index != -1) {
qname.prefix = fStringPool.addSymbol(fData.substring(nameOffset, index));
int indexOfSpaceChar = fData.indexOf( ' ', index + 1 );//one past : look for blank
String localPart;
if( indexOfSpaceChar != -1 ){//found one
localPart = fData.substring(index+1, indexOfSpaceChar );
qname.localpart = fStringPool.addSymbol(localPart);
} else{//then get up to end of String
int lenfData = fData.length();
localPart = fData.substring( index + 1, lenfData );
qname.localpart = fStringPool.addSymbol(localPart);
}
qname.localpart = fStringPool.addSymbol(localPart);
}
else {
qname.localpart = qname.rawname;
}
} // scanQName(char,QName)
//
//
//
public int scanName(char fastcheck) throws Exception {
int ch = fMostRecentChar;
if (ch == -1) {
return changeReaders().scanName(fastcheck);
}
if (!fCalledCharPropInit) {
XMLCharacterProperties.initCharFlags();
fCalledCharPropInit = true;
}
int nameOffset = fCurrentOffset;
if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_InitialNameCharFlag) == 0)
return -1;
while (true) {
if (++fCurrentOffset >= fEndOffset) {
if (oweTrailingSpace) {
oweTrailingSpace = false;
fMostRecentChar = ' ';
} else {
fMostRecentChar = -1;
}
break;
}
ch = fMostRecentChar = fData.charAt(fCurrentOffset);
if (fastcheck == ch)
break;
if ((XMLCharacterProperties.fgCharFlags[ch] & XMLCharacterProperties.E_NameCharFlag) == 0)
break;
}
int nameIndex = fStringPool.addSymbol(fData.substring(nameOffset, fCurrentOffset));
return nameIndex;
}
//
// There are no leading/trailing space checks here because scanContent cannot
// be called on a parameter entity reference value.
//
private int recognizeMarkup(int ch) throws Exception {
if (ch == -1) {
return XMLEntityHandler.CONTENT_RESULT_MARKUP_END_OF_INPUT;
}
switch (ch) {
case '?':
loadNextChar();
return XMLEntityHandler.CONTENT_RESULT_START_OF_PI;
case '!':
ch = loadNextChar();
if (ch == -1) {
fCurrentOffset -= 2;
loadNextChar();
return XMLEntityHandler.CONTENT_RESULT_MARKUP_END_OF_INPUT;
}
if (ch == '-') {
ch = loadNextChar();
if (ch == -1) {
fCurrentOffset -= 3;
loadNextChar();
return XMLEntityHandler.CONTENT_RESULT_MARKUP_END_OF_INPUT;
}
if (ch == '-') {
loadNextChar();
return XMLEntityHandler.CONTENT_RESULT_START_OF_COMMENT;
}
break;
}
if (ch == '[') {
for (int i = 0; i < 6; i++) {
ch = loadNextChar();
if (ch == -1) {
fCurrentOffset -= (3 + i);
loadNextChar();
return XMLEntityHandler.CONTENT_RESULT_MARKUP_END_OF_INPUT;
}
if (ch != cdata_string[i]) {
return XMLEntityHandler.CONTENT_RESULT_MARKUP_NOT_RECOGNIZED;
}
}
loadNextChar();
return XMLEntityHandler.CONTENT_RESULT_START_OF_CDSECT;
}
break;
case '/':
loadNextChar();
return XMLEntityHandler.CONTENT_RESULT_START_OF_ETAG;
default:
return XMLEntityHandler.CONTENT_RESULT_START_OF_ELEMENT;
}
return XMLEntityHandler.CONTENT_RESULT_MARKUP_NOT_RECOGNIZED;
}
private int recognizeReference(int ch) throws Exception {
if (ch == -1) {
return XMLEntityHandler.CONTENT_RESULT_MARKUP_END_OF_INPUT;
}
//
// [67] Reference ::= EntityRef | CharRef
// [68] EntityRef ::= '&' Name ';'
// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
//
if (ch == '#') {
loadNextChar();
return XMLEntityHandler.CONTENT_RESULT_START_OF_CHARREF;
} else {
return XMLEntityHandler.CONTENT_RESULT_START_OF_ENTITYREF;
}
}
public int scanContent(QName element) throws Exception {
int ch = fMostRecentChar;
if (ch == -1) {
return changeReaders().scanContent(element);
}
int offset = fCurrentOffset;
if (ch < 0x80) {
switch (XMLCharacterProperties.fgAsciiWSCharData[ch]) {
case 0:
ch = loadNextChar();
break;
case 1:
ch = loadNextChar();
if (!fInCDSect) {
return recognizeMarkup(ch);
}
break;
case 2:
ch = loadNextChar();
if (!fInCDSect) {
return recognizeReference(ch);
}
break;
case 3:
ch = loadNextChar();
if (ch == ']' && fCurrentOffset + 1 < fEndOffset && fData.charAt(fCurrentOffset + 1) == '>') {
loadNextChar();
loadNextChar();
return XMLEntityHandler.CONTENT_RESULT_END_OF_CDSECT;
}
break;
case 4:
return XMLEntityHandler.CONTENT_RESULT_INVALID_CHAR;
case 5:
do {
ch = loadNextChar();
if (ch == -1) {
callCharDataHandler(offset, fEndOffset, true);
return changeReaders().scanContent(element);
}
} while (ch == 0x20 || ch == 0x0A || ch == 0x0D || ch == 0x09);
if (ch < 0x80) {
switch (XMLCharacterProperties.fgAsciiCharData[ch]) {
case 0:
ch = loadNextChar();
break;
case 1:
ch = loadNextChar();
if (!fInCDSect) {
callCharDataHandler(offset, fCurrentOffset - 1, true);
return recognizeMarkup(ch);
}
break;
case 2:
ch = loadNextChar();
if (!fInCDSect) {
callCharDataHandler(offset, fCurrentOffset - 1, true);
return recognizeReference(ch);
}
break;
case 3:
ch = loadNextChar();
if (ch == ']' && fCurrentOffset + 1 < fEndOffset && fData.charAt(fCurrentOffset + 1) == '>') {
callCharDataHandler(offset, fCurrentOffset - 1, true);
loadNextChar();
loadNextChar();
return XMLEntityHandler.CONTENT_RESULT_END_OF_CDSECT;
}
break;
case 4:
callCharDataHandler(offset, fCurrentOffset, true);
return XMLEntityHandler.CONTENT_RESULT_INVALID_CHAR;
}
} else {
if (ch == 0xFFFE || ch == 0xFFFF) {
callCharDataHandler(offset, fCurrentOffset, true);
return XMLEntityHandler.CONTENT_RESULT_INVALID_CHAR;
}
ch = loadNextChar();
}
}
} else {
if (ch == 0xFFFE || ch == 0xFFFF) {
callCharDataHandler(offset, fCurrentOffset, false);
return XMLEntityHandler.CONTENT_RESULT_INVALID_CHAR;
}
ch = loadNextChar();
}
while (true) {
if (ch == -1) {
callCharDataHandler(offset, fEndOffset, false);
return changeReaders().scanContent(element);
}
if (ch >= 0x80)
break;
if (XMLCharacterProperties.fgAsciiCharData[ch] != 0)
break;
ch = loadNextChar();
}
while (true) { // REVISIT - EOF check ?
if (ch < 0x80) {
switch (XMLCharacterProperties.fgAsciiCharData[ch]) {
case 0:
ch = loadNextChar();
break;
case 1:
ch = loadNextChar();
if (!fInCDSect) {
callCharDataHandler(offset, fCurrentOffset - 1, false);
return recognizeMarkup(ch);
}
break;
case 2:
ch = loadNextChar();
if (!fInCDSect) {
callCharDataHandler(offset, fCurrentOffset - 1, false);
return recognizeReference(ch);
}
break;
case 3:
ch = loadNextChar();
if (ch == ']' && fCurrentOffset + 1 < fEndOffset && fData.charAt(fCurrentOffset + 1) == '>') {
callCharDataHandler(offset, fCurrentOffset - 1, false);
loadNextChar();
loadNextChar();
return XMLEntityHandler.CONTENT_RESULT_END_OF_CDSECT;
}
break;
case 4:
callCharDataHandler(offset, fCurrentOffset, false);
return XMLEntityHandler.CONTENT_RESULT_INVALID_CHAR;
}
} else {
if (ch == 0xFFFE || ch == 0xFFFF) {
callCharDataHandler(offset, fCurrentOffset, false);
return XMLEntityHandler.CONTENT_RESULT_INVALID_CHAR;
}
ch = loadNextChar();
}
if (ch == -1) {
callCharDataHandler(offset, fCurrentOffset, false);
return changeReaders().scanContent(element);
}
}
}
//
//
//
private void callCharDataHandler(int offset, int endOffset, boolean isWhitespace) throws Exception {
int length = endOffset - offset;
if (!fSendCharDataAsCharArray) {
int stringIndex = addString(offset, length);
if (isWhitespace)
fCharDataHandler.processWhitespace(stringIndex);
else
fCharDataHandler.processCharacters(stringIndex);
return;
}
if (isWhitespace)
fCharDataHandler.processWhitespace(fData.toCharArray(), offset, length);
else
fCharDataHandler.processCharacters(fData.toCharArray(), offset, length);
}
//
//
//
private static final char[] cdata_string = { 'C','D','A','T','A','[' };
//
//
//
private StringPool fStringPool = null;
private String fData = null;
private int fEndOffset;
private boolean hadTrailingSpace = false;
private boolean oweTrailingSpace = false;
private int fMostRecentChar;
private StringReader fNextFreeReader = null;
private static StringReader fgFreeReaders = null;
private boolean fCalledCharPropInit = false;
}