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