1 | /* |
1 | /* |
2 | * Copyright (c) 2000-2002 Marc Alexander Lehmann <pcg@goof.com> |
2 | * Copyright (c) 2000-2003 Marc Alexander Lehmann <pcg@goof.com> |
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, |
… | |
… | |
66 | * |
66 | * |
67 | */ |
67 | */ |
68 | |
68 | |
69 | unsigned int |
69 | unsigned int |
70 | lzf_compress (const void *const in_data, unsigned int in_len, |
70 | lzf_compress (const void *const in_data, unsigned int in_len, |
71 | void *out_data, unsigned int out_len) |
71 | void *out_data, unsigned int out_len |
|
|
72 | #if LZF_STATE_ARG |
|
|
73 | , LZF_STATE *htab |
|
|
74 | #endif |
|
|
75 | ) |
72 | { |
76 | { |
73 | const u8 *htab[HSIZE]; |
77 | #if !LZF_STATE_ARG |
|
|
78 | LZF_STATE htab; |
|
|
79 | #endif |
74 | const u8 **hslot; |
80 | const u8 **hslot; |
75 | const u8 *ip = in_data; |
81 | const u8 *ip = (const u8 *)in_data; |
76 | u8 *op = out_data; |
82 | u8 *op = (u8 *)out_data; |
77 | const u8 *in_end = ip + in_len; |
83 | const u8 *in_end = ip + in_len; |
78 | u8 *out_end = op + out_len; |
84 | u8 *out_end = op + out_len; |
79 | const u8 *ref; |
85 | const u8 *ref; |
80 | |
86 | |
81 | unsigned int hval = FRST (ip); |
87 | unsigned int hval = FRST (ip); |
… | |
… | |
89 | for (hslot = htab; hslot < htab + HSIZE; hslot++) |
95 | for (hslot = htab; hslot < htab + HSIZE; hslot++) |
90 | *hslot++ = ip; |
96 | *hslot++ = ip; |
91 | # endif |
97 | # endif |
92 | #endif |
98 | #endif |
93 | |
99 | |
94 | do |
100 | for (;;) |
95 | { |
101 | { |
|
|
102 | if (ip < in_end - 2) |
|
|
103 | { |
96 | hval = NEXT (hval, ip); |
104 | hval = NEXT (hval, ip); |
97 | hslot = htab + IDX (hval); |
105 | hslot = htab + IDX (hval); |
98 | ref = *hslot; *hslot = ip; |
106 | ref = *hslot; *hslot = ip; |
99 | |
107 | |
100 | if (1 |
108 | if (1 |
101 | #if INIT_HTAB && !USE_MEMCPY |
109 | #if INIT_HTAB && !USE_MEMCPY |
102 | && ref < ip /* the next test will actually take care of this, but it is faster */ |
110 | && ref < ip /* the next test will actually take care of this, but this is faster */ |
103 | #endif |
111 | #endif |
104 | && (off = ip - ref - 1) < MAX_OFF |
112 | && (off = ip - ref - 1) < MAX_OFF |
105 | && ip + 4 < in_end |
113 | && ip + 4 < in_end |
106 | && ref > (u8 *)in_data |
114 | && ref > (u8 *)in_data |
107 | #if STRICT_ALIGN |
115 | #if STRICT_ALIGN |
108 | && ref[0] == ip[0] |
116 | && ref[0] == ip[0] |
109 | && ref[1] == ip[1] |
117 | && ref[1] == ip[1] |
110 | && ref[2] == ip[2] |
118 | && ref[2] == ip[2] |
111 | #else |
119 | #else |
112 | && *(u16 *)ref == *(u16 *)ip |
120 | && *(u16 *)ref == *(u16 *)ip |
113 | && ref[2] == ip[2] |
121 | && ref[2] == ip[2] |
114 | #endif |
122 | #endif |
115 | ) |
123 | ) |
116 | { |
124 | { |
117 | /* match found at *ref++ */ |
125 | /* match found at *ref++ */ |
118 | unsigned int len = 2; |
126 | unsigned int len = 2; |
119 | unsigned int maxlen = in_end - ip - len; |
127 | unsigned int maxlen = in_end - ip - len; |
120 | maxlen = maxlen > MAX_REF ? MAX_REF : maxlen; |
128 | maxlen = maxlen > MAX_REF ? MAX_REF : maxlen; |
121 | |
129 | |
122 | do |
130 | do |
123 | len++; |
131 | len++; |
124 | while (len < maxlen && ref[len] == ip[len]); |
132 | while (len < maxlen && ref[len] == ip[len]); |
125 | |
133 | |
126 | if (op + lit + 1 + 3 >= out_end) |
134 | if (op + lit + 1 + 3 >= out_end) |
127 | return 0; |
135 | return 0; |
128 | |
136 | |
129 | if (lit) |
137 | if (lit) |
130 | { |
138 | { |
131 | *op++ = lit - 1; |
139 | *op++ = lit - 1; |
132 | lit = -lit; |
140 | lit = -lit; |
133 | do |
141 | do |
134 | *op++ = ip[lit]; |
142 | *op++ = ip[lit]; |
135 | while (++lit); |
143 | while (++lit); |
136 | } |
144 | } |
137 | |
145 | |
138 | len -= 2; |
146 | len -= 2; |
139 | ip++; |
147 | ip++; |
140 | |
148 | |
141 | if (len < 7) |
149 | if (len < 7) |
142 | { |
150 | { |
143 | *op++ = (off >> 8) + (len << 5); |
151 | *op++ = (off >> 8) + (len << 5); |
144 | } |
152 | } |
145 | else |
153 | else |
146 | { |
154 | { |
147 | *op++ = (off >> 8) + ( 7 << 5); |
155 | *op++ = (off >> 8) + ( 7 << 5); |
148 | *op++ = len - 7; |
156 | *op++ = len - 7; |
149 | } |
157 | } |
150 | |
158 | |
151 | *op++ = off; |
159 | *op++ = off; |
152 | |
160 | |
153 | #if ULTRA_FAST |
161 | #if ULTRA_FAST |
154 | ip += len; |
162 | ip += len; |
155 | hval = FRST (ip); |
163 | hval = FRST (ip); |
156 | hval = NEXT (hval, ip); |
164 | hval = NEXT (hval, ip); |
157 | htab[IDX (hval)] = ip; |
165 | htab[IDX (hval)] = ip; |
158 | ip++; |
166 | ip++; |
159 | #else |
167 | #else |
160 | do |
168 | do |
161 | { |
169 | { |
162 | hval = NEXT (hval, ip); |
170 | hval = NEXT (hval, ip); |
163 | htab[IDX (hval)] = ip; |
171 | htab[IDX (hval)] = ip; |
|
|
172 | ip++; |
|
|
173 | } |
|
|
174 | while (len--); |
|
|
175 | #endif |
|
|
176 | continue; |
|
|
177 | } |
|
|
178 | } |
|
|
179 | else if (ip == in_end) |
|
|
180 | break; |
|
|
181 | |
|
|
182 | /* one more literal byte we must copy */ |
|
|
183 | lit++; |
164 | ip++; |
184 | ip++; |
165 | } |
|
|
166 | while (len--); |
|
|
167 | #endif |
|
|
168 | } |
|
|
169 | else |
|
|
170 | { |
|
|
171 | /* one more literal byte we must copy */ |
|
|
172 | lit++; |
|
|
173 | ip++; |
|
|
174 | |
185 | |
175 | if (lit == MAX_LIT) |
186 | if (lit == MAX_LIT) |
176 | { |
187 | { |
177 | if (op + 1 + MAX_LIT >= out_end) |
188 | if (op + 1 + MAX_LIT >= out_end) |
178 | return 0; |
189 | return 0; |
179 | |
190 | |
180 | *op++ = MAX_LIT - 1; |
191 | *op++ = MAX_LIT - 1; |
181 | #if USE_MEMCPY |
192 | #if USE_MEMCPY |
182 | memcpy (op, ip - MAX_LIT, MAX_LIT); |
193 | memcpy (op, ip - MAX_LIT, MAX_LIT); |
183 | op += MAX_LIT; |
194 | op += MAX_LIT; |
184 | lit = 0; |
195 | lit = 0; |
185 | #else |
196 | #else |
186 | lit = -lit; |
197 | lit = -lit; |
187 | do |
198 | do |
188 | *op++ = ip[lit]; |
199 | *op++ = ip[lit]; |
189 | while (++lit); |
200 | while (++lit); |
190 | #endif |
201 | #endif |
191 | } |
202 | } |
192 | } |
|
|
193 | } |
203 | } |
194 | while (ip < in_end); |
|
|
195 | |
204 | |
196 | if (lit) |
205 | if (lit) |
197 | { |
206 | { |
198 | if (op + lit + 1 >= out_end) |
207 | if (op + lit + 1 >= out_end) |
199 | return 0; |
208 | return 0; |