/**
 * @file FLCBYT.h
 * @brief Specification for the FLUC byte interface
 * @author limes datentechnik gmbh
 * @date 01.03.2016
 * @copyright (c) 2016 limes datentechnik gmbh
 *
 * @mainpage FLUC Byte Interface
 *
 * This interface provides stream-, block-, record- or element-oriented
 * sequential read and write access to original files. Original files
 * can be binary, text or XML data sets as well as GZIP-, BZIP2-, XZ-,
 * PGP-, ZIP, FLAM4 files or any other kind of original local or remote
 * data stream format supported by FLAM. It includes all conversion and
 * formatting capabilities of the Frankenstein Limes Universal Converter
 * (FLUC). These conversion capabilities are also available as an
 * in-memory variant (fcbconv/runv/finv or fcbconp/runp/finp) without
 * file I/O.
 *
 * The byte interface provides functions similar to the byte-wise file
 * I/O functions in C. Only the file open function differs in that it
 * takes a filename string and a format string. You can specify them
 * using the syntax of our command line (FLCL). Instead of
 * <code>errno</code>, #fcberrno contains the FLAM return code.
 * #fcberrms() can be used instead of <code>strerror()</code>,
 * and the complete FLAM error trace can be fetched with #fcberrtr().
 * Additionally, this interface provides functions for getting help and
 * syntax information for the file and format string parameters.
 *
 * There is also a logging facility which causes log messages to be
 * collected in memory. These log messages can be queried when desired.
 *
 * Additionally, a set of conversion functions is available, which can
 * be used when accessing elements (format.element()), for example to
 * parse XML documents.
 *
 * There are also function for hash, MAC and HMAC calculations, base
 * encoding or decoding and a few other help function for example to
 * determine the amount of processed bytes or units (records or blocks).
 *
 * @section FILDEF File definition and format strings
 * When reading: Through the file definition string, you specify how the
 * read operation interprets and transforms your original data to produce
 * an internal neutral FLAM5 element list from it. The format string
 * describes how this element list will then be formatted for sequential
 * byte or record access. You also have the option of getting the raw
 * elements by specifying element formatting in the format string.
 *
 * When writing: The format string defines how the provided byte stream,
 * records or elements will be formatted into a FLAM5 element list. The
 * file definition string describes how this element list will be written
 * to a file. The converted data can be written to multiple targets in
 * parallel by specifying multiple I/Os through the OUTPUT object.
 * It is possible to specify multiple WRITE overlays or OUTPUT objects
 * to write the same data in different formats to different files,
 * reading the input only once.
 *
 * @section MBRWRT Write of multiple members to the same open file
 * To write more than one member to a ZIP archive or FLAMFILE
 * the functions #fcbnewmbr() and fcbnewmbr2() can be used. These functions
 * implement a reopen of the open file to append a new member. This is a lot
 * faster than to close the file and open it again with the append switch for
 * the next member.
 *
 * This will work for all kind of files (not only archives) and could
 * result in a concatenation or a bouquet of further files depending on
 * the input-output name mapping specified in the write string.
 *
 * The #fcbopen() describes the first member and for all other member of
 * this file you must call #fcbnewmbr(). Here you can provide a new format
 * and state string. If the new member is formated like the previous member,
 * the format string can be NULL. In this case the current formatting will be
 * reused. With #fcbnewmbr2 you have the possibility to get the interim
 * statistics buffer too.
 *
 * Here is the typical program sequence in pseudo code:
 * <pre>
 *    hdl=fcbopen("write.text(... archive.zip(member='[name]'))","format.text()","state(orgf='first.member.txt')");
 *    if (hdl==NULL) exit(1);
 *    fcbwrite(...,hdl);
 *    ...
 *    fcbwrite(...,hdl);
 *
 *    hdl=fcbnewmbr("format.record()","state(orgf='second.member.txt')");
 *    if (hdl==NULL) exit(2);
 *    fcbwrite(...,hdl);
 *    ...
 *    fcbwrite(...,hdl);
 *
 *    hdl=fcbnewmbr(NULL,"state(orgf='third.member.txt')");
 *    if (hdl==NULL) exit(3);
 *    ...
 *    ...
 *    ...
 *    fcbclose(hdl);
 * </pre>
 *
 * The member definition for the archive should contain an input output
 * name mapping, because the state string for each new member provides the
 * original file name (ORGF), which is mapped into the member name of the
 * archive.
 *
 * @section FORMAT Formatting
 * When reading or writing, you can define how to format the data (binary,
 * character, text, xml, ...), use different conversions (Base64, OpenPGP,
 * GZIP, CHRSET, ...) executed sequentially and different kinds of I/O
 * methods (block, record, text, FLAM4, ...). This means that you can read
 * and write compressed, encrypted and encoded files, where you can change
 * the character set and other things as part of the write and read operation.
 *
 * Through the format string, you specify how the data is transformed into
 * a sequential data stream, records or elements. For example, if the data
 * contains text, you can define which delimiter to add after each line,
 * which character set the output should be in. Please use the interactive
 * help function #fcbhelp() for more information.
 *
 * For stream-oriented data handling, you can choose between binary,
 * character, text and XML formatting. For read operations, you can use
 * the auto detection capabilities. For example:
 *
 * <pre>
 * fcbopen("read.file='filename'","format.record()")
 * </pre>
 *
 * This results in any kind of file (encoded, encrypted and/or
 * compressed) being converted to records. If the content is XML, then
 * the XML data is pretty printed into records. If it is text, then the
 * data is parsed based on the containing delimiters. If it is binary
 * and record lengths are detected, then the records are provided one by
 * one. If it is binary and no record lengths are known or detected, then
 * the data is wrapped into records.
 *
 * @subsection FMTREC Record formatting
 * If you use record formatting, then the read and write functions do
 * not operate like in stream-oriented I/O. Instead, the behavior is
 * more similar to the <code>fread()</code> and <code>fwrite()</code>
 * operations in z/OS with 'type=record', except that you can define
 * whether records are truncated (size>0) or a length error occurs
 * (size==0) of the provided buffer is too short. With size=-1 (SIZE_MAX),
 * there is also a zero-copy mode for optimized performance.
 *
 * The record formatting can be useful for normal text files to read
 * the text record-by-record without the delimiter and null termination
 * at the end (see #fcbputs() and #fcbgets()).
 *
 * @subsection FMTELM Element formatting
 * FLAM5 elements are parsed data elements with a type, a length, a value
 * and more. If the element data contains printable characters, then
 * these characters are encoded in UTF-8 by default, but can also be
 * converted as needed.
 *
 * With element formatting, you can read and write a serialized form of
 * FLAM5 elements. For example, it can be used to tokenize an XML document
 * and read these tokens (elements) for further processing. The
 * serialized element format is described by the struct #FlmElmRec0.
 *
 * @section ELMCNV Element conversion
 * When using element formatting, you can use several individual element
 * data conversion modules for per-element data conversion. If no converter
 * is used, the element data is simply copied into application memory to
 * build the element structure (#FlmElmRec0). A set of functions with 'v'
 * at the end of the function name can be used to set a custom element data
 * converter. A converter must be opened before using it, which can done by
 * calling #fcbopenv() with a corresponding conversion string. The conversion
 * string describes how the data is converted from the neutral format of a
 * FLAM5 element to the representation in the application memory (when
 * reading) or how the application memory must be interpreted to form the
 * corresponding neutral FLAM5 element data type (when writing). The functions
 * #fcbreadv() and #fcbwritev() accept an additional conversion handle as
 * parameter which was is obtained from #fcbopenv() to replace the default/standard
 * conversion. The #fcbreadv() and #fcbwritev() functions require to know the
 * data format that will be read in advance, which is not always the case.
 * Instead, you can also use the regular #fcbread() and #fcbwrite() functions
 * and use the function #fcbconv() to convert the data, if needed. In fact,
 * this function works on arbitrary data and may also be used independently.
 *
 * There is no limit on the amount of element converters that can be
 * opened. The output length of most converts can be controlled in two
 * ways: By passing appropriate length values in the conversion string or
 * or by passing a buffer of appropriate length at call time.
 *
 * The converter handle must be closed with #fcbclosev() to release all
 * associated resources.
 *
 * Some usage scenarios for element converters:
 * * Selective character conversion
 * * Number conversion from/to BCD/binary integer
 * * Removal of whitespace
 *
 * @section FMTTAB Table support
 * With version 5.1.16 of FLAM the table support was introduced.
 *
 * For the byte interface you can activate an end of table support if you read
 * from a file (file string). If you activate ENDOFT in the format string
 * at write and use #fcbstn() or auto detection in conjunction with an
 * output file name containing the processing rule [table], then you can
 * split the data in different files. But at read you have to handle FLMRTC_EOT
 * as well as FLMRTC_EOF if the switch ENDOFT is defined. If no data is read
 * the reason could be EOF or EOT. With EOT the next read gives the data
 * of the new table. At EOF you still get no data and still get EOF.
 *
 * If you activate ENDOFT at read you can use the new function #fcbgtn() to
 * get the name of the current table after #fcbopen() or after EOT was
 * recognized. This can be used to interpret the data correctly if more than
 * one table is in a file. Even the first read after open might give
 * no data and EOT in case the automatic detection needs more data to analyze
 * the correct format. Only further read calls will retrieve the data eventually.
 *
 * Depending on the block size in the block oriented approach a table
 * change (EOT) without data can also occur somewhere in the middle.
 * If block oriented reading is used it is important not to ignore this.
 *
 * If you want to write more than one table to a file, you can work with
 * the table format detection, but normally it is better to define the
 * table format with the new function #fcbstn(), before you provide the
 * data. If you set the table name then the data must match this table
 * format (row specification). The table format detection is disabled if
 * #fcbstn() is used. You can reactivate the automatic table detection
 * at write with a call to #fcbgtn().
 *
 * Setting of the table name only works if no remainder is in the buffer.
 * If a block oriented write method is used, it is required that the last row
 * is complete before using #fcbstn().
 *
 * If the record oriented write method is used, each record
 * must fit within the current table format. In this case a remainder in
 * the buffer is not possible. Usually we recommend the record oriented
 * approach to read and write tables.
 *
 * @section ENVVAR Environment variables
 * For all default character conversions, it is useful to set the environment
 * variable LANG. Other used environment variables of FLAM can be found
 * in the FLCL manual. With version 5.1.19 a new function was introduced
 * (#fcbenv()) to load the FLAM environment . This function can be used
 * before the first API call to establish the same environment used by
 * FLAM utilities, subsystems and so on. This give the application
 * developer the possibility to adjust the environment before the first
 * real call is done. Until version 5.1.18, each opening function has
 * read the system variables on z/OS. This is now part of the #fcbenv()
 * function to give complete control about the environment to users of
 * the API. To fetch a symbol from the environment, the function
 * #fcbsym() can be used.
 *
 * @section CODPGE Special EBCDIC code page support
 * On system using EBCDIC a special support for critical punctuation
 * characters was implemented (see FLCL manual). This support converts
 * the several punctuation character from a certain EBCDIC code page
 * to the local character set defined over the LANG variable (if LANG
 * not defined the default is 1047). Below you can find the list of
 * character with different code points in the different supported EBCDIC
 * code pages, which are part of the first 128 Unicode code points.
 *
 * <pre>
 *    CRITICAL PUNCTUATION CHARACTERS:
 *       ! $ # @ [ \\ ] ^ ` { | } ~
 *    SUPPORTED EBCDIC CODE PAGES FOR COMMAND ENTRY:
 *       "IBM-1140","IBM-1141","IBM-1142","IBM-1143",
 *       "IBM-1144","IBM-1145","IBM-1146","IBM-1147",
 *       "IBM-1148","IBM-1149","IBM-1153","IBM-1154",
 *       "IBM-1156","IBM-1122","IBM-1047","IBM-924",
 *       "IBM-500","IBM-273","IBM-037","IBM-875","IBM-424",
 *       "IBM-277","IBM-278","IBM-280","IBM-284","IBM-285",
 *       "IBM-297","IBM-871","IBM-870","IBM-1025","IBM-1112",
 *       "IBM-1157"
 * </pre>
 *
 * This conversion is required to interpret the command syntax correctly.
 * These CLP strings are the major part used by this interface. To work
 * with this API the user must build such CLP string. For this often
 * literals are used. On EBCDIC systems you can define in which CCSID
 * (code page) the literals are provided by the compiler. For example,
 * in C/C++ the default, if the CONVLIT() parameter not defined, is no
 * conversion, this means that 1047 is normally used.
 *
 * Your application could get variables from outside (e.g. file names)
 * in the local character set (e.g. 1141). Your literals are in 1047 and
 * you must build a CLP string with literals and variables. To support
 * this kind of inconsistent code pages (since version 5.1.19 of FLAM)
 * escape sequences (\&xxx;) the CCSID areas (\&nnnn;...\&nnnn;) are supported
 * (see FLCL manual). Below you can find two examples for a CLP info
 * command how to use it.
 *
 * <pre>
 *    snprintf(acClp,sizeof(acClp),"get.file='&TLD;/mydata.bin'")
 *    snprintf(acClp,sizeof(acClp),"&1047;get.file='&0000;%s;&1047;'",fn)
 * </pre>
 *
 * An unsupported CCSID (e.g. 0) can be used to define the local character
 * set as code page (default case). To get an area for the literal code
 * page you must add a CCSID escape sequence (&1047;). If you have a
 * variable part, you must switch to the local character set (&0000;) or
 * the correct CCSID for this variable and if the literal continued
 * switch back to the literal CCSID (&1047;). If you need such moving
 * characters in your literals you can use the corresponding escape
 * sequence for it. Below you can find all escape sequences for the
 * critical punctuation characters.
 *
 * <pre>
 *    ! = \&EXC;   - Exclamation mark
 *    $ = \&DLR;   - Dollar sign
 *    # = \&HSH;   - Hashtag (number sign)
 *    @ = \&ATS;   - At sign
 *    [ = \&SBO;   - Square bracket open
 *    \\ = \&BSL;   - Backslash
 *    ] = \&SBC;   - Square bracket close
 *    ^ = \&CRT;   - Caret (circumflex)
 *    ` = \&GRV;   - Grave accent
 *    { = \&CBO;   - Curly bracket open
 *    | = \&VBR;   - Vertical bar
 *    } = \&CBC;   - Curly bracket close
 *    ~ = \&TLD;   - Tilde
 * </pre>
 *
 * This two feature gives you the possibility to build CLP strings
 * Independent of the EBCDIC code page used for literals and as local
 * or system character set.
 *
 * @section INFCMD Info command
 * The interface also provides access to the info command. #fcbinfo()
 * can be used, for example, to get information about files and supported
 * CCSIDs.
 *
 * @section HASHMAC Hash, HMAC and MAC calculations with clear keys
 * The byte interface provides a set of function to calculate hash, MAC
 * and HMAC values. #fcbhini(), #fcbhadd() and #fcbhfin() can be used to
 * calculate a checksum of multiple consecutive buffers of the data.
 * #fcbhash() does the same, but processes only a single buffer and returns
 * the result.
 *
 * @section BASEENCDEC Base encoding decoding
 * There is a set of functions to encode and decode binary data to/from
 * base64/32/16. #fcbbini(), #fcbbrun() and #fcbbfin() can be used to
 * convert multiple consecutive buffers of data whereas #fcbbase()
 * converts a single buffer of data independent from previous calls.
 *
 * @section STATS Statistics
 * There are some additional open and close functions available that
 * take a few more parameters. With #fcbopen2() the internal state of FLUC
 * can be accessed after an open for read and set before open for write.
 * This is required to set the file attributes of the source in archive
 * headers like GZIP, PGP and FLAM. #fcbclose2() returns the statistics
 * information collected by FLUC.
 *
 * @section THREAD Thread-safety
 * The byte interface is thread-safe on all supported platforms except
 * USS on zSeries. On classical mainframe operating systems like z/OS,
 * threads are not supported but the interface is in general reentrant
 * and can be used in parallel by different processes. The compiler
 * switch <code>DEFINE(\__HOST\__)</code> or <code>DEFINE(\__USS\__)</code>
 * must be defined on z/OS systems.
 *
 * @section ZOSHNT Hints for z/OS
 * To use empty parameter list (#fcberrtr()) and fix integer data types
 * the language level on z/OS must at minimum C99. Additionally, the long
 * name support and DLL usage must be activated.
 *
 * <pre>
 * LANG(EXTC99),LO,DLL
 * </pre>
 *
 * We recommend to use application-specific runtime option defaults with
 * the CEEUOPT assembler language source program to establish application
 * default options. You can find the recommended runtime options as member
 * CEEUOPTx (x=3 for 31 bit and x=6 for 64 bit applications) in the
 * hlq.FLAM.SRCLIB partitioned dataset.
 *
 * @section SAMPLE Sample programs
 * Several sample program in C with name SCFCBCPY/ELM/DOM can be found as
 * part of the installation package for mainframe systems in the library
 * SRCLIBC(SCFCBCPY/ELM/DOM), with the corresponding compile and link step in
 * JOBLIB(SBUILD). For other platforms (Windows, UNIX) the sample program
 * source of SCFCBCPY/ELM/DOM is located in the 'sample' directory and the compile
 * and link procedures can be found in the Makefile of the same directory.
 *
 * * SCFCBCPY: Makes byte interface available as utility (you can define all 4 #fcbopen() strings)
 * * SCFCBELM: Read a file and writes each element to an element dump list to STDOUT
 * * SCFCBDOM: This utility reads a XML file to a DOM tree and write the tree to STDOUT
 *
 **********************************************************************/

