Vector.c 8.09 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
2
/*
htop
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
11
12
13
14
15
16
17
18
#include "Object.h"
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#include "debug.h"
#include <assert.h>

/*{

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

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

}*/

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

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

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

63
64
#ifdef DEBUG

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

87
88
#endif

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

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
185
186
187
188
189
190
191
   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;
   }
192
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
193
194
}

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

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

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

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

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

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

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

275
276
#ifdef DEBUG

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

283
284
285
286
287
288
#else

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

#endif

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

294
295
296
/*

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

307
308
*/

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

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