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