Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* |
michael@0 | 2 | ****************************************************************************** |
michael@0 | 3 | * Copyright (C) 1999-2013, International Business Machines Corporation and |
michael@0 | 4 | * others. All Rights Reserved. |
michael@0 | 5 | ****************************************************************************** |
michael@0 | 6 | * Date Name Description |
michael@0 | 7 | * 10/22/99 alan Creation. |
michael@0 | 8 | ********************************************************************** |
michael@0 | 9 | */ |
michael@0 | 10 | |
michael@0 | 11 | #include "uvector.h" |
michael@0 | 12 | #include "cmemory.h" |
michael@0 | 13 | #include "uarrsort.h" |
michael@0 | 14 | #include "uelement.h" |
michael@0 | 15 | |
michael@0 | 16 | U_NAMESPACE_BEGIN |
michael@0 | 17 | |
michael@0 | 18 | #define DEFAULT_CAPACITY 8 |
michael@0 | 19 | |
michael@0 | 20 | /* |
michael@0 | 21 | * Constants for hinting whether a key is an integer |
michael@0 | 22 | * or a pointer. If a hint bit is zero, then the associated |
michael@0 | 23 | * token is assumed to be an integer. This is needed for iSeries |
michael@0 | 24 | */ |
michael@0 | 25 | #define HINT_KEY_POINTER (1) |
michael@0 | 26 | #define HINT_KEY_INTEGER (0) |
michael@0 | 27 | |
michael@0 | 28 | UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector) |
michael@0 | 29 | |
michael@0 | 30 | UVector::UVector(UErrorCode &status) : |
michael@0 | 31 | count(0), |
michael@0 | 32 | capacity(0), |
michael@0 | 33 | elements(0), |
michael@0 | 34 | deleter(0), |
michael@0 | 35 | comparer(0) |
michael@0 | 36 | { |
michael@0 | 37 | _init(DEFAULT_CAPACITY, status); |
michael@0 | 38 | } |
michael@0 | 39 | |
michael@0 | 40 | UVector::UVector(int32_t initialCapacity, UErrorCode &status) : |
michael@0 | 41 | count(0), |
michael@0 | 42 | capacity(0), |
michael@0 | 43 | elements(0), |
michael@0 | 44 | deleter(0), |
michael@0 | 45 | comparer(0) |
michael@0 | 46 | { |
michael@0 | 47 | _init(initialCapacity, status); |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | UVector::UVector(UObjectDeleter *d, UElementsAreEqual *c, UErrorCode &status) : |
michael@0 | 51 | count(0), |
michael@0 | 52 | capacity(0), |
michael@0 | 53 | elements(0), |
michael@0 | 54 | deleter(d), |
michael@0 | 55 | comparer(c) |
michael@0 | 56 | { |
michael@0 | 57 | _init(DEFAULT_CAPACITY, status); |
michael@0 | 58 | } |
michael@0 | 59 | |
michael@0 | 60 | UVector::UVector(UObjectDeleter *d, UElementsAreEqual *c, int32_t initialCapacity, UErrorCode &status) : |
michael@0 | 61 | count(0), |
michael@0 | 62 | capacity(0), |
michael@0 | 63 | elements(0), |
michael@0 | 64 | deleter(d), |
michael@0 | 65 | comparer(c) |
michael@0 | 66 | { |
michael@0 | 67 | _init(initialCapacity, status); |
michael@0 | 68 | } |
michael@0 | 69 | |
michael@0 | 70 | void UVector::_init(int32_t initialCapacity, UErrorCode &status) { |
michael@0 | 71 | if (U_FAILURE(status)) { |
michael@0 | 72 | return; |
michael@0 | 73 | } |
michael@0 | 74 | // Fix bogus initialCapacity values; avoid malloc(0) and integer overflow |
michael@0 | 75 | if ((initialCapacity < 1) || (initialCapacity > (int32_t)(INT32_MAX / sizeof(UElement)))) { |
michael@0 | 76 | initialCapacity = DEFAULT_CAPACITY; |
michael@0 | 77 | } |
michael@0 | 78 | elements = (UElement *)uprv_malloc(sizeof(UElement)*initialCapacity); |
michael@0 | 79 | if (elements == 0) { |
michael@0 | 80 | status = U_MEMORY_ALLOCATION_ERROR; |
michael@0 | 81 | } else { |
michael@0 | 82 | capacity = initialCapacity; |
michael@0 | 83 | } |
michael@0 | 84 | } |
michael@0 | 85 | |
michael@0 | 86 | UVector::~UVector() { |
michael@0 | 87 | removeAllElements(); |
michael@0 | 88 | uprv_free(elements); |
michael@0 | 89 | elements = 0; |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | /** |
michael@0 | 93 | * Assign this object to another (make this a copy of 'other'). |
michael@0 | 94 | * Use the 'assign' function to assign each element. |
michael@0 | 95 | */ |
michael@0 | 96 | void UVector::assign(const UVector& other, UElementAssigner *assign, UErrorCode &ec) { |
michael@0 | 97 | if (ensureCapacity(other.count, ec)) { |
michael@0 | 98 | setSize(other.count, ec); |
michael@0 | 99 | if (U_SUCCESS(ec)) { |
michael@0 | 100 | for (int32_t i=0; i<other.count; ++i) { |
michael@0 | 101 | if (elements[i].pointer != 0 && deleter != 0) { |
michael@0 | 102 | (*deleter)(elements[i].pointer); |
michael@0 | 103 | } |
michael@0 | 104 | (*assign)(&elements[i], &other.elements[i]); |
michael@0 | 105 | } |
michael@0 | 106 | } |
michael@0 | 107 | } |
michael@0 | 108 | } |
michael@0 | 109 | |
michael@0 | 110 | // This only does something sensible if this object has a non-null comparer |
michael@0 | 111 | UBool UVector::operator==(const UVector& other) { |
michael@0 | 112 | int32_t i; |
michael@0 | 113 | if (count != other.count) return FALSE; |
michael@0 | 114 | if (comparer != NULL) { |
michael@0 | 115 | // Compare using this object's comparer |
michael@0 | 116 | for (i=0; i<count; ++i) { |
michael@0 | 117 | if (!(*comparer)(elements[i], other.elements[i])) { |
michael@0 | 118 | return FALSE; |
michael@0 | 119 | } |
michael@0 | 120 | } |
michael@0 | 121 | } |
michael@0 | 122 | return TRUE; |
michael@0 | 123 | } |
michael@0 | 124 | |
michael@0 | 125 | void UVector::addElement(void* obj, UErrorCode &status) { |
michael@0 | 126 | if (ensureCapacity(count + 1, status)) { |
michael@0 | 127 | elements[count++].pointer = obj; |
michael@0 | 128 | } |
michael@0 | 129 | } |
michael@0 | 130 | |
michael@0 | 131 | void UVector::addElement(int32_t elem, UErrorCode &status) { |
michael@0 | 132 | if (ensureCapacity(count + 1, status)) { |
michael@0 | 133 | elements[count].pointer = NULL; // Pointers may be bigger than ints. |
michael@0 | 134 | elements[count].integer = elem; |
michael@0 | 135 | count++; |
michael@0 | 136 | } |
michael@0 | 137 | } |
michael@0 | 138 | |
michael@0 | 139 | void UVector::setElementAt(void* obj, int32_t index) { |
michael@0 | 140 | if (0 <= index && index < count) { |
michael@0 | 141 | if (elements[index].pointer != 0 && deleter != 0) { |
michael@0 | 142 | (*deleter)(elements[index].pointer); |
michael@0 | 143 | } |
michael@0 | 144 | elements[index].pointer = obj; |
michael@0 | 145 | } |
michael@0 | 146 | /* else index out of range */ |
michael@0 | 147 | } |
michael@0 | 148 | |
michael@0 | 149 | void UVector::setElementAt(int32_t elem, int32_t index) { |
michael@0 | 150 | if (0 <= index && index < count) { |
michael@0 | 151 | if (elements[index].pointer != 0 && deleter != 0) { |
michael@0 | 152 | // TODO: this should be an error. mixing up ints and pointers. |
michael@0 | 153 | (*deleter)(elements[index].pointer); |
michael@0 | 154 | } |
michael@0 | 155 | elements[index].pointer = NULL; |
michael@0 | 156 | elements[index].integer = elem; |
michael@0 | 157 | } |
michael@0 | 158 | /* else index out of range */ |
michael@0 | 159 | } |
michael@0 | 160 | |
michael@0 | 161 | void UVector::insertElementAt(void* obj, int32_t index, UErrorCode &status) { |
michael@0 | 162 | // must have 0 <= index <= count |
michael@0 | 163 | if (0 <= index && index <= count && ensureCapacity(count + 1, status)) { |
michael@0 | 164 | for (int32_t i=count; i>index; --i) { |
michael@0 | 165 | elements[i] = elements[i-1]; |
michael@0 | 166 | } |
michael@0 | 167 | elements[index].pointer = obj; |
michael@0 | 168 | ++count; |
michael@0 | 169 | } |
michael@0 | 170 | /* else index out of range */ |
michael@0 | 171 | } |
michael@0 | 172 | |
michael@0 | 173 | void UVector::insertElementAt(int32_t elem, int32_t index, UErrorCode &status) { |
michael@0 | 174 | // must have 0 <= index <= count |
michael@0 | 175 | if (0 <= index && index <= count && ensureCapacity(count + 1, status)) { |
michael@0 | 176 | for (int32_t i=count; i>index; --i) { |
michael@0 | 177 | elements[i] = elements[i-1]; |
michael@0 | 178 | } |
michael@0 | 179 | elements[index].pointer = NULL; |
michael@0 | 180 | elements[index].integer = elem; |
michael@0 | 181 | ++count; |
michael@0 | 182 | } |
michael@0 | 183 | /* else index out of range */ |
michael@0 | 184 | } |
michael@0 | 185 | |
michael@0 | 186 | void* UVector::elementAt(int32_t index) const { |
michael@0 | 187 | return (0 <= index && index < count) ? elements[index].pointer : 0; |
michael@0 | 188 | } |
michael@0 | 189 | |
michael@0 | 190 | int32_t UVector::elementAti(int32_t index) const { |
michael@0 | 191 | return (0 <= index && index < count) ? elements[index].integer : 0; |
michael@0 | 192 | } |
michael@0 | 193 | |
michael@0 | 194 | UBool UVector::containsAll(const UVector& other) const { |
michael@0 | 195 | for (int32_t i=0; i<other.size(); ++i) { |
michael@0 | 196 | if (indexOf(other.elements[i]) < 0) { |
michael@0 | 197 | return FALSE; |
michael@0 | 198 | } |
michael@0 | 199 | } |
michael@0 | 200 | return TRUE; |
michael@0 | 201 | } |
michael@0 | 202 | |
michael@0 | 203 | UBool UVector::containsNone(const UVector& other) const { |
michael@0 | 204 | for (int32_t i=0; i<other.size(); ++i) { |
michael@0 | 205 | if (indexOf(other.elements[i]) >= 0) { |
michael@0 | 206 | return FALSE; |
michael@0 | 207 | } |
michael@0 | 208 | } |
michael@0 | 209 | return TRUE; |
michael@0 | 210 | } |
michael@0 | 211 | |
michael@0 | 212 | UBool UVector::removeAll(const UVector& other) { |
michael@0 | 213 | UBool changed = FALSE; |
michael@0 | 214 | for (int32_t i=0; i<other.size(); ++i) { |
michael@0 | 215 | int32_t j = indexOf(other.elements[i]); |
michael@0 | 216 | if (j >= 0) { |
michael@0 | 217 | removeElementAt(j); |
michael@0 | 218 | changed = TRUE; |
michael@0 | 219 | } |
michael@0 | 220 | } |
michael@0 | 221 | return changed; |
michael@0 | 222 | } |
michael@0 | 223 | |
michael@0 | 224 | UBool UVector::retainAll(const UVector& other) { |
michael@0 | 225 | UBool changed = FALSE; |
michael@0 | 226 | for (int32_t j=size()-1; j>=0; --j) { |
michael@0 | 227 | int32_t i = other.indexOf(elements[j]); |
michael@0 | 228 | if (i < 0) { |
michael@0 | 229 | removeElementAt(j); |
michael@0 | 230 | changed = TRUE; |
michael@0 | 231 | } |
michael@0 | 232 | } |
michael@0 | 233 | return changed; |
michael@0 | 234 | } |
michael@0 | 235 | |
michael@0 | 236 | void UVector::removeElementAt(int32_t index) { |
michael@0 | 237 | void* e = orphanElementAt(index); |
michael@0 | 238 | if (e != 0 && deleter != 0) { |
michael@0 | 239 | (*deleter)(e); |
michael@0 | 240 | } |
michael@0 | 241 | } |
michael@0 | 242 | |
michael@0 | 243 | UBool UVector::removeElement(void* obj) { |
michael@0 | 244 | int32_t i = indexOf(obj); |
michael@0 | 245 | if (i >= 0) { |
michael@0 | 246 | removeElementAt(i); |
michael@0 | 247 | return TRUE; |
michael@0 | 248 | } |
michael@0 | 249 | return FALSE; |
michael@0 | 250 | } |
michael@0 | 251 | |
michael@0 | 252 | void UVector::removeAllElements(void) { |
michael@0 | 253 | if (deleter != 0) { |
michael@0 | 254 | for (int32_t i=0; i<count; ++i) { |
michael@0 | 255 | if (elements[i].pointer != 0) { |
michael@0 | 256 | (*deleter)(elements[i].pointer); |
michael@0 | 257 | } |
michael@0 | 258 | } |
michael@0 | 259 | } |
michael@0 | 260 | count = 0; |
michael@0 | 261 | } |
michael@0 | 262 | |
michael@0 | 263 | UBool UVector::equals(const UVector &other) const { |
michael@0 | 264 | int i; |
michael@0 | 265 | |
michael@0 | 266 | if (this->count != other.count) { |
michael@0 | 267 | return FALSE; |
michael@0 | 268 | } |
michael@0 | 269 | if (comparer == 0) { |
michael@0 | 270 | for (i=0; i<count; i++) { |
michael@0 | 271 | if (elements[i].pointer != other.elements[i].pointer) { |
michael@0 | 272 | return FALSE; |
michael@0 | 273 | } |
michael@0 | 274 | } |
michael@0 | 275 | } else { |
michael@0 | 276 | UElement key; |
michael@0 | 277 | for (i=0; i<count; i++) { |
michael@0 | 278 | key.pointer = &other.elements[i]; |
michael@0 | 279 | if (!(*comparer)(key, elements[i])) { |
michael@0 | 280 | return FALSE; |
michael@0 | 281 | } |
michael@0 | 282 | } |
michael@0 | 283 | } |
michael@0 | 284 | return TRUE; |
michael@0 | 285 | } |
michael@0 | 286 | |
michael@0 | 287 | |
michael@0 | 288 | |
michael@0 | 289 | int32_t UVector::indexOf(void* obj, int32_t startIndex) const { |
michael@0 | 290 | UElement key; |
michael@0 | 291 | key.pointer = obj; |
michael@0 | 292 | return indexOf(key, startIndex, HINT_KEY_POINTER); |
michael@0 | 293 | } |
michael@0 | 294 | |
michael@0 | 295 | int32_t UVector::indexOf(int32_t obj, int32_t startIndex) const { |
michael@0 | 296 | UElement key; |
michael@0 | 297 | key.integer = obj; |
michael@0 | 298 | return indexOf(key, startIndex, HINT_KEY_INTEGER); |
michael@0 | 299 | } |
michael@0 | 300 | |
michael@0 | 301 | // This only works if this object has a non-null comparer |
michael@0 | 302 | int32_t UVector::indexOf(UElement key, int32_t startIndex, int8_t hint) const { |
michael@0 | 303 | int32_t i; |
michael@0 | 304 | if (comparer != 0) { |
michael@0 | 305 | for (i=startIndex; i<count; ++i) { |
michael@0 | 306 | if ((*comparer)(key, elements[i])) { |
michael@0 | 307 | return i; |
michael@0 | 308 | } |
michael@0 | 309 | } |
michael@0 | 310 | } else { |
michael@0 | 311 | for (i=startIndex; i<count; ++i) { |
michael@0 | 312 | /* Pointers are not always the same size as ints so to perform |
michael@0 | 313 | * a valid comparision we need to know whether we are being |
michael@0 | 314 | * provided an int or a pointer. */ |
michael@0 | 315 | if (hint & HINT_KEY_POINTER) { |
michael@0 | 316 | if (key.pointer == elements[i].pointer) { |
michael@0 | 317 | return i; |
michael@0 | 318 | } |
michael@0 | 319 | } else { |
michael@0 | 320 | if (key.integer == elements[i].integer) { |
michael@0 | 321 | return i; |
michael@0 | 322 | } |
michael@0 | 323 | } |
michael@0 | 324 | } |
michael@0 | 325 | } |
michael@0 | 326 | return -1; |
michael@0 | 327 | } |
michael@0 | 328 | |
michael@0 | 329 | UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) { |
michael@0 | 330 | if (minimumCapacity < 0) { |
michael@0 | 331 | status = U_ILLEGAL_ARGUMENT_ERROR; |
michael@0 | 332 | return FALSE; |
michael@0 | 333 | } |
michael@0 | 334 | if (capacity < minimumCapacity) { |
michael@0 | 335 | if (capacity > (INT32_MAX - 1) / 2) { // integer overflow check |
michael@0 | 336 | status = U_ILLEGAL_ARGUMENT_ERROR; |
michael@0 | 337 | return FALSE; |
michael@0 | 338 | } |
michael@0 | 339 | int32_t newCap = capacity * 2; |
michael@0 | 340 | if (newCap < minimumCapacity) { |
michael@0 | 341 | newCap = minimumCapacity; |
michael@0 | 342 | } |
michael@0 | 343 | if (newCap > (int32_t)(INT32_MAX / sizeof(UElement))) { // integer overflow check |
michael@0 | 344 | // We keep the original memory contents on bad minimumCapacity. |
michael@0 | 345 | status = U_ILLEGAL_ARGUMENT_ERROR; |
michael@0 | 346 | return FALSE; |
michael@0 | 347 | } |
michael@0 | 348 | UElement* newElems = (UElement *)uprv_realloc(elements, sizeof(UElement)*newCap); |
michael@0 | 349 | if (newElems == NULL) { |
michael@0 | 350 | // We keep the original contents on the memory failure on realloc or bad minimumCapacity. |
michael@0 | 351 | status = U_MEMORY_ALLOCATION_ERROR; |
michael@0 | 352 | return FALSE; |
michael@0 | 353 | } |
michael@0 | 354 | elements = newElems; |
michael@0 | 355 | capacity = newCap; |
michael@0 | 356 | } |
michael@0 | 357 | return TRUE; |
michael@0 | 358 | } |
michael@0 | 359 | |
michael@0 | 360 | /** |
michael@0 | 361 | * Change the size of this vector as follows: If newSize is smaller, |
michael@0 | 362 | * then truncate the array, possibly deleting held elements for i >= |
michael@0 | 363 | * newSize. If newSize is larger, grow the array, filling in new |
michael@0 | 364 | * slots with NULL. |
michael@0 | 365 | */ |
michael@0 | 366 | void UVector::setSize(int32_t newSize, UErrorCode &status) { |
michael@0 | 367 | int32_t i; |
michael@0 | 368 | if (newSize < 0) { |
michael@0 | 369 | return; |
michael@0 | 370 | } |
michael@0 | 371 | if (newSize > count) { |
michael@0 | 372 | if (!ensureCapacity(newSize, status)) { |
michael@0 | 373 | return; |
michael@0 | 374 | } |
michael@0 | 375 | UElement empty; |
michael@0 | 376 | empty.pointer = NULL; |
michael@0 | 377 | empty.integer = 0; |
michael@0 | 378 | for (i=count; i<newSize; ++i) { |
michael@0 | 379 | elements[i] = empty; |
michael@0 | 380 | } |
michael@0 | 381 | } else { |
michael@0 | 382 | /* Most efficient to count down */ |
michael@0 | 383 | for (i=count-1; i>=newSize; --i) { |
michael@0 | 384 | removeElementAt(i); |
michael@0 | 385 | } |
michael@0 | 386 | } |
michael@0 | 387 | count = newSize; |
michael@0 | 388 | } |
michael@0 | 389 | |
michael@0 | 390 | /** |
michael@0 | 391 | * Fill in the given array with all elements of this vector. |
michael@0 | 392 | */ |
michael@0 | 393 | void** UVector::toArray(void** result) const { |
michael@0 | 394 | void** a = result; |
michael@0 | 395 | for (int i=0; i<count; ++i) { |
michael@0 | 396 | *a++ = elements[i].pointer; |
michael@0 | 397 | } |
michael@0 | 398 | return result; |
michael@0 | 399 | } |
michael@0 | 400 | |
michael@0 | 401 | UObjectDeleter *UVector::setDeleter(UObjectDeleter *d) { |
michael@0 | 402 | UObjectDeleter *old = deleter; |
michael@0 | 403 | deleter = d; |
michael@0 | 404 | return old; |
michael@0 | 405 | } |
michael@0 | 406 | |
michael@0 | 407 | UElementsAreEqual *UVector::setComparer(UElementsAreEqual *d) { |
michael@0 | 408 | UElementsAreEqual *old = comparer; |
michael@0 | 409 | comparer = d; |
michael@0 | 410 | return old; |
michael@0 | 411 | } |
michael@0 | 412 | |
michael@0 | 413 | /** |
michael@0 | 414 | * Removes the element at the given index from this vector and |
michael@0 | 415 | * transfer ownership of it to the caller. After this call, the |
michael@0 | 416 | * caller owns the result and must delete it and the vector entry |
michael@0 | 417 | * at 'index' is removed, shifting all subsequent entries back by |
michael@0 | 418 | * one index and shortening the size of the vector by one. If the |
michael@0 | 419 | * index is out of range or if there is no item at the given index |
michael@0 | 420 | * then 0 is returned and the vector is unchanged. |
michael@0 | 421 | */ |
michael@0 | 422 | void* UVector::orphanElementAt(int32_t index) { |
michael@0 | 423 | void* e = 0; |
michael@0 | 424 | if (0 <= index && index < count) { |
michael@0 | 425 | e = elements[index].pointer; |
michael@0 | 426 | for (int32_t i=index; i<count-1; ++i) { |
michael@0 | 427 | elements[i] = elements[i+1]; |
michael@0 | 428 | } |
michael@0 | 429 | --count; |
michael@0 | 430 | } |
michael@0 | 431 | /* else index out of range */ |
michael@0 | 432 | return e; |
michael@0 | 433 | } |
michael@0 | 434 | |
michael@0 | 435 | /** |
michael@0 | 436 | * Insert the given object into this vector at its sorted position |
michael@0 | 437 | * as defined by 'compare'. The current elements are assumed to |
michael@0 | 438 | * be sorted already. |
michael@0 | 439 | */ |
michael@0 | 440 | void UVector::sortedInsert(void* obj, UElementComparator *compare, UErrorCode& ec) { |
michael@0 | 441 | UElement e; |
michael@0 | 442 | e.pointer = obj; |
michael@0 | 443 | sortedInsert(e, compare, ec); |
michael@0 | 444 | } |
michael@0 | 445 | |
michael@0 | 446 | /** |
michael@0 | 447 | * Insert the given integer into this vector at its sorted position |
michael@0 | 448 | * as defined by 'compare'. The current elements are assumed to |
michael@0 | 449 | * be sorted already. |
michael@0 | 450 | */ |
michael@0 | 451 | void UVector::sortedInsert(int32_t obj, UElementComparator *compare, UErrorCode& ec) { |
michael@0 | 452 | UElement e; |
michael@0 | 453 | e.integer = obj; |
michael@0 | 454 | sortedInsert(e, compare, ec); |
michael@0 | 455 | } |
michael@0 | 456 | |
michael@0 | 457 | // ASSUME elements[] IS CURRENTLY SORTED |
michael@0 | 458 | void UVector::sortedInsert(UElement e, UElementComparator *compare, UErrorCode& ec) { |
michael@0 | 459 | // Perform a binary search for the location to insert tok at. Tok |
michael@0 | 460 | // will be inserted between two elements a and b such that a <= |
michael@0 | 461 | // tok && tok < b, where there is a 'virtual' elements[-1] always |
michael@0 | 462 | // less than tok and a 'virtual' elements[count] always greater |
michael@0 | 463 | // than tok. |
michael@0 | 464 | int32_t min = 0, max = count; |
michael@0 | 465 | while (min != max) { |
michael@0 | 466 | int32_t probe = (min + max) / 2; |
michael@0 | 467 | int8_t c = (*compare)(elements[probe], e); |
michael@0 | 468 | if (c > 0) { |
michael@0 | 469 | max = probe; |
michael@0 | 470 | } else { |
michael@0 | 471 | // assert(c <= 0); |
michael@0 | 472 | min = probe + 1; |
michael@0 | 473 | } |
michael@0 | 474 | } |
michael@0 | 475 | if (ensureCapacity(count + 1, ec)) { |
michael@0 | 476 | for (int32_t i=count; i>min; --i) { |
michael@0 | 477 | elements[i] = elements[i-1]; |
michael@0 | 478 | } |
michael@0 | 479 | elements[min] = e; |
michael@0 | 480 | ++count; |
michael@0 | 481 | } |
michael@0 | 482 | } |
michael@0 | 483 | |
michael@0 | 484 | /** |
michael@0 | 485 | * Array sort comparator function. |
michael@0 | 486 | * Used from UVector::sort() |
michael@0 | 487 | * Conforms to function signature required for uprv_sortArray(). |
michael@0 | 488 | * This function is essentially just a wrapper, to make a |
michael@0 | 489 | * UVector style comparator function usable with uprv_sortArray(). |
michael@0 | 490 | * |
michael@0 | 491 | * The context pointer to this function is a pointer back |
michael@0 | 492 | * (with some extra indirection) to the user supplied comparator. |
michael@0 | 493 | * |
michael@0 | 494 | */ |
michael@0 | 495 | static int32_t U_CALLCONV |
michael@0 | 496 | sortComparator(const void *context, const void *left, const void *right) { |
michael@0 | 497 | UElementComparator *compare = *static_cast<UElementComparator * const *>(context); |
michael@0 | 498 | UElement e1 = *static_cast<const UElement *>(left); |
michael@0 | 499 | UElement e2 = *static_cast<const UElement *>(right); |
michael@0 | 500 | int32_t result = (*compare)(e1, e2); |
michael@0 | 501 | return result; |
michael@0 | 502 | } |
michael@0 | 503 | |
michael@0 | 504 | |
michael@0 | 505 | /** |
michael@0 | 506 | * Array sort comparison function for use from UVector::sorti() |
michael@0 | 507 | * Compares int32_t vector elements. |
michael@0 | 508 | */ |
michael@0 | 509 | static int32_t U_CALLCONV |
michael@0 | 510 | sortiComparator(const void * /*context */, const void *left, const void *right) { |
michael@0 | 511 | const UElement *e1 = static_cast<const UElement *>(left); |
michael@0 | 512 | const UElement *e2 = static_cast<const UElement *>(right); |
michael@0 | 513 | int32_t result = e1->integer < e2->integer? -1 : |
michael@0 | 514 | e1->integer == e2->integer? 0 : 1; |
michael@0 | 515 | return result; |
michael@0 | 516 | } |
michael@0 | 517 | |
michael@0 | 518 | /** |
michael@0 | 519 | * Sort the vector, assuming it constains ints. |
michael@0 | 520 | * (A more general sort would take a comparison function, but it's |
michael@0 | 521 | * not clear whether UVector's UElementComparator or |
michael@0 | 522 | * UComparator from uprv_sortAray would be more appropriate.) |
michael@0 | 523 | */ |
michael@0 | 524 | void UVector::sorti(UErrorCode &ec) { |
michael@0 | 525 | if (U_SUCCESS(ec)) { |
michael@0 | 526 | uprv_sortArray(elements, count, sizeof(UElement), |
michael@0 | 527 | sortiComparator, NULL, FALSE, &ec); |
michael@0 | 528 | } |
michael@0 | 529 | } |
michael@0 | 530 | |
michael@0 | 531 | |
michael@0 | 532 | /** |
michael@0 | 533 | * Sort with a user supplied comparator. |
michael@0 | 534 | * |
michael@0 | 535 | * The comparator function handling is confusing because the function type |
michael@0 | 536 | * for UVector (as defined for sortedInsert()) is different from the signature |
michael@0 | 537 | * required by uprv_sortArray(). This is handled by passing the |
michael@0 | 538 | * the UVector sort function pointer via the context pointer to a |
michael@0 | 539 | * sortArray() comparator function, which can then call back to |
michael@0 | 540 | * the original user functtion. |
michael@0 | 541 | * |
michael@0 | 542 | * An additional twist is that it's not safe to pass a pointer-to-function |
michael@0 | 543 | * as a (void *) data pointer, so instead we pass a (data) pointer to a |
michael@0 | 544 | * pointer-to-function variable. |
michael@0 | 545 | */ |
michael@0 | 546 | void UVector::sort(UElementComparator *compare, UErrorCode &ec) { |
michael@0 | 547 | if (U_SUCCESS(ec)) { |
michael@0 | 548 | uprv_sortArray(elements, count, sizeof(UElement), |
michael@0 | 549 | sortComparator, &compare, FALSE, &ec); |
michael@0 | 550 | } |
michael@0 | 551 | } |
michael@0 | 552 | |
michael@0 | 553 | |
michael@0 | 554 | /** |
michael@0 | 555 | * Stable sort with a user supplied comparator of type UComparator. |
michael@0 | 556 | */ |
michael@0 | 557 | void UVector::sortWithUComparator(UComparator *compare, const void *context, UErrorCode &ec) { |
michael@0 | 558 | if (U_SUCCESS(ec)) { |
michael@0 | 559 | uprv_sortArray(elements, count, sizeof(UElement), |
michael@0 | 560 | compare, context, TRUE, &ec); |
michael@0 | 561 | } |
michael@0 | 562 | } |
michael@0 | 563 | |
michael@0 | 564 | U_NAMESPACE_END |
michael@0 | 565 |