/*
-- ----------------------------------------------------------------------------
--
--          Copyright 1995 Division Limited.
--                All Rights Reserved
--
--
--  System       :
--  Module       :
--  Object Name  : $RCSfile: filelib.h,v $
--  Revision     : $Revision: 1.9 $
--  Date         : $Date: 95/05/16 13:46:20 $
--  Author       : $Author: bill $
--
--  Description
--
--  Notes
--
--  History
--
--
-- ----------------------------------------------------------------------------
*/

#ifndef __FILELIB_H__
#define __FILELIB_H__

#include <dsys/divtypes.h>

#ifndef _PFILE
#ifdef _PF_LOCAL
#include "pfile.h"
#else
#include <dsys/pfile.h>
#endif
#endif

/*****************************************************************************/
/* filelib error numbers */
#define dflENO_READ   0x2001
#define dflENO_WRITE  0x2002
#define dflENO_CPATH  0x2003
#define dflENO_CNAME  0x2004
#define dflENO_PERMIT 0x2005
#define dflENO_DIR    0x2006
#define dflENO_RMFILE 0x2007
#define dflENO_RMDIR  0x2008
#define dflENO_USAGE  0x2009

#define dfl_STDIN_NAME  "stdin"
#define dfl_STDOUT_NAME "stdout"

extern char     *progname ;

#define dfl_SET_TO_LITTLE  0
#define dfl_SET_TO_BIG     1

#define dflPATHDIV    '/'
#define dflREPPATHDIV '\\'

#ifndef _UNIX
#define dflDRIVEDIV ':'
#endif

/****************************************************************************
 * File reading and writing routines.
 */
   
typedef struct dflFILETYPE
{
    char  *name ;
    FILE  *fp ;
    int32  endian ;
    char *buf, *bufEnd;
    int32 remain ;
    int32 filePos, endPos ;
} dflFILE, *dflFILEPTR ;

#define dfl_BUFFER_SIZE 8192

void
dflSetEndian(dflFILEPTR file, int32 OutEndian) ;
dflFILEPTR
dflOpen(char *name, char *mode, int32 OutEndian) ;
int32
dflClose(dflFILEPTR file) ;

/****************************************************************************
 * File reading routines
 */
int32
dflSeek(dflFILEPTR fl, int32 offset, int32 whence) ;
int32
dflUngetc(char c, dflFILEPTR fl);
int32
_dflGetc(dflFILEPTR fl) ;
int32
_dflRead(void *ptr, int32 size, dflFILEPTR fl) ;

#define dflTell(fl)    ((fl)->filePos - (fl)->remain)
#define dflGetc(fl)                                               \
    (((fl)->remain) ?                                             \
        ((int32) *((fl)->bufEnd - ((fl)->remain)--))           :  \
        _dflGetc(fl))
#define dflRead(ptr,size,fl)                                      \
    (((fl)->remain >= (size))  ?                                  \
        ( memcpy((ptr),((fl)->bufEnd - (fl)->remain),(size)) ,    \
          (fl)->remain -= (size), (int32) dpgSUCCESS)          :  \
        _dflRead(ptr,size,fl))

#define dflError(fl)  ((int32) ferror(fl->fp))


int32
dflRead1byte(dflFILEPTR fl, void *dest) ;
int32
dflReadn1byte(dflFILEPTR fl, int32 n, void *dest) ;
int32
dflRead2byte(dflFILEPTR fl, void *dest) ;
int32
dflReadn2byte(dflFILEPTR fl, int32 n, void *dest) ;
int32
dflRead4byte(dflFILEPTR fl, void *dest) ;
int32
dflReadn4byte(dflFILEPTR fl, int32 n, void *dest) ;
int32
dflRead8byte(dflFILEPTR fl, void *dest) ;
int32
dflReadn8byte(dflFILEPTR fl, int32 n, void *dest) ;

/****************************************************************************
 * File writing routines
 */

void
dflWriteint8(dflFILEPTR fl, int8 i) ;
void
dflWriteuint8(dflFILEPTR fl, uint8 i) ;
void
dflWriteint16(dflFILEPTR fl, int16 i) ;
void
dflWriteuint16(dflFILEPTR fl, uint16 i) ;
void
dflWriteint32(dflFILEPTR fl, int32 i) ;
void
dflWritefloat32(dflFILEPTR fl, float32 f) ;
void
dflWritefloat64(dflFILEPTR fl, float64 f) ;
void
dflWritestr(dflFILEPTR fl, void *source, int32 size) ;


/***************************************************************************
 * File name manipulation routines
 *
 * Major re-write on 11/2/95 due to the introduction of material files. This
 * led to the need of hierarchical break down of files from all geometry
 * converters (i.e. dxf2vdi). As they all use the same structure the routines
 * have been placed into this library.
 */
/*****************************************************************************
* PLEASE NOTE:- These file name manipulation routines expect unix style      *
*               names, even on dos, a simple call to dflFormatName should    *
*               solve any potential problems.                                *
*****************************************************************************/

