1/* Multibyte printf buffers writing data to a FILE * stream.
2 Copyright (C) 2022-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
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.
9
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.
14
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/>. */
18
19#include <printf_buffer_to_file.h>
20
21#include <assert.h>
22#include <array_length.h>
23#include <libio/libioP.h>
24
25/* Switch to the file buffer if possible. If the file has write_ptr
26 == write_end, use the stage buffer instead. */
27void
28__printf_buffer_to_file_switch (struct __printf_buffer_to_file *buf)
29{
30 if (buf->fp->_IO_write_ptr < buf->fp->_IO_write_end)
31 {
32 /* buf->fp has a buffer associated with it, so write directly to
33 it from now on. */
34 buf->base.write_ptr = buf->fp->_IO_write_ptr;
35 buf->base.write_end = buf->fp->_IO_write_end;
36 }
37 else
38 {
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);
42 }
43
44 buf->base.write_base = buf->base.write_ptr;
45}
46
47void
48__printf_buffer_flush_to_file (struct __printf_buffer_to_file *buf)
49{
50 /* The bytes in the buffer are always consumed. */
51 buf->base.written += buf->base.write_ptr - buf->base.write_base;
52
53 if (buf->base.write_end == array_end (buf->stage))
54 {
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)
60 {
61 __printf_buffer_mark_failed (buf: &buf->base);
62 return;
63 }
64 /* buf->fp may have a buffer now. */
65 __printf_buffer_to_file_switch (buf);
66 return;
67 }
68 else if (buf->base.write_end == buf->stage + 1)
69 {
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)
73 {
74 if (__overflow (buf->fp, (unsigned char) *buf->stage) == EOF)
75 {
76 __printf_buffer_mark_failed (buf: &buf->base);
77 return;
78 }
79 __printf_buffer_to_file_switch (buf);
80 }
81 /* Else there is nothing to write. */
82 return;
83 }
84
85 /* We have written directly into the buf->fp buffer. */
86 assert (buf->base.write_end == buf->fp->_IO_write_end);
87
88 /* Mark the bytes as written. */
89 buf->fp->_IO_write_ptr = buf->base.write_ptr;
90
91 if (buf->base.write_ptr == buf->base.write_end)
92 {
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;
100 }
101 /* The bytes in the file stream were already marked as written above. */
102
103 buf->base.write_base = buf->base.write_ptr;
104}
105
106void
107__printf_buffer_to_file_init (struct __printf_buffer_to_file *buf, FILE *fp)
108{
109 __printf_buffer_init (buf: &buf->base, base: buf->stage, array_length (buf->stage),
110 mode: __printf_buffer_mode_to_file);
111 buf->fp = fp;
112 __printf_buffer_to_file_switch (buf);
113}
114
115int
116__printf_buffer_to_file_done (struct __printf_buffer_to_file *buf)
117{
118 if (__printf_buffer_has_failed (buf: &buf->base))
119 return -1;
120 __printf_buffer_flush_to_file (buf);
121 return __printf_buffer_done (buf: &buf->base);
122}
123

source code of glibc/stdio-common/printf_buffer_to_file.c