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  */
  81 
  82 public class XML11EntityScanner
  83     extends XMLEntityScanner {
  84 
  85     //
  86     // Constructors
  87     //
  88 
  89     /** Default constructor. */
  90     public XML11EntityScanner() {
  91         super();
  92     } // <init>()
  93 
  94     //
  95     // XMLEntityScanner methods
  96     //
  97 
  98     /**
  99      * Returns the next character on the input.
 100      * <p>
 101      * <strong>Note:</strong> The character is <em>not</em> consumed.
 102      *
 103      * @throws IOException  Thrown if i/o error occurs.
 104      * @throws EOFException Thrown on end of file.
 105      */
 106     public int peekChar() throws IOException {
 107 
 108         // load more characters, if needed
 109         if (fCurrentEntity.position == fCurrentEntity.count) {
 110             load(0, true, true);
 111         }
 112 
 113         // peek at character
 114         int c = fCurrentEntity.ch[fCurrentEntity.position];
 115 
 116         // return peeked character
 117         if (fCurrentEntity.isExternal()) {
 118             return (c != '\r' && c != 0x85 && c != 0x2028) ? c : '\n';
 119         }
 120         else {
 121             return c;
 122         }
 123 
 124     } // peekChar():int
 125 
 126     /**
 127      * Returns the next character on the input.
 128      * <p>
 129      * <strong>Note:</strong> The character is consumed.
 130      *
 131      * @throws IOException  Thrown if i/o error occurs.
 132      * @throws EOFException Thrown on end of file.
 133      */
 134     public int scanChar() throws IOException {
 135 
 136         // load more characters, if needed
 137         if (fCurrentEntity.position == fCurrentEntity.count) {
 138             load(0, true, true);
 139         }
 140 
 141         // scan character
 142         int c = fCurrentEntity.ch[fCurrentEntity.position++];
 143         boolean external = false;
 144         if (c == '\n' ||
 145             ((c == '\r' || c == 0x85 || c == 0x2028) && (external = fCurrentEntity.isExternal()))) {
 146             fCurrentEntity.lineNumber++;
 147             fCurrentEntity.columnNumber = 1;
 148             if (fCurrentEntity.position == fCurrentEntity.count) {
 149                 invokeListeners(1);
 150                 fCurrentEntity.ch[0] = (char)c;
 151                 load(1, false, false);
 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                 invokeListeners(1);
 310                 fCurrentEntity.ch[0] = ch;
 311                 offset = 0;
 312                 if (load(1, false, false)) {
 313                     fCurrentEntity.columnNumber++;
 314                     String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
 315                     return symbol;
 316                 }
 317             }
 318         }
 319         else if (XML11Char.isXML11NameHighSurrogate(ch)) {
 320             if (++fCurrentEntity.position == fCurrentEntity.count) {
 321                 invokeListeners(1);
 322                 fCurrentEntity.ch[0] = ch;
 323                 offset = 0;
 324                 if (load(1, false, false)) {
 325                     --fCurrentEntity.position;
 326                     --fCurrentEntity.startPosition;
 327                     return null;
 328                 }
 329             }
 330             char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
 331             if ( !XMLChar.isLowSurrogate(ch2) ||
 332                  !XML11Char.isXML11NameStart(XMLChar.supplemental(ch, ch2)) ) {
 333                 --fCurrentEntity.position;
 334                 return null;
 335             }
 336             if (++fCurrentEntity.position == fCurrentEntity.count) {
 337                 invokeListeners(2);
 338                 fCurrentEntity.ch[0] = ch;
 339                 fCurrentEntity.ch[1] = ch2;
 340                 offset = 0;
 341                 if (load(2, false, false)) {
 342                     fCurrentEntity.columnNumber += 2;
 343                     String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 2);
 344                     return symbol;
 345                 }
 346             }
 347         }
 348         else {
 349             return null;
 350         }
 351 
 352         do {
 353             ch = fCurrentEntity.ch[fCurrentEntity.position];
 354             if (XML11Char.isXML11Name(ch)) {
 355                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 356                     int length = fCurrentEntity.position - offset;
 357                     invokeListeners(length);
 358                     if (length == fCurrentEntity.ch.length) {
 359                         // bad luck we have to resize our buffer
 360                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 361                         System.arraycopy(fCurrentEntity.ch, offset,
 362                                          tmp, 0, length);
 363                         fCurrentEntity.ch = tmp;
 364                     }
 365                     else {
 366                         System.arraycopy(fCurrentEntity.ch, offset,
 367                                          fCurrentEntity.ch, 0, length);
 368                     }
 369                     offset = 0;
 370                     if (load(length, false, false)) {
 371                         break;
 372                     }
 373                 }
 374             }
 375             else if (XML11Char.isXML11NameHighSurrogate(ch)) {
 376                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 377                     int length = fCurrentEntity.position - offset;
 378                     invokeListeners(length);
 379                     if (length == fCurrentEntity.ch.length) {
 380                         // bad luck we have to resize our buffer
 381                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 382                         System.arraycopy(fCurrentEntity.ch, offset,
 383                                          tmp, 0, length);
 384                         fCurrentEntity.ch = tmp;
 385                     }
 386                     else {
 387                         System.arraycopy(fCurrentEntity.ch, offset,
 388                                          fCurrentEntity.ch, 0, length);
 389                     }
 390                     offset = 0;
 391                     if (load(length, false, false)) {
 392                         --fCurrentEntity.position;
 393                         --fCurrentEntity.startPosition;
 394                         break;
 395                     }
 396                 }
 397                 char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
 398                 if ( !XMLChar.isLowSurrogate(ch2) ||
 399                      !XML11Char.isXML11Name(XMLChar.supplemental(ch, ch2)) ) {
 400                     --fCurrentEntity.position;
 401                     break;
 402                 }
 403                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 404                     int length = fCurrentEntity.position - offset;
 405                     invokeListeners(length);
 406                     if (length == fCurrentEntity.ch.length) {
 407                         // bad luck we have to resize our buffer
 408                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 409                         System.arraycopy(fCurrentEntity.ch, offset,
 410                                          tmp, 0, length);
 411                         fCurrentEntity.ch = tmp;
 412                     }
 413                     else {
 414                         System.arraycopy(fCurrentEntity.ch, offset,
 415                                          fCurrentEntity.ch, 0, length);
 416                     }
 417                     offset = 0;
 418                     if (load(length, false, false)) {
 419                         break;
 420                     }
 421                 }
 422             }
 423             else {
 424                 break;
 425             }
 426         }
 427         while (true);
 428 
 429         int length = fCurrentEntity.position - offset;
 430         fCurrentEntity.columnNumber += length;
 431 
 432         // return name
 433         String symbol = null;
 434         if (length > 0) {
 435             symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
 436         }
 437         return symbol;
 438 
 439     } // scanName():String
 440 
 441     /**
 442      * Returns a string matching the NCName production appearing immediately
 443      * on the input as a symbol, or null if no NCName string is present.
 444      * <p>
 445      * <strong>Note:</strong> The NCName characters are consumed.
 446      * <p>
 447      * <strong>Note:</strong> The string returned must be a symbol. The
 448      * SymbolTable can be used for this purpose.
 449      *
 450      * @throws IOException  Thrown if i/o error occurs.
 451      * @throws EOFException Thrown on end of file.
 452      *
 453      * @see com.sun.org.apache.xerces.internal.util.SymbolTable
 454      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NCName
 455      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NCNameStart
 456      */
 457     public String scanNCName() throws IOException {
 458 
 459         // load more characters, if needed
 460         if (fCurrentEntity.position == fCurrentEntity.count) {
 461             load(0, true, true);
 462         }
 463 
 464         // scan name
 465         int offset = fCurrentEntity.position;
 466         char ch = fCurrentEntity.ch[offset];
 467 
 468         if (XML11Char.isXML11NCNameStart(ch)) {
 469             if (++fCurrentEntity.position == fCurrentEntity.count) {
 470                 invokeListeners(1);
 471                 fCurrentEntity.ch[0] = ch;
 472                 offset = 0;
 473                 if (load(1, false, false)) {
 474                     fCurrentEntity.columnNumber++;
 475                     String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
 476                     return symbol;
 477                 }
 478             }
 479         }
 480         else if (XML11Char.isXML11NameHighSurrogate(ch)) {
 481             if (++fCurrentEntity.position == fCurrentEntity.count) {
 482                 invokeListeners(1);
 483                 fCurrentEntity.ch[0] = ch;
 484                 offset = 0;
 485                 if (load(1, false, false)) {
 486                     --fCurrentEntity.position;
 487                     --fCurrentEntity.startPosition;
 488                     return null;
 489                 }
 490             }
 491             char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
 492             if ( !XMLChar.isLowSurrogate(ch2) ||
 493                  !XML11Char.isXML11NCNameStart(XMLChar.supplemental(ch, ch2)) ) {
 494                 --fCurrentEntity.position;
 495                 return null;
 496             }
 497             if (++fCurrentEntity.position == fCurrentEntity.count) {
 498                 invokeListeners(2);
 499                 fCurrentEntity.ch[0] = ch;
 500                 fCurrentEntity.ch[1] = ch2;
 501                 offset = 0;
 502                 if (load(2, false, false)) {
 503                     fCurrentEntity.columnNumber += 2;
 504                     String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 2);
 505                     return symbol;
 506                 }
 507             }
 508         }
 509         else {
 510             return null;
 511         }
 512 
 513         do {
 514             ch = fCurrentEntity.ch[fCurrentEntity.position];
 515             if (XML11Char.isXML11NCName(ch)) {
 516                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 517                     int length = fCurrentEntity.position - offset;
 518                     invokeListeners(length);
 519                     if (length == fCurrentEntity.ch.length) {
 520                         // bad luck we have to resize our buffer
 521                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 522                         System.arraycopy(fCurrentEntity.ch, offset,
 523                                          tmp, 0, length);
 524                         fCurrentEntity.ch = tmp;
 525                     }
 526                     else {
 527                         System.arraycopy(fCurrentEntity.ch, offset,
 528                                          fCurrentEntity.ch, 0, length);
 529                     }
 530                     offset = 0;
 531                     if (load(length, false, false)) {
 532                         break;
 533                     }
 534                 }
 535             }
 536             else if (XML11Char.isXML11NameHighSurrogate(ch)) {
 537                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 538                     int length = fCurrentEntity.position - offset;
 539                     invokeListeners(length);
 540                     if (length == fCurrentEntity.ch.length) {
 541                         // bad luck we have to resize our buffer
 542                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 543                         System.arraycopy(fCurrentEntity.ch, offset,
 544                                          tmp, 0, length);
 545                         fCurrentEntity.ch = tmp;
 546                     }
 547                     else {
 548                         System.arraycopy(fCurrentEntity.ch, offset,
 549                                          fCurrentEntity.ch, 0, length);
 550                     }
 551                     offset = 0;
 552                     if (load(length, false, false)) {
 553                         --fCurrentEntity.startPosition;
 554                         --fCurrentEntity.position;
 555                         break;
 556                     }
 557                 }
 558                 char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
 559                 if ( !XMLChar.isLowSurrogate(ch2) ||
 560                      !XML11Char.isXML11NCName(XMLChar.supplemental(ch, ch2)) ) {
 561                     --fCurrentEntity.position;
 562                     break;
 563                 }
 564                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 565                     int length = fCurrentEntity.position - offset;
 566                     invokeListeners(length);
 567                     if (length == fCurrentEntity.ch.length) {
 568                         // bad luck we have to resize our buffer
 569                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 570                         System.arraycopy(fCurrentEntity.ch, offset,
 571                                          tmp, 0, length);
 572                         fCurrentEntity.ch = tmp;
 573                     }
 574                     else {
 575                         System.arraycopy(fCurrentEntity.ch, offset,
 576                                          fCurrentEntity.ch, 0, length);
 577                     }
 578                     offset = 0;
 579                     if (load(length, false, false)) {
 580                         break;
 581                     }
 582                 }
 583             }
 584             else {
 585                 break;
 586             }
 587         }
 588         while (true);
 589 
 590         int length = fCurrentEntity.position - offset;
 591         fCurrentEntity.columnNumber += length;
 592 
 593         // return name
 594         String symbol = null;
 595         if (length > 0) {
 596             symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
 597         }
 598         return symbol;
 599 
 600     } // scanNCName():String
 601 
 602     /**
 603      * Scans a qualified name from the input, setting the fields of the
 604      * QName structure appropriately.
 605      * <p>
 606      * <strong>Note:</strong> The qualified name characters are consumed.
 607      * <p>
 608      * <strong>Note:</strong> The strings used to set the values of the
 609      * QName structure must be symbols. The SymbolTable can be used for
 610      * this purpose.
 611      *
 612      * @param qname The qualified name structure to fill.
 613      *
 614      * @return Returns true if a qualified name appeared immediately on
 615      *         the input and was scanned, false otherwise.
 616      *
 617      * @throws IOException  Thrown if i/o error occurs.
 618      * @throws EOFException Thrown on end of file.
 619      *
 620      * @see com.sun.org.apache.xerces.internal.util.SymbolTable
 621      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11Name
 622      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11NameStart
 623      */
 624     public boolean scanQName(QName qname) throws IOException {
 625 
 626         // load more characters, if needed
 627         if (fCurrentEntity.position == fCurrentEntity.count) {
 628             load(0, true, true);
 629         }
 630 
 631         // scan qualified name
 632         int offset = fCurrentEntity.position;
 633         char ch = fCurrentEntity.ch[offset];
 634 
 635         if (XML11Char.isXML11NCNameStart(ch)) {
 636             if (++fCurrentEntity.position == fCurrentEntity.count) {
 637                 invokeListeners(1);
 638                 fCurrentEntity.ch[0] = ch;
 639                 offset = 0;
 640                 if (load(1, false, false)) {
 641                     fCurrentEntity.columnNumber++;
 642                     String name = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
 643                     qname.setValues(null, name, name, null);
 644                     return true;
 645                 }
 646             }
 647         }
 648         else if (XML11Char.isXML11NameHighSurrogate(ch)) {
 649             if (++fCurrentEntity.position == fCurrentEntity.count) {
 650                 invokeListeners(1);
 651                 fCurrentEntity.ch[0] = ch;
 652                 offset = 0;
 653                 if (load(1, false, false)) {
 654                     --fCurrentEntity.startPosition;
 655                     --fCurrentEntity.position;
 656                     return false;
 657                 }
 658             }
 659             char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
 660             if ( !XMLChar.isLowSurrogate(ch2) ||
 661                  !XML11Char.isXML11NCNameStart(XMLChar.supplemental(ch, ch2)) ) {
 662                 --fCurrentEntity.position;
 663                 return false;
 664             }
 665             if (++fCurrentEntity.position == fCurrentEntity.count) {
 666                 invokeListeners(2);
 667                 fCurrentEntity.ch[0] = ch;
 668                 fCurrentEntity.ch[1] = ch2;
 669                 offset = 0;
 670                 if (load(2, false, false)) {
 671                     fCurrentEntity.columnNumber += 2;
 672                     String name = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 2);
 673                     qname.setValues(null, name, name, null);
 674                     return true;
 675                 }
 676             }
 677         }
 678         else {
 679             return false;
 680         }
 681 
 682         int index = -1;
 683         boolean sawIncompleteSurrogatePair = false;
 684         do {
 685             ch = fCurrentEntity.ch[fCurrentEntity.position];
 686             if (XML11Char.isXML11Name(ch)) {
 687                 if (ch == ':') {
 688                     if (index != -1) {
 689                         break;
 690                     }
 691                     index = fCurrentEntity.position;
 692                 }
 693                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 694                     int length = fCurrentEntity.position - offset;
 695                     invokeListeners(length);
 696                     if (length == fCurrentEntity.ch.length) {
 697                         // bad luck we have to resize our buffer
 698                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 699                         System.arraycopy(fCurrentEntity.ch, offset,
 700                                          tmp, 0, length);
 701                         fCurrentEntity.ch = tmp;
 702                     }
 703                     else {
 704                         System.arraycopy(fCurrentEntity.ch, offset,
 705                                          fCurrentEntity.ch, 0, length);
 706                     }
 707                     if (index != -1) {
 708                         index = index - offset;
 709                     }
 710                     offset = 0;
 711                     if (load(length, false, false)) {
 712                         break;
 713                     }
 714                 }
 715             }
 716             else if (XML11Char.isXML11NameHighSurrogate(ch)) {
 717                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 718                     int length = fCurrentEntity.position - offset;
 719                     invokeListeners(length);
 720                     if (length == fCurrentEntity.ch.length) {
 721                         // bad luck we have to resize our buffer
 722                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 723                         System.arraycopy(fCurrentEntity.ch, offset,
 724                                          tmp, 0, length);
 725                         fCurrentEntity.ch = tmp;
 726                     }
 727                     else {
 728                         System.arraycopy(fCurrentEntity.ch, offset,
 729                                          fCurrentEntity.ch, 0, length);
 730                     }
 731                     if (index != -1) {
 732                         index = index - offset;
 733                     }
 734                     offset = 0;
 735                     if (load(length, false, false)) {
 736                         sawIncompleteSurrogatePair = true;
 737                         --fCurrentEntity.startPosition;
 738                         --fCurrentEntity.position;
 739                         break;
 740                     }
 741                 }
 742                 char ch2 = fCurrentEntity.ch[fCurrentEntity.position];
 743                 if ( !XMLChar.isLowSurrogate(ch2) ||
 744                      !XML11Char.isXML11Name(XMLChar.supplemental(ch, ch2)) ) {
 745                     sawIncompleteSurrogatePair = true;
 746                     --fCurrentEntity.position;
 747                     break;
 748                 }
 749                 if (++fCurrentEntity.position == fCurrentEntity.count) {
 750                     int length = fCurrentEntity.position - offset;
 751                     invokeListeners(length);
 752                     if (length == fCurrentEntity.ch.length) {
 753                         // bad luck we have to resize our buffer
 754                         char[] tmp = new char[fCurrentEntity.ch.length << 1];
 755                         System.arraycopy(fCurrentEntity.ch, offset,
 756                                          tmp, 0, length);
 757                         fCurrentEntity.ch = tmp;
 758                     }
 759                     else {
 760                         System.arraycopy(fCurrentEntity.ch, offset,
 761                                          fCurrentEntity.ch, 0, length);
 762                     }
 763                     if (index != -1) {
 764                         index = index - offset;
 765                     }
 766                     offset = 0;
 767                     if (load(length, false, false)) {
 768                         break;
 769                     }
 770                 }
 771             }
 772             else {
 773                 break;
 774             }
 775         }
 776         while (true);
 777 
 778         int length = fCurrentEntity.position - offset;
 779         fCurrentEntity.columnNumber += length;
 780 
 781         if (length > 0) {
 782             String prefix = null;
 783             String localpart = null;
 784             String rawname = fSymbolTable.addSymbol(fCurrentEntity.ch,
 785                                                     offset, length);
 786             if (index != -1) {
 787                 int prefixLength = index - offset;
 788                 prefix = fSymbolTable.addSymbol(fCurrentEntity.ch,
 789                                                     offset, prefixLength);
 790                 int len = length - prefixLength - 1;
 791                 int startLocal = index +1;
 792                 if (!XML11Char.isXML11NCNameStart(fCurrentEntity.ch[startLocal]) &&
 793                     (!XML11Char.isXML11NameHighSurrogate(fCurrentEntity.ch[startLocal]) ||
 794                     sawIncompleteSurrogatePair)){
 795                     fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
 796                                                "IllegalQName",
 797                                                null,
 798                                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
 799                 }
 800                 localpart = fSymbolTable.addSymbol(fCurrentEntity.ch,
 801                                                    index + 1, len);
 802 
 803             }
 804             else {
 805                 localpart = rawname;
 806             }
 807             qname.setValues(prefix, localpart, rawname, null);
 808             return true;
 809         }
 810         return false;
 811 
 812     } // scanQName(QName):boolean
 813 
 814     /**
 815      * Scans a range of parsed character data, setting the fields of the
 816      * XMLString structure, appropriately.
 817      * <p>
 818      * <strong>Note:</strong> The characters are consumed.
 819      * <p>
 820      * <strong>Note:</strong> This method does not guarantee to return
 821      * the longest run of parsed character data. This method may return
 822      * before markup due to reaching the end of the input buffer or any
 823      * other reason.
 824      * <p>
 825      * <strong>Note:</strong> The fields contained in the XMLString
 826      * structure are not guaranteed to remain valid upon subsequent calls
 827      * to the entity scanner. Therefore, the caller is responsible for
 828      * immediately using the returned character data or making a copy of
 829      * the character data.
 830      *
 831      * @param content The content structure to fill.
 832      *
 833      * @return Returns the next character on the input, if known. This
 834      *         value may be -1 but this does <em>note</em> designate
 835      *         end of file.
 836      *
 837      * @throws IOException  Thrown if i/o error occurs.
 838      * @throws EOFException Thrown on end of file.
 839      */
 840     public int scanContent(XMLString content) throws IOException {
 841 
 842         // load more characters, if needed
 843         if (fCurrentEntity.position == fCurrentEntity.count) {
 844             load(0, true, true);
 845         }
 846         else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
 847             invokeListeners(0);
 848             fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
 849             load(1, false, false);
 850             fCurrentEntity.position = 0;
 851             fCurrentEntity.startPosition = 0;
 852         }
 853 
 854         // normalize newlines
 855         int offset = fCurrentEntity.position;
 856         int c = fCurrentEntity.ch[offset];
 857         int newlines = 0;
 858         boolean external = fCurrentEntity.isExternal();
 859         if (c == '\n' || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) {
 860             do {
 861                 c = fCurrentEntity.ch[fCurrentEntity.position++];
 862                 if ((c == '\r' ) && external) {
 863                     newlines++;
 864                     fCurrentEntity.lineNumber++;
 865                     fCurrentEntity.columnNumber = 1;
 866                     if (fCurrentEntity.position == fCurrentEntity.count) {
 867                         offset = 0;
 868                         fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
 869                         fCurrentEntity.position = newlines;
 870                         fCurrentEntity.startPosition = newlines;
 871                         if (load(newlines, false, true)) {
 872                             break;
 873                         }
 874                     }
 875                     int cc = fCurrentEntity.ch[fCurrentEntity.position];
 876                     if (cc == '\n' || cc == 0x85) {
 877                         fCurrentEntity.position++;
 878                         offset++;
 879                     }
 880                     /*** NEWLINE NORMALIZATION ***/
 881                     else {
 882                         newlines++;
 883                     }
 884                 }
 885                 else if (c == '\n' || ((c == 0x85 || c == 0x2028) && external)) {
 886                     newlines++;
 887                     fCurrentEntity.lineNumber++;
 888                     fCurrentEntity.columnNumber = 1;
 889                     if (fCurrentEntity.position == fCurrentEntity.count) {
 890                         offset = 0;
 891                         fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
 892                         fCurrentEntity.position = newlines;
 893                         fCurrentEntity.startPosition = newlines;
 894                         if (load(newlines, false, true)) {
 895                             break;
 896                         }
 897                     }
 898                 }
 899                 else {
 900                     fCurrentEntity.position--;
 901                     break;
 902                 }
 903             } while (fCurrentEntity.position < fCurrentEntity.count - 1);
 904             for (int i = offset; i < fCurrentEntity.position; i++) {
 905                 fCurrentEntity.ch[i] = '\n';
 906             }
 907             int length = fCurrentEntity.position - offset;
 908             if (fCurrentEntity.position == fCurrentEntity.count - 1) {
 909                 content.setValues(fCurrentEntity.ch, offset, length);
 910                 return -1;
 911             }
 912         }
 913 
 914         // inner loop, scanning for content
 915         if (external) {
 916             while (fCurrentEntity.position < fCurrentEntity.count) {
 917                 c = fCurrentEntity.ch[fCurrentEntity.position++];
 918                 if (!XML11Char.isXML11Content(c) || c == 0x85 || c == 0x2028) {
 919                     fCurrentEntity.position--;
 920                     break;
 921                 }
 922             }
 923         }
 924         else {
 925             while (fCurrentEntity.position < fCurrentEntity.count) {
 926                 c = fCurrentEntity.ch[fCurrentEntity.position++];
 927                 // In internal entities control characters are allowed to appear unescaped.
 928                 if (!XML11Char.isXML11InternalEntityContent(c)) {
 929                     fCurrentEntity.position--;
 930                     break;
 931                 }
 932             }
 933         }
 934         int length = fCurrentEntity.position - offset;
 935         fCurrentEntity.columnNumber += length - newlines;
 936         content.setValues(fCurrentEntity.ch, offset, length);
 937 
 938         // return next character
 939         if (fCurrentEntity.position != fCurrentEntity.count) {
 940             c = fCurrentEntity.ch[fCurrentEntity.position];
 941             // REVISIT: Does this need to be updated to fix the
 942             //          #x0D ^#x0A newline normalization problem? -Ac
 943             if ((c == '\r' || c == 0x85 || c == 0x2028) && external) {
 944                 c = '\n';
 945             }
 946         }
 947         else {
 948             c = -1;
 949         }
 950         return c;
 951 
 952     } // scanContent(XMLString):int
 953 
 954     /**
 955      * Scans a range of attribute value data, setting the fields of the
 956      * XMLString structure, appropriately.
 957      * <p>
 958      * <strong>Note:</strong> The characters are consumed.
 959      * <p>
 960      * <strong>Note:</strong> This method does not guarantee to return
 961      * the longest run of attribute value data. This method may return
 962      * before the quote character due to reaching the end of the input
 963      * buffer or any other reason.
 964      * <p>
 965      * <strong>Note:</strong> The fields contained in the XMLString
 966      * structure are not guaranteed to remain valid upon subsequent calls
 967      * to the entity scanner. Therefore, the caller is responsible for
 968      * immediately using the returned character data or making a copy of
 969      * the character data.
 970      *
 971      * @param quote   The quote character that signifies the end of the
 972      *                attribute value data.
 973      * @param content The content structure to fill.
 974      *
 975      * @return Returns the next character on the input, if known. This
 976      *         value may be -1 but this does <em>note</em> designate
 977      *         end of file.
 978      *
 979      * @throws IOException  Thrown if i/o error occurs.
 980      * @throws EOFException Thrown on end of file.
 981      */
 982     public int scanLiteral(int quote, XMLString content)
 983         throws IOException {
 984         // load more characters, if needed
 985         if (fCurrentEntity.position == fCurrentEntity.count) {
 986             load(0, true, true);
 987         }
 988         else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
 989             invokeListeners(0);
 990             fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
 991             load(1, false, false);
 992             fCurrentEntity.startPosition = 0;
 993             fCurrentEntity.position = 0;
 994         }
 995 
 996         // normalize newlines
 997         int offset = fCurrentEntity.position;
 998         int c = fCurrentEntity.ch[offset];
 999         int newlines = 0;
