Browse Source

update array, add vector

joe 4 years ago
parent
commit
30d975956f
13 changed files with 226 additions and 33 deletions
  1. 3 1
      .gitignore
  2. 1 0
      Makefile
  3. 4 8
      include/ds/array.h
  4. 5 5
      include/ds/common.h
  5. 15 0
      include/ds/vector.h
  6. 34 9
      src/array.c
  7. 2 2
      src/bitree.c
  8. 12 3
      src/common.c
  9. 125 0
      src/vector.c
  10. 5 4
      test/test.c
  11. 17 0
      test/test_array.h
  12. 2 1
      test/test_bitree.h
  13. 1 0
      test/test_vector.h

+ 3 - 1
.gitignore

@@ -1,3 +1,5 @@
 bin/
 build/
-.vscode/
+.vscode/
+.kdev4/
+*.kdev4

+ 1 - 0
Makefile

@@ -0,0 +1 @@
+

+ 4 - 8
include/ds/array.h

@@ -7,20 +7,16 @@
 
 #include "common.h"
 
-typedef struct ds_array_t {
-  int size;
-  func_destroyer destroyer;
-  ds_data_t *ptr;
-}ds_array_t;
 
-ds_array_t *  ds_array_init(func_destroyer destroyer, int size);
+typedef struct _ds_array ds_array_t;
+
+ds_array_t *  ds_array_new(int size, func_destroyer destroyer);
 void          ds_array_destroy(ds_array_t* arr);
 
 int           ds_array_get(ds_array_t* arr, int pos, ds_data_t* data);
 int           ds_array_set(ds_array_t* arr, int pos, ds_data_t data);
 
 int           ds_array_fill(ds_array_t* arr, ds_data_t data);
-
-#define ds_array_size(arr) ((arr)->size)
+int           ds_array_size(ds_array_t* arr);
 
 #endif

+ 5 - 5
include/ds/common.h

@@ -6,8 +6,8 @@
 // data type
 typedef void* ds_data_t;
 
-// function used for traversal a container
-typedef void (*func_each)(void*);
+// function used for traversal a container, stop traversal when return 0
+typedef int (*func_each)(ds_data_t);
 typedef void (*func_destroyer)(ds_data_t);
 // function used for comparing two values
 typedef int (*func_comparer)(ds_data_t, ds_data_t);
@@ -16,7 +16,7 @@ typedef int (*func_sort)(func_comparer comparer);
 
 // memory
 typedef void* (*func_malloc)(size_t);
-typedef void (*func_free)(void* ptr);
+typedef void (*func_free)(void*);
 
 // install new mem-allocate function
 void ds_setup(func_malloc m, func_free f);
@@ -29,8 +29,8 @@ int ds_cb_default_comparer(ds_data_t, ds_data_t);
 #define IMPL_FOREACH \
   (void*)0
 
-#define UNUSED(x) (void)(x)
+#define UNUSED(x) (void*)(x)
 
-#define DEF_ARRAY_SIZE 32
+#define DS_DEF_ARRAY_SIZE 32
 
 #endif

+ 15 - 0
include/ds/vector.h

@@ -4,5 +4,20 @@
 /**
  * Vector
  */
+#include "common.h"
+
+typedef struct _ds_vector ds_vector_t;
+
+ds_vector_t*ds_vector_new(func_destroyer destroyer);
+int         ds_vector_append(ds_vector_t * vec, ds_data_t data);
+int         ds_vector_get(ds_vector_t * vec, int pos, ds_data_t *ret);
+int         ds_vector_set(ds_vector_t * vec, int pos, ds_data_t data);
+#define     ds_vector_at ds_vector_get
+
+int         ds_vector_poptail(ds_vector_t * vec, ds_data_t *ret);
+void        ds_vector_destroy(ds_vector_t * vec);
+void        ds_vector_foreach(ds_vector_t * vec, func_each fn);
+int         ds_vector_size(ds_vector_t * vec);
+int         ds_vector_cap(ds_vector_t * vec);
 
 #endif  // vector

+ 34 - 9
src/array.c

@@ -1,10 +1,17 @@
 #include <ds/array.h>
 #include <ds/err.h>
+#include <string.h>
 
 extern func_malloc ds_malloc;
 extern func_free ds_free;
 
-ds_array_t*  ds_array_init(func_destroyer destroyer, int size)
+struct _ds_array {
+  int size;
+  func_destroyer destroyer;
+  ds_data_t *ptr;
+};
+
+ds_array_t*  ds_array_new(int size, func_destroyer destroyer)
 {
   ds_array_t* arr = (ds_array_t*)ds_malloc(sizeof(ds_array_t));
   if (!arr) {
@@ -12,14 +19,17 @@ ds_array_t*  ds_array_init(func_destroyer destroyer, int size)
   }
 
   if(size <= 0) {
-    size = DEF_ARRAY_SIZE;
+    size = DS_DEF_ARRAY_SIZE;
   }
   arr->ptr = (ds_data_t*)ds_malloc(sizeof(ds_data_t) * size);
   if(!arr->ptr) {
     ds_free(arr);
     return NULL;
   }
-  arr->destroyer = destroyer;
+  memset(arr->ptr, 0, sizeof(ds_data_t) * size);
+  
+  arr->size = size;
+  arr->destroyer = destroyer?destroyer:ds_cb_default_destroyer;
   return arr;
 }
 
