Vector.c 6.16 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
2
/*
htop
Hisham Muhammad's avatar
Hisham Muhammad committed
3
(C) 2004-2010 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
19
20
21
22
#include "Object.h"
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

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

/*{

#ifndef DEFAULT_SIZE
#define DEFAULT_SIZE -1
#endif

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

}*/

35
Vector* Vector_new(char* vectorType_, bool owner, int size, Object_Compare compare) {
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
45
46
   this->growthRate = size;
   this->array = (Object**) calloc(size, sizeof(Object*));
   this->arraySize = size;
   this->items = 0;
   this->vectorType = vectorType_;
   this->owner = owner;
47
   this->compare = compare;
Hisham Muhammad's avatar
Hisham Muhammad committed
48
49
50
   return this;
}

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

61
62
#ifdef DEBUG

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

85
86
#endif

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

100
void Vector_sort(Vector* this) {
101
   assert(this->compare);
102
   assert(Vector_isConsistent(this));
103
104
105
106
   Object_Compare compare = this->compare;
   /* Insertion sort works best on mostly-sorted arrays. */
   for (int i = 1; i < this->items; i++) {
      int j;
Hisham Muhammad's avatar
Hisham Muhammad committed
107
      void* t = this->array[i];
108
      for (j = i-1; j >= 0 && compare(this->array[j], t) > 0; j--)
Hisham Muhammad's avatar
Hisham Muhammad committed
109
110
111
         this->array[j+1] = this->array[j];
      this->array[j+1] = t;
   }
112
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
113
114
}

115
static void Vector_checkArraySize(Vector* this) {
116
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
117
118
119
120
121
122
123
124
   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;
   }
125
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
126
127
}

