]> git.saurik.com Git - apple/icu.git/blob - icuSources/common/uvector.cpp
ICU-3.13.tar.gz
[apple/icu.git] / icuSources / common / uvector.cpp
1 /*
2 ******************************************************************************
3 * Copyright (C) 1999-2001, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 ******************************************************************************
6 * Date Name Description
7 * 10/22/99 alan Creation.
8 **********************************************************************
9 */
10
11 #include "uvector.h"
12 #include "cmemory.h"
13
14 U_NAMESPACE_BEGIN
15
16 #define DEFUALT_CAPACITY 8
17
18 /*
19 * Constants for hinting whether a key is an integer
20 * or a pointer. If a hint bit is zero, then the associated
21 * token is assumed to be an integer. This is needed for iSeries
22 */
23 #define HINT_KEY_POINTER (1)
24 #define HINT_KEY_INTEGER (0)
25
26 const char UVector::fgClassID=0;
27
28 UVector::UVector(UErrorCode &status) :
29 count(0),
30 capacity(0),
31 elements(0),
32 deleter(0),
33 comparer(0)
34 {
35 _init(DEFUALT_CAPACITY, status);
36 }
37
38 UVector::UVector(int32_t initialCapacity, UErrorCode &status) :
39 count(0),
40 capacity(0),
41 elements(0),
42 deleter(0),
43 comparer(0)
44 {
45 _init(initialCapacity, status);
46 }
47
48 UVector::UVector(UObjectDeleter *d, UKeyComparator *c, UErrorCode &status) :
49 count(0),
50 capacity(0),
51 elements(0),
52 deleter(d),
53 comparer(c)
54 {
55 _init(DEFUALT_CAPACITY, status);
56 }
57
58 UVector::UVector(UObjectDeleter *d, UKeyComparator *c, int32_t initialCapacity, UErrorCode &status) :
59 count(0),
60 capacity(0),
61 elements(0),
62 deleter(d),
63 comparer(c)
64 {
65 _init(initialCapacity, status);
66 }
67
68 void UVector::_init(int32_t initialCapacity, UErrorCode &status) {
69 // Fix bogus initialCapacity values; avoid malloc(0)
70 if (initialCapacity < 1) {
71 initialCapacity = DEFUALT_CAPACITY;
72 }
73 elements = (UHashTok *)uprv_malloc(sizeof(UHashTok)*initialCapacity);
74 if (elements == 0) {
75 status = U_MEMORY_ALLOCATION_ERROR;
76 } else {
77 capacity = initialCapacity;
78 }
79 }
80
81 UVector::~UVector() {
82 removeAllElements();
83 uprv_free(elements);
84 elements = 0;
85 }
86
87 /**
88 * Assign this object to another (make this a copy of 'other').
89 * Use the 'assign' function to assign each element.
90 */
91 void UVector::assign(const UVector& other, UTokenAssigner *assign, UErrorCode &ec) {
92 if (ensureCapacity(other.count, ec)) {
93 setSize(other.count);
94 for (int32_t i=0; i<other.count; ++i) {
95 if (elements[i].pointer != 0 && deleter != 0) {
96 (*deleter)(elements[i].pointer);
97 }
98 (*assign)(&elements[i], &other.elements[i]);
99 }
100 }
101 }
102
103 // This only does something sensible if this object has a non-null comparer
104 UBool UVector::operator==(const UVector& other) {
105 int32_t i;
106 if (count != other.count) return FALSE;
107 if (comparer != NULL) {
108 // Compare using this object's comparer
109 for (i=0; i<count; ++i) {
110 if (!(*comparer)(elements[i], other.elements[i])) {
111 return FALSE;
112 }
113 }
114 }
115 return TRUE;
116 }
117
118 void UVector::addElement(void* obj, UErrorCode &status) {
119 if (ensureCapacity(count + 1, status)) {
120 elements[count++].pointer = obj;
121 }
122 }
123
124 void UVector::addElement(int32_t elem, UErrorCode &status) {
125 if (ensureCapacity(count + 1, status)) {
126 elements[count].pointer = NULL; // Pointers may be bigger than ints.
127 elements[count].integer = elem;
128 count++;
129 }
130 }
131
132 void UVector::setElementAt(void* obj, int32_t index) {
133 if (0 <= index && index < count) {
134 if (elements[index].pointer != 0 && deleter != 0) {
135 (*deleter)(elements[index].pointer);
136 }
137 elements[index].pointer = obj;
138 }
139 /* else index out of range */
140 }
141
142 void UVector::setElementAt(int32_t elem, int32_t index) {
143 if (0 <= index && index < count) {
144 if (elements[index].pointer != 0 && deleter != 0) {
145 // TODO: this should be an error. mixing up ints and pointers.
146 (*deleter)(elements[index].pointer);
147 }
148 elements[index].pointer = NULL;
149 elements[index].integer = elem;
150 }
151 /* else index out of range */
152 }
153
154 void UVector::insertElementAt(void* obj, int32_t index, UErrorCode &status) {
155 // must have 0 <= index <= count
156 if (0 <= index && index <= count && ensureCapacity(count + 1, status)) {
157 for (int32_t i=count; i>index; --i) {
158 elements[i] = elements[i-1];
159 }
160 elements[index].pointer = obj;
161 ++count;
162 }
163 /* else index out of range */
164 }
165
166 void UVector::insertElementAt(int32_t elem, int32_t index, UErrorCode &status) {
167 // must have 0 <= index <= count
168 if (0 <= index && index <= count && ensureCapacity(count + 1, status)) {
169 for (int32_t i=count; i>index; --i) {
170 elements[i] = elements[i-1];
171 }
172 elements[index].pointer = NULL;
173 elements[index].integer = elem;
174 ++count;
175 }
176 /* else index out of range */
177 }
178
179 void* UVector::elementAt(int32_t index) const {
180 return (0 <= index && index < count) ? elements[index].pointer : 0;
181 }
182
183 int32_t UVector::elementAti(int32_t index) const {
184 return (0 <= index && index < count) ? elements[index].integer : 0;
185 }
186
187 UBool UVector::containsAll(const UVector& other) const {
188 for (int32_t i=0; i<other.size(); ++i) {
189 if (indexOf(other.elements[i]) < 0) {
190 return FALSE;
191 }
192 }
193 return TRUE;
194 }
195
196 UBool UVector::containsNone(const UVector& other) const {
197 for (int32_t i=0; i<other.size(); ++i) {
198 if (indexOf(other.elements[i]) >= 0) {
199 return FALSE;
200 }
201 }
202 return TRUE;
203 }
204
205 UBool UVector::removeAll(const UVector& other) {
206 UBool changed = FALSE;
207 for (int32_t i=0; i<other.size(); ++i) {
208 int32_t j = indexOf(other.elements[i]);
209 if (j >= 0) {
210 removeElementAt(j);
211 changed = TRUE;
212 }
213 }
214 return changed;
215 }
216
217 UBool UVector::retainAll(const UVector& other) {
218 UBool changed = FALSE;
219 for (int32_t j=size()-1; j>=0; --j) {
220 int32_t i = other.indexOf(elements[j]);
221 if (i < 0) {
222 removeElementAt(j);
223 changed = TRUE;
224 }
225 }
226 return changed;
227 }
228
229 void UVector::removeElementAt(int32_t index) {
230 void* e = orphanElementAt(index);
231 if (e != 0 && deleter != 0) {
232 (*deleter)(e);
233 }
234 }
235
236 UBool UVector::removeElement(void* obj) {
237 int32_t i = indexOf(obj);
238 if (i >= 0) {
239 removeElementAt(i);
240 return TRUE;
241 }
242 return FALSE;
243 }
244
245 void UVector::removeAllElements(void) {
246 if (deleter != 0) {
247 for (int32_t i=0; i<count; ++i) {
248 if (elements[i].pointer != 0) {
249 (*deleter)(elements[i].pointer);
250 }
251 }
252 }
253 count = 0;
254 }
255
256 UBool UVector::equals(const UVector &other) const {
257 int i;
258
259 if (this->count != other.count) {
260 return FALSE;
261 }
262 if (comparer == 0) {
263 for (i=0; i<count; i++) {
264 if (elements[i].pointer != other.elements[i].pointer) {
265 return FALSE;
266 }
267 }
268 } else {
269 UHashTok key;
270 for (i=0; i<count; i++) {
271 key.pointer = &other.elements[i];
272 if (!(*comparer)(key, elements[i])) {
273 return FALSE;
274 }
275 }
276 }
277 return TRUE;
278 }
279
280
281
282 int32_t UVector::indexOf(void* obj, int32_t startIndex) const {
283 UHashTok key;
284 key.pointer = obj;
285 return indexOf(key, startIndex, HINT_KEY_POINTER);
286 }
287
288 int32_t UVector::indexOf(int32_t obj, int32_t startIndex) const {
289 UHashTok key;
290 key.integer = obj;
291 return indexOf(key, startIndex, HINT_KEY_INTEGER);
292 }
293
294 // This only works if this object has a non-null comparer
295 int32_t UVector::indexOf(UHashTok key, int32_t startIndex, int8_t hint) const {
296 int32_t i;
297 if (comparer != 0) {
298 for (i=startIndex; i<count; ++i) {
299 if ((*comparer)(key, elements[i])) {
300 return i;
301 }
302 }
303 } else {
304 for (i=startIndex; i<count; ++i) {
305 /* Pointers are not always the same size as ints so to perform
306 * a valid comparision we need to know whether we are being
307 * provided an int or a pointer. */
308 if (hint & HINT_KEY_POINTER) {
309 if (key.pointer == elements[i].pointer) {
310 return i;
311 }
312 } else {
313 if (key.integer == elements[i].integer) {
314 return i;
315 }
316 }
317 }
318 }
319 return -1;
320 }
321
322 UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) {
323 if (capacity >= minimumCapacity) {
324 return TRUE;
325 } else {
326 int32_t newCap = capacity * 2;
327 if (newCap < minimumCapacity) {
328 newCap = minimumCapacity;
329 }
330 UHashTok* newElems = (UHashTok *)uprv_malloc(sizeof(UHashTok)*newCap);
331 if (newElems == 0) {
332 status = U_MEMORY_ALLOCATION_ERROR;
333 return FALSE;
334 }
335 uprv_memcpy(newElems, elements, sizeof(elements[0]) * count);
336 uprv_free(elements);
337 elements = newElems;
338 capacity = newCap;
339 return TRUE;
340 }
341 }
342
343 /**
344 * Change the size of this vector as follows: If newSize is smaller,
345 * then truncate the array, possibly deleting held elements for i >=
346 * newSize. If newSize is larger, grow the array, filling in new
347 * slots with NULL.
348 */
349 void UVector::setSize(int32_t newSize) {
350 int32_t i;
351 if (newSize < 0) {
352 return;
353 }
354 if (newSize > count) {
355 UErrorCode ec = U_ZERO_ERROR;
356 if (!ensureCapacity(newSize, ec)) {
357 return;
358 }
359 UHashTok empty;
360 empty.pointer = NULL;
361 empty.integer = 0;
362 for (i=count; i<newSize; ++i) {
363 elements[i] = empty;
364 }
365 } else {
366 /* Most efficient to count down */
367 for (i=count-1; i>=newSize; --i) {
368 removeElementAt(i);
369 }
370 }
371 count = newSize;
372 }
373
374 /**
375 * Fill in the given array with all elements of this vector.
376 */
377 void** UVector::toArray(void** result) const {
378 void** a = result;
379 for (int i=0; i<count; ++i) {
380 *a++ = elements[i].pointer;
381 }
382 return result;
383 }
384
385 UObjectDeleter *UVector::setDeleter(UObjectDeleter *d) {
386 UObjectDeleter *old = deleter;
387 deleter = d;
388 return old;
389 }
390
391 UKeyComparator *UVector::setComparer(UKeyComparator *d) {
392 UKeyComparator *old = comparer;
393 comparer = d;
394 return old;
395 }
396
397 /**
398 * Removes the element at the given index from this vector and
399 * transfer ownership of it to the caller. After this call, the
400 * caller owns the result and must delete it and the vector entry
401 * at 'index' is removed, shifting all subsequent entries back by
402 * one index and shortening the size of the vector by one. If the
403 * index is out of range or if there is no item at the given index
404 * then 0 is returned and the vector is unchanged.
405 */
406 void* UVector::orphanElementAt(int32_t index) {
407 void* e = 0;
408 if (0 <= index && index < count) {
409 e = elements[index].pointer;
410 for (int32_t i=index; i<count-1; ++i) {
411 elements[i] = elements[i+1];
412 }
413 --count;
414 }
415 /* else index out of range */
416 return e;
417 }
418
419 /**
420 * Insert the given object into this vector at its sorted position
421 * as defined by 'compare'. The current elements are assumed to
422 * be sorted already.
423 */
424 void UVector::sortedInsert(void* obj, USortComparator *compare, UErrorCode& ec) {
425 UHashTok tok;
426 tok.pointer = obj;
427 sortedInsert(tok, compare, ec);
428 }
429
430 /**
431 * Insert the given integer into this vector at its sorted position
432 * as defined by 'compare'. The current elements are assumed to
433 * be sorted already.
434 */
435 void UVector::sortedInsert(int32_t obj, USortComparator *compare, UErrorCode& ec) {
436 UHashTok tok;
437 tok.integer = obj;
438 sortedInsert(tok, compare, ec);
439 }
440
441 // ASSUME elements[] IS CURRENTLY SORTED
442 void UVector::sortedInsert(UHashTok tok, USortComparator *compare, UErrorCode& ec) {
443 // Perform a binary search for the location to insert tok at. Tok
444 // will be inserted between two elements a and b such that a <=
445 // tok && tok < b, where there is a 'virtual' elements[-1] always
446 // less than tok and a 'virtual' elements[count] always greater
447 // than tok.
448 int32_t min = 0, max = count;
449 while (min != max) {
450 int32_t probe = (min + max) / 2;
451 int8_t c = (*compare)(elements[probe], tok);
452 if (c > 0) {
453 max = probe;
454 } else {
455 // assert(c <= 0);
456 min = probe + 1;
457 }
458 }
459 if (ensureCapacity(count + 1, ec)) {
460 for (int32_t i=count; i>min; --i) {
461 elements[i] = elements[i-1];
462 }
463 elements[min] = tok;
464 ++count;
465 }
466 }
467
468 const char UStack::fgClassID=0;
469
470 UStack::UStack(UErrorCode &status) :
471 UVector(status)
472 {
473 }
474
475 UStack::UStack(int32_t initialCapacity, UErrorCode &status) :
476 UVector(initialCapacity, status)
477 {
478 }
479
480 UStack::UStack(UObjectDeleter *d, UKeyComparator *c, UErrorCode &status) :
481 UVector(d, c, status)
482 {
483 }
484
485 UStack::UStack(UObjectDeleter *d, UKeyComparator *c, int32_t initialCapacity, UErrorCode &status) :
486 UVector(d, c, initialCapacity, status)
487 {
488 }
489
490 void* UStack::pop(void) {
491 int32_t n = size() - 1;
492 void* result = 0;
493 if (n >= 0) {
494 result = elementAt(n);
495 removeElementAt(n);
496 }
497 return result;
498 }
499
500 int32_t UStack::popi(void) {
501 int32_t n = size() - 1;
502 int32_t result = 0;
503 if (n >= 0) {
504 result = elementAti(n);
505 removeElementAt(n);
506 }
507 return result;
508 }
509
510 int32_t UStack::search(void* obj) const {
511 int32_t i = indexOf(obj);
512 return (i >= 0) ? size() - i : i;
513 }
514
515 U_NAMESPACE_END
516