/*! @cond PRIVATE */
#ifdef __cplusplus
   extern "C" {
#endif

#ifndef INC_FLCBYT_H
#define INC_FLCBYT_H
 /*! @endcond */

/**********************************************************************/

#include <stddef.h>
#include <stdint.h>
#include "FLMRTC.h"
#include "FLMDEF.h"

/**********************************************************************/
/*! @cond PRIVATE */

#define FCB_READ_FILE               FLC_READ_FILE
#define FCB_READ_FORMAT             FLC_READ_FORMAT
#define FCB_WRITE_FILE              FLC_WRITE_FILE
#define FCB_WRITE_FORMAT            FLC_WRITE_FORMAT
#define FCB_CONV_READ               FLC_CONV_READ
#define FCB_CONV_WRITE              FLC_CONV_WRITE
#define FCB_CONV_FROM_TO            FLC_CONV_FROM_TO
#define FCB_INPUT_FILE              FLC_INPUT_FILE
#define FCB_OUTPUT_FILE             FLC_OUTPUT_FILE
#define FCB_INFO                    FLC_INFO
#define FCB_STATE                   FLC_STATE

extern int* piFcbErrno(void);
 /*! @endcond */
/**********************************************************************/
/**
 * @defgroup GBLVAR Global variables
 * @brief Global variables exposed by the FLUC byte interface
 * @{
 */

/**
 * @brief FLAM return code
 *
 * Global int variable that contains the FLAM return code after a call to
 * #fcbopen(), #fcbopen2(), #fcbread(), #fcbwrite(), #fcbhelp(), #fcbsyntax(),
 * #fcbinfo(), #fcbclose() or #fcbclose2(). The error code is stored in
 * thread-local memory. Access to fcberrno is therefore thread-safe.
 *
 * Please have a look at FLMRTC.h for all possible return codes.
 * You may want to use #fcberrms() to get a corresponding error message.
 */
#define fcberrno (*piFcbErrno())

/** @} */
/**********************************************************************/
/**
 * @defgroup FUNC Functions
 * @brief All public functions provided by the FLUC byte interface
 * @{
 */

/**
 * @brief Retrieves version information
 *
 * This function returns a string with version information for each
 * used component. This should be used in a support case.
 *
 * @return a pointer to a static area containing the zero-terminated
 *         version string
 */
extern const char* fcbvsn(void);

/**
 * @brief Retrieves about information
 *
 * This function returns a string with about information for this
 * library on multiple lines and license information for used external
 * libraries.
 *
 * @return a pointer to a static area containing the zero-terminated
 *         about string
 */
extern const char* fcbabo(void);

/**
 * @brief Retrieves the license text
 *
 * This function can be used to get the current license text on multiple
 * lines. The license text defines the permissible use of this library.
 *
 * @return a pointer to a static area with a zero-terminated string
 *         containing the current license text.
 */
extern const char* fcblic(void);

/**
 * @brief Load the FLAM environment
 *
 * This function loads the FLAM system variables (only on z/OS or in EDZ
 * environment), the STDENV definitions ('DD:STDENV' or '\<SYSUID>.STDENV'
 * on z/OS or '.stdenv' file in working or home directory on other systems)
 * and a optional list of variables to the environment. This must be called
 * before any other FLAM API function to set the correct environment. This
 * function allows to work with the same environment used by FLAM utilities,
 * subsystems, etc.
 *
 * @param[in] sys Non-zero value to load system variables, 0 otherwise
 * @param[in] std Non-zero value to load standard environment, 0 otherwise
 * @param[in] env Optional list (can be NULL or empty) of environment
 *                variables (KEYWORD=VALUE) separated by new line ('\\n') or semicolon (';')
 * @return negative (<0) error else (>=0) amount of environment variable load
 */
extern int fcbenv(const int sys, const int std, const char* env);

/**
 * @brief Determines a symbol from environment
 *
 * The function can be used to fetch the value of an environment variable,
 * a JCL symbol (z/OS) or a system symbol (z/OS).
 *
 * @param[in]    name   Name of the symbol
 * @param[in]    size   Space for the output buffer
 * @param[out]   string Buffer for the output string
 * @return a pointer to the symbol string or NULL if error
 */
extern char* fcbsym(const char* name,size_t size,char* string);


/**
 * @brief Provides various information
 *
 * This function can be used to retrieve various information about
 * files, supported CCSIDs and other things. You must provide an info
 * string to define which information to request. You can define the
 * format in which the information will be output. The information is
 * written to a buffer which will be dynamically re-allocated by this
 * function so that it fits all requested information.
 *
 * The buffer can already be allocated before and must be freed by the
 * calling application. If the buffer is allocated by the calling
 * application, the first byte of the allocated buffer must be set to
 * 0x0, as the data is appended to the first zero-terminated string.
 * This can be used for example to include the generated XML into XML of
 * a higher level.
 *
 * The pointer to the buffer can point to a null pointer. In this case,
 * the whole buffer will be allocated by this function and the output
 * starts at offset 0.
 *
 * The info definition string uses the same syntax as the get method of
 * the FLCL INFO command. The complete syntax and help can be retrieved
 * with the corresponding functions below. The null-terminated string must
 * start with 'get.' followed by the corresponding method (file/ccsids/...).
 * Leading whitespace is ignored.
 *
 * Examples:
 * <pre>
 * "get.file='test.txt'"
 * "get.ccsids"
 * </pre>
 *
 * Please use:
 * <pre>
 * 'fcbhelp(FLC_INFO,10,NULL)'
 * 'fcbsyntax(FLC_INFO,10,NULL)'
 * </pre>
 * for more information.
 *
 * @param[in]       infstr  Info string with GET instructions
 * @param[in]       format  Format specification for the output buffer (\link FLMOUT_FORMAT_NON FLMOUT_FORMAT_*\endlink)
 * @param[inout]    bufsiz  Pre-allocated buffer size on input, is overwritten with final buffer size on output
 * @param[inout]    buffer  Pointer of pointer to a dynamically allocated buffer
 *
 * @return -1 if error or length of the data in the buffer
 */
extern int fcbinfo(const char* infstr, const int format, size_t* bufsiz, char** buffer);


/**
 * @brief Open the logging facility for in-memory logging
 *
 * Enables in-memory logging. Messages that would normally printed to the console when using command
 * line tools like FLCL are collected in-memory and can be queried when needed.
 *
 * A CLP string can be passed to the function to control the identifier,
 * format and messages to log. If no log string is passed, the minimal format and minimal messages
 * are used by default. The logging facility is useful to catch warnings during operation.
 * The functions fcbgetlog() and fcbclrlog() can be used to retrieve or clear the current log
 * buffer contents. The logging facility must be closed with fcbclslog().
 *
 * @param logstr NULL or a CLP string for logging ("LOG(IDENT='str',FORMAT=STANDARD/DIALOG/MINIMAL,MESSAGE(WARN))")
 * @return FLAM reason code or 0 on success
 */
extern int fcbopnlog(const char* logstr);

/**
 * @brief Get log information
 *
 * Returns the maximum error code since the last call to fcbopnlog() or
 * fcbclrlog(). Optionally, a read only buffer can be obtained by passing
 * memory for storing the buffer pointer. The returned buffer contains the
 * log messages separated by new line character and null-termination at
 * the end.
 *
 * @param buffer If not NULL, a pointer to the log buffer is written to the provided memory
 * @return The maximum error code logged
 */
extern int fcbgetlog(const char** buffer);

/**
 * @brief Clear the log information
 *
 * Clears the log buffer and resets the maximum error code to 0.
 *
 * @return The maximum error code logged
 */
extern int fcbclrlog(void);

/**
 * @brief Close the logging facility
 *
 * Closes the logging facility, frees all associated resources and
 * returns the maximum error code since the log was opened or cleared.
 *
 * @return The maximum error code logged
 */
extern int fcbclslog(void);

/**
 * @brief Open file (without state management)
 *
 * This function opens a normal file, a member in a FLAM4FILE, a PGP
 * file or a member in a concatenated GZIP-, BZIP- or XZ-File or some
 * other supported file format. It supports base encoding, encryption,
 * compression, character conversion and text, XML and table formatting,
 * among others.
 *
 * The file definition string uses the same syntax as the read or write
 * method of the FLCL CONV command or the INPUT and OUTPUT specification
 * of the XCNV command. The complete syntax and help can be determined with
 * the corresponding functions below. The string must start with 'read.' or
 * 'write.' followed by the corresponding method (binary/char/text/flam4/xml/...)
 * or with input() or output() object specifications (leading whitespace is
 * ignored).
 *
 * Examples:
 * <pre>
 * "read.text(file='test.txt')"
 * "write.binary(file='test.gz' comp.gzip(level=BEST))"
 * "input(sav.fil(fio.blk(name='~.GZ.TEST') cnv.zip() cnv.chr(from=latin1 to=ibm1141) fmt.txt()))"
 * "output(sav.fil(fmt.txt(method=host) fio.fl4(name='~.ADC.TEST')))"
 * "write[flam(file='flamfile.adc' ccsid=IBM1141),text(file='testfile.zip' method=windows ccsid=CP1252 archive.zip())]"
 * </pre>
 *
 * The last example shows multiple writes of the same data one as FLAMFILE
 * for IBM mainframes and another one as ZIP file for a Windows system.
 *
 * Please use:
 * <pre>
 * 'fcbhelp(FLC_READ_FILE,10,NULL)'
 * 'fcbsyntax(FLC_READ_FILE,10,NULL)'
 * 'fcbhelp(FLC_INPUT_FILE,10,NULL)'
 * 'fcbsyntax(FLC_INPUT_FILE,10,NULL)'
 * 'fcbhelp(FLC_WRITE_FILE,10,NULL)'
 * 'fcbsyntax(FLC_WRITE_FILE,10,NULL)'
 * 'fcbhelp(FLC_OUTPUT_FILE,10,NULL)'
 * 'fcbsyntax(FLC_OUTPUT_FILE,10,NULL)'
 * </pre>
 * for more information.
 *
 * The format string uses the syntax of the 'format' union which was specifically
 * designed for the byte interface to format a byte stream based on the FLAM
 * elements. The zero-terminated string must start with 'format.' followed by
 * the corresponding method.
 *
 * Examples:
 * <pre>
 * "format.text(method=CRLF suptws ccsid='UTF-16LE')"
 * "format.bin()"
 * "format.char(ccsid=DEFAULT)"
 * "format.record(ccsid='IBM-1141')"
 * "format.element(ccsid='IBM-1141')"
 * </pre>
 *
 * Please use:
 * <pre>
 * 'fcbhelp(FLC_READ_FORMAT,10,NULL)'
 * 'fcbhelp(FLC_WRITE_FORMAT,10,NULL)'
 * 'fcbsyntax(FLC_READ_FORMAT,10,NULL)'
 * 'fcbsyntax(FLC_WRITE_FORMAT,10,NULL)'
 * </pre>
 * for more information.
 *
 * The file string defines how the FLAM elements are read from or written
 * to the file. The format string defines how the FLAM elements are converted
 * into a byte stream, records or elements.
 *
 * @param [in] filstr   File string with READ/INPUT/WRITE/OUTPUT instructions
 * @param [in] fmtstr   Format string with FORMAT instructions
 *
 * @return a pointer to a handle to manage file I/O, must be passed to
 *         subsequent functions or NULL in case of an error
 */
extern void* fcbopen(const char* filstr, const char* fmtstr);

/**
 * @brief Open file (with state management)
 *
 * This function works like #fcbopen() with the capability to get the internal
 * state after an open for read operation and to pass a previously read
 * internal state for an open for write operation. The internal state can
 * be used to transfer attributes/values/information from an
 * fcbopen2("read."/"input()") to an fcbopen2("write."/"output()") or set
 * these string for an fcbopen2("write."/"output()"). The object contains
 * metadata like file attributes, data types and character set. These
 * values are, among others, important to fill header information of
 * archives like GZIP header or FLAM member headers.
 *
 * The parameter is a pointer to a pointer to a string. In read mode, if
 * you pass a non-null pointer, the pointer target will be a pointer to
 * a null-terminated string dynamically allocated in heap memory (i.e. you
 * must free() it!) containing the state string after this function returns.
 * On write mode, if you pass a non-null pointer to a pointer to a state
 * string, this state string is used to set the internal state. Otherwise,
 * the state is initialized with default values.
 *
 * You can look up the state string syntax and help with the corresponding
 * functions below. The zero-terminated string must start with 'state('
 * followed by the corresponding value definitions and closed with ')'.
 *
 * Example:
 * <pre>
 * "state(member='test.txt' recf=FBA recl=120)"
 * </pre>
 *
 * Please use:
 * <pre>
 * 'fcbhelp(FLC_STATE,10,NULL)'
 * 'fcbsyntax(FLC_STATE,10,NULL)'
 * </pre>
 * for more information.
 *
 * Below you can find two examples:
 *
 * 1. Write only
 * <pre>
 * char* state="STATE(file='test.txt')";
 * void* wrt=fcbopen2("write.text(comp.gzip())","format.text()",&state);
 * </pre>
 *
 * 2. Read and write
 * <pre>
 * char* state=NULL;
 * void* red=fcbopen2("read.text(file='test.txt')","format.text()",&state);
 * void* wrt=fcbopen2("write.text(comp.gzip())","format.text()",&state);
 * free(state);
 * </pre>
 *
 * In both cases, the member name for the original file in the GZIP header
 * is 'test.txt'.
 *
 * @param [in]      filstr   File string with READ/INPUT/WRITE/OUTPUT instructions
 * @param [in]      fmtstr   Format string with FORMAT instructions
 * @param [inout]   state    Pointer to a pointer to a string with STATE values
 *                           (You are responsible to free() the string in read mode!)
 *
 * @return a pointer to a handle to manage file I/O, must be passed to
 *         subsequent functions or NULL in case of an error
 */
extern void* fcbopen2(const char* filstr, const char* fmtstr, char** state);

/**
 * @brief Close file (without statistics)
 *
 * Opened files must be closed through this function after read or write
 * operations are completed. All internal buffers are flushed and all
 * allocated resources are released.
 *
 * @param [in] hdl File handle from #fcbopen()
 *
 * @return Upon successful completion 0 is returned. Otherwise, EOF is
 *         returned and #fcberrno is set to indicate the error.
 */
extern int fcbclose(void* hdl);

/**
 * @brief Close file with return of statistics information
 *
 * This function works like #fcbclose() with the capability to define a
 * success flag and get statistical information.
 *
 * The 'success' flag is relevant in read or write mode. It allows you to
 * indicate whether the operation using the file was successful from the
 * caller's point-of-view. If you set the 'remove' flag in the file
 * string passed to #fcbopen() or #fcbopen2(), the file is only removed
 * at read if you indicate success, i.e. pass TRUE for the 'success'
 * parameter or at write if you indicate failure, i.e. pass FALSE.
 * In case of an error while processing the read data, it may be more
 * reasonable to keep the file, even though it was flagged for deletion.
 *
 * For statistics you can define the format in which the information
 * will be output. The information is written to a buffer which will be
 * dynamically re-allocated by this function so that it fits all
 * requested information. The buffer can already be allocated before. In
 * that case, it must contain a (possibly empty) null-terminated string
 * because statistics output is appended. The buffer must be freed by
 * the calling application. The pointer to the buffer can point to a null
 * pointer. In this case, the whole buffer will be allocated by this
 * function.
 *
 * @param [in]      hdl     File handle from #fcbopen()
 * @param [in]      success True indicates that the data was processed successfully by the caller
 * @param [in]      stafmt  Format specification for the output buffer (\link FLMOUT_FORMAT_NON FLMOUT_FORMAT_*\endlink)
 * @param [inout]   stasiz  Pre-allocated buffer size on input, is overwritten with final buffer size on output
 * @param [inout]   stabuf  Pointer of pointer to a dynamically allocated buffer containing statistics
 *
 * @return Upon successful completion a value >=0 is returned. Otherwise,
 *         EOF is returned and #fcberrno is set to indicate the error.
 */
extern int fcbclose2(void* hdl, const int success, const int stafmt, size_t* stasiz, char** stabuf);

/**
 * @brief Returns the current table name
 *
 * When using table support while reading with end of table handling (ENDOFT),
 * this function returns the current table name (logical name defined in
 * the row specification). This name changes when the handle is obtained
 * (from #fcbopen() or #fcbopenv()) or reading returns the EOT error code.
 *
 * @param [in] hdl File or conversion handle from #fcbopen() or #fcbopenv()
 * @return Pointer to the table name or NULL if error
 */
extern const char* fcbgtn(void* hdl);

/**
 * @brief Returns the current file name
 *
 * If you open a file for write operation and use input output name mapping
 * running or random numbers, dates and times, this function is useful to
 * determine the current file name. To analyze the data read from memory at
 * write, the real open is delayed. To ensure to get the file name you must
 * call this function after a #fcbflush() in front of #fcbclose(). At read
 * the original file name read will be returned and the index ignored.
 *
 * @param [in] hdl File handle from #fcbopen()
 * @param [in] ind Index if multiple writes defined else set to 0
 * @return Pointer to the file name or NULL if error
 */
extern const char* fcbgfn(void* hdl, const int ind);

/**
 * @brief Sets the current table format
 *
 * When writing more than one table to a file, the current table format can
 * be set with this function. The function only succeeds after complete rows
 * have been written. It fails if there is a remainder in the
 * buffer. By using this function, automatic detection of the table
 * format is deactivated. The provided data must match the defined
 * row specification. You can re-activate auto detection of the table
 * format with a call to #fcbgtn(). A call to #fcbstn() will start
 * a new table of the same or another format. If ENDOFT is activated in the
 * format string, then FLMRTC_EOT will be returned internally and, when writing,
 * the file handle is re-opened. By using use the filename pattern [table] in
 * the output filename, the data of each table can be written to in different files.
 *
 * @param [in] hdl File or conversion handle from #fcbopen() or #fcbopenv()
 * @param [in] name Table name to define the new row specification
 * @return Pointer to the table name or NULL if error
 */
extern const char* fcbstn(void* hdl, const char* name);

/**
 * @brief Flush internal buffers to the file
 *
 * Flushes all internal buffers, i.e. writes all data that still resides
 * in memory to the file denoted by the handle. (This function also ensures
 * that the real open are done.)
 *
 * @param [in] hdl File handle from #fcbopen()
 * @return On success 0 is returned, on error EOF is returned
 */
extern int fcbflush(void* hdl);

/**
 * @brief Start with a new member in an open file
 *
 * The function implements a re-open of the current file handle to start
 * with a new member. You must provide a valid handle from #fcbopen() for
 * write operation and you can provide a new format string and/or state
 * string. If no format string (NULL) is given, the format of the
 * previous member is used. If no state (NULL) is provided, then the
 * default values are used.
 *
 * @param [in]      hdl      Valid handle from fcbopen()
 * @param [in]      fmtstr   Format string with FORMAT instructions
 * @param [in]      state    Pointer to a string with STATE values
 *
 * @return a pointer to a handle to manage file I/O, must be passed to
 *         subsequent functions or NULL in case of an error (the handle is closed in error case)
 */
extern void* fcbnewmbr(void* hdl, const char* fmtstr,const char* state);

/**
 * @brief Start with a new member in a open file (with statistics information)
 *
 * This function works like #fcbnewmbr() with the capability to get
 * statistical information, since open or last re-open.
 *
 * @param [in]      hdl      Valid handle from fcbopen()
 * @param [in]      fmtstr   Format string with FORMAT instructions
 * @param [in]      state    Pointer to a string with STATE values
 * @param [in]      stafmt   Format specification for the output buffer (\link FLMOUT_FORMAT_NON FLMOUT_FORMAT_*\endlink)
 * @param [inout]   stasiz   Pre-allocated buffer size on input, is overwritten with final buffer size on output
 * @param [inout]   stabuf   Pointer of pointer to a dynamically allocated buffer containing statistics
 *
 * @return a pointer to a handle to manage file I/O, must be passed to
 *         subsequent functions or NULL in case of an error (the handle is closed in error case)
 */
extern void* fcbnewmbr2(void* hdl, const char* fmtstr,const char* state, const int stafmt, size_t* stasiz, char** stabuf);

/**
 * @brief Open converter
 *
 * This function opens a data conversion module for read or write
 * operations if <code>format.element()</code> is used. All functions with
 * 'v' as last character accepts a conversion handle, which is only relevant
 * if <code>format.element()</code> done. With this set of 'v' functions, you
 * can define over such an converter how the element data is converted from
 * application memory to a neutral FLAM5 element or vice versa.
 *
 * The read type specification defines how the data type is read from application
 * memory and converted in the neutral data type at a write operation. The write
 * type specification defines how a neutral data type is written to the
 * application memory at a read operation.
 *
 * To use the converter in write operations, normally the read type specification
 * is required. If the converter is used for read operation, a write type
 * specification must be specified. The conversion string uses the syntax of the
 * 'type' union which was designed for element conversion. The zero-terminated
 * string must start with 'read.' or 'write.' followed by the corresponding data
 * type specification (binary/string/integer/float/...).
 *
 * It is also possible to use a read conversion in a read operation. For example,
 * this makes sense to convert a string of an XML element containing a decimal
 * number to the neutral form of a number (64 bit integer) in FLAM.
 * In this case, the 8 byte (64 bit) integer value is given as element data
 * instead of the string with the decimal number.
 *
 * The function optionally accepts a file or conversion handle. You can provide
 * the file handle for which the converter will be used, so that the system knows,
 * for example, the CCSID of the data. Otherwise, UTF-8 is assumed as neutral
 * character encoding, but with the INPUT() object another internal character set
 * can be set. If you provide the file handle, you can ensure that the correct
 * internal representation of the data is known and the converter is opened in
 * the right manner for that file. The same is valid for memory conversion handles.
 *
 * You can also use a conversion string (<code>CONV.type(from() to())</code>
 * or <code>CONV.MEMORY(READ.mode() WRITE.mode())</code>) which describes
 * a complete external representation to external representation conversion.
 * This form can be used with function #fcbconv/p for an independent memory
 * to memory conversion. You can use this, for example, for an XML element, which
 * contains a decimal number as UTF-8 string, to build an integer in two's complement
 * representation or to produce a PGP file which contains a CSV table or some other
 * complex in-memory conversions.
 *
 * Examples:
 * <pre>
 * "read.string(chrset(ccsid=default))"
 * "write.string(chrset(ccsid=default whitespace=collapse))"
 * "write.string(chrset(ccsid=default whitespace=number) number(format='%3.2f'))"
 * "conv.integer(from.string() to.bin())"
 * "conv.memory(read.char() write.char(ccsid=UTF-32))"
 * </pre>
 *
 * Please use:
 * <pre>
 * 'fcbhelp(FLC_CONV_READ,10,NULL)'
 * 'fcbsyntax(FLC_CONV_READ,10,NULL)'
 * 'fcbhelp(FLC_CONV_WRITE,10,NULL)'
 * 'fcbsyntax(FLC_CONV_WRITE,10,NULL)'
 * 'fcbhelp(FLC_CONV_FROM_TO,10,NULL)'
 * 'fcbsyntax(FLC_CONV_FROM_TO,10,NULL)'
 * </pre>
 * for more information.
 *
 * @param [in] hdl      File or memory conversion handle from #fcbopen or #fcbopenv (optional, can be NULL)
 * @param [in] cnvstr   Conversion string with READ or WRITE instructions
 *
 * @return a pointer to a handle to manage conversions, can be passed to
 *         subsequent v-functions, must be closed with fcbclosev()
 */
extern void* fcbopenv(void* hdl, const char* cnvstr);

/**
 * @brief Close a converter
 *
 * Opened conversion handles must be closed through this function after
 * read or write are completed. All allocated resources are released.
 *
 * @param [in] cnv Conversion handle from #fcbopenv()
 *
 * @return Upon successful completion 0 is returned. Otherwise, EOF is
 *         returned and #fcberrno is set to indicate the error.
 */
extern int fcbclosev(void* cnv);

/**
 * @brief Read file data
 *
 * This function reads @p count items, each @p size bytes long, from the
 * input stream (block/stream-oriented mode).
 *
 * In record- or element-oriented mode, the function reads at most one
 * record or element structure from the input stream on each call.
 * Therefore, the @p count and @p size parameters have a different
 * meaning, when the file was opened with <code>format.record()</code>
 * or <code>format.element()</code>.
 *
 * @par format.record()
 * If you use fcbread() for record I/O, only one record is read at most,
 * regardless of @p count, when using record I/O. There is no inherent
 * limit on record lengths for records produced by
 * <code>format.record()</code>. For example, when reading with
 * "read.bin(blksiz=1048576)" and formatting with "format.record()",
 * this function would return records of 1 MiB because every block that
 * was read would be formatted as one record.
 *
 * @par
 * The @p size parameter controls the behavior of the function in record
 * mode:
 * * <code>size = 0</code>
 *   - Set @p count to the maximum expected record length in bytes. This
 *     is also the minimum size for your buffer passed via @p ptr. If a
 *     record is encountered that is longer than @p count bytes, this
 *     function returns 0 and the error state returned by #fcberror() is
 *     set to #FLMRTC_LEN. You can allocate a bigger buffer and attempt
 *     to re-read the same record by calling this function again with
 *     the bigger buffer.
 * * <code>size = 1</code>
 *   - Set @p count to the maximum expected record length in bytes. This
 *     is also the minimum size for your buffer passed via @p ptr. If a
 *     record is encountered that is longer than @p count bytes, @p count
 *     bytes are copied to the provided buffer and remaining bytes are
 *     discarded.
 * * <code>size = -1</code> (SIZE_MAX)
 *   - This is the zero-copy mode for record I/O. Instead of passing
 *     your own buffer, you must pass a pointer to a NULL pointer which
 *     is set to an internal byte buffer containing the next record if
 *     the function succeeds. The function's return value is the number
 *     of bytes in this buffer.
 *
 * @note
 * If record I/O is used, the returned number of bytes can be zero
 * because records can contain zero-length data. Check #fcberror() and
 * #fcbeof() to distinguish between errors, EOF and zero-length records.
 *
 * @par format.element()
 * This formatting method provides access to the raw elements in a
 * serialized form that all data is split into internally when reading
 * any data. Each call to this functions returns at most one serialized
 * element. The buffer pointed to by @p ptr contains an element matching
 * the structure #FlmElmRec0, which can be used for type-casting.
 *
 * @par
 * Each element has a @ref MATTYP "matrix type", which indicates the
 * type of data, and an @ref ELMTYP "element type" which defines the kind
 * of content. The set of element types depends on the matrix type.
 * Besides the element data, each element can contain hash values
 * (checksums) and additional attributes. The presence of both depends
 * on the element type. There are some convenience macros like
 * #FLMELMREC0_DATAPTR(element) which help to get pointers to
 * the various data fields. These macros only work if the choosen byte
 * order matches the system byte order (big or little endian).
 *
 * @par
 * The @p size parameter controls the behavior of the function in
 * element mode:
 * * <code>size = 0</code>
 *   - The function reads one element at a time and writes it into the
 *     supplied buffer of length @p count. If the buffer is too small, 0
 *     is returned and #fcberror() returns #FLMRTC_LEN. If the buffer is
 *     at least <code>sizeof(#FlmElmRec0)</code> bytes long, all fields
 *     of the structure will have been written to the buffer except for
 *     the actual data (FlmElmRec0::buffer). You can use this information
 *     to reallocate your buffer to the required size. The required
 *     buffer size is the size of thestructure (e.g. #FlmElmRec0) plus
 *     the sum of all length fields of the structure. There is a
 *     convenient C macro for every supported structure, which calculates
 *     the correct length, e.g. #FLMELMREC0_LENGTH.
 * * <code>size = -1</code> (SIZE_MAX)
 *   - Instead of providing your own buffer, you pass a pointer to a
 *     NULL pointer via @p ptr. The @p count parameter is ignored and
 *     can have any value. If an element has been read successfully, the
 *     value of @p ptr is a pointer to a buffer that holds the whole
 *     element. The function ensures that the buffer is always large
 *     enough. Please note that this buffer should not be written to and
 *     that its contents are only valid until the next call to
 *     #fcbread(), #fcbclose() or #fcbclose2() on the same handle.
 *
 * @note
 * You should always check the version field (first 32 bits, currently
 * always 0) to determine the structure of the element. A version of 0
 * indicates that, #FlmElmRec0 is the structure of the data and may be
 * used to cast the buffer. In future versions, additional structures
 * might be added. Checking the version field avoids misinterpreting the
 * data by casting to the wrong structure.
 *
 * @param [out] ptr   Pointer to the data buffer that read data is written to
 * @param [in]  size  Size of one data element to be read\n
 *                    If you opened the file with record or element
 *                    formatting, this parameter controls the behavior
 *                    of this function. See the function description
 *                    above for details.
 * @param [in]  count Number of data elements to read
 * @param [in]  hdl   File handle from #fcbopen()
 *
 * @return Number of bytes actually read or 0 if end-of-file (EOF) is
 *         reached, an error occurs or an empty record is encountered.\n
 *         \n
 *         If you opened the file with record or element formatting,
 *         are zero return value can also mean that the supplied buffer
 *         is too small (see function description above).\n
 *         \n
 *         If you require the same behavior as fread(), i.e. the return
 *         value is the number of elements read of size @p size,
 *         the following macro can be used:
 * <pre>
 * \#define FREAD(p,s,c,h) ((s)?(fcbread(p,s,c,h)/(s)):0)
 * </pre>
 *
 * @see #fcberror(), #fcbeof()
 */
extern size_t fcbread(void* ptr, size_t size, size_t count, void* hdl);

/**
 * @brief Read file data with conversion
 *
 * This function works like #fcbread() but accepts two additional parameter.
 * The argument @p cnv point to a conversion handle and @p skip is a element
 * type which will be ignored at this read request. These parameters are only
 * relevant with <code>format.element()</code> and can be used to overwrite
 * the element data conversion and skip an unexpected element type. You can
 * open such an handle by calling #fcbopenv() and request a individual conversion
 * for that element.
 *
 * In XML data between a #FLMELM_TYPXML_ENDSTRTELM and the next #FLMELM_TYPXML_STARTELM
 * data elements (#FLMELM_TYPXML_DATA) could be exist and the parameter @p skip can be
 * used to ignore for example these data elements. With #FLMELM_NOSKIP the next element
 * is given.
 *
 * @param [out] ptr   Pointer to the data buffer that read data is written to
 * @param [in]  size  Size of one data element to be read\n
 *                    If you opened the file with record or element
 *                    formatting, this parameter controls the behavior
 *                    of this function. See the function description
 *                    above for details.
 * @param [in]  count Number of data elements to read
 * @param [in]  hdl   File handle from #fcbopen()
 * @param [in]  cnv   Conversion handle from #fcbopenv()
 * @param [in]  skip  Skip this element type
 *
 * @return Number of bytes actually read or 0 if end-of-file (EOF) is
 *         reached, an error occurs or an empty record is encountered.\n
 *         \n
 *         If you opened the file with record or element formatting,
 *         a zero return value can also mean that the supplied buffer
 *         is too small (see function description above).\n
 *         \n
 *         If you require the same behavior as fread(), i.e. the return
 *         value is the number of elements read of size @p size,
 *         the following macro can be used:
 * <pre>
 * \#define FREAD(p,s,c,h,v,k) ((s)?(fcbreadv(p,s,c,h,v,k)/(s)):0)
 * </pre>
 *
 * @see #fcberror(), #fcbeof()
 */
extern size_t fcbreadv(void* ptr, size_t size, size_t count, void* hdl, void* cnv, const int skip);

/**
 * @brief Write data to file
 *
 * This function writes size &times; count bytes to the output file
 * (block/stream-oriented mode).
 *
 * If the file was opened for record- or element formatting, only one
 * record or element can be written per call.
 *
 * @par format.record()
 * The @p size parameter is ignored when record formatting.
 * The record length in bytes must be passed via parameter @p count. The
 * record length is not limited when formatting record elements in
 * memory. However, when writing records to a dataset or a FLAMFILE,
 * respective limits apply. Therefore, you can specify how too long
 * records are handled via the file string passed to #fcbopen().
 *
 * @par format.element()
 * To write elements, the buffer pointed to by @p ptr must contain one
 * of the serialized element structures defined in FLMDEF.h (e.g.
 * #FlmElmRec0). The structure is expected to start at offset 0 in the
 * buffer. All members of the structure must be set to valid values. The
 * @p size parameter is ignored when element formatting. The length in
 * bytes of the serialized element structure must be passed via parameter
 * @p count. The length of an element is calculated as sum of all length
 * fields in the structure + the length of the structure itself without
 * the last field (i.e. buffer). You can use macros like
 * #FLMELMREC0_LENGTH(element) to conveniently calculate the correct
 * length of the structure.
 *
 * @par
 * All elements written to one file handle must have the same
 * matrix type. If an element of an element type is written which contains
 * text data, the data field must be provided in UTF-8 unless character
 * conversion was activated by setting the <code>ccsid</code> in the
 * <code>format.element()</code> clause to the character set of your data.
 * If the matrix and/or element type requires attributes, then the
 * attribute length and values must be set as described by the element
 * type.
 *
 * @note
 * Unlike *fwrite()*, fcbwrite() does not return the number of
 * elements written, but the number of bytes written. If you require the
 * same behavior as *fwrite()*, the following macro can be used:
 * <pre>
 * \#define FWRITE(p,s,c,h) ((s)?(fcbwrite(p,s,c,h)/(s)):0)
 * </pre>
 *
 * @param [in] ptr   Pointer to the data to be written
 * @param [in] size  Size of one data element to be written
 * @param [in] count Number of data elements to write
 * @param [in] hdl   File handle from #fcbopen()
 *
 * @return Number of bytes (not elements) written or 0 on error
 */
extern size_t fcbwrite(const void *ptr, size_t size, size_t count, void* hdl);

/**
 * @brief Write data to file with conversion
 *
 * This function works like #fcbwrite() but accepts one additional parameter
 * @p cnv which point the a conversion handle. This parameter  is only
 * relevant with <code>format.element()</code> and can be used to
 * overwrite the element data conversion. You can open such an handle by
 * calling #fcbopenv() and request a individual conversion for that element.
 *
 * @param [in] ptr   Pointer to the data to be written
 * @param [in] size  Size of one data element to be written
 * @param [in] count Number of data elements to write
 * @param [in] hdl   File handle from #fcbopen()
 * @param [in] cnv   Conversion handle from #fcbopen()
 *
 * @return Number of bytes (not elements) written or 0 on error
 */
extern size_t fcbwritev(const void *ptr, size_t size, size_t count, void* hdl, void* cnv);

/**
 * @brief Sets the read position to the previous record or element
 *
 * If the file handle has been opened for reading with element
 * formatting (<code>format.element()</code>) or record formatting
 * <code>format.record()</code>, the internal position is set to the
 * previously read element or record. I.e. the next call to #fcbread()
 * will return the same element as the last one.
 *
 * The function is guaranteed to decrement the file position at least
 * once after #fcbread() has been called. Multiple successive calls to
 * this function may or not be successful.
 *
 * @note
 * Calls to this function on a handle opened without record or element
 * formatting may result in undefined behavior.
 *
 * @param [in] hdl    File handle from #fcbopen()
 * @return A non-zero value (errno) in case of an error, zero on success
 */
extern int fcbprev(void* hdl);


/**
 * @brief Gets the next character
 *
 * The function gets the next character (an unsigned char) from the specified
 * stream and advances the position indicator by one. This function does not
 * work with <code>format.record()</code> or <code>format.element()</code>.
 * Use #fcbread() instead.
 *
 * @param [in] hdl    File handle from #fcbopen()
 * @return Returns the character read as an unsigned char cast to an int
 *         or EOF(-1) on end of file or error.
 */
extern int fcbgetc(void *hdl);

/**
 * @brief Push a character back back to the stream
 *
 * Pushes a character (unsigned char) back onto the specified stream.
 * Pushed-back characters will be returned in reverse order by subsequent
 * calls to #fcbgetc(). Only one pushback is guaranteed to work (after at
 * least one character has been read previously).
 *
 * @note
 * This function does not work with <code>format.record()</code>
 * and <code>format.element()</code>.
 *
 * @param [in] chr    Character value to push back
 * @param [in] hdl    File handle from #fcbopen()
 * @return If successful, returns the character that was pushed back.
 *         Otherwise, EOF(-1) is returned and the stream remains unchanged.
 */
extern int fcbungetc(int chr, void *hdl);

/**
 * @brief Writes a character
 *
 * Writes a character (unsigned char) to the stream specified by the given
 * handle and advances the position indicator by one.
 *
 * @note
 * This function does not work with <code>format.element()</code>. It
 * works with <code>format.record()</code>, but each character will be
 * turned into one record.
 *
 * @param [in] chr    Chracter value
 * @param [in] hdl    File handle from #fcbopen()
 * @return On success, @p chr is returned. If an error occurs, EOF(-1)
 *         is returned and the error indicator is set.
 */
extern int fcbputc(int chr, void *hdl);

/**
 * @brief Reads a line
 *
 * Reads a line from the specified stream and stores it as null-terminated
 * string into the buffer pointed to by @p str.
 *
 * If <code>format.record()</code> is used, each call returns one
 * null-terminated line with up to n-1 characters (no new line characters
 * at the end). The remainder of the record is discarded.
 *
 * Otherwise, reading stops when either (n-1) characters
 * are read, the newline character is encountered, or the end-of-file is
 * reached, whichever comes first. If a newline is read, it is stored
 * into the buffer. The character data must be in a local character
 * encoding (i.e. an EBCDIC charset on EBCDIC machines and an ASCII
 * charset on ASCII machines) for correct splitting on newlines (i.e.
 * specify a ccsid in the format string to convert to a local charset).
 *
 * Null-termination of the returned string is guaranteed.
 *
 * @note
 * This function does not work with <code>format.element()</code>.
 *
 * @param [out] str   Pointer to a character array where the string is stored
 * @param [in]  n     The maximum number of characters to be read (size of str).
 * @param [in]  hdl   File handle from #fcbopen()
 * @return On success, the function returns @p str. If the end-of-file
 *         is encountered and no characters have been read, the contents
 *         of @p str remain unchanged and a null pointer is returned.
 */
extern char *fcbgets(char *str, int n, void *hdl);

/**
 * @brief Writes a null-terminated string
 *
 * The function writes a null-terminated string to the specified stream
 * up to but not including the null character.
 *
 * If <code>format.record()</code> is used, each null-terminated string
 * passed to this function is treated as one record.
 *
 * @note
 * This function does not work with <code>format.element()</code>.
 *
 * @param [in] str   A null-terminated string
 * @param [in] hdl   File handle from #fcbopen()
 * @return A non-negative value (amount of bytes written) on success,
 *         EOF (-1) if an error occurred.
 */
extern int fcbputs(const char *str, void *hdl);

/**
 * @brief Converts independent data blocks (with copy)
 *
 * The function converts data between formats as specified by the conversion
 * string passed to #fcbopenv().
 *
 * It provides memory to memory conversion between external data representations
 * of different data types using a conversion handle from function #fcbopenv()
 * which was called with a conversion string of the form from-to or read-write.
 *
 * Please note that this function always converts the whole input data
 * independent of previous calls. This implies that data elements must
 * be passed as a whole. For example, passing a block of UTF-8 text as input
 * where the data in the input buffer ends in the middle of a multi-byte
 * character, will result in an error or unexpected output. To convert
 * multiple buffers of dependent data (e.g. whole files), use the functions
 * #fcbrunv() and #fcbfinv().
 *
 * The return code FLMRTC_LEN tells that the output buffer is too small.
 * In this case, the function must be called again with the same input
 * buffer and an output buffer of the size returned by the <code>outlen</code>
 * parameter (or larger).
 *
 * If EOT (end of table) handling is activated, the return code FLMRTC_EOT
 * can occur if the input buffer contains the data for more than one
 * table or if the order of tables in the input buffer does not match the
 * order of the row specifications. Only one table can be written to the
 * output buffer per call of this function. Hence, it must be called
 * repeatedly with the same input buffer as long as FLMRTC_EOT is returned.
 * Note that if the data in the input buffer does not match the first row
 * specification, FLMRTC_EOT is returned without writing any data to the
 * output buffer. Please be aware that FLMRTC_LEN may also be returned
 * for any of your repeated calls if the output buffer is not large enough
 * for the currently processed table.
 *
 * Below is an example on handling the return codes if EOT handling is
 * activated and length errors are expected:
 *
 * <pre>
 * hdl=fcbopenv(NULL,"...");
 * if (hdl==NULL) return(fcberrno);
 * do {
 *    do {
 *       fcbgtn(hdl,...);
 *       outlen=0; // ensure a length error
 *       err=flcconv(hdl,inplen,input,&outlen,output);
 *       if (err==FLMRTC_LEN) {
 *          output=realloc(output,outlen);
 *          err=flcconv(hdl,inplen,input,&outlen,output);
 *       }
 *       if (err && err!=FLMRTC_EOT) {
 *          fcbclosev(hdl);
 *          return(err);
 *       }
 *       if (outlen>0) {
 *         // process output
 *       }
 *    } while(err==FLMRTC_EOT);
 *    input+=inplen;
 * } while (input<end && err==FLMRTC_OK);
 * fcbclosev(hdl);
 * return(err);
 * </pre>
 *
 * To simplify the EOT handling and to increase performance, you can use the
 * corresponding p(ointer) function (#fcbconp()) which returns a pointer to
 * the data, where no length error can occur.
 *
 * @param [in]    cnv    Conversion handle from #fcbopenv()
 * @param [in]    inplen Length of the input buffer
 * @param [in]    inp    Pointer to the input buffer
 * @param [inout] outlen On input: Available space for the output buffer
 *                       At output: If return code 0: length of the output buffer
 *                                  If return code FLMRTC_LEN: required minimum length for @p out
 * @param [out]   out    Pointer to the output buffer
 * @return A FLAM return code or 0 if successful
 */
extern int fcbconv(void* cnv, size_t inplen, const void* inp, size_t* outlen, void* out);

/**
 * @brief Converts independent data blocks (with locate)
 *
 * This function is identical to #fcbconv(), except that the output buffer
 * is not user-provided. When the function returns, the buffer pointer
 * pointed to by the @p out parameter is set to a buffer that is large enough
 * to store the output data. As a result, the return code can never be FLMRTC_LEN.
 *
 * @param [in]    cnv    Conversion handle from #fcbopenv()
 * @param [in]    inplen Length of the input buffer
 * @param [in]    inp    Pointer to the input buffer
 * @param [out]   outlen Length of the output buffer out
 * @param [out]   out    Pointer to the output buffer pointer
 * @return A FLAM return code or 0 if successful
 */
extern int fcbconp(void* cnv, size_t inplen, const void* inp, size_t* outlen, void** out);

/**
 * @brief Converts dependent data blocks (with copy)
 *
 * The function converts data between formats as specified by the conversion
 * string passed to #fcbopenv().
 *
 * It provides memory to memory conversion between external data representations
 * of different data types using a conversion handle from function #fcbopenv()
 * which was called with a conversion string of the form from-to or read-write.
 *
 * This function must be used instead of #fcbconv() if processing consecutive
 * blocks of data, e.g. whole files. If no sufficient amount of input data
 * is available, the output length (outlen) might be shorter than the input
 * or even zero. When the last input block is processed, the function #fcbfinv()
 * must be called to force any pending data to be processed and written to the
 * output buffer. Failing to call #fcbfinv() might result in truncated output!
 *
 * The return code FLMRTC_LEN tells that the output buffer is too small.
 * In this case you can provide a larger buffer to get the conversion done.
 * The required length for the output buffer is provided in the <code>outlen</code>
 * parameter.
 *
 * @param [in]    cnv    Conversion handle from #fcbopenv()
 * @param [in]    inplen Length of the input buffer
 * @param [in]    inp    Pointer to the input buffer
 * @param [inout] outlen Length of the output field
 * @param [out]   out    Pointer to the output buffer
 * @return The fcberrno containing the FLAM return code or 0 if success
 */
extern int fcbrunv(void* cnv, size_t inplen, const void* inp, size_t* outlen, void* out);

/**
 * @brief Converts dependent data blocks (with locate)
 *
 * This function is identical to #fcbrunv(), except that the output buffer
 * is not user-provided. When the function returns, the buffer pointer
 * pointed to by the @p out parameter is set to a buffer that is large enough
 * to store the output data. As a result, the return code can never be FLMRTC_LEN.
 *
 * @param [in]    cnv    Conversion handle from #fcbopenv()
 * @param [in]    inplen Length of the input buffer
 * @param [in]    inp    Pointer to the input buffer
 * @param [out]   outlen Length of the output field
 * @param [out]   out    Pointer to the output buffer pointer
 * @return
 */
extern int fcbrunp(void* cnv, size_t inplen, const void* inp, size_t* outlen, void** out);

/**
 * @brief Finish conversion of dependent data blocks (with copy)
 *
 * This function must be called to finish data conversion when #fcbrunv() is used.
 * It forces all internally buffered, but unprocessed data to be converted and
 * written to the ouput buffer.
 *
 * A final block of input data may be passed. Calling with a zero length is also valid.
 *
 * The return code FLMRTC_LEN tells that the output buffer is too small.
 * In this case you can provide a larger buffer to get the conversion done.
 * The required length for the output buffer is provided in the <code>outlen</code>
 * parameter.
 *
 * @param [in]    cnv    Conversion handle from #fcbopenv()
 * @param [in]    inplen Length of the input buffer
 * @param [in]    inp    Pointer to the input buffer
 * @param [inout] outlen Length of the output field
 * @param [out]   out    Pointer to the output buffer
 * @return The fcberrno containing the FLAM return code or 0 if success
 */
extern int fcbfinv(void* cnv, size_t inplen, const void* inp, size_t* outlen, void* out);

/**
 * @brief Finish conversion of dependent data blocks (with locate)
 *
 * This function is identical to #fcbfinv(), except that the output buffer
 * is not user-provided. When the function returns, the buffer pointer
 * pointed to by the @p out parameter is set to a buffer that is large enough
 * to store the output data. As a result, the return code can never be FLMRTC_LEN.
 *
 * @param [in]    cnv    Conversion handle from #fcbopenv()
 * @param [in]    inplen Length of the input buffer
 * @param [in]    inp    Pointer to the input buffer
 * @param [out]   outlen Length of the output field
 * @param [out]   out    Pointer to the output buffer pointer
 * @return The fcberrno containing the FLAM return code or 0 if success
 */
extern int fcbfinp(void* cnv, size_t inplen, const void* inp, size_t* outlen, void** out);

/**
 * @brief Returns the end-of-file (EOF) flag
 *
 * Checks whether the end-of-file indicator associated with the handle
 * is set, returning a value different from zero if it is.
 *
 * @param [in] hdl File or conversion handle from #fcbopen() or #fcbopenv()
 * @return A non-zero value is returned in the case that the end-of-file
 *         indicator associated with the handle is set. Otherwise, zero
 *         is returned.
 */
extern int fcbeof(void* hdl);

/**
 * @brief Returns the end-of-table (EOT) flag
 *
 * Checks whether the end-of-table indicator associated with the handle
 * is set, returning a value different from zero if it is.
 *
 * @param [in] hdl File or conversion handle from #fcbopen() or #fcbopenv()
 * @return A non-zero value is returned in the case that the end-of-table
 *         indicator associated with the handle is set. Otherwise, zero
 *         is returned.
 */
extern int fcbeot(void* hdl);

/**
 * @brief Get error code
 *
 * Returns the error code for the last FLUC byte interface operation on
 * the provided handle. If the handle is null, the error code of the last
 * overall byte interface operation is returned (i.e. to get the error
 * code after a call to #fcbopen() failed).
 *
 * @param [in] hdl File or conversion handle from #fcbopen() or #fcbopenv()
 * @return A non-zero value if the last operation resulted in an error,
 *         zero otherwise.
 */
extern int fcberror(void* hdl);

/**
 * @brief Get error message
 *
 * This function can be used to retrieve a human-readable error message
 * using the error code returned by fcberror().
 *
 * @param [in] code A valid error code
 * @return A pointer to a static area with a zero-terminated string
 *         containing a FLAM error message matching the passed error code
 *         as one line. (no LF)
 */
extern const char* fcberrms(int code);

/**
 * @brief Get error trace
 *
 * This function can be used to get an error trace after a call to
 * #fcbopen(), #fcbopen2(),#fcbread(), #fcbwrite(), #fcbclose(), #fcbclose2(),
 * #fcbhelp() or #fcbsyntax(). The error trace contains the FLAM error
 * stack. If parsing the file or format string failed, the error trace
 * also contains the complete error stack of the Command-Line-Parser
 * (FLAMCLP).
 *
 * @return a pointer to a static area with a zero-terminated string
 *         containing the current FLAM error trace on several lines.
 */
extern const char* fcberrtr(void);

/**
 * @brief Clear error and EOF indicators
 *
 * This functions clears the end-of-file and error indicators for the
 * given stream.
 *
 * @param [in] hdl File or convesion handle from #fcbopen() or #fcbopenv()
 */
extern void fcbclearerr(void* hdl);

/**
 * @brief Returns help information about the file and format strings
 *
 * This function can be used to get all help messages or man pages for
 * each parameter in the file and format strings. If depth 0 or greater
 * then 9 aliases are provided. In all other cases aliases are suppressed.
 * Please use #fcbsyntax() to see possible aliases for the same argument.
 *
 * @param[in]  what  Integer constant for the corresponding file or format string (one of FLC_READ_* or FLC_WRITE_*)
 * @param[in]  depth Number of levels to display (0-Man page, 1-One Level, 2-Two Level, ..., <9-All)
 * @param[in]  path  Path (e.g. read.text.ccsid) to limit help to the (sub)tree of a certain object
 *
 * @return a pointer to a static area with a zero-terminated string
 *         containing the help information on several lines, in case
 *         of an error the string is empty.
 */
extern const char* fcbhelp(const int what, const int depth, const char* path);

/**
 * @brief Returns syntax information about the file and format strings
 *
 * This function can be used to determine the complete syntax of the
 * file and format strings.
 *
 * @param[in]  what  Integer constant for the corresponding file or format string (one of FLC_READ_* or FLC_WRITE_*)
 * @param[in]  depth Number of levels to display (0-Man page, 1-One Level, 2-Two Level, ..., <9-All)
 * @param[in]  path  Path (e.g. read.text.ccsid) to limit syntax to the (sub)tree of a certain object
 *
 * @return a pointer to a static area with a zero-terminated string
 *         containing the syntax information in one (level == 1) or
 *         several lines (level > 1), in case of an error the string
 *         is empty.
 */
extern const char* fcbsyntax(const int what, const int depth, const char* path);

/**
 * @brief Check syntax for a certain CLP string
 *
 * This function can be used to check if a CLP string is correct.
 *
 * @param[in]  what    Integer constant for the corresponding file or format string (one of FLC_READ_* or FLC_WRITE_*)
 * @param[in]  string  The CLP string to check
 *
 * @return a pointer to a static area with a zero-terminated string
 *         containing the error or NULL if CLP string is correct.
 */
extern const char* fcbcheck(const int what, const char* string);

/**
 * @brief Determine current amount of processed data
 *
 * This function can be used to determine different statistical values
 * from a file or memory conversion handle. This can be used to control
 * the size of the output or how many records are read.
 *
 * The value returned is the current value from the corresponding component.
 * This value is normally calculated at the end of the processing of one
 * chunk of data. This means, that the data which is currently collected
 * to a chunk of data is not included. At write for example you can
 * control how many bytes are processed by the formatting component (XML
 * written). If a certain limit is achieved you can close the file or start
 * a new member, but the resulting size of the file or member will be
 * increased by the remaining rest of the data which are not yet processed
 * but collected in the buffers.
 *
 * @param [in] hdl         File or conversion handle from #fcbopen() or #fcbopenv()
 * @param [in] direction   Input (1) or output (2)
 * @param [in] what        File I/O (1) or Formating (2)
 * @param [in] kind        Bytes (1) or Units (2)
 * @return  >=0 the requested amount, <0 error (FLAM reason code * -1)
 */
extern long long int fcbcount(void* hdl, const int direction, const int what, const int kind);

/**
 * @brief Creates a handle for Base16/32/64 encoding or decoding
 *
 * #fcbbini() creates and returns a handle for Base16/32/64 conversion that
 * can be passed to #fcbbrun() (to convert data) and #fcbbfin() (to release
 * the handle). May return NULL on error.
 *
 * To convert data to or from Base16/32/64 that does not fit in a single buffer,
 * the following sequence of function calls can be used:
 *
 * <pre>
 *    fcbbini()
 *    fcbbrun()
 *    fcbbrun()
 *    ...
 *    fcbbfin()
 * </pre>
 *
 * @param [in]    mode     Mode: 1 is Encode and 0 is Decode
 * @param [in]    base     Base: possible values 16, 32 or 64
 * @param [in]    chrs     Character set: 1 is ASCII and 2 is EBCDIC, otherwise the system character set is used
 * @return hdl A valid handle or NULL on error
 */
extern void* fcbbini(
   const unsigned int   mode,
   const unsigned int   base,
   const unsigned int   chrs);

/**
 * @brief En- or Decodes a data buffer
 *
 * #fcbbrun() converts the provided binary data buffer. The @p hdl must be
 * initialized by #fcbbini() first. The output buffer must be big enough to
 * write the encoded or decoded data in order to avoid buffer overflows.
 * When decoding, incomplete encoded bytes may occur at the end of the input
 * buffer, which are buffered internally until more input is provided with
 * the next call of this function. You must account for this in the size of
 * the ouput buffer.
 *
 * @param [in]    hdl      Handle created by #fcbbini()
 * @param [in]    inlen    Number of bytes in @p in
 * @param [in]    in       Input data buffer
 * @param [out]   out      Output data buffer
 * @return Number of bytes written to @p out, negative number on error
 */
extern int fcbbrun(
   void*                hdl,
   const int            inlen,
   const unsigned char* in,
   unsigned char*       out);

/**
 * @brief Finalize en- or decoding
 *
 * #fcbbfin() converts the provided binary data buffer. The @p hdl must be
 * initialized by #fcbbini() first. The output buffer must be big enough to
 * write the encoded or decoded data in order to avoid buffer overflows.
 * When decoding, incomplete encoded bytes at the end of the input buffer
 * lead to an error. However, this function may process incomplete encoded
 * bytes from previous calls to #fcbbrun(), which are buffered internally.
 * You must account for this in the size of the ouput buffer.
 *
 * @param [in]    hdl      Handle created by #fcbbini()
 * @param [in]    inlen    Number of bytes in @p in
 * @param [in]    in       Input data buffer
 * @param [out]   out      Output data buffer
 * @return Number of bytes written to @p out, negative number on error
 */
extern int fcbbfin(
   void*                hdl,
   const int            inlen,
   const unsigned char* in,
   unsigned char*       out);

/**
 * @brief Base encoding or decoding for one message
 *
 * The #fcbbase() function does the same as #fcbbini() and #fcbbfin()
 * It is a shortcut if the input data is not scattered.
 *
 * @param [in]    mode     Mode: 1 is Encode and 0 is Decode
 * @param [in]    base     Base: possible values 16, 32 or 64
 * @param [in]    chrs     Character set: 1 is ASCII and 2 is EBCDIC otherwise system character set is used
 * @param [in]    inlen    Length of @p in
 * @param [in]    in       Input data for en- or decoding
 * @param [out]   out      Output data
 * @return >=0 produced output length else error
 */
extern int fcbbase(
   const unsigned int   mode,
   const unsigned int   base,
   const unsigned int   chrs,
   const int            inlen,
   const unsigned char* in,
   unsigned char*       out);

/**
 * @brief Initialize hash calculation
 *
 * #fcbbini() creates and returns a handle for hash calculation that
 * can be passed to #fcbhadd() (to add more data to hash) and #fcbbfin()
 * (returns the hash result). May return NULL on error.
 *
 * To calculate a hash for data that does not fit in a single buffer,
 * the following sequence of function calls can be used:
 *
 * <pre>
 *    fcbhini()
 *    fcbhadd()
 *    fcbhadd()
 *    ...
 *    fcbhfin()
 * </pre>
 *
 * @param [in]      hmtd     Hash method to use, for example #FLCHSH_ALGO_SHA1 see header FLMDEF.h
 * @param [in]      kmtd     MAC method to use (if any), for example #FLCMAC_ALGO_HMAC see header file FLMDEF.h
 * @param [in]      keylen   Length of @p key in bytes
 * @param [in]      key      Key to use in hash calculation (only for keyed MAC or HMAC calculations)
 * @param [in]      icvlen   Length of @p icv
 * @param [in]      icv      Initial chaining vector (only for certain MAC calculations)
 * @return hdl A valid handle or NULL on error
 */
extern void* fcbhini(
   const unsigned int   hmtd,
   const unsigned int   kmtd,
   const unsigned int   keylen,
   const unsigned char* key,
   const unsigned int   icvlen,
   const unsigned char* icv);

/**
 * @brief Adds a buffer of data to the hash calculation
 *
 * #fcbhadd() adds a buffer of binary data to the hash calculation.
 * The @p hdl must be initialized by #fcbhini() first.
 *
 * @param [in]      hdl      Handle initialized with #fcbhini()
 * @param [in]      datlen   Length of @p dat
 * @param [in]      dat      Input data chunk to add to hash calculation
 * @return 0 on success, non-zero on error
 */
extern int fcbhadd(
   void*                hdl,
   const unsigned int   datlen,
   const unsigned char* dat);

/**
 * @brief Finalize hash calculation
 *
 * #fcbhfin() stores the calculated hash to the buffer pointer to by the
 * @p hsh parameter. The handle @p hdl must be initialized by #fcbhini()
 * and is released by this function. The parameter @p hshlen must point
 * to an unsigned integer containing the size of the @p hsh buffer and
 * will be set to the length of the hash in bytes when this function
 * return successfully. If the output buffer is shorter than the hash
 * length, the hash will be truncated.
 *
 * @param [in]      hdl      Handle initialized with #fcbhini()
 * @param [inout]   hshlen   Input: size of @p hsh ; output: length of @p hsh result
 * @param [out]     hsh      Buffer where calculated hash is written to
 * @return 0 on success, non-zero on error
 */
extern int fcbhfin(
   void*                hdl,
   unsigned int*        hshlen,
   unsigned char*       hsh);

/**
 * @brief Calculate hash for a single buffer
 *
 * The #fcbhash() function does the same as #fcbhini(), #fcbhadd(), #fcbhfin().
 * Refer to the documentation of these functions for details.
 * It is a shortcut for calculating the hash for a single buffer of data.
 *
 * @param [in]      hmtd     Hash method to use, for example #FLCHSH_ALGO_SHA1 see header FLMDEF.h
 * @param [in]      kmtd     MAC method to use, for example #FLCMAC_ALGO_HMAC see header file FLMDEF.h
 * @param [in]      keylen   Length of @p key
 * @param [in]      key      Key to use in hash calculation
 * @param [in]      icvlen   Length of @p icv
 * @param [in]      icv      Initial chaining vector (only for certain MAC calculation)
 * @param [in]      datlen   Length of @p dat
 * @param [in]      dat      Input data chunk to add to hash calculation
 * @param [inout]   hshlen   On input size of @p hsh on output length of @p hsh
 * @param [out]     hsh      Buffer where calculated hash is written to
 * @return 0 on success, non-zero on error
 */
extern int fcbhash(
   const unsigned int   hmtd,
   const unsigned int   kmtd,
   const unsigned int   keylen,
   const unsigned char* key,
   const unsigned int   icvlen,
   const unsigned char* icv,
   const unsigned int   datlen,
   const unsigned char* dat,
   unsigned int*        hshlen,
   unsigned char*       hsh);


/** @} */
/**********************************************************************/
/*! @cond PRIVATE */
#define FCB_KIND_NONE            0x00000000u
#define FCB_KIND_BLOCK           0x00000001u
#define FCB_KIND_RECORD          0x00000002u
#define FCB_KIND_ELEMENT         0x00000004u
#define FCB_KIND_ALL             0xFFFFFFFFu
extern int           flopen9(char* pcErr, void** ppGbl,const int sys, const int std, const char* env, const char* param);
extern int           flclose9(char* pcErr, void* pvGbl);
extern int           fcbvsn9(const int l, const int s, char* b);
extern int           fcbabo9(const int l, const int s, char* b);
extern int           fcblic9(const int s, char* b);
extern int           fcbinfo9(void* pvGbl, char* pcErr, const char* infstr, const int format, size_t* bufsiz, char** buffer, unsigned int* piLen);
extern int           fcbopen9(void* pvGbl, char* pcErr, void** ppHdl, const char* filstr, const char* fmtstr, char** state, unsigned int kind, const int64_t offset, const int number, const int isContinue);
extern int           fcbnewmbr9(char* pcErr, void* hdl,const char* fmtstr,const char* state, const int stafmt, size_t* stasiz, char** stabuf);
extern int           fcbgtn9(char* pcErr, void* hdl, const char** name);
extern int           fcbstn9(char* pcErr, void* hdl, const char* name);
extern int           fcbgfn9(char* pcErr, void* pvHdl, const int uiIndex, const char** ppName);
extern int           fcbflush9(char* pcErr, void* hdl, const int final, const int force);
extern int           fcbclose9(char* pcErr, void* hdl, const int success, const int stafmt, size_t* stasiz, char** stabuf, int* ivrSize, char** ivrBuf, int* ivrFmtSize, char** ivrFmtBuf, const int isContinue);
extern int           fcbopenv9(void* pvGbl, char* pcErr, void* hdl, void**ppHdl, const char* cnvstr);
extern int           fcbclosev9(char* pcErr, void* cnv);
extern int           fcbreadv9(char* pcErr, size_t* piRet, void* ptr, size_t size, size_t count, void* hdl, void* cnv, const int skip, size_t* len);
extern int           fcbunreadv9(char* pcErr, const void* ptr, size_t size, size_t count, void* hdl, void* cnv);
extern int           fcbwritev9(char* pcErr, size_t* piRet, const void *ptr, size_t size, size_t count, void* hdl, void* cnv);
extern int           fcbconv9(char* pcErr, void* cnv, size_t inplen, const void* inp, size_t* outlen, void* out);
extern int           fcbrunv9(char* pcErr, void* cnv, size_t inplen, const void* inp, size_t* outlen, void* out);
extern int           fcbfinv9(char* pcErr, void* cnv, size_t inplen, const void* inp, size_t* outlen, void* out);
extern int           fcbconp9(char* pcErr, void* cnv, size_t inplen, const void* inp, size_t* outlen, void** out);
extern int           fcbrunp9(char* pcErr, void* cnv, size_t inplen, const void* inp, size_t* outlen, void** out);
extern int           fcbfinp9(char* pcErr, void* cnv, size_t inplen, const void* inp, size_t* outlen, void** out);
extern int           fcbpos9(char* pcErr, void* hdl, const int64_t offset);
extern int           fcbrewind9(char* pcErr, void* pvHdl);
extern int           fcbcount9(char* pcErr, void* hdl, const int direction, const int what, const int kind, long long int* piCount);

extern int           fcbopnlog9(void* pvGbl, char* pcErr, void** loghdl, const char* logstr);
extern int           fcbgetlog9(void* loghdl,const char** buffer);
extern int           fcbclrlog9(void* loghdl);
extern int           fcbclslog9(void* loghdl);

extern void*         fcbpopen(char* errtrc, const char* filstr, const char* fmtstr, char** state, const int64_t offset);
extern int64_t       fcbpread(char* errtrc, void* hdl, void* ptr, size_t count, int64_t offset);
extern int64_t       fcbpwrite(char* errtrc, void* hdl, const void* ptr, size_t count, int64_t offset);
extern int           fcbpclose(char* errtrc, void* hdl, const int success, const int stafmt, size_t* stasiz, char** stabuf, int* ivrSize, char** ivrBuf, int* ivrFmtSize, char** ivrFmtBuf);
extern int           fcbpflush(char* errtrc, void* hdl, const int final, const int force);
extern int           fcbpfiopar(void* hdl, void** ppFioPar);
extern uint64_t      fcbpsize(char* errtrc, const char* filstr, const char* fmtstr);

extern void*         fcbopen3(const char* filstr, const char* fmtstr, char** state, const int number); /* only for internal tests*/
extern size_t        fcbreadr(void* ptr, size_t size, size_t count, void* hdl, void* cnv, const int skip); /* only for record interface*/
extern int           fcbisenvar(const int set);

/*! @endcond */
/**********************************************************************/

/*! @cond PRIVATE */
#endif /* INC_FLCBYT_H */

#ifdef __cplusplus
   }
#endif
 /*! @endcond */

/**********************************************************************/
