/* ----------------------------------------------------------------------------
 * Raima Database Manager
 *
 * Copyright (c) 2001-2011 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 Birdstep LICENSE which
 * is fully described in the LICENSE.TXT file, included within this
 * distribution of files.
 * ----------------------------------------------------------------------------
 */

/* psp.h - Contains definitions for the PSP */
#if !defined(__PSP_H)
#define __PSP_H

#define FILENMLEN   256
#define FILEPATHLEN 512     /* FILENMLEN + _MAX_DIR (Windows) */
#define TFSPATHLEN  512
#define FILEIDLEN   148
#define LOGFILELEN  48
#define LOCKMGRLEN  48

#ifndef PSP_PRIVATE
#define PSP_PRIVATE
#endif

#include "pspplat.h"

#if defined(RDM_UNIX) && !defined(RDM_VXWORKS)
#include <inttypes.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include <setjmp.h>

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

#define PSP_OKAY                0
#define PSP_TIMEOUT          1001
#define PSP_FAILED           1002
#define PSP_NOMEMORY         1003
#define PSP_NOSERVER         1004
#define PSP_DUPUSERID        1005
#define PSP_DUPLICATE        1006
#define PSP_NOSOURCE         1007
#define PSP_NODEST           1008
#define PSP_PRIV             1009
#define PSP_NOTIMPLEMENTED   1010
#define PSP_INVALID_UTF8     1011
#define PSP_INVALID_UUID     1012
#define PSP_INVNULL          1013
#define PSP_TRUNCATE         1014
#define PSP_FCNSEQUENCE      1015
#define PSP_INVALID_USER     1016
#define PSP_INVALID_PASSWORD 1017

#define PSP_THREAD_LOW     -1
#define PSP_THREAD_NORMAL   0
#define PSP_THREAD_HIGH     1

