Vector.c 8.11 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
   int arraySize;
   int growthRate;
   int items;
30
   char* type;
Hisham Muhammad's avatar
Hisham Muhammad committed
31
   bool owner;
32
} Vector;
Hisham Muhammad's avatar
Hisham Muhammad committed
33
34
35

}*/

36
Vector* Vector_new(char* type, 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
   this->growthRate = size;
   this->array = (Object**) calloc(size, sizeof(Object*));
   this->arraySize = size;
   this->items = 0;
46
   this->type = type;
Hisham Muhammad's avatar
Hisham Muhammad committed
47
   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
   if (this->owner) {
      for (int i = 0; i < this->items; i++)
68
         if (this->array[i] && this->array[i]->class != this->type)
Hisham Muhammad's avatar
Hisham Muhammad committed
69
70
71
72
73
74
75
            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
   int i;

92
93
94
   if (this->owner) {
      for (i = 0; i < this->items; i++)
         if (this->array[i]) {
Hisham Muhammad's avatar
Hisham Muhammad committed
95
            (this->array[i])->delete(this->array[i]);
96
97
98
            //this->array[i] = NULL;
         }
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
99
100
101
   this->items = 0;
}

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

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

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

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

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

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

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

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

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

277
278
#ifdef DEBUG

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

285
286
287
288
289
290
#else

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

#endif

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

296
297
298
/*

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

309
310
*/

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

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