1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * The Apache Software License, Version 1.1
   7  *
   8  *
   9  * Copyright (c) 1999-2002 The Apache Software Foundation.
  10  * All rights reserved.
  11  *
  12  * Redistribution and use in source and binary forms, with or without
  13  * modification, are permitted provided that the following conditions
  14  * are met:
  15  *
  16  * 1. Redistributions of source code must retain the above copyright
  17  *    notice, this list of conditions and the following disclaimer.
  18  *
  19  * 2. Redistributions in binary form must reproduce the above copyright
  20  *    notice, this list of conditions and the following disclaimer in
  21  *    the documentation and/or other materials provided with the
  22  *    distribution.
  23  *
  24  * 3. The end-user documentation included with the redistribution,
  25  *    if any, must include the following acknowledgment:
  26  *       "This product includes software developed by the
  27  *        Apache Software Foundation (http://www.apache.org/)."
  28  *    Alternately, this acknowledgment may appear in the software itself,
  29  *    if and wherever such third-party acknowledgments normally appear.
  30  *
  31  * 4. The names "Xerces" and "Apache Software Foundation" must
  32  *    not be used to endorse or promote products derived from this
  33  *    software without prior written permission. For written
  34  *    permission, please contact apache@apache.org.
  35  *
  36  * 5. Products derived from this software may not be called "Apache",
  37  *    nor may "Apache" appear in their name, without prior written
  38  *    permission of the Apache Software Foundation.
  39  *
  40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  43  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  46  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  51  * SUCH DAMAGE.
  52  * ====================================================================
  53  *
  54  * This software consists of voluntary contributions made by many
  55  * individuals on behalf of the Apache Software Foundation and was
  56  * originally based on software copyright (c) 1999, International
  57  * Business Machines, Inc., http://www.apache.org.  For more
  58  * information on the Apache Software Foundation, please see
  59  * <http://www.apache.org/>.
  60  */
  61 
  62 package com.sun.org.apache.xerces.internal.impl;
  63 
  64 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
  65 import com.sun.org.apache.xerces.internal.util.XML11Char;
  66 import com.sun.org.apache.xerces.internal.util.XMLChar;
  67 import com.sun.org.apache.xerces.internal.util.XMLStringBuffer;
  68 import com.sun.org.apache.xerces.internal.xni.QName;
  69 import com.sun.org.apache.xerces.internal.xni.XMLString;
  70 import java.io.IOException;
  71 
  72 /**
  73  * Implements the entity scanner methods in
  74  * the context of XML 1.1.
  75  *
  76  * @xerces.internal
  77  *
  78  * @author Michael Glavassevich, IBM
  79  * @author Neil Graham, IBM
  80  * @version $Id: XML11EntityScanner.java,v 1.5 2010-11-01 04:39:40 joehw Exp $
  81  */
  82 
  83 public class XML11EntityScanner
  84     extends XMLEntityScanner {
  85 
  86     //
  87     // Constructors
  88     //
  89 
  90     /** Default constructor. */
  91     public XML11EntityScanner() {
  92         super();
  93     } // <init>()
  94 
  95     //
  96     // XMLEntityScanner methods
  97     //
  98 
  99     /**
 100      * Returns the next character on the input.
 101      * <p>
 102      * <strong>Note:</strong> The character is <em>not</em> consumed.
 103      *
 104      * @throws IOException  Thrown if i/o error occurs.
 105      * @throws EOFException Thrown on end of file.
 106      */
 107     public int peekChar() throws IOException {
 108 
 109         // load more characters, if needed
 110         if (fCurrentEntity.position == fCurrentEntity.count) {
 111             load(0, true, true);
 112         }
 113 
 114         // peek at character
 115         int c = fCurrentEntity.ch[fCurrentEntity.position];
 116 
 117         // return peeked character
 118         if (fCurrentEntity.isExternal()) {
 119             return (c != '\r' && c != 0x85 && c != 0x2028) ? c : '\n';
 120         }
 121         else {
 122             return c;
 123         }
 124 
 125     } // peekChar():int
 126 
 127     /**
 128      * Returns the next character on the input.
 129      * <p>
 130      * <strong>Note:</strong> The character is consumed.
 131      *
 132      * @throws IOException  Thrown if i/o error occurs.
 133      * @throws EOFException Thrown on end of file.
 134      */
 135     public int scanChar() throws IOException {
 136 
 137         // load more characters, if needed
 138         if (fCurrentEntity.position == fCurrentEntity.count) {
 139             load(0, true, true);
 140         }
 141 
 142         // scan character
 143         int c = fCurrentEntity.ch[fCurrentEntity.position++];
 144         boolean external = false;
 145         if (c == '\n' ||
 146             ((c == '\r' || c == 0x85 || c == 0x2028) && (external = fCurrentEntity.isExternal()))) {
 147             fCurrentEntity.lineNumber++;
 148             fCurrentEntity.columnNumber = 1;
 149             if (fCurrentEntity.position == fCurrentEntity.count) {
 150                 fCurrentEntity.ch[0] = (char)c;
 151                 load(1, false, true);
 152             }
 153             if (c == '\r' && external) {
 154                 int cc = fCurrentEntity.ch[fCurrentEntity.position++];
 155                 if (cc != '\n' && cc != 0x85) {
 156                     fCurrentEntity.position--;
 157                 }
 158             }
 159             c = '\n';
 160         }
 161 
 162         // return character that was scanned
 163         fCurrentEntity.columnNumber++;
 164         return c;
 165 
 166     } // scanChar():int
 167 
 168     /**
 169      * Returns a string matching the NMTOKEN production appearing immediately
 170      * on the input as a symbol, or null if NMTOKEN Name string is present.
 171      * <p>
 172      * <strong>Note:</strong> The NMTOKEN characters are consumed.
 173      * <p>
 174      * <strong>Note:</strong> The string returned must be a symbol. The
 175      * SymbolTable can be used for this purpose.
 176      *
 177      * @throws IOException  Thrown if i/o error occurs.
 178      * @throws EOFException Thrown on end of file.
 179      *
 180      * @see com.sun.org.apache.xerces.internal.util.SymbolTable
 181      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11Name
 182      */
 183     public String scanNmtoken() throws IOException {
 184         // load more characters, if needed
 185         if (fCurrentEntity.position == fCurrentEntity.count) {
 186             load(0, true, true);
 187         }
 188 
 189         // scan nmtoken
 190         int offset = fCurrentEntity.position;
 191 
 192         do {
 193             char ch = fCurrentEntity.ch[fCurrentEntity.position];
 194             if (XML11Char.isXML11Name(ch)) {
 195                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 196                     int length = fCurrentEntity.position - offset;
 197                     invokeListeners(length);
 198                     if (length == fCurrentEntity.ch.length) {
 199                         // bad luck we have to resize our buffer
 200                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 201                         System.arraycopy(fCurrentEntity.ch, offset,
 202                                          tmp, 0, length);
 203                         fCurrentEntity.ch = tmp;
 204                     }
 205                     else {
 206                         System.arraycopy(fCurrentEntity.ch, offset,
 207                                          fCurrentEntity.ch, 0, length);
 208                     }
 209                     offset = 0;
 210                     if (load(length, false, false)) {
 211                         break;
 212                     }
 213                 }
 214             }
 215             else if (XML11Char.isXML11NameHighSurrogate(ch)) {
 216                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 217                     int length = fCurrentEntity.position - offset;
 218                     invokeListeners(length);
 219                     if (length == fCurrentEntity.ch.length) {
 220                         // bad luck we have to resize our buffer
 221                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 222                         System.arraycopy(fCurrentEntity.ch, offset,
 223                                          tmp, 0, length);
 224                         fCurrentEntity.ch = tmp;
 225                     }
 226                     else {
 227                         System.arraycopy(fCurrentEntity.ch, offset,
 228                                          fCurrentEntity.ch, 0, length);
 229                     }
 230                     offset = 0;
 231                     if (load(length, false, false)) {
 232                         --fCurrentEntity.startPosition;
 233                         --fCurrentEntity.position;
 234                         break;
 235                     }
 236                 }
 237                 char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
 238                 if ( !XMLChar.isLowSurrogate(ch2) ||
 239                      !XML11Char.isXML11Name(XMLChar.supplemental(ch, ch2)) ) {
 240                     --fCurrentEntity.position;
 241                     break;
 242                 }
 243                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 244                     int length = fCurrentEntity.position - offset;
 245                     invokeListeners(length);
 246                     if (length == fCurrentEntity.ch.length) {
 247                         // bad luck we have to resize our buffer
 248                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 249                         System.arraycopy(fCurrentEntity.ch, offset,
 250                                          tmp, 0, length);
 251                         fCurrentEntity.ch = tmp;
 252                     }
 253                     else {
 254                         System.arraycopy(fCurrentEntity.ch, offset,
 255                                          fCurrentEntity.ch, 0, length);
 256                     }
 257                     offset = 0;
 258                     if (load(length, false, false)) {
 259                         break;
 260                     }
 261                 }
 262             }
 263             else {
 264                 break;
 265             }
 266         }
 267         while (true);
 268 
 269         int length = fCurrentEntity.position - offset;
 270         fCurrentEntity.columnNumber += length;
 271 
 272         // return nmtoken
 273         String symbol = null;
 274         if (length > 0) {
 275             symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
 276         }
 277         return symbol;
 278 
 279     } // scanNmtoken():String
 280 
 281     /**
 282      * Returns a string matching the Name production appearing immediately
 283      * on the input as a symbol, or null if no Name string is present.
 284      * <p>
 285      * <strong>Note:</strong> The Name characters are consumed.
 286      * <p>
 287      * <strong>Note:</strong> The string returned must be a symbol. The
 288      * SymbolTable can be used for this purpose.
 289      *
 290      * @throws IOException  Thrown if i/o error occurs.
 291      * @throws EOFException Thrown on end of file.
 292      *
 293      * @see com.sun.org.apache.xerces.internal.util.SymbolTable
 294      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11Name
 295      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NameStart
 296      */
 297     public String scanName() throws IOException {
 298         // load more characters, if needed
 299         if (fCurrentEntity.position == fCurrentEntity.count) {
 300             load(0, true, true);
 301         }
 302 
 303         // scan name
 304         int offset = fCurrentEntity.position;
 305         char ch = fCurrentEntity.ch[offset];
 306 
 307         if (XML11Char.isXML11NameStart(ch)) {
 308             if (++fCurrentEntity.position == fCurrentEntity.count) {
 309                 fCurrentEntity.ch[0] = ch;
 310                 offset = 0;
 311                 if (load(1, false, true)) {
 312                     fCurrentEntity.columnNumber++;
 313                     String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
 314                     return symbol;
 315                 }
 316             }
 317         }
 318         else if (XML11Char.isXML11NameHighSurrogate(ch)) {
 319             if (++fCurrentEntity.position == fCurrentEntity.count) {
 320                 fCurrentEntity.ch[0] = ch;
 321                 offset = 0;
 322                 if (load(1, false, true)) {
 323                     --fCurrentEntity.position;
 324                     --fCurrentEntity.startPosition;
 325                     return null;
 326                 }
 327             }
 328             char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
 329             if ( !XMLChar.isLowSurrogate(ch2) ||
 330                  !XML11Char.isXML11NameStart(XMLChar.supplemental(ch, ch2)) ) {
 331                 --fCurrentEntity.position;
 332                 return null;
 333             }
 334             if (++fCurrentEntity.position == fCurrentEntity.count) {
 335                 fCurrentEntity.ch[0] = ch;
 336                 fCurrentEntity.ch[1] = ch2;
 337                 offset = 0;
 338                 if (load(2, false, true)) {
 339                     fCurrentEntity.columnNumber += 2;
 340                     String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 2);
 341                     return symbol;
 342                 }
 343             }
 344         }
 345         else {
 346             return null;
 347         }
 348 
 349         do {
 350             ch = fCurrentEntity.ch[fCurrentEntity.position];
 351             if (XML11Char.isXML11Name(ch)) {
 352                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 353                     int length = fCurrentEntity.position - offset;
 354                     invokeListeners(length);
 355                     if (length == fCurrentEntity.ch.length) {
 356                         // bad luck we have to resize our buffer
 357                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 358                         System.arraycopy(fCurrentEntity.ch, offset,
 359                                          tmp, 0, length);
 360                         fCurrentEntity.ch = tmp;
 361                     }
 362                     else {
 363                         System.arraycopy(fCurrentEntity.ch, offset,
 364                                          fCurrentEntity.ch, 0, length);
 365                     }
 366                     offset = 0;
 367                     if (load(length, false, false)) {
 368                         break;
 369                     }
 370                 }
 371             }
 372             else if (XML11Char.isXML11NameHighSurrogate(ch)) {
 373                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 374                     int length = fCurrentEntity.position - offset;
 375                     invokeListeners(length);
 376                     if (length == fCurrentEntity.ch.length) {
 377                         // bad luck we have to resize our buffer
 378                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 379                         System.arraycopy(fCurrentEntity.ch, offset,
 380                                          tmp, 0, length);
 381                         fCurrentEntity.ch = tmp;
 382                     }
 383                     else {
 384                         System.arraycopy(fCurrentEntity.ch, offset,
 385                                          fCurrentEntity.ch, 0, length);
 386                     }
 387                     offset = 0;
 388                     if (load(length, false, false)) {
 389                         --fCurrentEntity.position;
 390                         --fCurrentEntity.startPosition;
 391                         break;
 392                     }
 393                 }
 394                 char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
 395                 if ( !XMLChar.isLowSurrogate(ch2) ||
 396                      !XML11Char.isXML11Name(XMLChar.supplemental(ch, ch2)) ) {
 397                     --fCurrentEntity.position;
 398                     break;
 399                 }
 400                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 401                     int length = fCurrentEntity.position - offset;
 402                     invokeListeners(length);
 403                     if (length == fCurrentEntity.ch.length) {
 404                         // bad luck we have to resize our buffer
 405                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 406                         System.arraycopy(fCurrentEntity.ch, offset,
 407                                          tmp, 0, length);
 408                         fCurrentEntity.ch = tmp;
 409                     }
 410                     else {
 411                         System.arraycopy(fCurrentEntity.ch, offset,
 412                                          fCurrentEntity.ch, 0, length);
 413                     }
 414                     offset = 0;
 415                     if (load(length, false, false)) {
 416                         break;
 417                     }
 418                 }
 419             }
 420             else {
 421                 break;
 422             }
 423         }
 424         while (true);
 425 
 426         int length = fCurrentEntity.position - offset;
 427         fCurrentEntity.columnNumber += length;
 428 
 429         // return name
 430         String symbol = null;
 431         if (length > 0) {
 432             symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
 433         }
 434         return symbol;
 435 
 436     } // scanName():String
 437 
 438     /**
 439      * Returns a string matching the NCName production appearing immediately
 440      * on the input as a symbol, or null if no NCName string is present.
 441      * <p>
 442      * <strong>Note:</strong> The NCName characters are consumed.
 443      * <p>
 444      * <strong>Note:</strong> The string returned must be a symbol. The
 445      * SymbolTable can be used for this purpose.
 446      *
 447      * @throws IOException  Thrown if i/o error occurs.
 448      * @throws EOFException Thrown on end of file.
 449      *
 450      * @see com.sun.org.apache.xerces.internal.util.SymbolTable
 451      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NCName
 452      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NCNameStart
 453      */
 454     public String scanNCName() throws IOException {
 455 
 456         // load more characters, if needed
 457         if (fCurrentEntity.position == fCurrentEntity.count) {
 458             load(0, true, true);
 459         }
 460 
 461         // scan name
 462         int offset = fCurrentEntity.position;
 463         char ch = fCurrentEntity.ch[offset];
 464 
 465         if (XML11Char.isXML11NCNameStart(ch)) {
 466             if (++fCurrentEntity.position == fCurrentEntity.count) {
 467                 fCurrentEntity.ch[0] = ch;
 468                 offset = 0;
 469                 if (load(1, false, true)) {
 470                     fCurrentEntity.columnNumber++;
 471                     String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
 472                     return symbol;
 473                 }
 474             }
 475         }
 476         else if (XML11Char.isXML11NameHighSurrogate(ch)) {
 477             if (++fCurrentEntity.position == fCurrentEntity.count) {
 478                 fCurrentEntity.ch[0] = ch;
 479                 offset = 0;
 480                 if (load(1, false, true)) {
 481                     --fCurrentEntity.position;
 482                     --fCurrentEntity.startPosition;
 483                     return null;
 484                 }
 485             }
 486             char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
 487             if ( !XMLChar.isLowSurrogate(ch2) ||
 488                  !XML11Char.isXML11NCNameStart(XMLChar.supplemental(ch, ch2)) ) {
 489                 --fCurrentEntity.position;
 490                 return null;
 491             }
 492             if (++fCurrentEntity.position == fCurrentEntity.count) {
 493                 fCurrentEntity.ch[0] = ch;
 494                 fCurrentEntity.ch[1] = ch2;
 495                 offset = 0;
 496                 if (load(2, false, true)) {
 497                     fCurrentEntity.columnNumber += 2;
 498                     String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 2);
 499                     return symbol;
 500                 }
 501             }
 502         }
 503         else {
 504             return null;
 505         }
 506 
 507         do {
 508             ch = fCurrentEntity.ch[fCurrentEntity.position];
 509             if (XML11Char.isXML11NCName(ch)) {
 510                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 511                     int length = fCurrentEntity.position - offset;
 512                     invokeListeners(length);
 513                     if (length == fCurrentEntity.ch.length) {
 514                         // bad luck we have to resize our buffer
 515                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 516                         System.arraycopy(fCurrentEntity.ch, offset,
 517                                          tmp, 0, length);
 518                         fCurrentEntity.ch = tmp;
 519                     }
 520                     else {
 521                         System.arraycopy(fCurrentEntity.ch, offset,
 522                                          fCurrentEntity.ch, 0, length);
 523                     }
 524                     offset = 0;
 525                     if (load(length, false, false)) {
 526                         break;
 527                     }
 528                 }
 529             }
 530             else if (XML11Char.isXML11NameHighSurrogate(ch)) {
 531                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 532                     int length = fCurrentEntity.position - offset;
 533                     invokeListeners(length);
 534                     if (length == fCurrentEntity.ch.length) {
 535                         // bad luck we have to resize our buffer
 536                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 537                         System.arraycopy(fCurrentEntity.ch, offset,
 538                                          tmp, 0, length);
 539                         fCurrentEntity.ch = tmp;
 540                     }
 541                     else {
 542                         System.arraycopy(fCurrentEntity.ch, offset,
 543                                          fCurrentEntity.ch, 0, length);
 544                     }
 545                     offset = 0;
 546                     if (load(length, false, false)) {
 547                         --fCurrentEntity.startPosition;
 548                         --fCurrentEntity.position;
 549                         break;
 550                     }
 551                 }
 552                 char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
 553                 if ( !XMLChar.isLowSurrogate(ch2) ||
 554                      !XML11Char.isXML11NCName(XMLChar.supplemental(ch, ch2)) ) {
 555                     --fCurrentEntity.position;
 556                     break;
 557                 }
 558                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 559                     int length = fCurrentEntity.position - offset;
 560                     invokeListeners(length);
 561                     if (length == fCurrentEntity.ch.length) {
 562                         // bad luck we have to resize our buffer
 563                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 564                         System.arraycopy(fCurrentEntity.ch, offset,
 565                                          tmp, 0, length);
 566                         fCurrentEntity.ch = tmp;
 567                     }
 568                     else {
 569                         System.arraycopy(fCurrentEntity.ch, offset,
 570                                          fCurrentEntity.ch, 0, length);
 571                     }
 572                     offset = 0;
 573                     if (load(length, false, false)) {
 574                         break;
 575                     }
 576                 }
 577             }
 578             else {
 579                 break;
 580             }
 581         }
 582         while (true);
 583 
 584         int length = fCurrentEntity.position - offset;
 585         fCurrentEntity.columnNumber += length;
 586 
 587         // return name
 588         String symbol = null;
 589         if (length > 0) {
 590             symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
 591         }
 592         return symbol;
 593 
 594     } // scanNCName():String
 595 
 596     /**
 597      * Scans a qualified name from the input, setting the fields of the
 598      * QName structure appropriately.
 599      * <p>
 600      * <strong>Note:</strong> The qualified name characters are consumed.
 601      * <p>
 602      * <strong>Note:</strong> The strings used to set the values of the
 603      * QName structure must be symbols. The SymbolTable can be used for
 604      * this purpose.
 605      *
 606      * @param qname The qualified name structure to fill.
 607      *
 608      * @return Returns true if a qualified name appeared immediately on
 609      *         the input and was scanned, false otherwise.
 610      *
 611      * @throws IOException  Thrown if i/o error occurs.
 612      * @throws EOFException Thrown on end of file.
 613      *
 614      * @see com.sun.org.apache.xerces.internal.util.SymbolTable
 615      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11Name
 616      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NameStart
 617      */
 618     public boolean scanQName(QName qname) throws IOException {
 619 
 620         // load more characters, if needed
 621         if (fCurrentEntity.position == fCurrentEntity.count) {
 622             load(0, true, true);
 623         }
 624 
 625         // scan qualified name
 626         int offset = fCurrentEntity.position;
 627         char ch = fCurrentEntity.ch[offset];
 628 
 629         if (XML11Char.isXML11NCNameStart(ch)) {
 630             if (++fCurrentEntity.position == fCurrentEntity.count) {
 631                 fCurrentEntity.ch[0] = ch;
 632                 offset = 0;
 633                 if (load(1, false, true)) {
 634                     fCurrentEntity.columnNumber++;
 635                     String name = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
 636                     qname.setValues(null, name, name, null);
 637                     return true;
 638                 }
 639             }
 640         }
 641         else if (XML11Char.isXML11NameHighSurrogate(ch)) {
 642             if (++fCurrentEntity.position == fCurrentEntity.count) {
 643                 fCurrentEntity.ch[0] = ch;
 644                 offset = 0;
 645                 if (load(1, false, true)) {
 646                     --fCurrentEntity.startPosition;
 647                     --fCurrentEntity.position;
 648                     return false;
 649                 }
 650             }
 651             char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
 652             if ( !XMLChar.isLowSurrogate(ch2) ||
 653                  !XML11Char.isXML11NCNameStart(XMLChar.supplemental(ch, ch2)) ) {
 654                 --fCurrentEntity.position;
 655                 return false;
 656             }
 657             if (++fCurrentEntity.position == fCurrentEntity.count) {
 658                 fCurrentEntity.ch[0] = ch;
 659                 fCurrentEntity.ch[1] = ch2;
 660                 offset = 0;
 661                 if (load(2, false, true)) {
 662                     fCurrentEntity.columnNumber += 2;
 663                     String name = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 2);
 664                     qname.setValues(null, name, name, null);
 665                     return true;
 666                 }
 667             }
 668         }
 669         else {
 670             return false;
 671         }
 672 
 673         int index = -1;
 674         boolean sawIncompleteSurrogatePair = false;
 675         do {
 676             ch = fCurrentEntity.ch[fCurrentEntity.position];
 677             if (XML11Char.isXML11Name(ch)) {
 678                 if (ch == ':') {
 679                     if (index != -1) {
 680                         break;
 681                     }
 682                     index = fCurrentEntity.position;
 683                 }
 684                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 685                     int length = fCurrentEntity.position - offset;
 686                     invokeListeners(length);
 687                     if (length == fCurrentEntity.ch.length) {
 688                         // bad luck we have to resize our buffer
 689                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 690                         System.arraycopy(fCurrentEntity.ch, offset,
 691                                          tmp, 0, length);
 692                         fCurrentEntity.ch = tmp;
 693                     }
 694                     else {
 695                         System.arraycopy(fCurrentEntity.ch, offset,
 696                                          fCurrentEntity.ch, 0, length);
 697                     }
 698                     if (index != -1) {
 699                         index = index - offset;
 700                     }
 701                     offset = 0;
 702                     if (load(length, false, false)) {
 703                         break;
 704                     }
 705                 }
 706             }
 707             else if (XML11Char.isXML11NameHighSurrogate(ch)) {
 708                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 709                     int length = fCurrentEntity.position - offset;
 710                     invokeListeners(length);
 711                     if (length == fCurrentEntity.ch.length) {
 712                         // bad luck we have to resize our buffer
 713                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 714                         System.arraycopy(fCurrentEntity.ch, offset,
 715                                          tmp, 0, length);
 716                         fCurrentEntity.ch = tmp;
 717                     }
 718                     else {
 719                         System.arraycopy(fCurrentEntity.ch, offset,
 720                                          fCurrentEntity.ch, 0, length);
 721                     }
 722                     if (index != -1) {
 723                         index = index - offset;
 724                     }
 725                     offset = 0;
 726                     if (load(length, false, false)) {
 727                         sawIncompleteSurrogatePair = true;
 728                         --fCurrentEntity.startPosition;
 729                         --fCurrentEntity.position;
 730                         break;
 731                     }
 732                 }
 733                 char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
 734                 if ( !XMLChar.isLowSurrogate(ch2) ||
 735                      !XML11Char.isXML11Name(XMLChar.supplemental(ch, ch2)) ) {
 736                     sawIncompleteSurrogatePair = true;
 737                     --fCurrentEntity.position;
 738                     break;
 739                 }
 740                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 741                     int length = fCurrentEntity.position - offset;
 742                     invokeListeners(length);
 743                     if (length == fCurrentEntity.ch.length) {
 744                         // bad luck we have to resize our buffer
 745                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 746                         System.arraycopy(fCurrentEntity.ch, offset,
 747                                          tmp, 0, length);
 748                         fCurrentEntity.ch = tmp;
 749                     }
 750                     else {
 751                         System.arraycopy(fCurrentEntity.ch, offset,
 752                                          fCurrentEntity.ch, 0, length);
 753                     }
 754                     if (index != -1) {
 755                         index = index - offset;
 756                     }
 757                     offset = 0;
 758                     if (load(length, false, false)) {
 759                         break;
 760                     }
 761                 }
 762             }
 763             else {
 764                 break;
 765             }
 766         }
 767         while (true);
 768 
 769         int length = fCurrentEntity.position - offset;
 770         fCurrentEntity.columnNumber += length;
 771 
 772         if (length > 0) {
 773             String prefix = null;
 774             String localpart = null;
 775             String rawname = fSymbolTable.addSymbol(fCurrentEntity.ch,
 776                                                     offset, length);
 777             if (index != -1) {
 778                 int prefixLength = index - offset;
 779                 prefix = fSymbolTable.addSymbol(fCurrentEntity.ch,
 780                                                     offset, prefixLength);
 781                 int len = length - prefixLength - 1;
 782                 int startLocal = index +1;
 783                 if (!XML11Char.isXML11NCNameStart(fCurrentEntity.ch[startLocal]) &&
 784                     (!XML11Char.isXML11NameHighSurrogate(fCurrentEntity.ch[startLocal]) ||
 785                     sawIncompleteSurrogatePair)){
 786                     fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
 787                                                "IllegalQName",
 788                                                null,
 789                                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
 790                 }
 791                 localpart = fSymbolTable.addSymbol(fCurrentEntity.ch,
 792                                                    index + 1, len);
 793 
 794             }
 795             else {
 796                 localpart = rawname;
 797             }
 798             qname.setValues(prefix, localpart, rawname, null);
 799             return true;
 800         }
 801         return false;
 802 
 803     } // scanQName(QName):boolean
 804 
 805     /**
 806      * Scans a range of parsed character data, setting the fields of the
 807      * XMLString structure, appropriately.
 808      * <p>
 809      * <strong>Note:</strong> The characters are consumed.
 810      * <p>
 811      * <strong>Note:</strong> This method does not guarantee to return
 812      * the longest run of parsed character data. This method may return
 813      * before markup due to reaching the end of the input buffer or any
 814      * other reason.
 815      * <p>
 816      * <strong>Note:</strong> The fields contained in the XMLString
 817      * structure are not guaranteed to remain valid upon subsequent calls
 818      * to the entity scanner. Therefore, the caller is responsible for
 819      * immediately using the returned character data or making a copy of
 820      * the character data.
 821      *
 822      * @param content The content structure to fill.
 823      *
 824      * @return Returns the next character on the input, if known. This
 825      *         value may be -1 but this does <em>note</em> designate
 826      *         end of file.
 827      *
 828      * @throws IOException  Thrown if i/o error occurs.
 829      * @throws EOFException Thrown on end of file.
 830      */
 831     public int scanContent(XMLString content) throws IOException {
 832 
 833         // load more characters, if needed
 834         if (fCurrentEntity.position == fCurrentEntity.count) {
 835             load(0, true, true);
 836         }
 837         else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
 838             fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
 839             load(1, false, true);
 840             fCurrentEntity.position = 0;
 841             fCurrentEntity.startPosition = 0;
 842         }
 843 
 844         // normalize newlines
 845         int offset = fCurrentEntity.position;
 846         int c = fCurrentEntity.ch[offset];
 847         int newlines = 0;
 848         boolean external = fCurrentEntity.isExternal();
 849         if (c == '\n' || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) {
 850             do {
 851                 c = fCurrentEntity.ch[fCurrentEntity.position++];
 852                 if ((c == '\r' ) && external) {
 853                     newlines++;
 854                     fCurrentEntity.lineNumber++;
 855                     fCurrentEntity.columnNumber = 1;
 856                     if (fCurrentEntity.position == fCurrentEntity.count) {
 857                         offset = 0;
 858                         fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
 859                         fCurrentEntity.position = newlines;
 860                         fCurrentEntity.startPosition = newlines;
 861                         if (load(newlines, false, true)) {
 862                             break;
 863                         }
 864                     }
 865                     int cc = fCurrentEntity.ch[fCurrentEntity.position];
 866                     if (cc == '\n' || cc == 0x85) {
 867                         fCurrentEntity.position++;
 868                         offset++;
 869                     }
 870                     /*** NEWLINE NORMALIZATION ***/
 871                     else {
 872                         newlines++;
 873                     }
 874                 }
 875                 else if (c == '\n' || ((c == 0x85 || c == 0x2028) && external)) {
 876                     newlines++;
 877                     fCurrentEntity.lineNumber++;
 878                     fCurrentEntity.columnNumber = 1;
 879                     if (fCurrentEntity.position == fCurrentEntity.count) {
 880                         offset = 0;
 881                         fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
 882                         fCurrentEntity.position = newlines;
 883                         fCurrentEntity.startPosition = newlines;
 884                         if (load(newlines, false, true)) {
 885                             break;
 886                         }
 887                     }
 888                 }
 889                 else {
 890                     fCurrentEntity.position--;
 891                     break;
 892                 }
 893             } while (fCurrentEntity.position < fCurrentEntity.count - 1);
 894             for (int i = offset; i < fCurrentEntity.position; i++) {
 895                 fCurrentEntity.ch[i] = '\n';
 896             }
 897             int length = fCurrentEntity.position - offset;
 898             if (fCurrentEntity.position == fCurrentEntity.count - 1) {
 899                 content.setValues(fCurrentEntity.ch, offset, length);
 900                 return -1;
 901             }
 902         }
 903 
 904         // inner loop, scanning for content
 905         if (external) {
 906             while (fCurrentEntity.position < fCurrentEntity.count) {
 907                 c = fCurrentEntity.ch[fCurrentEntity.position++];
 908                 if (!XML11Char.isXML11Content(c) || c == 0x85 || c == 0x2028) {
 909                     fCurrentEntity.position--;
 910                     break;
 911                 }
 912             }
 913         }
 914         else {
 915             while (fCurrentEntity.position < fCurrentEntity.count) {
 916                 c = fCurrentEntity.ch[fCurrentEntity.position++];
 917                 // In internal entities control characters are allowed to appear unescaped.
 918                 if (!XML11Char.isXML11InternalEntityContent(c)) {
 919                     fCurrentEntity.position--;
 920                     break;
 921                 }
 922             }
 923         }
 924         int length = fCurrentEntity.position - offset;
 925         fCurrentEntity.columnNumber += length - newlines;
 926         content.setValues(fCurrentEntity.ch, offset, length);
 927 
 928         // return next character
 929         if (fCurrentEntity.position != fCurrentEntity.count) {
 930             c = fCurrentEntity.ch[fCurrentEntity.position];
 931             // REVISIT: Does this need to be updated to fix the
 932             //          #x0D ^#x0A newline normalization problem? -Ac
 933             if ((c == '\r' || c == 0x85 || c == 0x2028) && external) {
 934                 c = '\n';
 935             }
 936         }
 937         else {
 938             c = -1;
 939         }
 940         return c;
 941 
 942     } // scanContent(XMLString):int
 943 
 944     /**
 945      * Scans a range of attribute value data, setting the fields of the
 946      * XMLString structure, appropriately.
 947      * <p>
 948      * <strong>Note:</strong> The characters are consumed.
 949      * <p>
 950      * <strong>Note:</strong> This method does not guarantee to return
 951      * the longest run of attribute value data. This method may return
 952      * before the quote character due to reaching the end of the input
 953      * buffer or any other reason.
 954      * <p>
 955      * <strong>Note:</strong> The fields contained in the XMLString
 956      * structure are not guaranteed to remain valid upon subsequent calls
 957      * to the entity scanner. Therefore, the caller is responsible for
 958      * immediately using the returned character data or making a copy of
 959      * the character data.
 960      *
 961      * @param quote   The quote character that signifies the end of the
 962      *                attribute value data.
 963      * @param content The content structure to fill.
 964      *
 965      * @return Returns the next character on the input, if known. This
 966      *         value may be -1 but this does <em>note</em> designate
 967      *         end of file.
 968      *
 969      * @throws IOException  Thrown if i/o error occurs.
 970      * @throws EOFException Thrown on end of file.
 971      */
 972     public int scanLiteral(int quote, XMLString content)
 973         throws IOException {
 974         // load more characters, if needed
 975         if (fCurrentEntity.position == fCurrentEntity.count) {
 976             load(0, true, true);
 977         }
 978         else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
 979             fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
 980             load(1, false, true);
 981             fCurrentEntity.startPosition = 0;
 982             fCurrentEntity.position = 0;
 983         }
 984 
 985         // normalize newlines
 986         int offset = fCurrentEntity.position;
 987         int c = fCurrentEntity.ch[offset];
 988         int newlines = 0;
 989         boolean external = fCurrentEntity.isExternal();
 990         if (c == '\n' || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) {
 991             do {
 992                 c = fCurrentEntity.ch[fCurrentEntity.position++];
 993                 if ((c == '\r' ) && external) {
 994                     newlines++;
 995                     fCurrentEntity.lineNumber++;
 996                     fCurrentEntity.columnNumber = 1;
 997                     if (fCurrentEntity.position == fCurrentEntity.count) {
 998                         offset = 0;
 999                         fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1000                         fCurrentEntity.position = newlines;
1001                         fCurrentEntity.startPosition = newlines;
1002                         if (load(newlines, false, true)) {
1003                             break;
1004                         }
1005                     }
1006                     int cc = fCurrentEntity.ch[fCurrentEntity.position];
1007                     if (cc == '\n' || cc == 0x85) {
1008                         fCurrentEntity.position++;
1009                         offset++;
1010                     }
1011                     /*** NEWLINE NORMALIZATION ***/
1012                     else {
1013                         newlines++;
1014                     }
1015                 }
1016                 else if (c == '\n' || ((c == 0x85 || c == 0x2028) && external)) {
1017                     newlines++;
1018                     fCurrentEntity.lineNumber++;
1019                     fCurrentEntity.columnNumber = 1;
1020                     if (fCurrentEntity.position == fCurrentEntity.count) {
1021                         offset = 0;
1022                         fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1023                         fCurrentEntity.position = newlines;
1024                         fCurrentEntity.startPosition = newlines;
1025                         if (load(newlines, false, true)) {
1026                             break;
1027                         }
1028                     }
1029                 }
1030                 else {
1031                     fCurrentEntity.position--;
1032                     break;
1033                 }
1034             } while (fCurrentEntity.position < fCurrentEntity.count - 1);
1035             for (int i = offset; i < fCurrentEntity.position; i++) {
1036                 fCurrentEntity.ch[i] = '\n';
1037             }
1038             int length = fCurrentEntity.position - offset;
1039             if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1040                 content.setValues(fCurrentEntity.ch, offset, length);
1041                 return -1;
1042             }
1043         }
1044 
1045         // scan literal value
1046         if (external) {
1047             while (fCurrentEntity.position < fCurrentEntity.count) {
1048                 c = fCurrentEntity.ch[fCurrentEntity.position++];
1049                 if (c == quote || c == '%' || !XML11Char.isXML11Content(c)
1050                     || c == 0x85 || c == 0x2028) {
1051                     fCurrentEntity.position--;
1052                     break;
1053                 }
1054             }
1055         }
1056         else {
1057             while (fCurrentEntity.position < fCurrentEntity.count) {
1058                 c = fCurrentEntity.ch[fCurrentEntity.position++];
1059                 // In internal entities control characters are allowed to appear unescaped.
1060                 if ((c == quote && !fCurrentEntity.literal)
1061                     || c == '%' || !XML11Char.isXML11InternalEntityContent(c)) {
1062                     fCurrentEntity.position--;
1063                     break;
1064                 }
1065             }
1066         }
1067         int length = fCurrentEntity.position - offset;
1068         fCurrentEntity.columnNumber += length - newlines;
1069         content.setValues(fCurrentEntity.ch, offset, length);
1070 
1071         // return next character
1072         if (fCurrentEntity.position != fCurrentEntity.count) {
1073             c = fCurrentEntity.ch[fCurrentEntity.position];
1074             // NOTE: We don't want to accidentally signal the
1075             //       end of the literal if we're expanding an
1076             //       entity appearing in the literal. -Ac
1077             if (c == quote && fCurrentEntity.literal) {
1078                 c = -1;
1079             }
1080         }
1081         else {
1082             c = -1;
1083         }
1084         return c;
1085 
1086     } // scanLiteral(int,XMLString):int
1087 
1088     /**
1089      * Scans a range of character data up to the specicied delimiter,
1090      * setting the fields of the XMLString structure, appropriately.
1091      * <p>
1092      * <strong>Note:</strong> The characters are consumed.
1093      * <p>
1094      * <strong>Note:</strong> This assumes that the internal buffer is
1095      * at least the same size, or bigger, than the length of the delimiter
1096      * and that the delimiter contains at least one character.
1097      * <p>
1098      * <strong>Note:</strong> This method does not guarantee to return
1099      * the longest run of character data. This method may return before
1100      * the delimiter due to reaching the end of the input buffer or any
1101      * other reason.
1102      * <p>
1103      * <strong>Note:</strong> The fields contained in the XMLString
1104      * structure are not guaranteed to remain valid upon subsequent calls
1105      * to the entity scanner. Therefore, the caller is responsible for
1106      * immediately using the returned character data or making a copy of
1107      * the character data.
1108      *
1109      * @param delimiter The string that signifies the end of the character
1110      *                  data to be scanned.
1111      * @param data      The data structure to fill.
1112      *
1113      * @return Returns true if there is more data to scan, false otherwise.
1114      *
1115      * @throws IOException  Thrown if i/o error occurs.
1116      * @throws EOFException Thrown on end of file.
1117      */
1118     public boolean scanData(String delimiter, XMLStringBuffer buffer)
1119         throws IOException {
1120 
1121         boolean done = false;
1122         int delimLen = delimiter.length();
1123         char charAt0 = delimiter.charAt(0);
1124         boolean external = fCurrentEntity.isExternal();
1125         do {
1126             // load more characters, if needed
1127             if (fCurrentEntity.position == fCurrentEntity.count) {
1128                 load(0, true, false);
1129             }
1130 
1131             boolean bNextEntity = false;
1132 
1133             while ((fCurrentEntity.position >= fCurrentEntity.count - delimLen)
1134                 && (!bNextEntity))
1135             {
1136               System.arraycopy(fCurrentEntity.ch,
1137                                fCurrentEntity.position,
1138                                fCurrentEntity.ch,
1139                                0,
1140                                fCurrentEntity.count - fCurrentEntity.position);
1141 
1142               bNextEntity = load(fCurrentEntity.count - fCurrentEntity.position, false, false);
1143               fCurrentEntity.position = 0;
1144               fCurrentEntity.startPosition = 0;
1145             }
1146 
1147             if (fCurrentEntity.position >= fCurrentEntity.count - delimLen) {
1148                 // something must be wrong with the input:  e.g., file ends  an unterminated comment
1149                 int length = fCurrentEntity.count - fCurrentEntity.position;
1150                 buffer.append (fCurrentEntity.ch, fCurrentEntity.position, length);
1151                 fCurrentEntity.columnNumber += fCurrentEntity.count;
1152                 fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1153                 fCurrentEntity.position = fCurrentEntity.count;
1154                 fCurrentEntity.startPosition = fCurrentEntity.count;
1155                 load(0,true, false);
1156                 return false;
1157             }
1158 
1159             // normalize newlines
1160             int offset = fCurrentEntity.position;
1161             int c = fCurrentEntity.ch[offset];
1162             int newlines = 0;
1163             if (c == '\n' || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) {
1164                 do {
1165                     c = fCurrentEntity.ch[fCurrentEntity.position++];
1166                     if ((c == '\r' ) && external) {
1167                         newlines++;
1168                         fCurrentEntity.lineNumber++;
1169                         fCurrentEntity.columnNumber = 1;
1170                         if (fCurrentEntity.position == fCurrentEntity.count) {
1171                             offset = 0;
1172                             fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1173                             fCurrentEntity.position = newlines;
1174                             fCurrentEntity.startPosition = newlines;
1175                             if (load(newlines, false, true)) {
1176                                 break;
1177                             }
1178                         }
1179                         int cc = fCurrentEntity.ch[fCurrentEntity.position];
1180                         if (cc == '\n' || cc == 0x85) {
1181                             fCurrentEntity.position++;
1182                             offset++;
1183                         }
1184                         /*** NEWLINE NORMALIZATION ***/
1185                         else {
1186                             newlines++;
1187                         }
1188                     }
1189                     else if (c == '\n' || ((c == 0x85 || c == 0x2028) && external)) {
1190                         newlines++;
1191                         fCurrentEntity.lineNumber++;
1192                         fCurrentEntity.columnNumber = 1;
1193                         if (fCurrentEntity.position == fCurrentEntity.count) {
1194                             offset = 0;
1195                             fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1196                             fCurrentEntity.position = newlines;
1197                             fCurrentEntity.startPosition = newlines;
1198                             fCurrentEntity.count = newlines;
1199                             if (load(newlines, false, true)) {
1200                                 break;
1201                             }
1202                         }
1203                     }
1204                     else {
1205                         fCurrentEntity.position--;
1206                         break;
1207                     }
1208                 } while (fCurrentEntity.position < fCurrentEntity.count - 1);
1209                 for (int i = offset; i < fCurrentEntity.position; i++) {
1210                     fCurrentEntity.ch[i] = '\n';
1211                 }
1212                 int length = fCurrentEntity.position - offset;
1213                 if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1214                     buffer.append(fCurrentEntity.ch, offset, length);
1215                     return true;
1216                 }
1217             }
1218 
1219             // iterate over buffer looking for delimiter
1220             if (external) {
1221                 OUTER: while (fCurrentEntity.position < fCurrentEntity.count) {
1222                     c = fCurrentEntity.ch[fCurrentEntity.position++];
1223                     if (c == charAt0) {
1224                         // looks like we just hit the delimiter
1225                         int delimOffset = fCurrentEntity.position - 1;
1226                         for (int i = 1; i < delimLen; i++) {
1227                             if (fCurrentEntity.position == fCurrentEntity.count) {
1228                                 fCurrentEntity.position -= i;
1229                                 break OUTER;
1230                             }
1231                             c = fCurrentEntity.ch[fCurrentEntity.position++];
1232                             if (delimiter.charAt(i) != c) {
1233                                 fCurrentEntity.position--;
1234                                 break;
1235                             }
1236                          }
1237                          if (fCurrentEntity.position == delimOffset + delimLen) {
1238                             done = true;
1239                             break;
1240                          }
1241                     }
1242                     else if (c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) {
1243                         fCurrentEntity.position--;
1244                         break;
1245                     }
1246                     // In external entities control characters cannot appear
1247                     // as literals so do not skip over them.
1248                     else if (!XML11Char.isXML11ValidLiteral(c)) {
1249                         fCurrentEntity.position--;
1250                         int length = fCurrentEntity.position - offset;
1251                         fCurrentEntity.columnNumber += length - newlines;
1252                         buffer.append(fCurrentEntity.ch, offset, length);
1253                         return true;
1254                     }
1255                 }
1256             }
1257             else {
1258                 OUTER: while (fCurrentEntity.position < fCurrentEntity.count) {
1259                     c = fCurrentEntity.ch[fCurrentEntity.position++];
1260                     if (c == charAt0) {
1261                         // looks like we just hit the delimiter
1262                         int delimOffset = fCurrentEntity.position - 1;
1263                         for (int i = 1; i < delimLen; i++) {
1264                             if (fCurrentEntity.position == fCurrentEntity.count) {
1265                                 fCurrentEntity.position -= i;
1266                                 break OUTER;
1267                             }
1268                             c = fCurrentEntity.ch[fCurrentEntity.position++];
1269                             if (delimiter.charAt(i) != c) {
1270                                 fCurrentEntity.position--;
1271                                 break;
1272                             }
1273                         }
1274                         if (fCurrentEntity.position == delimOffset + delimLen) {
1275                             done = true;
1276                             break;
1277                         }
1278                     }
1279                     else if (c == '\n') {
1280                         fCurrentEntity.position--;
1281                         break;
1282                     }
1283                     // Control characters are allowed to appear as literals
1284                     // in internal entities.
1285                     else if (!XML11Char.isXML11Valid(c)) {
1286                         fCurrentEntity.position--;
1287                         int length = fCurrentEntity.position - offset;
1288                         fCurrentEntity.columnNumber += length - newlines;
1289                         buffer.append(fCurrentEntity.ch, offset, length);
1290                         return true;
1291                     }
1292                 }
1293             }
1294             int length = fCurrentEntity.position - offset;
1295             fCurrentEntity.columnNumber += length - newlines;
1296             if (done) {
1297                 length -= delimLen;
1298             }
1299             buffer.append(fCurrentEntity.ch, offset, length);
1300 
1301             // return true if string was skipped
1302         } while (!done);
1303         return !done;
1304 
1305     } // scanData(String,XMLString)
1306 
1307     /**
1308      * Skips a character appearing immediately on the input.
1309      * <p>
1310      * <strong>Note:</strong> The character is consumed only if it matches
1311      * the specified character.
1312      *
1313      * @param c The character to skip.
1314      *
1315      * @return Returns true if the character was skipped.
1316      *
1317      * @throws IOException  Thrown if i/o error occurs.
1318      * @throws EOFException Thrown on end of file.
1319      */
1320     public boolean skipChar(int c) throws IOException {
1321 
1322         // load more characters, if needed
1323         if (fCurrentEntity.position == fCurrentEntity.count) {
1324             load(0, true, true);
1325         }
1326 
1327         // skip character
1328         int cc = fCurrentEntity.ch[fCurrentEntity.position];
1329         if (cc == c) {
1330             fCurrentEntity.position++;
1331             if (c == '\n') {
1332                 fCurrentEntity.lineNumber++;
1333                 fCurrentEntity.columnNumber = 1;
1334             }
1335             else {
1336                 fCurrentEntity.columnNumber++;
1337             }
1338             return true;
1339         }
1340         else if (c == '\n' && ((cc == 0x2028 || cc == 0x85) && fCurrentEntity.isExternal())) {
1341             fCurrentEntity.position++;
1342             fCurrentEntity.lineNumber++;
1343             fCurrentEntity.columnNumber = 1;
1344             return true;
1345         }
1346         else if (c == '\n' && (cc == '\r' ) && fCurrentEntity.isExternal()) {
1347             // handle newlines
1348             if (fCurrentEntity.position == fCurrentEntity.count) {
1349                 fCurrentEntity.ch[0] = (char)cc;
1350                 load(1, false, true);
1351             }
1352             int ccc = fCurrentEntity.ch[++fCurrentEntity.position];
1353             if (ccc == '\n' || ccc == 0x85) {
1354                 fCurrentEntity.position++;
1355             }
1356             fCurrentEntity.lineNumber++;
1357             fCurrentEntity.columnNumber = 1;
1358             return true;
1359         }
1360 
1361         // character was not skipped
1362         return false;
1363 
1364     } // skipChar(int):boolean
1365 
1366     /**
1367      * Skips space characters appearing immediately on the input.
1368      * <p>
1369      * <strong>Note:</strong> The characters are consumed only if they are
1370      * space characters.
1371      *
1372      * @return Returns true if at least one space character was skipped.
1373      *
1374      * @throws IOException  Thrown if i/o error occurs.
1375      * @throws EOFException Thrown on end of file.
1376      *
1377      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace
1378      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11Space
1379      */
1380     public boolean skipSpaces() throws IOException {
1381 
1382         // load more characters, if needed
1383         if (fCurrentEntity.position == fCurrentEntity.count) {
1384             load(0, true, true);
1385         }
1386 
1387 
1388         //we are doing this check only in skipSpace() because it is called by
1389         //fMiscDispatcher and we want the parser to exit gracefully when document
1390         //is well-formed.
1391         //it is possible that end of document is reached and
1392         //fCurrentEntity becomes null
1393         //nothing was read so entity changed  'false' should be returned.
1394         if(fCurrentEntity == null){
1395             return false ;
1396         }
1397 
1398         // skip spaces
1399         int c = fCurrentEntity.ch[fCurrentEntity.position];
1400 
1401         // External --  Match: S + 0x85 + 0x2028, and perform end of line normalization
1402         if (fCurrentEntity.isExternal()) {
1403             if (XML11Char.isXML11Space(c)) {
1404                 do {
1405                     boolean entityChanged = false;
1406                     // handle newlines
1407                     if (c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) {
1408                         fCurrentEntity.lineNumber++;
1409                         fCurrentEntity.columnNumber = 1;
1410                         if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1411                             fCurrentEntity.ch[0] = (char)c;
1412                             entityChanged = load(1, true, true);
1413                             if (!entityChanged) {
1414                                 // the load change the position to be 1,
1415                                 // need to restore it when entity not changed
1416                                 fCurrentEntity.startPosition = 0;
1417                                 fCurrentEntity.position = 0;
1418                             } else if(fCurrentEntity == null){
1419                                 return true ;
1420                             }
1421 
1422                         }
1423                         if (c == '\r') {
1424                             // REVISIT: Does this need to be updated to fix the
1425                             //          #x0D ^#x0A newline normalization problem? -Ac
1426                             int cc = fCurrentEntity.ch[++fCurrentEntity.position];
1427                             if (cc != '\n' && cc != 0x85 ) {
1428                                 fCurrentEntity.position--;
1429                             }
1430                         }
1431                     }
1432                     else {
1433                         fCurrentEntity.columnNumber++;
1434                     }
1435                     // load more characters, if needed
1436                     if (!entityChanged)
1437                         fCurrentEntity.position++;
1438                     if (fCurrentEntity.position == fCurrentEntity.count) {
1439                         load(0, true, true);
1440 
1441                         if(fCurrentEntity == null){
1442                         return true ;
1443                         }
1444 
1445                     }
1446                 } while (XML11Char.isXML11Space(c = fCurrentEntity.ch[fCurrentEntity.position]));
1447                 return true;
1448             }
1449         }
1450         // Internal -- Match: S (only)
1451         else if (XMLChar.isSpace(c)) {
1452             do {
1453                 boolean entityChanged = false;
1454                 // handle newlines
1455                 if (c == '\n') {
1456                     fCurrentEntity.lineNumber++;
1457                     fCurrentEntity.columnNumber = 1;
1458                     if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1459                         fCurrentEntity.ch[0] = (char)c;
1460                         entityChanged = load(1, true, true);
1461                         if (!entityChanged) {
1462                             // the load change the position to be 1,
1463                             // need to restore it when entity not changed
1464                             fCurrentEntity.startPosition = 0;
1465                             fCurrentEntity.position = 0;
1466                         } else if(fCurrentEntity == null){
1467                         return true ;
1468                         }
1469                     }
1470                 }
1471                 else {
1472                     fCurrentEntity.columnNumber++;
1473                 }
1474                 // load more characters, if needed
1475                 if (!entityChanged)
1476                     fCurrentEntity.position++;
1477                 if (fCurrentEntity.position == fCurrentEntity.count) {
1478                     load(0, true, true);
1479 
1480                     if(fCurrentEntity == null){
1481                         return true ;
1482                     }
1483 
1484                 }
1485             } while (XMLChar.isSpace(c = fCurrentEntity.ch[fCurrentEntity.position]));
1486             return true;
1487         }
1488 
1489         // no spaces were found
1490         return false;
1491 
1492     } // skipSpaces():boolean
1493 
1494     /**
1495      * Skips the specified string appearing immediately on the input.
1496      * <p>
1497      * <strong>Note:</strong> The characters are consumed only if they are
1498      * space characters.
1499      *
1500      * @param s The string to skip.
1501      *
1502      * @return Returns true if the string was skipped.
1503      *
1504      * @throws IOException  Thrown if i/o error occurs.
1505      * @throws EOFException Thrown on end of file.
1506      */
1507     public boolean skipString(String s) throws IOException {
1508 
1509         // load more characters, if needed
1510         if (fCurrentEntity.position == fCurrentEntity.count) {
1511             load(0, true, true);
1512         }
1513 
1514         // skip string
1515         final int length = s.length();
1516         for (int i = 0; i < length; i++) {
1517             char c = fCurrentEntity.ch[fCurrentEntity.position++];
1518             if (c != s.charAt(i)) {
1519                 fCurrentEntity.position -= i + 1;
1520                 return false;
1521             }
1522             if (i < length - 1 && fCurrentEntity.position == fCurrentEntity.count) {
1523                 invokeListeners(0);
1524                 System.arraycopy(fCurrentEntity.ch, fCurrentEntity.count - i - 1, fCurrentEntity.ch, 0, i + 1);
1525                 // REVISIT: Can a string to be skipped cross an
1526                 //          entity boundary? -Ac
1527                 if (load(i + 1, false, false)) {
1528                     fCurrentEntity.startPosition -= i + 1;
1529                     fCurrentEntity.position -= i + 1;
1530                     return false;
1531                 }
1532             }
1533         }
1534         fCurrentEntity.columnNumber += length;
1535         return true;
1536 
1537     } // skipString(String):boolean
1538 
1539 } // class XML11EntityScanner