intl/icu/source/common/uvector.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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

mercurial