/* ....[@@@..[@@@..............[@.................. 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