Vector.c 8.08 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
/*
Hisham Muhammad's avatar
Hisham Muhammad committed
2
htop - Vector.c
Hisham Muhammad's avatar
Hisham Muhammad committed
3
(C) 2004-2011 Hisham H. Muhammad
Hisham Muhammad's avatar
Hisham Muhammad committed
4
5
6
7
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/

8
#include "Vector.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
9
10

#include <assert.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
11
12
13
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
14
15

/*{
Hisham Muhammad's avatar
Hisham Muhammad committed
16
#include "Object.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
17

18
19
#define swap(a_,x_,y_) do{ void* tmp_ = a_[x_]; a_[x_] = a_[y_]; a_[y_] = tmp_; }while(0)

Hisham Muhammad's avatar
Hisham Muhammad committed
20
21
22
23
#ifndef DEFAULT_SIZE
#define DEFAULT_SIZE -1
#endif

24
typedef struct Vector_ {
Hisham Muhammad's avatar
Hisham Muhammad committed
25
   Object **array;
26
   Object_Compare compare;
Hisham Muhammad's avatar
Hisham Muhammad committed
27
28
29
30
31
   int arraySize;
   int growthRate;
   int items;
   char* vectorType;
   bool owner;
32
} Vector;
Hisham Muhammad's avatar
Hisham Muhammad committed
33
34
35

}*/

36
Vector* Vector_new(char* vectorType_, bool owner, int size, Object_Compare compare) {
37
   Vector* this;
Hisham Muhammad's avatar
Hisham Muhammad committed
38
39
40

   if (size == DEFAULT_SIZE)
      size = 10;
41
   this = (Vector*) malloc(sizeof(Vector));
Hisham Muhammad's avatar
Hisham Muhammad committed
42
43
44
45
46
47
   this->growthRate = size;
   this->array = (Object**) calloc(size, sizeof(Object*));
   this->arraySize = size;
   this->items = 0;
   this->vectorType = vectorType_;
   this->owner = owner;
48
   this->compare = compare;
Hisham Muhammad's avatar
Hisham Muhammad committed
49
50
51
   return this;
}

52
void Vector_delete(Vector* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
53
54
55
56
57
58
59
60
61
   if (this->owner) {
      for (int i = 0; i < this->items; i++)
         if (this->array[i])
            (this->array[i])->delete(this->array[i]);
   }
   free(this->array);
   free(this);
}

62
63
#ifdef DEBUG

64
static inline bool Vector_isConsistent(Vector* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
65
   assert(this->items <= this->arraySize);
Hisham Muhammad's avatar
Hisham Muhammad committed
66
67
68
69
70
71
72
73
74
75
   if (this->owner) {
      for (int i = 0; i < this->items; i++)
         if (this->array[i] && this->array[i]->class != this->vectorType)
            return false;
      return true;
   } else {
      return true;
   }
}

Hisham Muhammad's avatar
Hisham Muhammad committed
76
77
78
79
80
81
82
83
84
85
int Vector_count(Vector* this) {
   int items = 0;
   for (int i = 0; i < this->items; i++) {
      if (this->array[i])
         items++;
   }
   assert(items == this->items);
   return items;
}

86
87
#endif

88
89
void Vector_prune(Vector* this) {
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
90
91
92
93
94
95
96
97
98
99
100
   int i;

   for (i = 0; i < this->items; i++)
      if (this->array[i]) {
         if (this->owner)
            (this->array[i])->delete(this->array[i]);
         this->array[i] = NULL;
      }
   this->items = 0;
}

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
static int comparisons = 0;

static int partition(Object** array, int left, int right, int pivotIndex, Object_Compare compare) {
   void* pivotValue = array[pivotIndex];
   swap(array, pivotIndex, right);
   int storeIndex = left;
   for (int i = left; i < right; i++) {
      comparisons++;
      if (compare(array[i], pivotValue) <= 0) {
         swap(array, i, storeIndex);
         storeIndex++;
      }
   }
   swap(array, storeIndex, right);
   return storeIndex;
}

