package org.cdlib.xtf.util;
/**
* Copyright (c) 2004, Regents of the University of California
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - 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.
* - Neither the name of the University of California nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR 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.
*/
import java.io.EOFException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* Reads a single sub-file within a {@link StructuredFile}. A sub-file
* provides standard DataInput/DataOutput facilities, and takes care of
* reading from the correct subset of the main StructuredFile.
*
* @author Martin Haye
*/
class SubFileReader extends SubStoreReader
{
/** Actual disk file to write to */
private RandomAccessFile file;
/** The structured file that owns this Subfile */
private StructuredFile parent;
/** Absolute file position for the subfile's start */
private long segOffset;
/** Length of this subfile */
private long segLength;
/** Current read position within the subfile */
private long curPos;
/**
* Construct a subfile reader. Reads will be constrained to the
* specified limit.
*
* @param file Disk file to attach to
* @param parent Structured file to attach to
* @param segOffset Beginning offset of the segment
* @param segLength Length of the segment
*/
SubFileReader(RandomAccessFile file, StructuredFile parent, long segOffset,
long segLength)
throws IOException
{
this.file = file;
this.parent = parent;
this.segOffset = segOffset;
this.segLength = segLength;
curPos = 0;
}
public void close()
throws IOException
{
synchronized (parent) {
parent.closeReader(this);
file = null;
}
}
public long getFilePointer()
throws IOException
{
return curPos;
}
public long length()
throws IOException
{
return segLength;
}
/**
* Ensure that the sub-file has room to read the specified number of
* bytes. As a side-effect, we also check that the main file position
* is current for this sub-file, and if not, we save the position for
* the other sub-file and restore ours.
*
* @param nBytes Amount of space desired
*/
private void checkLength(int nBytes)
throws IOException
{
synchronized (parent)
{
if (parent.curSubFile != this) {
file.seek(segOffset + curPos);
parent.curSubFile = this;
}
if (curPos + nBytes > segLength)
throw new EOFException("End of sub-file reached");
}
}
public void read(byte[] b, int off, int len)
throws IOException
{
synchronized (parent) {
checkLength(len);
file.readFully(b, off, len);
curPos += len;
}
}
public void seek(long pos)
throws IOException
{
synchronized (parent) {
if (segLength >= 0 && pos > segLength)
throw new EOFException("Cannot seek past end of subfile");
parent.curSubFile = this;
file.seek(pos + segOffset);
curPos = pos;
}
}
public byte readByte()
throws IOException
{
synchronized (parent) {
checkLength(1);
byte ret = file.readByte();
curPos++;
return ret;
}
}
public int readInt()
throws IOException
{
synchronized (parent) {
checkLength(4);
int ret = file.readInt();
curPos += 4;
return ret;
}
}
} // class Subfile