/**************************************************************************
* Copyright (c) 2001 by Punch Telematix. All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* 1. Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* 3. Neither the name of Punch Telematix nor the names of *
* other contributors may be used to endorse or promote products *
* derived from this software without specific prior written permission.*
* *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
* IN NO EVENT SHALL PUNCH TELEMATIX OR OTHER CONTRIBUTORS BE LIABLE *
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF *
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, *
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE *
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN *
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
**************************************************************************/
/*
** $Id: BufferedReader.java,v 1.2 2006/10/04 14:24:14 cvsroot Exp $
*/
package java.io;
public class BufferedReader extends Reader {
private Reader in;
/*
** these 5 fields have the same meaning as in the BufferedInputStream...
*/
private char buf[];
private int pos;
private int count;
private int markpos;
private int marklimit;
public BufferedReader(Reader in) {
this(in, 8192);
}
public BufferedReader(Reader in, int size) {
super(in);
if (size <= 0){
throw new IllegalArgumentException("negative buffer size");
}
this.in = in;
buf = new char[size];
markpos = -1;
}
public native int read() throws IOException;
/* [CG 200100501] Replaced by native code to help Knopfkerfish XMLReader
public int read() throws IOException {
synchronized (lock) {
if(buf == null){
throw new IOException("Reader is closed");
}
if(count <= pos && !updateBuffer()){
return -1;
}
return buf[pos++];
}
}
*/
public int read(char b[], int off, int len) throws IOException {
synchronized (lock) {
if(buf == null){
throw new IOException("Reader is closed");
}
if(off < 0 || len < 0 || off > b.length - len){
throw new IndexOutOfBoundsException();
}
int rd = 0;
while(len > 0) {
//first take the bytes out of buf
if(count > pos){
int cp = count - pos;
if(len > cp){
System.arraycopy(buf, pos, b, off, cp);
off += cp;
len -= cp;
pos += cp;
rd +=cp;
}else{
System.arraycopy(buf, pos, b, off, len);
pos += len;
break;
}
}
//we need more bytes ...
if(len > buf.length && (markpos == -1 || pos > (markpos+marklimit))){
len = in.read(b, off, len);
if(len == -1 && rd > 0){
len = 0;
}
break;
}else if (!updateBuffer()){
len = (rd == 0 ? -1 : 0);
break;
}
}
return rd + len;
}
}
private native int locateEnd(char[] chars, int startPos, int endPos);
public String readLine() throws IOException {
synchronized (lock) {
if(buf == null){
throw new IOException("Reader is closed");
}
StringBuffer line = new StringBuffer(64);
int end;
do {
end = locateEnd(buf,pos,count);
if(end != -1){
line.append(buf,pos, end - pos);
pos = end;
if(buf[pos++] == '\r'){
if ((count > pos || updateBuffer()) && buf[pos] == '\n'){
pos++;
}
}
return line.toString();
}
else {
line.append(buf,pos, count - pos);
pos = count;
}
} while(updateBuffer());
if (line.length() == 0 && end == -1){
return null;
}
return line.toString();
}
}
public long skip(long n) throws IOException {
synchronized (lock) {
if(buf == null){
throw new IOException("Reader is closed");
}
if(n < 0){
throw new IllegalArgumentException();
}
long skipped = 0;
while(n > 0){
if((n - count + pos) > 0){
//not enough bytes in the buffer
int skip = count - pos;
pos = count;
if((n - skip) > buf.length && (markpos == -1 || pos > (markpos+marklimit))){
return in.skip(n-skip)+skip;
}else if(!updateBuffer()){
break;
}
}else{
//take bytes from the buffer
pos += (int)n;
skipped += n;
break;
}
}
return skipped;
}
}
public boolean ready() throws IOException {
synchronized (lock) {
if(buf == null){
throw new IOException("Reader is closed");
}
return (count > pos || in.ready());
}
}
public boolean markSupported() {
return true;
}
public void mark(int readLimit) throws IOException {
synchronized (lock) {
if(buf == null){
throw new IOException("Reader is closed");
}
if(readLimit < 0){
throw new IllegalArgumentException();
}
marklimit = readLimit;
markpos = pos;
}
}
public void reset() throws IOException {
synchronized (lock) {
if(buf == null || markpos == -1 || (markpos+marklimit < pos)){
throw new IOException();
}
pos = markpos;
}
}
public void close() throws IOException {
synchronized (lock) {
if(buf != null){
buf = null;
in.close();
in = null;
}
}
}
private boolean updateBuffer() throws IOException{
if(markpos == -1 || pos >= (markpos + marklimit)){
int rd = in.read(buf, 0, buf.length);
pos = 0;
markpos = -1;
if (rd == -1){
count = 0;
return false;
}
else if (rd < 1) {
new Exception("OOPS - read on "+in+" returned "+rd).printStackTrace();
}
count = rd;
return true;
}else{
//a position is marked and still valid
char[] chars = buf;
if (marklimit > buf.length){
//let the buffer grow
chars = new char[marklimit];
}
int cp = count - markpos;
System.arraycopy(buf, markpos, chars, 0 ,cp);
int rd = in.read(chars, cp, chars.length - cp);
pos = cp;
markpos = 0;
buf = chars;
if (rd == -1){
count = cp;
return false;
}
else if (rd < 1) {
new Exception("OOPS - read on "+in+" returned "+rd).printStackTrace();
}
count = cp + rd;
return true;
}
}
}