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