Transliterator* TransliteratorAlias::create(UParseError& pe, UErrorCode& ec) { if (U_FAILURE(ec)) { return 0; } Transliterator *t = NULL; switch (type) { case SIMPLE: t = Transliterator::createInstance(aliasesOrRules, UTRANS_FORWARD, pe, ec); if(U_FAILURE(ec)){ return 0; } if (compoundFilter != 0) t->adoptFilter((UnicodeSet*)compoundFilter->clone()); break; case COMPOUND: { // the total number of transliterators in the compound is the total number of anonymous transliterators // plus the total number of ID blocks-- we start by assuming the list begins and ends with an ID // block and that each pair anonymous transliterators has an ID block between them. Then we go back // to see whether there really are ID blocks at the beginning and end (by looking for U+FFFF, which // marks the position where an anonymous transliterator goes) and adjust accordingly int32_t anonymousRBTs = transes->size(); int32_t transCount = anonymousRBTs * 2 + 1; if (!aliasesOrRules.isEmpty() && aliasesOrRules[0] == (UChar)(0xffff)) --transCount; if (aliasesOrRules.length() >= 2 && aliasesOrRules[aliasesOrRules.length() - 1] == (UChar)(0xffff)) --transCount; UnicodeString noIDBlock((UChar)(0xffff)); noIDBlock += ((UChar)(0xffff)); int32_t pos = aliasesOrRules.indexOf(noIDBlock); while (pos >= 0) { --transCount; pos = aliasesOrRules.indexOf(noIDBlock, pos + 1); } UVector transliterators(ec); UnicodeString idBlock; int32_t blockSeparatorPos = aliasesOrRules.indexOf((UChar)(0xffff)); while (blockSeparatorPos >= 0) { aliasesOrRules.extract(0, blockSeparatorPos, idBlock); aliasesOrRules.remove(0, blockSeparatorPos + 1); if (!idBlock.isEmpty()) transliterators.addElement(Transliterator::createInstance(idBlock, UTRANS_FORWARD, pe, ec), ec); if (!transes->isEmpty()) transliterators.addElement(transes->orphanElementAt(0), ec); blockSeparatorPos = aliasesOrRules.indexOf((UChar)(0xffff)); } if (!aliasesOrRules.isEmpty()) transliterators.addElement(Transliterator::createInstance(aliasesOrRules, UTRANS_FORWARD, pe, ec), ec); while (!transes->isEmpty()) transliterators.addElement(transes->orphanElementAt(0), ec); if (U_SUCCESS(ec)) { t = new CompoundTransliterator(ID, transliterators, (compoundFilter ? (UnicodeSet*)(compoundFilter->clone()) : 0), anonymousRBTs, pe, ec); if (t == 0) { ec = U_MEMORY_ALLOCATION_ERROR; return 0; } } else { for (int32_t i = 0; i < transliterators.size(); i++) delete (Transliterator*)(transliterators.elementAt(i)); } } break; case RULES: U_ASSERT(FALSE); // don't call create() if isRuleBased() returns TRUE! break; } return t; }
Transliterator* U_EXPORT2 Transliterator::createFromRules(const UnicodeString& ID, const UnicodeString& rules, UTransDirection dir, UParseError& parseError, UErrorCode& status) { Transliterator* t = NULL; TransliteratorParser parser(status); parser.parse(rules, dir, parseError, status); if (U_FAILURE(status)) { return 0; } // NOTE: The logic here matches that in TransliteratorRegistry. if (parser.idBlockVector.size() == 0 && parser.dataVector.size() == 0) { t = new NullTransliterator(); } else if (parser.idBlockVector.size() == 0 && parser.dataVector.size() == 1) { t = new RuleBasedTransliterator(ID, (TransliterationRuleData*)parser.dataVector.orphanElementAt(0), TRUE); } else if (parser.idBlockVector.size() == 1 && parser.dataVector.size() == 0) { // idBlock, no data -- this is an alias. The ID has // been munged from reverse into forward mode, if // necessary, so instantiate the ID in the forward // direction. if (parser.compoundFilter != NULL) { UnicodeString filterPattern; parser.compoundFilter->toPattern(filterPattern, FALSE); t = createInstance(filterPattern + UnicodeString(ID_DELIM) + *((UnicodeString*)parser.idBlockVector.elementAt(0)), UTRANS_FORWARD, parseError, status); } else t = createInstance(*((UnicodeString*)parser.idBlockVector.elementAt(0)), UTRANS_FORWARD, parseError, status); if (t != NULL) { t->setID(ID); } } else { UVector transliterators(status); int32_t passNumber = 1; int32_t limit = parser.idBlockVector.size(); if (parser.dataVector.size() > limit) limit = parser.dataVector.size(); for (int32_t i = 0; i < limit; i++) { if (i < parser.idBlockVector.size()) { UnicodeString* idBlock = (UnicodeString*)parser.idBlockVector.elementAt(i); if (!idBlock->isEmpty()) { Transliterator* temp = createInstance(*idBlock, UTRANS_FORWARD, parseError, status); if (temp != NULL && temp->getDynamicClassID() != NullTransliterator::getStaticClassID()) transliterators.addElement(temp, status); else delete temp; } } if (!parser.dataVector.isEmpty()) { TransliterationRuleData* data = (TransliterationRuleData*)parser.dataVector.orphanElementAt(0); RuleBasedTransliterator* temprbt = new RuleBasedTransliterator(UnicodeString(CompoundTransliterator::PASS_STRING) + (passNumber++), data, TRUE); // Check if NULL before adding it to transliterators to avoid future usage of NULL pointer. if (temprbt == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return t; } transliterators.addElement(temprbt, status); } } t = new CompoundTransliterator(transliterators, passNumber - 1, parseError, status); // Null pointer check if (t != NULL) { t->setID(ID); t->adoptFilter(parser.orphanCompoundFilter()); } } if (U_SUCCESS(status) && t == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } return t; }