Add LZW support for Teledisk 1.x advanced compressed files.

This commit is contained in:
OBattler
2024-07-08 03:18:26 +02:00
parent 0a8d98e913
commit db16f0f209
7 changed files with 876 additions and 9 deletions

View File

@@ -16,3 +16,6 @@
add_library(fdd OBJECT fdd.c fdc.c fdc_magitronic.c fdc_monster.c fdc_pii15xb.c
fdi2raw.c fdd_common.c fdd_86f.c fdd_fdi.c fdd_imd.c fdd_img.c fdd_pcjs.c
fdd_mfm.c fdd_td0.c)
add_subdirectory(lzw)
target_link_libraries(86Box lzw)

View File

@@ -42,6 +42,7 @@
#include <86box/fdd_86f.h>
#include <86box/fdd_td0.h>
#include <86box/fdc.h>
#include "lzw/lzw.h"
#define BUFSZ 512 /* new input buffer */
#define TD0_MAX_BUFSZ (1024UL * 1024UL * 4UL)
@@ -124,7 +125,9 @@ typedef struct td0_t {
uint8_t xdf_ordered_pos[256][2];
uint8_t interleave_ordered_pos[256][2];
uint8_t *lzw_buf;
uint8_t *imagebuf;
uint8_t *processed_buf;
} td0_t;
@@ -650,11 +653,20 @@ td0_initialize(int drive)
head_count = header[9];
if (header[0] == 't') {
td0_log("TD0: File is compressed\n");
disk_decode.fdd_file = dev->fp;
state_init_Decode(&disk_decode);
disk_decode.fdd_file_offset = 12;
state_Decode(&disk_decode, dev->imagebuf, TD0_MAX_BUFSZ);
if (((header[4] / 10) % 10) == 2) {
td0_log("TD0: File is compressed (TeleDisk 2.x, LZHUF)\n");
disk_decode.fdd_file = dev->fp;
state_init_Decode(&disk_decode);
disk_decode.fdd_file_offset = 12;
state_Decode(&disk_decode, dev->imagebuf, TD0_MAX_BUFSZ);
} else {
td0_log("TD0: File is compressed (TeleDisk 1.x, LZW)\n");
if (fseek(dev->fp, 12, SEEK_SET) == -1)
fatal("td0_initialize(): Error seeking to offet 12\n");
if (fread(dev->lzw_buf, 1, file_size - 12, dev->fp) != (file_size - 12))
fatal("td0_initialize(): Error reading LZW-encoded buffer\n");
LZWDecodeFile((char *) dev->imagebuf, (char *) dev->lzw_buf, NULL, file_size - 12);
}
} else {
td0_log("TD0: File is uncompressed\n");
if (fseek(dev->fp, 12, SEEK_SET) == -1)
@@ -1224,10 +1236,9 @@ td0_load(int drive, char *fn)
/* Allocate the processing buffers. */
i = 1024UL * 1024UL * 4UL;
dev->imagebuf = (uint8_t *) malloc(i);
memset(dev->imagebuf, 0x00, i);
dev->processed_buf = (uint8_t *) malloc(i);
memset(dev->processed_buf, 0x00, i);
dev->lzw_buf = (uint8_t *) calloc(1, i);
dev->imagebuf = (uint8_t *) calloc(1, i);
dev->processed_buf = (uint8_t *) calloc(1, i);
if (!td0_initialize(drive)) {
td0_log("TD0: Failed to initialize\n");
@@ -1268,6 +1279,8 @@ td0_close(int drive)
d86f_unregister(drive);
if (dev->lzw_buf)
free(dev->lzw_buf);
if (dev->imagebuf)
free(dev->imagebuf);
if (dev->processed_buf)

View File

@@ -0,0 +1,16 @@
#
# 86Box A hypervisor and IBM PC system emulator that specializes in
# running old operating systems and software designed for IBM
# PC systems and compatibles from 1981 through fairly recent
# system designs based on the PCI bus.
#
# This file is part of the 86Box distribution.
#
# CMake build script.
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2020-2021 David Hrdlička.
#
add_library(lzw STATIC lzwdecode.c lzwencode.c)

49
src/floppy/lzw/lzw.h Normal file
View File

@@ -0,0 +1,49 @@
/***************************************************************************
* Header for Lempel-Ziv-Welch Encoding and Decoding Library
*
* File : lzw.h
* Purpose : Provides prototypes for functions that use Lempel-Ziv-Welch
* coding to encode/decode files.
* Author : Michael Dipperstein
* Date : January 30, 2004
*
****************************************************************************
*
* LZW: An ANSI C Lempel-Ziv-Welch Encoding/Decoding Routines
* Copyright (C) 2005, 2007, 2014 by
* Michael Dipperstein (mdipperstein@gmail.com)
*
* This file is part of the lzw library.
*
* The lzw library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* The lzw library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
***************************************************************************/
#ifndef _LZW_H_
#define _LZW_H_
/***************************************************************************
* CONSTANTS
***************************************************************************/
/***************************************************************************
* PROTOTYPES
***************************************************************************/
/* encode inFile */
int LZWEncodeFile(char *dest, char *src, uint64_t *dst_len, uint64_t src_len);
/* decode inFile*/
int LZWDecodeFile(char *dest, char *src, uint64_t *dst_len, uint64_t src_len);
#endif /* ndef _LZW_H_ */

269
src/floppy/lzw/lzwdecode.c Normal file
View File

@@ -0,0 +1,269 @@
/***************************************************************************
* Lempel-Ziv-Welch Decoding Functions
*
* File : lzwdecode.c
* Purpose : Provides a function for decoding Lempel-Ziv-Welch encoded
* file streams
* Author : Michael Dipperstein
* Date : January 30, 2005
*
****************************************************************************
*
* LZW: An ANSI C Lempel-Ziv-Welch Encoding/Decoding Routines
* Copyright (C) 2005, 2007, 2014, 2017 by
* Michael Dipperstein (mdipperstein@gmail.com)
*
* This file is part of the lzw library.
*
* The lzw library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* The lzw library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
***************************************************************************/
/***************************************************************************
* INCLUDED FILES
***************************************************************************/
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "lzw.h"
#include "lzwlocal.h"
/***************************************************************************
* TYPE DEFINITIONS
***************************************************************************/
typedef struct
{
uint8_t suffixChar; /* last char in encoded string */
uint16_t prefixCode; /* code for remaining chars in string */
} decode_dictionary_t;
/***************************************************************************
* CONSTANTS
***************************************************************************/
/***************************************************************************
* MACROS
***************************************************************************/
/***************************************************************************
* GLOBAL VARIABLES
***************************************************************************/
/* dictionary of string the code word is the dictionary index */
static decode_dictionary_t dictionary[(MAX_CODES - FIRST_CODE)];
/***************************************************************************
* PROTOTYPES
***************************************************************************/
static uint8_t DecodeRecursive(unsigned int code, char **dest);
/* read encoded data */
static int GetCodeWord(char *src);
static uint16_t bufPos = 0x0000;
static uint16_t bufLen = 0x0000;
static uint32_t bufOutPos = 0x00000000;
/***************************************************************************
* FUNCTIONS
***************************************************************************/
/***************************************************************************
* Function : LZWDecodeFile
* Description: This routine reads an input file 1 encoded string at a
* time and decodes it using the LZW algorithm.
* Parameters : fpIn - pointer to the open binary file to decode
* fpOut - pointer to the open binary file to write decoded
* output
* Effects : fpIn is decoded using the LZW algorithm with CODE_LEN codes
* and written to fpOut. Neither file is closed after exit.
* Returned : 0 for success, -1 for failure. errno will be set in the
* event of a failure.
***************************************************************************/
int
LZWDecodeFile_Internal(char *dest, char *src)
{
uint16_t nextCode; /* value of next code */
uint16_t lastCode; /* last decoded code word */
int code; /* code word to decode */
uint8_t c; /* last decoded character */
/* validate arguments */
if (dest == NULL) {
errno = ENOENT;
return -1;
}
bufPos = 0x0000;
bufOutPos = 0x00000000;
/* initialize for decoding */
nextCode = FIRST_CODE; /* code for next (first) string */
/* first code from file must be a character. use it for initial values */
lastCode = GetCodeWord(src);
c = lastCode;
*(dest++) = lastCode;
bufOutPos++;
/* decode rest of file */
while ((int)(code = GetCodeWord(src)) != EOF) {
if (code < nextCode) {
/* we have a known code. decode it */
c = DecodeRecursive(code, &dest);
} else {
/***************************************************************
* We got a code that's not in our dictionary. This must be due
* to the string + char + string + char + string exception.
* Build the decoded string using the last character + the
* string from the last code.
***************************************************************/
unsigned char tmp;
tmp = c;
c = DecodeRecursive(lastCode, &dest);
*(dest++) = tmp;
bufOutPos++;
}
/* if room, add new code to the dictionary */
if (nextCode < MAX_CODES) {
dictionary[nextCode - FIRST_CODE].prefixCode = lastCode;
dictionary[nextCode - FIRST_CODE].suffixChar = c;
nextCode++;
}
/* save character and code for use in unknown code word case */
lastCode = code;
}
return 0;
}
int
LZWDecodeFile(char *dest, char *src, uint64_t *dst_len, uint64_t src_len)
{
uint16_t size = 0x0000;
uint64_t pos = 0x0000000000000000ULL;
/* validate arguments */
if ((dest == NULL) || (src == NULL)) {
errno = ENOENT;
return -1;
}
if (dst_len != NULL)
*dst_len = 0x0000000000000000ULL;
while (1) {
size = *(uint16_t *) src;
src += 2;
bufLen = size;
size >>= 1;
if (bufLen & 1)
size++;
if (size > 0x1800)
return -1;
LZWDecodeFile_Internal(dest, src);
src += size;
dest += bufOutPos;
if (dst_len != NULL)
*dst_len += bufOutPos;
pos += (size + 2);
if ((size < 0x1800) || (pos >= src_len))
/* We have just decoded a block smaller than 0x3000 bytes,
this means this has been the last block, end. */
break;
}
return 0;
}
/***************************************************************************
* Function : DecodeRecursive
* Description: This function uses the dictionary to decode a code word
* into the string it represents and write it to the output
* file. The string is actually built in reverse order and
* recursion is used to write it out in the correct order.
* Parameters : code - the code word to decode
* fpOut - the file that the decoded code word is written to
* Effects : Decoded code word is written to a file
* Returned : The first character in the decoded string
***************************************************************************/
static uint8_t
DecodeRecursive(unsigned int code, char **dest)
{
unsigned char c;
unsigned char firstChar;
if (code >= FIRST_CODE) {
/* code word is string + c */
c = dictionary[code - FIRST_CODE].suffixChar;
code = dictionary[code - FIRST_CODE].prefixCode;
/* evaluate new code word for remaining string */
firstChar = DecodeRecursive(code, dest);
} else {
/* code word is just c */
c = code;
firstChar = code;
}
*((*dest)++) = c;
bufOutPos++;
return firstChar;
}
/***************************************************************************
* Function : GetCodeWord
* Description: This function reads and returns a code word from an
* encoded file. In order to deal with endian issue the
* code word is read least significant byte followed by the
* remaining bits.
* Parameters : fpIn - file containing the encoded data
* codeLen - number of bits in code word
* Effects : code word is read from encoded input
* Returned : The next code word in the encoded file. EOF if the end
* of file has been reached.
*
* NOTE: If the code word contains more than 16 bits, this routine should
* be modified to read in all the bytes from least significant to
* most significant followed by any left over bits.
***************************************************************************/
static int
GetCodeWord(char *src)
{
int code = 0;
static unsigned int realPos;
realPos = bufPos >> 1;
if (bufPos >= bufLen)
/* End of buffer. */
code = EOF;
else if (bufPos & 1)
/* Odd position. */
code = (((uint8_t) src[realPos] & 0xf0) >> 4) | ((uint8_t) src[realPos + 1] << 4);
else
/* Even position. */
code = ((uint8_t) src[realPos] & 0xff) | (((uint8_t) src[realPos + 1] & 0xf) << 8);
bufPos += 3;
return code;
}

454
src/floppy/lzw/lzwencode.c Normal file
View File

@@ -0,0 +1,454 @@
/***************************************************************************
* Lempel-Ziv-Welch Encoding Functions
*
* File : lzwencode.c
* Purpose : Provides a function for Lempel-Ziv-Welch encoding of file
* streams
* Author : Michael Dipperstein
* Date : January 30, 2005
*
****************************************************************************
*
* LZW: An ANSI C Lempel-Ziv-Welch Encoding/Decoding Routines
* Copyright (C) 2005, 2007, 2014, 2017 by
* Michael Dipperstein (mdipperstein@gmail.com)
*
* This file is part of the lzw library.
*
* The lzw library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* The lzw library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
***************************************************************************/
/***************************************************************************
* INCLUDED FILES
***************************************************************************/
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "lzw.h"
#include "lzwlocal.h"
/***************************************************************************
* TYPE DEFINITIONS
***************************************************************************/
/* node in dictionary tree */
typedef struct dict_node_t
{
unsigned int codeWord; /* code word for this entry */
unsigned char suffixChar; /* last char in encoded string */
unsigned int prefixCode; /* code for remaining chars in string */
/* pointer to child nodes */
struct dict_node_t *left; /* child with < key */
struct dict_node_t *right; /* child with >= key */
} dict_node_t;
/***************************************************************************
* CONSTANTS
***************************************************************************/
/***************************************************************************
* MACROS
***************************************************************************/
/***************************************************************************
* GLOBAL VARIABLES
***************************************************************************/
/***************************************************************************
* PROTOTYPES
***************************************************************************/
/* dictionary tree node create/free */
static dict_node_t *MakeNode(const unsigned int codeWord, const unsigned int prefixCode,
const unsigned char suffixChar);
static void FreeTree(dict_node_t *node);
/* searches tree for matching dictionary entry */
static dict_node_t *FindDictionaryEntry(dict_node_t *root, const int unsigned prefixCode,
const unsigned char c);
/* makes key from prefix code and character */
static unsigned int MakeKey(const unsigned int prefixCode, const unsigned char suffixChar);
/* write encoded data */
static int PutCodeWord(char *dest, int code);
static char *src_base;
static uint64_t src_length = 0x0000000000000000ULL;
static uint32_t bufPos = 0x00000000;
static uint32_t bufInPos = 0x00000000;
static int
is_eob(char *src)
{
return ((uint64_t) (uintptr_t) (src - src_base)) >= src_length;
}
static int
get_char(char **src)
{
int ret = EOF;
if (!is_eob(*src)) {
ret = (uint8_t) **src;
(*src)++;
}
return ret;
}
/***************************************************************************
* FUNCTIONS
***************************************************************************/
static int
LZWEncodeFile_Internal(char *dest, char *src)
{
unsigned int code; /* code for current string */
unsigned int nextCode; /* next available code index */
int c; /* character to add to string */
dict_node_t *dictRoot; /* root of dictionary tree */
dict_node_t *node; /* node of dictionary tree */
/* validate arguments */
if (src == NULL) {
errno = ENOENT;
return -1;
}
/* initialize dictionary as empty */
dictRoot = NULL;
nextCode = FIRST_CODE; /* code for next (first) string */
bufPos = 0x00000000;
bufInPos = 0x00000000;
/* now start the actual encoding process */
c = get_char(&src);
if (c == EOF)
return -1; /* empty file */
else {
bufInPos++;
code = c; /* start with code string = first character */
}
/* create a tree root from 1st 2 character string */
if ((c = get_char(&src)) != EOF) {
bufInPos++;
/* special case for NULL root */
dictRoot = MakeNode(nextCode, code, c);
if (dictRoot == NULL) {
perror("Making Dictionary Root");
return -1;
}
nextCode++;
/* write code for 1st char */
(void) PutCodeWord(dest, code);
/* new code is just 2nd char */
code = c;
}
/* now encode normally */
while ((c = get_char(&src)) != EOF) {
/* look for code + c in the dictionary */
node = FindDictionaryEntry(dictRoot, code, c);
if ((node->prefixCode == code) && (node->suffixChar == c))
/* code + c is in the dictionary, make it's code the new code */
code = node->codeWord;
else {
/* code + c is not in the dictionary, add it if there's room */
if (nextCode < MAX_CODES) {
dict_node_t *tmp = MakeNode(nextCode, code, c);
if (tmp == NULL) {
perror("Making Dictionary Node");
FreeTree(dictRoot);
return -1;
}
nextCode++;
if (MakeKey(code, c) < MakeKey(node->prefixCode, node->suffixChar))
node->left = tmp;
else
node->right = tmp;
}
/* write out code for the string before c was added */
if (PutCodeWord(dest, code))
break;
/* new code is just c */
code = c;
}
bufInPos++;
}
/* no more input. write out last of the code. */
(void) PutCodeWord(dest, code);
/* free the dictionary */
FreeTree(dictRoot);
return (c == EOF) ? 1 : 0;
}
/***************************************************************************
* Function : LZWEncodeFile
* Description: This routine reads an input file 1 character at a time and
* writes out an LZW encoded version of that file.
* Parameters : fpIn - pointer to the open binary file to encode
* fpOut - pointer to the open binary file to write encoded
* output
* Effects : fpIn is encoded using the LZW algorithm with CODE_LEN codes
* and written to fpOut. Neither file is closed after exit.
* Returned : 0 for success, -1 for failure. errno will be set in the
* event of a failure.
***************************************************************************/
int
LZWEncodeFile(char *dest, char *src, uint64_t *dst_len, uint64_t src_len)
{
uint64_t pos = 0x0000000000000000ULL;
/* validate arguments */
if ((dest == NULL) || (src == NULL)) {
errno = ENOENT;
return -1;
}
if (dst_len != NULL)
*dst_len = 0x0000000000000000ULL;
src_base = src;
src_length = src_len;
while (1) {
int ret = LZWEncodeFile_Internal(dest + 2, src);
if (ret == -1)
break;
*(uint16_t *) dest = bufPos;
if (bufPos & 1)
bufPos = (bufPos >> 1) + 1;
else
bufPos >>= 1;
dest += (bufPos + 2);
if (dst_len != NULL)
*dst_len += (bufPos + 2);
/* TODO: Why do we need this - 1 clunkfest? */
src += bufInPos;
pos += bufInPos;
if ((ret == 1) || (pos >= src_len) || (bufPos < 0x1800))
break;
}
return 0;
}
/***************************************************************************
* Function : MakeKey
* Description: This routine creates a simple key from a prefix code and
* an appended character. The key may be used to establish
* an order when building/searching a dictionary tree.
* Parameters : prefixCode - code for all but the last character of a
* string.
* suffixChar - the last character of a string
* Effects : None
* Returned : Key built from string represented as a prefix + char. Key
* format is {ms nibble of c} + prefix + {ls nibble of c}
***************************************************************************/
static unsigned int
MakeKey(const unsigned int prefixCode, const unsigned char suffixChar)
{
unsigned int key;
/* position ms nibble */
key = suffixChar & 0xF0;
key <<= MAX_CODE_LEN;
/* include prefix code */
key |= (prefixCode << 4);
/* inclulde ls nibble */
key |= (suffixChar & 0x0F);
return key;
}
/***************************************************************************
* Function : MakeNode
* Description: This routine creates and initializes a dictionary entry
* for a string and the code word that encodes it.
* Parameters : codeWord - code word used to encode the string prefixCode +
* suffixChar
* prefixCode - code for all but the last character of a
* string.
* suffixChar - the last character of a string
* Effects : Node is allocated for new dictionary entry
* Returned : Pointer to newly allocated node or NULL on error.
* errno will be set on an error.
***************************************************************************/
static dict_node_t *
MakeNode(const unsigned int codeWord, const unsigned int prefixCode, const unsigned char suffixChar)
{
dict_node_t *node;
node = malloc(sizeof(dict_node_t));
if (node != NULL) {
node->codeWord = codeWord;
node->prefixCode = prefixCode;
node->suffixChar = suffixChar;
node->left = NULL;
node->right = NULL;
}
return node;
}
/***************************************************************************
* Function : FreeTree
* Description: This routine will free all nodes of a tree rooted at the
* node past as a parameter.
* Parameters : node - root of tree to free
* Effects : frees allocated tree node from initial parameter down.
* Returned : none
***************************************************************************/
static void
FreeTree(dict_node_t *node)
{
if (node == NULL)
/* nothing to free */
return;
/* free left branch */
if (node->left != NULL)
FreeTree(node->left);
/* free right branch */
if (node->right != NULL)
FreeTree(node->right);
/* free root */
free(node);
}
/***************************************************************************
* Function : FindDictionaryEntry
* Description: This routine searches the dictionary tree for an entry
* with a matching string (prefix code + suffix character).
* If one isn't found, the parent node for that string is
* returned.
* Parameters : prefixCode - code for the prefix of string
* c - last character in string
* Effects : None
* Returned : If string is in dictionary, pointer to node containing
* string, otherwise pointer to suitable parent node. NULL
* is returned for an empty tree.
***************************************************************************/
static dict_node_t *
FindDictionaryEntry(dict_node_t *root, const int unsigned prefixCode, const unsigned char c)
{
unsigned int searchKey, key;
if (root == NULL)
return NULL;
searchKey = MakeKey(prefixCode, c); /* key of string to find */
while (1) {
/* key of current node */
key = MakeKey(root->prefixCode, root->suffixChar);
if (key == searchKey)
/* current node contains string */
return root;
else if (searchKey < key) {
if (root->left != NULL)
/* check left branch for string */
root = root->left;
else
/* string isn't in tree, it can be added as a left child */
return root;
} else {
if (root->right != NULL)
/* check right branch for string */
root = root->right;
else
/* string isn't in tree, it can be added as a right child */
return root;
}
}
}
/***************************************************************************
* Function : PutCodeWord
* Description: This function writes a code word from to an encoded file.
* In order to deal with endian issue the code word is
* written least significant byte followed by the remaining
* bits.
* Parameters : bfpOut - bit file containing the encoded data
* code - code word to add to the encoded data
* codeLen - length of the code word
* Effects : code word is written to the encoded output
* Returned : EOF for failure, ENOTSUP unsupported architecture,
* otherwise the number of bits written. If an error occurs
* after a partial write, the partially written bits will not
* be unwritten.
***************************************************************************/
static int
PutCodeWord(char *dest, int code)
{
static unsigned int realPos;
int ret = 0;
if (bufPos >= 0x3000)
ret = -1;
else {
realPos = bufPos >> 1;
if (bufPos & 1) {
/* Odd position. */
dest[realPos] = (dest[realPos] & 0x0f) | ((code << 4) & 0xf0);
dest[realPos + 1] = (code >> 4) & 0xff;
} else {
/* Even position. */
dest[realPos] = code & 0xff;
dest[realPos + 1] = ((code >> 8) & 0x0f);
}
bufPos += 3;
if (bufPos >= 0x3000)
ret = 1;
}
return ret;
}

63
src/floppy/lzw/lzwlocal.h Normal file
View File

@@ -0,0 +1,63 @@
/***************************************************************************
* Header for Lempel-Ziv-Welch Encoding and Decoding Library
*
* File : lzwlocal.h
* Purpose : Provides constant definitions for functions values used within
* the functions for Lempel-Ziv-Welch encoding/decoding.
* Author : Michael Dipperstein
* Date : February 22, 2015
*
****************************************************************************
*
* LZW: An ANSI C Lempel-Ziv-Welch Encoding/Decoding Routines
* Copyright (C) 2015 by
* Michael Dipperstein (mdipperstein@gmail.com)
*
* This file is part of the lzw library.
*
* The lzw library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* The lzw library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
***************************************************************************/
#ifndef _LZWLOCAL_H_
#define _LZWLOCAL_H_
/***************************************************************************
* INCLUDED FILES
***************************************************************************/
#include <stdio.h>
#include <limits.h>
/***************************************************************************
* CONSTANTS
***************************************************************************/
#define MIN_CODE_LEN 12 /* min # bits in a code word */
#define MAX_CODE_LEN 12 /* max # bits in a code word */
#define FIRST_CODE (1 << CHAR_BIT) /* value of 1st string code */
#define MAX_CODES (1 << MAX_CODE_LEN)
#if (MIN_CODE_LEN <= CHAR_BIT)
#error Code words must be larger than 1 character
#endif
#if ((MAX_CODES - 1) > INT_MAX)
#error There cannot be more codes than can fit in an integer
#endif
/***************************************************************************
* MACROS
***************************************************************************/
#define CURRENT_MAX_CODES(bits) ((unsigned int)(1 << (bits)))
#endif /* ndef _LZWLOCAL_H_ */