1 /* Copyright (C) 1993, 1995, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
2 This file is part of the GNU IO Library.
3 Written by Ulrich Drepper <drepper@cygnus.com>.
4 Based on the single byte version by Per Bothner <bothner@cygnus.com>.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2, or (at
9 your option) any later version.
11 This library is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this library; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
21 As a special exception, if you link this library with files
22 compiled with a GNU compiler to produce an executable, this does
23 not cause the resulting executable to be covered by the GNU General
24 Public License. This exception does not however invalidate any
25 other reasons why the executable file might be covered by the GNU
26 General Public License. */
28 /* Generic or default I/O operations. */
31 #ifdef _GLIBCPP_USE_WCHAR_T
40 # define __wmemcpy(dst, src, n) wmemcpy (dst, src, n)
44 static int save_for_wbackup
__P ((_IO_FILE
*fp
, wchar_t *end_p
))
50 /* Return minimum _pos markers
51 Assumes the current get area is the main get area. */
52 _IO_ssize_t _IO_least_wmarker
__P ((_IO_FILE
*fp
, wchar_t *end_p
));
55 _IO_least_wmarker (fp
, end_p
)
59 _IO_ssize_t least_so_far
= end_p
- fp
->_wide_data
->_IO_read_base
;
60 struct _IO_marker
*mark
;
61 for (mark
= fp
->_markers
; mark
!= NULL
; mark
= mark
->_next
)
62 if (mark
->_pos
< least_so_far
)
63 least_so_far
= mark
->_pos
;
67 /* Switch current get area from backup buffer to (start of) main get area. */
69 _IO_switch_to_main_wget_area (fp
)
73 fp
->_flags
&= ~_IO_IN_BACKUP
;
74 /* Swap _IO_read_end and _IO_save_end. */
75 tmp
= fp
->_wide_data
->_IO_read_end
;
76 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_save_end
;
77 fp
->_wide_data
->_IO_save_end
= tmp
;
78 /* Swap _IO_read_base and _IO_save_base. */
79 tmp
= fp
->_wide_data
->_IO_read_base
;
80 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_save_base
;
81 fp
->_wide_data
->_IO_save_base
= tmp
;
82 /* Set _IO_read_ptr. */
83 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_base
;
87 /* Switch current get area from main get area to (end of) backup area. */
89 _IO_switch_to_wbackup_area (fp
)
93 fp
->_flags
|= _IO_IN_BACKUP
;
94 /* Swap _IO_read_end and _IO_save_end. */
95 tmp
= fp
->_wide_data
->_IO_read_end
;
96 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_save_end
;
97 fp
->_wide_data
->_IO_save_end
= tmp
;
98 /* Swap _IO_read_base and _IO_save_base. */
99 tmp
= fp
->_wide_data
->_IO_read_base
;
100 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_save_base
;
101 fp
->_wide_data
->_IO_save_base
= tmp
;
102 /* Set _IO_read_ptr. */
103 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
108 _IO_wsetb (f
, b
, eb
, a
)
114 if (f
->_wide_data
->_IO_buf_base
&& !(f
->_flags
& _IO_USER_BUF
))
115 FREE_BUF (f
->_wide_data
->_IO_buf_base
, _IO_wblen (f
));
116 f
->_wide_data
->_IO_buf_base
= b
;
117 f
->_wide_data
->_IO_buf_end
= eb
;
119 f
->_flags
&= ~_IO_USER_BUF
;
121 f
->_flags
|= _IO_USER_BUF
;
126 _IO_wdefault_pbackfail (fp
, c
)
130 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
131 && !_IO_in_backup (fp
)
132 && (wint_t) fp
->_IO_read_ptr
[-1] == c
)
136 /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
137 if (!_IO_in_backup (fp
))
139 /* We need to keep the invariant that the main get area
140 logically follows the backup area. */
141 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
142 && _IO_have_wbackup (fp
))
144 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_ptr
))
147 else if (!_IO_have_wbackup (fp
))
149 /* No backup buffer: allocate one. */
150 /* Use nshort buffer, if unused? (probably not) FIXME */
151 int backup_size
= 128;
152 wchar_t *bbuf
= (wchar_t *) malloc (backup_size
156 fp
->_wide_data
->_IO_save_base
= bbuf
;
157 fp
->_wide_data
->_IO_save_end
= (fp
->_wide_data
->_IO_save_base
159 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_save_end
;
161 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
;
162 _IO_switch_to_wbackup_area (fp
);
164 else if (fp
->_wide_data
->_IO_read_ptr
<= fp
->_wide_data
->_IO_read_base
)
166 /* Increase size of existing backup buffer. */
168 _IO_size_t old_size
= (fp
->_wide_data
->_IO_read_end
169 - fp
->_wide_data
->_IO_read_base
);
171 new_size
= 2 * old_size
;
172 new_buf
= (wchar_t *) malloc (new_size
* sizeof (wchar_t));
175 __wmemcpy (new_buf
+ (new_size
- old_size
),
176 fp
->_wide_data
->_IO_read_base
, old_size
);
177 free (fp
->_wide_data
->_IO_read_base
);
178 _IO_wsetg (fp
, new_buf
, new_buf
+ (new_size
- old_size
),
180 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_read_ptr
;
183 *--fp
->_wide_data
->_IO_read_ptr
= c
;
190 _IO_wdefault_finish (fp
, dummy
)
194 struct _IO_marker
*mark
;
195 if (fp
->_wide_data
->_IO_buf_base
&& !(fp
->_flags
& _IO_USER_BUF
))
197 FREE_BUF (fp
->_wide_data
->_IO_buf_base
,
198 _IO_wblen (fp
) * sizeof (wchar_t));
199 fp
->_wide_data
->_IO_buf_base
= fp
->_wide_data
->_IO_buf_end
= NULL
;
202 for (mark
= fp
->_markers
; mark
!= NULL
; mark
= mark
->_next
)
205 if (fp
->_IO_save_base
)
207 free (fp
->_wide_data
->_IO_save_base
);
208 fp
->_IO_save_base
= NULL
;
212 _IO_lock_fini (*fp
->_lock
);
215 _IO_un_link ((struct _IO_FILE_plus
*) fp
);
220 _IO_wdefault_uflow (fp
)
224 wch
= _IO_UNDERFLOW (fp
);
227 return *fp
->_wide_data
->_IO_read_ptr
++;
238 return _IO_OVERFLOW (f
, wch
);
246 if (fp
->_mode
< 0 || (fp
->_mode
== 0 && _IO_fwide (fp
, 1) != 1))
251 if (_IO_in_put_mode (fp
))
252 if (_IO_switch_to_wget_mode (fp
) == EOF
)
254 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
255 return *fp
->_wide_data
->_IO_read_ptr
++;
256 if (_IO_in_backup (fp
))
258 _IO_switch_to_main_wget_area (fp
);
259 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
260 return *fp
->_wide_data
->_IO_read_ptr
++;
262 if (_IO_have_markers (fp
))
264 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_end
))
267 else if (_IO_have_wbackup (fp
))
268 _IO_free_wbackup_area (fp
);
269 return _IO_UFLOW (fp
);
277 if (fp
->_mode
< 0 || (fp
->_mode
== 0 && _IO_fwide (fp
, 1) != 1))
282 if (_IO_in_put_mode (fp
))
283 if (_IO_switch_to_wget_mode (fp
) == EOF
)
285 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
286 return *fp
->_wide_data
->_IO_read_ptr
;
287 if (_IO_in_backup (fp
))
289 _IO_switch_to_main_wget_area (fp
);
290 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
291 return *fp
->_wide_data
->_IO_read_ptr
;
293 if (_IO_have_markers (fp
))
295 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_end
))
298 else if (_IO_have_backup (fp
))
299 _IO_free_wbackup_area (fp
);
300 return _IO_UNDERFLOW (fp
);
305 _IO_wdefault_xsputn (f
, data
, n
)
310 const wchar_t *s
= (const wchar_t *) data
;
316 /* Space available. */
317 _IO_ssize_t count
= (f
->_wide_data
->_IO_write_end
318 - f
->_wide_data
->_IO_write_ptr
);
321 if ((_IO_size_t
) count
> more
)
326 f
->_wide_data
->_IO_write_ptr
=
327 __wmempcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
329 memcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
330 f
->_wide_data
->_IO_write_ptr
+= count
;
338 wchar_t *p
= f
->_wide_data
->_IO_write_ptr
;
340 for (i
= count
; --i
>= 0; )
342 f
->_wide_data
->_IO_write_ptr
= p
;
346 if (more
== 0 || __woverflow (f
, *s
++) == WEOF
)
355 _IO_wdefault_xsgetn (fp
, data
, n
)
361 wchar_t *s
= (wchar_t*) data
;
364 /* Data available. */
365 _IO_ssize_t count
= (fp
->_wide_data
->_IO_read_end
366 - fp
->_wide_data
->_IO_read_ptr
);
369 if ((_IO_size_t
) count
> more
)
374 s
= __wmempcpy (s
, fp
->_wide_data
->_IO_read_ptr
, count
);
376 memcpy (s
, fp
->_wide_data
->_IO_read_ptr
, count
);
379 fp
->_wide_data
->_IO_read_ptr
+= count
;
385 wchar_t *p
= fp
->_wide_data
->_IO_read_ptr
;
389 fp
->_wide_data
->_IO_read_ptr
= p
;
393 if (more
== 0 || __wunderflow (fp
) == WEOF
)
404 if (fp
->_wide_data
->_IO_buf_base
)
406 if (!(fp
->_flags
& _IO_UNBUFFERED
))
407 if (_IO_DOALLOCATE (fp
) != WEOF
)
409 _IO_wsetb (fp
, fp
->_wide_data
->_shortbuf
, fp
->_wide_data
->_shortbuf
+ 1, 0);
414 _IO_wdefault_setbuf (fp
, p
, len
)
419 if (_IO_SYNC (fp
) == EOF
)
421 if (p
== NULL
|| len
== 0)
423 fp
->_flags
|= _IO_UNBUFFERED
;
424 _IO_wsetb (fp
, fp
->_wide_data
->_shortbuf
, fp
->_wide_data
->_shortbuf
+ 1,
429 fp
->_flags
&= ~_IO_UNBUFFERED
;
430 _IO_wsetb (fp
, p
, p
+ len
, 0);
432 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
433 = fp
->_wide_data
->_IO_write_end
= 0;
434 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
435 = fp
->_wide_data
->_IO_read_end
= 0;
441 _IO_wdefault_doallocate (fp
)
446 ALLOC_WBUF (buf
, _IO_BUFSIZ
, EOF
);
447 _IO_wsetb (fp
, buf
, buf
+ _IO_BUFSIZ
, 1);
453 _IO_switch_to_wget_mode (fp
)
456 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_write_base
)
457 if (_IO_OVERFLOW (fp
, WEOF
) == WEOF
)
459 if (_IO_in_backup (fp
))
460 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_backup_base
;
463 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_buf_base
;
464 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_read_end
)
465 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_write_ptr
;
467 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_write_ptr
;
469 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
470 = fp
->_wide_data
->_IO_write_end
= fp
->_wide_data
->_IO_read_ptr
;
472 fp
->_flags
&= ~_IO_CURRENTLY_PUTTING
;
477 _IO_free_wbackup_area (fp
)
480 if (_IO_in_backup (fp
))
481 _IO_switch_to_main_wget_area (fp
); /* Just in case. */
482 free (fp
->_wide_data
->_IO_save_base
);
483 fp
->_wide_data
->_IO_save_base
= NULL
;
484 fp
->_wide_data
->_IO_save_end
= NULL
;
485 fp
->_wide_data
->_IO_backup_base
= NULL
;
490 _IO_switch_to_wput_mode (fp
)
493 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_read_ptr
;
494 fp
->_wide_data
->_IO_write_ptr
= fp
->_wide_data
->_IO_read_ptr
;
495 /* Following is wrong if line- or un-buffered? */
496 fp
->_wide_data
->_IO_write_end
= (fp
->_flags
& _IO_IN_BACKUP
497 ? fp
->_wide_data
->_IO_read_end
498 : fp
->_wide_data
->_IO_buf_end
);
500 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
501 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_end
;
503 fp
->_flags
|= _IO_CURRENTLY_PUTTING
;
513 save_for_wbackup (fp
, end_p
)
517 /* Append [_IO_read_base..end_p] to backup area. */
518 _IO_ssize_t least_mark
= _IO_least_wmarker (fp
, end_p
);
519 /* needed_size is how much space we need in the backup area. */
520 _IO_size_t needed_size
= ((end_p
- fp
->_wide_data
->_IO_read_base
)
522 /* FIXME: Dubious arithmetic if pointers are NULL */
523 _IO_size_t current_Bsize
= (fp
->_wide_data
->_IO_save_end
524 - fp
->_wide_data
->_IO_save_base
);
525 _IO_size_t avail
; /* Extra space available for future expansion. */
527 struct _IO_marker
*mark
;
528 if (needed_size
> current_Bsize
)
532 new_buffer
= (wchar_t *) malloc ((avail
+ needed_size
)
534 if (new_buffer
== NULL
)
535 return EOF
; /* FIXME */
539 __wmempcpy (__wmempcpy (new_buffer
+ avail
,
540 fp
->_wide_data
->_IO_save_end
+ least_mark
,
542 fp
->_wide_data
->_IO_read_base
,
543 end_p
- fp
->_wide_data
->_IO_read_base
);
545 memcpy (new_buffer
+ avail
,
546 fp
->_wide_data
->_IO_save_end
+ least_mark
,
547 -least_mark
* sizeof (wchar_t));
548 memcpy (new_buffer
+ avail
- least_mark
,
549 fp
->_wide_data
->_IO_read_base
,
550 (end_p
- fp
->_wide_data
->_IO_read_base
) * sizeof (wchar_t));
556 __wmemcpy (new_buffer
+ avail
,
557 fp
->_wide_data
->_IO_read_base
+ least_mark
,
560 memcpy (new_buffer
+ avail
,
561 fp
->_wide_data
->_IO_read_base
+ least_mark
,
562 needed_size
* sizeof (wchar_t));
565 if (fp
->_wide_data
->_IO_save_base
)
566 free (fp
->_wide_data
->_IO_save_base
);
567 fp
->_wide_data
->_IO_save_base
= new_buffer
;
568 fp
->_wide_data
->_IO_save_end
= new_buffer
+ avail
+ needed_size
;
572 avail
= current_Bsize
- needed_size
;
576 __wmemmove (fp
->_wide_data
->_IO_save_base
+ avail
,
577 fp
->_wide_data
->_IO_save_end
+ least_mark
,
579 __wmemcpy (fp
->_wide_data
->_IO_save_base
+ avail
- least_mark
,
580 fp
->_wide_data
->_IO_read_base
,
581 end_p
- fp
->_wide_data
->_IO_read_base
);
583 memmove (fp
->_wide_data
->_IO_save_base
+ avail
,
584 fp
->_wide_data
->_IO_save_end
+ least_mark
,
585 -least_mark
* sizeof (wchar_t));
586 memcpy (fp
->_wide_data
->_IO_save_base
+ avail
- least_mark
,
587 fp
->_wide_data
->_IO_read_base
,
588 (end_p
- fp
->_wide_data
->_IO_read_base
) * sizeof (wchar_t));
591 else if (needed_size
> 0)
593 __wmemcpy (fp
->_wide_data
->_IO_save_base
+ avail
,
594 fp
->_wide_data
->_IO_read_base
+ least_mark
,
597 memcpy (fp
->_wide_data
->_IO_save_base
+ avail
,
598 fp
->_wide_data
->_IO_read_base
+ least_mark
,
599 needed_size
* sizeof (wchar_t));
602 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_save_base
+ avail
;
603 /* Adjust all the streammarkers. */
604 delta
= end_p
- fp
->_wide_data
->_IO_read_base
;
605 for (mark
= fp
->_markers
; mark
!= NULL
; mark
= mark
->_next
)
611 _IO_sputbackwc (fp
, c
)
617 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
618 && (wchar_t)fp
->_wide_data
->_IO_read_ptr
[-1] == (wchar_t) c
)
620 fp
->_wide_data
->_IO_read_ptr
--;
624 result
= _IO_PBACKFAIL (fp
, c
);
627 fp
->_flags
&= ~_IO_EOF_SEEN
;
638 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
)
640 fp
->_wide_data
->_IO_read_ptr
--;
641 result
= *fp
->_wide_data
->_IO_read_ptr
;
644 result
= _IO_PBACKFAIL (fp
, EOF
);
647 fp
->_flags
&= ~_IO_EOF_SEEN
;
654 _IO_adjust_wcolumn (start
, line
, count
)
659 const wchar_t *ptr
= line
+ count
;
662 return line
+ count
- ptr
- 1;
663 return start
+ count
;
667 _IO_init_wmarker (marker
, fp
)
668 struct _IO_marker
*marker
;
672 if (_IO_in_put_mode (fp
))
673 _IO_switch_to_wget_mode (fp
);
674 if (_IO_in_backup (fp
))
675 marker
->_pos
= fp
->_wide_data
->_IO_read_ptr
- fp
->_wide_data
->_IO_read_end
;
677 marker
->_pos
= (fp
->_wide_data
->_IO_read_ptr
678 - fp
->_wide_data
->_IO_read_base
);
680 /* Should perhaps sort the chain? */
681 marker
->_next
= fp
->_markers
;
682 fp
->_markers
= marker
;
685 #define BAD_DELTA EOF
687 /* Return difference between MARK and current position of MARK's stream. */
689 _IO_wmarker_delta (mark
)
690 struct _IO_marker
*mark
;
693 if (mark
->_sbuf
== NULL
)
695 if (_IO_in_backup (mark
->_sbuf
))
696 cur_pos
= (mark
->_sbuf
->_wide_data
->_IO_read_ptr
697 - mark
->_sbuf
->_wide_data
->_IO_read_end
);
699 cur_pos
= (mark
->_sbuf
->_wide_data
->_IO_read_ptr
700 - mark
->_sbuf
->_wide_data
->_IO_read_base
);
701 return mark
->_pos
- cur_pos
;
705 _IO_seekwmark (fp
, mark
, delta
)
707 struct _IO_marker
*mark
;
710 if (mark
->_sbuf
!= fp
)
714 if (_IO_in_backup (fp
))
715 _IO_switch_to_main_wget_area (fp
);
716 fp
->_wide_data
->_IO_read_ptr
= (fp
->_wide_data
->_IO_read_base
721 if (!_IO_in_backup (fp
))
722 _IO_switch_to_wbackup_area (fp
);
723 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
+ mark
->_pos
;
729 _IO_unsave_wmarkers (fp
)
732 struct _IO_marker
*mark
= fp
->_markers
;
736 streampos offset
= seekoff (0, ios::cur
, ios::in
);
739 offset
+= eGptr () - Gbase ();
740 for ( ; mark
!= NULL
; mark
= mark
->_next
)
741 mark
->set_streampos (mark
->_pos
+ offset
);
745 for ( ; mark
!= NULL
; mark
= mark
->_next
)
746 mark
->set_streampos (EOF
);
752 if (_IO_have_backup (fp
))
753 _IO_free_wbackup_area (fp
);
756 #endif /* _GLIBCPP_USE_WCHAR_T */