Hisham Muhammad's avatar
Hisham Muhammad committed
128
129
void Vector_insert(Vector* this, int idx, void* data_) {
   assert(idx >= 0);
Hisham Muhammad's avatar
Hisham Muhammad committed
130
131
   assert(((Object*)data_)->class == this->vectorType);
   Object* data = data_;
132
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
133
   
134
   Vector_checkArraySize(this);
Hisham Muhammad's avatar
Hisham Muhammad committed
135
   assert(this->array[this->items] == NULL);
Hisham Muhammad's avatar
Hisham Muhammad committed
136
   for (int i = this->items; i >= idx; i--) {
Hisham Muhammad's avatar
Hisham Muhammad committed
137
138
      this->array[i+1] = this->array[i];
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
139
   this->array[idx] = data;
Hisham Muhammad's avatar
Hisham Muhammad committed
140
   this->items++;
141
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
142
143
}

Hisham Muhammad's avatar
Hisham Muhammad committed
144
145
Object* Vector_take(Vector* this, int idx) {
   assert(idx >= 0 && idx < this->items);
146
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
147
   Object* removed = this->array[idx];
Hisham Muhammad's avatar
Hisham Muhammad committed
148
149
   assert (removed != NULL);
   this->items--;
Hisham Muhammad's avatar
Hisham Muhammad committed
150
   for (int i = idx; i < this->items; i++)
Hisham Muhammad's avatar
Hisham Muhammad committed
151
152
      this->array[i] = this->array[i+1];
   this->array[this->items] = NULL;
153
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
154
155
156
   return removed;
}

Hisham Muhammad's avatar
Hisham Muhammad committed
157
158
Object* Vector_remove(Vector* this, int idx) {
   Object* removed = Vector_take(this, idx);
Hisham Muhammad's avatar
Hisham Muhammad committed
159
160
161
162
163
164
165
   if (this->owner) {
      removed->delete(removed);
      return NULL;
   } else
      return removed;
}

Hisham Muhammad's avatar
Hisham Muhammad committed
166
167
void Vector_moveUp(Vector* this, int idx) {
   assert(idx >= 0 && idx < this->items);
168
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
169
   if (idx == 0)
Hisham Muhammad's avatar
Hisham Muhammad committed
170
      return;
Hisham Muhammad's avatar
Hisham Muhammad committed
171
172
173
   Object* temp = this->array[idx];
   this->array[idx] = this->array[idx - 1];
   this->array[idx - 1] = temp;
Hisham Muhammad's avatar
Hisham Muhammad committed
174
175
}

Hisham Muhammad's avatar
Hisham Muhammad committed
176
177
void Vector_moveDown(Vector* this, int idx) {
   assert(idx >= 0 && idx < this->items);
178
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
179
   if (idx == this->items - 1)
Hisham Muhammad's avatar
Hisham Muhammad committed
180
      return;
Hisham Muhammad's avatar
Hisham Muhammad committed
181
182
183
   Object* temp = this->array[idx];
   this->array[idx] = this->array[idx + 1];
   this->array[idx + 1] = temp;
Hisham Muhammad's avatar
Hisham Muhammad committed
184
185
}

Hisham Muhammad's avatar
Hisham Muhammad committed
186
187
void Vector_set(Vector* this, int idx, void* data_) {
   assert(idx >= 0);
Hisham Muhammad's avatar
Hisham Muhammad committed
188
189
   assert(((Object*)data_)->class == this->vectorType);
   Object* data = data_;
190
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
191

192
   Vector_checkArraySize(this);
Hisham Muhammad's avatar
Hisham Muhammad committed
193
194
   if (idx >= this->items) {
      this->items = idx+1;
Hisham Muhammad's avatar
Hisham Muhammad committed
195
196
   } else {
      if (this->owner) {
Hisham Muhammad's avatar
Hisham Muhammad committed
197
         Object* removed = this->array[idx];
Hisham Muhammad's avatar
Hisham Muhammad committed
198
199
200
201
202
203
         assert (removed != NULL);
         if (this->owner) {
            removed->delete(removed);
         }
      }
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
204
   this->array[idx] = data;
205
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
206
207
}

Hisham Muhammad's avatar
Hisham Muhammad committed
208
209
inline Object* Vector_get(Vector* this, int idx) {
   assert(idx < this->items);
210
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
211
   return this->array[idx];
Hisham Muhammad's avatar
Hisham Muhammad committed
212
213
}

214
215
inline int Vector_size(Vector* this) {
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
216
217
218
   return this->items;
}

219
220
221
/*

static void Vector_merge(Vector* this, Vector* v2) {
Hisham Muhammad's avatar
Hisham Muhammad committed
222
   int i;
223
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
224
225
   
   for (i = 0; i < v2->items; i++)
226
      Vector_add(this, v2->array[i]);
Hisham Muhammad's avatar
Hisham Muhammad committed
227
   v2->items = 0;
228
229
   Vector_delete(v2);
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
230
231
}

232
233
*/

234
void Vector_add(Vector* this, void* data_) {
Hisham Muhammad's avatar
Hisham Muhammad committed
235
236
   assert(data_ && ((Object*)data_)->class == this->vectorType);
   Object* data = data_;
237
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
238
   int i = this->items;
239
   Vector_set(this, this->items, data);
Hisham Muhammad's avatar
Hisham Muhammad committed
240
   assert(this->items == i+1); (void)(i);
241
   assert(Vector_isConsistent(this));
Hisham Muhammad's avatar
Hisham Muhammad committed
242
243
}

244
inline int Vector_indexOf(Vector* this, void* search_, Object_Compare compare) {
Hisham Muhammad's avatar
Hisham Muhammad committed
245
   assert(((Object*)search_)->class == this->vectorType);
246
   assert(this->compare);
Hisham Muhammad's avatar
Hisham Muhammad committed
247
   Object* search = search_;
248
   assert(Vector_isConsistent(this));
249
   for (int i = 0; i < this->items; i++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
250
      Object* o = (Object*)this->array[i];
251
      if (o && compare(search, o) == 0)
Hisham Muhammad's avatar
Hisham Muhammad committed
252
253
254
255
         return i;
   }
   return -1;
}