blob: 62f5aae682cd5fdc1863280e158612d656d1d5e4 [file] [log] [blame]
Radek Krejcif0e1ba52020-05-22 15:14:35 +02001/**
Michal Vaskoafac7822020-10-20 14:22:26 +02002 * @file in.h
Radek Krejcif0e1ba52020-05-22 15:14:35 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vaskoafac7822020-10-20 14:22:26 +02004 * @brief libyang input structures and functions
Radek Krejcif0e1ba52020-05-22 15:14:35 +02005 *
6 * Copyright (c) 2020 CESNET, z.s.p.o.
7 *
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_IN_H_
16#define LY_IN_H_
Radek Krejcif0e1ba52020-05-22 15:14:35 +020017
Radek Krejcica376bd2020-06-11 16:04:06 +020018#include <stdio.h>
Radek Krejcif0e1ba52020-05-22 15:14:35 +020019
Radek Krejcica376bd2020-06-11 16:04:06 +020020#include "log.h"
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
Radek Krejcif0e1ba52020-05-22 15:14:35 +020026/**
Michal Vaskoafac7822020-10-20 14:22:26 +020027 * @page howtoInput Input Processing
Radek Krejci8678fa42020-08-18 16:07:28 +020028 *
Michal Vaskoafac7822020-10-20 14:22:26 +020029 * libyang provides a mechanism to generalize work with the inputs (and [outputs](@ref howtoOutput)) of
Radek Krejci8678fa42020-08-18 16:07:28 +020030 * the different types. The ::ly_in handler can be created providing necessary information connected with the specific
31 * input type and then used throughout the parser functions processing the input data. Using a generic input handler avoids
32 * need to have a set of functions for each parser functionality and results in simpler API.
33 *
aPiecekb0445f22021-06-24 11:34:07 +020034 * The API allows to alter the source of the data behind the handler by another source. Also resetting a seekable source
Radek Krejci8678fa42020-08-18 16:07:28 +020035 * input is possible with ::ly_in_reset() to re-read the input.
36 *
37 * @note
38 * Currently, libyang supports only reading data from standard (disk) file, not from sockets, pipes, etc. The reason is
39 * that the parsers expects all the data to be present in the file (input data are complete). In future, we would like
40 * to change the internal mechanism and support sequential processing of the input data. In XML wording - we have DOM
41 * parser, but in future we would like to move to something like a SAX parser.
42 *
43 * @note
44 * This mechanism was introduced in libyang 2.0. To simplify transition from libyang 1.0 to version 2.0 and also for
45 * some simple use case where using the input handler would be an overkill, there are some basic parsers functions
46 * that do not require input handler. But remember, that functionality of these function can be limited in particular cases
47 * in contrast to the functions using input handlers.
48 *
49 * Functions List
50 * --------------
51 * - ::ly_in_new_fd()
52 * - ::ly_in_new_file()
53 * - ::ly_in_new_filepath()
54 * - ::ly_in_new_memory()
55 *
56 * - ::ly_in_fd()
57 * - ::ly_in_file()
58 * - ::ly_in_filepath()
59 * - ::ly_in_memory()
60 *
61 * - ::ly_in_type()
62 * - ::ly_in_parsed()
63 *
64 * - ::ly_in_reset()
65 * - ::ly_in_free()
66 *
67 * libyang Parsers List
68 * --------------------
69 * - @subpage howtoSchemaParsers
70 * - @subpage howtoDataParsers
71 */
72
73/**
74 * @struct ly_in
Radek Krejcif0e1ba52020-05-22 15:14:35 +020075 * @brief Parser input structure specifying where the data are read.
76 */
77struct ly_in;
78
79/**
80 * @brief Types of the parser's inputs
81 */
82typedef enum LY_IN_TYPE {
83 LY_IN_ERROR = -1, /**< error value to indicate failure of the functions returning LY_IN_TYPE */
84 LY_IN_FD, /**< file descriptor printer */
85 LY_IN_FILE, /**< FILE stream parser */
86 LY_IN_FILEPATH, /**< filepath parser */
87 LY_IN_MEMORY /**< memory parser */
88} LY_IN_TYPE;
89
90/**
91 * @brief Get input type of the input handler.
92 *
93 * @param[in] in Input handler.
94 * @return Type of the parser's input.
95 */
Jan Kundrátc53a7ec2021-12-09 16:01:19 +010096LIBYANG_API_DECL LY_IN_TYPE ly_in_type(const struct ly_in *in);
Radek Krejcif0e1ba52020-05-22 15:14:35 +020097
98/**
99 * @brief Reset the input medium to read from its beginning, so the following parser function will read from the object's beginning.
100 *
101 * Note that in case the underlying output is not seekable (stream referring a pipe/FIFO/socket or the callback output type),
102 * nothing actually happens despite the function succeeds. Also note that the medium is not returned to the state it was when
103 * the handler was created. For example, file is seeked into the offset zero, not to the offset where it was opened when
Radek Krejci8678fa42020-08-18 16:07:28 +0200104 * ::ly_in_new_file() was called.
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200105 *
106 * @param[in] in Input handler.
107 * @return LY_SUCCESS in case of success
108 * @return LY_ESYS in case of failure
109 */
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100110LIBYANG_API_DECL LY_ERR ly_in_reset(struct ly_in *in);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200111
112/**
113 * @brief Create input handler using file descriptor.
114 *
115 * @param[in] fd File descriptor to use.
116 * @param[out] in Created input handler supposed to be passed to different ly*_parse() functions.
117 * @return LY_SUCCESS in case of success
118 * @return LY_ERR value in case of failure.
119 */
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100120LIBYANG_API_DECL LY_ERR ly_in_new_fd(int fd, struct ly_in **in);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200121
122/**
123 * @brief Get or reset file descriptor input handler.
124 *
125 * @param[in] in Input handler.
126 * @param[in] fd Optional value of a new file descriptor for the handler. If -1, only the current file descriptor value is returned.
127 * @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.
128 * @return -1 in case of error when setting up the new file descriptor.
129 */
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100130LIBYANG_API_DECL int ly_in_fd(struct ly_in *in, int fd);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200131
132/**
133 * @brief Create input handler using file stream.
134 *
135 * @param[in] f File stream to use.
136 * @param[out] in Created input handler supposed to be passed to different ly*_parse() functions.
137 * @return LY_SUCCESS in case of success
138 * @return LY_ERR value in case of failure.
139 */
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100140LIBYANG_API_DECL LY_ERR ly_in_new_file(FILE *f, struct ly_in **in);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200141
142/**
143 * @brief Get or reset file stream input handler.
144 *
145 * @param[in] in Input handler.
146 * @param[in] f Optional new file stream for the handler. If NULL, only the current file stream is returned.
147 * @return NULL in case of invalid argument or an error when setting up the new input file, original input handler @p in is untouched in this case.
148 * @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.
149 */
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100150LIBYANG_API_DECL FILE *ly_in_file(struct ly_in *in, FILE *f);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200151
152/**
153 * @brief Create input handler using memory to read data.
154 *
155 * @param[in] str Pointer where to start reading data. The input data are expected to be NULL-terminated.
Radek Krejci8678fa42020-08-18 16:07:28 +0200156 * Note that in case the destroy argument of ::ly_in_free() is used, the input string is passed to free(),
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200157 * so if it is really a static string, do not use the destroy argument!
158 * @param[out] in Created input handler supposed to be passed to different ly*_parse() functions.
159 * @return LY_SUCCESS in case of success
160 * @return LY_ERR value in case of failure.
161 */
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100162LIBYANG_API_DECL LY_ERR ly_in_new_memory(const char *str, struct ly_in **in);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200163
164/**
165 * @brief Get or change memory where the data are read from.
166 *
167 * @param[in] in Input handler.
168 * @param[in] str String containing the data to read. The input data are expected to be NULL-terminated.
Radek Krejci8678fa42020-08-18 16:07:28 +0200169 * Note that in case the destroy argument of ::ly_in_free() is used, the input string is passed to free(),
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200170 * so if it is really a static string, do not use the destroy argument!
171 * @return Previous starting address to read data from. Note that the caller is responsible to free
172 * the data in case of changing string pointer @p str.
173 */
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100174LIBYANG_API_DECL const char *ly_in_memory(struct ly_in *in, const char *str);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200175
176/**
177 * @brief Create input handler file of the given filename.
178 *
179 * @param[in] filepath Path of the file where to read data.
180 * @param[in] len Optional number of bytes to use from @p filepath. If 0, the @p filepath is considered to be NULL-terminated and
181 * the whole string is taken into account.
182 * @param[out] in Created input handler supposed to be passed to different ly*_parse() functions.
183 * @return LY_SUCCESS in case of success
184 * @return LY_ERR value in case of failure.
185 */
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100186LIBYANG_API_DECL LY_ERR ly_in_new_filepath(const char *filepath, size_t len, struct ly_in **in);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200187
188/**
189 * @brief Get or change the filepath of the file where the parser reads the data.
190 *
191 * Note that in case of changing the filepath, the current file is closed and a new one is
192 * created/opened instead of renaming the previous file. Also note that the previous filepath
193 * string is returned only in case of not changing it's value.
194 *
195 * @param[in] in Input handler.
196 * @param[in] filepath Optional new filepath for the handler. If and only if NULL, the current filepath string is returned.
197 * @param[in] len Optional number of bytes to use from @p filepath. If 0, the @p filepath is considered to be NULL-terminated and
198 * the whole string is taken into account.
199 * @return Previous filepath string in case the @p filepath argument is NULL.
200 * @return NULL if changing filepath succeedes and ((void *)-1) otherwise.
201 */
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100202LIBYANG_API_DECL const char *ly_in_filepath(struct ly_in *in, const char *filepath, size_t len);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200203
204/**
Michal Vasko63f3d842020-07-08 10:10:14 +0200205 * @brief Get the number of parsed bytes by the last function.
206 *
207 * @param[in] in In structure used.
208 * @return Number of parsed bytes.
209 */
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100210LIBYANG_API_DECL size_t ly_in_parsed(const struct ly_in *in);
Michal Vasko63f3d842020-07-08 10:10:14 +0200211
212/**
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200213 * @brief Free the input handler.
Michal Vasko62c37262023-01-11 11:12:46 +0100214 *
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200215 * @param[in] in Input handler to free.
216 * @param[in] destroy Flag to free the input data buffer (for LY_IN_MEMORY) or to
217 * close stream/file descriptor (for LY_IN_FD and LY_IN_FILE)
218 */
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100219LIBYANG_API_DECL void ly_in_free(struct ly_in *in, ly_bool destroy);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200220
Michal Vasko62c37262023-01-11 11:12:46 +0100221/**
222 * @brief Read bytes from an input.
223 *
224 * Does not count new lines, which is expected from the caller who has better idea about
225 * the content of the read data and can better optimize counting.
226 *
227 * @param[in] in Input structure.
228 * @param[in] buf Destination buffer.
229 * @param[in] count Number of bytes to read.
230 * @return LY_SUCCESS on success,
231 * @return LY_EDENIED on EOF.
232 */
233LIBYANG_API_DECL LY_ERR ly_in_read(struct ly_in *in, void *buf, size_t count);
234
235/**
236 * @brief Just skip bytes in an input.
237 *
238 * Does not count new lines, which is expected from the caller who has better idea about
239 * the content of the skipped data and can better optimize counting.
240 *
241 * @param[in] in Input structure.
242 * @param[in] count Number of bytes to skip.
243 * @return LY_SUCCESS on success,
244 * @return LY_EDENIED on EOF.
245 */
246LIBYANG_API_DECL LY_ERR ly_in_skip(struct ly_in *in, size_t count);
247
Radek Krejcica376bd2020-06-11 16:04:06 +0200248#ifdef __cplusplus
249}
250#endif
251
Michal Vaskoafac7822020-10-20 14:22:26 +0200252#endif /* LY_IN_H_ */