aboutsummaryrefslogtreecommitdiff
path: root/gnu/lib/libg++/iostream/strstream.C
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/lib/libg++/iostream/strstream.C')
-rw-r--r--gnu/lib/libg++/iostream/strstream.C237
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);
+}