blob: 45393b14761ebc8030263a7709aa13ad151a0be9 [file] [log] [blame]
Mike Dodd8cfa7022010-11-17 11:12:26 -08001/* 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__ */