diff options
Diffstat (limited to 'intl/icu/source/i18n/transreg.h')
-rw-r--r-- | intl/icu/source/i18n/transreg.h | 466 |
1 files changed, 466 insertions, 0 deletions
diff --git a/intl/icu/source/i18n/transreg.h b/intl/icu/source/i18n/transreg.h new file mode 100644 index 000000000..334963f8d --- /dev/null +++ b/intl/icu/source/i18n/transreg.h @@ -0,0 +1,466 @@ +// Copyright (C) 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +********************************************************************** +* Copyright (c) 2001-2014, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +* Date Name Description +* 08/10/2001 aliu Creation. +********************************************************************** +*/ +#ifndef _TRANSREG_H +#define _TRANSREG_H + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_TRANSLITERATION + +#include "unicode/uobject.h" +#include "unicode/translit.h" +#include "hash.h" +#include "uvector.h" + +U_NAMESPACE_BEGIN + +class TransliteratorEntry; +class TransliteratorSpec; +class UnicodeString; + +//------------------------------------------------------------------ +// TransliteratorAlias +//------------------------------------------------------------------ + +/** + * A TransliteratorAlias object is returned by get() if the given ID + * actually translates into something else. The caller then invokes + * the create() method on the alias to create the actual + * transliterator, and deletes the alias. + * + * Why all the shenanigans? To prevent circular calls between + * the registry code and the transliterator code that deadlocks. + */ +class TransliteratorAlias : public UMemory { + public: + /** + * Construct a simple alias (type == SIMPLE) + * @param aliasID the given id. + */ + TransliteratorAlias(const UnicodeString& aliasID, const UnicodeSet* compoundFilter); + + /** + * Construct a compound RBT alias (type == COMPOUND) + */ + TransliteratorAlias(const UnicodeString& ID, const UnicodeString& idBlocks, + UVector* adoptedTransliterators, + const UnicodeSet* compoundFilter); + + /** + * Construct a rules alias (type = RULES) + */ + TransliteratorAlias(const UnicodeString& theID, + const UnicodeString& rules, + UTransDirection dir); + + ~TransliteratorAlias(); + + /** + * The whole point of create() is that the caller must invoke + * it when the registry mutex is NOT held, to prevent deadlock. + * It may only be called once. + * + * Note: Only call create() if isRuleBased() returns FALSE. + * + * This method must be called *outside* of the TransliteratorRegistry + * mutex. + */ + Transliterator* create(UParseError&, UErrorCode&); + + /** + * Return TRUE if this alias is rule-based. If so, the caller + * must call parse() on it, then call TransliteratorRegistry::reget(). + */ + UBool isRuleBased() const; + + /** + * If isRuleBased() returns TRUE, then the caller must call this + * method, followed by TransliteratorRegistry::reget(). The latter + * method must be called inside the TransliteratorRegistry mutex. + * + * Note: Only call parse() if isRuleBased() returns TRUE. + * + * This method must be called *outside* of the TransliteratorRegistry + * mutex, because it can instantiate Transliterators embedded in + * the rules via the "&Latin-Arabic()" syntax. + */ + void parse(TransliteratorParser& parser, + UParseError& pe, UErrorCode& ec) const; + + private: + // We actually come in three flavors: + // 1. Simple alias + // Here aliasID is the alias string. Everything else is + // null, zero, empty. + // 2. CompoundRBT + // Here ID is the ID, aliasID is the idBlock, trans is the + // contained RBT, and idSplitPoint is the offet in aliasID + // where the contained RBT goes. compoundFilter is the + // compound filter, and it is _not_ owned. + // 3. Rules + // Here ID is the ID, aliasID is the rules string. + // idSplitPoint is the UTransDirection. + UnicodeString ID; + UnicodeString aliasesOrRules; + UVector* transes; // owned + const UnicodeSet* compoundFilter; // alias + UTransDirection direction; + enum { SIMPLE, COMPOUND, RULES } type; + + TransliteratorAlias(const TransliteratorAlias &other); // forbid copying of this class + TransliteratorAlias &operator=(const TransliteratorAlias &other); // forbid copying of this class +}; + + +/** + * A registry of system transliterators. This is the data structure + * that implements the mapping between transliterator IDs and the data + * or function pointers used to create the corresponding + * transliterators. There is one instance of the registry that is + * created statically. + * + * The registry consists of a dynamic component -- a hashtable -- and + * a static component -- locale resource bundles. The dynamic store + * is semantically overlaid on the static store, so the static mapping + * can be dynamically overridden. + * + * This is an internal class that is only used by Transliterator. + * Transliterator maintains one static instance of this class and + * delegates all registry-related operations to it. + * + * @author Alan Liu + */ +class TransliteratorRegistry : public UMemory { + + public: + + /** + * Contructor + * @param status Output param set to success/failure code. + */ + TransliteratorRegistry(UErrorCode& status); + + /** + * Nonvirtual destructor -- this class is not subclassable. + */ + ~TransliteratorRegistry(); + + //------------------------------------------------------------------ + // Basic public API + //------------------------------------------------------------------ + + /** + * Given a simple ID (forward direction, no inline filter, not + * compound) attempt to instantiate it from the registry. Return + * 0 on failure. + * + * Return a non-NULL aliasReturn value if the ID points to an alias. + * We cannot instantiate it ourselves because the alias may contain + * filters or compounds, which we do not understand. Caller should + * make aliasReturn NULL before calling. + * @param ID the given ID + * @param aliasReturn output param to receive TransliteratorAlias; + * should be NULL on entry + * @param parseError Struct to recieve information on position + * of error if an error is encountered + * @param status Output param set to success/failure code. + */ + Transliterator* get(const UnicodeString& ID, + TransliteratorAlias*& aliasReturn, + UErrorCode& status); + + /** + * The caller must call this after calling get(), if [a] calling get() + * returns an alias, and [b] the alias is rule based. In that + * situation the caller must call alias->parse() to do the parsing + * OUTSIDE THE REGISTRY MUTEX, then call this method to retry + * instantiating the transliterator. + * + * Note: Another alias might be returned by this method. + * + * This method (like all public methods of this class) must be called + * from within the TransliteratorRegistry mutex. + * + * @param aliasReturn output param to receive TransliteratorAlias; + * should be NULL on entry + */ + Transliterator* reget(const UnicodeString& ID, + TransliteratorParser& parser, + TransliteratorAlias*& aliasReturn, + UErrorCode& status); + + /** + * Register a prototype (adopted). This adds an entry to the + * dynamic store, or replaces an existing entry. Any entry in the + * underlying static locale resource store is masked. + */ + void put(Transliterator* adoptedProto, + UBool visible, + UErrorCode& ec); + + /** + * Register an ID and a factory function pointer. This adds an + * entry to the dynamic store, or replaces an existing entry. Any + * entry in the underlying static locale resource store is masked. + */ + void put(const UnicodeString& ID, + Transliterator::Factory factory, + Transliterator::Token context, + UBool visible, + UErrorCode& ec); + + /** + * Register an ID and a resource name. This adds an entry to the + * dynamic store, or replaces an existing entry. Any entry in the + * underlying static locale resource store is masked. + */ + void put(const UnicodeString& ID, + const UnicodeString& resourceName, + UTransDirection dir, + UBool readonlyResourceAlias, + UBool visible, + UErrorCode& ec); + + /** + * Register an ID and an alias ID. This adds an entry to the + * dynamic store, or replaces an existing entry. Any entry in the + * underlying static locale resource store is masked. + */ + void put(const UnicodeString& ID, + const UnicodeString& alias, + UBool readonlyAliasAlias, + UBool visible, + UErrorCode& ec); + + /** + * Unregister an ID. This removes an entry from the dynamic store + * if there is one. The static locale resource store is + * unaffected. + * @param ID the given ID. + */ + void remove(const UnicodeString& ID); + + //------------------------------------------------------------------ + // Public ID and spec management + //------------------------------------------------------------------ + + /** + * Return a StringEnumeration over the IDs currently registered + * with the system. + * @internal + */ + StringEnumeration* getAvailableIDs() const; + + /** + * == OBSOLETE - remove in ICU 3.4 == + * Return the number of IDs currently registered with the system. + * To retrieve the actual IDs, call getAvailableID(i) with + * i from 0 to countAvailableIDs() - 1. + * @return the number of IDs currently registered with the system. + * @internal + */ + int32_t countAvailableIDs(void) const; + + /** + * == OBSOLETE - remove in ICU 3.4 == + * Return the index-th available ID. index must be between 0 + * and countAvailableIDs() - 1, inclusive. If index is out of + * range, the result of getAvailableID(0) is returned. + * @param index the given index. + * @return the index-th available ID. index must be between 0 + * and countAvailableIDs() - 1, inclusive. If index is out of + * range, the result of getAvailableID(0) is returned. + * @internal + */ + const UnicodeString& getAvailableID(int32_t index) const; + + /** + * Return the number of registered source specifiers. + * @return the number of registered source specifiers. + */ + int32_t countAvailableSources(void) const; + + /** + * Return a registered source specifier. + * @param index which specifier to return, from 0 to n-1, where + * n = countAvailableSources() + * @param result fill-in paramter to receive the source specifier. + * If index is out of range, result will be empty. + * @return reference to result + */ + UnicodeString& getAvailableSource(int32_t index, + UnicodeString& result) const; + + /** + * Return the number of registered target specifiers for a given + * source specifier. + * @param source the given source specifier. + * @return the number of registered target specifiers for a given + * source specifier. + */ + int32_t countAvailableTargets(const UnicodeString& source) const; + + /** + * Return a registered target specifier for a given source. + * @param index which specifier to return, from 0 to n-1, where + * n = countAvailableTargets(source) + * @param source the source specifier + * @param result fill-in paramter to receive the target specifier. + * If source is invalid or if index is out of range, result will + * be empty. + * @return reference to result + */ + UnicodeString& getAvailableTarget(int32_t index, + const UnicodeString& source, + UnicodeString& result) const; + + /** + * Return the number of registered variant specifiers for a given + * source-target pair. There is always at least one variant: If + * just source-target is registered, then the single variant + * NO_VARIANT is returned. If source-target/variant is registered + * then that variant is returned. + * @param source the source specifiers + * @param target the target specifiers + * @return the number of registered variant specifiers for a given + * source-target pair. + */ + int32_t countAvailableVariants(const UnicodeString& source, + const UnicodeString& target) const; + + /** + * Return a registered variant specifier for a given source-target + * pair. If NO_VARIANT is one of the variants, then it will be + * at index 0. + * @param index which specifier to return, from 0 to n-1, where + * n = countAvailableVariants(source, target) + * @param source the source specifier + * @param target the target specifier + * @param result fill-in paramter to receive the variant + * specifier. If source is invalid or if target is invalid or if + * index is out of range, result will be empty. + * @return reference to result + */ + UnicodeString& getAvailableVariant(int32_t index, + const UnicodeString& source, + const UnicodeString& target, + UnicodeString& result) const; + + private: + + //---------------------------------------------------------------- + // Private implementation + //---------------------------------------------------------------- + + TransliteratorEntry* find(const UnicodeString& ID); + + TransliteratorEntry* find(UnicodeString& source, + UnicodeString& target, + UnicodeString& variant); + + TransliteratorEntry* findInDynamicStore(const TransliteratorSpec& src, + const TransliteratorSpec& trg, + const UnicodeString& variant) const; + + TransliteratorEntry* findInStaticStore(const TransliteratorSpec& src, + const TransliteratorSpec& trg, + const UnicodeString& variant); + + static TransliteratorEntry* findInBundle(const TransliteratorSpec& specToOpen, + const TransliteratorSpec& specToFind, + const UnicodeString& variant, + UTransDirection direction); + + void registerEntry(const UnicodeString& source, + const UnicodeString& target, + const UnicodeString& variant, + TransliteratorEntry* adopted, + UBool visible); + + void registerEntry(const UnicodeString& ID, + TransliteratorEntry* adopted, + UBool visible); + + void registerEntry(const UnicodeString& ID, + const UnicodeString& source, + const UnicodeString& target, + const UnicodeString& variant, + TransliteratorEntry* adopted, + UBool visible); + + void registerSTV(const UnicodeString& source, + const UnicodeString& target, + const UnicodeString& variant); + + void removeSTV(const UnicodeString& source, + const UnicodeString& target, + const UnicodeString& variant); + + Transliterator* instantiateEntry(const UnicodeString& ID, + TransliteratorEntry *entry, + TransliteratorAlias*& aliasReturn, + UErrorCode& status); + + /** + * A StringEnumeration over the registered IDs in this object. + */ + class Enumeration : public StringEnumeration { + public: + Enumeration(const TransliteratorRegistry& reg); + virtual ~Enumeration(); + virtual int32_t count(UErrorCode& status) const; + virtual const UnicodeString* snext(UErrorCode& status); + virtual void reset(UErrorCode& status); + static UClassID U_EXPORT2 getStaticClassID(); + virtual UClassID getDynamicClassID() const; + private: + int32_t index; + const TransliteratorRegistry& reg; + }; + friend class Enumeration; + + private: + + /** + * Dynamic registry mapping full IDs to Entry objects. This + * contains both public and internal entities. The visibility is + * controlled by whether an entry is listed in availableIDs and + * specDAG or not. + */ + Hashtable registry; + + /** + * DAG of visible IDs by spec. Hashtable: source => (Hashtable: + * target => (UVector: variant)) The UVector of variants is never + * empty. For a source-target with no variant, the special + * variant NO_VARIANT (the empty string) is stored in slot zero of + * the UVector. + */ + Hashtable specDAG; + + /** + * Vector of public full IDs. + */ + UVector availableIDs; + + TransliteratorRegistry(const TransliteratorRegistry &other); // forbid copying of this class + TransliteratorRegistry &operator=(const TransliteratorRegistry &other); // forbid copying of this class +}; + +U_NAMESPACE_END + +U_CFUNC UBool utrans_transliterator_cleanup(void); + +#endif /* #if !UCONFIG_NO_TRANSLITERATION */ + +#endif +//eof |