Imported Upstream version 58.1
[platform/upstream/icu.git] / source / common / uvectr32.cpp
1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 ******************************************************************************
5 * Copyright (C) 1999-2015, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ******************************************************************************
8 *   Date        Name        Description
9 *   10/22/99    alan        Creation.
10 **********************************************************************
11 */
12
13 #include "uvectr32.h"
14 #include "cmemory.h"
15 #include "putilimp.h"
16
17 U_NAMESPACE_BEGIN
18
19 #define DEFAULT_CAPACITY 8
20
21 /*
22  * Constants for hinting whether a key is an integer
23  * or a pointer.  If a hint bit is zero, then the associated
24  * token is assumed to be an integer. This is needed for iSeries
25  */
26  
27 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector32)
28
29 UVector32::UVector32(UErrorCode &status) :
30     count(0),
31     capacity(0),
32     maxCapacity(0),
33     elements(NULL)
34 {
35     _init(DEFAULT_CAPACITY, status);
36 }
37
38 UVector32::UVector32(int32_t initialCapacity, UErrorCode &status) :
39     count(0),
40     capacity(0),
41     maxCapacity(0),
42     elements(0)
43 {
44     _init(initialCapacity, status);
45 }
46
47
48
49 void UVector32::_init(int32_t initialCapacity, UErrorCode &status) {
50     // Fix bogus initialCapacity values; avoid malloc(0)
51     if (initialCapacity < 1) {
52         initialCapacity = DEFAULT_CAPACITY;
53     }
54     if (maxCapacity>0 && maxCapacity<initialCapacity) {
55         initialCapacity = maxCapacity;
56     }
57     if (initialCapacity > (int32_t)(INT32_MAX / sizeof(int32_t))) {
58         initialCapacity = uprv_min(DEFAULT_CAPACITY, maxCapacity);
59     }
60     elements = (int32_t *)uprv_malloc(sizeof(int32_t)*initialCapacity);
61     if (elements == 0) {
62         status = U_MEMORY_ALLOCATION_ERROR;
63     } else {
64         capacity = initialCapacity;
65     }
66 }
67
68 UVector32::~UVector32() {
69     uprv_free(elements);
70     elements = 0;
71 }
72
73 /**
74  * Assign this object to another (make this a copy of 'other').
75  */
76 void UVector32::assign(const UVector32& other, UErrorCode &ec) {
77     if (ensureCapacity(other.count, ec)) {
78         setSize(other.count);
79         for (int32_t i=0; i<other.count; ++i) {
80             elements[i] = other.elements[i];
81         }
82     }
83 }
84
85
86 UBool UVector32::operator==(const UVector32& other) {
87     int32_t i;
88     if (count != other.count) return FALSE;
89     for (i=0; i<count; ++i) {
90         if (elements[i] != other.elements[i]) {
91             return FALSE;
92         }
93     }
94     return TRUE;
95 }
96
97
98 void UVector32::setElementAt(int32_t elem, int32_t index) {
99     if (0 <= index && index < count) {
100         elements[index] = elem;
101     }
102     /* else index out of range */
103 }
104
105 void UVector32::insertElementAt(int32_t elem, int32_t index, UErrorCode &status) {
106     // must have 0 <= index <= count
107     if (0 <= index && index <= count && ensureCapacity(count + 1, status)) {
108         for (int32_t i=count; i>index; --i) {
109             elements[i] = elements[i-1];
110         }
111         elements[index] = elem;
112         ++count;
113     }
114     /* else index out of range */
115 }
116
117 UBool UVector32::containsAll(const UVector32& other) const {
118     for (int32_t i=0; i<other.size(); ++i) {
119         if (indexOf(other.elements[i]) < 0) {
120             return FALSE;
121         }
122     }
123     return TRUE;
124 }
125
126 UBool UVector32::containsNone(const UVector32& other) const {
127     for (int32_t i=0; i<other.size(); ++i) {
128         if (indexOf(other.elements[i]) >= 0) {
129             return FALSE;
130         }
131     }
132     return TRUE;
133 }
134
135 UBool UVector32::removeAll(const UVector32& other) {
136     UBool changed = FALSE;
137     for (int32_t i=0; i<other.size(); ++i) {
138         int32_t j = indexOf(other.elements[i]);
139         if (j >= 0) {
140             removeElementAt(j);
141             changed = TRUE;
142         }
143     }
144     return changed;
145 }
146
147 UBool UVector32::retainAll(const UVector32& other) {
148     UBool changed = FALSE;
149     for (int32_t j=size()-1; j>=0; --j) {
150         int32_t i = other.indexOf(elements[j]);
151         if (i < 0) {
152             removeElementAt(j);
153             changed = TRUE;
154         }
155     }
156     return changed;
157 }
158
159 void UVector32::removeElementAt(int32_t index) {
160     if (index >= 0) {
161         for (int32_t i=index; i<count-1; ++i) {
162             elements[i] = elements[i+1];
163         }
164         --count;
165     }
166 }
167
168 void UVector32::removeAllElements(void) {
169     count = 0;
170 }
171
172 UBool   UVector32::equals(const UVector32 &other) const {
173     int      i;
174
175     if (this->count != other.count) {
176         return FALSE;
177     }
178     for (i=0; i<count; i++) {
179         if (elements[i] != other.elements[i]) {
180             return FALSE;
181         }
182     }
183     return TRUE;
184 }
185
186
187
188
189 int32_t UVector32::indexOf(int32_t key, int32_t startIndex) const {
190     int32_t i;
191     for (i=startIndex; i<count; ++i) {
192         if (key == elements[i]) {
193             return i;
194         }
195     }
196     return -1;
197 }
198
199
200 UBool UVector32::expandCapacity(int32_t minimumCapacity, UErrorCode &status) {
201     if (U_FAILURE(status)) {
202         return FALSE;
203     }
204     if (minimumCapacity < 0) {
205         status = U_ILLEGAL_ARGUMENT_ERROR;
206         return FALSE;
207     }
208     if (capacity >= minimumCapacity) {
209         return TRUE;
210     }
211     if (maxCapacity>0 && minimumCapacity>maxCapacity) {
212         status = U_BUFFER_OVERFLOW_ERROR;
213         return FALSE;
214     }
215     if (capacity > (INT32_MAX - 1) / 2) {  // integer overflow check
216         status = U_ILLEGAL_ARGUMENT_ERROR;
217         return FALSE;
218     }
219     int32_t newCap = capacity * 2;
220     if (newCap < minimumCapacity) {
221         newCap = minimumCapacity;
222     }
223     if (maxCapacity > 0 && newCap > maxCapacity) {
224         newCap = maxCapacity;
225     }
226     if (newCap > (int32_t)(INT32_MAX / sizeof(int32_t))) {  // integer overflow check
227         // We keep the original memory contents on bad minimumCapacity/maxCapacity.
228         status = U_ILLEGAL_ARGUMENT_ERROR;
229         return FALSE;
230     }
231     int32_t* newElems = (int32_t *)uprv_realloc(elements, sizeof(int32_t)*newCap);
232     if (newElems == NULL) {
233         // We keep the original contents on the memory failure on realloc.
234         status = U_MEMORY_ALLOCATION_ERROR;
235         return FALSE;
236     }
237     elements = newElems;
238     capacity = newCap;
239     return TRUE;
240 }
241
242 void UVector32::setMaxCapacity(int32_t limit) {
243     U_ASSERT(limit >= 0);
244     if (limit < 0) {
245         limit = 0;
246     }
247     if (limit > (int32_t)(INT32_MAX / sizeof(int32_t))) {  // integer overflow check for realloc
248         //  Something is very wrong, don't realloc, leave capacity and maxCapacity unchanged
249         return;
250     }
251     maxCapacity = limit;
252     if (capacity <= maxCapacity || maxCapacity == 0) {
253         // Current capacity is within the new limit.
254         return;
255     }
256     
257     // New maximum capacity is smaller than the current size.
258     // Realloc the storage to the new, smaller size.
259     int32_t* newElems = (int32_t *)uprv_realloc(elements, sizeof(int32_t)*maxCapacity);
260     if (newElems == NULL) {
261         // Realloc to smaller failed.
262         //   Just keep what we had.  No need to call it a failure.
263         return;
264     }
265     elements = newElems;
266     capacity = maxCapacity;
267     if (count > capacity) {
268         count = capacity;
269     }
270 }
271
272 /**
273  * Change the size of this vector as follows: If newSize is smaller,
274  * then truncate the array, possibly deleting held elements for i >=
275  * newSize.  If newSize is larger, grow the array, filling in new
276  * slots with NULL.
277  */
278 void UVector32::setSize(int32_t newSize) {
279     int32_t i;
280     if (newSize < 0) {
281         return;
282     }
283     if (newSize > count) {
284         UErrorCode ec = U_ZERO_ERROR;
285         if (!ensureCapacity(newSize, ec)) {
286             return;
287         }
288         for (i=count; i<newSize; ++i) {
289             elements[i] = 0;
290         }
291     } 
292     count = newSize;
293 }
294
295
296
297
298 /**
299  * Insert the given integer into this vector at its sorted position
300  * as defined by 'compare'.  The current elements are assumed to
301  * be sorted already.
302  */
303 void UVector32::sortedInsert(int32_t tok, UErrorCode& ec) {
304     // Perform a binary search for the location to insert tok at.  Tok
305     // will be inserted between two elements a and b such that a <=
306     // tok && tok < b, where there is a 'virtual' elements[-1] always
307     // less than tok and a 'virtual' elements[count] always greater
308     // than tok.
309     int32_t min = 0, max = count;
310     while (min != max) {
311         int32_t probe = (min + max) / 2;
312         //int8_t c = (*compare)(elements[probe], tok);
313         //if (c > 0) {
314         if (elements[probe] > tok) {
315             max = probe;
316         } else {
317             // assert(c <= 0);
318             min = probe + 1;
319         }
320     }
321     if (ensureCapacity(count + 1, ec)) {
322         for (int32_t i=count; i>min; --i) {
323             elements[i] = elements[i-1];
324         }
325         elements[min] = tok;
326         ++count;
327     }
328 }
329
330
331
332
333
334 U_NAMESPACE_END
335