#ifdef HAVE_CONFIG_H # include "config.h" #endif #include /* * Finds a match for the bytes at the specified offset. */ static int get_match (const unsigned char *source, int ptr, int source_size, int *hash, int *size, int *pos) { int hash_value; hash_value = (int) (40543L * (int) ((((source [ptr] << 4) ^ source [ptr + 1]) << 4) ^ source [ptr + 2]) >> 4) & 0xfff; *pos = hash [hash_value]; hash [hash_value] = ptr; if ((int) ((*pos != -1) && ((ptr - *pos)) < 4096U)) { for (*size = 0;; (*size)++) if ((*size >= 18) || ((int) (ptr + *size) >= source_size) || (source [ptr + *size] != source [*pos + *size])) break; return (int) (*size >= 3); } return 0; } int PLATON_FUNC(compress_lz_rle)(src, dst, src_size) const unsigned char *src; unsigned char *dst; int src_size; { static int Hash [4096]; int SymbolAddress; int Key; int Size; int Bit = 0; int Command = 0; int src_index = 0; int dst_size = 3; int HeaderIndex = 1; dst [0] = COMPRESS_LZ_RLE_COMPRESS; for (Key = 0; Key < 4096; Key++) Hash [Key] = -1; while ((src_index < src_size) && (dst_size <= src_size)) { if (Bit > 15) { dst [HeaderIndex] = (int) ((Command >> 8) & 0x00ff); dst [HeaderIndex + 1] = (int) ( Command & 0x00ff); HeaderIndex = dst_size; dst_size += 2; Bit = 0; } for (Size = 1;; Size++) if ((int) (src_index + Size) >= src_size || (src [src_index] != src [src_index + Size]) || (Size >= 0x0fff)) break; if (Size >= 16) { dst [dst_size++] = 0; dst [dst_size++] = (int) (((int) (Size - 16) >> 8) & 0x00ff); dst [dst_size++] = (int) ((Size - 16) & 0x00ff); dst [dst_size++] = src [src_index]; src_index += Size; Command = (Command << 1) + 1; } else if (get_match (src, src_index, src_size, Hash, &Size, &SymbolAddress) != 0) { Key = ((src_index - SymbolAddress) << 4) + (Size - 3); dst [dst_size++] = (int) ((Key >> 8) & 0x00ff); dst [dst_size++] = (int) (Key & 0x00ff); src_index += Size; Command = (Command << 1) + 1; } else { dst [dst_size++] = src [src_index++]; Command = (Command << 1); } Bit++; } Command <<= (16 - Bit); dst [HeaderIndex] = (int) ((Command >> 8) & 0x00ff); dst [HeaderIndex + 1] = (int) ( Command & 0x00ff); if (dst_size > src_size) { for (dst_size = 0; dst_size < src_size; dst_size++) dst [dst_size + 1] = src [dst_size]; dst [0] = COMPRESS_LZ_RLE_COPY; return (src_size + 1); } return (dst_size); } int PLATON_FUNC(uncompress_lz_rle)(src, dst, src_size) const unsigned char *src; unsigned char *dst; int src_size; { int SymbolAddress; int ChunkSize; int Counter; int Command = 0; int src_index = 1; int dst_size = 0; int Bit = 0; if (src [0] == COMPRESS_LZ_RLE_COPY) { for (dst_size = 1; dst_size < src_size; dst_size++) dst [dst_size - 1] = src [dst_size]; return (src_size - 1); } while (src_index < src_size) { if (Bit == 0) { Command = src [src_index++] << 8; Command += src [src_index++]; Bit = 16; } if (Command & 0x8000) { SymbolAddress = (int) (src [src_index++] << 4); SymbolAddress += (int) (src [src_index] >> 4); if (SymbolAddress) { ChunkSize = (int) (src [src_index++] & 0x0f) + 3; SymbolAddress = dst_size - SymbolAddress; for (Counter = 0; Counter < ChunkSize; Counter++) dst [dst_size++] = dst [SymbolAddress++]; } else { ChunkSize = (int) (src [src_index++] << 8); ChunkSize += (int) (src [src_index++] + 16); for (Counter = 0; Counter < ChunkSize; Counter++) dst [dst_size++] = src [src_index]; src_index++; } } else dst [dst_size++] = src [src_index++]; Command <<= 1; Bit--; } return (dst_size); }