public static string GetHeaderValue(string name, char[] array, int startIndex, int length)
        {
            Debug.Assert(name != null);
            CharArrayHelpers.DebugAssertArrayInputs(array, startIndex, length);

            if (length == 0)
            {
                return(string.Empty);
            }

            // If it's a known header value, use the known value instead of allocating a new string.

            // Do a really quick reference equals check to see if name is the same object as
            // HttpKnownHeaderNames.ContentEncoding, in which case the value is very likely to
            // be either "gzip" or "deflate".
            if (ReferenceEquals(name, ContentEncoding))
            {
                if (CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase(Gzip, array, startIndex, length))
                {
                    return(Gzip);
                }
                else if (CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase(Deflate, array, startIndex, length))
                {
                    return(Deflate);
                }
            }

            return(new string(array, startIndex, length));
        }
Beispiel #2
0
        public WinHttpResponseHeaderReader(char[] buffer, int startIndex, int length)
        {
            CharArrayHelpers.DebugAssertArrayInputs(buffer, startIndex, length);

            _buffer   = buffer;
            _position = startIndex;
            _length   = length;
        }
Beispiel #3
0
        /// <summary>
        /// Gets a known header name string from a matching char[] array segment, using an ordinal comparison.
        /// Used to avoid allocating new strings for known header names.
        /// </summary>
        public static bool TryGetHeaderName(char[] array, int startIndex, int length, out string name)
        {
            CharArrayHelpers.DebugAssertArrayInputs(array, startIndex, length);

            return(TryGetHeaderName(
                       array, startIndex, length,
                       (arr, index) => arr[index],
                       (known, arr, start, len) => CharArrayHelpers.EqualsOrdinal(known, arr, start, len),
                       out name));
        }
        /// <summary>
        /// Gets a known header name string from a matching char[] array segment, using a case-sensitive
        /// ordinal comparison. Used to avoid allocating new strings for known header names.
        /// </summary>
        public static bool TryGetHeaderName(char[] array, int startIndex, int length, out string name)
        {
            CharArrayHelpers.DebugAssertArrayInputs(array, startIndex, length);

            return(TryGetHeaderName(
                       array, startIndex, length,
                       (arr, index) => arr[index],
                       (known, arr, start, len) => known.AsSpan().SequenceEqual(arr.AsSpan(start, len)),
                       out name));
        }
Beispiel #5
0
        private static string GetReasonPhrase(HttpStatusCode statusCode, char[] buffer, int bufferLength)
        {
            CharArrayHelpers.DebugAssertArrayInputs(buffer, 0, bufferLength);
            Debug.Assert(bufferLength > 0);

            // If it's a known reason phrase, use the known reason phrase instead of allocating a new string.

            string knownReasonPhrase = HttpStatusDescription.Get(statusCode);

            return((knownReasonPhrase != null && CharArrayHelpers.EqualsOrdinal(knownReasonPhrase, buffer, 0, bufferLength)) ?
                   knownReasonPhrase :
                   new string(buffer, 0, bufferLength));
        }
Beispiel #6
0
        /// <summary>
        /// Returns true if <paramref name="known"/> matches the <paramref name="key"/> char[] array segment,
        /// using an ordinal comparison.
        /// </summary>
        private static bool TryMatch(string known, char[] key, int startIndex, int length, out string name)
        {
            Debug.Assert(known != null);
            Debug.Assert(known.Length > 0);
            CharArrayHelpers.DebugAssertArrayInputs(key, startIndex, length);

            // The lengths should be equal because this method is only called
            // from within a "switch (length) { ... }".
            Debug.Assert(known.Length == length);

            if (CharArrayHelpers.EqualsOrdinal(known, key, startIndex, length))
            {
                name = known;
                return(true);
            }

            name = null;
            return(false);
        }
