001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.regexp;
019:
020: import java.io.Reader;
021: import java.io.IOException;
022:
023: /**
024: * Encapsulates java.io.Reader as CharacterIterator
025: *
026: * @author <a href="mailto:ales.novak@netbeans.com">Ales Novak</a>
027: * @version CVS $Id: ReaderCharacterIterator.java 518156 2007-03-14 14:31:26Z vgritsenko $
028: */
029: public final class ReaderCharacterIterator implements CharacterIterator {
030: /** Underlying reader */
031: private final Reader reader;
032:
033: /** Buffer of read chars */
034: private final StringBuffer buff;
035:
036: /** read end? */
037: private boolean closed;
038:
039: /** @param reader a Reader, which is parsed */
040: public ReaderCharacterIterator(Reader reader) {
041: this .reader = reader;
042: this .buff = new StringBuffer(512);
043: this .closed = false;
044: }
045:
046: /** @return a substring */
047: public String substring(int beginIndex, int endIndex) {
048: try {
049: ensure(endIndex);
050: return buff.toString().substring(beginIndex, endIndex);
051: } catch (IOException e) {
052: throw new StringIndexOutOfBoundsException(e.getMessage());
053: }
054: }
055:
056: /** @return a substring */
057: public String substring(int beginIndex) {
058: try {
059: readAll();
060: return buff.toString().substring(beginIndex);
061: } catch (IOException e) {
062: throw new StringIndexOutOfBoundsException(e.getMessage());
063: }
064: }
065:
066: /** @return a character at the specified position. */
067: public char charAt(int pos) {
068: try {
069: ensure(pos);
070: return buff.charAt(pos);
071: } catch (IOException e) {
072: throw new StringIndexOutOfBoundsException(e.getMessage());
073: }
074: }
075:
076: /** @return <tt>true</tt> iff if the specified index is after the end of the character stream */
077: public boolean isEnd(int pos) {
078: if (buff.length() > pos) {
079: return false;
080: } else {
081: try {
082: ensure(pos);
083: return (buff.length() <= pos);
084: } catch (IOException e) {
085: throw new StringIndexOutOfBoundsException(e
086: .getMessage());
087: }
088: }
089: }
090:
091: /** Reads n characters from the stream and appends them to the buffer */
092: private int read(int n) throws IOException {
093: if (closed) {
094: return 0;
095: }
096:
097: char[] c = new char[n];
098: int count = 0;
099: int read = 0;
100:
101: do {
102: read = reader.read(c);
103: if (read < 0) // EOF
104: {
105: closed = true;
106: break;
107: }
108: count += read;
109: buff.append(c, 0, read);
110: } while (count < n);
111:
112: return count;
113: }
114:
115: /** Reads rest of the stream. */
116: private void readAll() throws IOException {
117: while (!closed) {
118: read(1000);
119: }
120: }
121:
122: /** Reads chars up to the idx */
123: private void ensure(int idx) throws IOException {
124: if (closed) {
125: return;
126: }
127:
128: if (idx < buff.length()) {
129: return;
130: }
131: read(idx + 1 - buff.length());
132: }
133: }
|