1/* This is part of libio/iostream, providing -*- C++ -*- input/output. 2Copyright (C) 2000 Free Software Foundation 3 4This file is part of the GNU IO Library. This library is free 5software; you can redistribute it and/or modify it under the 6terms of the GNU General Public License as published by the 7Free Software Foundation; either version 2, or (at your option) 8any later version. 9 10This library is distributed in the hope that it will be useful, 11but WITHOUT ANY WARRANTY; without even the implied warranty of 12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this library; see the file COPYING. If not, write to the Free 17Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19As a special exception, if you link this library with files 20compiled with a GNU compiler to produce an executable, this does not cause 21the resulting executable to be covered by the GNU General Public License. 22This exception does not however invalidate any other reasons why 23the executable file might be covered by the GNU General Public License. */ 24 25/* Written by Magnus Fromreide (magfr@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 35namespace 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 { 231 public: 232 typedef char char_type; 233 typedef int int_type; 234 typedef streampos pos_type; 235 typedef streamoff off_type; 236 237 explicit 238 istringstream(int which=ios::in) 239 : istream(&sb), sb(which | ios::in) 240 { } 241 242 explicit 243 istringstream(const string& str, int which=ios::in) 244 : istream(&sb), sb(str, which | ios::in) 245 { } 246 247 stringbuf* 248 rdbuf() const 249 { 250 return const_cast<stringbuf*>(&sb); 251 } 252 253 string 254 str() const 255 { 256 return rdbuf()->str(); 257 } 258 void 259 str(const string& s) 260 { 261 rdbuf()->str(s); 262 } 263 private: 264 stringbuf sb; 265 }; 266 267 class ostringstream : public ostream { 268 public: 269 typedef char char_type; 270 typedef int int_type; 271 typedef streampos pos_type; 272 typedef streamoff off_type; 273 274 explicit 275 ostringstream(int which=ios::out) 276 : ostream(&sb), sb(which | ios::out) 277 { } 278 279 explicit 280 ostringstream(const string& str, int which=ios::out) 281 : ostream(&sb), sb(str, which | ios::out) 282 { } 283 284 stringbuf* 285 rdbuf() const 286 { 287 return const_cast<stringbuf*>(&sb); 288 } 289 290 string 291 str() const 292 { 293 return rdbuf()->str(); 294 } 295 296 void str(const string& s) 297 { 298 rdbuf()->str(s); 299 } 300 private: 301 stringbuf sb; 302 }; 303 304 class stringstream : public iostream { 305 public: 306 typedef char char_type; 307 typedef int int_type; 308 typedef streampos pos_type; 309 typedef streamoff off_type; 310 311 explicit 312 stringstream(int which=ios::out|ios::in) 313 : iostream(&sb), sb(which) 314 { } 315 316 explicit 317 stringstream(const string& str, int which=ios::out|ios::in) 318 : iostream(&sb), sb(str, which) 319 { } 320 321 stringbuf* 322 rdbuf() const 323 { 324 return const_cast<stringbuf*>(&sb); 325 } 326 327 string 328 str() const 329 { 330 return rdbuf()->str(); 331 } 332 333 void 334 str(const string& s) 335 { 336 rdbuf()->str(s); 337 } 338 private: 339 stringbuf sb; 340 }; 341}; 342 343#endif /* not __STRSTREAM__ */ 344