blob: c52fcb86da56ce9c287cdb5e7e8fe4b03b6787e7 [file] [log] [blame]
Radek Krejcia5bba312020-01-09 15:41:20 +01001/**
Michal Vaskoafac7822020-10-20 14:22:26 +02002 * @file out.h
Radek Krejcia5bba312020-01-09 15:41:20 +01003 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vaskoafac7822020-10-20 14:22:26 +02004 * @brief libyang output structures and functions
Radek Krejcia5bba312020-01-09 15:41:20 +01005 *
Michal Vaskoafac7822020-10-20 14:22:26 +02006 * Copyright (c) 2015-2020 CESNET, z.s.p.o.
Radek Krejcia5bba312020-01-09 15:41:20 +01007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
Michal Vaskoafac7822020-10-20 14:22:26 +020015#ifndef LY_OUT_H_
16#define LY_OUT_H_
Radek Krejcia5bba312020-01-09 15:41:20 +010017
Radek Krejci535ea9f2020-05-29 16:01:05 +020018#include <stdio.h>
Radek Krejcia5bba312020-01-09 15:41:20 +010019#include <unistd.h>
20
Radek Krejci535ea9f2020-05-29 16:01:05 +020021#include "log.h"
22
Radek Krejcica376bd2020-06-11 16:04:06 +020023#ifdef __cplusplus
24extern "C" {
25#endif
26
Radek Krejcia5bba312020-01-09 15:41:20 +010027/**
Michal Vaskoafac7822020-10-20 14:22:26 +020028 * @page howtoOutput Output Processing
Radek Krejci8678fa42020-08-18 16:07:28 +020029 *
Michal Vaskoafac7822020-10-20 14:22:26 +020030 * libyang provides a mechanism to generalize work with the outputs (and [inputs](@ref howtoInput)) of
Radek Krejci8678fa42020-08-18 16:07:28 +020031 * the different types. The ::ly_out handler can be created providing necessary information connected with the specific
32 * output type and then used throughout the printers functions. The API allows to combine output from libyang (data or schema)
33 * printers and output directly provided by the caller (via ::ly_print() or ::ly_write()).
34 *
35 * Using a generic output handler avoids need to have a set of functions for each printer functionality and results in simpler API.
36 *
37 * The API allows to alter the target of the data behind the handler by another target (of the same type). Also reseting
38 * a seekable output is possible with ::ly_out_reset() to re-write the output.
39 *
40 * @note
41 * This mechanism was introduced in libyang 2.0. To simplify transition from libyang 1.0 to version 2.0 and also for
42 * some simple use case where using the output handler would be an overkill, there are some basic printer functions
43 * that do not require output handler. But remember, that functionality of these function can be limited in particular cases
44 * in contrast to the functions using output handlers.
45 *
46 * Functions List
47 * --------------
48 * - ::ly_out_new_clb()
49 * - ::ly_out_new_fd()
50 * - ::ly_out_new_file()
51 * - ::ly_out_new_filepath()
52 * - ::ly_out_new_memory()
53 *
54 * - ::ly_out_clb()
55 * - ::ly_out_clb_arg()
56 * - ::ly_out_fd()
57 * - ::ly_out_file()
58 * - ::ly_out_filepath()
59 * - ::ly_out_memory()
60 *
61 * - ::ly_out_type()
62 * - ::ly_out_printed()
63 *
64 * - ::ly_out_reset()
65 * - ::ly_out_free()
66 *
67 * - ::ly_print()
68 * - ::ly_print_flush()
69 * - ::ly_write()
70 *
71 * libyang Printers List
72 * --------------------
73 * - @subpage howtoSchemaPrinters
74 * - @subpage howtoDataPrinters
75 */
76
77/**
78 * @struct ly_out
Radek Krejcia5bba312020-01-09 15:41:20 +010079 * @brief Printer output structure specifying where the data are printed.
80 */
Radek Krejci241f6b52020-05-21 18:13:49 +020081struct ly_out;
Radek Krejcia5bba312020-01-09 15:41:20 +010082
83/**
Radek Krejci52f65552020-09-01 17:03:35 +020084 * @brief Common value for data as well as schema printers to avoid formatting indentations and new lines
85 */
86#define LY_PRINT_SHRINK 0x02
87
88/**
Radek Krejcia5bba312020-01-09 15:41:20 +010089 * @brief Types of the printer's output
90 */
Radek Krejci241f6b52020-05-21 18:13:49 +020091typedef enum LY_OUT_TYPE {
92 LY_OUT_ERROR = -1, /**< error value to indicate failure of the functions returning LY_OUT_TYPE */
93 LY_OUT_FD, /**< file descriptor printer */
94 LY_OUT_FDSTREAM, /**< internal replacement for LY_OUT_FD in case vdprintf() is not available */
95 LY_OUT_FILE, /**< FILE stream printer */
96 LY_OUT_FILEPATH, /**< filepath printer */
97 LY_OUT_MEMORY, /**< memory printer */
98 LY_OUT_CALLBACK /**< callback printer */
99} LY_OUT_TYPE;
Radek Krejcia5bba312020-01-09 15:41:20 +0100100
101/**
102 * @brief Get output type of the printer handler.
103 *
104 * @param[in] out Printer handler.
105 * @return Type of the printer's output.
106 */
Radek Krejci241f6b52020-05-21 18:13:49 +0200107LY_OUT_TYPE ly_out_type(const struct ly_out *out);
Radek Krejcia5bba312020-01-09 15:41:20 +0100108
109/**
110 * @brief Reset the output medium to write from its beginning, so the following printer function will rewrite the current data
111 * instead of appending.
112 *
113 * Note that in case the underlying output is not seekable (stream referring a pipe/FIFO/socket or the callback output type),
114 * nothing actually happens despite the function succeeds. Also note that the medium is not returned to the state it was when
Radek Krejcic5a12e12020-05-27 17:09:59 +0200115 * the handler was created. For example, file is seeked into the offset zero and truncated, the content from the time it was opened with
Radek Krejci8678fa42020-08-18 16:07:28 +0200116 * ::ly_out_new_file() is not restored.
Radek Krejcia5bba312020-01-09 15:41:20 +0100117 *
118 * @param[in] out Printer handler.
119 * @return LY_SUCCESS in case of success
120 * @return LY_ESYS in case of failure
121 */
Radek Krejci241f6b52020-05-21 18:13:49 +0200122LY_ERR ly_out_reset(struct ly_out *out);
Radek Krejcia5bba312020-01-09 15:41:20 +0100123
124/**
Michal Vaskoce2b8742020-08-24 13:20:25 +0200125 * @brief Generic write callback for data printed by libyang.
126 *
127 * @param[in] user_data Optional caller-specific argument.
128 * @param[in] buf Data to write.
129 * @param[in] count Number of bytes to write.
130 * @return Number of printed bytes.
131 * @return Negative value in case of error.
132 */
133typedef ssize_t (*ly_write_clb)(void *user_data, const void *buf, size_t count);
134
135/**
Radek Krejcia5bba312020-01-09 15:41:20 +0100136 * @brief Create printer handler using callback printer function.
137 *
138 * @param[in] writeclb Pointer to the printer callback function writing the data (see write(2)).
Michal Vaskoce2b8742020-08-24 13:20:25 +0200139 * @param[in] user_data Optional caller-specific argument to be passed to the @p writeclb callback.
Radek Krejci84ce7b12020-06-11 17:28:25 +0200140 * @param[out] out Created printer handler supposed to be passed to different ly*_print() functions.
141 * @return LY_SUCCESS in case of success
142 * @return LY_EMEM in case allocating the @p out handler fails.
Radek Krejcia5bba312020-01-09 15:41:20 +0100143 */
Michal Vaskoce2b8742020-08-24 13:20:25 +0200144LY_ERR ly_out_new_clb(ly_write_clb writeclb, void *user_data, struct ly_out **out);
Radek Krejcia5bba312020-01-09 15:41:20 +0100145
146/**
147 * @brief Get or reset callback function associated with a callback printer handler.
148 *
149 * @param[in] out Printer handler.
Radek Krejci8678fa42020-08-18 16:07:28 +0200150 * @param[in] writeclb Optional argument providing a new printer callback function for the handler. If NULL, only the current
151 * printer callback is returned.
152 * @return Previous printer callback.
Radek Krejcia5bba312020-01-09 15:41:20 +0100153 */
Michal Vaskoce2b8742020-08-24 13:20:25 +0200154ly_write_clb ly_out_clb(struct ly_out *out, ly_write_clb writeclb);
Radek Krejcia5bba312020-01-09 15:41:20 +0100155
156/**
157 * @brief Get or reset callback function's argument aasociated with a callback printer handler.
158 *
159 * @param[in] out Printer handler.
160 * @param[in] arg caller-specific argument to be passed to the callback function associated with the printer handler.
161 * If NULL, only the current file descriptor value is returned.
162 * @return The previous callback argument.
163 */
Radek Krejci241f6b52020-05-21 18:13:49 +0200164void *ly_out_clb_arg(struct ly_out *out, void *arg);
Radek Krejcia5bba312020-01-09 15:41:20 +0100165
166/**
167 * @brief Create printer handler using file descriptor.
168 *
169 * @param[in] fd File descriptor to use.
Radek Krejci84ce7b12020-06-11 17:28:25 +0200170 * @param[out] out Created printer handler supposed to be passed to different ly*_print() functions.
171 * @return LY_SUCCESS in case of success
172 * @return LY_ERR value in case of failure.
Radek Krejcia5bba312020-01-09 15:41:20 +0100173 */
Radek Krejci84ce7b12020-06-11 17:28:25 +0200174LY_ERR ly_out_new_fd(int fd, struct ly_out **out);
Radek Krejcia5bba312020-01-09 15:41:20 +0100175
176/**
177 * @brief Get or reset file descriptor printer handler.
178 *
179 * @param[in] out Printer handler.
180 * @param[in] fd Optional value of a new file descriptor for the handler. If -1, only the current file descriptor value is returned.
181 * @return Previous value of the file descriptor. Note that caller is responsible for closing the returned file descriptor in case of setting new descriptor @p fd.
182 * @return -1 in case of error when setting up the new file descriptor.
183 */
Radek Krejci241f6b52020-05-21 18:13:49 +0200184int ly_out_fd(struct ly_out *out, int fd);
Radek Krejcia5bba312020-01-09 15:41:20 +0100185
186/**
187 * @brief Create printer handler using file stream.
188 *
189 * @param[in] f File stream to use.
Radek Krejci84ce7b12020-06-11 17:28:25 +0200190 * @param[out] out Created printer handler supposed to be passed to different ly*_print() functions.
191 * @return LY_SUCCESS in case of success
192 * @return LY_ERR value in case of failure.
Radek Krejcia5bba312020-01-09 15:41:20 +0100193 */
Radek Krejci84ce7b12020-06-11 17:28:25 +0200194LY_ERR ly_out_new_file(FILE *f, struct ly_out **out);
Radek Krejcia5bba312020-01-09 15:41:20 +0100195
196/**
197 * @brief Get or reset file stream printer handler.
198 *
199 * @param[in] out Printer handler.
200 * @param[in] f Optional new file stream for the handler. If NULL, only the current file stream is returned.
201 * @return Previous file stream of the handler. Note that caller is responsible for closing the returned stream in case of setting new stream @p f.
202 */
Radek Krejci241f6b52020-05-21 18:13:49 +0200203FILE *ly_out_file(struct ly_out *out, FILE *f);
Radek Krejcia5bba312020-01-09 15:41:20 +0100204
205/**
206 * @brief Create printer handler using memory to dump data.
207 *
208 * @param[in] strp Pointer to store the resulting data. If it points to a pointer to an allocated buffer and
209 * @p size of the buffer is set, the buffer is used (and extended if needed) to store the printed data.
210 * @param[in] size Size of the buffer provided via @p strp. In case it is 0, the buffer for the printed data
211 * is newly allocated even if @p strp points to a pointer to an existing buffer.
Radek Krejci84ce7b12020-06-11 17:28:25 +0200212 * @param[out] out Created printer handler supposed to be passed to different ly*_print() functions.
213 * @return LY_SUCCESS in case of success
214 * @return LY_ERR value in case of failure.
Radek Krejcia5bba312020-01-09 15:41:20 +0100215 */
Radek Krejci84ce7b12020-06-11 17:28:25 +0200216LY_ERR ly_out_new_memory(char **strp, size_t size, struct ly_out **out);
Radek Krejcia5bba312020-01-09 15:41:20 +0100217
218/**
219 * @brief Get or change memory where the data are dumped.
220 *
221 * @param[in] out Printer handler.
Radek Krejci8678fa42020-08-18 16:07:28 +0200222 * @param[in] strp Optional new string pointer to store the resulting data, same rules as in ::ly_out_new_memory() are applied.
Radek Krejcia5bba312020-01-09 15:41:20 +0100223 * @param[in] size Size of the buffer provided via @p strp. In case it is 0, the buffer for the printed data
Radek Krejcibaeb8382020-05-27 16:44:53 +0200224 * is newly allocated even if @p strp points to a pointer to an existing buffer. In case the @p strp is NULL, this
225 * parameter is ignored.
Radek Krejcia5bba312020-01-09 15:41:20 +0100226 * @return Previous dumped data. Note that the caller is responsible to free the data in case of changing string pointer @p strp.
227 */
Radek Krejci241f6b52020-05-21 18:13:49 +0200228char *ly_out_memory(struct ly_out *out, char **strp, size_t size);
Radek Krejcia5bba312020-01-09 15:41:20 +0100229
230/**
231 * @brief Create printer handler file of the given filename.
232 *
233 * @param[in] filepath Path of the file where to write data.
Radek Krejci8678fa42020-08-18 16:07:28 +0200234 * @param[out] out Created printer handler supposed to be passed to different ly*_print() functions.
Radek Krejcia5bba312020-01-09 15:41:20 +0100235 * @return NULL in case of error.
236 * @return Created printer handler supposed to be passed to different ly*_print_*() functions.
237 */
Radek Krejci84ce7b12020-06-11 17:28:25 +0200238LY_ERR ly_out_new_filepath(const char *filepath, struct ly_out **out);
Radek Krejcia5bba312020-01-09 15:41:20 +0100239
240/**
241 * @brief Get or change the filepath of the file where the printer prints the data.
242 *
243 * Note that in case of changing the filepath, the current file is closed and a new one is
244 * created/opened instead of renaming the previous file. Also note that the previous filepath
245 * string is returned only in case of not changing it's value.
246 *
247 * @param[in] out Printer handler.
248 * @param[in] filepath Optional new filepath for the handler. If and only if NULL, the current filepath string is returned.
249 * @return Previous filepath string in case the @p filepath argument is NULL.
250 * @return NULL if changing filepath succeedes and ((void *)-1) otherwise.
251 */
Radek Krejci241f6b52020-05-21 18:13:49 +0200252const char *ly_out_filepath(struct ly_out *out, const char *filepath);
Radek Krejcia5bba312020-01-09 15:41:20 +0100253
254/**
255 * @brief Generic printer of the given format string into the specified output.
256 *
Radek Krejci8678fa42020-08-18 16:07:28 +0200257 * Alternatively, ::ly_write() can be used.
Radek Krejcia5bba312020-01-09 15:41:20 +0100258 *
259 * @param[in] out Output specification.
Michal Vasko5233e962020-08-14 14:26:20 +0200260 * @param[in] format Format string to be printed.
261 * @return LY_ERR value, get number of the printed bytes using ::ly_out_printed.
Radek Krejcia5bba312020-01-09 15:41:20 +0100262 */
Michal Vasko5233e962020-08-14 14:26:20 +0200263LY_ERR ly_print(struct ly_out *out, const char *format, ...);
Radek Krejcia5bba312020-01-09 15:41:20 +0100264
265/**
Radek Krejci099fd212020-05-27 18:17:35 +0200266 * @brief Flush the output from any internal buffers and clean any auxiliary data.
267 * @param[in] out Output specification.
268 */
269void ly_print_flush(struct ly_out *out);
270
271/**
Radek Krejcia5bba312020-01-09 15:41:20 +0100272 * @brief Generic printer of the given string buffer into the specified output.
273 *
Radek Krejci8678fa42020-08-18 16:07:28 +0200274 * Alternatively, ::ly_print() can be used.
Radek Krejcia5bba312020-01-09 15:41:20 +0100275 *
Radek Krejcia5bba312020-01-09 15:41:20 +0100276 * @param[in] out Output specification.
277 * @param[in] buf Memory buffer with the data to print.
278 * @param[in] len Length of the data to print in the @p buf.
Michal Vasko5233e962020-08-14 14:26:20 +0200279 * @return LY_ERR value, get number of the printed bytes using ::ly_out_printed.
Radek Krejcia5bba312020-01-09 15:41:20 +0100280 */
Michal Vasko5233e962020-08-14 14:26:20 +0200281LY_ERR ly_write(struct ly_out *out, const char *buf, size_t len);
Radek Krejcia5bba312020-01-09 15:41:20 +0100282
283/**
Michal Vasko63f3d842020-07-08 10:10:14 +0200284 * @brief Get the number of printed bytes by the last function.
285 *
286 * @param[in] out Out structure used.
287 * @return Number of printed bytes.
288 */
289size_t ly_out_printed(const struct ly_out *out);
290
291/**
Radek Krejcia5bba312020-01-09 15:41:20 +0100292 * @brief Free the printer handler.
293 * @param[in] out Printer handler to free.
Radek Krejci241f6b52020-05-21 18:13:49 +0200294 * @param[in] clb_arg_destructor Freeing function for printer callback (LY_OUT_CALLBACK) argument.
295 * @param[in] destroy Flag to free allocated buffer (for LY_OUT_MEMORY) or to
296 * close stream/file descriptor (for LY_OUT_FD, LY_OUT_FDSTREAM and LY_OUT_FILE)
Radek Krejcia5bba312020-01-09 15:41:20 +0100297 */
Radek Krejci857189e2020-09-01 13:26:36 +0200298void ly_out_free(struct ly_out *out, void (*clb_arg_destructor)(void *arg), ly_bool destroy);
Radek Krejcia5bba312020-01-09 15:41:20 +0100299
Radek Krejcica376bd2020-06-11 16:04:06 +0200300#ifdef __cplusplus
301}
302#endif
303
Michal Vaskoafac7822020-10-20 14:22:26 +0200304#endif /* LY_OUT_H_ */