data tree CHANGE modify lyd_leaf_type()

change the function to return not only the data type enumeration but
the complete data type definition. This allows caller to get detailed
information about the type restrictions.

Relates to CESNET/Netopeer2#47
diff --git a/src/printer_json.c b/src/printer_json.c
index 01c87d0..aa6498f 100644
--- a/src/printer_json.c
+++ b/src/printer_json.c
@@ -90,6 +90,7 @@
     const char *schema = NULL;
     const struct lys_module *wdmod = NULL;
     LY_DATA_TYPE datatype;
+    const struct lys_type *type;
 
     if ((node->dflt && (options & (LYP_WD_ALL_TAG | LYP_WD_IMPL_TAG))) ||
             (!node->dflt && (options & LYP_WD_ALL_TAG) && lyd_wd_default(leaf))) {
@@ -134,7 +135,13 @@
         break;
 
     case LY_TYPE_LEAFREF:
-        datatype = lyd_leaf_type(leaf);
+        type = lyd_leaf_type(leaf);
+        if (!type) {
+            /* error */
+            ly_print(out, "\"(!error!)\"");
+            break;
+        }
+        datatype = type->base;
         goto contentprint;
 
     case LY_TYPE_EMPTY:
diff --git a/src/resolve.c b/src/resolve.c
index 196bdab..fe52f24 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -3050,7 +3050,7 @@
         if (lyp_parse_value(&node, NULL, 1)) {
             ret = -1;
             if (base_tpdf) {
-                /* default value was is defined in some base typedef */
+                /* default value is defined in some base typedef */
                 if ((type->base == LY_TYPE_BITS && type->der->type.der) ||
                         (type->base == LY_TYPE_ENUM && type->der->type.der)) {
                     /* we have refined bits/enums */
@@ -6643,7 +6643,7 @@
     return EXIT_SUCCESS;
 }
 
-API LY_DATA_TYPE
+API const struct lys_type *
 lyd_leaf_type(const struct lyd_node_leaf_list *leaf)
 {
     struct lyd_node *node;
@@ -6652,13 +6652,7 @@
     int f = 0, r;
 
     if (!leaf || !(leaf->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
-        return LY_TYPE_ERR;
-    }
-
-    if (leaf->value_type > 0 && (leaf->value_type & LY_DATA_TYPE_MASK) != LY_TYPE_UNION &&
-            (leaf->value_type & LY_DATA_TYPE_MASK) != LY_TYPE_LEAFREF) {
-        /* we can get the type directly from the data node (it was already resolved) */
-        return leaf->value_type & LY_DATA_TYPE_MASK;
+        return NULL;
     }
 
     /* init */
@@ -6694,23 +6688,28 @@
                 } else if (type_iter->base == LY_TYPE_INST) {
                     if (type_iter->info.inst.req == -1) {
                         /* target not required, so it always succeeds */
-                        return LY_TYPE_INST;
+                        return type_iter;
                     } else {
                         /* try to resolve instance-identifier */
                         ly_err_clean(1);
                         node = resolve_instid((struct lyd_node *)leaf, leaf->value_str);
                         if (!ly_errno && node) {
                             /* the real type is instance-identifier */
-                            return LY_TYPE_INST;
+                            return type_iter;
                         }
                     }
                 } else {
                     r = lyp_parse_value_type((struct lyd_node_leaf_list *)leaf, type_iter, NULL, 1);
                     /* revert leaf's content affected by resolve_leafref */
+                    if (leaf->value_type == LY_TYPE_BITS) {
+                        if (leaf->value.bit) {
+                            free(leaf->value.bit);
+                        }
+                    }
                     ((struct lyd_node_leaf_list *)leaf)->value = value;
                     if (!r) {
                         /* we have the real type */
-                        return type_iter->base;
+                        return type_iter;
                     }
                 }
                 f = 0;
@@ -6720,19 +6719,19 @@
 
             if (!type_iter) {
                 LOGERR(LY_EINVAL, "Unable to get type from union \"%s\" with no valid type.", type->parent->name)
-                return LY_TYPE_ERR;
+                return NULL;
             }
             type = type_iter;
             break;
         default:
             /* we have the real type */
             ly_vlog_hide(0);
-            return type->base;
+            return type;
         }
     }
 
     ly_vlog_hide(0);
-    return LY_TYPE_ERR;
+    return NULL;
 }
 
 static int
diff --git a/src/tree_data.h b/src/tree_data.h
index d4a253a..0cd6842 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -1143,16 +1143,17 @@
 double lyd_dec64_to_double(const struct lyd_node *node);
 
 /**
- * @brief Get the real data type of the leaf/leaf-list node.
+ * @brief Get the real data type definition of the leaf/leaf-list node.
  *
  * Usually the data type can be obtained directly from the value_type member of the leaf/leaf-list.
- * However, in case the node is unresolved leafref, it can be more complicated to get the correct
- * data type, so this function can be used.
+ * However, in case the node is unresolved leafref or the complete definition of the type is needed, it can be quite
+ * complicated to get the correct data type, so this function can be used. The real type describes the value
+ * representation so it is not #LY_TYPE_UNION neither #LY_TYPE_LEAFREF.
  *
  * @param[in] leaf The leaf/leaf-list node to be examined.
- * @return The specific data type of the \p leaf.
+ * @return Pointer to the type definition of the \p leaf.
  */
-LY_DATA_TYPE lyd_leaf_type(const struct lyd_node_leaf_list *leaf);
+const struct lys_type *lyd_leaf_type(const struct lyd_node_leaf_list *leaf);
 
 /**@} */
 
diff --git a/src/tree_schema.c b/src/tree_schema.c
index e5f00b7..c905a5b 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -3703,3 +3703,4 @@
 
     return result;
 }
+
diff --git a/tests/api/test_tree_data.c b/tests/api/test_tree_data.c
index 4338b84..0ea8831 100644
--- a/tests/api/test_tree_data.c
+++ b/tests/api/test_tree_data.c
@@ -1589,18 +1589,18 @@
 
     data = lyd_parse_mem(ctx, xml1, LYD_XML, LYD_OPT_CONFIG);
     assert_ptr_not_equal(data, NULL);
-    assert_int_equal(lyd_leaf_type((struct lyd_node_leaf_list *)data->child->prev), LY_TYPE_STRING);
+    assert_int_equal(lyd_leaf_type((struct lyd_node_leaf_list *)data->child->prev)->base, LY_TYPE_STRING);
     lyd_free_withsiblings(data);
 
     data = lyd_parse_mem(ctx, xml2, LYD_XML, LYD_OPT_CONFIG);
     assert_ptr_not_equal(data, NULL);
-    assert_int_equal(lyd_leaf_type((struct lyd_node_leaf_list *)data->child->prev), LY_TYPE_ENUM);
+    assert_int_equal(lyd_leaf_type((struct lyd_node_leaf_list *)data->child->prev)->base, LY_TYPE_ENUM);
     lyd_free_withsiblings(data);
 
     /* Use trusted flag to avoid getting error on parsing since 'ssh' is invalid value */
     data = lyd_parse_mem(ctx, xml3, LYD_XML, LYD_OPT_CONFIG | LYD_OPT_TRUSTED);
     assert_ptr_not_equal(data, NULL);
-    assert_int_equal(lyd_leaf_type((struct lyd_node_leaf_list *)data->child->prev), LY_TYPE_ERR);
+    assert_int_equal(lyd_leaf_type((struct lyd_node_leaf_list *)data->child->prev), NULL);
     assert_string_equal(ly_errmsg(), "Unable to get type from union \"u\" with no valid type.");
     lyd_free_withsiblings(data);
 }