/*** *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 #include #include #include #include #include #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()= 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() { }