private bool ParseExtensions(StringTokenEnumerator itr, ParseStatus sts) { if (itr.IsDone || sts.IsError) { return(false); } bool found = false; while (!itr.IsDone) { string s = itr.Current; if (IsExtensionSingleton(s)) { int start = itr.CurrentStart; string singleton = s; StringBuilder sb = new StringBuilder(singleton); itr.MoveNext(); while (!itr.IsDone) { s = itr.Current; if (IsExtensionSubtag(s)) { sb.Append(SEP).Append(s); sts.ParseLength = itr.CurrentEnd; } else { break; } itr.MoveNext(); } if (sts.ParseLength <= start) { sts.ErrorIndex = start; sts.ErrorMessage = "Incomplete extension '" + singleton + "'"; break; } if (_extensions.Count == 0) { _extensions = new List <String>(4); } _extensions.Add(sb.ToString()); found = true; } else { break; } } return(found); }
/// <summary> /// Remove special private use subtag sequence identified by "lvariant" /// and return the rest. Only used by LocaleExtensions. /// </summary> internal static string RemovePrivateuseVariant(string privuseVal) { StringTokenEnumerator itr = new StringTokenEnumerator(privuseVal, LanguageTag.Separator); // Note: privateuse value "abc-lvariant" is unchanged // because no subtags after "lvariant". int prefixStart = -1; bool sawPrivuseVar = false; while (itr.MoveNext()) { if (prefixStart != -1) { // Note: privateuse value "abc-lvariant" is unchanged // because no subtags after "lvariant". sawPrivuseVar = true; break; } if (AsciiUtil.CaseIgnoreMatch(itr.Current, LanguageTag.PrivateUse_Variant_Prefix)) { prefixStart = itr.CurrentStart; } } if (!sawPrivuseVar) { return(privuseVal); } Debug.Assert(prefixStart == 0 || prefixStart > 1); return((prefixStart == 0) ? null : privuseVal.Substring(0, prefixStart - 1)); // ICU4N: Checked 2nd parameter }
private bool ParseVariants(StringTokenEnumerator itr, ParseStatus sts) { if (itr.IsDone || sts.IsError) { return(false); } bool found = false; while (!itr.IsDone) { string s = itr.Current; if (!IsVariant(s)) { break; } found = true; if (!_variants.Any()) { _variants = new List <string>(3); } _variants.Add(s); sts.ParseLength = itr.CurrentEnd; itr.MoveNext(); } return(found); }
private bool ParseExtlangs(StringTokenEnumerator itr, ParseStatus sts) { if (itr.IsDone || sts.IsError) { return(false); } bool found = false; while (!itr.IsDone) { string s = itr.Current; if (!IsExtlang(s)) { break; } found = true; if (!_extlangs.Any()) { _extlangs = new List <string>(3); } _extlangs.Add(s); sts.ParseLength = itr.CurrentEnd; itr.MoveNext(); if (_extlangs.Count == 3) { // Maximum 3 extlangs break; } } return(found); }
private bool ParsePrivateuse(StringTokenEnumerator itr, ParseStatus sts) { if (itr.IsDone || sts.IsError) { return(false); } bool found = false; string s = itr.Current; if (IsPrivateusePrefix(s)) { int start = itr.CurrentStart; StringBuilder sb = new StringBuilder(s); itr.MoveNext(); while (!itr.IsDone) { s = itr.Current; if (!IsPrivateuseSubtag(s)) { break; } sb.Append(SEP).Append(s); sts.ParseLength = itr.CurrentEnd; itr.MoveNext(); } if (sts.ParseLength <= start) { // need at least 1 private subtag sts.ErrorIndex = start; sts.ErrorMessage = "Incomplete privateuse"; } else { _privateuse = sb.ToString(); found = true; } } return(found); }
/// <summary> /// Check if the given variant subtags separated by the given /// separator(s) are valid. /// </summary> private int CheckVariants(string variants, string sep) { StringTokenEnumerator itr = new StringTokenEnumerator(variants, sep); while (itr.MoveNext()) { string s = itr.Current; if (!LanguageTag.IsVariant(s)) { return(itr.CurrentStart); } } return(-1); }
public BaseLocale GetBaseLocale() { string language = _language; string script = _script; string region = _region; string variant = _variant; // Special private use subtag sequence identified by "lvariant" will be // interpreted as Java variant. if (_extensions != null) { string privuse; if (_extensions.TryGetValue(PRIVUSE_KEY, out privuse) && privuse != null) { StringTokenEnumerator itr = new StringTokenEnumerator(privuse, LanguageTag.Separator); bool sawPrefix = false; int privVarStart = -1; while (itr.MoveNext()) { if (sawPrefix) { privVarStart = itr.CurrentStart; break; } if (AsciiUtil.CaseIgnoreMatch(itr.Current, LanguageTag.PrivateUse_Variant_Prefix)) { sawPrefix = true; } } if (privVarStart != -1) { StringBuilder sb = new StringBuilder(variant); if (sb.Length != 0) { sb.Append(BaseLocale.Separator); } sb.Append(privuse.Substring(privVarStart).Replace(LanguageTag.Separator, BaseLocale.Separator)); variant = sb.ToString(); } } } return(BaseLocale.GetInstance(language, script, region, variant)); }
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); }
private bool ParseRegion(StringTokenEnumerator itr, ParseStatus sts) { if (itr.IsDone || sts.IsError) { return(false); } bool found = false; string s = itr.Current; if (IsRegion(s)) { found = true; _region = s; sts.ParseLength = itr.CurrentEnd; itr.MoveNext(); } return(found); }
/// <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(); } }
/// <summary> /// Set extension/private subtags in a single string representation /// </summary> public InternalLocaleBuilder SetExtensions(string subtags) { if (subtags == null || subtags.Length == 0) { ClearExtensions(); return(this); } subtags = subtags.Replace(BaseLocale.Separator, LanguageTag.Separator); StringTokenEnumerator itr = new StringTokenEnumerator(subtags, LanguageTag.Separator); List <string> extensions = null; string privateuse = null; int parsed = 0; int start; // Move to first element itr.MoveNext(); // Make a list of extension subtags while (!itr.IsDone) { string s = itr.Current; if (LanguageTag.IsExtensionSingleton(s)) { start = itr.CurrentStart; string singleton = s; StringBuilder sb = new StringBuilder(singleton); itr.MoveNext(); while (!itr.IsDone) { s = itr.Current; if (LanguageTag.IsExtensionSubtag(s)) { sb.Append(LanguageTag.Separator).Append(s); parsed = itr.CurrentEnd; } else { break; } itr.MoveNext(); } if (parsed < start) { throw new FormatException("Incomplete extension '" + singleton + "'" /*, start*/); } if (extensions == null) { extensions = new List <string>(4); } extensions.Add(sb.ToString()); } else { break; } } if (!itr.IsDone) { string s = itr.Current; if (LanguageTag.IsPrivateusePrefix(s)) { start = itr.CurrentStart; StringBuilder sb = new StringBuilder(s); itr.MoveNext(); while (!itr.IsDone) { s = itr.Current; if (!LanguageTag.IsPrivateuseSubtag(s)) { break; } sb.Append(LanguageTag.Separator).Append(s); parsed = itr.CurrentEnd; itr.MoveNext(); } if (parsed <= start) { throw new FormatException("Incomplete privateuse:" + subtags.Substring(start) /*, start*/); } else { privateuse = sb.ToString(); } } } if (!itr.IsDone) { throw new FormatException("Ill-formed extension subtags:" + subtags.Substring(itr.CurrentStart) /*, itr.CurrentStart*/); } return(SetExtensions(extensions, privateuse)); }
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); }
public static LanguageTag ParseLocale(BaseLocale baseLocale, LocaleExtensions localeExtensions) { LanguageTag tag = new LanguageTag(); string language = baseLocale.GetLanguage(); string script = baseLocale.GetScript(); string region = baseLocale.GetRegion(); string variant = baseLocale.GetVariant(); bool hasSubtag = false; string privuseVar = null; // store ill-formed variant subtags if (language.Length > 0 && IsLanguage(language)) { // Convert a deprecated language code used by Java to // a new code if (language.Equals("iw")) { language = "he"; } else if (language.Equals("ji")) { language = "yi"; } else if (language.Equals("in")) { language = "id"; } tag._language = language; } if (script.Length > 0 && IsScript(script)) { tag._script = CanonicalizeScript(script); hasSubtag = true; } if (region.Length > 0 && IsRegion(region)) { tag._region = CanonicalizeRegion(region); hasSubtag = true; } // ICU4N TODO: Remove ? if (JDKIMPL) { // Special handling for no_NO_NY - use nn_NO for language tag if (tag._language.Equals("no") && tag._region.Equals("NO") && variant.Equals("NY")) // ICU4N TODO: Fix this handling for .NET (no-NO is not reliable across platforms) { tag._language = "nn"; variant = ""; } } if (variant.Length > 0) { List <string> variants = null; StringTokenEnumerator varitr = new StringTokenEnumerator(variant, BaseLocale.SEP); while (varitr.MoveNext()) { string var = varitr.Current; if (!IsVariant(var)) { break; } if (variants == null) { variants = new List <string>(); } if (JDKIMPL) { variants.Add(var); // Do not canonicalize! } else { variants.Add(CanonicalizeVariant(var)); } } if (variants != null) { tag._variants = variants; hasSubtag = true; } if (!varitr.IsDone) { // ill-formed variant subtags StringBuilder buf = new StringBuilder(); while (!varitr.IsDone) { string prvv = varitr.Current; if (!IsPrivateuseSubtag(prvv)) { // cannot use private use subtag - truncated break; } if (buf.Length > 0) { buf.Append(SEP); } if (!JDKIMPL) { prvv = AsciiUtil.ToLowerString(prvv); } buf.Append(prvv); varitr.MoveNext(); } if (buf.Length > 0) { privuseVar = buf.ToString(); } } } List <string> extensions = null; string privateuse = null; var locextKeys = localeExtensions.Keys; foreach (char locextKey in locextKeys) { Extension ext = localeExtensions.GetExtension(locextKey); if (IsPrivateusePrefixChar(locextKey)) { privateuse = ext.Value; } else { if (extensions == null) { extensions = new List <string>(); } extensions.Add(locextKey.ToString() + SEP + ext.Value); } } if (extensions != null) { tag._extensions = extensions; hasSubtag = true; } // append ill-formed variant subtags to private use if (privuseVar != null) { if (privateuse == null) { privateuse = PRIVUSE_VARIANT_PREFIX + SEP + privuseVar; } else { privateuse = privateuse + SEP + PRIVUSE_VARIANT_PREFIX + SEP + privuseVar.Replace(BaseLocale.SEP, SEP); } } if (privateuse != null) { tag._privateuse = privateuse; } if (tag._language.Length == 0 && (hasSubtag || privateuse == null)) { // use lang "und" when 1) no language is available AND // 2) any of other subtags other than private use are available or // no private use tag is available tag._language = UNDETERMINED; } return(tag); }