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