/* ----------------------------------------------------------------------------
 * Raima Database Manager
 *
 * Copyright (c) 2010 Raima Inc.,  All rights reserved.
 *
 * Use of this software, whether in source code format, or in executable,
 * binary object code form, is governed by the Raima LICENSE which
 * is fully described in the LICENSE.TXT file, included within this
 * distribution of files.
 * ----------------------------------------------------------------------------
 */

#if !defined(BASE_H)
#define BASE_H

#include "psp.h"        /* for TXID */
#include "transport.h"

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

#define RDM_MAX_TEXT    20
#define RDM_MAX_STRING  255
#define RDM_MAX_BUFFER  1024
#define DBD_COMPAT_LEN  6

/* =========================================================================
   Command line handling definitions
*/

/* Mode flags for cmdline_opt.opttype */

#define ARG_END         0
#define ARG_OPT         1
#define ARG_FINAL       2
#define ARG_FINAL_MULTI 3
#define ARG_FINAL_OPT   4
#define ARG_DEPRECATED  5

#define B_CMD_OKAY     (0)
#define B_CMD_USAGE    (1)
#define B_CMD_VERSION  (2)
#define B_CMD_ERROR   (-1)

/* tfs types */
typedef enum
{
    TFS_TYPE_TFS, /* TFST: built-in tfs */
    TFS_TYPE_RPC, /* TFSR: remote client */
    TFS_TYPE_STANDALONE, /* TFSS: standalone tfs */ 
    TFS_TYPE_DEFAULT /* default configuration - tfst */
} TFS_TYPE;

/** Enumeration for RDM boolen values
 *
 *   This enumeration adds support for a platform/language agnostic BOOLEAN value in the RDM
 *   library
 */
typedef enum RDM_BOOLEAN_E
{
    RDM_FALSE = 0,   /**< enum value for FALSE */
    RDM_TRUE  = 1    /**< enum value for TRUE  */
} RDM_BOOLEAN;

/** Enumeration for RDM print type value
 *
 *   This enumeration adds support for specifying how to display structures inside functions
 *   provided to display the structure contents
 */
typedef enum RDM_PRINT_TYPE_E
{
    RDM_PRINT_CONSOLE = 0,   /**< enum value for formatting values to print to a console */
    RDM_PRINT_XML  = 1       /**< enum value for formatting values to print as XML  */
} RDM_PRINT_TYPE;

typedef struct _cmdline_status 
{
    uint16_t    quiet;
    uint16_t    stdout_opened;
    uint16_t    stderr_opened;
    TFS_TYPE    tfs_type;
    const char *enc_key;
    const char *docroot;
} cmdline_status;

typedef struct _default_opts 
{
    uint8_t no_help;
    uint8_t no_banner;
    uint8_t no_version;
    uint8_t no_quiet;
    uint8_t no_stdout;
    uint8_t no_stderr;
    uint8_t no_tfs;
    uint8_t no_encryption;
    uint8_t no_docroot;
    uint8_t no_docroot_alias;
} default_opts;

/* Generic usage function option record */
typedef struct tag_cmdline_opt {
    int16_t     opttype;  /* type of option record, see above for choices */
    const char *opt;
    const char *optarg;
    const char *desc;     /* option description string (may be NULL) */
    int32_t     descval;  /* integer for %d (if any) in desc. string */
    int16_t     state;    /* private - processing state */
    int16_t     next_arg; /* private - processing state, only for '*' */
    int32_t     optcnt;   /* private - number of instances, only for '*' */
    union {
        const char  *arg;
        int32_t      final_id;
        const char **arglist;
    } data;                    /* private */
} cmdline_opt;

#define HELP_ARG     "h"
#define BANNER_ARG   "B"
#define VERSION_ARG  "V"
#define QUIET_ARG    "q"
#define TFS_ARG      "tfs type"
#define STDOUT_ARG   "stdout file"
#define STDERR_ARG   "stderr file"
#define KEY_ARG      "key key"
#define DOCROOT_ARG  "docroot path"

#define OPT_CHAR    "-"

#if defined(RDM_UNIX)
#define CHARSINCRLF 1
#else
#define CHARSINCRLF 2
#endif

#define HELP_DESC    "Display this usage information"
#define BANNER_DESC  "Do not display the banner"
#define VERSION_DESC "Display the version information"
#define QUIET_DESC   "Quiet mode.  No information will be displayed"
#define TFS_DESC     "Specify the TFS type to use (TFST, TFSR, or TFSS) [default = TFST]"
#define STDOUT_DESC  "Redirect stdout to the specified file"
#define STDERR_DESC  "Redirect stderr to the specified file"
#if defined(RDM_WITH_STRONG_ENCRYPTION)
#define KEY_DESC     "Specify the encryption key for the database [algorithm:]passcode.  The valid algorithms are xor, aes128, aes192, and aes256.  If an algorithm is not specified the default is " ENC_DEFAULT_TEXT
#else
#define KEY_DESC     "Specify the encryption key for the database [algorithm:]passcode.  The valid only valid algorithm for this version is xor."
#endif
#define DOCROOT_DESC "Document root under which to place database files."

RDM_EXPORT int32_t EXTERNAL_FCN b_cmd_finaloptpos(
    const cmdline_opt *opts);

RDM_EXPORT int32_t EXTERNAL_FCN b_cmd_initopt( /*lint -esym(534,b_cmd_initopt*) */
    const char         *banner,
    int32_t             argc,
    const char *const   argv[],
    cmdline_opt        *opts,
    const default_opts *defaults,
    cmdline_status     *status);

RDM_EXPORT char EXTERNAL_FCN b_cmd_nextoptchr(
    cmdline_opt *opts,
    const char **arg);

RDM_EXPORT const char *EXTERNAL_FCN b_cmd_nextoptstr(
    cmdline_opt *opts,
    const char **arg);

RDM_EXPORT int32_t EXTERNAL_FCN b_cmd_nextoptidx(
    cmdline_opt *opts,
    const char **arg);

RDM_EXPORT int32_t EXTERNAL_FCN b_cmd_std_usage(  /*lint -esym(534,b_cmd_std_usage*) */
    const char         *progname,
    const char         *errmsg,
    const cmdline_opt  *opts,
    const default_opts *defaults);

RDM_EXPORT int32_t EXTERNAL_FCN b_cmd_expand(
    int32_t            argc,
    const char  *const argv[],
    int32_t           *exArgc,
    const char *const *exArgv[]);

RDM_EXPORT void EXTERNAL_FCN b_cmd_freeArgv(
    int32_t           argc,
    const char *const argv[]);

/* =========================================================================
   Log file handling defintions
*/

/* Database File Location - used if mirrored slave has database files located
   opposite from master (ie: in-memory to on-disk)
*/
typedef enum {  DFL_DEFAULT = 0,
                DFL_INMEM,
                DFL_DISK
             } DFL_TYPE;
                 
typedef enum TX_LOG_VERSION_E
{
    TX_LOG_VERSION_001 = 1,  /**< The log file format for a single transaction per log */
    TX_LOG_VERSION_002       /**< The initial log file format for multiple transactions in a log */
} TX_LOG_VERSION;
#define TX_CURRENT_LOG_VERSION TX_LOG_VERSION_002

typedef struct TX_LOG_HDR_S
{
    uint64_t        starting_txid;           /**< the starting txid in the log */    
    uint64_t        lfid;                    /**< the log identifier for this log file */    
    uint64_t        max_size;                /**< the maximum size of the log file */    
    uint64_t        num_trans;               /**< the number of transactions stored in the log */
    uint64_t        max_trans;               /**< the max number of transactions that can be stored in the file */
    uint16_t        log_ver;                 /**< transaction log version format */
    uint16_t        status;                  /**< A TX_LOG_STATUS enum value for the log status */
    char            dbd_ver[DBD_COMPAT_LEN]; /**< the dbd format this log file supports */ 
    uint16_t        dummy01;                 /**< a dummy field so the structure is a multiple of 8 bytes */
    uint16_t        dummy02;                 /**< a dummy field so the structure is a multiple of 8 bytes */
    uint16_t        dummy03;                 /**< a dummy field so the structure is a multiple of 8 bytes */
} TX_LOG_HDR;

typedef struct {
    char    *tmp_buffer;
    uint32_t tmp_buffer_size;
} LOG_CTX;

