1 40 41 package org.h2.compress; 42 43 public class CompressLZF implements Compresser { 44 45 public void setOptions(String options) { 46 } 47 48 public int getAlgorithm() { 49 return Compresser.LZF; 50 } 51 52 static final int HLOG = 14; 53 static final int HASH_SIZE = (1 << 14); 54 static final int MAX_LITERAL = (1 << 5); 55 static final int MAX_OFF = (1 << 13); 56 static final int MAX_REF = ((1 << 8) + (1 << 3)); 57 58 int first(byte[] in, int inPos) { 59 return (in[inPos] << 8) + (in[inPos + 1] & 255); 60 } 61 62 int next(int v, byte[] in, int inPos) { 63 return (v << 8) + (in[inPos + 2] & 255); 64 } 65 66 int hash(int h) { 67 return ((h * 184117) >> 9) & (HASH_SIZE - 1); 69 } 70 71 private int[] hashTab; 72 private static int[] empty = new int[HASH_SIZE]; 73 74 public int compress(byte[] in, int inLen, byte[] out, int outPos) { 75 int inPos = 0; 76 if(hashTab == null) { 77 hashTab = new int[HASH_SIZE]; 78 } else { 79 System.arraycopy(empty, 0, hashTab, 0, HASH_SIZE); 80 } 81 int literals = 0; 82 int hval = first(in, inPos); 83 while (true) { 84 if (inPos < inLen - 4) { 85 hval = next(hval, in, inPos); 86 int off = hash(hval); 87 int ref = hashTab[off]; 88 hashTab[off] = inPos; 89 off = inPos - ref - 1; 90 if (off < MAX_OFF && ref > 0 && in[ref + 2] == in[inPos + 2] && in[ref + 1] == in[inPos + 1] && in[ref] == in[inPos]) { 91 int maxlen = inLen - inPos - 2; 92 maxlen = maxlen > MAX_REF ? MAX_REF : maxlen; 93 int len = 3; 94 while (len < maxlen && in[ref + len] == in[inPos + len]) { 95 len++; 96 } 97 len -= 2; 98 if (literals != 0) { 99 out[outPos++] = (byte) (literals - 1); 100 literals = -literals; 101 do { 102 out[outPos++] = in[inPos + literals++]; 103 } while (literals != 0); 104 } 105 if (len < 7) { 106 out[outPos++] = (byte) ((off >> 8) + (len << 5)); 107 } else { 108 out[outPos++] = (byte) ((off >> 8) + (7 << 5)); 109 out[outPos++] = (byte) (len - 7); 110 } 111 out[outPos++] = (byte) off; 112 inPos += len; 113 hval = first(in, inPos); 114 hval = next(hval, in, inPos); 115 hashTab[hash(hval)] = inPos++; 116 hval = next(hval, in, inPos); 117 hashTab[hash(hval)] = inPos++; 118 continue; 119 } 120 } else if (inPos == inLen) { 121 break; 122 } 123 inPos++; 124 literals++; 125 if (literals == MAX_LITERAL) { 126 out[outPos++] = (byte) (literals - 1); 127 literals = -literals; 128 do { 129 out[outPos++] = in[inPos + literals++]; 130 } while (literals != 0); 131 } 132 } 133 if (literals != 0) { 134 out[outPos++] = (byte) (literals - 1); 135 literals = -literals; 136 do { 137 out[outPos++] = in[inPos + literals++]; 138 } while (literals != 0); 139 } 140 return outPos; 141 } 142 143 public void expand(byte[] in, int inPos, int inLen, byte[] out, int outPos, int outLen) { 144 do { 145 int ctrl = in[inPos++] & 255; 146 if (ctrl < (1 << 5)) { 147 ctrl += inPos; 149 do { 150 out[outPos++] = in[inPos]; 151 } while (inPos++ < ctrl); 152 } else { 153 int len = ctrl >> 5; 155 int ref = -((ctrl & 0x1f) << 8) - 1; 156 if (len == 7) { 157 len += in[inPos++] & 255; 158 } 159 ref -= in[inPos++] & 255; 160 len += outPos + 2; 161 out[outPos] = out[outPos++ + ref]; 162 out[outPos] = out[outPos++ + ref]; 163 while (outPos < len - 8) { 164 out[outPos] = out[outPos++ + ref]; 165 out[outPos] = out[outPos++ + ref]; 166 out[outPos] = out[outPos++ + ref]; 167 out[outPos] = out[outPos++ + ref]; 168 out[outPos] = out[outPos++ + ref]; 169 out[outPos] = out[outPos++ + ref]; 170 out[outPos] = out[outPos++ + ref]; 171 out[outPos] = out[outPos++ + ref]; 172 } 173 while (outPos < len) { 174 out[outPos] = out[outPos++ + ref]; 175 } 176 } 177 } while (outPos < outLen); 178 } 179 } 180 181 182 | Popular Tags |