Exemple #1
0
        public static bool ValidateTag(string textTag)
        {
            LanguageTag tag    = null;
            bool        result = TryParse(textTag, out tag);

            return(result);
        }
        public static bool TryParse(string textTag, out LanguageTag tag)
        {
            CheckNullOrEmpty(textTag, "languageTag");
            textTag = textTag.ToLowerInvariant();

            /*
            string language = null;
            string extlang;
            string script = null;
            string region = null;
            Collection<string> variants = null;
            Dictionary<char, string> extensions = null;
            string privateUse = null;*/
            tag = new LanguageTag();

            if (IsPrivateUse(textTag))
            {
                tag.IsPrivateUse = true;
                tag.PrivateUse = textTag;
                return true;
            }

            if (Array.BinarySearch<string>(Grandfathered, textTag) >= 0)
            {
                tag.IsGrandfathered = true;
                tag.Grandfathered = textTag;
                return true;

            }

            char[] separator = new char[] {'-'};
            string[] parts = textTag.Split(separator, StringSplitOptions.RemoveEmptyEntries);

            ParseState state = ParseState.None;

            if (parts.Length == 0) { return false; }

            #region Language
            string nextPart = parts[0];
            if (nextPart.Length < 2 || nextPart.Length > 8 || !IsUsAsciiLetters(nextPart)) // 2*3ALPHA / 4ALPHA / 5*8ALPHA
            {
                // "Invalid language format."
                return false;
            }
            if (Array.BinarySearch<string>(Languages, nextPart) < 0)
            {
                // "Invalid language."
                return false;
            }
            tag.Language = nextPart;
            state = ParseState.Language;
            #endregion

            for (int i = 1; i < parts.Length; ++i)
            {
                nextPart = parts[i];

                if (nextPart.Length == 3 && IsUsAsciiLetters(nextPart)) // 3ALPHA   not used yet-> *2("-" 3ALPHA)
                {
                    if (state != ParseState.Language)
                    {
                        // "Invalid extended language location, must follow language."
                        return false;
                    }

                    if (Array.BinarySearch<string>(ExtLangs, nextPart) < 0)
                    {
                        // "Invalid ext Language, see selected ISO 639 codes"
                        return false;
                    }
                    tag.Extlang = nextPart;
                    state = ParseState.ExtLang;
                    continue;
                }

                if (nextPart.Length == 4 && IsUsAsciiLetters(nextPart)) // 4ALPHA
                {
                    if (state >= ParseState.Script)
                    {
                        // "Invalid extended language location, must come before " +state.ToString();
                        return false;
                    }

                    if (Array.BinarySearch<string>(Scripts, nextPart) < 0)
                    {
                        // "Invalid Script, see ISO 15924 codes."
                        return false;
                    }
                    tag.Script = nextPart;
                    state = ParseState.Script;
                    continue;
                }

                if ((nextPart.Length == 2 && IsUsAsciiLetters(nextPart)) ||       // 2ALPHA
                    (nextPart.Length == 3 && nextPart.All(c => char.IsDigit(c)))) // 3DIGIT
                {
                    if (state >= ParseState.Region)
                    {
                        // "Invalid Region location, must come before " +state.ToString();
                        return false;
                    }

                    if (Array.BinarySearch<string>(Regions, nextPart) < 0)
                    {
                        // "Invalid Region, see ISO 3166-1 codes and UN M.49 codes
                        return false;
                    }
                    tag.Region = nextPart;
                    state = ParseState.Region;
                    continue;
                }

                if ((nextPart.Length >= 5 && nextPart.Length <= 8 && IsUsAsciiLettersOrDigits(nextPart)) ||               // 5*8alphanum
                    (nextPart.Length == 4 && char.IsDigit(nextPart[0]) && IsUsAsciiLettersOrDigits(nextPart.Substring(1, 3)))) //DIGIT 3alphanum
                {
                    if (state > ParseState.Variant)
                    {
                        // "Invalid Variant location, must come before " +state.ToString();
                        return false;
                    }

                    if (Array.BinarySearch<string>(Variants, nextPart) < 0)
                    {
                        // "Invalid Variant"
                        return false;
                    }
                    //if (variants == null) { variants = new Collection<string>(); }
                    if (tag.Variants.Contains(nextPart))
                    {
                        // "Repeated Variant"
                        return false;
                    }
                    tag.Variants.Add(nextPart);
                    state = ParseState.Variant;
                    continue;
                }

                if (nextPart.Length == 1 &&
                    nextPart[0] != 'x' && nextPart[0] != 'X' &&
                    (char.IsDigit(nextPart[0]) || IsUsAsciiLetters(nextPart[0])) ) // A-W Y-Z a-w y-z 0-9
                {
                    if (state > ParseState.Extension)
                    {
                        // "Invalid Extension location, must come before " +state.ToString();
                        return false;
                    }

                    char singleton = nextPart[0];
                    string extValue = null;

                    i++;
                    if (i >= parts.Length)
                    {
                        // "Extension value not present."
                        return false;
                    }
                    nextPart = parts[i];

                    if (nextPart.Length < 2 || nextPart.Length > 8 || !IsUsAsciiLettersOrDigits(nextPart))
                    {
                        // "Invalid Extension value format."
                        return false;
                    }
                    extValue = nextPart;
                    while (i + 1 < parts.Length)
                    {
                        i++;
                        nextPart = parts[i];
                        if (nextPart.Length < 2 || nextPart.Length > 8 || !IsUsAsciiLettersOrDigits(nextPart))
                        {
                            i--;
                            nextPart = parts[i];
                            break;
                        }
                        extValue = extValue + "-" + nextPart;
                    }

                    //if (extensions == null) { extensions = new Dictionary<char, string>(); }
                    if (tag.Extensions.ContainsKey(singleton))
                    {
                        // "Repeated Extension"
                        return false;
                    }
                    tag.Extensions.Add(singleton, extValue);
                    state = ParseState.Extension;
                    continue;
                }

                if (nextPart.Length == 1 && (nextPart[0] == 'x' || nextPart[0] == 'X' )) // x x
                {
                    if (state >= ParseState.PrivateUse)
                    {
                        // "Private Use location must be used only once.";
                        return false;
                    }

                    i++;
                    if (i >= parts.Length)
                    {
                        // "Private Use value not present."
                        return false;
                    }
                    nextPart = parts[i];

                    if (nextPart.Length < 1 || nextPart.Length > 8 || !IsUsAsciiLettersOrDigits(nextPart))
                    {
                        // "Invalid Private Use value format."
                        return false;
                    }

                    string privateValue = nextPart;
                    while (i + 1 < parts.Length)
                    {
                        i++;
                        nextPart = parts[i];
                        if (nextPart.Length < 1 || nextPart.Length > 8 || !IsUsAsciiLettersOrDigits(nextPart))
                        {
                            i--;
                            nextPart = parts[i];
                            break;
                        }
                        privateValue = privateValue + "-" + nextPart;
                    }

                    tag.PrivateUse = privateValue;
                    state = ParseState.PrivateUse;
                    continue;
                }

                // Could not match Subtag to specific section
                return false;
            }

            return true;
        }