@@ -29,11 +39,13 @@ void ds_array_destroy(ds_array_t* arr)
   if(!arr) {
     return;
   }
-  for(i=0; i<arr->size; i++) {
-    if(arr->destroyer) {
-      arr->destroyer(arr->ptr+i);
+  for(i=arr->size - 1; i>0; i--) {
+    if(arr->ptr[i]) {
+      arr->destroyer(arr->ptr[i]);
     }
   }
+  ds_free(arr->ptr);
+  ds_free(arr);
 }
 
 int ds_array_get(ds_array_t* arr, int pos, ds_data_t* data)
@@ -41,7 +53,7 @@ int ds_array_get(ds_array_t* arr, int pos, ds_data_t* data)
   if(!arr) {
     return DS_ERR_PARAMS;
   }
-  if(pos >= arr->size){
+  if(pos >= arr->size || pos < 0){
     return DS_ERR_PARAMS;
   }
   if(data){
@@ -55,9 +67,14 @@ int ds_array_set(ds_array_t* arr, int pos, ds_data_t data)
   if(!arr) {
     return DS_ERR_PARAMS;
   }
-  if(pos >= arr->size){
+  if(pos >= arr->size || pos < 0){
     return DS_ERR_PARAMS;
   }
+  // if occupied
+  if( arr->ptr[pos]) {
+    arr->destroyer(arr->ptr[pos]);
+  }
+  
   arr->ptr[pos] = data;
   return DS_ERR_OK;
 }
@@ -69,8 +86,16 @@ int ds_array_fill(ds_array_t* arr, ds_data_t data)
   }
   int i;
   for (i=0; i<arr->size; i++){
+    if (arr->ptr[i]) {
+        arr->destroyer(arr->ptr[i]);
+    }
     arr->ptr[i] = data;
   }
 
   return DS_ERR_OK;
-}
+}
+
+inline int           ds_array_size(ds_array_t* arr)
+{
+    return arr->size;
+}

+ 2 - 2
src/bitree.c

@@ -4,7 +4,7 @@
 extern func_malloc ds_malloc;
 extern func_free ds_free;
 
-ds_bitree_t* ds_bitree_init(func_each destroyer)
+ds_bitree_t* ds_bitree_init(func_destroyer destroyer)
 {
   ds_bitree_t* tree = (ds_bitree_t*)ds_malloc(sizeof(ds_bitree_t));
   if (!tree) {
@@ -191,4 +191,4 @@ void ds_bitree_postorder(ds_bitree_node_t* node, func_each each)
       each(node);
     }
   }
-}
+}

+ 12 - 3
src/common.c

@@ -1,10 +1,14 @@
 #include <ds/common.h>
-#include <memory.h>
+#include <stdlib.h>
 
 func_malloc ds_malloc = malloc;
 func_free ds_free = free;
 
 void ds_setup(func_malloc m, func_free f){
+  if(!m || !f) {
+      return;
+  }
+  
   ds_malloc = m;
   ds_free = f;
 }
@@ -17,5 +21,10 @@ void ds_cb_default_destroyer(ds_data_t data){
 void ds_cb_default_each(ds_data_t data) {}
 
 int ds_cb_default_comparer(ds_data_t left, ds_data_t right) {
-  return left == right;
-}
+    if (left > right) {
+        return 1;
+    } else if (left < right) {
+        return -1;
+    }
+    return 0;
+}

+ 125 - 0
src/vector.c

@@ -1 +1,126 @@
 #include <ds/vector.h>
