1 | /* |
1 | /* |
2 | * Copyright (c) 2000-2003 Marc Alexander Lehmann <pcg@goof.com> |
2 | * Copyright (c) 2000-2005 Marc Alexander Lehmann <schmorp@schmorp.de> |
3 | * |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without modifica- |
4 | * Redistribution and use in source and binary forms, with or without modifica- |
5 | * tion, are permitted provided that the following conditions are met: |
5 | * tion, are permitted provided that the following conditions are met: |
6 | * |
6 | * |
7 | * 1. Redistributions of source code must retain the above copyright notice, |
7 | * 1. Redistributions of source code must retain the above copyright notice, |
… | |
… | |
44 | * don't play with this unless you benchmark! |
44 | * don't play with this unless you benchmark! |
45 | * decompression is not dependent on the hash function |
45 | * decompression is not dependent on the hash function |
46 | * the hashing function might seem strange, just believe me |
46 | * the hashing function might seem strange, just believe me |
47 | * it works ;) |
47 | * it works ;) |
48 | */ |
48 | */ |
|
|
49 | #ifndef FRST |
49 | #define FRST(p) (((p[0]) << 8) + p[1]) |
50 | # define FRST(p) (((p[0]) << 8) | p[1]) |
50 | #define NEXT(v,p) (((v) << 8) + p[2]) |
51 | # define NEXT(v,p) (((v) << 8) | p[2]) |
51 | #define IDX(h) ((((h ^ (h << 5)) >> (3*8 - HLOG)) + h*3) & (HSIZE - 1)) |
52 | # define IDX(h) ((((h ^ (h << 5)) >> (3*8 - HLOG)) - h*5) & (HSIZE - 1)) |
|
|
53 | //# define IDX(h) ((ip[0] * 121 ^ ip[1] * 33 ^ ip[2] * 1) & (HSIZE-1)) |
|
|
54 | #endif |
52 | /* |
55 | /* |
53 | * IDX works because it is very similar to a multiplicative hash, e.g. |
56 | * IDX works because it is very similar to a multiplicative hash, e.g. |
54 | * (h * 57321 >> (3*8 - HLOG)) |
57 | * ((h * 57321 >> (3*8 - HLOG)) & (HSIZE - 1)) |
|
|
58 | * the latter is also quite fast on newer CPUs, and compresses similarly. |
|
|
59 | * |
55 | * the next one is also quite good, albeit slow ;) |
60 | * the next one is also quite good, albeit slow ;) |
56 | * (int)(cos(h & 0xffffff) * 1e6) |
61 | * (int)(cos(h & 0xffffff) * 1e6) |
57 | */ |
62 | */ |
58 | |
63 | |
59 | #if 0 |
64 | #if 0 |
60 | /* original lzv-like hash function */ |
65 | /* original lzv-like hash function, much worse and thus slower */ |
61 | # define FRST(p) (p[0] << 5) ^ p[1] |
66 | # define FRST(p) (p[0] << 5) ^ p[1] |
62 | # define NEXT(v,p) ((v) << 5) ^ p[2] |
67 | # define NEXT(v,p) ((v) << 5) ^ p[2] |
63 | # define IDX(h) ((h) & (HSIZE - 1)) |
68 | # define IDX(h) ((h) & (HSIZE - 1)) |
64 | #endif |
69 | #endif |
65 | |
70 | |
66 | #define MAX_LIT (1 << 5) |
71 | #define MAX_LIT (1 << 5) |
67 | #define MAX_OFF (1 << 13) |
72 | #define MAX_OFF (1 << 13) |
68 | #define MAX_REF ((1 << 8) + (1 << 3)) |
73 | #define MAX_REF ((1 << 8) + (1 << 3)) |
69 | |
74 | |
70 | /* |
75 | /* |
71 | * compressed format |
76 | * compressed format |
72 | * |
77 | * |
73 | * 000LLLLL <L+1> ; literal |
78 | * 000LLLLL <L+1> ; literal |
74 | * LLLOOOOO oooooooo ; backref L |
79 | * LLLooooo oooooooo ; backref L |
75 | * 111OOOOO LLLLLLLL oooooooo ; backref L+7 |
80 | * 111ooooo LLLLLLLL oooooooo ; backref L+7 |
76 | * |
81 | * |
77 | */ |
82 | */ |
78 | |
83 | |
79 | unsigned int |
84 | unsigned int |
80 | lzf_compress (const void *const in_data, unsigned int in_len, |
85 | lzf_compress (const void *const in_data, unsigned int in_len, |
81 | void *out_data, unsigned int out_len |
86 | void *out_data, unsigned int out_len |
82 | #if LZF_STATE_ARG |
87 | #if LZF_STATE_ARG |
83 | , LZF_STATE *htab |
88 | , LZF_STATE htab |
84 | #endif |
89 | #endif |
85 | ) |
90 | ) |
86 | { |
91 | { |
87 | #if !LZF_STATE_ARG |
92 | #if !LZF_STATE_ARG |
88 | LZF_STATE htab; |
93 | LZF_STATE htab; |
… | |
… | |
135 | /* match found at *ref++ */ |
140 | /* match found at *ref++ */ |
136 | unsigned int len = 2; |
141 | unsigned int len = 2; |
137 | unsigned int maxlen = in_end - ip - len; |
142 | unsigned int maxlen = in_end - ip - len; |
138 | maxlen = maxlen > MAX_REF ? MAX_REF : maxlen; |
143 | maxlen = maxlen > MAX_REF ? MAX_REF : maxlen; |
139 | |
144 | |
|
|
145 | if (op + lit + 1 + 3 >= out_end) |
|
|
146 | return 0; |
|
|
147 | |
140 | do |
148 | do |
141 | len++; |
149 | len++; |
142 | while (len < maxlen && ref[len] == ip[len]); |
150 | while (len < maxlen && ref[len] == ip[len]); |
143 | |
|
|
144 | if (op + lit + 1 + 3 >= out_end) |
|
|
145 | return 0; |
|
|
146 | |
151 | |
147 | if (lit) |
152 | if (lit) |
148 | { |
153 | { |
149 | *op++ = lit - 1; |
154 | *op++ = lit - 1; |
150 | lit = -lit; |
155 | lit = -lit; |
… | |
… | |
166 | *op++ = len - 7; |
171 | *op++ = len - 7; |
167 | } |
172 | } |
168 | |
173 | |
169 | *op++ = off; |
174 | *op++ = off; |
170 | |
175 | |
171 | #if ULTRA_FAST |
176 | #if ULTRA_FAST || VERY_FAST |
172 | ip += len; |
177 | ip += len; |
|
|
178 | #if VERY_FAST && !ULTRA_FAST |
|
|
179 | --ip; |
|
|
180 | #endif |
173 | hval = FRST (ip); |
181 | hval = FRST (ip); |
|
|
182 | |
174 | hval = NEXT (hval, ip); |
183 | hval = NEXT (hval, ip); |
175 | htab[IDX (hval)] = ip; |
184 | htab[IDX (hval)] = ip; |
176 | ip++; |
185 | ip++; |
|
|
186 | |
|
|
187 | #if VERY_FAST && !ULTRA_FAST |
|
|
188 | hval = NEXT (hval, ip); |
|
|
189 | htab[IDX (hval)] = ip; |
|
|
190 | ip++; |
|
|
191 | #endif |
177 | #else |
192 | #else |
178 | do |
193 | do |
179 | { |
194 | { |
180 | hval = NEXT (hval, ip); |
195 | hval = NEXT (hval, ip); |
181 | htab[IDX (hval)] = ip; |
196 | htab[IDX (hval)] = ip; |