/* ....[@@@..[@@@..............[@.................. 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@falcon.mercer.peachnet.edu MUD++ development mailing list mudpp-list@spice.com ------------------------------------------------------------------------------ io.cc */ // This is a quick hack to get around being dependant on iostream // Not robust, etc. // Basic one hour job. // -Melvin #include "io.h" // These are currently in string.cc const char * itoa( int ); const char * ltoa( unsigned long ); IStream::IStream( const char *fname ) : line(1), ptr(0), cache(0) { if( ( fd = ::open( fname, O_RDONLY ) ) < 0 ) { return; } // Get stats on the file (size is what we need) if( fstat( fd, &stats ) < 0 ) { return; } // Tell kernel to map this device to memory. If your mmap() // is failing then change the define below and it will skip to // allocator. #if(HAVE_MMAP) if( ( cache = (char *)mmap( 0, stats.st_size + 1, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0 ) ) == (caddr_t) -1) #endif { // If mmap fails or is not available then we use our own allocation // We lose performance like this but the class internals // will still use the whole buffer just like if we mmap() int tot = 0; int num; cache = new char[ stats.st_size + 1 ]; while( tot < stats.st_size ) { if( ( num = read( fd, (cache + tot), stats.st_size - tot ) ) == -1 ) { perror( "read" ); exit(0); } else if( ( tot += num ) == stats.st_size ) { break; } continue; } *( cache + stats.st_size ) = 0; flags |= STR_NOTMAPPED; } ::close( fd ); // We dont need it, its all in RAM now. flags |= STR_OPEN; ptr = cache; } IStream::~IStream() { if( cache ) { // See if the device was ever mapped or did we fall to // backup with new char[] and read() if( flags & STR_NOTMAPPED ) { delete [] cache; } else if( ( munmap( cache, stats.st_size ) ) < 0 ) { perror( "munmap" ); exit(0); } } } OStream Cout; OStream::OStream( const char * fname ) : Stream(), ptr( cache ), highwater( cache + CACHE_SIZE ) { fd = ::open( fname, O_WRONLY | O_CREAT | O_TRUNC, 0777 ); if( fd < 0 ) { // Add error handling later. exit(0); } flags |= STR_OPEN; } OStream::~OStream() { flush(); if( fd > 2 ) ::close( fd ); } OStream & OStream::operator << ( const char * x ) { if( ! x ) return *this; int len = strlen( x ); if( ( ptr + len ) < highwater ) { memcpy( ptr, x, len ); ptr += len; } else { write( fd, cache, (int)( ptr - cache ) ); ptr = cache; write( fd, x, strlen( x ) ); } return *this; } OStream & OStream::operator << ( char * x ) { return ( *this << (const char *)x ); } OStream & OStream::operator << ( int x ) { const char *p = itoa( x ); int len = strlen( p ); if( ( ptr + len ) < highwater ) { memcpy( ptr, p, len ); ptr += len; } else { write( fd, cache, (int)( ptr - cache ) ); ptr = cache; write( fd, p, len ); } return *this; } OStream & OStream::operator << ( long x ) { const char *p = ltoa( x ); int len = strlen( p ); if( ( ptr + len ) < highwater ) { memcpy( ptr, p, len ); ptr += len; } else { write( fd, cache, (int)( ptr - cache ) ); ptr = cache; write( fd, p, len ); } return *this; } OStream & OStream::operator << ( unsigned long x ) { const char *p = ltoa( x ); int len = strlen( p ); if( ( ptr + len ) < highwater ) { memcpy( ptr, p, len ); ptr += len; } else { write( fd, cache, (int)( ptr - cache ) ); ptr = cache; write( fd, p, len ); } return *this; } OStream & OStream::operator << ( char x ) { if( ptr < highwater ) { *ptr = x; ptr++; } else { // Using iovec may be nice here. write( fd, cache, CACHE_SIZE ); write( fd, &x, 1 ); ptr = cache; } return *this; } void OStream::flush() { if( ptr > cache ) { write( fd, cache, (int)( ptr - cache ) ); ptr = cache; } } int OStream::open() { return -1; } int OStream::open( const char * ) { return -1; } void OStream::close() { if( fd >= 0 ) ::close( fd ); fd = -1; } // IStream class implementation, memory mapped void IStream::close() { if( !cache ) return; if( ( munmap( cache, stats.st_size ) ) < 0 ) { perror( "munmap" ); exit(0); } cache = ptr = 0; } void IStream::putback() { if( cache ) if( ptr > cache ) { ptr--; if( *ptr == '\n' ) line--; } } char IStream::get( char & ch ) { if( cache ) { if( ( ch = *ptr ) ) { if( *ptr == '\n' ) line++; return *ptr++; } return *ptr; // EOF = 0 } ch = '\0'; return '\0'; } char * IStream::getline( char * buf ) { char *save = buf; if( cache ) { while( *ptr ) { *buf = *ptr; if( *ptr++ == '\n' ) { line++; *buf = '\0'; return save; } buf++; } *buf = '\0'; return save; } *buf = '\0'; return buf; }