static void quickSort(Object** array, int left, int right, Object_Compare compare) {
   if (left >= right)
      return;
   int pivotIndex = (left+right) / 2;
   int pivotNewIndex = partition(array, left, right, pivotIndex, compare);
   quickSort(array, left, pivotNewIndex - 1, compare);
   quickSort(array, pivotNewIndex + 1, right, compare);
}

// If I were to use only one sorting algorithm for both cases, it would probably be this one:
/*

static void combSort(Object** array, int left, int right, Object_Compare compare) {
   int gap = right - left;
   bool swapped = true;
   while ((gap > 1) || swapped) {
      if (gap > 1) {
         gap = (int)((double)gap / 1.247330950103979);
      }
      swapped = false;
      for (int i = left; gap + i <= right; i++) {
         comparisons++;
         if (compare(array[i], array[i+gap]) > 0) {
            swap(array, i, i+gap);
            swapped = true;
         }
      }
   }
}

*/

static void insertionSort(Object** array, int left, int right, Object_Compare compare) {
   for (int i = left+1; i <= right; i++) {
      void* t = array[i];
      int j = i - 1;
      while (j >= left) {
         comparisons++;
         if (compare(array[j], t) <= 0)
            break;
         array[j+1] = array[j];
         j--;
      }
      array[j+1] = t;
   }
}

void Vector_quickSort(Vector* this) {
166
   assert(this->compare);
167
   assert(Vector_isConsistent(this));
168
   Object_Compare compare = this->compare;
169
170
171
172
173
174
175
176
177
   quickSort(this->array, 0, this->items - 1, compare);
   assert(Vector_isConsistent(this));
}

void Vector_insertionSort(Vector* this) {
   assert(this->compare);
   assert(Vector_isConsistent(this));
   Object_Compare compare = this->compare;
   insertionSort(this->array, 0, this->items - 1, compare);
178
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
179
180
}

181
static void Vector_checkArraySize(Vector* this) {
182
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
183
184
185
186
187
188
189
190
   if (this->items >= this->arraySize) {
      int i;
      i = this->arraySize;
      this->arraySize = this->items + this->growthRate;
      this->array = (Object**) realloc(this->array, sizeof(Object*) * this->arraySize);
      for (; i < this->arraySize; i++)
         this->array[i] = NULL;
   }
191
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
192
193
}

