mud++0.35/etc/
mud++0.35/etc/guilds/
mud++0.35/help/propert/
mud++0.35/mudC/
mud++0.35/player/
mud++0.35/src/interface/
mud++0.35/src/os/cygwin32/
mud++0.35/src/os/win32/
mud++0.35/src/os/win32/bcppbuilder/
mud++0.35/src/osaddon/
mud++0.35/src/util/
/*
....[@@@..[@@@..............[@.................. 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@hom.net
MUD++ development mailing list    mudpp@van.ml.org
------------------------------------------------------------------------------
ionew.h
*/

#ifndef _IO_H
#define _IO_H

#include <stdarg.h>
#include <stdio.h>
#include <sys/stat.h>
#include "config.h"
#include "string.h"
#include "erratum.h"

#define TERM_CHAR '~'
#if defined(WIN32) || defined(__CYGWIN32__)
#define endl "\n\r"
#else
#define endl '\n'
#endif

class StaticInput
{
	protected:
			const char * cache;
			const char * ptr;
			const char * highwater;
			int line;

		// protected constructor to avoid direct instances
		StaticInput() :
			cache(0), ptr(0), highwater(0), line(1)
		{}

		virtual ~StaticInput() {}

	public:

		bool eof() const { return (ptr >= highwater); }
		int size() const { return (highwater - cache); }
		operator bool() { return (cache != 0); }
		
		char getch()
		{
			if ( eof() )
				return '\0';
			if ( *ptr =='\n' )
				line++;
			return *ptr++;
		}

		int getnum();
		float getfloat();
		unsigned long getlong();
		char * getword(char *);
		char * getstring(char *); 	// ~ delimited
		char * getCstring(char *);	// \0 delimited
		char * getline(char *);
		char * getsmartline(char *);	// may be extended by \ on the end
		void getbitfield( unsigned long *);
		void * read( void *, int ); // for reading structs directly

		void skipwhite() 
		{ 
			while( !eof() && isspace(*ptr) ) 
			{
				if ( *ptr == '\n' )
					line++;
				ptr++; 
			}
		}
		void skipblank() { while( !eof() && isblank(*ptr) ) ptr++; }
		void skipline();
		void putback() {ptr--; if(*ptr=='\n') line--;}

		void error( const char * );
		void errorf( const char *, ...);
		int getLineNo() { return line; }
		virtual const char * getName() { return "Unknown"; }
		const char * getBuf() { return cache; }

};

inline void StaticInput::skipline()
{
	char ch;
	while( !eof() )
	{
		ch = getch();
		if( ch == '\n' || ch == '\r' )
		{
			ch = getch();
			if( ch != '\n' && ch != '\r' )
				putback();
			line++;
			return;
		}		
	}
}

#define MAX_FILENAME 128

class InputFile : public StaticInput
{
	protected:
		char * tcache;
		char filename[MAX_FILENAME];
		int flags;
		struct stat stats;
	
	public:
		InputFile( const char * name )
		{
			flags = 0;
			strncpy(filename, name, MAX_FILENAME);
			open();
		}
		
		~InputFile()	{ close();}
		
		void open();	// all mmap mess goes into this implementation
		void close();			// and here goes unmap
		const char * getName() { return filename; }

};

class InputBuffer : public StaticInput
{
	protected:
		bool shared;

	public:
		InputBuffer( char * src, int size, bool copy = true )
		{
			if ( copy )
			{
				char * tmpcache;
				tmpcache = new char[size];
				memcpy( tmpcache, src, size );
				cache = tmpcache;
			}
			else
			{
				cache = src;
			}

			ptr = cache;
			highwater = cache + size;
			shared = !copy;
		}

		~InputBuffer()
		{
			if (!shared)
			{
				delete [] cache;
			}
		}
};

class InputString : public StaticInput
{
	protected:
		String data;

	public:
		InputString( String & src )
		{
			data = src;
			cache = data.chars();
			ptr = cache;
			highwater = cache + data.len();
		}

		~InputString() {}	// data string is deallocated automatically
};



#define BUFFERSIZE 4096

class Output
{
	protected:
		char buf[BUFFERSIZE];
		char * ptr;
		char * highwater;
		bool active;

		Output() :
			ptr(buf), highwater(&buf[BUFFERSIZE])
			{}

		virtual ~Output() {}

	public:
		
		virtual void flush() =0;
		virtual void largewrite( const void *, size_t ) =0;

