home *** CD-ROM | disk | FTP | other *** search
- /***
- *strstream.cpp - definitions for strstreambuf, strstream
- *
- * Copyright (c) 1991-1997, Microsoft Corporation. All rights reserved.
- *
- *Purpose:
- * This file defines the functions used by strstream and strstrembuf
- * classes.
- *
- *******************************************************************************/
-
- #include <cruntime.h>
- #include <internal.h>
- #include <stdlib.h>
- #include <string.h>
- #include <strstrea.h>
- #include <dbgint.h>
- #pragma hdrstop
-
- /***
- *strstreambuf::strstreambuf() - default constructor for strstreambuf
- *
- *Purpose:
- * Default constructor for class strstreambuf.
- *
- *Entry:
- *
- *Exit:
- *
- *Exceptions:
- *
- *******************************************************************************/
- strstreambuf::strstreambuf()
- : streambuf()
- {
- x_bufmin = x_dynamic = 1;
- x_static = 0;
- x_alloc = (0);
- x_free = (0);
- }
-
- /***
- *strstreambuf::strstreambuf(int n) - constructor for strstreambuf
- *
- *Purpose:
- * Constructor for class strstreambuf. Created in dynamic mode.
- *
- *Entry:
- * n = minimum size for initial allocation.
- *
- *Exit:
- *
- *Exceptions:
- *
- *******************************************************************************/
- strstreambuf::strstreambuf(int n)
- : streambuf()
- {
- x_dynamic = 1;
- x_static = 0;
- x_alloc = (0);
- x_free = (0);
- setbuf(0,n);
- }
-
- /***
- *strstreambuf::strstreambuf(void* (*_a)(long), void (*_f)(void*)) - constructor for strstreambuf
- *
- *Purpose:
- * Construct a strstreambuf in dynamic mode. Use specified allocator
- * and deallocator instead of new and delete.
- *
- *Entry:
- * *_a = allocator: void * (*_a)(long)
- * *_f = deallocator: void (*_f)(void *)
- *
- *Exit:
- *
- *Exceptions:
- *
- *******************************************************************************/
- strstreambuf::strstreambuf(void* (*_a)(long), void (*_f)(void*))
- : streambuf()
- {
- x_dynamic = x_bufmin = 1;
- x_static = 0;
- x_alloc = _a;
- x_free = _f;
- }
-
- /***
- *strstreambuf::strstreambuf(unsigned char * ptr, int size, unsigned char * pstart = 0)
- *strstreambuf::strstreambuf(char * ptr, int size, char * pstart = 0) -
- *
- *Purpose:
- * Construct a strstreambuf in static mode. Buffer used is of 'size'
- * bytes. If 'size' is 0, uses a null-terminated string as buffer.
- * If negative, size is considered infinite. Get starts at ptr.
- * If pstart!=0, put buffer starts at pstart. Otherwise, no output.
- *
- *Entry:
- * [unsigned] char * ptr; pointer to buffer base()
- * int size; size of buffer, or 0= use strlen to calculate size
- * or if negative size is 'infinite'.
- * [unsigned] char * pstart; pointer to put buffer of NULL if none.
- *
- *Exit:
- *
- *Exceptions:
- *
- *******************************************************************************/
- strstreambuf::strstreambuf(unsigned char * ptr, int size, unsigned char * pstart)
- : streambuf()
- {
- strstreambuf((char *)ptr, size, (char *)pstart);
- }
-
- strstreambuf::strstreambuf(char * ptr, int size, char * pstart)
- : streambuf()
- {
- x_static = 1;
- x_dynamic = 0;
- char * pend;
-
- if (!size)
- pend = ptr + strlen(ptr);
- else if (size < 0)
- {
- pend = (char*)-1L;
- }
- else
- pend = ptr + size;
-
- setb(ptr, pend,0);
- if (pstart)
- {
- setg(ptr,ptr,pstart);
- setp(pstart, pend);
- }
- else
- {
- setg(ptr,ptr,pend);
- setp(0, 0);
- }
- }
-
- strstreambuf::~strstreambuf()
- {
- if ((x_dynamic) && (base()))
- {
- if (x_free)
- {
- (*x_free)(base());
- }
- else
- {
- delete base();
- }
- }
- }
-
- void strstreambuf::freeze(int n)
- {
- if (!x_static)
- {
- x_dynamic = (!n);
- #ifdef _DEBUG
- if (n)
- _CrtSetDbgBlockType(base(), _NORMAL_BLOCK);
- else
- _CrtSetDbgBlockType(base(), _CRT_BLOCK);
- #endif /* _DEBUG */
- }
- }
-
- char * strstreambuf::str()
- {
- x_dynamic = 0; // freeze();
-
- #ifdef _DEBUG
- if (!x_static)
- _CrtSetDbgBlockType(base(), _NORMAL_BLOCK);
- #endif /* _DEBUG */
-
- return base();
- }
-
- int strstreambuf::doallocate()
- {
- char * bptr;
- int size;
- size = __max(x_bufmin,blen() + __max(x_bufmin,1));
- long offset = 0;
-
- if (x_alloc)
- {
- bptr = (char*)(*x_alloc)(size);
- }
- else
- {
- bptr = _new_crt char[size];
- }
- if (!bptr)
- return EOF;
-
- if (blen())
- {
- memcpy(bptr, base(), blen());
- offset = bptr - base(); // amount to adjust pointers by
- }
- if (x_free)
- {
- (*x_free)(base());
- }
- else
- {
- delete base();
- }
- setb(bptr,bptr+size,0); // we handle deallocation
-
- // adjust get/put pointers too, if necessary
- if (offset)
- if (egptr())
- {
- setg(eback()+offset,gptr()+offset,egptr()+offset);
- }
- if (epptr())
- {
- size = pptr() - pbase();
- setp(pbase()+offset,epptr()+offset);
- pbump(size);
- }
- return(1);
- }
-
- streambuf * strstreambuf::setbuf( char *, int l)
- {
- if (l)
- x_bufmin = l;
- return this;
- }
-
- int strstreambuf::overflow(int c)
- {
- /*
- - if no room and not dynamic, give error
- - if no room and dynamic, allocate (1 more or min) and store
- - if and when the buffer has room, store c if not EOF
- */
- int temp;
- if (pptr() >= epptr())
- {
- if (!x_dynamic)
- return EOF;
-
- if (strstreambuf::doallocate()==EOF)
- return EOF;
-
- if (!epptr()) // init if first time through
- {
- setp(base() + (egptr() - eback()),ebuf());
- }
- else
- {
- temp = pptr()-pbase();
- setp(pbase(),ebuf());
- pbump(temp);
- }
- }
-
- if (c!=EOF)
- {
- *pptr() = (char)c;
- pbump(1);
- }
- return(1);
- }
-
- int strstreambuf::underflow()
- {
- char * tptr;
- if (gptr() >= egptr())
- {
- // try to grow get area if we can...
- if (egptr()<pptr())
- {
- tptr = base() + (gptr()-eback());
- setg(base(),tptr,pptr());
- }
- if (gptr() >= egptr())
- return EOF;
- }
-
- return (int)(unsigned char) *gptr();
- }
-
- int strstreambuf::sync()
- {
- // a strstreambuf is always in sync, by definition!
- return 0;
- }
-
- streampos strstreambuf::seekoff(streamoff off, ios::seek_dir dir, int mode)
- {
- char * tptr;
- long offset = EOF; // default return value
- if (mode & ios::in)
- {
- strstreambuf::underflow(); // makes sure entire buffer available
- switch (dir) {
- case ios::beg :
- tptr = eback();
- break;
- case ios::cur :
- tptr = gptr();
- break;
- case ios::end :
- tptr = egptr();
- break;
- default:
- return EOF;
- }
- tptr += off;
- offset = tptr - eback();
- if ((tptr < eback()) || (tptr > egptr()))
- {
- return EOF;
- }
- gbump(tptr-gptr());
- }
- if (mode & ios::out)
- {
- if (!epptr())
- {
- if (strstreambuf::overflow(EOF)==EOF) // make sure there's a put buffer
- return EOF;
- }
- switch (dir) {
- case ios::beg :
- tptr = pbase();
- break;
- case ios::cur :
- tptr = pptr();
- break;
- case ios::end :
- tptr = epptr();
- break;
- default:
- return EOF;
- }
- tptr += off;
- offset = tptr - pbase();
- if (tptr < pbase())
- return EOF;
- if (tptr > epptr())
- {
- if (x_dynamic)
- {
- x_bufmin = __max(x_bufmin, (tptr-pbase()));
- if (strstreambuf::doallocate()==EOF)
- return EOF;
- }
- else
- return EOF;
- }
- pbump(tptr-pptr());
- }
- return offset; // note: if both in and out set, returns out offset
- }
-
-
- istrstream::istrstream(char * pszStr)
- : istream(_new_crt strstreambuf(pszStr,0))
- {
- delbuf(1);
- }
-
- istrstream::istrstream(char * pStr, int len)
- : istream(_new_crt strstreambuf(pStr,len))
- {
- delbuf(1);
- }
-
- istrstream::~istrstream()
- {
- }
-
- ostrstream::ostrstream()
- : ostream(_new_crt strstreambuf)
- {
- delbuf(1);
- }
-
- ostrstream::ostrstream(char * str, int size, int mode)
- : ostream(_new_crt strstreambuf(str,size,str))
- {
- delbuf(1);
- if (mode & (ios::app|ios::ate))
- seekp(strlen(str),ios::beg);
- }
-
- ostrstream::~ostrstream()
- {
- }
-
- strstream::strstream()
- : iostream(_new_crt strstreambuf)
- {
- istream::delbuf(1);
- ostream::delbuf(1);
- }
-
- strstream::strstream(char * str, int size, int mode)
- : iostream(_new_crt strstreambuf(str,size,str))
- {
- istream::delbuf(1);
- ostream::delbuf(1);
- if ((mode & ostream::out) && (mode & (ostream::app|ostream::ate)))
- seekp(strlen(str),ostream::beg);
- // rdbuf()->setg(rdbuf()->base(),rdbuf()->base(),rdbuf()->ebuf());
- }
-
- strstream::~strstream()
- {
- }
-