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