		void write( const void *, size_t );
		void send( const char * src) { write(src, strlen(src)); }
		void sendCstring( const char * src ) { write( src, strlen(src)+1 ); } 
		void vsendf(const char * fmt, va_list args)
		{
			char buf[BUF*2];
			write( buf, vsnprintf( buf, BUF*2, fmt, args) );
		}
		void sendf( const char * fmt, ... )
		{
			va_list args;
			va_start(args, fmt );
			this->vsendf(fmt, args);
			va_end(args);
		}

		operator bool() { return active; }
				
		// all this << operator stuff for int, String etc
		// ...
		// using write(void *, int) which puts it into buffer, and if it
		// is filled flushes it

		Output & operator << ( const char * );
		Output & operator << ( char * x )
			{	return (*this) << (const char *)x;	}
		Output & operator << ( const String & str )
			{	return *(this) << str.chars(); }
		Output & operator << ( int );
		Output & operator << ( long );
		Output & operator << ( unsigned long );
		Output & operator << ( char );
		Output & operator << ( short int );
		Output & operator << ( unsigned short int );
		void putbitfield( const unsigned long *, int );

};

class OutputBuffer : public Output
{
	protected:
		char * data;
		int size;
		int usedsize;

	public:
		OutputBuffer( int s )
		{
			size = s;
			data = new char[size];
			usedsize = 0;
			active = true;
		}

		~OutputBuffer()
		{
			delete [] data;
		}

		void flush();	// memcopy buf to data, reset ptr, alloc more
						// larger data if needed
		void largewrite( const void *, size_t );

		const char * getData() { return data; };
		const char * getDataAsString();
};

enum OutputFileMode
{
	Write, Append
};

// Normal files are created with that mode by default
const int DEFAULT_FILE_MODE = 0644;

class OutputFile: public Output
{
	protected:
		char filename[MAX_FILENAME];
	  	int fd;
		bool systemfd;

		void open(OutputFileMode);
	
	public:
		OutputFile( int gfd )
		{
			strcpy(filename, "System descriptor" );
			fd = gfd;
			systemfd = true;
			active = true;
		}

		OutputFile( const char * name, OutputFileMode mode = Write )
		{
			systemfd = false;
			strncpy(filename, name, MAX_FILENAME);
			open(mode);
		}

		~OutputFile()
		{
			flush();
			close();
		}

		void flush();
		void largewrite( const void *, size_t );
		void close();

};

extern OutputFile Cout;

const int DEFAULT_INBUF_SIZE = 2048;

class DynamicInput
{
	protected:
		int size;
		char * startptr;
		char * getptr;
		char * eobptr;
		char * topptr;
		char * endptr;
		bool gotline;

		static const char emptyChar;

		DynamicInput() :
			size(DEFAULT_INBUF_SIZE), startptr( new char[size] ),
			getptr(startptr), eobptr(startptr), topptr(startptr),
			endptr(startptr+size), gotline(false)
		{}

		virtual ~DynamicInput()
		{
			if ( startptr )
				delete startptr;
		}

		bool scanForLine();

	public:
		bool lineAvailable() { return ( gotline || scanForLine()); }
		const char * getLine();
		void pull();
		void skipWhite()
		{
			while( getptr < topptr )
			{
				if ( !isspace(*getptr) )
					return;
				getptr++;
			}
			// no important data in buffer, reset
			getptr = topptr = eobptr = topptr = startptr;
		}


		virtual int read(char *, size_t) = 0;
		virtual bool active() const = 0;
};

#ifdef _SOCKET_H

class Socket;

class OutputSocket : public Output 
{
	protected:
		Socket * sock;

	public:

		OutputSocket( Socket * s ) :
			Output(), sock(s)
		{
			//if ( s )
			  //  s->addOwner();
		}

		~OutputSocket()
		{
			//if (sock )
			  //  sock->removeOwner();
		}

		void flush();
		void largewrite( const void *, size_t );
};

#if ( 0 )

class InputSocket : public DynamicInput
{
	protected:
		Socket * sock;

	public:
		InputSocket( Socket * s ) :
			DynamicInput(), sock(s)
		{
			//if ( s )
			  //  s->addOwner();
		}

		~InputSocket()
		{
			//if (sock )
			  //  sock->removeOwner();
		}

		int read(char *, size_t);
		bool active();
};

#endif // 0

#endif // _SOCKET_H

#endif