Exemplo n.º 1
0
        internal Unit(string input, char sep)
        {
            if (input == null || input == String.Empty)
            {
                type     = (UnitType)0;
                value    = 0.0;
                valueSet = false;
                return;
            }

            value = 0.0;
            double       dv = 0, factor = .1;
            int          i = 0;
            int          count = input.Length;
            int          sign = 1, unitStart = -1, unitLen = 0, wsCount = 0;
            char         c;
            ParsingStage ps = ParsingStage.Trim;
            bool         done = false, haveSep = false, haveDigits = false, isWhiteSpace;

            while (!done && i < count)
            {
                c = input [i];

                switch (ps)
                {
                case ParsingStage.Trim:
                    if (Char.IsWhiteSpace(c))
                    {
                        i++;
                        continue;
                    }
                    ps = ParsingStage.SignOrSep;
                    continue;

                case ParsingStage.SignOrSep:
                    wsCount = 0;
                    if (c == '-')
                    {
                        sign = -1;
                        i++;
                        ps = ParsingStage.DigitOrSep;
                        continue;
                    }

                    if (c == sep)
                    {
                        i++;
                        haveSep = true;
                        ps      = ParsingStage.DigitOrUnit;
                        dv      = 0;
                        continue;
                    }

                    if (Char.IsDigit(c))
                    {
                        ps = ParsingStage.DigitOrSep;
                        continue;
                    }

                    throw new FormatException();

                case ParsingStage.DigitOrSep:
                    if (Char.IsDigit(c))
                    {
                        dv = dv * 10 + ((int)c) - ((int)'0');
                        i++;
                        haveDigits = true;
                        continue;
                    }

                    if (c == sep)
                    {
                        if (wsCount > 0)
                        {
                            throw new ArgumentOutOfRangeException("input");
                        }

                        i++;
                        haveSep = true;
                        value   = dv * sign;
                        dv      = 0;
                        ps      = ParsingStage.DigitOrUnit;
                        continue;
                    }

                    isWhiteSpace = Char.IsWhiteSpace(c);
                    if (isWhiteSpace || c == '%' || Char.IsLetter(c))
                    {
                        if (isWhiteSpace)
                        {
                            if (!haveDigits)
                            {
                                throw new ArgumentOutOfRangeException("input");
                            }
                            wsCount++;
                            i++;
                            continue;
                        }

                        value     = dv * sign;
                        dv        = 0;
                        unitStart = i;

                        if (haveSep)
                        {
                            haveDigits = false;
                            ps         = ParsingStage.DigitOrUnit;
                        }
                        else
                        {
                            ps = ParsingStage.Unit;
                        }
                        wsCount = 0;
                        continue;
                    }

                    throw new FormatException();

                case ParsingStage.DigitOrUnit:
                    if (c == '%')
                    {
                        unitStart = i;
                        unitLen   = 1;
                        done      = true;
                        continue;
                    }

                    isWhiteSpace = Char.IsWhiteSpace(c);
                    if (isWhiteSpace || Char.IsLetter(c))
                    {
                        if (isWhiteSpace)
                        {
                            wsCount++;
                            i++;
                            continue;
                        }

                        ps        = ParsingStage.Unit;
                        unitStart = i;
                        continue;
                    }

                    if (Char.IsDigit(c))
                    {
                        if (wsCount > 0)
                        {
                            throw new ArgumentOutOfRangeException();
                        }

                        dv     = dv + (((int)c) - ((int)'0')) * factor;
                        factor = factor * .1;
                        i++;
                        continue;
                    }

                    throw new FormatException();

                case ParsingStage.Unit:
                    if (c == '%' || Char.IsLetter(c))
                    {
                        i++;
                        unitLen++;
                        continue;
                    }

                    if (unitLen == 0 && Char.IsWhiteSpace(c))
                    {
                        i++;
                        unitStart++;
                        continue;
                    }

                    done = true;
                    break;
                }
            }

            value += dv * sign;
            if (unitStart >= 0)
            {
                int unitTail = unitStart + unitLen;
                if (unitTail < count)
                {
                    for (int j = unitTail; j < count; j++)
                    {
                        if (!Char.IsWhiteSpace(input [j]))
                        {
                            throw new ArgumentOutOfRangeException("input");
                        }
                    }
                }

                if (unitLen == 1 && input [unitStart] == '%')
                {
                    type = UnitType.Percentage;
                }
                else
                {
                    switch (input.Substring(unitStart, unitLen).ToLower(Helpers.InvariantCulture))
                    {
                    case "in": type = UnitType.Inch; break;

                    case "cm": type = UnitType.Cm; break;

                    case "mm": type = UnitType.Mm; break;

                    case "pt": type = UnitType.Point; break;

                    case "pc": type = UnitType.Pica; break;

                    case "em": type = UnitType.Em; break;

                    case "ex": type = UnitType.Ex; break;

                    case "px":
                        type = UnitType.Pixel;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("value");
                    }
                }
            }
            else
            {
                type = UnitType.Pixel;
            }

            if (haveSep && type == UnitType.Pixel)
            {
                throw new FormatException("Pixel units do not allow floating point values");
            }
            valueSet = true;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Parses response/request header
        /// </summary>
        /// <param name="s">data to parse, must be long enough to contain at least the start line</param>
        /// <param name="isResponse"></param>
        /// <returns>is header parsing finished</returns>
        /// <exception cref="InvalidHttpHeaderException">Thrown when parsing is unsuccessful</exception>
        /// <remarks>Max headers size is limited by 512KiB</remarks>
        public bool Parse(IDataStream s, bool isResponse)
        {
            lock (builder)
            {
                if (stage == ParsingStage.Finished)
                {
                    return(true);
                }
                if (s.Length <= nextRead)
                {
                    return(false);
                }

                byte[] arr;
                // max 512KiB
                int len = (int)Math.Min(s.Length - nextRead, 524288);
                arr = s.ReadBytes(nextRead, len);
                var str = ASCIIEncoding.ASCII.GetString(arr);
                if (stage == ParsingStage.StatusLine)
                {
                    if (isResponse)
                    {
                        var match = statusLineRegex.Match(str);
                        if (!match.Success && str.Length < s.Length)
                        {
                            throw new InvalidHttpHeaderException();
                        }

                        builder.IsRequest    = false;
                        builder.HttpVersion  = match.Groups["Version"].Value;
                        builder.StatusCode   = int.Parse(match.Groups["Code"].Value);
                        builder.ReasonPhrase = match.Groups["ReasonPhrase"].Value;
                        nextRead             = match.Length;
                        stage = ParsingStage.Headers;
                        str   = str.Substring(nextRead);
                    }
                    else
                    {
                        var match = requestLineRegex.Match(str);
                        if (!match.Success && str.Length < s.Length)
                        {
                            throw new InvalidHttpHeaderException();
                        }

                        var target = match.Groups["Target"].Value;
                        HttpRequestMethod method;
                        if (!Enum.TryParse(match.Groups["Method"].Value, out method))
                        {
                            throw new InvalidHttpHeaderException();
                        }
                        builder.IsRequest     = true;
                        builder.HttpVersion   = match.Groups["Version"].Value;
                        builder.Method        = method;
                        builder.RequestTarget = target;
                        nextRead = match.Length;
                        stage    = ParsingStage.Headers;
                        str      = str.Substring(nextRead);
                    }
                }
                if (stage == ParsingStage.Headers)
                {
                    int   read = 0;
                    Match match;
                    while ((match = headerRegex.Match(str, read)).Success)
                    {
                        // Check for end of the string
                        if (str.Length - (match.Length + read) < 2)
                        {
                            nextRead += read;
                            return(false);
                        }
                        var key   = match.Groups["Key"].Value;
                        var value = match.Groups["Value"].Value;
                        builder.AddHeader(key, value);
                        read += match.Length;
                        if (str.Substring(read, 2) != "\r\n")
                        {
                            throw new InvalidHttpHeaderException();
                        }
                        read += 2;
                    }
                    if (str.Length > 0 && read == 0)
                    {
                        throw new InvalidHttpHeaderException();
                    }
                    str       = str.Substring(read);
                    nextRead += read;
                }
                if (stage != ParsingStage.Finished && str.Length >= 2 && str.Substring(0, 2) == "\r\n")
                {
                    stage     = ParsingStage.Finished;
                    nextRead += 2;
                    return(true);
                }
                return(false);
            }
        }