typedef struct LOG_FILE_CTX_S 
{
    TX_LOG_HDR             hdr;                      /**< the transaction log file header */
    PSP_FILE_OFFSET        current_size;             /**< the current size of the log file */
    PSP_SEM                sem;                      /**< a semaphore to arbitrate log file access */
    PSP_FH                 logfh;                    /**< the log file handle for TFS threads */
    struct LOG_FILE_CTX_S *next;                     /**< the next log file */
    struct LOG_FILE_CTX_S *prev;                     /**< the previous log file */
    uint16_t               modified;                 /**< has the log file been modified */
    uint16_t               sync;                     /**< should we sync the log file */
    TXID                   last_txid;                /**< the last txid stored in the log file */
    struct DB_REC_S       *db_rec;                   /**< the database this log file has tranactions for */
    char                  *name;                     /**< place to store the log file name */
    uint16_t              xflags;                    /**< the open flags for the log file */

    /* These are helper varaiables for checkpoing transactions in the log */
    PSP_FILE_OFFSET        dbfile_offset;            /**< the offset for next TX_DB_FILE_HDR to checkpoint */
    PSP_FILE_OFFSET        page_offset;              /**< the offset for next TX_PAGE_HDR to checkpoint */
    char                  *filename;                 /**< place to store the db file name the checkpointer is processing */
    uint32_t               filename_size;            /**< the current size of the filename buffer */
    uint32_t               pagesize;                 /**< the pagesize for the database file the checkpointer is processing */
    LOG_CTX               *log_ctx_read;             /**< the temporary buffer for reading pages from the log file */
    LOG_CTX               *log_ctx_write;            /**< the temporary buffer for writing pages to the log file */

    uint32_t               curr_page;
    uint32_t               curr_file;
} LOG_FILE_CTX;

typedef const void *B_LOG_DATA;

#define B_LOG_VERSION 1

#define LOG_FH_NULL ((LOG_FILE_CTX *) 0)

#define MULTITRANS_LOG_EXTENSION "tlog"
#define LOG_EXTENSION            "log"
#define REPLOG_EXTENSION    "rep"
#define MIRLOG_EXTENSION    "mir"
#define DATLOG_EXTENSION    "dat"
#define PRELOG_EXTENSION    "prelog"
#define REPPRELOG_EXTENSION "rep_prelog"
#define REPTMPLOG_EXTENSION "rep_tmplog"
#define DBLOG_EXTENSION     "db"

/* We specify 8 bytes for the transaction id, but it can actually be 16 bytes
 * long.  */
#define LOGIFIED_DATLOG_FILE COMMITTED_LOG_FILE "." DATLOG_EXTENSION
#define MULTITRANS_LOG_FILE UINT64_SPEC_SIZE_HEX("08") "." MULTITRANS_LOG_EXTENSION
#define COMMITTED_LOG_FILE UINT64_SPEC_SIZE_HEX("08") "." LOG_EXTENSION
#define COMMITTED_REPTMP_FILE UINT64_SPEC_SIZE_HEX("08") "." REPTMPLOG_EXTENSION
#define COMMITTED_REPLOG_FILE COMMITTED_LOG_FILE "." REPLOG_EXTENSION
#define COMMITTED_REPTMP_FILE UINT64_SPEC_SIZE_HEX("08") "." REPTMPLOG_EXTENSION
#define MIR_LOG_FILE COMMITTED_LOG_FILE "." MIRLOG_EXTENSION
#define DATABASE_LOG_FILE  UINT64_SPEC_SIZE_HEX("08") "." UINT64_SPEC_SIZE_HEX("04") "." LOG_EXTENSION "." DBLOG_EXTENSION

#define MULTITRANS_LOG_FILE_PATTERN "*." MULTITRANS_LOG_EXTENSION
#define COMMITTED_LOG_FILE_PATTERN "*." LOG_EXTENSION
#define REPLOG_FILE_PATTERN        COMMITTED_LOG_FILE_PATTERN "." REPLOG_EXTENSION
#define DATLOG_FILE_PATTERN        COMMITTED_LOG_FILE_PATTERN "." DATLOG_EXTENSION
#define DB_LOG_FILE_PATTERN        COMMITTED_LOG_FILE_PATTERN "." DBLOG_EXTENSION
#define ALL_LOG_FILE_PATTERN       COMMITTED_LOG_FILE_PATTERN "*"
#define PRE_LOG_FILE_PATTERN       "*." PRELOG_EXTENSION
#define REPPRE_LOG_FILE_PATTERN    "*." REPPRELOG_EXTENSION
#define REPTMP_LOG_FILE_PATTERN    "*." REPTMPLOG_EXTENSION
#define CLEANUP_LOG_FILE_PATTERN   COMMITTED_LOG_FILE_PATTERN ".*"

typedef struct TX_ENTRY_HDR_S
{
    uint64_t     txid;             /**< transaction identification number */
    uint64_t     first_file;       /**< The offset to the first TX_DB_FILE_HDR for the db files in this 
                                        transaction */
    uint64_t     next_trans;       /**< The offset to next transaction header in the log file */
    uint64_t     replog_offset;    /**< The offset to the first replication action log chunk (can be 0 if
                                        the transaction will not be replicated) */
    uint16_t     status;           /**< A TX_ENTRY_STATUS enum value for the log status */
    uint16_t     num_files;        /**< the number of files modified in the transaction */
    uint16_t     dummy01;          /**< a dummy field so the structure is a multiple of 8 bytes */
    uint16_t     dummy02;          /**< a dummy field so the structure is a multiple of 8 bytes */
} TX_ENTRY_HDR;

typedef struct TX_DB_FILE_HDR_S
{
    uint64_t  first_page;       /**< The offset to the first TX_PAGE_HDR for the file data */
    uint64_t  next_file;        /**< The offset to the next TX_DB_FILE_HDR.  If this is the last 
                                     file in this transaction the value will be zero */
    uint32_t  pagesize;         /**< the database file page size */    
    uint32_t  num_pages;        /**< the number of pages for this file in the log */
    uint32_t  filename_len;     /**< length of the database file name */
    uint16_t  x_flags;          /**< xflags for opening the database file */
    uint16_t  initialize;       /**< the file initialization flag */
    char     *filename;         /**< the name of the database file */
} TX_DB_FILE_HDR;

typedef struct TX_PAGE_HDR_S
{
    uint64_t  next_page;         /**< offset to the next page for this file.  If this is
                                      the last page in the file the value will be zero */
    uint64_t  page_no;           /**< the page number */
    uint32_t  actual_size;       /**< the compressed size of the page buffer */
    uint16_t  compression_type;  /**< a RDM_COMPRESSION_TYPE enum value */
    uint16_t  dummy;             /**< a dummy field so the structure is a multiple of 8 bytes */
} TX_PAGE_HDR;

typedef enum TX_ENTRY_STATUS_E
{
    TX_ENTRY_EMPTY = 0,            /**< The transaction entry has not been used */
    TX_ENTRY_IN_PROGRESS,          /**< The transaction entry is actively being written to */
    TX_ENTRY_PRECOMMIT,            /**< The transaction has been pre-committed, but not finalized */
    TX_ENTRY_HELD,                 /**< The transaction is being held based on ROT status */
    TX_ENTRY_READY,                /**< The transaction entry is ready to be checkpointed */
    TX_ENTRY_IMFLUSH_READY,        /**< The transaction entry for an inmemory flush is ready to be checkpointed */
    TX_ENTRY_CHECKPOINTED,         /**< The transaction entry has been checkpointed */
    TX_ENTRY_IMFLUSH_CHECKPOINTED, /**< The transaction entry for an inmemory flush has been checkpointed */
    TX_ENTRY_ROLLED_BACK,          /**< The transaction has been rolled back (should never be processed) */
    TX_ENTRY_ABANDONED             /**< The client crashed prior to finishing the transaction (should never 
                                        be processed) */
} TX_ENTRY_STATUS;

typedef enum TX_LOG_STATUS_E
{
    LOG_ACTIVE = 0,    /**< The transaction log is having entries added to it */
    LOG_COMPLETED,     /**< The transaction log is no longer having entries added to it */
    LOG_CHECKPOINTED,  /**< All log entries have been checkpointed */
    LOG_REMOVED        /**< The log file is currently being removed */
} TX_LOG_STATUS;

typedef enum { COMMITTED, HELD, ARCHIVE, DAT, REP, DB } LOG_FILE_TYPE;

typedef enum { NO_COMPRESSION=0, ZERO_COMPRESSION, LZ_COMPRESSION } RDM_COMPRESSION_TYPE;

