| 211 | } |
| 212 | |
| 213 | void Compressor::pack(const UCHAR* input, UCHAR* output) const |
| 214 | { |
| 215 | /************************************** |
| 216 | * |
| 217 | * Compress a string into a sufficiently large area. |
| 218 | * Don't check nuttin' -- go for speed, man, raw SPEED! |
| 219 | * |
| 220 | **************************************/ |
| 221 | if (m_runs.isEmpty()) |
| 222 | { |
| 223 | // Perform raw byte copying instead of compressing |
| 224 | memcpy(output, input, m_length); |
| 225 | return; |
| 226 | } |
| 227 | |
| 228 | for (const auto length : m_runs) |
| 229 | { |
| 230 | if (length < 0) |
| 231 | { |
| 232 | const auto zipLength = (unsigned) -length; |
| 233 | |
| 234 | if (zipLength <= MAX_SHORT_RUN) |
| 235 | { |
| 236 | *output++ = (UCHAR) length; |
| 237 | } |
| 238 | else if (zipLength <= MAX_MEDIUM_RUN) |
| 239 | { |
| 240 | *output++ = (UCHAR) -1; |
| 241 | put_short(output, zipLength); |
| 242 | output += sizeof(USHORT); |
| 243 | } |
| 244 | else if (zipLength <= MAX_LONG_RUN) |
| 245 | { |
| 246 | *output++ = (UCHAR) -2; |
| 247 | put_long(output, zipLength); |
| 248 | output += sizeof(ULONG); |
| 249 | } |
| 250 | else |
| 251 | fb_assert(false); |
| 252 | |
| 253 | *output++ = *input; |
| 254 | input += zipLength; |
| 255 | } |
| 256 | else |
| 257 | { |
| 258 | fb_assert(length > 0 && length <= MAX_NONCOMP_RUN); |
| 259 | |
| 260 | *output++ = (UCHAR) length; |
| 261 | memcpy(output, input, length); |
| 262 | output += length; |
| 263 | input += length; |
| 264 | } |
| 265 | } |
| 266 | } |
| 267 | |
| 268 | ULONG Compressor::truncate(ULONG outLength) |
| 269 | { |