* sstream: Backport libstdc++-V3 sstream to V2.
authorMagnus Fromreide <magfr@lysator.liu.se>
Mon, 4 Dec 2000 17:03:27 +0000 (18:03 +0100)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 4 Dec 2000 17:03:27 +0000 (12:03 -0500)
From-SVN: r38000

libstdc++/ChangeLog
libstdc++/sstream

index 1b6aac0..1323c65 100644 (file)
@@ -1,3 +1,7 @@
+2000-11-24  Magnus Fromreide <magfr@lysator.liu.se>
+
+       * sstream: Backport libstdc++-V3 sstream to V2.
+
 2000-10-23  Gabriel Dos Reis  <gdr@codesourcery.com>
 
        * std/std_valarray.h (valarray::valarray): Use __valarray_copy,
index 714be71..45393b1 100644 (file)
-/* This is part of libio/iostream, providing -*- C++ -*- input/output.\r
-Copyright (C) 2000 Free Software Foundation\r
-\r
-This file is part of the GNU IO Library.  This library is free\r
-software; you can redistribute it and/or modify it under the\r
-terms of the GNU General Public License as published by the\r
-Free Software Foundation; either version 2, or (at your option)\r
-any later version.\r
-\r
-This library is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with this library; see the file COPYING.  If not, write to the Free\r
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
-\r
-As a special exception, if you link this library with files\r
-compiled with a GNU compiler to produce an executable, this does not cause\r
-the resulting executable to be covered by the GNU General Public License.\r
-This exception does not however invalidate any other reasons why\r
-the executable file might be covered by the GNU General Public License. */\r
-\r
-/* Written by Magnus Fromreide (magfr@lysator.liu.se). */\r
-\r
-#ifndef __SSTREAM__\r
-#define __SSTREAM__\r
-\r
-#include <string>\r
-#include <iostream.h>\r
-#include <streambuf.h>\r
-\r
-namespace std\r
-{\r
-  class stringbuf : public streambuf\r
-  {\r
-  public:\r
-    typedef char       char_type;\r
-    typedef int                int_type;\r
-    typedef streampos  pos_type;\r
-    typedef streamoff  off_type;\r
-\r
-    explicit stringbuf(int which=ios::in|ios::out) :\r
-      streambuf(which), buf(), mode(static_cast<ios::open_mode>(which)),\r
-      rpos(0), bufsize(1)\r
-    { }\r
-       \r
-    explicit stringbuf(const std::string &s, int which=ios::in|ios::out) :\r
-      streambuf(which), buf(s), mode(static_cast<ios::open_mode>(which)),\r
-      bufsize(1)\r
-    {\r
-      if(mode & ios::in)\r
-       {\r
-         setg(&defbuf, &defbuf + bufsize, &defbuf + bufsize);\r
-       }\r
-      if(mode & ios::out)\r
-       {\r
-         setp(&defbuf, &defbuf + bufsize);\r
-       }\r
-      rpos = (mode & ios::ate ? s.size() : 0);\r
-    }\r
-       \r
-    std::string str() const\r
-    {\r
-      const_cast<stringbuf*>(this)->sync();  // Sigh, really ugly hack\r
-      return buf;\r
-    };\r
-\r
-    void str(const std::string& s)\r
-    {\r
-      buf = s;\r
-      if(mode & ios::in)\r
-       {\r
-         gbump(egptr() - gptr());\r
-       }\r
-      if(mode & ios::out)\r
-       {\r
-         pbump(pbase() - pptr());\r
-       }\r
-      rpos = (mode & ios::ate ? s.size() : 0);\r
-    }\r
-\r
-  protected:\r
-    inline virtual int sync();\r
-    inline virtual int overflow(int = EOF);\r
-    inline virtual int underflow();\r
-  private:\r
-    std::string                        buf;\r
-    ios::open_mode             mode;\r
-    std::string::size_type     rpos;\r
-    streamsize                 bufsize;\r
-    char                       defbuf;\r
-  };\r
-\r
-  class stringstreambase : virtual public ios {\r
-  protected:\r
-    stringbuf __my_sb;\r
-  public:\r
-    std::string str() const\r
-    {\r
-      return dynamic_cast<stringbuf*>(_strbuf)->str();\r
-    }\r
-    void str(const std::string& s)\r
-    {\r
-      clear();\r
-      dynamic_cast<stringbuf*>(_strbuf)->str(s);\r
-    }\r
-       \r
-    stringbuf* rdbuf()\r
-    {\r
-      return &__my_sb;\r
-    }\r
-  protected:\r
-    stringstreambase(int which) :\r
-      __my_sb(which)\r
-    {\r
-      init (&__my_sb);\r
-    }\r
-       \r
-    stringstreambase(const std::string& s, int which) :\r
-      __my_sb(s, which)\r
-    {\r
-      init (&__my_sb);\r
-    }\r
-  };\r
-    \r
-  class istringstream : public stringstreambase, public istream {\r
-  public:\r
-    istringstream(int which=ios::in) :\r
-      stringstreambase(which)\r
-    { }\r
-       \r
-    istringstream(const std::string& s, int which=ios::in) :\r
-      stringstreambase(s, which)\r
-    { }\r
-  };\r
-    \r
-  class ostringstream : public stringstreambase, public ostream {\r
-  public:\r
-    ostringstream(int which=ios::out) :\r
-      stringstreambase(which)\r
-    { }\r
-       \r
-    ostringstream(const std::string& s, int which=ios::out) :\r
-      stringstreambase(s, which)\r
-    { }\r
-  };\r
-    \r
-  class stringstream : public stringstreambase, public iostream {\r
-  public:\r
-    stringstream(int which=ios::in|ios::out) :\r
-      stringstreambase(which)\r
-    { }\r
-    \r
-    stringstream(const std::string &s, int which=ios::in|ios::out) :\r
-      stringstreambase(s, which)\r
-    { }\r
-  };\r
-}\r
-\r
-inline int std::stringbuf::sync()\r
-{\r
-  if((mode & ios::out) == 0)\r
-    return EOF;\r
-\r
-  streamsize n = pptr() - pbase();\r
-  if(n)\r
-    {\r
-      buf.replace(rpos, std::string::npos, pbase(), n);\r
-      if(buf.size() - rpos != n)\r
-       return EOF;\r
-      rpos += n;\r
-      pbump(-n);\r
-      gbump(egptr() - gptr());\r
-    }\r
-  return 0;\r
-}\r
-\r
-inline int std::stringbuf::overflow(int ch)\r
-{\r
-  if((mode & ios::out) == 0)\r
-    return EOF;\r
-\r
-  streamsize n = pptr() - pbase();\r
-\r
-  if(n && sync())\r
-    return EOF;\r
-\r
-  if(ch != EOF)\r
-    {\r
-      std::string::size_type oldSize = buf.size();\r
-      \r
-      buf.replace(rpos, std::string::npos, ch);\r
-      if(buf.size() - oldSize != 1)\r
-       return EOF;\r
-      ++rpos;\r
-    }\r
-  return 0;\r
-}\r
-\r
-inline int std::stringbuf::underflow()\r
-{\r
-  sync();\r
-  if((mode & ios::in) == 0)\r
-    {\r
-      return EOF;\r
-    }\r
-  if(rpos >= buf.size())\r
-    {\r
-      return EOF;\r
-    }\r
-  \r
-  std::string::size_type n = egptr() - eback();\r
-  std::string::size_type s;\r
-\r
-  s = buf.copy(eback(), n, rpos);\r
-  pbump(pbase() - pptr());\r
-  gbump(eback() - gptr());\r
-  int res = (0377 & buf[rpos]);\r
-  rpos += s;\r
-  return res;\r
-}\r
-\r
-#endif /* not __STRSTREAM__ */\r
+/* This is part of libio/iostream, providing -*- C++ -*- input/output.
+Copyright (C) 2000 Free Software Foundation
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+/* Written by Magnus Fromreide (magfr@lysator.liu.se). */
+/* seekoff and ideas for overflow is largely borrowed from libstdc++-v3 */
+
+#ifndef __SSTREAM__
+#define __SSTREAM__
+
+#include <iostream.h>
+#include <streambuf.h>
+#include <string>
+
+namespace std
+{
+  class stringbuf : public streambuf
+  {
+  public:
+    typedef char       char_type;
+    typedef int                int_type;
+    typedef streampos  pos_type;
+    typedef streamoff  off_type;
+
+    explicit
+    stringbuf(int which=ios::in|ios::out)
+      : streambuf(), mode(static_cast<ios::open_mode>(which)),
+       stream(NULL), stream_len(0)
+    {
+      stringbuf_init();
+    }
+
+    explicit
+    stringbuf(const string &str, int which=ios::in|ios::out)
+      : streambuf(), mode(static_cast<ios::open_mode>(which)),
+       stream(NULL), stream_len(0)
+    {
+      if (mode & (ios::in|ios::out))
+       {
+         stream_len = str.size();
+         stream = new char_type[stream_len];
+         str.copy(stream, stream_len);
+       }
+      stringbuf_init();
+    }
+
+    virtual
+    ~stringbuf()
+    {
+      delete[] stream;
+    }
+
+    string
+    str() const
+    {
+      if (pbase() != 0)
+       return string(stream, pptr()-pbase());
+      else
+       return string();
+    }
+
+    void
+    str(const string& str)
+    {
+      delete[] stream;
+      stream_len = str.size();
+      stream = new char_type[stream_len];
+      str.copy(stream, stream_len);
+      stringbuf_init();
+    }
+
+  protected:
+    // The buffer is already in gptr, so if it ends then it is out of data.
+    virtual int
+    underflow()
+    {
+      return EOF;
+    }
+
+    virtual int
+    overflow(int c = EOF)
+    {
+      int res;
+      if (mode & ios::out)
+       {
+         if (c != EOF)
+           {
+             streamsize old_stream_len = stream_len;
+             stream_len += 1;
+             char_type* new_stream = new char_type[stream_len];
+             memcpy(new_stream, stream, old_stream_len);
+             delete[] stream;
+             stream = new_stream;
+             stringbuf_sync(gptr()-eback(), pptr()-pbase());
+             sputc(c);
+             res = c;
+           }
+         else
+           res = EOF;
+       }
+      else
+       res = 0;
+      return res;
+    }
+
+    virtual streambuf*
+    setbuf(char_type* s, streamsize n)
+    {
+      if (n != 0)
+       {
+         delete[] stream;
+         stream = new char_type[n];
+         memcpy(stream, s, n);
+         stream_len = n;
+         stringbuf_sync(0, 0);
+       }
+      return this;
+    }
+
+    virtual pos_type
+    seekoff(off_type off, ios::seek_dir way, int which = ios::in | ios::out)
+    {
+      pos_type ret =  pos_type(off_type(-1));
+      bool testin = which & ios::in && mode & ios::in;
+      bool testout = which & ios::out && mode & ios::out;
+      bool testboth = testin && testout && way != ios::cur;
+
+      if (stream_len && ((testin != testout) || testboth))
+       {
+         char_type* beg = stream;
+         char_type* curi = NULL;
+         char_type* curo = NULL;
+         char_type* endi = NULL;
+         char_type* endo = NULL;
+
+         if (testin)
+           {
+             curi = gptr();
+             endi = egptr();
+           }
+         if (testout)
+           {
+             curo = pptr();
+             endo = epptr();
+           }
+
+         off_type newoffi = 0;
+         off_type newoffo = 0;
+         if (way == ios::beg)
+           {
+             newoffi = beg - curi;
+             newoffo = beg - curo;
+           }
+         else if (way == ios::end)
+           {
+             newoffi = endi - curi;
+             newoffo = endo - curo;
+           }
+
+         if (testin && newoffi + off + curi - beg >= 0 &&
+             endi - beg >= newoffi + off + curi - beg)
+           {
+             gbump(newoffi + off);
+             ret = pos_type(newoffi + off + curi);
+           }
+         if (testout && newoffo + off + curo - beg >= 0 &&
+             endo - beg >= newoffo + off + curo - beg)
+           {
+             pbump(newoffo + off);
+             ret = pos_type(newoffo + off + curo);
+           }
+       }
+      return ret;
+    }
+
+    virtual pos_type
+    seekpos(pos_type sp, int which = ios::in | ios::out)
+    {
+      pos_type ret = seekoff(sp, ios::beg, which);
+      return ret;
+    }
+
+  private:
+    void
+    stringbuf_sync(streamsize i, streamsize o)
+    {
+      if (mode & ios::in)
+       setg(stream, stream + i, stream + stream_len);
+      if (mode & ios::out)
+       {
+         setp(stream, stream + stream_len);
+         pbump(o);
+       }
+    }
+    void
+    stringbuf_init()
+    {
+      if (mode & ios::ate)
+       stringbuf_sync(0, stream_len);
+      else
+       stringbuf_sync(0, 0);
+    }
+
+  private:
+    ios::open_mode     mode;
+    char_type*         stream;
+    streamsize         stream_len;
+  };
+\f
+  class istringstream : public istream {
+  public:
+    typedef char       char_type;
+    typedef int                int_type;
+    typedef streampos  pos_type;
+    typedef streamoff  off_type;
+
+    explicit
+    istringstream(int which=ios::in)
+      : istream(&sb), sb(which | ios::in)
+    { }
+
+    explicit
+    istringstream(const string& str, int which=ios::in)
+      : istream(&sb), sb(str, which | ios::in)
+    { }
+
+    stringbuf*
+    rdbuf() const
+    {
+      return const_cast<stringbuf*>(&sb);
+    }
+
+    string
+    str() const
+    {
+      return rdbuf()->str();
+    }
+    void
+    str(const string& s)
+    {
+      rdbuf()->str(s);
+    }
+  private:
+    stringbuf sb;
+  };
+\f
+  class ostringstream : public ostream {
+  public:
+    typedef char       char_type;
+    typedef int                int_type;
+    typedef streampos  pos_type;
+    typedef streamoff  off_type;
+
+    explicit
+    ostringstream(int which=ios::out)
+      : ostream(&sb), sb(which | ios::out)
+    { }
+
+    explicit
+    ostringstream(const string& str, int which=ios::out)
+      : ostream(&sb), sb(str, which | ios::out)
+    { }
+
+    stringbuf*
+    rdbuf() const
+    {
+      return const_cast<stringbuf*>(&sb);
+    }
+
+    string
+    str() const
+    {
+      return rdbuf()->str();
+    }
+
+    void str(const string& s)
+    {
+      rdbuf()->str(s);
+    }
+  private:
+    stringbuf sb;
+  };
+\f
+  class stringstream : public iostream {
+  public:
+    typedef char       char_type;
+    typedef int                int_type;
+    typedef streampos  pos_type;
+    typedef streamoff  off_type;
+
+    explicit
+    stringstream(int which=ios::out|ios::in)
+      : iostream(&sb), sb(which)
+    { }
+
+    explicit
+    stringstream(const string& str, int which=ios::out|ios::in)
+      : iostream(&sb), sb(str, which)
+    { }
+
+    stringbuf*
+    rdbuf() const
+    {
+      return const_cast<stringbuf*>(&sb);
+    }
+
+    string
+    str() const
+    {
+      return rdbuf()->str();
+    }
+
+    void
+    str(const string& s)
+    {
+      rdbuf()->str(s);
+    }
+  private:
+    stringbuf sb;
+  };
+};
+
+#endif /* not __STRSTREAM__ */