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