RDM_EXPORT int32_t EXTERNAL_FCN b_log_open(const char *, uint16_t, uint16_t, LOG_FILE_CTX **);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_create(const char *, uint16_t, const char *, size_t, uint64_t, uint64_t, uint64_t, uint64_t, uint16_t, LOG_FILE_CTX **);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_close(const LOG_FILE_CTX *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_close_fh(LOG_FILE_CTX *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getVersion(const LOG_FILE_CTX *, char *, size_t);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_checkVersion(char *ver);

/* These functions are updated for the new log format */
RDM_EXPORT void    EXTERNAL_FCN b_log_sync(LOG_FILE_CTX *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getTransHdr(LOG_FILE_CTX *, TXID, TX_ENTRY_HDR *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getNextDbFile(LOG_FILE_CTX *, TX_DB_FILE_HDR *, DFL_TYPE);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getNextDbPage(LOG_FILE_CTX *, void *, uint32_t, uint32_t *, TX_PAGE_HDR *);
int32_t EXTERNAL_FCN b_log_getCurrDbPageData(LOG_FILE_CTX *, void *, uint32_t, const TX_PAGE_HDR *, uint32_t *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_precommit(LOG_FILE_CTX *, TXID, uint16_t, uint64_t);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_commit(LOG_FILE_CTX *, TXID);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_transSetStatus(LOG_FILE_CTX *, TXID, TX_ENTRY_STATUS);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getLfidFromLogFileName(const char *, uint64_t *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_putNewFile(LOG_FILE_CTX*, const TX_DB_FILE_HDR *, uint64_t *); /* JRP - remove */
RDM_EXPORT int32_t EXTERNAL_FCN b_log_putNewPage(LOG_FILE_CTX*, RDM_COMPRESSION_TYPE, uint64_t, uint64_t, uint64_t *, const void *, uint32_t);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getTxidFromLogFileName(const char *, TXID *, LOG_FILE_TYPE *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_setStatus(LOG_FILE_CTX*, TX_LOG_STATUS);

/* These functions currently work with the old log format.  the need to be updated or removed */
#if 0
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getNumFiles(LOG_FILE_CTX *, uint32_t *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getNextFile(LOG_FILE_CTX *, char *, uint32_t, uint16_t *, uint32_t *, uint16_t *, uint32_t *, DFL_TYPE);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getCurrFilename(LOG_FILE_CTX *, char *, uint32_t, uint32_t *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getCurrNumPages(LOG_FILE_CTX *, uint32_t *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getCurrXFlags(LOG_FILE_CTX *, uint16_t *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getCurrPageSize(LOG_FILE_CTX *, uint32_t *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getCurrInitializedFlag(LOG_FILE_CTX *, uint16_t *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getNextPage(LOG_FILE_CTX *, void *, uint32_t, uint32_t *, uint64_t *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getCurrPageData(LOG_FILE_CTX *, void *, uint32_t, uint32_t *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getCurrPageAddr(LOG_FILE_CTX *, uint64_t *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getCurrPageOffset(LOG_FILE_CTX *, PSP_FILE_OFFSET *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_setCurrPageOffset(LOG_FILE_CTX *, PSP_FILE_OFFSET);
int32_t EXTERNAL_FCN b_log_putNewFile2(LOG_FILE_CTX *, const char *, uint16_t, uint32_t, uint16_t); /* JRP - remove */
int32_t EXTERNAL_FCN b_log_getTxidFromLogFileName(const char *, TXID *, LOG_FILE_TYPE *);
#endif
RDM_EXPORT int32_t EXTERNAL_FCN b_log_findFirstTxidFromDirectory(const char *, uint16_t, TXID *, const char *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getRepLogName(char *, uint32_t, TXID);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_findLastTxidFromDirectory(const char *, uint16_t, TXID *, const char *);
RDM_EXPORT int32_t EXTERNAL_FCN b_log_getDatLogName(char *, uint32_t, TXID);

/* These functions are used to display information about a log file */
RDM_EXPORT void EXTERNAL_FCN b_log_print_hdr(LOG_FILE_CTX *, RDM_PRINT_TYPE);
RDM_EXPORT void EXTERNAL_FCN b_log_print_tx_hdr(TX_ENTRY_HDR *, RDM_PRINT_TYPE);
RDM_EXPORT void EXTERNAL_FCN b_log_print_file_hdr(TX_DB_FILE_HDR *, RDM_PRINT_TYPE);
RDM_EXPORT void EXTERNAL_FCN b_log_print_page_hdr(TX_PAGE_HDR *, RDM_PRINT_TYPE);
/* =========================================================================
   Zero-run compression
*/

RDM_EXPORT int32_t EXTERNAL_FCN b_zcmp_compress(const char *, uint32_t, char *, uint32_t, uint32_t *);
RDM_EXPORT int32_t EXTERNAL_FCN b_zcmp_decompress(const char *, uint32_t, char *, uint32_t, uint32_t *);

/* =========================================================================
   B-tree implementation
*/

typedef int32_t (EXTERNAL_FCN *B_BT_COMPARE)(const void *, const void *, const void *);
typedef const void *B_BT;

RDM_EXPORT B_BT     EXTERNAL_FCN b_btCreateEx(const char *, B_BT_COMPARE, uint32_t, uint32_t, const void *, const char *, uint32_t);
RDM_EXPORT void     EXTERNAL_FCN b_btDestroy(B_BT); /*lint -esym(534,b_btDestroy */
RDM_EXPORT void    *EXTERNAL_FCN b_btFind(B_BT, const void *);
RDM_EXPORT int32_t  EXTERNAL_FCN b_btAdd(B_BT, const void *);
RDM_EXPORT void    *EXTERNAL_FCN b_btDelete(B_BT, const void *);
RDM_EXPORT void    *EXTERNAL_FCN b_btDeleteFirst(B_BT);
RDM_EXPORT void    *EXTERNAL_FCN b_btDeleteLast(B_BT);
RDM_EXPORT void    *EXTERNAL_FCN b_btFirst(B_BT);
RDM_EXPORT void    *EXTERNAL_FCN b_btLast(B_BT);
RDM_EXPORT void    *EXTERNAL_FCN b_btNext(B_BT);
RDM_EXPORT void    *EXTERNAL_FCN b_btPrev(B_BT);
RDM_EXPORT uint32_t EXTERNAL_FCN b_btCount(B_BT);
RDM_EXPORT void    *EXTERNAL_FCN b_btDeleteFirstInRange(B_BT, const void *, const void *);
RDM_EXPORT void    *EXTERNAL_FCN b_btDeleteLastInRange(B_BT, const void *, const void *);
#define b_btCreate(name, cmpfcn, slots, ctx) b_btCreateEx((name), (cmpfcn), (slots), (0), (ctx), __FILE__, __LINE__)
#define b_btCreate_sync(name, cmpfcn, slots, ctx) b_btCreateEx((name), (cmpfcn), (slots), (1), (ctx), __FILE__, __LINE__)

/* =========================================================================
   Cached B-tree implementation
*/

typedef int32_t (EXTERNAL_FCN *B_CBT_COMPARE)(void *, const void *, const void *);
typedef int32_t (EXTERNAL_FCN *B_CBT_LOADER)(void *, const char *, uint32_t, const void **);
typedef void    (EXTERNAL_FCN *B_CBT_ZAPPER)(void *, char *, uint32_t, const void *);

typedef const void *B_CBT;

RDM_EXPORT B_CBT    EXTERNAL_FCN b_cbtCreateEx(const char *, const void *, B_CBT_COMPARE, B_CBT_LOADER, B_CBT_ZAPPER, uint32_t, uint32_t, uint32_t, const char *, int32_t);
RDM_EXPORT void     EXTERNAL_FCN b_cbtDestroy(B_CBT);
RDM_EXPORT void    *EXTERNAL_FCN b_cbtFind(B_CBT, const void *);
RDM_EXPORT int32_t  EXTERNAL_FCN b_cbtAdd(B_CBT, const void *);
RDM_EXPORT void    *EXTERNAL_FCN b_cbtDelete(B_CBT, const void *);
RDM_EXPORT void    *EXTERNAL_FCN b_cbtFirst(B_CBT);
RDM_EXPORT void    *EXTERNAL_FCN b_cbtLast(B_CBT);
RDM_EXPORT void    *EXTERNAL_FCN b_cbtNext(B_CBT);
RDM_EXPORT void    *EXTERNAL_FCN b_cbtPrev(B_CBT);
RDM_EXPORT uint64_t EXTERNAL_FCN b_cbtCount(B_CBT);
RDM_EXPORT void     EXTERNAL_FCN b_cbtClear(B_CBT);
#define b_cbtCreate(name, ctx, cmpfcn, loadfcn, zapfcn, cachednodes, slots, entrysize) b_cbtCreateEx((name), (ctx), (cmpfcn), (loadfcn), (zapfcn), (cachednodes), (slots), (entrysize), __FILE__, __LINE__)

/* =========================================================================
   Hash implementation
*/
typedef struct _B_HASH B_HASH;

typedef int32_t  (EXTERNAL_FCN *B_HASH_COMPARE)(const void *, const void *, const void *);
typedef uint64_t (EXTERNAL_FCN *B_HASH_HASH)(const void *, const void *);

RDM_EXPORT int32_t EXTERNAL_FCN b_hashCreate(const char *, B_HASH_COMPARE, B_HASH_HASH, uint64_t, const void *, B_HASH **);
RDM_EXPORT int32_t EXTERNAL_FCN b_hashDestroy(const B_HASH *); /*lint -esym(534,b_hashDestroy) */
RDM_EXPORT int32_t EXTERNAL_FCN b_hashFind(const B_HASH *, const void *, void **);
RDM_EXPORT int32_t EXTERNAL_FCN b_hashAdd(B_HASH *, const void *);
RDM_EXPORT int32_t EXTERNAL_FCN b_hashDelete(B_HASH *, const void *, void **);
RDM_EXPORT int32_t EXTERNAL_FCN b_hashDeleteAny(B_HASH *, void **);
RDM_EXPORT int32_t EXTERNAL_FCN b_hashCount(const B_HASH *, uint64_t *);

/* =========================================================================
   Server functions
*/
#define B_QUERY_INACTIVE    1
#define B_QUERY_ERROR       2

RDM_EXPORT int32_t EXTERNAL_FCN b_server_start(const char *, const char *, TFS_SERVER_TYPE, const TRANSPORT_PARAMS *);
RDM_EXPORT int32_t EXTERNAL_FCN b_server_stop(const char *, const char *, TFS_SERVER_TYPE, const TRANSPORT_PARAMS *);
RDM_EXPORT int32_t EXTERNAL_FCN b_server_query(const char *, TFS_SERVER_TYPE, const TRANSPORT_PARAMS *);
RDM_EXPORT int32_t EXTERNAL_FCN b_server_install(const char *, const char *, const char *, const char *, const char *, const char *, const char *, const TRANSPORT_PARAMS *); 
RDM_EXPORT int32_t EXTERNAL_FCN b_server_uninstall(const char *, const TRANSPORT_PARAMS *);
RDM_EXPORT int32_t EXTERNAL_FCN b_server_ping(TFS_SERVER_TYPE, const TRANSPORT_PARAMS *);

#if 0
/* =========================================================================
   Environment variable functions
*/

RDM_EXPORT uint16_t EXTERNAL_FCN b_getTFSDefaultPort(void);
RDM_EXPORT uint16_t EXTERNAL_FCN b_getMirDefaultPort(void);
RDM_EXPORT uint16_t EXTERNAL_FCN b_getSQLDefaultPort(void);
#endif

/* =========================================================================
   General purpose cache management functions
   (defined in cache.c and used in sort.c)
*/

typedef void       *BCACHE;
typedef const void *CBCACHE;

typedef int16_t (*BCACHE_LOADER)(int32_t, void **, void *);
typedef int16_t (*BCACHE_ZAPPER)(int32_t, void *, void *);

int16_t  EXTERNAL_FCN b_cacheCreate(uint32_t, BCACHE_LOADER, BCACHE_ZAPPER, PSP_MEMTAG, void *, BCACHE *);
int16_t  EXTERNAL_FCN b_cacheDestroy(int32_t, BCACHE);
int16_t  EXTERNAL_FCN b_cacheGetEntry(int32_t, void **, BCACHE);
int16_t  EXTERNAL_FCN b_cacheReleaseEntry(int32_t, CBCACHE);

/* =========================================================================
   Versioning cache management functions
   (defined in vcache.c and used in source/rdm/dio.c)
*/

typedef const void *BVCACHE;
typedef const void *BVCACHE_PAGE_HANDLE;

typedef enum _BVCACHE_DIRECTION
{
    BVCACHE_FORWARD = 0,
    BVCACHE_BACKWARD
} BVCACHE_DIRECTION;


typedef int32_t (*BVCACHE_COMPARE)(const void *group1, const void *group2, const void *user_ctx);
typedef int32_t (*BVCACHE_FULL)(uint32_t num_modified, const void *user_ctx);
typedef int32_t (*BVCACHE_COMMIT)(const void *group, uint64_t id, const void *data, uint32_t len, const void *user_ctx);

RDM_EXPORT int32_t EXTERNAL_FCN b_vcacheCreate(uint32_t max_entries, BVCACHE_COMPARE compare_fcn, BVCACHE_FULL full_fcn, BVCACHE_COMMIT commit_fcn, const void *user_ctx, BVCACHE *cache);
RDM_EXPORT int32_t EXTERNAL_FCN b_vcacheDestroy(BVCACHE cache);
RDM_EXPORT int32_t EXTERNAL_FCN b_vcacheFind(BVCACHE cache, const void *group, uint64_t id, int16_t for_write, void **data, BVCACHE_PAGE_HANDLE *handle);
RDM_EXPORT int32_t EXTERNAL_FCN b_vcacheWrite(BVCACHE cache, BVCACHE_PAGE_HANDLE handle);
RDM_EXPORT int32_t EXTERNAL_FCN b_vcacheRelease(BVCACHE cache, BVCACHE_PAGE_HANDLE handle);
RDM_EXPORT int32_t EXTERNAL_FCN b_vcacheAdd(BVCACHE cache, const void *group, uint64_t id, void **data, uint32_t len);
RDM_EXPORT int32_t EXTERNAL_FCN b_vcacheDelete(BVCACHE cache, const void *group, uint64_t id);
RDM_EXPORT int32_t EXTERNAL_FCN b_vcacheClearFile(BVCACHE cache, const void *group);
RDM_EXPORT int32_t EXTERNAL_FCN b_vcachePrealloc(BVCACHE cache, uint32_t page_size);
RDM_EXPORT int32_t EXTERNAL_FCN b_vcacheCommit(BVCACHE_DIRECTION dir, BVCACHE cache);
RDM_EXPORT int32_t EXTERNAL_FCN b_vcacheSetMark(BVCACHE cache, const void *mark);
RDM_EXPORT int32_t EXTERNAL_FCN b_vcacheReleaseMark(BVCACHE cache, const void *mark);
RDM_EXPORT int32_t EXTERNAL_FCN b_vcacheRollback(BVCACHE cache, const void *mark);


/* =========================================================================
   General purpose bitmap management functions
   (defined in bitmap.c)
*/
typedef const void *BBITMAP;

RDM_EXPORT int32_t  EXTERNAL_FCN b_bmCreate(uint64_t, PSP_MEMTAG, BBITMAP *);
RDM_EXPORT void     EXTERNAL_FCN b_bmDestroy(BBITMAP);
RDM_EXPORT int32_t  EXTERNAL_FCN b_bmResize(uint64_t, BBITMAP);
RDM_EXPORT int32_t  EXTERNAL_FCN b_bmSetBit(uint64_t, BBITMAP);
RDM_EXPORT int32_t  EXTERNAL_FCN b_bmClearBit(uint64_t, BBITMAP);
RDM_EXPORT int32_t  EXTERNAL_FCN b_bmNegateBit(uint64_t, BBITMAP);
RDM_EXPORT int32_t  EXTERNAL_FCN b_bmTestBit(uint64_t, BBITMAP);
RDM_EXPORT void     EXTERNAL_FCN b_bmClearAll(BBITMAP);
RDM_EXPORT uint64_t EXTERNAL_FCN b_bmSize(BBITMAP);
RDM_EXPORT uint64_t EXTERNAL_FCN b_bmCount(BBITMAP);
RDM_EXPORT int32_t  EXTERNAL_FCN b_bmIsClear(BBITMAP);
/*lint -esym(534,b_bmSetBit,b_bmClearBit,b_bmNegateBit) */

/* =========================================================================
   Prime functions
   (defined in prime.c)
*/
typedef const void *BPRIME;

RDM_EXPORT int32_t         EXTERNAL_FCN b_primeCreate(uint64_t, PSP_MEMTAG, BPRIME *);
RDM_EXPORT void            EXTERNAL_FCN b_primeDestroy(BPRIME);
RDM_EXPORT int32_t         EXTERNAL_FCN b_primeIsNumPrime(uint64_t, BPRIME);
RDM_EXPORT const uint64_t *EXTERNAL_FCN b_primeGetPrimes(uint64_t *, PSP_MEMTAG, BPRIME);

RDM_EXPORT uint64_t EXTERNAL_FCN b_primeNextGreaterOrEqual(uint64_t);

/* =======================================================================
    Docroot functions
*/
RDM_EXPORT int32_t EXTERNAL_FCN b_lockDocroot(const char *, const char *, PSP_FH *, uint32_t);
RDM_EXPORT void    EXTERNAL_FCN b_unlockDocroot(PSP_FH);

/* =========================================================================
    Sort/merge constant and type defintions 
*/

#define S_SORT_NOMEMORY      -1

#define S_SORT_KEYNO_ERR    -10
#define S_SORT_TYPE_ERR     -11
#define S_SORT_OFFSET_ERR   -12
#define S_SORT_PATH_ERR     -13
#define S_SORT_POS_ERR      -14
#define S_SORT_BUFSZ_ERR    -15

#define S_SORT_HANDLE_ERR   -20
#define S_SORT_STATE_ERR    -21

#define S_SORT_IO_ERR       -31
#define S_SORT_EOB          -32

#define S_SORT_ERROR        -41

#define SORT_NOTASYNC       0x0001
#define SORT_NOPENDING      0x0010

#define SORT_BYTES 0xFFFF

#define SORT_MINBUFFERS         4 

#define SORT_CHAR_COMPARE_ATTR     "char compare"
#define SORT_WCHAR_COMPARE_ATTR    "wchar compare"

typedef const void *B_SORTCB;

#define SORT_FIELD_CHAR      0x0000  /* field is a character field */
#define SORT_FIELD_WCHAR     0x0001  /* field is a wide character field */
#define SORT_FIELD_INT16     0x0002  /* field is a 16-bit integer field */
#define SORT_FIELD_INT32     0x0003  /* field is a 32-bit integer field */
#define SORT_FIELD_INT64     0x0004  /* field is a 64-bit integer field */
#define SORT_FIELD_FLOAT     0x0005  /* field is a float field */
#define SORT_FIELD_DOUBLE    0x0006  /* field is a double field */
#define SORT_FIELD_DBADDR    0x0007  /* field is a database address field */
#define SORT_FIELD_BLOB      0x0008  /* field is a blob field */
#define SORT_FIELD_GROUPED   0x0009  /* field is a structure */
#define SORT_FIELD_INT8      0x000A  /* field is a 8-bit integer field */
#define SORT_FIELD_DATE      0x000B  /* field is a date */
#define SORT_FIELD_TIME      0x000C  /* field is a time */
#define SORT_FIELD_TIMESTAMP 0x000D  /* field is a timestamp */
#define SORT_FIELD_BCD       0x000E  /* field is a decimal */
#define SORT_FIELD_GUID      0x000F  /* field is a guid (uuid) */
#define SORT_FIELD_TYPE_MASK 0x000F  /* mask for field types */
#define SORT_FIELD_UNSIGNED  0x0010  /* field is unsigned */

/* Comparison Function Prototypes  */
typedef int16_t (EXTERNAL_FCN CMPFUNCTION)(const void *, uint32_t, const void *, uint32_t);
typedef int16_t (EXTERNAL_FCN GCMPFUNCTION)(const void *, const void *, const void *);
typedef int16_t (EXTERNAL_FCN STRCMPFUNCTION)(const void *, const void *, uint32_t);

typedef struct _SORTDESCR {
    CMPFUNCTION   *pCmpFcn; /* pointer to the compare function (NULL, if none) */
    void          *ctxt;    /* context for compare function (NULL, if NONE) */
    uint32_t       keyno;   /* the sort key field number */
    uint32_t       len;     /* length of the field (bytes) */
    uint32_t       offset;  /* offset to the start of data in the sort record */
    char           desc;    /* 0 for ascending, 1 for descending */
    uint16_t       type;    /* data type */
} SORTDESCR;

typedef struct _B_SORTATTR {           
    const char     *attrName;   /* name of the attribute */
    STRCMPFUNCTION *attrValue;  /* value of the attribute */
    uint32_t       *puFileNo;   /* temporary file number */
} B_SORTATTR;

/* sort/merge API function prototypes -------------------------------- */
RDM_EXPORT int16_t  EXTERNAL_FCN b_sortOpen(const B_SORTATTR *, uint32_t, PSP_MEMTAG, B_SORTCB *);
RDM_EXPORT int16_t  EXTERNAL_FCN b_sortStart(int, const SORTDESCR *, B_SORTCB);
RDM_EXPORT int16_t  EXTERNAL_FCN b_sortStore(const void *, B_SORTCB);
RDM_EXPORT int16_t  EXTERNAL_FCN b_sortComplete(B_SORTCB);
RDM_EXPORT uint32_t EXTERNAL_FCN b_sortCount(B_SORTCB);
RDM_EXPORT int16_t  EXTERNAL_FCN b_sortSeek(uint32_t, B_SORTCB);
RDM_EXPORT int      EXTERNAL_FCN b_sortRead(int, void*, B_SORTCB);
RDM_EXPORT int16_t  EXTERNAL_FCN b_sortClose(B_SORTCB);

/**************************************************************************
  Data type declarations
*/

/* Field formats (varchar fields and partial keys) for field values passed
   to comparison functions:

    DB_DATASLOT Format used in data file slots, i.e. short value containing
                string length followed by array of vardata pointers, in the
                case of varchar fields.
    DB_KEYSLOT  Format used in key files, i.e. key string value truncated
                to length of partial key, followed by database address of
                record slot.
    DB_EXTVAL   External format used by the application, i.e. fully expanded
                string field.
*/

typedef enum
{
    DB_DATASLOT,  /* Format used in data file slots */
    DB_KEYSLOT,   /* Format used in key file nodes */
    DB_EXTVAL     /* Format used in application space */
} RDM_DATA_FORMAT;

typedef struct {
    const char     *val;  /* pointer to the value */
    uint16_t        len;  /* length of the value */
    RDM_DATA_FORMAT fmt;  /* data format */
} FIELD_DATA;

typedef uint32_t BLOBSIZE_T;

struct FIELD_ENTRY_S;

RDM_EXPORT const char *EXTERNAL_FCN b_printable_string(const char *, uint32_t);
RDM_EXPORT const char *EXTERNAL_FCN b_printable_wstring(const wchar_t *, uint32_t);

typedef int32_t (*B_TYPE_GET_VAR_FIELD)(const struct FIELD_ENTRY_S *, const void *, void *, const void *);

typedef void    (EXTERNAL_FCN *B_TYPE_COPY_USER_FIELD_FCN)(const struct FIELD_ENTRY_S *, void *, const void *);
typedef int32_t (EXTERNAL_FCN *B_TYPE_PUT_DATA_FIELD_FCN)(const struct FIELD_ENTRY_S *, void *, const void *);
typedef int32_t (EXTERNAL_FCN *B_TYPE_GET_DATA_FIELD_FCN)(const struct FIELD_ENTRY_S *, void *, const void *, B_TYPE_GET_VAR_FIELD, const void *, const void *);
typedef int32_t (EXTERNAL_FCN *B_TYPE_GET_DATA_FIELD_PTR_FCN)(const struct FIELD_ENTRY_S *, void *, const void **, const void *, B_TYPE_GET_VAR_FIELD, const void *, const void *);
typedef int32_t (EXTERNAL_FCN *B_TYPE_PUT_KEY_FIELD_FCN)(const struct FIELD_ENTRY_S *, void *, const void *, uint32_t *);
typedef int32_t (EXTERNAL_FCN *B_TYPE_GET_KEY_FIELD_FCN)(const struct FIELD_ENTRY_S *, void *, const void *, uint32_t *);
typedef int32_t (EXTERNAL_FCN *B_TYPE_CMP_FIELD_FCN)(const struct FIELD_ENTRY_S *, const FIELD_DATA *, const FIELD_DATA *);
typedef int32_t (EXTERNAL_FCN *B_TYPE_UTIL_TO_TEXT_FIELD_FCN)(const struct FIELD_ENTRY_S *, const char **, const void *, int32_t);
typedef int32_t (EXTERNAL_FCN *B_TYPE_UTIL_FROM_TEXT_FIELD_FCN)(const struct FIELD_ENTRY_S *, void **, const char **);
typedef int32_t (EXTERNAL_FCN *B_TYPE_TO_TEXT_FIELD_FCN)(const struct FIELD_ENTRY_S *, const void *, BLOBSIZE_T, const char ***, uint32_t *);
typedef int32_t (EXTERNAL_FCN *B_TYPE_HASH_NORM_FIELD_FCN)(const struct FIELD_ENTRY_S *, void **, const void *);

typedef struct {
    ALIGN_TYPE                      int_align;
    ALIGN_TYPE                      ext_align;
    char                            legacy_type;
    uint16_t                        legacy_unsigned_flag;
    const char                     *enum_name;
    const char                     *field_type_text;
    const char                     *ddl_type_text;
    const char                     *objc_field_type_text;
    const char                     *objc_field_array_type_text;
    B_TYPE_COPY_USER_FIELD_FCN      copy_user_field;      /* copy data from user buffer (may not be full field size) */
    B_TYPE_PUT_DATA_FIELD_FCN       put_data_field;       /* put record into a data slot */
    B_TYPE_GET_DATA_FIELD_FCN       get_data_field;       /* get record from a data slot */
    B_TYPE_GET_DATA_FIELD_PTR_FCN   get_data_field_ptr;   /* get a pointer to field contents */
    B_TYPE_PUT_KEY_FIELD_FCN        put_key_field;        /* put key into a key slot */
    B_TYPE_GET_KEY_FIELD_FCN        get_key_field;        /* get key from a key slot */
    B_TYPE_CMP_FIELD_FCN            cmp_field;            /* compare field contents */
    B_TYPE_UTIL_TO_TEXT_FIELD_FCN   util_to_text_field;   /* convert the field contents to text (for utilities) */
    B_TYPE_UTIL_FROM_TEXT_FIELD_FCN util_from_text_field; /* interpret text into a field (for utilities) */
    B_TYPE_TO_TEXT_FIELD_FCN        to_text_field;        /* convert the field data to an array of strings (one for each element) (dbexp) */
    B_TYPE_HASH_NORM_FIELD_FCN      hash_norm_field;      /* normalize the field for the hash function */
} RDM_TYPE_INFO;

typedef uint32_t F_ADDR4;      /* file address: page or slot number */
typedef uint64_t F_ADDR8;      /* file address: page or slot number */
typedef uint32_t DB_ADDR4;   /* 3 bytes for slot, 1 byte for file */
typedef uint64_t DB_ADDR8;   /* 6 bytes for slot, 2 byte for file */

typedef uint16_t FILE_NO;    /* RDM file number */

/* Internal database address structure */
typedef struct 
{
    uint16_t   dba_uno;       /* dba union number */
    FILE_NO    dba_file;      /* dba file number */
    F_ADDR8    dba_offset;    /* dba offset */
} DB_ADDR;

RDM_EXPORT void                 EXTERNAL_FCN b_typeDbaToDba4(DB_ADDR4 *, const DB_ADDR *);
RDM_EXPORT void                 EXTERNAL_FCN b_typeDbaToDba8(DB_ADDR8 *, const DB_ADDR *);
RDM_EXPORT void                 EXTERNAL_FCN b_typeDba4ToDba(DB_ADDR *, const DB_ADDR4 *);
RDM_EXPORT void                 EXTERNAL_FCN b_typeDba8ToDba(DB_ADDR *, const DB_ADDR8 *);
RDM_EXPORT const RDM_TYPE_INFO *EXTERNAL_FCN b_typeGetInfo(RDM_TYPE);

/**************************************************************************
  Date/Time/Timestamp declarations
*/

/* Date, time, and timestamp definitions */
typedef uint32_t DATE_VAL;
typedef uint32_t TIME_VAL;

typedef struct {
    DATE_VAL date;
    TIME_VAL time;
} TIMESTAMP_VAL;

#define RDM_DATE_MAX RDM_UINT32_MAX
#define RDM_TIME_MAX ((((((23 * 60) + 59) * 60) + 59) * 10000) + 9999)

#define MAX_TIME_PREC 10000
#define MAX_PRECISION MAX_TIME_PREC

typedef struct tagCAL_DATE {
    int32_t  year;      /* 1 - ???? */
    uint16_t month;     /* 1 - 12 */
    uint16_t day;       /* 1 - 31 */
} CAL_DATE;

typedef struct tagCAL_TIME {
    uint16_t hour;      /* 0 - 23 */
    uint16_t minute;    /* 0 - 59 */
    uint16_t second;    /* 0 - 59 */
    uint16_t fraction;  /* 0 - 9999 */
} CAL_TIME;

typedef struct tagCAL_TIMESTAMP {
    int32_t  year;      /* 1 - ???? */
    uint16_t month;     /* 1 - 12 */
    uint16_t day;       /* 1 - 31 */
    uint16_t hour;      /* 0 - 23 */
    uint16_t minute;    /* 0 - 59 */
    uint16_t second;    /* 0 - 59 */
    uint16_t fraction;  /* 0 - 9999 */
} CAL_TIMESTAMP;

/* date functions */
RDM_EXPORT const char *EXTERNAL_FCN dt_dateDayAbr(DATE_VAL);
RDM_EXPORT const char *EXTERNAL_FCN dt_dateDayName(DATE_VAL);
RDM_EXPORT uint16_t    EXTERNAL_FCN dt_dateDayOfYear(DATE_VAL);
RDM_EXPORT uint16_t    EXTERNAL_FCN dt_dateDayOfMonth(DATE_VAL);
RDM_EXPORT uint16_t    EXTERNAL_FCN dt_dateDayOfWeek(DATE_VAL);
RDM_EXPORT int16_t     EXTERNAL_FCN dt_dateFromCalDate(const CAL_DATE *, DATE_VAL *);
RDM_EXPORT DATE_VAL    EXTERNAL_FCN dt_dateFromString(const char *);
RDM_EXPORT uint16_t    EXTERNAL_FCN dt_dateMonth(DATE_VAL);
RDM_EXPORT const char *EXTERNAL_FCN dt_dateMonthAbr(DATE_VAL);
RDM_EXPORT const char *EXTERNAL_FCN dt_dateMonthName(DATE_VAL);
RDM_EXPORT uint16_t    EXTERNAL_FCN dt_dateQuarter(DATE_VAL);
RDM_EXPORT int16_t     EXTERNAL_FCN dt_dateToCalDate(DATE_VAL, CAL_DATE *);
RDM_EXPORT void        EXTERNAL_FCN dt_dateToday(DATE_VAL *);
RDM_EXPORT const char *EXTERNAL_FCN dt_dateToString(DATE_VAL, char *, size_t);
RDM_EXPORT uint16_t    EXTERNAL_FCN dt_dateValidateMonth(const char *);
RDM_EXPORT uint16_t    EXTERNAL_FCN dt_dateWeek(DATE_VAL);
RDM_EXPORT int32_t     EXTERNAL_FCN dt_dateYear(DATE_VAL);

/* time functions */
RDM_EXPORT uint16_t    EXTERNAL_FCN dt_timeFraction(TIME_VAL);
RDM_EXPORT int16_t     EXTERNAL_FCN dt_timeFromCalTime(const CAL_TIME *, TIME_VAL *);
RDM_EXPORT TIME_VAL    EXTERNAL_FCN dt_timeFromString(const char *);
RDM_EXPORT uint16_t    EXTERNAL_FCN dt_timeHour(TIME_VAL);
RDM_EXPORT uint16_t    EXTERNAL_FCN dt_timeMinute(TIME_VAL);
RDM_EXPORT void        EXTERNAL_FCN dt_timeNow(TIME_VAL *);
RDM_EXPORT uint16_t    EXTERNAL_FCN dt_timeSecond(TIME_VAL);
RDM_EXPORT int16_t     EXTERNAL_FCN dt_timeToCalTime(TIME_VAL, CAL_TIME *);
RDM_EXPORT const char *EXTERNAL_FCN dt_timeToString(TIME_VAL, char *, size_t);

/* timestamp functions and macros */
RDM_EXPORT TIMESTAMP_VAL EXTERNAL_FCN dt_timestampFromString(const char *);
RDM_EXPORT void          EXTERNAL_FCN dt_timestampNow(TIMESTAMP_VAL *);
RDM_EXPORT void          EXTERNAL_FCN dt_timestampDaysDiff(TIMESTAMP_VAL, TIMESTAMP_VAL, uint32_t *);
RDM_EXPORT const char   *EXTERNAL_FCN dt_timestampToString(TIMESTAMP_VAL, char *, size_t);

RDM_EXPORT const char *EXTERNAL_FCN dt_todaysDate(char *, size_t);
RDM_EXPORT const char *EXTERNAL_FCN dt_todaysTime(char *, size_t);
RDM_EXPORT const char *EXTERNAL_FCN dt_todaysTimestamp(char *, size_t);

#define dt_timestampDayAbr(ts)     dt_dateDayAbr(ts.date)
#define dt_timestampDayName(ts)    dt_dateDayName(ts.date)
#define dt_timestampDayOfMonth(ts) dt_dateDayOfMonth(ts.date)
#define dt_timestampDayOfWeek(ts)  dt_dateDayOfWeek(ts.date)
#define dt_timestampDayOfYear(ts)  dt_dateDayOfYear(ts.date)
#define dt_timestampFraction(ts)   dt_timeFraction(ts.time)
#define dt_timestampHour(ts)       dt_timeHour(ts.time)
#define dt_timestampMinute(ts)     dt_timeMinute(ts.time)
#define dt_timestampMonthAbr(ts)   dt_dateMonthAbr(ts.date)
#define dt_timestampMonthName(ts)  dt_dateMonthName(ts.date)
#define dt_timestampQuarter(ts)    dt_dateQuarter(ts.date)
#define dt_timestampSecond(ts)     dt_timeSecond(ts.time)
#define dt_timestampWeek(ts)       dt_dateWeek(ts.date)
#define dt_timestampMonth(ts)      dt_dateMonth(ts.date)
#define dt_timestampYear(ts)       dt_dateYear(ts.date)
/*lint -esym(534,dt_dateToCalDate,dt_timeToCalTime,dt_dateToString,dt_timeToString,dt_timestampToString) */

/**************************************************************************
   LZ compress/decompress functions
*/
typedef enum { LZBEGIN, LZBYTE, LZEND } LZOPERATION;
typedef int32_t (EXTERNAL_FCN LZOUTPUTFUNCTION)(const void *, LZOPERATION, uint8_t);

typedef const void *LZCTX;

RDM_EXPORT int32_t EXTERNAL_FCN b_lzCompress(const void *, uint32_t, void **, uint32_t *, PSP_MEMTAG);
RDM_EXPORT int32_t EXTERNAL_FCN b_lzDecompress(const void *, uint32_t, void **, uint32_t *, PSP_MEMTAG);

RDM_EXPORT int32_t EXTERNAL_FCN b_lzStart(const void *, LZOUTPUTFUNCTION *, LZCTX *);
RDM_EXPORT int32_t EXTERNAL_FCN b_lzCompressChunk(LZCTX, const void *, uint32_t);
RDM_EXPORT int32_t EXTERNAL_FCN b_lzDecompressChunk(LZCTX, const void *, uint32_t);
RDM_EXPORT int32_t EXTERNAL_FCN b_lzFinish(LZCTX);

/* =========================================================================
   Embed functions
*/
#define EMBED_BUFFER_SIZE 4096
#define EMBED_INITIAL_HASH   1
typedef enum { EMBED_CREATE, EMBED_DELETE, EMBED_VERIFY } B_EMBED_COMMAND;

RDM_EXPORT int32_t EXTERNAL_FCN b_embed_file(const char *, const uint8_t *const [], size_t, uint32_t, B_EMBED_COMMAND, const char *, uint16_t);

/* =========================================================================
   BCD (decimal) functions
*/

typedef enum {
    RDM_BCD_ROUND_NEAREST_TIES_TO_EVEN,
    RDM_BCD_ROUND_NEAREST_TIES_AWAY_FROM_ZERO,
    RDM_BCD_ROUND_UP,
    RDM_BCD_ROUND_DOWN,
    RDM_BCD_ROUND_TOWARDS_ZERO
} RDM_BCD_ROUNDING_MODE;

#define RDM_BCD_MAXPRECISION 32
#define RDM_BCD_MAXSCALE     32

typedef struct {
    uint8_t prec;
    int8_t  exp;
    uint8_t flags;
    int8_t  sign;
    uint8_t data[RDM_BCD_MAXPRECISION + 1];
} RDM_BCD;

typedef RDM_BCD BCD_VAL;
typedef uint8_t RDM_PACKED_BCD;

#define RDM_BCDLEN(prec)       ((uint16_t) (offsetof(RDM_BCD, data) + (prec) + 1))
#define RDM_BCDPACKEDLEN(prec) ((uint16_t) (((prec) / 2) + 1))

#define BCD_OKAY         0
#define BCD_PRECTOOBIG (-1)
#define BCD_INVALID    (-2)

#define BCD_FLAGS_PRECLOSS 0x01
#define BCD_FLAGS_OVERFLOW 0x02
#define BCD_FLAGS_ZERODIV  0x04
#define BCD_FLAGS_TOOSMALL 0x08
#define BCD_FLAGS_NOMEMORY 0x10
#define BCD_FLAGS_NAN      0x20
#define BCD_FLAGS_POSITIVE 0x80

/* Basic arithmetic functions */
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_add(const RDM_BCD *, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_addInt32(const RDM_BCD *, int32_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_addInt64(const RDM_BCD *, int64_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_addUInt32(const RDM_BCD *, uint32_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_addUInt64(const RDM_BCD *, uint64_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_addDouble(const RDM_BCD *, double, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_sub(const RDM_BCD *, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_subInt32(const RDM_BCD *, int32_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_subInt64(const RDM_BCD *, int64_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_subUInt32(const RDM_BCD *, uint32_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_subUInt64(const RDM_BCD *, uint64_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_subDouble(const RDM_BCD *, double, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_subFromInt32(int32_t, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_subFromInt64(int64_t, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_subFromUInt32(uint32_t, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_subFromUInt64(uint64_t, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_subFromDouble(double, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_mult(const RDM_BCD *, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_multInt32(const RDM_BCD *, int32_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_multInt64(const RDM_BCD *, int64_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_multUInt32(const RDM_BCD *, uint32_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_multUInt64(const RDM_BCD *, uint64_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_multDouble(const RDM_BCD *, double, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_div(const RDM_BCD *, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_divByInt32(const RDM_BCD *, int32_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_divByInt64(const RDM_BCD *, int64_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_divByUInt32(const RDM_BCD *, uint32_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_divByUInt64(const RDM_BCD *, uint64_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_divByDouble(const RDM_BCD *, double, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_divInt32(int32_t, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_divInt64(int64_t, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_divUInt32(uint32_t, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_divUInt64(uint64_t, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_divDouble(double, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_reciprocal(const RDM_BCD *, RDM_BCD *);

/* Advanced math functions */
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_exp(const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_log(const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_log10(const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_powInt32(const RDM_BCD *, int32_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_powInt64(const RDM_BCD *, int64_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_powUInt32(const RDM_BCD *, uint32_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_powUInt64(const RDM_BCD *, uint64_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_pow(const RDM_BCD *, const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_sqrt(const RDM_BCD *, RDM_BCD *);

/* Trigonometric functions */
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_csc(const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_cos(const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_cot(const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_pi(RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_sec(const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_sin(const RDM_BCD *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_tan(const RDM_BCD *, RDM_BCD *);

RDM_EXPORT void     EXTERNAL_FCN bcd_chgSign(RDM_BCD *);
RDM_EXPORT void     EXTERNAL_FCN bcd_ceiling(RDM_BCD *);
RDM_EXPORT void     EXTERNAL_FCN bcd_floor(RDM_BCD *);
RDM_EXPORT void     EXTERNAL_FCN bcd_round(RDM_BCD *);
RDM_EXPORT int16_t  EXTERNAL_FCN bcd_sign(const RDM_BCD *);

RDM_EXPORT int16_t  EXTERNAL_FCN bcd_isZero(const RDM_BCD *);
RDM_EXPORT int32_t  EXTERNAL_FCN bcd_compare(const RDM_BCD *, const RDM_BCD *);

RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_maxprec(void);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_maxscale(void);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_setRoundingMode(RDM_BCD_ROUNDING_MODE);

RDM_EXPORT int16_t  EXTERNAL_FCN bcd_pack(const RDM_BCD *, void *, uint8_t, uint8_t);
RDM_EXPORT int16_t  EXTERNAL_FCN bcd_unpack(const void *, RDM_BCD *, uint8_t, uint8_t);
RDM_EXPORT void     EXTERNAL_FCN bcd_copy(RDM_BCD *, const RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_adjust(RDM_BCD *, uint8_t, uint8_t);
RDM_EXPORT int16_t  EXTERNAL_FCN bcd_validate(const RDM_BCD *);
RDM_EXPORT int16_t  EXTERNAL_FCN bcd_packed_validate(const RDM_PACKED_BCD *, uint8_t);

RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_fromChar(const char *, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_fromFloat(float, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_fromDouble(double, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_fromInt8(int8_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_fromInt16(int16_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_fromInt32(int32_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_fromInt64(int64_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_fromUInt8(uint8_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_fromUInt16(uint16_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_fromUInt32(uint32_t, RDM_BCD *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_fromUInt64(uint64_t, RDM_BCD *);
#if !defined(RDM_NO_UNICODE)
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_fromWChar(const wchar_t *, RDM_BCD *);
#endif

RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_toChar(const RDM_BCD *, char *, uint32_t, uint16_t);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_toCharWithScale(const RDM_BCD *, uint8_t, char *, uint32_t, uint16_t);
#if !defined(RDM_NO_UNICODE)
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_toWChar(const RDM_BCD *, wchar_t *, uint32_t, uint16_t);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_toWCharWithScale(const RDM_BCD *, uint8_t, wchar_t *, uint32_t, uint16_t);
#endif
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_toDouble(const RDM_BCD *, double *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_toFloat(const RDM_BCD *, float *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_toInt8(const RDM_BCD *, int8_t *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_toInt16(const RDM_BCD *, int16_t *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_toInt32(const RDM_BCD *, int32_t *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_toInt64(const RDM_BCD *, int64_t *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_toUInt8(const RDM_BCD *, uint8_t *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_toUInt16(const RDM_BCD *, uint16_t *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_toUInt32(const RDM_BCD *, uint32_t *);
RDM_EXPORT uint8_t  EXTERNAL_FCN bcd_toUInt64(const RDM_BCD *, uint64_t *);

/* =========================================================================
   Miscellaneous functions
*/
/*lint -printf(3, DisplayMessage, DisplayMessageNow, DisplayError, DisplayErrorNow) */
RDM_EXPORT void        EXTERNAL_FCN DisplayMessage(uint16_t, uint16_t, const char *, ...);
RDM_EXPORT void        EXTERNAL_FCN DisplayMessageNow(uint16_t, uint16_t, const char *, ...);
RDM_EXPORT void        EXTERNAL_FCN DisplayError(uint16_t, uint16_t, const char *, ...);
RDM_EXPORT void        EXTERNAL_FCN DisplayErrorNow(uint16_t, uint16_t, const char *, ...);
RDM_EXPORT int32_t     EXTERNAL_FCN b_OpenStdFiles(int16_t, const char *, PSP_FILE_STREAM *, const char *, PSP_FILE_STREAM *, const char *, PSP_FILE_STREAM *);

/* C++ API class generation functions */
void EXTERNAL_FCN b_write_cpp_header_header(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cpp_header_footer(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cursor_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_db_header_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_db_open_declaration(PSP_FILE_STREAM, int16_t, const char*);
void EXTERNAL_FCN b_write_db_constructor_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_db_operator_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_db_destructor_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_db_add_record_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_db_get_record_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_db_get_record_by_key_declaration(PSP_FILE_STREAM, const char*, const char*);
void EXTERNAL_FCN b_write_db_private_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_db_footer_declaration(PSP_FILE_STREAM);
void EXTERNAL_FCN b_write_cursor_compound_key_find_declaration(PSP_FILE_STREAM, const char *, const char *, const char *, const char *, uint16_t);
void EXTERNAL_FCN b_write_cursor_compound_key_find_definition(PSP_FILE_STREAM, const char *, const char *, const char *, const char *, uint16_t);
void EXTERNAL_FCN b_write_cursor_header_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cursor_constructor_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cursor_operator_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cursor_set_owner_declaration(PSP_FILE_STREAM, const char*, const char*, const char*);
void EXTERNAL_FCN b_write_cursor_set_member_declaration(PSP_FILE_STREAM, const char*, const char*, const char*, const char*);
void EXTERNAL_FCN b_write_cursor_system_set_member_declaration(PSP_FILE_STREAM, const char*, const char*, const char*);
void EXTERNAL_FCN b_write_cursor_key_declaration(PSP_FILE_STREAM, const char*, const char*);
void EXTERNAL_FCN b_write_cursor_key_find_declaration(PSP_FILE_STREAM, const char*, const char*, const char *, const char *);
void EXTERNAL_FCN b_write_cursor_record_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cursor_blob_field_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cursor_field_declaration(PSP_FILE_STREAM, const char*, const char*, const char*);
void EXTERNAL_FCN b_write_cursor_struct_field_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cursor_destructor_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cursor_private_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cursor_friend_declaration(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cursor_footer_declaration(PSP_FILE_STREAM);
void EXTERNAL_FCN b_write_cpp_source_header(PSP_FILE_STREAM, int16_t, const char*);
void EXTERNAL_FCN b_write_db_open_definition(PSP_FILE_STREAM, int16_t, const char*);
void EXTERNAL_FCN b_write_db_misc_definition(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_db_constructor_definition(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_db_operator_definition(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_db_destructor_definition(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_db_add_record_definition(PSP_FILE_STREAM, const char*, const char*);
void EXTERNAL_FCN b_write_db_get_record_definition(PSP_FILE_STREAM, const char*, const char*);
void EXTERNAL_FCN b_write_db_get_record_by_key_definition(PSP_FILE_STREAM, const char*, const char*, const char*, uint16_t);
void EXTERNAL_FCN b_write_cursor_misc_definition(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cursor_constructor_definition(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cursor_operator_definition(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cursor_set_owner_definition(PSP_FILE_STREAM, const char *, const char*, const char*);
void EXTERNAL_FCN b_write_cursor_set_member_definition(PSP_FILE_STREAM, const char*, const char*, const char*);
void EXTERNAL_FCN b_write_cursor_system_set_member_definition(PSP_FILE_STREAM, const char*, const char*);
void EXTERNAL_FCN b_write_cursor_key_definition(PSP_FILE_STREAM, const char*, const char*, uint16_t);
void EXTERNAL_FCN b_write_cursor_key_find_definition(PSP_FILE_STREAM, const char*, const char*, const char*, const char*, uint16_t);
void EXTERNAL_FCN b_write_cursor_record_definition(PSP_FILE_STREAM, const char*);
void EXTERNAL_FCN b_write_cursor_blob_field_definition(PSP_FILE_STREAM, const char*, const char*, uint16_t);
void EXTERNAL_FCN b_write_cursor_field_definition(PSP_FILE_STREAM, const char*, const char*, const char*, const char*, uint16_t);
void EXTERNAL_FCN b_write_cursor_struct_field_definition(PSP_FILE_STREAM, const char*, const char*, uint16_t);
void EXTERNAL_FCN b_write_cursor_destructor_definition(PSP_FILE_STREAM, const char*);

/***************************************************************************
   Replication schema information (SI) definitions
*/
#define B_SCHEMA_NAMELEN   32
#define B_SCHEMA_TYPELEN   16
#define B_SCHEMA_MAXDIMS   3
#define B_SCHEMA_MAXKEYLEN 1024
#define B_SCHEMA_ALLCHAR   "*"

typedef uint64_t B_SCHEMA_VER;

typedef enum {
    REP_IMG_DEFAULT = 0,
    REP_IMG_NONE,
    REP_IMG_PRE,
    REP_IMG_POST,
    REP_IMG_BOTH
} B_REP_IMG_TYPE;

#define IMG_DEFAULT(c)  ((c)->hdr.img_type == (uint16_t) REP_IMG_DEFAULT)
#define IMG_NONE(c)     ((c)->hdr.img_type == (uint16_t) REP_IMG_NONE)
#define IMG_PRE(c)      ((c)->hdr.img_type == (uint16_t) REP_IMG_PRE)
#define IMG_POST(c)     ((c)->hdr.img_type == (uint16_t) REP_IMG_POST)
#define IMG_BOTH(c)     ((c)->hdr.img_type == (uint16_t) REP_IMG_BOTH)

#define SET_IMG_NONE(c) ((c)->hdr.img_type = (uint16_t) REP_IMG_NONE)
#define SET_IMG_PRE(c)  ((c)->hdr.img_type = (uint16_t) REP_IMG_PRE)
#define SET_IMG_POST(c) ((c)->hdr.img_type = (uint16_t) REP_IMG_POST)
#define SET_IMG_BOTH(c) ((c)->hdr.img_type = (uint16_t) REP_IMG_BOTH)

typedef struct {
    /* HEADER -- 24 bytes (aligned for writing) */
    uint32_t         index;                         /*  2 bytes */
    uint16_t         tab_index; /* accessibility */ /*  2 bytes */
    uint16_t         img_type;                      /*  2 bytes */
    uint16_t         rdm_type;                      /*  2 bytes */
    uint16_t         type_entries;                  /*  2 bytes */
    uint16_t         type_strdim;                   /*  2 bytes */
    uint16_t         type_flags;                    /*  2 bytes */
    uint16_t         type_num_flds;                 /*  2 bytes */
    uint16_t         type_len_ex;                   /*  2 bytes */
    uint16_t         type_dim[B_SCHEMA_MAXDIMS];    /*  6 bytes */
    uint8_t          type_prec;                     /*  1 byte */
    uint8_t          type_scale;                    /*  1 byte */
} B_REP_COLUMN_HEADER;

typedef struct {
    const char         *name;
    B_REP_COLUMN_HEADER hdr;
} B_REP_COLUMN;

typedef struct {
    /* HEADER -- 16 bytes (aligned for writing) */
    uint16_t         index;
    uint16_t         colcount;
    uint16_t         null_offset;
    uint16_t         circular;
} B_REP_TABLE_HEADER;

typedef struct {
    const char        *name;
    B_REP_TABLE_HEADER hdr;

    /* FIELD pointers */
    B_REP_COLUMN     **ppRepCols;
} B_REP_TABLE;

typedef struct {
    /* HEADER -- 4 bytes (aligned for writing) */
    uint16_t    index;
    uint16_t    owner_tab_index;
} B_REP_SET_HEADER;

typedef struct {
    const char      *name;
    B_REP_SET_HEADER hdr;
} B_REP_SET;

typedef struct {
    /* HEADER -- 16 bytes (aligned for writing) */
    B_SCHEMA_VER     version;
    uint16_t         tabcount;
    uint16_t         setcount;
    uint16_t         timestamp_flag;
    uint16_t         def_img_type;
} B_REP_DB_HEADER;

typedef struct {
    const char      *name;
    uint32_t         size;
    B_REP_DB_HEADER  hdr;

    /* RECORD pointers */
    B_REP_TABLE    **ppRepTabs;
    B_REP_SET      **ppRepSets;
} B_REP_DB;

/* ========================================================================
   Selective Replication functions
*/
typedef int32_t (B_REP_READFCN)(void *, void *, size_t);
typedef int32_t (B_REP_WRITEFCN)(void *, const void *, size_t);

RDM_EXPORT int32_t        EXTERNAL_FCN b_rep_addColumn(B_REP_TABLE *, const char *, B_REP_COLUMN **, PSP_MEMTAG);
RDM_EXPORT int32_t        EXTERNAL_FCN b_rep_addSet(B_REP_DB *, const char *, B_REP_SET **, PSP_MEMTAG);
RDM_EXPORT int32_t        EXTERNAL_FCN b_rep_addTable(B_REP_DB *, const char *, B_REP_TABLE **, PSP_MEMTAG);
RDM_EXPORT void           EXTERNAL_FCN b_rep_freeDatabase(const B_REP_DB *, PSP_MEMTAG);
RDM_EXPORT B_REP_IMG_TYPE EXTERNAL_FCN b_rep_imgTypeFromString(const char *);
RDM_EXPORT int32_t        EXTERNAL_FCN b_rep_createDatabase(const char *, B_REP_DB **, PSP_MEMTAG);
RDM_EXPORT int32_t        EXTERNAL_FCN b_rep_readSchema(B_REP_READFCN *, void *, B_REP_DB **, RDM_BOOLEAN, PSP_MEMTAG);
RDM_EXPORT int32_t        EXTERNAL_FCN b_rep_writeSchema(B_REP_WRITEFCN *, void *, const B_REP_DB *);
RDM_EXPORT int32_t        EXTERNAL_FCN b_rep_hasTimestamp(const B_REP_DB *, RDM_BOOLEAN *);

RDM_EXPORT const B_REP_TABLE  *EXTERNAL_FCN b_rep_findTable(const B_REP_DB *, uint32_t);
RDM_EXPORT const B_REP_TABLE  *EXTERNAL_FCN b_rep_findTableByName(const B_REP_DB *, const char *);
RDM_EXPORT const B_REP_SET    *EXTERNAL_FCN b_rep_findSet(const B_REP_DB *, uint32_t);
RDM_EXPORT const B_REP_COLUMN *EXTERNAL_FCN b_rep_findColumn(const B_REP_TABLE *, uint32_t);
RDM_EXPORT const B_REP_COLUMN *EXTERNAL_FCN b_rep_findColumnByName(const B_REP_TABLE *, const char *);
RDM_EXPORT int32_t             EXTERNAL_FCN b_log_check_version(const char *, RDM_BOOLEAN *);

RDM_EXPORT int16_t EXTERNAL_FCN b_bit_read(const char *, uint16_t);
RDM_EXPORT void    EXTERNAL_FCN b_bit_write(char *, uint16_t, int16_t);
RDM_EXPORT int32_t EXTERNAL_FCN b_dir_createAll(const char *, uint32_t);

#if defined(__cplusplus)
}
#endif

#endif  /* BASE_H */

