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));
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
192
   assert(idx >= 0);
   assert(idx <= this->items);
193
   assert(Object_isA(data, this->type));
194
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
195
   
196
   Vector_checkArraySize(this);
197
   //assert(this->array[this->items] == NULL);
198
199
   for (int i = this->items; i > idx; i--) {
      this->array[i] = this->array[i-1];
Hisham Muhammad's avatar
Hisham Muhammad committed
200
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
201
   this->array[idx] = data;
Hisham Muhammad's avatar
Hisham Muhammad committed
202
   this->items++;
203
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
204
205
}

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

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

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

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

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

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

270
271
#ifdef DEBUG

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

278
279
280
281
282
283
#else

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

#endif

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

289
290
291
/*

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

302
303
*/

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

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