libio: Remove the usage of __libc_IO_vtables
[platform/upstream/glibc.git] / stdio-common / printf_buffer_as_file.c
1 /* FILE * interface to a struct __printf_buffer.  Multibyte version.
2    Copyright (C) 2022-2023 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_as_file.h>
20
21 #include <assert.h>
22 #include <printf_buffer.h>
23
24 /* Commit the data directly written through the stdio stream.  */
25 static void
26 __printf_buffer_as_file_commit (struct __printf_buffer_as_file *file)
27 {
28   /* Check that the write pointers in the file stream are consistent
29      with the next buffer.  */
30   assert (file->stream._IO_write_ptr >= file->next->write_ptr);
31   assert (file->stream._IO_write_ptr <= file->next->write_end);
32   assert (file->stream._IO_write_base == file->next->write_base);
33   assert (file->stream._IO_write_end == file->next->write_end);
34
35   file->next->write_ptr = file->stream._IO_write_ptr;
36 }
37
38 /* Pointer the FILE * write buffer into the active printf_buffer
39    area.  */
40 static void
41 __printf_buffer_as_file_switch_to_buffer (struct __printf_buffer_as_file *file)
42 {
43   file->stream._IO_write_base = file->next->write_base;
44   file->stream._IO_write_ptr = file->next->write_ptr;
45   file->stream._IO_write_end = file->next->write_end;
46 }
47
48 /* Only a small subset of the vtable functions is implemented here,
49    following _IO_obstack_jumps.  */
50
51 int
52 __printf_buffer_as_file_overflow (FILE *fp, int ch)
53 {
54   struct __printf_buffer_as_file *file = (struct __printf_buffer_as_file *) fp;
55
56   __printf_buffer_as_file_commit (file);
57
58   /* EOF means only a flush is requested.   */
59   if (ch != EOF)
60     __printf_buffer_putc (file->next, ch);
61
62   /* Ensure that flushing actually produces room.  */
63   if (!__printf_buffer_has_failed (file->next)
64       && file->next->write_ptr == file->next->write_end)
65     __printf_buffer_flush (file->next);
66
67   __printf_buffer_as_file_switch_to_buffer (file);
68
69   if (!__printf_buffer_has_failed (file->next))
70     return (unsigned char) ch;
71   else
72     return EOF;
73 }
74
75 size_t
76 __printf_buffer_as_file_xsputn (FILE *fp, const void *buf, size_t len)
77 {
78   struct __printf_buffer_as_file *file = (struct __printf_buffer_as_file *) fp;
79
80   __printf_buffer_as_file_commit (file);
81
82   /* Copy the data.  */
83   __printf_buffer_write (file->next, buf, len);
84
85   __printf_buffer_as_file_switch_to_buffer (file);
86
87   if (!__printf_buffer_has_failed (file->next))
88     return len;
89   else
90     /* We may actually have written something.  But the stream is
91        corrupted in this case anyway, so try not to divine the write
92        count here.  */
93     return 0;
94 }
95
96 void
97 __printf_buffer_as_file_init (struct __printf_buffer_as_file *file,
98                               struct __printf_buffer *next)
99 {
100   file->stream._lock = NULL;
101   _IO_no_init (&file->stream, _IO_USER_LOCK, -1, NULL, NULL);
102   file->vtable = &_IO_printf_buffer_as_file_jumps;
103
104   /* Set up the write buffer from the next buffer.  */
105   file->next = next;
106   __printf_buffer_as_file_switch_to_buffer (file);
107
108   /* Mark the read area as inactive, by making all pointers equal.  */
109   file->stream._IO_read_base = file->stream._IO_write_base;
110   file->stream._IO_read_ptr = file->stream._IO_write_base;
111   file->stream._IO_read_end = file->stream._IO_write_base;
112 }
113
114 bool
115 __printf_buffer_as_file_terminate (struct __printf_buffer_as_file *file)
116 {
117   if (file->stream._flags & _IO_ERR_SEEN)
118     return false;
119   else
120     {
121       __printf_buffer_as_file_commit (file);
122       return true;
123     }
124 }