From 888a0fee7726e6f1fe05acca45a639ebf8b9b60e Mon Sep 17 00:00:00 2001
From: Aleksandr Lysikov <lysikov@inbox.ru>
Date: Thu, 28 Mar 2019 15:51:10 +0500
Subject: [PATCH] added dap_string_t functions renamed DapList -> dap_list_t

---
 core/dap_common.h                |   1 +
 core/dap_list.c                  | 116 ++--
 core/dap_list.h                  |  80 +--
 core/dap_strfuncs.c              |  47 +-
 core/dap_strfuncs.h              |   8 +-
 core/dap_string.c                | 971 +++++++++++++++++++++++++++++++
 core/dap_string.h                |  97 +++
 crypto/iaes/iaes256_cbc_cernal.c |  19 +-
 8 files changed, 1223 insertions(+), 116 deletions(-)
 create mode 100755 core/dap_string.c
 create mode 100755 core/dap_string.h

diff --git a/core/dap_common.h b/core/dap_common.h
index 7027890..147da6a 100644
--- a/core/dap_common.h
+++ b/core/dap_common.h
@@ -32,6 +32,7 @@
 #define DAP_NEW_SIZE(a,b)    ( (a*) malloc(b))
 #define DAP_NEW_Z(a) ( (a*) calloc(1,sizeof(a)))
 #define DAP_NEW_Z_SIZE(a,b) ( (a*) calloc(1,b))
+#define DAP_REALLOC(a,b) (realloc(a,b))
 
 #define DAP_DELETE(a)   free(a)
 #define DAP_DUP(a) (__typeof(a) ret = memcpy(ret,a,sizeof(*a)) )
diff --git a/core/dap_list.c b/core/dap_list.c
index e47aadf..6d28340 100755
--- a/core/dap_list.c
+++ b/core/dap_list.c
@@ -15,15 +15,15 @@
  * dap_list_alloc:
  * Returns: a pointer to the newly-allocated DapList element
  **/
-DapList *dap_list_alloc(void)
+dap_list_t *dap_list_alloc(void)
 {
-    DapList *list = DAP_NEW(DapList);
+    dap_list_t *list = DAP_NEW(dap_list_t);
     return list;
 }
 
-DapList *dap_list_alloc0(void)
+dap_list_t *dap_list_alloc0(void)
 {
-    DapList *list = DAP_NEW_Z(DapList);
+    dap_list_t *list = DAP_NEW_Z(dap_list_t);
     return list;
 }
 
@@ -34,11 +34,11 @@ DapList *dap_list_alloc0(void)
  * If list elements contain dynamically-allocated memory, you should
  * either use dap_list_free_full() or free them manually first.
  */
