113 lines
3.9 KiB
Java
113 lines
3.9 KiB
Java
/** Copyright (c) 2010 Scott A. Crosby. <scott@sacrosby.com>
|
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
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;
|
|
}
|