printers CHANGE rewrite printers mechanism

Instead of specifying output type (memory, stream, file descriptor, ...)
with each printer function call, use printer handler mechanism. The
handler is first created with specifying the output type with necessary
parameters. Then, the handler can be used in the single print function
without the need to specify the specific output type parameters. There
are also a helper functions to update/change the output type parameter
without a need to recreate the printer handler.

This change is necessary due to the increasing complexity of the
printer functions. We want to add another parameters/specific functions,
for example to print a separate node, but together with the specific
output type parameters, the function parameters list would be quite
complex.
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);
 }