/** * Creates an index, and buckets and sorts the list of records into the index. */ void AlphabeticIndex::initBuckets(UErrorCode &errorCode) { if (U_FAILURE(errorCode) || buckets_ != NULL) { return; } buckets_ = createBucketList(errorCode); if (U_FAILURE(errorCode) || inputList_ == NULL || inputList_->isEmpty()) { return; } // Sort the records by name. // Stable sort preserves input order of collation duplicates. inputList_->sortWithUComparator(recordCompareFn, collator_, errorCode); // Now, we traverse all of the input, which is now sorted. // If the item doesn't go in the current bucket, we find the next bucket that contains it. // This makes the process order n*log(n), since we just sort the list and then do a linear process. // However, if the user adds an item at a time and then gets the buckets, this isn't efficient, so // we need to improve it for that case. Bucket *currentBucket = getBucket(*buckets_->bucketList_, 0); int32_t bucketIndex = 1; Bucket *nextBucket; const UnicodeString *upperBoundary; if (bucketIndex < buckets_->bucketList_->size()) { nextBucket = getBucket(*buckets_->bucketList_, bucketIndex++); upperBoundary = &nextBucket->lowerBoundary_; } else { nextBucket = NULL; upperBoundary = NULL; } for (int32_t i = 0; i < inputList_->size(); ++i) { Record *r = getRecord(*inputList_, i); // if the current bucket isn't the right one, find the one that is // We have a special flag for the last bucket so that we don't look any further while (upperBoundary != NULL && collatorPrimaryOnly_->compare(r->name_, *upperBoundary, errorCode) >= 0) { currentBucket = nextBucket; // now reset the boundary that we compare against if (bucketIndex < buckets_->bucketList_->size()) { nextBucket = getBucket(*buckets_->bucketList_, bucketIndex++); upperBoundary = &nextBucket->lowerBoundary_; } else { upperBoundary = NULL; } } // now put the record into the bucket. Bucket *bucket = currentBucket; if (bucket->displayBucket_ != NULL) { bucket = bucket->displayBucket_; } if (bucket->records_ == NULL) { bucket->records_ = new UVector(errorCode); if (bucket->records_ == NULL) { errorCode = U_MEMORY_ALLOCATION_ERROR; return; } } bucket->records_->addElement(r, errorCode); } }
HashMap createHash(hashCodeGenerator gethash, keyComparator compare){ HashMap hash; int index; hash.bucket = createArrList(10); hash.getHash = gethash; hash.compare = compare; for(index = 0; index < 10; index++) hash.bucket.base[index] = createBucketList(); return hash; };
AlphabeticIndex::ImmutableIndex *AlphabeticIndex::buildImmutableIndex(UErrorCode &errorCode) { if (U_FAILURE(errorCode)) { return NULL; } // In C++, the ImmutableIndex must own its copy of the BucketList, // even if it contains no records, for proper memory management. // We could clone the buckets_ if they are not NULL, // but that would be worth it only if this method is called multiple times, // or called after using the old-style bucket iterator API. LocalPointer<BucketList> immutableBucketList(createBucketList(errorCode)); LocalPointer<RuleBasedCollator> coll( static_cast<RuleBasedCollator *>(collatorPrimaryOnly_->clone())); if (immutableBucketList.isNull() || coll.isNull()) { errorCode = U_MEMORY_ALLOCATION_ERROR; return NULL; } ImmutableIndex *immIndex = new ImmutableIndex(immutableBucketList.getAlias(), coll.getAlias()); if (immIndex == NULL) { errorCode = U_MEMORY_ALLOCATION_ERROR; return NULL; } // The ImmutableIndex adopted its parameter objects. immutableBucketList.orphan(); coll.orphan(); return immIndex; }