/***********************************************************************
**	
**	Pandora Streams.h
**	
**	Copyright©1997 by Terry Greeniaus
**	tgree@relay.phys.ualberta.ca
**	
**	Permission is given to the Pandora OS group to use this file in the development of the Pandora Operating
**	System.  The Pandora OS group is located at: http://www.huh.com/pandora/
**	
************************************************************************/
#ifndef __PANDORA_STREAMS__
#define __PANDORA_STREAMS__

#pragma options align=power

enum PStreamState
{
	noState	=		0UL,
	stateReadWillFail =	(1UL << 0),		// The last write to the stream failed
	stateWriteWillFail =	(1UL << 1),		// The next attempt to write to the stream is known to fail
	stateBadRead =		(1UL << 2),		// The last read from the stream failed
	stateBadWrite =	(1UL << 3)	,		// The next attempt to read from the stream is known to fail
	stateClosing =		(1UL << 4)	,		// The stream is in the process of closing
	stateClosed =		(1UL << 5),		// The stream is closed
	stateOpening =		(1UL << 6),		// The stream is opening
	stateOpened =		(1UL << 7),		// The stream is succesfully opened
	stateBadAsyncOp =	(1UL << 8)			// Some asynchronous operation failed
};

enum PStreamType
{
	typeNoAccess =		0UL,
	typeReadAccess =		(1UL << 0),		// This stream supports read access
	typeWriteAccess =		(1UL << 1),		// This stream supports write access
	typeSeekableAccess =	(1UL << 2)			// This stream is seekable
};

// The PStreamable class is the base class for C++ classes which can be saved/written to a stream and for
// objects which can also be constructed from a stream.
struct PStreamable
{
	// You should also provide a constructor for each class in the hierarchy of the following form:
	PStreamable(class PIStream& istream) throw(PErr);
	virtual ~PStreamable();
	
	virtual	void	write(class POStream& ostream) const throw(PErr) = 0;
	virtual	void	read(class PIStream& istream) throw(PErr) = 0;
};

// The PStream is the base class for all streams in Pandora.  It allows a stream to be named.
struct PStream
{
	struct PStreamData*	data;
	
			const char*		name();
			void				waitForStreamToClose();	// Waits until the state of the stream is closed.
	virtual	void				block();				// Waits for all asynchronous I/O to complete.
	virtual					operator unsigned long();	// Returns the state of the stream.
	
	static	class PIOStream*	newStreamFromURL(const char* url);	// Creates a stream to access a given URL.
	static	void				pipe(class PIStream& iStream,class POStream& oStream,unsigned long len = -1);
	
	// You should never need to call these functions.  This part of the API is only exposed for MacOS completion routines.
			void				setModeOpening();
			void				setModeOpened();
			void				setModeClosing();
			void				setModeClosed();
protected:
	PStream(const char* name = nil) throw(PErr);
	virtual ~PStream();
	
};

// The POStream class is the base class for all output streams in Pandora.  It is derived virtually from PStream so that
// there is only 1 PStream object associated with classes using multiple inheritance.  The abstract function "write" must
// be overloaded by someone down the hierarchy in order for the POStream to work.  The class also provides some nice "<<"
// operators which will be inherited by all output streams.
class POStream	:	virtual	public	PStream
{
	struct POStreamData*	data;
protected:
	POStream() throw(PErr);
	
	// Support for overloaded writing of built in types (you don't have to overload these if writing pure binary data to your
	// stream is fine.)
	virtual	void	_write(char x) throw(PErr);
	virtual	void	_write(unsigned char x) throw(PErr);
	virtual	void	_write(signed char x) throw(PErr);
	virtual	void	_write(unsigned short x) throw(PErr);
	virtual	void	_write(signed short x) throw(PErr);
	virtual	void	_write(unsigned long x) throw(PErr);
	virtual	void	_write(signed long x) throw(PErr);
	virtual	void	_write(float x) throw(PErr);
	virtual	void	_write(double x) throw(PErr);
	virtual	void	_write(long double x) throw(PErr);
	virtual	void	_write(const char* x) throw(PErr);
public:
	virtual ~POStream();
	
	virtual	void	writeAsync(const char* src,unsigned long len) throw(PErr);		// This is a request to write asynchronously.  Default action is call write().
	virtual	void	write(const char* src,unsigned long len) throw(PErr) = 0;		// This is a promise to write synchronously.
	
