2 * This file is part of DisOrder
3 * Copyright (C) 2004, 2007-9, 2013 Richard Kettlewell
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program 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
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * @brief Abstract output sink type
34 /** @brief Formatted output to a sink
35 * @param s Sink to write to
36 * @param fmt Format string
37 * @param ap Argument list
38 * @return Number of bytes written on success, -1 on error
40 int sink_vprintf(struct sink
*s
, const char *fmt
, va_list ap
) {
41 return byte_vsinkprintf(s
, fmt
, ap
);
44 /** @brief Formatted output to a sink
45 * @param s Sink to write to
46 * @param fmt Format string
47 * @return Number of bytes written on success, -1 on error
49 int sink_printf(struct sink
*s
, const char *fmt
, ...) {
54 n
= byte_vsinkprintf(s
, fmt
, ap
);
59 static int sink_generic_flush(struct sink
attribute((unused
)) *s
) {
63 static int sink_generic_error(struct sink
attribute((unused
)) *s
) {
67 /* stdio sink *****************************************************************/
69 /** @brief Sink that writes to a stdio @c FILE */
71 /** @brief Base member */
74 /** @brief Filename */
77 /** @brief Stream to write to */
83 /** @brief Reinterpret a @ref sink as a @ref stdio_sink */
84 #define S(s) ((struct stdio_sink *)s)
86 /** @brief Write callback for @ref stdio_sink */
87 static int sink_stdio_write(struct sink
*s
, const void *buffer
, int nbytes
) {
88 int n
= fwrite(buffer
, 1, nbytes
, S(s
)->fp
);
92 disorder_fatal(errno
, "error writing to %s", S(s
)->name
);
99 static int sink_stdio_error(struct sink
*s
) {
103 /** @brief Create a sink that writes to a stdio stream
104 * @param name Filename for use in error messages
105 * @param fp Stream to write to
106 * @return Pointer to new sink
108 struct sink
*sink_stdio(const char *name
, FILE *fp
) {
109 struct stdio_sink
*s
= xmalloc(sizeof *s
);
111 s
->s
.write
= sink_stdio_write
;
112 s
->s
.flush
= sink_generic_flush
;
113 s
->s
.error
= sink_stdio_error
;
114 s
->s
.eclass
= ec_errno
;
117 return (struct sink
*)s
;
120 /* dynstr sink ****************************************************************/
122 /** @brief Sink that writes to a dynamic string */
124 /** @brief Base member */
126 /** @brief Pointer to dynamic string to append to */
130 /** @brief Write callback for @ref dynstr_sink */
131 static int sink_dynstr_write(struct sink
*s
, const void *buffer
, int nbytes
) {
132 dynstr_append_bytes(((struct dynstr_sink
*)s
)->d
, buffer
, nbytes
);
136 /** @brief Create a sink that appends to a @ref dynstr
137 * @param output Dynamic string to append to
138 * @return Pointer to new sink
140 struct sink
*sink_dynstr(struct dynstr
*output
) {
141 struct dynstr_sink
*s
= xmalloc(sizeof *s
);
143 s
->s
.write
= sink_dynstr_write
;
144 s
->s
.flush
= sink_generic_flush
;
145 s
->s
.error
= sink_generic_error
;
146 s
->s
.eclass
= ec_errno
;
148 return (struct sink
*)s
;
151 /* discard sink **************************************************************/
153 static int sink_discard_write(struct sink
attribute((unused
)) *s
,
154 const void attribute((unused
)) *buffer
,
159 /** @brief Return a sink which discards all output */
160 struct sink
*sink_discard(void) {
161 struct sink
*s
= xmalloc(sizeof *s
);
163 s
->write
= sink_discard_write
;
164 s
->flush
= sink_generic_flush
;
165 s
->error
= sink_generic_error
;
166 s
->eclass
= ec_errno
;
170 /* error sink **************************************************************/
172 static int sink_error_write(struct sink
attribute((unused
)) *s
,
173 const void attribute((unused
)) *buffer
,
174 int attribute((unused
)) nbytes
) {
178 /** @brief Return a sink which discards all output */
179 struct sink
*sink_error(void) {
180 struct sink
*s
= xmalloc(sizeof *s
);
182 s
->write
= sink_error_write
;
183 s
->flush
= sink_generic_flush
;
184 s
->error
= sink_generic_error
;
185 s
->eclass
= ec_errno
;
189 /* socket sink *************************************************************/
191 /** @brief Sink that writes to a socket handle */
192 struct socketio_sink
{
193 /** @brief Base member */
196 struct socketio
*sio
;
199 static int sink_socketio_flush(struct sink
*s
) {
200 struct socketio_sink
*ss
= (struct socketio_sink
*)s
;
201 return socketio_flush(ss
->sio
);
204 /** @brief Write callback for @ref stdio_sink */
205 static int sink_socketio_write(struct sink
*s
, const void *buffer
, int nbytes
) {
206 struct socketio_sink
*ss
= (struct socketio_sink
*)s
;
207 return socketio_write(ss
->sio
, buffer
, nbytes
);
210 static int sink_socketio_error(struct sink
*s
) {
211 struct socketio_sink
*ss
= (struct socketio_sink
*)s
;
212 return socketio_error(ss
->sio
);
215 /** @brief Create a sink that writes to a socket
216 * @param sio Socket IO context
217 * @return Pointer to new sink
219 struct sink
*sink_socketio(struct socketio
*sio
) {
220 struct socketio_sink
*s
= xmalloc(sizeof *s
);
222 s
->s
.write
= sink_socketio_write
;
223 s
->s
.flush
= sink_socketio_flush
;
224 s
->s
.error
= sink_socketio_error
;
225 s
->s
.eclass
= ec_native
;
230 /* stdio source *************************************************************/
232 /** @brief Source that reads from a socket handle */
233 struct stdio_source
{
234 /** @brief Base member */
240 static int source_stdio_getc(struct source
*s
) {
241 return getc(((struct stdio_source
*)s
)->fp
);
244 static int source_stdio_error(struct source
*s
) {
245 FILE *fp
= ((struct stdio_source
*)s
)->fp
;
248 return GetLastError();
256 static int source_stdio_eof(struct source
*s
) {
257 FILE *fp
= ((struct stdio_source
*)s
)->fp
;
261 struct source
*source_stdio(FILE *fp
) {
262 struct stdio_source
*ss
= xmalloc(sizeof *ss
);
263 ss
->s
.getch
= source_stdio_getc
;
264 ss
->s
.error
= source_stdio_error
;
265 ss
->s
.eof
= source_stdio_eof
;
266 ss
->s
.eclass
= ec_errno
;
268 return (struct source
*)ss
;
271 /* socket source ***********************************************************/
273 /** @brief Source that reads from a socket handle */
274 struct socket_source
{
275 /** @brief Base member */
278 struct socketio
*sio
;
281 static int source_socketio_getc(struct source
*s
) {
282 return socketio_getc(((struct socket_source
*)s
)->sio
);
285 static int source_socketio_error(struct source
*s
) {
286 return socketio_error(((struct socket_source
*)s
)->sio
);
288 static int source_socketio_eof(struct source
*s
) {
289 return socketio_eof(((struct socket_source
*)s
)->sio
);
292 struct source
*source_socketio(struct socketio
*sio
) {
293 struct socket_source
*ss
= xmalloc(sizeof *ss
);
294 ss
->s
.getch
= source_socketio_getc
;
295 ss
->s
.error
= source_socketio_error
;
296 ss
->s
.eof
= source_socketio_eof
;
297 ss
->s
.eclass
= ec_native
;
299 return (struct source
*)ss
;