63.33% Lines (38/60) 66.67% Functions (2/3)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 4   // Distributed under the Boost Software License, Version 1.0. (See accompanying
5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/cppalliance/http 7   // Official repository: https://github.com/cppalliance/http
8   // 8   //
9   9  
10   #include "src/server/detail/pct_decode.hpp" 10   #include "src/server/detail/pct_decode.hpp"
11   11  
12   namespace boost { 12   namespace boost {
13   namespace http { 13   namespace http {
14   namespace detail { 14   namespace detail {
15   15  
16   bool 16   bool
MISUBC 17   ci_is_equal( 17   ci_is_equal(
18   core::string_view s0, 18   core::string_view s0,
19   core::string_view s1) noexcept 19   core::string_view s1) noexcept
20   { 20   {
MISUBC 21   auto n = s0.size(); 21   auto n = s0.size();
MISUBC 22   if(s1.size() != n) 22   if(s1.size() != n)
MISUBC 23   return false; 23   return false;
MISUBC 24   auto p1 = s0.data(); 24   auto p1 = s0.data();
MISUBC 25   auto p2 = s1.data(); 25   auto p2 = s1.data();
26   char a, b; 26   char a, b;
27   // fast loop 27   // fast loop
MISUBC 28   while(n--) 28   while(n--)
29   { 29   {
MISUBC 30   a = *p1++; 30   a = *p1++;
MISUBC 31   b = *p2++; 31   b = *p2++;
MISUBC 32   if(a != b) 32   if(a != b)
MISUBC 33   goto slow; 33   goto slow;
34   } 34   }
MISUBC 35   return true; 35   return true;
36   do 36   do
37   { 37   {
MISUBC 38   a = *p1++; 38   a = *p1++;
MISUBC 39   b = *p2++; 39   b = *p2++;
MISUBC 40   slow: 40   slow:
MISUBC 41   if( grammar::to_lower(a) != 41   if( grammar::to_lower(a) !=
MISUBC 42   grammar::to_lower(b)) 42   grammar::to_lower(b))
MISUBC 43   return false; 43   return false;
44   } 44   }
MISUBC 45   while(n--); 45   while(n--);
MISUBC 46   return true; 46   return true;
47   } 47   }
48   48  
49   std::string 49   std::string
HITCBC 50   192 pct_decode( 50   192 pct_decode(
51   urls::pct_string_view s) 51   urls::pct_string_view s)
52   { 52   {
HITCBC 53   192 std::string result; 53   192 std::string result;
HITCBC 54   192 core::string_view sv(s); 54   192 core::string_view sv(s);
HITCBC 55   192 result.reserve(s.size()); 55   192 result.reserve(s.size());
HITCBC 56   192 auto it = sv.data(); 56   192 auto it = sv.data();
HITCBC 57   192 auto const end = it + sv.size(); 57   192 auto const end = it + sv.size();
58   for(;;) 58   for(;;)
59   { 59   {
HITCBC 60   1069 if(it == end) 60   1069 if(it == end)
HITCBC 61   192 break; 61   192 break;
HITCBC 62   877 if(*it != '%') 62   877 if(*it != '%')
63   { 63   {
HITCBC 64   876 result.push_back(*it++); 64   876 result.push_back(*it++);
HITCBC 65   876 continue; 65   876 continue;
66   } 66   }
HITCBC 67   1 ++it; 67   1 ++it;
68   #if 0 68   #if 0
69   // pct_string_view can never have invalid pct-encodings 69   // pct_string_view can never have invalid pct-encodings
70   if(it == end) 70   if(it == end)
71   goto invalid; 71   goto invalid;
72   #endif 72   #endif
HITCBC 73   1 auto d0 = urls::grammar::hexdig_value(*it++); 73   1 auto d0 = urls::grammar::hexdig_value(*it++);
74   #if 0 74   #if 0
75   // pct_string_view can never have invalid pct-encodings 75   // pct_string_view can never have invalid pct-encodings
76   if( d0 < 0 || 76   if( d0 < 0 ||
77   it == end) 77   it == end)
78   goto invalid; 78   goto invalid;
79   #endif 79   #endif
HITCBC 80   1 auto d1 = urls::grammar::hexdig_value(*it++); 80   1 auto d1 = urls::grammar::hexdig_value(*it++);
81   #if 0 81   #if 0
82   // pct_string_view can never have invalid pct-encodings 82   // pct_string_view can never have invalid pct-encodings
83   if(d1 < 0) 83   if(d1 < 0)
84   goto invalid; 84   goto invalid;
85   #endif 85   #endif
HITCBC 86   1 result.push_back(d0 * 16 + d1); 86   1 result.push_back(d0 * 16 + d1);
HITCBC 87   877 } 87   877 }
HITCBC 88   384 return result; 88   384 return result;
89   #if 0 89   #if 0
90   invalid: 90   invalid:
91   // can't get here, as received a pct_string_view 91   // can't get here, as received a pct_string_view
92   detail::throw_invalid_argument(); 92   detail::throw_invalid_argument();
93   #endif 93   #endif
MISUBC 94   } 94   }
95   95  
96   // decode all percent escapes except forward slash '/' 96   // decode all percent escapes except forward slash '/'
97   // (backslash is decoded since it's not a path separator in URLs) 97   // (backslash is decoded since it's not a path separator in URLs)
98   std::string 98   std::string
HITCBC 99   112 pct_decode_path( 99   112 pct_decode_path(
100   urls::pct_string_view s) 100   urls::pct_string_view s)
101   { 101   {
HITCBC 102   112 std::string result; 102   112 std::string result;
HITCBC 103   112 core::string_view sv(s); 103   112 core::string_view sv(s);
HITCBC 104   112 result.reserve(s.size()); 104   112 result.reserve(s.size());
HITCBC 105   112 auto it = sv.data(); 105   112 auto it = sv.data();
HITCBC 106   112 auto const end = it + sv.size(); 106   112 auto const end = it + sv.size();
107   for(;;) 107   for(;;)
108   { 108   {
HITCBC 109   802 if(it == end) 109   802 if(it == end)
HITCBC 110   112 break; 110   112 break;
HITCBC 111   690 if(*it != '%') 111   690 if(*it != '%')
112   { 112   {
HITCBC 113   684 result.push_back(*it++); 113   684 result.push_back(*it++);
HITCBC 114   684 continue; 114   684 continue;
115   } 115   }
HITCBC 116   6 ++it; 116   6 ++it;
117   #if 0 117   #if 0
118   // pct_string_view can never have invalid pct-encodings 118   // pct_string_view can never have invalid pct-encodings
119   if(it == end) 119   if(it == end)
120   goto invalid; 120   goto invalid;
121   #endif 121   #endif
HITCBC 122   6 auto d0 = urls::grammar::hexdig_value(*it++); 122   6 auto d0 = urls::grammar::hexdig_value(*it++);
123   #if 0 123   #if 0
124   // pct_string_view can never have invalid pct-encodings 124   // pct_string_view can never have invalid pct-encodings
125   if( d0 < 0 || 125   if( d0 < 0 ||
126   it == end) 126   it == end)
127   goto invalid; 127   goto invalid;
128   #endif 128   #endif
HITCBC 129   6 auto d1 = urls::grammar::hexdig_value(*it++); 129   6 auto d1 = urls::grammar::hexdig_value(*it++);
130   #if 0 130   #if 0
131   // pct_string_view can never have invalid pct-encodings 131   // pct_string_view can never have invalid pct-encodings
132   if(d1 < 0) 132   if(d1 < 0)
133   goto invalid; 133   goto invalid;
134   #endif 134   #endif
HITCBC 135   6 char c = d0 * 16 + d1; 135   6 char c = d0 * 16 + d1;
HITCBC 136   6 if(c != '/') 136   6 if(c != '/')
137   { 137   {
HITCBC 138   5 result.push_back(c); 138   5 result.push_back(c);
HITCBC 139   5 continue; 139   5 continue;
140   } 140   }
HITCBC 141   1 result.append(it - 3, 3); 141   1 result.append(it - 3, 3);
HITCBC 142   690 } 142   690 }
HITCBC 143   224 return result; 143   224 return result;
144   #if 0 144   #if 0
145   invalid: 145   invalid:
146   // can't get here, as received a pct_string_view 146   // can't get here, as received a pct_string_view
147   detail::throw_invalid_argument(); 147   detail::throw_invalid_argument();
148   #endif 148   #endif
MISUBC 149   } 149   }
150   150  
151   } // detail 151   } // detail
152   } // http 152   } // http
153   } // boost 153   } // boost