Beispiel #7
0
        /// <summary>
        /// Gets a known header name string from a matching char[] array segment, using a case-sensitive
        /// ordinal comparison. Used to avoid allocating new strings for known header names.
        /// </summary>
        public static bool TryGetHeaderName(char[] array, int startIndex, int length, [NotNullWhen(true)] out string?name)
        {
            CharArrayHelpers.DebugAssertArrayInputs(array, startIndex, length);

            return(TryGetHeaderName(
                       array, startIndex, length,
Beispiel #8
0
        /// <summary>
        /// Gets a known header name string from a matching char[] array segment, using an ordinal comparison.
        /// Used to avoid allocating new strings for known header names.
        /// </summary>
        public static bool TryGetHeaderName(char[] key, int startIndex, int length, out string name)
        {
            CharArrayHelpers.DebugAssertArrayInputs(key, startIndex, length);

            // When adding a new constant, add it to HttpKnownHeaderNames.cs as well.

            // The lookup works as follows: first switch on the length of the passed-in char[] array segment.
            //
            //  - If there is only one known header of that length and the char[] array segment matches that
            //    known header, set it as the out param and return true.
            //
            //  - If there are more than one known headers of that length, switch on a unique char from that
            //    set of same-length known headers. Typically this will be the first char, but some sets of
            //    same-length known headers do not have unique chars in the first position, so a char in a
            //    position further in the strings is used. If the char[] array segment matches one of the
            //    known headers, set it as the out param and return true.
            //
            //  - Otherwise, set the out param to null and return false.

            switch (length)
            {
            case 2:
                return(TryMatch(TE, key, startIndex, length, out name));    // TE

            case 3:
                switch (key[startIndex])
                {
                case 'A': return(TryMatch(Age, key, startIndex, length, out name));        // [A]ge

                case 'P': return(TryMatch(P3P, key, startIndex, length, out name));        // [P]3P

                case 'V': return(TryMatch(Via, key, startIndex, length, out name));        // [V]ia
                }
                break;

            case 4:
                switch (key[startIndex])
                {
                case 'D': return(TryMatch(Date, key, startIndex, length, out name));        // [D]ate

                case 'E': return(TryMatch(ETag, key, startIndex, length, out name));        // [E]Tag

                case 'F': return(TryMatch(From, key, startIndex, length, out name));        // [F]rom

                case 'H': return(TryMatch(Host, key, startIndex, length, out name));        // [H]ost

                case 'V': return(TryMatch(Vary, key, startIndex, length, out name));        // [V]ary
                }
                break;

            case 5:
                switch (key[startIndex])
                {
                case 'A': return(TryMatch(Allow, key, startIndex, length, out name));        // [A]llow

                case 'R': return(TryMatch(Range, key, startIndex, length, out name));        // [R]ange
                }
                break;

            case 6:
                switch (key[startIndex])
                {
                case 'A': return(TryMatch(Accept, key, startIndex, length, out name));        // [A]ccept

                case 'C': return(TryMatch(Cookie, key, startIndex, length, out name));        // [C]ookie

                case 'E': return(TryMatch(Expect, key, startIndex, length, out name));        // [E]xpect

                case 'O': return(TryMatch(Origin, key, startIndex, length, out name));        // [O]rigin

                case 'P': return(TryMatch(Pragma, key, startIndex, length, out name));        // [P]ragma

                case 'S': return(TryMatch(Server, key, startIndex, length, out name));        // [S]erver
                }
                break;

            case 7:
                switch (key[startIndex])
                {
                case 'C': return(TryMatch(Cookie2, key, startIndex, length, out name));        // [C]ookie2

                case 'E': return(TryMatch(Expires, key, startIndex, length, out name));        // [E]xpires

                case 'R': return(TryMatch(Referer, key, startIndex, length, out name));        // [R]eferer

                case 'T': return(TryMatch(Trailer, key, startIndex, length, out name));        // [T]railer

                case 'U': return(TryMatch(Upgrade, key, startIndex, length, out name));        // [U]pgrade

                case 'W': return(TryMatch(Warning, key, startIndex, length, out name));        // [W]arning
                }
                break;

            case 8:
                switch (key[startIndex + 3])
                {
                case 'M': return(TryMatch(IfMatch, key, startIndex, length, out name));         // If-[M]atch

                case 'R': return(TryMatch(IfRange, key, startIndex, length, out name));         // If-[R]ange

                case 'a': return(TryMatch(Location, key, startIndex, length, out name));        // Loc[a]tion
                }
                break;

            case 10:
                switch (key[startIndex])
                {
                case 'C': return(TryMatch(Connection, key, startIndex, length, out name));        // [C]onnection

                case 'K': return(TryMatch(KeepAlive, key, startIndex, length, out name));         // [K]eep-Alive

                case 'S': return(TryMatch(SetCookie, key, startIndex, length, out name));         // [S]et-Cookie

                case 'U': return(TryMatch(UserAgent, key, startIndex, length, out name));         // [U]ser-Agent
                }
                break;

            case 11:
                switch (key[startIndex])
                {
                case 'C': return(TryMatch(ContentMD5, key, startIndex, length, out name));        // [C]ontent-MD5

                case 'R': return(TryMatch(RetryAfter, key, startIndex, length, out name));        // [R]etry-After

                case 'S': return(TryMatch(SetCookie2, key, startIndex, length, out name));        // [S]et-Cookie2
                }
                break;

            case 12:
                switch (key[startIndex])
                {
                case 'C': return(TryMatch(ContentType, key, startIndex, length, out name));        // [C]ontent-Type

                case 'M': return(TryMatch(MaxForwards, key, startIndex, length, out name));        // [M]ax-Forwards

                case 'X': return(TryMatch(XPoweredBy, key, startIndex, length, out name));         // [X]-Powered-By
                }
                break;

            case 13:
                switch (key[startIndex + 6])
                {
                case '-': return(TryMatch(AcceptRanges, key, startIndex, length, out name));         // Accept[-]Ranges

                case 'i': return(TryMatch(Authorization, key, startIndex, length, out name));        // Author[i]zation

                case 'C': return(TryMatch(CacheControl, key, startIndex, length, out name));         // Cache-[C]ontrol

                case 't': return(TryMatch(ContentRange, key, startIndex, length, out name));         // Conten[t]-Range

                case 'e': return(TryMatch(IfNoneMatch, key, startIndex, length, out name));          // If-Non[e]-Match

                case 'o': return(TryMatch(LastModified, key, startIndex, length, out name));         // Last-M[o]dified
                }
                break;

            case 14:
                switch (key[startIndex])
                {
                case 'A': return(TryMatch(AcceptCharset, key, startIndex, length, out name));        // [A]ccept-Charset

                case 'C': return(TryMatch(ContentLength, key, startIndex, length, out name));        // [C]ontent-Length
                }
                break;

            case 15:
                switch (key[startIndex + 7])
                {
                case 'E': return(TryMatch(AcceptEncoding, key, startIndex, length, out name));        // Accept-[E]ncoding

                case 'L': return(TryMatch(AcceptLanguage, key, startIndex, length, out name));        // Accept-[L]anguage
                }
                break;

            case 16:
                switch (key[startIndex + 11])
                {
                case 'o': return(TryMatch(ContentEncoding, key, startIndex, length, out name));        // Content-Enc[o]ding

                case 'g': return(TryMatch(ContentLanguage, key, startIndex, length, out name));        // Content-Lan[g]uage

                case 'a': return(TryMatch(ContentLocation, key, startIndex, length, out name));        // Content-Loc[a]tion

                case 'c': return(TryMatch(ProxyConnection, key, startIndex, length, out name));        // Proxy-Conne[c]tion

                case 'i': return(TryMatch(WWWAuthenticate, key, startIndex, length, out name));        // WWW-Authent[i]cate

                case 'r': return(TryMatch(XAspNetVersion, key, startIndex, length, out name));         // X-AspNet-Ve[r]sion
                }
                break;

            case 17:
                switch (key[startIndex])
                {
                case 'I': return(TryMatch(IfModifiedSince, key, startIndex, length, out name));         // [I]f-Modified-Since

                case 'S': return(TryMatch(SecWebSocketKey, key, startIndex, length, out name));         // [S]ec-WebSocket-Key

                case 'T': return(TryMatch(TransferEncoding, key, startIndex, length, out name));        // [T]ransfer-Encoding
                }
                break;

            case 18:
                return(TryMatch(ProxyAuthenticate, key, startIndex, length, out name));    // Proxy-Authenticate

            case 19:
                switch (key[startIndex])
                {
                case 'C': return(TryMatch(ContentDisposition, key, startIndex, length, out name));        // [C]ontent-Disposition

                case 'I': return(TryMatch(IfUnmodifiedSince, key, startIndex, length, out name));         // [I]f-Unmodified-Since

                case 'P': return(TryMatch(ProxyAuthorization, key, startIndex, length, out name));        // [P]roxy-Authorization
                }
                break;

            case 20:
                return(TryMatch(SecWebSocketAccept, key, startIndex, length, out name));    // Sec-WebSocket-Accept

            case 21:
                return(TryMatch(SecWebSocketVersion, key, startIndex, length, out name));    // Sec-WebSocket-Version

            case 22:
                return(TryMatch(SecWebSocketProtocol, key, startIndex, length, out name));    // Sec-WebSocket-Protocol

            case 24:
                return(TryMatch(SecWebSocketExtensions, key, startIndex, length, out name));    // Sec-WebSocket-Extensions
            }

            name = null;
            return(false);
        }