Hisham Muhammad's avatar
Hisham Muhammad committed
194
195
void Vector_insert(Vector* this, int idx, void* data_) {
   assert(idx >= 0);
Hisham Muhammad's avatar
Hisham Muhammad committed
196
197
   assert(((Object*)data_)->class == this->vectorType);
   Object* data = data_;
198
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
199
   
200
   Vector_checkArraySize(this);
Hisham Muhammad's avatar
Hisham Muhammad committed
201
   assert(this->array[this->items] == NULL);
202
203
   for (int i = this->items; i > idx; i--) {
      this->array[i] = this->array[i-1];
Hisham Muhammad's avatar
Hisham Muhammad committed
204
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
205
   this->array[idx] = data;
Hisham Muhammad's avatar
Hisham Muhammad committed
206
   this->items++;
207
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
208
209
}

Hisham Muhammad's avatar
Hisham Muhammad committed
210
211
Object* Vector_take(Vector* this, int idx) {
   assert(idx >= 0 && idx < this->items);
212
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
213
   Object* removed = this->array[idx];
Hisham Muhammad's avatar
Hisham Muhammad committed
214
215
   assert (removed != NULL);
   this->items--;
Hisham Muhammad's avatar
Hisham Muhammad committed
216
   for (int i = idx; i < this->items; i++)
Hisham Muhammad's avatar
Hisham Muhammad committed
217
218
      this->array[i] = this->array[i+1];
   this->array[this->items] = NULL;
219
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
220
221
222
   return removed;
}

Hisham Muhammad's avatar
Hisham Muhammad committed
223
224
Object* Vector_remove(Vector* this, int idx) {
   Object* removed = Vector_take(this, idx);
Hisham Muhammad's avatar
Hisham Muhammad committed
225
226
227
228
229
230
231
   if (this->owner) {
      removed->delete(removed);
      return NULL;
   } else
      return removed;
}

Hisham Muhammad's avatar
Hisham Muhammad committed
232
233
void Vector_moveUp(Vector* this, int idx) {
   assert(idx >= 0 && idx < this->items);
234
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
235
   if (idx == 0)
Hisham Muhammad's avatar
Hisham Muhammad committed
236
      return;
Hisham Muhammad's avatar
Hisham Muhammad committed
237
238
239
   Object* temp = this->array[idx];
   this->array[idx] = this->array[idx - 1];
   this->array[idx - 1] = temp;
Hisham Muhammad's avatar
Hisham Muhammad committed
240
241
}

Hisham Muhammad's avatar
Hisham Muhammad committed
242
243
void Vector_moveDown(Vector* this, int idx) {
   assert(idx >= 0 && idx < this->items);
244
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
245
   if (idx == this->items - 1)
Hisham Muhammad's avatar
Hisham Muhammad committed
246
      return;
Hisham Muhammad's avatar
Hisham Muhammad committed
247
248
249
   Object* temp = this->array[idx];
   this->array[idx] = this->array[idx + 1];
   this->array[idx + 1] = temp;
Hisham Muhammad's avatar
Hisham Muhammad committed
250
251
}

Hisham Muhammad's avatar
Hisham Muhammad committed
252
253
void Vector_set(Vector* this, int idx, void* data_) {
   assert(idx >= 0);
Hisham Muhammad's avatar
Hisham Muhammad committed
254
255
   assert(((Object*)data_)->class == this->vectorType);
   Object* data = data_;
256
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
257

258
   Vector_checkArraySize(this);
Hisham Muhammad's avatar
Hisham Muhammad committed
259
260
   if (idx >= this->items) {
      this->items = idx+1;
Hisham Muhammad's avatar
Hisham Muhammad committed
261
262
   } else {
      if (this->owner) {
Hisham Muhammad's avatar
Hisham Muhammad committed
263
         Object* removed = this->array[idx];
Hisham Muhammad's avatar
Hisham Muhammad committed
264
265
266
267
268
269
         assert (removed != NULL);
         if (this->owner) {
            removed->delete(removed);
         }
      }
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
270
   this->array[idx] = data;
271
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
272
273
}

274
275
#ifdef DEBUG

Hisham Muhammad's avatar
Hisham Muhammad committed
276
277
inline Object* Vector_get(Vector* this, int idx) {
   assert(idx < this->items);
278
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
279
   return this->array[idx];
Hisham Muhammad's avatar
Hisham Muhammad committed
280
281
}

282
283
284
285
286
287
#else

#define Vector_get(v_, idx_) ((v_)->array[idx_])

#endif

288
289
inline int Vector_size(Vector* this) {
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
290
291
292
   return this->items;
}

293
294
295
/*

static void Vector_merge(Vector* this, Vector* v2) {
Hisham Muhammad's avatar
Hisham Muhammad committed
296
   int i;
297
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
298
299
   
   for (i = 0; i < v2->items; i++)
300
      Vector_add(this, v2->array[i]);
Hisham Muhammad's avatar
Hisham Muhammad committed
301
   v2->items = 0;
302
303
   Vector_delete(v2);
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
304
305
}

306
307
*/

308
void Vector_add(Vector* this, void* data_) {
Hisham Muhammad's avatar
Hisham Muhammad committed
309
310
   assert(data_ && ((Object*)data_)->class == this->vectorType);
   Object* data = data_;
311
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
312
   int i = this->items;
313
   Vector_set(this, this->items, data);
Hisham Muhammad's avatar
Hisham Muhammad committed
314
   assert(this->items == i+1); (void)(i);
315
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
316
317
}

318
inline int Vector_indexOf(Vector* this, void* search_, Object_Compare compare) {
Hisham Muhammad's avatar
Hisham Muhammad committed
319
   assert(((Object*)search_)->class == this->vectorType);
320
   assert(this->compare);
Hisham Muhammad's avatar
Hisham Muhammad committed
321
   Object* search = search_;
322
   assert(Vector_isConsistent(this));
323
   for (int i = 0; i < this->items; i++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
324
      Object* o = (Object*)this->array[i];
325
      if (o && compare(search, o) == 0)
Hisham Muhammad's avatar
Hisham Muhammad committed
326
327
328
329
         return i;
   }
   return -1;
}