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 | |||||||