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 import static org.waarp.compress.zstdunsafe.UnsafeUtil.*;
38 import static sun.misc.Unsafe.*;
39
40 class SequenceStore {
41 public final byte[] literalsBuffer;
42 public int literalsLength;
43
44 public final int[] offsets;
45 public final int[] literalLengths;
46 public final int[] matchLengths;
47 public int sequenceCount;
48
49 public final byte[] literalLengthCodes;
50 public final byte[] matchLengthCodes;
51 public final byte[] offsetCodes;
52
53 public LongField longLengthField;
54 public int longLengthPosition;
55
56 public enum LongField {
57 LITERAL, MATCH
58 }
59
60 private static final byte[] LITERAL_LENGTH_CODE = {
61 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 17, 17, 18,
62 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22,
63 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24,
64 24, 24, 24, 24, 24, 24, 24
65 };
66
67 private static final byte[] MATCH_LENGTH_CODE = {
68 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
69 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 33, 33, 34, 34, 35,
70 35, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 39,
71 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
72 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
73 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
74 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42
75 };
76
77 public SequenceStore(final int blockSize, final int maxSequences) {
78 offsets = new int[maxSequences];
79 literalLengths = new int[maxSequences];
80 matchLengths = new int[maxSequences];
81
82 literalLengthCodes = new byte[maxSequences];
83 matchLengthCodes = new byte[maxSequences];
84 offsetCodes = new byte[maxSequences];
85
86 literalsBuffer = new byte[blockSize];
87
88 reset();
89 }
90
91 public void appendLiterals(final Object inputBase, final long inputAddress,
92 final int inputSize) {
93 UNSAFE.copyMemory(inputBase, inputAddress, literalsBuffer,
94 ARRAY_BYTE_BASE_OFFSET + literalsLength, inputSize);
95 literalsLength += inputSize;
96 }
97
98 public void storeSequence(final Object literalBase, final long literalAddress,
99 final int literalLength, final int offsetCode,
100 final int matchLengthBase) {
101 long input = literalAddress;
102 long output = ARRAY_BYTE_BASE_OFFSET + literalsLength;
103 int copied = 0;
104 do {
105 UNSAFE.putLong(literalsBuffer, output,
106 UNSAFE.getLong(literalBase, input));
107 input += SIZE_OF_LONG;
108 output += SIZE_OF_LONG;
109 copied += SIZE_OF_LONG;
110 } while (copied < literalLength);
111
112 literalsLength += literalLength;
113
114 if (literalLength > 65535) {
115 longLengthField = LongField.LITERAL;
116 longLengthPosition = sequenceCount;
117 }
118 literalLengths[sequenceCount] = literalLength;
119
120 offsets[sequenceCount] = offsetCode + 1;
121
122 if (matchLengthBase > 65535) {
123 longLengthField = LongField.MATCH;
124 longLengthPosition = sequenceCount;
125 }
126
127 matchLengths[sequenceCount] = matchLengthBase;
128
129 sequenceCount++;
130 }
131
132 public void reset() {
133 literalsLength = 0;
134 sequenceCount = 0;
135 longLengthField = null;
136 }
137
138 public void generateCodes() {
139 for (int i = 0; i < sequenceCount; ++i) {
140 literalLengthCodes[i] = (byte) literalLengthToCode(literalLengths[i]);
141 offsetCodes[i] = (byte) Util.highestBit(offsets[i]);
142 matchLengthCodes[i] = (byte) matchLengthToCode(matchLengths[i]);
143 }
144
145 if (longLengthField == LongField.LITERAL) {
146 literalLengthCodes[longLengthPosition] =
147 Constants.MAX_LITERALS_LENGTH_SYMBOL;
148 }
149 if (longLengthField == LongField.MATCH) {
150 matchLengthCodes[longLengthPosition] = Constants.MAX_MATCH_LENGTH_SYMBOL;
151 }
152 }
153
154 private static int literalLengthToCode(final int literalLength) {
155 if (literalLength >= 64) {
156 return Util.highestBit(literalLength) + 19;
157 } else {
158 return LITERAL_LENGTH_CODE[literalLength];
159 }
160 }
161
162
163
164
165
166 private static int matchLengthToCode(final int matchLengthBase) {
167 if (matchLengthBase >= 128) {
168 return Util.highestBit(matchLengthBase) + 36;
169 } else {
170 return MATCH_LENGTH_CODE[matchLengthBase];
171 }
172 }
173 }