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