1 | /** Copyright (c) 2010 Scott A. Crosby. <scott@sacrosby.com>
|
---|
2 |
|
---|
3 | This program is free software: you can redistribute it and/or modify
|
---|
4 | it under the terms of the GNU Lesser General Public License as
|
---|
5 | published by the Free Software Foundation, either version 3 of the
|
---|
6 | License, or (at your option) any later version.
|
---|
7 |
|
---|
8 | This program is distributed in the hope that it will be useful,
|
---|
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
11 | GNU General Public License for more details.
|
---|
12 |
|
---|
13 | You should have received a copy of the GNU General Public License
|
---|
14 | along with this program. If not, see <http://www.gnu.org/licenses/>.
|
---|
15 |
|
---|
16 | */
|
---|
17 |
|
---|
18 | package crosby.binary.file;
|
---|
19 |
|
---|
20 | import java.io.DataInputStream;
|
---|
21 | import java.io.FileInputStream;
|
---|
22 | import java.io.IOException;
|
---|
23 | import java.io.InputStream;
|
---|
24 | import java.util.zip.DataFormatException;
|
---|
25 | import java.util.zip.Inflater;
|
---|
26 |
|
---|
27 | import com.google.protobuf.ByteString;
|
---|
28 | import com.google.protobuf.InvalidProtocolBufferException;
|
---|
29 |
|
---|
30 | import crosby.binary.Fileformat;
|
---|
31 |
|
---|
32 | /**
|
---|
33 | * Stores the position in the stream of a fileblock so that it can be easily
|
---|
34 | * read in a random-access fashion.
|
---|
35 | *
|
---|
36 | * We can turn this into a 'real' block by appropriately seeking into the file
|
---|
37 | * and doing a 'read'.
|
---|
38 | *
|
---|
39 | * */
|
---|
40 | public class FileBlockPosition extends FileBlockBase {
|
---|
41 | protected FileBlockPosition(String type, ByteString indexdata) {
|
---|
42 | super(type, indexdata);
|
---|
43 | }
|
---|
44 |
|
---|
45 | /** Parse out and decompress the data part of a fileblock helper function. */
|
---|
46 | FileBlock parseData(byte buf[]) throws InvalidProtocolBufferException {
|
---|
47 | FileBlock out = FileBlock.newInstance(type, null, indexdata);
|
---|
48 | Fileformat.Blob blob = Fileformat.Blob.parseFrom(buf);
|
---|
49 | if (blob.hasRaw()) {
|
---|
50 | out.data = blob.getRaw();
|
---|
51 | } else if (blob.hasZlibData()) {
|
---|
52 | byte buf2[] = new byte[blob.getRawSize()];
|
---|
53 | Inflater decompresser = new Inflater();
|
---|
54 | decompresser.setInput(blob.getZlibData().toByteArray());
|
---|
55 | // decompresser.getRemaining();
|
---|
56 | try {
|
---|
57 | decompresser.inflate(buf2);
|
---|
58 | } catch (DataFormatException e) {
|
---|
59 | e.printStackTrace();
|
---|
60 | throw new Error(e);
|
---|
61 | }
|
---|
62 | assert (decompresser.finished());
|
---|
63 | decompresser.end();
|
---|
64 | out.data = ByteString.copyFrom(buf2);
|
---|
65 | }
|
---|
66 | return out;
|
---|
67 | }
|
---|
68 |
|
---|
69 | public int getDatasize() {
|
---|
70 | return datasize;
|
---|
71 | }
|
---|
72 |
|
---|
73 | /*
|
---|
74 | * Given any form of fileblock and an offset/length value, return a
|
---|
75 | * reference that can be used to dereference and read the contents.
|
---|
76 | */
|
---|
77 | static FileBlockPosition newInstance(FileBlockBase base, long offset,
|
---|
78 | int length) {
|
---|
79 | FileBlockPosition out = new FileBlockPosition(base.type, base.indexdata);
|
---|
80 | out.datasize = length;
|
---|
81 | out.data_offset = offset;
|
---|
82 | return out;
|
---|
83 | }
|
---|
84 |
|
---|
85 | public FileBlock read(InputStream input) throws IOException {
|
---|
86 | if (input instanceof FileInputStream) {
|
---|
87 | ((FileInputStream) input).getChannel().position(data_offset);
|
---|
88 | byte buf[] = new byte[getDatasize()];
|
---|
89 | (new DataInputStream(input)).readFully(buf);
|
---|
90 | return parseData(buf);
|
---|
91 | } else {
|
---|
92 | throw new Error("Random access binary reads require seekability");
|
---|
93 | }
|
---|
94 | }
|
---|
95 |
|
---|
96 | /**
|
---|
97 | * TODO: Convert this reference into a serialized representation that can be
|
---|
98 | * stored.
|
---|
99 | */
|
---|
100 | public ByteString serialize() {
|
---|
101 | throw new Error("TODO");
|
---|
102 | }
|
---|
103 |
|
---|
104 | /** TODO: Parse a serialized representation of this block reference */
|
---|
105 | static FileBlockPosition parseFrom(ByteString b) {
|
---|
106 | throw new Error("TODO");
|
---|
107 | }
|
---|
108 |
|
---|
109 | protected int datasize;
|
---|
110 | /** Offset into the file of the data part of the block */
|
---|
111 | long data_offset;
|
---|
112 | }
|
---|