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