printers FEATURE add printer options

Add generic 'options' parameter to the data printer functions.
Currently it implements LYP_WITHSIBLINGS option to print besides
the provided data node also the sibling nodes/trees.
diff --git a/src/libyang.h b/src/libyang.h
index 5929c41..0c24000 100644
--- a/src/libyang.h
+++ b/src/libyang.h
@@ -667,6 +667,20 @@
                   const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node);
 
 /**
+ * @defgroup printerflags Printer flags
+ * @ingroup printers
+ *
+ * Validity flags for data nodes.
+ *
+ * @{
+ */
+#define LYP_WITHSIBLINGS 0x01 /**< Flag for printing also the (following) sibling nodes of the data node. */
+
+/**
+ * @}
+ */
+
+/**
  * @brief Print data tree in the specified format.
  *
  * To write data into a file descriptor, use lyd_print_fd().
@@ -675,9 +689,10 @@
  * node of the data tree to print the specific subtree.
  * @param[in] f File stream where to print the data.
  * @param[in] format Data output format.
+ * @param[in] options [printer flags](@ref printerflags).
  * @return 0 on success, 1 on failure (#ly_errno is set).
  */
-int lyd_print_file(FILE *f, const struct lyd_node *root, LYD_FORMAT format);
+int lyd_print_file(FILE *f, const struct lyd_node *root, LYD_FORMAT format, int options);
 
 /**
  * @brief Print data tree in the specified format.
@@ -688,9 +703,10 @@
  * node of the data tree to print the specific subtree.
  * @param[in] fd File descriptor where to print the data.
  * @param[in] format Data output format.
+ * @param[in] options [printer flags](@ref printerflags).
  * @return 0 on success, 1 on failure (#ly_errno is set).
  */
-int lyd_print_fd(int fd, const struct lyd_node *root, LYD_FORMAT format);
+int lyd_print_fd(int fd, const struct lyd_node *root, LYD_FORMAT format, int options);
 
 
  /**
@@ -703,9 +719,10 @@
  * @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 [printer flags](@ref printerflags).
  * @return 0 on success, 1 on failure (#ly_errno is set).
  */
-int lyd_print_mem(char **strp, const struct lyd_node *root, LYD_FORMAT format);
+int lyd_print_mem(char **strp, const struct lyd_node *root, LYD_FORMAT format, int options);
 
 /**
  * @brief Print data tree in the specified format.
@@ -717,10 +734,11 @@
  * @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 Data output format.
+ * @param[in] options [printer flags](@ref printerflags).
  * @return 0 on success, 1 on failure (#ly_errno is set).
  */
 int lyd_print_clb(ssize_t (*writeclb)(void *arg, const void *buf, size_t count), void *arg,
-                  const struct lyd_node *root, LYD_FORMAT format);
+                  const struct lyd_node *root, LYD_FORMAT format, int options);
 
 /**@} printers */
 
diff --git a/src/printer.c b/src/printer.c
index 803d8f6..640d1ce 100644
--- a/src/printer.c
+++ b/src/printer.c
@@ -228,15 +228,15 @@
 }
 
 static int
-lyd_print_(struct lyout *out, const struct lyd_node *root, LYD_FORMAT format)
+lyd_print_(struct lyout *out, const struct lyd_node *root, LYD_FORMAT format, int options)
 {
     switch (format) {
     case LYD_XML:
-        return xml_print_data(out, root, 0);
+        return xml_print_data(out, root, 0, options);
     case LYD_XML_FORMAT:
-        return xml_print_data(out, root, 1);
+        return xml_print_data(out, root, 1, options);
     case LYD_JSON:
-        return json_print_data(out, root);
+        return json_print_data(out, root, options);
     default:
         LOGERR(LY_EINVAL, "Unknown output format.");
         return EXIT_FAILURE;
@@ -244,7 +244,7 @@
 }
 
 API int
-lyd_print_file(FILE *f, const struct lyd_node *root, LYD_FORMAT format)
+lyd_print_file(FILE *f, const struct lyd_node *root, LYD_FORMAT format, int options)
 {
     struct lyout out;
 
@@ -256,11 +256,11 @@
     out.type = LYOUT_STREAM;
     out.method.f = f;
 
-    return lyd_print_(&out, root, format);
+    return lyd_print_(&out, root, format, options);
 }
 
 API int
-lyd_print_fd(int fd, const struct lyd_node *root, LYD_FORMAT format)
+lyd_print_fd(int fd, const struct lyd_node *root, LYD_FORMAT format, int options)
 {
     struct lyout out;
 
@@ -272,11 +272,11 @@
     out.type = LYOUT_FD;
     out.method.fd = fd;
 
-    return lyd_print_(&out, root, format);
+    return lyd_print_(&out, root, format, options);
 }
 
 API int
-lyd_print_mem(char **strp, const struct lyd_node *root, LYD_FORMAT format)
+lyd_print_mem(char **strp, const struct lyd_node *root, LYD_FORMAT format, int options)
 {
     struct lyout out;
     int r;
@@ -291,14 +291,15 @@
     out.method.mem.len = 0;
     out.method.mem.size = 0;
 
-    r = lyd_print_(&out, root, format);
+    r = lyd_print_(&out, root, format, options);
 
     *strp = out.method.mem.buf;
     return r;
 }
 
 API int
-lyd_print_clb(ssize_t (*writeclb)(void *arg, const void *buf, size_t count), void *arg, const struct lyd_node *root, LYD_FORMAT format)
+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)
 {
     struct lyout out;
 
@@ -311,5 +312,5 @@
     out.method.clb.f = writeclb;
     out.method.clb.arg = arg;
 
-    return lyd_print_(&out, root, format);
+    return lyd_print_(&out, root, format, options);
 }
