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.zstdunsafe;
35
36 import static org.waarp.compress.zstdunsafe.Constants.*;
37
38 class HuffmanCompressor {
39 private HuffmanCompressor() {
40 }
41
42 public static int compress4streams(final Object outputBase,
43 final long outputAddress,
44 final int outputSize,
45 final Object inputBase,
46 final long inputAddress,
47 final int inputSize,
48 final HuffmanCompressionTable table) {
49 long input = inputAddress;
50 final long inputLimit = inputAddress + inputSize;
51 long output = outputAddress;
52 final long outputLimit = outputAddress + outputSize;
53
54 final int segmentSize = (inputSize + 3) / 4;
55
56 if (outputSize <
57 6 + 1 + 1 +
58 1 +
59 8 ) {
60 return 0;
61 }
62
63 if (inputSize <= 6 + 1 + 1 + 1) {
64 return 0;
65 }
66
67 output += SIZE_OF_SHORT + SIZE_OF_SHORT + SIZE_OF_SHORT;
68
69 int compressedSize;
70
71
72 compressedSize =
73 compressSingleStream(outputBase, output, (int) (outputLimit - output),
74 inputBase, input, segmentSize, table);
75 if (compressedSize == 0) {
76 return 0;
77 }
78 UnsafeUtil.UNSAFE.putShort(outputBase, outputAddress,
79 (short) compressedSize);
80 output += compressedSize;
81 input += segmentSize;
82
83
84 compressedSize =
85 compressSingleStream(outputBase, output, (int) (outputLimit - output),
86 inputBase, input, segmentSize, table);
87 if (compressedSize == 0) {
88 return 0;
89 }
90 UnsafeUtil.UNSAFE.putShort(outputBase, outputAddress + SIZE_OF_SHORT,
91 (short) compressedSize);
92 output += compressedSize;
93 input += segmentSize;
94
95
96 compressedSize =
97 compressSingleStream(outputBase, output, (int) (outputLimit - output),
98 inputBase, input, segmentSize, table);
99 if (compressedSize == 0) {
100 return 0;
101 }
102 UnsafeUtil.UNSAFE.putShort(outputBase,
103 outputAddress + SIZE_OF_SHORT + SIZE_OF_SHORT,
104 (short) compressedSize);
105 output += compressedSize;
106 input += segmentSize;
107
108
109 compressedSize =
110 compressSingleStream(outputBase, output, (int) (outputLimit - output),
111 inputBase, input, (int) (inputLimit - input),
112 table);
113 if (compressedSize == 0) {
114 return 0;
115 }
116 output += compressedSize;
117
118 return (int) (output - outputAddress);
119 }
120
121 public static int compressSingleStream(final Object outputBase,
122 final long outputAddress,
123 final int outputSize,
124 final Object inputBase,
125 final long inputAddress,
126 final int inputSize,
127 final HuffmanCompressionTable table) {
128 if (outputSize < SIZE_OF_LONG) {
129 return 0;
130 }
131 final BitOutputStream bitstream =
132 new BitOutputStream(outputBase, outputAddress, outputSize);
133
134 int n = inputSize & ~3;
135
136 switch (inputSize & 3) {
137 case 3:
138 table.encodeSymbol(bitstream, UnsafeUtil.UNSAFE.getByte(inputBase,
139 inputAddress +
140 n + 2) & 0xFF);
141
142 case 2:
143 table.encodeSymbol(bitstream, UnsafeUtil.UNSAFE.getByte(inputBase,
144 inputAddress +
145 n + 1) & 0xFF);
146
147 case 1:
148 table.encodeSymbol(bitstream, UnsafeUtil.UNSAFE.getByte(inputBase,
149 inputAddress +
150 n) & 0xFF);
151 bitstream.flush();
152
153 case 0:
154 default:
155 break;
156 }
157
158 for (; n > 0; n -= 4) {
159 table.encodeSymbol(bitstream, UnsafeUtil.UNSAFE.getByte(inputBase,
160 inputAddress + n -
161 1) & 0xFF);
162 table.encodeSymbol(bitstream, UnsafeUtil.UNSAFE.getByte(inputBase,
163 inputAddress + n -
164 2) & 0xFF);
165 table.encodeSymbol(bitstream, UnsafeUtil.UNSAFE.getByte(inputBase,
166 inputAddress + n -
167 3) & 0xFF);
168 table.encodeSymbol(bitstream, UnsafeUtil.UNSAFE.getByte(inputBase,
169 inputAddress + n -
170 4) & 0xFF);
171 bitstream.flush();
172 }
173
174 return bitstream.close();
175 }
176 }