home *** CD-ROM | disk | FTP | other *** search
- /*-----------------------------------------------------------------------*
- * filename - strstrea.cpp
- * Class strstrea member functions
- *-----------------------------------------------------------------------*/
-
- /*[]------------------------------------------------------------[]*/
- /*| |*/
- /*| Turbo C++ Run Time Library - Version 1.0 |*/
- /*| |*/
- /*| |*/
- /*| Copyright (c) 1990 by Borland International |*/
- /*| All Rights Reserved. |*/
- /*| |*/
- /*[]------------------------------------------------------------[]*/
-
- #include <strstrea.h>
- #include <string.h>
- #include <limits.h>
-
-
-
- // minimum string size
- const int min_str_alloc = 16;
-
- // minimum string increment when extending
- const int min_str_incr = 4;
-
- // to improve legibility
- #define expandable ((ssbflags&(dynamic|frozen))==dynamic)
-
-
- strstreambuf::strstreambuf()
- {
- allocf = 0;
- freef = 0;
- ssbflags = dynamic;
- }
-
-
- strstreambuf::strstreambuf(void* (*a)(long), void (*f)(void*))
- {
- allocf = a;
- freef = f;
- ssbflags = dynamic;
- }
-
-
- strstreambuf::strstreambuf(int n)
- {
- if( n < min_str_alloc )
- n = min_str_alloc;
- char *p = new char[n];
- setb(p, p+n, 0);
- *p = 0;
- allocf = 0;
- freef = 0;
- ssbflags = dynamic;
- }
-
-
- /*
- If n is negative, the provided buffer is supposed to be unlimited.
- As a practical way to handle this, the buffer is arbitrarily defined
- to be size INT_MAX. (It really should be the max value supported by
- type size_t, but AT&T defined all sizes to be int.)
- */
- void strstreambuf::init(signed char* ptr, int n, signed char* pstart)
- {
- ssbflags = 0;
- if( n == 0 ) n = strlen((char*)ptr);
- else if( n < 0 ) {
- n = INT_MAX;
- ssbflags |= unlimited; // distinguish it from merely large
- }
- setb((char*)ptr, (char*)ptr+n, 0);
- if( pstart ) {
- setp((char*)pstart, ebuf());
- setg((char*)ptr, (char*)ptr, (char*)pstart);
- }
- else
- setg((char*)ptr, (char*)ptr, (char*)ebuf());
-
- allocf = 0;
- freef = 0;
- }
-
-
- strstreambuf::strstreambuf(signed char* ptr, int n, signed char* pstart)
- {
- init(ptr, n, pstart);
- }
-
-
- strstreambuf::strstreambuf(unsigned char* ptr, int n, unsigned char* pstart)
- {
- init((signed char*)ptr, n, (signed char*)pstart);
- }
-
-
- strstreambuf::~strstreambuf()
- {
- if( expandable )
- if( freef )
- (*freef)((void*)base());
- else
- delete base();
- }
-
-
- void strstreambuf::freeze(int n)
- {
- if( ssbflags & dynamic )
- if( n )
- ssbflags |= frozen;
- else
- ssbflags &= ~frozen;
- }
-
-
- char* strstreambuf::str()
- {
- freeze(1);
- return base();
- }
-
-
- int strstreambuf::doallocate()
- {
- int size = next_alloc ? next_alloc : min_str_alloc;
- char *p;
- if( allocf )
- p = (char*)(*allocf)((long)size);
- else
- p = new char[size];
- if( ! p )
- return EOF;
-
- next_alloc = 0; // assume next_alloc increment is one time only
- setb(p, p + size, 0);
- *p = 0;
- return 1;
- }
-
-
- int strstreambuf::overflow(int c)
- {
- if( expandable ) {
- // allocate put area as needed
- if( ! base() )
- doallocate();
- if( ! pbase() )
- setp(base(), ebuf());
- }
- if( pbase() ) {
- if( (pptr() >= epptr()) && expandable ) {
- // expand the reserve area
- char *oldp = base(); // old buf
- int len = blen(); // length of old buf
- char *p = new char[len + min_str_incr]; // new buf
- if( ! p )
- return EOF; // out of memory
-
- memcpy(p, oldp, len); // copy data to new buf
- // get relative pointer data
- int ebloc, gloc, egloc; // get area pointer data
- int ploc = (int)(pptr() - oldp); // put area pointer data
- int get_area = (gptr() != 0);
- if( get_area ) {
- ebloc = (int)(eback() - oldp); // eback location
- gloc = (int)(gptr() - oldp); // gptr location
- egloc = (int)(egptr() - oldp); // egptr location
- }
- // set up new pointers
- setb(p, p + len + min_str_incr, 0);
- setp(p, ebuf()); // the put area goes to end of buf
- pbump(ploc);
- if( get_area )
- setg(p + ebloc, p + gloc, p + egloc);
- }
- if( pptr() < epptr() )
- return sputc(c); // now there is room in the put area
- }
-
- return EOF; // could not make more space
- }
-
-
- int strstreambuf::underflow()
- {
- if( egptr() > gptr() )
- return (unsigned char) *gptr();
-
- if( base() && ! unbuffered() && pptr() > pbase() ) {
- if( ! gptr() || gptr() < pbase() ) {
- // initialize get area to current put area
- setg(base(), pbase(), pptr());
- return (unsigned char) *gptr();
- }
- if( gptr() < pptr() ) {
- // extend get area to match put area
- setg(eback(), gptr(), pptr());
- return (unsigned char) *gptr();
- }
- // else no more chars
- }
-
- return EOF;
- }
-
-
- streambuf* strstreambuf::setbuf(char* p, int n)
- {
- if( p )
- return 0; // can't honor this kind of request
-
- if( n > min_str_incr )
- next_alloc = n; // next alloc will be this many
- return this;
- }
-
-
- // we assume streampos and streamoff are type int or long
- streampos strstreambuf::seekoff(streamoff off, seek_dir dir, int omode)
- {
- streamoff pos = EOF; // result
-
- // find position if from beginning or end
- if( dir == ios::end ) {
- if( (ssbflags & unlimited) || off > 0 )
- pos = -1; // can't do it
- else
- pos = blen() + off;
- }
- else if( dir == ios::beg )
- pos = off;
-
- if( omode & ios::in ) {
- // set up get area
- if( dir == ios::cur ) {
- // find a reasonable value for current position
- if( gptr() ) pos = streamoff(gptr() - base()) + off;
- else if( pptr() ) pos = streamoff(pptr() - base()) + off;
- else pos = off;
- }
- if( pos < 0 || blen() < pos )
- pos = EOF; // illegal request
- else {
- #pragma warn -sig
- char* g = base() + pos;
- #pragma warn .sig
- char* eb = (eback() && eback() < g) ? eback() : g;
- char* eg = (egptr() && g < egptr()) ? egptr() : g;
- setg(eb, g, eg);
- }
- }
- if( omode & ios::out ) {
- // set up put area
- if( dir == ios::cur ) {
- // find a reasonable value for current position
- if( pptr() ) pos = streamoff(pptr() - base()) + off;
- else if( gptr() ) pos = streamoff(gptr() - base()) + off;
- else pos = off;
- }
- if( pos < 0 || blen() < pos )
- pos = EOF; // illegal request
- else {
- #pragma warn -sig
- char* p = base() + pos;
- #pragma warn .sig
- char* ep = (epptr() && p < epptr()) ? epptr() : ebuf();
- setp(p, ep);
- }
- }
- return streampos(pos);
- }
-
-
-
- strstreambase::strstreambase(char* ptr, int n, char* pstart) :
- buf(ptr, n, pstart)
- {
- ios::init(&this->buf);
- }
-
-
- strstreambase::strstreambase() :
- buf()
- {
- ios::init(&this->buf);
- }
-
-
- strstreambase::~strstreambase()
- {
- }
-
-
-
- istrstream::istrstream(char* str) :
- strstreambase(str, 0, 0),
- istream(strstreambase::rdbuf())
- {
- }
-
-
- istrstream::istrstream(char* str, int len) :
- strstreambase(str, len, 0),
- istream(strstreambase::rdbuf())
- {
- }
-
-
- istrstream::~istrstream()
- {
- }
-
-
-
- ostrstream::ostrstream(char* str, int len, int omode) :
- strstreambase(str, len, str),
- ostream(strstreambase::rdbuf())
- {
- if( omode & (ios::ate | ios::app) )
- strstreambase::rdbuf()->seekoff(strlen(str), ios::beg, ios::out);
- }
-
-
- ostrstream::ostrstream() :
- strstreambase(),
- ostream(strstreambase::rdbuf())
- {
- }
-
-
- ostrstream::~ostrstream()
- {
- }
-
-
-
- strstream::strstream() :
- strstreambase(),
- iostream(strstreambase::rdbuf())
- {
- }
-
-
- strstream::strstream(char* str, int size, int omode) :
- strstreambase(str, size, str),
- iostream(strstreambase::rdbuf())
- {
- if( omode & (ios::ate | ios::app) )
- strstreambase::rdbuf()->seekoff(strlen(str), ios::beg, ios::out);
- }
-
-
- strstream::~strstream()
- {
- }
-