00001
00005 #include <stdlib.h>
00006 #include <string.h>
00007 #include <errno.h>
00008
00009 #include "log.h"
00010 #include "common.h"
00011
00012 #include "vector.h"
00013
00014 cp_vector *cp_vector_create_by_option(int size,
00015 int mode,
00016 cp_copy_fn copy_item,
00017 cp_destructor_fn free_item)
00018 {
00019 cp_vector *v = calloc(1, sizeof(cp_vector));
00020 if (v == NULL)
00021 {
00022 errno = ENOMEM;
00023 return NULL;
00024 }
00025
00026 v->mem = calloc(size, sizeof(void *));
00027 if (v->mem == NULL)
00028 {
00029 errno = ENOMEM;
00030 return NULL;
00031 }
00032
00033 v->size = size;
00034 v->mode = mode;
00035 v->copy_item = copy_item;
00036 v->free_item = free_item;
00037 v->head = v->tail = 0;
00038
00039 return v;
00040 }
00041
00042 cp_vector *cp_vector_create(int size)
00043 {
00044 return cp_vector_create_by_option(size, 0, NULL, NULL);
00045 }
00046
00047 cp_vector *cp_vector_wrap(void **data, int len, int mode)
00048 {
00049 cp_vector *v = calloc(1, sizeof(cp_vector));
00050 if (v == NULL) return NULL;
00051
00052 v->mem = data;
00053 v->size = len;
00054 v->mode = mode;
00055 v->head = len;
00056 v->tail = 0;
00057
00058 return v;
00059 }
00060
00061 void cp_vector_destroy(cp_vector *v)
00062 {
00063 if (v)
00064 {
00065 if ((v->mode & COLLECTION_MODE_DEEP) && v->free_item != NULL)
00066 {
00067 int i;
00068 int n = cp_vector_size(v);
00069 void *item;
00070 for (i = 0; i < n; i++)
00071 {
00072 item = cp_vector_element_at(v, i);
00073 if (item) (*v->free_item)(item);
00074 }
00075 }
00076 free(v->mem);
00077 free(v);
00078 }
00079 }
00080
00081 void cp_vector_destroy_custom(cp_vector *v, cp_destructor_fn dtr)
00082 {
00083 if (v)
00084 {
00085 int i;
00086 int n = cp_vector_size(v);
00087
00088 if (dtr)
00089 {
00090 for (i = 0; i < n; i++)
00091 if (v->mem[i]) (*dtr)(v->mem[i]);
00092 }
00093
00094 free(v->mem);
00095 free(v);
00096 }
00097 }
00098
00099 void *cp_vector_element_at(cp_vector *v, int index)
00100 {
00101 return index >= 0 && index <= cp_vector_size(v) ? v->mem[index] : NULL;
00102 }
00103
00104 void *cp_vector_set_element(cp_vector *v, int index, void *element)
00105 {
00106 if (index < 0)
00107 {
00108 errno = EINVAL;
00109 return NULL;
00110 }
00111
00112 if (index >= v->head)
00113 v->head = index + 1;
00114
00115 if (v->head >= v->size)
00116 {
00117 v->size = index + 2;
00118 v->mem = realloc(v->mem, v->size * sizeof(void *));
00119 }
00120
00121 if ((v->mode & COLLECTION_MODE_DEEP) &&
00122 v->mem[index] != NULL && v->free_item != NULL)
00123 (*v->free_item)(v->mem[index]);
00124
00125 if ((v->mode & COLLECTION_MODE_COPY) && element != NULL && v->copy_item != NULL)
00126 v->mem[index] = (*v->copy_item)(element);
00127 else
00128 v->mem[index] = element;
00129
00130 return element;
00131 }
00132
00133 void *cp_vector_add_element(cp_vector *v, void *element)
00134 {
00135 void *addr = NULL;
00136
00137 if (v->head + 1 >= v->tail + v->size)
00138 {
00139 void **newptr = realloc(v->mem, 2 * v->size * sizeof(void *));
00140 if (newptr == NULL) return NULL;
00141 v->mem = newptr;
00142 if (v->head < v->tail)
00143 {
00144 memcpy(v->mem, &v->mem[v->size], v->head * sizeof(void *));
00145 v->head += v->size;
00146 }
00147 v->size *= 2;
00148 }
00149
00150 if (v->mode & COLLECTION_MODE_COPY)
00151 v->mem[v->head] = (*v->copy_item)(element);
00152 else
00153 v->mem[v->head] = element;
00154 addr = v->mem[v->head];
00155 v->head = (v->head + 1) % v->size;
00156
00157 return addr;
00158 }
00159
00160 void *cp_vector_remove_element_at(cp_vector *v, int index)
00161 {
00162 void *rm = NULL;
00163 if (index >= v->head || index < 0) return NULL;
00164 rm = v->mem[index];
00165 memmove(&v->mem[index], &v->mem[index + 1],
00166 (v->head - index) * sizeof(void *));
00167 v->head--;
00168 return rm;
00169 }
00170
00171 int cp_vector_size(cp_vector *v)
00172 {
00173 return (v->head - v->tail + v->size) % v->size;
00174 }
00175