Vector.c 8.1 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 "debug.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
11

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

/*{
Hisham Muhammad's avatar
Hisham Muhammad committed
18
#include "Object.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
19

20
21
#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
22
23
24
25
#ifndef DEFAULT_SIZE
#define DEFAULT_SIZE -1
#endif

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

}*/

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

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

54
void Vector_delete(Vector* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
55
56
57
58
59
60
61
62
63
   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);
}

64
65
#ifdef DEBUG

66
static inline bool Vector_isConsistent(Vector* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
67
   assert(this->items <= this->arraySize);
Hisham Muhammad's avatar
Hisham Muhammad committed
68
69
70
71
72
73
74
75
76
77
   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
78
79
80
81
82
83
84
85
86
87
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;
}

88
89
#endif

90
91
void Vector_prune(Vector* this) {
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
92
93
94
95
96
97
98
99
100
101
102
   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;
}

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
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) {
168
   assert(this->compare);
169
   assert(Vector_isConsistent(this));
170
   Object_Compare compare = this->compare;
171
172
173
174
175
176
177
178
179
   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);
180
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
181
182
}

183
static void Vector_checkArraySize(Vector* this) {
184
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
185
186
187
188
189
190
191
192
   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;
   }
193
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
194
195
}

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

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

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

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

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

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

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

276
277
#ifdef DEBUG

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

284
285
286
287
288
289
#else

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

#endif

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

295
296
297
/*

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

308
309
*/

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

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