Revision 337 (by dpavlin, 2004/06/10 19:22:40) new trunk for webpac v2
/*
	openisis - an open implementation of the CDS/ISIS database
	Version 0.8.x (patchlevel see file Version)
	Copyright (C) 2001-2003 by Erik Grziwotz, erik@openisis.org

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

	see README for more information
EOH */
#ifndef LIO_H

/*
	$Id: lio.h,v 1.22 2003/05/29 18:02:54 kripke Exp $
	I/O support for the openisis library.
	Provides non-blocking, look-ahead network streams and other nice stuff.
*/

#include "luti.h"
#include "lll.h"


/* ************************************************************
	time
*/

/* struct wrapper just for struct Tm *Time */ 
typedef struct Tm {
	lll   millis;
}	Tm;

/**
	set Tm to current time, return difference in millis
*/
extern int timeUpd ( Tm * );
/**
	print generalized time yyyyMMddHHmmss + 0 byte to buffer
	if Tm is 0, current time is used
	if Tm.millis is 0, Tm is updated
	return buffer, which must have 15 bytes
*/
extern char *timeGtf ( char *buf, Tm * );
/**
	like timeAsc, but with additional 3 digits millis
	return buffer, which must have 18 bytes
*/
extern char *timeGtfm ( char *buf, Tm * );
/**
	nanosl
*/
extern void timeSleep ( Tm * );


/* ************************************************************
	system files
*/

/**
	system file is a non-negative 32bit int including status bits.
	main status bits are LIO_IN and LIO_OUT,
	which are set by open and cleared by close.

	negative values are reserved for use by non-system based streams.
*/
#define LIO_WANT  0xfff00000 /* what we want: open flags */
#define LIO_FD    0x0000ffff /* what we get: system fd */
#define LIO_STAT  0x000f0000 /* how it's going: it's status */

/* status flags */
#define LIO_IN    0x00010000 /* support input */
#define LIO_OUT   0x00020000 /* support output */
#define LIO_INOUT 0x00030000 /* support both */
#define LIO_ISOPEN( file ) (LIO_INOUT & (file))

/* common requirements that are also used by non-system streams. */
#define LIO_RD    0x00100000 /* shall be opened for input */
#define LIO_WR    0x00200000 /* shall be opened for output */
#define LIO_RDWR  0x00300000 /* shall be opened for both */
#define LIO_SYNC  0x00400000 /* with WR: syncing output */
#define LIO_NBLK  0x00800000 /* non blocking IO (not used) */

/* system files only. */
#define LIO_CREAT 0x01000000 /* with WR: shall be created */
#define LIO_TRY   0x01000000 /* w/o  WR: do not complain if open fails */
#define LIO_TRUNC 0x02000000 /* with WR: shall be truncated */
#define LIO_SEEK  0x04000000 /* random access (with WR: else append mode) */
#define LIO_SOCK  0x08000000 /* is a socket (support shutdown) */

/* locking */
#define LIO_TLOCK 0x10000000 /* try locking (EX with WR) */
#define LIO_WLOCK 0x20000000 /* lock waiting (EX with WR) */
#define LIO_FLOCK 0x30000000 /* any locking is set */


/** create a new fid based on name and flags.
	name may be &i to use fd i, esp. for i=0,1 or 2.
	@return non-negative file or some error code
*/
extern int lio_open ( const char *name, int flags );
extern int lio_close ( int *file, int flags );
extern int lio_size ( int file );
extern unsigned lio_time ( int file ); /* mtime sec */

extern int lio_in;
extern int lio_out;
extern int lio_err;


/*
	Like the syscalls, this returns the number of bytes on success.
	Unlike the syscalls, it returns 0 rather than an error
	when no bytes are available after interrupt (EINTR)
	or on non-blocking IO (EAGAIN); i.e. you may try later.
	On error, a negative value is returned.
	On errors that render the file unusable,
	it is closed for input or output, resp.
	These are most errors but EFAULT (bad buf)
	and ESPIPE (which clears the SEEK bit).
	For files that do not have the SEEK bit set,
	EOF is considered such an error and -LERR_EOF is returned.
	If you want to stream a disk file like 'tail -f', set the SEEK bit.
*/
extern int lio_read ( int *file, void *buf, unsigned count );
extern int lio_write ( int *file, const void *buf, unsigned count );
extern int lio_pread ( int *file, void *buf, unsigned count, int offset );
extern int lio_pwrite ( int *file, const void *buf, unsigned count, int offset );
extern int lio_seek ( int *file, int offset );
extern int lio_trunc ( int *file, int offset );
/**
	open, sync or close a memory mapping

	@param file pointer to open file handle to map.
		if file is NULL, *map is unmapped (and set to NULL)
		else if *map is NULL, length bytes are mapped
		else *map is synced (flushed)
	@param length number of bytes to map; if 0, size will be used
	@return mapped length; if <= 0, *map is set to 0, else to memory region
*/
extern int lio_mmap ( int *file, void **map, int length );


