]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.lz4/src/net/jpountz/lz4/LZ4JavaUnsafeCompressor.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.lz4 / src / net / jpountz / lz4 / LZ4JavaUnsafeCompressor.java
1 // Auto-generated: DO NOT EDIT
2
3 package net.jpountz.lz4;
4
5 import static net.jpountz.lz4.LZ4Constants.*;
6 import static net.jpountz.lz4.LZ4Utils.*;
7
8 import java.nio.ByteBuffer;
9 import java.util.Arrays;
10
11 import net.jpountz.util.ByteBufferUtils;
12 import net.jpountz.util.UnsafeUtils;
13
14 /**
15  * Compressor. 
16  */
17 final class LZ4JavaUnsafeCompressor extends LZ4Compressor {
18
19   public static final LZ4Compressor INSTANCE = new LZ4JavaUnsafeCompressor();
20
21   static int compress64k(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int destEnd) {
22     final int srcEnd = srcOff + srcLen;
23     final int srcLimit = srcEnd - LAST_LITERALS;
24     final int mflimit = srcEnd - MF_LIMIT;
25
26     int sOff = srcOff, dOff = destOff;
27
28     int anchor = sOff;
29
30     if (srcLen >= MIN_LENGTH) {
31
32       final short[] hashTable = new short[HASH_TABLE_SIZE_64K];
33
34       ++sOff;
35
36       main:
37       while (true) {
38
39         // find a match
40         int forwardOff = sOff;
41
42         int ref;
43         int step = 1;
44         int searchMatchNb = 1 << SKIP_STRENGTH;
45         do {
46           sOff = forwardOff;
47           forwardOff += step;
48           step = searchMatchNb++ >>> SKIP_STRENGTH;
49
50           if (forwardOff > mflimit) {
51             break main;
52           }
53
54           final int h = hash64k(UnsafeUtils.readInt(src, sOff));
55           ref = srcOff + UnsafeUtils.readShort(hashTable, h);
56           UnsafeUtils.writeShort(hashTable, h, sOff - srcOff);
57         } while (!LZ4UnsafeUtils.readIntEquals(src, ref, sOff));
58
59         // catch up
60         final int excess = LZ4UnsafeUtils.commonBytesBackward(src, ref, sOff, srcOff, anchor);
61         sOff -= excess;
62         ref -= excess;
63
64         // sequence == refsequence
65         final int runLen = sOff - anchor;
66
67         // encode literal length
68         int tokenOff = dOff++;
69
70         if (dOff + runLen + (2 + 1 + LAST_LITERALS) + (runLen >>> 8) > destEnd) {
71           throw new LZ4Exception("maxDestLen is too small");
72         }
73
74         if (runLen >= RUN_MASK) {
75           UnsafeUtils.writeByte(dest, tokenOff, RUN_MASK << ML_BITS);
76           dOff = LZ4UnsafeUtils.writeLen(runLen - RUN_MASK, dest, dOff);
77         } else {
78           UnsafeUtils.writeByte(dest, tokenOff, runLen << ML_BITS);
79         }
80
81         // copy literals
82         LZ4UnsafeUtils.wildArraycopy(src, anchor, dest, dOff, runLen);
83         dOff += runLen;
84
85         while (true) {
86           // encode offset
87           UnsafeUtils.writeShortLE(dest, dOff, (short) (sOff - ref));
88           dOff += 2;
89
90           // count nb matches
91           sOff += MIN_MATCH;
92           ref += MIN_MATCH;
93           final int matchLen = LZ4UnsafeUtils.commonBytes(src, ref, sOff, srcLimit);
94           if (dOff + (1 + LAST_LITERALS) + (matchLen >>> 8) > destEnd) {
95             throw new LZ4Exception("maxDestLen is too small");
96           }
97           sOff += matchLen;
98
99           // encode match len
100           if (matchLen >= ML_MASK) {
101             UnsafeUtils.writeByte(dest, tokenOff, UnsafeUtils.readByte(dest, tokenOff) | ML_MASK);
102             dOff = LZ4UnsafeUtils.writeLen(matchLen - ML_MASK, dest, dOff);
103           } else {
104             UnsafeUtils.writeByte(dest, tokenOff, UnsafeUtils.readByte(dest, tokenOff) | matchLen);
105           }
106
107           // test end of chunk
108           if (sOff > mflimit) {
109             anchor = sOff;
110             break main;
111           }
112
113           // fill table
114           UnsafeUtils.writeShort(hashTable, hash64k(UnsafeUtils.readInt(src, sOff - 2)), sOff - 2 - srcOff);
115
116           // test next position
117           final int h = hash64k(UnsafeUtils.readInt(src, sOff));
118           ref = srcOff + UnsafeUtils.readShort(hashTable, h);
119           UnsafeUtils.writeShort(hashTable, h, sOff - srcOff);
120
121           if (!LZ4UnsafeUtils.readIntEquals(src, sOff, ref)) {
122             break;
123           }
124
125           tokenOff = dOff++;
126           UnsafeUtils.writeByte(dest, tokenOff, 0);
127         }
128
129         // prepare next loop
130         anchor = sOff++;
131       }
132     }
133
134     dOff = LZ4UnsafeUtils.lastLiterals(src, anchor, srcEnd - anchor, dest, dOff, destEnd);
135     return dOff - destOff;
136   }
137
138   @Override
139   public int compress(byte[] src, final int srcOff, int srcLen, byte[] dest, final int destOff, int maxDestLen) {
140
141     UnsafeUtils.checkRange(src, srcOff, srcLen);
142     UnsafeUtils.checkRange(dest, destOff, maxDestLen);
143     final int destEnd = destOff + maxDestLen;
144
145     if (srcLen < LZ4_64K_LIMIT) {
146       return compress64k(src, srcOff, srcLen, dest, destOff, destEnd);
147     }
148
149     final int srcEnd = srcOff + srcLen;
150     final int srcLimit = srcEnd - LAST_LITERALS;
151     final int mflimit = srcEnd - MF_LIMIT;
152
153     int sOff = srcOff, dOff = destOff;
154     int anchor = sOff++;
155
156     final int[] hashTable = new int[HASH_TABLE_SIZE];
157     Arrays.fill(hashTable, anchor);
158
159     main:
160     while (true) {
161
162       // find a match
163       int forwardOff = sOff;
164
165       int ref;
166       int step = 1;
167       int searchMatchNb = 1 << SKIP_STRENGTH;
168       int back;
169       do {
170         sOff = forwardOff;
171         forwardOff += step;
172         step = searchMatchNb++ >>> SKIP_STRENGTH;
173
174         if (forwardOff > mflimit) {
175           break main;
176         }
177
178         final int h = hash(UnsafeUtils.readInt(src, sOff));
179         ref = UnsafeUtils.readInt(hashTable, h);
180         back = sOff - ref;
181         UnsafeUtils.writeInt(hashTable, h, sOff);
182       } while (back >= MAX_DISTANCE || !LZ4UnsafeUtils.readIntEquals(src, ref, sOff));
183
184
185       final int excess = LZ4UnsafeUtils.commonBytesBackward(src, ref, sOff, srcOff, anchor);
186       sOff -= excess;
187       ref -= excess;
188
189       // sequence == refsequence
190       final int runLen = sOff - anchor;
191
192       // encode literal length
193       int tokenOff = dOff++;
194
195       if (dOff + runLen + (2 + 1 + LAST_LITERALS) + (runLen >>> 8) > destEnd) {
196         throw new LZ4Exception("maxDestLen is too small");
197       }
198
199       if (runLen >= RUN_MASK) {
200         UnsafeUtils.writeByte(dest, tokenOff, RUN_MASK << ML_BITS);
201         dOff = LZ4UnsafeUtils.writeLen(runLen - RUN_MASK, dest, dOff);
202       } else {
203         UnsafeUtils.writeByte(dest, tokenOff, runLen << ML_BITS);
204       }
205
206       // copy literals
207       LZ4UnsafeUtils.wildArraycopy(src, anchor, dest, dOff, runLen);
208       dOff += runLen;
209
210       while (true) {
211         // encode offset
212         UnsafeUtils.writeShortLE(dest, dOff, back);
213         dOff += 2;
214
215         // count nb matches
216         sOff += MIN_MATCH;
217         final int matchLen = LZ4UnsafeUtils.commonBytes(src, ref + MIN_MATCH, sOff, srcLimit);
218         if (dOff + (1 + LAST_LITERALS) + (matchLen >>> 8) > destEnd) {
219           throw new LZ4Exception("maxDestLen is too small");
220         }
221         sOff += matchLen;
222
223         // encode match len
224         if (matchLen >= ML_MASK) {
225           UnsafeUtils.writeByte(dest, tokenOff, UnsafeUtils.readByte(dest, tokenOff) | ML_MASK);
226           dOff = LZ4UnsafeUtils.writeLen(matchLen - ML_MASK, dest, dOff);
227         } else {
228           UnsafeUtils.writeByte(dest, tokenOff, UnsafeUtils.readByte(dest, tokenOff) | matchLen);
229         }
230
231         // test end of chunk
232         if (sOff > mflimit) {
233           anchor = sOff;
234           break main;
235         }
236
237         // fill table
238         UnsafeUtils.writeInt(hashTable, hash(UnsafeUtils.readInt(src, sOff - 2)), sOff - 2);
239
240         // test next position
241         final int h = hash(UnsafeUtils.readInt(src, sOff));
242         ref = UnsafeUtils.readInt(hashTable, h);
243         UnsafeUtils.writeInt(hashTable, h, sOff);
244         back = sOff - ref;
245
246         if (back >= MAX_DISTANCE || !LZ4UnsafeUtils.readIntEquals(src, ref, sOff)) {
247           break;
248         }
249
250         tokenOff = dOff++;
251         UnsafeUtils.writeByte(dest, tokenOff, 0);
252       }
253
254       // prepare next loop
255       anchor = sOff++;
256     }
257
258     dOff = LZ4UnsafeUtils.lastLiterals(src, anchor, srcEnd - anchor, dest, dOff, destEnd);
259     return dOff - destOff;
260   }
261
262
263   static int compress64k(ByteBuffer src, int srcOff, int srcLen, ByteBuffer dest, int destOff, int destEnd) {
264     final int srcEnd = srcOff + srcLen;
265     final int srcLimit = srcEnd - LAST_LITERALS;
266     final int mflimit = srcEnd - MF_LIMIT;
267
268     int sOff = srcOff, dOff = destOff;
269
270     int anchor = sOff;
271
272     if (srcLen >= MIN_LENGTH) {
273
274       final short[] hashTable = new short[HASH_TABLE_SIZE_64K];
275
276       ++sOff;
277
278       main:
279       while (true) {
280
281         // find a match
282         int forwardOff = sOff;
283
284         int ref;
285         int step = 1;
286         int searchMatchNb = 1 << SKIP_STRENGTH;
287         do {
288           sOff = forwardOff;
289           forwardOff += step;
290           step = searchMatchNb++ >>> SKIP_STRENGTH;
291
292           if (forwardOff > mflimit) {
293             break main;
294           }
295
296           final int h = hash64k(ByteBufferUtils.readInt(src, sOff));
297           ref = srcOff + UnsafeUtils.readShort(hashTable, h);
298           UnsafeUtils.writeShort(hashTable, h, sOff - srcOff);
299         } while (!LZ4ByteBufferUtils.readIntEquals(src, ref, sOff));
300
301         // catch up
302         final int excess = LZ4ByteBufferUtils.commonBytesBackward(src, ref, sOff, srcOff, anchor);
303         sOff -= excess;
304         ref -= excess;
305
306         // sequence == refsequence
307         final int runLen = sOff - anchor;
308
309         // encode literal length
310         int tokenOff = dOff++;
311
312         if (dOff + runLen + (2 + 1 + LAST_LITERALS) + (runLen >>> 8) > destEnd) {
313           throw new LZ4Exception("maxDestLen is too small");
314         }
315
316         if (runLen >= RUN_MASK) {
317           ByteBufferUtils.writeByte(dest, tokenOff, RUN_MASK << ML_BITS);
318           dOff = LZ4ByteBufferUtils.writeLen(runLen - RUN_MASK, dest, dOff);
319         } else {
320           ByteBufferUtils.writeByte(dest, tokenOff, runLen << ML_BITS);
321         }
322
323         // copy literals
324         LZ4ByteBufferUtils.wildArraycopy(src, anchor, dest, dOff, runLen);
325         dOff += runLen;
326
327         while (true) {
328           // encode offset
329           ByteBufferUtils.writeShortLE(dest, dOff, (short) (sOff - ref));
330           dOff += 2;
331
332           // count nb matches
333           sOff += MIN_MATCH;
334           ref += MIN_MATCH;
335           final int matchLen = LZ4ByteBufferUtils.commonBytes(src, ref, sOff, srcLimit);
336           if (dOff + (1 + LAST_LITERALS) + (matchLen >>> 8) > destEnd) {
337             throw new LZ4Exception("maxDestLen is too small");
338           }
339           sOff += matchLen;
340
341           // encode match len
342           if (matchLen >= ML_MASK) {
343             ByteBufferUtils.writeByte(dest, tokenOff, ByteBufferUtils.readByte(dest, tokenOff) | ML_MASK);
344             dOff = LZ4ByteBufferUtils.writeLen(matchLen - ML_MASK, dest, dOff);
345           } else {
346             ByteBufferUtils.writeByte(dest, tokenOff, ByteBufferUtils.readByte(dest, tokenOff) | matchLen);
347           }
348
349           // test end of chunk
350           if (sOff > mflimit) {
351             anchor = sOff;
352             break main;
353           }
354
355           // fill table
356           UnsafeUtils.writeShort(hashTable, hash64k(ByteBufferUtils.readInt(src, sOff - 2)), sOff - 2 - srcOff);
357
358           // test next position
359           final int h = hash64k(ByteBufferUtils.readInt(src, sOff));
360           ref = srcOff + UnsafeUtils.readShort(hashTable, h);
361           UnsafeUtils.writeShort(hashTable, h, sOff - srcOff);
362
363           if (!LZ4ByteBufferUtils.readIntEquals(src, sOff, ref)) {
364             break;
365           }
366
367           tokenOff = dOff++;
368           ByteBufferUtils.writeByte(dest, tokenOff, 0);
369         }
370
371         // prepare next loop
372         anchor = sOff++;
373       }
374     }
375
376     dOff = LZ4ByteBufferUtils.lastLiterals(src, anchor, srcEnd - anchor, dest, dOff, destEnd);
377     return dOff - destOff;
378   }
379
380   @Override
381   public int compress(ByteBuffer src, final int srcOff, int srcLen, ByteBuffer dest, final int destOff, int maxDestLen) {
382
383     if (src.hasArray() && dest.hasArray()) {
384       return compress(src.array(), srcOff + src.arrayOffset(), srcLen, dest.array(), destOff + dest.arrayOffset(), maxDestLen);
385     }
386     src = ByteBufferUtils.inNativeByteOrder(src);
387     dest = ByteBufferUtils.inNativeByteOrder(dest);
388
389     ByteBufferUtils.checkRange(src, srcOff, srcLen);
390     ByteBufferUtils.checkRange(dest, destOff, maxDestLen);
391     final int destEnd = destOff + maxDestLen;
392
393     if (srcLen < LZ4_64K_LIMIT) {
394       return compress64k(src, srcOff, srcLen, dest, destOff, destEnd);
395     }
396
397     final int srcEnd = srcOff + srcLen;
398     final int srcLimit = srcEnd - LAST_LITERALS;
399     final int mflimit = srcEnd - MF_LIMIT;
400
401     int sOff = srcOff, dOff = destOff;
402     int anchor = sOff++;
403
404     final int[] hashTable = new int[HASH_TABLE_SIZE];
405     Arrays.fill(hashTable, anchor);
406
407     main:
408     while (true) {
409
410       // find a match
411       int forwardOff = sOff;
412
413       int ref;
414       int step = 1;
415       int searchMatchNb = 1 << SKIP_STRENGTH;
416       int back;
417       do {
418         sOff = forwardOff;
419         forwardOff += step;
420         step = searchMatchNb++ >>> SKIP_STRENGTH;
421
422         if (forwardOff > mflimit) {
423           break main;
424         }
425
426         final int h = hash(ByteBufferUtils.readInt(src, sOff));
427         ref = UnsafeUtils.readInt(hashTable, h);
428         back = sOff - ref;
429         UnsafeUtils.writeInt(hashTable, h, sOff);
430       } while (back >= MAX_DISTANCE || !LZ4ByteBufferUtils.readIntEquals(src, ref, sOff));
431
432
433       final int excess = LZ4ByteBufferUtils.commonBytesBackward(src, ref, sOff, srcOff, anchor);
434       sOff -= excess;
435       ref -= excess;
436
437       // sequence == refsequence
438       final int runLen = sOff - anchor;
439
440       // encode literal length
441       int tokenOff = dOff++;
442
443       if (dOff + runLen + (2 + 1 + LAST_LITERALS) + (runLen >>> 8) > destEnd) {
444         throw new LZ4Exception("maxDestLen is too small");
445       }
446
447       if (runLen >= RUN_MASK) {
448         ByteBufferUtils.writeByte(dest, tokenOff, RUN_MASK << ML_BITS);
449         dOff = LZ4ByteBufferUtils.writeLen(runLen - RUN_MASK, dest, dOff);
450       } else {
451         ByteBufferUtils.writeByte(dest, tokenOff, runLen << ML_BITS);
452       }
453
454       // copy literals
455       LZ4ByteBufferUtils.wildArraycopy(src, anchor, dest, dOff, runLen);
456       dOff += runLen;
457
458       while (true) {
459         // encode offset
460         ByteBufferUtils.writeShortLE(dest, dOff, back);
461         dOff += 2;
462
463         // count nb matches
464         sOff += MIN_MATCH;
465         final int matchLen = LZ4ByteBufferUtils.commonBytes(src, ref + MIN_MATCH, sOff, srcLimit);
466         if (dOff + (1 + LAST_LITERALS) + (matchLen >>> 8) > destEnd) {
467           throw new LZ4Exception("maxDestLen is too small");
468         }
469         sOff += matchLen;
470
471         // encode match len
472         if (matchLen >= ML_MASK) {
473           ByteBufferUtils.writeByte(dest, tokenOff, ByteBufferUtils.readByte(dest, tokenOff) | ML_MASK);
474           dOff = LZ4ByteBufferUtils.writeLen(matchLen - ML_MASK, dest, dOff);
475         } else {
476           ByteBufferUtils.writeByte(dest, tokenOff, ByteBufferUtils.readByte(dest, tokenOff) | matchLen);
477         }
478
479         // test end of chunk
480         if (sOff > mflimit) {
481           anchor = sOff;
482           break main;
483         }
484
485         // fill table
486         UnsafeUtils.writeInt(hashTable, hash(ByteBufferUtils.readInt(src, sOff - 2)), sOff - 2);
487
488         // test next position
489         final int h = hash(ByteBufferUtils.readInt(src, sOff));
490         ref = UnsafeUtils.readInt(hashTable, h);
491         UnsafeUtils.writeInt(hashTable, h, sOff);
492         back = sOff - ref;
493
494         if (back >= MAX_DISTANCE || !LZ4ByteBufferUtils.readIntEquals(src, ref, sOff)) {
495           break;
496         }
497
498         tokenOff = dOff++;
499         ByteBufferUtils.writeByte(dest, tokenOff, 0);
500       }
501
502       // prepare next loop
503       anchor = sOff++;
504     }
505
506     dOff = LZ4ByteBufferUtils.lastLiterals(src, anchor, srcEnd - anchor, dest, dOff, destEnd);
507     return dOff - destOff;
508   }
509
510
511 }