6 /** This class supports the FITS heap. This
7 * is currently used for variable length columns
10 public class FitsHeap implements FitsElement {
12 /** The storage buffer */
14 /** The current used size of the buffer <= heap.length */
16 /** The offset within a file where the heap begins */
17 private long fileOffset = -1;
18 /** Has the heap ever been expanded? */
19 private boolean expanded = false;
20 /** The stream the last read used */
21 private ArrayDataInput input;
22 /** Our current offset into the heap. When we read from
23 * the heap we use a byte array input stream. So long
24 * as we continue to read further into the heap, we can
25 * continue to use the same stream, but we need to
26 * recreate the stream whenever we skip backwards.
28 private int heapOffset = 0;
29 /** A stream used to read the heap data */
30 private BufferedDataInputStream bstr;
32 /** Create a heap of a given size. */
34 heap = new byte[size];
39 public void read(ArrayDataInput str) throws FitsException {
41 if (str instanceof RandomAccess) {
42 fileOffset = FitsUtil.findOffset(str);
48 str.read(heap, 0, heapSize);
49 } catch (IOException e) {
50 throw new FitsException("Error reading heap:" + e);
58 public void write(ArrayDataOutput str) throws FitsException {
60 str.write(heap, 0, heapSize);
61 } catch (IOException e) {
62 throw new FitsException("Error writing heap:" + e);
66 public boolean rewriteable() {
67 return fileOffset >= 0 && input instanceof ArrayDataOutput && !expanded;
70 /** Attempt to rewrite the heap with the current contents.
71 * Note that no checking is done to make sure that the
72 * heap does not extend past its prior boundaries.
74 public void rewrite() throws IOException, FitsException {
76 ArrayDataOutput str = (ArrayDataOutput) input;
77 FitsUtil.reposition(str, fileOffset);
80 throw new FitsException("Invalid attempt to rewrite FitsHeap");
85 public boolean reset() {
87 FitsUtil.reposition(input, fileOffset);
89 } catch (Exception e) {
94 /** Get data from the heap.
95 * @param offset The offset at which the data begins.
96 * @param array The array to be extracted.
98 public void getData(int offset, Object array) throws FitsException {
101 // Can we reuse the existing byte stream?
102 if (bstr == null || heapOffset > offset) {
104 bstr = new BufferedDataInputStream(
105 new ByteArrayInputStream(heap));
108 bstr.skipBytes(offset - heapOffset);
110 heapOffset += bstr.readLArray(array);
112 } catch (IOException e) {
113 throw new FitsException("Error decoding heap area at offset=" + offset
114 + ". Exception: Exception " + e);
118 /** Check if the Heap can accommodate a given requirement.
119 * If not expand the heap.
121 void expandHeap(int need) {
123 // Invalidate any existing input stream to the heap.
126 if (heapSize + need > heap.length) {
128 int newlen = (heapSize + need) * 2;
129 if (newlen < 16384) {
132 byte[] newHeap = new byte[newlen];
133 System.arraycopy(heap, 0, newHeap, 0, heapSize);
138 /** Add some data to the heap. */
139 int putData(Object data) throws FitsException {
141 long lsize = ArrayFuncs.computeLSize(data);
142 if (lsize > Integer.MAX_VALUE) {
143 throw new FitsException("FITS Heap > 2 G");
145 int size = (int) lsize;
147 ByteArrayOutputStream bo = new ByteArrayOutputStream(size);
150 BufferedDataOutputStream o = new BufferedDataOutputStream(bo);
154 } catch (IOException e) {
155 throw new FitsException("Unable to write variable column length data");
158 System.arraycopy(bo.toByteArray(), 0, heap, heapSize, size);
159 int oldOffset = heapSize;
165 /** Return the size of the Heap */
170 /** Return the size of the heap using the more bean compatbile format */
171 public long getSize() {
175 /** Get the file offset of the heap */
176 public long getFileOffset() {