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 UBool operator==(const UVector& other); 117 118 /** 119 * Equivalent to !operator==() 120 */ 121 inline UBool operator!=(const UVector& other); 122 123 //------------------------------------------------------------ 124 // java.util.Vector API 125 //------------------------------------------------------------ 126 127 void addElement(void* obj, UErrorCode &status); 128 129 void addElement(int32_t elem, UErrorCode &status); 130 131 void setElementAt(void* obj, int32_t index); 132 133 void setElementAt(int32_t elem, int32_t index); 134 135 void insertElementAt(void* obj, int32_t index, UErrorCode &status); 136 137 void insertElementAt(int32_t elem, int32_t index, UErrorCode &status); 138 139 void* elementAt(int32_t index) const; 140 141 int32_t elementAti(int32_t index) const; 142 143 UBool equals(const UVector &other) const; 144 145 void* firstElement(void) const; 146 147 void* lastElement(void) const; 148 149 int32_t lastElementi(void) const; 150 151 int32_t indexOf(void* obj, int32_t startIndex = 0) const; 152 153 int32_t indexOf(int32_t obj, int32_t startIndex = 0) const; 154 155 UBool contains(void* obj) const; 156 157 UBool contains(int32_t obj) const; 158 159 UBool containsAll(const UVector& other) const; 160 161 UBool removeAll(const UVector& other); 162 163 UBool retainAll(const UVector& other); 164 165 void removeElementAt(int32_t index); 166 167 UBool removeElement(void* obj); 168 169 void removeAllElements(); 170 171 int32_t size(void) const; 172 173 UBool isEmpty(void) const; 174 175 UBool ensureCapacity(int32_t minimumCapacity, UErrorCode &status); 176 177 /** 178 * Change the size of this vector as follows: If newSize is 179 * smaller, then truncate the array, possibly deleting held 180 * elements for i >= newSize. If newSize is larger, grow the 181 * array, filling in new slots with NULL. 182 */ 183 void setSize(int32_t newSize, UErrorCode &status); 184 185 /** 186 * Fill in the given array with all elements of this vector. 187 */ 188 void** toArray(void** result) const; 189 190 //------------------------------------------------------------ 191 // New API 192 //------------------------------------------------------------ 193 194 UObjectDeleter *setDeleter(UObjectDeleter *d); 195 196 UElementsAreEqual *setComparer(UElementsAreEqual *c); 197 198 void* operator[](int32_t index) const; 199 200 /** 201 * Removes the element at the given index from this vector and 202 * transfer ownership of it to the caller. After this call, the 203 * caller owns the result and must delete it and the vector entry 204 * at 'index' is removed, shifting all subsequent entries back by 205 * one index and shortening the size of the vector by one. If the 206 * index is out of range or if there is no item at the given index 207 * then 0 is returned and the vector is unchanged. 208 */ 209 void* orphanElementAt(int32_t index); 210 211 /** 212 * Returns true if this vector contains none of the elements 213 * of the given vector. 214 * @param other vector to be checked for containment 215 * @return true if the test condition is met 216 */ 217 UBool containsNone(const UVector& other) const; 218 219 /** 220 * Insert the given object into this vector at its sorted position 221 * as defined by 'compare'. The current elements are assumed to 222 * be sorted already. 223 */ 224 void sortedInsert(void* obj, UElementComparator *compare, UErrorCode& ec); 225 226 /** 227 * Insert the given integer into this vector at its sorted position 228 * as defined by 'compare'. The current elements are assumed to 229 * be sorted already. 230 */ 231 void sortedInsert(int32_t obj, UElementComparator *compare, UErrorCode& ec); 232 233 /** 234 * Sort the contents of the vector, assuming that the contents of the 235 * vector are of type int32_t. 236 */ 237 void sorti(UErrorCode &ec); 238 239 /** 240 * Sort the contents of this vector, using a caller-supplied function 241 * to do the comparisons. (It's confusing that 242 * UVector's UElementComparator function is different from the 243 * UComparator function type defined in uarrsort.h) 244 */ 245 void sort(UElementComparator *compare, UErrorCode &ec); 246 247 /** 248 * Stable sort the contents of this vector using a caller-supplied function 249 * of type UComparator to do the comparison. Provides more flexibility 250 * than UVector::sort() because an additional user parameter can be passed to 251 * the comparison function. 252 */ 253 void sortWithUComparator(UComparator *compare, const void *context, UErrorCode &ec); 254 255 /** 256 * ICU "poor man's RTTI", returns a UClassID for this class. 257 */ 258 static UClassID U_EXPORT2 getStaticClassID(); 259 260 /** 261 * ICU "poor man's RTTI", returns a UClassID for the actual class. 262 */ 263 virtual UClassID getDynamicClassID() const; 264 265 private: 266 void _init(int32_t initialCapacity, UErrorCode &status); 267 268 int32_t indexOf(UElement key, int32_t startIndex = 0, int8_t hint = 0) const; 269 270 void sortedInsert(UElement e, UElementComparator *compare, UErrorCode& ec); 271 272 // Disallow 273 UVector(const UVector&); 274 275 // Disallow 276 UVector& operator=(const UVector&); 277 278 }; 279 280 281 /** 282 * <p>Ultralightweight C++ implementation of a <tt>void*</tt> stack 283 * that is (mostly) compatible with java.util.Stack. As in java, this 284 * is merely a paper thin layer around UVector. See the UVector 285 * documentation for further information. 286 * 287 * <p><b>Design notes</b> 288 * 289 * <p>The element at index <tt>n-1</tt> is (of course) the top of the 290 * stack. 291 * 292 * <p>The poorly named <tt>empty()</tt> method doesn't empty the 293 * stack; it determines if the stack is empty. 294 * 295 * @author Alan Liu 296 */ 297 class U_COMMON_API UStack : public UVector { 298 public: 299 UStack(UErrorCode &status); 300 301 UStack(int32_t initialCapacity, UErrorCode &status); 302 303 UStack(UObjectDeleter *d, UElementsAreEqual *c, UErrorCode &status); 304 305 UStack(UObjectDeleter *d, UElementsAreEqual *c, int32_t initialCapacity, UErrorCode &status); 306 307 virtual ~UStack(); 308 309 // It's okay not to have a virtual destructor (in UVector) 310 // because UStack has no special cleanup to do. 311 312 UBool empty(void) const; 313 314 void* peek(void) const; 315 316 int32_t peeki(void) const; 317 318 void* pop(void); 319 320 int32_t popi(void); 321 322 void* push(void* obj, UErrorCode &status); 323 324 int32_t push(int32_t i, UErrorCode &status); 325 326 /* 327 If the object o occurs as an item in this stack, 328 this method returns the 1-based distance from the top of the stack. 329 */ 330 int32_t search(void* obj) const; 331 332 /** 333 * ICU "poor man's RTTI", returns a UClassID for this class. 334 */ 335 static UClassID U_EXPORT2 getStaticClassID(); 336 337 /** 338 * ICU "poor man's RTTI", returns a UClassID for the actual class. 339 */ 340 virtual UClassID getDynamicClassID() const; 341 342 private: 343 // Disallow 344 UStack(const UStack&); 345 346 // Disallow 347 UStack& operator=(const UStack&); 348 }; 349 350 351 // UVector inlines 352 353 inline int32_t UVector::size(void) const { 354 return count; 355 } 356 357 inline UBool UVector::isEmpty(void) const { 358 return count == 0; 359 } 360 361 inline UBool UVector::contains(void* obj) const { 362 return indexOf(obj) >= 0; 363 } 364 365 inline UBool UVector::contains(int32_t obj) const { 366 return indexOf(obj) >= 0; 367 } 368 369 inline void* UVector::firstElement(void) const { 370 return elementAt(0); 371 } 372 373 inline void* UVector::lastElement(void) const { 374 return elementAt(count-1); 375 } 376 377 inline int32_t UVector::lastElementi(void) const { 378 return elementAti(count-1); 379 } 380 381 inline void* UVector::operator[](int32_t index) const { 382 return elementAt(index); 383 } 384 385 inline UBool UVector::operator!=(const UVector& other) { 386 return !operator==(other); 387 } 388 389 // UStack inlines 390 391 inline UBool UStack::empty(void) const { 392 return isEmpty(); 393 } 394 395 inline void* UStack::peek(void) const { 396 return lastElement(); 397 } 398 399 inline int32_t UStack::peeki(void) const { 400 return lastElementi(); 401 } 402 403 inline void* UStack::push(void* obj, UErrorCode &status) { 404 addElement(obj, status); 405 return obj; 406 } 407 408 inline int32_t UStack::push(int32_t i, UErrorCode &status) { 409 addElement(i, status); 410 return i; 411 } 412 413 U_NAMESPACE_END 414 415 #endif 416