Пример #1
0
 public InternalLocaleBuilder RemoveUnicodeLocaleAttribute(string attribute)
 {
     if (attribute == null || !UnicodeLocaleExtension.IsAttribute(attribute))
     {
         throw new FormatException("Ill-formed Unicode locale attribute: " + attribute);
     }
     if (_uattributes != null)
     {
         _uattributes.Remove(new CaseInsensitiveString(attribute));
     }
     return(this);
 }
Пример #2
0
        static UnicodeLocaleExtension()
        {
            CA_JAPANESE                 = new UnicodeLocaleExtension();
            CA_JAPANESE._keywords       = new SortedDictionary <string, string>(StringComparer.Ordinal);
            CA_JAPANESE._keywords["ca"] = "japanese";
            CA_JAPANESE._value          = "ca-japanese";

            NU_THAI                 = new UnicodeLocaleExtension();
            NU_THAI._keywords       = new SortedDictionary <string, string>(StringComparer.Ordinal);
            NU_THAI._keywords["nu"] = "thai";
            NU_THAI._value          = "nu-thai";
        }
Пример #3
0
 public InternalLocaleBuilder AddUnicodeLocaleAttribute(string attribute)
 {
     if (attribute == null || !UnicodeLocaleExtension.IsAttribute(attribute))
     {
         throw new FormatException("Ill-formed Unicode locale attribute: " + attribute);
     }
     // Use case insensitive string to prevent duplication
     if (_uattributes == null)
     {
         _uattributes = new HashSet <CaseInsensitiveString>(/*4*/);
     }
     _uattributes.Add(new CaseInsensitiveString(attribute));
     return(this);
 }
Пример #4
0
        public InternalLocaleBuilder SetUnicodeLocaleKeyword(string key, string type)
        {
            if (!UnicodeLocaleExtension.IsKey(key))
            {
                throw new FormatException("Ill-formed Unicode locale keyword key: " + key);
            }

            CaseInsensitiveString cikey = new CaseInsensitiveString(key);

            if (type == null)
            {
                if (_ukeywords != null)
                {
                    // null type is used for remove the key
                    _ukeywords.Remove(cikey);
                }
            }
            else
            {
                if (type.Length != 0)
                {
                    // normalize separator to "-"
                    string tp = type.Replace(BaseLocale.Separator, LanguageTag.Separator);
                    // validate
                    StringTokenEnumerator itr = new StringTokenEnumerator(tp, LanguageTag.Separator);
                    while (itr.MoveNext())
                    {
                        string s = itr.Current;
                        if (!UnicodeLocaleExtension.IsTypeSubtag(s))
                        {
                            throw new FormatException("Ill-formed Unicode locale keyword type: " + type /*, itr.CurrentStart*/);
                        }
                    }
                }
                if (_ukeywords == null)
                {
                    _ukeywords = new Dictionary <CaseInsensitiveString, string>(4);
                }
                _ukeywords[cikey] = type;
            }
            return(this);
        }
Пример #5
0
        /// <summary>
        /// Set a list of BCP47 extensions and private use subtags.
        /// BCP47 extensions are already validated and well-formed, but may contain duplicates.
        /// </summary>
        private InternalLocaleBuilder SetExtensions(IList <string> bcpExtensions, string privateuse)
        {
            ClearExtensions();

            if (bcpExtensions != null && bcpExtensions.Count > 0)
            {
                HashSet <CaseInsensitiveChar> processedExtensions = new HashSet <CaseInsensitiveChar>(/*bcpExtensions.Count*/);
                foreach (string bcpExt in bcpExtensions)
                {
                    CaseInsensitiveChar key = new CaseInsensitiveChar(bcpExt[0]);
                    // ignore duplicates
                    if (!processedExtensions.Contains(key))
                    {
                        // each extension string contains singleton, e.g. "a-abc-def"
                        if (UnicodeLocaleExtension.IsSingletonChar(key.Value))
                        {
                            SetUnicodeLocaleExtension(bcpExt.Substring(2));
                        }
                        else
                        {
                            if (_extensions == null)
                            {
                                _extensions = new Dictionary <CaseInsensitiveChar, string>(4);
                            }
                            _extensions[key] = bcpExt.Substring(2);
                        }
                    }
                }
            }
            if (privateuse != null && privateuse.Length > 0)
            {
                // privateuse string contains prefix, e.g. "x-abc-def"
                if (_extensions == null)
                {
                    _extensions = new Dictionary <CaseInsensitiveChar, string>(1);
                }
                _extensions[new CaseInsensitiveChar(privateuse[0])] = privateuse.Substring(2);
            }

            return(this);
        }
