/* (c) Copyright 2007 Hewlett-Packard Development Company, LP [See end of file] $Id: JBufferedReader.java 1121 2007-04-11 15:02:58Z jeremy_carroll $ */ package com.hp.hpl.jena.grddl.impl; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.List; /** * JBufferedReader * * @author Jeremy J. Carroll */ public class JBufferedReader extends Reader { final Reader base; private List<char[]> buffers = null; private int bufSz; static private final int MAXBUF = 1024 * 1024; private int whichBuf = 0; private int where = 0; private int lastBuf; private int lastWhere; private int markedWhere; private boolean remember = false; private boolean replaying = false; private int markLimit; private int oldMarkLimit; /** * This constructor is intended for testing only. * * @param base * @param bSz * Initial value of bufSz - for testing try 1 or 2. */ public JBufferedReader(Reader base, int bSz) { this.base = base; bufSz = bSz; } public JBufferedReader(Reader base) { this(base, 256); } @Override public void close() throws IOException { forget(); base.close(); remember = false; replaying = false; where = 0; whichBuf = 0; } @Override public int read(char[] buf, int off, int len) throws IOException { int nc = read1(buf, off, len); if (replaying || remember) { where += nc; markLimit -= nc; if (markLimit < 0) { if (!replaying) forget(); remember = false; } } return nc; } public int read1(char[] buf, int off, int len) throws IOException { char currentBuf[]; if (replaying) { int endOfCopiable; currentBuf = get(); if (whichBuf < lastBuf) { endOfCopiable = currentBuf.length; } else { endOfCopiable = lastWhere; } if (where < endOfCopiable) { if (len + where < endOfCopiable) { System.arraycopy(currentBuf, where, buf, off, len); return len; } int rslt = endOfCopiable - where; System.arraycopy(currentBuf, where, buf, off, rslt); if (whichBuf == lastBuf) { replaying = false; if (!remember) { forget(); } } else { whichBuf++; where = -rslt; } return rslt; } else { // if (whichBuf != lastBuf) throw new AssertionError("Replay logic"); } // replaying = false; } if (!remember) return base.read(buf, off, len); currentBuf = get(); if (where == currentBuf.length) { whichBuf++; currentBuf = get(); where = 0; } int space = currentBuf.length - where; if (space > len) space = len; int cRead = base.read(currentBuf, where, space); if (cRead > 0) { System.arraycopy(currentBuf, where, buf, off, cRead); } return cRead; } private void forget() { buffers = null; whichBuf = 0; where = 0; remember = false; lastWhere = 0; lastBuf = 0; } private char[] get() { if (buffers == null) buffers = new ArrayList<char[]>(); if (buffers.size() > whichBuf) return buffers.get(whichBuf); char[] rslt = new char[bufSz]; if (buffers.size() != whichBuf) throw new AssertionError("buffer logic"); bufSz = bufSz + bufSz; if (bufSz > MAXBUF) bufSz = MAXBUF; buffers.add(whichBuf, rslt); return rslt; } public boolean markSupported() { return true; } public void mark(int x) { markedWhere = where; while (whichBuf > 0) { buffers.remove(0); whichBuf--; lastBuf--; } // if (where != 0 || whichBuf != 0) // throw new UnsupportedOperationException( // "mark only supported at beginning of input"); if (x <= 0) { remember = false; } else { remember = true; } markLimit = x; oldMarkLimit = markLimit; } public void reset() throws IOException { if (!remember) { throw new IOException("No valid mark currently set."); } if (!replaying) { lastWhere = where; lastBuf = whichBuf; replaying = whichBuf > 0 || where > markedWhere; } where = markedWhere; whichBuf = 0; markLimit = oldMarkLimit; } public boolean ready() throws IOException { if (!replaying) return base.ready(); if (whichBuf == lastBuf && where == lastWhere) { replaying = false; return base.ready(); } return true; } public long skip(long l) throws IOException { return super.skip(l); // TODO somewhat inefficient } } /* * (c) Copyright 2007 Hewlett-Packard Development Company, LP 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. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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. */