xref: /freebsd/contrib/pkgconf/libpkgconf/output.c (revision 592efe252472a3385acf36b1f49ecf710a7f3d9c)
1 /*
2  * output.c
3  * I/O abstraction layer
4  *
5  * SPDX-License-Identifier: pkgconf
6  *
7  * Copyright (c) 2025 pkgconf authors (see AUTHORS).
8  *
9  * Permission to use, copy, modify, and/or distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * This software is provided 'as is' and without any warranty, express or
14  * implied.  In no event shall the authors be liable for any damages arising
15  * from the use of this software.
16  */
17 
18 #include <libpkgconf/stdinc.h>
19 #include <libpkgconf/libpkgconf.h>
20 
21 bool
pkgconf_output_putbuf(pkgconf_output_t * output,pkgconf_output_stream_t stream,const pkgconf_buffer_t * buffer,bool newline)22 pkgconf_output_putbuf(pkgconf_output_t *output, pkgconf_output_stream_t stream, const pkgconf_buffer_t *buffer, bool newline)
23 {
24 	bool ret;
25 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
26 
27 	if (pkgconf_buffer_len(buffer) != 0)
28 		pkgconf_buffer_append(&buf, pkgconf_buffer_str(buffer));
29 
30 	if (newline)
31 		pkgconf_buffer_push_byte(&buf, '\n');
32 
33 	ret = output->write(output, stream, &buf);
34 	pkgconf_buffer_finalize(&buf);
35 
36 	return ret;
37 }
38 
39 bool
pkgconf_output_puts(pkgconf_output_t * output,pkgconf_output_stream_t stream,const char * str)40 pkgconf_output_puts(pkgconf_output_t *output, pkgconf_output_stream_t stream, const char *str)
41 {
42 	bool ret;
43 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
44 
45 	pkgconf_buffer_append(&buf, str);
46 	pkgconf_buffer_push_byte(&buf, '\n');
47 	ret = output->write(output, stream, &buf);
48 	pkgconf_buffer_finalize(&buf);
49 
50 	return ret;
51 }
52 
53 bool
pkgconf_output_fmt(pkgconf_output_t * output,pkgconf_output_stream_t stream,const char * fmt,...)54 pkgconf_output_fmt(pkgconf_output_t *output, pkgconf_output_stream_t stream, const char *fmt, ...)
55 {
56 	bool ret;
57 	va_list va;
58 
59 	va_start(va, fmt);
60 	ret = pkgconf_output_vfmt(output, stream, fmt, va);
61 	va_end(va);
62 
63 	return ret;
64 }
65 
66 bool
pkgconf_output_vfmt(pkgconf_output_t * output,pkgconf_output_stream_t stream,const char * fmt,va_list src_va)67 pkgconf_output_vfmt(pkgconf_output_t *output, pkgconf_output_stream_t stream, const char *fmt, va_list src_va)
68 {
69 	va_list va;
70 	bool ret;
71 	pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
72 
73 	va_copy(va, src_va);
74 	pkgconf_buffer_append_vfmt(&buf, fmt, va);
75 	va_end(va);
76 
77 	ret = output->write(output, stream, &buf);
78 	pkgconf_buffer_finalize(&buf);
79 
80 	return ret;
81 }
82 
83 static bool
pkgconf_output_stdio_write(pkgconf_output_t * output,pkgconf_output_stream_t stream,const pkgconf_buffer_t * buffer)84 pkgconf_output_stdio_write(pkgconf_output_t *output, pkgconf_output_stream_t stream, const pkgconf_buffer_t *buffer)
85 {
86 	(void) output;
87 
88 	FILE *target = stream == PKGCONF_OUTPUT_STDERR ? stderr : stdout;
89 
90 	if (buffer != NULL)
91 	{
92 		const char *str = pkgconf_buffer_str(buffer);
93 		size_t size = pkgconf_buffer_len(buffer);
94 
95 		if (size > 0 && !fwrite(str, size, 1, target))
96 			return false;
97 	}
98 
99 	fflush(target);
100 	return true;
101 }
102 
103 static pkgconf_output_t pkgconf_default_output = {
104 	.privdata = NULL,
105 	.write = pkgconf_output_stdio_write,
106 };
107 
108 pkgconf_output_t *
pkgconf_output_default(void)109 pkgconf_output_default(void)
110 {
111 	return &pkgconf_default_output;
112 }
113 
114 /*
115  * !doc
116  *
117  * .. c:function:: bool pkgconf_output_file_vfmt(FILE *f, const char *fmt, va_list va)
118  *
119  *    Wrapper around :code:`vfprintf` that returns a boolean.
120  *
121  *    :param FILE *f: Pointer to an open `FILE` pointer.
122  *    :param: const char *fmt: Format string.
123  *    :param va_list va: Variable list.
124  *    :return: :code:`true` on success, :code:`false` on failure.
125  */
126 bool
pkgconf_output_file_vfmt(FILE * f,const char * fmt,va_list va)127 pkgconf_output_file_vfmt(FILE *f, const char *fmt, va_list va)
128 {
129 	int ret = vfprintf(f, fmt, va);
130 	return ret >= 0;
131 }
132 
133 /*
134  * !doc
135  *
136  * .. c:function:: bool pkgconf_output_file_fmt(FILE *f, const char *fmt, va_list va)
137  *
138  *    Wrapper around :code:`fprintf` that returns a boolean.
139  *
140  *    :param FILE *f: Pointer to an open `FILE` pointer.
141  *    :param: const char *fmt: Format string.
142  *    :return: :code:`true` on success, :code:`false` on failure.
143  */
144 bool
pkgconf_output_file_fmt(FILE * f,const char * fmt,...)145 pkgconf_output_file_fmt(FILE *f, const char *fmt, ...)
146 {
147 	va_list va;
148 	va_start(va, fmt);
149 	bool ret = pkgconf_output_file_vfmt(f, fmt, va);
150 	va_end(va);
151 
152 	return ret;
153 }
154