Vector.c 7.94 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));
Hisham Muhammad's avatar
Hisham Muhammad committed
88
89
   int i;

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

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

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

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

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

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

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

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

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

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

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

272
273
#ifdef DEBUG

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

280
281
282
283
284
285
#else

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

#endif

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

291
292
293
/*

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

304
305
*/

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

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