-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvector.c
167 lines (137 loc) · 5 KB
/
vector.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include "vector.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <search.h>
/* calls prespecified free function on vector @v s element
* @elem location of vectors element @v given vector
* if free function was not specified function does nothing */
static void freeVecElement(vector *v, void *elem){
assert(elem != NULL);//check if vector is valid
if (v->freeFn != NULL){
v->freeFn(elem);
}
}
/* function is called when we want to add new element
* to the vector. it checks if there is enough room for it
* and if its not it reallocates new space */
static void elemAddingRequiered(vector *v){
assert(v != NULL);//check if vector is valid
if (v->logicalSize == v->allocatedSize){
v->allocatedSize += v->reallocSize;
v->elems = realloc(v->elems, v->elemSize * v->allocatedSize);
assert(v->elems != NULL);
}
}
static const int DefaultAllocSize = 1;
void VectorNew(vector *v, int elemSize, VectorFreeFunction freeFn, int initialAllocation)
{
assert(v != NULL);//check if vector is valid
assert(elemSize > 0);//check for valid elemSize
if (initialAllocation <= 0) initialAllocation = DefaultAllocSize;
v->reallocSize = initialAllocation;
v->elemSize = elemSize;
v->logicalSize = 0;
v->allocatedSize = initialAllocation;
v->freeFn = freeFn;
//make place for elems
v->elems = malloc(elemSize * initialAllocation);
assert(v->elems != NULL);
}
void VectorDispose(vector *v)
{
assert(v != NULL);//check if vector is valid
if (v->freeFn != NULL){
//dispose elements one by one if free function exists
for (int i = 0; i < v->logicalSize; i++){
v->freeFn(VectorNth(v, i));
}
}
//free elems space
free(v->elems);
}
int VectorLength(const vector *v)
{
assert(v != NULL);//check if vector is valid
return v->logicalSize;
}
void *VectorNth(const vector *v, int position)
{
assert(v != NULL);//check if vector is valid
assert(position >= 0);//check for valid position value
assert(position < v->logicalSize);//check if requested is bigger then possible
return (char *)(v->elems) + (position * v->elemSize);
}
void VectorReplace(vector *v, const void *elemAddr, int position)
{
//get pointer on position element
//(if doensot exists VectorNth function will take care of it)
void *elemOnPosition = VectorNth(v, position);
freeVecElement(v, elemOnPosition);
memmove(elemOnPosition, elemAddr, v->elemSize);
}
void VectorInsert(vector *v, const void *elemAddr, int position)
{
//check if its adding at last point or not
if (position == v->logicalSize){
VectorAppend(v, elemAddr);
return;
}
//get pointer on position element
//(if doensot exists VectorNth function will take care of it)
void *elemOnPosition = VectorNth(v, position);
elemAddingRequiered(v);//make sure there is space for new element
//shifting old part by 1
memmove((char *) elemOnPosition + v->elemSize, elemOnPosition, v->elemSize * (v->logicalSize - position));
//copying new one
memmove(elemOnPosition, elemAddr, v->elemSize);
v->logicalSize++;
}
void VectorAppend(vector *v, const void *elemAddr)
{
elemAddingRequiered(v);//make sure there is space for new element
v->logicalSize++;
memmove(VectorNth(v, v->logicalSize - 1), elemAddr, v->elemSize);
}
void VectorDelete(vector *v, int position)
{
//get pointer on position element
//(if doensot exists VectorNth function will take care of it)
void *elemOnPosition = VectorNth(v, position);
freeVecElement(v, elemOnPosition);
v->logicalSize--;
memmove(elemOnPosition, (char *) elemOnPosition + v->elemSize, v->elemSize * (v->logicalSize - position));
}
void VectorSort(vector *v, VectorCompareFunction compare)
{
//sorting array using quick sort
qsort(v->elems, v->logicalSize, v->elemSize, compare);
}
void VectorMap(vector *v, VectorMapFunction mapFn, void *auxData)
{
assert(mapFn != NULL);
//iterate over all elemets
for (int i = 0; i < v->logicalSize; i++){
mapFn(VectorNth(v, i), auxData);
}
}
static const int kNotFound = -1;
int VectorSearch(const vector *v, const void *key, VectorCompareFunction searchFn, int startIndex, bool isSorted)
{
//check if vector is empty return always kNotFound
if (v->logicalSize == 0) return kNotFound;
void *startPos = VectorNth(v, startIndex);
size_t elemsNumToSearch = v->logicalSize - startIndex;
void * found;
if (isSorted){
//we know that array is sorted so we can use binary search algorithm to find it
found = bsearch(key, startPos, elemsNumToSearch, v->elemSize, searchFn);
}else{
// no guaranties that array is sorted so lfind is used to search for value
found = lfind(key, startPos, &elemsNumToSearch, v->elemSize, searchFn);
}
if (found == NULL) return kNotFound;
//if we are here and nothing retured so far key found and found is pointer to it
return ((char *)found - (char *)v->elems) / v->elemSize;
}