/** Copyright (c) 2010 Scott A. Crosby. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package crosby.binary.file; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; import java.util.zip.DataFormatException; import java.util.zip.Inflater; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import crosby.binary.Fileformat; /** * Stores the position in the stream of a fileblock so that it can be easily * read in a random-access fashion. * * We can turn this into a 'real' block by appropriately seeking into the file * and doing a 'read'. * * */ public class FileBlockPosition extends FileBlockBase { protected FileBlockPosition(String type, ByteString indexdata) { super(type, indexdata); } /** Parse out and decompress the data part of a fileblock helper function. */ FileBlock parseData(byte[] buf) throws InvalidProtocolBufferException { FileBlock out = FileBlock.newInstance(type, null, indexdata); Fileformat.Blob blob = Fileformat.Blob.parseFrom(buf); if (blob.hasRaw()) { out.data = blob.getRaw(); } else if (blob.hasZlibData()) { byte[] buf2 = new byte[blob.getRawSize()]; Inflater decompresser = new Inflater(); decompresser.setInput(blob.getZlibData().toByteArray()); // decompresser.getRemaining(); try { decompresser.inflate(buf2); } catch (DataFormatException e) { throw new UncheckedIOException(new FileFormatException(e)); } assert (decompresser.finished()); decompresser.end(); out.data = ByteString.copyFrom(buf2); } return out; } public int getDatasize() { return datasize; } /* * Given any form of fileblock and an offset/length value, return a * reference that can be used to dereference and read the contents. */ static FileBlockPosition newInstance(FileBlockBase base, long offset, int length) { FileBlockPosition out = new FileBlockPosition(base.type, base.indexdata); out.datasize = length; out.data_offset = offset; return out; } public FileBlock read(InputStream input) throws IOException { if (input instanceof FileInputStream) { ((FileInputStream) input).getChannel().position(data_offset); byte[] buf = new byte[getDatasize()]; (new DataInputStream(input)).readFully(buf); return parseData(buf); } else { throw new IllegalArgumentException("Random access binary reads require seekability"); } } /** * TODO: Convert this reference into a serialized representation that can be * stored. */ public ByteString serialize() { throw new UnsupportedOperationException("TODO"); } /** TODO: Parse a serialized representation of this block reference */ static FileBlockPosition parseFrom(ByteString b) { throw new UnsupportedOperationException("TODO"); } protected int datasize; /** Offset into the file of the data part of the block */ long data_offset; }