/* File: huffman.h
   Author: David Bourgin (David.Bourgin@ufrima.imag.fr)
   Creation date: 7/2/94
   Last update: 24/7/95
   Purpose: Example of Huffman encoding with a file source to compress.
   Attention: The compiler must have been configured for a stack of at least
   20 kb.
*/

#ifndef _HUFFMAN_H_
#define _HUFFMAN_H_

#define _DEV_   /* Development stage. #undef it when running on target */

/* Error codes returned to the caller */
#define NO_ERROR      0
#define BAD_FILE_NAME 1
#define BAD_ARGUMENT  2
#define BAD_MEM_ALLOC 3

/* Useful constants */
#define FALSE 0
#define TRUE  1
#define NOT_A_LEAF 257

/* Double NUM_BITS if the file to compress is very large */
/* Change the other values accordingly */
#define NUM_BITS  8
#define NUM_BITS_MIN_ONE  7
#define NUM_BITS_PLUS_ONE 9


/* Global variables */
FILE *source_file,*dest_file, *code_file;


/* Binary tree structure */

/* byte has the value of the node itself. For a Huffman tree:
   If 0 < byte < 255, it's a character, i.e. a leaf of the tree.
   If byte = NOT_A_LEAF, it's a node of the tree.
*/
typedef struct s_tree 
{ 
  unsigned int byte;  /* A byte has to be coded as an unsigned integer */
                      /* to allow  a node to have a value over 255 */
#ifdef _ENCODER_
 unsigned int weight;
#endif

 struct s_tree  *left_ptr, /* Branches of the node */
                *right_ptr;
} t_tree,*p_tree;


#define NODE_BYTE(ptr_tree)       ((ptr_tree)->byte)
#define WEIGHT_OF_NODE(ptr_tree)  ((ptr_tree)->weight)
#define LEFT_BRANCH(ptr_tree)     ((ptr_tree)->left_ptr)
#define RIGHT_BRANCH(ptr_tree)    ((ptr_tree)->right_ptr)

/* Structure which describes a code */
typedef struct
{ 
  unsigned char bits[ NUM_BITS ];       /* Code value  */
  unsigned int bits_nb;                 /* Code length */
#ifdef _DECODER_
  unsigned char presence;
#endif
} t_bin_val;


#define BITS(bin_val)     ((bin_val).bits)
#define LENGTH(bin_val)  ((bin_val).bits_nb)
#define BITS_AVAIL(x)       ((x).presence)
 /* Being that fgetc=EOF only after any access
	then 'stored_byte_status' is 'TRUE' if a byte has been stored with 'fgetc'
	or 'FALSE' if there's no valid byte not already read and not 
	handled in 'stored_byte_val' */
int stored_byte_status = FALSE;
int stored_byte_val;

/* Pseudo procedures */
#define beginning_of_data() \
{\
  (void)rewind(source_file);\
  stored_byte_status = FALSE;\
}

#define end_of_data() \
(\
  stored_byte_status ? FALSE :\
  !(stored_byte_status = ( (stored_byte_val = fgetc(source_file)) != EOF ))\
)

#define read_byte() \
(\
  stored_byte_status ? stored_byte_status = FALSE,\
                       (unsigned char)stored_byte_val :\
  (unsigned char)fgetc(source_file)\
)

#define write_byte(byte) \
(\
  (void)fputc((byte),dest_file)\
)



#endif /* _HUFFMAN_H */