			// Special support for flattening PStreamable objects onto a stream.
			POStream&	operator<<(const PStreamable& x) throw(PErr);
			
			// Support for writing built-in types to a stream.
			POStream&	operator<<(char x) throw(PErr);
			POStream&	operator<<(unsigned char x) throw(PErr);
			POStream&	operator<<(signed char x) throw(PErr);
			POStream&	operator<<(unsigned short x) throw(PErr);
			POStream&	operator<<(signed short x) throw(PErr);
			POStream&	operator<<(unsigned long x) throw(PErr);
			POStream&	operator<<(signed long x) throw(PErr);
			POStream&	operator<<(float x) throw(PErr);
			POStream&	operator<<(double x) throw(PErr);
			POStream&	operator<<(long double x) throw(PErr);
			POStream&	operator<<(const char* x) throw(PErr);
};

// The PIStream class is the base class for all output streams in Pandora.  It is derived virtually from PStream so that
// there is only 1 PStream object associated with classes using multiple inheritance.  The abstract function "read" must
// be overloaded by someone down the hierarchy in order for the PIStream to work.  The class also provides some nice ">>"
// operators which will be inherited by all output streams.
class PIStream	:	virtual	public	PStream
{
	struct PIStreamData*	data;
protected:
	PIStream() throw(PErr);
	
	// Support for overloaded reading of built in types (you don't have to overload these if your stream reads pure binary data.)
	virtual	void	_read(char& x) throw(PErr);
	virtual	void	_read(unsigned char& x) throw(PErr);
	virtual	void	_read(signed char& x) throw(PErr);
	virtual	void	_read(unsigned short& x) throw(PErr);
	virtual	void	_read(signed short& x) throw(PErr);
	virtual	void	_read(unsigned long& x) throw(PErr);
	virtual	void	_read(signed long& x) throw(PErr);
	virtual	void	_read(float& x) throw(PErr);
	virtual	void	_read(double& x) throw(PErr);
	virtual	void	_read(long double& x) throw(PErr);
	virtual	void	_read(char* x) throw(PErr);
public:
	virtual ~PIStream();
	
	virtual	void	readAsync(char* src,unsigned long len) throw(PErr);	// This is a request to read asynchronously.  Default action is to call read().
	virtual	void	read(char* src,unsigned long len) throw(PErr) = 0;		// This is a promise to read synchronously.
	
			// Special support for flattening PStreamable objects onto a stream.
			PIStream&	operator>>(PStreamable& x) throw(PErr);
			
			// Support for writing built-in types to a stream.
			PIStream&	operator>>(char& x) throw(PErr);
			PIStream&	operator>>(unsigned char& x) throw(PErr);
			PIStream&	operator>>(signed char& x) throw(PErr);
			PIStream&	operator>>(unsigned short& x) throw(PErr);
			PIStream&	operator>>(signed short& x) throw(PErr);
			PIStream&	operator>>(unsigned long& x) throw(PErr);
			PIStream&	operator>>(signed long& x) throw(PErr);
			PIStream&	operator>>(float& x) throw(PErr);
			PIStream&	operator>>(double& x) throw(PErr);
			PIStream&	operator>>(long double& x) throw(PErr);
			PIStream&	operator>>(char* x) throw(PErr);
	
	virtual	void			advance(unsigned long len) throw(PErr);	// Input streams can always be advanced.
};

// PIOStream is the base class for streams which are both readable and writeable
class PIOStream	:	virtual	public	PIStream,
					virtual	public	POStream
{
	struct PIOStreamData*	data;
protected:
	PIOStream() throw(PErr);
public:
	virtual ~PIOStream();
};

// PSeekableStream is the base class for streams which allow you to position where the next read/write
// will occur from.
class PSeekableStream	:	virtual	public	PStream
{
	struct PSeekableStreamData*	data;
protected:
	PSeekableStream() throw(PErr);
public:
	virtual ~PSeekableStream();
	
	virtual	unsigned long	getPos() const = 0;
	virtual	void			setPos(unsigned long pos) throw(PErr) = 0;
	virtual	unsigned long	getEOS() const = 0;
};

