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

Generated by: LCOV version 1.15