/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project.  All 
................................................ contributions are welcome. 
....Copyright(C).1995.Melvin.Smith.............. Enjoy. 
------------------------------------------------------------------------------
Melvin Smith (aka Fusion)         msmith@falcon.mercer.peachnet.edu 
MUD++ development mailing list    mudpp-list@spice.com
------------------------------------------------------------------------------
io.h
*/


// This is a quick hack to get around being dependant on iostream
// Not robust, etc.
// Basic 1 hour job.
// -Fusion

#ifndef _STREAM_H
#define _STREAM_H

#include "config.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>

#ifdef ultrix
// All ULTRIX I know have no prototypes for mmap(), munmap()
extern "C"
{
	caddr_t mmap( caddr_t, size_t, int, int, int, off_t );
	int munmap( caddr_t, size_t );
}
#endif

#define endl '\n'

#define CACHE_SIZE 1

#define STR_OPEN 1
#define STR_EOF  2
#define STR_NOTMAPPED 4  // This means mmap() failed and class had to allocate.

#ifndef MAP_FILE
#define MAP_FILE 0  // non BSD systems.
#endif

class Stream
{
	protected:
		int flags;
		int fd;
	public:
		Stream()
		:	flags(0), fd(0)
		{
		}

		Stream( int filedesc )
		:	flags( STR_OPEN ), fd( filedesc )
		{
		}

		virtual ~Stream()
		{
		}

		operator bool() { return (bool) flags & STR_OPEN; }
		virtual int open() = 0; 
		virtual int open( const char * ) = 0; 
		virtual void close() = 0; 
		virtual void flush() = 0; 
};



class OStream : public Stream
{
	private:
		char cache[ CACHE_SIZE ];
		char *ptr;
		char *highwater;
	public:
		OStream()
		:	Stream( STDOUT_FILENO ),
			ptr( cache ), highwater( cache + CACHE_SIZE )
		{
		}

		OStream( int filedesc )
		:	Stream( filedesc ),
			ptr( cache ), highwater( cache + CACHE_SIZE )
		{
		}

		OStream( const char * );
		virtual ~OStream();
		virtual OStream & operator << ( const char * );
		virtual OStream & operator << ( char * );
		virtual OStream & operator << ( int );
		virtual OStream & operator << ( long );
		virtual OStream & operator << ( unsigned long );
		virtual OStream & operator << ( char );
		virtual int open();
		virtual int open( const char * );
		virtual void close();
		virtual void flush();
};


// My implementation of the standard C++ 'cout'
extern OStream Cout;



class IStream : public Stream
{
	private:
		int line;
		char *ptr;
		char *cache;
		struct stat stats;

	public:
		IStream()
		: Stream(), line(1), ptr(0), cache(0)
		{
		}

		IStream( const char *fname );

		virtual ~IStream();

		long getLineNo() { return line; }
		long getLineNum() { return line; }
		IStream & operator >> ( char * );
		IStream & operator >> ( int );
		IStream & operator >> ( char & );
		IStream & operator >> ( unsigned long int );

		// incomplete methods
		virtual int open() { return -1; }
		virtual int open( const char * ) { return -1; }
		virtual void flush() {}

		operator bool()
		{
			if( ptr && *ptr )
				return true;
			return false;
		}

		bool eof()
		{
			if( ptr && *ptr )
				return false;
			return true;
		}

		void putback();
		char get( char &ch );
		char *getline( char *buf );
		void close();
};

#endif