/src/icu/source/common/uvector.h
Line | Count | Source (jump to first uncovered line) |
1 | | // © 2016 and later: Unicode, Inc. and others. |
2 | | // License & terms of use: http://www.unicode.org/copyright.html |
3 | | /* |
4 | | ********************************************************************** |
5 | | * Copyright (C) 1999-2016, International Business Machines |
6 | | * Corporation and others. All Rights Reserved. |
7 | | ********************************************************************** |
8 | | * Date Name Description |
9 | | * 10/22/99 alan Creation. This is an internal header. |
10 | | * It should not be exported. |
11 | | ********************************************************************** |
12 | | */ |
13 | | |
14 | | #ifndef UVECTOR_H |
15 | | #define UVECTOR_H |
16 | | |
17 | | #include "unicode/utypes.h" |
18 | | #include "unicode/uobject.h" |
19 | | #include "cmemory.h" |
20 | | #include "uarrsort.h" |
21 | | #include "uelement.h" |
22 | | |
23 | | U_NAMESPACE_BEGIN |
24 | | |
25 | | /** |
26 | | * <p>Ultralightweight C++ implementation of a <tt>void*</tt> vector |
27 | | * that is (mostly) compatible with java.util.Vector. |
28 | | * |
29 | | * <p>This is a very simple implementation, written to satisfy an |
30 | | * immediate porting need. As such, it is not completely fleshed out, |
31 | | * and it aims for simplicity and conformity. Nonetheless, it serves |
32 | | * its purpose (porting code from java that uses java.util.Vector) |
33 | | * well, and it could be easily made into a more robust vector class. |
34 | | * |
35 | | * <p><b>Design notes</b> |
36 | | * |
37 | | * <p>There is index bounds checking, but little is done about it. If |
38 | | * indices are out of bounds, either nothing happens, or zero is |
39 | | * returned. We <em>do</em> avoid indexing off into the weeds. |
40 | | * |
41 | | * <p>There is detection of out of memory, but the handling is very |
42 | | * coarse-grained -- similar to UnicodeString's protocol, but even |
43 | | * coarser. The class contains <em>one static flag</em> that is set |
44 | | * when any call to <tt>new</tt> returns zero. This allows the caller |
45 | | * to use several vectors and make just one check at the end to see if |
46 | | * a memory failure occurred. This is more efficient than making a |
47 | | * check after each call on each vector when doing many operations on |
48 | | * multiple vectors. The single static flag works best when memory |
49 | | * failures are infrequent, and when recovery options are limited or |
50 | | * nonexistent. |
51 | | * |
52 | | * <p>Since we don't have garbage collection, UVector was given the |
53 | | * option to <em>own</em>its contents. To employ this, set a deleter |
54 | | * function. The deleter is called on a void* pointer when that |
55 | | * pointer is released by the vector, either when the vector itself is |
56 | | * destructed, or when a call to setElementAt() overwrites an element, |
57 | | * or when a call to remove() or one of its variants explicitly |
58 | | * removes an element. If no deleter is set, or the deleter is set to |
59 | | * zero, then it is assumed that the caller will delete elements as |
60 | | * needed. |
61 | | * |
62 | | * <p>In order to implement methods such as contains() and indexOf(), |
63 | | * UVector needs a way to compare objects for equality. To do so, it |
64 | | * uses a comparison function, or "comparer." If the comparer is not |
65 | | * set, or is set to zero, then all such methods will act as if the |
66 | | * vector contains no element. That is, indexOf() will always return |
67 | | * -1, contains() will always return false, etc. |
68 | | * |
69 | | * <p><b>To do</b> |
70 | | * |
71 | | * <p>Improve the handling of index out of bounds errors. |
72 | | * |
73 | | * @author Alan Liu |
74 | | */ |
75 | | class U_COMMON_API UVector : public UObject { |
76 | | // NOTE: UVector uses the UHashKey (union of void* and int32_t) as |
77 | | // its basic storage type. It uses UElementsAreEqual as its |
78 | | // comparison function. It uses UObjectDeleter as its deleter |
79 | | // function. These are named for hashtables, but used here as-is |
80 | | // rather than duplicating the type. This allows sharing of |
81 | | // support functions. |
82 | | |
83 | | private: |
84 | | int32_t count; |
85 | | |
86 | | int32_t capacity; |
87 | | |
88 | | UElement* elements; |
89 | | |
90 | | UObjectDeleter *deleter; |
91 | | |
92 | | UElementsAreEqual *comparer; |
93 | | |
94 | | public: |
95 | | UVector(UErrorCode &status); |
96 | | |
97 | | UVector(int32_t initialCapacity, UErrorCode &status); |
98 | | |
99 | | UVector(UObjectDeleter *d, UElementsAreEqual *c, UErrorCode &status); |
100 | | |
101 | | UVector(UObjectDeleter *d, UElementsAreEqual *c, int32_t initialCapacity, UErrorCode &status); |
102 | | |
103 | | virtual ~UVector(); |
104 | | |
105 | | /** |
106 | | * Assign this object to another (make this a copy of 'other'). |
107 | | * Use the 'assign' function to assign each element. |
108 | | */ |
109 | | void assign(const UVector& other, UElementAssigner *assign, UErrorCode &ec); |
110 | | |
111 | | /** |
112 | | * Compare this vector with another. They will be considered |
113 | | * equal if they are of the same size and all elements are equal, |
114 | | * as compared using this object's comparer. |
115 | | */ |
116 | | bool operator==(const UVector& other); |
117 | | |
118 | | /** |
119 | | * Equivalent to !operator==() |
120 | | */ |
121 | | inline bool operator!=(const UVector& other); |
122 | | |
123 | | //------------------------------------------------------------ |
124 | | // java.util.Vector API |
125 | | //------------------------------------------------------------ |
126 | | |
127 | | /* |
128 | | * Old version of addElement, with non-standard error handling. |
129 | | * Will be removed once all uses have been switched to the new addElement(). |
130 | | */ |
131 | | void addElementX(void* obj, UErrorCode &status); |
132 | | |
133 | | void addElement(int32_t elem, UErrorCode &status); |
134 | | |
135 | | void setElementAt(void* obj, int32_t index); |
136 | | |
137 | | void setElementAt(int32_t elem, int32_t index); |
138 | | |
139 | | void insertElementAt(void* obj, int32_t index, UErrorCode &status); |
140 | | |
141 | | void insertElementAt(int32_t elem, int32_t index, UErrorCode &status); |
142 | | |
143 | | void* elementAt(int32_t index) const; |
144 | | |
145 | | int32_t elementAti(int32_t index) const; |
146 | | |
147 | | UBool equals(const UVector &other) const; |
148 | | |
149 | | inline void* firstElement(void) const; |
150 | | |
151 | | inline void* lastElement(void) const; |
152 | | |
153 | | inline int32_t lastElementi(void) const; |
154 | | |
155 | | int32_t indexOf(void* obj, int32_t startIndex = 0) const; |
156 | | |
157 | | int32_t indexOf(int32_t obj, int32_t startIndex = 0) const; |
158 | | |
159 | | inline UBool contains(void* obj) const; |
160 | | |
161 | | inline UBool contains(int32_t obj) const; |
162 | | |
163 | | UBool containsAll(const UVector& other) const; |
164 | | |
165 | | UBool removeAll(const UVector& other); |
166 | | |
167 | | UBool retainAll(const UVector& other); |
168 | | |
169 | | void removeElementAt(int32_t index); |
170 | | |
171 | | UBool removeElement(void* obj); |
172 | | |
173 | | void removeAllElements(); |
174 | | |
175 | | inline int32_t size(void) const; |
176 | | |
177 | | inline UBool isEmpty(void) const; |
178 | | |
179 | | /* |
180 | | * Old version of ensureCapacity, with non-standard error handling. |
181 | | * Will be removed once all uses have been switched to the new ensureCapacity(). |
182 | | */ |
183 | | UBool ensureCapacityX(int32_t minimumCapacity, UErrorCode &status); |
184 | | |
185 | | /** |
186 | | * Change the size of this vector as follows: If newSize is |
187 | | * smaller, then truncate the array, possibly deleting held |
188 | | * elements for i >= newSize. If newSize is larger, grow the |
189 | | * array, filling in new slots with NULL. |
190 | | */ |
191 | | void setSize(int32_t newSize, UErrorCode &status); |
192 | | |
193 | | /** |
194 | | * Fill in the given array with all elements of this vector. |
195 | | */ |
196 | | void** toArray(void** result) const; |
197 | | |
198 | | //------------------------------------------------------------ |
199 | | // New API |
200 | | //------------------------------------------------------------ |
201 | | |
202 | | UObjectDeleter *setDeleter(UObjectDeleter *d); |
203 | | |
204 | | UElementsAreEqual *setComparer(UElementsAreEqual *c); |
205 | | |
206 | | inline void* operator[](int32_t index) const; |
207 | | |
208 | | /** |
209 | | * Removes the element at the given index from this vector and |
210 | | * transfer ownership of it to the caller. After this call, the |
211 | | * caller owns the result and must delete it and the vector entry |
212 | | * at 'index' is removed, shifting all subsequent entries back by |
213 | | * one index and shortening the size of the vector by one. If the |
214 | | * index is out of range or if there is no item at the given index |
215 | | * then 0 is returned and the vector is unchanged. |
216 | | */ |
217 | | void* orphanElementAt(int32_t index); |
218 | | |
219 | | /** |
220 | | * Returns true if this vector contains none of the elements |
221 | | * of the given vector. |
222 | | * @param other vector to be checked for containment |
223 | | * @return true if the test condition is met |
224 | | */ |
225 | | UBool containsNone(const UVector& other) const; |
226 | | |
227 | | /** |
228 | | * Insert the given object into this vector at its sorted position |
229 | | * as defined by 'compare'. The current elements are assumed to |
230 | | * be sorted already. |
231 | | */ |
232 | | void sortedInsert(void* obj, UElementComparator *compare, UErrorCode& ec); |
233 | | |
234 | | /** |
235 | | * Insert the given integer into this vector at its sorted position |
236 | | * as defined by 'compare'. The current elements are assumed to |
237 | | * be sorted already. |
238 | | */ |
239 | | void sortedInsert(int32_t obj, UElementComparator *compare, UErrorCode& ec); |
240 | | |
241 | | /** |
242 | | * Sort the contents of the vector, assuming that the contents of the |
243 | | * vector are of type int32_t. |
244 | | */ |
245 | | void sorti(UErrorCode &ec); |
246 | | |
247 | | /** |
248 | | * Sort the contents of this vector, using a caller-supplied function |
249 | | * to do the comparisons. (It's confusing that |
250 | | * UVector's UElementComparator function is different from the |
251 | | * UComparator function type defined in uarrsort.h) |
252 | | */ |
253 | | void sort(UElementComparator *compare, UErrorCode &ec); |
254 | | |
255 | | /** |
256 | | * Stable sort the contents of this vector using a caller-supplied function |
257 | | * of type UComparator to do the comparison. Provides more flexibility |
258 | | * than UVector::sort() because an additional user parameter can be passed to |
259 | | * the comparison function. |
260 | | */ |
261 | | void sortWithUComparator(UComparator *compare, const void *context, UErrorCode &ec); |
262 | | |
263 | | /** |
264 | | * ICU "poor man's RTTI", returns a UClassID for this class. |
265 | | */ |
266 | | static UClassID U_EXPORT2 getStaticClassID(); |
267 | | |
268 | | /** |
269 | | * ICU "poor man's RTTI", returns a UClassID for the actual class. |
270 | | */ |
271 | | virtual UClassID getDynamicClassID() const; |
272 | | |
273 | | private: |
274 | | void _init(int32_t initialCapacity, UErrorCode &status); |
275 | | |
276 | | int32_t indexOf(UElement key, int32_t startIndex = 0, int8_t hint = 0) const; |
277 | | |
278 | | void sortedInsert(UElement e, UElementComparator *compare, UErrorCode& ec); |
279 | | |
280 | | // Disallow |
281 | | UVector(const UVector&); |
282 | | |
283 | | // Disallow |
284 | | UVector& operator=(const UVector&); |
285 | | |
286 | | }; |
287 | | |
288 | | |
289 | | /** |
290 | | * <p>Ultralightweight C++ implementation of a <tt>void*</tt> stack |
291 | | * that is (mostly) compatible with java.util.Stack. As in java, this |
292 | | * is merely a paper thin layer around UVector. See the UVector |
293 | | * documentation for further information. |
294 | | * |
295 | | * <p><b>Design notes</b> |
296 | | * |
297 | | * <p>The element at index <tt>n-1</tt> is (of course) the top of the |
298 | | * stack. |
299 | | * |
300 | | * <p>The poorly named <tt>empty()</tt> method doesn't empty the |
301 | | * stack; it determines if the stack is empty. |
302 | | * |
303 | | * @author Alan Liu |
304 | | */ |
305 | | class U_COMMON_API UStack : public UVector { |
306 | | public: |
307 | | UStack(UErrorCode &status); |
308 | | |
309 | | UStack(int32_t initialCapacity, UErrorCode &status); |
310 | | |
311 | | UStack(UObjectDeleter *d, UElementsAreEqual *c, UErrorCode &status); |
312 | | |
313 | | UStack(UObjectDeleter *d, UElementsAreEqual *c, int32_t initialCapacity, UErrorCode &status); |
314 | | |
315 | | virtual ~UStack(); |
316 | | |
317 | | // It's okay not to have a virtual destructor (in UVector) |
318 | | // because UStack has no special cleanup to do. |
319 | | |
320 | | inline UBool empty(void) const; |
321 | | |
322 | | inline void* peek(void) const; |
323 | | |
324 | | inline int32_t peeki(void) const; |
325 | | |
326 | | void* pop(void); |
327 | | |
328 | | int32_t popi(void); |
329 | | |
330 | | inline void* push(void* obj, UErrorCode &status); |
331 | | |
332 | | inline int32_t push(int32_t i, UErrorCode &status); |
333 | | |
334 | | /* |
335 | | If the object o occurs as an item in this stack, |
336 | | this method returns the 1-based distance from the top of the stack. |
337 | | */ |
338 | | int32_t search(void* obj) const; |
339 | | |
340 | | /** |
341 | | * ICU "poor man's RTTI", returns a UClassID for this class. |
342 | | */ |
343 | | static UClassID U_EXPORT2 getStaticClassID(); |
344 | | |
345 | | /** |
346 | | * ICU "poor man's RTTI", returns a UClassID for the actual class. |
347 | | */ |
348 | | virtual UClassID getDynamicClassID() const; |
349 | | |
350 | | private: |
351 | | // Disallow |
352 | | UStack(const UStack&); |
353 | | |
354 | | // Disallow |
355 | | UStack& operator=(const UStack&); |
356 | | }; |
357 | | |
358 | | |
359 | | // UVector inlines |
360 | | |
361 | 0 | inline int32_t UVector::size(void) const { |
362 | 0 | return count; |
363 | 0 | } |
364 | | |
365 | 0 | inline UBool UVector::isEmpty(void) const { |
366 | 0 | return count == 0; |
367 | 0 | } |
368 | | |
369 | 0 | inline UBool UVector::contains(void* obj) const { |
370 | 0 | return indexOf(obj) >= 0; |
371 | 0 | } |
372 | | |
373 | 0 | inline UBool UVector::contains(int32_t obj) const { |
374 | 0 | return indexOf(obj) >= 0; |
375 | 0 | } |
376 | | |
377 | 0 | inline void* UVector::firstElement(void) const { |
378 | 0 | return elementAt(0); |
379 | 0 | } |
380 | | |
381 | 0 | inline void* UVector::lastElement(void) const { |
382 | 0 | return elementAt(count-1); |
383 | 0 | } |
384 | | |
385 | 0 | inline int32_t UVector::lastElementi(void) const { |
386 | 0 | return elementAti(count-1); |
387 | 0 | } |
388 | | |
389 | 0 | inline void* UVector::operator[](int32_t index) const { |
390 | 0 | return elementAt(index); |
391 | 0 | } |
392 | | |
393 | 0 | inline bool UVector::operator!=(const UVector& other) { |
394 | 0 | return !operator==(other); |
395 | 0 | } |
396 | | |
397 | | // UStack inlines |
398 | | |
399 | 0 | inline UBool UStack::empty(void) const { |
400 | 0 | return isEmpty(); |
401 | 0 | } |
402 | | |
403 | 0 | inline void* UStack::peek(void) const { |
404 | 0 | return lastElement(); |
405 | 0 | } |
406 | | |
407 | 0 | inline int32_t UStack::peeki(void) const { |
408 | 0 | return lastElementi(); |
409 | 0 | } |
410 | | |
411 | 0 | inline void* UStack::push(void* obj, UErrorCode &status) { |
412 | 0 | addElementX(obj, status); |
413 | 0 | return obj; |
414 | 0 | } |
415 | | |
416 | 0 | inline int32_t UStack::push(int32_t i, UErrorCode &status) { |
417 | 0 | addElement(i, status); |
418 | 0 | return i; |
419 | 0 | } |
420 | | |
421 | | U_NAMESPACE_END |
422 | | |
423 | | #endif |