Пример #6
0
        /// <summary>
        /// Private methods parsing Unicode Locale Extension subtags.
        /// Duplicated attributes/keywords will be ignored.
        /// The input must be a valid extension subtags (excluding singleton).
        /// </summary>
        private void SetUnicodeLocaleExtension(string subtags)
        {
            // wipe out existing attributes/keywords
            if (_uattributes != null)
            {
                _uattributes.Clear();
            }
            if (_ukeywords != null)
            {
                _ukeywords.Clear();
            }

            StringTokenEnumerator itr = new StringTokenEnumerator(subtags, LanguageTag.Separator);

            // parse attributes
            while (itr.MoveNext())
            {
                if (!UnicodeLocaleExtension.IsAttribute(itr.Current))
                {
                    break;
                }
                if (_uattributes == null)
                {
                    _uattributes = new HashSet <CaseInsensitiveString>(/*4*/);
                }
                _uattributes.Add(new CaseInsensitiveString(itr.Current));
            }

            // parse keywords
            CaseInsensitiveString key = null;
            string type;
            int    typeStart = -1;
            int    typeEnd   = -1;

            while (!itr.IsDone)
            {
                if (key != null)
                {
                    if (UnicodeLocaleExtension.IsKey(itr.Current))
                    {
                        // next keyword - emit previous one
                        Debug.Assert(typeStart == -1 || typeEnd != -1);
                        type = (typeStart == -1) ? "" : subtags.Substring(typeStart, typeEnd - typeStart); // ICU4N: Corrected 2nd parameter
                        if (_ukeywords == null)
                        {
                            _ukeywords = new Dictionary <CaseInsensitiveString, string>(4);
                        }
                        _ukeywords[key] = type;

                        // reset keyword info
                        CaseInsensitiveString tmpKey = new CaseInsensitiveString(itr.Current);
                        key       = _ukeywords.ContainsKey(tmpKey) ? null : tmpKey;
                        typeStart = typeEnd = -1;
                    }
                    else
                    {
                        if (typeStart == -1)
                        {
                            typeStart = itr.CurrentStart;
                        }
                        typeEnd = itr.CurrentEnd;
                    }
                }
                else if (UnicodeLocaleExtension.IsKey(itr.Current))
                {
                    // 1. first keyword or
                    // 2. next keyword, but previous one was duplicate
                    key = new CaseInsensitiveString(itr.Current);
                    if (_ukeywords != null && _ukeywords.ContainsKey(key))
                    {
                        // duplicate
                        key = null;
                    }
                }

                if (!itr.HasNext)
                {
                    if (key != null)
                    {
                        // last keyword
                        Debug.Assert(typeStart == -1 || typeEnd != -1);
                        type = (typeStart == -1) ? "" : subtags.Substring(typeStart, typeEnd - typeStart); // ICU4N: Corrected 2nd parameter
                        if (_ukeywords == null)
                        {
                            _ukeywords = new Dictionary <CaseInsensitiveString, string>(4);
                        }
                        _ukeywords[key] = type;
                    }
                    break;
                }

                itr.MoveNext();
            }
        }
