plugins BUGFIX fix several bug in bits plugin
diff --git a/src/plugins_types_bits.c b/src/plugins_types_bits.c
index c015b61..c06661f 100644
--- a/src/plugins_types_bits.c
+++ b/src/plugins_types_bits.c
@@ -40,19 +40,25 @@
         const struct lysc_node *UNUSED(ctx_node), struct lyd_value *storage, struct lys_glob_unres *UNUSED(unres),
         struct ly_err_item **err)
 {
+
+    /* necessary variables */
     LY_ERR ret = LY_SUCCESS;
-    size_t item_len;
-    const char *item;
-    struct ly_set *items = NULL, *items_ordered = NULL;
-    size_t buf_size = 0;
-    char *buf = NULL;
-    size_t index;
-    LY_ARRAY_COUNT_TYPE u;
     struct lysc_type_bits *type_bits = (struct lysc_type_bits *)type;
-    ly_bool iscanonical = 1;
-    size_t ws_count;
-    size_t lws_count; /* leading whitespace count */
-    const char *can = NULL;
+    struct lysc_type_bitenum_item **bits_items = NULL;
+    struct ly_set *items = NULL;
+
+    uint32_t index_start;   /* start index of bit name */
+    uint32_t index_end = 0; /* end index of bit name */
+    uint32_t item_len;      /* length of bit name */
+    uint32_t buf_len = 0;
+    uint32_t item_pos;
+    uint32_t item_pos_expected;
+    char *buf = NULL;
+    const char *item = NULL;
+
+    ly_bool item_present;
+    LY_ARRAY_COUNT_TYPE item_present_index;
+    LY_ARRAY_COUNT_TYPE it;
 
     /* check hints */
     ret = ly_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
@@ -62,113 +68,122 @@
     ret = ly_set_new(&items);
     LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup_value);
 