-void dap_list_free(DapList *list)
+void dap_list_free(dap_list_t *list)
 {
     while(list)
     {
-        DapList *next = list->next;
+        dap_list_t *next = list->next;
         DAP_DELETE(list);
         list = next;
     }
@@ -50,7 +50,7 @@ void dap_list_free(DapList *list)
  * Frees one DapList element.
  * It is usually used after dap_list_remove_link().
  */
-void dap_list_free1(DapList *list)
+void dap_list_free1(dap_list_t *list)
 {
     DAP_DELETE(list);
 }
@@ -63,7 +63,7 @@ void dap_list_free1(DapList *list)
  * Convenience method, which frees all the memory used by a DapList,
  * and calls @free_func on every element's data.
  */
-void dap_list_free_full(DapList *list, DapDestroyNotify free_func)
+void dap_list_free_full(dap_list_t *list, DapDestroyNotify free_func)
 {
     dap_list_foreach(list, (DapFunc) free_func, NULL);
     dap_list_free(list);
@@ -99,10 +99,10 @@ void dap_list_free_full(DapList *list, DapDestroyNotify free_func)
  *
  * Returns: either @list or the new start of the DapList if @list was %NULL
  */
-DapList * dap_list_append(DapList *list, void* data)
+dap_list_t * dap_list_append(dap_list_t *list, void* data)
 {
-    DapList *new_list;
-    DapList *last;
+    dap_list_t *new_list;
+    dap_list_t *last;
 
     new_list = dap_list_alloc();
     new_list->data = data;
@@ -148,9 +148,9 @@ DapList * dap_list_append(DapList *list, void* data)
  * Returns: a pointer to the newly prepended element, which is the new 
  *     start of the DapList
  */
-DapList *dap_list_prepend(DapList *list, void* data)
+dap_list_t *dap_list_prepend(dap_list_t *list, void* data)
 {
-    DapList *new_list;
+    dap_list_t *new_list;
 
     new_list = dap_list_alloc();
     new_list->data = data;
@@ -181,10 +181,10 @@ DapList *dap_list_prepend(DapList *list, void* data)
  *
  * Returns: the (possibly changed) start of the DapList
  */
-DapList *dap_list_insert(DapList *list, void* data, int position)
+dap_list_t *dap_list_insert(dap_list_t *list, void* data, int position)
 {
-    DapList *new_list;
-    DapList *tmp_list;
+    dap_list_t *new_list;
+    dap_list_t *tmp_list;
 
     if(position < 0)
         return dap_list_append(list, data);
@@ -216,7 +216,7 @@ DapList *dap_list_insert(DapList *list, void* data, int position)
  *
  * Returns: the (possibly changed) start of the DapList
  */
-DapList *dap_list_insert_before(DapList *list, DapList *sibling, void* data)
+dap_list_t *dap_list_insert_before(dap_list_t *list, dap_list_t *sibling, void* data)
 {
     if(!list)
     {
@@ -227,7 +227,7 @@ DapList *dap_list_insert_before(DapList *list, DapList *sibling, void* data)
     }
     else if(sibling)
     {
-        DapList *node;
+        dap_list_t *node;
 
         node = dap_list_alloc();
         node->data = data;
@@ -247,7 +247,7 @@ DapList *dap_list_insert_before(DapList *list, DapList *sibling, void* data)
     }
     else
     {
-        DapList *last;
+        dap_list_t *last;
 
         last = list;
         while(last->next)
@@ -281,9 +281,9 @@ DapList *dap_list_insert_before(DapList *list, DapList *sibling, void* data)
  *
  * Returns: the start of the new DapList, which equals @list1 if not %NULL
  */
-DapList *dap_list_concat(DapList *list1, DapList *list2)
+dap_list_t *dap_list_concat(dap_list_t *list1, dap_list_t *list2)
 {
-    DapList *tmp_list;
+    dap_list_t *tmp_list;
 
     if(list2)
     {
@@ -298,7 +298,7 @@ DapList *dap_list_concat(DapList *list1, DapList *list2)
     return list1;
 }
 
-static inline DapList * _dap_list_remove_link(DapList *list, DapList *link)
+static inline dap_list_t * _dap_list_remove_link(dap_list_t *list, dap_list_t *link)
 {
     if(link == NULL)
         return list;
@@ -338,9 +338,9 @@ static inline DapList * _dap_list_remove_link(DapList *list, DapList *link)
  *
  * Returns: the (possibly changed) start of the DapList
  */
-DapList *dap_list_remove(DapList *list, const void * data)
+dap_list_t *dap_list_remove(dap_list_t *list, const void * data)
 {
-    DapList *tmp;
+    dap_list_t *tmp;
 
     tmp = list;
     while(tmp)
@@ -370,9 +370,9 @@ DapList *dap_list_remove(DapList *list, const void * data)
  *
  * Returns: the (possibly changed) start of the DapList
  */
-DapList *dap_list_remove_all(DapList *list, const void * data)
+dap_list_t *dap_list_remove_all(dap_list_t *list, const void * data)
 {
-    DapList *tmp = list;
+    dap_list_t *tmp = list;
 
     while(tmp)
     {
@@ -380,7 +380,7 @@ DapList *dap_list_remove_all(DapList *list, const void * data)
             tmp = tmp->next;
         else
         {
-            DapList *next = tmp->next;
+            dap_list_t *next = tmp->next;
 
             if(tmp->prev)
                 tmp->prev->next = next;
@@ -416,7 +416,7 @@ DapList *dap_list_remove_all(DapList *list, const void * data)
  *
  * Returns: the (possibly changed) start of the DapList
  */
-DapList *dap_list_remove_link(DapList *list, DapList *llink)
+dap_list_t *dap_list_remove_link(dap_list_t *list, dap_list_t *llink)
 {
     return _dap_list_remove_link(list, llink);
 }
@@ -432,7 +432,7 @@ DapList *dap_list_remove_link(DapList *list, DapList *llink)
  *
  * Returns: the (possibly changed) start of the DapList
  */
-DapList *dap_list_delete_link(DapList *list, DapList *link_)
+dap_list_t *dap_list_delete_link(dap_list_t *list, dap_list_t *link_)
 {
     list = _dap_list_remove_link(list, link_);
     dap_list_free1(link_);
@@ -453,7 +453,7 @@ DapList *dap_list_delete_link(DapList *list, DapList *link_)
  *
  * Returns: the start of the new list that holds the same data as @list
  */
-DapList *dap_list_copy(DapList *list)
+dap_list_t *dap_list_copy(dap_list_t *list)
 {
     return dap_list_copy_deep(list, NULL, NULL);
 }
@@ -487,13 +487,13 @@ DapList *dap_list_copy(DapList *list)
  * Returns: the start of the new list that holds a full copy of @list, 
  *     use dap_list_free_full() to free it
  */
-DapList *dap_list_copy_deep(DapList *list, DapCopyFunc func, void* user_data)
+dap_list_t *dap_list_copy_deep(dap_list_t *list, DapCopyFunc func, void* user_data)
 {
-    DapList *new_list = NULL;
+    dap_list_t *new_list = NULL;
 
     if(list)
     {
-        DapList *last;
+        dap_list_t *last;
 
         new_list = dap_list_alloc();
         if(func)
@@ -529,9 +529,9 @@ DapList *dap_list_copy_deep(DapList *list, DapCopyFunc func, void* user_data)
  *
  * Returns: the start of the reversed DapList
  */
-DapList * dap_list_reverse(DapList *list)
+dap_list_t * dap_list_reverse(dap_list_t *list)
 {
-    DapList *last;
+    dap_list_t *last;
 
     last = NULL;
     while(list)
@@ -555,7 +555,7 @@ DapList * dap_list_reverse(DapList *list)
  * Returns: the element, or %NULL if the position is off 
  *     the end of the DapList
  */
-DapList *dap_list_nth(DapList *list, unsigned int n)
+dap_list_t *dap_list_nth(dap_list_t *list, unsigned int n)
 {
     while((n-- > 0) && list)
         list = list->next;
@@ -573,7 +573,7 @@ DapList *dap_list_nth(DapList *list, unsigned int n)
  * Returns: the element, or %NULL if the position is 
  *     off the end of the DapList
  */
-DapList *dap_list_nth_prev(DapList *list, unsigned int n)
+dap_list_t *dap_list_nth_prev(dap_list_t *list, unsigned int n)
 {
     while((n-- > 0) && list)
         list = list->prev;
@@ -591,7 +591,7 @@ DapList *dap_list_nth_prev(DapList *list, unsigned int n)
  * Returns: the element's data, or %NULL if the position 
  *     is off the end of the DapList
  */
-void* dap_list_nth_data(DapList *list, unsigned int n)
+void* dap_list_nth_data(dap_list_t *list, unsigned int n)
 {
     while((n-- > 0) && list)
         list = list->next;
@@ -608,7 +608,7 @@ void* dap_list_nth_data(DapList *list, unsigned int n)
  *
  * Returns: the found DapList element, or %NULL if it is not found
  */
-DapList *dap_list_find(DapList *list, const void * data)
+dap_list_t *dap_list_find(dap_list_t *list, const void * data)
 {
     while(list)
     {
@@ -636,7 +636,7 @@ DapList *dap_list_find(DapList *list, const void * data)
  *
  * Returns: the found DapList element, or %NULL if it is not found
  */
-DapList *dap_list_find_custom(DapList *list, const void * data, DapCompareFunc func)
+dap_list_t *dap_list_find_custom(dap_list_t *list, const void * data, DapCompareFunc func)
 {
     dap_return_val_if_fail(func != NULL, list);
 
@@ -661,7 +661,7 @@ DapList *dap_list_find_custom(DapList *list, const void * data, DapCompareFunc f
  * Returns: the position of the element in the DapList,
  *     or -1 if the element is not found
  */
-int dap_list_position(DapList *list, DapList *llink)
+int dap_list_position(dap_list_t *list, dap_list_t *llink)
 {
     int i;
 
@@ -688,7 +688,7 @@ int dap_list_position(DapList *list, DapList *llink)
  * Returns: the index of the element containing the data, 
  *     or -1 if the data is not found
  */
-int dap_list_index(DapList *list, const void * data)
+int dap_list_index(dap_list_t *list, const void * data)
 {
     int i;
 
@@ -713,7 +713,7 @@ int dap_list_index(DapList *list, const void * data)
  * Returns: the last element in the DapList,
  *     or %NULL if the DapList has no elements
  */
-DapList * dap_list_last(DapList *list)
+dap_list_t * dap_list_last(dap_list_t *list)
 {
     if(list)
     {
@@ -733,7 +733,7 @@ DapList * dap_list_last(DapList *list)
  * Returns: the first element in the DapList,
  *     or %NULL if the DapList has no elements
  */
-DapList *dap_list_first(DapList *list)
+dap_list_t *dap_list_first(dap_list_t *list)
 {
     if(list)
     {
@@ -754,7 +754,7 @@ DapList *dap_list_first(DapList *list)
  *
  * Returns: the number of elements in the DapList
  */
-unsigned int dap_list_length(DapList *list)
+unsigned int dap_list_length(dap_list_t *list)
 {
     unsigned int length;
 
@@ -776,20 +776,20 @@ unsigned int dap_list_length(DapList *list)
  *
  * Calls a function for each element of a DapList.
  */
-void dap_list_foreach(DapList *list, DapFunc func, void* user_data)
+void dap_list_foreach(dap_list_t *list, DapFunc func, void* user_data)
 {
     while(list)
     {
-        DapList *next = list->next;
+        dap_list_t *next = list->next;
         (*func)(list->data, user_data);
         list = next;
     }
 }
 
-static DapList* dap_list_insert_sorted_real(DapList *list, void* data, DapFunc func, void* user_data)
+static dap_list_t* dap_list_insert_sorted_real(dap_list_t *list, void* data, DapFunc func, void* user_data)
 {
-    DapList *tmp_list = list;
-    DapList *new_list;
+    dap_list_t *tmp_list = list;
+    dap_list_t *new_list;
     int cmp;
 
     dap_return_val_if_fail(func != NULL, list);
@@ -853,7 +853,7 @@ static DapList* dap_list_insert_sorted_real(DapList *list, void* data, DapFunc f
  *
  * Returns: the (possibly changed) start of the DapList
  */
-DapList *dap_list_insert_sorted(DapList *list, void* data, DapCompareFunc func)
+dap_list_t *dap_list_insert_sorted(dap_list_t *list, void* data, DapCompareFunc func)
 {
     return dap_list_insert_sorted_real(list, data, (DapFunc) func, NULL);
 }
@@ -878,14 +878,14 @@ DapList *dap_list_insert_sorted(DapList *list, void* data, DapCompareFunc func)
  *
  * Returns: the (possibly changed) start of the DapList
  */
-DapList * dap_list_insert_sorted_with_data(DapList *list, void* data, DapCompareDataFunc func, void* user_data)
+dap_list_t * dap_list_insert_sorted_with_data(dap_list_t *list, void* data, DapCompareDataFunc func, void* user_data)
 {
     return dap_list_insert_sorted_real(list, data, (DapFunc) func, user_data);
 }
 
-static DapList *dap_list_sort_merge(DapList *l1, DapList *l2, DapFunc compare_func, void* user_data)
+static dap_list_t *dap_list_sort_merge(dap_list_t *l1, dap_list_t *l2, DapFunc compare_func, void* user_data)
 {
-    DapList list, *l, *lprev;
+    dap_list_t list, *l, *lprev;
     int cmp;
 
     l = &list;
@@ -915,9 +915,9 @@ static DapList *dap_list_sort_merge(DapList *l1, DapList *l2, DapFunc compare_fu
     return list.next;
 }
 
-static DapList *dap_list_sort_real(DapList *list, DapFunc compare_func, void* user_data)
+static dap_list_t *dap_list_sort_real(dap_list_t *list, DapFunc compare_func, void* user_data)
 {
-    DapList *l1, *l2;
+    dap_list_t *l1, *l2;
 
     if(!list)
         return NULL ;
@@ -969,7 +969,7 @@ static DapList *dap_list_sort_real(DapList *list, DapFunc compare_func, void* us
  * Returns: negative value if @a < @b; zero if @a = @b; positive
  *          value if @a > @b
  */
-DapList *dap_list_sort(DapList *list, DapCompareFunc compare_func)
+dap_list_t *dap_list_sort(dap_list_t *list, DapCompareFunc compare_func)
 {
     return dap_list_sort_real(list, (DapFunc) compare_func, NULL);
 }
@@ -999,7 +999,7 @@ DapList *dap_list_sort(DapList *list, DapCompareFunc compare_func)
  * Returns: negative value if @a < @b; zero if @a = @b; positive
  *          value if @a > @b
  */
-DapList *dap_list_sort_with_data(DapList *list, DapCompareDataFunc compare_func, void* user_data)
+dap_list_t *dap_list_sort_with_data(dap_list_t *list, DapCompareDataFunc compare_func, void* user_data)
 {
     return dap_list_sort_real(list, (DapFunc) compare_func, user_data);
 }
diff --git a/core/dap_list.h b/core/dap_list.h
index 08445a2..5bcf960 100755
--- a/core/dap_list.h
+++ b/core/dap_list.h
@@ -11,52 +11,52 @@ typedef void* (*DapCopyFunc)(const void * src, void* data);
 typedef int (*DapCompareFunc)(const void * a, const void * b);
 typedef int (*DapCompareDataFunc)(const void * a, const void * b, void* user_data);
 
-typedef struct _DapList DapList;
+typedef struct _dap_list dap_list_t;
 
-struct _DapList
+struct _dap_list
 {
     void* data;
-    DapList *next;
-    DapList *prev;
+    dap_list_t *next;
+    dap_list_t *prev;
 };
 
 /* Doubly linked lists
  */
-DapList* dap_list_alloc(void);
-void dap_list_free(DapList *list);
-void dap_list_free1(DapList *list);
-void dap_list_free_full(DapList *list, DapDestroyNotify free_func);
-DapList* dap_list_append(DapList *list, void* data);
-DapList* dap_list_prepend(DapList *list, void* data);
-DapList* dap_list_insert(DapList *list, void* data, int position);
-DapList* dap_list_insert_sorted(DapList *list, void* data, DapCompareFunc func);
-DapList* dap_list_insert_sorted_with_data(DapList *list, void* data, DapCompareDataFunc func, void* user_data);
-DapList* dap_list_insert_before(DapList *list, DapList *sibling, void* data);
-DapList* dap_list_concat(DapList *list1, DapList *list2);
-DapList* dap_list_remove(DapList *list, const void * data);
-DapList* dap_list_remove_all(DapList *list, const void * data);
-DapList* dap_list_remove_link(DapList *list, DapList *llink);
-DapList* dap_list_delete_link(DapList *list, DapList *link_);
-DapList* dap_list_reverse(DapList *list);
-DapList* dap_list_copy(DapList *list);
-
-DapList* dap_list_copy_deep(DapList *list, DapCopyFunc func, void* user_data);
-
-DapList* dap_list_nth(DapList *list, unsigned int n);
-DapList* dap_list_nth_prev(DapList *list, unsigned int n);
-DapList* dap_list_find(DapList *list, const void * data);
-DapList* dap_list_find_custom(DapList *list, const void * data, DapCompareFunc func);
-int dap_list_position(DapList *list, DapList *llink);
-int dap_list_index(DapList *list, const void * data);
-DapList* dap_list_last(DapList *list);
-DapList* dap_list_first(DapList *list);
-unsigned int dap_list_length(DapList *list);
-void dap_list_foreach(DapList *list, DapFunc func, void* user_data);
-DapList* dap_list_sort(DapList *list, DapCompareFunc compare_func);
-DapList* dap_list_sort_with_data(DapList *list, DapCompareDataFunc compare_func, void* user_data);
-void* dap_list_nth_data(DapList *list, unsigned int n);
-
-#define dap_list_previous(list)	        ((list) ? (((DapList *)(list))->prev) : NULL)
-#define dap_list_next(list)	        ((list) ? (((DapList *)(list))->next) : NULL)
+dap_list_t* dap_list_alloc(void);
+void dap_list_free(dap_list_t *list);
+void dap_list_free1(dap_list_t *list);
+void dap_list_free_full(dap_list_t *list, DapDestroyNotify free_func);
+dap_list_t* dap_list_append(dap_list_t *list, void* data);
+dap_list_t* dap_list_prepend(dap_list_t *list, void* data);
+dap_list_t* dap_list_insert(dap_list_t *list, void* data, int position);
+dap_list_t* dap_list_insert_sorted(dap_list_t *list, void* data, DapCompareFunc func);
+dap_list_t* dap_list_insert_sorted_with_data(dap_list_t *list, void* data, DapCompareDataFunc func, void* user_data);
+dap_list_t* dap_list_insert_before(dap_list_t *list, dap_list_t *sibling, void* data);
+dap_list_t* dap_list_concat(dap_list_t *list1, dap_list_t *list2);
+dap_list_t* dap_list_remove(dap_list_t *list, const void * data);
+dap_list_t* dap_list_remove_all(dap_list_t *list, const void * data);
+dap_list_t* dap_list_remove_link(dap_list_t *list, dap_list_t *llink);
+dap_list_t* dap_list_delete_link(dap_list_t *list, dap_list_t *link_);
+dap_list_t* dap_list_reverse(dap_list_t *list);
+dap_list_t* dap_list_copy(dap_list_t *list);
+
+dap_list_t* dap_list_copy_deep(dap_list_t *list, DapCopyFunc func, void* user_data);
+
+dap_list_t* dap_list_nth(dap_list_t *list, unsigned int n);
+dap_list_t* dap_list_nth_prev(dap_list_t *list, unsigned int n);
+dap_list_t* dap_list_find(dap_list_t *list, const void * data);
+dap_list_t* dap_list_find_custom(dap_list_t *list, const void * data, DapCompareFunc func);
+int dap_list_position(dap_list_t *list, dap_list_t *llink);
+int dap_list_index(dap_list_t *list, const void * data);
+dap_list_t* dap_list_last(dap_list_t *list);
+dap_list_t* dap_list_first(dap_list_t *list);
+unsigned int dap_list_length(dap_list_t *list);
+void dap_list_foreach(dap_list_t *list, DapFunc func, void* user_data);
+dap_list_t* dap_list_sort(dap_list_t *list, DapCompareFunc compare_func);
+dap_list_t* dap_list_sort_with_data(dap_list_t *list, DapCompareDataFunc compare_func, void* user_data);
+void* dap_list_nth_data(dap_list_t *list, unsigned int n);
+
+#define dap_list_previous(list)	        ((list) ? (((dap_list_t *)(list))->prev) : NULL)
+#define dap_list_next(list)	        ((list) ? (((dap_list_t *)(list))->next) : NULL)
 
 #endif /* __DAP_LIST_H__ */
diff --git a/core/dap_strfuncs.c b/core/dap_strfuncs.c
index cd07363..88dff5d 100755
--- a/core/dap_strfuncs.c
+++ b/core/dap_strfuncs.c
@@ -4,7 +4,6 @@
 #include <windows.h>
 #endif
 #include <stddef.h>
-#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -42,18 +41,54 @@ char* dap_strdup(const char *a_str)
     return l_new_str;
 }
 
+/**
+ * dap_strdup_vprintf:
+ * @a_format: a standard printf() format string, but notice
+ *     [string precision pitfalls][string-precision]
+ * @a_args: the list of parameters to insert into the format string
+ *
+ * Similar to the standard C vsprintf() function but safer, since it
+ * calculates the maximum space required and allocates memory to hold
+ * the result. The returned string should be freed with DAP_DELETE()
+ * when no longer needed.
+ *
+ * Returns: a newly-allocated string holding the result
+ */
+char* dap_strdup_vprintf(const char *a_format, va_list a_args)
+{
+    char *l_string = NULL;
+    int len = vasprintf(&l_string, a_format, a_args);
+    if(len < 0)
+        l_string = NULL;
+    return l_string;
+}
+
 /**
  * dap_strdup_printf:
  * @a_format: a standard printf() format string
  *
  * Similar to the standard C sprintf() function but safer, since it
  * calculates the maximum space required and allocates memory to hold
- * the result. The returned string should be freed when no
- * longer needed.
+ * the result. The returned string should be freed with DAP_DELETE()
+ * when no longer needed.
  *
  * Returns: a newly-allocated string holding the result
  */
 char* dap_strdup_printf(const char *a_format, ...)
+{
+    char *l_buffer;
+    va_list l_args;
+
+    va_start(l_args, a_format);
+    l_buffer = dap_strdup_vprintf(a_format, l_args);
+    va_end(l_args);
+
+    return l_buffer;
+}
+
+/*
+// alternative version
+char* dap_strdup_printf2(const char *a_format, ...)
 {
     size_t l_buffer_size = 0;
     char *l_buffer = NULL;
@@ -72,7 +107,7 @@ char* dap_strdup_printf(const char *a_format, ...)
     va_end(l_args);
 
     return l_buffer;
-}
+}*/
 
 /**
  * dap_stpcpy:
@@ -125,9 +160,9 @@ char* dap_strstr_len(const char *a_haystack, ssize_t a_haystack_len, const char
     else
     {
         const char *l_p = a_haystack;
-        ssize_t l_needle_len = (ssize_t)strlen(a_needle);
+        ssize_t l_needle_len = (ssize_t) strlen(a_needle);
         const char *l_end;
-        size_t l_i;
+        ssize_t l_i;
 
         if(l_needle_len == 0)
             return (char *) a_haystack;
diff --git a/core/dap_strfuncs.h b/core/dap_strfuncs.h
index 5e8d471..68abb1c 100755
--- a/core/dap_strfuncs.h
+++ b/core/dap_strfuncs.h
@@ -1,11 +1,12 @@
 /* DAP String Functions */
 
-#ifndef __DAP_LIB_MINI_H
-#define __DAP_LIB_MINI_H
+#ifndef __DAP_STR_FUNC_H
+#define __DAP_STR_FUNC_H
 
 #include <limits.h>
 #include <stdbool.h>
 #include <stdint.h>
+#include <stdarg.h>
 
 #define dap_return_if_fail(expr)			{if(!(expr)) {return;}}
 #define dap_return_val_if_fail(expr,val)	{if(!(expr)) {return (val);}}
@@ -29,6 +30,7 @@
 #define clamp(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
 
 char* dap_strdup(const char *a_str);
+char* dap_strdup_vprintf(const char *a_format, va_list a_args);
 char* dap_strdup_printf(const char *a_format, ...);
 
 char* dap_stpcpy(char *a_dest, const char *a_src);
@@ -60,4 +62,4 @@ char* dap_strreverse(char *a_string);
 #define DAP_USEC_PER_SEC 1000000
 void dap_usleep(time_t a_microseconds);
 
-#endif /* __DAP_LIB_MINI_H */
+#endif /* __DAP_STR_FUNC_H */
diff --git a/core/dap_string.c b/core/dap_string.c
new file mode 100755
index 0000000..831c4ab
--- /dev/null
+++ b/core/dap_string.c
@@ -0,0 +1,971 @@
+// dap_string_t is an object that handles the memory management of a C string for you.
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "dap_common.h"
+#include "dap_strfuncs.h"
+#include "dap_string.h"
+
+#define MY_MAXSIZE ((size_t)-1)
+
+static inline size_t nearest_power(size_t a_base, size_t a_num)
+{
+    if(a_num > MY_MAXSIZE / 2) {
+        return MY_MAXSIZE;
+    }
+    else {
+        size_t l_n = a_base;
+
+        while(l_n < a_num)
+            l_n <<= 1;
+
+        return l_n;
+    }
+}
+
+static void dap_string_maybe_expand(dap_string_t *a_string, size_t a_len)
+{
+    if(a_string->len + a_len >= a_string->allocated_len) {
+        a_string->allocated_len = nearest_power(1, a_string->len + a_len + 1);
+        a_string->str = DAP_REALLOC(a_string->str, a_string->allocated_len);
+    }
+}
+
+/**
+ * dap_string_sized_new:
+ * @a_a_dfl_size: the default size of the space allocated to
+ *     hold the string
+ *
+ * Creates a new #dap_string_t, with enough space for @a_a_dfl_size
+ * bytes. This is useful if you are going to add a lot of
+ * text to the string and don't want it to be reallocated
+ * too often.
+ *
+ * Returns: the new #dap_string_t
+ */
+dap_string_t * dap_string_sized_new(size_t a_dfl_size)
+{
+    dap_string_t *l_string = DAP_NEW(dap_string_t);
+
+    l_string->allocated_len = 0;
+    l_string->len = 0;
+    l_string->str = NULL;
+
+    dap_string_maybe_expand(l_string, max(a_dfl_size, 2));
+    l_string->str[0] = 0;
+
+    return l_string;
+}
+
+/**
+ * dap_string_new:
+ * @a_a_init: (nullable): the initial text to copy into the string, or %NULL to
+ * start with an empty string
+ *
+ * Creates a new #dap_string_t, initialized with the given string.
+ *
+ * Returns: the new #dap_string_t
+ */
+dap_string_t* dap_string_new(const char *a_init)
+{
+    dap_string_t *l_string;
+
+    if(a_init == NULL || *a_init == '\0')
+        l_string = dap_string_sized_new(2);
+    else
+    {
+        int len;
+
+        len = strlen(a_init);
+        l_string = dap_string_sized_new(len + 2);
+
+        dap_string_append_len(l_string, a_init, len);
+    }
+
+    return l_string;
+}
+
+/**
+ * dap_string_new_len:
+ * @a_init: initial contents of the string
+ * @a_len: length of @a_init to use
+ *
+ * Creates a new #dap_string_t with @a_len bytes of the @a_init buffer.
+ * Because a length is provided, @a_init need not be nul-terminated,
+ * and can contain embedded nul bytes.
+ *
+ * Since this function does not stop at nul bytes, it is the caller's
+ * responsibility to ensure that @a_init has at least @a_len addressable
+ * bytes.
+ *
+ * Returns: a new #dap_string_t
+ */
+dap_string_t* dap_string_new_len(const char *a_init, ssize_t a_len)
+{
+    dap_string_t *l_string;
+
+    if(a_len < 0)
+        return dap_string_new(a_init);
+    else
+    {
+        l_string = dap_string_sized_new(a_len);
+
+        if(a_init)
+            dap_string_append_len(l_string, a_init, a_len);
+
+        return l_string;
+    }
+}
+
+/**
+ * dap_string_free:
+ * @a_string: (transfer full): a #dap_string_t
+ * @a_free_segment: if %true, the actual character data is freed as well
+ *
+ * Frees the memory allocated for the #dap_string_t.
+ * If @a_free_segment is %true it also frees the character data.  If
+ * it's %false, the caller gains ownership of the buffer and must
+ * free it after use with dap_free().
+ *
+ * Returns: (nullable): the character data of @a_string
+ *          (i.e. %NULL if @a_free_segment is %true)
+ */
+char* dap_string_free(dap_string_t *a_string, bool a_free_segment)
+{
+    char *l_segment;
+
+    dap_return_val_if_fail(a_string != NULL, NULL);
+
+    if(a_free_segment)
+    {
+        DAP_DELETE(a_string->str);
+        l_segment = NULL;
+    }
+    else
+        l_segment = a_string->str;
+
+    DAP_DELETE(a_string);
+
+    return l_segment;
+}
+
+/**
+ * dap_string_equal:
+ * @a_v: a #dap_string_t
+ * @a_v2: another #dap_string_t
+ *
+ * Compares two strings for equality, returning %true if they are equal.
+ * For use with #GHashTable.
+ *
+ * Returns: %true if the strings are the same length and contain the
+ *     same bytes
+ */
+bool dap_string_equal(const dap_string_t *a_v, const dap_string_t *a_v2)
+{
+    char *p, *q;
+    dap_string_t *l_string1 = (dap_string_t *) a_v;
+    dap_string_t *l_string2 = (dap_string_t *) a_v2;
+    size_t i = l_string1->len;
+
+    if(i != l_string2->len)
+        return false;
+
+    p = l_string1->str;
+    q = l_string2->str;
+    while(i)
+    {
+        if(*p != *q)
+            return false;
+        p++;
+        q++;
+        i--;
+    }
+    return true;
+}
+
+/**
+ * dap_string_hash:
+ * @a_str: a string to hash
+ *
+ * Creates a hash code for @a_str
+ *
+ * Returns: hash code for @a_str
+ */
+unsigned int dap_string_hash(const dap_string_t *a_str)
+{
+    const char *p = a_str->str;
+    size_t n = a_str->len;
+    unsigned int h = 0;
+
+    /* 31 bit hash function */
+    while(n--)
+    {
+        h = (h << 5) - h + *p;
+        p++;
+    }
+
+    return h;
+}
+
+/**
+ * dap_string_assign:
+ * @a_string: the destination #dap_string_t. Its current contents
+ *          are destroyed.
+ * @a_rval: the string to copy into @a_string
+ *
+ * Copies the bytes from a string into a #dap_string_t,
+ * destroying any previous contents. It is rather like
+ * the standard strcpy() function, except that you do not
+ * have to worry about having enough space to copy the string.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_assign(dap_string_t *a_string, const char *a_rval)
+{
+    dap_return_val_if_fail(a_string != NULL, NULL);
+    dap_return_val_if_fail(a_rval != NULL, a_string);
+
+    /* Make sure assigning to itself doesn't corrupt the string. */
+    if(a_string->str != a_rval)
+            {
+        /* Assigning from substring should be ok, since
+         * dap_string_truncate() does not reallocate.
+         */
+        dap_string_truncate(a_string, 0);
+        dap_string_append(a_string, a_rval);
+    }
+
+    return a_string;
+}
+
+/**
+ * dap_string_truncate:
+ * @a_string: a #dap_string_t
+ * @a_len: the new size of @a_string
+ *
+ * Cuts off the end of the dap_string_t, leaving the first @a_len bytes.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_truncate(dap_string_t *string, size_t len)
+{
+    dap_return_val_if_fail(string != NULL, NULL);
+
+    string->len = min(len, string->len);
+    string->str[string->len] = 0;
+
+    return string;
+}
+
+/**
+ * dap_string_set_size:
+ * @a_string: a #dap_string_t
+ * @a_len: the new length
+ *
+ * Sets the length of a #dap_string_t. If the length is less than
+ * the current length, the string will be truncated. If the
+ * length is greater than the current length, the contents
+ * of the newly added area are undefined. (However, as
+ * always, string->str[string->len] will be a nul byte.)
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_set_size(dap_string_t *string, size_t len)
+{
+    dap_return_val_if_fail(string != NULL, NULL);
+
+    if(len >= string->allocated_len)
+        dap_string_maybe_expand(string, len - string->len);
+
+    string->len = len;
+    string->str[len] = 0;
+
+    return string;
+}
+
+/**
+ * dap_string_insert_len:
+ * @a_string: a #dap_string_t
+ * @a_pos: position in @a_string where insertion should
+ *       happen, or -1 for at the end
+ * @a_val: bytes to insert
+ * @a_len: number of bytes of @a_val to insert
+ *
+ * Inserts @a_len bytes of @a_val into @a_string at @a_pos.
+ * Because @a_len is provided, @a_val may contain embedded
+ * nuls and need not be nul-terminated. If @a_pos is -1,
+ * bytes are inserted at the end of the string.
+ *
+ * Since this function does not stop at nul bytes, it is
+ * the caller's responsibility to ensure that @a_val has at
+ * least @a_len addressable bytes.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_insert_len(dap_string_t *string, ssize_t pos, const char *val, ssize_t len)
+{
+    dap_return_val_if_fail(string != NULL, NULL);
+    dap_return_val_if_fail(len == 0 || val != NULL, string);
+
+    if(len == 0)
+        return string;
+
+    if(len < 0)
+        len = strlen(val);
+
+    if(pos < 0)
+        pos = string->len;
+    else
+        dap_return_val_if_fail((size_t )pos <= string->len, string);
+
+    /* Check whether val represents a substring of string.
+     * This test probably violates chapter and verse of the C standards,
+     * since ">=" and "<=" are only valid when val really is a substring.
+     * In practice, it will work on modern archs.
+     */
+    if(val >= string->str && val <= string->str + string->len)
+            {
+        size_t offset = val - string->str;
+        size_t precount = 0;
+
+        dap_string_maybe_expand(string, len);
+        val = string->str + offset;
+        /* At this point, val is valid again.  */
+
+        /* Open up space where we are going to insert.  */
+        if((size_t) pos < string->len)
+            memmove(string->str + pos + len, string->str + pos, string->len - pos);
+
+        /* Move the source part before the gap, if any.  */
+        if(offset < (size_t) pos) {
+            precount = min(len, pos - (ssize_t )offset);
+            memcpy(string->str + pos, val, precount);
+        }
+
+        /* Move the source part after the gap, if any.  */
+        if((size_t) len > precount)
+            memcpy(string->str + pos + precount,
+                    val + /* Already moved: */precount + /* Space opened up: */len,
+                    len - precount);
+    }
+    else
+    {
+        dap_string_maybe_expand(string, len);
+
+        /* If we aren't appending at the end, move a hunk
+         * of the old string to the end, opening up space
+         */
+        if((size_t) pos < string->len)
+            memmove(string->str + pos + len, string->str + pos, string->len - pos);
+
+        /* insert the new string */
+        if(len == 1)
+            string->str[pos] = *val;
+        else
+            memcpy(string->str + pos, val, len);
+    }
+
+    string->len += len;
+
+    string->str[string->len] = 0;
+
+    return string;
+}
+
+/**
+ * dap_string_append:
+ * @a_string: a #dap_string_t
+ * @a_val: the string to append onto the end of @a_string
+ *
+ * Adds a string onto the end of a #dap_string_t, expanding
+ * it if necessary.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_append(dap_string_t *string, const char *val)
+{
+    return dap_string_insert_len(string, -1, val, -1);
+}
+
+/**
+ * dap_string_append_len:
+ * @a_string: a #dap_string_t
+ * @a_val: bytes to append
+ * @a_len: number of bytes of @a_val to use
+ *
+ * Appends @a_len bytes of @a_val to @a_string. Because @a_len is
+ * provided, @a_val may contain embedded nuls and need not
+ * be nul-terminated.
+ *
+ * Since this function does not stop at nul bytes, it is
+ * the caller's responsibility to ensure that @a_val has at
+ * least @a_len addressable bytes.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_append_len(dap_string_t *string, const char *val, ssize_t len)
+{
+    return dap_string_insert_len(string, -1, val, len);
+}
+
+/**
+ * dap_string_append_c:
+ * @a_string: a #dap_string_t
+ * @a_c: the byte to append onto the end of @a_string
+ *
+ * Adds a byte onto the end of a #dap_string_t, expanding
+ * it if necessary.
+ *
+ * Returns: (transfer none): @a_string
+ */
+#undef dap_string_append_c
+dap_string_t* dap_string_append_c(dap_string_t *string, char c)
+{
+    dap_return_val_if_fail(string != NULL, NULL);
+
+    return dap_string_insert_c(string, -1, c);
+}
+
+/**
+ * dap_string_append_unichar:
+ * @a_string: a #dap_string_t
+ * @a_wc: a Unicode character
+ *
+ * Converts a Unicode character into UTF-8, and appends it
+ * to the string.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_append_unichar(dap_string_t *string, uint32_t wc)
+{
+    dap_return_val_if_fail(string != NULL, NULL);
+
+    return dap_string_insert_unichar(string, -1, wc);
+}
+
+/**
+ * dap_string_prepend:
+ * @a_string: a #dap_string_t
+ * @a_val: the string to prepend on the start of @a_string
+ *
+ * Adds a string on to the start of a #dap_string_t,
+ * expanding it if necessary.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_prepend(dap_string_t *string, const char *val)
+{
+    return dap_string_insert_len(string, 0, val, -1);
+}
+
+/**
+ * dap_string_prepend_len:
+ * @a_string: a #dap_string_t
+ * @a_val: bytes to prepend
+ * @a_len: number of bytes in @a_val to prepend
+ *
+ * Prepends @a_len bytes of @a_val to @a_string.
+ * Because @a_len is provided, @a_val may contain
+ * embedded nuls and need not be nul-terminated.
+ *
+ * Since this function does not stop at nul bytes,
+ * it is the caller's responsibility to ensure that
+ * @a_val has at least @a_len addressable bytes.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_prepend_len(dap_string_t *string, const char *val, ssize_t len)
+{
+    return dap_string_insert_len(string, 0, val, len);
+}
+
+/**
+ * dap_string_prepend_c:
+ * @a_string: a #dap_string_t
+ * @a_c: the byte to prepend on the start of the #dap_string_t
+ *
+ * Adds a byte onto the start of a #dap_string_t,
+ * expanding it if necessary.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_prepend_c(dap_string_t *string, char c)
+{
+    dap_return_val_if_fail(string != NULL, NULL);
+
+    return dap_string_insert_c(string, 0, c);
+}
+
+/**
+ * dap_string_prepend_unichar:
+ * @a_string: a #dap_string_t
+ * @a_wc: a Unicode character
+ *
+ * Converts a Unicode character into UTF-8, and prepends it
+ * to the string.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_prepend_unichar(dap_string_t *string, uint32_t wc)
+{
+    dap_return_val_if_fail(string != NULL, NULL);
+
+    return dap_string_insert_unichar(string, 0, wc);
+}
+
+/**
+ * dap_string_insert:
+ * @a_string: a #dap_string_t
+ * @a_pos: the position to insert the copy of the string
+ * @a_val: the string to insert
+ *
+ * Inserts a copy of a string into a #dap_string_t,
+ * expanding it if necessary.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_insert(dap_string_t *string, ssize_t pos, const char *val)
+{
+    return dap_string_insert_len(string, pos, val, -1);
+}
+
+/**
+ * dap_string_insert_c:
+ * @a_string: a #dap_string_t
+ * @a_pos: the position to insert the byte
+ * @a_c: the byte to insert
+ *
+ * Inserts a byte into a #dap_string_t, expanding it if necessary.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_insert_c(dap_string_t *string, ssize_t pos, char c)
+{
+    dap_return_val_if_fail(string != NULL, NULL);
+
+    dap_string_maybe_expand(string, 1);
+
+    if(pos < 0)
+        pos = string->len;
+    else
+        dap_return_val_if_fail((size_t )pos <= string->len, string);
+
+    /* If not just an append, move the old stuff */
+    if((size_t) pos < string->len)
+        memmove(string->str + pos + 1, string->str + pos, string->len - pos);
+
+    string->str[pos] = c;
+
+    string->len += 1;
+
+    string->str[string->len] = 0;
+
+    return string;
+}
+
+/**
+ * dap_string_insert_unichar:
+ * @a_string: a #dap_string_t
+ * @a_pos: the position at which to insert character, or -1
+ *     to append at the end of the string
+ * @a_wc: a Unicode character
+ *
+ * Converts a Unicode character into UTF-8, and insert it
+ * into the string at the given position.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_insert_unichar(dap_string_t *string, ssize_t pos, uint32_t wc)
+{
+    int charlen, first, i;
+    char *dest;
+
+    dap_return_val_if_fail(string != NULL, NULL);
+
+    /* Code copied from dap_unichar_to_utf() */
+    if(wc < 0x80)
+            {
+        first = 0;
+        charlen = 1;
+    }
+    else if(wc < 0x800)
+            {
+        first = 0xc0;
+        charlen = 2;
+    }
+    else if(wc < 0x10000)
+            {
+        first = 0xe0;
+        charlen = 3;
+    }
+    else if(wc < 0x200000)
+            {
+        first = 0xf0;
+        charlen = 4;
+    }
+    else if(wc < 0x4000000)
+            {
+        first = 0xf8;
+        charlen = 5;
+    }
+    else
+    {
+        first = 0xfc;
+        charlen = 6;
+    }
+    /* End of copied code */
+
+    dap_string_maybe_expand(string, charlen);
+
+    if(pos < 0)
+        pos = string->len;
+    else
+        dap_return_val_if_fail((size_t )pos <= string->len, string);
+
+    /* If not just an append, move the old stuff */
+    if((size_t) pos < string->len)
+        memmove(string->str + pos + charlen, string->str + pos, string->len - pos);
+
+    dest = string->str + pos;
+    /* Code copied from dap_unichar_to_utf() */
+    for(i = charlen - 1; i > 0; --i)
+            {
+        dest[i] = (wc & 0x3f) | 0x80;
+        wc >>= 6;
+    }
+    dest[0] = wc | first;
+    /* End of copied code */
+
+    string->len += charlen;
+
+    string->str[string->len] = 0;
+
+    return string;
+}
+
+/**
+ * dap_string_overwrite:
+ * @a_string: a #dap_string_t
+ * @a_pos: the position at which to start overwriting
+ * @a_val: the string that will overwrite the @a_string starting at @a_pos
+ *
+ * Overwrites part of a string, lengthening it if necessary.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_overwrite(dap_string_t *string, size_t pos, const char *val)
+{
+    dap_return_val_if_fail(val != NULL, string);
+    return dap_string_overwrite_len(string, pos, val, strlen(val));
+}
+
+/**
+ * dap_string_overwrite_len:
+ * @a_string: a #dap_string_t
+ * @a_pos: the position at which to start overwriting
+ * @a_val: the string that will overwrite the @a_string starting at @a_pos
+ * @a_len: the number of bytes to write from @a_val
+ *
+ * Overwrites part of a string, lengthening it if necessary.
+ * This function will work with embedded nuls.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_overwrite_len(dap_string_t *string, size_t pos, const char *val, ssize_t len)
+{
+    size_t end;
+
+    dap_return_val_if_fail(string != NULL, NULL);
+
+    if(!len)
+        return string;
+
+    dap_return_val_if_fail(val != NULL, string);
+    dap_return_val_if_fail(pos <= string->len, string);
+
+    if(len < 0)
+        len = strlen(val);
+
+    end = pos + len;
+
+    if(end > string->len)
+        dap_string_maybe_expand(string, end - string->len);
+
+    memcpy(string->str + pos, val, len);
+
+    if(end > string->len)
+            {
+        string->str[end] = '\0';
+        string->len = end;
+    }
+
+    return string;
+}
+
+/**
+ * dap_string_erase:
+ * @a_string: a #dap_string_t
+ * @a_pos: the position of the content to remove
+ * @a_len: the number of bytes to remove, or -1 to remove all
+ *       following bytes
+ *
+ * Removes @a_len bytes from a #dap_string_t, starting at position @a_pos.
+ * The rest of the #dap_string_t is shifted down to fill the gap.
+ *
+ * Returns: (transfer none): @a_string
+ */
+dap_string_t* dap_string_erase(dap_string_t *string, ssize_t pos, ssize_t len)
+{
+    dap_return_val_if_fail(string != NULL, NULL);
+    dap_return_val_if_fail(pos >= 0, string);
+    dap_return_val_if_fail((size_t )pos <= string->len, string);
+
+    if(len < 0)
+        len = string->len - pos;
+    else
+    {
+        dap_return_val_if_fail((size_t )(pos + len) <= string->len, string);
+
+        if((size_t) (pos + len) < string->len)
+            memmove(string->str + pos, string->str + pos + len, string->len - (pos + len));
+    }
+
+    string->len -= len;
+
+    string->str[string->len] = 0;
+
+    return string;
+}
+
+/**
+ * dap_string_ascii_down:
+ * @a_string: a dap_string_t
+ *
+ * Converts all uppercase ASCII letters to lowercase ASCII letters.
+ *
+ * Returns: (transfer none): passed-in @a_string pointer, with all the
+ *     uppercase characters converted to lowercase in place,
+ *     with semantics that exactly match dap_ascii_tolower().
+ */
+dap_string_t* dap_string_ascii_down(dap_string_t *string)
+{
+    char *s;
+    int n;
+
+    dap_return_val_if_fail(string != NULL, NULL);
+
+    n = string->len;
+    s = string->str;
+
+    while(n)
+    {
+        *s = tolower(*s);
+        s++;
+        n--;
+    }
+
+    return string;
+}
+
+/**
+ * dap_string_ascii_up:
+ * @a_string: a dap_string_t
+ *
+ * Converts all lowercase ASCII letters to uppercase ASCII letters.
+ *
+ * Returns: (transfer none): passed-in @a_string pointer, with all the
+ *     lowercase characters converted to uppercase in place,
+ *     with semantics that exactly match dap_ascii_toupper().
+ */
+dap_string_t* dap_string_ascii_up(dap_string_t *string)
+{
+    char *s;
+    int n;
+
+    dap_return_val_if_fail(string != NULL, NULL);
+
+    n = string->len;
+    s = string->str;
+
+    while(n)
+    {
+        *s = toupper(*s);
+        s++;
+        n--;
+    }
+
+    return string;
+}
+
+/**
+ * dap_string_down:
+ * @a_string: a #dap_string_t
+ *
+ * Converts a #dap_string_t to lowercase.
+ *
+ * Returns: (transfer none): the #dap_string_t
+ *
+ * Deprecated:2.2: This function uses the locale-specific
+ *     tolower() function, which is almost never the right thing.
+ *     Use dap_string_ascii_down() or dap_utf8_strdown() instead.
+ */
+dap_string_t* dap_string_down(dap_string_t *string)
+{
+    uint8_t *s;
+    long n;
+
+    dap_return_val_if_fail(string != NULL, NULL);
+
+    n = string->len;
+    s = (uint8_t *) string->str;
+
+    while(n)
+    {
+        if(isupper(*s))
+            *s = tolower(*s);
+        s++;
+        n--;
+    }
+
+    return string;
+}
+
+/**
+ * dap_string_up:
+ * @a_string: a #dap_string_t
+ *
+ * Converts a #dap_string_t to uppercase.
+ *
+ * Returns: (transfer none): @a_string
+ *
+ * Deprecated:2.2: This function uses the locale-specific
+ *     toupper() function, which is almost never the right thing.
+ *     Use dap_string_ascii_up() or dap_utf8_strup() instead.
+ */
+dap_string_t* dap_string_up(dap_string_t *string)
+{
+    uint8_t *s;
+    long n;
+
+    dap_return_val_if_fail(string != NULL, NULL);
+
+    n = string->len;
+    s = (uint8_t *) string->str;
+
+    while(n)
+    {
+        if(islower(*s))
+            *s = toupper(*s);
+        s++;
+        n--;
+    }
+
+    return string;
+}
+
+/**
+ * dap_string_append_vprintf:
+ * @a_string: a #dap_string_t
+ * @a_format: the string format. See the printf() documentation
+ * @a_args: the list of arguments to insert in the output
+ *
+ * Appends a formatted string onto the end of a #dap_string_t.
+ * This function is similar to dap_string_append_printf()
+ * except that the arguments to the format string are passed
+ * as a va_list.
+ */
+void dap_string_append_vprintf(dap_string_t *string, const char *format, va_list args)
+{
+    char *buf;
+    int len;
+
+    dap_return_if_fail(string != NULL);
+    dap_return_if_fail(format != NULL);
+
+    len = vasprintf(&buf, format, args);
+
+    if(len >= 0) {
+        dap_string_maybe_expand(string, len);
+        memcpy(string->str + string->len, buf, len + 1);
+        string->len += len;
+        DAP_DELETE(buf);
+    }
+}
+
+/**
+ * dap_string_vprintf:
+ * @a_string: a #dap_string_t
+ * @a_format: the string format. See the printf() documentation
+ * @a_args: the parameters to insert into the format string
+ *
+ * Writes a formatted string into a #dap_string_t.
+ * This function is similar to dap_string_printf() except that
+ * the arguments to the format string are passed as a va_list.
+ */
+void dap_string_vprintf(dap_string_t *string, const char *format, va_list args)
+{
+    dap_string_truncate(string, 0);
+    dap_string_append_vprintf(string, format, args);
+}
+
+/**
+ * dap_string_sprintf:
+ * @a_string: a #dap_string_t
+ * @a_format: the string format. See the sprintf() documentation
+ * @...: the parameters to insert into the format string
+ *
+ * Writes a formatted string into a #dap_string_t.
+ * This is similar to the standard sprintf() function,
+ * except that the #dap_string_t buffer automatically expands
+ * to contain the results. The previous contents of the
+ * #dap_string_t are destroyed.
+ *
+ * Deprecated: This function has been renamed to dap_string_printf().
+ */
+
+/**
+ * dap_string_printf:
+ * @a_string: a #dap_string_t
+ * @a_format: the string format. See the printf() documentation
+ * @...: the parameters to insert into the format string
+ *
+ * Writes a formatted string into a #dap_string_t.
+ * This is similar to the standard sprintf() function,
+ * except that the #dap_string_t buffer automatically expands
+ * to contain the results. The previous contents of the
+ * #dap_string_t are destroyed.
+ */
+void dap_string_printf(dap_string_t *string, const char *format, ...)
+{
+    va_list args;
+
+    dap_string_truncate(string, 0);
+
+    va_start(args, format);
+    dap_string_append_vprintf(string, format, args);
+    va_end(args);
+}
+
+/**
+ * dap_string_append_printf:
+ * @a_string: a #dap_string_t
+ * @a_format: the string format. See the printf() documentation
+ * @...: the parameters to insert into the format string
+ *
+ * Appends a formatted string onto the end of a #dap_string_t.
+ * This function is similar to dap_string_printf() except
+ * that the text is appended to the #dap_string_t.
+ */
+void dap_string_append_printf(dap_string_t *string, const char *format, ...)
+{
+    va_list args;
+
+    va_start(args, format);
+    dap_string_append_vprintf(string, format, args);
+    va_end(args);
+}
diff --git a/core/dap_string.h b/core/dap_string.h
new file mode 100755
index 0000000..ae4c977
--- /dev/null
+++ b/core/dap_string.h
@@ -0,0 +1,97 @@
+// dap_string_t is an object that handles the memory management of a C string for you.
+
+#ifndef __DAP_STRING_H__
+#define __DAP_STRING_H__
+
+#include <stdbool.h>
+#include <stdio.h>
+
+typedef struct _dap_string dap_string_t;
+
+struct _dap_string
+{
+    char *str;
+    size_t len;
+    size_t allocated_len;
+};
+
+dap_string_t* dap_string_new(const char *init);
+dap_string_t* dap_string_new_len(const char *init, ssize_t len);
+dap_string_t * dap_string_sized_new(size_t a_dfl_size);
+char* dap_string_free(dap_string_t *string, bool free_segment);
+
+bool dap_string_equal(const dap_string_t *v, const dap_string_t *v2);
+
+unsigned int dap_string_hash(const dap_string_t *str);
+
+dap_string_t* dap_string_assign(dap_string_t *string, const char *rval);
+
+dap_string_t* dap_string_truncate(dap_string_t *string, size_t len);
+
+dap_string_t* dap_string_set_size(dap_string_t *string, size_t len);
+
+dap_string_t* dap_string_insert_len(dap_string_t *string, ssize_t pos, const char *val, ssize_t len);
+
+dap_string_t* dap_string_append(dap_string_t *string, const char *val);
+
+dap_string_t* dap_string_append_len(dap_string_t *string, const char *val, ssize_t len);
+
+dap_string_t* dap_string_append_c(dap_string_t *string, char a_c);
+
+dap_string_t* dap_string_append_unichar(dap_string_t *string, uint32_t wc);
+
+dap_string_t* dap_string_prepend(dap_string_t *string, const char *val);
+
+dap_string_t* dap_string_prepend_c(dap_string_t *string, char a_c);
+
+dap_string_t* dap_string_prepend_unichar(dap_string_t *string, uint32_t wc);
+
+dap_string_t* dap_string_prepend_len(dap_string_t *string, const char *val, ssize_t len);
+
+dap_string_t* dap_string_insert(dap_string_t *string, ssize_t pos, const char *val);
+
+dap_string_t* dap_string_insert_c(dap_string_t *string, ssize_t pos, char a_c);
+
+dap_string_t* dap_string_insert_unichar(dap_string_t *string, ssize_t pos, uint32_t wc);
+
+dap_string_t* dap_string_overwrite(dap_string_t *string, size_t pos, const char *val);
+
+dap_string_t* dap_string_overwrite_len(dap_string_t *string, size_t pos, const char *val, ssize_t len);
+
+dap_string_t* dap_string_erase(dap_string_t *string, ssize_t pos, ssize_t len);
+
+dap_string_t* dap_string_ascii_down(dap_string_t *string);
+
+dap_string_t* dap_string_ascii_up(dap_string_t *string);
+
+void dap_string_vprintf(dap_string_t *string, const char *format, va_list args);
+void dap_string_printf(dap_string_t *string, const char *format, ...);
+void dap_string_append_vprintf(dap_string_t *string, const char *format, va_list args);
+void dap_string_append_printf(dap_string_t *string, const char *format, ...);
+
+/* -- optimize dap_strig_append_c --- */
+#ifdef G_CAN_INLINE
+static inline dap_string_t* dap_string_append_c_inline(dap_string_t *a_string, char a_c)
+{
+    if(a_string->len + 1 < a_string->allocated_len)
+    {
+        a_string->str[a_string->len++] = a_c;
+        a_string->str[a_string->len] = 0;
+    }
+    else
+    dap_string_insert_c(a_string, -1, a_c);
+    return a_string;
+}
+#define dap_string_append_c(a_string,a_c)       dap_string_append_c_inline (a_string, a_c)
+#endif /* G_CAN_INLINE */
+
+dap_string_t *dap_string_down(dap_string_t *string);
+
+dap_string_t *dap_string_up(dap_string_t *string);
+
+#ifndef G_DISABLE_DEPRECATED
+#define  dap_string_sprintf  dap_string_printf
+#define  dap_string_sprintfa dap_string_append_printf
+#endif
+
+#endif /* __DAP_STRING_H__ */
diff --git a/crypto/iaes/iaes256_cbc_cernal.c b/crypto/iaes/iaes256_cbc_cernal.c
index a598985..4163ed1 100755
--- a/crypto/iaes/iaes256_cbc_cernal.c
+++ b/crypto/iaes/iaes256_cbc_cernal.c
@@ -488,15 +488,16 @@ size_t IAES_256_CBC_decrypt(const uint8_t *cdata, uint8_t *data, uint8_t *ivec,
     }
     swap_endian((uint32_t *)masterkey, IAES_KEYSIZE/sizeof(uint32_t));
 
-    size_t i,  padding = 0;
-    size_t end = length - 16 > 0 ? length - 16 : 0;
-    for(i = length-1; i >= end; i--)
-    {
-        if(data[i] == 0)
-            padding++;
-        else
-            break;
-    }
+    size_t i, padding = 0;
+    size_t end = length > 16 ? length - 16 : 0;
+    if(length>0)
+        for(i = length-1; i >= end; i--)
+        {
+            if(data[i] == 0)
+                padding++;
+            else
+                break;
+        }
 
     return length - padding;
 }
-- 
GitLab