/****************************************************************************
 * dflFormatName
 * 
 * Converts all file names to unix style, i.e. all '\\' to '/'
 * Should be called for every file name!
 */
void
dflFormatName(char *name) ;

/****************************************************************************
 * dflSplitName - splits the given file name into is 3 constituent parts.
 * If path, body or ext are NULL, no problems, that part isn't done.
 * returns dymanically allocated strings, the path will have the closing
 * '/' and neither the body ext will have the dividing '.'
 */
void
dflSplitName(char *FName, char **path, char **body, char **ext) ;

/*****************************************************************************
 * dflComposeName - Opposite to SplitName, i.e. given the 3 parts, it joins 
 * them together. Any of them can be NULL. If the body starts with a '/' then
 * the path is ignored. if the path doesnt end with a '/' then one is inserted
 * if the extension is NULL or "" then no '.' is inserted at the end of body.
 */
char *
dflComposeName(char *path, char *body, char *ext) ;

/****************************************************************************
 * dflCreateName - same as dflComposeName, only excepts 3 paths and joins 
 * them together, any can be NULL.
 */
char *
dflCreateName(char *basePath, char *midPath, char *extPath, 
              char *base, char *ext) ;

/***************************************************************************
 * dflBackupName - Checks for existance of the file 'filename', if it exists,
 * it creates a backup filename 'BackName' by either inserting the 
 * "division.sav" directory into the path, or if the environment variable
 * ${division.sav} is set then it is asumed to be the absolute output path
 * and the base name of 'filename' is appended. If the file 'BackName' exists
 * then it is removed, and 'filename' is moved to 'BackName'.
 * 
 * Returns -1 if an error occured or the number of paths created.
 * 'BackName is a dynamically allocated string which must be freed be the
 * user
 */
int32
dflBackupName(char *filename, char **Backup) ;

/****************************************************************************
 * dflRemoveBackup - removes everything generated from a call to dflBackupName
 * Requires the return value to determine how many directories are to be 
 * removed. If backing up 2 or more files it is important to Remove the backup 
 * in an reversed order, soley because the first one will have created any 
 * required directies and its return value will be non zero, these directies 
 * can only be removed after all the the backup files have been removed.
 * returns dpgERROR if failed to remove something, else returns dpgSUCCESS
 */
int32
dflRemoveBackup(char *backName, int32 noDirs) ;

/****************************************************************************
 * dflTempName - Creates a temporary file name based on the given file name.
 * returns NULL on failure, dynamically allocated string otherwise.
 */
char *
dflTempName(char *fname) ;

#define dflUSEMID  0x01
#define dflASCII   0x02
#define dflLIBRARY 0x04
char *
dflCreateVtxName(char *basePath, int32 useMid, char *extPath, char *base) ;
char *
dflCreateBgfName(char *basePath, int32 useMid, char *extPath, char *base,
                 dpfFILETYPE OutMode) ;
char *
dflCreateBmfName(char *basePath, int32 useMid, char *extPath, char *base,
                 dpfFILETYPE OutMode, int libOut) ;
char *
dflCreateVdiName(char *basePath, int32 useMid, char *extPath, char *base,
                 int libOut) ;

/**************************************************************************
 * Create Path
 * creates a single path given the path string, last path must terminate in
 * a '/' else it will not be tested for.
 * 
 * Return -1 on an error (dpgERROR), else the number of directories created.
 */
int32
dflCreatePath(char *path) ;
/**************************************************************************
 * dflCreatePaths - Sets up the division path structure given the base and
 * extended paths and whether to use mid paths, all required
 * paths are created, which includes material, geometry, texture, vdifiles 
 * and the vdi library path.
 */
int32
dflCreatePaths(char *basePath, int32 useMid, char *extPath) ;

/************************************************************************
 * dflCreateBaseName
 * creates a base name (bit between the path and the extension) ready
 * for a Compose or CreateName. if the numb is less than zero, it is 
 * ignored, if dosName is non-zero then the output name will be no long
 * than 8 chars.
 */
char *
dflCreateBaseName(char *base, int32 numb, int32 dosName) ;


#define byte8_flip(p) do { \
    char ___t; \
    ___t=p[0]; \
    p[0]=p[7]; \
    p[7]=___t; \
    ___t=p[1]; \
    p[1]=p[6]; \
    p[6]=___t; \
    ___t=p[2]; \
    p[2]=p[5]; \
    p[5]=___t; \
    ___t=p[3]; \
    p[3]=p[4]; \
    p[4]=___t; \
} while (0)

#define byte4_flip(p) do { \
    char ___t; \
    ___t=p[0]; \
    p[0]=p[3]; \
    p[3]=___t; \
    ___t=p[1]; \
    p[1]=p[2]; \
    p[2]=___t; \
} while (0)

#define byte2_flip(p) do { \
    char ___t; \
    ___t=p[0]; \
    p[0]=p[1]; \
    p[1]=___t; \
} while (0)


#endif /* __FILELIB_H__ */

