Example #1
0
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;
}
Example #2
0
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;
}