]>
Commit | Line | Data |
---|---|---|
6599da04 | 1 | /* This is part of libio/iostream, providing -*- C++ -*- input/output. |
e693cc28 UD |
2 | Copyright (C) 1993, 1997 Free Software Foundation, Inc. |
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, | |
18 | USA. | |
19 | ||
20 | As a special exception, if you link this library with files | |
21 | compiled with a GNU compiler to produce an executable, this does not cause | |
22 | the resulting executable to be covered by the GNU General Public License. | |
23 | This exception does not however invalidate any other reasons why | |
24 | the executable file might be covered by the GNU General Public License. */ | |
6599da04 JM |
25 | |
26 | /* Written by Per Bothner (bothner@cygnus.com). */ | |
27 | ||
28 | #ifdef __GNUC__ | |
29 | #pragma implementation | |
30 | #endif | |
31 | #define _STREAM_COMPAT | |
32 | #include <iostream.h> | |
33 | #include "libioP.h" | |
34 | #include <stdio.h> /* Needed for sprintf */ | |
35 | #include <ctype.h> | |
36 | #include <string.h> | |
37 | #include <limits.h> | |
e693cc28 UD |
38 | |
39 | #if _G_HAVE_PRINTF_FP | |
40 | #include <printf.h> | |
41 | extern "C" int __printf_fp (_IO_FILE *, const struct printf_info *, | |
42 | const void *const *); | |
43 | #else | |
6599da04 | 44 | #include "floatio.h" |
6c1d5706 UD |
45 | # ifndef _IO_USE_DTOA |
46 | int __cvt_double(double number, register int prec, int flags, int *signp, | |
d604f4c6 | 47 | int fmtch, char *startp, char *endp); |
6c1d5706 | 48 | # endif |
e693cc28 | 49 | #endif |
6599da04 JM |
50 | |
51 | #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ | |
52 | ||
53 | //#define isspace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n') | |
54 | ||
55 | istream::istream(streambuf *sb, ostream* tied) | |
56 | { | |
57 | init (sb, tied); | |
58 | _gcount = 0; | |
59 | } | |
60 | ||
61 | int skip_ws(streambuf* sb) | |
62 | { | |
63 | int ch; | |
64 | for (;;) { | |
65 | ch = sb->sbumpc(); | |
66 | if (ch == EOF || !isspace(ch)) | |
67 | return ch; | |
68 | } | |
69 | } | |
70 | ||
71 | istream& istream::get(char& c) | |
72 | { | |
73 | if (ipfx1()) { | |
74 | int ch = _strbuf->sbumpc(); | |
75 | if (ch == EOF) { | |
76 | set(ios::eofbit|ios::failbit); | |
77 | _gcount = 0; | |
78 | } | |
79 | else { | |
80 | c = (char)ch; | |
81 | _gcount = 1; | |
82 | } | |
83 | } | |
84 | else | |
85 | _gcount = 0; | |
86 | return *this; | |
87 | } | |
88 | ||
89 | int istream::peek() | |
90 | { | |
91 | if (!good()) | |
92 | return EOF; | |
93 | if (_tie && rdbuf()->in_avail() == 0) | |
94 | _tie->flush(); | |
95 | int ch = _strbuf->sgetc(); | |
96 | if (ch == EOF) | |
97 | set(ios::eofbit); | |
98 | return ch; | |
99 | } | |
100 | ||
101 | istream& istream::ignore(int n /* = 1 */, int delim /* = EOF */) | |
102 | { | |
103 | _gcount = 0; | |
104 | if (ipfx1()) { | |
105 | register streambuf* sb = _strbuf; | |
106 | if (delim == EOF) { | |
107 | _gcount = sb->ignore(n); | |
108 | return *this; | |
109 | } | |
110 | for (;;) { | |
111 | #if 0 | |
112 | if (n != MAXINT) // FIXME | |
113 | #endif | |
114 | if (--n < 0) | |
115 | break; | |
116 | int ch = sb->sbumpc(); | |
117 | if (ch == EOF) { | |
118 | set(ios::eofbit|ios::failbit); | |
119 | break; | |
120 | } | |
121 | _gcount++; | |
122 | if (ch == delim) | |
123 | break; | |
124 | } | |
125 | } | |
126 | return *this; | |
127 | } | |
128 | ||
129 | istream& istream::read(char *s, streamsize n) | |
130 | { | |
131 | if (ipfx1()) { | |
132 | _gcount = _strbuf->sgetn(s, n); | |
133 | if (_gcount != n) | |
134 | set(ios::failbit|ios::eofbit); | |
135 | } | |
136 | else | |
137 | _gcount = 0; | |
138 | return *this; | |
139 | } | |
140 | ||
141 | int | |
142 | istream::sync () | |
143 | { | |
144 | streambuf *sb = rdbuf (); | |
145 | if (sb == NULL) | |
146 | return EOF; | |
147 | if (sb->sync ()) // Later: pubsync | |
e693cc28 | 148 | { |
6599da04 JM |
149 | setstate (ios::badbit); |
150 | return EOF; | |
151 | } | |
152 | else | |
153 | return 0; | |
154 | } | |
155 | ||
156 | istream& istream::seekg(streampos pos) | |
157 | { | |
158 | pos = _strbuf->pubseekpos(pos, ios::in); | |
159 | if (pos == streampos(EOF)) | |
160 | set(ios::badbit); | |
161 | return *this; | |
162 | } | |
163 | ||
164 | istream& istream::seekg(streamoff off, _seek_dir dir) | |
165 | { | |
166 | streampos pos = _IO_seekoff (_strbuf, off, (int) dir, _IOS_INPUT); | |
167 | if (pos == streampos(EOF)) | |
168 | set(ios::badbit); | |
169 | return *this; | |
170 | } | |
171 | ||
172 | streampos istream::tellg() | |
173 | { | |
174 | #if 0 | |
175 | streampos pos = _strbuf->pubseekoff(0, ios::cur, ios::in); | |
176 | #else | |
177 | streampos pos = _IO_seekoff (_strbuf, 0, _IO_seek_cur, _IOS_INPUT); | |
178 | #endif | |
179 | if (pos == streampos(EOF)) | |
180 | set(ios::badbit); | |
181 | return pos; | |
182 | } | |
183 | ||
184 | istream& istream::operator>>(char& c) | |
185 | { | |
186 | if (ipfx0()) { | |
187 | int ch = _strbuf->sbumpc(); | |
188 | if (ch == EOF) | |
189 | set(ios::eofbit|ios::failbit); | |
190 | else | |
191 | c = (char)ch; | |
192 | } | |
193 | return *this; | |
194 | } | |
195 | ||
196 | istream& | |
197 | istream::operator>> (char* ptr) | |
198 | { | |
199 | register char *p = ptr; | |
200 | int w = width(0); | |
201 | if (ipfx0()) | |
202 | { | |
203 | register streambuf* sb = _strbuf; | |
204 | for (;;) | |
205 | { | |
206 | int ch = sb->sbumpc(); | |
207 | if (ch == EOF) | |
208 | { | |
209 | set(ios::eofbit); | |
210 | break; | |
211 | } | |
212 | else if (isspace(ch) || w == 1) | |
213 | { | |
214 | sb->sputbackc(ch); | |
215 | break; | |
216 | } | |
217 | else *p++ = ch; | |
218 | w--; | |
219 | } | |
220 | if (p == ptr) | |
221 | set(ios::failbit); | |
222 | } | |
223 | *p = '\0'; | |
224 | return *this; | |
225 | } | |
226 | ||
227 | #if defined(__GNUC__) && !defined(__STRICT_ANSI__) | |
228 | #define LONGEST long long | |
229 | #else | |
230 | #define LONGEST long | |
231 | #endif | |
232 | ||
233 | static int read_int(istream& stream, unsigned LONGEST& val, int& neg) | |
234 | { | |
235 | if (!stream.ipfx0()) | |
236 | return 0; | |
237 | register streambuf* sb = stream.rdbuf(); | |
238 | int base = 10; | |
239 | int ndigits = 0; | |
240 | register int ch = skip_ws(sb); | |
241 | if (ch == EOF) | |
242 | goto eof_fail; | |
243 | neg = 0; | |
244 | if (ch == '+') { | |
245 | ch = skip_ws(sb); | |
246 | } | |
247 | else if (ch == '-') { | |
248 | neg = 1; | |
249 | ch = skip_ws(sb); | |
250 | } | |
251 | if (ch == EOF) goto eof_fail; | |
252 | if (!(stream.flags() & ios::basefield)) { | |
253 | if (ch == '0') { | |
254 | ch = sb->sbumpc(); | |
255 | if (ch == EOF) { | |
256 | val = 0; | |
257 | return 1; | |
258 | } | |
259 | if (ch == 'x' || ch == 'X') { | |
260 | base = 16; | |
261 | ch = sb->sbumpc(); | |
262 | if (ch == EOF) goto eof_fail; | |
263 | } | |
264 | else { | |
265 | sb->sputbackc(ch); | |
266 | base = 8; | |
267 | ch = '0'; | |
268 | } | |
269 | } | |
270 | } | |
271 | else if ((stream.flags() & ios::basefield) == ios::hex) | |
272 | base = 16; | |
273 | else if ((stream.flags() & ios::basefield) == ios::oct) | |
274 | base = 8; | |
275 | val = 0; | |
276 | for (;;) { | |
277 | if (ch == EOF) | |
278 | break; | |
279 | int digit; | |
280 | if (ch >= '0' && ch <= '9') | |
281 | digit = ch - '0'; | |
282 | else if (ch >= 'A' && ch <= 'F') | |
283 | digit = ch - 'A' + 10; | |
284 | else if (ch >= 'a' && ch <= 'f') | |
285 | digit = ch - 'a' + 10; | |
286 | else | |
287 | digit = 999; | |
288 | if (digit >= base) { | |
289 | sb->sputbackc(ch); | |
290 | if (ndigits == 0) | |
291 | goto fail; | |
292 | else | |
293 | return 1; | |
294 | } | |
295 | ndigits++; | |
296 | val = base * val + digit; | |
297 | ch = sb->sbumpc(); | |
298 | } | |
299 | return 1; | |
300 | fail: | |
301 | stream.set(ios::failbit); | |
302 | return 0; | |
303 | eof_fail: | |
304 | stream.set(ios::failbit|ios::eofbit); | |
305 | return 0; | |
306 | } | |
307 | ||
308 | #define READ_INT(TYPE) \ | |
309 | istream& istream::operator>>(TYPE& i)\ | |
310 | {\ | |
311 | unsigned LONGEST val; int neg;\ | |
312 | if (read_int(*this, val, neg)) {\ | |
313 | if (neg) val = -val;\ | |
314 | i = (TYPE)val;\ | |
315 | }\ | |
316 | return *this;\ | |
317 | } | |
318 | ||
319 | READ_INT(short) | |
320 | READ_INT(unsigned short) | |
321 | READ_INT(int) | |
322 | READ_INT(unsigned int) | |
323 | READ_INT(long) | |
324 | READ_INT(unsigned long) | |
325 | #if defined(__GNUC__) && !defined(__STRICT_ANSI__) | |
326 | READ_INT(long long) | |
327 | READ_INT(unsigned long long) | |
328 | #endif | |
329 | #if _G_HAVE_BOOL | |
330 | READ_INT(bool) | |
331 | #endif | |
332 | ||
333 | istream& istream::operator>>(long double& x) | |
334 | { | |
335 | if (ipfx0()) | |
54a60f6e | 336 | { |
e693cc28 UD |
337 | #if _G_HAVE_LONG_DOUBLE_IO |
338 | scan("%Lg", &x); | |
339 | #else | |
54a60f6e AS |
340 | double y; |
341 | scan("%lg", &y); | |
342 | x = y; | |
e693cc28 | 343 | #endif |
54a60f6e | 344 | } |
6599da04 JM |
345 | return *this; |
346 | } | |
347 | ||
348 | istream& istream::operator>>(double& x) | |
349 | { | |
350 | if (ipfx0()) | |
351 | scan("%lg", &x); | |
352 | return *this; | |
353 | } | |
354 | ||
355 | istream& istream::operator>>(float& x) | |
356 | { | |
357 | if (ipfx0()) | |
358 | scan("%g", &x); | |
359 | return *this; | |
360 | } | |
361 | ||
362 | istream& istream::operator>>(register streambuf* sbuf) | |
363 | { | |
364 | if (ipfx0()) { | |
365 | register streambuf* inbuf = rdbuf(); | |
366 | // FIXME: Should optimize! | |
367 | for (;;) { | |
368 | register int ch = inbuf->sbumpc(); | |
369 | if (ch == EOF) { | |
370 | set(ios::eofbit); | |
371 | break; | |
372 | } | |
373 | if (sbuf->sputc(ch) == EOF) { | |
374 | set(ios::failbit); | |
375 | break; | |
376 | } | |
377 | } | |
378 | } | |
379 | return *this; | |
380 | } | |
381 | ||
382 | ostream& ostream::operator<<(char c) | |
383 | { | |
384 | if (opfx()) { | |
e693cc28 UD |
385 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
386 | _strbuf); | |
6599da04 JM |
387 | #if 1 |
388 | // This is what the cfront implementation does. | |
e693cc28 UD |
389 | if (_strbuf->sputc(c) == EOF) { |
390 | set(ios::badbit); | |
391 | goto failed; | |
392 | } | |
6599da04 JM |
393 | #else |
394 | // This is what cfront documentation and current ANSI drafts say. | |
395 | int w = width(0); | |
396 | char fill_char = fill(); | |
397 | register int padding = w > 0 ? w - 1 : 0; | |
398 | register streambuf *sb = _strbuf; | |
399 | if (!(flags() & ios::left) && padding) // Default adjustment. | |
e693cc28 UD |
400 | if (_IO_padn(sb, fill_char, padding) < padding) { |
401 | set(ios::badbit); | |
6599da04 | 402 | goto failed; |
e693cc28 UD |
403 | } |
404 | if (sb->sputc(c) == EOF) { | |
405 | set(ios::badbit); | |
6599da04 | 406 | goto failed; |
e693cc28 | 407 | } |
6599da04 JM |
408 | if (flags() & ios::left && padding) // Left adjustment. |
409 | if (_IO_padn(sb, fill_char, padding) < padding) | |
e693cc28 | 410 | set(ios::badbit); |
6599da04 | 411 | #endif |
e693cc28 | 412 | failed: |
6599da04 | 413 | osfx(); |
e693cc28 | 414 | _IO_cleanup_region_end (0); |
6599da04 JM |
415 | } |
416 | return *this; | |
6599da04 JM |
417 | } |
418 | ||
419 | /* Write VAL on STREAM. | |
420 | If SIGN<0, val is the absolute value of a negative number. | |
421 | If SIGN>0, val is a signed non-negative number. | |
422 | If SIGN==0, val is unsigned. */ | |
423 | ||
424 | static void write_int(ostream& stream, unsigned LONGEST val, int sign) | |
425 | { | |
426 | #define WRITE_BUF_SIZE (10 + sizeof(unsigned LONGEST) * 3) | |
427 | char buf[WRITE_BUF_SIZE]; | |
428 | register char *buf_ptr = buf+WRITE_BUF_SIZE; // End of buf. | |
429 | const char *show_base = ""; | |
430 | int show_base_len = 0; | |
431 | int show_pos = 0; // If 1, print a '+'. | |
432 | ||
433 | // Now do the actual conversion, placing the result at the *end* of buf. | |
434 | // Note that we use separate code for decimal, octal, and hex, | |
435 | // so we can divide by optimizable constants. | |
436 | if ((stream.flags() & ios::basefield) == ios::oct) { // Octal | |
437 | do { | |
438 | *--buf_ptr = (val & 7) + '0'; | |
439 | val = val >> 3; | |
440 | } while (val != 0); | |
441 | if ((stream.flags() & ios::showbase) && (*buf_ptr != '0')) | |
442 | *--buf_ptr = '0'; | |
443 | } | |
444 | else if ((stream.flags() & ios::basefield) == ios::hex) { // Hex | |
445 | const char *xdigs = (stream.flags() & ios::uppercase) ? "0123456789ABCDEF0X" | |
446 | : "0123456789abcdef0x"; | |
447 | do { | |
448 | *--buf_ptr = xdigs[val & 15]; | |
449 | val = val >> 4; | |
450 | } while (val != 0); | |
451 | if ((stream.flags() & ios::showbase)) { | |
452 | show_base = xdigs + 16; // Either "0X" or "0x". | |
453 | show_base_len = 2; | |
454 | } | |
455 | } | |
456 | else { // Decimal | |
457 | #if defined(__GNUC__) && !defined(__STRICT_ANSI__) | |
458 | // Optimization: Only use long long when we need to. | |
459 | while (val > UINT_MAX) { | |
460 | *--buf_ptr = (val % 10) + '0'; | |
461 | val /= 10; | |
462 | } | |
463 | // Use more efficient (int) arithmetic for the rest. | |
464 | register unsigned int ival = (unsigned int)val; | |
465 | #else | |
466 | register unsigned LONGEST ival = val; | |
467 | #endif | |
468 | do { | |
469 | *--buf_ptr = (ival % 10) + '0'; | |
470 | ival /= 10; | |
471 | } while (ival != 0); | |
472 | if (sign > 0 && (stream.flags() & ios::showpos)) | |
473 | show_pos=1; | |
474 | } | |
475 | ||
476 | int buf_len = buf+WRITE_BUF_SIZE - buf_ptr; | |
477 | int w = stream.width(0); | |
478 | ||
479 | // Calculate padding. | |
480 | int len = buf_len+show_pos; | |
481 | if (sign < 0) len++; | |
482 | len += show_base_len; | |
483 | int padding = len > w ? 0 : w - len; | |
484 | ||
485 | // Do actual output. | |
486 | register streambuf* sbuf = stream.rdbuf(); | |
487 | ios::fmtflags pad_kind = | |
488 | stream.flags() & (ios::left|ios::right|ios::internal); | |
489 | char fill_char = stream.fill(); | |
490 | if (padding > 0 | |
491 | && pad_kind != (ios::fmtflags)ios::left | |
492 | && pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust. | |
493 | if (_IO_padn(sbuf, fill_char, padding) < padding) | |
494 | goto failed; | |
495 | if (sign < 0 || show_pos) | |
496 | { | |
497 | char ch = sign < 0 ? '-' : '+'; | |
498 | if (sbuf->sputc(ch) < 0) | |
499 | goto failed; | |
500 | } | |
501 | if (show_base_len) | |
502 | if (_IO_sputn(sbuf, show_base, show_base_len) <= 0) | |
503 | goto failed; | |
504 | if (pad_kind == (ios::fmtflags)ios::internal && padding > 0) | |
505 | if (_IO_padn(sbuf, fill_char, padding) < padding) | |
506 | goto failed; | |
507 | if (_IO_sputn (sbuf, buf_ptr, buf_len) != buf_len) | |
508 | goto failed; | |
509 | if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment | |
510 | if (_IO_padn(sbuf, fill_char, padding) < padding) | |
511 | goto failed; | |
512 | stream.osfx(); | |
513 | return; | |
514 | failed: | |
515 | stream.set(ios::badbit); | |
516 | stream.osfx(); | |
517 | } | |
518 | ||
519 | ostream& ostream::operator<<(int n) | |
520 | { | |
521 | if (opfx()) { | |
e693cc28 UD |
522 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
523 | _strbuf); | |
6599da04 JM |
524 | int sign = 1; |
525 | unsigned int abs_n = (unsigned)n; | |
526 | if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) | |
527 | abs_n = -((unsigned)n), sign = -1; | |
528 | write_int(*this, abs_n, sign); | |
e693cc28 | 529 | _IO_cleanup_region_end (0); |
6599da04 JM |
530 | } |
531 | return *this; | |
532 | } | |
533 | ||
534 | ostream& ostream::operator<<(unsigned int n) | |
535 | { | |
e693cc28 UD |
536 | if (opfx()) { |
537 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, | |
538 | _strbuf); | |
6599da04 | 539 | write_int(*this, n, 0); |
e693cc28 UD |
540 | _IO_cleanup_region_end (0); |
541 | } | |
6599da04 JM |
542 | return *this; |
543 | } | |
544 | ||
545 | ||
546 | ostream& ostream::operator<<(long n) | |
547 | { | |
548 | if (opfx()) { | |
e693cc28 UD |
549 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
550 | _strbuf); | |
6599da04 JM |
551 | int sign = 1; |
552 | unsigned long abs_n = (unsigned long)n; | |
553 | if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) | |
554 | abs_n = -((unsigned long)n), sign = -1; | |
555 | write_int(*this, abs_n, sign); | |
e693cc28 | 556 | _IO_cleanup_region_end (0); |
6599da04 JM |
557 | } |
558 | return *this; | |
559 | } | |
560 | ||
561 | ostream& ostream::operator<<(unsigned long n) | |
562 | { | |
e693cc28 UD |
563 | if (opfx()) { |
564 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, | |
565 | _strbuf); | |
6599da04 | 566 | write_int(*this, n, 0); |
e693cc28 UD |
567 | _IO_cleanup_region_end (0); |
568 | } | |
6599da04 JM |
569 | return *this; |
570 | } | |
571 | ||
572 | #if defined(__GNUC__) && !defined(__STRICT_ANSI__) | |
573 | ostream& ostream::operator<<(long long n) | |
574 | { | |
575 | if (opfx()) { | |
e693cc28 UD |
576 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
577 | _strbuf); | |
6599da04 JM |
578 | int sign = 1; |
579 | unsigned long long abs_n = (unsigned long long)n; | |
580 | if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) | |
581 | abs_n = -((unsigned long long)n), sign = -1; | |
582 | write_int(*this, abs_n, sign); | |
e693cc28 | 583 | _IO_cleanup_region_end (0); |
6599da04 JM |
584 | } |
585 | return *this; | |
586 | } | |
587 | ||
588 | ||
589 | ostream& ostream::operator<<(unsigned long long n) | |
590 | { | |
e693cc28 UD |
591 | if (opfx()) { |
592 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, | |
593 | _strbuf); | |
6599da04 | 594 | write_int(*this, n, 0); |
e693cc28 UD |
595 | _IO_cleanup_region_end (0); |
596 | } | |
6599da04 JM |
597 | return *this; |
598 | } | |
599 | #endif /*__GNUC__*/ | |
600 | ||
601 | ostream& ostream::operator<<(double n) | |
602 | { | |
603 | if (opfx()) { | |
e693cc28 UD |
604 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
605 | _strbuf); | |
6599da04 JM |
606 | // Uses __cvt_double (renamed from static cvt), in Chris Torek's |
607 | // stdio implementation. The setup code uses the same logic | |
608 | // as in __vsbprintf.C (also based on Torek's code). | |
609 | int format_char; | |
610 | if ((flags() & ios::floatfield) == ios::fixed) | |
611 | format_char = 'f'; | |
612 | else if ((flags() & ios::floatfield) == ios::scientific) | |
613 | format_char = flags() & ios::uppercase ? 'E' : 'e'; | |
614 | else | |
615 | format_char = flags() & ios::uppercase ? 'G' : 'g'; | |
616 | ||
617 | int prec = precision(); | |
618 | if (prec <= 0 && !(flags() & ios::fixed)) | |
619 | prec = 6; /* default */ | |
620 | ||
621 | // Do actual conversion. | |
808d0b10 | 622 | #if _G_HAVE_PRINTF_FP |
e693cc28 UD |
623 | { |
624 | struct printf_info info = { prec: prec, | |
625 | width: width(0), | |
626 | spec: format_char, | |
627 | is_long_double: 0, | |
628 | is_short: 0, | |
629 | is_long: 0, | |
d604f4c6 | 630 | alt: (flags() & ios::showpoint) != 0, |
e693cc28 | 631 | space: 0, |
d604f4c6 UD |
632 | left: (flags() & ios::left) != 0, |
633 | showsign: (flags() & ios::showpos) != 0, | |
e693cc28 | 634 | group: 0, |
d604f4c6 | 635 | #if defined __GLIBC__ && __GLIBC__ >= 2 |
54a60f6e | 636 | extra: 0, |
d604f4c6 | 637 | #endif |
54a60f6e | 638 | pad: fill() |
d604f4c6 UD |
639 | }; |
640 | const void *ptr = (const void *) &n; | |
e693cc28 UD |
641 | if (__printf_fp (rdbuf(), &info, &ptr) < 0) |
642 | set(ios::badbit|ios::failbit); | |
643 | } | |
644 | #elif defined _IO_USE_DTOA | |
6599da04 JM |
645 | if (_IO_outfloat(n, rdbuf(), format_char, width(0), |
646 | prec, flags(), | |
647 | flags() & ios::showpos ? '+' : 0, | |
648 | fill()) < 0) | |
649 | set(ios::badbit|ios::failbit); // ?? | |
650 | #else | |
651 | int fpprec = 0; // 'Extra' (suppressed) floating precision. | |
652 | if (prec > MAXFRACT) { | |
653 | if (flags() & (ios::fixed|ios::scientific) & ios::showpos) | |
654 | fpprec = prec - MAXFRACT; | |
655 | prec = MAXFRACT; | |
656 | } | |
657 | int negative; | |
658 | char buf[BUF]; | |
659 | int sign = '\0'; | |
660 | char *cp = buf; | |
661 | *cp = 0; | |
662 | int size = __cvt_double(n, prec, | |
663 | flags() & ios::showpoint ? 0x80 : 0, | |
664 | &negative, | |
665 | format_char, cp, buf + sizeof(buf)); | |
666 | if (negative) sign = '-'; | |
667 | else if (flags() & ios::showpos) sign = '+'; | |
668 | if (*cp == 0) | |
669 | cp++; | |
670 | ||
671 | // Calculate padding. | |
672 | int fieldsize = size + fpprec; | |
673 | if (sign) fieldsize++; | |
674 | int padding = 0; | |
675 | int w = width(0); | |
676 | if (fieldsize < w) | |
677 | padding = w - fieldsize; | |
678 | ||
679 | // Do actual output. | |
680 | register streambuf* sbuf = rdbuf(); | |
681 | register i; | |
682 | char fill_char = fill(); | |
683 | ios::fmtflags pad_kind = | |
684 | flags() & (ios::left|ios::right|ios::internal); | |
685 | if (pad_kind != (ios::fmtflags)ios::left // Default (right) adjust. | |
686 | && pad_kind != (ios::fmtflags)ios::internal) | |
687 | for (i = padding; --i >= 0; ) sbuf->sputc(fill_char); | |
688 | if (sign) | |
689 | sbuf->sputc(sign); | |
690 | if (pad_kind == (ios::fmtflags)ios::internal) | |
691 | for (i = padding; --i >= 0; ) sbuf->sputc(fill_char); | |
e693cc28 | 692 | |
6599da04 JM |
693 | // Emit the actual concented field, followed by extra zeros. |
694 | _IO_sputn (sbuf, cp, size); | |
695 | for (i = fpprec; --i >= 0; ) sbuf->sputc('0'); | |
696 | ||
697 | if (pad_kind == (ios::fmtflags)ios::left) // Left adjustment | |
698 | for (i = padding; --i >= 0; ) sbuf->sputc(fill_char); | |
699 | #endif | |
700 | osfx(); | |
e693cc28 | 701 | _IO_cleanup_region_end (0); |
6599da04 JM |
702 | } |
703 | return *this; | |
704 | } | |
705 | ||
e693cc28 UD |
706 | #if _G_HAVE_LONG_DOUBLE_IO |
707 | ostream& ostream::operator<<(long double n) | |
708 | { | |
709 | if (opfx()) | |
710 | { | |
711 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, | |
712 | _strbuf); | |
713 | int format_char; | |
714 | if ((flags() & ios::floatfield) == ios::fixed) | |
715 | format_char = 'f'; | |
716 | else if ((flags() & ios::floatfield) == ios::scientific) | |
717 | format_char = flags() & ios::uppercase ? 'E' : 'e'; | |
718 | else | |
719 | format_char = flags() & ios::uppercase ? 'G' : 'g'; | |
720 | ||
721 | int prec = precision(); | |
722 | if (prec <= 0 && !(flags() & ios::fixed)) | |
723 | prec = 6; /* default */ | |
724 | ||
c44e099f | 725 | #if _G_HAVE_PRINTF_FP |
e693cc28 UD |
726 | // Do actual conversion. |
727 | struct printf_info info = { prec: prec, | |
728 | width: width(0), | |
729 | spec: format_char, | |
730 | is_long_double: 1, | |
731 | is_short: 0, | |
732 | is_long: 0, | |
d604f4c6 | 733 | alt: (flags() & ios::showpoint) != 0, |
e693cc28 | 734 | space: 0, |
d604f4c6 UD |
735 | left: (flags() & ios::left) != 0, |
736 | showsign: (flags() & ios::showpos) != 0, | |
e693cc28 | 737 | group: 0, |
d604f4c6 | 738 | #if defined __GLIBC__ && __GLIBC__ >= 2 |
54a60f6e | 739 | extra: 0, |
d604f4c6 | 740 | #endif |
54a60f6e | 741 | pad: fill() |
d604f4c6 | 742 | }; |
e693cc28 | 743 | |
d604f4c6 | 744 | const void *ptr = (const void *) &n; |
e693cc28 UD |
745 | |
746 | if (__printf_fp (rdbuf(), &info, &ptr) < 0) | |
747 | set (ios::badbit|ios::failbit); | |
748 | #else | |
749 | # error "long double I/O using dtoa or cvt_double is not implemented" | |
750 | #endif | |
751 | osfx(); | |
752 | _IO_cleanup_region_end (0); | |
753 | } | |
754 | return *this; | |
755 | } | |
756 | #endif | |
757 | ||
6599da04 JM |
758 | ostream& ostream::operator<<(const char *s) |
759 | { | |
760 | if (opfx()) | |
761 | { | |
e693cc28 UD |
762 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
763 | _strbuf); | |
6599da04 JM |
764 | if (s == NULL) |
765 | s = "(null)"; | |
766 | int len = strlen(s); | |
767 | int w = width(0); | |
768 | // FIXME: Should we: if (w && len>w) len = w; | |
769 | char fill_char = fill(); | |
770 | register streambuf *sbuf = rdbuf(); | |
771 | register int padding = w > len ? w - len : 0; | |
772 | if (!(flags() & ios::left) && padding > 0) // Default adjustment. | |
773 | if (_IO_padn(sbuf, fill_char, padding) != padding) | |
e693cc28 UD |
774 | { |
775 | set(ios::badbit); | |
776 | goto failed; | |
777 | } | |
6599da04 | 778 | if (_IO_sputn (sbuf, s, len) != len) |
e693cc28 UD |
779 | { |
780 | set(ios::badbit); | |
781 | goto failed; | |
782 | } | |
6599da04 JM |
783 | if (flags() & ios::left && padding > 0) // Left adjustment. |
784 | if (_IO_padn(sbuf, fill_char, padding) != padding) | |
e693cc28 | 785 | set(ios::badbit); |
6599da04 | 786 | osfx(); |
e693cc28 UD |
787 | failed: |
788 | _IO_cleanup_region_end (0); | |
6599da04 JM |
789 | } |
790 | return *this; | |
6599da04 JM |
791 | } |
792 | ||
793 | #if 0 | |
794 | ostream& ostream::operator<<(const void *p) | |
795 | { Is in osform.cc, to avoid pulling in all of _IO_vfprintf by this file. */ } | |
796 | #endif | |
797 | ||
798 | ostream& ostream::operator<<(register streambuf* sbuf) | |
799 | { | |
800 | if (opfx()) | |
801 | { | |
e693cc28 UD |
802 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
803 | _strbuf); | |
6599da04 JM |
804 | char buffer[_IO_BUFSIZ]; |
805 | register streambuf* outbuf = _strbuf; | |
806 | for (;;) | |
807 | { | |
808 | _IO_size_t count = _IO_sgetn(sbuf, buffer, _IO_BUFSIZ); | |
809 | if (count <= 0) | |
810 | break; | |
811 | if (_IO_sputn(outbuf, buffer, count) != count) | |
812 | { | |
813 | set(ios::badbit); | |
814 | break; | |
815 | } | |
816 | } | |
817 | osfx(); | |
e693cc28 | 818 | _IO_cleanup_region_end (0); |
6599da04 JM |
819 | } |
820 | return *this; | |
821 | } | |
822 | ||
823 | ostream::ostream(streambuf* sb, ostream* tied) | |
824 | { | |
825 | init (sb, tied); | |
826 | } | |
827 | ||
828 | ostream& ostream::seekp(streampos pos) | |
829 | { | |
830 | pos = _strbuf->pubseekpos(pos, ios::out); | |
831 | if (pos == streampos(EOF)) | |
832 | set(ios::badbit); | |
833 | return *this; | |
834 | } | |
835 | ||
836 | ostream& ostream::seekp(streamoff off, _seek_dir dir) | |
837 | { | |
838 | streampos pos = _IO_seekoff (_strbuf, off, (int) dir, _IOS_OUTPUT); | |
839 | if (pos == streampos(EOF)) | |
840 | set(ios::badbit); | |
841 | return *this; | |
842 | } | |
843 | ||
844 | streampos ostream::tellp() | |
845 | { | |
846 | #if 1 | |
847 | streampos pos = _IO_seekoff (_strbuf, 0, _IO_seek_cur, _IOS_OUTPUT); | |
848 | #else | |
849 | streampos pos = _strbuf->pubseekoff(0, ios::cur, ios::out); | |
850 | #endif | |
851 | if (pos == streampos(EOF)) | |
852 | set(ios::badbit); | |
853 | return pos; | |
854 | } | |
855 | ||
856 | ostream& ostream::flush() | |
857 | { | |
858 | if (_strbuf->sync()) | |
859 | set(ios::badbit); | |
860 | return *this; | |
861 | } | |
862 | ||
863 | ostream& flush(ostream& outs) | |
864 | { | |
865 | return outs.flush(); | |
866 | } | |
867 | ||
868 | istream& ws(istream& ins) | |
869 | { | |
870 | if (ins.ipfx1()) { | |
e693cc28 UD |
871 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
872 | ins._strbuf); | |
6599da04 JM |
873 | int ch = skip_ws(ins._strbuf); |
874 | if (ch == EOF) | |
875 | ins.set(ios::eofbit); | |
876 | else | |
877 | ins._strbuf->sputbackc(ch); | |
e693cc28 UD |
878 | ins.isfx(); |
879 | _IO_cleanup_region_end (0); | |
6599da04 JM |
880 | } |
881 | return ins; | |
882 | } | |
883 | ||
884 | // Skip white-space. Return 0 on failure (EOF), or 1 on success. | |
885 | // Differs from ws() manipulator in that failbit is set on EOF. | |
886 | // Called by ipfx() and ipfx0() if needed. | |
887 | ||
888 | int istream::_skip_ws() | |
889 | { | |
890 | int ch = skip_ws(_strbuf); | |
891 | if (ch == EOF) { | |
892 | set(ios::eofbit|ios::failbit); | |
893 | return 0; | |
894 | } | |
895 | else { | |
896 | _strbuf->sputbackc(ch); | |
897 | return 1; | |
898 | } | |
899 | } | |
900 | ||
901 | ostream& ends(ostream& outs) | |
902 | { | |
903 | outs.put('\0'); | |
904 | return outs; | |
905 | } | |
906 | ||
907 | ostream& endl(ostream& outs) | |
908 | { | |
909 | return flush(outs.put('\n')); | |
910 | } | |
911 | ||
e693cc28 UD |
912 | istream& lock(istream& ins) |
913 | { | |
914 | _IO_flockfile (ins._strbuf); | |
915 | return ins; | |
916 | } | |
917 | istream& unlock(istream& ins) | |
918 | { | |
919 | _IO_funlockfile (ins._strbuf); | |
920 | return ins; | |
921 | } | |
922 | ostream& lock(ostream& outs) | |
923 | { | |
924 | _IO_flockfile (outs._strbuf); | |
925 | return outs; | |
926 | } | |
927 | ostream& unlock(ostream& outs) | |
928 | { | |
929 | _IO_funlockfile (outs._strbuf); | |
930 | return outs; | |
931 | } | |
932 | ||
933 | ||
6599da04 JM |
934 | ostream& ostream::write(const char *s, streamsize n) |
935 | { | |
936 | if (opfx()) { | |
e693cc28 UD |
937 | _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, |
938 | _strbuf); | |
6599da04 JM |
939 | if (_IO_sputn(_strbuf, s, n) != n) |
940 | set(ios::failbit); | |
e693cc28 UD |
941 | osfx(); |
942 | _IO_cleanup_region_end (0); | |
6599da04 JM |
943 | } |
944 | return *this; | |
945 | } | |
946 | ||
947 | void ostream::do_osfx() | |
948 | { | |
949 | if (flags() & ios::unitbuf) | |
950 | flush(); | |
951 | if (flags() & ios::stdio) { | |
952 | fflush(stdout); | |
953 | fflush(stderr); | |
954 | } | |
955 | } | |
956 | ||
957 | iostream::iostream(streambuf* sb, ostream* tied) | |
958 | { | |
959 | init (sb, tied); | |
960 | } | |
961 | ||
962 | // NOTE: extension for compatibility with old libg++. | |
963 | // Not really compatible with fistream::close(). | |
964 | #ifdef _STREAM_COMPAT | |
965 | void ios::close() | |
966 | { | |
967 | if (_strbuf->_flags & _IO_IS_FILEBUF) | |
968 | ((struct filebuf*)rdbuf())->close(); | |
969 | else if (_strbuf != NULL) | |
970 | rdbuf()->sync(); | |
971 | _strbuf = NULL; | |
972 | _state = badbit; | |
973 | } | |
974 | ||
975 | int istream::skip(int i) | |
976 | { | |
977 | int old = (_flags & ios::skipws) != 0; | |
978 | if (i) | |
979 | _flags |= ios::skipws; | |
980 | else | |
981 | _flags &= ~ios::skipws; | |
982 | return old; | |
983 | } | |
984 | #endif |