+#include <ds/err.h>
+#include <string.h>
+
+extern func_malloc ds_malloc;
+extern func_free ds_free;
+
+struct _ds_vector {
+    int size;
+    int cap;
+    ds_data_t *ptr;
+    func_destroyer destroyer;
+};
+
+ds_vector_t*ds_vector_new(func_destroyer destroyer)
+{
+    ds_vector_t * vec = (ds_vector_t*) ds_malloc(sizeof(ds_vector_t));
+    if (!vec) {
+        return NULL;
+    }
+    
+    vec->cap = DS_DEF_ARRAY_SIZE;
+    vec->size = 0;
+    vec->ptr = (ds_data_t*)ds_malloc(sizeof(ds_data_t) * vec->cap);
+    if (!vec->ptr) {
+        ds_free(vec);
+        return NULL;
+    }
+    memset(vec->ptr, 0, sizeof(ds_data_t) * vec->cap);
+    vec->destroyer = destroyer ? destroyer : ds_cb_default_destroyer;
+    
+    return vec;
+}
+
+int        ds_vector_append(ds_vector_t * vec, ds_data_t data)
+{
+    if(vec->size >= vec->cap - 1) {
+        int old_cap = vec->cap;
+        vec->cap += DS_DEF_ARRAY_SIZE;
+        ds_data_t *new_ptr = (ds_data_t*) ds_malloc ( sizeof(ds_data_t) * vec->cap);    
+        if (!new_ptr){
+            vec->cap = old_cap;
+            return DS_ERR_MEM;
+        }
+        memcpy(new_ptr, vec->ptr, sizeof(ds_data_t) * vec->size);
+        ds_free(vec->ptr);
+        vec->ptr = new_ptr;
+    }
+    
+    vec->ptr[vec->size++] = data;
+    return DS_ERR_OK;
+}
+
+
+int         ds_vector_get(ds_vector_t * vec, int pos, ds_data_t *ret)
+{
+    if(!vec || !ret) return DS_ERR_PARAMS;
+    if(pos < 0 || pos >= vec->size) return DS_ERR_PARAMS;
+    
+    *ret = vec->ptr[pos];
+    return DS_ERR_OK;
+}
+
+int         ds_vector_set(ds_vector_t * vec, int pos, ds_data_t data)
+{
+    if(!vec) return DS_ERR_MEM;
+    if(pos < 0 || pos >= vec->size) return DS_ERR_MEM;
+    
+    if(vec->ptr[pos]) {
+        vec->destroyer(vec->ptr[pos]);
+    }
+    
+    vec->ptr[pos] = data;
+    return DS_ERR_OK;
+}
+
+int         ds_vector_poptail(ds_vector_t * vec, ds_data_t *ret)
+{
+    if(!vec || !ret) return DS_ERR_PARAMS;
+    if(vec->size <= 0) return DS_ERR_EMPTY;
+    
+    *ret = vec->ptr[vec->size--];
+    return DS_ERR_OK;
+}
+
+void        ds_vector_destroy(ds_vector_t * vec)
+{
+    if (!vec) {
+        return;
+    }
+    
+    // release userdata
+    for(int i = 0; i < vec->size; i++) {
+        if ( vec->ptr[i]) {
+            vec->destroyer(vec->ptr[i]);
+        }
+    }
+    
+    ds_free(vec->ptr);
+    ds_free(vec);
+}
+
+void        ds_vector_foreach(ds_vector_t * vec, func_each fn)
+{
+    if(!vec || !fn) {
+        return;
+    }
+    
+    for(int i = 0; i < vec->size; i++) {
+        if(fn) {
+            if(!fn(vec->ptr[i])) {
+                break;
+            }
+        }
+    }
+}
+
+inline int         ds_vector_size(ds_vector_t * vec)
+{
+    return vec->size;
+}
+
+inline int         ds_vector_cap(ds_vector_t * vec)
+{
+    return vec->cap;
+}

+ 5 - 4
test/test.c

@@ -2,16 +2,17 @@
 #include <stdarg.h>
 #include <stddef.h>
 #include <google/cmockery.h>
+#include "test_array.h"
 #include "test_list.h"
 #include "test_dlist.h"
 #include "test_bitree.h"
 
 int main() {
   const UnitTest tests[] = {
-      unit_test(test_list_generally),
-      unit_test(test_dlist_generally),
-      unit_test(test_bitree_generally),
+      unit_test(test_array_generally),
+      //unit_test(test_dlist_generally),
+      //unit_test(test_bitree_generally),
   };
   
   return run_tests(tests);
-}
+}

+ 17 - 0
test/test_array.h

@@ -0,0 +1,17 @@
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <google/cmockery.h>
+#include <ds.h>
+
+
+void test_array_generally(void **state) 
+{
+    ds_array_t* arr = ds_array_new(0, NULL);
+    assert_true(arr != NULL);
+    assert_true(ds_array_size(arr) == DS_DEF_ARRAY_SIZE);
+    
+    ds_array_destroy(arr);
+    assert_true(arr != NULL); // in face arr is freed, should never use again.
+}

+ 2 - 1
test/test_bitree.h

@@ -9,9 +9,10 @@
 #include <google/cmockery.h>
 #include <ds.h>
 
-void tree_printer(void* node){
+int tree_printer(void* node){
   ds_bitree_node_t* n = (ds_bitree_node_t*)node;
   printf("%d\n", (int)ds_bitree_data(n));
+  return 1;
 }
 
 void test_bitree_generally(void **state) {

+ 1 - 0
test/test_vector.h

@@ -0,0 +1 @@
+