Пример #7
0
        public InternalLocaleBuilder SetExtension(char singleton, string value)
        {
            // validate key
            bool isBcpPrivateuse = LanguageTag.IsPrivateusePrefixChar(singleton);

            if (!isBcpPrivateuse && !LanguageTag.IsExtensionSingletonChar(singleton))
            {
                throw new FormatException("Ill-formed extension key: " + singleton);
            }

            bool remove             = (value == null || value.Length == 0);
            CaseInsensitiveChar key = new CaseInsensitiveChar(singleton);

            if (remove)
            {
                if (UnicodeLocaleExtension.IsSingletonChar(key.Value))
                {
                    // clear entire Unicode locale extension
                    if (_uattributes != null)
                    {
                        _uattributes.Clear();
                    }
                    if (_ukeywords != null)
                    {
                        _ukeywords.Clear();
                    }
                }
                else
                {
                    if (_extensions != null && _extensions.ContainsKey(key))
                    {
                        _extensions.Remove(key);
                    }
                }
            }
            else
            {
                // validate value
                string val = value.Replace(BaseLocale.Separator, LanguageTag.Separator);
                StringTokenEnumerator itr = new StringTokenEnumerator(val, LanguageTag.Separator);
                while (itr.MoveNext())
                {
                    string s = itr.Current;
                    bool   validSubtag;
                    if (isBcpPrivateuse)
                    {
                        validSubtag = LanguageTag.IsPrivateuseSubtag(s);
                    }
                    else
                    {
                        validSubtag = LanguageTag.IsExtensionSubtag(s);
                    }
                    if (!validSubtag)
                    {
                        throw new FormatException("Ill-formed extension value: " + s /*, itr.CurrentStart*/);
                    }
                }

                if (UnicodeLocaleExtension.IsSingletonChar(key.Value))
                {
                    SetUnicodeLocaleExtension(val);
                }
                else
                {
                    if (_extensions == null)
                    {
                        _extensions = new Dictionary <CaseInsensitiveChar, string>(4);
                    }
                    _extensions[key] = val;
                }
            }
            return(this);
        }
Пример #8
0
        public InternalLocaleBuilder SetLocale(BaseLocale @base, LocaleExtensions extensions)
        {
            string language = @base.GetLanguage();
            string script   = @base.GetScript();
            string region   = @base.GetRegion();
            string variant  = @base.GetVariant();

            // ICU4N TODO: Remove ?
            if (JDKIMPL)
            {
                // Special backward compatibility support

                // Exception 1 - ja_JP_JP
                if (language.Equals("ja") && region.Equals("JP") && variant.Equals("JP"))
                {
                    // When locale ja_JP_JP is created, ca-japanese is always there.
                    // The builder ignores the variant "JP"
                    Debug.Assert("japanese".Equals(extensions.GetUnicodeLocaleType("ca")));
                    variant = "";
                }
                // Exception 2 - th_TH_TH
                else if (language.Equals("th") && region.Equals("TH") && variant.Equals("TH"))
                {
                    // When locale th_TH_TH is created, nu-thai is always there.
                    // The builder ignores the variant "TH"
                    Debug.Assert("thai".Equals(extensions.GetUnicodeLocaleType("nu")));
                    variant = "";
                }
                // Exception 3 - no_NO_NY
                else if (language.Equals("no") && region.Equals("NO") && variant.Equals("NY")) // ICU4N TODO: Fix this handling for .NET (no-NO is not reliable across platforms)
                {
                    // no_NO_NY is a valid locale and used by Java 6 or older versions.
                    // The build ignores the variant "NY" and change the language to "nn".
                    language = "nn";
                    variant  = "";
                }
            }

            // Validate base locale fields before updating internal state.
            // LocaleExtensions always store validated/canonicalized values,
            // so no checks are necessary.
            if (language.Length > 0 && !LanguageTag.IsLanguage(language))
            {
                throw new FormatException("Ill-formed language: " + language);
            }

            if (script.Length > 0 && !LanguageTag.IsScript(script))
            {
                throw new FormatException("Ill-formed script: " + script);
            }

            if (region.Length > 0 && !LanguageTag.IsRegion(region))
            {
                throw new FormatException("Ill-formed region: " + region); // ICU4N TODO: Port LocaleSyntaxException (instead of FormatException)
            }

            if (variant.Length > 0)
            {
                int errIdx = CheckVariants(variant, BaseLocale.SEP);
                if (errIdx != -1)
                {
                    throw new FormatException("Ill-formed variant: " + variant /*, errIdx*/);
                }
            }

            // The input locale is validated at this point.
            // Now, updating builder's internal fields.
            _language = language;
            _script   = script;
            _region   = region;
            _variant  = variant;
            ClearExtensions();

            var extKeys = (extensions == null) ? null : extensions.Keys;

            if (extKeys != null)
            {
                // map extensions back to builder's internal format
                foreach (char key in extKeys)
                {
                    Extension e = extensions.GetExtension(key);
                    if (e is UnicodeLocaleExtension)
                    {
                        UnicodeLocaleExtension ue = (UnicodeLocaleExtension)e;
                        foreach (string uatr in ue.GetUnicodeLocaleAttributes())
                        {
                            if (_uattributes == null)
                            {
                                _uattributes = new HashSet <CaseInsensitiveString>(/*4*/);
                            }
                            _uattributes.Add(new CaseInsensitiveString(uatr));
                        }
                        foreach (string ukey in ue.GetUnicodeLocaleKeys())
                        {
                            if (_ukeywords == null)
                            {
                                _ukeywords = new Dictionary <CaseInsensitiveString, string>(4);
                            }
                            _ukeywords[new CaseInsensitiveString(ukey)] = ue.GetUnicodeLocaleType(ukey);
                        }
                    }
                    else
                    {
                        if (_extensions == null)
                        {
                            _extensions = new Dictionary <CaseInsensitiveChar, string>(4);
                        }
                        _extensions[new CaseInsensitiveChar(key)] = e.Value;
                    }
                }
            }
            return(this);
        }
