< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Runtime.UrlUtility
Assembly: CoreWCF.Http
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Http/src/CoreWCF/Runtime/UrlUtility.cs
Line coverage
70%
Covered lines: 40
Uncovered lines: 17
Coverable lines: 57
Total lines: 177
Line coverage: 70.1%
Branch coverage
64%
Covered branches: 32
Total branches: 50
Branch coverage: 64%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
UrlDecode(...)50%2266.66%
UrlDecodeStringFromStringInternal(...)69.23%262660.71%
HexToInt(...)50%1212100%
FlushBytes()100%22100%
.ctor(...)100%11100%
AddChar(...)0%220%
AddByte(...)100%22100%
GetString()75%4480%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Http/src/CoreWCF/Runtime/UrlUtility.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Text;
 6
 7namespace CoreWCF.Runtime
 8{
 9    internal static class UrlUtility
 10    {
 11        public static string UrlDecode(string str, Encoding e)
 12        {
 49413            if (str == null)
 14            {
 015                return null;
 16            }
 49417            return UrlDecodeStringFromStringInternal(str, e);
 18        }
 19
 20        private static string UrlDecodeStringFromStringInternal(string s, Encoding e)
 21        {
 49422            int count = s.Length;
 49423            UrlDecoder helper = new UrlDecoder(count, e);
 24
 25            // go through the string's chars collapsing %XX and %uXXXX and
 26            // appending each char as char, with exception of %XX constructs
 27            // that are appended as bytes
 28
 5592629            for (int pos = 0; pos < count; pos++)
 30            {
 2746931                char ch = s[pos];
 32
 2746933                if (ch == '+')
 34                {
 035                    ch = ' ';
 36                }
 2746937                else if (ch == '%' && pos < count - 2)
 38                {
 1639                    if (s[pos + 1] == 'u' && pos < count - 5)
 40                    {
 041                        int h1 = HexToInt(s[pos + 2]);
 042                        int h2 = HexToInt(s[pos + 3]);
 043                        int h3 = HexToInt(s[pos + 4]);
 044                        int h4 = HexToInt(s[pos + 5]);
 45
 046                        if (h1 >= 0 && h2 >= 0 && h3 >= 0 && h4 >= 0)
 47                        {   // valid 4 hex chars
 048                            ch = (char)((h1 << 12) | (h2 << 8) | (h3 << 4) | h4);
 049                            pos += 5;
 50
 51                            // only add as char
 052                            helper.AddChar(ch);
 053                            continue;
 54                        }
 55                    }
 56                    else
 57                    {
 1658                        int h1 = HexToInt(s[pos + 1]);
 1659                        int h2 = HexToInt(s[pos + 2]);
 60
 1661                        if (h1 >= 0 && h2 >= 0)
 62                        {     // valid 2 hex chars
 1663                            byte b = (byte)((h1 << 4) | h2);
 1664                            pos += 2;
 65
 66                            // don't add as char
 1667                            helper.AddByte(b);
 1668                            continue;
 69                        }
 70                    }
 71                }
 72
 2745373                if ((ch & 0xFF80) == 0)
 74                {
 2745375                    helper.AddByte((byte)ch); // 7 bit have to go as bytes because of Unicode
 76                }
 77                else
 78                {
 079                    helper.AddChar(ch);
 80                }
 81            }
 82
 49483            return helper.GetString();
 84        }
 85
 86        // Private helpers for URL encoding/decoding
 87        private static int HexToInt(char h)
 88        {
 3289            return (h >= '0' && h <= '9') ? h - '0' :
 3290            (h >= 'a' && h <= 'f') ? h - 'a' + 10 :
 3291            (h >= 'A' && h <= 'F') ? h - 'A' + 10 :
 3292            -1;
 93        }
 94
 95        // Internal class to facilitate URL decoding -- keeps char buffer and byte buffer, allows appending of either ch
 96        private class UrlDecoder
 97        {
 98            private readonly int _bufferSize;
 99
 100            // Accumulate characters in a special array
 101            private int _numChars;
 102            private readonly char[] _charBuffer;
 103
 104            // Accumulate bytes for decoding into characters in a special array
 105            private int _numBytes;
 106            private byte[] _byteBuffer;
 107
 108            // Encoding to convert chars to bytes
 109            private readonly Encoding _encoding;
 110
 111            private void FlushBytes()
 112            {
 494113                if (_numBytes > 0)
 114                {
 494115                    _numChars += _encoding.GetChars(_byteBuffer, 0, _numBytes, _charBuffer, _numChars);
 494116                    _numBytes = 0;
 117                }
 494118            }
 119
 494120            internal UrlDecoder(int bufferSize, Encoding encoding)
 121            {
 494122                _bufferSize = bufferSize;
 494123                _encoding = encoding;
 124
 494125                _charBuffer = new char[bufferSize];
 126                // byte buffer created on demand
 494127            }
 128
 129            internal void AddChar(char ch)
 130            {
 0131                if (_numBytes > 0)
 132                {
 0133                    FlushBytes();
 134                }
 135
 0136                _charBuffer[_numChars++] = ch;
 0137            }
 138
 139            internal void AddByte(byte b)
 140            {
 141                // if there are no pending bytes treat 7 bit bytes as characters
 142                // this optimization is temp disable as it doesn't work for some encodings
 143
 144                //if (_numBytes == 0 && ((b & 0x80) == 0)) {
 145                //    AddChar((char)b);
 146                //}
 147                //else
 148
 149                {
 27469150                    if (_byteBuffer == null)
 151                    {
 494152                        _byteBuffer = new byte[_bufferSize];
 153                    }
 154
 27469155                    _byteBuffer[_numBytes++] = b;
 156                }
 27469157            }
 158
 159            internal string GetString()
 160            {
 494161                if (_numBytes > 0)
 162                {
 494163                    FlushBytes();
 164                }
 165
 494166                if (_numChars > 0)
 167                {
 494168                    return new string(_charBuffer, 0, _numChars);
 169                }
 170                else
 171                {
 0172                    return string.Empty;
 173                }
 174            }
 175        }
 176    }
 177}