Oh GACK! src-clean doesn't quite work that easily since cleandist rebuilds the
[unix-history] / gnu / lib / libg++ / libg++ / istream.cc
CommitLineData
15637ed4
RG
1// This may look like C code, but it is really -*- C++ -*-
2/*
3Copyright (C) 1989 Free Software Foundation
4 written by Doug Lea (dl@rocky.oswego.edu)
5
6This file is part of GNU CC.
7
8GNU CC is distributed in the hope that it will be useful,
9but WITHOUT ANY WARRANTY. No author or distributor
10accepts responsibility to anyone for the consequences of using it
11or for whether it serves any particular purpose or works at all,
12unless he says so in writing. Refer to the GNU CC General Public
13License for full details.
14
15Everyone is granted permission to copy, modify and redistribute
16GNU CC, but only under the conditions described in the
17GNU CC General Public License. A copy of this license is
18supposed to have been given to you along with GNU CC so you
19can know your rights and responsibilities. It should be in a
20file named COPYING. Among other things, the copyright notice
21and this notice must be preserved on all copies.
22*/
23
24/* *** Version 1.2 -- nearly 100% AT&T 1.2 compatible *** */
25
26#ifdef __GNUG__
27#pragma implementation
28#endif
29#include <stream.h>
30#include <stdarg.h>
31#include <values.h>
32#include <ctype.h>
33#include <Obstack.h>
34
35
36istream::istream(streambuf* s, int sk, ostream* t)
37 : bp(s), state(_good), skipws(sk), tied_to(t), ownbuf(0) {}
38
39istream::istream(int sz, char* buf, int sk, ostream* t)
40 : state(_good), skipws(sk), tied_to(t), ownbuf(1)
41{
42 bp = new streambuf;
43 if (buf == 0)
44 {
45 bp->alloc = 1;
46 buf = new char[sz];
47 }
48 else
49 bp->alloc = 0;
50
51 bp->setbuf(buf, sz, sz);
52}
53
54istream::~istream()
55{
56 if (ownbuf) delete bp;
57}
58
59istream::istream(const char* filename, io_mode m, access_mode a, int sk, ostream* t)
60 : state(_good), skipws(sk), tied_to(t), ownbuf(1)
61{
62 bp = new filebuf(filename, m, a);
63}
64
65istream::istream(const char* filename, const char* m, int sk, ostream* t)
66 : state(_good), skipws(sk), tied_to(t), ownbuf(1)
67{
68 bp = new filebuf(filename, m);
69}
70
71istream::istream(int filedesc, io_mode m, int sk, ostream* t)
72 : state(_good), skipws(sk), tied_to(t), ownbuf(1)
73{
74 bp = new filebuf(filedesc, m);
75}
76
77istream::istream(FILE* fileptr, int sk, ostream* t)
78 : state(_good), skipws(sk), tied_to(t), ownbuf(1)
79{
80 bp = new filebuf(fileptr);
81
82}
83
84istream::istream(int filedesc, int sk, ostream* t)
85 : state(_good), skipws(sk), tied_to(t), ownbuf(1)
86{
87 bp = new filebuf(filedesc);
88}
89
90istream::istream(int filedesc, char* buf, int buflen, int sk, ostream* t)
91 : state(_good), skipws(sk), tied_to(t), ownbuf(1)
92{
93 bp = new filebuf(filedesc, buf, buflen);
94}
95
96istream& istream::open(const char* filename, io_mode m, access_mode a)
97{
98 return failif(bp->open(filename, m, a) == 0);
99}
100
101istream& istream::open(const char* filename, const char* m)
102{
103 return failif(bp->open(filename, m) == 0);
104}
105
106istream& istream::open(int filedesc, io_mode m)
107{
108 return failif(bp->open(filedesc, m) == 0);
109}
110
111istream& istream::open(FILE* fileptr)
112{
113 return failif(bp->open(fileptr) == 0);
114}
115
116istream& istream::open(const char* filenam, open_mode m)
117{
118 return failif(bp->open(filenam, m) == 0);
119}
120
121istream& istream::get(char& c)
122{
123 if (good())
124 {
125 if(tied_to != 0) tied_to->flush();
126 int ch = bp->sgetc();
127 if (ch == EOF)
128 set(_eof);
129 else
130 {
131 c = ch;
132 bp->stossc();
133 }
134 }
135 return *this;
136}
137
138
139istream& istream::operator >> (whitespace&)
140{
141 if (good())
142 {
143 int ch;
144 if(tied_to != 0) tied_to->flush();
145 while (((ch = bp->sgetc()) != EOF) && isspace(ch)) bp->stossc();
146 if (ch == EOF) set(_eof);
147 }
148 return *this;
149}
150
151
152istream& istream::operator >> (char& c)
153{
154 if (skipws) (*this >> WS);
155 return get(c);
156}
157
158istream& istream::get(char* s, int n, char terminator)
159{
160 if (!readable())
161 {
162 set(_fail);
163 return *this;
164 }
165
166 char ch = 0;
167 char* start = s;
168 if (--n > 0 && get(ch))
169 {
170 if (ch == terminator)
171 unget(ch);
172 else
173 {
174 *s++ = ch; --n;
175 while (n-- > 0 && get(ch))
176 {
177 if (ch == terminator)
178 {
179 unget(ch);
180 break;
181 }
182 else
183 *s++ = ch;
184 }
185 }
186 }
187
188 *s = 0;
189 if (s != start) clear();
190 return *this;
191}
192
193
194istream& istream::operator >> (char* s)
195{
196 if (!readable() || s == 0)
197 {
198 set(_fail);
199 return *this;
200 }
201
202 if (skipws && !(*this >> WS)) return *this;
203
204 char ch;
205 char* start = s;
206 if (get(ch))
207 {
208 *s++ = ch;
209 while (get(ch))
210 {
211 if (isspace(ch))
212 {
213 unget(ch);
214 break;
215 }
216 else
217 *s++ = ch;
218 }
219 }
220
221 *s = 0;
222 if (s != start) clear();
223 return *this;
224}
225
226
227istream& istream::getline(char* s, int n, char terminator)
228{
229 if (!readable())
230 {
231 set(_fail);
232 return *this;
233 }
234 char* start = s;
235 char ch;
236 while (--n > 0 && get(ch) && ((*s++ = ch) != terminator));
237
238 *s = 0;
239 if (s != start) clear();
240 return *this;
241}
242
243// from Doug Schmidt
244
245// This should probably be a page size....
246#define CHUNK_SIZE 512
247
248/* Reads an arbitrarily long input line terminated by a user-specified
249 TERMINATOR. Super-nifty trick using recursion avoids unnecessary calls
250 to NEW! */
251
252char *istream::readline (int chunk_number, char terminator)
253{
254 char buf[CHUNK_SIZE];
255 register char *bufptr = buf;
256 register char *ptr;
257 char ch;
258 int continu;
259
260 while ((continu = !!get(ch)) && ch != terminator) /* fill the current buffer */
261 {
262 *bufptr++ = ch;
263 if (bufptr - buf >= CHUNK_SIZE) /* prepend remainder to ptr buffer */
264 {
265 if (ptr = readline (chunk_number + 1, terminator))
266
267 for (; bufptr != buf; *--ptr = *--bufptr);
268
269 return ptr;
270 }
271 }
272 if (!continu && bufptr == buf)
273 return NULL;
274
275 int size = (chunk_number * CHUNK_SIZE + bufptr - buf) + 1;
276
277 if (ptr = new char[size])
278 {
279
280 for (*(ptr += (size - 1)) = '\0'; bufptr != buf; *--ptr = *--bufptr)
281 ;
282
283 return ptr;
284 }
285 else
286 return NULL;
287}
288
289/* Reads an arbitrarily long input line terminated by TERMINATOR.
290 This routine allocates its own memory, so the user should
291 only supply the address of a (char *). */
292
293istream& istream::gets(char **s, char terminator)
294{
295 return failif(!readable() || !(*s = readline (0, terminator)));
296}
297
298istream& istream::operator >> (long& y)
299{
300 if (!readable())
301 {
302 set(_bad);
303 return *this;
304 }
305
306 int got_one = 0;
307 char sgn = 0;
308 char ch;
309 y = 0;
310 if (skipws) *this >> WS;
311 if (!good())
312 {
313 set(_bad);
314 return *this;
315 }
316 while (get(ch))
317 {
318 if (ch == '-')
319 {
320 if (sgn == 0 && got_one == 0)
321 sgn = '-';
322 else
323 break;
324 }
325 else if (ch >= '0' && ch <= '9')
326 y = y * 10 + ((got_one = ch) - '0');
327 else
328 break;
329 }
330 if (good())
331 unget(ch);
332 if (!got_one)
333 set(_bad);
334 else
335 clear();
336
337 if (sgn == '-')
338 y = -y;
339
340 return *this;
341}
342
343istream& istream::operator >> (unsigned long& y)
344{
345 if (!readable())
346 {
347 set(_bad);
348 return *this;
349 }
350
351 int got_one = 0;
352 char ch;
353 y = 0;
354 if (skipws) *this >> WS;
355 if (!good())
356 while (get(ch))
357 {
358 if (ch >= '0' && ch <= '9')
359 y = y * 10 + ((got_one = ch) - '0');
360 else
361 break;
362 }
363 if (good())
364 unget(ch);
365 if (!got_one)
366 set(_bad);
367 else
368 clear();
369 return *this;
370}
371
372
373/* for input to a double, we must trust atof (cannot even use
374the better strtod since it is not universally supported). So
375guaranteed legal chars are gathered up into an obstack. The
376only possible, undiagnosable error is that the input number
377might give a floating overflow or underflow inside atof.
378I know of no way to avoid this */
379
380extern Obstack _libgxx_io_ob;
381
382istream& istream::operator >> (double & y)
383{
384 if (!readable())
385 {
386 set(_bad);
387 return *this;
388 }
389
390
391 char seenint = 0;
392 char seendec = 0;
393 char seenexp = 0;
394 char seensgn = 0;
395 char seene = 0;
396 char seenexpsgn = 0;
397 char seendot = 0;
398 char ch;
399
400 if (skipws) *this >> WS;
401 if (!good())
402 {
403 set(_bad);
404 return *this;
405 }
406 while (get(ch))
407 {
408 if (ch == '-' || ch == '+')
409 {
410 if (seene && !seenexpsgn)
411 _libgxx_io_ob.grow(seenexpsgn = ch);
412 else if (!seensgn && !seenint)
413 _libgxx_io_ob.grow(seensgn = ch);
414 else
415 break;
416 }
417 else if (ch == '.' && !seendot)
418 {
419 _libgxx_io_ob.grow(seendot = ch);
420 }
421 else if ((ch == 'e' || ch == 'E') && !seene)
422 {
423 _libgxx_io_ob.grow(seene = ch);
424 }
425 else if (ch >= '0' && ch <= '9')
426 {
427 _libgxx_io_ob.grow(ch);
428 if (seene) seenexp = ch;
429 else if (seendot) seendec = ch;
430 else seenint = ch;
431 }
432 else
433 break;
434 }
435 char* str = (char *) _libgxx_io_ob.finish(0);
436 if (good())
437 unget(ch);
438 if ((seenint || seendec) && (!seene || seenexp))
439 y = atof(str);
440 else
441 set(_bad);
442 _libgxx_io_ob.free(str);
443 return *this;
444}
445
446istream& istream::operator >> (int& y)
447{
448 long l; (*this >> l); y = int(l); return *this;
449}
450
451istream& istream:: operator >> (unsigned int& y)
452{
453 long l; (*this >> l); y = (unsigned int)(l); return *this;
454}
455
456istream& istream:: operator >> (short& y)
457{
458 long l; (*this >> l); y = short(l); return *this;
459}
460
461istream& istream:: operator >> (unsigned short& y)
462{
463 long l; (*this >> l); y = (unsigned short)(l); return *this;
464}
465
466istream& istream:: operator >> (float& y)
467{
468 double d; (*this >> d); y = float(d); return *this;
469}
470
471const char* istream::name()
472{
473 return bp->name();
474}
475
476void istream::error()
477{
478 bp->error();
479}
480
481ostream* istream::tie(ostream* s)
482{
483 ostream* was = tied_to; tied_to = s; return was;
484}
485
486void istream::_flush()
487{
488 if(tied_to != 0) tied_to->flush();
489}
490
491
492//--------------------------------------------------------------
493
494extern ostream cout;
495
496#if 0 /* BSD 4.4 */
497
498istream cin(stdin, 1, &cout);
499
500#else
501
502static char cinbuf[BUFSIZE];
503istream cin (0, cinbuf, BUFSIZE, 1, &cout);
504
505#endif
506
507whitespace WS;