1 /* Multibyte printf buffers writing data to a FILE * stream.
2 Copyright (C) 2022-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C 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 GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <printf_buffer_to_file.h>
22 #include <array_length.h>
23 #include <libio/libioP.h>
25 /* Switch to the file buffer if possible. If the file has write_ptr
26 == write_end, use the stage buffer instead. */
28 __printf_buffer_to_file_switch (struct __printf_buffer_to_file
*buf
)
30 if (buf
->fp
->_IO_write_ptr
< buf
->fp
->_IO_write_end
)
32 /* buf->fp has a buffer associated with it, so write directly to
34 buf
->base
.write_ptr
= buf
->fp
->_IO_write_ptr
;
35 buf
->base
.write_end
= buf
->fp
->_IO_write_end
;
39 /* Use the staging area if no buffer is available in buf->fp. */
40 buf
->base
.write_ptr
= buf
->stage
;
41 buf
->base
.write_end
= array_end (buf
->stage
);
44 buf
->base
.write_base
= buf
->base
.write_ptr
;
48 __printf_buffer_flush_to_file (struct __printf_buffer_to_file
*buf
)
50 /* The bytes in the buffer are always consumed. */
51 buf
->base
.written
+= buf
->base
.write_ptr
- buf
->base
.write_base
;
53 if (buf
->base
.write_end
== array_end (buf
->stage
))
55 /* If the stage buffer is used, make a copy into the file. The
56 stage buffer is always consumed fully, even if just partially
57 written, to ensure that the file stream has all the data. */
58 size_t count
= buf
->base
.write_ptr
- buf
->stage
;
59 if ((size_t) _IO_sputn (buf
->fp
, buf
->stage
, count
) != count
)
61 __printf_buffer_mark_failed (&buf
->base
);
64 /* buf->fp may have a buffer now. */
65 __printf_buffer_to_file_switch (buf
);
68 else if (buf
->base
.write_end
== buf
->stage
+ 1)
70 /* Special one-character buffer case. This is used to avoid
71 flush-only overflow below. */
72 if (buf
->base
.write_ptr
== buf
->base
.write_end
)
74 if (__overflow (buf
->fp
, (unsigned char) *buf
->stage
) == EOF
)
76 __printf_buffer_mark_failed (&buf
->base
);
79 __printf_buffer_to_file_switch (buf
);
81 /* Else there is nothing to write. */
85 /* We have written directly into the buf->fp buffer. */
86 assert (buf
->base
.write_end
== buf
->fp
->_IO_write_end
);
88 /* Mark the bytes as written. */
89 buf
->fp
->_IO_write_ptr
= buf
->base
.write_ptr
;
91 if (buf
->base
.write_ptr
== buf
->base
.write_end
)
93 /* The buffer in buf->fp has been filled. This should just call
94 __overflow (buf->fp, EOF), but flush-only overflow is obscure
95 and not always correctly implemented. See bug 28949. Be
96 conservative and switch to a one-character buffer instead, to
97 obtain one more character for a regular __overflow call. */
98 buf
->base
.write_ptr
= buf
->stage
;
99 buf
->base
.write_end
= buf
->stage
+ 1;
101 /* The bytes in the file stream were already marked as written above. */
103 buf
->base
.write_base
= buf
->base
.write_ptr
;
107 __printf_buffer_to_file_init (struct __printf_buffer_to_file
*buf
, FILE *fp
)
109 __printf_buffer_init (&buf
->base
, buf
->stage
, array_length (buf
->stage
),
110 __printf_buffer_mode_to_file
);
112 __printf_buffer_to_file_switch (buf
);
116 __printf_buffer_to_file_done (struct __printf_buffer_to_file
*buf
)
118 if (__printf_buffer_has_failed (&buf
->base
))
120 __printf_buffer_flush_to_file (buf
);
121 return __printf_buffer_done (&buf
->base
);