1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)********************************************************************** 3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Copyright (c) 2001-2010, International Business Machines 4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Corporation and others. All Rights Reserved. 5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)********************************************************************** 6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Date Name Description 7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 08/10/2001 aliu Creation. 8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)********************************************************************** 9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*/ 10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/utypes.h" 12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#if !UCONFIG_NO_TRANSLITERATION 14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/translit.h" 16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/resbund.h" 17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/uniset.h" 18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/uscript.h" 19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "rbt.h" 20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "cpdtrans.h" 21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "nultrans.h" 22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "transreg.h" 23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "rbt_data.h" 24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "rbt_pars.h" 25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "tridpars.h" 26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "charstr.h" 27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "uassert.h" 28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "locutil.h" 29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Enable the following symbol to add debugging code that tracks the 31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// allocation, deletion, and use of Entry objects. BoundsChecker has 32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// reported dangling pointer errors with these objects, but I have 33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// been unable to confirm them. I suspect BoundsChecker is getting 34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// confused with pointers going into and coming out of a UHashtable, 35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// despite the hinting code that is designed to help it. 36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// #define DEBUG_MEM 37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#ifdef DEBUG_MEM 38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include <stdio.h> 39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif 40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// UChar constants 42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const UChar LOCALE_SEP = 95; // '_' 43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//static const UChar ID_SEP = 0x002D; /*-*/ 44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//static const UChar VARIANT_SEP = 0x002F; // '/' 45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// String constants 47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const UChar NO_VARIANT[] = { 0 }; // empty string 48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const UChar ANY[] = { 65, 110, 121, 0 }; // Any 49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Resource bundle key for the RuleBasedTransliterator rule. 52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//static const char RB_RULE[] = "Rule"; 54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_NAMESPACE_BEGIN 56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//------------------------------------------------------------------ 58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Alias 59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//------------------------------------------------------------------ 60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorAlias::TransliteratorAlias(const UnicodeString& theAliasID, 62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeSet* cpdFilter) : 63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ID(), 64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) aliasesOrRules(theAliasID), 65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) transes(0), 66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) compoundFilter(cpdFilter), 67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) direction(UTRANS_FORWARD), 68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) type(TransliteratorAlias::SIMPLE) { 69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorAlias::TransliteratorAlias(const UnicodeString& theID, 72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& idBlocks, 73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UVector* adoptedTransliterators, 74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeSet* cpdFilter) : 75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ID(theID), 76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) aliasesOrRules(idBlocks), 77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) transes(adoptedTransliterators), 78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) compoundFilter(cpdFilter), 79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) direction(UTRANS_FORWARD), 80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) type(TransliteratorAlias::COMPOUND) { 81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorAlias::TransliteratorAlias(const UnicodeString& theID, 84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& rules, 85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UTransDirection dir) : 86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ID(theID), 87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) aliasesOrRules(rules), 88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) transes(0), 89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) compoundFilter(0), 90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) direction(dir), 91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) type(TransliteratorAlias::RULES) { 92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorAlias::~TransliteratorAlias() { 95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete transes; 96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)Transliterator* TransliteratorAlias::create(UParseError& pe, 100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode& ec) { 101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_FAILURE(ec)) { 102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Transliterator *t = NULL; 105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) switch (type) { 106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case SIMPLE: 107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) t = Transliterator::createInstance(aliasesOrRules, UTRANS_FORWARD, pe, ec); 108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(U_FAILURE(ec)){ 109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (compoundFilter != 0) 112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) t->adoptFilter((UnicodeSet*)compoundFilter->clone()); 113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case COMPOUND: 115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) { 116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // the total number of transliterators in the compound is the total number of anonymous transliterators 117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // plus the total number of ID blocks-- we start by assuming the list begins and ends with an ID 118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // block and that each pair anonymous transliterators has an ID block between them. Then we go back 119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // to see whether there really are ID blocks at the beginning and end (by looking for U+FFFF, which 120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // marks the position where an anonymous transliterator goes) and adjust accordingly 121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t anonymousRBTs = transes->size(); 122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t transCount = anonymousRBTs * 2 + 1; 123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!aliasesOrRules.isEmpty() && aliasesOrRules[0] == (UChar)(0xffff)) 124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) --transCount; 125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (aliasesOrRules.length() >= 2 && aliasesOrRules[aliasesOrRules.length() - 1] == (UChar)(0xffff)) 126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) --transCount; 127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString noIDBlock((UChar)(0xffff)); 128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) noIDBlock += ((UChar)(0xffff)); 129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t pos = aliasesOrRules.indexOf(noIDBlock); 130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while (pos >= 0) { 131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) --transCount; 132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) pos = aliasesOrRules.indexOf(noIDBlock, pos + 1); 133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UVector transliterators(ec); 136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString idBlock; 137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t blockSeparatorPos = aliasesOrRules.indexOf((UChar)(0xffff)); 138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while (blockSeparatorPos >= 0) { 139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) aliasesOrRules.extract(0, blockSeparatorPos, idBlock); 140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) aliasesOrRules.remove(0, blockSeparatorPos + 1); 141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!idBlock.isEmpty()) 142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) transliterators.addElement(Transliterator::createInstance(idBlock, UTRANS_FORWARD, pe, ec), ec); 143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!transes->isEmpty()) 144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) transliterators.addElement(transes->orphanElementAt(0), ec); 145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) blockSeparatorPos = aliasesOrRules.indexOf((UChar)(0xffff)); 146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!aliasesOrRules.isEmpty()) 148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) transliterators.addElement(Transliterator::createInstance(aliasesOrRules, UTRANS_FORWARD, pe, ec), ec); 149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while (!transes->isEmpty()) 150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) transliterators.addElement(transes->orphanElementAt(0), ec); 151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_SUCCESS(ec)) { 153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) t = new CompoundTransliterator(ID, transliterators, 154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (compoundFilter ? (UnicodeSet*)(compoundFilter->clone()) : 0), 155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) anonymousRBTs, pe, ec); 156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (t == 0) { 157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ec = U_MEMORY_ALLOCATION_ERROR; 158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for (int32_t i = 0; i < transliterators.size(); i++) 162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete (Transliterator*)(transliterators.elementAt(i)); 163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case RULES: 167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(FALSE); // don't call create() if isRuleBased() returns TRUE! 168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return t; 171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UBool TransliteratorAlias::isRuleBased() const { 174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return type == RULES; 175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorAlias::parse(TransliteratorParser& parser, 178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UParseError& pe, UErrorCode& ec) const { 179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(type == RULES); 180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_FAILURE(ec)) { 181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) parser.parse(aliasesOrRules, direction, pe, ec); 185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//---------------------------------------------------------------------- 188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// class TransliteratorSpec 189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//---------------------------------------------------------------------- 190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * A TransliteratorSpec is a string specifying either a source or a target. In more 193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * general terms, it may also specify a variant, but we only use the 194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Spec class for sources and targets. 195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * A Spec may be a locale or a script. If it is a locale, it has a 197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * fallback chain that goes xx_YY_ZZZ -> xx_YY -> xx -> ssss, where 198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * ssss is the script mapping of xx_YY_ZZZ. The Spec API methods 199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * hasFallback(), next(), and reset() iterate over this fallback 200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * sequence. 201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The Spec class canonicalizes itself, so the locale is put into 203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * canonical form, or the script is transformed from an abbreviation 204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * to a full name. 205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)class TransliteratorSpec : public UMemory { 207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) public: 208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorSpec(const UnicodeString& spec); 209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ~TransliteratorSpec(); 210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& get() const; 212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool hasFallback() const; 213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& next(); 214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) void reset(); 215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool isLocale() const; 217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ResourceBundle& getBundle() const; 218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) operator const UnicodeString&() const { return get(); } 220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& getTop() const { return top; } 221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) private: 223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) void setupNext(); 224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString top; 226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString spec; 227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString nextSpec; 228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString scriptName; 229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool isSpecLocale; // TRUE if spec is a locale 230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool isNextLocale; // TRUE if nextSpec is a locale 231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ResourceBundle* res; 232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorSpec(const TransliteratorSpec &other); // forbid copying of this class 234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorSpec &operator=(const TransliteratorSpec &other); // forbid copying of this class 235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}; 236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorSpec::TransliteratorSpec(const UnicodeString& theSpec) 238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles): top(theSpec), 239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) res(0) 240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode status = U_ZERO_ERROR; 242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Locale topLoc(""); 243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) LocaleUtility::initLocaleFromName(theSpec, topLoc); 244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!topLoc.isBogus()) { 245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) res = new ResourceBundle(U_ICUDATA_TRANSLIT, topLoc, status); 246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* test for NULL */ 247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (res == 0) { 248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_FAILURE(status) || status == U_USING_DEFAULT_WARNING) { 251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete res; 252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) res = 0; 253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Canonicalize script name -or- do locale->script mapping 257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_ZERO_ERROR; 258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) static const int32_t capacity = 10; 259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UScriptCode script[capacity]={USCRIPT_INVALID_CODE}; 260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t num = uscript_getCode(CharString().appendInvariantChars(theSpec, status).data(), 261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) script, capacity, &status); 262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (num > 0 && script[0] != USCRIPT_INVALID_CODE) { 263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) scriptName = UnicodeString(uscript_getName(script[0]), -1, US_INV); 264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Canonicalize top 267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (res != 0) { 268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Canonicalize locale name 269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString locStr; 270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) LocaleUtility::initNameFromLocale(topLoc, locStr); 271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!locStr.isBogus()) { 272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) top = locStr; 273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if (scriptName.length() != 0) { 275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // We are a script; use canonical name 276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) top = scriptName; 277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // assert(spec != top); 280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) reset(); 281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorSpec::~TransliteratorSpec() { 284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete res; 285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UBool TransliteratorSpec::hasFallback() const { 288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return nextSpec.length() != 0; 289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorSpec::reset() { 292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (spec != top) { 293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) spec = top; 294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) isSpecLocale = (res != 0); 295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) setupNext(); 296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorSpec::setupNext() { 300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) isNextLocale = FALSE; 301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (isSpecLocale) { 302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) nextSpec = spec; 303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t i = nextSpec.lastIndexOf(LOCALE_SEP); 304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // If i == 0 then we have _FOO, so we fall through 305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // to the scriptName. 306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (i > 0) { 307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) nextSpec.truncate(i); 308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) isNextLocale = TRUE; 309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) nextSpec = scriptName; // scriptName may be empty 311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // spec is a script, so we are at the end 314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) nextSpec.truncate(0); 315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Protocol: 319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// for(const UnicodeString& s(spec.get()); 320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// spec.hasFallback(); s(spec.next())) { ... 321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const UnicodeString& TransliteratorSpec::next() { 323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) spec = nextSpec; 324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) isSpecLocale = isNextLocale; 325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) setupNext(); 326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return spec; 327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const UnicodeString& TransliteratorSpec::get() const { 330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return spec; 331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UBool TransliteratorSpec::isLocale() const { 334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return isSpecLocale; 335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ResourceBundle& TransliteratorSpec::getBundle() const { 338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return *res; 339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//---------------------------------------------------------------------- 342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#ifdef DEBUG_MEM 344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Vector of Entry pointers currently in use 346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static UVector* DEBUG_entries = NULL; 347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 348f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void DEBUG_setup() { 349f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (DEBUG_entries == NULL) { 350f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode ec = U_ZERO_ERROR; 351f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DEBUG_entries = new UVector(ec); 352f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 353f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 354f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 355f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Caller must call DEBUG_setup first. Return index of given Entry, 356f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// if it is in use (not deleted yet), or -1 if not found. 357f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int DEBUG_findEntry(TransliteratorEntry* e) { 358f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for (int i=0; i<DEBUG_entries->size(); ++i) { 359f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (e == (TransliteratorEntry*) DEBUG_entries->elementAt(i)) { 360f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return i; 361f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 362f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 363f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return -1; 364f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 365f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 366f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Track object creation 367f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void DEBUG_newEntry(TransliteratorEntry* e) { 368f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DEBUG_setup(); 369f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (DEBUG_findEntry(e) >= 0) { 370f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // This should really never happen unless the heap is broken 371f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) printf("ERROR DEBUG_newEntry duplicate new pointer %08X\n", e); 372f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 373f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 374f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode ec = U_ZERO_ERROR; 375f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DEBUG_entries->addElement(e, ec); 376f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 377f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 378f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Track object deletion 379f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void DEBUG_delEntry(TransliteratorEntry* e) { 380f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DEBUG_setup(); 381f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int i = DEBUG_findEntry(e); 382f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (i < 0) { 383f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) printf("ERROR DEBUG_delEntry possible double deletion %08X\n", e); 384f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 385f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 386f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DEBUG_entries->removeElementAt(i); 387f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 388f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 389f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Track object usage 390f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void DEBUG_useEntry(TransliteratorEntry* e) { 391f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (e == NULL) return; 392f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DEBUG_setup(); 393f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int i = DEBUG_findEntry(e); 394f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (i < 0) { 395f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) printf("ERROR DEBUG_useEntry possible dangling pointer %08X\n", e); 396f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 397f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 398f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 399f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#else 400f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// If we're not debugging then make these macros into NOPs 401f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define DEBUG_newEntry(x) 402f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define DEBUG_delEntry(x) 403f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define DEBUG_useEntry(x) 404f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif 405f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 406f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//---------------------------------------------------------------------- 407f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// class Entry 408f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//---------------------------------------------------------------------- 409f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 410f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 411f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The Entry object stores objects of different types and 412f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * singleton objects as placeholders for rule-based transliterators to 413f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * be built as needed. Instances of this struct can be placeholders, 414f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * can represent prototype transliterators to be cloned, or can 415f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * represent TransliteratorData objects. We don't support storing 416f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * classes in the registry because we don't have the rtti infrastructure 417f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * for it. We could easily add this if there is a need for it in the 418f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * future. 419f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 420f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)class TransliteratorEntry : public UMemory { 421f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)public: 422f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) enum Type { 423f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RULES_FORWARD, 424f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RULES_REVERSE, 425f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) LOCALE_RULES, 426f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) PROTOTYPE, 427f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) RBT_DATA, 428f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) COMPOUND_RBT, 429f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ALIAS, 430f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) FACTORY, 431f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) NONE // Only used for uninitialized entries 432f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } entryType; 433f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // NOTE: stringArg cannot go inside the union because 434f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // it has a copy constructor 435f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString stringArg; // For RULES_*, ALIAS, COMPOUND_RBT 436f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t intArg; // For COMPOUND_RBT, LOCALE_RULES 437f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeSet* compoundFilter; // For COMPOUND_RBT 438f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) union { 439f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Transliterator* prototype; // For PROTOTYPE 440f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliterationRuleData* data; // For RBT_DATA 441f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UVector* dataVector; // For COMPOUND_RBT 442f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) struct { 443f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Transliterator::Factory function; 444f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Transliterator::Token context; 445f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } factory; // For FACTORY 446f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } u; 447f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry(); 448f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ~TransliteratorEntry(); 449f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) void adoptPrototype(Transliterator* adopted); 450f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) void setFactory(Transliterator::Factory factory, 451f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Transliterator::Token context); 452f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 453f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)private: 454f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 455f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry(const TransliteratorEntry &other); // forbid copying of this class 456f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry &operator=(const TransliteratorEntry &other); // forbid copying of this class 457f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}; 458f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 459f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorEntry::TransliteratorEntry() { 460f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) u.prototype = 0; 461f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) compoundFilter = NULL; 462f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entryType = NONE; 463f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DEBUG_newEntry(this); 464f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 465f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 466f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorEntry::~TransliteratorEntry() { 467f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DEBUG_delEntry(this); 468f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entryType == PROTOTYPE) { 469f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete u.prototype; 470f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if (entryType == RBT_DATA) { 471f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // The data object is shared between instances of RBT. The 472f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // entry object owns it. It should only be deleted when the 473f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // transliterator component is being cleaned up. Doing so 474f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // invalidates any RBTs that the user has instantiated. 475f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete u.data; 476f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if (entryType == COMPOUND_RBT) { 477f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while (u.dataVector != NULL && !u.dataVector->isEmpty()) 478f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete (TransliterationRuleData*)u.dataVector->orphanElementAt(0); 479f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete u.dataVector; 480f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 481f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete compoundFilter; 482f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 483f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 484f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorEntry::adoptPrototype(Transliterator* adopted) { 485f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entryType == PROTOTYPE) { 486f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete u.prototype; 487f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 488f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entryType = PROTOTYPE; 489f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) u.prototype = adopted; 490f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 491f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 492f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorEntry::setFactory(Transliterator::Factory factory, 493f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Transliterator::Token context) { 494f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entryType == PROTOTYPE) { 495f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete u.prototype; 496f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 497f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entryType = FACTORY; 498f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) u.factory.function = factory; 499f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) u.factory.context = context; 500f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 501f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 502f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// UObjectDeleter for Hashtable::setValueDeleter 503f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CDECL_BEGIN 504f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void U_CALLCONV 505f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)deleteEntry(void* obj) { 506f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete (TransliteratorEntry*) obj; 507f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 508f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CDECL_END 509f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 510f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//---------------------------------------------------------------------- 511f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// class TransliteratorRegistry: Basic public API 512f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//---------------------------------------------------------------------- 513f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 514f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorRegistry::TransliteratorRegistry(UErrorCode& status) : 515f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) registry(TRUE, status), 516f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) specDAG(TRUE, status), 517f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) availableIDs(status) 518f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 519f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) registry.setValueDeleter(deleteEntry); 520f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) availableIDs.setDeleter(uhash_deleteUnicodeString); 521f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) availableIDs.setComparer(uhash_compareCaselessUnicodeString); 522f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) specDAG.setValueDeleter(uhash_deleteHashtable); 523f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 524f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 525f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorRegistry::~TransliteratorRegistry() { 526f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Through the magic of C++, everything cleans itself up 527f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 528f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 529f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)Transliterator* TransliteratorRegistry::get(const UnicodeString& ID, 530f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorAlias*& aliasReturn, 531f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode& status) { 532f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(aliasReturn == NULL); 533f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry *entry = find(ID); 534f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return (entry == 0) ? 0 535f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) : instantiateEntry(ID, entry, aliasReturn, status); 536f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 537f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 538f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)Transliterator* TransliteratorRegistry::reget(const UnicodeString& ID, 539f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorParser& parser, 540f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorAlias*& aliasReturn, 541f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode& status) { 542f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(aliasReturn == NULL); 543f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry *entry = find(ID); 544f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 545f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entry == 0) { 546f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // We get to this point if there are two threads, one of which 547f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // is instantiating an ID, and another of which is removing 548f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // the same ID from the registry, and the timing is just right. 549f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 550f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 551f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 552f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // The usage model for the caller is that they will first call 553f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // reg->get() inside the mutex, they'll get back an alias, they call 554f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // alias->isRuleBased(), and if they get TRUE, they call alias->parse() 555f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // outside the mutex, then reg->reget() inside the mutex again. A real 556f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // mess, but it gets things working for ICU 3.0. [alan]. 557f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 558f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Note: It's possible that in between the caller calling 559f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // alias->parse() and reg->reget(), that another thread will have 560f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // called reg->reget(), and the entry will already have been fixed up. 561f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // We have to detect this so we don't stomp over existing entry 562f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // data members and potentially leak memory (u.data and compoundFilter). 563f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 564f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entry->entryType == TransliteratorEntry::RULES_FORWARD || 565f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->entryType == TransliteratorEntry::RULES_REVERSE || 566f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->entryType == TransliteratorEntry::LOCALE_RULES) { 567f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 568f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (parser.idBlockVector.isEmpty() && parser.dataVector.isEmpty()) { 569f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->u.data = 0; 570f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->entryType = TransliteratorEntry::ALIAS; 571f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->stringArg = UNICODE_STRING_SIMPLE("Any-NULL"); 572f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 573f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if (parser.idBlockVector.isEmpty() && parser.dataVector.size() == 1) { 574f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->u.data = (TransliterationRuleData*)parser.dataVector.orphanElementAt(0); 575f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->entryType = TransliteratorEntry::RBT_DATA; 576f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 577f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if (parser.idBlockVector.size() == 1 && parser.dataVector.isEmpty()) { 578f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->stringArg = *(UnicodeString*)(parser.idBlockVector.elementAt(0)); 579f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->compoundFilter = parser.orphanCompoundFilter(); 580f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->entryType = TransliteratorEntry::ALIAS; 581f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 582f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else { 583f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->entryType = TransliteratorEntry::COMPOUND_RBT; 584f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->compoundFilter = parser.orphanCompoundFilter(); 585f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->u.dataVector = new UVector(status); 586f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->stringArg.remove(); 587f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 588f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t limit = parser.idBlockVector.size(); 589f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (parser.dataVector.size() > limit) 590f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) limit = parser.dataVector.size(); 591f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 592f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for (int32_t i = 0; i < limit; i++) { 593f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (i < parser.idBlockVector.size()) { 594f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString* idBlock = (UnicodeString*)parser.idBlockVector.elementAt(i); 595f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!idBlock->isEmpty()) 596f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->stringArg += *idBlock; 597f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 598f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!parser.dataVector.isEmpty()) { 599f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliterationRuleData* data = (TransliterationRuleData*)parser.dataVector.orphanElementAt(0); 600f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->u.dataVector->addElement(data, status); 601f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->stringArg += (UChar)0xffff; // use U+FFFF to mark position of RBTs in ID block 602f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 603f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 604f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 605f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 606f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 607f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Transliterator *t = 608f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) instantiateEntry(ID, entry, aliasReturn, status); 609f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return t; 610f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 611f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 612f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorRegistry::put(Transliterator* adoptedProto, 613f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool visible, 614f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode& ec) 615f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 616f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry *entry = new TransliteratorEntry(); 617f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entry == NULL) { 618f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ec = U_MEMORY_ALLOCATION_ERROR; 619f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 620f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 621f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->adoptPrototype(adoptedProto); 622f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) registerEntry(adoptedProto->getID(), entry, visible); 623f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 624f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 625f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorRegistry::put(const UnicodeString& ID, 626f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Transliterator::Factory factory, 627f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Transliterator::Token context, 628f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool visible, 629f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode& ec) { 630f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry *entry = new TransliteratorEntry(); 631f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entry == NULL) { 632f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ec = U_MEMORY_ALLOCATION_ERROR; 633f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 634f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 635f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->setFactory(factory, context); 636f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) registerEntry(ID, entry, visible); 637f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 638f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 639f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorRegistry::put(const UnicodeString& ID, 640f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& resourceName, 641f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UTransDirection dir, 642f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool readonlyResourceAlias, 643f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool visible, 644f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode& ec) { 645f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry *entry = new TransliteratorEntry(); 646f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entry == NULL) { 647f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ec = U_MEMORY_ALLOCATION_ERROR; 648f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 649f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 650f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->entryType = (dir == UTRANS_FORWARD) ? TransliteratorEntry::RULES_FORWARD 651f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) : TransliteratorEntry::RULES_REVERSE; 652f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (readonlyResourceAlias) { 653f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->stringArg.setTo(TRUE, resourceName.getBuffer(), -1); 654f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 655f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else { 656f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->stringArg = resourceName; 657f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 658f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) registerEntry(ID, entry, visible); 659f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 660f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 661f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorRegistry::put(const UnicodeString& ID, 662f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& alias, 663f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool readonlyAliasAlias, 664f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool visible, 665f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode& /*ec*/) { 666f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry *entry = new TransliteratorEntry(); 667f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Null pointer check 668f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entry != NULL) { 669f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->entryType = TransliteratorEntry::ALIAS; 670f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (readonlyAliasAlias) { 671f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->stringArg.setTo(TRUE, alias.getBuffer(), -1); 672f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 673f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else { 674f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->stringArg = alias; 675f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 676f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) registerEntry(ID, entry, visible); 677f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 678f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 679f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 680f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorRegistry::remove(const UnicodeString& ID) { 681f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString source, target, variant; 682f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool sawSource; 683f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorIDParser::IDtoSTV(ID, source, target, variant, sawSource); 684f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Only need to do this if ID.indexOf('-') < 0 685f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString id; 686f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorIDParser::STVtoID(source, target, variant, id); 687f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) registry.remove(id); 688f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) removeSTV(source, target, variant); 689f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) availableIDs.removeElement((void*) &id); 690f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 691f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 692f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//---------------------------------------------------------------------- 693f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// class TransliteratorRegistry: Public ID and spec management 694f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//---------------------------------------------------------------------- 695f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 696f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 697f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * == OBSOLETE - remove in ICU 3.4 == 698f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Return the number of IDs currently registered with the system. 699f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * To retrieve the actual IDs, call getAvailableID(i) with 700f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * i from 0 to countAvailableIDs() - 1. 701f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 702f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)int32_t TransliteratorRegistry::countAvailableIDs(void) const { 703f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return availableIDs.size(); 704f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 705f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 706f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 707f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * == OBSOLETE - remove in ICU 3.4 == 708f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Return the index-th available ID. index must be between 0 709f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * and countAvailableIDs() - 1, inclusive. If index is out of 710f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * range, the result of getAvailableID(0) is returned. 711f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 712f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const UnicodeString& TransliteratorRegistry::getAvailableID(int32_t index) const { 713f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (index < 0 || index >= availableIDs.size()) { 714f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) index = 0; 715f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 716f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return *(const UnicodeString*) availableIDs[index]; 717f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 718f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 719f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)StringEnumeration* TransliteratorRegistry::getAvailableIDs() const { 720f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return new Enumeration(*this); 721f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 722f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 723f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)int32_t TransliteratorRegistry::countAvailableSources(void) const { 724f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return specDAG.count(); 725f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 726f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 727f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString& TransliteratorRegistry::getAvailableSource(int32_t index, 728f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString& result) const { 729f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t pos = -1; 730f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UHashElement *e = 0; 731f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while (index-- >= 0) { 732f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) e = specDAG.nextElement(pos); 733f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (e == 0) { 734f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 735f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 736f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 737f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (e == 0) { 738f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result.truncate(0); 739f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 740f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result = *(UnicodeString*) e->key.pointer; 741f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 742f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return result; 743f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 744f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 745f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)int32_t TransliteratorRegistry::countAvailableTargets(const UnicodeString& source) const { 746f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Hashtable *targets = (Hashtable*) specDAG.get(source); 747f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return (targets == 0) ? 0 : targets->count(); 748f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 749f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 750f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString& TransliteratorRegistry::getAvailableTarget(int32_t index, 751f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& source, 752f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString& result) const { 753f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Hashtable *targets = (Hashtable*) specDAG.get(source); 754f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (targets == 0) { 755f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result.truncate(0); // invalid source 756f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return result; 757f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 758f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t pos = -1; 759f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UHashElement *e = 0; 760f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while (index-- >= 0) { 761f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) e = targets->nextElement(pos); 762f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (e == 0) { 763f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 764f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 765f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 766f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (e == 0) { 767f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result.truncate(0); // invalid index 768f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 769f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result = *(UnicodeString*) e->key.pointer; 770f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 771f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return result; 772f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 773f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 774f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)int32_t TransliteratorRegistry::countAvailableVariants(const UnicodeString& source, 775f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& target) const { 776f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Hashtable *targets = (Hashtable*) specDAG.get(source); 777f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (targets == 0) { 778f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 779f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 780f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UVector *variants = (UVector*) targets->get(target); 781f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // variants may be 0 if the source/target are invalid 782f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return (variants == 0) ? 0 : variants->size(); 783f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 784f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 785f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString& TransliteratorRegistry::getAvailableVariant(int32_t index, 786f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& source, 787f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& target, 788f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString& result) const { 789f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Hashtable *targets = (Hashtable*) specDAG.get(source); 790f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (targets == 0) { 791f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result.truncate(0); // invalid source 792f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return result; 793f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 794f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UVector *variants = (UVector*) targets->get(target); 795f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (variants == 0) { 796f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result.truncate(0); // invalid target 797f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return result; 798f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 799f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString *v = (UnicodeString*) variants->elementAt(index); 800f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (v == 0) { 801f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result.truncate(0); // invalid index 802f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 803f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) result = *v; 804f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 805f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return result; 806f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 807f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 808f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//---------------------------------------------------------------------- 809f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// class TransliteratorRegistry::Enumeration 810f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//---------------------------------------------------------------------- 811f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 812f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorRegistry::Enumeration::Enumeration(const TransliteratorRegistry& _reg) : 813f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) index(0), reg(_reg) { 814f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 815f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 816f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorRegistry::Enumeration::~Enumeration() { 817f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 818f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 819f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)int32_t TransliteratorRegistry::Enumeration::count(UErrorCode& /*status*/) const { 820f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return reg.availableIDs.size(); 821f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 822f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 823f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const UnicodeString* TransliteratorRegistry::Enumeration::snext(UErrorCode& status) { 824f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // This is sloppy but safe -- if we get out of sync with the underlying 825f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // registry, we will still return legal strings, but they might not 826f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // correspond to the snapshot at construction time. So there could be 827f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // duplicate IDs or omitted IDs if insertions or deletions occur in one 828f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // thread while another is iterating. To be more rigorous, add a timestamp, 829f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // which is incremented with any modification, and validate this iterator 830f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // against the timestamp at construction time. This probably isn't worth 831f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // doing as long as there is some possibility of removing this code in favor 832f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // of some new code based on Doug's service framework. 833f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_FAILURE(status)) { 834f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 835f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 836f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t n = reg.availableIDs.size(); 837f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (index > n) { 838f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_ENUM_OUT_OF_SYNC_ERROR; 839f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 840f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // index == n is okay -- this means we've reached the end 841f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (index < n) { 842f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Copy the string! This avoids lifetime problems. 843f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) unistr = *(const UnicodeString*)reg.availableIDs[index++]; 844f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return &unistr; 845f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 846f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 847f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 848f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 849f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 850f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorRegistry::Enumeration::reset(UErrorCode& /*status*/) { 851f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) index = 0; 852f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 853f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 854f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TransliteratorRegistry::Enumeration) 855f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 856f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//---------------------------------------------------------------------- 857f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// class TransliteratorRegistry: internal 858f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//---------------------------------------------------------------------- 859f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 860f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 861f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Convenience method. Calls 6-arg registerEntry(). 862f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 863f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorRegistry::registerEntry(const UnicodeString& source, 864f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& target, 865f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& variant, 866f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry* adopted, 867f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool visible) { 868f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString ID; 869f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString s(source); 870f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (s.length() == 0) { 871f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) s = ANY; 872f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 873f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorIDParser::STVtoID(source, target, variant, ID); 874f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) registerEntry(ID, s, target, variant, adopted, visible); 875f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 876f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 877f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 878f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Convenience method. Calls 6-arg registerEntry(). 879f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 880f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorRegistry::registerEntry(const UnicodeString& ID, 881f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry* adopted, 882f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool visible) { 883f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString source, target, variant; 884f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool sawSource; 885f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorIDParser::IDtoSTV(ID, source, target, variant, sawSource); 886f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Only need to do this if ID.indexOf('-') < 0 887f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString id; 888f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorIDParser::STVtoID(source, target, variant, id); 889f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) registerEntry(id, source, target, variant, adopted, visible); 890f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 891f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 892f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 893f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Register an entry object (adopted) with the given ID, source, 894f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * target, and variant strings. 895f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 896f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorRegistry::registerEntry(const UnicodeString& ID, 897f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& source, 898f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& target, 899f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& variant, 900f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry* adopted, 901f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool visible) { 902f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode status = U_ZERO_ERROR; 903f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) registry.put(ID, adopted, status); 904f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (visible) { 905f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) registerSTV(source, target, variant); 906f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!availableIDs.contains((void*) &ID)) { 907f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString *newID = (UnicodeString *)ID.clone(); 908f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Check to make sure newID was created. 909f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (newID != NULL) { 910f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // NUL-terminate the ID string 911f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) newID->getTerminatedBuffer(); 912f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) availableIDs.addElement(newID, status); 913f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 914f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 915f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 916f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) removeSTV(source, target, variant); 917f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) availableIDs.removeElement((void*) &ID); 918f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 919f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 920f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 921f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 922f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Register a source-target/variant in the specDAG. Variant may be 923f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * empty, but source and target must not be. If variant is empty then 924f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * the special variant NO_VARIANT is stored in slot zero of the 925f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * UVector of variants. 926f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 927f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorRegistry::registerSTV(const UnicodeString& source, 928f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& target, 929f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& variant) { 930f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // assert(source.length() > 0); 931f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // assert(target.length() > 0); 932f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode status = U_ZERO_ERROR; 933f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Hashtable *targets = (Hashtable*) specDAG.get(source); 934f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (targets == 0) { 935f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) targets = new Hashtable(TRUE, status); 936f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_FAILURE(status) || targets == 0) { 937f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 938f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 939f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) targets->setValueDeleter(uhash_deleteUObject); 940f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) specDAG.put(source, targets, status); 941f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 942f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UVector *variants = (UVector*) targets->get(target); 943f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (variants == 0) { 944f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) variants = new UVector(uhash_deleteUnicodeString, 945f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) uhash_compareCaselessUnicodeString, status); 946f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (variants == 0) { 947f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 948f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 949f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) targets->put(target, variants, status); 950f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 951f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // assert(NO_VARIANT == ""); 952f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // We add the variant string. If it is the special "no variant" 953f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // string, that is, the empty string, we add it at position zero. 954f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!variants->contains((void*) &variant)) { 955f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString *tempus; // Used for null pointer check. 956f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (variant.length() > 0) { 957f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) tempus = new UnicodeString(variant); 958f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (tempus != NULL) { 959f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) variants->addElement(tempus, status); 960f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 961f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 962f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) tempus = new UnicodeString(NO_VARIANT) ; 963f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (tempus != NULL) { 964f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) variants->insertElementAt(tempus, 0, status); 965f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 966f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 967f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 968f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 969f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 970f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 971f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Remove a source-target/variant from the specDAG. 972f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 973f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TransliteratorRegistry::removeSTV(const UnicodeString& source, 974f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& target, 975f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& variant) { 976f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // assert(source.length() > 0); 977f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // assert(target.length() > 0); 978f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// UErrorCode status = U_ZERO_ERROR; 979f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Hashtable *targets = (Hashtable*) specDAG.get(source); 980f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (targets == 0) { 981f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; // should never happen for valid s-t/v 982f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 983f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UVector *variants = (UVector*) targets->get(target); 984f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (variants == 0) { 985f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; // should never happen for valid s-t/v 986f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 987f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) variants->removeElement((void*) &variant); 988f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (variants->size() == 0) { 989f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) targets->remove(target); // should delete variants 990f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (targets->count() == 0) { 991f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) specDAG.remove(source); // should delete targets 992f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 993f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 994f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 995f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 996f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 997f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Attempt to find a source-target/variant in the dynamic registry 998f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * store. Return 0 on failure. 999f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 1000f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Caller does NOT own returned object. 1001f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 1002f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorEntry* TransliteratorRegistry::findInDynamicStore(const TransliteratorSpec& src, 1003f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const TransliteratorSpec& trg, 1004f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& variant) const { 1005f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString ID; 1006f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorIDParser::STVtoID(src, trg, variant, ID); 1007f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry *e = (TransliteratorEntry*) registry.get(ID); 1008f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) DEBUG_useEntry(e); 1009f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return e; 1010f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 1011f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1012f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 1013f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Attempt to find a source-target/variant in the static locale 1014f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * resource store. Do not perform fallback. Return 0 on failure. 1015f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 1016f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * On success, create a new entry object, register it in the dynamic 1017f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * store, and return a pointer to it, but do not make it public -- 1018f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * just because someone requested something, we do not expand the 1019f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * available ID list (or spec DAG). 1020f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 1021f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Caller does NOT own returned object. 1022f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 1023f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorEntry* TransliteratorRegistry::findInStaticStore(const TransliteratorSpec& src, 1024f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const TransliteratorSpec& trg, 1025f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& variant) { 1026f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry* entry = 0; 1027f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (src.isLocale()) { 1028f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry = findInBundle(src, trg, variant, UTRANS_FORWARD); 1029f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else if (trg.isLocale()) { 1030f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry = findInBundle(trg, src, variant, UTRANS_REVERSE); 1031f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1032f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1033f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // If we found an entry, store it in the Hashtable for next 1034f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // time. 1035f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entry != 0) { 1036f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) registerEntry(src.getTop(), trg.getTop(), variant, entry, FALSE); 1037f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1038f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1039f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return entry; 1040f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 1041f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1042f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// As of 2.0, resource bundle keys cannot contain '_' 1043f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const UChar TRANSLITERATE_TO[] = {84,114,97,110,115,108,105,116,101,114,97,116,101,84,111,0}; // "TransliterateTo" 1044f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1045f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const UChar TRANSLITERATE_FROM[] = {84,114,97,110,115,108,105,116,101,114,97,116,101,70,114,111,109,0}; // "TransliterateFrom" 1046f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1047f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const UChar TRANSLITERATE[] = {84,114,97,110,115,108,105,116,101,114,97,116,101,0}; // "Transliterate" 1048f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1049f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 1050f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Attempt to find an entry in a single resource bundle. This is 1051f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * a one-sided lookup. findInStaticStore() performs up to two such 1052f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * lookups, one for the source, and one for the target. 1053f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 1054f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Do not perform fallback. Return 0 on failure. 1055f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 1056f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * On success, create a new Entry object, populate it, and return it. 1057f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The caller owns the returned object. 1058f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 1059f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorEntry* TransliteratorRegistry::findInBundle(const TransliteratorSpec& specToOpen, 1060f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const TransliteratorSpec& specToFind, 1061f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UnicodeString& variant, 1062f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UTransDirection direction) 1063f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 1064f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString utag; 1065f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString resStr; 1066f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t pass; 1067f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1068f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for (pass=0; pass<2; ++pass) { 1069f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) utag.truncate(0); 1070f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // First try either TransliteratorTo_xxx or 1071f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // TransliterateFrom_xxx, then try the bidirectional 1072f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Transliterate_xxx. This precedence order is arbitrary 1073f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // but must be consistent and documented. 1074f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (pass == 0) { 1075f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) utag.append(direction == UTRANS_FORWARD ? 1076f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TRANSLITERATE_TO : TRANSLITERATE_FROM); 1077f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 1078f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) utag.append(TRANSLITERATE); 1079f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1080f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString s(specToFind.get()); 1081f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) utag.append(s.toUpper("")); 1082f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode status = U_ZERO_ERROR; 1083f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ResourceBundle subres(specToOpen.getBundle().get( 1084f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) CharString().appendInvariantChars(utag, status).data(), status)); 1085f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_FAILURE(status) || status == U_USING_DEFAULT_WARNING) { 1086f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) continue; 1087f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1088f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1089f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) s.truncate(0); 1090f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (specToOpen.get() != LocaleUtility::initNameFromLocale(subres.getLocale(), s)) { 1091f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) continue; 1092f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1093f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1094f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (variant.length() != 0) { 1095f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_ZERO_ERROR; 1096f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) resStr = subres.getStringEx( 1097f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) CharString().appendInvariantChars(variant, status).data(), status); 1098f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_SUCCESS(status)) { 1099f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Exit loop successfully 1100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 1101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 1103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Variant is empty, which means match the first variant listed. 1104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_ZERO_ERROR; 1105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) resStr = subres.getStringEx(1, status); 1106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_SUCCESS(status)) { 1107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Exit loop successfully 1108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 1109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (pass==2) { 1114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Failed 1115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 1116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // We have succeeded in loading a string from the locale 1119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // resources. Create a new registry entry to hold it and return it. 1120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry *entry = new TransliteratorEntry(); 1121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entry != 0) { 1122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // The direction is always forward for the 1123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // TransliterateTo_xxx and TransliterateFrom_xxx 1124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // items; those are unidirectional forward rules. 1125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // For the bidirectional Transliterate_xxx items, 1126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // the direction is the value passed in to this 1127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // function. 1128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t dir = (pass == 0) ? UTRANS_FORWARD : direction; 1129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->entryType = TransliteratorEntry::LOCALE_RULES; 1130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->stringArg = resStr; 1131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry->intArg = dir; 1132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return entry; 1135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 1136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 1138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Convenience method. Calls 3-arg find(). 1139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 1140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorEntry* TransliteratorRegistry::find(const UnicodeString& ID) { 1141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString source, target, variant; 1142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool sawSource; 1143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorIDParser::IDtoSTV(ID, source, target, variant, sawSource); 1144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return find(source, target, variant); 1145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 1146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 1148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Top-level find method. Attempt to find a source-target/variant in 1149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * either the dynamic or the static (locale resource) store. Perform 1150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * fallback. 1151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 1152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Lookup sequence for ss_SS_SSS-tt_TT_TTT/v: 1153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 1154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * ss_SS_SSS-tt_TT_TTT/v -- in hashtable 1155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * ss_SS_SSS-tt_TT_TTT/v -- in ss_SS_SSS (no fallback) 1156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 1157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * repeat with t = tt_TT_TTT, tt_TT, tt, and tscript 1158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 1159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * ss_SS_SSS-t/ * 1160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * ss_SS-t/ * 1161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * ss-t/ * 1162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * sscript-t/ * 1163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 1164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Here * matches the first variant listed. 1165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 1166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Caller does NOT own returned object. Return 0 on failure. 1167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 1168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TransliteratorEntry* TransliteratorRegistry::find(UnicodeString& source, 1169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString& target, 1170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString& variant) { 1171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorSpec src(source); 1173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorSpec trg(target); 1174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry* entry; 1175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Seek exact match in hashtable. Temporary fix for ICU 4.6. 1177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // TODO: The general logic for finding a matching transliterator needs to be reviewed. 1178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // ICU ticket #8089 1179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString ID; 1180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorIDParser::STVtoID(source, target, variant, ID); 1181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry = (TransliteratorEntry*) registry.get(ID); 1182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entry != 0) { 1183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // std::string ss; 1184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // std::cout << ID.toUTF8String(ss) << std::endl; 1185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return entry; 1186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (variant.length() != 0) { 1189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Seek exact match in hashtable 1191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry = findInDynamicStore(src, trg, variant); 1192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entry != 0) { 1193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return entry; 1194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Seek exact match in locale resources 1197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry = findInStaticStore(src, trg, variant); 1198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entry != 0) { 1199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return entry; 1200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for (;;) { 1204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) src.reset(); 1205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for (;;) { 1206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Seek match in hashtable 1207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry = findInDynamicStore(src, trg, NO_VARIANT); 1208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entry != 0) { 1209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return entry; 1210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Seek match in locale resources 1213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) entry = findInStaticStore(src, trg, NO_VARIANT); 1214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (entry != 0) { 1215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return entry; 1216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!src.hasFallback()) { 1218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 1219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) src.next(); 1221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (!trg.hasFallback()) { 1223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) break; 1224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) trg.next(); 1226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 1229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 1230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 1232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Given an Entry object, instantiate it. Caller owns result. Return 1233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 0 on failure. 1234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 1235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Return a non-empty aliasReturn value if the ID points to an alias. 1236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * We cannot instantiate it ourselves because the alias may contain 1237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * filters or compounds, which we do not understand. Caller should 1238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * make aliasReturn empty before calling. 1239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 1240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The entry object is assumed to reside in the dynamic store. It may be 1241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * modified. 1242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 1243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)Transliterator* TransliteratorRegistry::instantiateEntry(const UnicodeString& ID, 1244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorEntry *entry, 1245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorAlias* &aliasReturn, 1246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode& status) { 1247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Transliterator *t = 0; 1248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(aliasReturn == 0); 1249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) switch (entry->entryType) { 1251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case TransliteratorEntry::RBT_DATA: 1252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) t = new RuleBasedTransliterator(ID, entry->u.data); 1253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (t == 0) { 1254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_MEMORY_ALLOCATION_ERROR; 1255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return t; 1257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case TransliteratorEntry::PROTOTYPE: 1258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) t = entry->u.prototype->clone(); 1259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (t == 0) { 1260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_MEMORY_ALLOCATION_ERROR; 1261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return t; 1263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case TransliteratorEntry::ALIAS: 1264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) aliasReturn = new TransliteratorAlias(entry->stringArg, entry->compoundFilter); 1265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (aliasReturn == 0) { 1266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_MEMORY_ALLOCATION_ERROR; 1267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 1269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case TransliteratorEntry::FACTORY: 1270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) t = entry->u.factory.function(ID, entry->u.factory.context); 1271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (t == 0) { 1272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_MEMORY_ALLOCATION_ERROR; 1273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return t; 1275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case TransliteratorEntry::COMPOUND_RBT: 1276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) { 1277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UVector* rbts = new UVector(entry->u.dataVector->size(), status); 1278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Check for null pointer 1279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (rbts == NULL) { 1280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_MEMORY_ALLOCATION_ERROR; 1281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return NULL; 1282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t passNumber = 1; 1284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for (int32_t i = 0; U_SUCCESS(status) && i < entry->u.dataVector->size(); i++) { 1285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Transliterator* t = new RuleBasedTransliterator(UnicodeString(CompoundTransliterator::PASS_STRING) + (passNumber++), 1286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (TransliterationRuleData*)(entry->u.dataVector->elementAt(i)), FALSE); 1287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (t == 0) 1288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_MEMORY_ALLOCATION_ERROR; 1289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else 1290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) rbts->addElement(t, status); 1291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (U_FAILURE(status)) { 1293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete rbts; 1294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 1295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) aliasReturn = new TransliteratorAlias(ID, entry->stringArg, rbts, entry->compoundFilter); 1297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (aliasReturn == 0) { 1299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_MEMORY_ALLOCATION_ERROR; 1300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 1302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case TransliteratorEntry::LOCALE_RULES: 1303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) aliasReturn = new TransliteratorAlias(ID, entry->stringArg, 1304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (UTransDirection) entry->intArg); 1305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (aliasReturn == 0) { 1306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_MEMORY_ALLOCATION_ERROR; 1307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 1309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case TransliteratorEntry::RULES_FORWARD: 1310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) case TransliteratorEntry::RULES_REVERSE: 1311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Process the rule data into a TransliteratorRuleData object, 1312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // and possibly also into an ::id header and/or footer. Then 1313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // we modify the registry with the parsed data and retry. 1314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) { 1315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TransliteratorParser parser(status); 1316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // We use the file name, taken from another resource bundle 1318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // 2-d array at static init time, as a locale language. We're 1319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // just using the locale mechanism to map through to a file 1320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // name; this in no way represents an actual locale. 1321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) //CharString ch(entry->stringArg); 1322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) //UResourceBundle *bundle = ures_openDirect(0, ch, &status); 1323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString rules = entry->stringArg; 1324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) //ures_close(bundle); 1325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) //if (U_FAILURE(status)) { 1327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // We have a failure of some kind. Remove the ID from the 1328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // registry so we don't keep trying. NOTE: This will throw off 1329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // anyone who is, at the moment, trying to iterate over the 1330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // available IDs. That's acceptable since we should never 1331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // really get here except under installation, configuration, 1332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // or unrecoverable run time memory failures. 1333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // remove(ID); 1334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) //} else { 1335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // If the status indicates a failure, then we don't have any 1337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // rules -- there is probably an installation error. The list 1338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // in the root locale should correspond to all the installed 1339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // transliterators; if it lists something that's not 1340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // installed, we'll get an error from ResourceBundle. 1341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) aliasReturn = new TransliteratorAlias(ID, rules, 1342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ((entry->entryType == TransliteratorEntry::RULES_REVERSE) ? 1343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UTRANS_REVERSE : UTRANS_FORWARD)); 1344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (aliasReturn == 0) { 1345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) status = U_MEMORY_ALLOCATION_ERROR; 1346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) //} 1348f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1349f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 1350f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) default: 1351f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) U_ASSERT(FALSE); // can't get here 1352f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return 0; 1353f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 1354f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 1355f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_NAMESPACE_END 1356f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1357f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif /* #if !UCONFIG_NO_TRANSLITERATION */ 1358f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 1359f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//eof 1360