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