// PSeekableIStream is the base class for PIStreams which are seekable
class PSeekableIStream	:	virtual 	public	PSeekableStream,
						virtual	public	PIStream
{
	struct PSeekableIStreamData*	data;
protected:
	PSeekableIStream() throw(PErr);
public:
	virtual ~PSeekableIStream();
};

// PSeekableOStream is the base class for POStreams which are seekable
class PSeekableOStream	:	virtual	public	PSeekableStream,
						virtual	public	POStream
{
	struct PSeekableOStreamData*	data;
protected:
	PSeekableOStream() throw(PErr);
public:
	virtual ~PSeekableOStream();
};

// PSeekableIOStream is the base class for PIOStreams which are seekable
class PSeekableIOStream	:	virtual	public	PSeekableIStream,
						virtual	public	PSeekableOStream,
								public	PIOStream
{
	struct PSeekableIOStreamData*	data;
protected:
	PSeekableIOStream() throw(PErr);
public:
	virtual ~PSeekableIOStream();
};

// PPtrStream is the base class for stream buffers in memory
class PPtrStream	:	virtual	public	PSeekableStream
{
protected:
	struct PPtrStreamData*	data;
	
	PPtrStream() throw(PErr);	// "Fake"
	PPtrStream(char* buffer,unsigned long len) throw(PErr);
public:
	virtual ~PPtrStream();
	
	virtual	void			setPos(unsigned long pos) throw(PErr);
	virtual	unsigned long	getPos() const;
	virtual	unsigned long	getEOS() const;
};

// PPtrIStream is a seekable stream class which can access a buffer in memory
class PPtrIStream	:	virtual	public	PPtrStream,
					virtual	public	PSeekableIStream
{
	struct PPtrIStreamData*	data;
protected:
	PPtrIStream();	// "Fake"
public:
	PPtrIStream(char* buffer,unsigned long len,const char* name = nil) throw(PErr);
	virtual ~PPtrIStream();
	
	virtual	void	read(char* dst,unsigned long len) throw(PErr);
};

// PPtrOStream is a seekable stream class which can write to a buffer in memory
class PPtrOStream	:	virtual	public	PPtrStream,
					virtual	public	PSeekableOStream
{
	struct PPtrOStreamData*	data;
protected:
	PPtrOStream();	// "Fake"
public:
	PPtrOStream(char* buffer,unsigned long len,const char* name = nil) throw(PErr);
	virtual ~PPtrOStream();
	
	virtual	void	write(const char* src,unsigned long len) throw(PErr);
};

// PPtrIOStream is a seekable stream class which can read/write from a buffer in memory
class PPtrIOStream	:	virtual	public	PSeekableIOStream,
							public	PPtrIStream,
							public	PPtrOStream
{
	struct PPtrIOStreamData*	data;
public:
	PPtrIOStream(char* buffer,unsigned long len,const char* name = nil) throw(PErr);
	virtual ~PPtrIOStream();
};

// PTextIFilter reads text one line at a time from a given stream
#pragma warn_hidevirtual off
struct PTextIFilter	:	virtual	public	PIStream
{
	struct PTextIFilterData*	data;
	
	PTextIFilter(PIStream& stream,const char* name = nil);
	virtual ~PTextIFilter();
	
	virtual	void	read(char* dst,unsigned long len) throw(PErr);
	virtual				operator unsigned long();
	
protected:
	PTextIFilter();	// "Fake"
	virtual	void	_read(char* x) throw(PErr);
};

struct PTextOFilter	:	virtual	public	POStream
{
	struct PTextOFilterData*	data;
	
	PTextOFilter(POStream& stream,const char* name = nil);
	virtual ~PTextOFilter();
	
	virtual	void	write(const char* src,unsigned long len) throw(PErr);
	virtual				operator unsigned long();
	
protected:
	PTextOFilter();	// "Fake"
	virtual	void	_write(const char* x) throw(PErr);
};

struct PTextIOFilter	:	virtual public PTextIFilter,
					virtual public PTextOFilter
{
	struct PTextIOFilterData*	data;
	PTextIOFilter(PIOStream& stream,const char* name = nil) throw(PErr);
	virtual ~PTextIOFilter();
	virtual				operator unsigned long();
};

#pragma warn_hidevirtual reset

#else

#if WARNINCLUDETWICE
#error Included Pandora Streams.h twice!
#endif

#endif
