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