Пример #1
0
            public virtual Transliterator GetInstance()
            {
                List <Transliterator> transliterators = new List <Transliterator>();
                int passNumber = 1;

                int limit = Math.Max(idBlockVector.Count, dataVector.Count);

                for (int i = 0; i < limit; i++)
                {
                    if (i < idBlockVector.Count)
                    {
                        string idBlock = idBlockVector[i];
                        if (idBlock.Length > 0)
                        {
                            transliterators.Add(Transliterator.GetInstance(idBlock));
                        }
                    }
                    if (i < dataVector.Count)
                    {
#pragma warning disable 612, 618
                        Data data = dataVector[i];
                        transliterators.Add(new RuleBasedTransliterator("%Pass" + passNumber++, data, null));
#pragma warning restore 612, 618
                    }
                }

                Transliterator t = new CompoundTransliterator(transliterators, passNumber - 1);
                t.ID = id;
                if (compoundFilter != null)
                {
                    t.Filter = compoundFilter;
                }
                return(t);
            }
Пример #2
0
        /// <summary>
        /// Given an Entry object, instantiate it.  Caller owns result.  Return
        /// 0 on failure.
        /// <para/>
        /// Return a non-empty <paramref name="aliasReturn"/> value if the <paramref name="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 <paramref name="aliasReturn"/> empty before calling.
        /// <para/>
        /// The entry object is assumed to reside in the dynamic store.  It may be
        /// modified.
        /// </summary>
        private Transliterator InstantiateEntry(string ID,
                                                object[] entryWrapper,
                                                StringBuffer aliasReturn)
        {
            // We actually modify the entry object in some cases.  If it
            // is a string, we may partially parse it and turn it into a
            // more processed precursor.  This makes the next
            // instantiation faster and allows sharing of immutable
            // components like the RuleBasedTransliterator.Data objects.
            // For this reason, the entry object is an Object[] of length
            // 1.

            for (; ;)
            {
                object entry = entryWrapper[0];
#pragma warning disable 612, 618
                if (entry is RuleBasedTransliterator.Data)
                {
                    RuleBasedTransliterator.Data data = (RuleBasedTransliterator.Data)entry;
                    return(new RuleBasedTransliterator(ID, data, null));

#pragma warning restore 612, 618
                }
                else if (entry is Type)
                {
                    try
                    {
                        //return (Transliterator)((Type)entry).newInstance();
                        return((Transliterator)Activator.CreateInstance((Type)entry));
                    }
                    catch (TargetInvocationException)
                    {
                    }
                    catch (MethodAccessException) { }
                    return(null);
                }
                else if (entry is AliasEntry)
                {
                    aliasReturn.Append(((AliasEntry)entry).Alias);
                    return(null);
                }
                else if (entry is ITransliteratorFactory)
                {
                    return(((ITransliteratorFactory)entry).GetInstance(ID));
                }
                else if (entry is CompoundRBTEntry)
                {
                    return(((CompoundRBTEntry)entry).GetInstance());
                }
                else if (entry is AnyTransliterator)
                {
                    AnyTransliterator temp = (AnyTransliterator)entry;
                    return(temp.SafeClone());
                }
#pragma warning disable 612, 618
                else if (entry is RuleBasedTransliterator)
                {
                    RuleBasedTransliterator temp = (RuleBasedTransliterator)entry;
                    return(temp.SafeClone());
                }
#pragma warning restore 612, 618
                else if (entry is CompoundTransliterator)
                {
                    CompoundTransliterator temp = (CompoundTransliterator)entry;
                    return(temp.SafeClone());
                }
                else if (entry is Transliterator)
                {
                    return((Transliterator)entry);
                }

                // At this point entry type must be either RULES_FORWARD or
                // RULES_REVERSE.  We process the rule data into a
                // TransliteratorRuleData object, and possibly also into an
                // .id header and/or footer.  Then we modify the registry with
                // the parsed data and retry.

                TransliteratorParser parser = new TransliteratorParser();

                try
                {
                    ResourceEntry re = (ResourceEntry)entry;
                    parser.Parse(re.Resource, re.Direction);
                }
                catch (InvalidCastException)
                {
                    // If we pull a rule from a locale resource bundle it will
                    // be a LocaleEntry.
                    LocaleEntry le = (LocaleEntry)entry;
                    parser.Parse(le.Rule, le.Direction);
                }

                // Reset entry to something that we process at the
                // top of the loop, then loop back to the top.  As long as we
                // do this, we only loop through twice at most.
                // NOTE: The logic here matches that in
                // Transliterator.createFromRules().
                if (parser.IdBlockVector.Count == 0 && parser.DataVector.Count == 0)
                {
                    // No idBlock, no data -- this is just an
                    // alias for Null
                    entryWrapper[0] = new AliasEntry(NullTransliterator._ID);
                }
                else if (parser.IdBlockVector.Count == 0 && parser.DataVector.Count == 1)
                {
                    // No idBlock, data != 0 -- this is an
                    // ordinary RBT_DATA
                    entryWrapper[0] = parser.DataVector[0];
                }
                else if (parser.IdBlockVector.Count == 1 && parser.DataVector.Count == 0)
                {
                    // idBlock, no data -- this is an alias.  The ID has
                    // been munged from reverse into forward mode, if
                    // necessary, so instantiate the ID in the forward
                    // direction.
                    if (parser.CompoundFilter != null)
                    {
                        entryWrapper[0] = new AliasEntry(parser.CompoundFilter.ToPattern(false) + ";"
                                                         + parser.IdBlockVector[0]);
                    }
                    else
                    {
                        entryWrapper[0] = new AliasEntry(parser.IdBlockVector[0]);
                    }
                }
                else
                {
                    entryWrapper[0] = new CompoundRBTEntry(ID, parser.IdBlockVector, parser.DataVector,
                                                           parser.CompoundFilter);
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Returns a transliterator from the given source to our target or
        /// target/variant.  Returns NULL if the source is the same as our
        /// target script, or if the source is <see cref="UScript.InvalidCode"/>.
        /// Caches the result and returns the same transliterator the next
        /// time.  The caller does NOT own the result and must not delete
        /// it.
        /// </summary>
        private Transliterator GetTransliterator(int source)
        {
            if (source == targetScript || source == UScript.InvalidCode)
            {
                if (IsWide(targetScript))
                {
                    return(null);
                }
                else
                {
                    return(widthFix);
                }
            }

            int            key = (int)source;
            Transliterator t   = cache.Get(key);

            if (!cache.TryGetValue(key, out t) || t == null)
            {
                string sourceName = UScript.GetName(source);
                string id         = sourceName + TARGET_SEP + target;

                try
                {
                    t = Transliterator.GetInstance(id, FORWARD);
                }
                catch (Exception e) { }
                if (t == null)
                {
                    // Try to pivot around Latin, our most common script
                    id = sourceName + LATIN_PIVOT + target;
                    try
                    {
                        t = Transliterator.GetInstance(id, FORWARD);
                    }
                    catch (Exception e) { }
                }

                if (t != null)
                {
                    if (!IsWide(targetScript))
                    {
                        IList <Transliterator> v = new List <Transliterator>();
                        v.Add(widthFix);
                        v.Add(t);
                        t = new CompoundTransliterator(v);
                    }
                    //Transliterator prevCachedT = cache.putIfAbsent(key, t);
                    Transliterator prevCachedT;
                    // ICU4N: This is to simulate putIfAbsent
                    // ICU4N TODO: If this works, make it into a PutIfAbsent extension method so we can go back to using ConcurrentDictionary elsewhere
                    if (!cache.TryGetValue(key, out prevCachedT))
                    {
                        // If another thread beat us here, set the prevCachedT
                        // value to NullTransliterator to indicate it already exists
                        if (!cache.TryAdd(key, t))
                        {
                            prevCachedT = new NullTransliterator();
                        }
                    }
                    if (prevCachedT != null)
                    {
                        t = prevCachedT;
                    }
                }
                else if (!IsWide(targetScript))
                {
                    return(widthFix);
                }
            }

            return(t);
        }