/** slurp in a whole file at once.
	@param buf points to buffer of size sz.
		lio_slurp will allocate one, if *buf is NULL
	@param sz maximum number of bytes to read
	@param name of file to slurp
	@param opt if != 0, do not complain on failure
	@return number of bytes read or negative on error
*/
extern int lio_slurp ( char **buf, int sz, const char *name, int opt );



/* ************************************************************
	streams
*/

/** an I/O buffered stream similar to stdio's FILE.
	Unlike FILE with it's stupid ungetc,
	it supports efficient scanning of the whole input buffer without
	actually consuming it.
	Also unlike at least Linux' glibc's stdio, access is not interlocked.
	The buffer is typically used for input OR output.
	However, for internal pipes, the same buffer is used from both ends.

	High level access functions like printf operate directly on the buffer
	and call the stream function on buffer underflow or overflow
	(or explicit flush).
*/
typedef int lio_sfunc ( struct Ios *s, int op );

enum {
	LIO_BUFSIZ = 8192
};

typedef struct Buf {
	/* struct Buf     *nxt; chain -- not used */
	short           fill; /* total #bytes in the buffer */
	short           done; /* #bytes done */
	unsigned char   c[LIO_BUFSIZ]; /* actual buffer may be longer */
} Buf;
/* fill - done is the number of available bytes */
#define LIO_BAVAIL( b )  ((b)->fill - (b)->done)
#define LIO_BINIT( b ) do { \
	/*(b)->nxt = 0;*/ (b)->fill = 0; (b)->done = 0; \
	} while (0)
#define LIO_BINITIALIZER { 0,0,"" }

typedef struct Ios {
	lio_sfunc  *func;
	const char *name; /* stream's name */
	int         file; /* file "id" and flags as above */
	int         pos;  /* logical position of buffer start within stream */
	Buf         b;
}	Ios;

#define LIO_SISOPEN( s ) LIO_ISOPEN( (s)->file )
#define LIO_SAVAIL( s )  LIO_BAVAIL( &(s)->b )
#define LIO_SINIT( s, fun, nam, fil ) do { \
	(s)->func = fun; (s)->name = nam; (s)->file = fil; \
	(s)->pos = 0; \
	LIO_BINIT( &(s)->b ); \
	} while (0)
#define LIO_STDINIT( s, nam, fil ) LIO_SINIT( s, lio_stdio, nam, fil )
#define LIO_SINITIALIZER( fun, nam, fil ) { fun, nam, fil, 0, LIO_BINITIALIZER }
#define LIO_STDINITIALIZER( nam, fil ) LIO_SINITIALIZER( lio_stdio, nam, fil )
	

/** stream operations.
*/
enum {
	LIO_SSIZE,  /* tell the size of the stream structure */
	LIO_SOPEN,  /* initialize the structure */
	LIO_SCLOSE, /* close */
	LIO_SPURGE, /* kill the done bytes. return fill buffer size */
	LIO_SFILL,  /* try to refill the buffer (poll input). return # new bytes */
	LIO_SFLUSH, /* try to flush the buffer. return # bytes written */
	LIO_SPUSH   /* push input stream: munge prefilled input */
};

/**
	"abstract" base implementation of stream.
	not very useful in itself, but used by derived impl.
*/
extern int ioStream ( Ios *s, int op );

/**
	stream func based on system file to mimic stdio.
	on LIO_SOPEN, the fid is set by lio_open based on name.
	other ops used the correponding lio system call.
*/
extern int ioStdio ( Ios *s, int op );

#define LIO_OPEN( s )  (s)->func( (s), LIO_SOPEN )
#define LIO_CLOSE( s ) (s)->func( (s), LIO_SCLOSE )
#define LIO_FILL( s )  (s)->func( (s), LIO_SFILL )
#define LIO_FLUSH( s ) (s)->func( (s), LIO_SFLUSH )




/* ************************************************************
	inter process communication
*/

extern CLockFunc *lio_lock;
#define LIO_LOCK() (NULL != lio_lock && lio_lock(OPENISIS_LOCK))
#define LIO_RELE() (NULL != lio_lock && lio_lock(OPENISIS_RELE))
#define LIO_WAIT( c ) (NULL != lio_lock && lio_lock(OPENISIS_WAIT \
	| (OPENISIS_COND & (c))))
#define LIO_WAKE( c ) (NULL != lio_lock && lio_lock(OPENISIS_WAKE \
	| (OPENISIS_COND & (c))))

#define LIO_H
#endif /* LIO_H */