/* -*- C++ -*-  vim: set syntax=cpp:
 * (C) 2007-2008 Frank-Rene Schaefer  */
#ifndef  __QUEX_INCLUDE_GUARD__BUFFER__FILLER__CONVERTER__CONVERTER
#define  __QUEX_INCLUDE_GUARD__BUFFER__FILLER__CONVERTER__CONVERTER

#include <quex/code_base/definitions>
#include <quex/code_base/MemoryManager>

QUEX_NAMESPACE_MAIN_OPEN

typedef struct QUEX_SETTING_USER_CLASS_DECLARATION_EPILOG QUEX_NAME(Converter_tag) {
    E_Ownership   ownership;

    bool    (*convert)(struct QUEX_NAME(Converter_tag)*, 
                       uint8_t**             source, const uint8_t*             SourceEnd, 
                       QUEX_TYPE_CHARACTER** drain,  const QUEX_TYPE_CHARACTER* DrainEnd);
    /* Tries to convert all characters given in 'source' with the coding specified
     * earlier to _open(...). 'source' and 'drain' are passed as pointers to pointers
     * so that the pointers can be changed. This way the converter can inform the
     * user about the state of conversion from source to drain buffer.
     *
     * BEFORE:         *source              SourceEnd
     *                 |                    |
     *          [      .....................]   source buffer
     *
     *               *drain         DrainEnd
     *               |              |
     *          [....               ] drain buffer
     *
     *       At the beginning, 'source' points to the first character to be
     *       converted. 'drain' points to the place where the first converted
     *       character is to be written to.
     *  
     * AFTER:                          *source                              
     *                                 |     
     *          [                      .....]   source buffer
     *
     *                        *drain 
     *                        |      
     *          [.............      ] drain buffer
     *
     *       After conversion, 'source' points immediately behind the last 
     *       character that was subject to conversion. 'drain' points behind the
     *       last character that resulted from the conversion. 
     *  
     * RETURNS:  true  --> Drain buffer is filled as much as possible with converted 
     *                     characters.
     *           false --> More source bytes are needed to fill the drain buffer.     */

    ptrdiff_t (*stomach_byte_n)(struct QUEX_NAME(Converter_tag)*);
    void      (*stomach_clear)(struct QUEX_NAME(Converter_tag)*);
    /*  [OPTIONAL] can be set to '0x0'. 
     * 
     *  This function is called whenever a conversion discontinuity appears.
     *  Such cases appear only when the user navigates through the input
     *  stream (seek_character_index(...)), or with long pre-conditions when
     *  the buffer size is exceeded. 
     *
     *  For 'normal' converters this function can be set to '0x0'. If a converter
     *  has an internal 'statefulness' that is difficult to be tamed, then use
     *  this function to reset the converter. Actually, the initial reason
     *  for introducing the function pointer was the strange behavior of the 
     *  ICU Converters of IBM(R).                                                     */

    void    (*delete_self)(struct QUEX_NAME(Converter_tag)*);
    /* Closes the conversion handle produced with open(...).      
     * Deletes the object of the derived class.                                       */

    int     byte_n_per_character;
    /* Some encodings (such as UTF-8) occupy different number of bytes for different
     * characters. Others, such as ASCII or UCS-4 use the same number of bytes for
     * all characters of the character set. Using the flag, the buffer filler can
     * adapt the seek algorithm for navigation in the character stream.               */

    bool    virginity_f;

} QUEX_NAME(Converter);

QUEX_INLINE bool
QUEX_NAME(Converter_construct)(QUEX_NAME(Converter)* me,
                    const char* FromCodec, const char* ToCodec,
                    bool        (*open)(QUEX_NAME(Converter)*, 
                                        const char* FromCodingName, const char* ToCodingName),  
                    bool        (*convert)(QUEX_NAME(Converter)*, 
                                           uint8_t**             source, const uint8_t*             SourceEnd, 
                                           QUEX_TYPE_CHARACTER** drain,  const QUEX_TYPE_CHARACTER* DrainEnd),
                    void        (*delete_self)(QUEX_NAME(Converter)*),
                    ptrdiff_t   (*stomach_byte_n)(QUEX_NAME(Converter)*),
                    void        (*stomach_clear)(QUEX_NAME(Converter)*));


QUEX_NAMESPACE_MAIN_CLOSE

#endif /*  __QUEX_INCLUDE_GUARD__BUFFER__FILLER__CONVERTER__CONVERTER */
