diff --git a/core/include/dap_common.h b/core/include/dap_common.h
index 264f351ca59c5fb4a1e14806ad9e48a0d95d6c8b..e5a03fbaa7ec8fb93f4c7ed5bbc83fff92582ea4 100755
--- a/core/include/dap_common.h
+++ b/core/include/dap_common.h
@@ -755,7 +755,7 @@ void dap_set_log_tag_width(size_t width);
 const char * dap_get_appname();
 void dap_set_appname(const char * a_appname);
 
-char *dap_itoa(int i);
+char *dap_itoa(long long i);
 
 unsigned dap_gettid();
 
diff --git a/core/include/dap_config.h b/core/include/dap_config.h
old mode 100755
new mode 100644
index 41cab495498aa73cf079294010ad70f31ab1e7e4..92156d75555559f9e42b7c15d704de2bab144f02
--- a/core/include/dap_config.h
+++ b/core/include/dap_config.h
@@ -1,89 +1,77 @@
-/*
- * Authors:
- * Dmitriy A. Gearasimov <kahovski@gmail.com>
- * Anatolii Kurotych <akurotych@gmail.com>
- * DeM Labs Inc.   https://demlabs.net
- * DeM Labs Open source community https://gitlab.demlabs.net/cellframe
- * Copyright  (c) 2017-2019
- * All rights reserved.
-
- This file is part of DAP (Deus Applications Prototypes) the open source project
-
-    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _DAP_CONFIG_H_
-#define _DAP_CONFIG_H_
+#pragma once
 
 #include <stdbool.h>
 #include <stdint.h>
+#include "uthash.h"
+
+typedef struct dap_conf {
+    char *path;
+    struct dap_config_item {
+        char type, *name;
+        union dap_config_val {
+            bool        val_bool;
+            char        *val_str;
+            char        **val_arr;
+            int64_t     val_int;
+            uint64_t    val_uint;
+        } val;
+        UT_hash_handle hh;
+    } *items;
+    UT_hash_handle hh;
+} dap_config_t;
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-typedef struct dap_config{
-    void * _internal;
-} dap_config_t;
-
-int dap_config_init(const char * a_configs_path);
-void dap_config_deinit();
-dap_config_t * dap_config_open(const char * a_name);
-dap_config_t * dap_config_load(const char * a_file_path);
-void dap_config_close(dap_config_t * a_config);
+#if 0
+extern dap_config_t *g_configs_table;
+#endif
+extern dap_config_t *g_config;
 
-const char * dap_config_path();
+int dap_config_init(const char*);
+dap_config_t *dap_config_open(const char*);
 
-uint16_t dap_config_get_item_uint16(dap_config_t * a_config, const char * a_section_path, const char * a_item_name);
-uint16_t dap_config_get_item_uint16_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, uint16_t a_default);
+void dap_config_close(dap_config_t*);
+void dap_config_deinit();
 
-int16_t dap_config_get_item_int16(dap_config_t * a_config, const char * a_section_path, const char * a_item_name);
-int16_t dap_config_get_item_int16_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, int16_t a_default);
+const char *dap_config_path();
 
-uint32_t dap_config_get_item_uint32(dap_config_t * a_config, const char * a_section_path, const char * a_item_name);
-uint32_t dap_config_get_item_uint32_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, uint32_t a_default);
+bool dap_config_get_item_bool_default(dap_config_t *a_config, const char *a_section, const char *a_item_name, bool a_default);
+int64_t _dap_config_get_item_int(dap_config_t *a_config, const char *a_section, const char *a_item_name, int64_t a_default);
+uint64_t _dap_config_get_item_uint(dap_config_t *a_config, const char *a_section, const char *a_item_name, uint64_t a_default);
+const char *dap_config_get_item_str_default(dap_config_t *a_config, const char *a_section, const char *a_item_name, const char *a_default);
+const char *dap_config_get_item_str_path_default(dap_config_t *a_config, const char *a_section, const char *a_item_name, const char *a_default);
+char** dap_config_get_array_str(dap_config_t *a_config, const char *a_section, const char *a_item_name, uint16_t *array_length);
+double dap_config_get_item_double_default(dap_config_t *a_config, const char *a_section, const char *a_item_name, double a_default);
 
-int32_t dap_config_get_item_int32(dap_config_t * a_config, const char * a_section_path, const char * a_item_name);
-int32_t dap_config_get_item_int32_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, int32_t a_default);
+#define dap_config_get_item_bool(a_conf, a_path, a_item) dap_config_get_item_bool_default(a_conf, a_path, a_item, false)
 
-int64_t dap_config_get_item_int64(dap_config_t * a_config, const char * a_section_path, const char * a_item_name);
-int64_t dap_config_get_item_int64_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, int64_t a_default);
+#define dap_config_get_item_str(a_conf, a_path, a_item) dap_config_get_item_str_default(a_conf, a_path, a_item, NULL)
 
-uint64_t dap_config_get_item_uint64(dap_config_t * a_config, const char * a_section_path, const char * a_item_name);
-uint64_t dap_config_get_item_uint64_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, uint64_t a_default);
+#define dap_config_get_item_uint16(a_conf, a_path, a_item) (uint16_t)_dap_config_get_item_uint(a_conf, a_path, a_item, 0)
+#define dap_config_get_item_uint16_default(a_conf, a_path, a_item, a_default) (uint16_t)_dap_config_get_item_uint(a_conf, a_path, a_item, a_default)
 
-const char * dap_config_get_item_str(dap_config_t * a_config, const char * a_section_path, const char * a_item_name);
-const char * dap_config_get_item_str_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, const char * a_value_default);
+#define dap_config_get_item_int16(a_conf, a_path, a_item) (int16_t)_dap_config_get_item_int(a_conf, a_path, a_item, 0)
+#define dap_config_get_item_int16_default(a_conf, a_path, a_item, a_default) (int16_t)_dap_config_get_item_int(a_conf, a_path, a_item, a_default)
 
-const char * dap_config_get_item_path(dap_config_t * a_config, const char * a_section_path, const char * a_item_name);
-const char * dap_config_get_item_path_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, const char * a_value_default);
+#define dap_config_get_item_uint32(a_conf, a_path, a_item) (uint32_t)_dap_config_get_item_uint(a_conf, a_path, a_item, 0)
+#define dap_config_get_item_uint32_default(a_conf, a_path, a_item, a_default) (uint32_t)_dap_config_get_item_uint(a_conf, a_path, a_item, a_default)
 
-char** dap_config_get_array_str(dap_config_t * a_config, const char * a_section_path,
-                                      const char * a_item_name, uint16_t * array_length);
+#define dap_config_get_item_int32(a_conf, a_path, a_item) (int32_t)_dap_config_get_item_int(a_conf, a_path, a_item, 0)
+#define dap_config_get_item_int32_default(a_conf, a_path, a_item, a_default) (int32_t)_dap_config_get_item_int(a_conf, a_path, a_item, a_default)
 
-bool dap_config_get_item_bool(dap_config_t * a_config, const char * a_section_path, const char * a_item_name);
-bool dap_config_get_item_bool_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, bool a_default);
+#define dap_config_get_item_uint64(a_conf, a_path, a_item) (uint64_t)_dap_config_get_item_uint(a_conf, a_path, a_item, 0)
+#define dap_config_get_item_uint64_default(a_conf, a_path, a_item, a_default) (uint64_t)_dap_config_get_item_uint(a_conf, a_path, a_item, a_default)
 
-double dap_config_get_item_double(dap_config_t * a_config, const char * a_section_path, const char * a_item_name);
-double dap_config_get_item_double_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, double a_default);
+#define dap_config_get_item_int64(a_conf, a_path, a_item) (int64_t)_dap_config_get_item_int(a_conf, a_path, a_item, 0)
+#define dap_config_get_item_int64_default(a_conf, a_path, a_item, a_default) (int64_t)_dap_config_get_item_int(a_conf, a_path, a_item, a_default)
 
-extern dap_config_t * g_config;
+#define dap_config_get_item_path(a_conf, a_path, a_item) dap_config_get_item_str_path_default(a_conf, a_path, a_item, NULL)
+#define dap_config_get_item_path_default(a_conf, a_path, a_item, a_default) dap_config_get_item_str_path_default(a_conf, a_path, a_item, a_default)
 
+#define dap_config_get_item_double(a_conf, a_path, a_item) dap_config_get_item_double_default(a_conf, a_path, a_item, 0)
 
 #ifdef __cplusplus
 }
 #endif
-
-
-#endif
diff --git a/core/include/dap_strfuncs.h b/core/include/dap_strfuncs.h
index 3caab32c413ede5a73b6e9bd68612df72ce2c76c..ec61ce3f0d9af4f12f55b0fe294e17b8ce0f715b 100755
--- a/core/include/dap_strfuncs.h
+++ b/core/include/dap_strfuncs.h
@@ -45,7 +45,12 @@ char *dap_strjoin(const char *a_separator, ...);
 char** dap_strsplit(const char *a_string, const char *a_delimiter, int a_max_tokens);
 size_t dap_str_countv(char **a_str_array);
 size_t dap_str_symbol_count(const char *a_str, char a_sym);
+<<<<<<< HEAD
 
+=======
+char **dap_str_appv(char **a_dst, char **a_src, size_t *a_count);
+char *dap_str_remove_spaces(char *a_str);
+>>>>>>> 93a0e7cc (Feature 10079)
 // copies a NULL-terminated array of strings
 char** dap_strdupv(const char **a_str_array);
 // frees the array itself and all of its strings.
diff --git a/core/src/dap_common.c b/core/src/dap_common.c
index 0b53b5062920e8f5d632ebdaab4e5eb69ddc9ab1..1f7c1fde98adc0ef9144f0a61ea4d1cdd618a5a5 100755
--- a/core/src/dap_common.c
+++ b/core/src/dap_common.c
@@ -664,10 +664,10 @@ const char *log_error()
  * @param[in] i number
  * @return
  */
