blob: 78530998ce31d55983496d3aa8d641d939ee4555 [file] [log] [blame]
Radek Krejcie7b95092019-05-15 11:03:07 +02001/**
2 * @file printer_data.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Generic data printers functions.
5 *
6 * Copyright (c) 2015 - 2019 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
15#include "common.h"
16
17#include <errno.h>
18#include <stdio.h>
19#include <string.h>
20#include <unistd.h>
21
22#include "log.h"
23#include "printer_internal.h"
24#include "tree_schema.h"
25#include "tree_data.h"
26
27/**
28 * @brief Common YANG data printer.
29 *
30 * @param[in] out Prepared structure defining the type and details of the printer output.
31 * @param[in] root The root element of the (sub)tree to print.
32 * @param[in] format Output format.
33 * @param[in] options [Data printer flags](@ref dataprinterflags). With \p format LYD_LYB, only #LYP_WITHSIBLINGS option is accepted.
34 * @return LY_ERR value.
35 */
36static LY_ERR
37lyd_print_(struct lyout *out, const struct lyd_node *root, LYD_FORMAT format, int options)
38{
39 LY_ERR ret;
40
41 switch (format) {
42 case LYD_XML:
43 ret = xml_print_data(out, root, options);
44 break;
45#if 0
46 case LYD_JSON:
47 ret = json_print_data(out, root, options);
48 break;
49 case LYD_LYB:
50 ret = lyb_print_data(out, root, options);
51 break;
52#endif
53 default:
54 LOGERR(root->schema->module->ctx, LY_EINVAL, "Unknown output format.");
55 ret = LY_EINVAL;
56 break;
57 }
58
59 return ret;
60}
61
62API ssize_t
63lyd_print_file(FILE *f, const struct lyd_node *root, LYD_FORMAT format, int options)
64{
65 struct lyout out;
66 LY_ERR ret;
67
68 LY_CHECK_ARG_RET(NULL, f, LY_EINVAL);
69
70 memset(&out, 0, sizeof out);
71 out.type = LYOUT_STREAM;
72 out.method.f = f;
73
74 if (root) {
75 out.ctx = root->schema->module->ctx;
76 }
77
78 ret = lyd_print_(&out, root, format, options);
79 if (ret) {
80 /* error */
81 return (-1) * ret;
82 } else {
83 /* success */
84 return (ssize_t)out.printed;
85 }
86}
87
88API ssize_t
89lyd_print_path(const char *path, const struct lyd_node *root, LYD_FORMAT format, int options)
90{
91 FILE *f;
92 ssize_t ret;
93
94 LY_CHECK_ARG_RET(NULL, path, LY_EINVAL);
95
96 f = fopen(path, "w");
97 if (!f) {
98 LOGERR(root ? root->schema->module->ctx : NULL, LY_ESYS, "Failed to open file \"%s\" (%s).", path, strerror(errno));
99 return LY_ESYS;
100 }
101
102 ret = lyd_print_file(f, root, format, options);
103 fclose(f);
104 return ret;
105}
106
107API ssize_t
108lyd_print_fd(int fd, const struct lyd_node *root, LYD_FORMAT format, int options)
109{
110 LY_ERR ret;
111 struct lyout out;
112
113 LY_CHECK_ARG_RET(NULL, fd >= 0, LY_EINVAL);
114
115 memset(&out, 0, sizeof out);
116 out.type = LYOUT_FD;
117 out.method.fd = fd;
118
119 if (root) {
120 out.ctx = root->schema->module->ctx;
121 }
122
123 ret = lyd_print_(&out, root, format, options);
124
125 if (out.type == LYOUT_FDSTREAM) {
126 /* close temporary stream based on the given file descriptor */
127 fclose(out.method.f);
128 /* move the original file descriptor to the end of the output file */
129 lseek(fd, 0, SEEK_END);
130 }
131
132 if (ret) {
133 /* error */
134 return (-1) * ret;
135 } else {
136 /* success */
137 return (ssize_t)out.printed;
138 }
139}
140
141API ssize_t
142lyd_print_mem(char **strp, const struct lyd_node *root, LYD_FORMAT format, int options)
143{
144 struct lyout out;
145 LY_ERR ret;
146
147 LY_CHECK_ARG_RET(NULL, strp, LY_EINVAL);
148
149 memset(&out, 0, sizeof out);
150 out.type = LYOUT_MEMORY;
151
152 if (root) {
153 out.ctx = root->schema->module->ctx;
154 }
155
156 ret = lyd_print_(&out, root, format, options);
157 if (ret) {
158 /* error */
159 *strp = NULL;
160 return (-1) * ret;
161 } else {
162 /* success */
163 *strp = out.method.mem.buf;
164 return (ssize_t)out.printed;
165 }
166}
167
168API ssize_t
169lyd_print_clb(ssize_t (*writeclb)(void *arg, const void *buf, size_t count), void *arg, const struct lyd_node *root,
170 LYD_FORMAT format, int options)
171{
172 LY_ERR ret;
173 struct lyout out;
174
175 LY_CHECK_ARG_RET(NULL, writeclb, LY_EINVAL);
176
177 memset(&out, 0, sizeof out);
178 out.type = LYOUT_CALLBACK;
179 out.method.clb.f = writeclb;
180 out.method.clb.arg = arg;
181
182 if (root) {
183 out.ctx = root->schema->module->ctx;
184 }
185
186 ret = lyd_print_(&out, root, format, options);
187 if (ret) {
188 /* error */
189 return (-1) * ret;
190 } else {
191 /* success */
192 return (ssize_t)out.printed;
193 }
194}