1 /* This is part of libio/iostream, providing -*- C++ -*- input/output. 2 Copyright (C) 2000 Free Software Foundation 3 4 This file is part of the GNU IO Library. This library is free 5 software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the 7 Free Software Foundation; either version 2, or (at your option) 8 any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this library; see the file COPYING. If not, write to the Free 17 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 As a special exception, if you link this library with files 20 compiled with a GNU compiler to produce an executable, this does not cause 21 the resulting executable to be covered by the GNU General Public License. 22 This exception does not however invalidate any other reasons why 23 the executable file might be covered by the GNU General Public License. */ 24 25 /* Written by Magnus Fromreide (magfr (at) lysator.liu.se). */ 26 /* seekoff and ideas for overflow is largely borrowed from libstdc++-v3 */ 27 28 #ifndef __SSTREAM__ 29 #define __SSTREAM__ 30 31 #include <iostream.h> 32 #include <streambuf.h> 33 #include <string> 34 35 namespace std 36 { 37 class stringbuf : public streambuf 38 { 39 public: 40 typedef char char_type; 41 typedef int int_type; 42 typedef streampos pos_type; 43 typedef streamoff off_type; 44 45 explicit 46 stringbuf(int which=ios::in|ios::out) 47 : streambuf(), mode(static_cast<ios::open_mode>(which)), 48 stream(NULL), stream_len(0) 49 { 50 stringbuf_init(); 51 } 52 53 explicit 54 stringbuf(const string &str, int which=ios::in|ios::out) 55 : streambuf(), mode(static_cast<ios::open_mode>(which)), 56 stream(NULL), stream_len(0) 57 { 58 if (mode & (ios::in|ios::out)) 59 { 60 stream_len = str.size(); 61 stream = new char_type[stream_len]; 62 str.copy(stream, stream_len); 63 } 64 stringbuf_init(); 65 } 66 67 virtual 68 ~stringbuf() 69 { 70 delete[] stream; 71 } 72 73 string 74 str() const 75 { 76 if (pbase() != 0) 77 return string(stream, pptr()-pbase()); 78 else 79 return string(); 80 } 81 82 void 83 str(const string& str) 84 { 85 delete[] stream; 86 stream_len = str.size(); 87 stream = new char_type[stream_len]; 88 str.copy(stream, stream_len); 89 stringbuf_init(); 90 } 91 92 protected: 93 // The buffer is already in gptr, so if it ends then it is out of data. 94 virtual int 95 underflow() 96 { 97 return EOF; 98 } 99 100 virtual int 101 overflow(int c = EOF) 102 { 103 int res; 104 if (mode & ios::out) 105 { 106 if (c != EOF) 107 { 108 streamsize old_stream_len = stream_len; 109 stream_len += 1; 110 char_type* new_stream = new char_type[stream_len]; 111 memcpy(new_stream, stream, old_stream_len); 112 delete[] stream; 113 stream = new_stream; 114 stringbuf_sync(gptr()-eback(), pptr()-pbase()); 115 sputc(c); 116 res = c; 117 } 118 else 119 res = EOF; 120 } 121 else 122 res = 0; 123 return res; 124 } 125 126 virtual streambuf* 127 setbuf(char_type* s, streamsize n) 128 { 129 if (n != 0) 130 { 131 delete[] stream; 132 stream = new char_type[n]; 133 memcpy(stream, s, n); 134 stream_len = n; 135 stringbuf_sync(0, 0); 136 } 137 return this; 138 } 139 140 virtual pos_type 141 seekoff(off_type off, ios::seek_dir way, int which = ios::in | ios::out) 142 { 143 pos_type ret = pos_type(off_type(-1)); 144 bool testin = which & ios::in && mode & ios::in; 145 bool testout = which & ios::out && mode & ios::out; 146 bool testboth = testin && testout && way != ios::cur; 147 148 if (stream_len && ((testin != testout) || testboth)) 149 { 150 char_type* beg = stream; 151 char_type* curi = NULL; 152 char_type* curo = NULL; 153 char_type* endi = NULL; 154 char_type* endo = NULL; 155 156 if (testin) 157 { 158 curi = gptr(); 159 endi = egptr(); 160 } 161 if (testout) 162 { 163 curo = pptr(); 164 endo = epptr(); 165 } 166 167 off_type newoffi = 0; 168 off_type newoffo = 0; 169 if (way == ios::beg) 170 { 171 newoffi = beg - curi; 172 newoffo = beg - curo; 173 } 174 else if (way == ios::end) 175 { 176 newoffi = endi - curi; 177 newoffo = endo - curo; 178 } 179 180 if (testin && newoffi + off + curi - beg >= 0 && 181 endi - beg >= newoffi + off + curi - beg) 182 { 183 gbump(newoffi + off); 184 ret = pos_type(newoffi + off + curi); 185 } 186 if (testout && newoffo + off + curo - beg >= 0 && 187 endo - beg >= newoffo + off + curo - beg) 188 { 189 pbump(newoffo + off); 190 ret = pos_type(newoffo + off + curo); 191 } 192 } 193 return ret; 194 } 195 196 virtual pos_type 197 seekpos(pos_type sp, int which = ios::in | ios::out) 198 { 199 pos_type ret = seekoff(sp, ios::beg, which); 200 return ret; 201 } 202 203 private: 204 void 205 stringbuf_sync(streamsize i, streamsize o) 206 { 207 if (mode & ios::in) 208 setg(stream, stream + i, stream + stream_len); 209 if (mode & ios::out) 210 { 211 setp(stream, stream + stream_len); 212 pbump(o); 213 } 214 } 215 void 216 stringbuf_init() 217 { 218 if (mode & ios::ate) 219 stringbuf_sync(0, stream_len); 220 else 221 stringbuf_sync(0, 0); 222 } 223 224 private: 225 ios::open_mode mode; 226 char_type* stream; 227 streamsize stream_len; 228 }; 229 230 class istringstream : public istream { 232 public: 233 typedef char char_type; 234 typedef int int_type; 235 typedef streampos pos_type; 236 typedef streamoff off_type; 237 238 explicit 239 istringstream(int which=ios::in) 240 : istream(&sb), sb(which | ios::in) 241 { } 242 243 explicit 244 istringstream(const string& str, int which=ios::in) 245 : istream(&sb), sb(str, which | ios::in) 246 { } 247 248 stringbuf* 249 rdbuf() const 250 { 251 return const_cast<stringbuf*>(&sb); 252 } 253 254 string 255 str() const 256 { 257 return rdbuf()->str(); 258 } 259 void 260 str(const string& s) 261 { 262 rdbuf()->str(s); 263 } 264 private: 265 stringbuf sb; 266 }; 267 268 class ostringstream : public ostream { 270 public: 271 typedef char char_type; 272 typedef int int_type; 273 typedef streampos pos_type; 274 typedef streamoff off_type; 275 276 explicit 277 ostringstream(int which=ios::out) 278 : ostream(&sb), sb(which | ios::out) 279 { } 280 281 explicit 282 ostringstream(const string& str, int which=ios::out) 283 : ostream(&sb), sb(str, which | ios::out) 284 { } 285 286 stringbuf* 287 rdbuf() const 288 { 289 return const_cast<stringbuf*>(&sb); 290 } 291 292 string 293 str() const 294 { 295 return rdbuf()->str(); 296 } 297 298 void str(const string& s) 299 { 300 rdbuf()->str(s); 301 } 302 private: 303 stringbuf sb; 304 }; 305 306 class stringstream : public iostream { 308 public: 309 typedef char char_type; 310 typedef int int_type; 311 typedef streampos pos_type; 312 typedef streamoff off_type; 313 314 explicit 315 stringstream(int which=ios::out|ios::in) 316 : iostream(&sb), sb(which) 317 { } 318 319 explicit 320 stringstream(const string& str, int which=ios::out|ios::in) 321 : iostream(&sb), sb(str, which) 322 { } 323 324 stringbuf* 325 rdbuf() const 326 { 327 return const_cast<stringbuf*>(&sb); 328 } 329 330 string 331 str() const 332 { 333 return rdbuf()->str(); 334 } 335 336 void 337 str(const string& s) 338 { 339 rdbuf()->str(s); 340 } 341 private: 342 stringbuf sb; 343 }; 344 }; 345 346 #endif /* not __STRSTREAM__ */ 347