UnicodeString& TransliteratorRegistry::getAvailableVariant(int32_t index, const UnicodeString& source, const UnicodeString& target, UnicodeString& result) const { Hashtable *targets = (Hashtable*) specDAG.get(source); if (targets == 0) { result.truncate(0); // invalid source return result; } uint32_t varMask = targets->geti(target); int32_t varCount = 0; int32_t varListIndex = 0; while (varMask > 0) { if (varMask & 1) { if (varCount == index) { UnicodeString *v = (UnicodeString*) variantList.elementAt(varListIndex); if (v != NULL) { result = *v; return result; } break; } varCount++; } varMask >>= 1; varListIndex++; } result.truncate(0); // invalid target or index return result; }
/** * Remove a source-target/variant from the specDAG. */ void TransliteratorRegistry::removeSTV(const UnicodeString& source, const UnicodeString& target, const UnicodeString& variant) { // assert(source.length() > 0); // assert(target.length() > 0); UErrorCode status = U_ZERO_ERROR; Hashtable *targets = (Hashtable*) specDAG.get(source); if (targets == NULL) { return; // should never happen for valid s-t/v } uint32_t varMask = targets->geti(target); if (varMask == 0) { return; // should never happen for valid s-t/v } int32_t variantListIndex = variantList.indexOf((void*) &variant, 0); if (variantListIndex < 0) { return; // should never happen for valid s-t/v } int32_t remMask = 1 << variantListIndex; varMask &= (~remMask); if (varMask != 0) { targets->puti(target, varMask, status); } else { targets->remove(target); // should delete variants if (targets->count() == 0) { specDAG.remove(source); // should delete targets } } }
int32_t TransliteratorRegistry::countAvailableVariants(const UnicodeString& source, const UnicodeString& target) const { Hashtable *targets = (Hashtable*) specDAG.get(source); if (targets == 0) { return 0; } uint32_t varMask = targets->geti(target); int32_t varCount = 0; while (varMask > 0) { if (varMask & 1) { varCount++; } varMask >>= 1; } return varCount; }
/** * Register a source-target/variant in the specDAG. Variant may be * empty, but source and target must not be. */ void TransliteratorRegistry::registerSTV(const UnicodeString& source, const UnicodeString& target, const UnicodeString& variant) { // assert(source.length() > 0); // assert(target.length() > 0); UErrorCode status = U_ZERO_ERROR; Hashtable *targets = (Hashtable*) specDAG.get(source); if (targets == 0) { int32_t size = 3; if (source.compare(ANY,3) == 0) { size = ANY_TARGETS_INIT_SIZE; } else if (source.compare(LAT,3) == 0) { size = LAT_TARGETS_INIT_SIZE; } targets = new Hashtable(TRUE, size, status); if (U_FAILURE(status) || targets == NULL) { return; } specDAG.put(source, targets, status); } int32_t variantListIndex = variantList.indexOf((void*) &variant, 0); if (variantListIndex < 0) { if (variantList.size() >= VARIANT_LIST_MAX_SIZE) { // can't handle any more variants return; } UnicodeString *variantEntry = new UnicodeString(variant); if (variantEntry != NULL) { variantList.addElement(variantEntry, status); if (U_SUCCESS(status)) { variantListIndex = variantList.size() - 1; } } if (variantListIndex < 0) { return; } } uint32_t addMask = 1 << variantListIndex; uint32_t varMask = targets->geti(target); targets->puti(target, varMask | addMask, status); }