RDM_EXPORT int32_t EXTERNAL_FCN psp_init(void);
RDM_EXPORT void    EXTERNAL_FCN psp_term(void);
RDM_EXPORT void    EXTERNAL_FCN psp_rdonly(void);
RDM_EXPORT void    EXTERNAL_FCN psp_nodisk(void);
RDM_EXPORT int32_t EXTERNAL_FCN psp_setMemLimit(void *, size_t);
RDM_EXPORT void    EXTERNAL_FCN psp_getMemUsage(size_t *, size_t *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_setTmpDir(const char *);

/* Totally portable macro to get the number of elements in an array of
 * ANYTHING:
 */
#define RLEN(x)     (sizeof(x) / sizeof(x[0]))

#define RDM_MIN(a, b) ((a) < (b) ? (a) : (b))
#define RDM_MAX(a, b) ((a) > (b) ? (a) : (b))

/***************************************************************************
  RDM type definitions
*/
#define RDM_INTEGRAL_FLAG  0x0000
#define RDM_FLOATING_FLAG  0x0001
#define RDM_FIXED_FLAG     0x0002
#define RDM_STRING_FLAG    0x0003
#define RDM_BINARY_FLAG    0x0004
#define RDM_ADDR_FLAG      0x0005
#define RDM_DATETIME_FLAG  0x0006
#define RDM_UID_FLAG       0x0007
#define RDM_STRUCTURE_FLAG 0x0008
#define RDM_BASE_MASK      0x000F

#define RDM_8_FLAG         0x0000
#define RDM_16_FLAG        0x0100
#define RDM_32_FLAG        0x0200
#define RDM_64_FLAG        0x0300
#define RDM_SIZE_MASK      0x0300

#define RDM_DATE_FLAG      0x0100
#define RDM_TIME_FLAG      0x0200

#define RDM_FIXEDLEN_FLAG  0x0000
#define RDM_VARLEN_FLAG    0x0400
#define RDM_LOB_FLAG       0x0800
#define RDM_LEN_MASK       0x0C00

#define RDM_SIGNED_FLAG    0x0000
#define RDM_UNSIGNED_FLAG  0x1000

#define RDM_KEY_FLAG       0x2000

#define RDM_PACKED_FLAG    0x0100

#define RDM_TYPE_INT8           (RDM_INTEGRAL_FLAG | RDM_SIGNED_FLAG | RDM_8_FLAG)
#define RDM_TYPE_UINT8          (RDM_INTEGRAL_FLAG | RDM_UNSIGNED_FLAG | RDM_8_FLAG)
#define RDM_TYPE_INT16          (RDM_INTEGRAL_FLAG | RDM_SIGNED_FLAG | RDM_16_FLAG)
#define RDM_TYPE_UINT16         (RDM_INTEGRAL_FLAG | RDM_UNSIGNED_FLAG | RDM_16_FLAG)
#define RDM_TYPE_INT32          (RDM_INTEGRAL_FLAG | RDM_SIGNED_FLAG | RDM_32_FLAG)
#define RDM_TYPE_UINT32         (RDM_INTEGRAL_FLAG | RDM_UNSIGNED_FLAG | RDM_32_FLAG)
#define RDM_TYPE_INT64          (RDM_INTEGRAL_FLAG | RDM_SIGNED_FLAG | RDM_64_FLAG)
#define RDM_TYPE_UINT64         (RDM_INTEGRAL_FLAG | RDM_UNSIGNED_FLAG | RDM_64_FLAG)

#define RDM_TYPE_FLOAT          (RDM_FLOATING_FLAG | RDM_32_FLAG)
#define RDM_TYPE_DOUBLE         (RDM_FLOATING_FLAG | RDM_64_FLAG)

#define RDM_TYPE_DECIMAL        (RDM_FIXED_FLAG)
#define RDM_TYPE_PACKED_DECIMAL (RDM_FIXED_FLAG | RDM_PACKED_FLAG)

#define RDM_TYPE_UTF8           (RDM_STRING_FLAG | RDM_FIXEDLEN_FLAG | RDM_8_FLAG)
#define RDM_TYPE_UTF16          (RDM_STRING_FLAG | RDM_FIXEDLEN_FLAG | RDM_16_FLAG)
#define RDM_TYPE_UTF32          (RDM_STRING_FLAG | RDM_FIXEDLEN_FLAG | RDM_32_FLAG)

#define RDM_TYPE_VARUTF8        (RDM_STRING_FLAG | RDM_VARLEN_FLAG | RDM_8_FLAG)
#define RDM_TYPE_VARUTF16       (RDM_STRING_FLAG | RDM_VARLEN_FLAG | RDM_16_FLAG)
#define RDM_TYPE_VARUTF32       (RDM_STRING_FLAG | RDM_VARLEN_FLAG | RDM_32_FLAG)

#define RDM_TYPE_CLOBUTF8       (RDM_STRING_FLAG | RDM_LOB_FLAG | RDM_8_FLAG)
#define RDM_TYPE_CLOBUTF16      (RDM_STRING_FLAG | RDM_LOB_FLAG | RDM_16_FLAG)
#define RDM_TYPE_CLOBUTF32      (RDM_STRING_FLAG | RDM_LOB_FLAG | RDM_32_FLAG)

#define RDM_TYPE_BINARY         (RDM_BINARY_FLAG | RDM_FIXEDLEN_FLAG)
#define RDM_TYPE_VARBINARY      (RDM_BINARY_FLAG | RDM_VARLEN_FLAG)
#define RDM_TYPE_BLOB           (RDM_BINARY_FLAG | RDM_LOB_FLAG)

#define RDM_TYPE_DBADDR4        (RDM_ADDR_FLAG | RDM_32_FLAG)
#define RDM_TYPE_DBADDR8        (RDM_ADDR_FLAG | RDM_64_FLAG)

#define RDM_TYPE_DATE           (RDM_DATETIME_FLAG | RDM_DATE_FLAG)
#define RDM_TYPE_TIME           (RDM_DATETIME_FLAG | RDM_TIME_FLAG)
#define RDM_TYPE_TIMESTAMP      (RDM_DATETIME_FLAG | RDM_DATE_FLAG | RDM_TIME_FLAG)

#define RDM_TYPE_UUID           (RDM_UID_FLAG)

#define RDM_TYPE_STRUCTURE      (RDM_STRUCTURE_FLAG)
#define RDM_TYPE_COMPOUNDKEY    (RDM_STRUCTURE_FLAG | RDM_KEY_FLAG)

typedef enum {
    RDM_INT8           = RDM_TYPE_INT8,
    RDM_UINT8          = RDM_TYPE_UINT8,
    RDM_INT16          = RDM_TYPE_INT16,
    RDM_UINT16         = RDM_TYPE_UINT16,
    RDM_INT32          = RDM_TYPE_INT32,
    RDM_UINT32         = RDM_TYPE_UINT32,
    RDM_INT64          = RDM_TYPE_INT64,
    RDM_UINT64         = RDM_TYPE_UINT64,
    RDM_FLOAT          = RDM_TYPE_FLOAT,
    RDM_DOUBLE         = RDM_TYPE_DOUBLE,
    RDM_DECIMAL        = RDM_TYPE_DECIMAL,
#if !defined(RDM_NO_PACKED_DECIMAL)
    RDM_PACKED_DECIMAL = RDM_TYPE_PACKED_DECIMAL,
#endif
    RDM_DATE           = RDM_TYPE_DATE,
    RDM_TIME           = RDM_TYPE_TIME,
    RDM_TIMESTAMP      = RDM_TYPE_TIMESTAMP,
    RDM_DBADDR4        = RDM_TYPE_DBADDR4,
    RDM_DBADDR8        = RDM_TYPE_DBADDR8,
    RDM_UUID           = RDM_TYPE_UUID,
    RDM_UTF8           = RDM_TYPE_UTF8,
    RDM_UTF16          = RDM_TYPE_UTF16,
    RDM_UTF32          = RDM_TYPE_UTF32,
    RDM_VARUTF8        = RDM_TYPE_VARUTF8,
    RDM_VARUTF16       = RDM_TYPE_VARUTF16,
    RDM_VARUTF32       = RDM_TYPE_VARUTF32,
    RDM_BINARY         = RDM_TYPE_BINARY,
    RDM_VARBINARY      = RDM_TYPE_VARBINARY,
    RDM_BLOB           = RDM_TYPE_BLOB,
    RDM_CLOBUTF8       = RDM_TYPE_CLOBUTF8,
    RDM_CLOBUTF16      = RDM_TYPE_CLOBUTF16,
    RDM_CLOBUTF32      = RDM_TYPE_CLOBUTF32,
    RDM_STRUCTURE      = RDM_TYPE_STRUCTURE,
    RDM_COMPOUNDKEY    = RDM_TYPE_COMPOUNDKEY
} RDM_TYPE;

#define RDM_IS_UNSIGNED(type)  (((uint32_t) (type)) & RDM_UNSIGNED_FLAG)
#define RDM_IS_LOB(type)       (((uint32_t) (type)) & RDM_LOB_FLAG)
#define RDM_IS_VARDATA(type)   (((uint32_t) (type)) & RDM_VARLEN_FLAG)

#define RDM_IS_INTEGRAL(type)  ((((uint32_t) (type)) & RDM_BASE_MASK) == RDM_INTEGRAL_FLAG)
#define RDM_IS_FLOATING(type)  ((((uint32_t) (type)) & RDM_BASE_MASK) == RDM_FLOATING_FLAG)
#define RDM_IS_FIXED(type)     ((((uint32_t) (type)) & RDM_BASE_MASK) == RDM_FIXED_FLAG)
#define RDM_IS_STRING(type)    ((((uint32_t) (type)) & RDM_BASE_MASK) == RDM_STRING_FLAG)
#define RDM_IS_BINARY(type)    ((((uint32_t) (type)) & RDM_BASE_MASK) == RDM_BINARY_FLAG)
#define RDM_IS_DBADDR(type)    ((((uint32_t) (type)) & RDM_BASE_MASK) == RDM_ADDR_FLAG)
#define RDM_IS_DATETIME(type)  ((((uint32_t) (type)) & RDM_BASE_MASK) == RDM_DATETIME_FLAG)
#define RDM_IS_UID(type)       ((((uint32_t) (type)) & RDM_BASE_MASK) == RDM_UID_FLAG)
#define RDM_IS_STRUCTURE(type) ((((uint32_t) (type)) & RDM_BASE_MASK) == RDM_STRUCTURE_FLAG)

/*lint -emacro(835,RDM_IS_UTF8) */
#define RDM_IS_UTF8(type)  ((((uint32_t) (type)) & (RDM_BASE_MASK | RDM_SIZE_MASK)) == (RDM_STRING_FLAG | RDM_8_FLAG))
#define RDM_IS_UTF16(type) ((((uint32_t) (type)) & (RDM_BASE_MASK | RDM_SIZE_MASK)) == (RDM_STRING_FLAG | RDM_16_FLAG))
#define RDM_IS_UTF32(type) ((((uint32_t) (type)) & (RDM_BASE_MASK | RDM_SIZE_MASK)) == (RDM_STRING_FLAG | RDM_32_FLAG))
#define RDM_IS_WCHAR(type) (RDM_IS_UTF16(type) || RDM_IS_UTF32(type))

#if defined(RDM_WCHAR_IS_UTF16)
#define RDM_IS_NON_NATIVE_WCHAR(type) RDM_IS_UTF32(type) 
#else
#define RDM_IS_NON_NATIVE_WCHAR(type) RDM_IS_UTF16(type)
#endif

#define RDM_IS_ENCODED(type)   (RDM_IS_STRUCTURE(type) || RDM_IS_DBADDR(type) || RDM_IS_FIXED(type) || RDM_IS_NON_NATIVE_WCHAR(type) || RDM_IS_VARDATA(type))

#define RDM_CAN_BE_INDEXED(type)  (!RDM_IS_LOB(type))
#define RDM_CAN_BE_ARRAYED(type)  (!RDM_IS_LOB(type))
#define RDM_CAN_BE_PARTIAL(type)  ((RDM_IS_STRING(type) || RDM_IS_BINARY(type)) && !RDM_IS_LOB(type))

#if !defined(RDM_NO_UNICODE)
#if defined(RDM_WCHAR_IS_UTF16)
#define RDM_WCHAR    RDM_UTF16
#define RDM_VARWCHAR RDM_VARUTF16
#elif defined(RDM_WCHAR_IS_UCS4)
#define RDM_WCHAR    RDM_UTF32
#define RDM_VARWCHAR RDM_VARUTF32
#else
#error "Please make sure that either RDM_WCHAR_IS_UTF16 or RDM_WCHAR_IS_UCS2 is defined"
#endif
#endif

/***************************************************************************
  Memory functions
*/

struct _TAG_ENTRY;
typedef struct _TAG_ENTRY *PSP_MEMTAG;

#define NULL_MEMTAG ((PSP_MEMTAG) -1)
#define TAGG        ((PSP_MEMTAG) 0) /* System global tag */
#define TAGL        ((PSP_MEMTAG) 1) /* Thread local (TLS) tag */
#define TAG0        TAGG

typedef struct {
    size_t in_use;
    size_t max_in_use;
} PSP_MEM_INFO;

typedef struct {
    PSP_MEM_INFO bytes;
    PSP_MEM_INFO capacity;
} PSP_TAG_MEM_INFO;

RDM_EXPORT void       *EXTERNAL_FCN psp_getMem(size_t, PSP_MEMTAG, int32_t, const void *, const char *, uint32_t);
RDM_EXPORT void       *EXTERNAL_FCN psp_extendMem(const void *, size_t, PSP_MEMTAG, int32_t, size_t, const char *, uint32_t);
RDM_EXPORT void        EXTERNAL_FCN psp_freeMem(const void *, PSP_MEMTAG, const char *, uint32_t);
#if 0
RDM_EXPORT const char *EXTERNAL_FCN psp_locModId(uint32_t, char *, size_t);
RDM_EXPORT void        EXTERNAL_FCN psp_moveMemTag(const void *, PSP_MEMTAG, PSP_MEMTAG);
#endif
#if !defined(RDM_NO_TLS)
RDM_EXPORT void        EXTERNAL_FCN psp_releaseTLSTag(void);
#endif
RDM_EXPORT int32_t     EXTERNAL_FCN psp_getTagMemInfo(PSP_MEMTAG, PSP_TAG_MEM_INFO *);

#define PSP_TAG_NOSEM   0x0000
#define PSP_TAG_USESEM  0x0001

typedef enum {
    BLOCK_ALLOCATOR, LIST_ALLOCATOR, STACK_ALLOCATOR, LEGACY_ALLOCATOR
} PSP_ALLOCATOR_TYPE;

#define DEFAULT_ALLOCATOR BLOCK_ALLOCATOR

typedef void (EXTERNAL_FCN *PSP_DESTROY_FCN)(void *);

RDM_EXPORT PSP_MEMTAG EXTERNAL_FCN psp_createTagEx(jmp_buf *, int16_t, PSP_ALLOCATOR_TYPE, PSP_DESTROY_FCN, void *, const char *, uint32_t);
RDM_EXPORT void       EXTERNAL_FCN psp_freeTagMem(PSP_MEMTAG, int16_t, const char *, uint32_t);
RDM_EXPORT void       EXTERNAL_FCN psp_resetTag(jmp_buf *, PSP_MEMTAG);

/*lint -printf(1, psp_memReport) */
RDM_EXPORT void       EXTVARARG_FCN psp_memReport(uint32_t, const char *, ...);
/*lint -printf(2, psp_memReportTag) */
RDM_EXPORT void       EXTVARARG_FCN psp_memReportTag(PSP_MEMTAG, uint32_t, const char *, ...);

#define PSP_MEM_ALL_FLAG  0x00000000
#define PSP_MEM_LEAK_FLAG 0x00000001

#define MEM_FLAG_ALLOC 0x01
#define MEM_FLAG_CLEAR 0x02
#define MEM_FLAG_COPY  0x04
#define MEM_FLAG_STR   0x08
#define MEM_FLAG_WCS   0x10

#define MEM_ALLOC  MEM_FLAG_ALLOC
#define MEM_CALLOC (MEM_FLAG_ALLOC | MEM_FLAG_CLEAR)
#define MEM_MEMDUP (MEM_FLAG_ALLOC | MEM_FLAG_COPY)
#define MEM_STRDUP (MEM_FLAG_ALLOC | MEM_FLAG_COPY | MEM_FLAG_STR)
#define MEM_WCSDUP (MEM_FLAG_ALLOC | MEM_FLAG_COPY | MEM_FLAG_WCS)

#define psp_createTag(jb, fl)                 psp_createTagEx(jb, fl, DEFAULT_ALLOCATOR, NULL, NULL, __FILE__, __LINE__)
#define psp_createStackTag(jb, fl)            psp_createTagEx(jb, fl, STACK_ALLOCATOR, NULL, NULL, __FILE__, __LINE__)
#define psp_createBlockTag(jb, fl)            psp_createTagEx(jb, fl, BLOCK_ALLOCATOR, NULL, NULL, __FILE__, __LINE__)
#define psp_createListTag(jb, fl)             psp_createTagEx(jb, fl, LIST_ALLOCATOR, NULL, NULL, __FILE__, __LINE__)
#define psp_freeTagMemory(tag, fl)            psp_freeTagMem(tag, fl, __FILE__, __LINE__)

#define psp_getMemory(sz, tag)                psp_getMem(sz, tag, MEM_ALLOC, NULL, __FILE__, __LINE__)
#define psp_cGetMemory(sz, tag)               psp_getMem(sz, tag, MEM_CALLOC, NULL, __FILE__, __LINE__)
#define psp_strdup(str, tag)                  ((char *) psp_getMem(0, tag, MEM_STRDUP, str, __FILE__, __LINE__))
#if !defined(RDM_NO_UNICODE)
#define psp_wcsdup(wcs, tag)                  ((wchar_t *) psp_getMem(0, tag, MEM_WCSDUP, wcs, __FILE__, __LINE__))
#endif
#define psp_memdup(sz, mem, tag)              psp_getMem(sz, tag, MEM_MEMDUP, mem, __FILE__, __LINE__)
#define psp_extendMemory(mem, sz, tag)        psp_extendMem(mem, sz, tag, 0, 0, __FILE__, __LINE__)
#define psp_cExtendMemory(mem, newsz, incsz, tag) psp_extendMem(mem, newsz, tag, 1, incsz, __FILE__, __LINE__)
#define psp_zFreeMemory(pptr, tag)            { psp_freeMem(*pptr, tag, __FILE__, __LINE__); *pptr = NULL; }
#define psp_freeMemory(ptr, tag)              psp_freeMem(ptr, tag, __FILE__, __LINE__)

/***************************************************************************
  File functions
*/
#if !defined(PSP_FILE_OFFSET)
typedef uint64_t PSP_FILE_OFFSET;
#endif

#if defined(RDM_VXWORKS_54) && (CPU == SIMNT)
#define PSP_FILE_NAME_PREFIX "host:"
#define PSP_NEED_PREFIX
#define PSP_MAX_FILE_NAME_SIZE 272
#else
#define PSP_FILE_NAME_PREFIX ""
#endif
    
typedef const void *PSP_FH;
typedef void       *PSP_MEM_FH;

typedef uint64_t TX_FILE;
typedef uint64_t TX_USER;
typedef uint64_t TX_DB;
typedef uint64_t TX_INI;
typedef uint64_t TXID;
#define TX_FILE_FMT UINT64_FMT
#define TX_USER_FMT UINT64_FMT
#define TX_DB_FMT   UINT64_FMT
#define TX_INI_FMT   UINT64_FMT

#define DBADDR8_FMT UINT64_FMT
#define DBADDR4_FMT "%u"

#define INVALID_TX_FILE ((TX_FILE) 0)

#if !defined(O_BINARY)
#if defined(_O_BINARY)
#define O_BINARY _O_BINARY
#else
#define O_BINARY 0
#endif
#endif

/* extended flags */
#define PSP_FLAG_DENYNO         0x0000
#define PSP_FLAG_DENYRD         0x0001
#define PSP_FLAG_DENYWR         0x0002
#define PSP_FLAG_DENYRW         (PSP_FLAG_DENYRD | PSP_FLAG_DENYWR)
#define PSP_FLAG_STICKY         0x0004
#define PSP_FLAG_MAPPED         0x0008
#define PSP_FLAG_INMEMORY       0x0040
#define PSP_FLAG_INMEMORY_READ  0x0080
#define PSP_FLAG_INMEMORY_WRITE 0x0100
#define PSP_FLAG_NO_SYNC        0x0200
#define PSP_FLAG_MKDIR          0x0400

/* Value returned by psp_fileRead(), psp_fileSeekRead(), psp_fileWrite and
   psp_fileSeekWrite() when I/O error occurs.
*/
#define PSP_IO_ERROR ((uint32_t)-1)

RDM_EXPORT int32_t         EXTERNAL_FCN psp_dirnameEx(const char *, char *, PSP_MEMTAG);
#define psp_dirname(path, dir)  psp_dirnameEx(path, dir, TAGL)
RDM_EXPORT char           *EXTERNAL_FCN psp_currdirEx(PSP_MEMTAG);
#define psp_currdir() psp_currdirEx(TAGL)
RDM_EXPORT char           *EXTERNAL_FCN psp_fullpathEx(const char *, PSP_MEMTAG);
#define psp_fullpath(path) psp_fullpathEx(path, TAGL)
RDM_EXPORT void            EXTERNAL_FCN psp_fileClose(PSP_FH);
RDM_EXPORT PSP_FILE_OFFSET EXTERNAL_FCN psp_fileLength(PSP_FH);
RDM_EXPORT PSP_FILE_OFFSET EXTERNAL_FCN psp_fileLengthStat(const char *, uint16_t);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileLock(PSP_FH);
RDM_EXPORT time64_t        EXTERNAL_FCN psp_fileModTimeStat(const char *, uint16_t);
#if 0
RDM_EXPORT void            EXTERNAL_FCN psp_fileScan(PSP_FH);
#endif
RDM_EXPORT PSP_FH          EXTERNAL_FCN psp_fileOpen(const char *, uint32_t, uint16_t);
RDM_EXPORT uint32_t        EXTERNAL_FCN psp_fileRead(PSP_FH, void *, uint32_t);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileSeek(PSP_FH, PSP_FILE_OFFSET, int32_t, PSP_FILE_OFFSET *);
RDM_EXPORT uint32_t        EXTERNAL_FCN psp_fileSeekRead(PSP_FH, PSP_FILE_OFFSET, void *, uint32_t);
RDM_EXPORT uint32_t        EXTERNAL_FCN psp_fileSeekWrite(PSP_FH, PSP_FILE_OFFSET, const void *, uint32_t);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileSetSize(PSP_FH, PSP_FILE_OFFSET);
RDM_EXPORT uint32_t        EXTERNAL_FCN psp_fileSync(PSP_FH);
RDM_EXPORT void            EXTERNAL_FCN psp_fileUnlock(PSP_FH);
RDM_EXPORT uint32_t        EXTERNAL_FCN psp_fileWrite(PSP_FH, const void *, uint32_t);

RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileCmp(const char *, const char *);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileCmpEx(const char *, uint16_t, const char *, uint16_t);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileCopy(const char *, const char *);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileCopyEx(const char *, uint16_t, const char *, uint16_t);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileMove(const char *, const char *);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileMoveEx(const char *, uint16_t, const char *, uint16_t);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileRemove(const char *);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileRemoveEx(const char *, uint16_t);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileRename(const char *, const char *);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileRenameEx(const char *, uint16_t, const char *, uint16_t);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileValidate(const char *);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileValidateEx(const char *, uint16_t, uint32_t *);

RDM_EXPORT const char     *EXTERNAL_FCN psp_fileCreateTmpName(uint32_t *, const char *, const char *, uint16_t, PSP_MEMTAG);

#if !defined(RDM_NO_UNICODE)
RDM_EXPORT PSP_FH          EXTERNAL_FCN psp_fileOpenW(const wchar_t *, uint32_t, uint16_t);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileCmpW(const wchar_t *, const wchar_t *);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileCmpExW(const wchar_t *, uint16_t, const wchar_t *, uint16_t);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileCopyW(const wchar_t *, const wchar_t *);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileCopyExW(const wchar_t *, uint16_t, const wchar_t *, uint16_t);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileMoveW(const wchar_t *, const wchar_t *);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileMoveExW(const wchar_t *, uint16_t, const wchar_t *, uint16_t);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileRemoveW(const wchar_t *);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileRemoveExW(const wchar_t *, uint16_t);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileRenameW(const wchar_t *, const wchar_t *);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileRenameExW(const wchar_t *, uint16_t, const wchar_t *, uint16_t);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileValidateW(const wchar_t *);
RDM_EXPORT int32_t         EXTERNAL_FCN psp_fileValidateExW(const wchar_t *, uint16_t, uint32_t *);
#endif

/* Issue 3826: Do case insensitive comparisons on all platforms */
#define psp_pathcmp  stricmp
#define psp_pathncmp strnicmp
#define psp_pathchrcmp(a, b) (toupper((int32_t) (a)) == toupper((int32_t) (b)))

typedef const void *PSP_FILE_STREAM;

typedef enum {
    PSP_FILE_MODE_UNKNOWN,
    PSP_FILE_MODE_UTF8,
    PSP_FILE_MODE_UTF16
} PSP_FILE_MODE;

RDM_EXPORT PSP_FILE_STREAM EXTERNAL_FCN  psp_fopen(const char *, const char *, PSP_FILE_MODE);
RDM_EXPORT PSP_FILE_STREAM EXTERNAL_FCN  psp_fopenEx(const char *, const char *, PSP_FILE_MODE, uint16_t);
RDM_EXPORT PSP_FILE_STREAM EXTERNAL_FCN  psp_fopen_std(const char *);
RDM_EXPORT void            EXTERNAL_FCN  psp_fclose(PSP_FILE_STREAM);
RDM_EXPORT void            EXTERNAL_FCN  psp_flush(void);
RDM_EXPORT void            EXTERNAL_FCN  psp_flushErr(void);
RDM_EXPORT int32_t         EXTERNAL_FCN  psp_fgetc(PSP_FILE_STREAM);
RDM_EXPORT char           *EXTERNAL_FCN  psp_fGetLine(PSP_FILE_STREAM, char **, uint32_t *, PSP_MEMTAG);
RDM_EXPORT char           *EXTERNAL_FCN  psp_fgets(char *, int32_t, PSP_FILE_STREAM);
RDM_EXPORT int32_t         EXTERNAL_FCN  psp_fputc(int32_t, PSP_FILE_STREAM);
RDM_EXPORT int32_t         EXTERNAL_FCN  psp_fputs(const char *, PSP_FILE_STREAM);
/*lint -printf(2, psp_fprintf) */
RDM_EXPORT int32_t         EXTVARARG_FCN psp_fprintf(PSP_FILE_STREAM, const char *, ...);
RDM_EXPORT int32_t         EXTERNAL_FCN  psp_fflush(PSP_FILE_STREAM);
RDM_EXPORT int32_t         EXTERNAL_FCN  psp_fseek(PSP_FILE_STREAM, int32_t, int32_t);
RDM_EXPORT int32_t         EXTERNAL_FCN  psp_fungetc(int32_t, PSP_FILE_STREAM);
/*lint -printf(1, psp_printf) */
RDM_EXPORT int32_t         EXTVARARG_FCN psp_printf(const char *, ...);
RDM_EXPORT int32_t         EXTERNAL_FCN  psp_printfV(const char *, va_list);
/*lint -printf(1, psp_printfErr) */
RDM_EXPORT int32_t         EXTVARARG_FCN psp_printfErr(const char *, ...);
RDM_EXPORT int32_t         EXTERNAL_FCN  psp_printfErrV(const char *, va_list);
RDM_EXPORT int32_t         EXTERNAL_FCN  psp_vfprintf(PSP_FILE_STREAM, const char *, va_list);

/**************************************************************************
  Logging functions
*/
#define PSP_STDOUT NULL
#define PSP_STDERR NULL
#define PSP_STDIN  NULL
typedef const void *PSP_LOG_CHUNK;

/*lint -printf(1, psp_log) */
RDM_EXPORT int32_t       EXTVARARG_FCN psp_log(const char *, ...);
/*lint -printf(1, psp_log_err) */
RDM_EXPORT int32_t       EXTVARARG_FCN psp_log_err(const char *, ...);
RDM_EXPORT int32_t       EXTERNAL_FCN  psp_logV(const char *, va_list);
RDM_EXPORT int32_t       EXTERNAL_FCN  psp_log_errV(const char *, va_list);
RDM_EXPORT PSP_LOG_CHUNK EXTERNAL_FCN  psp_log_chunk_init(void);
/*lint -printf(2, psp_log_chunk) */
RDM_EXPORT void          EXTVARARG_FCN psp_log_chunk(PSP_LOG_CHUNK, const char *, ...);
/*lint -printf(2, psp_log_chunk_end) */
RDM_EXPORT void          EXTVARARG_FCN psp_log_chunk_end(PSP_LOG_CHUNK, const char *, ...);
RDM_EXPORT int32_t       EXTERNAL_FCN  psp_log_open(const char *);
RDM_EXPORT int32_t       EXTERNAL_FCN  psp_log_create(const char *, const char *);
RDM_EXPORT void          EXTERNAL_FCN  psp_log_flush(void);
RDM_EXPORT void          EXTERNAL_FCN  psp_log_close(void);
RDM_EXPORT int32_t       EXTERNAL_FCN  psp_stdout_open(const char *);
RDM_EXPORT void          EXTERNAL_FCN  psp_stdout_close(void);
RDM_EXPORT int32_t       EXTERNAL_FCN  psp_stderr_open(const char *);
RDM_EXPORT void          EXTERNAL_FCN  psp_stderr_close(void);

/**************************************************************************
  Queue declarations
*/

#define PSP_QUEUE_NORMAL   0x0000
#define PSP_QUEUE_WAIT     0x0001
#define PSP_QUEUE_PRIORITY 0x0002
#define PSP_QUEUE_EMPTY  2
#define PSP_QUEUE_CLOSED 3
typedef void    *PSP_QUEUE_HANDLE;

RDM_EXPORT void             EXTERNAL_FCN psp_queueClose(PSP_QUEUE_HANDLE);
RDM_EXPORT PSP_QUEUE_HANDLE EXTERNAL_FCN psp_queueCreate(const char*);
RDM_EXPORT int32_t          EXTERNAL_FCN psp_queueCount(PSP_QUEUE_HANDLE);
RDM_EXPORT void             EXTERNAL_FCN psp_queueDelete(PSP_QUEUE_HANDLE);
RDM_EXPORT PSP_QUEUE_HANDLE EXTERNAL_FCN psp_queueFind(const char *);
RDM_EXPORT void             EXTERNAL_FCN psp_queuePurge(PSP_QUEUE_HANDLE, int32_t);
RDM_EXPORT int32_t          EXTERNAL_FCN psp_queueRead(PSP_QUEUE_HANDLE, void **, uint32_t *, int32_t *, uint32_t);
RDM_EXPORT int32_t          EXTERNAL_FCN psp_queueWrite(PSP_QUEUE_HANDLE, void *, uint32_t, int32_t, int16_t);

/***************************************************************************
  Synchronization functions
*/
typedef const void *PSP_SEM;
#define NO_PSP_SEM ((PSP_SEM) -1)
#define PSP_INDEFINITE_WAIT ((uint32_t) (-1))

#define PSP_EXCLUSIVE 0x0000
#define PSP_SHAREABLE 0x0100

#define PSP_UNDEF_SEM 0
#define PSP_MUTEX_SEM 1
#define PSP_EVENT_SEM 2

#define psp_syncCreate(type) psp_syncCreate_check((type), __FILE__, __LINE__)

RDM_EXPORT PSP_SEM EXTERNAL_FCN psp_syncCreate_check(int16_t, const char *, int32_t);
RDM_EXPORT void    EXTERNAL_FCN psp_syncDelete(PSP_SEM);
RDM_EXPORT void    EXTERNAL_FCN psp_syncEnterExcl(PSP_SEM);
RDM_EXPORT void    EXTERNAL_FCN psp_syncExitExcl(PSP_SEM);
RDM_EXPORT void    EXTERNAL_FCN psp_syncResume(PSP_SEM);
RDM_EXPORT void    EXTERNAL_FCN psp_syncStart(PSP_SEM);
RDM_EXPORT int16_t EXTERNAL_FCN psp_syncWait(PSP_SEM, uint32_t);

RDM_EXPORT void    EXTERNAL_FCN psp_enterCritSec(void);
RDM_EXPORT void    EXTERNAL_FCN psp_exitCritSec(void);

/***************************************************************************
  Memory pooling
*/
typedef const void *PSP_POOL;

typedef enum {
    PSP_POOL_FIXED_SIZE,
    PSP_POOL_VAR_SIZE
} PSP_POOL_SIZE_INFO;

RDM_EXPORT int32_t EXTERNAL_FCN psp_poolCreate(PSP_MEMTAG, PSP_POOL_SIZE_INFO, const char *, PSP_POOL *);
RDM_EXPORT void   *EXTERNAL_FCN psp_poolGetMem(PSP_POOL, size_t, int32_t, const void *, const char *, uint32_t);
RDM_EXPORT void    EXTERNAL_FCN psp_poolPut(PSP_POOL, const void *);
RDM_EXPORT void    EXTERNAL_FCN psp_poolDestroy(PSP_POOL);
RDM_EXPORT void    EXTERNAL_FCN psp_poolSetMaxPooled(PSP_POOL, uint32_t);

#define psp_poolGet(pl, sz)          psp_poolGetMem((pl), (sz), MEM_ALLOC, NULL, __FILE__, __LINE__)
#define psp_poolGetCleared(pl, sz)   psp_poolGetMem((pl), (sz), MEM_CALLOC, NULL, __FILE__, __LINE__)
#define psp_poolMemdup(pl, sz, data) psp_poolGetMem((pl), (sz), MEM_MEMDUP, (data), __FILE__, __LINE__)

/***************************************************************************
  UTF-8/Unicode conversion functions
*/
#if !defined(RDM_NO_UNICODE)
#if 0
RDM_EXPORT void     EXTERNAL_FCN psp_utf8_codes(uint32_t, uint8_t *, uint32_t *);
#endif
RDM_EXPORT uint32_t EXTERNAL_FCN psp_wchar_to_utf8(char *, const wchar_t *, uint32_t, uint32_t);
RDM_EXPORT uint32_t EXTERNAL_FCN psp_wchar_to_utf8_len(char *, uint32_t, const wchar_t *, uint32_t, uint32_t);
RDM_EXPORT uint32_t EXTERNAL_FCN psp_utf8_to_wchar(wchar_t *, const char *, uint32_t, uint32_t);
RDM_EXPORT uint32_t EXTERNAL_FCN psp_utf8_to_wchar_len(wchar_t *, uint32_t, const char *, uint32_t, uint32_t);
RDM_EXPORT char    *EXTERNAL_FCN psp_convToUTF8(const wchar_t *, uint32_t, PSP_MEMTAG);
RDM_EXPORT char    *EXTERNAL_FCN psp_convToUTF8_len(const wchar_t *, uint32_t, uint32_t, PSP_MEMTAG);
RDM_EXPORT wchar_t *EXTERNAL_FCN psp_convToWchar(const char *, uint32_t, PSP_MEMTAG);
RDM_EXPORT int32_t  EXTERNAL_FCN psp_convArgvToUTF8(int32_t, const wchar_t *const *, const char ***, PSP_MEMTAG);

#define psp_convertToUTF8(a, b) psp_convToUTF8((a), (b), TAGL)
#define psp_convertToUTF8_len(a, b, c) psp_convToUTF8_len((a), (b), (c), TAGL)
#define psp_convertToWchar(a, b) psp_convToWchar((a), (b), TAGL)
#define psp_convertArgvToUTF8(a, b, c) psp_convArgvToUTF8((a), (b), (c), TAGL)

#define PSP_UTF8_ERROR_BREAK    0
#define PSP_UTF8_ERROR_CONTINUE 1
#endif

#if !defined(RDM_NO_ATOMIC)
/***************************************************************************
  Atomic functions
*/
RDM_EXPORT uint32_t EXTERNAL_FCN psp_atomicSetUInt32(volatile uint32_t *, uint32_t, uint32_t);
RDM_EXPORT void     EXTERNAL_FCN psp_atomicIncrUInt32(volatile uint32_t *);
RDM_EXPORT void     EXTERNAL_FCN psp_atomicDecrUInt32(volatile uint32_t *);
RDM_EXPORT uint32_t EXTERNAL_FCN psp_atomicIncrUInt32WithVal(volatile uint32_t *);
RDM_EXPORT uint32_t EXTERNAL_FCN psp_atomicDecrUInt32WithVal(volatile uint32_t *);
#endif

#if !defined(RDM_NO_TLS)
/***************************************************************************
  TLS (Thread Local Storage) functions
*/
#if defined(RDM_WINDOWS) || defined(RDM_WINCE)
#define PSP_TLS_KEY uint32_t
#else
#define PSP_TLS_KEY pthread_key_t
#endif

RDM_EXPORT int32_t EXTERNAL_FCN psp_tlsCreateKey(PSP_TLS_KEY *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_tlsDestroyKey(PSP_TLS_KEY);
RDM_EXPORT int32_t EXTERNAL_FCN psp_tlsGetPtr(PSP_TLS_KEY, void **);
RDM_EXPORT int32_t EXTERNAL_FCN psp_tlsSetPtr(PSP_TLS_KEY, void *);
#endif

/***************************************************************************
  INI file functions
*/
RDM_EXPORT void    EXTERNAL_FCN psp_iniCleanup(void);
RDM_EXPORT int32_t EXTERNAL_FCN psp_readIniFile(const char *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_readIniFileEx(const char *, uint16_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniSet(const char *, const char *, const char *, const char *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniSetEx(const char *, const char *, const char *, const char *, uint16_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniGet(const char *, const char *, const char *, char *, uint32_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniGetEx(const char *, const char *, const char *, char *, uint32_t, uint16_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniGetStr(const char *, const char *, const char *, char **, uint16_t, PSP_MEMTAG);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniString(const char *, const char *, const char *, char *, uint32_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniStringEx(const char *, const char *, const char *, char *, uint32_t, uint16_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniInt32(const char *, const char *, const char *, int32_t *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniInt32Ex(const char *, const char *, const char *, int32_t *, uint16_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniUInt64Ex(const char *, const char *, const char *, uint64_t *, uint16_t);
#define psp_iniGetString(ini, sec, entry, str, xflags) psp_iniGetStr((ini), (sec), (entry), (str), (xflags), TAGL)
#if !defined(RDM_NO_UNICODE)
RDM_EXPORT int32_t EXTERNAL_FCN psp_readIniFileW(const wchar_t *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_readIniFileExW(const wchar_t *, uint16_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniSetW(const wchar_t *, const wchar_t *, const wchar_t *, const wchar_t *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniSetExW(const wchar_t *, const wchar_t *, const wchar_t *, const wchar_t *, uint16_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniGetW(const wchar_t *, const wchar_t *, const wchar_t *, wchar_t *, uint32_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniGetExW(const wchar_t *, const wchar_t *, const wchar_t *, wchar_t *, uint32_t, uint16_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniStringW(const wchar_t *, const wchar_t *, const wchar_t *, wchar_t *, uint32_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniStringExW(const wchar_t *, const wchar_t *, const wchar_t *, wchar_t *, uint32_t, uint16_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniInt32W(const wchar_t *, const wchar_t *, const wchar_t *, int32_t *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_iniInt32ExW(const wchar_t *, const wchar_t *, const wchar_t *, int32_t *, uint16_t);
#endif

/***************************************************************************
  Communication functions
*/
typedef const void *PSP_LMC;
typedef const void *PSP_CONN;

typedef int32_t (LMC_SEND_FCN)(const void *, uint32_t, const void *);
typedef int32_t (LMC_RECV_FCN)(void **, uint32_t *, const void *);

typedef int32_t (LMC_CHECKID_FCN)(const char *);
typedef int32_t (LMC_CONNECT_FCN)(const char *, const char *, const char *, void **);
typedef void    (LMC_DISCONNECT_FCN)(const void *);

typedef int32_t (LMC_LISTEN_FCN)(const char *, const char *, uint32_t,
        void **);
typedef void   *(LMC_WAITMSG_FCN)(void *, int32_t);
typedef void    (LMC_STOPLISTEN_FCN)(void *);
typedef void    (LMC_DISCONCLIENT_FCN)(const void *, const void *);
typedef void    (LMC_INFO_FCN)(const void *, char *, char *, char *);

typedef struct {
    const char           *name;
    LMC_SEND_FCN         *send;
    LMC_RECV_FCN         *recv;

    LMC_CHECKID_FCN      *checkid;
    LMC_CONNECT_FCN      *connect;
    LMC_DISCONNECT_FCN   *disconnect;

    LMC_LISTEN_FCN       *listen;
    LMC_WAITMSG_FCN      *waitmsg;
    LMC_STOPLISTEN_FCN   *stoplisten;
    LMC_DISCONCLIENT_FCN *disconclient;

    LMC_INFO_FCN         *info;
} LOCKCOMM_FCNS;

typedef int32_t (LMC_AVAIL_FCN)(int32_t *, const LOCKCOMM_FCNS **);

#define PSP_FLAG_NETWORK_ORDER 0x0001
#define PSP_FLAG_NO_FILE_LOCKS 0x0004

/* Alignment calculations */
typedef enum {
    ALN_CHAR, ALN_INT16, ALN_WCHAR, ALN_INT32, ALN_FLOAT, ALN_INT64, ALN_DOUBLE
} ALIGN_TYPE;


RDM_EXPORT uint16_t EXTERNAL_FCN psp_swaporder16(uint16_t);
RDM_EXPORT uint32_t EXTERNAL_FCN psp_swaporder32(uint32_t);
RDM_EXPORT uint64_t EXTERNAL_FCN psp_swaporder64(uint64_t);
RDM_EXPORT float    EXTERNAL_FCN psp_swaporderf32(float);
RDM_EXPORT double   EXTERNAL_FCN psp_swaporderf64(double);

#if defined(RDM_BIGENDIAN)
#define psp_ntoh_i16(v) (v)
#define psp_ntoh_i32(v) (v)
#define psp_ntoh_i64(v) (v)
#define psp_ntoh_u16(v) (v)
#define psp_ntoh_u32(v) (v)
#define psp_ntoh_u64(v) (v)
#define psp_ntoh_f32(v) (v)
#define psp_ntoh_f64(v) (v)
#define psp_hton_i16(v) (v)
#define psp_hton_i32(v) (v)
#define psp_hton_i64(v) (v)
#define psp_hton_u16(v) (v)
#define psp_hton_u32(v) (v)
#define psp_hton_u64(v) (v)
#define psp_hton_f32(v) (v)
#define psp_hton_f64(v) (v)
#else
#define psp_ntoh_i16(v) (int16_t) psp_swaporder16((uint16_t) v)
#define psp_ntoh_i32(v) (int32_t) psp_swaporder32((uint32_t) v)
#define psp_ntoh_i64(v) (int64_t) psp_swaporder64((uint64_t) v)
#define psp_ntoh_u16(v) psp_swaporder16(v)
#define psp_ntoh_u32(v) psp_swaporder32(v)
#define psp_ntoh_u64(v) psp_swaporder64(v)
#define psp_ntoh_f32(v) psp_swaporderf32(v)
#define psp_ntoh_f64(v) psp_swaporderf64(v)
#define psp_hton_i16(v) (int16_t) psp_swaporder16((uint16_t) v)
#define psp_hton_i32(v) (int32_t) psp_swaporder32((uint32_t) v)
#define psp_hton_i64(v) (int64_t) psp_swaporder64((uint64_t) v)
#define psp_hton_u16(v) psp_swaporder16(v)
#define psp_hton_u32(v) psp_swaporder32(v)
#define psp_hton_u64(v) psp_swaporder64(v)
#define psp_hton_f32(v) psp_swaporderf32(v)
#define psp_hton_f64(v) psp_swaporderf64(v)
#endif

#define psp_ntoh_faddr  psp_ntoh_u64
#define psp_hton_faddr  psp_hton_u64
#if defined(RDM_WCHAR_IS_UCS4)
#define psp_ntoh_wchar(w)  (wchar_t) psp_ntoh_u32((uint32_t) w)
#define psp_hton_wchar(w)  (wchar_t) psp_hton_u32((uint32_t) w)
#elif defined(RDM_WCHAR_IS_UTF16)
#define psp_ntoh_wchar(w)  (wchar_t) psp_ntoh_u16((uint16_t) w)
#define psp_hton_wchar(w)  (wchar_t) psp_hton_u16((uint16_t) w)
#endif

/***************************************************************************
  Thread and Process functions
*/
typedef int32_t (EXTERNAL_FCN *PSP_THREAD_FCN)(void *);
RDM_EXPORT uint64_t     EXTERNAL_FCN psp_get_pid(void);
RDM_EXPORT void         EXTERNAL_FCN psp_sleep(uint32_t);
RDM_EXPORT int16_t      EXTERNAL_FCN psp_threadBeginEx(PSP_THREAD_FCN, uint32_t, void *, psp_thread_t *, int32_t, const char *name);
#define psp_threadBegin(a, b, c) psp_threadBeginEx(a, b, c, NULL, 0, NULL)
RDM_EXPORT psp_thread_t EXTERNAL_FCN psp_threadId(void);
RDM_EXPORT int16_t      EXTERNAL_FCN psp_threadSetPriority(psp_thread_t, int32_t);
RDM_EXPORT void         EXTERNAL_FCN psp_threadEnd(int32_t rc);
RDM_EXPORT int32_t      EXTERNAL_FCN psp_threadJoin (psp_thread_t);

typedef const void *PSP_DAEMON_CTX;
RDM_EXPORT int32_t      EXTERNAL_FCN psp_daemonStart(const char *, PSP_DAEMON_CTX *);
RDM_EXPORT void         EXTERNAL_FCN psp_daemonComplete(PSP_DAEMON_CTX);

RDM_EXPORT int32_t EXTERNAL_FCN psp_serviceStart(const char *, uint16_t *, int32_t, const char *const *, int32_t (EXTERNAL_FCN *)(int32_t, const char *const *));
RDM_EXPORT void    EXTERNAL_FCN psp_serviceStarted(void);
RDM_EXPORT void    EXTERNAL_FCN psp_serviceDone(void);

RDM_EXPORT int32_t EXTERNAL_FCN psp_serviceInstall(const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_serviceUninstall(const char *, const char *);


#if defined(RDM_VXWORKS) || defined(RDM_UC_OS_II)
#define PSP_DEFAULT_STACKSIZE  0x8000
#else
#define PSP_DEFAULT_STACKSIZE  0
#endif

/***************************************************************************
  Global variable handling functions
*/
typedef int32_t (*PSP_GLOBAL_CREATE_FCN)(void *);
typedef void    (*PSP_GLOBAL_DELETE_FCN)(void *);

RDM_EXPORT int32_t EXTERNAL_FCN psp_globalGet(const char *, size_t, PSP_GLOBAL_CREATE_FCN, PSP_GLOBAL_DELETE_FCN, void **);

/***************************************************************************
  Thread pooling functions
*/
typedef enum { JOB_WAITING, JOB_STARTED, JOB_FINISHED } PSP_THRPOOL_JOB_STATUS;

typedef struct _PSP_THRPOOL     PSP_THRPOOL;
typedef struct _PSP_THRPOOL_JOB PSP_THRPOOL_JOB;

typedef int32_t (*PSP_THRPOOL_FCN)(void *);
typedef void    (*PSP_THRPOOL_CALLBACK_FCN)(PSP_THRPOOL_JOB *, void *, int32_t);

RDM_EXPORT int32_t EXTERNAL_FCN psp_thrpoolCreate(uint32_t, PSP_THRPOOL **);
RDM_EXPORT void    EXTERNAL_FCN psp_thrpoolDestroy(PSP_THRPOOL *);

RDM_EXPORT int32_t EXTERNAL_FCN psp_thrpoolAddJob(const PSP_THRPOOL *, PSP_THRPOOL_FCN, void *, PSP_THRPOOL_CALLBACK_FCN, void *, PSP_THRPOOL_JOB **);
RDM_EXPORT int32_t EXTERNAL_FCN psp_thrpoolJobsLeft(const PSP_THRPOOL *);

RDM_EXPORT int32_t EXTERNAL_FCN psp_thrpoolJobStatus(const PSP_THRPOOL_JOB *, PSP_THRPOOL_JOB_STATUS *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_thrpoolJobWaitTime(const PSP_THRPOOL_JOB *, uint64_t *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_thrpoolJobExecTime(const PSP_THRPOOL_JOB *, uint64_t *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_thrpoolJobResult(const PSP_THRPOOL_JOB *, int32_t *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_thrpoolJobDelete(const PSP_THRPOOL_JOB *);

/***************************************************************************
  Path (File and Directory) functions
*/

RDM_EXPORT int32_t        EXTERNAL_FCN psp_dirCreate(const char *);
RDM_EXPORT int32_t        EXTERNAL_FCN psp_dirCreateAll(const char *);
RDM_EXPORT int32_t        EXTERNAL_FCN psp_dirRemove(const char *);
RDM_EXPORT int32_t        EXTERNAL_FCN psp_dirMove(const char *, const char *);
RDM_EXPORT int32_t        EXTERNAL_FCN psp_dirMoveEx(const char *, uint16_t, const char *, uint16_t);

#if !defined(RDM_NO_UNICODE)
RDM_EXPORT int32_t        EXTERNAL_FCN psp_dirCreateW(const wchar_t *);
RDM_EXPORT int32_t        EXTERNAL_FCN psp_dirCreateAllW(const wchar_t *);
RDM_EXPORT int32_t        EXTERNAL_FCN psp_dirRemoveW(const wchar_t *);
RDM_EXPORT int32_t        EXTERNAL_FCN psp_dirMoveW(const wchar_t *, const wchar_t *);
RDM_EXPORT int32_t        EXTERNAL_FCN psp_dirMoveExW(const wchar_t *, uint16_t, const wchar_t *, uint16_t);
#endif

RDM_EXPORT PSP_DIR        EXTERNAL_FCN psp_pathOpen(const char *, const char *);
RDM_EXPORT PSP_DIR        EXTERNAL_FCN psp_pathOpenEx(const char *, uint16_t, const char *);
RDM_EXPORT const char    *EXTERNAL_FCN psp_pathNext(PSP_DIR, uint32_t *);
RDM_EXPORT void           EXTERNAL_FCN psp_pathClose(PSP_DIR);

#if 0
RDM_EXPORT const char    *EXTERNAL_FCN psp_pathDefTmp(void);
RDM_EXPORT const char    *EXTERNAL_FCN psp_pathGetTmp(void);
RDM_EXPORT int16_t        EXTERNAL_FCN psp_pathSetTmp(char *);
#endif
RDM_EXPORT int32_t        EXTERNAL_FCN psp_pathIsDir(const char *);
RDM_EXPORT int32_t        EXTERNAL_FCN psp_pathIsFullyQualified(const char *);
RDM_EXPORT int32_t        EXTERNAL_FCN psp_pathSplitEx(const char *, char **, char **, PSP_MEMTAG);
#define psp_pathSplit(a, b, c) psp_pathSplitEx(a, b, c, TAGL)
RDM_EXPORT const char    *EXTERNAL_FCN psp_pathStripDrive(const char *);

#if !defined(RDM_NO_UNICODE)
RDM_EXPORT PSP_DIR        EXTERNAL_FCN psp_pathOpenW(const wchar_t *, const wchar_t *);
RDM_EXPORT PSP_DIR        EXTERNAL_FCN psp_pathOpenExW(const wchar_t *, uint16_t, const wchar_t *);
RDM_EXPORT const wchar_t *EXTERNAL_FCN psp_pathNextW(PSP_DIR, uint32_t *);
#endif

#if defined(NEED_TEMPNAM)
RDM_EXPORT char         *EXTERNAL_FCN tempnam(char *, char *);
#endif

/**************************************************************************
  Sorted array definitions
*/
typedef const void *PSP_SA;
typedef int32_t (EXTERNAL_FCN *PSP_SA_COMPARE)(const void *, const void *, const void *);

RDM_EXPORT PSP_SA  EXTERNAL_FCN psp_saCreateEx(const char *, PSP_SA_COMPARE, uint32_t, const void *, const char *, uint32_t);
RDM_EXPORT void    EXTERNAL_FCN psp_saDestroy(PSP_SA);
RDM_EXPORT void   *EXTERNAL_FCN psp_saFind(PSP_SA, const void *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_saAdd(PSP_SA, const void *);
RDM_EXPORT void   *EXTERNAL_FCN psp_saDelete(PSP_SA, const void *);
RDM_EXPORT void   *EXTERNAL_FCN psp_saFirst(PSP_SA);
RDM_EXPORT void   *EXTERNAL_FCN psp_saDeleteFirst(PSP_SA);
RDM_EXPORT void   *EXTERNAL_FCN psp_saLast(PSP_SA);
RDM_EXPORT void   *EXTERNAL_FCN psp_saDeleteLast(PSP_SA);
RDM_EXPORT void   *EXTERNAL_FCN psp_saNext(PSP_SA);
RDM_EXPORT void   *EXTERNAL_FCN psp_saPrev(PSP_SA);
RDM_EXPORT size_t  EXTERNAL_FCN psp_saCount(PSP_SA);

#define psp_saCreate(name, cmp, ctx) psp_saCreateEx((name), (cmp), 0, (ctx), __FILE__, __LINE__)
#define psp_saCreate_sync(name, cmp, ctx) psp_saCreateEx((name), (cmp), 1, (ctx), __FILE__, __LINE__)

/**************************************************************************
  Encryption definitions
*/

/** Enumeration for RDM encryption algorithms
 *
 *   The enumeration identifies the supported encryption algorithms
 */
typedef enum ENC_TYPE_E
{
    ENC_NONE = 0,   /**< enum value no encryption */
    ENC_AES_128,    /**< enum value 128 bit AES encryption */
    ENC_AES_192,    /**< enum value 192 bit AES encryption */
    ENC_AES_256,    /**< enum value 256 bit AES encryption */
    ENC_XOR = 4     /**< enum value for the simple XOR encryption */
} ENC_TYPE;

#if defined(RDM_WITH_STRONG_ENCRYPTION)
#define ENC_DEFAULT      ENC_AES_128
#define ENC_DEFAULT_TEXT "aes128"
#else
#define ENC_DEFAULT      ENC_XOR
#define ENC_DEFAULT_TEXT "xor"
#endif
#define RDM_SYS_KEYLEN 129

struct ENC_S;

typedef const struct ENC_S *(ENC_DEFAULT_FCN)(ENC_TYPE, const char *, const void *);
typedef int32_t (ENC_CREATE_FCN)(ENC_TYPE, const void *, size_t, const struct ENC_S**);
typedef void    (ENC_DELETE_FCN)(const struct ENC_S *);
typedef void    (ENC_ENCDEC_FCN)(const void *, void *, uint32_t);
typedef int32_t (ENC_SET_FCN)(const void *, void *);
typedef int32_t (ENC_CHK_FCN)(const void *, const void *);
typedef void    (ENC_DIGEST_FCN)(const void *, uint64_t, void *);

/** Structure for encryption context information
 *
 *   This structure contains the elements required for using encryption
 *   with an RDM database.
 */
typedef struct ENC_S {
    ENC_TYPE         type;        /**< encrption algorithm used */
    const void      *data;        /**< buffer for internal encryption operations */
    uint32_t         blocksize;   /**< algorithm blocksize */
    ENC_CREATE_FCN  *cre;         /**< function pointer to algorithms creation function */
    ENC_DELETE_FCN  *del;         /**< function pointer to algorithms deletion function */
    ENC_ENCDEC_FCN  *enc;         /**< function pointer to algorithms encrypt function */
    ENC_ENCDEC_FCN  *dec;         /**< function pointer to algorithms decrypt function */
    ENC_SET_FCN     *set;         /**< function pointer to algorithms set key function */
    ENC_CHK_FCN     *chk;         /**< function pointer to algorithms check key function */
    ENC_DIGEST_FCN  *digest;      /**< function pointer to algorithms digest function */
} ENC;

#define CRYPTPWLEN 16

/***************************************************************************
  Miscellaneous functions
*/
typedef void (INTERRUPT_FCN)(void);

RDM_EXPORT int32_t     EXTERNAL_FCN  psp_errno(void);
RDM_EXPORT int32_t     EXTERNAL_FCN  psp_strerr(int32_t, char *, size_t);
RDM_EXPORT char       *EXTERNAL_FCN  psp_strerr_alloc(int32_t, PSP_MEMTAG);
RDM_EXPORT void        EXTERNAL_FCN  psp_errPrint(const char *);
RDM_EXPORT const char *EXTERNAL_FCN  psp_getenv(const char *);
RDM_EXPORT int32_t     EXTERNAL_FCN  psp_seed(void);
RDM_EXPORT struct tm  *EXTERNAL_FCN  psp_timeLocaltime(time64_t, struct tm *);
RDM_EXPORT time64_t    EXTERNAL_FCN  psp_timeSecs(void);
RDM_EXPORT uint64_t    EXTERNAL_FCN  psp_timeMilliSecs(void);
RDM_EXPORT uint64_t    EXTERNAL_FCN  psp_timeNanoSecs(void);
RDM_EXPORT const char *EXTERNAL_FCN  psp_tmpdir(PSP_MEMTAG);
RDM_EXPORT int32_t     EXTERNAL_FCN  psp_handleInterrupt(INTERRUPT_FCN *);
RDM_EXPORT uint32_t    EXTERNAL_FCN  psp_getcpucount(void);

RDM_EXPORT const char *EXTERNAL_FCN  psp_setlocale(int32_t, const char *);
RDM_EXPORT void        EXTERNAL_FCN  psp_version(int16_t *, int16_t *, int16_t *);
RDM_EXPORT uint16_t    EXTERNAL_FCN  psp_align(uint16_t, ALIGN_TYPE);
/*lint -printf(3, psp_execfile) */
RDM_EXPORT int32_t     EXTVARARG_FCN psp_execfile(const char *, int32_t *, const char *, ...);
RDM_EXPORT int32_t     EXTERNAL_FCN  psp_system(const char *);
#if defined(RDM_NEED_ISFINITE)
RDM_EXPORT int         EXTERNAL_FCN  psp_isFinite(double);
#endif

#if !defined(RDM_NO_UNICODE)
RDM_EXPORT const wchar_t *EXTERNAL_FCN psp_getenvW(const wchar_t *);
RDM_EXPORT const wchar_t *EXTERNAL_FCN psp_setlocaleW(int32_t, const wchar_t *);
#endif

#if defined(NEED_STRUPR)
RDM_EXPORT char    *EXTERNAL_FCN strlwr(char *);
RDM_EXPORT char    *EXTERNAL_FCN strupr(char *);
#if !defined(RDM_NO_UNICODE)
RDM_EXPORT wchar_t *EXTERNAL_FCN wcslwr(wchar_t *);
RDM_EXPORT wchar_t *EXTERNAL_FCN wcsupr(wchar_t *);
#endif
#endif

#if defined(NEED_STRNCMP)
RDM_EXPORT int32_t EXTERNAL_FCN psp_strncmp (const char *s1, const char *s2, size_t len);
#else
#define psp_strncmp(s1,s2,n) strncmp(s1,s2,n)
#endif
    
RDM_EXPORT int64_t  EXTERNAL_FCN psp_atoi64(const char *s);
RDM_EXPORT uint64_t EXTERNAL_FCN psp_atoui64(const char *s);

RDM_EXPORT char    *EXTERNAL_FCN psp_strncpyZ(char *, const char *, size_t); /*lint -esym(534,psp_strncpyZ) */
#if !defined(RDM_NO_UNICODE)
RDM_EXPORT wchar_t *EXTERNAL_FCN psp_wcsncpyZ(wchar_t *, const wchar_t *, size_t); /*lint -esym(534,psp_wcsncpyZ) */
#endif
RDM_EXPORT char    *EXTERNAL_FCN psp_strtok(char *, const char *, char **);
RDM_EXPORT int32_t  EXTERNAL_FCN psp_tokenize(char *, const char *, const char ***, uint32_t *, int32_t, PSP_MEMTAG);
RDM_EXPORT double   EXTERNAL_FCN psp_round(double);

/*lint -printf(3,psp_snprintf) */
RDM_EXPORT int      EXTVARARG_FCN psp_snprintf(char *, size_t, const char *, ...); /*lint -esym(534,psp_snprintf) */
RDM_EXPORT int      EXTERNAL_FCN  psp_vsnprintf(char *, size_t, const char *, va_list);
/*lint -wprintf(3,psp_snwprintf) */
RDM_EXPORT int      EXTVARARG_FCN psp_snwprintf(wchar_t *, size_t, const wchar_t *, ...); /*lint -esym(534,psp_snwprintf) */
RDM_EXPORT int      EXTERNAL_FCN  psp_vsnwprintf(wchar_t *, size_t, const wchar_t *, va_list);
RDM_EXPORT char    *EXTERNAL_FCN  psp_makeStrV(const char *, uint32_t, PSP_MEMTAG, const char *, va_list);
/*lint -printf(4,psp_makeStrVA) */
RDM_EXPORT char    *EXTVARARG_FCN psp_makeStrVA(const char *, uint32_t, PSP_MEMTAG, const char *, ...);
RDM_EXPORT wchar_t *EXTERNAL_FCN  psp_makeWStrV(const char *, uint32_t, PSP_MEMTAG, const wchar_t *, va_list);
/*lint -wprintf(4,psp_makeWStrVA) */
RDM_EXPORT wchar_t *EXTVARARG_FCN psp_makeWStrVA(const char *, uint32_t, PSP_MEMTAG, const wchar_t *, ...);
RDM_EXPORT char    *EXTERNAL_FCN  psp_appendStrV(const char *, uint32_t, PSP_MEMTAG, const char *, const char *, va_list);
/*lint -printf(5,psp_appendStrVA) */
RDM_EXPORT char    *EXTVARARG_FCN psp_appendStrVA(const char *, uint32_t, PSP_MEMTAG, const char *, const char *, ...);
RDM_EXPORT wchar_t *EXTERNAL_FCN  psp_appendWStrV(const char *, uint32_t, PSP_MEMTAG, const wchar_t *, const wchar_t *, va_list);
/*lint -wprintf(5,psp_appendWStrVA) */
RDM_EXPORT wchar_t *EXTVARARG_FCN psp_appendWStrVA(const char *, uint32_t, PSP_MEMTAG, const wchar_t *, const wchar_t *, ...);
#if defined(RDM_NO_VARIADIC_MACROS) || defined(RDM_WINDOWS) || defined(RDM_WINCE)
/*lint -printf(2,psp_makeStr) */
RDM_EXPORT char    *EXTVARARG_FCN psp_makeStr(PSP_MEMTAG, const char *, ...);
/*lint -printf(1,psp_makeString) */
RDM_EXPORT char    *EXTVARARG_FCN psp_makeString(const char *, ...);
/*lint -wprintf(2,psp_makeWStr) */
RDM_EXPORT wchar_t *EXTVARARG_FCN psp_makeWStr(PSP_MEMTAG, const wchar_t *, ...);
/*lint -wprintf(1,psp_makeWString) */
RDM_EXPORT wchar_t *EXTVARARG_FCN psp_makeWString(const wchar_t *, ...);
/*lint -printf(3,psp_appendStr) */
RDM_EXPORT char    *EXTVARARG_FCN psp_appendStr(PSP_MEMTAG, const char *, const char *, ...);
/*lint -printf(2,psp_appendString) */
RDM_EXPORT char    *EXTVARARG_FCN psp_appendString(const char *, const char *, ...);
/*lint -wprintf(3,psp_appendWStr) */
RDM_EXPORT wchar_t *EXTVARARG_FCN psp_appendWStr(PSP_MEMTAG, const wchar_t *, const wchar_t *, ...);
/*lint -wprintf(2,psp_appendWString) */
RDM_EXPORT wchar_t *EXTVARARG_FCN psp_appendWString(const wchar_t *, const wchar_t *, ...);
#endif

#if !defined(RDM_NO_VARIADIC_MACROS)
#define psp_makeStr(tag, ...) psp_makeStrVA(__FILE__, __LINE__, tag, __VA_ARGS__)
#define psp_makeString(...) psp_makeStrVA(__FILE__, __LINE__, TAGL, __VA_ARGS__)
#define psp_makeWStr(tag, ...) psp_makeWStrVA(__FILE__, __LINE__, tag, __VA_ARGS__)
#define psp_makeWString(...) psp_makeWStrVA(__FILE__, __LINE__, TAGL, __VA_ARGS__)
#define psp_appendStr(tag, str, ...) psp_appendStrVA(__FILE__, __LINE__, tag, str, __VA_ARGS__)
#define psp_appendString(str, ...) psp_appendStrVA(__FILE__, __LINE__, TAGL, str, __VA_ARGS__)
#define psp_appendWStr(tag, str, ...) psp_appendWStrVA(__FILE__, __LINE__, tag, str, __VA_ARGS__)
#define psp_appendWString(str, ...) psp_appendWStrVA(__FILE__, __LINE__, TAGL, str, __VA_ARGS__)
#endif

#define psp_makeStringV(fmt, args) psp_makeStrV(__FILE__, __LINE__, TAGL, fmt, args)
#define psp_makeWStringV(fmt, args) psp_makeWStrV(__FILE__, __LINE__, TAGL, fmt, args)
#define psp_appendStringV(str, fmt, args) psp_appendStrV(__FILE__, __LINE__, TAGL, str, fmt, args)
#define psp_appendWStringV(str, fmt, args) psp_appendWStrV(__FILE__, __LINE__, TAGL, str, fmt, args)

RDM_EXPORT int32_t EXTERNAL_FCN psp_isPurifyRunning(void);
#if defined(RDM_WINDOWS) && !defined(RELEASE)
#define RDM_PURIFY_CHECK
#endif

/* User table status */
#define U_EMPTY         0
#define U_LIVE          1
#if defined(RDM_HAS_XLOCKS)
#define U_HOLDING_X     6
#endif

/* Buffered I/O Handling */
typedef int32_t (*PSP_BUFFREADFCN)(const void *, void *, uint32_t, uint32_t *, uint32_t);
typedef int32_t (*PSP_BUFFWRITEFCN)(const void *, const void *, uint32_t);

typedef const void *PSP_INPUTBUFF;
typedef const void *PSP_OUTPUTBUFF;

RDM_EXPORT int32_t EXTERNAL_FCN psp_inputBuffCreate(PSP_BUFFREADFCN, const void *, int16_t, PSP_INPUTBUFF *);
RDM_EXPORT void    EXTERNAL_FCN psp_inputBuffDestroy(PSP_INPUTBUFF);
RDM_EXPORT int32_t EXTERNAL_FCN psp_inputBuffGetChar(PSP_INPUTBUFF, char *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_inputBuffGetInt16(PSP_INPUTBUFF, int16_t *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_inputBuffGetInt32(PSP_INPUTBUFF, int32_t *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_inputBuffGetInt32Timeout(PSP_INPUTBUFF, int32_t *, uint32_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_inputBuffGetInt64(PSP_INPUTBUFF, int64_t *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_inputBuffGetFloat32(PSP_INPUTBUFF, float *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_inputBuffGetFloat64(PSP_INPUTBUFF, double *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_inputBuffGetStringWithLength(PSP_INPUTBUFF, char *, size_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_inputBuffGetString(PSP_INPUTBUFF, char **);
RDM_EXPORT int32_t EXTERNAL_FCN psp_inputBuffGetBytes(PSP_INPUTBUFF, void *, size_t);
RDM_EXPORT void    EXTERNAL_FCN psp_inputBuffReset(PSP_INPUTBUFF);

#define psp_inputBuffGetUser(b, u)     psp_inputBuffGetBytes((b), (u), sizeof(*(u)))
#define psp_inputBuffGetFile(b, f)     psp_inputBuffGetBytes((b), (f), sizeof(*(f)))
#define psp_inputBuffGetDb(b, d)       psp_inputBuffGetBytes((b), (d), sizeof(*(d)))
#define psp_inputBuffGetIni(b, i)      psp_inputBuffGetBytes((b), (i), sizeof(*(i)))

#define psp_inputBuffGetInt8(b, i8)    psp_inputBuffGetChar((b), ((char *) (i8)))
#define psp_inputBuffGetUInt8(b, u8)   psp_inputBuffGetChar((b), ((char *) (u8)))
#define psp_inputBuffGetUInt16(b, u16) psp_inputBuffGetInt16((b), ((int16_t *) (u16)))
#define psp_inputBuffGetUInt32(b, u32) psp_inputBuffGetInt32((b), ((int32_t *) (u32)))
#define psp_inputBuffGetUInt64(b, u64) psp_inputBuffGetInt64((b), ((int64_t *) (u64)))

RDM_EXPORT int32_t EXTERNAL_FCN psp_outputBuffCreate(PSP_BUFFWRITEFCN, const void *, int16_t, PSP_OUTPUTBUFF *);
RDM_EXPORT void    EXTERNAL_FCN psp_outputBuffDestroy(PSP_OUTPUTBUFF);
RDM_EXPORT int32_t EXTERNAL_FCN psp_outputBuffFlush(PSP_OUTPUTBUFF);
RDM_EXPORT int32_t EXTERNAL_FCN psp_outputBuffPutChar(PSP_OUTPUTBUFF, char);
RDM_EXPORT int32_t EXTERNAL_FCN psp_outputBuffPutInt16(PSP_OUTPUTBUFF, int16_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_outputBuffPutInt32(PSP_OUTPUTBUFF, int32_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_outputBuffPutInt64(PSP_OUTPUTBUFF, int64_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_outputBuffPutFloat32(PSP_OUTPUTBUFF, float);
RDM_EXPORT int32_t EXTERNAL_FCN psp_outputBuffPutFloat64(PSP_OUTPUTBUFF, double);
RDM_EXPORT int32_t EXTERNAL_FCN psp_outputBuffPutString(PSP_OUTPUTBUFF, const char *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_outputBuffPutStringWithLength(PSP_OUTPUTBUFF, const char *);
RDM_EXPORT int32_t EXTERNAL_FCN psp_outputBuffPutBytes(PSP_OUTPUTBUFF, const void *, size_t);
RDM_EXPORT int32_t EXTERNAL_FCN psp_outputBuffSendDirect(PSP_OUTPUTBUFF, const void *, size_t);

#define psp_outputBuffPutFcnID(b, f)    psp_outputBuffPutBytes((b), (f), sizeof(f) - 1)
#define psp_outputBuffPutUser(b, u)     psp_outputBuffPutBytes((b), &(u), sizeof(u))
#define psp_outputBuffPutFile(b, f)     psp_outputBuffPutBytes((b), &(f), sizeof(f))
#define psp_outputBuffPutDb(b, d)       psp_outputBuffPutBytes((b), &(d), sizeof(d))
#define psp_outputBuffPutIni(b, i)      psp_outputBuffPutBytes((b), &(i), sizeof(i))

#define psp_outputBuffPutInt8(b, i8)    psp_outputBuffPutChar((b), (char) (u8))
#define psp_outputBuffPutUInt8(b, u8)   psp_outputBuffPutChar((b), (char) (i8))
#define psp_outputBuffPutUInt16(b, u16) psp_outputBuffPutInt16((b), (int16_t) (u16))
#define psp_outputBuffPutUInt32(b, u32) psp_outputBuffPutInt32((b), (int32_t) (u32))
#define psp_outputBuffPutUInt64(b, u64) psp_outputBuffPutInt64((b), (int64_t) (u64))

/* Parse definitions for psp_yyparse */
typedef void *PSP_PYYCONTEXT;
typedef void *PSP_PYYSTYPE;

typedef int16_t (*PSP_YYLEX)(PSP_PYYCONTEXT, PSP_PYYSTYPE);
typedef int16_t (*PSP_YYACT)(PSP_PYYCONTEXT, PSP_PYYSTYPE, int16_t, PSP_PYYSTYPE);
typedef void    (*PSP_YYSYNTAXERR)(PSP_PYYCONTEXT);
typedef void    (*PSP_YYDEBUG)(PSP_PYYCONTEXT, char *, ...);

#if defined(YYDEBUG)
typedef struct {
    char   *t_name;
    int16_t t_val;
} PSP_YYTOKTYPE;
#endif

typedef struct {
    int16_t              yyerrcode;
    int16_t              yylast;
    const int16_t       *yyexca;
    const int16_t       *yyact;
    const int16_t       *yypact;
    const int16_t       *yypgo;
    const uint16_t      *yyr1;
    const uint16_t      *yyr2;
    const int16_t       *yychk;
    const int16_t       *yydef;
#if defined(YYDEBUG)
    const PSP_YYTOKTYPE *yytoks;
    const char   *const *yyreds;
#endif
} PSP_YYTABLES;

typedef struct {
    uint32_t            yytoksize;
    PSP_PYYCONTEXT      yyctx;
    const PSP_YYTABLES *yytab;
    PSP_YYLEX           yylex;
    PSP_YYACT           yyacts;
    PSP_YYSYNTAXERR     yysyntaxerr;
#if defined(YYDEBUG)
    PSP_YYDEBUG         yydebug;
#endif
    PSP_MEMTAG          yytag;
} PSP_YYPDATA;

RDM_EXPORT int16_t EXTERNAL_FCN psp_yyparse(const PSP_YYPDATA *);

/* Random number generator */
typedef const void *PSP_RAND;

RDM_EXPORT PSP_RAND EXTERNAL_FCN psp_randCreate(uint32_t seed);
RDM_EXPORT void     EXTERNAL_FCN psp_randDestroy(PSP_RAND);
RDM_EXPORT int32_t  EXTERNAL_FCN psp_randGet(PSP_RAND);
RDM_EXPORT uint32_t EXTERNAL_FCN psp_randGetUInt32(PSP_RAND);
RDM_EXPORT uint64_t EXTERNAL_FCN psp_randGetUInt64(PSP_RAND);
RDM_EXPORT double   EXTERNAL_FCN psp_randGetDouble(PSP_RAND);
RDM_EXPORT void     EXTERNAL_FCN psp_randResetSeed(PSP_RAND, uint32_t seed);

/* UUID support.  UUIDs are always stored in big-endian order. */
typedef struct {
    uint32_t time_low;
    uint16_t time_mid;
    uint16_t time_high_and_version;
    uint8_t  clock_seq_high_and_reserved;
    uint8_t  clock_seq_low;
    uint8_t  node[6];
} psp_uuid_t;

/* String length of a UUID including the NULL terminator but not including
 * braces */
#define RDM_UUID_STRLEN 37

typedef psp_uuid_t UUID_VAL;
typedef UUID_VAL   GUID_VAL;

RDM_EXPORT void        EXTERNAL_FCN uuid_create(UUID_VAL *);
RDM_EXPORT int32_t     EXTERNAL_FCN uuid_toString(const UUID_VAL *, char *, size_t, int32_t);
RDM_EXPORT int32_t     EXTERNAL_FCN uuid_fromString(const char *, UUID_VAL *);
/*lint -esym(534,uuid_toString) */

/* Tracing code for debugging */

#if !defined(RELEASE)
#define PSP_TRACE_LIST_SIZE 1000

typedef const char *PSP_TRACE_LIST[PSP_TRACE_LIST_SIZE];
extern PSP_TRACE_LIST *psp_trace_list; /*lint !e956 */

RDM_EXPORT void EXTVARARG_FCN psp_trace(const char *, ...);
RDM_EXPORT void EXTVARARG_FCN psp_traceFile(const char *, ...);
#endif

#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
#define __LOC__ __FILE__ "("__STR1__(__LINE__)") : Warning Msg: "

#define PSP_ROUND_UP(value, num) (((value + num - 1) / num) * num)

RDM_EXPORT char *EXTERNAL_FCN   psp_getcwd(char *, uint32_t);

#if defined(RDM_ANDROID) && !defined(RELEASE)
typedef void (EXTVARARG_FCN ANDROIDLOG_FCN)(const char *, va_list);
RDM_EXPORT void EXTERNAL_FCN psp_set_androidlog_fcn(ANDROIDLOG_FCN);
RDM_EXPORT void EXTVARARG_FCN psp_androidlog(const char *, ...);
RDM_EXPORT void EXTVARARG_FCN psp_androidlogV(const char *, va_list);
#endif

#if defined(__cplusplus)
}
#endif

#endif  /* __PSP_H */

