/*
 * encvars.h
 *
 * Variables for the compressor
 */

#ifdef ALLOC_VARS
#	undef EXT
#	define EXT
#else
#   undef EXT
#   define EXT extern
#endif


/*
 * For the optimal parser
 *
 * Uses less memory if it's ushort, but then we're forcing the CPU
 * to do 16 bit operations.  
 *
 * Change this to ulong if you don't mind a small memory hit.
 * Also, if you make LOOK too large, this number may cause the
 * cost estimation to overflow; e.g. 10000 uncompressed symbols
 * @ 8 bits each > 65535 bits.
 */
typedef ulong		numbits_t;


/*
 * For the optimal parser
 */
typedef struct
{
	ulong			link;
	ulong			path;
	ulong			repeated_offset[NUM_REPEATED_OFFSETS];
	numbits_t		numbits;
} decision_node;


/*
 * 8 * max_position_slots(50) = 656
 */
#define MAX_MAIN_TREE_ELEMENTS 700

typedef struct
{
	/* "fake" window pointer, based on enc_RealMemWindow */
	byte				*enc_MemWindow;

	ulong				enc_window_size;

#ifdef MULTIPLE_SEARCH_TREES
	/* root node pointers for our search trees */
	ulong				*enc_tree_root;
#else /* !MULTIPLE_SEARCH_TREES */
	ulong				 enc_single_tree_root;
#endif /* MULTIPLE_SEARCH_TREES */

	/* "fake" start of left nodes */
	ulong				*enc_Left;

	/* "fake" start of right nodes */
	ulong				*enc_Right;

	/* bitwise outputting */
	ulong               enc_bitbuf;
	signed char			enc_bitcount;
    bool                enc_output_overflow;
    char                pad1[2];

	/* used to record literals and displacements */
	ulong               enc_literals;    /* current number of literals */
	ulong               enc_distances;   /* current number of displacements */
	ulong              *enc_DistData;		/* match displacement array */
	byte               *enc_LitData;     /* contains a character or a matchlength */
	byte               *enc_ItemType;  /* bitmap for whether it's a character or matchlength */
	ulong				enc_repeated_offset_at_literal_zero[NUM_REPEATED_OFFSETS];

	/*
	 * the last three match offsets (displacements) encoded, the most recent
	 * one being enc_last_matchpos_offset[0]. 
	 */
	ulong				enc_last_matchpos_offset[NUM_REPEATED_OFFSETS];

	/* used for optimal parsing */
	ulong               enc_matchpos_table[MAX_MATCH+1];

	/* current encoding position in data */
	ulong				enc_BufPos;

	/* lookup table for converting a match position into a slot */
	byte                enc_slot_table[1024];

	/* buffering the output data */
	byte                *enc_output_buffer_start; 
	byte                *enc_output_buffer_curpos; 
	byte                *enc_output_buffer_end; 
	ulong				enc_input_running_total;
	ulong				enc_bufpos_last_output_block;

	/* number of distinct position slots */
	ulong               enc_num_position_slots;

	/* misc */
	ulong               enc_file_size_for_translation;

	bool                enc_allocated_compression_memory;

    /* number of block splits for this 32K of uncompressed data */
    byte                enc_num_block_splits;

	/* the number of 1 bits in any given integer */
	byte				enc_ones[256];

	/* compression parameters */
	byte				enc_first_block;
	bool				enc_need_to_recalc_stats;
	bool				enc_first_time_this_group;
	ulong				enc_encoder_second_partition_size;
	ulong				enc_earliest_window_data_remaining;
	ulong				enc_bufpos_at_last_block;
	byte				*enc_input_ptr;
	long				enc_input_left;
	ulong				enc_instr_pos;

	/* for tree.c */
	ushort				*enc_tree_freq;
	ushort				*enc_tree_sortptr;
	byte				*enc_len;
	short				enc_tree_heap[MAX_MAIN_TREE_ELEMENTS + 2];
	ushort				enc_tree_leftright[2*(2*MAX_MAIN_TREE_ELEMENTS-1)];
	ushort				enc_tree_len_cnt[17];
	int					enc_tree_n;
	short				enc_tree_heapsize;
	char				enc_depth;

	ulong				enc_next_tree_create;
	ulong				enc_last_literals;
	ulong				enc_last_distances;
	decision_node		*enc_decision_node;

	/* trees */
	byte				enc_main_tree_len[MAX_MAIN_TREE_ELEMENTS+1];
	byte				enc_secondary_tree_len[NUM_SECONDARY_LENGTHS+1];

	ushort				enc_main_tree_freq[MAX_MAIN_TREE_ELEMENTS*2];
	ushort				enc_main_tree_code[MAX_MAIN_TREE_ELEMENTS];
	byte				enc_main_tree_prev_len[MAX_MAIN_TREE_ELEMENTS+1];

	ushort				enc_secondary_tree_freq[NUM_SECONDARY_LENGTHS*2];
	ushort				enc_secondary_tree_code[NUM_SECONDARY_LENGTHS];
	byte				enc_secondary_tree_prev_len[NUM_SECONDARY_LENGTHS+1];

	ushort				enc_aligned_tree_freq[ALIGNED_NUM_ELEMENTS*2];
	ushort				enc_aligned_tree_code[ALIGNED_NUM_ELEMENTS];
	byte				enc_aligned_tree_len[ALIGNED_NUM_ELEMENTS];
	byte				enc_aligned_tree_prev_len[ALIGNED_NUM_ELEMENTS];

	/* start of allocated window memory */
	byte				*enc_RealMemWindow;

	/* start of allocated left nodes */
	ulong				*enc_RealLeft;

	/* start of allocated right nodes */
	ulong				*enc_RealRight;

    /* # cfdata frames this folder */
    ulong               enc_num_cfdata_frames;

	/* misc */
    void                *enc_fci_data;

	PFNALLOC			enc_malloc;
	PFNFREE				enc_free;

	int FAR (DIAMONDAPI *enc_output_callback_function)(
		void *			pfol,
		unsigned char *	compressed_data,
		long			compressed_size,
		long			uncompressed_size
	);


} t_encoder_context;


/*
 * Declare arrays? 
 */

#ifdef ALLOC_VARS

/*
 * (1 << extra_bits[n])-1 
 */
const ulong enc_slot_mask[] =
{
	     0,      0,      0,      0,     1,       1,      3,      3,
	     7,      7,     15,     15,    31,      31,     63,     63,
	   127,    127,    255,    255,   511,     511,   1023,   1023,
	  2047,   2047,   4095,   4095,  8191,    8191,  16383,  16383,
	 32767,  32767,  65535,  65535, 131071, 131071, 131071, 131071,
	131071, 131071, 131071, 131071, 131071, 131071, 131071, 131071,
	131071, 131071, 131071
};

const byte enc_extra_bits[] =   
{
	0,0,0,0,1,1,2,2,
	3,3,4,4,5,5,6,6,
	7,7,8,8,9,9,10,10,
	11,11,12,12,13,13,14,14,
	15,15,16,16,17,17,17,17,
	17,17,17,17,17,17,17,17,
	17,17,17
};

#else

extern const ulong enc_slot_mask[];
extern const byte enc_extra_bits[];

#endif