001: /*
002: * @(#)AbstractLineReader.java 1.2 04/12/06
003: *
004: * Copyright (c) 2002-2004 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package org.pnuts.text;
010:
011: import java.io.*;
012:
013: /**
014: * Abstract base class of LineReader.
015: */
016: public abstract class AbstractLineReader implements LineProcessor {
017:
018: protected static int defaultCharBufferSize = 8192;
019:
020: protected char[] cb;
021: protected int size;
022: protected int startChar;
023:
024: protected boolean stopped = false;
025:
026: /**
027: * Constructor
028: *
029: * @param sz Input-buffer size
030: * @exception IllegalArgumentException If sz is <= 0
031: */
032: protected AbstractLineReader(int sz) {
033: if (sz <= 0) {
034: throw new IllegalArgumentException();
035: }
036: this .cb = new char[sz];
037: }
038:
039: /**
040: * Constructor
041: */
042: protected AbstractLineReader() {
043: this (defaultCharBufferSize);
044: }
045:
046: /*
047: * Defines how to fetch data
048: */
049: protected abstract int fill(char[] c, int offset, int size)
050: throws IOException;
051:
052: /*
053: * Defines how to process a line
054: */
055: protected void process(char[] c, int offset, int length) {
056: }
057:
058: boolean fillBuffer() throws IOException {
059: int n = 0;
060: int offset = size - startChar;
061: if (offset < 0) {
062: return false;
063: }
064: do {
065: if (startChar > 0 && startChar < cb.length) {
066: System.arraycopy(cb, startChar, cb, 0, offset);
067: } else if (offset == cb.length) {
068: char[] newarray = new char[cb.length * 2];
069: System.arraycopy(cb, startChar, newarray, 0, offset);
070: cb = newarray;
071: }
072: n = fill(cb, offset, cb.length - offset);
073: } while (n == 0);
074: if (n > 0) {
075: this .size = n + offset;
076: }
077: return n > 0;
078: }
079:
080: /**
081: * Reads one line.
082: */
083: public synchronized boolean processLine(boolean includeNewLine)
084: throws IOException {
085:
086: int n = 0;
087: int startChar = this .startChar;
088:
089: if (this .size < 1) {
090: fillBuffer();
091: }
092:
093: for (;;) {
094: boolean eol = false;
095: boolean cr = false;
096: char c = 0;
097: int i, e;
098: int size = this .size;
099:
100: for (i = e = startChar + n; i < size;) {
101: c = cb[i++];
102: n++;
103: if (c == '\n') {
104: eol = true;
105: if (includeNewLine) {
106: e++;
107: }
108: break;
109: } else if (c == '\r') {
110: eol = true;
111: if (cr) {
112: n--;
113: break;
114: }
115: if (includeNewLine) {
116: e++;
117: }
118: cr = true;
119: if (i == size) {
120: if (fillBuffer()) {
121: e -= startChar;
122: this .startChar = startChar = 0;
123: size = this .size;
124: i = n;
125: } else {
126: if (i > startChar) {
127: process(cb, startChar, e - startChar);
128: }
129: return false;
130: }
131: }
132: } else {
133: if (cr) {
134: n--;
135: break;
136: } else {
137: e++;
138: }
139: cr = false;
140: }
141: }
142: if (eol) {
143: if (e >= startChar) {
144: process(cb, startChar, e - startChar);
145: }
146: this .startChar += n;
147: return true;
148: }
149: if (fillBuffer()) {
150: e -= startChar;
151: this .startChar = startChar = 0;
152: size = this .size;
153: i = n;
154: } else {
155: if (e > startChar) {
156: process(cb, startChar, e - startChar);
157: }
158: return false;
159: }
160: }
161: }
162:
163: /**
164: * If this method is called during the processAll() call, the processing
165: * will be interrupted.
166: */
167: public void stop() {
168: stopped = true;
169: }
170:
171: /**
172: * Process all lines.
173: * The line string does not include the newline character at the end of lines.
174: *
175: * @return the number of lines processed
176: */
177: public int processAll() throws IOException {
178: return processAll(false);
179: }
180:
181: /**
182: * Process all lines.
183: *
184: * @param includeNewLine if true newline code (\r|\n|\r\n) is appended.
185: * @return the number of lines processed
186: */
187: public int processAll(boolean includeNewLine) throws IOException {
188: int count = 0;
189: while (!stopped && processLine(includeNewLine)) {
190: count++;
191: }
192: return count;
193: }
194: }
|