-    ws_count = lws_count = 0;
-    for (index = 0; index < value_len; ++index) {
-        if (isspace(value[index])) {
-            ++ws_count;
-            continue;
+    /* get all values */
+    while (index_end < value_len) {
+        /* skip leading spaces */
+        index_start = index_end;
+        while ((index_start < value_len) && isspace(value[index_start])) {
+            index_start++;
         }
-        if (index == ws_count) {
-            lws_count = ws_count;
-        } else if (ws_count) {
-            iscanonical = 0;
+
+        index_end = index_start;
+        /* find end of word */
+        while ((index_end < value_len) && !isspace(value[index_end])) {
+            index_end++;
         }
-        ws_count = 0;
 
-        /* start of the item */
-        item = &value[index];
-        for (item_len = 0; index + item_len < value_len && !isspace(item[item_len]); item_len++) {}
-        LY_ARRAY_FOR(type_bits->bits, u) {
-            if (!ly_strncmp(type_bits->bits[u].name, item, item_len)) {
-                /* we have the match */
-                uint32_t inserted;
+        /* check if name of bit is valid */
+        item = &value[index_start];
+        item_len = index_end - index_start;
+        if (item_len == 0) {
+            /* loop read all bits names*/
+            break;
+        }
 
-                if (iscanonical && items->count && (type_bits->bits[u].position < ((struct lysc_type_bitenum_item *)items->objs[items->count - 1])->position)) {
-                    iscanonical = 0;
-                }
-                ret = ly_set_add(items, &type_bits->bits[u], 0, &inserted);
-                LY_CHECK_GOTO(ret, cleanup);
-                if (inserted != items->count - 1) {
-                    ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL,
-                            "Bit \"%s\" used multiple times.", type_bits->bits[u].name);
-                    goto cleanup;
-                }
-                goto next;
+        /* looking for correct name */
+        item_present = 0;
+        LY_ARRAY_FOR(type_bits->bits, it) {
+            if (!ly_strncmp(type_bits->bits[it].name, item, item_len)) {
+                item_present = 1;
+                item_present_index = it;
             }
         }
-        /* item not found */
-        ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid bit value \"%.*s\".", (int)item_len, item);
-        goto cleanup;
-next:
-        /* remember for canonized form: item + space/termination-byte */
-        buf_size += item_len + 1;
-        index += item_len;
-    }
-    /* validation done */
 
-    if (iscanonical) {
-        /* items are already ordered */
-        items_ordered = items;
-        items = NULL;
-
-        if (!ws_count && !lws_count && (options & LY_TYPE_STORE_DYNAMIC)) {
-            ret = lydict_insert_zc(ctx, (char *)value, &can);
-            value = NULL;
-            options &= ~LY_TYPE_STORE_DYNAMIC;
-            LY_CHECK_GOTO(ret, cleanup);
-        } else {
-            ret = lydict_insert(ctx, value_len ? &value[lws_count] : "", value_len - ws_count - lws_count, &can);
-            LY_CHECK_GOTO(ret, cleanup);
-        }
-    } else {
-        buf = malloc(buf_size * sizeof *buf);
-        if (!buf) {
-            ret = ly_err_new(err, LY_EMEM, 0, NULL, NULL, LY_EMEM_MSG);
+        /* check if name exists */
+        if (!item_present) {
+            ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL,
+                    "Invalid bit value \"%.*s\".", (int)item_len, item);
             goto cleanup;
         }
-        index = 0;
 
-        ret = ly_set_dup(items, NULL, &items_ordered);
+        /* add item to set */
+        item_pos_expected = items->count;
+        ret = ly_set_add(items, &type_bits->bits[item_present_index], 0, &item_pos);
         LY_CHECK_GOTO(ret, cleanup);
-        items_ordered->count = 0;
+        if (item_pos != item_pos_expected) {
+            ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL,
+                    "Bit \"%s\" used multiple times.", type_bits->bits[item_present_index].name);
+            goto cleanup;
+        }
+        /* count require buff size */
+        buf_len += item_len + 1;
+    }
 
-        /* generate ordered bits list */
-        LY_ARRAY_FOR(type_bits->bits, u) {
-            if (ly_set_contains(items, &type_bits->bits[u], NULL)) {
-                int c = sprintf(&buf[index], "%s%s", index ? " " : "", type_bits->bits[u].name);
-                if (c < 0) {
-                    ret = ly_err_new(err, LY_ESYS, 0, NULL, NULL, "sprintf() failed.");
-                    goto cleanup;
+
+    /* creating buffer for cannonical value */
+    if (buf_len != 0) {
+        uint32_t buf_index = 0;
+        LY_ARRAY_COUNT_TYPE it;
+
+        /* create space for cannonical value and array for bits*/
+        buf = malloc(buf_len * sizeof *buf);
+        if (buf == NULL) {
+            ret = LY_EMEM;
+            LOGMEM(ctx);
+            goto cleanup;
+        }
+        LY_ARRAY_CREATE_GOTO(ctx, bits_items, items->count, ret, cleanup);
+
+        /* generate ordered bits list and cannonical value*/
+        LY_ARRAY_FOR(type_bits->bits, it) {
+            if (ly_set_contains(items, &type_bits->bits[it], NULL)) {
+                uint32_t name_index = 0;
+
+                /* write space */
+                if (buf_index != 0) {
+                    buf[buf_index] = ' ';
+                    buf_index++;
                 }
-                index += c;
-                ret = ly_set_add(items_ordered, &type_bits->bits[u], 1, NULL);
-                LY_CHECK_GOTO(ret, cleanup);
+
+                /* write bit name*/
+                while (type_bits->bits[it].name[name_index]) {
+                    buf[buf_index] = type_bits->bits[it].name[name_index];
+                    buf_index++;
+                    name_index++;
+                }
+
+                bits_items[LY_ARRAY_COUNT(bits_items)] = &type_bits->bits[it];
+                LY_ARRAY_INCREMENT(bits_items);
             }
         }
-        assert(buf_size == index + 1);
-        /* termination NULL-byte */
-        buf[index] = '\0';
+        buf[buf_index] = 0;
 
-        ret = lydict_insert_zc(ctx, buf, &can);
+        ret = lydict_insert_zc(ctx, buf, &storage->canonical);
+        buf = NULL;
+        LY_CHECK_GOTO(ret, cleanup);
+    } else {
+        bits_items = NULL;
+        ret = lydict_insert(ctx, "", 0, &storage->canonical);
         buf = NULL;
         LY_CHECK_GOTO(ret, cleanup);
     }
 
-    /* store all data */
-    storage->canonical = can;
-    can = NULL;
-    LY_ARRAY_CREATE_GOTO(ctx, storage->bits_items, items_ordered->count, ret, cleanup);
-    for (uint32_t x = 0; x < items_ordered->count; x++) {
-        storage->bits_items[x] = items_ordered->objs[x];
-        LY_ARRAY_INCREMENT(storage->bits_items);
-    }
+    /* store value */
+    storage->bits_items = bits_items;
     storage->realtype = type;
 
-cleanup:
+    /* RETURN LY_SUCCESS */
     ly_set_free(items, NULL);
-    ly_set_free(items_ordered, NULL);
+    if (options & LY_TYPE_STORE_DYNAMIC) {
+        free((char *)value);
+    }
+    return LY_SUCCESS;
+
+    /* ERROR HANDLING */
+cleanup:
+    LY_ARRAY_FREE(bits_items);
     free(buf);
-    lydict_remove(ctx, can);
+    ly_set_free(items, NULL);
 cleanup_value:
     if (options & LY_TYPE_STORE_DYNAMIC) {
         free((char *)value);
@@ -184,17 +199,26 @@
 LY_ERR
 ly_type_dup_bits(const struct ly_ctx *ctx, const struct lyd_value *original, struct lyd_value *dup)
 {
+    LY_ERR ret = LY_SUCCESS;
     LY_ARRAY_COUNT_TYPE u;
+    struct lysc_type_bitenum_item **bits_items = NULL;
 
-    LY_ARRAY_CREATE_RET(ctx, dup->bits_items, LY_ARRAY_COUNT(original->bits_items), LY_EMEM);
+    LY_ARRAY_CREATE_RET(ctx, bits_items, LY_ARRAY_COUNT(original->bits_items), LY_EMEM);
     LY_ARRAY_FOR(original->bits_items, u) {
-        LY_ARRAY_INCREMENT(dup->bits_items);
-        dup->bits_items[u] = original->bits_items[u];
+        LY_ARRAY_INCREMENT(bits_items);
+        bits_items[u] = original->bits_items[u];
     }
 
-    LY_CHECK_RET(lydict_insert(ctx, original->canonical, strlen(original->canonical), &dup->canonical));
+    ret = lydict_insert(ctx, original->canonical, strlen(original->canonical), &dup->canonical);
+    LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
+    dup->bits_items = bits_items;
     dup->realtype = original->realtype;
     return LY_SUCCESS;
+
+    /* ERROR HANDLING */
+cleanup:
+    LY_ARRAY_FREE(bits_items);
+    return ret;
 }
 
 /**