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

}*/

35
Vector* Vector_new(ObjectClass* type, bool owner, int size) {
36
   Vector* this;
Hisham Muhammad's avatar
Hisham Muhammad committed
37
38
39

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

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

60
61
#ifdef DEBUG

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

Hisham Muhammad's avatar
Hisham Muhammad committed
74
75
76
77
78
79
80
81
82
83
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;
}

84
85
#endif

86
87
void Vector_prune(Vector* this) {
   assert(Vector_isConsistent(this));
88
   if (this->owner) {
Hisham Muhammad's avatar
Hisham Muhammad committed
89
      for (int i = 0; i < this->items; i++)
90
         if (this->array[i]) {
91
            Object_delete(this->array[i]);
92
93
94
            //this->array[i] = NULL;
         }
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
95
96
97
   this->items = 0;
}

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
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) {
163
   assert(this->type->compare);
164
   assert(Vector_isConsistent(this));
165
   quickSort(this->array, 0, this->items - 1, this->type->compare);
166
167
168
169
   assert(Vector_isConsistent(this));
}

void Vector_insertionSort(Vector* this) {
170
   assert(this->type->compare);
171
   assert(Vector_isConsistent(this));
172
   insertionSort(this->array, 0, this->items - 1, this->type->compare);
173
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
174
175
}

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

Hisham Muhammad's avatar
Hisham Muhammad committed
189
void Vector_insert(Vector* this, int idx, void* data_) {
Hisham Muhammad's avatar
Hisham Muhammad committed
190
   Object* data = data_;
191
   assert(idx >= 0);
192
   assert(Object_isA(data, this->type));
193
   assert(Vector_isConsistent(this));
194
195
196
197

   if (idx > this->items) {
      idx = this->items;
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
198
   
199
   Vector_checkArraySize(this);
200
   //assert(this->array[this->items] == NULL);
201
202
   for (int i = this->items; i > idx; i--) {
      this->array[i] = this->array[i-1];
Hisham Muhammad's avatar
Hisham Muhammad committed
203
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
204
   this->array[idx] = data;
Hisham Muhammad's avatar
Hisham Muhammad committed
205
   this->items++;
206
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
207
208
}

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

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

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

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

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

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

273
274
#ifdef DEBUG

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

281
282
283
284
285
286
#else

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

#endif

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

292
293
294
/*

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

305
306
*/

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

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