1 package nom.tam.util;
2
3 /*
4 * #%L
5 * nom.tam FITS library
6 * %%
7 * Copyright (C) 1996 - 2024 nom-tam-fits
8 * %%
9 * This is free and unencumbered software released into the public domain.
10 *
11 * Anyone is free to copy, modify, publish, use, compile, sell, or
12 * distribute this software, either in source code form or as a compiled
13 * binary, for any purpose, commercial or non-commercial, and by any
14 * means.
15 *
16 * In jurisdictions that recognize copyright laws, the author or authors
17 * of this software dedicate any and all copyright interest in the
18 * software to the public domain. We make this dedication for the benefit
19 * of the public at large and to the detriment of our heirs and
20 * successors. We intend this dedication to be an overt act of
21 * relinquishment in perpetuity of all present and future rights to this
22 * software under copyright law.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
27 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
28 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
29 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30 * OTHER DEALINGS IN THE SOFTWARE.
31 * #L%
32 */
33
34 import java.io.EOFException;
35 import java.io.IOException;
36
37 /**
38 * @deprecated Use {@link FitsDecoder} instead which provides a similar function but in a more consistent way and with a
39 * less misleading name. This is a rusty rail implementation for of an older abandoned class only,
40 * unsafe for general use. For reading non-FITS encoding you may also use {@link InputDecoder} as a base
41 * for implementing efficient custom decoding of binary inputs in general.
42 *
43 * @see FitsDecoder
44 */
45 @Deprecated
46 public abstract class BufferDecoder extends FitsDecoder {
47
48 private BufferPointer p;
49
50 /**
51 * @param p Unused, but the position and length fields are set/reset as to pretend that half of the buffer is
52 * perpetually available for reading. However, at no point will there be any data actually in the
53 * buffer of this object, and you should by all means avoid directly loading data from the stream into
54 * this dead-end buffer, other than the hopefully untiggered existing implementation of
55 * <code>checkBuffer(int)</code> (and it's safest if you don't override or ever call
56 * <code>checkBuffer(int)</code> from your code!).
57 */
58 public BufferDecoder(BufferPointer p) {
59 super();
60
61 this.p = p;
62
63 pretendHalfPopulated();
64
65 setInput(new InputReader() {
66 private byte[] b1 = new byte[1];
67
68 @Override
69 public int read() throws IOException {
70 int n = BufferDecoder.this.read(b1, 0, 1);
71 if (n < 0) {
72 return n;
73 }
74 return b1[0];
75 }
76
77 @Override
78 public int read(byte[] b, int from, int length) throws IOException {
79 return BufferDecoder.this.read(b, from, length);
80 }
81 });
82 }
83
84 /**
85 * We'll always pretend the buffer to be half populated at pos=0, in order to avoid triggering a read from the input
86 * into the unused buffer of BufferPointer, or a write to the output from that buffer... If the pointer has no
87 * buffer, length will be 0 also.
88 */
89 private void pretendHalfPopulated() {
90 p.pos = 0;
91 p.length = p.buffer == null ? 0 : p.buffer.length >>> 1;
92 }
93
94 @Override
95 boolean makeAvailable(int needBytes) throws IOException {
96 pretendHalfPopulated();
97 boolean result = super.makeAvailable(needBytes);
98 return result;
99 }
100
101 /**
102 * @deprecated No longer used internally, kept only for back-compatibility since it used to be a needed
103 * abstract method. It's safest if you never override or call this method from your
104 * code!
105 *
106 * @param needBytes the number of byte we need available to decode the next element
107 *
108 * @throws IOException if the data could not be made available due to an IO error of the underlying input.
109 */
110 @Deprecated
111 protected void checkBuffer(int needBytes) throws IOException {
112 }
113
114 @Override
115 protected int read(byte[] buf, int offset, int length) throws IOException {
116 throw new UnsupportedOperationException(
117 "You need to override this with an implementation that reads from the desired input.");
118 }
119
120 /**
121 * @deprecated No longer used internally, kept only for back-compatibility since it used to be a needed
122 * abstract method.
123 *
124 * @param e the <code>EOFException</code> thrown by one of the read calls.
125 * @param start the index of the first array element we wanted to fill
126 * @param index the array index of the element during which the exception was thrown
127 * @param elementSize the number of bytes per element we were processing
128 *
129 * @return the numer of bytes successfully processed from the input before the exception occurred.
130 *
131 * @throws EOFException if the input had no more data to process
132 */
133 @Deprecated
134 protected int eofCheck(EOFException e, int start, int index, int elementSize) throws EOFException {
135 return (int) super.eofCheck(e, (index - start), -1) * elementSize;
136 }
137
138 /**
139 * See the contract of {@link ArrayDataInput#readLArray(Object)}.
140 *
141 * @param o an array, to be populated
142 *
143 * @return the actual number of bytes read from the input, or -1 if already at the
144 * end-of-file.
145 *
146 * @throws IllegalArgumentException if the argument is not an array or if it contains an element that is not
147 * supported for decoding.
148 * @throws IOException if there was an IO error reading from the input
149 */
150 protected long readLArray(Object o) throws IOException {
151 try {
152 return super.readArray(o);
153 } catch (IllegalArgumentException e) {
154 throw new IOException(e);
155 }
156 }
157
158 }