-/* 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__ */