LCOV - code coverage report
Current view: top level - libs/url/src/detail - pct_format.cpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 78 78 100.0 %
Date: 2024-03-08 17:32:04 Functions: 2 2 100.0 %

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

Generated by: LCOV version 1.15