/
mud++0.33/etc/
mud++0.33/etc/guilds/
mud++0.33/help/propert/
mud++0.33/mudC/
mud++0.33/player/
mud++0.33/src/
mud++0.33/src/bcppbuilder/
mud++0.33/src/unix/
mud++0.33/src/vm/
/*
....[@@@..[@@@..............[@.................. 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-list@mailhost.net
------------------------------------------------------------------------------
ionew.h
*/

#ifndef _IONEW_H
#define _IONEW_H

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

#ifndef HAVE_VSNPRINTF
#define vsnprintf( str, size, fmt, ap ) vsprintf(str, fmt, ap)
//#warning "do not have vsnsprintf"
#endif

#define TERM_CHAR '~'
#define endl '\n'

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() && isspace(*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();
};

#define OUTFILE_WRITE	1
#define OUTFILE_APPEND  2

// 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(int);
	
	public:
		OutputFile( int gfd )
		{
			strcpy(filename, "System descriptor" );
			fd = gfd;
			systemfd = true;
			active = true;
		}

		OutputFile( const char * name, int mode = OUTFILE_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;

/*
class OutputSocket : public Output 
	{
	// ? I'm not sure about that one
};
 */

#endif