diff options
| author | svn2git <svn2git@FreeBSD.org> | 1994-05-01 08:00:00 +0000 | 
|---|---|---|
| committer | svn2git <svn2git@FreeBSD.org> | 1994-05-01 08:00:00 +0000 | 
| commit | a16f65c7d117419bd266c28a1901ef129a337569 (patch) | |
| tree | 2626602f66dc3551e7a7c7bc9ad763c3bc7ab40a /gnu/lib/libg++/iostream/strstream.C | |
| parent | 8503f4f13f77abf7adc8f7e329c6f9c1d52b6a20 (diff) | |
Diffstat (limited to 'gnu/lib/libg++/iostream/strstream.C')
| -rw-r--r-- | gnu/lib/libg++/iostream/strstream.C | 237 | 
1 files changed, 237 insertions, 0 deletions
| diff --git a/gnu/lib/libg++/iostream/strstream.C b/gnu/lib/libg++/iostream/strstream.C new file mode 100644 index 000000000000..d5a57137d52c --- /dev/null +++ b/gnu/lib/libg++/iostream/strstream.C @@ -0,0 +1,237 @@ +//    This is part of the iostream library, providing input/output for C++. +//    Copyright (C) 1991 Per Bothner. +// +//    This library is free software; you can redistribute it and/or +//    modify it under the terms of the GNU Library General Public +//    License as published by the Free Software Foundation; either +//    version 2 of the License, or (at your option) any later version. +// +//    This library is distributed in the hope that it will be useful, +//    but WITHOUT ANY WARRANTY; without even the implied warranty of +//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +//    Library General Public License for more details. +// +//    You should have received a copy of the GNU Library General Public +//    License along with this library; if not, write to the Free +//    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "ioprivate.h" +#include <strstream.h> + +static void* default_alloc(_G_size_t size) +{ +    return (void*)new char[size]; +} + +static void default_free(void* ptr) +{ +    delete [] (char*)ptr; +} + +istrstream::istrstream(const char *cp, int n) +{ +    init(new strstreambuf(cp, n)); +} + +ostrstream::ostrstream() +{ +    init(new strstreambuf()); +} + +strstreambase::strstreambase(char *cp, int n, int mode) +{ +    char *pstart; +    if (mode == ios::app || mode == ios::ate) +	pstart = cp + strlen(cp); +    else +	pstart = cp; +    init(new strstreambuf(cp, n, pstart)); +} + +char *strstreambuf::str() +{ +    freeze(1); +    return base(); +} + +_G_size_t strstreambuf::pcount() +{ +    _G_size_t put_len = pptr() - pbase(); +    if (put_len < _len) put_len = _len; +    return put_len; +} + +int strstreambuf::overflow(int c /* = EOF */) +{ +  const int flush_only = c == EOF; +  if (_flags & _S_NO_WRITES) +      return flush_only ? 0 : EOF; +  size_t pos = pptr() - pbase(); +  size_t get_pos = gptr() - pbase(); +  if (pos > _len) _len = pos; +  if (pos >= blen() + flush_only) { +      char *new_buf; +      size_t new_size = 2 * blen(); +      if (frozen()) /* not allowed to enlarge */ +	  return EOF; +      new_buf = (char*)(*_allocate_buffer)(new_size); +      memcpy(new_buf, base(), blen()); +      if (new_buf == NULL) { +//	  __ferror(fp) = 1; +	  return EOF; +      } +#if 0 +      if (lenp == &_len) /* use '\0'-filling */ +	  memset(new_buf + pos, 0, blen() - pos); +#endif +      if (_base) { +	  (*_free_buffer)(_base); +	  _base = NULL; // So setb() won't try to delete _base. +      } +      setb(new_buf, new_buf + new_size, 1); +    } + +  setp(base(), ebuf()); +  pbump(pos); +  setg(base(), base() + get_pos, base() + _len); +  if (!flush_only) { +      *pptr() = (unsigned char) c; +      pbump(1); +  } +  return c; +} + +int strstreambuf::underflow() +{ +    size_t ppos = pptr() - pbase(); +    if (ppos > _len) _len = ppos; +    setg(base(), gptr(), base() + _len); +    if (gptr() < egptr()) +	return *gptr(); +    else +	return EOF; +} + + +void strstreambuf::init_dynamic(_alloc_type alloc, _free_type free, +				int initial_size) +				 +{ +    _len = 0; +    if (initial_size < 16) +	initial_size = 16; +    _allocate_buffer = alloc ? alloc : default_alloc; +    _free_buffer = free ? free : default_free; +    char * buf = (char*)(*_allocate_buffer)(initial_size); +    setb(buf, buf + initial_size, 1); +    setp(buf, buf + initial_size); +    setg(buf, buf, buf); +} + +void strstreambuf::init_static(char *ptr, int size, char *pstart) +{ +    if (size == 0) +	size = strlen(ptr); +    else if (size < 0) { +	// If size is negative 'the characters are assumed to +	// continue indefinitely.'  This is kind of messy ... +#if 1 +	size = 512; +	// Try increasing powers of 2, as long as we don't wrap around. +	// This can lose in pathological cases (ptr near the end +	// of the address space).  A better solution might be to +	// adjust the size on underflow/overflow.  FIXME. +	for (int s; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; ) +	    size = s; +	size = s; +#else +	// The following semi-portable kludge assumes that +	// sizeof(unsigned long) == sizeof(char*). Hence, +	// (unsigned long)(-1) should be the largest possible address. +	unsigned long highest = (unsigned long)(-1); +	// Pointers are signed on some brain-damaged systems, in +	// which case we divide by two to get the maximum signed address. +	if  ((char*)highest < ptr) +	    highest >>= 1; +	size = (char*)highest - ptr; +#endif +    } +    setb(ptr, ptr+size); +    if (pstart) { +	setp(ptr, ebuf()); +	pbump(pstart-ptr); +	setg(ptr, ptr, pstart); +    } +    else { +	setp(ptr, ptr);  +	setg(ptr, ptr, ebuf()); +    } +    _len = egptr() - ptr; +} + +void strstreambuf::init_static (const char *ptr, int size) +{ +  init_static((char*)ptr, size, NULL); +  xsetflags(_S_NO_WRITES); +} + +strstreambuf::~strstreambuf() +{ +    if (_base && !(_flags & _S_USER_BUF)) +        (_free_buffer)(_base); +    _base = NULL; +} + +streampos strstreambuf::seekoff(streamoff off, _seek_dir dir, +					int mode /*=ios::in|ios::out*/) +{ +    size_t cur_size = pcount(); +    streampos new_pos = EOF; + +    // Move the get pointer, if requested. +    if (mode & ios::in) { +	switch (dir) { +	  case ios::end: +	    off += cur_size; +	    break; +	  case ios::cur: +	    off += gptr() - pbase(); +	    break; +	  default: /*case ios::beg: */ +	    break; +	} +	if (off < 0 || (size_t)off > cur_size) +	    return EOF; +	setg(base(), base() + off, base() + cur_size); +	new_pos = off; +    } + +    // Move the put pointer, if requested. +    if (mode & ios::out) { +	switch (dir) { +	  case ios::end: +	    off += cur_size; +	    break; +	  case ios::cur: +	    off += pptr() - pbase(); +	    break; +	  default: /*case ios::beg: */ +	    break; +	} +	if (off < 0 || (size_t)off > cur_size) +	    return EOF; +	pbump(base() + off - pptr()); +	new_pos = off; +    } +    return new_pos; +} + +int strstreambuf::pbackfail(int c) +{ +    if ((_flags & _S_NO_WRITES) && c != EOF) +	return EOF; +    return backupbuf::pbackfail(c); +} | 
