示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        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);
        }
示例#4
0
        /// <summary>
        /// BNF in RFC5464
        /// </summary>
        /// <remarks>
        /// Language-Tag  = langtag             ; normal language tags
        ///               / privateuse          ; private use tag
        ///               / grandfathered       ; grandfathered tags
        ///
        ///
        /// langtag       = language
        ///                 ["-" script]
        ///                 ["-" region]
        ///                 *("-" variant)
        ///                 *("-" extension)
        ///                 ["-" privateuse]
        ///
        /// language      = 2*3ALPHA            ; shortest ISO 639 code
        ///                 ["-" extlang]       ; sometimes followed by
        ///                                     ; extended language subtags
        ///               / 4ALPHA              ; or reserved for future use
        ///               / 5*8ALPHA            ; or registered language subtag
        ///
        /// extlang       = 3ALPHA              ; selected ISO 639 codes
        ///                 *2("-" 3ALPHA)      ; permanently reserved
        ///
        /// script        = 4ALPHA              ; ISO 15924 code
        ///
        /// region        = 2ALPHA              ; ISO 3166-1 code
        ///               / 3DIGIT              ; UN M.49 code
        ///
        /// variant       = 5*8alphanum         ; registered variants
        ///               / (DIGIT 3alphanum)
        ///
        /// extension     = singleton 1*("-" (2*8alphanum))
        ///
        ///                                     ; Single alphanumerics
        ///                                     ; "x" reserved for private use
        /// singleton     = DIGIT               ; 0 - 9
        ///               / %x41-57             ; A - W
        ///               / %x59-5A             ; Y - Z
        ///               / %x61-77             ; a - w
        ///               / %x79-7A             ; y - z
        ///
        /// privateuse    = "x" 1*("-" (1*8alphanum))
        /// </remarks>
        public static LanguageTag Parse(string languageTag, ParseStatus sts)
        {
            if (sts == null)
            {
                sts = new ParseStatus();
            }
            else
            {
                sts.Reset();
            }

            StringTokenEnumerator itr;
            bool isGrandfathered = false;

            // Check if the tag is grandfathered
            if (Grandfathered.TryGetValue(new AsciiCaseInsensitiveKey(languageTag), out string[] gfmap) && gfmap != null)
示例#5
0
        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);
        }
示例#6
0
        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);
        }
示例#7
0
        /// <summary>
        /// BNF in RFC5464
        /// </summary>
        /// <remarks>
        /// Language-Tag  = langtag             ; normal language tags
        ///               / privateuse          ; private use tag
        ///               / grandfathered       ; grandfathered tags
        ///
        ///
        /// langtag       = language
        ///                 ["-" script]
        ///                 ["-" region]
        ///                 *("-" variant)
        ///                 *("-" extension)
        ///                 ["-" privateuse]
        ///
        /// language      = 2*3ALPHA            ; shortest ISO 639 code
        ///                 ["-" extlang]       ; sometimes followed by
        ///                                     ; extended language subtags
        ///               / 4ALPHA              ; or reserved for future use
        ///               / 5*8ALPHA            ; or registered language subtag
        ///
        /// extlang       = 3ALPHA              ; selected ISO 639 codes
        ///                 *2("-" 3ALPHA)      ; permanently reserved
        ///
        /// script        = 4ALPHA              ; ISO 15924 code
        ///
        /// region        = 2ALPHA              ; ISO 3166-1 code
        ///               / 3DIGIT              ; UN M.49 code
        ///
        /// variant       = 5*8alphanum         ; registered variants
        ///               / (DIGIT 3alphanum)
        ///
        /// extension     = singleton 1*("-" (2*8alphanum))
        ///
        ///                                     ; Single alphanumerics
        ///                                     ; "x" reserved for private use
        /// singleton     = DIGIT               ; 0 - 9
        ///               / %x41-57             ; A - W
        ///               / %x59-5A             ; Y - Z
        ///               / %x61-77             ; a - w
        ///               / %x79-7A             ; y - z
        ///
        /// privateuse    = "x" 1*("-" (1*8alphanum))
        /// </remarks>
        public static LanguageTag Parse(string languageTag, ParseStatus sts)
        {
            if (sts == null)
            {
                sts = new ParseStatus();
            }
            else
            {
                sts.Reset();
            }

            StringTokenEnumerator itr;
            bool isGrandfathered = false;

            // Check if the tag is grandfathered
            string[] gfmap;
            if (GRANDFATHERED.TryGetValue(new AsciiUtil.CaseInsensitiveKey(languageTag), out gfmap) && gfmap != null)
            {
                // use preferred mapping
                itr             = new StringTokenEnumerator(gfmap[1], SEP);
                isGrandfathered = true;
            }
            else
            {
                itr = new StringTokenEnumerator(languageTag, SEP);
            }

            // ICU4N: Move to the first element
            itr.MoveNext();
            LanguageTag tag = new LanguageTag();

            // langtag must start with either language or privateuse
            if (tag.ParseLanguage(itr, sts))
            {
                tag.ParseExtlangs(itr, sts);
                tag.ParseScript(itr, sts);
                tag.ParseRegion(itr, sts);
                tag.ParseVariants(itr, sts);
                tag.ParseExtensions(itr, sts);
            }
            tag.ParsePrivateuse(itr, sts);

            if (isGrandfathered)
            {
                // Grandfathered tag is replaced with a well-formed tag above.
                // However, the parsed length must be the original tag length.
                Debug.Assert(itr.IsDone);
                Debug.Assert(!sts.IsError);
                sts.ParseLength = languageTag.Length;
            }
            else if (!itr.IsDone && !sts.IsError)
            {
                string s = itr.Current;
                sts.ErrorIndex = itr.CurrentStart;
                if (s.Length == 0)
                {
                    sts.ErrorMessage = "Empty subtag";
                }
                else
                {
                    sts.ErrorMessage = "Invalid subtag: " + s;
                }
            }

            return(tag);
        }