Exemple #3
0
        public static bool TryParse(string textTag, out LanguageTag tag)
        {
            CheckNullOrEmpty(textTag, "languageTag");
            textTag = textTag.ToLowerInvariant();

            /*
             * string language = null;
             * string extlang;
             * string script = null;
             * string region = null;
             * Collection<string> variants = null;
             * Dictionary<char, string> extensions = null;
             * string privateUse = null;*/
            tag = new LanguageTag();

            if (IsPrivateUse(textTag))
            {
                tag.IsPrivateUse = true;
                tag.PrivateUse   = textTag;
                return(true);
            }

            if (Array.BinarySearch <string>(Grandfathered, textTag) >= 0)
            {
                tag.IsGrandfathered = true;
                tag.Grandfathered   = textTag;
                return(true);
            }


            char[]   separator = new char[] { '-' };
            string[] parts     = textTag.Split(separator, StringSplitOptions.RemoveEmptyEntries);

            ParseState state = ParseState.None;

            if (parts.Length == 0)
            {
                return(false);
            }

            #region Language
            string nextPart = parts[0];
            if (nextPart.Length < 2 || nextPart.Length > 8 || !IsUsAsciiLetters(nextPart)) // 2*3ALPHA / 4ALPHA / 5*8ALPHA
            {
                // "Invalid language format."
                return(false);
            }
            if (Array.BinarySearch <string>(Languages, nextPart) < 0)
            {
                // "Invalid language."
                return(false);
            }
            tag.Language = nextPart;
            state        = ParseState.Language;
            #endregion

            for (int i = 1; i < parts.Length; ++i)
            {
                nextPart = parts[i];

                if (nextPart.Length == 3 && IsUsAsciiLetters(nextPart)) // 3ALPHA   not used yet-> *2("-" 3ALPHA)
                {
                    if (state != ParseState.Language)
                    {
                        // "Invalid extended language location, must follow language."
                        return(false);
                    }

                    if (Array.BinarySearch <string>(ExtLangs, nextPart) < 0)
                    {
                        // "Invalid ext Language, see selected ISO 639 codes"
                        return(false);
                    }
                    tag.Extlang = nextPart;
                    state       = ParseState.ExtLang;
                    continue;
                }

                if (nextPart.Length == 4 && IsUsAsciiLetters(nextPart)) // 4ALPHA
                {
                    if (state >= ParseState.Script)
                    {
                        // "Invalid extended language location, must come before " +state.ToString();
                        return(false);
                    }

                    if (Array.BinarySearch <string>(Scripts, nextPart) < 0)
                    {
                        // "Invalid Script, see ISO 15924 codes."
                        return(false);
                    }
                    tag.Script = nextPart;
                    state      = ParseState.Script;
                    continue;
                }

                if ((nextPart.Length == 2 && IsUsAsciiLetters(nextPart)) ||       // 2ALPHA
                    (nextPart.Length == 3 && nextPart.All(c => char.IsDigit(c)))) // 3DIGIT
                {
                    if (state >= ParseState.Region)
                    {
                        // "Invalid Region location, must come before " +state.ToString();
                        return(false);
                    }

                    if (Array.BinarySearch <string>(Regions, nextPart) < 0)
                    {
                        // "Invalid Region, see ISO 3166-1 codes and UN M.49 codes
                        return(false);
                    }
                    tag.Region = nextPart;
                    state      = ParseState.Region;
                    continue;
                }

                if ((nextPart.Length >= 5 && nextPart.Length <= 8 && IsUsAsciiLettersOrDigits(nextPart)) ||                    // 5*8alphanum
                    (nextPart.Length == 4 && char.IsDigit(nextPart[0]) && IsUsAsciiLettersOrDigits(nextPart.Substring(1, 3)))) //DIGIT 3alphanum
                {
                    if (state > ParseState.Variant)
                    {
                        // "Invalid Variant location, must come before " +state.ToString();
                        return(false);
                    }

                    if (Array.BinarySearch <string>(Variants, nextPart) < 0)
                    {
                        // "Invalid Variant"
                        return(false);
                    }
                    //if (variants == null) { variants = new Collection<string>(); }
                    if (tag.Variants.Contains(nextPart))
                    {
                        // "Repeated Variant"
                        return(false);
                    }
                    tag.Variants.Add(nextPart);
                    state = ParseState.Variant;
                    continue;
                }

                if (nextPart.Length == 1 &&
                    nextPart[0] != 'x' && nextPart[0] != 'X' &&
                    (char.IsDigit(nextPart[0]) || IsUsAsciiLetters(nextPart[0])))  // A-W Y-Z a-w y-z 0-9
                {
                    if (state > ParseState.Extension)
                    {
                        // "Invalid Extension location, must come before " +state.ToString();
                        return(false);
                    }

                    char   singleton = nextPart[0];
                    string extValue  = null;

                    i++;
                    if (i >= parts.Length)
                    {
                        // "Extension value not present."
                        return(false);
                    }
                    nextPart = parts[i];

                    if (nextPart.Length < 2 || nextPart.Length > 8 || !IsUsAsciiLettersOrDigits(nextPart))
                    {
                        // "Invalid Extension value format."
                        return(false);
                    }
                    extValue = nextPart;
                    while (i + 1 < parts.Length)
                    {
                        i++;
                        nextPart = parts[i];
                        if (nextPart.Length < 2 || nextPart.Length > 8 || !IsUsAsciiLettersOrDigits(nextPart))
                        {
                            i--;
                            nextPart = parts[i];
                            break;
                        }
                        extValue = extValue + "-" + nextPart;
                    }

                    //if (extensions == null) { extensions = new Dictionary<char, string>(); }
                    if (tag.Extensions.ContainsKey(singleton))
                    {
                        // "Repeated Extension"
                        return(false);
                    }
                    tag.Extensions.Add(singleton, extValue);
                    state = ParseState.Extension;
                    continue;
                }

                if (nextPart.Length == 1 && (nextPart[0] == 'x' || nextPart[0] == 'X'))  // x x
                {
                    if (state >= ParseState.PrivateUse)
                    {
                        // "Private Use location must be used only once.";
                        return(false);
                    }

                    i++;
                    if (i >= parts.Length)
                    {
                        // "Private Use value not present."
                        return(false);
                    }
                    nextPart = parts[i];


                    if (nextPart.Length < 1 || nextPart.Length > 8 || !IsUsAsciiLettersOrDigits(nextPart))
                    {
                        // "Invalid Private Use value format."
                        return(false);
                    }

                    string privateValue = nextPart;
                    while (i + 1 < parts.Length)
                    {
                        i++;
                        nextPart = parts[i];
                        if (nextPart.Length < 1 || nextPart.Length > 8 || !IsUsAsciiLettersOrDigits(nextPart))
                        {
                            i--;
                            nextPart = parts[i];
                            break;
                        }
                        privateValue = privateValue + "-" + nextPart;
                    }

                    tag.PrivateUse = privateValue;
                    state          = ParseState.PrivateUse;
                    continue;
                }

                // Could not match Subtag to specific section
                return(false);
            }



            return(true);
        }