View Javadoc
1   package nom.tam.fits.compression.algorithm.rice;
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.nio.ByteBuffer;
35  
36  /**
37   * (<i>for internal use</i>) A bit wise reader writer around a {@link ByteBuffer}.
38   * 
39   * @deprecated (<i>for internal use</i>) Its visibility may be reduced to the package level in the future.
40   * 
41   * @author     Ritchie
42   */
43  @SuppressWarnings("javadoc")
44  public class BitBuffer {
45  
46      private static final int BITS_OF_4_BYTES = 32;
47  
48      private static final int BYTE_MASK = 0xFF;
49  
50      private static final long INTEGER_MASK = 0xFFFFFFFFL;
51  
52      private static final int BITS_OF_1_BYTE = 8;
53  
54      private static final int BITS_OF_2_BYTES = 16;
55  
56      private static final int BITS_OF_3_BYTES = 24;
57  
58      private static final int BYTE_1_OF_INT = 0x000000FF;
59  
60      private static final int BYTE_2_OF_INT = 0x0000FF00;
61  
62      private static final int BYTE_3_OF_INT = 0x00FF0000;
63  
64      private static final int BYTE_4_OF_INT = 0xFF000000;
65  
66      private final ByteBuffer buffer;
67  
68      private long position;
69  
70      public BitBuffer(ByteBuffer writeBuffer) {
71          buffer = writeBuffer;
72      }
73  
74      public int bitbuffer() {
75          return buffer.get((int) (position / BITS_OF_1_BYTE));
76      }
77  
78      void close() {
79          if (position % BITS_OF_1_BYTE != 0) {
80              putByte((byte) 0, (int) (BITS_OF_1_BYTE - position % BITS_OF_1_BYTE));
81          }
82          buffer.position((int) (position / BITS_OF_1_BYTE));
83      }
84  
85      public int missingBitsInCurrentByte() {
86          return (int) (BITS_OF_1_BYTE - position % BITS_OF_1_BYTE);
87      }
88  
89      public void movePosition(int i) {
90          position += i;
91      }
92  
93      public void putByte(byte byteToAdd) {
94          final int bytePosition = (int) (position / BITS_OF_1_BYTE);
95          final int positionInByte = (int) (position % BITS_OF_1_BYTE);
96          final byte old = (byte) (buffer.get(bytePosition) & (byte) ~(BYTE_MASK >>> positionInByte));
97          final int byteAsInt = byteToAdd & BYTE_MASK;
98          buffer.put(bytePosition, (byte) (old | (byte) (byteAsInt >>> positionInByte)));
99          if (positionInByte > 0) {
100             buffer.put(bytePosition + 1, (byte) (byteAsInt << BITS_OF_1_BYTE - positionInByte));
101         }
102         position += BITS_OF_1_BYTE;
103     }
104 
105     public void putByte(byte byteToAdd, int bits) {
106         final int bytePosition = (int) (position / BITS_OF_1_BYTE);
107         final int positionInByte = (int) (position % BITS_OF_1_BYTE);
108         final byte old = buffer.get(bytePosition);
109         final int byteAsInt = BYTE_MASK & (byteToAdd & BYTE_MASK >>> BITS_OF_1_BYTE - bits) << BITS_OF_1_BYTE - bits;
110         buffer.put(bytePosition, (byte) (BYTE_MASK & //
111                 (old & BYTE_MASK << BITS_OF_1_BYTE - positionInByte | byteAsInt >>> positionInByte)));
112         if (BITS_OF_1_BYTE - positionInByte < bits) {
113             buffer.put(bytePosition + 1, (byte) (BYTE_MASK & byteAsInt << BITS_OF_1_BYTE - positionInByte));
114         }
115         position += bits;
116     }
117 
118     /**
119      * write out int value to the next 4 bytes of the buffer
120      * 
121      * @param i integer to write
122      */
123     public void putInt(int i) {
124         putByte((byte) ((i & BYTE_4_OF_INT) >>> BITS_OF_3_BYTES));
125         putByte((byte) ((i & BYTE_3_OF_INT) >>> BITS_OF_2_BYTES));
126         putByte((byte) ((i & BYTE_2_OF_INT) >>> BITS_OF_1_BYTE));
127         putByte((byte) (i & BYTE_1_OF_INT));
128     }
129 
130     public void putInt(int i, int bits) {
131         if (bits == 0) {
132             return;
133         }
134         do {
135             if (bits >= BITS_OF_1_BYTE) {
136                 putByte((byte) ((i & BYTE_MASK << bits - BITS_OF_1_BYTE) >>> bits - BITS_OF_1_BYTE & BYTE_MASK));
137                 bits -= BITS_OF_1_BYTE;
138             } else {
139                 putByte((byte) (i & BYTE_MASK >> -(bits - BITS_OF_1_BYTE)), bits);
140                 bits = 0;
141             }
142         } while (bits > 0);
143     }
144 
145     public void putLong(long l, int bits) {
146         if (bits == 0) {
147             return;
148         }
149         do {
150             if (bits >= BITS_OF_4_BYTES) {
151                 putInt((int) ((l & INTEGER_MASK << bits - BITS_OF_4_BYTES) >>> bits - BITS_OF_4_BYTES));
152                 bits -= BITS_OF_4_BYTES;
153             } else {
154                 putInt((int) (l & INTEGER_MASK >> -(bits - BITS_OF_4_BYTES)), bits);
155                 bits = 0;
156             }
157         } while (bits > 0);
158     }
159 
160 }