/*
Copyright (c) 2000-2010, Dirk Krause
All rights reserved.

Redistribution and use in source and binary forms,
with or without modification, are permitted provided
that the following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.
* Redistributions in binary form must reproduce the above 
  opyright notice, this list of conditions and the following
  disclaimer in the documentation and/or other materials
  provided with the distribution.
* Neither the name of the Dirk Krause nor the names of
  contributors may be used to endorse or promote
  products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/

/**	@file dkof.h
	Output filtering.
	This module provides functions to use output
	filters (i.e. compression and encoding) and bit
	writing filters on top of
	a dk_stream_t.

	After opening an output filtering stream you
	can configure the filter cells for compression
	and encoding methods. Data written to the stream
	is passed to the highest filtering cell first.
	The output of each filtering cell is passed to
	the filtering cell one level below, output from
	the lowest filtering cell (level 0) is passed to
	the target stream.

	Unless otherwise stated, int functions in this module return a positive
	number to indicate success or a true condition, 0 to indicate an error
	or an unfullfilled condition.
	Pointer functions return valid pointers on success, NULL on error.
*/

#ifndef DK_OF_INCLUDED
#define DK_OF_INCLUDED 1

#include <dk.h>
#include <dktypes.h>

#if defined(EXTERN)
#undef EXTERN
#endif
#ifndef DK_OF_C
#if !DK_HAVE_PROTOTYPES
#define EXTERN extern
#else
#define EXTERN /* nix */
#endif
#else
#define EXTERN /* nix */
#endif

#if defined(__cplusplus)
extern "C" {
#endif



/**	Create new output filtering dk_stream_t on top
	of an existing stream. The resulting dk_stream_t
	must be released by calling dkof_close() after
	usage.
	@param	s	Existing dk_stream_t.
	@param	n	Number of filter cells (Filter cells
	have indices 0 ... n-1).
	@return	New dk_stream_t on success, NULL on error.
*/
EXTERN dk_stream_t *
dkof_open DK_PR((dk_stream_t *s, size_t n));



/**	Close/release dk_stream_t obtained from dkof_open().
	This function does not close the underlaying
	dk_stream_t (provided as parameter \a s to
	dkof_open()).
	@param	s	Output filtering stream to close.
*/
EXTERN void
dkof_close DK_PR((dk_stream_t *s));



/**	Set output filtering cell type.
	This function may be used only for streams created by dkof_open().
	@param	s	The output filtering stream.
	@param	i	Index of cell to configure (0...n-1).
	@param	t	Output filtering cell type (DK_OF_TYPE_...)
	@return	Flag to indicate success.
*/
EXTERN int
dkof_set DK_PR((dk_stream_t *s, size_t i, int t));



/**	Set maximum line length for ASCII-Hex or ASCII85 encoded
	output.
	This function may be used only for streams created by dkof_open().
	@param	s	Output filtering stream.
	@param	l	Maximum line length.
*/
EXTERN void
dkof_set_max_line_length DK_PR((dk_stream_t *s, size_t l));



/**	Execute the stream handler function.
	@param	a	API structure.
*/
EXTERN void
dkof_stream_fct DK_PR((dk_stream_api_t *a));



/**	Configure the use of CR-NL combination or simple NL.
	Some file types want carriage-newline combinations at line
	breaks, others want simple newlines.
	This function may be used only for streams created by dkof_open().
	@param	s	Output filtering stream to configure.
	@param	f	Flag to use CF-NL combination.
*/
EXTERN void
dkof_set_crnl DK_PR((dk_stream_t *s, int f));



/**	Configure finalizers for ASCII-Hex or ASCII85 encoded chunks.
	Some systems want ">" or "~>" finalizers for ASCII-Hex or
	ASCII85 encoded chunks, others don't.
	This function may be used only for streams created by dkof_open().
	@param	s	Output filtering stream to configure.
	@param	f	Flag to create finalizers.
*/
EXTERN void
dkof_set_finalizing DK_PR((dk_stream_t *s, int f));



/**	Start filtered chunk.
	@param	s	Output filtering stream.
	@return	Flag to indicate success.
*/
EXTERN int
dkof_start_chunk DK_PR((dk_stream_t *s));



/**	End filtered chunk.
	@param	s	Output filtering stream.
	@return	Flag to indicate success.
*/
EXTERN int
dkof_end_chunk DK_PR((dk_stream_t *s));



/**	Open bit shifter on top of a stream.
	A new bit shifter (dk_bitshift_t) is created in dynamically allocated
	memory. You must release the memory by calling dkof_bs_close()
	after usage.
	@param	s	The stream to write the bits to.
	@return	Pointer to new dk_bitshift_t.
*/
EXTERN dk_bitshift_t *
dkof_bs_open DK_PR((dk_stream_t *s));



/**	Release/close a bitshifter obtained from dkof_bs_open().
	@param	b	The bit shifter.
*/
EXTERN void
dkof_bs_close DK_PR((dk_bitshift_t *b));



/**	Write bits.
	The least significant \a n bits from \a c are written to the
	bit shifter.
	@param	b	The bit shifter.
	@param	c	Integer value containing the bits.
	@param	n	Number of bits
	@return	Flag to indicate success.
*/
EXTERN int
dkof_bs_put DK_PR((dk_bitshift_t *b,unsigned short c,unsigned short n));



/**	Flush bits.
	The bit shifters internal buffers are written to the underlaying
	stream. Unused bits in the last byte are zero-padded.
	@param	b	The bit shifter.
	@return	Flag to indicate success.
*/
EXTERN int
dkof_bs_flush DK_PR((dk_bitshift_t *b));



/**	Check whether or not LZW compression is available.
	@return	1=yes, 0=no.
*/
EXTERN int
dkof_lzw_available DK_PR((void));

#if defined(__cplusplus)
}
#endif

/** Output filter cell type: No filtering at all */
#define DK_OF_TYPE_NONE		0

/** Output filter cell type: Buffering to chunks of 512 bytes */
#define DK_OF_TYPE_BUFFERED	1

/** Output filter cell type: ASCII85 encoding */
#define DK_OF_TYPE_ASCII85	2

/** Output filter cell type: Flate compression */
#define DK_OF_TYPE_FLATE	3

/** Output filter cell type: ASCII-Hex encoding */
#define DK_OF_TYPE_ASCIIHEX	4

/** Output filter cell type: Run-length compression for PostScript */
#define DK_OF_TYPE_PSRL		5

/** Output filter cell type: LZW compression (not supported) */
#define DK_OF_TYPE_LZW		6

#endif
/* indef DK_OF_INCLUDED */



