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