1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package org.waarp.compress.zstdsafe;
35
36 import static org.waarp.compress.zstdsafe.Constants.*;
37 import static org.waarp.compress.zstdsafe.UnsafeUtil.*;
38 import static org.waarp.compress.zstdsafe.Util.*;
39
40
41
42
43
44
45
46
47 class BitInputStream {
48 private BitInputStream() {
49 }
50
51 public static boolean isEndOfStream(final int startAddress,
52 final int currentAddress,
53 final int bitsConsumed) {
54 return startAddress == currentAddress && bitsConsumed == Long.SIZE;
55 }
56
57 static long readTail(final byte[] inputBase, final int inputAddress,
58 final int inputSize) {
59 long bits = inputBase[inputAddress] & 0xFF;
60
61 switch (inputSize) {
62 case 7:
63 bits |= (inputBase[inputAddress + 6] & 0xFFL) << 48;
64 case 6:
65 bits |= (inputBase[inputAddress + 5] & 0xFFL) << 40;
66 case 5:
67 bits |= (inputBase[inputAddress + 4] & 0xFFL) << 32;
68 case 4:
69 bits |= (inputBase[inputAddress + 3] & 0xFFL) << 24;
70 case 3:
71 bits |= (inputBase[inputAddress + 2] & 0xFFL) << 16;
72 case 2:
73 bits |= (inputBase[inputAddress + 1] & 0xFFL) << 8;
74 }
75
76 return bits;
77 }
78
79
80
81
82 public static long peekBits(final int bitsConsumed, final long bitContainer,
83 final int numberOfBits) {
84 return (((bitContainer << bitsConsumed) >>> 1) >>> (63 - numberOfBits));
85 }
86
87
88
89
90
91
92 public static long peekBitsFast(final int bitsConsumed,
93 final long bitContainer,
94 final int numberOfBits) {
95 return ((bitContainer << bitsConsumed) >>> (64 - numberOfBits));
96 }
97
98 static class Initializer {
99 private final byte[] inputBase;
100 private final int startAddress;
101 private final int endAddress;
102 private long bits;
103 private int currentAddress;
104 private int bitsConsumed;
105
106 public Initializer(final byte[] inputBase, final int startAddress,
107 final int endAddress) {
108 this.inputBase = inputBase;
109 this.startAddress = startAddress;
110 this.endAddress = endAddress;
111 }
112
113 public long getBits() {
114 return bits;
115 }
116
117 public int getCurrentAddress() {
118 return currentAddress;
119 }
120
121 public int getBitsConsumed() {
122 return bitsConsumed;
123 }
124
125 public void initialize() {
126 verify(endAddress - startAddress >= 1, startAddress,
127 "Bitstream is empty");
128
129 final int lastByte = inputBase[endAddress - 1] & 0xFF;
130 verify(lastByte != 0, endAddress, "Bitstream end mark not present");
131
132 bitsConsumed = SIZE_OF_LONG - highestBit(lastByte);
133
134 final int inputSize = endAddress - startAddress;
135 if (inputSize >= SIZE_OF_LONG) {
136 currentAddress = endAddress - SIZE_OF_LONG;
137 bits = getLong(inputBase, currentAddress);
138 } else {
139 currentAddress = startAddress;
140 bits = readTail(inputBase, startAddress, inputSize);
141
142 bitsConsumed += (SIZE_OF_LONG - inputSize) * 8;
143 }
144 }
145 }
146
147 static final class Loader {
148 private final byte[] inputBase;
149 private final int startAddress;
150 private long bits;
151 private int currentAddress;
152 private int bitsConsumed;
153 private boolean overflow;
154
155 public Loader(final byte[] inputBase, final int startAddress,
156 final int currentAddress, final long bits,
157 final int bitsConsumed) {
158 this.inputBase = inputBase;
159 this.startAddress = startAddress;
160 this.bits = bits;
161 this.currentAddress = currentAddress;
162 this.bitsConsumed = bitsConsumed;
163 }
164
165 public long getBits() {
166 return bits;
167 }
168
169 public int getCurrentAddress() {
170 return currentAddress;
171 }
172
173 public int getBitsConsumed() {
174 return bitsConsumed;
175 }
176
177 public boolean isOverflow() {
178 return overflow;
179 }
180
181 public boolean load() {
182 if (bitsConsumed > 64) {
183 overflow = true;
184 return true;
185 } else if (currentAddress == startAddress) {
186 return true;
187 }
188
189 int bytes = bitsConsumed >>> 3;
190 if (currentAddress >= startAddress + SIZE_OF_LONG) {
191 if (bytes > 0) {
192 currentAddress -= bytes;
193 bits = getLong(inputBase, currentAddress);
194 }
195 bitsConsumed &= 0x7;
196 } else if (currentAddress - bytes < startAddress) {
197 bytes = currentAddress - startAddress;
198 currentAddress = startAddress;
199 bitsConsumed -= bytes * SIZE_OF_LONG;
200 bits = getLong(inputBase, startAddress);
201 return true;
202 } else {
203 currentAddress -= bytes;
204 bitsConsumed -= bytes * SIZE_OF_LONG;
205 bits = getLong(inputBase, currentAddress);
206 }
207
208 return false;
209 }
210 }
211 }