schema tree FEATURE allow changing enabled features

At the cost of recompiling the whole context.
diff --git a/src/schema_features.c b/src/schema_features.c
index 8cd92a4..303ee51 100644
--- a/src/schema_features.c
+++ b/src/schema_features.c
@@ -472,12 +472,48 @@
     return LY_SUCCESS;
 }
 
+/**
+ * @brief Check whether all enabled features have their if-features satisfied.
+ * Enabled features with false if-features are disabled with a warning.
+ *
+ * @param[in] pmod Parsed module features to check.
+ * @return LY_ERR value.
+ */
+static LY_ERR
+lys_check_features(struct lysp_module *pmod)
+{
+    LY_ERR r;
+    uint32_t i = 0;
+    struct lysp_feature *f = NULL;
+
+    while ((f = lysp_feature_next(f, pmod, &i))) {
+        if (!(f->flags & LYS_FENABLED) || !f->iffeatures) {
+            /* disabled feature or no if-features to check */
+            continue;
+        }
+
+        assert(f->iffeatures_c);
+        r = lysc_iffeature_value(f->iffeatures_c);
+        if (r == LY_ENOT) {
+            LOGWRN(pmod->mod->ctx, "Feature \"%s\" cannot be enabled because its \"if-feature\" is not satisfied.",
+                    f->name);
+
+            /* disable feature and re-evaluate all the feature if-features again */
+            f->flags &= ~LYS_FENABLED;
+            return lys_check_features(pmod);
+        } else if (r) {
+            return r;
+        } /* else if-feature satisfied */
+    }
+
+    return LY_SUCCESS;
+}
+
 LY_ERR
 lys_enable_features(struct lysp_module *pmod, const char **features)
 {
-    uint32_t i;
-    struct lysp_feature *f;
-    LY_ERR ret;
+    uint32_t i = 0;
+    struct lysp_feature *f = 0;
 
     if (!features) {
         /* keep all features disabled */
@@ -486,8 +522,6 @@
 
     if (!strcmp(features[0], "*")) {
         /* enable all features */
-        f = NULL;
-        i = 0;
         while ((f = lysp_feature_next(f, pmod, &i))) {
             f->flags |= LYS_FENABLED;
         }
@@ -507,31 +541,61 @@
         }
     }
 
-check_iffeature:
-    /* check whether all enabled features have their if-features satisfied */
-    f = NULL;
-    i = 0;
-    while ((f = lysp_feature_next(f, pmod, &i))) {
-        if (!(f->flags & LYS_FENABLED) || !f->iffeatures) {
-            /* disabled feature or no if-features to check */
-            continue;
+    /* check final features if-feature state */
+    return lys_check_features(pmod);
+}
+
+LY_ERR
+lys_set_features(struct lysp_module *pmod, const char **features)
+{
+    uint32_t i = 0, j;
+    struct lysp_feature *f = 0;
+    ly_bool change = 0;
+
+    if (!features) {
+        /* disable all the features */
+        while ((f = lysp_feature_next(f, pmod, &i))) {
+            if (f->flags & LYS_FENABLED) {
+                f->flags &= ~LYS_FENABLED;
+                change = 1;
+            }
         }
+    } else if (!strcmp(features[0], "*")) {
+        /* enable all the features */
+        while ((f = lysp_feature_next(f, pmod, &i))) {
+            if (!(f->flags & LYS_FENABLED)) {
+                f->flags |= LYS_FENABLED;
+                change = 1;
+            }
+        }
+    } else {
+        /* enable specific features, disable the rest */
+        while ((f = lysp_feature_next(f, pmod, &i))) {
+            for (j = 0; features[j]; ++j) {
+                if (!strcmp(f->name, features[j])) {
+                    break;
+                }
+            }
 
-        assert(f->iffeatures_c);
-        ret = lysc_iffeature_value(f->iffeatures_c);
-        if (ret == LY_ENOT) {
-            LOGWRN(pmod->mod->ctx, "Feature \"%s\" cannot be enabled because its \"if-feature\" is not satisfied.",
-                    f->name);
-
-            /* disable feature and re-evaluate all the feature if-features again */
-            f->flags &= ~LYS_FENABLED;
-            goto check_iffeature;
-        } else if (ret) {
-            return ret;
-        } /* else if-feature satisfied */
+            if (features[j] && !(f->flags & LYS_FENABLED)) {
+                /* enable */
+                f->flags |= LYS_FENABLED;
+                change = 1;
+            } else if (!features[j] && (f->flags & LYS_FENABLED)) {
+                /* disable */
+                f->flags &= ~LYS_FENABLED;
+                change = 1;
+            }
+        }
     }
 
-    return LY_SUCCESS;
+    if (!change) {
+        /* features already set correctly */
+        return LY_EEXIST;
+    }
+
+    /* check final features if-feature state */
+    return lys_check_features(pmod);
 }
 
 /**