100.00% Lines (80/80) 100.00% Functions (2/2)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com) 2   // Copyright (c) 2022 Alan de Freitas (alandefreitas@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/boostorg/url 7   // Official repository: https://github.com/boostorg/url
8   // 8   //
9   9  
10   10  
11   #include <boost/url/detail/config.hpp> 11   #include <boost/url/detail/config.hpp>
12   #include "pct_format.hpp" 12   #include "pct_format.hpp"
13   #include <boost/url/grammar/parse.hpp> 13   #include <boost/url/grammar/parse.hpp>
14   #include <boost/url/grammar/unsigned_rule.hpp> 14   #include <boost/url/grammar/unsigned_rule.hpp>
15   15  
16   namespace boost { 16   namespace boost {
17   namespace urls { 17   namespace urls {
18   namespace detail { 18   namespace detail {
19   19  
20   std::size_t 20   std::size_t
HITCBC 21   301 pct_vmeasure( 21   301 pct_vmeasure(
22   grammar::lut_chars const& cs, 22   grammar::lut_chars const& cs,
23   format_parse_context& pctx, 23   format_parse_context& pctx,
24   measure_context& mctx) 24   measure_context& mctx)
25   { 25   {
HITCBC 26   301 auto it0 = pctx.begin(); 26   301 auto it0 = pctx.begin();
HITCBC 27   301 auto end = pctx.end(); 27   301 auto end = pctx.end();
HITCBC 28   589 while( it0 != end ) 28   589 while( it0 != end )
29   { 29   {
30   // look for replacement id 30   // look for replacement id
HITCBC 31   354 char const* it1 = it0; 31   354 char const* it1 = it0;
HITCBC 32   354 while( 32   354 while(
HITCBC 33   912 it1 != end && 33   912 it1 != end &&
HITCBC 34   848 *it1 != '{' ) 34   848 *it1 != '{' )
35   { 35   {
HITCBC 36   558 ++it1; 36   558 ++it1;
37   } 37   }
38   38  
39   // output literal prefix 39   // output literal prefix
HITCBC 40   354 if( it0 != it1 ) 40   354 if( it0 != it1 )
41   { 41   {
HITCBC 42   701 for (char const* i = it0; i != it1; ++i) 42   701 for (char const* i = it0; i != it1; ++i)
HITCBC 43   558 mctx.advance_to( mctx.out() + measure_one(*i, cs)); 43   558 mctx.advance_to( mctx.out() + measure_one(*i, cs));
44   } 44   }
45   45  
46   // over 46   // over
HITCBC 47   354 if( it1 == end ) 47   354 if( it1 == end )
48   { 48   {
HITCBC 49   64 break; 49   64 break;
50   } 50   }
51   51  
52   // enter replacement id 52   // enter replacement id
HITCBC 53   290 ++it1; 53   290 ++it1;
HITCBC 54   290 BOOST_ASSERT(it1 != end); 54   290 BOOST_ASSERT(it1 != end);
55   55  
56   // handle escaped replacement (second '{') 56   // handle escaped replacement (second '{')
57   // there's no "{{" in URL templates because 57   // there's no "{{" in URL templates because
58   // '{'s are not allowed in URLs 58   // '{'s are not allowed in URLs
HITCBC 59   290 BOOST_ASSERT(*it1 != '{'); 59   290 BOOST_ASSERT(*it1 != '{');
60   /* 60   /*
61   if( *it1 == '{' ) 61   if( *it1 == '{' )
62   { 62   {
63   mctx.advance_to( mctx.out() + measure_one('{', cs)); 63   mctx.advance_to( mctx.out() + measure_one('{', cs));
64   ++it1; 64   ++it1;
65   // this was not a real replacement, 65   // this was not a real replacement,
66   // so we just keep moving 66   // so we just keep moving
67   continue; 67   continue;
68   } 68   }
69   */ 69   */
70   70  
71   71  
72   // parse {id} or {id:specs} 72   // parse {id} or {id:specs}
HITCBC 73   290 char const* id_start = it1; 73   290 char const* id_start = it1;
HITCBC 74   290 while (it1 != end && 74   290 while (it1 != end &&
HITCBC 75   540 *it1 != ':' && 75   540 *it1 != ':' &&
HITCBC 76   498 *it1 != '}') 76   498 *it1 != '}')
77   { 77   {
HITCBC 78   250 ++it1; 78   250 ++it1;
79   } 79   }
HITCBC 80   290 core::string_view id(id_start, it1); 80   290 core::string_view id(id_start, it1);
81   81  
82   // move to specs start 82   // move to specs start
HITCBC 83   290 if (it1 != end && 83   290 if (it1 != end &&
HITCBC 84   290 *it1 == ':') 84   290 *it1 == ':')
HITCBC 85   42 ++it1; 85   42 ++it1;
HITCBC 86   290 pctx.advance_to( it1 ); 86   290 pctx.advance_to( it1 );
87   87  
88   // get format_arg to use 88   // get format_arg to use
HITCBC 89   290 auto idv = grammar::parse( 89   290 auto idv = grammar::parse(
HITCBC 90   290 id, grammar::unsigned_rule<std::size_t>{}); 90   290 id, grammar::unsigned_rule<std::size_t>{});
HITCBC 91   290 if (idv) 91   290 if (idv)
92   { 92   {
HITCBC 93   33 mctx.arg( *idv ).measure( pctx, mctx, cs ); 93   33 mctx.arg( *idv ).measure( pctx, mctx, cs );
94   } 94   }
HITCBC 95   257 else if (!id.empty()) 95   257 else if (!id.empty())
96   { 96   {
HITCBC 97   43 mctx.arg( id ).measure( pctx, mctx, cs ); 97   43 mctx.arg( id ).measure( pctx, mctx, cs );
98   } 98   }
99   else 99   else
100   { 100   {
HITCBC 101   214 std::size_t arg_id = pctx.next_arg_id(); 101   214 std::size_t arg_id = pctx.next_arg_id();
HITCBC 102   214 mctx.arg( arg_id ).measure( pctx, mctx, cs ); 102   214 mctx.arg( arg_id ).measure( pctx, mctx, cs );
103   } 103   }
104   104  
105   105  
HITCBC 106   288 it1 = pctx.begin(); 106   288 it1 = pctx.begin();
HITCBC 107   288 BOOST_ASSERT(*it1 == '}'); 107   288 BOOST_ASSERT(*it1 == '}');
HITCBC 108   288 it0 = it1 + 1; 108   288 it0 = it1 + 1;
109   } 109   }
110   110  
HITCBC 111   299 return mctx.out(); 111   299 return mctx.out();
112   } 112   }
113   113  
114   char* 114   char*
HITCBC 115   296 pct_vformat( 115   296 pct_vformat(
116   grammar::lut_chars const& cs, 116   grammar::lut_chars const& cs,
117   format_parse_context& pctx, 117   format_parse_context& pctx,
118   format_context& fctx) 118   format_context& fctx)
119   { 119   {
HITCBC 120   296 auto it0 = pctx.begin(); 120   296 auto it0 = pctx.begin();
HITCBC 121   296 auto end = pctx.end(); 121   296 auto end = pctx.end();
HITCBC 122   582 while( it0 != end ) 122   582 while( it0 != end )
123   { 123   {
124   // look for replacement id 124   // look for replacement id
HITCBC 125   349 char const* it1 = it0; 125   349 char const* it1 = it0;
HITCBC 126   349 while( 126   349 while(
HITCBC 127   898 it1 != end && 127   898 it1 != end &&
HITCBC 128   835 *it1 != '{' ) 128   835 *it1 != '{' )
129   { 129   {
HITCBC 130   549 ++it1; 130   549 ++it1;
131   } 131   }
132   132  
133   // output literal prefix 133   // output literal prefix
HITCBC 134   349 if( it0 != it1 ) 134   349 if( it0 != it1 )
135   { 135   {
HITCBC 136   691 for (char const* i = it0; i != it1; ++i) 136   691 for (char const* i = it0; i != it1; ++i)
137   { 137   {
HITCBC 138   549 char* o = fctx.out(); 138   549 char* o = fctx.out();
HITCBC 139   549 encode_one(o, *i, cs); 139   549 encode_one(o, *i, cs);
HITCBC 140   549 fctx.advance_to(o); 140   549 fctx.advance_to(o);
141   } 141   }
142   } 142   }
143   143  
144   // over 144   // over
HITCBC 145   349 if( it1 == end ) 145   349 if( it1 == end )
146   { 146   {
HITCBC 147   63 break; 147   63 break;
148   } 148   }
149   149  
150   // enter replacement id 150   // enter replacement id
HITCBC 151   286 ++it1; 151   286 ++it1;
HITCBC 152   286 BOOST_ASSERT(it1 != end); 152   286 BOOST_ASSERT(it1 != end);
153   153  
154   // handle escaped replacement (second '{') 154   // handle escaped replacement (second '{')
155   // there's no "{{" in URL templates because 155   // there's no "{{" in URL templates because
156   // '{'s are not allowed in URLs 156   // '{'s are not allowed in URLs
HITCBC 157   286 BOOST_ASSERT(*it1 != '{'); 157   286 BOOST_ASSERT(*it1 != '{');
158   /* 158   /*
159   if( *it1 == '{' ) 159   if( *it1 == '{' )
160   { 160   {
161   char* o = fctx.out(); 161   char* o = fctx.out();
162   encode_one(o, '{', cs); 162   encode_one(o, '{', cs);
163   fctx.advance_to(o); 163   fctx.advance_to(o);
164   ++it1; 164   ++it1;
165   // this was not a real replacement, 165   // this was not a real replacement,
166   // so we just keep moving 166   // so we just keep moving
167   continue; 167   continue;
168   } 168   }
169   */ 169   */
170   170  
171   // parse {id} or {id:specs} 171   // parse {id} or {id:specs}
HITCBC 172   286 char const* id_start = it1; 172   286 char const* id_start = it1;
HITCBC 173   286 while (it1 != end && 173   286 while (it1 != end &&
HITCBC 174   536 *it1 != ':' && 174   536 *it1 != ':' &&
HITCBC 175   496 *it1 != '}') 175   496 *it1 != '}')
176   { 176   {
HITCBC 177   250 ++it1; 177   250 ++it1;
178   } 178   }
HITCBC 179   286 core::string_view id(id_start, it1); 179   286 core::string_view id(id_start, it1);
180   180  
181   // move to specs part 181   // move to specs part
HITCBC 182   286 if (it1 != end && 182   286 if (it1 != end &&
HITCBC 183   286 *it1 == ':') 183   286 *it1 == ':')
HITCBC 184   40 ++it1; 184   40 ++it1;
HITCBC 185   286 pctx.advance_to( it1 ); 185   286 pctx.advance_to( it1 );
186   186  
187   // get format_arg to use 187   // get format_arg to use
HITCBC 188   286 auto idv = grammar::parse( 188   286 auto idv = grammar::parse(
HITCBC 189   286 id, grammar::unsigned_rule<std::size_t>{}); 189   286 id, grammar::unsigned_rule<std::size_t>{});
HITCBC 190   286 if (idv) 190   286 if (idv)
191   { 191   {
HITCBC 192   33 fctx.arg( *idv ).format( pctx, fctx, cs ); 192   33 fctx.arg( *idv ).format( pctx, fctx, cs );
193   } 193   }
HITCBC 194   253 else if (!id.empty()) 194   253 else if (!id.empty())
195   { 195   {
HITCBC 196   43 fctx.arg( id ).format( pctx, fctx, cs ); 196   43 fctx.arg( id ).format( pctx, fctx, cs );
197   } 197   }
198   else 198   else
199   { 199   {
HITCBC 200   210 std::size_t arg_id = pctx.next_arg_id(); 200   210 std::size_t arg_id = pctx.next_arg_id();
HITCBC 201   210 fctx.arg( arg_id ).format( pctx, fctx, cs ); 201   210 fctx.arg( arg_id ).format( pctx, fctx, cs );
202   } 202   }
203   203  
HITCBC 204   286 it1 = pctx.begin(); 204   286 it1 = pctx.begin();
HITCBC 205   286 BOOST_ASSERT(*it1 == '}'); 205   286 BOOST_ASSERT(*it1 == '}');
HITCBC 206   286 it0 = it1 + 1; 206   286 it0 = it1 + 1;
207   } 207   }
208   208  
HITCBC 209   296 return fctx.out(); 209   296 return fctx.out();
210   } 210   }
211   211  
212   } // detail 212   } // detail
213   } // urls 213   } // urls
214   } // boost 214   } // boost
215   215