-char *dap_itoa(int i)
+char *dap_itoa(long long i)
 {
     /* Room for INT_DIGITS digits, - and '\0' */
-    static char buf[INT_DIGITS + 2];
+    static _Thread_local char buf[INT_DIGITS + 2];
     char *p = buf + INT_DIGITS + 1; /* points to terminating '\0' */
     if (i >= 0) {
         do {
diff --git a/core/src/dap_config.c b/core/src/dap_config.c
old mode 100755
new mode 100644
index 5e6adfb8089c6653a53763dc812b2d10d74d6f7e..d86095a627c5d6557a88d28b9259f2974f0ef8f8
--- a/core/src/dap_config.c
+++ b/core/src/dap_config.c
@@ -1,767 +1,539 @@
-#include <stdio.h>
 #include <string.h>
-
 #include <errno.h>
-#include <ctype.h>
-#include "dap_file_utils.h"
-#include "uthash.h"
-#include "dap_common.h"
+#include <stdint.h>
 #include "dap_config.h"
+#include "uthash.h"
+#include "dap_strfuncs.h"
+#include "dap_file_utils.h"
+#ifdef DAP_OS_WINDOWS
+#include "dap_list.h"
+#endif
 
 #define LOG_TAG "dap_config"
 
-dap_config_t * g_config = NULL;
-
-/**
- * @brief The dap_config_item struct
- */
-typedef struct dap_config_item{
-    char name[64];
-    struct dap_config_item * childs;
-    struct dap_config_item * item_next;
-    union{
-        char *data_str;
-        uint8_t data_uint8;
-        bool data_bool;
-        double data_double;
-        int32_t data_int32;
-        struct {
-            char **data_str_array;
-            uint16_t array_length;
-        };
-    };
-    bool is_array;
-    UT_hash_handle hh;
-} dap_config_item_t;
-
-
-typedef struct dap_config_internal
-{
-    dap_config_item_t * item_root;
-    char * path;
-} dap_config_internal_t;
-#define DAP_CONFIG_INTERNAL(a) ( (dap_config_internal_t* ) a->_internal )
+//dap_config_t *g_configs_table = NULL;
+
+typedef struct dap_config_item dap_config_item_t;
 
-#define MAX_CONFIG_PATH 256
-static char s_configs_path[MAX_CONFIG_PATH] = "/opt/dap/etc";
+static char *s_configs_path = NULL;
+dap_config_t *g_config = NULL;
 
+static bool debug_config = false;
 
-/**
- * @brief dap_config_init Initialization settings
- * @param[in] a_configs_path If NULL path is set to default
- * @return
- */
-int dap_config_init(const char * a_configs_path)
+int dap_config_init(const char *a_configs_path)
 {
-    if( a_configs_path ) {
-#ifdef _WIN32
-        // Check up under Windows, in Linux is not required
-        if(!dap_valid_ascii_symbols(a_configs_path)) {
-            log_it(L_ERROR, "Supported only ASCII symbols for directory path");
-            return -1;
-        }
+    if (!a_configs_path || !a_configs_path[0]) {
+        log_it(L_ERROR, "Empty path!");
+        return -1;
+    }
+#ifdef DAP_OS_WINDOWS
+    // Check up under Windows, in Linux is not required
+    if(!dap_valid_ascii_symbols(a_configs_path)) {
+        log_it(L_ERROR, "Supported only ASCII symbols for directory path");
+        return -1;
+    }
 #endif
-        if(dap_dir_test(a_configs_path) || !dap_mkdir_with_parents(a_configs_path)) {
-            strncpy(s_configs_path, a_configs_path,sizeof(s_configs_path)-1);
-            return 0;
-        }
+    if(dap_dir_test(a_configs_path) || !dap_mkdir_with_parents(a_configs_path)) {
+        DAP_DEL_Z(s_configs_path);
+        s_configs_path = dap_strdup(a_configs_path);
+        return 0;
+    } else {
+        log_it(L_ERROR, "Invalid path %s!", a_configs_path);
+        return -2;
     }
-    return -1;
 }
 
-const char * dap_config_path()
+const char *dap_config_path()
 {
     return s_configs_path;
 }
 
-
-/**
- * @brief dap_config_deinit Deinitialize settings
- */
-void dap_config_deinit()
-{
-
+#define dap_config_item_del(a_item)         \
+{                                           \
+    DAP_DELETE(a_item->name);               \
+    switch (a_item->type) {                 \
+    case 's':                               \
+        DAP_DELETE(a_item->val.val_str);    \
+        break;                              \
+    case 'a':                               \
+        dap_strfreev(a_item->val.val_arr);  \
+        break;                              \
+    default:                                \
+        break;                              \
+    }                                       \
+    DAP_DELETE(a_item);                     \
 }
 
-
-/**
- * @brief get_array_length Function parse string and return array length
- * @param[in] value
- * @details internal function parse string and return array length
- * @return
- */
-static uint16_t get_array_length(const char* str) {
-    uint16_t array_length = 1; // by default if not find ','
-    while (*str) {
-        if (*str == ',')
-            array_length++;
-        str++;
+void dap_config_dump(dap_config_t *a_conf) {
+    dap_config_item_t *l_item = NULL, *l_tmp = NULL;
+    log_it(L_DEBUG, " Config %s", a_conf->path);
+    HASH_ITER(hh, a_conf->items, l_item, l_tmp) {
+        switch (l_item->type) {
+        case 's':
+            log_it(L_DEBUG, " String param: %s = %s", l_item->name, l_item->val.val_str);
+            break;
+        case 'd':
+            log_it(L_DEBUG, " Int param: %s = %ld", l_item->name, l_item->val.val_int);
+            break;
+        case 'u':
+            log_it(L_DEBUG, " UInt param: %s = %lu", l_item->name, l_item->val.val_uint);
+            break;
+        case 'b':
+            log_it(L_DEBUG, " Bool param: %s = %d", l_item->name, l_item->val.val_bool);
+            break;
+        case 'a': {
+            log_it(L_DEBUG, " Array param: %s = ", l_item->name);
+            for (char **l_str = l_item->val.val_arr; *l_str; ++l_str) {
+                log_it(L_DEBUG, " %s", *l_str);
+            }
+            break;
+        }
+        }
     }
-    return array_length;
 }
-/**
- * @brief dap_config_open Open the configuration settings
- * @param[in] a_name Configuration name
- * @return dap_config_t Configuration
- */
-dap_config_t * dap_config_open(const char * a_name)
-{
-    dap_config_t * l_ret = NULL;
-    if ( a_name ){
-        log_it(L_DEBUG,"Looking for config name %s...",a_name);
-        size_t l_config_path_size_max = strlen(a_name)+6+strlen(s_configs_path);
-        char *l_config_path = DAP_NEW_Z_SIZE(char,l_config_path_size_max);
-        snprintf(l_config_path,l_config_path_size_max, "%s/%s.cfg",s_configs_path,a_name);
-        l_ret = dap_config_load(l_config_path);
-//        DAP_DELETE(l_config_path);
-    }else{
-        log_it(L_ERROR,"Config name is NULL");
-    }
-    return l_ret;
+
+#ifdef DAP_OS_WINDOWS
+static int s_name_sort_cb(const void *a_str1, const void *a_str2) {
+    char    *l_str1 = (char*)((dap_list_t*)a_str1)->data,
+            *l_str2 = (char*)((dap_list_t*)a_str2)->data;
+    return dap_strcmp(l_str1, l_str2);
 }
+#endif
 
-/**
- * @brief Load config from file
- * @param a_file_path
- * @return
- */
-dap_config_t * dap_config_load(const char * a_file_path)
-{
-    dap_config_t * l_ret = NULL;
-
-    FILE * f = fopen(a_file_path,"r");
-    if ( f ){
-        fseek(f, 0, SEEK_END);
-        long buf_len = ftell(f);
-        char buf[buf_len];
-        fseek(f, 0L, SEEK_SET);
-        log_it(L_DEBUG,"Opened config %s",a_file_path);
-        l_ret = DAP_NEW_Z(dap_config_t);
-        if (!l_ret) {
-            log_it(L_CRITICAL, "Memory allocation error");
-            fclose(f);
-            return NULL;
+static int _dap_config_load(const char* a_abs_path, dap_config_t **a_conf) {
+    if (!a_conf || !*a_conf) {
+        log_it(L_ERROR, "Config is not initialized");
+        return 1;
+    }
+    FILE *f = fopen(a_abs_path, "r");
+    if (!f) {
+        log_it(L_ERROR, "Can't open config file \"%s\", error %d", a_abs_path, errno);
+        return 2;
+    }
+#define MAX_CONFIG_LINE_LEN 1024
+    unsigned l_len = MAX_CONFIG_LINE_LEN, l_shift = 0;
+    log_it(L_DEBUG, "Opened config %s", a_abs_path);
+
+    char    *l_line = DAP_NEW_Z_SIZE(char, l_len),
+            *l_section = NULL;
+    dap_config_item_t *l_item = NULL;
+    char l_type = '\0', *l_key_for_arr = NULL, **l_values_arr = NULL;
+    for (uint16_t l_line_counter = 0, l_line_counter2 = 0; fgets(l_line + l_shift, MAX_CONFIG_LINE_LEN, f); ++l_line_counter) {
+        if (!l_shift)
+            l_line = DAP_REALLOC(l_line, MAX_CONFIG_LINE_LEN);
+        unsigned l_eol = strcspn(l_line + l_shift, "\r\n") + l_shift;
+        if (l_eol == l_len - 1) {
+            if (l_line_counter != l_line_counter2) {
+                log_it(L_WARNING, "Config \"%s\": line %d is too long, preserving the tail ...", a_abs_path, l_line_counter);
+            }
+            l_line_counter2 = l_line_counter--;
+            l_shift = l_eol;
+            l_len += (MAX_CONFIG_LINE_LEN - 1);
+            l_line = DAP_REALLOC(l_line, l_len);
+            continue;
         }
-        dap_config_internal_t * l_config_internal = DAP_NEW_Z(dap_config_internal_t);
-        if (!l_config_internal) {
-            log_it(L_CRITICAL, "Memory allocation error");
-            fclose(f);
-            DAP_DELETE(l_ret);
-            return NULL;
+        if (l_shift) {
+            l_len = MAX_CONFIG_LINE_LEN;
+            l_shift = 0;
         }
-        l_config_internal->path = (char*)a_file_path;
-        l_ret->_internal = l_config_internal;
-        size_t l_global_offset=0;
-        size_t l_buf_size=0;
-        size_t l_buf_pos_line_start=0;
-        size_t l_buf_pos_line_end=0;
-        dap_config_item_t * l_section_current = NULL ;
-        bool l_is_space_now = false;
-        while ( feof(f)==0){ // Break on lines
-            size_t i;
-            l_global_offset +=  (l_buf_size = fread(buf, 1, buf_len, f) );
-            for (i=0; i< l_buf_size; i++){
-                if( (buf[i] == '\r') || (buf[i] == '\n' ) ){
-                    if( ! l_is_space_now){
-                        l_buf_pos_line_end = i;
-                        l_is_space_now = true;
-                        //if(l_buf_pos_line_end)
-                        //    l_buf_pos_line_end--;
-                        if(l_buf_pos_line_end != l_buf_pos_line_start ){ // Line detected
-                            char *l_line = NULL;
-                            uint32_t l_line_length = 0;
-                            size_t j;
-
-                            // Trimming spaces and skip the line if commented
-                            for ( j = l_buf_pos_line_start; j < l_buf_pos_line_end; j++ ){
-                                if ( buf[j] == '#' )
-                                    break;
-                                if (buf[j] != ' ' ){
-                                    l_line_length = (l_buf_pos_line_end - j);
-                                    break;
-                                }
-                            }
-                            if( l_line_length ){
-                                l_line = DAP_NEW_SIZE(char,l_line_length+1);
-                                if (!l_line) {
-                                    log_it(L_CRITICAL, "Memory allocation error");
-                                    DAP_DEL_Z(l_config_internal);
-                                    DAP_DELETE(l_ret);
-                                    fclose(f);
-                                    return NULL;
-                                }
-                                memcpy(l_line,buf+j,l_line_length);
-                                l_line[l_line_length] = 0;
-
-                                // Process trimmed line
-                                if( (l_line[0] == '[' ) && (l_line[l_line_length-1] == ']' ) ){ // Section detected
-                                    //log_it(L_DEBUG, "Raw line '%s'",l_line);
-                                    char * l_section_name = strdup(l_line+1);
-                                    if (!l_section_name) {
-                                        log_it(L_CRITICAL, "Memory allocation error");
-                                        DAP_DEL_Z(l_config_internal);
-                                        DAP_DELETE(l_line);
-                                        DAP_DELETE(l_ret);
-                                        fclose(f);
-                                        return NULL;
-                                    }
-                                    size_t l_section_name_length = (l_line_length - 2);
-                                    l_section_name[l_section_name_length]='\0';
-                                    // log_it(L_DEBUG,"Config section '%s'",l_section_name);
-
-                                    dap_config_item_t * l_item_section = DAP_NEW_Z(dap_config_item_t);
-                                    if(!l_item_section) {
-                                        log_it(L_CRITICAL, "Memory allocation error");
-                                        free(l_section_name);
-                                        DAP_DEL_Z(l_config_internal);
-                                        DAP_DELETE(l_line);
-                                        DAP_DELETE(l_ret);
-                                        fclose(f);
-                                        return NULL;
-                                    }
-                                    strncpy(l_item_section->name,l_section_name,sizeof(l_item_section->name)-1);
-                                    l_item_section->item_next = l_config_internal->item_root;
-                                    l_config_internal->item_root = l_item_section;
-                                    free(l_section_name);
-
-                                    l_section_current = l_item_section;
-                                }else{ // key-value line
-                                    //log_it(L_DEBUG,"Read line '%s'",l_line);
-                                    char l_param_name[sizeof(l_section_current->name)];
-                                    size_t l_param_name_size=0;
-                                    size_t l_param_value_size=0;
-                                    char l_param_value[262144];
-                                    l_param_name[0] = 0;
-                                    l_param_value[0] = 0;
-                                    for ( j = 0; j < l_line_length; j++ ){ // Parse param name
-                                        if ( ( l_line[j] == ' ' )|| ( l_line[j] == '=' ) ||( l_line[j] == '\t' ) ){ // Param name
-                                            l_param_name_size = j;
-                                            if (l_param_name_size > (sizeof(l_param_name) -1) ){
-                                                l_param_name_size = (sizeof(l_param_name) - 1 );
-                                                log_it(L_WARNING,"Too long param name in config, %zu is more than %zu maximum",
-                                                       j,sizeof(l_param_name) -1);
-                                            }
-                                            strncpy(l_param_name,l_line,j);
-                                            l_param_name[j] = 0;
-                                            break;
-                                        }
-
-                                    }
-
-                                    for (; j < l_line_length; j++ ){ // Find beginning of param value
-                                        if ( ( l_line[j] != '\t' ) && ( l_line[j] != ' ' ) && ( l_line[j] != '=' ) ){
-                                            break;
-                                        }
-                                    }
-                                    l_param_value_size = l_line_length - j;
-                                    if (l_param_value_size ){
-                                        if (l_param_value_size > (sizeof(l_param_value) -1) ){
-                                            l_param_value_size = (sizeof(l_param_value) - 1 );
-                                            log_it(L_WARNING,"Too long param value in config, %zu is more than %zu maximum",
-                                                   l_line_length - j,sizeof(l_param_value) -1);
-                                        }
-                                        strncpy(l_param_value,l_line +j, l_param_value_size);
-                                        l_param_value[l_param_value_size] = '\0';
-                                        for(int j=(int)l_param_value_size-1; j>=0; j--){
-                                            if( (l_param_value[j] ==' ') || (l_param_value[j] =='\t') ){
-                                                l_param_value[j] = '\0';
-                                            }else{
-                                                break;
-                                            }
-                                        }
-                                    }
-                                //    log_it(L_DEBUG,"  Param '%s' = '%s'", l_param_name, l_param_value);
-                                    if (l_section_current){
-
-                                        if (l_param_value[0] == '[') {
-                                            if(l_param_value[1] == ']') {
-                                                //log_it(L_WARNING, "Empty array!");
-                                                DAP_DELETE(l_line);
-                                                continue;
-                                            }
-
-                                            // delete '[' and ']'
-                                            char* values = l_param_value + 1;
-                                            values[l_param_value_size-2] = 0;
-
-                                            dap_config_item_t * l_item = DAP_NEW_Z(dap_config_item_t);
-                                            if (!l_item) {
-                                                log_it(L_CRITICAL, "Memory allocation error");
-                                                DAP_DEL_Z(l_config_internal);
-                                                DAP_DELETE(l_line);
-                                                DAP_DELETE(l_ret);
-                                                fclose(f);
-                                                return NULL;
-                                            }
-                                            strncpy(l_item->name,l_param_name,sizeof(l_item->name));
-                                            l_item->item_next = l_section_current->childs;
-                                            l_item->is_array = true;
-                                            l_section_current->childs = l_item;
-                                            l_item->array_length = get_array_length(l_param_value);
-                                            l_item->data_str_array = (char**) malloc (sizeof(char*) * l_item->array_length);
-                                            if (!l_item->data_str_array) {
-                                                log_it(L_CRITICAL, "Memory allocation error");
-                                                DAP_DEL_Z(l_config_internal);
-                                                DAP_DELETE(l_item);
-                                                DAP_DELETE(l_line);
-                                                DAP_DELETE(l_ret);
-                                                fclose(f);
-                                                return NULL;
-                                            }
-                                            // parsing items in array
-                                            int j = 0;
-                                            char * l_tmp = NULL;
-                                            char *token = strtok_r(values, ",",&l_tmp);
-                                            while(token) {
-
-                                                // trim token whitespace
-                                                if (isspace(token[0]))
-                                                    token = token + 1;
-                                                char *closer = strchr(token, ']');
-                                                if (closer) /* last item in array */
-                                                    *closer = 0;
-
-                                                l_item->data_str_array[j] = strdup(token);
-
-                                                token = strtok_r(NULL, ",",&l_tmp);
-                                                j++;
-                                            }
-                                            l_item->array_length = j;
-                                        } else {
-                                            dap_config_item_t * l_item = DAP_NEW_Z(dap_config_item_t);
-                                            if (!l_item) {
-                                                log_it(L_CRITICAL, "Memory allocation error");
-                                                DAP_DEL_Z(l_config_internal);
-                                                DAP_DELETE(l_line);
-                                                DAP_DELETE(l_ret);
-                                                fclose(f);
-                                                return NULL;
-                                            }
-
-                                            strncpy(l_item->name,l_param_name,sizeof(l_item->name));
-                                            l_item->item_next = l_section_current->childs;
-                                            l_item->data_str = strdup (l_param_value);
-
-                                            l_section_current->childs = l_item;
-                                        }
-                                    }else{
-                                        log_it(L_ERROR,"Can't add param to a tree without current section");
-                                    }
-
-                                }
-                                DAP_DELETE(l_line);
-                            }
-                        }
-                    }
-                    continue;
-                }else{
-                    if (l_is_space_now){
-                        l_is_space_now = false;
-                        l_buf_pos_line_start = i;
-                    }
+        l_eol = strcspn(l_line, "#\r\n");
+        l_line[l_eol] = '\0';
+        {
+            char *l_tmp = l_line, *l_tmp1 = l_line;
+            int l_shift = 0;
+            do {
+                while(isspace(*l_tmp1)) {
+                    ++l_tmp1;
+                    ++l_shift;
                 }
+            } while((*l_tmp++ = *l_tmp1++));
+        }
+        unsigned l_stripped_len = strlen(l_line);
+        if (!l_stripped_len) {
+            // No useful data remained
+            continue;
+        }
+        char *l_key = NULL, *l_val = NULL;
+        if (!l_values_arr) {
+            --l_stripped_len;
+            if (l_line[0] == '[' && l_line[l_stripped_len] == ']') {
+                // A section start
+                l_line[l_stripped_len] = '\0';
+                DAP_DEL_Z(l_section);
+                l_section = dap_strdup(l_line + 1);
+                continue;
+            } else if (!l_section) {
+                log_it(L_WARNING, "Config \"%s\": line %d belongs to unknown section. Dump it",
+                       a_abs_path, l_line_counter);
+                continue;
+            }
+            if (!strchr(l_line, '=')) {
+                log_it(L_WARNING, "Config \"%s\": unknown pattern on line %d, dump it",
+                       a_abs_path, l_line_counter);
+                continue;
             }
+            l_key = strtok_r(l_line, "=", &l_val);
+        } else {
+            l_val = l_line;
         }
-        fclose(f);
-    }else{
-        log_it(L_ERROR,"Can't open config file '%s' (%s)",a_file_path,strerror(errno));
-    }
-    return l_ret;
-}
+        union dap_config_val l_item_val = { };
+        if (*l_val != '[' && !l_values_arr) {
+            // Single val
+            l_type = 'd';
+            if (!*l_val)
+                l_type = 'r';
+            else if (
+         #ifdef DAP_OS_WINDOWS
+                     !stricmp(l_val, "true")
+         #else
+                     !strcasecmp(l_val, "true")
+         #endif
+                     )
+                l_type = 1;
+            else if (
+         #ifdef DAP_OS_WINDOWS
+                     !stricmp(l_val, "false")
+         #else
+                     !strcasecmp(l_val, "false")
+         #endif
+                     )
+                l_type = 0;
+            else {
+                char *c;
+                if (*l_val == '-') {
+                    c = l_val + 1;
+                } else {
+                    c = l_val;
+                    l_type = 'u';
+                }
+                while (*c) {
+                    if (!isdigit(*c++)) {
+                        l_type = 's';
+                        break;
+                    }
+                }
+            }
+            switch (l_type) {
+            case 0:
+            case 1:
+                l_item_val.val_bool = l_type;
+                l_type = 'b';
+                break;
+            case 'd': {
+                l_item_val.val_int = strtoll(l_val, NULL, 10);
+                break;
+            }
+            case 'u':{
+                l_item_val.val_uint = strtoull(l_val, NULL, 10);
+                break;
+            }
+            case 's':
+                l_item_val.val_str = dap_strdup(l_val);
+                break;
+            default:
+                break;
+            }
+        } else {
+            // Array of strings
+            if (!l_values_arr)
+                ++l_val;
+            if (l_type != 'r') {
+                l_type = 'a';
+                int l_pos = dap_strlen(l_val) - 1;
+                char l_term = l_val[l_pos];
+                if (l_term == ']') {
+                    l_val[l_pos] = '\0';
+                }
+                char **l_vals = dap_strsplit(l_val, ",", -1);
+                if (!*l_vals) {
+                    l_type = 'r';
+                } else {
+                    l_values_arr = dap_str_appv(l_values_arr, l_vals, NULL);
+                }
 
-/**
- * @brief dap_config_close Closing the configuration
- * @param[in] a_config Configuration
- */
-void dap_config_close(dap_config_t * a_config)
-{
-    dap_config_item_t * l_item = DAP_CONFIG_INTERNAL(a_config)->item_root ;
-    while(l_item) {
-        dap_config_item_t * l_item_child = l_item->childs;
-        DAP_CONFIG_INTERNAL(a_config)->item_root = l_item->item_next;
-
-        while(l_item_child) {
-            l_item->childs = l_item_child->item_next;
-            if(l_item_child->is_array) {
-                for(int i = 0; i< l_item_child->array_length; i++)
-                    free(l_item_child->data_str_array[i]);
-                free(l_item_child->data_str_array);
-            } else if (l_item_child->data_str) {
-                DAP_DELETE(l_item_child->data_str);
+                DAP_DELETE(l_vals);
+                if (l_term != ']' || !l_values_arr) {
+                    if (!l_key_for_arr && l_key)
+                        l_key_for_arr = strdup(l_key);
+                    continue;
+                }
+                if (!dap_str_countv(l_values_arr))
+                    l_type = 'r';
             }
-            DAP_DELETE(l_item_child);
-            l_item_child = l_item->childs;
         }
 
-        if(l_item->data_str) {
-            DAP_DELETE(l_item->data_str);
+        char *l_name = dap_strdup_printf("%s:%s", l_section, l_key_for_arr ? l_key_for_arr : l_key);
+        DAP_DEL_Z(l_key_for_arr);
+        for (char *c = l_name; *c; ++c) {
+            if (*c == '-')
+                *c = '_';
+        }
+        HASH_FIND_STR((*a_conf)->items, l_name, l_item);
+
+        switch (l_type) {
+        case 'r':
+            if (l_item) {
+                DAP_DELETE(l_name);
+                HASH_DEL((*a_conf)->items, l_item);
+                dap_config_item_del(l_item);
+            }
+            dap_strfreev(l_values_arr);
+            l_values_arr = NULL;
+            break;
+        case 'a':
+            l_item_val.val_arr = dap_str_appv(l_item_val.val_arr, l_values_arr, NULL);
+            DAP_DEL_Z(l_values_arr);
+            if (l_item)
+                dap_strfreev(l_item->val.val_arr);
+        default:
+            if (!l_item) {
+                l_item = DAP_NEW_Z(dap_config_item_t);
+                l_item->name = l_name;
+                HASH_ADD_KEYPTR(hh, (*a_conf)->items, l_item->name, strlen(l_item->name), l_item);
+            } else {
+                DAP_DELETE(l_name);
+            }
+            l_item->type = l_type;
+            l_item->val = l_item_val;
+            break;
         }
-        DAP_DELETE(l_item);
-        l_item = DAP_CONFIG_INTERNAL(a_config)->item_root;
     }
-
-    free(DAP_CONFIG_INTERNAL(a_config)->path);
-    free(a_config->_internal);
-    free(a_config);
-
-}
-
-/**
- * @brief dap_config_get_item_int32 Getting a configuration item as a int32
- * @param[in] a_config
- * @param[in] a_section_path
- * @param[in] a_item_name
- * @return
- */
-int32_t dap_config_get_item_int32(dap_config_t * a_config, const char * a_section_path, const char * a_item_name)
-{
-    return atoi(dap_config_get_item_str(a_config,a_section_path,a_item_name));
+    DAP_DELETE(l_line);
+    fclose(f);
+    return 0;
 }
 
-/**
- * @brief dap_config_get_item_int64
- * @param a_config
- * @param a_section_path
- * @param a_item_name
- * @return
- */
-int64_t dap_config_get_item_int64(dap_config_t * a_config, const char * a_section_path, const char * a_item_name)
-{
-    return atoll(dap_config_get_item_str(a_config,a_section_path,a_item_name));
-}
-
-/**
- * @brief dap_config_get_item_uint64
- * @param a_config
- * @param a_section_path
- * @param a_item_name
- * @return
- */
-uint64_t dap_config_get_item_uint64(dap_config_t * a_config, const char * a_section_path, const char * a_item_name)
-{
-    return (uint64_t) atoll(dap_config_get_item_str(a_config,a_section_path,a_item_name));
-}
-
-/**
- * @brief dap_config_get_item_uint16
- * @param a_config
- * @param a_section_path
- * @param a_item_name
- * @return
- */
-uint16_t dap_config_get_item_uint16(dap_config_t * a_config, const char * a_section_path, const char * a_item_name)
-{
-    return (uint16_t) atoi(dap_config_get_item_str(a_config,a_section_path,a_item_name));
-}
+dap_config_t *dap_config_open(const char* a_file_path) {
+    if (!a_file_path || !a_file_path[0]) {
+        log_it(L_ERROR, "Empty config name!");
+        return NULL;
+    }
+    log_it(L_DEBUG, "Looking for config name %s...", a_file_path);
+    char l_path[MAX_PATH] = { '\0' };
+    int l_pos = dap_strncmp(a_file_path, s_configs_path, strlen(s_configs_path))
+            ? dap_snprintf(l_path, MAX_PATH, "%s/%s.cfg", s_configs_path, a_file_path)
+            : dap_snprintf(l_path, MAX_PATH, "%s.cfg", a_file_path);
+
+    if (l_pos >= MAX_PATH) {
+        log_it(L_ERROR, "Too long config name!");
+        return NULL;
+    }
 
-/**
- * @brief dap_config_get_item_int16
- * @param a_config
- * @param a_section_path
- * @param a_item_name
- * @return
- */
-int16_t dap_config_get_item_int16(dap_config_t * a_config, const char * a_section_path, const char * a_item_name)
-{
-    return (int16_t) atoi(dap_config_get_item_str(a_config,a_section_path,a_item_name));
+    int l_basic_len = strlen(l_path) - 4;
+    char *l_basic_name = dap_strdup_printf("%.*s", l_basic_len, l_path);
+#if 0
+    dap_config_t *l_conf = NULL;
+    HASH_FIND_STR(g_configs_table, l_basic_name, l_conf);
+    if (!l_conf) {
+        l_conf = DAP_NEW_Z(dap_config_t);
+        l_conf->path = l_basic_name;
+        HASH_ADD_KEYPTR(hh, g_configs_table, l_conf->path, l_basic_len, l_conf);
+    } else {
+        DAP_DELETE(l_basic_name);
+    }
+#endif
+    dap_config_t *l_conf = DAP_NEW_Z(dap_config_t);
+    l_conf->path = l_basic_name;
+    if (_dap_config_load(l_path, &l_conf))
+       return NULL;
+    debug_config = g_config ? dap_config_get_item_bool(g_config, "general", "debug-config") : false;
+
+    if (l_pos >= MAX_PATH - 3)
+        return l_conf;
+
+    strncpy(l_path + l_pos, ".d", 2);
+#ifdef DAP_OS_WINDOWS
+    DIR *l_dir = opendir(l_path);
+    if (!l_dir) {
+        log_it(L_DEBUG, "Cannot open directory %s", l_path);
+        if (debug_config)
+            dap_config_dump(l_conf);
+        return l_conf;
+    }
+    struct dirent *l_entry;
+    dap_list_t *l_filenames = NULL;
+    while ((l_entry = readdir(l_dir))) {
+        const char *l_filename = l_entry->d_name;
+        if (!strncmp(l_filename + strlen(l_filename) - 4, ".cfg", 4))
+            l_filenames = dap_list_append(l_filenames, dap_strdup(l_filename));
+    }
+    closedir(l_dir);
+    l_filenames = dap_list_sort(l_filenames, s_name_sort_cb);
+    for (dap_list_t *l_filename = l_filenames; l_filename; l_filename = l_filename->next) {
+        char *l_entry_file = dap_strdup_printf("%s/%s", l_path, (char*)l_filename->data);
+        _dap_config_load(l_entry_file, &l_conf);
+        DAP_DELETE(l_entry_file);
+    }
+    dap_list_free_full(l_filenames, NULL);
+#else
+    struct dirent **l_entries;
+    int l_err = scandir(l_path, &l_entries, 0, alphasort);
+    if (l_err < 0) {
+        log_it(L_DEBUG, "Cannot open directory %s", l_path);
+        if (debug_config)
+            dap_config_dump(l_conf);
+        return l_conf;
+    }
+    for (int i = 0; i < l_err; ++i) {
+        if (!strncmp(l_entries[i]->d_name + strlen(l_entries[i]->d_name) - 4, ".cfg", 4)) {
+            char *l_entry_file = dap_strdup_printf("%s/%s", l_path, l_entries[i]->d_name);
+            _dap_config_load(l_entry_file, &l_conf);
+            DAP_DELETE(l_entry_file);
+        }
+        DAP_DELETE(l_entries[i]);
+    }
+    DAP_DELETE(l_entries);
+#endif
+    if (debug_config)
+        dap_config_dump(l_conf);
+    return l_conf;
 }
 
-
-/**
- * @brief dap_config_get_item_int32_default Getting a configuration item as a int32
- * @param[in] a_config Configuration
- * @param[in] a_section_path Path
- * @param[in] a_item_name setting
- * @param[in] a_default
- * @return
- */
-int32_t dap_config_get_item_int32_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, int32_t a_default)
-{
-    const char * l_str_ret = dap_config_get_item_str(a_config,a_section_path,a_item_name);
-    return l_str_ret?atoi(l_str_ret):a_default;
+struct dap_config_item *dap_config_get_item(dap_config_t *a_config, const char *a_section, const char *a_item_name) {
+    char *l_key = dap_strdup_printf("%s:%s", a_section, a_item_name);
+    for (char *c = l_key; *c; ++c) {
+        if (*c == '-')
+            *c = '_';
+    }
+    struct dap_config_item *l_item = NULL;
+    HASH_FIND_STR(a_config->items, l_key, l_item);
+    if (!l_item) {
+        log_it(L_DEBUG, "Not found param \"%s\"", l_key);
+    }
+    DAP_DELETE(l_key);
+    return l_item;
 }
 
-/**
- * @brief dap_config_get_item_uint32_default
- * @param a_config
- * @param a_section_path
- * @param a_item_name
- * @param a_default
- * @return
- */
-uint32_t dap_config_get_item_uint32_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, uint32_t a_default)
-{
-    const char * l_str_ret = dap_config_get_item_str(a_config,a_section_path,a_item_name);
-    uint32_t l_ret = 0;
-    if (l_str_ret && sscanf(l_str_ret, "%u", &l_ret) == 1)
-        return l_ret;
-    else
+bool dap_config_get_item_bool_default(dap_config_t *a_config, const char *a_section, const char *a_item_name, bool a_default) {
+    dap_config_item_t *l_item = dap_config_get_item(a_config, a_section, a_item_name);
+    if (!l_item)
         return a_default;
+    if (l_item->type != 'b') {
+        log_it(L_ERROR, "Parameter \"%s\" '%c' is not bool", l_item->name, l_item->type);
+        return a_default;
+    }
+    return l_item->val.val_bool;
 }
 
-/**
- * @brief dap_config_get_item_uint32
- * @param a_config
- * @param a_section_path
- * @param a_item_name
- * @return
- */
-uint32_t dap_config_get_item_uint32(dap_config_t * a_config, const char * a_section_path, const char * a_item_name)
-{
-    const char * l_str_ret = dap_config_get_item_str(a_config,a_section_path,a_item_name);
-    uint32_t l_ret = 0;
-    if (l_str_ret)
-        sscanf(l_str_ret, "%u", &l_ret);
-    return l_ret;
-}
-
-/**
- * @brief dap_config_get_item_uint16_default
- * @param a_config
- * @param a_section_path
- * @param a_item_name
- * @param a_default
- * @return
- */
-uint16_t dap_config_get_item_uint16_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, uint16_t a_default)
-{
-    const char * l_str_ret = dap_config_get_item_str(a_config,a_section_path,a_item_name);
-    return l_str_ret? (uint16_t) atoi(l_str_ret):a_default;
-}
-
-/**
- * @brief dap_config_get_item_int16_default
- * @param a_config
- * @param a_section_path
- * @param a_item_name
- * @param a_default
- * @return
- */
-int16_t dap_config_get_item_int16_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, int16_t a_default)
-{
-    const char * l_str_ret = dap_config_get_item_str(a_config,a_section_path,a_item_name);
-    return l_str_ret? (int16_t) atoi(l_str_ret):a_default;
-}
-
-/**
- * @brief dap_config_get_item_int64_default
- * @param a_config
- * @param a_section_path
- * @param a_item_name
- * @param a_default
- * @return
- */
-int64_t dap_config_get_item_int64_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, int64_t a_default)
-{
-    const char * l_str_ret = dap_config_get_item_str(a_config,a_section_path,a_item_name);
-    return l_str_ret? (int64_t) atoll(l_str_ret):a_default;
-}
-
-/**
- * @brief dap_config_get_item_int64_default
- * @param a_config
- * @param a_section_path
- * @param a_item_name
- * @param a_default
- * @return
- */
-uint64_t dap_config_get_item_uint64_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, uint64_t a_default)
-{
-    const char * l_str_ret = dap_config_get_item_str(a_config,a_section_path,a_item_name);
-    return l_str_ret? (uint64_t) atoll(l_str_ret):a_default;
-}
-
-
-/**
- * @brief dap_config_get_item Get the configuration as a item
- * @param[in] a_config Configuration
- * @param[in] a_section_path Path
- * @param[in] a_item_name setting
- * @return
- */
-static dap_config_item_t * dap_config_get_item(dap_config_t * a_config, const char * a_section_path, const char * a_item_name)
-{
-    dap_config_item_t * l_item_section = a_config? DAP_CONFIG_INTERNAL(a_config)->item_root: NULL ;
-    while(l_item_section){
-        if (strcmp(l_item_section->name,a_section_path)==0){
-            dap_config_item_t * l_item = l_item_section->childs;
-            while (l_item){
-                if (strcmp(l_item->name,a_item_name)==0){
-                    return l_item;
-                }
-                l_item = l_item->item_next;
-            }
+int64_t _dap_config_get_item_int(dap_config_t *a_config, const char *a_section, const char *a_item_name, int64_t a_default) {
+    dap_config_item_t *l_item = dap_config_get_item(a_config, a_section, a_item_name);
+    if (!l_item)
+        return a_default;
+    switch (l_item->type) {
+    case 'd':
+        return l_item->val.val_int;
+    case 'u':
+        if (l_item->val.val_uint > INT64_MAX) {
+            log_it(L_WARNING, "Signed parameter \"%s\" requested, but the value %zu exeeds the limit", l_item->name, l_item->val.val_uint);
+            return a_default;
+        } else {
+            return (int64_t)l_item->val.val_uint;
         }
-        l_item_section = l_item_section->item_next;
+    default:
+        log_it(L_ERROR, "Parameter \"%s\" '%c' is not signed integer", l_item->name, l_item->type);
+        return a_default;
     }
-    return NULL;
 }
 
-
-/**
- * @brief dap_config_get_item_str Getting a configuration item as a string
- * @param[in] a_config Configuration
- * @param[in] a_section_path Path
- * @param[in] a_item_name setting
- * @return
- */
-const char * dap_config_get_item_str(dap_config_t * a_config, const char * a_section_path, const char * a_item_name)
-{
-    dap_config_item_t * item = dap_config_get_item(a_config, a_section_path, a_item_name);
-
-    return  (!item) ?  NULL : item->data_str;
+uint64_t _dap_config_get_item_uint(dap_config_t *a_config, const char *a_section, const char *a_item_name, uint64_t a_default) {
+    dap_config_item_t *l_item = dap_config_get_item(a_config, a_section, a_item_name);
+    if (!l_item)
+        return a_default;
+    switch (l_item->type) {
+    case 'u':
+        return l_item->val.val_uint;
+    case 'd':
+        if (l_item->val.val_int < 0) {
+            log_it(L_WARNING, "Unsigned parameter \"%s\" requested, but the value is negative: %ld", l_item->name, l_item->val.val_int);
+            return a_default;
+        } else {
+            return (uint64_t)l_item->val.val_int;
+        }
+    default:
+        log_it(L_ERROR, "Parameter \"%s\" '%c' is not unsigned integer", l_item->name, l_item->type);
+        return a_default;
+    }
 }
 
-/**
- * @brief dap_config_get_item_path Getting a configuration item as a filsystem path (may be relative to config location)
- * @param[in] a_config Configuration
- * @param[in] a_section_path Path
- * @param[in] a_item_name setting
- * @return
- */
-const char * dap_config_get_item_path(dap_config_t * a_config, const char * a_section_path, const char * a_item_name)
-{
-    const char* raw_path = dap_config_get_item_str(a_config, a_section_path, a_item_name);
-    if (!raw_path) return NULL;
-    char * res = dap_canonicalize_filename(raw_path, dap_path_get_dirname(DAP_CONFIG_INTERNAL(a_config)->path));
-    log_it(L_DEBUG, "Config-path item: '%s': composed from '%s' and '%s'", res, raw_path, dap_path_get_dirname(DAP_CONFIG_INTERNAL(a_config)->path));
-    return res;
+const char *dap_config_get_item_str_default(dap_config_t *a_config, const char *a_section, const char *a_item_name, const char *a_default) {
+    dap_config_item_t *l_item = dap_config_get_item(a_config, a_section, a_item_name);
+    if (!l_item)
+        return a_default;
+    switch (l_item->type) {
+    case 's':
+        return l_item->val.val_str;
+    case 'a':
+        return l_item->val.val_arr[0];
+    default:
+        log_it(L_ERROR, "Parameter \"%s\" '%c' is not string", l_item->name, l_item->type);
+        return a_default;
+    }
 }
 
-/**
- * @brief dap_config_get_item_path_default Getting a configuration item as a filsystem path (may be relative to config location) (or default)
- * @param[in] a_config Configuration
- * @param[in] a_section_path Path
- * @param[in] a_item_name setting
- * @param[in] a_value_default Default value
- * @return
- */
-const char * dap_config_get_item_path_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, const char * a_value_default)
-{
-    const char * res = dap_config_get_item_path(a_config, a_section_path, a_item_name);
-    return res ?  res : a_value_default;
+const char *dap_config_get_item_str_path_default(dap_config_t *a_config, const char *a_section, const char *a_item_name, const char *a_default) {
+    dap_config_item_t *l_item = dap_config_get_item(a_config, a_section, a_item_name);
+    if (!l_item)
+        return a_default;
+    if (l_item->type != 's') {
+        log_it(L_ERROR, "Parameter \"%s\" '%c' is not string", l_item->name, l_item->type);
+        return a_default;
+    }
+    char l_abs_path[strlen(a_config->path) + 5];
+    dap_stpcpy(l_abs_path, a_config->path);
+    char *l_dir = dap_path_get_dirname(l_abs_path);
+    char *l_ret = dap_canonicalize_filename(l_item->val.val_str, l_dir);
+    log_it(L_DEBUG, "Config-path item: \"%s\": composed from \"%s\" and \"%s\"",
+           l_ret, l_item->val.val_str, l_dir);
+    DAP_DELETE(l_dir);
+    return l_ret;
 }
 
-/**
- * @brief dap_config_get_array_str Getting an array of configuration items as a string
- * @param[in] a_config Configuration
- * @param[in] a_section_path Path
- * @param[in] a_item_name setting
- * @return
- */
-char** dap_config_get_array_str(dap_config_t * a_config, const char * a_section_path,
-                                const char * a_item_name, uint16_t * array_length) {
-    dap_config_item_t * item = dap_config_get_item(a_config, a_section_path, a_item_name);
-    if (item == NULL){
-        if(array_length != NULL)
-            *array_length = 0;
+char **dap_config_get_array_str(dap_config_t *a_config, const char *a_section, const char *a_item_name, uint16_t *array_length) {
+    dap_config_item_t *l_item = dap_config_get_item(a_config, a_section, a_item_name);
+    if (array_length)
+        *array_length = 0;
+    if (!l_item)
+        return NULL;
+    if (l_item->type != 'a') {
+        log_it(L_ERROR, "Parameter \"%s\" '%c' is not array", l_item->name, l_item->type);
         return NULL;
-    }else{
-        if (array_length != NULL)
-            *array_length = item->array_length;
-        return item->data_str_array;
     }
+    if (array_length)
+        *array_length = dap_str_countv(l_item->val.val_arr);
+    return l_item->val.val_arr;
 }
 
-
-/**
- * @brief dap_config_get_item_str_default Getting an array of configuration items as a string
- * @param[in] a_config Configuration
- * @param[in] a_section_path Path
- * @param[in] a_item_name setting
- * @param[in] a_value_default Default
- * @return
- */
-const char * dap_config_get_item_str_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, const char * a_value_default)
-{
-    dap_config_item_t * l_item_section =a_config? DAP_CONFIG_INTERNAL(a_config)->item_root: NULL ;
-    while(l_item_section){
-        if (strcmp(l_item_section->name,a_section_path)==0){
-            dap_config_item_t * l_item = l_item_section->childs;
-            while (l_item){
-                if (strcmp(l_item->name,a_item_name)==0){
-                    return l_item->data_str;
-                }
-                l_item = l_item->item_next;
-            }
-        }
-        l_item_section = l_item_section->item_next;
+double dap_config_get_item_double_default(dap_config_t *a_config, const char *a_section, const char *a_item_name, double a_default) {
+    dap_config_item_t *l_item = dap_config_get_item(a_config, a_section, a_item_name);
+    if (!l_item)
+        return a_default;
+    switch (l_item->type) {
+    case 's':
+        return strtod(l_item->val.val_str, NULL);
+    case 'd':
+        return (double)l_item->val.val_int;
+    case 'u':
+        return (double)l_item->val.val_uint;
+    default:
+        log_it(L_ERROR, "Parameter \"%s\" '%c' can't be represented as double", l_item->name, l_item->type);
+        return a_default;
     }
-    return a_value_default;
 }
 
-/**
- * @brief dap_config_get_item_bool Getting a configuration item as a boolean
- * @param[in] a_config Configuration
- * @param[in] a_section_path Path
- * @param[in] a_item_name Setting
- * @return
- */
-bool dap_config_get_item_bool(dap_config_t * a_config, const char * a_section_path, const char * a_item_name)
-{
-const char *l_str_ret;
-
-    if ( !(l_str_ret = dap_config_get_item_str(a_config, a_section_path, a_item_name)) )
-        return	false;
-
-#ifdef	WIN32
-    return	!strnicmp (l_str_ret, "true", 4);
-#else
-    return	!strncasecmp (l_str_ret, "true", 4);	/* 0 == True */
-#endif
-}
-
-
-/**
- * @brief dap_config_get_item_bool_default Getting a configuration item as a boolean
- * @param[in] a_config Configuration
- * @param[in] a_section_path Path
- * @param[in] a_item_name Setting
- * @param[in] a_default Default
- * @return
- */
-bool dap_config_get_item_bool_default(dap_config_t * a_config, const char * a_section_path,
-                                      const char * a_item_name, bool a_default)
-{
-const char *l_str_ret;
 
-    if ( !(l_str_ret = dap_config_get_item_str_default(a_config,a_section_path, a_item_name, a_default ? "true" : "false")) )
-        return  a_default;
-
-#ifdef	WIN32
-    return	!strnicmp (l_str_ret, "true", 4);
-#else
-    return	!strncasecmp (l_str_ret, "true", 4);	/* 0 == True */
+void dap_config_close(dap_config_t *a_conf) {
+    DAP_DELETE(a_conf->path);
+    dap_config_item_t *l_item = NULL, *l_tmp = NULL;
+    HASH_ITER(hh, a_conf->items, l_item, l_tmp) {
+        HASH_DEL(a_conf->items, l_item);
+        dap_config_item_del(l_item);
+    }
+#if 0
+    HASH_DEL(g_configs_table, a_conf);
 #endif
-
+    DAP_DELETE(a_conf);
 }
 
-/**
- * @brief dap_config_get_item_double Getting a configuration item as a floating-point value
- * @param[in] a_config Configuration
- * @param[in] a_section_path Path
- * @param[in] a_item_name Setting
- * @return
- */
-double dap_config_get_item_double(dap_config_t * a_config, const char * a_section_path, const char * a_item_name)
-{
-const char *l_str_ret;
+void dap_config_deinit() {
 
-    l_str_ret = dap_config_get_item_str(a_config,a_section_path,a_item_name);
-    return l_str_ret ? atof(l_str_ret) : 0.0;
 }
-
-/**
- * @brief dap_config_get_item_double Getting a configuration item as a floating-point value
- * @param[in] a_config Configuration
- * @param[in] a_section_path Path
- * @param[in] a_item_name Setting
- * @param[in] a_default Defailt
- * @return
- */
-double dap_config_get_item_double_default(dap_config_t * a_config, const char * a_section_path, const char * a_item_name, double a_default)
-{
-    const char * l_str_ret = dap_config_get_item_str(a_config,a_section_path,a_item_name);
-    return l_str_ret?atof(l_str_ret):a_default;
-}
-
diff --git a/core/src/dap_strfuncs.c b/core/src/dap_strfuncs.c
index 6b5f0166cfac0b891d5ce83adb0b5a4c9502b2fc..fde2244a652f920af721b7520cbcd40fa6b79c96 100755
--- a/core/src/dap_strfuncs.c
+++ b/core/src/dap_strfuncs.c
@@ -11,6 +11,7 @@
 
 #include "dap_common.h"
 #include "dap_strfuncs.h"
+#include "dap_list.h"
 
 #define LOG_TAG "dap_strfunc"
 
@@ -578,43 +579,6 @@ char* dap_strjoin(const char *a_separator, ...)
     return string;
 }
 
-typedef struct _dap_slist dap_slist;
-
-struct _dap_slist
-{
-    void* data;
-    dap_slist *next;
-};
-
-static dap_slist* dap_slist_prepend(dap_slist *a_list, void* a_data)
-{
-    dap_slist *l_new_list;
-
-    l_new_list = DAP_NEW_Z(dap_slist);
-    if (!l_new_list) {
-        return NULL;
-    }
-    l_new_list->data = a_data;
-    l_new_list->next = a_list;
-
-    return l_new_list;
-}
-
-static void dap_slist_free(dap_slist *a_list)
-{
-    if(a_list)
-    {
-        dap_slist *l_cur_node;
-        dap_slist *l_last_node = a_list;
-        while(l_last_node)
-        {
-            l_cur_node = l_last_node;
-            l_last_node = l_last_node->next;
-            DAP_DELETE(l_cur_node);
-        }
-    }
-}
-
 /**
  * dap_strsplit:
  * @a_string: a string to split
@@ -644,7 +608,7 @@ static void dap_slist_free(dap_slist *a_list)
  */
 char** dap_strsplit(const char *a_string, const char *a_delimiter, int a_max_tokens)
 {
-    dap_slist *l_string_list = NULL, *l_slist;
+    dap_list_t *l_string_list = NULL, *l_slist;
     char **l_str_array, *l_s;
     uint32_t l_n = 1;
 
@@ -665,17 +629,17 @@ char** dap_strsplit(const char *a_string, const char *a_delimiter, int a_max_tok
             char *new_string;
 
             len = (uint32_t) (l_s - a_string);
-            new_string = DAP_NEW_SIZE(char, len + 1);
+            new_string = DAP_NEW_Z_SIZE(char, len + 1);
             strncpy(new_string, a_string, len);
             new_string[len] = 0;
-            l_string_list = dap_slist_prepend(l_string_list, new_string);
+            l_string_list = dap_list_prepend(l_string_list, new_string);
             l_n++;
             a_string = l_s + delimiter_len;
             l_s = strstr(a_string, a_delimiter);
         }
         while(--a_max_tokens && l_s);
     }
-    l_string_list = dap_slist_prepend(l_string_list, dap_strdup(a_string));
+    l_string_list = dap_list_prepend(l_string_list, dap_strdup(a_string));
 
     l_str_array = DAP_NEW_SIZE(char*, (l_n + 1) * sizeof(char*));
 
@@ -683,7 +647,7 @@ char** dap_strsplit(const char *a_string, const char *a_delimiter, int a_max_tok
     for(l_slist = l_string_list; l_slist; l_slist = l_slist->next)
         l_str_array[l_n--] = l_slist->data;
 
-    dap_slist_free(l_string_list);
+    dap_list_free(l_string_list);
 
     return l_str_array;
 }
@@ -717,6 +681,31 @@ size_t dap_str_symbol_count(const char *a_str, char a_sym)
     return l_count;
 }
 
+char **dap_str_appv(char **a_dst, char **a_src, size_t *a_count) {
+    size_t  l_count_dst = dap_str_countv(a_dst),
+            l_count     = a_count && *a_count ? *a_count : (size_t)-1,
+            l_count_src = dap_min(dap_str_countv(a_src), l_count);
+    if (!l_count_src) {
+        if (a_count)
+            *a_count = l_count_dst;
+        return a_dst;
+    }
+    l_count = l_count_dst + l_count_src + 1;
+    char **l_res = DAP_REALLOC_COUNT(a_dst, l_count);
+    char **l_src = a_src;
+    while (l_src && l_count_src--) {
+        if (**l_src)
+            l_res[l_count_dst++] = *l_src;
+        l_src++;
+    }
+    l_res[l_count_dst] = NULL;
+    if (l_count > l_count_dst + 1)
+        l_res = DAP_REALLOC_COUNT(l_res, l_count_dst + 1);
+    if (a_count)
+        *a_count = l_count_dst;
+    return l_res;
+}
+
 /**
  * @brief  dap_strdupv:
  * 
diff --git a/plugin/src/dap_plugin_manifest.c b/plugin/src/dap_plugin_manifest.c
index 9ad9748fe102ad7b41ef72e88e57f347167aa559..6a4d8697b373eb7aee3d59c2d98c99dc0d9ce8db 100644
--- a/plugin/src/dap_plugin_manifest.c
+++ b/plugin/src/dap_plugin_manifest.c
@@ -234,7 +234,7 @@ dap_plugin_manifest_t* dap_plugin_manifest_add_from_file(const char *a_file_path
 
     char * l_config_path = dap_strdup_printf("%s/%s.cfg", l_manifest->path,l_manifest->name );
     if(dap_file_test(l_config_path)) // If present custom config
-        l_manifest->config = dap_config_load(l_config_path);
+        l_manifest->config = dap_config_open(l_config_path);
     DAP_DELETE(l_config_path);
 
     HASH_ADD_STR(s_manifests,name,l_manifest);