1 /* Copyright (C) 1993,1995,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Written by Ulrich Drepper <drepper@cygnus.com>.
4 Based on the single byte version by Per Bothner <bothner@cygnus.com>.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 As a special exception, if you link the code in this file with
22 files compiled with a GNU compiler to produce an executable,
23 that does not cause the resulting executable to be covered by
24 the GNU Lesser General Public License. This exception does not
25 however invalidate any other reasons why the executable file
26 might be covered by the GNU Lesser General Public License.
27 This exception applies to code released by its copyright holders
28 in files containing the exception. */
30 /* Generic or default I/O operations. */
41 # define __wmemcpy(dst, src, n) wmemcpy (dst, src, n)
45 static int save_for_wbackup
__P ((_IO_FILE
*fp
, wchar_t *end_p
))
51 /* Return minimum _pos markers
52 Assumes the current get area is the main get area. */
53 _IO_ssize_t _IO_least_wmarker
__P ((_IO_FILE
*fp
, wchar_t *end_p
));
56 _IO_least_wmarker (fp
, end_p
)
60 _IO_ssize_t least_so_far
= end_p
- fp
->_wide_data
->_IO_read_base
;
61 struct _IO_marker
*mark
;
62 for (mark
= fp
->_markers
; mark
!= NULL
; mark
= mark
->_next
)
63 if (mark
->_pos
< least_so_far
)
64 least_so_far
= mark
->_pos
;
68 /* Switch current get area from backup buffer to (start of) main get area. */
70 _IO_switch_to_main_wget_area (fp
)
74 fp
->_flags
&= ~_IO_IN_BACKUP
;
75 /* Swap _IO_read_end and _IO_save_end. */
76 tmp
= fp
->_wide_data
->_IO_read_end
;
77 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_save_end
;
78 fp
->_wide_data
->_IO_save_end
= tmp
;
79 /* Swap _IO_read_base and _IO_save_base. */
80 tmp
= fp
->_wide_data
->_IO_read_base
;
81 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_save_base
;
82 fp
->_wide_data
->_IO_save_base
= tmp
;
83 /* Set _IO_read_ptr. */
84 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_base
;
88 /* Switch current get area from main get area to (end of) backup area. */
90 _IO_switch_to_wbackup_area (fp
)
94 fp
->_flags
|= _IO_IN_BACKUP
;
95 /* Swap _IO_read_end and _IO_save_end. */
96 tmp
= fp
->_wide_data
->_IO_read_end
;
97 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_save_end
;
98 fp
->_wide_data
->_IO_save_end
= tmp
;
99 /* Swap _IO_read_base and _IO_save_base. */
100 tmp
= fp
->_wide_data
->_IO_read_base
;
101 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_save_base
;
102 fp
->_wide_data
->_IO_save_base
= tmp
;
103 /* Set _IO_read_ptr. */
104 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
109 _IO_wsetb (f
, b
, eb
, a
)
115 if (f
->_wide_data
->_IO_buf_base
&& !(f
->_flags
& _IO_USER_BUF
))
116 FREE_BUF (f
->_wide_data
->_IO_buf_base
, _IO_wblen (f
));
117 f
->_wide_data
->_IO_buf_base
= b
;
118 f
->_wide_data
->_IO_buf_end
= eb
;
120 f
->_flags
&= ~_IO_USER_BUF
;
122 f
->_flags
|= _IO_USER_BUF
;
127 _IO_wdefault_pbackfail (fp
, c
)
131 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
132 && !_IO_in_backup (fp
)
133 && (wint_t) fp
->_IO_read_ptr
[-1] == c
)
137 /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
138 if (!_IO_in_backup (fp
))
140 /* We need to keep the invariant that the main get area
141 logically follows the backup area. */
142 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
143 && _IO_have_wbackup (fp
))
145 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_ptr
))
148 else if (!_IO_have_wbackup (fp
))
150 /* No backup buffer: allocate one. */
151 /* Use nshort buffer, if unused? (probably not) FIXME */
152 int backup_size
= 128;
153 wchar_t *bbuf
= (wchar_t *) malloc (backup_size
157 fp
->_wide_data
->_IO_save_base
= bbuf
;
158 fp
->_wide_data
->_IO_save_end
= (fp
->_wide_data
->_IO_save_base
160 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_save_end
;
162 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
;
163 _IO_switch_to_wbackup_area (fp
);
165 else if (fp
->_wide_data
->_IO_read_ptr
<= fp
->_wide_data
->_IO_read_base
)
167 /* Increase size of existing backup buffer. */
169 _IO_size_t old_size
= (fp
->_wide_data
->_IO_read_end
170 - fp
->_wide_data
->_IO_read_base
);
172 new_size
= 2 * old_size
;
173 new_buf
= (wchar_t *) malloc (new_size
* sizeof (wchar_t));
176 __wmemcpy (new_buf
+ (new_size
- old_size
),
177 fp
->_wide_data
->_IO_read_base
, old_size
);
178 free (fp
->_wide_data
->_IO_read_base
);
179 _IO_wsetg (fp
, new_buf
, new_buf
+ (new_size
- old_size
),
181 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_read_ptr
;
184 *--fp
->_wide_data
->_IO_read_ptr
= c
;
191 _IO_wdefault_finish (fp
, dummy
)
195 struct _IO_marker
*mark
;
196 if (fp
->_wide_data
->_IO_buf_base
&& !(fp
->_flags
& _IO_USER_BUF
))
198 FREE_BUF (fp
->_wide_data
->_IO_buf_base
,
199 _IO_wblen (fp
) * sizeof (wchar_t));
200 fp
->_wide_data
->_IO_buf_base
= fp
->_wide_data
->_IO_buf_end
= NULL
;
203 for (mark
= fp
->_markers
; mark
!= NULL
; mark
= mark
->_next
)
206 if (fp
->_IO_save_base
)
208 free (fp
->_wide_data
->_IO_save_base
);
209 fp
->_IO_save_base
= NULL
;
213 _IO_lock_fini (*fp
->_lock
);
216 _IO_un_link ((struct _IO_FILE_plus
*) fp
);
221 _IO_wdefault_uflow (fp
)
225 wch
= _IO_UNDERFLOW (fp
);
228 return *fp
->_wide_data
->_IO_read_ptr
++;
239 return _IO_OVERFLOW (f
, wch
);
247 if (fp
->_mode
< 0 || (fp
->_mode
== 0 && _IO_fwide (fp
, 1) != 1))
252 if (_IO_in_put_mode (fp
))
253 if (_IO_switch_to_wget_mode (fp
) == EOF
)
255 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
256 return *fp
->_wide_data
->_IO_read_ptr
++;
257 if (_IO_in_backup (fp
))
259 _IO_switch_to_main_wget_area (fp
);
260 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
261 return *fp
->_wide_data
->_IO_read_ptr
++;
263 if (_IO_have_markers (fp
))
265 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_end
))
268 else if (_IO_have_wbackup (fp
))
269 _IO_free_wbackup_area (fp
);
270 return _IO_UFLOW (fp
);
278 if (fp
->_mode
< 0 || (fp
->_mode
== 0 && _IO_fwide (fp
, 1) != 1))
283 if (_IO_in_put_mode (fp
))
284 if (_IO_switch_to_wget_mode (fp
) == EOF
)
286 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
287 return *fp
->_wide_data
->_IO_read_ptr
;
288 if (_IO_in_backup (fp
))
290 _IO_switch_to_main_wget_area (fp
);
291 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
292 return *fp
->_wide_data
->_IO_read_ptr
;
294 if (_IO_have_markers (fp
))
296 if (save_for_wbackup (fp
, fp
->_wide_data
->_IO_read_end
))
299 else if (_IO_have_backup (fp
))
300 _IO_free_wbackup_area (fp
);
301 return _IO_UNDERFLOW (fp
);
306 _IO_wdefault_xsputn (f
, data
, n
)
311 const wchar_t *s
= (const wchar_t *) data
;
317 /* Space available. */
318 _IO_ssize_t count
= (f
->_wide_data
->_IO_write_end
319 - f
->_wide_data
->_IO_write_ptr
);
322 if ((_IO_size_t
) count
> more
)
327 f
->_wide_data
->_IO_write_ptr
=
328 __wmempcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
330 memcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
331 f
->_wide_data
->_IO_write_ptr
+= count
;
339 wchar_t *p
= f
->_wide_data
->_IO_write_ptr
;
341 for (i
= count
; --i
>= 0; )
343 f
->_wide_data
->_IO_write_ptr
= p
;
347 if (more
== 0 || __woverflow (f
, *s
++) == WEOF
)
356 _IO_wdefault_xsgetn (fp
, data
, n
)
362 wchar_t *s
= (wchar_t*) data
;
365 /* Data available. */
366 _IO_ssize_t count
= (fp
->_wide_data
->_IO_read_end
367 - fp
->_wide_data
->_IO_read_ptr
);
370 if ((_IO_size_t
) count
> more
)
375 s
= __wmempcpy (s
, fp
->_wide_data
->_IO_read_ptr
, count
);
377 memcpy (s
, fp
->_wide_data
->_IO_read_ptr
, count
);
380 fp
->_wide_data
->_IO_read_ptr
+= count
;
386 wchar_t *p
= fp
->_wide_data
->_IO_read_ptr
;
390 fp
->_wide_data
->_IO_read_ptr
= p
;
394 if (more
== 0 || __wunderflow (fp
) == WEOF
)
405 if (fp
->_wide_data
->_IO_buf_base
)
407 if (!(fp
->_flags
& _IO_UNBUFFERED
))
408 if ((wint_t)_IO_WDOALLOCATE (fp
) != WEOF
)
410 _IO_wsetb (fp
, fp
->_wide_data
->_shortbuf
, fp
->_wide_data
->_shortbuf
+ 1, 0);
415 _IO_wdefault_setbuf (fp
, p
, len
)
420 if (_IO_SYNC (fp
) == EOF
)
422 if (p
== NULL
|| len
== 0)
424 fp
->_flags
|= _IO_UNBUFFERED
;
425 _IO_wsetb (fp
, fp
->_wide_data
->_shortbuf
, fp
->_wide_data
->_shortbuf
+ 1,
430 fp
->_flags
&= ~_IO_UNBUFFERED
;
431 _IO_wsetb (fp
, p
, p
+ len
, 0);
433 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
434 = fp
->_wide_data
->_IO_write_end
= 0;
435 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
436 = fp
->_wide_data
->_IO_read_end
= 0;
442 _IO_wdefault_doallocate (fp
)
447 ALLOC_WBUF (buf
, _IO_BUFSIZ
, EOF
);
448 _IO_wsetb (fp
, buf
, buf
+ _IO_BUFSIZ
, 1);
454 _IO_switch_to_wget_mode (fp
)
457 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_write_base
)
458 if ((wint_t)_IO_WOVERFLOW (fp
, WEOF
) == WEOF
)
460 if (_IO_in_backup (fp
))
461 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_backup_base
;
464 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_buf_base
;
465 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_read_end
)
466 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_write_ptr
;
468 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_write_ptr
;
470 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
471 = fp
->_wide_data
->_IO_write_end
= fp
->_wide_data
->_IO_read_ptr
;
473 fp
->_flags
&= ~_IO_CURRENTLY_PUTTING
;
478 _IO_free_wbackup_area (fp
)
481 if (_IO_in_backup (fp
))
482 _IO_switch_to_main_wget_area (fp
); /* Just in case. */
483 free (fp
->_wide_data
->_IO_save_base
);
484 fp
->_wide_data
->_IO_save_base
= NULL
;
485 fp
->_wide_data
->_IO_save_end
= NULL
;
486 fp
->_wide_data
->_IO_backup_base
= NULL
;
491 _IO_switch_to_wput_mode (fp
)
494 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_read_ptr
;
495 fp
->_wide_data
->_IO_write_ptr
= fp
->_wide_data
->_IO_read_ptr
;
496 /* Following is wrong if line- or un-buffered? */
497 fp
->_wide_data
->_IO_write_end
= (fp
->_flags
& _IO_IN_BACKUP
498 ? fp
->_wide_data
->_IO_read_end
499 : fp
->_wide_data
->_IO_buf_end
);
501 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
502 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_end
;
504 fp
->_flags
|= _IO_CURRENTLY_PUTTING
;
514 save_for_wbackup (fp
, end_p
)
518 /* Append [_IO_read_base..end_p] to backup area. */
519 _IO_ssize_t least_mark
= _IO_least_wmarker (fp
, end_p
);
520 /* needed_size is how much space we need in the backup area. */
521 _IO_size_t needed_size
= ((end_p
- fp
->_wide_data
->_IO_read_base
)
523 /* FIXME: Dubious arithmetic if pointers are NULL */
524 _IO_size_t current_Bsize
= (fp
->_wide_data
->_IO_save_end
525 - fp
->_wide_data
->_IO_save_base
);
526 _IO_size_t avail
; /* Extra space available for future expansion. */
528 struct _IO_marker
*mark
;
529 if (needed_size
> current_Bsize
)
533 new_buffer
= (wchar_t *) malloc ((avail
+ needed_size
)
535 if (new_buffer
== NULL
)
536 return EOF
; /* FIXME */
540 __wmempcpy (__wmempcpy (new_buffer
+ avail
,
541 fp
->_wide_data
->_IO_save_end
+ least_mark
,
543 fp
->_wide_data
->_IO_read_base
,
544 end_p
- fp
->_wide_data
->_IO_read_base
);
546 memcpy (new_buffer
+ avail
,
547 fp
->_wide_data
->_IO_save_end
+ least_mark
,
548 -least_mark
* sizeof (wchar_t));
549 memcpy (new_buffer
+ avail
- least_mark
,
550 fp
->_wide_data
->_IO_read_base
,
551 (end_p
- fp
->_wide_data
->_IO_read_base
) * sizeof (wchar_t));
557 __wmemcpy (new_buffer
+ avail
,
558 fp
->_wide_data
->_IO_read_base
+ least_mark
,
561 memcpy (new_buffer
+ avail
,
562 fp
->_wide_data
->_IO_read_base
+ least_mark
,
563 needed_size
* sizeof (wchar_t));
566 if (fp
->_wide_data
->_IO_save_base
)
567 free (fp
->_wide_data
->_IO_save_base
);
568 fp
->_wide_data
->_IO_save_base
= new_buffer
;
569 fp
->_wide_data
->_IO_save_end
= new_buffer
+ avail
+ needed_size
;
573 avail
= current_Bsize
- needed_size
;
577 __wmemmove (fp
->_wide_data
->_IO_save_base
+ avail
,
578 fp
->_wide_data
->_IO_save_end
+ least_mark
,
580 __wmemcpy (fp
->_wide_data
->_IO_save_base
+ avail
- least_mark
,
581 fp
->_wide_data
->_IO_read_base
,
582 end_p
- fp
->_wide_data
->_IO_read_base
);
584 memmove (fp
->_wide_data
->_IO_save_base
+ avail
,
585 fp
->_wide_data
->_IO_save_end
+ least_mark
,
586 -least_mark
* sizeof (wchar_t));
587 memcpy (fp
->_wide_data
->_IO_save_base
+ avail
- least_mark
,
588 fp
->_wide_data
->_IO_read_base
,
589 (end_p
- fp
->_wide_data
->_IO_read_base
) * sizeof (wchar_t));
592 else if (needed_size
> 0)
594 __wmemcpy (fp
->_wide_data
->_IO_save_base
+ avail
,
595 fp
->_wide_data
->_IO_read_base
+ least_mark
,
598 memcpy (fp
->_wide_data
->_IO_save_base
+ avail
,
599 fp
->_wide_data
->_IO_read_base
+ least_mark
,
600 needed_size
* sizeof (wchar_t));
603 fp
->_wide_data
->_IO_backup_base
= fp
->_wide_data
->_IO_save_base
+ avail
;
604 /* Adjust all the streammarkers. */
605 delta
= end_p
- fp
->_wide_data
->_IO_read_base
;
606 for (mark
= fp
->_markers
; mark
!= NULL
; mark
= mark
->_next
)
612 _IO_sputbackwc (fp
, c
)
618 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
619 && (wchar_t)fp
->_wide_data
->_IO_read_ptr
[-1] == (wchar_t) c
)
621 fp
->_wide_data
->_IO_read_ptr
--;
625 result
= _IO_PBACKFAIL (fp
, c
);
628 fp
->_flags
&= ~_IO_EOF_SEEN
;
639 if (fp
->_wide_data
->_IO_read_ptr
> fp
->_wide_data
->_IO_read_base
)
641 fp
->_wide_data
->_IO_read_ptr
--;
642 result
= *fp
->_wide_data
->_IO_read_ptr
;
645 result
= _IO_PBACKFAIL (fp
, EOF
);
648 fp
->_flags
&= ~_IO_EOF_SEEN
;
655 _IO_adjust_wcolumn (start
, line
, count
)
660 const wchar_t *ptr
= line
+ count
;
663 return line
+ count
- ptr
- 1;
664 return start
+ count
;
668 _IO_init_wmarker (marker
, fp
)
669 struct _IO_marker
*marker
;
673 if (_IO_in_put_mode (fp
))
674 _IO_switch_to_wget_mode (fp
);
675 if (_IO_in_backup (fp
))
676 marker
->_pos
= fp
->_wide_data
->_IO_read_ptr
- fp
->_wide_data
->_IO_read_end
;
678 marker
->_pos
= (fp
->_wide_data
->_IO_read_ptr
679 - fp
->_wide_data
->_IO_read_base
);
681 /* Should perhaps sort the chain? */
682 marker
->_next
= fp
->_markers
;
683 fp
->_markers
= marker
;
686 #define BAD_DELTA EOF
688 /* Return difference between MARK and current position of MARK's stream. */
690 _IO_wmarker_delta (mark
)
691 struct _IO_marker
*mark
;
694 if (mark
->_sbuf
== NULL
)
696 if (_IO_in_backup (mark
->_sbuf
))
697 cur_pos
= (mark
->_sbuf
->_wide_data
->_IO_read_ptr
698 - mark
->_sbuf
->_wide_data
->_IO_read_end
);
700 cur_pos
= (mark
->_sbuf
->_wide_data
->_IO_read_ptr
701 - mark
->_sbuf
->_wide_data
->_IO_read_base
);
702 return mark
->_pos
- cur_pos
;
706 _IO_seekwmark (fp
, mark
, delta
)
708 struct _IO_marker
*mark
;
711 if (mark
->_sbuf
!= fp
)
715 if (_IO_in_backup (fp
))
716 _IO_switch_to_main_wget_area (fp
);
717 fp
->_wide_data
->_IO_read_ptr
= (fp
->_wide_data
->_IO_read_base
722 if (!_IO_in_backup (fp
))
723 _IO_switch_to_wbackup_area (fp
);
724 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
+ mark
->_pos
;
730 _IO_unsave_wmarkers (fp
)
733 struct _IO_marker
*mark
= fp
->_markers
;
737 streampos offset
= seekoff (0, ios::cur
, ios::in
);
740 offset
+= eGptr () - Gbase ();
741 for ( ; mark
!= NULL
; mark
= mark
->_next
)
742 mark
->set_streampos (mark
->_pos
+ offset
);
746 for ( ; mark
!= NULL
; mark
= mark
->_next
)
747 mark
->set_streampos (EOF
);
753 if (_IO_have_backup (fp
))
754 _IO_free_wbackup_area (fp
);