diff --git a/src/printer.h b/src/printer.h
index eb13049..8a66e05 100644
--- a/src/printer.h
+++ b/src/printer.h
@@ -60,8 +60,8 @@
 int tree_print_model(struct lyout *out, const struct lys_module *module);
 int info_print_model(struct lyout *out, const struct lys_module *module, const char *target_node);
 
-int json_print_data(struct lyout *out, const struct lyd_node *root);
-int xml_print_data(struct lyout *out, const struct lyd_node *root, int format);
+int json_print_data(struct lyout *out, const struct lyd_node *root, int options);
+int xml_print_data(struct lyout *out, const struct lyd_node *root, int format, int options);
 
 /* 0 - same, 1 - different */
 int nscmp(const struct lyd_node *node1, const struct lyd_node *node2);
diff --git a/src/printer_json.c b/src/printer_json.c
index 77b1d84..00f1743 100644
--- a/src/printer_json.c
+++ b/src/printer_json.c
@@ -34,7 +34,7 @@
 #define INDENT ""
 #define LEVEL (level*2)
 
-void json_print_nodes(struct lyout *out, int level, const struct lyd_node *root);
+static void json_print_nodes(struct lyout *out, int level, const struct lyd_node *root, int withsiblings);
 
 static int
 json_print_string(struct lyout *out, const char *text)
@@ -179,7 +179,7 @@
         json_print_attrs(out, level + 1, node);
         ly_print(out, "%*s}%s", LEVEL, INDENT, node->child ? ",\n" : "");
     }
-    json_print_nodes(out, level, node->child);
+    json_print_nodes(out, level, node->child, 1);
     level--;
     ly_print(out, "%*s}", LEVEL, INDENT);
 }
@@ -230,7 +230,7 @@
                 json_print_attrs(out, level + 1, node);
                 ly_print(out, "%*s}%s", LEVEL, INDENT, list->child ? ",\n" : "");
             }
-            json_print_nodes(out, level, list->child);
+            json_print_nodes(out, level, list->child, 1);
             --level;
             ly_print(out, "%*s}", LEVEL, INDENT);
             --level;
@@ -312,8 +312,8 @@
     }
 }
 
-void
-json_print_nodes(struct lyout *out, int level, const struct lyd_node *root)
+static void
+json_print_nodes(struct lyout *out, int level, const struct lyd_node *root, int withsiblings)
 {
     const struct lyd_node *node, *iter;
 
@@ -368,12 +368,16 @@
             LOGINT;
             break;
         }
+
+        if (!withsiblings) {
+            break;
+        }
     }
     ly_print(out, "\n");
 }
 
 int
-json_print_data(struct lyout *out, const struct lyd_node *root)
+json_print_data(struct lyout *out, const struct lyd_node *root, int options)
 {
     int level = 0;
 
@@ -381,7 +385,7 @@
     ly_print(out, "{\n");
 
     /* content */
-    json_print_nodes(out, level + 1, root);
+    json_print_nodes(out, level + 1, root, options & LYP_WITHSIBLINGS);
 
     /* end */
     ly_print(out, "}\n");
diff --git a/src/printer_xml.c b/src/printer_xml.c
index 6929b6d..990d520 100644
--- a/src/printer_xml.c
+++ b/src/printer_xml.c
@@ -403,13 +403,16 @@
 }
 
 int
-xml_print_data(struct lyout *out, const struct lyd_node *root, int format)
+xml_print_data(struct lyout *out, const struct lyd_node *root, int format, int options)
 {
     const struct lyd_node *node;
 
     /* content */
     LY_TREE_FOR(root, node) {
         xml_print_node(out, format ? 1 : 0, node, 1);
+        if (!(options & LYP_WITHSIBLINGS)) {
+            break;
+        }
     }
 
     return EXIT_SUCCESS;