Пример #9
0
        /// <summary>
        /// Internal constructor, only used by <see cref="InternalLocaleBuilder"/>.
        /// </summary>
        internal LocaleExtensions(IDictionary <CaseInsensitiveChar, string> extensions,
                                  ISet <CaseInsensitiveString> uattributes, IDictionary <CaseInsensitiveString, string> ukeywords)
        {
            bool hasExtension   = (extensions != null && extensions.Count > 0);
            bool hasUAttributes = (uattributes != null && uattributes.Count > 0);
            bool hasUKeywords   = (ukeywords != null && ukeywords.Count > 0);

            if (!hasExtension && !hasUAttributes && !hasUKeywords)
            {
                _map = EmptyMap;
                _id  = "";
                return;
            }

            // Build extension map
            _map = new JCG.SortedDictionary <char, Extension>();
            if (hasExtension)
            {
                foreach (var ext in extensions)
                {
                    char   key   = AsciiUtil.ToLower(ext.Key.Value);
                    string value = ext.Value;

                    if (LanguageTag.IsPrivateusePrefixChar(key))
                    {
                        // we need to exclude special variant in privuateuse, e.g. "x-abc-lvariant-DEF"
                        value = InternalLocaleBuilder.RemovePrivateuseVariant(value);
                        if (value == null)
                        {
                            continue;
                        }
                    }

                    Extension e = new Extension(key, AsciiUtil.ToLower(value));
                    _map[key] = e;
                }
            }

            if (hasUAttributes || hasUKeywords)
            {
                JCG.SortedSet <string> uaset = null;
                JCG.SortedDictionary <string, string> ukmap = null;

                if (hasUAttributes)
                {
                    uaset = new JCG.SortedSet <string>(StringComparer.Ordinal);
                    foreach (CaseInsensitiveString cis in uattributes)
                    {
                        uaset.Add(AsciiUtil.ToLower(cis.Value));
                    }
                }

                if (hasUKeywords)
                {
                    ukmap = new JCG.SortedDictionary <string, string>(StringComparer.Ordinal);
                    foreach (var kwd in ukeywords)
                    {
                        string key  = AsciiUtil.ToLower(kwd.Key.Value);
                        string type = AsciiUtil.ToLower(kwd.Value);
                        ukmap[key] = type;
                    }
                }

                UnicodeLocaleExtension ule = new UnicodeLocaleExtension(uaset, ukmap);
                _map[UnicodeLocaleExtension.Singleton] = ule;
            }

            if (_map.Count == 0)
            {
                // this could happen when only privuateuse with special variant
                _map = EmptyMap;
                _id  = "";
            }
            else
            {
                _id = ToID(_map);
            }
        }
Пример #10
0
 public static bool IsValidUnicodeLocaleKey(string ukey)
 {
     return(UnicodeLocaleExtension.IsKey(ukey));
 }