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