1000         boolean external = fCurrentEntity.isExternal();
1001         if (c == '\n' || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) {
1002             do {
1003                 c = fCurrentEntity.ch[fCurrentEntity.position++];
1004                 if ((c == '\r' ) && external) {
1005                     newlines++;
1006                     fCurrentEntity.lineNumber++;
1007                     fCurrentEntity.columnNumber = 1;
1008                     if (fCurrentEntity.position == fCurrentEntity.count) {
1009                         offset = 0;
1010                         fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1011                         fCurrentEntity.position = newlines;
1012                         fCurrentEntity.startPosition = newlines;
1013                         if (load(newlines, false, true)) {
1014                             break;
1015                         }
1016                     }
1017                     int cc = fCurrentEntity.ch[fCurrentEntity.position];
1018                     if (cc == '\n' || cc == 0x85) {
1019                         fCurrentEntity.position++;
1020                         offset++;
1021                     }
1022                     /*** NEWLINE NORMALIZATION ***/
1023                     else {
1024                         newlines++;
1025                     }
1026                 }
1027                 else if (c == '\n' || ((c == 0x85 || c == 0x2028) && external)) {
1028                     newlines++;
1029                     fCurrentEntity.lineNumber++;
1030                     fCurrentEntity.columnNumber = 1;
1031                     if (fCurrentEntity.position == fCurrentEntity.count) {
1032                         offset = 0;
1033                         fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1034                         fCurrentEntity.position = newlines;
1035                         fCurrentEntity.startPosition = newlines;
1036                         if (load(newlines, false, true)) {
1037                             break;
1038                         }
1039                     }
1040                 }
1041                 else {
1042                     fCurrentEntity.position--;
1043                     break;
1044                 }
1045             } while (fCurrentEntity.position < fCurrentEntity.count - 1);
1046             for (int i = offset; i < fCurrentEntity.position; i++) {
1047                 fCurrentEntity.ch[i] = '\n';
1048             }
1049             int length = fCurrentEntity.position - offset;
1050             if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1051                 content.setValues(fCurrentEntity.ch, offset, length);
1052                 return -1;
1053             }
1054         }
1055 
1056         // scan literal value
1057         if (external) {
1058             while (fCurrentEntity.position < fCurrentEntity.count) {
1059                 c = fCurrentEntity.ch[fCurrentEntity.position++];
1060                 if (c == quote || c == '%' || !XML11Char.isXML11Content(c)
1061                     || c == 0x85 || c == 0x2028) {
1062                     fCurrentEntity.position--;
1063                     break;
1064                 }
1065             }
1066         }
1067         else {
1068             while (fCurrentEntity.position < fCurrentEntity.count) {
1069                 c = fCurrentEntity.ch[fCurrentEntity.position++];
1070                 // In internal entities control characters are allowed to appear unescaped.
1071                 if ((c == quote && !fCurrentEntity.literal)
1072                     || c == '%' || !XML11Char.isXML11InternalEntityContent(c)) {
1073                     fCurrentEntity.position--;
1074                     break;
1075                 }
1076             }
1077         }
1078         int length = fCurrentEntity.position - offset;
1079         fCurrentEntity.columnNumber += length - newlines;
1080         content.setValues(fCurrentEntity.ch, offset, length);
1081 
1082         // return next character
1083         if (fCurrentEntity.position != fCurrentEntity.count) {
1084             c = fCurrentEntity.ch[fCurrentEntity.position];
1085             // NOTE: We don't want to accidentally signal the
1086             //       end of the literal if we're expanding an
1087             //       entity appearing in the literal. -Ac
1088             if (c == quote && fCurrentEntity.literal) {
1089                 c = -1;
1090             }
1091         }
1092         else {
1093             c = -1;
1094         }
1095         return c;
1096 
1097     } // scanLiteral(int,XMLString):int
1098 
1099     /**
1100      * Scans a range of character data up to the specicied delimiter,
1101      * setting the fields of the XMLString structure, appropriately.
1102      * <p>
1103      * <strong>Note:</strong> The characters are consumed.
1104      * <p>
1105      * <strong>Note:</strong> This assumes that the internal buffer is
1106      * at least the same size, or bigger, than the length of the delimiter
1107      * and that the delimiter contains at least one character.
1108      * <p>
1109      * <strong>Note:</strong> This method does not guarantee to return
1110      * the longest run of character data. This method may return before
1111      * the delimiter due to reaching the end of the input buffer or any
1112      * other reason.
1113      * <p>
1114      * <strong>Note:</strong> The fields contained in the XMLString
1115      * structure are not guaranteed to remain valid upon subsequent calls
1116      * to the entity scanner. Therefore, the caller is responsible for
1117      * immediately using the returned character data or making a copy of
1118      * the character data.
1119      *
1120      * @param delimiter The string that signifies the end of the character
1121      *                  data to be scanned.
1122      * @param data      The data structure to fill.
1123      *
1124      * @return Returns true if there is more data to scan, false otherwise.
1125      *
1126      * @throws IOException  Thrown if i/o error occurs.
1127      * @throws EOFException Thrown on end of file.
1128      */
1129     public boolean scanData(String delimiter, XMLStringBuffer buffer)
1130         throws IOException {
1131 
1132         boolean done = false;
1133         int delimLen = delimiter.length();
1134         char charAt0 = delimiter.charAt(0);
1135         boolean external = fCurrentEntity.isExternal();
1136         do {
1137             // load more characters, if needed
1138             if (fCurrentEntity.position == fCurrentEntity.count) {
1139                 load(0, true, false);
1140             }
1141 
1142             boolean bNextEntity = false;
1143 
1144             while ((fCurrentEntity.position >= fCurrentEntity.count - delimLen)
1145                 && (!bNextEntity))
1146             {
1147               System.arraycopy(fCurrentEntity.ch,
1148                                fCurrentEntity.position,
1149                                fCurrentEntity.ch,
1150                                0,
1151                                fCurrentEntity.count - fCurrentEntity.position);
1152 
1153               bNextEntity = load(fCurrentEntity.count - fCurrentEntity.position, false, false);
1154               fCurrentEntity.position = 0;
1155               fCurrentEntity.startPosition = 0;
1156             }
1157 
1158             if (fCurrentEntity.position >= fCurrentEntity.count - delimLen) {
1159                 // something must be wrong with the input:  e.g., file ends  an unterminated comment
1160                 int length = fCurrentEntity.count - fCurrentEntity.position;
1161                 buffer.append (fCurrentEntity.ch, fCurrentEntity.position, length);
1162                 fCurrentEntity.columnNumber += fCurrentEntity.count;
1163                 fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1164                 fCurrentEntity.position = fCurrentEntity.count;
1165                 fCurrentEntity.startPosition = fCurrentEntity.count;
1166                 load(0,true, false);
1167                 return false;
1168             }
1169 
1170             // normalize newlines
1171             int offset = fCurrentEntity.position;
1172             int c = fCurrentEntity.ch[offset];
1173             int newlines = 0;
1174             if (c == '\n' || ((c == '\r' || c == 0x85 || c == 0x2028) && external)) {
1175                 do {
1176                     c = fCurrentEntity.ch[fCurrentEntity.position++];
1177                     if ((c == '\r' ) && external) {
1178                         newlines++;
1179                         fCurrentEntity.lineNumber++;
1180                         fCurrentEntity.columnNumber = 1;
1181                         if (fCurrentEntity.position == fCurrentEntity.count) {
1182                             offset = 0;
1183                             fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1184                             fCurrentEntity.position = newlines;
1185                             fCurrentEntity.startPosition = newlines;
1186                             if (load(newlines, false, true)) {
1187                                 break;
1188                             }
1189                         }
1190                         int cc = fCurrentEntity.ch[fCurrentEntity.position];
1191                         if (cc == '\n' || cc == 0x85) {
1192                             fCurrentEntity.position++;
1193                             offset++;
1194                         }
1195                         /*** NEWLINE NORMALIZATION ***/
1196                         else {
1197                             newlines++;
1198                         }
1199                     }
1200                     else if (c == '\n' || ((c == 0x85 || c == 0x2028) && external)) {
1201                         newlines++;
1202                         fCurrentEntity.lineNumber++;
1203                         fCurrentEntity.columnNumber = 1;
1204                         if (fCurrentEntity.position == fCurrentEntity.count) {
1205                             offset = 0;
1206                             fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1207                             fCurrentEntity.position = newlines;
1208                             fCurrentEntity.startPosition = newlines;
1209                             fCurrentEntity.count = newlines;
1210                             if (load(newlines, false, true)) {
1211                                 break;
1212                             }
1213                         }
1214                     }
1215                     else {
1216                         fCurrentEntity.position--;
1217                         break;
1218                     }
1219                 } while (fCurrentEntity.position < fCurrentEntity.count - 1);
1220                 for (int i = offset; i < fCurrentEntity.position; i++) {
1221                     fCurrentEntity.ch[i] = '\n';
1222                 }
1223                 int length = fCurrentEntity.position - offset;
1224                 if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1225                     buffer.append(fCurrentEntity.ch, offset, length);
1226                     return true;
1227                 }
1228             }
1229 
1230             // iterate over buffer looking for delimiter
1231             if (external) {
1232                 OUTER: while (fCurrentEntity.position < fCurrentEntity.count) {
1233                     c = fCurrentEntity.ch[fCurrentEntity.position++];
1234                     if (c == charAt0) {
1235                         // looks like we just hit the delimiter
1236                         int delimOffset = fCurrentEntity.position - 1;
1237                         for (int i = 1; i < delimLen; i++) {
1238                             if (fCurrentEntity.position == fCurrentEntity.count) {
1239                                 fCurrentEntity.position -= i;
1240                                 break OUTER;
1241                             }
1242                             c = fCurrentEntity.ch[fCurrentEntity.position++];
1243                             if (delimiter.charAt(i) != c) {
1244                                 fCurrentEntity.position--;
1245                                 break;
1246                             }
1247                          }
1248                          if (fCurrentEntity.position == delimOffset + delimLen) {
1249                             done = true;
1250                             break;
1251                          }
1252                     }
1253                     else if (c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) {
1254                         fCurrentEntity.position--;
1255                         break;
1256                     }
1257                     // In external entities control characters cannot appear
1258                     // as literals so do not skip over them.
1259                     else if (!XML11Char.isXML11ValidLiteral(c)) {
1260                         fCurrentEntity.position--;
1261                         int length = fCurrentEntity.position - offset;
1262                         fCurrentEntity.columnNumber += length - newlines;
1263                         buffer.append(fCurrentEntity.ch, offset, length);
1264                         return true;
1265                     }
1266                 }
1267             }
1268             else {
1269                 OUTER: while (fCurrentEntity.position < fCurrentEntity.count) {
1270                     c = fCurrentEntity.ch[fCurrentEntity.position++];
1271                     if (c == charAt0) {
1272                         // looks like we just hit the delimiter
1273                         int delimOffset = fCurrentEntity.position - 1;
1274                         for (int i = 1; i < delimLen; i++) {
1275                             if (fCurrentEntity.position == fCurrentEntity.count) {
1276                                 fCurrentEntity.position -= i;
1277                                 break OUTER;
1278                             }
1279                             c = fCurrentEntity.ch[fCurrentEntity.position++];
1280                             if (delimiter.charAt(i) != c) {
1281                                 fCurrentEntity.position--;
1282                                 break;
1283                             }
1284                         }
1285                         if (fCurrentEntity.position == delimOffset + delimLen) {
1286                             done = true;
1287                             break;
1288                         }
1289                     }
1290                     else if (c == '\n') {
1291                         fCurrentEntity.position--;
1292                         break;
1293                     }
1294                     // Control characters are allowed to appear as literals
1295                     // in internal entities.
1296                     else if (!XML11Char.isXML11Valid(c)) {
1297                         fCurrentEntity.position--;
1298                         int length = fCurrentEntity.position - offset;
1299                         fCurrentEntity.columnNumber += length - newlines;
1300                         buffer.append(fCurrentEntity.ch, offset, length);
1301                         return true;
1302                     }
1303                 }
1304             }
1305             int length = fCurrentEntity.position - offset;
1306             fCurrentEntity.columnNumber += length - newlines;
1307             if (done) {
1308                 length -= delimLen;
1309             }
1310             buffer.append(fCurrentEntity.ch, offset, length);
1311 
1312             // return true if string was skipped
1313         } while (!done);
1314         return !done;
1315 
1316     } // scanData(String,XMLString)
1317 
1318     /**
1319      * Skips a character appearing immediately on the input.
1320      * <p>
1321      * <strong>Note:</strong> The character is consumed only if it matches
1322      * the specified character.
1323      *
1324      * @param c The character to skip.
1325      *
1326      * @return Returns true if the character was skipped.
1327      *
1328      * @throws IOException  Thrown if i/o error occurs.
1329      * @throws EOFException Thrown on end of file.
1330      */
1331     public boolean skipChar(int c) throws IOException {
1332 
1333         // load more characters, if needed
1334         if (fCurrentEntity.position == fCurrentEntity.count) {
1335             load(0, true, true);
1336         }
1337 
1338         // skip character
1339         int cc = fCurrentEntity.ch[fCurrentEntity.position];
1340         if (cc == c) {
1341             fCurrentEntity.position++;
1342             if (c == '\n') {
1343                 fCurrentEntity.lineNumber++;
1344                 fCurrentEntity.columnNumber = 1;
1345             }
1346             else {
1347                 fCurrentEntity.columnNumber++;
1348             }
1349             return true;
1350         }
1351         else if (c == '\n' && ((cc == 0x2028 || cc == 0x85) && fCurrentEntity.isExternal())) {
1352             fCurrentEntity.position++;
1353             fCurrentEntity.lineNumber++;
1354             fCurrentEntity.columnNumber = 1;
1355             return true;
1356         }
1357         else if (c == '\n' && (cc == '\r' ) && fCurrentEntity.isExternal()) {
1358             // handle newlines
1359             if (fCurrentEntity.position == fCurrentEntity.count) {
1360                 invokeListeners(1);
1361                 fCurrentEntity.ch[0] = (char)cc;
1362                 load(1, false, false);
1363             }
1364             int ccc = fCurrentEntity.ch[++fCurrentEntity.position];
1365             if (ccc == '\n' || ccc == 0x85) {
1366                 fCurrentEntity.position++;
1367             }
1368             fCurrentEntity.lineNumber++;
1369             fCurrentEntity.columnNumber = 1;
1370             return true;
1371         }
1372 
1373         // character was not skipped
1374         return false;
1375 
1376     } // skipChar(int):boolean
1377 
1378     /**
1379      * Skips space characters appearing immediately on the input.
1380      * <p>
1381      * <strong>Note:</strong> The characters are consumed only if they are
1382      * space characters.
1383      *
1384      * @return Returns true if at least one space character was skipped.
1385      *
1386      * @throws IOException  Thrown if i/o error occurs.
1387      * @throws EOFException Thrown on end of file.
1388      *
1389      * @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace
1390      * @see com.sun.org.apache.xerces.internal.util.XML11Char#isXML11Space
1391      */
1392     public boolean skipSpaces() throws IOException {
1393 
1394         // load more characters, if needed
1395         if (fCurrentEntity.position == fCurrentEntity.count) {
1396             load(0, true, true);
1397         }
1398 
1399 
1400         //we are doing this check only in skipSpace() because it is called by
1401         //fMiscDispatcher and we want the parser to exit gracefully when document
1402         //is well-formed.
1403         //it is possible that end of document is reached and
1404         //fCurrentEntity becomes null
1405         //nothing was read so entity changed  'false' should be returned.
1406         if(fCurrentEntity == null){
1407             return false ;
1408         }
1409 
1410         // skip spaces
1411         int c = fCurrentEntity.ch[fCurrentEntity.position];
1412 
1413         // External --  Match: S + 0x85 + 0x2028, and perform end of line normalization
1414         if (fCurrentEntity.isExternal()) {
1415             if (XML11Char.isXML11Space(c)) {
1416                 do {
1417                     boolean entityChanged = false;
1418                     // handle newlines
1419                     if (c == '\n' || c == '\r' || c == 0x85 || c == 0x2028) {
1420                         fCurrentEntity.lineNumber++;
1421                         fCurrentEntity.columnNumber = 1;
1422                         if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1423                             invokeListeners(0);
1424                             fCurrentEntity.ch[0] = (char)c;
1425                             entityChanged = load(1, true, false);
1426                             if (!entityChanged) {
1427                                 // the load change the position to be 1,
1428                                 // need to restore it when entity not changed
1429                                 fCurrentEntity.startPosition = 0;
1430                                 fCurrentEntity.position = 0;
1431                             } else if(fCurrentEntity == null){
1432                                 return true ;
1433                             }
1434 
1435                         }
1436                         if (c == '\r') {
1437                             // REVISIT: Does this need to be updated to fix the
1438                             //          #x0D ^#x0A newline normalization problem? -Ac
1439                             int cc = fCurrentEntity.ch[++fCurrentEntity.position];
1440                             if (cc != '\n' && cc != 0x85 ) {
1441                                 fCurrentEntity.position--;
1442                             }
1443                         }
1444                     }
1445                     else {
1446                         fCurrentEntity.columnNumber++;
1447                     }
1448                     // load more characters, if needed
1449                     if (!entityChanged)
1450                         fCurrentEntity.position++;
1451                     if (fCurrentEntity.position == fCurrentEntity.count) {
1452                         load(0, true, true);
1453 
1454                         if(fCurrentEntity == null){
1455                         return true ;
1456                         }
1457 
1458                     }
1459                 } while (XML11Char.isXML11Space(c = fCurrentEntity.ch[fCurrentEntity.position]));
1460                 return true;
1461             }
1462         }
1463         // Internal -- Match: S (only)
1464         else if (XMLChar.isSpace(c)) {
1465             do {
1466                 boolean entityChanged = false;
1467                 // handle newlines
1468                 if (c == '\n') {
1469                     fCurrentEntity.lineNumber++;
1470                     fCurrentEntity.columnNumber = 1;
1471                     if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1472                         fCurrentEntity.ch[0] = (char)c;
1473                         entityChanged = load(1, true, true);
1474                         if (!entityChanged) {
1475                             // the load change the position to be 1,
1476                             // need to restore it when entity not changed
1477                             fCurrentEntity.startPosition = 0;
1478                             fCurrentEntity.position = 0;
1479                         } else if(fCurrentEntity == null){
1480                         return true ;
1481                         }
1482                     }
1483                 }
1484                 else {
1485                     fCurrentEntity.columnNumber++;
1486                 }
1487                 // load more characters, if needed
1488                 if (!entityChanged)
1489                     fCurrentEntity.position++;
1490                 if (fCurrentEntity.position == fCurrentEntity.count) {
1491                     load(0, true, true);
1492 
1493                     if(fCurrentEntity == null){
1494                         return true ;
1495                     }
1496 
1497                 }
1498             } while (XMLChar.isSpace(c = fCurrentEntity.ch[fCurrentEntity.position]));
1499             return true;
1500         }
1501 
1502         // no spaces were found
1503         return false;
1504 
1505     } // skipSpaces():boolean
1506 
1507     /**
1508      * Skips the specified string appearing immediately on the input.
1509      * <p>
1510      * <strong>Note:</strong> The characters are consumed only if they are
1511      * space characters.
1512      *
1513      * @param s The string to skip.
1514      *
1515      * @return Returns true if the string was skipped.
1516      *
1517      * @throws IOException  Thrown if i/o error occurs.
1518      * @throws EOFException Thrown on end of file.
1519      */
1520     public boolean skipString(String s) throws IOException {
1521 
1522         // load more characters, if needed
1523         if (fCurrentEntity.position == fCurrentEntity.count) {
1524             load(0, true, true);
1525         }
1526 
1527         // skip string
1528         final int length = s.length();
1529         for (int i = 0; i < length; i++) {
1530             char c = fCurrentEntity.ch[fCurrentEntity.position++];
1531             if (c != s.charAt(i)) {
1532                 fCurrentEntity.position -= i + 1;
1533                 return false;
1534             }
1535             if (i < length - 1 && fCurrentEntity.position == fCurrentEntity.count) {
1536                 invokeListeners(0);
1537                 System.arraycopy(fCurrentEntity.ch, fCurrentEntity.count - i - 1, fCurrentEntity.ch, 0, i + 1);
1538                 // REVISIT: Can a string to be skipped cross an
1539                 //          entity boundary? -Ac
1540                 if (load(i + 1, false, false)) {
1541                     fCurrentEntity.startPosition -= i + 1;
1542                     fCurrentEntity.position -= i + 1;
1543                     return false;
1544                 }
1545             }
1546         }
1547         fCurrentEntity.columnNumber += length;
1548         return true;
1549 
1550     } // skipString(String):boolean
1551 
1552 } // class XML11EntityScanner