|
1 /* |
|
2 ********************************************************************** |
|
3 * Copyright (C) 1999-2011, International Business Machines |
|
4 * Corporation and others. All Rights Reserved. |
|
5 ********************************************************************** |
|
6 */ |
|
7 |
|
8 // |
|
9 // UVector32 is a class implementing a vector of 32 bit integers. |
|
10 // It is similar to UVector, but holds int32_t values rather than pointers. |
|
11 // Most of the code is unchanged from UVector. |
|
12 // |
|
13 |
|
14 #ifndef UVECTOR32_H |
|
15 #define UVECTOR32_H |
|
16 |
|
17 #include "unicode/utypes.h" |
|
18 #include "unicode/uobject.h" |
|
19 #include "uhash.h" |
|
20 #include "uassert.h" |
|
21 |
|
22 U_NAMESPACE_BEGIN |
|
23 |
|
24 |
|
25 |
|
26 /** |
|
27 * <p>Ultralightweight C++ implementation of a <tt>void*</tt> vector |
|
28 * that is (mostly) compatible with java.util.Vector. |
|
29 * |
|
30 * <p>This is a very simple implementation, written to satisfy an |
|
31 * immediate porting need. As such, it is not completely fleshed out, |
|
32 * and it aims for simplicity and conformity. Nonetheless, it serves |
|
33 * its purpose (porting code from java that uses java.util.Vector) |
|
34 * well, and it could be easily made into a more robust vector class. |
|
35 * |
|
36 * <p><b>Design notes</b> |
|
37 * |
|
38 * <p>There is index bounds checking, but little is done about it. If |
|
39 * indices are out of bounds, either nothing happens, or zero is |
|
40 * returned. We <em>do</em> avoid indexing off into the weeds. |
|
41 * |
|
42 * <p>There is detection of out of memory, but the handling is very |
|
43 * coarse-grained -- similar to UnicodeString's protocol, but even |
|
44 * coarser. The class contains <em>one static flag</em> that is set |
|
45 * when any call to <tt>new</tt> returns zero. This allows the caller |
|
46 * to use several vectors and make just one check at the end to see if |
|
47 * a memory failure occurred. This is more efficient than making a |
|
48 * check after each call on each vector when doing many operations on |
|
49 * multiple vectors. The single static flag works best when memory |
|
50 * failures are infrequent, and when recovery options are limited or |
|
51 * nonexistent. |
|
52 * |
|
53 * <p><b>To do</b> |
|
54 * |
|
55 * <p>Improve the handling of index out of bounds errors. |
|
56 * |
|
57 * @author Alan Liu |
|
58 */ |
|
59 class U_COMMON_API UVector32 : public UObject { |
|
60 private: |
|
61 int32_t count; |
|
62 |
|
63 int32_t capacity; |
|
64 |
|
65 int32_t maxCapacity; // Limit beyond which capacity is not permitted to grow. |
|
66 |
|
67 int32_t* elements; |
|
68 |
|
69 public: |
|
70 UVector32(UErrorCode &status); |
|
71 |
|
72 UVector32(int32_t initialCapacity, UErrorCode &status); |
|
73 |
|
74 virtual ~UVector32(); |
|
75 |
|
76 /** |
|
77 * Assign this object to another (make this a copy of 'other'). |
|
78 * Use the 'assign' function to assign each element. |
|
79 */ |
|
80 void assign(const UVector32& other, UErrorCode &ec); |
|
81 |
|
82 /** |
|
83 * Compare this vector with another. They will be considered |
|
84 * equal if they are of the same size and all elements are equal, |
|
85 * as compared using this object's comparer. |
|
86 */ |
|
87 UBool operator==(const UVector32& other); |
|
88 |
|
89 /** |
|
90 * Equivalent to !operator==() |
|
91 */ |
|
92 inline UBool operator!=(const UVector32& other); |
|
93 |
|
94 //------------------------------------------------------------ |
|
95 // java.util.Vector API |
|
96 //------------------------------------------------------------ |
|
97 |
|
98 void addElement(int32_t elem, UErrorCode &status); |
|
99 |
|
100 void setElementAt(int32_t elem, int32_t index); |
|
101 |
|
102 void insertElementAt(int32_t elem, int32_t index, UErrorCode &status); |
|
103 |
|
104 int32_t elementAti(int32_t index) const; |
|
105 |
|
106 UBool equals(const UVector32 &other) const; |
|
107 |
|
108 int32_t lastElementi(void) const; |
|
109 |
|
110 int32_t indexOf(int32_t elem, int32_t startIndex = 0) const; |
|
111 |
|
112 UBool contains(int32_t elem) const; |
|
113 |
|
114 UBool containsAll(const UVector32& other) const; |
|
115 |
|
116 UBool removeAll(const UVector32& other); |
|
117 |
|
118 UBool retainAll(const UVector32& other); |
|
119 |
|
120 void removeElementAt(int32_t index); |
|
121 |
|
122 void removeAllElements(); |
|
123 |
|
124 int32_t size(void) const; |
|
125 |
|
126 UBool isEmpty(void) const; |
|
127 |
|
128 // Inline. Use this one for speedy size check. |
|
129 inline UBool ensureCapacity(int32_t minimumCapacity, UErrorCode &status); |
|
130 |
|
131 // Out-of-line, handles actual growth. Called by ensureCapacity() when necessary. |
|
132 UBool expandCapacity(int32_t minimumCapacity, UErrorCode &status); |
|
133 |
|
134 /** |
|
135 * Change the size of this vector as follows: If newSize is |
|
136 * smaller, then truncate the array, possibly deleting held |
|
137 * elements for i >= newSize. If newSize is larger, grow the |
|
138 * array, filling in new slows with zero. |
|
139 */ |
|
140 void setSize(int32_t newSize); |
|
141 |
|
142 //------------------------------------------------------------ |
|
143 // New API |
|
144 //------------------------------------------------------------ |
|
145 |
|
146 /** |
|
147 * Returns true if this vector contains none of the elements |
|
148 * of the given vector. |
|
149 * @param other vector to be checked for containment |
|
150 * @return true if the test condition is met |
|
151 */ |
|
152 UBool containsNone(const UVector32& other) const; |
|
153 |
|
154 |
|
155 /** |
|
156 * Insert the given integer into this vector at its sorted position. |
|
157 * The current elements are assumed to be sorted already. |
|
158 */ |
|
159 void sortedInsert(int32_t elem, UErrorCode& ec); |
|
160 |
|
161 /** |
|
162 * Returns a pointer to the internal array holding the vector. |
|
163 */ |
|
164 int32_t *getBuffer() const; |
|
165 |
|
166 /** |
|
167 * Set the maximum allowed buffer capacity for this vector/stack. |
|
168 * Default with no limit set is unlimited, go until malloc() fails. |
|
169 * A Limit of zero means unlimited capacity. |
|
170 * Units are vector elements (32 bits each), not bytes. |
|
171 */ |
|
172 void setMaxCapacity(int32_t limit); |
|
173 |
|
174 /** |
|
175 * ICU "poor man's RTTI", returns a UClassID for this class. |
|
176 */ |
|
177 static UClassID U_EXPORT2 getStaticClassID(); |
|
178 |
|
179 /** |
|
180 * ICU "poor man's RTTI", returns a UClassID for the actual class. |
|
181 */ |
|
182 virtual UClassID getDynamicClassID() const; |
|
183 |
|
184 private: |
|
185 void _init(int32_t initialCapacity, UErrorCode &status); |
|
186 |
|
187 // Disallow |
|
188 UVector32(const UVector32&); |
|
189 |
|
190 // Disallow |
|
191 UVector32& operator=(const UVector32&); |
|
192 |
|
193 |
|
194 // API Functions for Stack operations. |
|
195 // In the original UVector, these were in a separate derived class, UStack. |
|
196 // Here in UVector32, they are all together. |
|
197 public: |
|
198 UBool empty(void) const; // TODO: redundant, same as empty(). Remove it? |
|
199 |
|
200 int32_t peeki(void) const; |
|
201 |
|
202 int32_t popi(void); |
|
203 |
|
204 int32_t push(int32_t i, UErrorCode &status); |
|
205 |
|
206 int32_t *reserveBlock(int32_t size, UErrorCode &status); |
|
207 int32_t *popFrame(int32_t size); |
|
208 }; |
|
209 |
|
210 |
|
211 // UVector32 inlines |
|
212 |
|
213 inline UBool UVector32::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) { |
|
214 if ((minimumCapacity >= 0) && (capacity >= minimumCapacity)) { |
|
215 return TRUE; |
|
216 } else { |
|
217 return expandCapacity(minimumCapacity, status); |
|
218 } |
|
219 } |
|
220 |
|
221 inline int32_t UVector32::elementAti(int32_t index) const { |
|
222 return (index >= 0 && count > 0 && count - index > 0) ? elements[index] : 0; |
|
223 } |
|
224 |
|
225 |
|
226 inline void UVector32::addElement(int32_t elem, UErrorCode &status) { |
|
227 if (ensureCapacity(count + 1, status)) { |
|
228 elements[count] = elem; |
|
229 count++; |
|
230 } |
|
231 } |
|
232 |
|
233 inline int32_t *UVector32::reserveBlock(int32_t size, UErrorCode &status) { |
|
234 if (ensureCapacity(count+size, status) == FALSE) { |
|
235 return NULL; |
|
236 } |
|
237 int32_t *rp = elements+count; |
|
238 count += size; |
|
239 return rp; |
|
240 } |
|
241 |
|
242 inline int32_t *UVector32::popFrame(int32_t size) { |
|
243 U_ASSERT(count >= size); |
|
244 count -= size; |
|
245 if (count < 0) { |
|
246 count = 0; |
|
247 } |
|
248 return elements+count-size; |
|
249 } |
|
250 |
|
251 |
|
252 |
|
253 inline int32_t UVector32::size(void) const { |
|
254 return count; |
|
255 } |
|
256 |
|
257 inline UBool UVector32::isEmpty(void) const { |
|
258 return count == 0; |
|
259 } |
|
260 |
|
261 inline UBool UVector32::contains(int32_t obj) const { |
|
262 return indexOf(obj) >= 0; |
|
263 } |
|
264 |
|
265 inline int32_t UVector32::lastElementi(void) const { |
|
266 return elementAti(count-1); |
|
267 } |
|
268 |
|
269 inline UBool UVector32::operator!=(const UVector32& other) { |
|
270 return !operator==(other); |
|
271 } |
|
272 |
|
273 inline int32_t *UVector32::getBuffer() const { |
|
274 return elements; |
|
275 } |
|
276 |
|
277 |
|
278 // UStack inlines |
|
279 |
|
280 inline UBool UVector32::empty(void) const { |
|
281 return isEmpty(); |
|
282 } |
|
283 |
|
284 inline int32_t UVector32::peeki(void) const { |
|
285 return lastElementi(); |
|
286 } |
|
287 |
|
288 inline int32_t UVector32::push(int32_t i, UErrorCode &status) { |
|
289 addElement(i, status); |
|
290 return i; |
|
291 } |
|
292 |
|
293 inline int32_t UVector32::popi(void) { |
|
294 int32_t result = 0; |
|
295 if (count > 0) { |
|
296 count--; |
|
297 result = elements[count]; |
|
298 } |
|
299 return result; |
|
300 } |
|
301 |
|
302 U_NAMESPACE_END |
|
303 |
|
304 #endif |