Merge pull request #948 from CESNET/print_info
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1bab1e9..875edc9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -213,6 +213,7 @@
src/tree_data_hash.c
src/parser_xml.c
src/parser_json.c
+ src/printer.c
src/printer_data.c
src/printer_xml.c
src/printer_json.c
@@ -249,6 +250,7 @@
src/context.h
src/tree.h
src/tree_data.h
+ src/printer.h
src/printer_data.h
src/tree_schema.h
src/printer_schema.h
@@ -331,6 +333,7 @@
add_custom_target(doc
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+ string(REPLACE ";" " " DOXY_HEADERS "${headers}")
configure_file(Doxyfile.in Doxyfile)
endif()
diff --git a/Doxyfile.in b/Doxyfile.in
index 869013f..9abd406 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -561,7 +561,7 @@
# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
-SORT_MEMBER_DOCS = NO
+SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
@@ -569,7 +569,7 @@
# this will also influence the order of the classes in the class list.
# The default value is: NO.
-SORT_BRIEF_DOCS = NO
+SORT_BRIEF_DOCS = YES
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
# (brief and detailed) documentation of class members so that constructors and
@@ -581,14 +581,14 @@
# detailed member documentation.
# The default value is: NO.
-SORT_MEMBERS_CTORS_1ST = NO
+SORT_MEMBERS_CTORS_1ST = YES
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
# of group names into alphabetical order. If set to NO the group names will
# appear in their defined order.
# The default value is: NO.
-SORT_GROUP_NAMES = NO
+SORT_GROUP_NAMES = YES
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
# fully-qualified names, including namespaces. If set to NO, the class list will
@@ -781,16 +781,7 @@
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
-INPUT = ./src/libyang.h \
- ./src/context.h \
- ./src/tree.h \
- ./src/tree_schema.h \
- ./src/plugins_types.h \
- ./src/plugins_exts.h \
- ./src/tree_data.h \
- ./src/log.h \
- ./src/set.h \
- ./src/dict.h
+INPUT = @DOXY_HEADERS@
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/src/libyang.h b/src/libyang.h
index eba8008..c86bd13 100644
--- a/src/libyang.h
+++ b/src/libyang.h
@@ -28,6 +28,8 @@
#include "tree.h"
#include "tree_data.h"
#include "tree_schema.h"
+#include "printer.h"
+#include "printer_data.h"
#include "printer_schema.h"
#include "printer_data.h"
#include "plugins_types.h"
diff --git a/src/printer.c b/src/printer.c
index e9a6041..6a70cdf 100644
--- a/src/printer.c
+++ b/src/printer.c
@@ -19,6 +19,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
#include <unistd.h>
#include <assert.h>
@@ -143,61 +144,371 @@
return 1;
}
-LY_ERR
-ly_print(struct lyout *out, const char *format, ...)
+API LYP_OUT_TYPE
+lyp_out_type(const struct lyp_out *out)
+{
+ LY_CHECK_ARG_RET(NULL, out, LYP_OUT_ERROR);
+ return out->type;
+}
+
+API struct lyp_out *
+lyp_new_clb(ssize_t (*writeclb)(void *arg, const void *buf, size_t count), void *arg)
+{
+ struct lyp_out *out;
+
+ out = calloc(1, sizeof *out);
+ LY_CHECK_ERR_RET(!out, LOGMEM(NULL), NULL);
+
+ out->type = LYP_OUT_CALLBACK;
+ out->method.clb.func = writeclb;
+ out->method.clb.arg = arg;
+
+ return out;
+}
+
+API ssize_t (*lyp_clb(struct lyp_out *out, ssize_t (*writeclb)(void *arg, const void *buf, size_t count)))(void *arg, const void *buf, size_t count)
+{
+ void *prev_clb;
+
+ LY_CHECK_ARG_RET(NULL, out, out->type == LYP_OUT_CALLBACK, NULL);
+
+ prev_clb = out->method.clb.func;
+
+ if (writeclb) {
+ out->method.clb.func = writeclb;
+ }
+
+ return prev_clb;
+}
+
+API void *
+lyp_clb_arg(struct lyp_out *out, void *arg)
+{
+ void *prev_arg;
+
+ LY_CHECK_ARG_RET(NULL, out, out->type == LYP_OUT_CALLBACK, NULL);
+
+ prev_arg = out->method.clb.arg;
+
+ if (arg) {
+ out->method.clb.arg = arg;
+ }
+
+ return prev_arg;
+}
+
+API struct lyp_out *
+lyp_new_fd(int fd)
+{
+ struct lyp_out *out;
+
+ out = calloc(1, sizeof *out);
+ LY_CHECK_ERR_RET(!out, LOGMEM(NULL), NULL);
+
+#ifdef HAVE_VDPRINTF
+ out->type = LYP_OUT_FD;
+ out->method.fd = fd;
+#else
+ /* Without vdfprintf(), change the printing method to printing to a FILE stream.
+ * To preserve the original file descriptor, duplicate it and use it to open file stream. */
+ out->type = LYP_OUT_FDSTREAM;
+ out->method.fdstream.fd = fd;
+
+ fd = dup(out->method.fdstream.fd);
+ if (fd < 0) {
+ LOGERR(NULL, LY_ESYS, "Unable to duplicate provided file descriptor (%d) for printing the output (%s).",
+ out->method.fdstream.fd, strerror(errno));
+ free(out);
+ return NULL;
+ }
+ out->method.fdstream.f = fdopen(fd, "a");
+ if (!out->method.fdstream.f) {
+ LOGERR(NULL, LY_ESYS, "Unable to open provided file descriptor (%d) for printing the output (%s).",
+ out->method.fdstream.fd, strerror(errno));
+ free(out);
+ fclose(fd);
+ return NULL;
+ }
+#endif
+
+ return out;
+}
+
+API int
+lyp_fd(struct lyp_out *out, int fd)
+{
+ int prev_fd;
+
+ LY_CHECK_ARG_RET(NULL, out, out->type <= LYP_OUT_FDSTREAM, -1);
+
+ if (out->type == LYP_OUT_FDSTREAM) {
+ prev_fd = out->method.fdstream.fd;
+ } else { /* LYP_OUT_FD */
+ prev_fd = out->method.fd;
+ }
+
+ if (fd != -1) {
+ /* replace output stream */
+ if (out->type == LYP_OUT_FDSTREAM) {
+ int streamfd;
+ FILE *stream;
+
+ streamfd = dup(fd);
+ if (streamfd < 0) {
+ LOGERR(NULL, LY_ESYS, "Unable to duplicate provided file descriptor (%d) for printing the output (%s).", fd, strerror(errno));
+ return -1;
+ }
+ stream = fdopen(streamfd, "a");
+ if (!stream) {
+ LOGERR(NULL, LY_ESYS, "Unable to open provided file descriptor (%d) for printing the output (%s).", fd, strerror(errno));
+ close(streamfd);
+ return -1;
+ }
+ /* close only the internally created stream, file descriptor is returned and supposed to be closed by the caller */
+ fclose(out->method.fdstream.f);
+ out->method.fdstream.f = stream;
+ out->method.fdstream.fd = streamfd;
+ } else { /* LYP_OUT_FD */
+ out->method.fd = fd;
+ }
+ }
+
+ return prev_fd;
+}
+
+API struct lyp_out *
+lyp_new_file(FILE *f)
+{
+ struct lyp_out *out;
+
+ out = calloc(1, sizeof *out);
+ LY_CHECK_ERR_RET(!out, LOGMEM(NULL), NULL);
+
+ out->type = LYP_OUT_FILE;
+ out->method.f = f;
+
+ return out;
+}
+
+API FILE *
+lyp_file(struct lyp_out *out, FILE *f)
+{
+ FILE *prev_f;
+
+ LY_CHECK_ARG_RET(NULL, out, out->type == LYP_OUT_FILE, NULL);
+
+ prev_f = out->method.f;
+
+ if (f) {
+ out->method.f = f;
+ }
+
+ return prev_f;
+}
+
+API struct lyp_out *
+lyp_new_memory(char **strp, size_t size)
+{
+ struct lyp_out *out;
+
+ out = calloc(1, sizeof *out);
+ LY_CHECK_ERR_RET(!out, LOGMEM(NULL), NULL);
+
+ out->type = LYP_OUT_MEMORY;
+ out->method.mem.buf = strp;
+ if (!size) {
+ /* buffer is supposed to be allocated */
+ *strp = NULL;
+ } else if (*strp) {
+ /* there is already buffer to use */
+ out->method.mem.size = size;
+ }
+
+ return out;
+}
+
+char *
+lyp_memory(struct lyp_out *out, char **strp, size_t size)
+{
+ char *data;
+
+ LY_CHECK_ARG_RET(NULL, out, out->type == LYP_OUT_MEMORY, NULL);
+
+ data = *out->method.mem.buf;
+
+ if (strp) {
+ out->method.mem.buf = strp;
+ out->method.mem.len = out->method.mem.size = 0;
+ out->printed = 0;
+ if (!size) {
+ /* buffer is supposed to be allocated */
+ *strp = NULL;
+ } else if (*strp) {
+ /* there is already buffer to use */
+ out->method.mem.size = size;
+ }
+ }
+
+ return data;
+}
+
+API LY_ERR
+lyp_out_reset(struct lyp_out *out)
+{
+ LY_CHECK_ARG_RET(NULL, out, LY_EINVAL);
+
+ switch(out->type) {
+ case LYP_OUT_ERROR:
+ LOGINT(NULL);
+ return LY_EINT;
+ case LYP_OUT_FD:
+ if ((lseek(out->method.fd, 0, SEEK_SET) == -1) && errno != ESPIPE) {
+ LOGERR(NULL, LY_ESYS, "Seeking output file descriptor failed (%s).", strerror(errno));
+ return LY_ESYS;
+ }
+ break;
+ case LYP_OUT_FDSTREAM:
+ case LYP_OUT_FILE:
+ case LYP_OUT_FILEPATH:
+ if ((fseek(out->method.f, 0, SEEK_SET) == -1) && errno != ESPIPE) {
+ LOGERR(NULL, LY_ESYS, "Seeking output file stream failed (%s).", strerror(errno));
+ return LY_ESYS;
+ }
+ break;
+ case LYP_OUT_MEMORY:
+ out->printed = 0;
+ out->method.mem.len = 0;
+ break;
+ case LYP_OUT_CALLBACK:
+ /* nothing to do (not seekable) */
+ break;
+ }
+
+ return LY_SUCCESS;
+}
+
+API struct lyp_out *
+lyp_new_filepath(const char *filepath)
+{
+ struct lyp_out *out;
+
+ out = calloc(1, sizeof *out);
+ LY_CHECK_ERR_RET(!out, LOGMEM(NULL), NULL);
+
+ out->type = LYP_OUT_FILEPATH;
+ out->method.fpath.f = fopen(filepath, "w");
+ if (!out->method.fpath.f) {
+ LOGERR(NULL, LY_ESYS, "Failed to open file \"%s\" (%s).", filepath, strerror(errno));
+ return NULL;
+ }
+ out->method.fpath.filepath = strdup(filepath);
+ return out;
+}
+
+API const char *
+lyp_filepath(struct lyp_out *out, const char *filepath)
+{
+ FILE *f;
+
+ LY_CHECK_ARG_RET(NULL, out, out->type == LYP_OUT_FILEPATH, filepath ? NULL : ((void *)-1));
+
+ if (!filepath) {
+ return out->method.fpath.filepath;
+ }
+
+ /* replace filepath */
+ f = out->method.fpath.f;
+ out->method.fpath.f = fopen(filepath, "w");
+ if (!out->method.fpath.f) {
+ LOGERR(NULL, LY_ESYS, "Failed to open file \"%s\" (%s).", filepath, strerror(errno));
+ out->method.fpath.f = f;
+ return ((void *)-1);
+ }
+ fclose(f);
+ free(out->method.fpath.filepath);
+ out->method.fpath.filepath = strdup(filepath);
+
+ return NULL;
+}
+
+API void
+lyp_free(struct lyp_out *out, void (*clb_arg_destructor)(void *arg), int destroy)
+{
+ if (!out) {
+ return;
+ }
+
+ switch (out->type) {
+ case LYP_OUT_CALLBACK:
+ if (clb_arg_destructor) {
+ clb_arg_destructor(out->method.clb.arg);
+ }
+ break;
+ case LYP_OUT_FDSTREAM:
+ fclose(out->method.fdstream.f);
+ if (destroy) {
+ close(out->method.fdstream.fd);
+ }
+ break;
+ case LYP_OUT_FD:
+ if (destroy) {
+ close(out->method.fd);
+ }
+ break;
+ case LYP_OUT_FILE:
+ if (destroy) {
+ fclose(out->method.f);
+ }
+ break;
+ case LYP_OUT_MEMORY:
+ if (destroy) {
+ free(*out->method.mem.buf);
+ }
+ break;
+ case LYP_OUT_FILEPATH:
+ free(out->method.fpath.filepath);
+ if (destroy) {
+ fclose(out->method.fpath.f);
+ }
+ break;
+ case LYP_OUT_ERROR:
+ LOGINT(NULL);
+ }
+ free(out);
+}
+
+API LY_ERR
+lyp_print(struct lyp_out *out, const char *format, ...)
{
int count = 0;
char *msg = NULL, *aux;
va_list ap;
-#ifndef HAVE_VDPRINTF
- int fd;
- FILE *stream;
-#endif
LYOUT_CHECK(out, out->status);
va_start(ap, format);
switch (out->type) {
- case LYOUT_FD:
+ case LYP_OUT_FD:
#ifdef HAVE_VDPRINTF
count = vdprintf(out->method.fd, format, ap);
break;
#else
- /* Without vdfprintf(), change the printing method to printing to a FILE stream.
- * To preserve the original file descriptor, duplicate it and use it to open file stream.
- * Due to a standalone LYOUT_FDSTREAM, ly*_print_fd() functions are supposed to detect the
- * change and close the stream on their exit. */
- fd = dup(out->method.fd);
- if (fd < 0) {
- LOGERR(NULL, LY_ESYS, "Unable to duplicate provided file descriptor (%d) for printing the output (%s).",
- out->method.fd, strerror(errno));
- va_end(ap);
- out->status = LY_ESYS;
- return LY_ESYS;
- }
- stream = fdopen(fd, "a");
- if (!stream) {
- LOGERR(NULL, LY_ESYS, "Unable to open provided file descriptor (%d) for printing the output (%s).",
- out->method.fd, strerror(errno));
- va_end(ap);
- out->status = LY_ESYS;
- return LY_ESYS;
- }
- out->method.f = stream;
- out->type = LYOUT_FDSTREAM;
+ /* never should be here since lyp_fd() is supposed to set type to LYP_OUT_FDSTREAM in case vdprintf() is missing */
+ LOGINT(NULL);
+ return LY_EINT;
#endif
- /* fall through */
- case LYOUT_FDSTREAM:
- case LYOUT_STREAM:
+ case LYP_OUT_FDSTREAM:
+ case LYP_OUT_FILEPATH:
+ case LYP_OUT_FILE:
count = vfprintf(out->method.f, format, ap);
break;
- case LYOUT_MEMORY:
+ case LYP_OUT_MEMORY:
if ((count = vasprintf(&msg, format, ap)) < 0) {
break;
}
if (out->method.mem.len + count + 1 > out->method.mem.size) {
- aux = ly_realloc(out->method.mem.buf, out->method.mem.len + count + 1);
+ aux = ly_realloc(*out->method.mem.buf, out->method.mem.len + count + 1);
if (!aux) {
out->method.mem.buf = NULL;
out->method.mem.len = 0;
@@ -206,21 +517,23 @@
va_end(ap);
return LY_EMEM;
}
- out->method.mem.buf = aux;
+ *out->method.mem.buf = aux;
out->method.mem.size = out->method.mem.len + count + 1;
}
- memcpy(&out->method.mem.buf[out->method.mem.len], msg, count);
+ memcpy(&(*out->method.mem.buf)[out->method.mem.len], msg, count);
out->method.mem.len += count;
- out->method.mem.buf[out->method.mem.len] = '\0';
+ (*out->method.mem.buf)[out->method.mem.len] = '\0';
free(msg);
break;
- case LYOUT_CALLBACK:
+ case LYP_OUT_CALLBACK:
if ((count = vasprintf(&msg, format, ap)) < 0) {
break;
}
- count = out->method.clb.f(out->method.clb.arg, msg, count);
+ count = out->method.clb.func(out->method.clb.arg, msg, count);
free(msg);
break;
+ case LYP_OUT_ERROR:
+ LOGINT(NULL);
}
va_end(ap);
@@ -230,34 +543,45 @@
out->status = LY_ESYS;
return LY_ESYS;
} else {
+ if (out->type == LYP_OUT_FDSTREAM) {
+ /* move the original file descriptor to the end of the output file */
+ lseek(out->method.fdstream.fd, 0, SEEK_END);
+ }
out->printed += count;
return LY_SUCCESS;
}
}
void
-ly_print_flush(struct lyout *out)
+ly_print_flush(struct lyp_out *out)
{
switch (out->type) {
- case LYOUT_FDSTREAM:
- case LYOUT_STREAM:
+ case LYP_OUT_FDSTREAM:
+ /* move the original file descriptor to the end of the output file */
+ lseek(out->method.fdstream.fd, 0, SEEK_END);
+ fflush(out->method.fdstream.f);
+ break;
+ case LYP_OUT_FILEPATH:
+ case LYP_OUT_FILE:
fflush(out->method.f);
break;
- case LYOUT_FD:
+ case LYP_OUT_FD:
fsync(out->method.fd);
break;
- case LYOUT_MEMORY:
- case LYOUT_CALLBACK:
+ case LYP_OUT_MEMORY:
+ case LYP_OUT_CALLBACK:
/* nothing to do */
break;
+ case LYP_OUT_ERROR:
+ LOGINT(NULL);
}
free(out->buffered);
out->buf_size = out->buf_len = 0;
}
-LY_ERR
-ly_write(struct lyout *out, const char *buf, size_t len)
+API LY_ERR
+lyp_write(struct lyp_out *out, const char *buf, size_t len)
{
int written = 0;
@@ -282,32 +606,35 @@
repeat:
switch (out->type) {
- case LYOUT_MEMORY:
+ case LYP_OUT_MEMORY:
if (out->method.mem.len + len + 1 > out->method.mem.size) {
- out->method.mem.buf = ly_realloc(out->method.mem.buf, out->method.mem.len + len + 1);
- if (!out->method.mem.buf) {
+ *out->method.mem.buf = ly_realloc(*out->method.mem.buf, out->method.mem.len + len + 1);
+ if (!*out->method.mem.buf) {
out->method.mem.len = 0;
out->method.mem.size = 0;
LOGMEM_RET(NULL);
}
out->method.mem.size = out->method.mem.len + len + 1;
}
- memcpy(&out->method.mem.buf[out->method.mem.len], buf, len);
+ memcpy(&(*out->method.mem.buf)[out->method.mem.len], buf, len);
out->method.mem.len += len;
- out->method.mem.buf[out->method.mem.len] = '\0';
+ (*out->method.mem.buf)[out->method.mem.len] = '\0';
out->printed += len;
return LY_SUCCESS;
- case LYOUT_FD:
+ case LYP_OUT_FD:
written = write(out->method.fd, buf, len);
break;
- case LYOUT_FDSTREAM:
- case LYOUT_STREAM:
+ case LYP_OUT_FDSTREAM:
+ case LYP_OUT_FILEPATH:
+ case LYP_OUT_FILE:
written = fwrite(buf, sizeof *buf, len, out->method.f);
break;
- case LYOUT_CALLBACK:
- written = out->method.clb.f(out->method.clb.arg, buf, len);
+ case LYP_OUT_CALLBACK:
+ written = out->method.clb.func(out->method.clb.arg, buf, len);
break;
+ case LYP_OUT_ERROR:
+ LOGINT(NULL);
}
if (written < 0) {
@@ -322,21 +649,25 @@
out->status = LY_ESYS;
return LY_ESYS;
} else {
+ if (out->type == LYP_OUT_FDSTREAM) {
+ /* move the original file descriptor to the end of the output file */
+ lseek(out->method.fdstream.fd, 0, SEEK_END);
+ }
out->printed += written;
return LY_SUCCESS;
}
}
LY_ERR
-ly_write_skip(struct lyout *out, size_t count, size_t *position)
+ly_write_skip(struct lyp_out *out, size_t count, size_t *position)
{
LYOUT_CHECK(out, out->status);
switch (out->type) {
- case LYOUT_MEMORY:
+ case LYP_OUT_MEMORY:
if (out->method.mem.len + count > out->method.mem.size) {
- out->method.mem.buf = ly_realloc(out->method.mem.buf, out->method.mem.len + count);
- if (!out->method.mem.buf) {
+ *out->method.mem.buf = ly_realloc(*out->method.mem.buf, out->method.mem.len + count);
+ if (!(*out->method.mem.buf)) {
out->method.mem.len = 0;
out->method.mem.size = 0;
out->status = LY_ESYS;
@@ -354,10 +685,11 @@
/* update printed bytes counter despite we actually printed just a hole */
out->printed += count;
break;
- case LYOUT_FD:
- case LYOUT_FDSTREAM:
- case LYOUT_STREAM:
- case LYOUT_CALLBACK:
+ case LYP_OUT_FD:
+ case LYP_OUT_FDSTREAM:
+ case LYP_OUT_FILEPATH:
+ case LYP_OUT_FILE:
+ case LYP_OUT_CALLBACK:
/* buffer the hole */
if (out->buf_len + count > out->buf_size) {
out->buffered = ly_realloc(out->buffered, out->buf_len + count);
@@ -378,27 +710,32 @@
/* increase hole counter */
++out->hole_count;
+
+ break;
+ case LYP_OUT_ERROR:
+ LOGINT(NULL);
}
return LY_SUCCESS;
}
LY_ERR
-ly_write_skipped(struct lyout *out, size_t position, const char *buf, size_t count)
+ly_write_skipped(struct lyp_out *out, size_t position, const char *buf, size_t count)
{
LY_ERR ret = LY_SUCCESS;
LYOUT_CHECK(out, out->status);
switch (out->type) {
- case LYOUT_MEMORY:
+ case LYP_OUT_MEMORY:
/* write */
- memcpy(&out->method.mem.buf[position], buf, count);
+ memcpy(&(*out->method.mem.buf)[position], buf, count);
break;
- case LYOUT_FD:
- case LYOUT_FDSTREAM:
- case LYOUT_STREAM:
- case LYOUT_CALLBACK:
+ case LYP_OUT_FD:
+ case LYP_OUT_FDSTREAM:
+ case LYP_OUT_FILEPATH:
+ case LYP_OUT_FILE:
+ case LYP_OUT_CALLBACK:
if (out->buf_len < position + count) {
out->status = LY_ESYS;
LOGMEM_RET(NULL);
@@ -413,11 +750,17 @@
if (!out->hole_count) {
/* all holes filled, we can write the buffer,
* printed bytes counter is updated by ly_write() */
- ret = ly_write(out, out->buffered, out->buf_len);
+ ret = lyp_write(out, out->buffered, out->buf_len);
out->buf_len = 0;
}
break;
+ case LYP_OUT_ERROR:
+ LOGINT(NULL);
}
+ if (out->type == LYP_OUT_FILEPATH) {
+ /* move the original file descriptor to the end of the output file */
+ lseek(out->method.fdstream.fd, 0, SEEK_END);
+ }
return ret;
}
diff --git a/src/printer.h b/src/printer.h
new file mode 100644
index 0000000..0034132
--- /dev/null
+++ b/src/printer.h
@@ -0,0 +1,208 @@
+/**
+ * @file printer.h
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @brief Generic libyang printer structures and functions
+ *
+ * Copyright (c) 2015-2019 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#ifndef LY_PRINTER_H_
+#define LY_PRINTER_H_
+
+#include <unistd.h>
+
+/**
+ * @brief Printer output structure specifying where the data are printed.
+ */
+struct lyp_out;
+
+/**
+ * @brief Types of the printer's output
+ */
+typedef enum LYP_OUT_TYPE {
+ LYP_OUT_ERROR = -1, /**< error value to indicate failure of the functions returning LYP_OUT_TYPE */
+ LYP_OUT_FD, /**< file descriptor printer */
+ LYP_OUT_FDSTREAM, /**< internal replacement for LYP_OUT_FD in case vdprintf() is not available */
+ LYP_OUT_FILE, /**< FILE stream printer */
+ LYP_OUT_FILEPATH, /**< filepath printer */
+ LYP_OUT_MEMORY, /**< memory printer */
+ LYP_OUT_CALLBACK /**< callback printer */
+} LYP_OUT_TYPE;
+
+/**
+ * @brief Get output type of the printer handler.
+ *
+ * @param[in] out Printer handler.
+ * @return Type of the printer's output.
+ */
+LYP_OUT_TYPE lyp_out_type(const struct lyp_out *out);
+
+/**
+ * @brief Reset the output medium to write from its beginning, so the following printer function will rewrite the current data
+ * instead of appending.
+ *
+ * Note that in case the underlying output is not seekable (stream referring a pipe/FIFO/socket or the callback output type),
+ * nothing actually happens despite the function succeeds. Also note that the medium is not returned to the state it was when
+ * the handler was created. For example, file is seeked into the offset zero, not to the offset where it was opened when
+ * lyp_new_file() was called.
+ *
+ * @param[in] out Printer handler.
+ * @return LY_SUCCESS in case of success
+ * @return LY_ESYS in case of failure
+ */
+LY_ERR lyp_out_reset(struct lyp_out *out);
+
+/**
+ * @brief Create printer handler using callback printer function.
+ *
+ * @param[in] writeclb Pointer to the printer callback function writing the data (see write(2)).
+ * @param[in] arg Optional caller-specific argument to be passed to the @p writeclb callback.
+ * @return NULL in case of memory allocation error.
+ * @return Created printer handler supposed to be passed to different ly*_print_*() functions.
+ */
+struct lyp_out *lyp_new_clb(ssize_t (*writeclb)(void *arg, const void *buf, size_t count), void *arg);
+
+/**
+ * @brief Get or reset callback function associated with a callback printer handler.
+ *
+ * @param[in] out Printer handler.
+ * @param[in] fd Optional value of a new file descriptor for the handler. If -1, only the current file descriptor value is returned.
+ * @return Previous value of the file descriptor.
+ */
+ssize_t (*lyp_clb(struct lyp_out *out, ssize_t (*writeclb)(void *arg, const void *buf, size_t count)))(void *arg, const void *buf, size_t count);
+
+/**
+ * @brief Get or reset callback function's argument aasociated with a callback printer handler.
+ *
+ * @param[in] out Printer handler.
+ * @param[in] arg caller-specific argument to be passed to the callback function associated with the printer handler.
+ * If NULL, only the current file descriptor value is returned.
+ * @return The previous callback argument.
+ */
+void *lyp_clb_arg(struct lyp_out *out, void *arg);
+
+/**
+ * @brief Create printer handler using file descriptor.
+ *
+ * @param[in] fd File descriptor to use.
+ * @return NULL in case of error.
+ * @return Created printer handler supposed to be passed to different ly*_print_*() functions.
+ */
+struct lyp_out *lyp_new_fd(int fd);
+
+/**
+ * @brief Get or reset file descriptor printer handler.
+ *
+ * @param[in] out Printer handler.
+ * @param[in] fd Optional value of a new file descriptor for the handler. If -1, only the current file descriptor value is returned.
+ * @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.
+ * @return -1 in case of error when setting up the new file descriptor.
+ */
+int lyp_fd(struct lyp_out *out, int fd);
+
+/**
+ * @brief Create printer handler using file stream.
+ *
+ * @param[in] f File stream to use.
+ * @return NULL in case of error.
+ * @return Created printer handler supposed to be passed to different ly*_print_*() functions.
+ */
+struct lyp_out *lyp_new_file(FILE *f);
+
+/**
+ * @brief Get or reset file stream printer handler.
+ *
+ * @param[in] out Printer handler.
+ * @param[in] f Optional new file stream for the handler. If NULL, only the current file stream is returned.
+ * @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.
+ */
+FILE *lyp_file(struct lyp_out *out, FILE *f);
+
+/**
+ * @brief Create printer handler using memory to dump data.
+ *
+ * @param[in] strp Pointer to store the resulting data. If it points to a pointer to an allocated buffer and
+ * @p size of the buffer is set, the buffer is used (and extended if needed) to store the printed data.
+ * @param[in] size Size of the buffer provided via @p strp. In case it is 0, the buffer for the printed data
+ * is newly allocated even if @p strp points to a pointer to an existing buffer.
+ * @return NULL in case of error.
+ * @return Created printer handler supposed to be passed to different ly*_print_*() functions.
+ */
+struct lyp_out *lyp_new_memory(char **strp, size_t size);
+
+/**
+ * @brief Get or change memory where the data are dumped.
+ *
+ * @param[in] out Printer handler.
+ * @param[in] strp A new string pointer to store the resulting data, same rules as in lyp_new_memory() are applied.
+ * @param[in] size Size of the buffer provided via @p strp. In case it is 0, the buffer for the printed data
+ * is newly allocated even if @p strp points to a pointer to an existing buffer.
+ * @return Previous dumped data. Note that the caller is responsible to free the data in case of changing string pointer @p strp.
+ */
+char *lyp_memory(struct lyp_out *out, char **strp, size_t size);
+
+/**
+ * @brief Create printer handler file of the given filename.
+ *
+ * @param[in] filepath Path of the file where to write data.
+ * @return NULL in case of error.
+ * @return Created printer handler supposed to be passed to different ly*_print_*() functions.
+ */
+struct lyp_out *lyp_new_filepath(const char *filepath);
+
+/**
+ * @brief Get or change the filepath of the file where the printer prints the data.
+ *
+ * Note that in case of changing the filepath, the current file is closed and a new one is
+ * created/opened instead of renaming the previous file. Also note that the previous filepath
+ * string is returned only in case of not changing it's value.
+ *
+ * @param[in] out Printer handler.
+ * @param[in] filepath Optional new filepath for the handler. If and only if NULL, the current filepath string is returned.
+ * @return Previous filepath string in case the @p filepath argument is NULL.
+ * @return NULL if changing filepath succeedes and ((void *)-1) otherwise.
+ */
+const char *lyp_filepath(struct lyp_out *out, const char *filepath);
+
+/**
+ * @brief Generic printer of the given format string into the specified output.
+ *
+ * Alternatively, lyp_write() can be used.
+ *
+ * @param[in] out Output specification.
+ * @param[in] format format string to be printed.
+ * @return LY_ERR value, number of the printed bytes is updated in lyout::printed.
+ */
+LY_ERR lyp_print(struct lyp_out *out, const char *format, ...);
+
+/**
+ * @brief Generic printer of the given string buffer into the specified output.
+ *
+ * Alternatively, lyp_print() can be used.
+ *
+ * As an extension for printing holes (skipping some data until they are known),
+ * ly_write_skip() and ly_write_skipped() can be used.
+ *
+ * @param[in] out Output specification.
+ * @param[in] buf Memory buffer with the data to print.
+ * @param[in] len Length of the data to print in the @p buf.
+ * @return LY_ERR value, number of the printed bytes is updated in lyout::printed.
+ */
+LY_ERR lyp_write(struct lyp_out *out, const char *buf, size_t len);
+
+/**
+ * @brief Free the printer handler.
+ * @param[in] out Printer handler to free.
+ * @param[in] clb_arg_destructor Freeing function for printer callback (LYP_OUT_CALLBACK) argument.
+ * @param[in] destroy Flag to free allocated buffer (for LYP_OUT_MEMORY) or to
+ * close stream/file descriptor (for LYP_OUT_FD, LYP_OUT_FDSTREAM and LYP_OUT_FILE)
+ */
+void lyp_free(struct lyp_out *out, void (*clb_arg_destructor)(void *arg), int destroy);
+
+#endif /* LY_PRINTER_H_ */
diff --git a/src/printer_data.c b/src/printer_data.c
index 790b19d..96c2109 100644
--- a/src/printer_data.c
+++ b/src/printer_data.c
@@ -21,6 +21,7 @@
#include "log.h"
#include "printer_internal.h"
+#include "printer_data.h"
#include "tree_schema.h"
#include "tree_data.h"
@@ -33,10 +34,15 @@
* @param[in] options [Data printer flags](@ref dataprinterflags). With \p format LYD_LYB, only #LYP_WITHSIBLINGS option is accepted.
* @return LY_ERR value.
*/
-static LY_ERR
-lyd_print_(struct lyout *out, const struct lyd_node *root, LYD_FORMAT format, int options)
+API ssize_t
+lyd_print(struct lyp_out *out, const struct lyd_node *root, LYD_FORMAT format, int options)
{
LY_ERR ret;
+ size_t printed_prev;
+
+ LY_CHECK_ARG_RET(NULL, out, root, -LY_EINVAL);
+
+ printed_prev = out->printed;
switch (format) {
case LYD_XML:
@@ -56,139 +62,11 @@
break;
}
- return ret;
-}
-
-API ssize_t
-lyd_print_file(FILE *f, const struct lyd_node *root, LYD_FORMAT format, int options)
-{
- struct lyout out;
- LY_ERR ret;
-
- LY_CHECK_ARG_RET(NULL, f, LY_EINVAL);
-
- memset(&out, 0, sizeof out);
- out.type = LYOUT_STREAM;
- out.method.f = f;
-
- if (root) {
- out.ctx = LYD_NODE_CTX(root);
- }
-
- ret = lyd_print_(&out, root, format, options);
if (ret) {
/* error */
return (-1) * ret;
} else {
/* success */
- return (ssize_t)out.printed;
- }
-}
-
-API ssize_t
-lyd_print_path(const char *path, const struct lyd_node *root, LYD_FORMAT format, int options)
-{
- FILE *f;
- ssize_t ret;
-
- LY_CHECK_ARG_RET(NULL, path, LY_EINVAL);
-
- f = fopen(path, "w");
- if (!f) {
- LOGERR(root ? LYD_NODE_CTX(root) : NULL, LY_ESYS, "Failed to open file \"%s\" (%s).", path, strerror(errno));
- return LY_ESYS;
- }
-
- ret = lyd_print_file(f, root, format, options);
- fclose(f);
- return ret;
-}
-
-API ssize_t
-lyd_print_fd(int fd, const struct lyd_node *root, LYD_FORMAT format, int options)
-{
- LY_ERR ret;
- struct lyout out;
-
- LY_CHECK_ARG_RET(NULL, fd >= 0, LY_EINVAL);
-
- memset(&out, 0, sizeof out);
- out.type = LYOUT_FD;
- out.method.fd = fd;
-
- if (root) {
- out.ctx = LYD_NODE_CTX(root);
- }
-
- ret = lyd_print_(&out, root, format, options);
-
- if (out.type == LYOUT_FDSTREAM) {
- /* close temporary stream based on the given file descriptor */
- fclose(out.method.f);
- /* move the original file descriptor to the end of the output file */
- lseek(fd, 0, SEEK_END);
- }
-
- if (ret) {
- /* error */
- return (-1) * ret;
- } else {
- /* success */
- return (ssize_t)out.printed;
- }
-}
-
-API ssize_t
-lyd_print_mem(char **strp, const struct lyd_node *root, LYD_FORMAT format, int options)
-{
- struct lyout out;
- LY_ERR ret;
-
- LY_CHECK_ARG_RET(NULL, strp, LY_EINVAL);
-
- memset(&out, 0, sizeof out);
- out.type = LYOUT_MEMORY;
-
- if (root) {
- out.ctx = LYD_NODE_CTX(root);
- }
-
- ret = lyd_print_(&out, root, format, options);
- if (ret) {
- /* error */
- *strp = NULL;
- return (-1) * ret;
- } else {
- /* success */
- *strp = out.method.mem.buf;
- return (ssize_t)out.printed;
- }
-}
-
-API ssize_t
-lyd_print_clb(ssize_t (*writeclb)(void *arg, const void *buf, size_t count), void *arg, const struct lyd_node *root,
- LYD_FORMAT format, int options)
-{
- LY_ERR ret;
- struct lyout out;
-
- LY_CHECK_ARG_RET(NULL, writeclb, LY_EINVAL);
-
- memset(&out, 0, sizeof out);
- out.type = LYOUT_CALLBACK;
- out.method.clb.f = writeclb;
- out.method.clb.arg = arg;
-
- if (root) {
- out.ctx = LYD_NODE_CTX(root);
- }
-
- ret = lyd_print_(&out, root, format, options);
- if (ret) {
- /* error */
- return (-1) * ret;
- } else {
- /* success */
- return (ssize_t)out.printed;
+ return (ssize_t)(out->printed - printed_prev);
}
}
diff --git a/src/printer_data.h b/src/printer_data.h
index 38c757b..921793f 100644
--- a/src/printer_data.h
+++ b/src/printer_data.h
@@ -19,6 +19,7 @@
#include <unistd.h>
#include "tree_data.h"
+#include "printer.h"
/**
* @defgroup dataprinterflags Data printer flags
@@ -50,71 +51,15 @@
*/
/**
- * @brief Print data tree in the specified format into a memory block.
- * It is up to caller to free the returned string by free().
+ * @brief Common YANG data printer.
*
- * @param[out] strp Pointer to store the resulting dump.
- * @param[in] root Root node of the data tree to print. It can be actually any (not only real root)
- * node of the data tree to print the specific subtree.
- * @param[in] format Data output format.
+ * @param[in] out Printer handler for a specific output. Use lyp_*() functions to create the handler and lyp_free() to remove the handler.
+ * @param[in] root The root element of the (sub)tree to print.
+ * @param[in] format Output format.
* @param[in] options [Data printer flags](@ref dataprinterflags). With \p format LYD_LYB, only #LYP_WITHSIBLINGS option is accepted.
* @return Number of printed characters (excluding the null byte used to end the string) in case of success.
* @return Negative value failure (absolute value corresponds to LY_ERR values).
*/
-ssize_t lyd_print_mem(char **strp, const struct lyd_node *root, LYD_FORMAT format, int options);
-
-/**
- * @brief Print data tree in the specified format into a file descriptor.
- *
- * @param[in] fd File descriptor where to print the data.
- * @param[in] root Root node of the data tree to print. It can be actually any (not only real root)
- * node of the data tree to print the specific subtree.
- * @param[in] format Data output format.
- * @param[in] options [Data printer flags](@ref dataprinterflags). With \p format LYD_LYB, only #LYP_WITHSIBLINGS option is accepted.
- * @return Number of printed characters (excluding the null byte used to end the string) in case of success.
- * @return Negative value failure (absolute value corresponds to LY_ERR values).
- */
-ssize_t lyd_print_fd(int fd, const struct lyd_node *root, LYD_FORMAT format, int options);
-
-/**
- * @brief Print data tree in the specified format into a file stream.
- *
- * @param[in] f File stream where to print the schema.
- * @param[in] root Root node of the data tree to print. It can be actually any (not only real root)
- * node of the data tree to print the specific subtree.
- * @param[in] format Data output format.
- * @param[in] options [Data printer flags](@ref dataprinterflags). With \p format LYD_LYB, only #LYP_WITHSIBLINGS option is accepted.
- * @return Number of printed characters (excluding the null byte used to end the string) in case of success.
- * @return Negative value failure (absolute value corresponds to LY_ERR values).
- */
-ssize_t lyd_print_file(FILE *f, const struct lyd_node *root, LYD_FORMAT format, int options);
-
-/**
- * @brief Print data tree in the specified format into a file.
- *
- * @param[in] path File where to print the schema.
- * @param[in] root Root node of the data tree to print. It can be actually any (not only real root)
- * node of the data tree to print the specific subtree.
- * @param[in] format Data output format.
- * @param[in] options [Data printer flags](@ref dataprinterflags). With \p format LYD_LYB, only #LYP_WITHSIBLINGS option is accepted.
- * @return Number of printed characters (excluding the null byte used to end the string) in case of success.
- * @return Negative value failure (absolute value corresponds to LY_ERR values).
- */
-ssize_t lyd_print_path(const char *path, const struct lyd_node *root, LYD_FORMAT format, int options);
-
-/**
- * @brief Print data tree in the specified format using the provided callback.
- *
- * @param[in] writeclb Callback function to write the data (see write(2)).
- * @param[in] arg Optional caller-specific argument to be passed to the \p writeclb callback.
- * @param[in] root Root node of the data tree to print. It can be actually any (not only real root)
- * node of the data tree to print the specific subtree.
- * @param[in] format Data output format.
- * @param[in] options [Data printer flags](@ref dataprinterflags). With \p format LYD_LYB, only #LYP_WITHSIBLINGS option is accepted.
- * @return Number of printed characters (excluding the null byte used to end the string) in case of success.
- * @return Negative value failure (absolute value corresponds to LY_ERR values).
- */
-ssize_t lyd_print_clb(ssize_t (*writeclb)(void *arg, const void *buf, size_t count), void *arg, const struct lyd_node *root,
- LYD_FORMAT format, int options);
+ssize_t lyd_print(struct lyp_out *out, const struct lyd_node *root, LYD_FORMAT format, int options);
#endif /* LY_PRINTER_DATA_H_ */
diff --git a/src/printer_internal.h b/src/printer_internal.h
index 139a5bc..f60f6d4 100644
--- a/src/printer_internal.h
+++ b/src/printer_internal.h
@@ -15,37 +15,35 @@
#ifndef LY_PRINTER_INTERNAL_H_
#define LY_PRINTER_INTERNAL_H_
+#include "printer.h"
#include "printer_schema.h"
#include "printer_data.h"
/**
- * @brief Types of the printer's output
- */
-typedef enum LYOUT_TYPE {
- LYOUT_FD, /**< file descriptor */
- LYOUT_STREAM, /**< FILE stream */
- LYOUT_FDSTREAM, /**< FILE stream based on duplicated file descriptor */
- LYOUT_MEMORY, /**< memory */
- LYOUT_CALLBACK /**< print via provided callback */
-} LYOUT_TYPE;
-
-/**
* @brief Printer output structure specifying where the data are printed.
*/
-struct lyout {
- LYOUT_TYPE type; /**< type of the output to select the output method */
+struct lyp_out {
+ LYP_OUT_TYPE type; /**< type of the output to select the output method */
union {
- int fd; /**< file descriptor for LYOUT_FD type */
- FILE *f; /**< file structure for LYOUT_STREAM and LYOUT_FDSTREAM types */
+ int fd; /**< file descriptor for LYP_OUT_FD type */
+ FILE *f; /**< file structure for LYP_OUT_STREAM, LYP_OUT_FDSTREAM and LYP_OUT_FILEPATH types */
struct {
- char *buf; /**< pointer to the memory buffer to store the output */
+ FILE *f; /**< file stream from the original file descriptor, variable is mapped to the LYP_OUT_STREAM's f */
+ int fd; /**< original file descriptor, which was not used directly because of missing vdprintf() */
+ } fdstream; /**< structure for LYP_OUT_FDSTREAM type, which is LYP_OUT_FD when vdprintf() is missing */
+ struct {
+ FILE *f; /**< file structure for LYP_OUT_FILEPATH, variable is mapped to the LYP_OUT_STREAM's f */
+ char *filepath; /**< stored original filepath */
+ } fpath; /**< filepath structure for LYP_OUT_FILEPATH */
+ struct {
+ char **buf; /**< storage for the pointer to the memory buffer to store the output */
size_t len; /**< number of used bytes in the buffer */
size_t size; /**< allocated size of the buffer */
- } mem; /**< memory buffer information for LYOUT_MEMORY type */
+ } mem; /**< memory buffer information for LYP_OUT_MEMORY type */
struct {
- ssize_t (*f)(void *arg, const void *buf, size_t count); /**< callback function */
+ ssize_t (*func)(void *arg, const void *buf, size_t count); /**< callback function */
void *arg; /**< optional argument for the callback function */
- } clb; /**< printer callback for LYOUT_CALLBACK type */
+ } clb; /**< printer callback for LYP_OUT_CALLBACK type */
} method; /**< type-specific information about the output */
char *buffered; /**< additional buffer for holes, used only for LYB data format */
@@ -85,7 +83,7 @@
* @param[in] module Schema to be printed (the parsed member is used).
* @return LY_ERR value, number of the printed bytes is updated in lyout::printed.
*/
-LY_ERR yang_print_parsed(struct lyout *out, const struct lys_module *module);
+LY_ERR yang_print_parsed(struct lyp_out *out, const struct lys_module *module);
/**
* @brief YANG printer of the compiled schemas.
@@ -96,9 +94,24 @@
*
* @param[in] out Output specification.
* @param[in] module Schema to be printed (the compiled member is used).
+ * @param[in] options Schema output options (see @ref schemaprinterflags).
* @return LY_ERR value, number of the printed bytes is updated in lyout::printed.
*/
-LY_ERR yang_print_compiled(struct lyout *out, const struct lys_module *module);
+LY_ERR yang_print_compiled(struct lyp_out *out, const struct lys_module *module, int options);
+
+/**
+ * @brief YANG printer of the compiled schema node
+ *
+ * This printer provides information about modules how they are understood by libyang.
+ * Despite the format is inspired by YANG, it is not fully compatible and should not be
+ * used as a standard YANG format.
+ *
+ * @param[in] out Output specification.
+ * @param[in] node Schema node to be printed including all its substatements.
+ * @param[in] options Schema output options (see @ref schemaprinterflags).
+ * @return LY_ERR value, number of the printed bytes is updated in lyout::printed.
+ */
+LY_ERR yang_print_compiled_node(struct lyp_out *out, const struct lysc_node *node, int options);
/**
* @brief YIN printer of the parsed schemas. Full YIN printer.
@@ -107,7 +120,7 @@
* @param[in] module Schema to be printed (the parsed member is used).
* @return LY_ERR value, number of the printed bytes is updated in lyout::printed.
*/
-LY_ERR yin_print_parsed(struct lyout *out, const struct lys_module *module);
+LY_ERR yin_print_parsed(struct lyp_out *out, const struct lys_module *module);
/**
* @brief XML printer of the YANG data.
@@ -117,7 +130,7 @@
* @param[in] options [Data printer flags](@ref dataprinterflags).
* @return LY_ERR value, number of the printed bytes is updated in lyout::printed.
*/
-LY_ERR xml_print_data(struct lyout *out, const struct lyd_node *root, int options);
+LY_ERR xml_print_data(struct lyp_out *out, const struct lyd_node *root, int options);
/**
* @brief Check whether a node value equals to its default one.
@@ -139,36 +152,10 @@
int ly_should_print(const struct lyd_node *node, int options);
/**
- * @brief Generic printer of the given format string into the specified output.
- *
- * Alternatively, ly_write() can be used.
- *
- * @param[in] out Output specification.
- * @param[in] format format string to be printed.
- * @return LY_ERR value, number of the printed bytes is updated in lyout::printed.
- */
-LY_ERR ly_print(struct lyout *out, const char *format, ...);
-
-/**
* @brief Flush the output from any internal buffers and clean any auxiliary data.
* @param[in] out Output specification.
*/
-void ly_print_flush(struct lyout *out);
-
-/**
- * @brief Generic printer of the given string buffer into the specified output.
- *
- * Alternatively, ly_print() can be used.
- *
- * As an extension for printing holes (skipping some data until they are known),
- * ly_write_skip() and ly_write_skipped() can be used.
- *
- * @param[in] out Output specification.
- * @param[in] buf Memory buffer with the data to print.
- * @param[in] len Length of the data to print in the @p buf.
- * @return LY_ERR value, number of the printed bytes is updated in lyout::printed.
- */
-LY_ERR ly_write(struct lyout *out, const char *buf, size_t len);
+void ly_print_flush(struct lyp_out *out);
/**
* @brief Create a hole in the output data that will be filled later.
@@ -179,7 +166,7 @@
* @return LY_ERR value. The number of the printed bytes is updated in lyout::printed
* only in case the data are really written into the output.
*/
-LY_ERR ly_write_skip(struct lyout *out, size_t len, size_t *position);
+LY_ERR ly_write_skip(struct lyp_out *out, size_t len, size_t *position);
/**
* @brief Write data into the hole at given position.
@@ -192,6 +179,6 @@
* @return LY_ERR value. The number of the printed bytes is updated in lyout::printed
* only in case the data are really written into the output.
*/
-LY_ERR ly_write_skipped(struct lyout *out, size_t position, const char *buf, size_t len);
+LY_ERR ly_write_skipped(struct lyp_out *out, size_t position, const char *buf, size_t len);
#endif /* LY_PRINTER_INTERNAL_H_ */
diff --git a/src/printer_schema.c b/src/printer_schema.c
index bacf136..a4cbf1f 100644
--- a/src/printer_schema.c
+++ b/src/printer_schema.c
@@ -20,30 +20,26 @@
#include <unistd.h>
#include "log.h"
+#include "printer.h"
#include "printer_internal.h"
#include "tree_schema.h"
-/**
- * @brief Common schema printer.
- *
- * @param[in] out Prepared structure defining the type and details of the printer output.
- * @param[in] module Schema to print.
- * @param[in] format Output format.
- * @param[in] line_length Maximum characters to be printed on a line, 0 for unlimited. Only for #LYS_OUT_TREE printer.
- * @param[in] options Schema output options (see @ref schemaprinterflags).
- * @return LY_ERR value, number of the printed bytes is updated in lyout::printed.
- */
-static LY_ERR
-lys_print_(struct lyout *out, const struct lys_module *module, LYS_OUTFORMAT format, int UNUSED(line_length), int UNUSED(options))
+API ssize_t
+lys_print(struct lyp_out *out, const struct lys_module *module, LYS_OUTFORMAT format, int UNUSED(line_length), int options)
{
LY_ERR ret;
+ size_t printed_prev;
+
+ LY_CHECK_ARG_RET(NULL, out, module, -LY_EINVAL);
+
+ printed_prev = out->printed;
switch (format) {
case LYS_OUT_YANG:
ret = yang_print_parsed(out, module);
break;
case LYS_OUT_YANG_COMPILED:
- ret = yang_print_compiled(out, module);
+ ret = yang_print_compiled(out, module, options);
break;
case LYS_OUT_YIN:
ret = yin_print_parsed(out, module);
@@ -55,81 +51,48 @@
case LYS_OUT_INFO:
ret = info_print_model(out, module, target_node);
break;
- case LYS_OUT_JSON:
- ret = jsons_print_model(out, module, target_node);
- break;
*/
default:
- LOGERR(module->ctx, LY_EINVAL, "Unknown output format.");
+ LOGERR(module->ctx, LY_EINVAL, "Unsupported output format.");
ret = LY_EINVAL;
break;
}
- return ret;
-}
-
-API ssize_t
-lys_print_file(FILE *f, const struct lys_module *module, LYS_OUTFORMAT format, int line_length, int options)
-{
- struct lyout out;
- LY_ERR ret;
-
- LY_CHECK_ARG_RET(NULL, f, module, LY_EINVAL);
-
- memset(&out, 0, sizeof out);
- out.ctx = module->ctx;
- out.type = LYOUT_STREAM;
- out.method.f = f;
-
- ret = lys_print_(&out, module, format, line_length, options);
if (ret) {
/* error */
return (-1) * ret;
} else {
/* success */
- return (ssize_t)out.printed;
+ return (ssize_t)(out->printed - printed_prev);
}
}
API ssize_t
-lys_print_path(const char *path, const struct lys_module *module, LYS_OUTFORMAT format, int line_length, int options)
-{
- FILE *f;
- ssize_t ret;
-
- LY_CHECK_ARG_RET(NULL, path, module, LY_EINVAL);
-
- f = fopen(path, "w");
- if (!f) {
- LOGERR(module->ctx, LY_ESYS, "Failed to open file \"%s\" (%s).", path, strerror(errno));
- return LY_ESYS;
- }
-
- ret = lys_print_file(f, module, format, line_length, options);
- fclose(f);
- return ret;
-}
-
-API ssize_t
-lys_print_fd(int fd, const struct lys_module *module, LYS_OUTFORMAT format, int line_length, int options)
+lys_print_node(struct lyp_out *out, const struct lysc_node *node, LYS_OUTFORMAT format, int UNUSED(line_length), int options)
{
LY_ERR ret;
- struct lyout out;
+ size_t printed_prev;
- LY_CHECK_ARG_RET(NULL, fd >= 0, module, LY_EINVAL);
+ LY_CHECK_ARG_RET(NULL, out, node, -LY_EINVAL);
- memset(&out, 0, sizeof out);
- out.ctx = module->ctx;
- out.type = LYOUT_FD;
- out.method.fd = fd;
+ printed_prev = out->printed;
- ret = lys_print_(&out, module, format, line_length, options);
-
- if (out.type == LYOUT_FDSTREAM) {
- /* close temporary stream based on the given file descriptor */
- fclose(out.method.f);
- /* move the original file descriptor to the end of the output file */
- lseek(fd, 0, SEEK_END);
+ switch (format) {
+ case LYS_OUT_YANG_COMPILED:
+ ret = yang_print_compiled_node(out, node, options);
+ break;
+ /* TODO not yet implemented
+ case LYS_OUT_YIN:
+ ret = yin_print_parsed(out, module);
+ break;
+ case LYS_OUT_TREE:
+ ret = tree_print_model(out, module, target_node, line_length, options);
+ break;
+ */
+ default:
+ LOGERR(NULL, LY_EINVAL, "Unsupported output format.");
+ ret = LY_EINVAL;
+ break;
}
if (ret) {
@@ -137,55 +100,7 @@
return (-1) * ret;
} else {
/* success */
- return (ssize_t)out.printed;
+ return (ssize_t)(out->printed - printed_prev);
}
}
-API ssize_t
-lys_print_mem(char **strp, const struct lys_module *module, LYS_OUTFORMAT format, int line_length, int options)
-{
- struct lyout out;
- LY_ERR ret;
-
- LY_CHECK_ARG_RET(NULL, strp, module, LY_EINVAL);
-
- memset(&out, 0, sizeof out);
- out.ctx = module->ctx;
- out.type = LYOUT_MEMORY;
-
- ret = lys_print_(&out, module, format, line_length, options);
- if (ret) {
- /* error */
- *strp = NULL;
- return (-1) * ret;
- } else {
- /* success */
- *strp = out.method.mem.buf;
- return (ssize_t)out.printed;
- }
-}
-
-API ssize_t
-lys_print_clb(ssize_t (*writeclb)(void *arg, const void *buf, size_t count), void *arg, const struct lys_module *module,
- LYS_OUTFORMAT format, int line_length, int options)
-{
- LY_ERR ret;
- struct lyout out;
-
- LY_CHECK_ARG_RET(NULL, writeclb, module, LY_EINVAL);
-
- memset(&out, 0, sizeof out);
- out.ctx = module->ctx;
- out.type = LYOUT_CALLBACK;
- out.method.clb.f = writeclb;
- out.method.clb.arg = arg;
-
- ret = lys_print_(&out, module, format, line_length, options);
- if (ret) {
- /* error */
- return (-1) * ret;
- } else {
- /* success */
- return (ssize_t)out.printed;
- }
-}
diff --git a/src/printer_schema.h b/src/printer_schema.h
index 613e768..1162cc2 100644
--- a/src/printer_schema.h
+++ b/src/printer_schema.h
@@ -18,74 +18,53 @@
#include <stdio.h>
#include <unistd.h>
+#include "printer.h"
#include "tree_schema.h"
/**
- * @brief Print schema tree in the specified format into a memory block.
- * It is up to caller to free the returned string by free().
+ * @addtogroup schematree
+ * @{
+ */
+
+/**
+ * @defgroup schemaprinterflags Schema output options
+ * @{
+ */
+#define LYS_OUTPUT_NO_SUBSTMT 0x10 /**< Print only top-level/referede node information,
+ do not print information from the substatements */
+//#define LYS_OUTOPT_TREE_RFC 0x01 /**< Conform to the RFC TODO tree output (only for tree format) */
+//#define LYS_OUTOPT_TREE_GROUPING 0x02 /**< Print groupings separately (only for tree format) */
+//#define LYS_OUTOPT_TREE_USES 0x04 /**< Print only uses instead the resolved grouping nodes (only for tree format) */
+//#define LYS_OUTOPT_TREE_NO_LEAFREF 0x08 /**< Do not print the target of leafrefs (only for tree format) */
+
+/** @} schemaprinterflags */
+
+/**
+ * @brief Schema module printer.
*
- * @param[out] strp Pointer to store the resulting dump.
- * @param[in] module Schema tree to print.
- * @param[in] format Schema output format.
+ * @param[in] out Printer handler for a specific output. Use lyp_*() functions to create the handler and lyp_free() to remove the handler.
+ * @param[in] module Schema to print.
+ * @param[in] format Output format.
* @param[in] line_length Maximum characters to be printed on a line, 0 for unlimited. Only for #LYS_OUT_TREE printer.
* @param[in] options Schema output options (see @ref schemaprinterflags).
* @return Number of printed bytes in case of success.
* @return Negative value failure (absolute value corresponds to LY_ERR values).
*/
-ssize_t lys_print_mem(char **strp, const struct lys_module *module, LYS_OUTFORMAT format, int line_length, int options);
+ssize_t lys_print(struct lyp_out *out, const struct lys_module *module, LYS_OUTFORMAT format, int line_length, int options);
/**
- * @brief Print schema tree in the specified format into a file descriptor.
+ * @brief Schema node printer.
*
- * @param[in] module Schema tree to print.
- * @param[in] fd File descriptor where to print the data.
- * @param[in] format Schema output format.
- * @param[in] line_length Maximum characters to be printed on a line, 0 for unlimited. Only for #LYS_OUT_TREE format.
- * @param[in] options Schema output options (see @ref schemaprinterflags).
- * @return Number of printed bytes in case of success.
- * @return Negative value failure (absolute value corresponds to LY_ERR values).
- */
-ssize_t lys_print_fd(int fd, const struct lys_module *module, LYS_OUTFORMAT format, int line_length, int options);
-
-/**
- * @brief Print schema tree in the specified format into a file stream.
- *
- * @param[in] module Schema tree to print.
- * @param[in] f File stream where to print the schema.
- * @param[in] format Schema output format.
+ * @param[in] out Printer handler for a specific output. Use lyp_*() functions to create the handler and lyp_free() to remove the handler.
+ * @param[in] node Schema node to print, lys_find_node() can be used to get it from a path string.
+ * @param[in] format Output format.
* @param[in] line_length Maximum characters to be printed on a line, 0 for unlimited. Only for #LYS_OUT_TREE printer.
* @param[in] options Schema output options (see @ref schemaprinterflags).
* @return Number of printed bytes in case of success.
* @return Negative value failure (absolute value corresponds to LY_ERR values).
*/
-ssize_t lys_print_file(FILE *f, const struct lys_module *module, LYS_OUTFORMAT format, int line_length, int options);
+ssize_t lys_print_node(struct lyp_out *out, const struct lysc_node *node, LYS_OUTFORMAT format, int line_length, int options);
-/**
- * @brief Print schema tree in the specified format into a file.
- *
- * @param[in] path File where to print the schema.
- * @param[in] module Schema tree to print.
- * @param[in] format Schema output format.
- * @param[in] line_length Maximum characters to be printed on a line, 0 for unlimited. Only for #LYS_OUT_TREE printer.
- * @param[in] options Schema output options (see @ref schemaprinterflags).
- * @return Number of printed bytes in case of success.
- * @return Negative value failure (absolute value corresponds to LY_ERR values).
- */
-ssize_t lys_print_path(const char *path, const struct lys_module *module, LYS_OUTFORMAT format, int line_length, int options);
-
-/**
- * @brief Print schema tree in the specified format using a provided callback.
- *
- * @param[in] module Schema tree to print.
- * @param[in] writeclb Callback function to write the data (see write(1)).
- * @param[in] arg Optional caller-specific argument to be passed to the \p writeclb callback.
- * @param[in] format Schema output format.
- * @param[in] line_length Maximum characters to be printed on a line, 0 for unlimited. Only for #LYS_OUT_TREE printer.
- * @param[in] options Schema output options (see @ref schemaprinterflags).
- * @return Number of printed bytes in case of success.
- * @return Negative value failure (absolute value corresponds to LY_ERR values).
- */
-ssize_t lys_print_clb(ssize_t (*writeclb)(void *arg, const void *buf, size_t count), void *arg,
- const struct lys_module *module, LYS_OUTFORMAT format, int line_length, int options);
+/** @} schematree */
#endif /* LY_PRINTER_SCHEMA_H_ */
diff --git a/src/printer_xml.c b/src/printer_xml.c
index 279d336..b1d187c 100644
--- a/src/printer_xml.c
+++ b/src/printer_xml.c
@@ -32,7 +32,7 @@
* @brief XML printer context.
*/
struct xmlpr_ctx {
- struct lyout *out; /**< output specification */
+ struct lyp_out *out; /**< output specification */
unsigned int level; /**< current indentation level: 0 - no formatting, >= 1 indentation levels */
int options; /**< [Data printer flags](@ref dataprinterflags) */
const struct ly_ctx *ctx; /**< libyang context */
@@ -89,7 +89,7 @@
if (i == -1) {
/* suitable namespace not found, must be printed */
- ly_print(ctx->out, " xmlns%s%s=\"%s\"", new_prefix ? ":" : "", new_prefix ? new_prefix : "", ns);
+ lyp_print(ctx->out, " xmlns%s%s=\"%s\"", new_prefix ? ":" : "", new_prefix ? new_prefix : "", ns);
/* and added into namespaces */
if (new_prefix) {
@@ -144,7 +144,7 @@
/* we have implicit OR explicit default node, print attribute only if context include with-defaults schema */
mod = ly_ctx_get_module_latest(node->schema->module->ctx, "ietf-netconf-with-defaults");
if (mod) {
- ly_print(ctx->out, " %s:default=\"true\"", xml_print_ns(ctx, mod->ns, mod->prefix, 0));
+ lyp_print(ctx->out, " %s:default=\"true\"", xml_print_ns(ctx, mod->ns, mod->prefix, 0));
}
}
}
@@ -177,17 +177,17 @@
}
for (i = 0; i < ns_count; ++i) {
- ly_print(out, " xmlns:%s=\"%s\"", prefs[i], nss[i]);
+ lyp_print(out, " xmlns:%s=\"%s\"", prefs[i], nss[i]);
}
free(prefs);
free(nss);
}
- ly_print(out, " %s=\"", meta->name);
+ lyp_print(out, " %s=\"", meta->name);
} else {
#endif
/* print the metadata with its namespace */
mod = meta->annotation->module;
- ly_print(ctx->out, " %s:%s=\"", xml_print_ns(ctx, mod->ns, mod->prefix, 1), meta->name);
+ lyp_print(ctx->out, " %s:%s=\"", xml_print_ns(ctx, mod->ns, mod->prefix, 1), meta->name);
#if 0
}
#endif
@@ -196,7 +196,7 @@
if (value && value[0]) {
lyxml_dump_text(ctx->out, value, 1);
}
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
if (dynamic) {
free((void *)value);
}
@@ -215,7 +215,7 @@
xml_print_node_open(struct xmlpr_ctx *ctx, const struct lyd_node *node)
{
/* print node name */
- ly_print(ctx->out, "%*s<%s", INDENT, node->schema->name);
+ lyp_print(ctx->out, "%*s<%s", INDENT, node->schema->name);
/* print default namespace */
xml_print_ns(ctx, node->schema->module->ns, NULL, 0);
@@ -254,7 +254,7 @@
}
/* print the attribute with its prefix and value */
- ly_print(ctx->out, " %s%s%s=\"%s\"", pref ? pref : "", pref ? ":" : "", attr->name, attr->value);
+ lyp_print(ctx->out, " %s%s%s=\"%s\"", pref ? pref : "", pref ? ":" : "", attr->name, attr->value);
}
return LY_SUCCESS;
@@ -264,7 +264,7 @@
xml_print_opaq_open(struct xmlpr_ctx *ctx, const struct lyd_node_opaq *node)
{
/* print node name */
- ly_print(ctx->out, "%*s<%s", INDENT, node->name);
+ lyp_print(ctx->out, "%*s<%s", INDENT, node->name);
/* print default namespace */
switch (node->format) {
@@ -305,16 +305,16 @@
/* print namespaces connected with the values's prefixes */
for (u = 0; u < ns_list.count; ++u) {
const struct lys_module *mod = (const struct lys_module *)ns_list.objs[u];
- ly_print(ctx->out, " xmlns:%s=\"%s\"", mod->prefix, mod->ns);
+ lyp_print(ctx->out, " xmlns:%s=\"%s\"", mod->prefix, mod->ns);
}
ly_set_erase(&ns_list, NULL);
if (!value || !value[0]) {
- ly_print(ctx->out, "/>%s", LEVEL ? "\n" : "");
+ lyp_print(ctx->out, "/>%s", LEVEL ? "\n" : "");
} else {
- ly_print(ctx->out, ">");
+ lyp_print(ctx->out, ">");
lyxml_dump_text(ctx->out, value, 0);
- ly_print(ctx->out, "</%s>%s", node->schema->name, LEVEL ? "\n" : "");
+ lyp_print(ctx->out, "</%s>%s", node->schema->name, LEVEL ? "\n" : "");
}
if (dynamic) {
free((void *)value);
@@ -337,12 +337,12 @@
xml_print_node_open(ctx, (struct lyd_node *)node);
if (!node->child) {
- ly_print(ctx->out, "/>%s", ctx->level ? "\n" : "");
+ lyp_print(ctx->out, "/>%s", ctx->level ? "\n" : "");
return LY_SUCCESS;
}
/* children */
- ly_print(ctx->out, ">%s", ctx->level ? "\n" : "");
+ lyp_print(ctx->out, ">%s", ctx->level ? "\n" : "");
LEVEL_INC;
LY_LIST_FOR(node->child, child) {
@@ -351,7 +351,7 @@
}
LEVEL_DEC;
- ly_print(ctx->out, "%*s</%s>%s", INDENT, node->schema->name, LEVEL ? "\n" : "");
+ lyp_print(ctx->out, "%*s</%s>%s", INDENT, node->schema->name, LEVEL ? "\n" : "");
return LY_SUCCESS;
}
@@ -369,7 +369,7 @@
if (!any->value.tree) {
/* no content */
no_content:
- ly_print(ctx->out, "/>%s", LEVEL ? "\n" : "");
+ lyp_print(ctx->out, "/>%s", LEVEL ? "\n" : "");
return LY_SUCCESS;
} else {
switch (any->value_type) {
@@ -379,7 +379,7 @@
ctx->options &= ~LYDP_WITHSIBLINGS;
LEVEL_INC;
- ly_print(ctx->out, ">%s", LEVEL ? "\n" : "");
+ lyp_print(ctx->out, ">%s", LEVEL ? "\n" : "");
LY_LIST_FOR(any->value.tree, iter) {
ret = xml_print_node(ctx, iter);
LY_CHECK_ERR_RET(ret, LEVEL_DEC, ret);
@@ -394,7 +394,7 @@
goto no_content;
}
/* close opening tag and print data */
- ly_print(ctx->out, ">");
+ lyp_print(ctx->out, ">");
lyxml_dump_text(ctx->out, any->value.str, 0);
break;
case LYD_ANYDATA_XML:
@@ -402,7 +402,7 @@
if (!any->value.str[0]) {
goto no_content;
}
- ly_print(ctx->out, ">%s", any->value.str);
+ lyp_print(ctx->out, ">%s", any->value.str);
break;
case LYD_ANYDATA_JSON:
#if 0 /* TODO LYB format */
@@ -415,9 +415,9 @@
/* closing tag */
if (any->value_type == LYD_ANYDATA_DATATREE) {
- ly_print(ctx->out, "%*s</%s>%s", INDENT, node->schema->name, LEVEL ? "\n" : "");
+ lyp_print(ctx->out, "%*s</%s>%s", INDENT, node->schema->name, LEVEL ? "\n" : "");
} else {
- ly_print(ctx->out, "</%s>%s", node->schema->name, LEVEL ? "\n" : "");
+ lyp_print(ctx->out, "</%s>%s", node->schema->name, LEVEL ? "\n" : "");
}
}
@@ -441,13 +441,13 @@
}
}
- ly_print(ctx->out, ">%s", node->value);
+ lyp_print(ctx->out, ">%s", node->value);
}
if (node->child) {
/* children */
if (!node->value[0]) {
- ly_print(ctx->out, ">%s", ctx->level ? "\n" : "");
+ lyp_print(ctx->out, ">%s", ctx->level ? "\n" : "");
}
LEVEL_INC;
@@ -457,12 +457,12 @@
}
LEVEL_DEC;
- ly_print(ctx->out, "%*s</%s>%s", INDENT, node->name, LEVEL ? "\n" : "");
+ lyp_print(ctx->out, "%*s</%s>%s", INDENT, node->name, LEVEL ? "\n" : "");
} else if (node->value[0]) {
- ly_print(ctx->out, "</%s>%s", node->name, LEVEL ? "\n" : "");
+ lyp_print(ctx->out, "</%s>%s", node->name, LEVEL ? "\n" : "");
} else {
/* no value or children */
- ly_print(ctx->out, "/>%s", ctx->level ? "\n" : "");
+ lyp_print(ctx->out, "/>%s", ctx->level ? "\n" : "");
}
return LY_SUCCESS;
@@ -526,14 +526,14 @@
}
LY_ERR
-xml_print_data(struct lyout *out, const struct lyd_node *root, int options)
+xml_print_data(struct lyp_out *out, const struct lyd_node *root, int options)
{
const struct lyd_node *node;
struct xmlpr_ctx ctx = {0};
if (!root) {
- if (out->type == LYOUT_MEMORY || out->type == LYOUT_CALLBACK) {
- ly_print(out, "");
+ if (out->type == LYP_OUT_MEMORY || out->type == LYP_OUT_CALLBACK) {
+ lyp_print(out, "");
}
goto finish;
}
diff --git a/src/printer_yang.c b/src/printer_yang.c
index 41fb7e9..43d3833 100755
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -41,10 +41,11 @@
* @brief YANG printer context.
*/
struct ypr_ctx {
- struct lyout *out; /**< output specification */
+ struct lyp_out *out; /**< output specification */
unsigned int level; /**< current indentation level: 0 - no formatting, >= 1 indentation levels */
const struct lys_module *module; /**< schema to print */
enum schema_type schema; /**< type of the schema to print */
+ int options; /**< Schema output options (see @ref schemaprinterflags). */
};
#define LEVEL ctx->level /**< current level */
@@ -63,7 +64,7 @@
* the @p text is printed completely as a NULL-terminated string.
*/
static void
-ypr_encode(struct lyout *out, const char *text, int len)
+ypr_encode(struct lyp_out *out, const char *text, int len)
{
int i, start_len;
const char *start;
@@ -93,19 +94,19 @@
}
if (special) {
- ly_write(out, start, start_len);
+ lyp_write(out, start, start_len);
switch (special) {
case '\n':
- ly_write(out, "\\n", 2);
+ lyp_write(out, "\\n", 2);
break;
case '\t':
- ly_write(out, "\\t", 2);
+ lyp_write(out, "\\t", 2);
break;
case '\"':
- ly_write(out, "\\\"", 2);
+ lyp_write(out, "\\\"", 2);
break;
case '\\':
- ly_write(out, "\\\\", 2);
+ lyp_write(out, "\\\\", 2);
break;
}
@@ -116,15 +117,15 @@
}
}
- ly_write(out, start, start_len);
+ lyp_write(out, start, start_len);
}
static void
-ypr_open(struct lyout *out, int *flag)
+ypr_open(struct lyp_out *out, int *flag)
{
if (flag && !*flag) {
*flag = 1;
- ly_print(out, " {\n");
+ lyp_print(out, " {\n");
}
}
@@ -132,9 +133,9 @@
ypr_close(struct ypr_ctx *ctx, int flag)
{
if (flag) {
- ly_print(ctx->out, "%*s}\n", INDENT);
+ lyp_print(ctx->out, "%*s}\n", INDENT);
} else {
- ly_print(ctx->out, ";\n");
+ lyp_print(ctx->out, ";\n");
}
}
@@ -144,28 +145,28 @@
const char *s, *t;
if (singleline) {
- ly_print(ctx->out, "%*s%s \"", INDENT, name);
+ lyp_print(ctx->out, "%*s%s \"", INDENT, name);
} else {
- ly_print(ctx->out, "%*s%s\n", INDENT, name);
+ lyp_print(ctx->out, "%*s%s\n", INDENT, name);
LEVEL++;
- ly_print(ctx->out, "%*s\"", INDENT);
+ lyp_print(ctx->out, "%*s\"", INDENT);
}
t = text;
while ((s = strchr(t, '\n'))) {
ypr_encode(ctx->out, t, s - t);
- ly_print(ctx->out, "\n");
+ lyp_print(ctx->out, "\n");
t = s + 1;
if (*t != '\n') {
- ly_print(ctx->out, "%*s ", INDENT);
+ lyp_print(ctx->out, "%*s ", INDENT);
}
}
ypr_encode(ctx->out, t, strlen(t));
if (closed) {
- ly_print(ctx->out, "\";\n");
+ lyp_print(ctx->out, "\";\n");
} else {
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
}
if (!singleline) {
LEVEL--;
@@ -180,26 +181,26 @@
if (stmt->arg) {
if (stmt->flags) {
- ly_print(ctx->out, "%*s%s\n", INDENT, stmt->stmt);
+ lyp_print(ctx->out, "%*s%s\n", INDENT, stmt->stmt);
LEVEL++;
- ly_print(ctx->out, "%*s%c", INDENT, (stmt->flags & LYS_DOUBLEQUOTED) ? '\"' : '\'');
+ lyp_print(ctx->out, "%*s%c", INDENT, (stmt->flags & LYS_DOUBLEQUOTED) ? '\"' : '\'');
t = stmt->arg;
while ((s = strchr(t, '\n'))) {
ypr_encode(ctx->out, t, s - t);
- ly_print(ctx->out, "\n");
+ lyp_print(ctx->out, "\n");
t = s + 1;
if (*t != '\n') {
- ly_print(ctx->out, "%*s ", INDENT);
+ lyp_print(ctx->out, "%*s ", INDENT);
}
}
LEVEL--;
ypr_encode(ctx->out, t, strlen(t));
- ly_print(ctx->out, "%c%s", (stmt->flags & LYS_DOUBLEQUOTED) ? '\"' : '\'', stmt->child ? " {\n" : ";\n");
+ lyp_print(ctx->out, "%c%s", (stmt->flags & LYS_DOUBLEQUOTED) ? '\"' : '\'', stmt->child ? " {\n" : ";\n");
} else {
- ly_print(ctx->out, "%*s%s %s%s", INDENT, stmt->stmt, stmt->arg, stmt->child ? " {\n" : ";\n");
+ lyp_print(ctx->out, "%*s%s %s%s", INDENT, stmt->stmt, stmt->arg, stmt->child ? " {\n" : ";\n");
}
} else {
- ly_print(ctx->out, "%*s%s%s", INDENT, stmt->stmt, stmt->child ? " {\n" : ";\n");
+ lyp_print(ctx->out, "%*s%s%s", INDENT, stmt->stmt, stmt->child ? " {\n" : ";\n");
}
if (stmt->child) {
@@ -208,7 +209,7 @@
yprp_stmt(ctx, childstmt);
}
LEVEL--;
- ly_print(ctx->out, "%*s}\n", INDENT);
+ lyp_print(ctx->out, "%*s}\n", INDENT);
}
}
@@ -238,7 +239,7 @@
}
if (!ext->compiled && ext->yin) {
- ly_print(ctx->out, "%*s%s; // Model comes from different input format, extensions must be resolved first.\n", INDENT, ext[u].name);
+ lyp_print(ctx->out, "%*s%s; // Model comes from different input format, extensions must be resolved first.\n", INDENT, ext[u].name);
continue;
}
@@ -251,11 +252,11 @@
argument = ext[u].argument;
}
if (argument) {
- ly_print(ctx->out, "%*s%s \"", INDENT, ext[u].name);
+ lyp_print(ctx->out, "%*s%s \"", INDENT, ext[u].name);
ypr_encode(ctx->out, argument, -1);
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
} else {
- ly_print(ctx->out, "%*s%s", INDENT, ext[u].name);
+ lyp_print(ctx->out, "%*s%s", INDENT, ext[u].name);
}
child_presence = 0;
@@ -265,16 +266,16 @@
continue;
}
if (!child_presence) {
- ly_print(ctx->out, " {\n");
+ lyp_print(ctx->out, " {\n");
child_presence = 1;
}
yprp_stmt(ctx, stmt);
}
LEVEL--;
if (child_presence) {
- ly_print(ctx->out, "%*s}\n", INDENT);
+ lyp_print(ctx->out, "%*s}\n", INDENT);
} else {
- ly_print(ctx->out, ";\n");
+ lyp_print(ctx->out, ";\n");
}
}
}
@@ -317,7 +318,7 @@
}
if (ext_substmt_info[substmt].flags & SUBST_FLAG_ID) {
- ly_print(ctx->out, "%*s%s %s", INDENT, ext_substmt_info[substmt].name, text);
+ lyp_print(ctx->out, "%*s%s %s", INDENT, ext_substmt_info[substmt].name, text);
} else {
ypr_text(ctx, ext_substmt_info[substmt].name, text,
(ext_substmt_info[substmt].flags & SUBST_FLAG_YIN) ? 0 : 1, 0);
@@ -372,15 +373,15 @@
yprp_revision(struct ypr_ctx *ctx, const struct lysp_revision *rev)
{
if (rev->dsc || rev->ref || rev->exts) {
- ly_print(ctx->out, "%*srevision %s {\n", INDENT, rev->date);
+ lyp_print(ctx->out, "%*srevision %s {\n", INDENT, rev->date);
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, rev->exts, NULL, 0);
ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, rev->dsc, rev->exts);
ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, rev->ref, rev->exts);
LEVEL--;
- ly_print(ctx->out, "%*s}\n", INDENT);
+ lyp_print(ctx->out, "%*s}\n", INDENT);
} else {
- ly_print(ctx->out, "%*srevision %s;\n", INDENT, rev->date);
+ lyp_print(ctx->out, "%*srevision %s;\n", INDENT, rev->date);
}
}
@@ -449,7 +450,7 @@
ypr_open(ctx->out, flag);
extflag = 0;
- ly_print(ctx->out, "%*sif-feature \"%s\"", INDENT, iff[u]);
+ lyp_print(ctx->out, "%*sif-feature \"%s\"", INDENT, iff[u]);
/* extensions */
LEVEL++;
@@ -476,14 +477,14 @@
switch (op) {
case LYS_IFF_F:
if (ctx->module == feat->features[*index_f]->module) {
- ly_print(ctx->out, "%s", feat->features[*index_f]->name);
+ lyp_print(ctx->out, "%s", feat->features[*index_f]->name);
} else {
- ly_print(ctx->out, "%s:%s", feat->features[*index_f]->module->prefix, feat->features[*index_f]->name);
+ lyp_print(ctx->out, "%s:%s", feat->features[*index_f]->module->prefix, feat->features[*index_f]->name);
}
(*index_f)++;
break;
case LYS_IFF_NOT:
- ly_print(ctx->out, "not ");
+ lyp_print(ctx->out, "not ");
yprc_iffeature(ctx, feat, index_e, index_f);
break;
case LYS_IFF_AND:
@@ -496,13 +497,13 @@
/* falls through */
case LYS_IFF_OR:
if (brackets_flag) {
- ly_print(ctx->out, "(");
+ lyp_print(ctx->out, "(");
}
yprc_iffeature(ctx, feat, index_e, index_f);
- ly_print(ctx->out, " %s ", op == LYS_IFF_OR ? "or" : "and");
+ lyp_print(ctx->out, " %s ", op == LYS_IFF_OR ? "or" : "and");
yprc_iffeature(ctx, feat, index_e, index_f);
if (brackets_flag) {
- ly_print(ctx->out, ")");
+ lyp_print(ctx->out, ")");
}
}
}
@@ -519,9 +520,9 @@
ypr_open(ctx->out, flag);
extflag = 0;
- ly_print(ctx->out, "%*sif-feature \"", INDENT);
+ lyp_print(ctx->out, "%*sif-feature \"", INDENT);
yprc_iffeature(ctx, iff, &index_e, &index_f);
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
/* extensions */
LEVEL++;
@@ -542,7 +543,7 @@
int flag = 0, flag2 = 0;
LY_ARRAY_SIZE_TYPE u;
- ly_print(ctx->out, "%*sextension %s", INDENT, ext->name);
+ lyp_print(ctx->out, "%*sextension %s", INDENT, ext->name);
LEVEL++;
if (ext->exts) {
@@ -551,7 +552,7 @@
if (ext->argument) {
ypr_open(ctx->out, &flag);
- ly_print(ctx->out, "%*sargument %s", INDENT, ext->argument);
+ lyp_print(ctx->out, "%*sargument %s", INDENT, ext->argument);
LEVEL++;
if (ext->exts) {
u = -1;
@@ -581,7 +582,7 @@
{
int flag = 0;
- ly_print(ctx->out, "\n%*sfeature %s", INDENT, feat->name);
+ lyp_print(ctx->out, "\n%*sfeature %s", INDENT, feat->name);
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, feat->exts, &flag, 0);
yprp_iffeatures(ctx, feat->iffeatures, feat->exts, &flag);
@@ -597,7 +598,7 @@
{
int flag = 0;
- ly_print(ctx->out, "\n%*sfeature %s", INDENT, feat->name);
+ lyp_print(ctx->out, "\n%*sfeature %s", INDENT, feat->name);
LEVEL++;
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, feat->exts, &flag, 0);
yprc_iffeatures(ctx, feat->iffeatures, feat->exts, &flag);
@@ -614,7 +615,7 @@
int flag = 0;
LY_ARRAY_SIZE_TYPE u;
- ly_print(ctx->out, "\n%*sidentity %s", INDENT, ident->name);
+ lyp_print(ctx->out, "\n%*sidentity %s", INDENT, ident->name);
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, ident->exts, &flag, 0);
@@ -639,7 +640,7 @@
int flag = 0;
LY_ARRAY_SIZE_TYPE u;
- ly_print(ctx->out, "\n%*sidentity %s", INDENT, ident->name);
+ lyp_print(ctx->out, "\n%*sidentity %s", INDENT, ident->name);
LEVEL++;
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, ident->exts, &flag, 0);
@@ -648,9 +649,9 @@
LY_ARRAY_FOR(ident->derived, u) {
ypr_open(ctx->out, &flag);
if (ctx->module != ident->derived[u]->module) {
- ly_print(ctx->out, "%*sderived %s:%s;\n", INDENT, ident->derived[u]->module->prefix, ident->derived[u]->name);
+ lyp_print(ctx->out, "%*sderived %s:%s;\n", INDENT, ident->derived[u]->module->prefix, ident->derived[u]->name);
} else {
- ly_print(ctx->out, "%*sderived %s;\n", INDENT, ident->derived[u]->name);
+ lyp_print(ctx->out, "%*sderived %s;\n", INDENT, ident->derived[u]->name);
}
}
@@ -672,9 +673,9 @@
}
ypr_open(ctx->out, flag);
- ly_print(ctx->out, "%*s%s \"", INDENT, name);
+ lyp_print(ctx->out, "%*s%s \"", INDENT, name);
ypr_encode(ctx->out, (restr->arg[0] != 0x15 && restr->arg[0] != 0x06) ? restr->arg : &restr->arg[1], -1);
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, restr->exts, &inner_flag, 0);
@@ -704,9 +705,9 @@
int inner_flag = 0;
ypr_open(ctx->out, flag);
- ly_print(ctx->out, "%*smust \"", INDENT);
+ lyp_print(ctx->out, "%*smust \"", INDENT);
ypr_encode(ctx->out, must->cond->expr, -1);
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
LEVEL++;
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, must->exts, &inner_flag, 0);
@@ -736,26 +737,26 @@
}
ypr_open(ctx->out, flag);
- ly_print(ctx->out, "%*s%s \"", INDENT, (basetype == LY_TYPE_STRING || basetype == LY_TYPE_BINARY) ? "length" : "range");
+ lyp_print(ctx->out, "%*s%s \"", INDENT, (basetype == LY_TYPE_STRING || basetype == LY_TYPE_BINARY) ? "length" : "range");
LY_ARRAY_FOR(range->parts, u) {
if (u > 0) {
- ly_print(ctx->out, " | ");
+ lyp_print(ctx->out, " | ");
}
if (range->parts[u].max_64 == range->parts[u].min_64) {
if (basetype <= LY_TYPE_STRING) { /* unsigned values */
- ly_print(ctx->out, "%"PRIu64, range->parts[u].max_u64);
+ lyp_print(ctx->out, "%"PRIu64, range->parts[u].max_u64);
} else { /* signed values */
- ly_print(ctx->out, "%"PRId64, range->parts[u].max_64);
+ lyp_print(ctx->out, "%"PRId64, range->parts[u].max_64);
}
} else {
if (basetype <= LY_TYPE_STRING) { /* unsigned values */
- ly_print(ctx->out, "%"PRIu64"..%"PRIu64, range->parts[u].min_u64, range->parts[u].max_u64);
+ lyp_print(ctx->out, "%"PRIu64"..%"PRIu64, range->parts[u].min_u64, range->parts[u].max_u64);
} else { /* signed values */
- ly_print(ctx->out, "%"PRId64"..%"PRId64, range->parts[u].min_64, range->parts[u].max_64);
+ lyp_print(ctx->out, "%"PRId64"..%"PRId64, range->parts[u].min_64, range->parts[u].max_64);
}
}
}
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
LEVEL++;
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, range->exts, &inner_flag, 0);
@@ -780,9 +781,9 @@
int inner_flag = 0;
ypr_open(ctx->out, flag);
- ly_print(ctx->out, "%*spattern \"", INDENT);
+ lyp_print(ctx->out, "%*spattern \"", INDENT);
ypr_encode(ctx->out, pattern->expr, -1);
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
LEVEL++;
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, pattern->exts, &inner_flag, 0);
@@ -816,9 +817,9 @@
}
ypr_open(ctx->out, flag);
- ly_print(ctx->out, "%*swhen \"", INDENT);
+ lyp_print(ctx->out, "%*swhen \"", INDENT);
ypr_encode(ctx->out, when->cond, -1);
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, when->exts, &inner_flag, 0);
@@ -838,9 +839,9 @@
}
ypr_open(ctx->out, flag);
- ly_print(ctx->out, "%*swhen \"", INDENT);
+ lyp_print(ctx->out, "%*swhen \"", INDENT);
ypr_encode(ctx->out, when->cond->expr, -1);
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
LEVEL++;
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, when->exts, &inner_flag, 0);
@@ -859,11 +860,11 @@
LY_ARRAY_FOR(items, u) {
ypr_open(ctx->out, flag);
if (type == LY_TYPE_BITS) {
- ly_print(ctx->out, "%*sbit %s", INDENT, items[u].name);
+ lyp_print(ctx->out, "%*sbit %s", INDENT, items[u].name);
} else { /* LY_TYPE_ENUM */
- ly_print(ctx->out, "%*senum \"", INDENT);
+ lyp_print(ctx->out, "%*senum \"", INDENT);
ypr_encode(ctx->out, items[u].name, -1);
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
}
inner_flag = 0;
LEVEL++;
@@ -890,7 +891,7 @@
LY_ARRAY_SIZE_TYPE u;
int flag = 0;
- ly_print(ctx->out, "%*stype %s", INDENT, type->name);
+ lyp_print(ctx->out, "%*stype %s", INDENT, type->name);
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, type->exts, &flag, 0);
@@ -946,7 +947,7 @@
LY_ARRAY_SIZE_TYPE u;
int flag = 0;
- ly_print(ctx->out, "%*stype %s", INDENT, lys_datatype2str(type->basetype));
+ lyp_print(ctx->out, "%*stype %s", INDENT, lys_datatype2str(type->basetype));
LEVEL++;
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, type->exts, &flag, 0);
@@ -990,9 +991,9 @@
int inner_flag = 0;
ypr_open(ctx->out, &flag);
- ly_print(ctx->out, "%*s%s \"", INDENT, type->basetype == LY_TYPE_BITS ? "bit" : "enum");
+ lyp_print(ctx->out, "%*s%s \"", INDENT, type->basetype == LY_TYPE_BITS ? "bit" : "enum");
ypr_encode(ctx->out, item->name, -1);
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
LEVEL++;
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, item->exts, &inner_flag, 0);
yprc_iffeatures(ctx, item->iffeatures, item->exts, &inner_flag);
@@ -1064,7 +1065,7 @@
{
LYOUT_CHECK(ctx->out);
- ly_print(ctx->out, "\n%*stypedef %s {\n", INDENT, tpdf->name);
+ lyp_print(ctx->out, "\n%*stypedef %s {\n", INDENT, tpdf->name);
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, tpdf->exts, NULL, 0);
@@ -1083,7 +1084,7 @@
ypr_reference(ctx, tpdf->ref, tpdf->exts, NULL);
LEVEL--;
- ly_print(ctx->out, "%*s}\n", INDENT);
+ lyp_print(ctx->out, "%*s}\n", INDENT);
}
static void yprp_node(struct ypr_ctx *ctx, const struct lysp_node *node);
@@ -1099,7 +1100,7 @@
LYOUT_CHECK(ctx->out);
- ly_print(ctx->out, "\n%*sgrouping %s", INDENT, grp->name);
+ lyp_print(ctx->out, "\n%*sgrouping %s", INDENT, grp->name);
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, grp->exts, &flag, 0);
@@ -1142,7 +1143,7 @@
}
ypr_open(ctx->out, flag);
- ly_print(ctx->out, "\n%*s%s {\n", INDENT, (inout->nodetype == LYS_INPUT ? "input" : "output"));
+ lyp_print(ctx->out, "\n%*s%s {\n", INDENT, (inout->nodetype == LYS_INPUT ? "input" : "output"));
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, inout->exts, NULL, 0);
@@ -1176,7 +1177,7 @@
}
ypr_open(ctx->out, flag);
- ly_print(ctx->out, "\n%*s%s {\n", INDENT, (&action->input == inout) ? "input" : "output");
+ lyp_print(ctx->out, "\n%*s%s {\n", INDENT, (&action->input == inout) ? "input" : "output");
LEVEL++;
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, (&action->input == inout) ? action->input_exts : action->output_exts, NULL, 0);
@@ -1184,8 +1185,10 @@
yprc_must(ctx, &inout->musts[u], NULL);
}
- LY_LIST_FOR(inout->data, data) {
- yprc_node(ctx, data);
+ if (!(ctx->options & LYS_OUTPUT_NO_SUBSTMT)) {
+ LY_LIST_FOR(inout->data, data) {
+ yprc_node(ctx, data);
+ }
}
LEVEL--;
@@ -1201,7 +1204,7 @@
LYOUT_CHECK(ctx->out);
- ly_print(ctx->out, "%*snotification %s", INDENT, notif->name);
+ lyp_print(ctx->out, "%*snotification %s", INDENT, notif->name);
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, notif->exts, &flag, 0);
@@ -1242,7 +1245,7 @@
LYOUT_CHECK(ctx->out);
- ly_print(ctx->out, "%*snotification %s", INDENT, notif->name);
+ lyp_print(ctx->out, "%*snotification %s", INDENT, notif->name);
LEVEL++;
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, notif->exts, &flag, 0);
@@ -1255,9 +1258,11 @@
ypr_description(ctx, notif->dsc, notif->exts, &flag);
ypr_reference(ctx, notif->ref, notif->exts, &flag);
- LY_LIST_FOR(notif->data, data) {
- ypr_open(ctx->out, &flag);
- yprc_node(ctx, data);
+ if (!(ctx->options & LYS_OUTPUT_NO_SUBSTMT)) {
+ LY_LIST_FOR(notif->data, data) {
+ ypr_open(ctx->out, &flag);
+ yprc_node(ctx, data);
+ }
}
LEVEL--;
@@ -1272,7 +1277,7 @@
LYOUT_CHECK(ctx->out);
- ly_print(ctx->out, "%*s%s %s", INDENT, action->parent ? "action" : "rpc", action->name);
+ lyp_print(ctx->out, "%*s%s %s", INDENT, action->parent ? "action" : "rpc", action->name);
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, action->exts, &flag, 0);
@@ -1305,7 +1310,7 @@
LYOUT_CHECK(ctx->out);
- ly_print(ctx->out, "%*s%s %s", INDENT, action->parent ? "action" : "rpc", action->name);
+ lyp_print(ctx->out, "%*s%s %s", INDENT, action->parent ? "action" : "rpc", action->name);
LEVEL++;
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, action->exts, &flag, 0);
@@ -1324,7 +1329,7 @@
static void
yprp_node_common1(struct ypr_ctx *ctx, const struct lysp_node *node, int *flag)
{
- ly_print(ctx->out, "%*s%s %s%s", INDENT, lys_nodetype2str(node->nodetype), node->name, flag ? "" : " {\n");
+ lyp_print(ctx->out, "%*s%s %s%s", INDENT, lys_nodetype2str(node->nodetype), node->name, flag ? "" : " {\n");
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, node->exts, flag, 0);
@@ -1337,7 +1342,7 @@
{
LY_ARRAY_SIZE_TYPE u;
- ly_print(ctx->out, "%*s%s %s%s", INDENT, lys_nodetype2str(node->nodetype), node->name, flag ? "" : " {\n");
+ lyp_print(ctx->out, "%*s%s %s%s", INDENT, lys_nodetype2str(node->nodetype), node->name, flag ? "" : " {\n");
LEVEL++;
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, node->exts, flag, 0);
@@ -1440,19 +1445,21 @@
yprc_node_common2(ctx, node, &flag);
- LY_LIST_FOR(cont->child, child) {
- ypr_open(ctx->out, &flag);
- yprc_node(ctx, child);
- }
+ if (!(ctx->options & LYS_OUTPUT_NO_SUBSTMT)) {
+ LY_LIST_FOR(cont->child, child) {
+ ypr_open(ctx->out, &flag);
+ yprc_node(ctx, child);
+ }
- LY_ARRAY_FOR(cont->actions, u) {
- ypr_open(ctx->out, &flag);
- yprc_action(ctx, &cont->actions[u]);
- }
+ LY_ARRAY_FOR(cont->actions, u) {
+ ypr_open(ctx->out, &flag);
+ yprc_action(ctx, &cont->actions[u]);
+ }
- LY_ARRAY_FOR(cont->notifs, u) {
- ypr_open(ctx->out, &flag);
- yprc_notification(ctx, &cont->notifs[u]);
+ LY_ARRAY_FOR(cont->notifs, u) {
+ ypr_open(ctx->out, &flag);
+ yprc_notification(ctx, &cont->notifs[u]);
+ }
}
LEVEL--;
@@ -1487,9 +1494,11 @@
yprc_node_common1(ctx, (struct lysc_node*)cs, &flag);
yprc_node_common2(ctx, (struct lysc_node*)cs, &flag);
- for (child = cs->child; child && child->parent == (struct lysc_node*)cs; child = child->next) {
- ypr_open(ctx->out, &flag);
- yprc_node(ctx, child);
+ if (!(ctx->options & LYS_OUTPUT_NO_SUBSTMT)) {
+ for (child = cs->child; child && child->parent == (struct lysc_node*)cs; child = child->next) {
+ ypr_open(ctx->out, &flag);
+ yprc_node(ctx, child);
+ }
}
LEVEL--;
@@ -1564,7 +1573,7 @@
yprp_node_common2(ctx, node, NULL);
LEVEL--;
- ly_print(ctx->out, "%*s}\n", INDENT);
+ lyp_print(ctx->out, "%*s}\n", INDENT);
}
static void
@@ -1588,7 +1597,7 @@
yprc_node_common2(ctx, node, NULL);
LEVEL--;
- ly_print(ctx->out, "%*s}\n", INDENT);
+ lyp_print(ctx->out, "%*s}\n", INDENT);
}
static void
@@ -1630,7 +1639,7 @@
ypr_reference(ctx, node->ref, node->exts, NULL);
LEVEL--;
- ly_print(ctx->out, "%*s}\n", INDENT);
+ lyp_print(ctx->out, "%*s}\n", INDENT);
}
static void
@@ -1666,7 +1675,7 @@
ypr_reference(ctx, node->ref, node->exts, NULL);
LEVEL--;
- ly_print(ctx->out, "%*s}\n", INDENT);
+ lyp_print(ctx->out, "%*s}\n", INDENT);
}
static void
@@ -1756,17 +1765,17 @@
}
if (!(list->flags & LYS_KEYLESS)) {
ypr_open(ctx->out, &flag);
- ly_print(ctx->out, "%*skey \"", INDENT);
+ lyp_print(ctx->out, "%*skey \"", INDENT);
for (struct lysc_node *key = list->child; key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY); key = key->next) {
- ly_print(ctx->out, "%s%s", u > 0 ? ", " : "", key->name);
+ lyp_print(ctx->out, "%s%s", u > 0 ? ", " : "", key->name);
}
- ly_print(ctx->out, "\";\n");
+ lyp_print(ctx->out, "\";\n");
}
LY_ARRAY_FOR(list->uniques, u) {
ypr_open(ctx->out, &flag);
- ly_print(ctx->out, "%*sunique \"", INDENT);
+ lyp_print(ctx->out, "%*sunique \"", INDENT);
LY_ARRAY_FOR(list->uniques[u], v) {
- ly_print(ctx->out, "%s%s", v > 0 ? ", " : "", list->uniques[u][v]->name);
+ lyp_print(ctx->out, "%s%s", v > 0 ? ", " : "", list->uniques[u][v]->name);
}
ypr_close(ctx, 0);
}
@@ -1786,19 +1795,21 @@
ypr_description(ctx, node->dsc, node->exts, NULL);
ypr_reference(ctx, node->ref, node->exts, NULL);
- LY_LIST_FOR(list->child, child) {
- ypr_open(ctx->out, &flag);
- yprc_node(ctx, child);
- }
+ if (!(ctx->options & LYS_OUTPUT_NO_SUBSTMT)) {
+ LY_LIST_FOR(list->child, child) {
+ ypr_open(ctx->out, &flag);
+ yprc_node(ctx, child);
+ }
- LY_ARRAY_FOR(list->actions, u) {
- ypr_open(ctx->out, &flag);
- yprc_action(ctx, &list->actions[u]);
- }
+ LY_ARRAY_FOR(list->actions, u) {
+ ypr_open(ctx->out, &flag);
+ yprc_action(ctx, &list->actions[u]);
+ }
- LY_ARRAY_FOR(list->notifs, u) {
- ypr_open(ctx->out, &flag);
- yprc_notification(ctx, &list->notifs[u]);
+ LY_ARRAY_FOR(list->notifs, u) {
+ ypr_open(ctx->out, &flag);
+ yprc_notification(ctx, &list->notifs[u]);
+ }
}
LEVEL--;
@@ -1811,7 +1822,7 @@
LY_ARRAY_SIZE_TYPE u;
int flag = 0;
- ly_print(ctx->out, "%*srefine \"%s\"", INDENT, refine->nodeid);
+ lyp_print(ctx->out, "%*srefine \"%s\"", INDENT, refine->nodeid);
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, refine->exts, &flag, 0);
@@ -1861,7 +1872,7 @@
LY_ARRAY_SIZE_TYPE u;
struct lysp_node *child;
- ly_print(ctx->out, "%*saugment \"%s\" {\n", INDENT, aug->nodeid);
+ lyp_print(ctx->out, "%*saugment \"%s\" {\n", INDENT, aug->nodeid);
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, aug->exts, NULL, 0);
@@ -2027,7 +2038,7 @@
struct lysp_deviate_del *del;
struct lysp_deviate *elem;
- ly_print(ctx->out, "%*sdeviation \"%s\" {\n", INDENT, deviation->nodeid);
+ lyp_print(ctx->out, "%*sdeviation \"%s\" {\n", INDENT, deviation->nodeid);
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, deviation->exts, NULL, 0);
@@ -2035,20 +2046,20 @@
ypr_reference(ctx, deviation->ref, deviation->exts, NULL);
LY_LIST_FOR(deviation->deviates, elem) {
- ly_print(ctx->out, "%*sdeviate ", INDENT);
+ lyp_print(ctx->out, "%*sdeviate ", INDENT);
if (elem->mod == LYS_DEV_NOT_SUPPORTED) {
if (elem->exts) {
- ly_print(ctx->out, "not-supported {\n");
+ lyp_print(ctx->out, "not-supported {\n");
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, elem->exts, NULL, 0);
} else {
- ly_print(ctx->out, "not-supported;\n");
+ lyp_print(ctx->out, "not-supported;\n");
continue;
}
} else if (elem->mod == LYS_DEV_ADD) {
add = (struct lysp_deviate_add*)elem;
- ly_print(ctx->out, "add {\n");
+ lyp_print(ctx->out, "add {\n");
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, add->exts, NULL, 0);
@@ -2076,7 +2087,7 @@
}
} else if (elem->mod == LYS_DEV_REPLACE) {
rpl = (struct lysp_deviate_rpl*)elem;
- ly_print(ctx->out, "replace {\n");
+ lyp_print(ctx->out, "replace {\n");
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, rpl->exts, NULL, 0);
@@ -2099,7 +2110,7 @@
}
} else if (elem->mod == LYS_DEV_DELETE) {
del = (struct lysp_deviate_del*)elem;
- ly_print(ctx->out, "delete {\n");
+ lyp_print(ctx->out, "delete {\n");
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, del->exts, NULL, 0);
@@ -2144,7 +2155,7 @@
/* meta-stmts */
if (module->org || module->contact || module->dsc || module->ref) {
- ly_print(ctx->out, "\n");
+ lyp_print(ctx->out, "\n");
}
ypr_substmt(ctx, LYEXT_SUBSTMT_ORGANIZATION, 0, module->org, NULL);
ypr_substmt(ctx, LYEXT_SUBSTMT_CONTACT, 0, module->contact, NULL);
@@ -2153,29 +2164,29 @@
/* revision-stmts */
if (module->revision) {
- ly_print(ctx->out, "\n%*srevision %s;\n", INDENT, module->revision);
+ lyp_print(ctx->out, "\n%*srevision %s;\n", INDENT, module->revision);
}
LEVEL--;
- ly_print(ctx->out, "%*s}\n", INDENT);
+ lyp_print(ctx->out, "%*s}\n", INDENT);
ly_print_flush(ctx->out);
return LY_SUCCESS;
}
LY_ERR
-yang_print_parsed(struct lyout *out, const struct lys_module *module)
+yang_print_parsed(struct lyp_out *out, const struct lys_module *module)
{
LY_ARRAY_SIZE_TYPE u;
struct lysp_node *data;
struct lysp_module *modp = module->parsed;
struct ypr_ctx ctx_ = {.out = out, .level = 0, .module = module, .schema = YPR_PARSED}, *ctx = &ctx_;
- ly_print(ctx->out, "%*smodule %s {\n", INDENT, module->name);
+ lyp_print(ctx->out, "%*smodule %s {\n", INDENT, module->name);
LEVEL++;
if (!modp) {
- ly_print(ctx->out, "%*s/* PARSED INFORMATION ARE NOT FULLY PRESENT */\n", INDENT);
+ lyp_print(ctx->out, "%*s/* PARSED INFORMATION ARE NOT FULLY PRESENT */\n", INDENT);
return ypr_missing_format(ctx, module);
}
@@ -2190,7 +2201,7 @@
/* linkage-stmts */
LY_ARRAY_FOR(modp->imports, u) {
- ly_print(out, "%s%*simport %s {\n", u ? "" : "\n", INDENT, modp->imports[u].module->name);
+ lyp_print(out, "%s%*simport %s {\n", u ? "" : "\n", INDENT, modp->imports[u].module->name);
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, modp->imports[u].exts, NULL, 0);
ypr_substmt(ctx, LYEXT_SUBSTMT_PREFIX, 0, modp->imports[u].prefix, modp->imports[u].exts);
@@ -2200,11 +2211,11 @@
ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, modp->imports[u].dsc, modp->imports[u].exts);
ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, modp->imports[u].ref, modp->imports[u].exts);
LEVEL--;
- ly_print(out, "%*s}\n", INDENT);
+ lyp_print(out, "%*s}\n", INDENT);
}
LY_ARRAY_FOR(modp->includes, u) {
if (modp->includes[u].rev[0] || modp->includes[u].dsc || modp->includes[u].ref || modp->includes[u].exts) {
- ly_print(out, "%s%*sinclude %s {\n", u ? "" : "\n", INDENT, modp->includes[u].submodule->name);
+ lyp_print(out, "%s%*sinclude %s {\n", u ? "" : "\n", INDENT, modp->includes[u].submodule->name);
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, modp->includes[u].exts, NULL, 0);
if (modp->includes[u].rev[0]) {
@@ -2213,15 +2224,15 @@
ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, modp->includes[u].dsc, modp->includes[u].exts);
ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, modp->includes[u].ref, modp->includes[u].exts);
LEVEL--;
- ly_print(out, "%*s}\n", INDENT);
+ lyp_print(out, "%*s}\n", INDENT);
} else {
- ly_print(out, "\n%*sinclude \"%s\";\n", INDENT, modp->includes[u].submodule->name);
+ lyp_print(out, "\n%*sinclude \"%s\";\n", INDENT, modp->includes[u].submodule->name);
}
}
/* meta-stmts */
if (module->org || module->contact || module->dsc || module->ref) {
- ly_print(out, "\n");
+ lyp_print(out, "\n");
}
ypr_substmt(ctx, LYEXT_SUBSTMT_ORGANIZATION, 0, module->org, modp->exts);
ypr_substmt(ctx, LYEXT_SUBSTMT_CONTACT, 0, module->contact, modp->exts);
@@ -2230,18 +2241,18 @@
/* revision-stmts */
if (modp->revs) {
- ly_print(out, "\n");
+ lyp_print(out, "\n");
}
LY_ARRAY_FOR(modp->revs, u) {
yprp_revision(ctx, &modp->revs[u]);
}
/* body-stmts */
LY_ARRAY_FOR(modp->extensions, u) {
- ly_print(out, "\n");
+ lyp_print(out, "\n");
yprp_extension(ctx, &modp->extensions[u]);
}
if (modp->exts) {
- ly_print(out, "\n");
+ lyp_print(out, "\n");
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, module->parsed->exts, NULL, 0);
}
@@ -2282,25 +2293,36 @@
}
LEVEL--;
- ly_print(out, "%*s}\n", INDENT);
+ lyp_print(out, "%*s}\n", INDENT);
ly_print_flush(out);
return LY_SUCCESS;
}
LY_ERR
-yang_print_compiled(struct lyout *out, const struct lys_module *module)
+yang_print_compiled_node(struct lyp_out *out, const struct lysc_node *node, int options)
+{
+ struct ypr_ctx ctx_ = {.out = out, .level = 0, .module = node->module, .options = options}, *ctx = &ctx_;
+
+ yprc_node(ctx, node);
+
+ ly_print_flush(out);
+ return LY_SUCCESS;
+}
+
+LY_ERR
+yang_print_compiled(struct lyp_out *out, const struct lys_module *module, int options)
{
LY_ARRAY_SIZE_TYPE u;
struct lysc_node *data;
struct lysc_module *modc = module->compiled;
- struct ypr_ctx ctx_ = {.out = out, .level = 0, .module = module}, *ctx = &ctx_;
+ struct ypr_ctx ctx_ = {.out = out, .level = 0, .module = module, .options = options}, *ctx = &ctx_;
- ly_print(ctx->out, "%*smodule %s {\n", INDENT, module->name);
+ lyp_print(ctx->out, "%*smodule %s {\n", INDENT, module->name);
LEVEL++;
if (!modc) {
- ly_print(ctx->out, "%*s/* COMPILED INFORMATION ARE NOT PRESENT */\n", INDENT);
+ lyp_print(ctx->out, "%*s/* COMPILED INFORMATION ARE NOT PRESENT */\n", INDENT);
return ypr_missing_format(ctx, module);
}
@@ -2315,7 +2337,7 @@
/* linkage-stmts */
LY_ARRAY_FOR(modc->imports, u) {
- ly_print(out, "\n%*simport %s {\n", INDENT, modc->imports[u].module->name);
+ lyp_print(out, "\n%*simport %s {\n", INDENT, modc->imports[u].module->name);
LEVEL++;
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, modc->imports[u].exts, NULL, 0);
ypr_substmt(ctx, LYEXT_SUBSTMT_PREFIX, 0, modc->imports[u].prefix, modc->imports[u].exts);
@@ -2323,12 +2345,12 @@
ypr_substmt(ctx, LYEXT_SUBSTMT_REVISIONDATE, 0, modc->imports[u].module->revision, modc->imports[u].exts);
}
LEVEL--;
- ly_print(out, "%*s}\n", INDENT);
+ lyp_print(out, "%*s}\n", INDENT);
}
/* meta-stmts */
if (module->org || module->contact || module->dsc || module->ref) {
- ly_print(out, "\n");
+ lyp_print(out, "\n");
}
ypr_substmt(ctx, LYEXT_SUBSTMT_ORGANIZATION, 0, module->org, modc->exts);
ypr_substmt(ctx, LYEXT_SUBSTMT_CONTACT, 0, module->contact, modc->exts);
@@ -2337,12 +2359,12 @@
/* revision-stmts */
if (module->revision) {
- ly_print(ctx->out, "\n%*srevision %s;\n", INDENT, module->revision);
+ lyp_print(ctx->out, "\n%*srevision %s;\n", INDENT, module->revision);
}
/* body-stmts */
if (modc->exts) {
- ly_print(out, "\n");
+ lyp_print(out, "\n");
yprc_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, module->compiled->exts, NULL, 0);
}
@@ -2354,20 +2376,22 @@
yprc_identity(ctx, &modc->identities[u]);
}
- LY_LIST_FOR(modc->data, data) {
- yprc_node(ctx, data);
- }
+ if (!(ctx->options & LYS_OUTPUT_NO_SUBSTMT)) {
+ LY_LIST_FOR(modc->data, data) {
+ yprc_node(ctx, data);
+ }
- LY_ARRAY_FOR(modc->rpcs, u) {
- yprc_action(ctx, &modc->rpcs[u]);
- }
+ LY_ARRAY_FOR(modc->rpcs, u) {
+ yprc_action(ctx, &modc->rpcs[u]);
+ }
- LY_ARRAY_FOR(modc->notifs, u) {
- yprc_notification(ctx, &modc->notifs[u]);
+ LY_ARRAY_FOR(modc->notifs, u) {
+ yprc_notification(ctx, &modc->notifs[u]);
+ }
}
LEVEL--;
- ly_print(out, "%*s}\n", INDENT);
+ lyp_print(out, "%*s}\n", INDENT);
ly_print_flush(out);
return LY_SUCCESS;
diff --git a/src/printer_yin.c b/src/printer_yin.c
index 95dddd3..c27404a 100644
--- a/src/printer_yin.c
+++ b/src/printer_yin.c
@@ -34,7 +34,7 @@
* @brief YIN printer context.
*/
struct ypr_ctx {
- struct lyout *out; /**< output specification */
+ struct lyp_out *out; /**< output specification */
unsigned int level; /**< current indentation level: 0 - no formatting, >= 1 indentation levels */
const struct lys_module *module; /**< schema to print */
};
@@ -48,14 +48,14 @@
static void
ypr_open(struct ypr_ctx *ctx, const char *elem_name, const char *attr_name, const char *attr_value, int flag)
{
- ly_print(ctx->out, "%*s<%s", INDENT, elem_name);
+ lyp_print(ctx->out, "%*s<%s", INDENT, elem_name);
if (attr_name) {
- ly_print(ctx->out, " %s=\"", attr_name);
+ lyp_print(ctx->out, " %s=\"", attr_name);
lyxml_dump_text(ctx->out, attr_value, 1);
- ly_print(ctx->out, "\"%s", flag == -1 ? "/>\n" : flag == 1 ? ">\n" : "");
+ lyp_print(ctx->out, "\"%s", flag == -1 ? "/>\n" : flag == 1 ? ">\n" : "");
} else if (flag) {
- ly_print(ctx->out, flag == -1 ? "/>\n" : ">\n");
+ lyp_print(ctx->out, flag == -1 ? "/>\n" : ">\n");
}
}
@@ -63,9 +63,9 @@
ypr_close(struct ypr_ctx *ctx, const char *elem_name, int flag)
{
if (flag) {
- ly_print(ctx->out, "%*s</%s>\n", INDENT, elem_name);
+ lyp_print(ctx->out, "%*s</%s>\n", INDENT, elem_name);
} else {
- ly_print(ctx->out, "/>\n");
+ lyp_print(ctx->out, "/>\n");
}
}
@@ -79,16 +79,16 @@
{
if (par_close_flag && !(*par_close_flag)) {
(*par_close_flag) = 1;
- ly_print(ctx->out, ">\n");
+ lyp_print(ctx->out, ">\n");
}
}
static void
ypr_yin_arg(struct ypr_ctx *ctx, const char *arg, const char *text)
{
- ly_print(ctx->out, "%*s<%s>", INDENT, arg);
+ lyp_print(ctx->out, "%*s<%s>", INDENT, arg);
lyxml_dump_text(ctx->out, text, 0);
- ly_print(ctx->out, "</%s>\n", arg);
+ lyp_print(ctx->out, "</%s>\n", arg);
}
@@ -236,7 +236,7 @@
ypr_close_parent(ctx, flag);
extflag = 0;
- ly_print(ctx->out, "%*s<if-feature name=\"%s", INDENT, iff[u]);
+ lyp_print(ctx->out, "%*s<if-feature name=\"%s", INDENT, iff[u]);
/* extensions */
LEVEL++;
@@ -247,7 +247,7 @@
yprp_extension_instances(ctx, LYEXT_SUBSTMT_IFFEATURE, u, &exts[u], &extflag, 1);
}
LEVEL--;
- ly_print(ctx->out, "\"/>\n");
+ lyp_print(ctx->out, "\"/>\n");
}
}
@@ -345,9 +345,9 @@
return;
}
- ly_print(ctx->out, "%*s<%s %s=\"", INDENT, name, attr);
+ lyp_print(ctx->out, "%*s<%s %s=\"", INDENT, name, attr);
lyxml_dump_text(ctx->out, (restr->arg[0] != 0x15 && restr->arg[0] != 0x06) ? restr->arg : &restr->arg[1], 1);
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, restr->exts, &inner_flag, 0);
@@ -381,9 +381,9 @@
return;
}
- ly_print(ctx->out, "%*s<when condition=\"", INDENT);
+ lyp_print(ctx->out, "%*s<when condition=\"", INDENT);
lyxml_dump_text(ctx->out, when->cond, 1);
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, when->exts, &inner_flag, 0);
@@ -402,13 +402,13 @@
LY_ARRAY_FOR(items, u) {
if (type == LY_TYPE_BITS) {
- ly_print(ctx->out, "%*s<bit name=\"", INDENT);
+ lyp_print(ctx->out, "%*s<bit name=\"", INDENT);
lyxml_dump_text(ctx->out, items[u].name, 1);
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
} else { /* LY_TYPE_ENUM */
- ly_print(ctx->out, "%*s<enum name=\"", INDENT);
+ lyp_print(ctx->out, "%*s<enum name=\"", INDENT);
lyxml_dump_text(ctx->out, items[u].name, 1);
- ly_print(ctx->out, "\"");
+ lyp_print(ctx->out, "\"");
}
inner_flag = 0;
LEVEL++;
@@ -1099,20 +1099,20 @@
ypr_reference(ctx, deviation->ref, deviation->exts, NULL);
LY_LIST_FOR(deviation->deviates, elem) {
- ly_print(ctx->out, "%*s<deviate value=\"", INDENT);
+ lyp_print(ctx->out, "%*s<deviate value=\"", INDENT);
if (elem->mod == LYS_DEV_NOT_SUPPORTED) {
if (elem->exts) {
- ly_print(ctx->out, "not-supported\"/>\n");
+ lyp_print(ctx->out, "not-supported\"/>\n");
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, elem->exts, NULL, 0);
} else {
- ly_print(ctx->out, "not-supported\"/>\n");
+ lyp_print(ctx->out, "not-supported\"/>\n");
continue;
}
} else if (elem->mod == LYS_DEV_ADD) {
add = (struct lysp_deviate_add*)elem;
- ly_print(ctx->out, "add\">\n");
+ lyp_print(ctx->out, "add\">\n");
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, add->exts, NULL, 0);
@@ -1140,7 +1140,7 @@
}
} else if (elem->mod == LYS_DEV_REPLACE) {
rpl = (struct lysp_deviate_rpl*)elem;
- ly_print(ctx->out, "replace\">\n");
+ lyp_print(ctx->out, "replace\">\n");
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, rpl->exts, NULL, 0);
@@ -1163,7 +1163,7 @@
}
} else if (elem->mod == LYS_DEV_DELETE) {
del = (struct lysp_deviate_del*)elem;
- ly_print(ctx->out, "delete\">\n");
+ lyp_print(ctx->out, "delete\">\n");
LEVEL++;
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, del->exts, NULL, 0);
@@ -1206,7 +1206,7 @@
/* meta-stmts */
if (module->org || module->contact || module->dsc || module->ref) {
- ly_print(ctx->out, "\n");
+ lyp_print(ctx->out, "\n");
}
ypr_substmt(ctx, LYEXT_SUBSTMT_ORGANIZATION, 0, module->org, NULL);
ypr_substmt(ctx, LYEXT_SUBSTMT_CONTACT, 0, module->contact, NULL);
@@ -1230,13 +1230,13 @@
{
LY_ARRAY_SIZE_TYPE u;
- ly_print(ctx->out, "%*sxmlns=\"%s\"", indent + INDENT, YIN_NS_URI);
- ly_print(ctx->out, "\n%*sxmlns:%s=\"%s\"", indent + INDENT, module->prefix, module->ns);
+ lyp_print(ctx->out, "%*sxmlns=\"%s\"", indent + INDENT, YIN_NS_URI);
+ lyp_print(ctx->out, "\n%*sxmlns:%s=\"%s\"", indent + INDENT, module->prefix, module->ns);
struct lysp_module *modp = module->parsed;
LY_ARRAY_FOR(modp->imports, u){
- ly_print(ctx->out, "\n%*sxmlns:%s=\"%s\"", indent + INDENT, modp->imports[u].prefix, modp->imports[u].module->ns);
+ lyp_print(ctx->out, "\n%*sxmlns:%s=\"%s\"", indent + INDENT, modp->imports[u].prefix, modp->imports[u].module->ns);
}
}
@@ -1375,7 +1375,7 @@
}
if (!ext->compiled && ext->yin) {
- ly_print(ctx->out, "%*s<%s/> <!-- Model comes from different input format, extensions must be resolved first. -->\n", INDENT, ext[u].name);
+ lyp_print(ctx->out, "%*s<%s/> <!-- Model comes from different input format, extensions must be resolved first. -->\n", INDENT, ext[u].name);
continue;
}
@@ -1419,22 +1419,22 @@
}
LY_ERR
-yin_print_parsed(struct lyout *out, const struct lys_module *module)
+yin_print_parsed(struct lyp_out *out, const struct lys_module *module)
{
unsigned int u;
struct lysp_node *data;
struct lysp_module *modp = module->parsed;
struct ypr_ctx ctx_ = {.out = out, .level = 0, .module = module}, *ctx = &ctx_;
- ly_print(ctx->out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
- ly_print(ctx->out, "%*s<module name=\"%s\"\n", INDENT, module->name);
+ lyp_print(ctx->out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ lyp_print(ctx->out, "%*s<module name=\"%s\"\n", INDENT, module->name);
ypr_xmlns(ctx, module, 8);
- ly_print(ctx->out, ">\n");
+ lyp_print(ctx->out, ">\n");
LEVEL++;
if (!modp) {
- ly_print(ctx->out, "%*s<!-- PARSED INFORMATION ARE NOT FULLY PRESENT -->\n", INDENT);
+ lyp_print(ctx->out, "%*s<!-- PARSED INFORMATION ARE NOT FULLY PRESENT -->\n", INDENT);
return ypr_missing_format(ctx, module);
}
@@ -1472,7 +1472,7 @@
ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, modp->includes[u].dsc, modp->includes[u].exts);
ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, modp->includes[u].ref, modp->includes[u].exts);
LEVEL--;
- ly_print(out, "%*s}\n", INDENT);
+ lyp_print(out, "%*s}\n", INDENT);
} else {
ypr_open(ctx, "include", "module", modp->includes[u].submodule->name, -1);
}
@@ -1480,7 +1480,7 @@
/* meta-stmts */
if (module->org || module->contact || module->dsc || module->ref) {
- ly_print(out, "\n");
+ lyp_print(out, "\n");
}
ypr_substmt(ctx, LYEXT_SUBSTMT_ORGANIZATION, 0, module->org, modp->exts);
ypr_substmt(ctx, LYEXT_SUBSTMT_CONTACT, 0, module->contact, modp->exts);
@@ -1489,18 +1489,18 @@
/* revision-stmts */
if (modp->revs) {
- ly_print(out, "\n");
+ lyp_print(out, "\n");
}
LY_ARRAY_FOR(modp->revs, u) {
yprp_revision(ctx, &modp->revs[u]);
}
/* body-stmts */
LY_ARRAY_FOR(modp->extensions, u) {
- ly_print(out, "\n");
+ lyp_print(out, "\n");
yprp_extension(ctx, &modp->extensions[u]);
}
if (modp->exts) {
- ly_print(out, "\n");
+ lyp_print(out, "\n");
yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, module->parsed->exts, NULL, 0);
}
@@ -1541,7 +1541,7 @@
}
LEVEL--;
- ly_print(out, "%*s</module>\n", INDENT);
+ lyp_print(out, "%*s</module>\n", INDENT);
ly_print_flush(out);
return LY_SUCCESS;
diff --git a/src/tree.h b/src/tree.h
index d1313b7..e63cfc1 100644
--- a/src/tree.h
+++ b/src/tree.h
@@ -24,6 +24,14 @@
#endif
/**
+ * @defgroup trees Trees
+ *
+ * Generic macros, functions, etc. to work with both [schema](@ref schematree) and [data](@ref datatree) trees.
+ *
+ * @{
+ */
+
+/**
* @brief Type (i.e. size) of the [sized array](@ref sizedarrays)'s size counter.
*
* To print the value via a print format, use LY_PRI_ARRAY_SIZE_TYPE specifier.
@@ -70,13 +78,6 @@
++INDEX)
/**
- * @defgroup schematree Schema Tree
- * @{
- *
- * Data structures and functions to manipulate and access schema tree.
- */
-
-/**
* @brief Get a number of records in the ARRAY.
*
* Does not check if array exists!
@@ -165,7 +166,7 @@
*/
extern const char* ly_data_type2str[LY_DATA_TYPE_COUNT];
-/** @} */
+/** @} trees */
#ifdef __cplusplus
}
diff --git a/src/tree_data.h b/src/tree_data.h
index b3a2ab4..5d7d480 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -31,6 +31,7 @@
/**
* @defgroup datatree Data Tree
+ * @ingroup trees
* @{
*
* Data structures and functions to manipulate and access instance data tree.
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 9a2ee1f..f5a70b7 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -186,6 +186,73 @@
}
API const struct lysc_node *
+lys_find_node(struct ly_ctx *ctx, const struct lysc_node *context_node, const char *qpath)
+{
+ const char *id = qpath;
+ const char *prefix, *name;
+ size_t prefix_len, name_len;
+ unsigned int u;
+ const struct lysc_node *node = context_node;
+ struct lys_module *mod = NULL;
+
+ LY_CHECK_ARG_RET(ctx, qpath, NULL);
+
+ while(*id) {
+ if (id[0] == '/') {
+ ++id;
+ }
+ /* precess ".." in relative paths */
+ while (!strncmp("../", id, 3)) {
+ id += 3;
+ if (!node) {
+ LOGERR(ctx, LY_EINVAL, "Invalid qpath \"%s\" - too many \"..\" in the path.", qpath);
+ return NULL;
+ }
+ node = node->parent;
+ }
+
+ if (ly_parse_nodeid(&id, &prefix, &prefix_len, &name, &name_len) != LY_SUCCESS) {
+ LOGERR(ctx, LY_EINVAL, "Invalid qpath \"%s\" - invalid nodeid \"%.*s\".", qpath, id- qpath, qpath);
+ return NULL;
+ }
+ if (prefix) {
+ if (context_node) {
+ mod = lys_module_find_prefix(context_node->module, prefix, prefix_len);
+ } else {
+ for (u = 0; u < ctx->list.count; ++u) {
+ if (!ly_strncmp(((struct lys_module *)ctx->list.objs[u])->name, prefix, prefix_len)) {
+ struct lys_module *m = (struct lys_module *)ctx->list.objs[u];
+ if (mod) {
+ if (m->implemented) {
+ mod = m;
+ break;
+ } else if (m->latest_revision) {
+ mod = m;
+ }
+ } else {
+ mod = m;
+ }
+ }
+ }
+ }
+ }
+ if (!mod) {
+ LOGERR(ctx, LY_EINVAL, "Invalid qpath - unable to find module connected with the prefix of the node \"%.*s\".",
+ id - qpath, qpath);
+ return NULL;
+ }
+
+ node = lys_find_child(node, mod, name, name_len, 0, LYS_GETNEXT_NOSTATECHECK);
+ if (!node) {
+ LOGERR(ctx, LY_EINVAL, "Invalid qpath - unable to find \"%.*s\".", id - qpath, qpath);
+ return NULL;
+ }
+ }
+
+ return node;
+}
+
+API const struct lysc_node *
lys_find_child(const struct lysc_node *parent, const struct lys_module *module, const char *name, size_t name_len,
uint16_t nodetype, int options)
{
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 94786b1..b3139dc 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -32,6 +32,14 @@
#endif
/**
+ * @defgroup schematree Schema Tree
+ * @ingroup trees
+ * @{
+ *
+ * Data structures and functions to manipulate and access schema tree.
+ */
+
+/**
* @brief Macro to iterate via all elements in a schema tree which can be instantiated in data tree
* (skips cases, input, output). This is the opening part to the #LYSC_TREE_DFS_END - they always have to be used together.
*
@@ -134,8 +142,6 @@
LYS_OUT_YIN = 3, /**< YIN schema output format */
LYS_OUT_TREE, /**< Tree schema output format, for more information see the [printers](@ref howtoschemasprinters) page */
- LYS_OUT_INFO, /**< Info schema output format, for more information see the [printers](@ref howtoschemasprinters) page */
- LYS_OUT_JSON, /**< JSON schema output format, reflecting YIN format with conversion of attributes to object's members */
} LYS_OUTFORMAT;
#define LY_REV_SIZE 11 /**< revision data string length (including terminating NULL byte) */
@@ -579,7 +585,7 @@
#define LYS_DEV_ADD 2 /**< deviate type add */
#define LYS_DEV_DELETE 3 /**< deviate type delete */
#define LYS_DEV_REPLACE 4 /**< deviate type replace */
-/** @} */
+/** @} deviatetypes */
/**
* @brief Generic deviate structure to get type and cast to lysp_deviate_* structure
@@ -742,7 +748,6 @@
/**
* @defgroup snodeflags Schema nodes flags
- * @ingroup schematree
* @{
*/
#define LYS_CONFIG_W 0x01 /**< config true; also set for input children nodes */
@@ -807,7 +812,7 @@
#define LYS_ISENUM 0x200 /**< flag to simply distinguish type in struct lysc_type_bitenum_item */
#define LYS_FLAGS_COMPILED_MASK 0xff /**< mask for flags that maps to the compiled structures */
-/** @} */
+/** @} snodeflags */
/**
* @brief Generic YANG data node
@@ -1208,9 +1213,7 @@
#define LYS_IFF_AND 0x01 /**< operand "and" */
#define LYS_IFF_OR 0x02 /**< operand "or" */
#define LYS_IFF_F 0x03 /**< feature */
-/**
- * @}
- */
+/** @} ifftokens */
/**
* @brief Compiled YANG revision statement
@@ -1908,8 +1911,6 @@
/**
* @defgroup sgetnextflags lys_getnext() flags
- * @ingroup schematree
- *
* @{
*/
#define LYS_GETNEXT_WITHCHOICE 0x01 /**< lys_getnext() option to allow returning #LYS_CHOICE nodes instead of looking into them */
@@ -1938,6 +1939,25 @@
const char *name, size_t name_len, uint16_t nodetype, int options);
/**
+ * @brief Get schema node specified by the schema path.
+ *
+ * In case the @p qpath uses prefixes (from imports or of the schema itself), the @p context_node must be specified
+ * even if the path is absolute. In case the @p context_node is not provided, the names of the schemas are expected as the
+ * node's prefixes in the @qpath. It also means that the relative paths are accepted only with the schema prefixes,
+ * not the full names.
+ *
+ * @param[in] ctx libyang context for logging and getting the correct schema if @p contet_node not provided.
+ * @param[in] context_node Context node for relative paths and/or as a source of the context module to resolve node's
+ * prefixes in @qpath.
+ * @param[in] qpath Schema path to be resolved. Not prefixed nodes inherits the prefix from its parent nodes. It means
+ * that the first node in the path must be prefixed. Both, import prefixes as well as full schema names are accepted as
+ * prefixes according to the @p context_node parameter presence.
+ * @return NULL in case of invalid path.
+ * @return found schema node.
+ */
+const struct lysc_node *lys_find_node(struct ly_ctx *ctx, const struct lysc_node *context_node, const char *qpath);
+
+/**
* @brief Make the specific module implemented.
*
* @param[in] mod Module to make implemented. It is not an error
@@ -1985,7 +2005,7 @@
*/
const char *lys_nodetype2str(uint16_t nodetype);
-/** @} */
+/** @} schematree */
#ifdef __cplusplus
}
diff --git a/src/xml.c b/src/xml.c
index f376672..b682960 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -1025,7 +1025,7 @@
}
LY_ERR
-lyxml_dump_text(struct lyout *out, const char *text, int attribute)
+lyxml_dump_text(struct lyp_out *out, const char *text, int attribute)
{
LY_ERR ret = LY_SUCCESS;
unsigned int u;
@@ -1037,23 +1037,23 @@
for (u = 0; text[u]; u++) {
switch (text[u]) {
case '&':
- ret = ly_print(out, "&");
+ ret = lyp_print(out, "&");
break;
case '<':
- ret = ly_print(out, "<");
+ ret = lyp_print(out, "<");
break;
case '>':
/* not needed, just for readability */
- ret = ly_print(out, ">");
+ ret = lyp_print(out, ">");
break;
case '"':
if (attribute) {
- ret = ly_print(out, """);
+ ret = lyp_print(out, """);
break;
}
/* falls through */
default:
- ly_write(out, &text[u], 1);
+ lyp_write(out, &text[u], 1);
}
}
diff --git a/src/xml.h b/src/xml.h
index 2bbf5da..c4ade27 100644
--- a/src/xml.h
+++ b/src/xml.h
@@ -22,7 +22,7 @@
#include "set.h"
#include "tree_schema.h"
-struct lyout;
+struct lyp_out;
struct ly_prefix;
/* Macro to test if character is whitespace */
@@ -128,7 +128,7 @@
* @param[in] attribute Flag for attribute's value where a double quotes must be replaced.
* @return LY_ERR values.
*/
-LY_ERR lyxml_dump_text(struct lyout *out, const char *text, int attribute);
+LY_ERR lyxml_dump_text(struct lyp_out *out, const char *text, int attribute);
/**
* @brief Remove the allocated working memory of the context.
diff --git a/src/xpath.c b/src/xpath.c
index 6f7937f..9f9dde4 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -400,6 +400,8 @@
buf = strdup("");
LY_CHECK_ERR_RET(!buf, LOGMEM(LYD_NODE_CTX(node)), LY_EMEM);
} else {
+ struct lyp_out *out;
+
switch (any->value_type) {
case LYD_ANYDATA_STRING:
case LYD_ANYDATA_XML:
@@ -408,8 +410,10 @@
LY_CHECK_ERR_RET(!buf, LOGMEM(LYD_NODE_CTX(node)), LY_EMEM);
break;
case LYD_ANYDATA_DATATREE:
- rc = lyd_print_mem(&buf, any->value.tree, LYD_XML, LYDP_WITHSIBLINGS);
- LY_CHECK_RET(rc);
+ out = lyp_new_memory(&buf, 0);
+ rc = lyd_print(out, any->value.tree, LYD_XML, LYDP_WITHSIBLINGS);
+ lyp_free(out, NULL, 0);
+ LY_CHECK_RET(rc < 0, -rc);
break;
/* TODO case LYD_ANYDATA_LYB:
LOGERR(LYD_NODE_CTX(node), LY_EINVAL, "Cannot convert LYB anydata into string.");
diff --git a/tests/utests/data/test_parser_xml.c b/tests/utests/data/test_parser_xml.c
index e0357d7..a40fdf5 100644
--- a/tests/utests/data/test_parser_xml.c
+++ b/tests/utests/data/test_parser_xml.c
@@ -175,6 +175,9 @@
char *str;
struct lyd_node *tree;
+ struct lyp_out *out;
+ assert_non_null(out = lyp_new_memory(&str, 0));
+
data =
"<any xmlns=\"urn:tests:a\">"
"<element1>"
@@ -187,7 +190,7 @@
assert_int_equal(LYS_ANYDATA, tree->schema->nodetype);
assert_string_equal("any", tree->schema->name);
- lyd_print_mem(&str, tree, LYD_XML, 0);
+ lyd_print(out, tree, LYD_XML, 0);
assert_string_equal(str,
"<any xmlns=\"urn:tests:a\">"
"<element1>"
@@ -196,9 +199,11 @@
"<element1a/>"
"</any>"
);
- free(str);
+ lyp_out_reset(out);
lyd_free_all(tree);
+ lyp_free(out, NULL, 1);
+
*state = NULL;
}
@@ -319,6 +324,9 @@
char *str;
struct lyd_node *tree;
+ struct lyp_out *out;
+ assert_non_null(out = lyp_new_memory(&str, 0));
+
/* invalid value, no flags */
data = "<foo3 xmlns=\"urn:tests:a\"/>";
assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
@@ -332,9 +340,9 @@
assert_string_equal(((struct lyd_node_opaq *)tree)->name, "foo3");
assert_string_equal(((struct lyd_node_opaq *)tree)->value, "");
- lyd_print_mem(&str, tree, LYD_XML, 0);
+ lyd_print(out, tree, LYD_XML, 0);
assert_string_equal(str, "<foo3 xmlns=\"urn:tests:a\"/>");
- free(str);
+ lyp_out_reset(out);
lyd_free_all(tree);
/* missing key, no flags */
@@ -350,9 +358,9 @@
assert_string_equal(((struct lyd_node_opaq *)tree)->name, "l1");
assert_string_equal(((struct lyd_node_opaq *)tree)->value, "");
- lyd_print_mem(&str, tree, LYD_XML, 0);
+ lyd_print(out, tree, LYD_XML, 0);
assert_string_equal(str, data);
- free(str);
+ lyp_out_reset(out);
lyd_free_all(tree);
/* invalid key, no flags */
@@ -368,9 +376,9 @@
assert_string_equal(((struct lyd_node_opaq *)tree)->name, "l1");
assert_string_equal(((struct lyd_node_opaq *)tree)->value, "");
- lyd_print_mem(&str, tree, LYD_XML, 0);
+ lyd_print(out, tree, LYD_XML, 0);
assert_string_equal(str, data);
- free(str);
+ lyp_out_reset(out);
lyd_free_all(tree);
/* opaq flag and fail */
@@ -378,6 +386,8 @@
LYD_OPT_OPAQ | LYD_VALOPT_DATA_ONLY, &tree));
assert_null(tree);
+ lyp_free(out, NULL, 1);
+
*state = NULL;
}
@@ -391,6 +401,9 @@
struct lyd_node *tree, *op;
const struct lyd_node *node;
+ struct lyp_out *out;
+ assert_non_null(out = lyp_new_memory(&str, 0));
+
data =
"<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" msgid=\"25\" custom-attr=\"val\">"
"<edit-config>"
@@ -434,7 +447,7 @@
assert_null(node->schema);
assert_string_equal(((struct lyd_node_opaq *)node)->name, "z");
- lyd_print_mem(&str, tree, LYD_XML, 0);
+ lyd_print(out, tree, LYD_XML, 0);
assert_string_equal(str,
"<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" msgid=\"25\" custom-attr=\"val\">"
"<edit-config>"
@@ -453,12 +466,14 @@
"</config>"
"</edit-config>"
"</rpc>");
- free(str);
+ lyp_out_reset(out);
lyd_free_all(tree);
/* wrong namespace, element name, whatever... */
/* TODO */
+ lyp_free(out, NULL, 1);
+
*state = NULL;
}
@@ -472,6 +487,9 @@
struct lyd_node *tree, *op;
const struct lyd_node *node;
+ struct lyp_out *out;
+ assert_non_null(out = lyp_new_memory(&str, 0));
+
data =
"<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" msgid=\"25\" custom-attr=\"val\">"
"<action xmlns=\"urn:ietf:params:xml:ns:yang:1\">"
@@ -496,7 +514,7 @@
assert_string_equal(((struct lyd_node_opaq *)node)->name, "action");
assert_null(((struct lyd_node_opaq *)node)->attr);
- lyd_print_mem(&str, tree, LYD_XML, 0);
+ lyd_print(out, tree, LYD_XML, 0);
assert_string_equal(str,
"<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" msgid=\"25\" custom-attr=\"val\">"
"<action xmlns=\"urn:ietf:params:xml:ns:yang:1\">"
@@ -507,12 +525,14 @@
"</c>"
"</action>"
"</rpc>");
- free(str);
+ lyp_out_reset(out);
lyd_free_all(tree);
/* wrong namespace, element name, whatever... */
/* TODO */
+ lyp_free(out, NULL, 1);
+
*state = NULL;
}
@@ -526,6 +546,9 @@
struct lyd_node *tree, *ntf;
const struct lyd_node *node;
+ struct lyp_out *out;
+ assert_non_null(out = lyp_new_memory(&str, 0));
+
data =
"<notification xmlns=\"urn:ietf:params:xml:ns:netconf:notification:1.0\">"
"<eventTime>2037-07-08T00:01:00Z</eventTime>"
@@ -553,9 +576,9 @@
assert_non_null(node->schema);
assert_string_equal(node->schema->name, "c");
- lyd_print_mem(&str, tree, LYD_XML, 0);
+ lyd_print(out, tree, LYD_XML, 0);
assert_string_equal(str, data);
- free(str);
+ lyp_out_reset(out);
lyd_free_all(tree);
/* top-level notif without envelope */
@@ -568,14 +591,16 @@
assert_non_null(tree);
assert_ptr_equal(ntf, tree);
- lyd_print_mem(&str, tree, LYD_XML, 0);
+ lyd_print(out, tree, LYD_XML, 0);
assert_string_equal(str, data);
- free(str);
+ lyp_out_reset(out);
lyd_free_all(tree);
/* wrong namespace, element name, whatever... */
/* TODO */
+ lyp_free(out, NULL, 1);
+
*state = NULL;
}
@@ -589,6 +614,9 @@
struct lyd_node *request, *tree, *op;
const struct lyd_node *node;
+ struct lyp_out *out;
+ assert_non_null(out = lyp_new_memory(&str, 0));
+
data =
"<c xmlns=\"urn:tests:a\">"
"<act>"
@@ -619,15 +647,17 @@
assert_string_equal(node->schema->name, "c");
/* TODO print only rpc-reply node and then output subtree */
- lyd_print_mem(&str, lyd_node_children(op), LYD_XML, 0);
+ lyd_print(out, lyd_node_children(op), LYD_XML, 0);
assert_string_equal(str,
"<al xmlns=\"urn:tests:a\">25</al>");
- free(str);
+ lyp_out_reset(out);
lyd_free_all(tree);
/* wrong namespace, element name, whatever... */
/* TODO */
+ lyp_free(out, NULL, 1);
+
*state = NULL;
}
diff --git a/tests/utests/data/test_printer_xml.c b/tests/utests/data/test_printer_xml.c
index f6cca7b..084ac2c 100644
--- a/tests/utests/data/test_printer_xml.c
+++ b/tests/utests/data/test_printer_xml.c
@@ -176,18 +176,20 @@
const char *result;
char *printed;
ssize_t len;
+ struct lyp_out *out;
s->func = test_leaf;
+ assert_non_null(out = lyp_new_memory(&printed, 0));
data = "<int8 xmlns=\"urn:tests:types\">\n 15 \t\n </int8>";
result = "<int8 xmlns=\"urn:tests:types\">15</int8>";
assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, 0)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, 0)) >= 0);
assert_int_equal(len, strlen(printed));
assert_string_equal(printed, result);
- free(printed);
lyd_free_all(tree);
+ lyp_free(out, NULL, 1);
s->func = NULL;
}
@@ -199,25 +201,27 @@
const char *data;
char *printed;
ssize_t len;
+ struct lyp_out *out;
s->func = test_anydata;
+ assert_non_null(out = lyp_new_memory(&printed, 0));
data = "<any xmlns=\"urn:tests:types\"><somexml xmlns:x=\"url:x\" xmlns=\"example.com\"><x:x/></somexml></any>";
assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, 0)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, 0)) >= 0);
assert_int_equal(len, strlen(printed));
/* canonized */
data = "<any xmlns=\"urn:tests:types\"><somexml xmlns=\"example.com\"><x xmlns=\"url:x\"/></somexml></any>";
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
lyd_free_all(tree);
data = "<any xmlns=\"urn:tests:types\"/>";
assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, 0)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, 0)) >= 0);
assert_int_equal(len, strlen(printed));
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
lyd_free_all(tree);
data =
@@ -236,7 +240,7 @@
assert_string_equal(((struct lyd_node_any *)tree)->value.tree->schema->name, "cont");
/* but its children not */
assert_null(((struct lyd_node_inner *)(((struct lyd_node_any *)tree)->value.tree))->child->schema);
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, 0)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, 0)) >= 0);
assert_int_equal(len, strlen(printed));
/* canonized */
data =
@@ -249,9 +253,11 @@
"</cont>"
"</any>";
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
+
lyd_free_all(tree);
+ lyp_free(out, NULL, 1);
s->func = NULL;
}
@@ -263,39 +269,42 @@
const char *data;
char *printed;
ssize_t len;
+ struct lyp_out *out;
s->func = test_defaults;
+ assert_non_null(out = lyp_new_memory(&printed, 0));
+
/* standard default value */
data = "<c xmlns=\"urn:defaults\">aa</c>";
assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_TRIM)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_TRIM)) >= 0);
assert_int_equal(len, strlen(printed));
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL)) >= 0);
assert_int_equal(len, strlen(printed));
data = "<c xmlns=\"urn:defaults\">aa</c><a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a>";
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL_TAG)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL_TAG)) >= 0);
assert_int_equal(len, strlen(printed));
data = "<c xmlns=\"urn:defaults\">aa</c>"
"<a xmlns=\"urn:defaults\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\""
" ncwd:default=\"true\" xmlns:d=\"urn:defaults\">/d:b</a>";
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG)) >= 0);
assert_int_equal(len, strlen(printed));
data = "<c xmlns=\"urn:defaults\">aa</c>"
"<a xmlns=\"urn:defaults\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\""
" ncwd:default=\"true\" xmlns:d=\"urn:defaults\">/d:b</a>";
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
lyd_free_all(tree);
@@ -303,25 +312,25 @@
data = "<c xmlns=\"urn:defaults\">aa</c><a xmlns=\"urn:defaults\">/d:b</a>";
assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_TRIM)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_TRIM)) >= 0);
assert_int_equal(len, strlen(printed));
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL)) >= 0);
assert_int_equal(len, strlen(printed));
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL_TAG)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL_TAG)) >= 0);
assert_int_equal(len, strlen(printed));
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG)) >= 0);
assert_int_equal(len, strlen(printed));
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
lyd_free_all(tree);
@@ -329,34 +338,35 @@
data = "<c xmlns=\"urn:defaults\">aa</c><a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a><b xmlns=\"urn:defaults\">val</b>";
assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_VALOPT_DATA_ONLY));
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_TRIM)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_TRIM)) >= 0);
assert_int_equal(len, strlen(printed));
data = "<c xmlns=\"urn:defaults\">aa</c><b xmlns=\"urn:defaults\">val</b>";
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL)) >= 0);
assert_int_equal(len, strlen(printed));
data = "<c xmlns=\"urn:defaults\">aa</c><a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a><b xmlns=\"urn:defaults\">val</b>";
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL_TAG)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_ALL_TAG)) >= 0);
assert_int_equal(len, strlen(printed));
data = "<c xmlns=\"urn:defaults\">aa</c>"
"<a xmlns=\"urn:defaults\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\""
" ncwd:default=\"true\" xmlns:d=\"urn:defaults\">/d:b</a>"
"<b xmlns=\"urn:defaults\">val</b>";
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
- assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG)) >= 0);
+ assert_true((len = lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG)) >= 0);
assert_int_equal(len, strlen(printed));
data = "<c xmlns=\"urn:defaults\">aa</c><a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a><b xmlns=\"urn:defaults\">val</b>";
assert_string_equal(printed, data);
- free(printed);
+ lyp_out_reset(out);
lyd_free_all(tree);
+ lyp_free(out, NULL, 1);
s->func = NULL;
}
@@ -374,23 +384,25 @@
const char *reply, *result;
char *printed;
ssize_t len;
+ struct lyp_out *out;
s->func = test_rpc;
+ assert_non_null(out = lyp_new_memory(&printed, 0));
request = "<sum xmlns=\"urn:tests:types\"><x>10</x><y>20</y></sum>";
reply = "<result xmlns=\"urn:tests:types\">30</result>";
result = "<sum xmlns=\"urn:tests:types\"><result>30</result></sum>";
assert_non_null(tree1 = lyd_parse_mem(s->ctx, request, LYD_XML, LYD_OPT_RPC, NULL));
- assert_true((len = lyd_print_mem(&printed, tree1, LYD_XML, 0)) >= 0);
+ assert_true((len = lyd_print(out, tree1, LYD_XML, 0)) >= 0);
assert_int_equal(len, strlen(printed));
assert_string_equal(printed, request);
- free(printed);
+ lyp_out_reset(out);
assert_non_null(trees = lyd_trees_new(1, tree1));
assert_non_null(tree2 = lyd_parse_mem(s->ctx, reply, LYD_XML, LYD_OPT_RPCREPLY, trees));
- assert_true((len = lyd_print_mem(&printed, tree2, LYD_XML, 0)) >= 0);
+ assert_true((len = lyd_print(out, tree2, LYD_XML, 0)) >= 0);
assert_int_equal(len, strlen(printed));
assert_string_equal(printed, result);
- free(printed);
+ lyp_out_reset(out);
lyd_trees_free(trees, 0);
lyd_free_all(tree1);
lyd_free_all(tree2);
@@ -400,16 +412,16 @@
reply = "";
result = "<sum xmlns=\"urn:tests:types\"/>";
assert_non_null(tree1 = lyd_parse_mem(s->ctx, request, LYD_XML, LYD_OPT_RPC, NULL));
- assert_true((len = lyd_print_mem(&printed, tree1, LYD_XML, 0)) >= 0);
+ assert_true((len = lyd_print(out, tree1, LYD_XML, 0)) >= 0);
assert_int_equal(len, strlen(printed));
assert_string_equal(printed, request);
- free(printed);
+ lyp_out_reset(out);
assert_non_null(trees = lyd_trees_new(1, tree1));
assert_non_null(tree2 = lyd_parse_mem(s->ctx, reply, LYD_XML, LYD_OPT_RPCREPLY, trees));
- assert_true((len = lyd_print_mem(&printed, tree2, LYD_XML, 0)) >= 0);
+ assert_true((len = lyd_print(out, tree2, LYD_XML, 0)) >= 0);
assert_int_equal(len, strlen(printed));
assert_string_equal(printed, result);
- free(printed);
+ lyp_out_reset(out);
lyd_trees_free(trees, 0);
lyd_free_all(tree1);
lyd_free_all(tree2);
@@ -424,20 +436,21 @@
reply = "<b xmlns=\"urn:tests:types\">test-reply</b>";
result = "<cont xmlns=\"urn:tests:types\"><listtarget><id>10</id><test><b>test-reply</b></test></listtarget></cont>";;
assert_non_null(tree1 = lyd_parse_mem(s->ctx, request, LYD_XML, LYD_OPT_RPC, NULL));
- assert_true((len = lyd_print_mem(&printed, tree1, LYD_XML, 0)) >= 0);
+ assert_true((len = lyd_print(out, tree1, LYD_XML, 0)) >= 0);
assert_int_equal(len, strlen(printed));
assert_string_equal(printed, request);
- free(printed);
+ lyp_out_reset(out);
assert_non_null(trees = lyd_trees_new(1, tree1));
assert_non_null(tree2 = lyd_parse_mem(s->ctx, reply, LYD_XML, LYD_OPT_RPCREPLY, trees));
- assert_true((len = lyd_print_mem(&printed, tree2, LYD_XML, 0)) >= 0);
+ assert_true((len = lyd_print(out, tree2, LYD_XML, 0)) >= 0);
assert_int_equal(len, strlen(printed));
assert_string_equal(printed, result);
- free(printed);
+ lyp_out_reset(out);
lyd_trees_free(trees, 0);
lyd_free_all(tree1);
lyd_free_all(tree2);
+ lyp_free(out, NULL, 1);
s->func = NULL;
}
diff --git a/tests/utests/data/test_validation.c b/tests/utests/data/test_validation.c
index 52d59ec..16d742a 100644
--- a/tests/utests/data/test_validation.c
+++ b/tests/utests/data/test_validation.c
@@ -1019,13 +1019,16 @@
struct lyd_node *tree, *node;
const struct lys_module *mod = ly_ctx_get_module_latest(ctx, "f");
+ struct lyp_out *out;
+ assert_non_null(out = lyp_new_memory(&str, 0));
+
/* get defaults */
tree = NULL;
assert_int_equal(lyd_validate_modules(&tree, &mod, 1, 0), LY_SUCCESS);
assert_non_null(tree);
/* check all defaults exist */
- lyd_print_mem(&str, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
+ lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
assert_string_equal(str,
"<ll1 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>"
"<ll1 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def2</ll1>"
@@ -1041,7 +1044,7 @@
"<ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>"
"<ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>"
"</cont>");
- free(str);
+ lyp_out_reset(out);
/* create another explicit case and validate */
node = lyd_new_term(NULL, mod, "l", "value");
@@ -1050,7 +1053,7 @@
assert_int_equal(lyd_validate(&tree, ctx, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
/* check data tree */
- lyd_print_mem(&str, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
+ lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
assert_string_equal(str,
"<d xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>"
"<ll2 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>"
@@ -1064,7 +1067,7 @@
"<ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>"
"</cont>"
"<l xmlns=\"urn:tests:f\">value</l>");
- free(str);
+ lyp_out_reset(out);
/* create explicit leaf-list and leaf and validate */
node = lyd_new_term(NULL, mod, "d", "15");
@@ -1076,7 +1079,7 @@
assert_int_equal(lyd_validate(&tree, ctx, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
/* check data tree */
- lyd_print_mem(&str, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
+ lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
assert_string_equal(str,
"<cont xmlns=\"urn:tests:f\">"
"<ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>"
@@ -1089,7 +1092,7 @@
"<l xmlns=\"urn:tests:f\">value</l>"
"<d xmlns=\"urn:tests:f\">15</d>"
"<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>");
- free(str);
+ lyp_out_reset(out);
/* create first explicit container, which should become implicit */
node = lyd_new_inner(NULL, mod, "cont");
@@ -1099,7 +1102,7 @@
assert_int_equal(lyd_validate(&tree, ctx, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
/* check data tree */
- lyd_print_mem(&str, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
+ lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
assert_string_equal(str,
"<cont xmlns=\"urn:tests:f\">"
"<ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>"
@@ -1112,7 +1115,7 @@
"<l xmlns=\"urn:tests:f\">value</l>"
"<d xmlns=\"urn:tests:f\">15</d>"
"<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>");
- free(str);
+ lyp_out_reset(out);
/* create second explicit container, which should become implicit, so the first tree node should be removed */
node = lyd_new_inner(NULL, mod, "cont");
@@ -1121,7 +1124,7 @@
assert_int_equal(lyd_validate(&tree, ctx, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
/* check data tree */
- lyd_print_mem(&str, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
+ lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
assert_string_equal(str,
"<cont xmlns=\"urn:tests:f\">"
"<ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>"
@@ -1134,7 +1137,7 @@
"<l xmlns=\"urn:tests:f\">value</l>"
"<d xmlns=\"urn:tests:f\">15</d>"
"<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>");
- free(str);
+ lyp_out_reset(out);
/* similar changes for nested defaults */
assert_non_null(lyd_new_term(tree, NULL, "ll1", "def3"));
@@ -1143,7 +1146,7 @@
assert_int_equal(lyd_validate(&tree, ctx, LYD_VALOPT_DATA_ONLY), LY_SUCCESS);
/* check data tree */
- lyd_print_mem(&str, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
+ lyd_print(out, tree, LYD_XML, LYDP_WITHSIBLINGS | LYDP_WD_IMPL_TAG);
assert_string_equal(str,
"<cont xmlns=\"urn:tests:f\">"
"<ll1>def3</ll1>"
@@ -1153,9 +1156,10 @@
"<l xmlns=\"urn:tests:f\">value</l>"
"<d xmlns=\"urn:tests:f\">15</d>"
"<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>");
- free(str);
+ lyp_out_reset(out);
lyd_free_siblings(tree);
+ lyp_free(out, NULL, 1);
*state = NULL;
}
diff --git a/tests/utests/schema/test_printer_yang.c b/tests/utests/schema/test_printer_yang.c
index 1f3f749..93e3aeb 100644
--- a/tests/utests/schema/test_printer_yang.c
+++ b/tests/utests/schema/test_printer_yang.c
@@ -131,16 +131,19 @@
" \"some reference\";\n"
"}\n";
char *printed;
+ struct lyp_out *out;
+ size_t size = 0;
+ assert_non_null(out = lyp_new_memory(&printed, 0));
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx));
assert_non_null(mod = lys_parse_mem(ctx, orig, LYS_IN_YANG));
- assert_int_equal(strlen(orig), lys_print_mem(&printed, mod, LYS_OUT_YANG, 0, 0));
+ assert_int_equal(strlen(orig), size = lys_print(out, mod, LYS_OUT_YANG, 0, 0));
assert_string_equal(printed, orig);
- free(printed);
- assert_int_equal(strlen(compiled), lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0, 0));
+ lyp_out_reset(out);
+ assert_int_equal(strlen(compiled), lys_print(out, mod, LYS_OUT_YANG_COMPILED, 0, 0));
assert_string_equal(printed, compiled);
- free(printed);
+ lyp_out_reset(out);
orig = "module b {\n"
" yang-version 1.1;\n"
@@ -184,12 +187,12 @@
" }\n"
"}\n";
assert_non_null(mod = lys_parse_mem(ctx, orig, LYS_IN_YANG));
- assert_int_equal(strlen(orig), lys_print_mem(&printed, mod, LYS_OUT_YANG, 0, 0));
+ assert_int_equal(strlen(orig), lys_print(out, mod, LYS_OUT_YANG, 0, 0));
assert_string_equal(printed, orig);
- free(printed);
- assert_int_equal(strlen(compiled), lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0, 0));
+ lyp_out_reset(out);
+ assert_int_equal(strlen(compiled), lys_print(out, mod, LYS_OUT_YANG_COMPILED, 0, 0));
assert_string_equal(printed, compiled);
- free(printed);
+ lyp_out_reset(out);
orig = compiled ="module c {\n"
" yang-version 1.1;\n"
@@ -209,14 +212,15 @@
" }\n"
"}\n";
assert_non_null(mod = lys_parse_mem(ctx, orig, LYS_IN_YANG));
- assert_int_equal(strlen(orig), lys_print_mem(&printed, mod, LYS_OUT_YANG, 0, 0));
+ assert_int_equal(strlen(orig), lys_print(out, mod, LYS_OUT_YANG, 0, 0));
assert_string_equal(printed, orig);
- free(printed);
- assert_int_equal(strlen(compiled), lys_print_mem(&printed, mod, LYS_OUT_YANG, 0, 0));
+ lyp_out_reset(out);
+ assert_int_equal(strlen(compiled), lys_print(out, mod, LYS_OUT_YANG, 0, 0));
assert_string_equal(printed, compiled);
- free(printed);
+ /* missing free(printed); which is done in the following lyp_free() */
*state = NULL;
+ lyp_free(out, NULL, 1);
ly_ctx_destroy(ctx, NULL);
}
diff --git a/tests/utests/schema/test_printer_yin.c b/tests/utests/schema/test_printer_yin.c
index 2ffa611..5656795 100644
--- a/tests/utests/schema/test_printer_yin.c
+++ b/tests/utests/schema/test_printer_yin.c
@@ -578,20 +578,27 @@
" </rpc>\n"
"</module>\n";
- char * printed;
+ char *printed;
+ struct lyp_out *out;
+
+ assert_non_null(out = lyp_new_memory(&printed, 0));
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx));
assert_non_null(mod = lys_parse_mem(ctx, orig, LYS_IN_YANG));
- assert_int_equal(strlen(ori_res), lys_print_mem(&printed, mod, LYS_OUT_YIN, 0, 0));
+ assert_int_equal(strlen(ori_res), lys_print(out, mod, LYS_OUT_YIN, 0, 0));
assert_string_equal(printed, ori_res);
- free(printed);
+
/*
+ lyp_memory_clean(out);
assert_int_equal(strlen(compiled), lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0, 0));
assert_string_equal(printed, compiled);
- free(printed);
*/
+ /* note that the printed is freed here, so it must not be freed via lyp_free()! */
+ free(printed);
+
*state = NULL;
+ lyp_free(out, NULL, 0);
ly_ctx_destroy(ctx, NULL);
}
diff --git a/tools/lint/commands.c b/tools/lint/commands.c
index 0ef960e..d82e6e9 100644
--- a/tools/lint/commands.c
+++ b/tools/lint/commands.c
@@ -58,7 +58,7 @@
void
cmd_print_help(void)
{
- printf("print [-f (yang | yin | tree [<tree-options>] | info [-P <info-path>] | jsons)] [-o <output-file>]"
+ printf("print [-f (yang | yin | tree [<tree-options>] | info [-P <info-path>] [-(-s)ingle-node])] [-o <output-file>]"
" <model-name>[@<revision>]\n");
printf("\n");
printf("\ttree-options:\t--tree-print-groupings\t(print top-level groupings in a separate section)\n");
@@ -68,10 +68,7 @@
printf("\t \t--tree-line-length <line-length>\t(wrap lines if longer than line-length,\n");
printf("\t \t\tnot a strict limit, longer lines can often appear)\n");
printf("\n");
- printf("\tinfo-path:\t<schema-path> | typedef[<schema-path>]/<typedef-name> |\n");
- printf("\t \t| identity/<identity-name> | feature/<feature-name> |\n");
- printf("\t \t| grouping[<schema-path>]/<grouping-name> |\n");
- printf("\t \t| type/<schema-path-leaf-or-leaflist>\n");
+ printf("\tinfo-path:\t<schema-path> | identity/<identity-name> | feature/<feature-name>\n");
printf("\n");
printf("\tschema-path:\t( /<module-name>:<node-identifier> )+\n");
}
@@ -344,14 +341,13 @@
int
cmd_print(const char *arg)
{
- int c, argc, option_index, ret = 1, tree_ll = 0, tree_opts = 0, compiled = 0;
+ int c, argc, option_index, ret = 1, tree_ll = 0, output_opts = 0;
char **argv = NULL, *ptr, *model_name, *revision;
- const char *out_path = NULL;
+ const char *out_path = NULL, *target_path = NULL;
const struct lys_module *module;
LYS_OUTFORMAT format = LYS_OUT_TREE;
- FILE *output = stdout;
+ struct lyp_out *out = NULL;
static struct option long_options[] = {
- {"compiled", no_argument, 0, 'c'},
{"help", no_argument, 0, 'h'},
{"format", required_argument, 0, 'f'},
{"output", required_argument, 0, 'o'},
@@ -360,7 +356,10 @@
{"tree-print-uses", no_argument, 0, 'u'},
{"tree-no-leafref-target", no_argument, 0, 'n'},
{"tree-path", required_argument, 0, 'P'},
+#endif
{"info-path", required_argument, 0, 'P'},
+ {"single-node", no_argument, 0, 's'},
+#if 0
{"tree-line-length", required_argument, 0, 'L'},
#endif
{NULL, 0, 0, 0}
@@ -385,15 +384,12 @@
optind = 0;
while (1) {
option_index = 0;
- c = getopt_long(argc, argv, "chf:go:guP:L:", long_options, &option_index);
+ c = getopt_long(argc, argv, "chf:go:guP:sL:", long_options, &option_index);
if (c == -1) {
break;
}
switch (c) {
- case 'c':
- compiled = 1;
- break;
case 'h':
cmd_print_help();
ret = 0;
@@ -408,12 +404,10 @@
format = LYS_OUT_TREE;
} else if (!strcmp(optarg, "tree-rfc")) {
format = LYS_OUT_TREE;
- tree_opts |= LYS_OUTOPT_TREE_RFC;
- } else if (!strcmp(optarg, "info")) {
- format = LYS_OUT_INFO;
- } else if (!strcmp(optarg, "jsons")) {
- format = LYS_OUT_JSON;
+ output_opts |= LYS_OUTOPT_TREE_RFC;
#endif
+ } else if (!strcmp(optarg, "info")) {
+ format = LYS_OUT_YANG_COMPILED;
} else {
fprintf(stderr, "Unknown output format \"%s\".\n", optarg);
goto cleanup;
@@ -428,17 +422,22 @@
break;
#if 0
case 'g':
- tree_opts |= LYS_OUTOPT_TREE_GROUPING;
+ output_opts |= LYS_OUTOPT_TREE_GROUPING;
break;
case 'u':
- tree_opts |= LYS_OUTOPT_TREE_USES;
+ output_opts |= LYS_OUTOPT_TREE_USES;
break;
case 'n':
- tree_opts |= LYS_OUTOPT_TREE_NO_LEAFREF;
+ output_opts |= LYS_OUTOPT_TREE_NO_LEAFREF;
break;
+#endif
case 'P':
target_path = optarg;
break;
+ case 's':
+ output_opts |= LYS_OUTPUT_NO_SUBSTMT;
+ break;
+#if 0
case 'L':
tree_ll = atoi(optarg);
break;
@@ -450,75 +449,76 @@
}
/* file name */
- if (optind == argc) {
+ if (optind == argc && !target_path) {
fprintf(stderr, "Missing the module name.\n");
goto cleanup;
}
- /* compiled format */
- if (compiled) {
- if (format == LYS_OUT_YANG) {
- format = LYS_OUT_YANG_COMPILED;
- } else {
- fprintf(stderr, "warning: --compiled option takes effect only in case of printing schemas in YANG format.\n");
- }
- }
#if 0
/* tree fromat with or without gropings */
- if ((tree_opts || tree_ll) && format != LYS_OUT_TREE) {
+ if ((output_opts || tree_ll) && format != LYS_OUT_TREE) {
fprintf(stderr, "--tree options take effect only in case of the tree output format.\n");
}
#endif
- /* module, revision */
- model_name = argv[optind];
- revision = NULL;
- if (strchr(model_name, '@')) {
- revision = strchr(model_name, '@');
- revision[0] = '\0';
- ++revision;
- }
- if (revision) {
- module = ly_ctx_get_module(ctx, model_name, revision);
- } else {
- module = ly_ctx_get_module_latest(ctx, model_name);
- }
+ if (!target_path) {
+ /* module, revision */
+ model_name = argv[optind];
+ revision = NULL;
+ if (strchr(model_name, '@')) {
+ revision = strchr(model_name, '@');
+ revision[0] = '\0';
+ ++revision;
+ }
+
+ if (revision) {
+ module = ly_ctx_get_module(ctx, model_name, revision);
+ } else {
+ module = ly_ctx_get_module_latest(ctx, model_name);
+ }
#if 0
- if (!module) {
- /* not a module, try to find it as a submodule */
- module = (const struct lys_module *)ly_ctx_get_submodule(ctx, NULL, NULL, model_name, revision);
- }
+ if (!module) {
+ /* not a module, try to find it as a submodule */
+ module = (const struct lys_module *)ly_ctx_get_submodule(ctx, NULL, NULL, model_name, revision);
+ }
#endif
- if (!module) {
- if (revision) {
- fprintf(stderr, "No (sub)module \"%s\" in revision %s found.\n", model_name, revision);
- } else {
- fprintf(stderr, "No (sub)module \"%s\" found.\n", model_name);
- }
- goto cleanup;
- }
-
- if (out_path) {
- output = fopen(out_path, "w");
- if (!output) {
- fprintf(stderr, "Could not open the output file (%s).\n", strerror(errno));
+ if (!module) {
+ if (revision) {
+ fprintf(stderr, "No (sub)module \"%s\" in revision %s found.\n", model_name, revision);
+ } else {
+ fprintf(stderr, "No (sub)module \"%s\" found.\n", model_name);
+ }
goto cleanup;
}
}
- ret = lys_print_file(output, module, format, tree_ll, tree_opts);
- if (format == LYS_OUT_JSON) {
- fputs("\n", output);
+ if (out_path) {
+ out = lyp_new_filepath(out_path);
+ } else {
+ out = lyp_new_file(stdout);
+ }
+ if (!out) {
+ fprintf(stderr, "Could not open the output file (%s).\n", strerror(errno));
+ goto cleanup;
+ }
+
+ if (target_path) {
+ const struct lysc_node *node = lys_find_node(ctx, NULL, target_path);
+ if (node) {
+ ret = lys_print_node(out, node, format, tree_ll, output_opts);
+ } else {
+ fprintf(stderr, "The requested schema node \"%s\" does not exists.\n", target_path);
+ }
+ } else {
+ ret = lys_print(out, module, format, tree_ll, output_opts);
}
cleanup:
free(*argv);
free(argv);
- if (output && (output != stdout)) {
- fclose(output);
- }
+ lyp_free(out, NULL, out_path ? 1 : 0);
return ret;
}
@@ -698,8 +698,9 @@
const char *out_path = NULL;
struct lyd_node *data = NULL;
struct lyd_node *tree = NULL;
+ const struct lyd_node **trees = NULL;
LYD_FORMAT outformat = 0;
- FILE *output = stdout;
+ struct lyp_out *out = NULL;
static struct option long_options[] = {
{"defaults", required_argument, 0, 'd'},
{"help", no_argument, 0, 'h'},
@@ -834,15 +835,17 @@
}
if (out_path) {
- output = fopen(out_path, "w");
- if (!output) {
- fprintf(stderr, "Could not open the output file (%s).\n", strerror(errno));
- goto cleanup;
- }
+ out = lyp_new_filepath(out_path);
+ } else {
+ out = lyp_new_file(stdout);
+ }
+ if (!out) {
+ fprintf(stderr, "Could not open the output file (%s).\n", strerror(errno));
+ goto cleanup;
}
if (outformat) {
- lyd_print_file(output, data, outformat, LYDP_WITHSIBLINGS | LYDP_FORMAT | printopt);
+ lyd_print(out, data, outformat, LYDP_WITHSIBLINGS | LYDP_FORMAT | printopt);
}
ret = 0;
@@ -851,9 +854,7 @@
free(*argv);
free(argv);
- if (output && (output != stdout)) {
- fclose(output);
- }
+ lyp_free(out, NULL, out_path ? 1 : 0);
lyd_free_all(data);
diff --git a/tools/lint/main_ni.c b/tools/lint/main_ni.c
index 97b5e4e..7a16b62 100644
--- a/tools/lint/main_ni.c
+++ b/tools/lint/main_ni.c
@@ -39,7 +39,7 @@
help(int shortout)
{
fprintf(stdout, "Usage:\n");
- fprintf(stdout, " yanglint [options] [-f { yang | yin | tree | tree-rfc | jsons}] <file>...\n");
+ fprintf(stdout, " yanglint [options] [-f { yang | yin | tree | tree-rfc | info}] <file>...\n");
fprintf(stdout, " Validates the YANG module in <file>, and all its dependencies.\n\n");
fprintf(stdout, " yanglint [options] [-f { xml | json }] <schema>... <file>...\n");
fprintf(stdout, " Validates the YANG modeled data in <file> according to the <schema>.\n\n");
@@ -71,7 +71,7 @@
" has no effect for the auto, rpc, rpcreply and notif TYPEs.\n\n"
" -f FORMAT, --format=FORMAT\n"
" Convert to FORMAT. Supported formats: \n"
- " yang, yin, tree and jsons (JSON) for schemas,\n"
+ " yang, yin, tree and info for schemas,\n"
" xml, json for data.\n"
" -a, --auto Modify the xml output by adding envelopes for autodetection.\n\n"
" -i, --allimplemented Make all the imported modules implemented.\n\n"
@@ -125,7 +125,12 @@
" Print only the specified subtree.\n"
" --tree-line-length=LINE_LENGTH\n"
" Wrap lines if longer than the specified length (it is not a strict limit, longer lines\n"
- " can often appear).\n"
+ " can often appear).\n\n"
+ "Info output specific options:\n"
+ " -P INFOPATH, --info-path=INFOPATH\n"
+ " - Schema path with full module names used as node's prefixes, the path identify the root\n"
+ " node of the subtree to print information about.\n"
+ " --single-node - Print information about a single node instead of a subtree."
"\n");
}
@@ -253,7 +258,7 @@
main_ni(int argc, char* argv[])
{
int ret = EXIT_FAILURE;
- int opt, opt_index = 0, i, featsize = 0, compiled = 0;
+ int opt, opt_index = 0, i, featsize = 0;
struct option options[] = {
#if 0
{"auto", no_argument, NULL, 'a'},
@@ -268,7 +273,6 @@
{"tree-path", required_argument, NULL, 'P'},
{"tree-line-length", required_argument, NULL, 'L'},
#endif
- {"compiled", no_argument, NULL, 'c'},
{"help", no_argument, NULL, 'h'},
#if 0
{"tree-help", no_argument, NULL, 'H'},
@@ -281,10 +285,12 @@
#endif
{"output", required_argument, NULL, 'o'},
{"path", required_argument, NULL, 'p'},
+ {"info-path", required_argument, NULL, 'P'},
#if 0
{"running", required_argument, NULL, 'r'},
{"operational", required_argument, NULL, 'O'},
#endif
+ {"single-node", no_argument, NULL, 'q'},
{"strict", no_argument, NULL, 's'},
{"type", required_argument, NULL, 't'},
{"version", no_argument, NULL, 'v'},
@@ -295,7 +301,7 @@
{NULL, required_argument, NULL, 'y'},
{NULL, 0, NULL, 0}
};
- FILE *out = stdout;
+ struct lyp_out *out = NULL;
struct ly_ctx *ctx = NULL;
const struct lys_module *mod;
LYS_OUTFORMAT outformat_s = 0;
@@ -359,9 +365,6 @@
}
break;
#endif
- case 'c':
- compiled = 1;
- break;
case 'f':
if (!strcasecmp(optarg, "yang")) {
outformat_s = LYS_OUT_YANG;
@@ -378,11 +381,9 @@
} else if (!strcasecmp(optarg, "yin")) {
outformat_s = LYS_OUT_YIN;
outformat_d = 0;
-#if 0
- } else if (!strcasecmp(optarg, "jsons")) {
- outformat_s = LYS_OUT_JSON;
+ } else if (!strcasecmp(optarg, "info")) {
+ outformat_s = LYS_OUT_YANG_COMPILED;
outformat_d = 0;
-#endif
} else if (!strcasecmp(optarg, "xml")) {
outformat_s = 0;
outformat_d = LYD_XML;
@@ -428,9 +429,11 @@
case 'n':
outoptions_s |= LYS_OUTOPT_TREE_NO_LEAFREF;
break;
+#endif
case 'P':
outtarget_s = optarg;
break;
+#if 0
case 'L':
outline_length_s = atoi(optarg);
break;
@@ -468,13 +471,17 @@
break;
#endif
case 'o':
- if (out != stdout) {
- fclose(out);
- }
- out = fopen(optarg, "w");
- if (!out) {
- fprintf(stderr, "yanglint error: unable open output file %s (%s)\n", optarg, strerror(errno));
- goto cleanup;
+ if (out) {
+ if (lyp_filepath(out, optarg) != NULL) {
+ fprintf(stderr, "yanglint error: unable open output file %s (%s)\n", optarg, strerror(errno));
+ goto cleanup;
+ }
+ } else {
+ out = lyp_new_filepath(optarg);
+ if (!out) {
+ fprintf(stderr, "yanglint error: unable open output file %s (%s)\n", optarg, strerror(errno));
+ goto cleanup;
+ }
}
break;
case 'p':
@@ -606,13 +613,6 @@
fprintf(stderr, "yanglint error: missing <file> to process\n");
goto cleanup;
}
- if (compiled) {
- if (outformat_s != LYS_OUT_YANG) {
- fprintf(stderr, "yanglint warning: --compiled option takes effect only in case of printing schemas in YANG format.\n");
- } else {
- outformat_s = LYS_OUT_YANG_COMPILED;
- }
- }
if (outformat_s && outformat_s != LYS_OUT_TREE && (optind + 1) < argc) {
/* we have multiple schemas to be printed as YIN or YANG */
fprintf(stderr, "yanglint error: too many schemas to convert and store.\n");
@@ -765,24 +765,19 @@
/* convert (print) to FORMAT */
if (outformat_s) {
- if (outformat_s == LYS_OUT_JSON && mods->count > 1) {
- fputs("[", out);
- }
- for (u = 0; u < mods->count; u++) {
- if (u) {
- if (outformat_s == LYS_OUT_JSON) {
- fputs(",\n", out);
- } else {
- fputs("\n", out);
- }
+ if (outtarget_s) {
+ const struct lysc_node *node = lys_find_node(ctx, NULL, outtarget_s);
+ if (node) {
+ lys_print_node(out, node, outformat_s, outline_length_s, outoptions_s);
+ } else {
+ fprintf(stderr, "yanglint error: The requested schema node \"%s\" does not exists.\n", outtarget_s);
}
- lys_print_file(out, (struct lys_module *)mods->objs[u], outformat_s, outline_length_s, outoptions_s);
- }
- if (outformat_s == LYS_OUT_JSON) {
- if (mods->count > 1) {
- fputs("]\n", out);
- } else if (mods->count == 1) {
- fputs("\n", out);
+ } else {
+ for (u = 0; u < mods->count; u++) {
+ if (u) {
+ lyp_print(out, "\n");
+ }
+ lys_print(out, (struct lys_module *)mods->objs[u], outformat_s, outline_length_s, outoptions_s);
}
}
} else if (data) {
@@ -1060,7 +1055,7 @@
}
}
#endif
- lyd_print_file(out, data_item->tree, outformat_d, LYDP_WITHSIBLINGS | LYDP_FORMAT /* TODO defaults | options_dflt */);
+ lyd_print(out, data_item->tree, outformat_d, LYDP_WITHSIBLINGS | LYDP_FORMAT /* TODO defaults | options_dflt */);
#if 0
if (envelope_s) {
if (data_item->type == LYD_OPT_RPC && data_item->tree->schema->nodetype != LYS_RPC) {
@@ -1085,9 +1080,6 @@
ret = EXIT_SUCCESS;
cleanup:
- if (out && out != stdout) {
- fclose(out);
- }
ly_set_free(mods, NULL);
ly_set_free(searchpaths, NULL);
for (i = 0; i < featsize; i++) {
@@ -1101,5 +1093,6 @@
}
ly_ctx_destroy(ctx, NULL);
+ lyp_free(out, NULL, 1);
return ret;
}