0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package org.apache.xerces.impl;
0019:
0020: import java.io.IOException;
0021:
0022: import org.apache.xerces.impl.msg.XMLMessageFormatter;
0023: import org.apache.xerces.util.XMLChar;
0024: import org.apache.xerces.util.XML11Char;
0025: import org.apache.xerces.util.XMLStringBuffer;
0026: import org.apache.xerces.xni.QName;
0027: import org.apache.xerces.xni.XMLString;
0028:
0029: /**
0030: * Implements the entity scanner methods in
0031: * the context of XML 1.1.
0032: *
0033: * @xerces.internal
0034: *
0035: * @author Michael Glavassevich, IBM
0036: * @author Neil Graham, IBM
0037: * @version $Id: XML11EntityScanner.java 568406 2007-08-22 04:22:40Z mrglavas $
0038: */
0039: public class XML11EntityScanner extends XMLEntityScanner {
0040:
0041: //
0042: // Constructors
0043: //
0044:
0045: /** Default constructor. */
0046: public XML11EntityScanner() {
0047: super ();
0048: } // <init>()
0049:
0050: //
0051: // XMLEntityScanner methods
0052: //
0053:
0054: /**
0055: * Returns the next character on the input.
0056: * <p>
0057: * <strong>Note:</strong> The character is <em>not</em> consumed.
0058: *
0059: * @throws IOException Thrown if i/o error occurs.
0060: * @throws EOFException Thrown on end of file.
0061: */
0062: public int peekChar() throws IOException {
0063:
0064: // load more characters, if needed
0065: if (fCurrentEntity.position == fCurrentEntity.count) {
0066: load(0, true);
0067: }
0068:
0069: // peek at character
0070: int c = fCurrentEntity.ch[fCurrentEntity.position];
0071:
0072: // return peeked character
0073: if (fCurrentEntity.isExternal()) {
0074: return (c != '\r' && c != 0x85 && c != 0x2028) ? c : '\n';
0075: } else {
0076: return c;
0077: }
0078:
0079: } // peekChar():int
0080:
0081: /**
0082: * Returns the next character on the input.
0083: * <p>
0084: * <strong>Note:</strong> The character is consumed.
0085: *
0086: * @throws IOException Thrown if i/o error occurs.
0087: * @throws EOFException Thrown on end of file.
0088: */
0089: public int scanChar() throws IOException {
0090:
0091: // load more characters, if needed
0092: if (fCurrentEntity.position == fCurrentEntity.count) {
0093: load(0, true);
0094: }
0095:
0096: // scan character
0097: int c = fCurrentEntity.ch[fCurrentEntity.position++];
0098: boolean external = false;
0099: if (c == '\n'
0100: || ((c == '\r' || c == 0x85 || c == 0x2028) && (external = fCurrentEntity
0101: .isExternal()))) {
0102: fCurrentEntity.lineNumber++;
0103: fCurrentEntity.columnNumber = 1;
0104: if (fCurrentEntity.position == fCurrentEntity.count) {
0105: fCurrentEntity.ch[0] = (char) c;
0106: load(1, false);
0107: }
0108: if (c == '\r' && external) {
0109: int cc = fCurrentEntity.ch[fCurrentEntity.position++];
0110: if (cc != '\n' && cc != 0x85) {
0111: fCurrentEntity.position--;
0112: }
0113: }
0114: c = '\n';
0115: }
0116:
0117: // return character that was scanned
0118: fCurrentEntity.columnNumber++;
0119: return c;
0120:
0121: } // scanChar():int
0122:
0123: /**
0124: * Returns a string matching the NMTOKEN production appearing immediately
0125: * on the input as a symbol, or null if NMTOKEN Name string is present.
0126: * <p>
0127: * <strong>Note:</strong> The NMTOKEN characters are consumed.
0128: * <p>
0129: * <strong>Note:</strong> The string returned must be a symbol. The
0130: * SymbolTable can be used for this purpose.
0131: *
0132: * @throws IOException Thrown if i/o error occurs.
0133: * @throws EOFException Thrown on end of file.
0134: *
0135: * @see org.apache.xerces.util.SymbolTable
0136: * @see org.apache.xerces.util.XML11Char#isXML11Name
0137: */
0138: public String scanNmtoken() throws IOException {
0139: // load more characters, if needed
0140: if (fCurrentEntity.position == fCurrentEntity.count) {
0141: load(0, true);
0142: }
0143:
0144: // scan nmtoken
0145: int offset = fCurrentEntity.position;
0146:
0147: do {
0148: char ch = fCurrentEntity.ch[fCurrentEntity.position];
0149: if (XML11Char.isXML11Name(ch)) {
0150: if (++fCurrentEntity.position == fCurrentEntity.count) {
0151: int length = fCurrentEntity.position - offset;
0152: if (length == fCurrentEntity.ch.length) {
0153: // bad luck we have to resize our buffer
0154: char[] tmp = new char[fCurrentEntity.ch.length << 1];
0155: System.arraycopy(fCurrentEntity.ch, offset,
0156: tmp, 0, length);
0157: fCurrentEntity.ch = tmp;
0158: } else {
0159: System.arraycopy(fCurrentEntity.ch, offset,
0160: fCurrentEntity.ch, 0, length);
0161: }
0162: offset = 0;
0163: if (load(length, false)) {
0164: break;
0165: }
0166: }
0167: } else if (XML11Char.isXML11NameHighSurrogate(ch)) {
0168: if (++fCurrentEntity.position == fCurrentEntity.count) {
0169: int length = fCurrentEntity.position - offset;
0170: if (length == fCurrentEntity.ch.length) {
0171: // bad luck we have to resize our buffer
0172: char[] tmp = new char[fCurrentEntity.ch.length << 1];
0173: System.arraycopy(fCurrentEntity.ch, offset,
0174: tmp, 0, length);
0175: fCurrentEntity.ch = tmp;
0176: } else {
0177: System.arraycopy(fCurrentEntity.ch, offset,
0178: fCurrentEntity.ch, 0, length);
0179: }
0180: offset = 0;
0181: if (load(length, false)) {
0182: --fCurrentEntity.startPosition;
0183: --fCurrentEntity.position;
0184: break;
0185: }
0186: }
0187: char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
0188: if (!XMLChar.isLowSurrogate(ch2)
0189: || !XML11Char.isXML11Name(XMLChar.supplemental(
0190: ch, ch2))) {
0191: --fCurrentEntity.position;
0192: break;
0193: }
0194: if (++fCurrentEntity.position == fCurrentEntity.count) {
0195: int length = fCurrentEntity.position - offset;
0196: if (length == fCurrentEntity.ch.length) {
0197: // bad luck we have to resize our buffer
0198: char[] tmp = new char[fCurrentEntity.ch.length << 1];
0199: System.arraycopy(fCurrentEntity.ch, offset,
0200: tmp, 0, length);
0201: fCurrentEntity.ch = tmp;
0202: } else {
0203: System.arraycopy(fCurrentEntity.ch, offset,
0204: fCurrentEntity.ch, 0, length);
0205: }
0206: offset = 0;
0207: if (load(length, false)) {
0208: break;
0209: }
0210: }
0211: } else {
0212: break;
0213: }
0214: } while (true);
0215:
0216: int length = fCurrentEntity.position - offset;
0217: fCurrentEntity.columnNumber += length;
0218:
0219: // return nmtoken
0220: String symbol = null;
0221: if (length > 0) {
0222: symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset,
0223: length);
0224: }
0225: return symbol;
0226:
0227: } // scanNmtoken():String
0228:
0229: /**
0230: * Returns a string matching the Name production appearing immediately
0231: * on the input as a symbol, or null if no Name string is present.
0232: * <p>
0233: * <strong>Note:</strong> The Name characters are consumed.
0234: * <p>
0235: * <strong>Note:</strong> The string returned must be a symbol. The
0236: * SymbolTable can be used for this purpose.
0237: *
0238: * @throws IOException Thrown if i/o error occurs.
0239: * @throws EOFException Thrown on end of file.
0240: *
0241: * @see org.apache.xerces.util.SymbolTable
0242: * @see org.apache.xerces.util.XML11Char#isXML11Name
0243: * @see org.apache.xerces.util.XML11Char#isXML11NameStart
0244: */
0245: public String scanName() throws IOException {
0246: // load more characters, if needed
0247: if (fCurrentEntity.position == fCurrentEntity.count) {
0248: load(0, true);
0249: }
0250:
0251: // scan name
0252: int offset = fCurrentEntity.position;
0253: char ch = fCurrentEntity.ch[offset];
0254:
0255: if (XML11Char.isXML11NameStart(ch)) {
0256: if (++fCurrentEntity.position == fCurrentEntity.count) {
0257: fCurrentEntity.ch[0] = ch;
0258: offset = 0;
0259: if (load(1, false)) {
0260: fCurrentEntity.columnNumber++;
0261: String symbol = fSymbolTable.addSymbol(
0262: fCurrentEntity.ch, 0, 1);
0263: return symbol;
0264: }
0265: }
0266: } else if (XML11Char.isXML11NameHighSurrogate(ch)) {
0267: if (++fCurrentEntity.position == fCurrentEntity.count) {
0268: fCurrentEntity.ch[0] = ch;
0269: offset = 0;
0270: if (load(1, false)) {
0271: --fCurrentEntity.position;
0272: --fCurrentEntity.startPosition;
0273: return null;
0274: }
0275: }
0276: char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
0277: if (!XMLChar.isLowSurrogate(ch2)
0278: || !XML11Char.isXML11NameStart(XMLChar
0279: .supplemental(ch, ch2))) {
0280: --fCurrentEntity.position;
0281: return null;
0282: }
0283: if (++fCurrentEntity.position == fCurrentEntity.count) {
0284: fCurrentEntity.ch[0] = ch;
0285: fCurrentEntity.ch[1] = ch2;
0286: offset = 0;
0287: if (load(2, false)) {
0288: fCurrentEntity.columnNumber += 2;
0289: String symbol = fSymbolTable.addSymbol(
0290: fCurrentEntity.ch, 0, 2);
0291: return symbol;
0292: }
0293: }
0294: } else {
0295: return null;
0296: }
0297:
0298: do {
0299: ch = fCurrentEntity.ch[fCurrentEntity.position];
0300: if (XML11Char.isXML11Name(ch)) {
0301: if (++fCurrentEntity.position == fCurrentEntity.count) {
0302: int length = fCurrentEntity.position - offset;
0303: if (length == fCurrentEntity.ch.length) {
0304: // bad luck we have to resize our buffer
0305: char[] tmp = new char[fCurrentEntity.ch.length << 1];
0306: System.arraycopy(fCurrentEntity.ch, offset,
0307: tmp, 0, length);
0308: fCurrentEntity.ch = tmp;
0309: } else {
0310: System.arraycopy(fCurrentEntity.ch, offset,
0311: fCurrentEntity.ch, 0, length);
0312: }
0313: offset = 0;
0314: if (load(length, false)) {
0315: break;
0316: }
0317: }
0318: } else if (XML11Char.isXML11NameHighSurrogate(ch)) {
0319: if (++fCurrentEntity.position == fCurrentEntity.count) {
0320: int length = fCurrentEntity.position - offset;
0321: if (length == fCurrentEntity.ch.length) {
0322: // bad luck we have to resize our buffer
0323: char[] tmp = new char[fCurrentEntity.ch.length << 1];
0324: System.arraycopy(fCurrentEntity.ch, offset,
0325: tmp, 0, length);
0326: fCurrentEntity.ch = tmp;
0327: } else {
0328: System.arraycopy(fCurrentEntity.ch, offset,
0329: fCurrentEntity.ch, 0, length);
0330: }
0331: offset = 0;
0332: if (load(length, false)) {
0333: --fCurrentEntity.position;
0334: --fCurrentEntity.startPosition;
0335: break;
0336: }
0337: }
0338: char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
0339: if (!XMLChar.isLowSurrogate(ch2)
0340: || !XML11Char.isXML11Name(XMLChar.supplemental(
0341: ch, ch2))) {
0342: --fCurrentEntity.position;
0343: break;
0344: }
0345: if (++fCurrentEntity.position == fCurrentEntity.count) {
0346: int length = fCurrentEntity.position - offset;
0347: if (length == fCurrentEntity.ch.length) {
0348: // bad luck we have to resize our buffer
0349: char[] tmp = new char[fCurrentEntity.ch.length << 1];
0350: System.arraycopy(fCurrentEntity.ch, offset,
0351: tmp, 0, length);
0352: fCurrentEntity.ch = tmp;
0353: } else {
0354: System.arraycopy(fCurrentEntity.ch, offset,
0355: fCurrentEntity.ch, 0, length);
0356: }
0357: offset = 0;
0358: if (load(length, false)) {
0359: break;
0360: }
0361: }
0362: } else {
0363: break;
0364: }
0365: } while (true);
0366:
0367: int length = fCurrentEntity.position - offset;
0368: fCurrentEntity.columnNumber += length;
0369:
0370: // return name
0371: String symbol = null;
0372: if (length > 0) {
0373: symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset,
0374: length);
0375: }
0376: return symbol;
0377:
0378: } // scanName():String
0379:
0380: /**
0381: * Returns a string matching the NCName production appearing immediately
0382: * on the input as a symbol, or null if no NCName string is present.
0383: * <p>
0384: * <strong>Note:</strong> The NCName characters are consumed.
0385: * <p>
0386: * <strong>Note:</strong> The string returned must be a symbol. The
0387: * SymbolTable can be used for this purpose.
0388: *
0389: * @throws IOException Thrown if i/o error occurs.
0390: * @throws EOFException Thrown on end of file.
0391: *
0392: * @see org.apache.xerces.util.SymbolTable
0393: * @see org.apache.xerces.util.XML11Char#isXML11NCName
0394: * @see org.apache.xerces.util.XML11Char#isXML11NCNameStart
0395: */
0396: public String scanNCName() throws IOException {
0397:
0398: // load more characters, if needed
0399: if (fCurrentEntity.position == fCurrentEntity.count) {
0400: load(0, true);
0401: }
0402:
0403: // scan name
0404: int offset = fCurrentEntity.position;
0405: char ch = fCurrentEntity.ch[offset];
0406:
0407: if (XML11Char.isXML11NCNameStart(ch)) {
0408: if (++fCurrentEntity.position == fCurrentEntity.count) {
0409: fCurrentEntity.ch[0] = ch;
0410: offset = 0;
0411: if (load(1, false)) {
0412: fCurrentEntity.columnNumber++;
0413: String symbol = fSymbolTable.addSymbol(
0414: fCurrentEntity.ch, 0, 1);
0415: return symbol;
0416: }
0417: }
0418: } else if (XML11Char.isXML11NameHighSurrogate(ch)) {
0419: if (++fCurrentEntity.position == fCurrentEntity.count) {
0420: fCurrentEntity.ch[0] = ch;
0421: offset = 0;
0422: if (load(1, false)) {
0423: --fCurrentEntity.position;
0424: --fCurrentEntity.startPosition;
0425: return null;
0426: }
0427: }
0428: char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
0429: if (!XMLChar.isLowSurrogate(ch2)
0430: || !XML11Char.isXML11NCNameStart(XMLChar
0431: .supplemental(ch, ch2))) {
0432: --fCurrentEntity.position;
0433: return null;
0434: }
0435: if (++fCurrentEntity.position == fCurrentEntity.count) {
0436: fCurrentEntity.ch[0] = ch;
0437: fCurrentEntity.ch[1] = ch2;
0438: offset = 0;
0439: if (load(2, false)) {
0440: fCurrentEntity.columnNumber += 2;
0441: String symbol = fSymbolTable.addSymbol(
0442: fCurrentEntity.ch, 0, 2);
0443: return symbol;
0444: }
0445: }
0446: } else {
0447: return null;
0448: }
0449:
0450: do {
0451: ch = fCurrentEntity.ch[fCurrentEntity.position];
0452: if (XML11Char.isXML11NCName(ch)) {
0453: if (++fCurrentEntity.position == fCurrentEntity.count) {
0454: int length = fCurrentEntity.position - offset;
0455: if (length == fCurrentEntity.ch.length) {
0456: // bad luck we have to resize our buffer
0457: char[] tmp = new char[fCurrentEntity.ch.length << 1];
0458: System.arraycopy(fCurrentEntity.ch, offset,
0459: tmp, 0, length);
0460: fCurrentEntity.ch = tmp;
0461: } else {
0462: System.arraycopy(fCurrentEntity.ch, offset,
0463: fCurrentEntity.ch, 0, length);
0464: }
0465: offset = 0;
0466: if (load(length, false)) {
0467: break;
0468: }
0469: }
0470: } else if (XML11Char.isXML11NameHighSurrogate(ch)) {
0471: if (++fCurrentEntity.position == fCurrentEntity.count) {
0472: int length = fCurrentEntity.position - offset;
0473: if (length == fCurrentEntity.ch.length) {
0474: // bad luck we have to resize our buffer
0475: char[] tmp = new char[fCurrentEntity.ch.length << 1];
0476: System.arraycopy(fCurrentEntity.ch, offset,
0477: tmp, 0, length);
0478: fCurrentEntity.ch = tmp;
0479: } else {
0480: System.arraycopy(fCurrentEntity.ch, offset,
0481: fCurrentEntity.ch, 0, length);
0482: }
0483: offset = 0;
0484: if (load(length, false)) {
0485: --fCurrentEntity.startPosition;
0486: --fCurrentEntity.position;
0487: break;
0488: }
0489: }
0490: char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
0491: if (!XMLChar.isLowSurrogate(ch2)
0492: || !XML11Char.isXML11NCName(XMLChar
0493: .supplemental(ch, ch2))) {
0494: --fCurrentEntity.position;
0495: break;
0496: }
0497: if (++fCurrentEntity.position == fCurrentEntity.count) {
0498: int length = fCurrentEntity.position - offset;
0499: if (length == fCurrentEntity.ch.length) {
0500: // bad luck we have to resize our buffer
0501: char[] tmp = new char[fCurrentEntity.ch.length << 1];
0502: System.arraycopy(fCurrentEntity.ch, offset,
0503: tmp, 0, length);
0504: fCurrentEntity.ch = tmp;
0505: } else {
0506: System.arraycopy(fCurrentEntity.ch, offset,
0507: fCurrentEntity.ch, 0, length);
0508: }
0509: offset = 0;
0510: if (load(length, false)) {
0511: break;
0512: }
0513: }
0514: } else {
0515: break;
0516: }
0517: } while (true);
0518:
0519: int length = fCurrentEntity.position - offset;
0520: fCurrentEntity.columnNumber += length;
0521:
0522: // return name
0523: String symbol = null;
0524: if (length > 0) {
0525: symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset,
0526: length);
0527: }
0528: return symbol;
0529:
0530: } // scanNCName():String
0531:
0532: /**
0533: * Scans a qualified name from the input, setting the fields of the
0534: * QName structure appropriately.
0535: * <p>
0536: * <strong>Note:</strong> The qualified name characters are consumed.
0537: * <p>
0538: * <strong>Note:</strong> The strings used to set the values of the
0539: * QName structure must be symbols. The SymbolTable can be used for
0540: * this purpose.
0541: *
0542: * @param qname The qualified name structure to fill.
0543: *
0544: * @return Returns true if a qualified name appeared immediately on
0545: * the input and was scanned, false otherwise.
0546: *
0547: * @throws IOException Thrown if i/o error occurs.
0548: * @throws EOFException Thrown on end of file.
0549: *
0550: * @see org.apache.xerces.util.SymbolTable
0551: * @see org.apache.xerces.util.XML11Char#isXML11Name
0552: * @see org.apache.xerces.util.XML11Char#isXML11NameStart
0553: */
0554: public boolean scanQName(QName qname) throws IOException {
0555:
0556: // load more characters, if needed
0557: if (fCurrentEntity.position == fCurrentEntity.count) {
0558: load(0, true);
0559: }
0560:
0561: // scan qualified name
0562: int offset = fCurrentEntity.position;
0563: char ch = fCurrentEntity.ch[offset];
0564:
0565: if (XML11Char.isXML11NCNameStart(ch)) {
0566: if (++fCurrentEntity.position == fCurrentEntity.count) {
0567: fCurrentEntity.ch[0] = ch;
0568: offset = 0;
0569: if (load(1, false)) {
0570: fCurrentEntity.columnNumber++;
0571: String name = fSymbolTable.addSymbol(
0572: fCurrentEntity.ch, 0, 1);
0573: qname.setValues(null, name, name, null);
0574: return true;
0575: }
0576: }
0577: } else if (XML11Char.isXML11NameHighSurrogate(ch)) {
0578: if (++fCurrentEntity.position == fCurrentEntity.count) {
0579: fCurrentEntity.ch[0] = ch;
0580: offset = 0;
0581: if (load(1, false)) {
0582: --fCurrentEntity.startPosition;
0583: --fCurrentEntity.position;
0584: return false;
0585: }
0586: }
0587: char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
0588: if (!XMLChar.isLowSurrogate(ch2)
0589: || !XML11Char.isXML11NCNameStart(XMLChar
0590: .supplemental(ch, ch2))) {
0591: --fCurrentEntity.position;
0592: return false;
0593: }
0594: if (++fCurrentEntity.position == fCurrentEntity.count) {
0595: fCurrentEntity.ch[0] = ch;
0596: fCurrentEntity.ch[1] = ch2;
0597: offset = 0;
0598: if (load(2, false)) {
0599: fCurrentEntity.columnNumber += 2;
0600: String name = fSymbolTable.addSymbol(
0601: fCurrentEntity.ch, 0, 2);
0602: qname.setValues(null, name, name, null);
0603: return true;
0604: }
0605: }
0606: } else {
0607: return false;
0608: }
0609:
0610: int index = -1;
0611: boolean sawIncompleteSurrogatePair = false;
0612: do {
0613: ch = fCurrentEntity.ch[fCurrentEntity.position];
0614: if (XML11Char.isXML11Name(ch)) {
0615: if (ch == ':') {
0616: if (index != -1) {
0617: break;
0618: }
0619: index = fCurrentEntity.position;
0620: }
0621: if (++fCurrentEntity.position == fCurrentEntity.count) {
0622: int length = fCurrentEntity.position - offset;
0623: if (length == fCurrentEntity.ch.length) {
0624: // bad luck we have to resize our buffer
0625: char[] tmp = new char[fCurrentEntity.ch.length << 1];
0626: System.arraycopy(fCurrentEntity.ch, offset,
0627: tmp, 0, length);
0628: fCurrentEntity.ch = tmp;
0629: } else {
0630: System.arraycopy(fCurrentEntity.ch, offset,
0631: fCurrentEntity.ch, 0, length);
0632: }
0633: if (index != -1) {
0634: index = index - offset;
0635: }
0636: offset = 0;
0637: if (load(length, false)) {
0638: break;
0639: }
0640: }
0641: } else if (XML11Char.isXML11NameHighSurrogate(ch)) {
0642: if (++fCurrentEntity.position == fCurrentEntity.count) {
0643: int length = fCurrentEntity.position - offset;
0644: if (length == fCurrentEntity.ch.length) {
0645: // bad luck we have to resize our buffer
0646: char[] tmp = new char[fCurrentEntity.ch.length << 1];
0647: System.arraycopy(fCurrentEntity.ch, offset,
0648: tmp, 0, length);
0649: fCurrentEntity.ch = tmp;
0650: } else {
0651: System.arraycopy(fCurrentEntity.ch, offset,
0652: fCurrentEntity.ch, 0, length);
0653: }
0654: if (index != -1) {
0655: index = index - offset;
0656: }
0657: offset = 0;
0658: if (load(length, false)) {
0659: sawIncompleteSurrogatePair = true;
0660: --fCurrentEntity.startPosition;
0661: --fCurrentEntity.position;
0662: break;
0663: }
0664: }
0665: char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
0666: if (!XMLChar.isLowSurrogate(ch2)
0667: || !XML11Char.isXML11Name(XMLChar.supplemental(
0668: ch, ch2))) {
0669: sawIncompleteSurrogatePair = true;
0670: --fCurrentEntity.position;
0671: break;
0672: }
0673: if (++fCurrentEntity.position == fCurrentEntity.count) {
0674: int length = fCurrentEntity.position - offset;
0675: if (length == fCurrentEntity.ch.length) {
0676: // bad luck we have to resize our buffer
0677: char[] tmp = new char[fCurrentEntity.ch.length << 1];
0678: System.arraycopy(fCurrentEntity.ch, offset,
0679: tmp, 0, length);
0680: fCurrentEntity.ch = tmp;
0681: } else {
0682: System.arraycopy(fCurrentEntity.ch, offset,
0683: fCurrentEntity.ch, 0, length);
0684: }
0685: if (index != -1) {
0686: index = index - offset;
0687: }
0688: offset = 0;
0689: if (load(length, false)) {
0690: break;
0691: }
0692: }
0693: } else {
0694: break;
0695: }
0696: } while (true);
0697:
0698: int length = fCurrentEntity.position - offset;
0699: fCurrentEntity.columnNumber += length;
0700:
0701: if (length > 0) {
0702: String prefix = null;
0703: String localpart = null;
0704: String rawname = fSymbolTable.addSymbol(fCurrentEntity.ch,
0705: offset, length);
0706: if (index != -1) {
0707: int prefixLength = index - offset;
0708: prefix = fSymbolTable.addSymbol(fCurrentEntity.ch,
0709: offset, prefixLength);
0710: int len = length - prefixLength - 1;
0711: int startLocal = index + 1;
0712: if (!XML11Char
0713: .isXML11NCNameStart(fCurrentEntity.ch[startLocal])
0714: && (!XML11Char
0715: .isXML11NameHighSurrogate(fCurrentEntity.ch[startLocal]) || sawIncompleteSurrogatePair)) {
0716: fErrorReporter.reportError(
0717: XMLMessageFormatter.XML_DOMAIN,
0718: "IllegalQName", null,
0719: XMLErrorReporter.SEVERITY_FATAL_ERROR);
0720: }
0721: localpart = fSymbolTable.addSymbol(fCurrentEntity.ch,
0722: index + 1, len);
0723:
0724: } else {
0725: localpart = rawname;
0726: }
0727: qname.setValues(prefix, localpart, rawname, null);
0728: return true;
0729: }
0730: return false;
0731:
0732: } // scanQName(QName):boolean
0733:
0734: /**
0735: * Scans a range of parsed character data, setting the fields of the
0736: * XMLString structure, appropriately.
0737: * <p>
0738: * <strong>Note:</strong> The characters are consumed.
0739: * <p>
0740: * <strong>Note:</strong> This method does not guarantee to return
0741: * the longest run of parsed character data. This method may return
0742: * before markup due to reaching the end of the input buffer or any
0743: * other reason.
0744: * <p>
0745: * <strong>Note:</strong> The fields contained in the XMLString
0746: * structure are not guaranteed to remain valid upon subsequent calls
0747: * to the entity scanner. Therefore, the caller is responsible for
0748: * immediately using the returned character data or making a copy of
0749: * the character data.
0750: *
0751: * @param content The content structure to fill.
0752: *
0753: * @return Returns the next character on the input, if known. This
0754: * value may be -1 but this does <em>note</em> designate
0755: * end of file.
0756: *
0757: * @throws IOException Thrown if i/o error occurs.
0758: * @throws EOFException Thrown on end of file.
0759: */
0760: public int scanContent(XMLString content) throws IOException {
0761:
0762: // load more characters, if needed
0763: if (fCurrentEntity.position == fCurrentEntity.count) {
0764: load(0, true);
0765: } else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
0766: fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
0767: load(1, false);
0768: fCurrentEntity.position = 0;
0769: fCurrentEntity.startPosition = 0;
0770: }
0771:
0772: // normalize newlines
0773: int offset = fCurrentEntity.position;
0774: int c = fCurrentEntity.ch[offset];
0775: int newlines = 0;
0776: boolean external = fCurrentEntity.isExternal();
0777: if (c == '\n'
0778: || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) {
0779: do {
0780: c = fCurrentEntity.ch[fCurrentEntity.position++];
0781: if ((c == '\r') && external) {
0782: newlines++;
0783: fCurrentEntity.lineNumber++;
0784: fCurrentEntity.columnNumber = 1;
0785: if (fCurrentEntity.position == fCurrentEntity.count) {
0786: offset = 0;
0787: fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
0788: fCurrentEntity.position = newlines;
0789: fCurrentEntity.startPosition = newlines;
0790: if (load(newlines, false)) {
0791: break;
0792: }
0793: }
0794: int cc = fCurrentEntity.ch[fCurrentEntity.position];
0795: if (cc == '\n' || cc == 0x85) {
0796: fCurrentEntity.position++;
0797: offset++;
0798: }
0799: /*** NEWLINE NORMALIZATION ***/
0800: else {
0801: newlines++;
0802: }
0803: } else if (c == '\n'
0804: || ((c == 0x85 || c == 0x2028) && external)) {
0805: newlines++;
0806: fCurrentEntity.lineNumber++;
0807: fCurrentEntity.columnNumber = 1;
0808: if (fCurrentEntity.position == fCurrentEntity.count) {
0809: offset = 0;
0810: fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
0811: fCurrentEntity.position = newlines;
0812: fCurrentEntity.startPosition = newlines;
0813: if (load(newlines, false)) {
0814: break;
0815: }
0816: }
0817: } else {
0818: fCurrentEntity.position--;
0819: break;
0820: }
0821: } while (fCurrentEntity.position < fCurrentEntity.count - 1);
0822: for (int i = offset; i < fCurrentEntity.position; i++) {
0823: fCurrentEntity.ch[i] = '\n';
0824: }
0825: int length = fCurrentEntity.position - offset;
0826: if (fCurrentEntity.position == fCurrentEntity.count - 1) {
0827: content.setValues(fCurrentEntity.ch, offset, length);
0828: return -1;
0829: }
0830: }
0831:
0832: // inner loop, scanning for content
0833: if (external) {
0834: while (fCurrentEntity.position < fCurrentEntity.count) {
0835: c = fCurrentEntity.ch[fCurrentEntity.position++];
0836: if (!XML11Char.isXML11Content(c) || c == 0x85
0837: || c == 0x2028) {
0838: fCurrentEntity.position--;
0839: break;
0840: }
0841: }
0842: } else {
0843: while (fCurrentEntity.position < fCurrentEntity.count) {
0844: c = fCurrentEntity.ch[fCurrentEntity.position++];
0845: // In internal entities control characters are allowed to appear unescaped.
0846: if (!XML11Char.isXML11InternalEntityContent(c)) {
0847: fCurrentEntity.position--;
0848: break;
0849: }
0850: }
0851: }
0852: int length = fCurrentEntity.position - offset;
0853: fCurrentEntity.columnNumber += length - newlines;
0854: content.setValues(fCurrentEntity.ch, offset, length);
0855:
0856: // return next character
0857: if (fCurrentEntity.position != fCurrentEntity.count) {
0858: c = fCurrentEntity.ch[fCurrentEntity.position];
0859: // REVISIT: Does this need to be updated to fix the
0860: // #x0D ^#x0A newline normalization problem? -Ac
0861: if ((c == '\r' || c == 0x85 || c == 0x2028) && external) {
0862: c = '\n';
0863: }
0864: } else {
0865: c = -1;
0866: }
0867: return c;
0868:
0869: } // scanContent(XMLString):int
0870:
0871: /**
0872: * Scans a range of attribute value data, setting the fields of the
0873: * XMLString structure, appropriately.
0874: * <p>
0875: * <strong>Note:</strong> The characters are consumed.
0876: * <p>
0877: * <strong>Note:</strong> This method does not guarantee to return
0878: * the longest run of attribute value data. This method may return
0879: * before the quote character due to reaching the end of the input
0880: * buffer or any other reason.
0881: * <p>
0882: * <strong>Note:</strong> The fields contained in the XMLString
0883: * structure are not guaranteed to remain valid upon subsequent calls
0884: * to the entity scanner. Therefore, the caller is responsible for
0885: * immediately using the returned character data or making a copy of
0886: * the character data.
0887: *
0888: * @param quote The quote character that signifies the end of the
0889: * attribute value data.
0890: * @param content The content structure to fill.
0891: *
0892: * @return Returns the next character on the input, if known. This
0893: * value may be -1 but this does <em>note</em> designate
0894: * end of file.
0895: *
0896: * @throws IOException Thrown if i/o error occurs.
0897: * @throws EOFException Thrown on end of file.
0898: */
0899: public int scanLiteral(int quote, XMLString content)
0900: throws IOException {
0901:
0902: // load more characters, if needed
0903: if (fCurrentEntity.position == fCurrentEntity.count) {
0904: load(0, true);
0905: } else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
0906: fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
0907: load(1, false);
0908: fCurrentEntity.startPosition = 0;
0909: fCurrentEntity.position = 0;
0910: }
0911:
0912: // normalize newlines
0913: int offset = fCurrentEntity.position;
0914: int c = fCurrentEntity.ch[offset];
0915: int newlines = 0;
0916: boolean external = fCurrentEntity.isExternal();
0917: if (c == '\n'
0918: || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) {
0919: do {
0920: c = fCurrentEntity.ch[fCurrentEntity.position++];
0921: if ((c == '\r') && external) {
0922: newlines++;
0923: fCurrentEntity.lineNumber++;
0924: fCurrentEntity.columnNumber = 1;
0925: if (fCurrentEntity.position == fCurrentEntity.count) {
0926: offset = 0;
0927: fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
0928: fCurrentEntity.position = newlines;
0929: fCurrentEntity.startPosition = newlines;
0930: if (load(newlines, false)) {
0931: break;
0932: }
0933: }
0934: int cc = fCurrentEntity.ch[fCurrentEntity.position];
0935: if (cc == '\n' || cc == 0x85) {
0936: fCurrentEntity.position++;
0937: offset++;
0938: }
0939: /*** NEWLINE NORMALIZATION ***/
0940: else {
0941: newlines++;
0942: }
0943: } else if (c == '\n'
0944: || ((c == 0x85 || c == 0x2028) && external)) {
0945: newlines++;
0946: fCurrentEntity.lineNumber++;
0947: fCurrentEntity.columnNumber = 1;
0948: if (fCurrentEntity.position == fCurrentEntity.count) {
0949: offset = 0;
0950: fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
0951: fCurrentEntity.position = newlines;
0952: fCurrentEntity.startPosition = newlines;
0953: if (load(newlines, false)) {
0954: break;
0955: }
0956: }
0957: } else {
0958: fCurrentEntity.position--;
0959: break;
0960: }
0961: } while (fCurrentEntity.position < fCurrentEntity.count - 1);
0962: for (int i = offset; i < fCurrentEntity.position; i++) {
0963: fCurrentEntity.ch[i] = '\n';
0964: }
0965: int length = fCurrentEntity.position - offset;
0966: if (fCurrentEntity.position == fCurrentEntity.count - 1) {
0967: content.setValues(fCurrentEntity.ch, offset, length);
0968: return -1;
0969: }
0970: }
0971:
0972: // scan literal value
0973: if (external) {
0974: while (fCurrentEntity.position < fCurrentEntity.count) {
0975: c = fCurrentEntity.ch[fCurrentEntity.position++];
0976: if (c == quote || c == '%'
0977: || !XML11Char.isXML11Content(c) || c == 0x85
0978: || c == 0x2028) {
0979: fCurrentEntity.position--;
0980: break;
0981: }
0982: }
0983: } else {
0984: while (fCurrentEntity.position < fCurrentEntity.count) {
0985: c = fCurrentEntity.ch[fCurrentEntity.position++];
0986: // In internal entities control characters are allowed to appear unescaped.
0987: if ((c == quote && !fCurrentEntity.literal) || c == '%'
0988: || !XML11Char.isXML11InternalEntityContent(c)) {
0989: fCurrentEntity.position--;
0990: break;
0991: }
0992: }
0993: }
0994: int length = fCurrentEntity.position - offset;
0995: fCurrentEntity.columnNumber += length - newlines;
0996: content.setValues(fCurrentEntity.ch, offset, length);
0997:
0998: // return next character
0999: if (fCurrentEntity.position != fCurrentEntity.count) {
1000: c = fCurrentEntity.ch[fCurrentEntity.position];
1001: // NOTE: We don't want to accidentally signal the
1002: // end of the literal if we're expanding an
1003: // entity appearing in the literal. -Ac
1004: if (c == quote && fCurrentEntity.literal) {
1005: c = -1;
1006: }
1007: } else {
1008: c = -1;
1009: }
1010: return c;
1011:
1012: } // scanLiteral(int,XMLString):int
1013:
1014: /**
1015: * Scans a range of character data up to the specicied delimiter,
1016: * setting the fields of the XMLString structure, appropriately.
1017: * <p>
1018: * <strong>Note:</strong> The characters are consumed.
1019: * <p>
1020: * <strong>Note:</strong> This assumes that the internal buffer is
1021: * at least the same size, or bigger, than the length of the delimiter
1022: * and that the delimiter contains at least one character.
1023: * <p>
1024: * <strong>Note:</strong> This method does not guarantee to return
1025: * the longest run of character data. This method may return before
1026: * the delimiter due to reaching the end of the input buffer or any
1027: * other reason.
1028: * <p>
1029: * <strong>Note:</strong> The fields contained in the XMLString
1030: * structure are not guaranteed to remain valid upon subsequent calls
1031: * to the entity scanner. Therefore, the caller is responsible for
1032: * immediately using the returned character data or making a copy of
1033: * the character data.
1034: *
1035: * @param delimiter The string that signifies the end of the character
1036: * data to be scanned.
1037: * @param buffer The XMLStringBuffer to fill.
1038: *
1039: * @return Returns true if there is more data to scan, false otherwise.
1040: *
1041: * @throws IOException Thrown if i/o error occurs.
1042: * @throws EOFException Thrown on end of file.
1043: */
1044: public boolean scanData(String delimiter, XMLStringBuffer buffer)
1045: throws IOException {
1046:
1047: boolean done = false;
1048: int delimLen = delimiter.length();
1049: char charAt0 = delimiter.charAt(0);
1050: boolean external = fCurrentEntity.isExternal();
1051: do {
1052: // load more characters, if needed
1053: if (fCurrentEntity.position == fCurrentEntity.count) {
1054: load(0, true);
1055: }
1056:
1057: boolean bNextEntity = false;
1058:
1059: while ((fCurrentEntity.position >= fCurrentEntity.count
1060: - delimLen)
1061: && (!bNextEntity)) {
1062: System.arraycopy(fCurrentEntity.ch,
1063: fCurrentEntity.position, fCurrentEntity.ch, 0,
1064: fCurrentEntity.count - fCurrentEntity.position);
1065:
1066: bNextEntity = load(fCurrentEntity.count
1067: - fCurrentEntity.position, false);
1068: fCurrentEntity.position = 0;
1069: fCurrentEntity.startPosition = 0;
1070: }
1071:
1072: if (fCurrentEntity.position >= fCurrentEntity.count
1073: - delimLen) {
1074: // something must be wrong with the input: e.g., file ends an unterminated comment
1075: int length = fCurrentEntity.count
1076: - fCurrentEntity.position;
1077: buffer.append(fCurrentEntity.ch,
1078: fCurrentEntity.position, length);
1079: fCurrentEntity.columnNumber += fCurrentEntity.count;
1080: fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1081: fCurrentEntity.position = fCurrentEntity.count;
1082: fCurrentEntity.startPosition = fCurrentEntity.count;
1083: load(0, true);
1084: return false;
1085: }
1086:
1087: // normalize newlines
1088: int offset = fCurrentEntity.position;
1089: int c = fCurrentEntity.ch[offset];
1090: int newlines = 0;
1091: if (c == '\n'
1092: || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) {
1093: do {
1094: c = fCurrentEntity.ch[fCurrentEntity.position++];
1095: if ((c == '\r') && external) {
1096: newlines++;
1097: fCurrentEntity.lineNumber++;
1098: fCurrentEntity.columnNumber = 1;
1099: if (fCurrentEntity.position == fCurrentEntity.count) {
1100: offset = 0;
1101: fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1102: fCurrentEntity.position = newlines;
1103: fCurrentEntity.startPosition = newlines;
1104: if (load(newlines, false)) {
1105: break;
1106: }
1107: }
1108: int cc = fCurrentEntity.ch[fCurrentEntity.position];
1109: if (cc == '\n' || cc == 0x85) {
1110: fCurrentEntity.position++;
1111: offset++;
1112: }
1113: /*** NEWLINE NORMALIZATION ***/
1114: else {
1115: newlines++;
1116: }
1117: } else if (c == '\n'
1118: || ((c == 0x85 || c == 0x2028) && external)) {
1119: newlines++;
1120: fCurrentEntity.lineNumber++;
1121: fCurrentEntity.columnNumber = 1;
1122: if (fCurrentEntity.position == fCurrentEntity.count) {
1123: offset = 0;
1124: fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1125: fCurrentEntity.position = newlines;
1126: fCurrentEntity.startPosition = newlines;
1127: fCurrentEntity.count = newlines;
1128: if (load(newlines, false)) {
1129: break;
1130: }
1131: }
1132: } else {
1133: fCurrentEntity.position--;
1134: break;
1135: }
1136: } while (fCurrentEntity.position < fCurrentEntity.count - 1);
1137: for (int i = offset; i < fCurrentEntity.position; i++) {
1138: fCurrentEntity.ch[i] = '\n';
1139: }
1140: int length = fCurrentEntity.position - offset;
1141: if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1142: buffer.append(fCurrentEntity.ch, offset, length);
1143: return true;
1144: }
1145: }
1146:
1147: // iterate over buffer looking for delimiter
1148: if (external) {
1149: OUTER: while (fCurrentEntity.position < fCurrentEntity.count) {
1150: c = fCurrentEntity.ch[fCurrentEntity.position++];
1151: if (c == charAt0) {
1152: // looks like we just hit the delimiter
1153: int delimOffset = fCurrentEntity.position - 1;
1154: for (int i = 1; i < delimLen; i++) {
1155: if (fCurrentEntity.position == fCurrentEntity.count) {
1156: fCurrentEntity.position -= i;
1157: break OUTER;
1158: }
1159: c = fCurrentEntity.ch[fCurrentEntity.position++];
1160: if (delimiter.charAt(i) != c) {
1161: fCurrentEntity.position--;
1162: break;
1163: }
1164: }
1165: if (fCurrentEntity.position == delimOffset
1166: + delimLen) {
1167: done = true;
1168: break;
1169: }
1170: } else if (c == '\n' || c == '\r' || c == 0x85
1171: || c == 0x2028) {
1172: fCurrentEntity.position--;
1173: break;
1174: }
1175: // In external entities control characters cannot appear
1176: // as literals so do not skip over them.
1177: else if (!XML11Char.isXML11ValidLiteral(c)) {
1178: fCurrentEntity.position--;
1179: int length = fCurrentEntity.position - offset;
1180: fCurrentEntity.columnNumber += length
1181: - newlines;
1182: buffer
1183: .append(fCurrentEntity.ch, offset,
1184: length);
1185: return true;
1186: }
1187: }
1188: } else {
1189: OUTER: while (fCurrentEntity.position < fCurrentEntity.count) {
1190: c = fCurrentEntity.ch[fCurrentEntity.position++];
1191: if (c == charAt0) {
1192: // looks like we just hit the delimiter
1193: int delimOffset = fCurrentEntity.position - 1;
1194: for (int i = 1; i < delimLen; i++) {
1195: if (fCurrentEntity.position == fCurrentEntity.count) {
1196: fCurrentEntity.position -= i;
1197: break OUTER;
1198: }
1199: c = fCurrentEntity.ch[fCurrentEntity.position++];
1200: if (delimiter.charAt(i) != c) {
1201: fCurrentEntity.position--;
1202: break;
1203: }
1204: }
1205: if (fCurrentEntity.position == delimOffset
1206: + delimLen) {
1207: done = true;
1208: break;
1209: }
1210: } else if (c == '\n') {
1211: fCurrentEntity.position--;
1212: break;
1213: }
1214: // Control characters are allowed to appear as literals
1215: // in internal entities.
1216: else if (!XML11Char.isXML11Valid(c)) {
1217: fCurrentEntity.position--;
1218: int length = fCurrentEntity.position - offset;
1219: fCurrentEntity.columnNumber += length
1220: - newlines;
1221: buffer
1222: .append(fCurrentEntity.ch, offset,
1223: length);
1224: return true;
1225: }
1226: }
1227: }
1228: int length = fCurrentEntity.position - offset;
1229: fCurrentEntity.columnNumber += length - newlines;
1230: if (done) {
1231: length -= delimLen;
1232: }
1233: buffer.append(fCurrentEntity.ch, offset, length);
1234:
1235: // return true if string was skipped
1236: } while (!done);
1237: return !done;
1238:
1239: } // scanData(String,XMLString)
1240:
1241: /**
1242: * Skips a character appearing immediately on the input.
1243: * <p>
1244: * <strong>Note:</strong> The character is consumed only if it matches
1245: * the specified character.
1246: *
1247: * @param c The character to skip.
1248: *
1249: * @return Returns true if the character was skipped.
1250: *
1251: * @throws IOException Thrown if i/o error occurs.
1252: * @throws EOFException Thrown on end of file.
1253: */
1254: public boolean skipChar(int c) throws IOException {
1255:
1256: // load more characters, if needed
1257: if (fCurrentEntity.position == fCurrentEntity.count) {
1258: load(0, true);
1259: }
1260:
1261: // skip character
1262: int cc = fCurrentEntity.ch[fCurrentEntity.position];
1263: if (cc == c) {
1264: fCurrentEntity.position++;
1265: if (c == '\n') {
1266: fCurrentEntity.lineNumber++;
1267: fCurrentEntity.columnNumber = 1;
1268: } else {
1269: fCurrentEntity.columnNumber++;
1270: }
1271: return true;
1272: } else if (c == '\n'
1273: && ((cc == 0x2028 || cc == 0x85) && fCurrentEntity
1274: .isExternal())) {
1275: fCurrentEntity.position++;
1276: fCurrentEntity.lineNumber++;
1277: fCurrentEntity.columnNumber = 1;
1278: return true;
1279: } else if (c == '\n' && (cc == '\r')
1280: && fCurrentEntity.isExternal()) {
1281: // handle newlines
1282: if (fCurrentEntity.position == fCurrentEntity.count) {
1283: fCurrentEntity.ch[0] = (char) cc;
1284: load(1, false);
1285: }
1286: int ccc = fCurrentEntity.ch[++fCurrentEntity.position];
1287: if (ccc == '\n' || ccc == 0x85) {
1288: fCurrentEntity.position++;
1289: }
1290: fCurrentEntity.lineNumber++;
1291: fCurrentEntity.columnNumber = 1;
1292: return true;
1293: }
1294:
1295: // character was not skipped
1296: return false;
1297:
1298: } // skipChar(int):boolean
1299:
1300: /**
1301: * Skips space characters appearing immediately on the input.
1302: * <p>
1303: * <strong>Note:</strong> The characters are consumed only if they are
1304: * space characters.
1305: *
1306: * @return Returns true if at least one space character was skipped.
1307: *
1308: * @throws IOException Thrown if i/o error occurs.
1309: * @throws EOFException Thrown on end of file.
1310: *
1311: * @see org.apache.xerces.util.XMLChar#isSpace
1312: * @see org.apache.xerces.util.XML11Char#isXML11Space
1313: */
1314: public boolean skipSpaces() throws IOException {
1315:
1316: // load more characters, if needed
1317: if (fCurrentEntity.position == fCurrentEntity.count) {
1318: load(0, true);
1319: }
1320:
1321: // skip spaces
1322: int c = fCurrentEntity.ch[fCurrentEntity.position];
1323:
1324: // External -- Match: S + 0x85 + 0x2028, and perform end of line normalization
1325: if (fCurrentEntity.isExternal()) {
1326: if (XML11Char.isXML11Space(c)) {
1327: do {
1328: boolean entityChanged = false;
1329: // handle newlines
1330: if (c == '\n' || c == '\r' || c == 0x85
1331: || c == 0x2028) {
1332: fCurrentEntity.lineNumber++;
1333: fCurrentEntity.columnNumber = 1;
1334: if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1335: fCurrentEntity.ch[0] = (char) c;
1336: entityChanged = load(1, true);
1337: if (!entityChanged) {
1338: // the load change the position to be 1,
1339: // need to restore it when entity not changed
1340: fCurrentEntity.startPosition = 0;
1341: fCurrentEntity.position = 0;
1342: }
1343: }
1344: if (c == '\r') {
1345: // REVISIT: Does this need to be updated to fix the
1346: // #x0D ^#x0A newline normalization problem? -Ac
1347: int cc = fCurrentEntity.ch[++fCurrentEntity.position];
1348: if (cc != '\n' && cc != 0x85) {
1349: fCurrentEntity.position--;
1350: }
1351: }
1352: } else {
1353: fCurrentEntity.columnNumber++;
1354: }
1355: // load more characters, if needed
1356: if (!entityChanged)
1357: fCurrentEntity.position++;
1358: if (fCurrentEntity.position == fCurrentEntity.count) {
1359: load(0, true);
1360: }
1361: } while (XML11Char
1362: .isXML11Space(c = fCurrentEntity.ch[fCurrentEntity.position]));
1363: return true;
1364: }
1365: }
1366: // Internal -- Match: S (only)
1367: else if (XMLChar.isSpace(c)) {
1368: do {
1369: boolean entityChanged = false;
1370: // handle newlines
1371: if (c == '\n') {
1372: fCurrentEntity.lineNumber++;
1373: fCurrentEntity.columnNumber = 1;
1374: if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1375: fCurrentEntity.ch[0] = (char) c;
1376: entityChanged = load(1, true);
1377: if (!entityChanged) {
1378: // the load change the position to be 1,
1379: // need to restore it when entity not changed
1380: fCurrentEntity.startPosition = 0;
1381: fCurrentEntity.position = 0;
1382: }
1383: }
1384: } else {
1385: fCurrentEntity.columnNumber++;
1386: }
1387: // load more characters, if needed
1388: if (!entityChanged)
1389: fCurrentEntity.position++;
1390: if (fCurrentEntity.position == fCurrentEntity.count) {
1391: load(0, true);
1392: }
1393: } while (XMLChar
1394: .isSpace(c = fCurrentEntity.ch[fCurrentEntity.position]));
1395: return true;
1396: }
1397:
1398: // no spaces were found
1399: return false;
1400:
1401: } // skipSpaces():boolean
1402:
1403: /**
1404: * Skips the specified string appearing immediately on the input.
1405: * <p>
1406: * <strong>Note:</strong> The characters are consumed only if they are
1407: * space characters.
1408: *
1409: * @param s The string to skip.
1410: *
1411: * @return Returns true if the string was skipped.
1412: *
1413: * @throws IOException Thrown if i/o error occurs.
1414: * @throws EOFException Thrown on end of file.
1415: */
1416: public boolean skipString(String s) throws IOException {
1417:
1418: // load more characters, if needed
1419: if (fCurrentEntity.position == fCurrentEntity.count) {
1420: load(0, true);
1421: }
1422:
1423: // skip string
1424: final int length = s.length();
1425: for (int i = 0; i < length; i++) {
1426: char c = fCurrentEntity.ch[fCurrentEntity.position++];
1427: if (c != s.charAt(i)) {
1428: fCurrentEntity.position -= i + 1;
1429: return false;
1430: }
1431: if (i < length - 1
1432: && fCurrentEntity.position == fCurrentEntity.count) {
1433: System.arraycopy(fCurrentEntity.ch,
1434: fCurrentEntity.count - i - 1,
1435: fCurrentEntity.ch, 0, i + 1);
1436: // REVISIT: Can a string to be skipped cross an
1437: // entity boundary? -Ac
1438: if (load(i + 1, false)) {
1439: fCurrentEntity.startPosition -= i + 1;
1440: fCurrentEntity.position -= i + 1;
1441: return false;
1442: }
1443: }
1444: }
1445: fCurrentEntity.columnNumber += length;
1446: return true;
1447:
1448: } // skipString(String):boolean
1449:
1450: } // class XML11EntityScanner
|