100.00% Lines (88/88) 100.00% Functions (30/30)
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   #ifndef BOOST_URL_DETAIL_FORMAT_ARGS_HPP 10   #ifndef BOOST_URL_DETAIL_FORMAT_ARGS_HPP
11   #define BOOST_URL_DETAIL_FORMAT_ARGS_HPP 11   #define BOOST_URL_DETAIL_FORMAT_ARGS_HPP
12   12  
13   #include <boost/url/detail/encode.hpp> 13   #include <boost/url/detail/encode.hpp>
14   #include <boost/url/grammar/lut_chars.hpp> 14   #include <boost/url/grammar/lut_chars.hpp>
15   15  
16   #include <boost/core/ignore_unused.hpp> 16   #include <boost/core/ignore_unused.hpp>
17   #include <array> 17   #include <array>
18   18  
19   // This file implements functions and classes to 19   // This file implements functions and classes to
20   // type-erase format arguments. 20   // type-erase format arguments.
21   21  
22   namespace boost { 22   namespace boost {
23   namespace urls { 23   namespace urls {
24   namespace detail { 24   namespace detail {
25   25  
26   // state of the format string. It basically keeps 26   // state of the format string. It basically keeps
27   // track of where we are in the format string. 27   // track of where we are in the format string.
28   class format_parse_context 28   class format_parse_context
29   { 29   {
30   char const* begin_; 30   char const* begin_;
31   char const* end_; 31   char const* end_;
32   std::size_t arg_id_ = 0; 32   std::size_t arg_id_ = 0;
33   33  
34   public: 34   public:
35   constexpr 35   constexpr
HITCBC 36   752 format_parse_context( 36   752 format_parse_context(
37   char const* first, 37   char const* first,
38   char const* last, 38   char const* last,
39   std::size_t arg_id = 0) 39   std::size_t arg_id = 0)
HITCBC 40   752 : begin_( first ) 40   752 : begin_( first )
HITCBC 41   752 , end_( last ) 41   752 , end_( last )
HITCBC 42   752 , arg_id_( arg_id ) 42   752 , arg_id_( arg_id )
HITCBC 43   752 {} 43   752 {}
44   44  
45   constexpr 45   constexpr
HITCBC 46   597 format_parse_context( 46   597 format_parse_context(
47   core::string_view fmt, 47   core::string_view fmt,
48   std::size_t arg_id = 0) 48   std::size_t arg_id = 0)
HITCBC 49   597 : format_parse_context( 49   597 : format_parse_context(
50   fmt.data(), 50   fmt.data(),
HITCBC 51   597 fmt.data() + fmt.size(), 51   597 fmt.data() + fmt.size(),
HITCBC 52   597 arg_id ) 52   597 arg_id )
HITCBC 53   597 {} 53   597 {}
54   54  
55   constexpr 55   constexpr
56   char const* 56   char const*
HITCBC 57   1747 begin() const noexcept 57   1747 begin() const noexcept
58   { 58   {
HITCBC 59   1747 return begin_; 59   1747 return begin_;
60   } 60   }
61   61  
62   constexpr 62   constexpr
63   char const* 63   char const*
HITCBC 64   1173 end() const noexcept 64   1173 end() const noexcept
65   { 65   {
HITCBC 66   1173 return end_; 66   1173 return end_;
67   } 67   }
68   68  
69   BOOST_CXX14_CONSTEXPR 69   BOOST_CXX14_CONSTEXPR
70   void 70   void
HITCBC 71   1150 advance_to( char const* it ) 71   1150 advance_to( char const* it )
72   { 72   {
HITCBC 73   1150 begin_ = it; 73   1150 begin_ = it;
HITCBC 74   1150 } 74   1150 }
75   75  
76   std::size_t 76   std::size_t
HITCBC 77   1027 next_arg_id() 77   1027 next_arg_id()
78   { 78   {
HITCBC 79   1027 return arg_id_++; 79   1027 return arg_id_++;
80   } 80   }
81   }; 81   };
82   82  
83   // State of the destination string 83   // State of the destination string
84   class format_context; 84   class format_context;
85   class measure_context; 85   class measure_context;
86   struct ignore_format {}; 86   struct ignore_format {};
87   87  
88   template <class T> 88   template <class T>
89   struct named_arg 89   struct named_arg
90   { 90   {
91   core::string_view name; 91   core::string_view name;
92   T const& value; 92   T const& value;
93   93  
HITCBC 94   21 named_arg(core::string_view n, T const& v) 94   21 named_arg(core::string_view n, T const& v)
HITCBC 95   21 : name(n) 95   21 : name(n)
HITCBC 96   21 , value(v) 96   21 , value(v)
HITCBC 97   21 {} 97   21 {}
98   }; 98   };
99   99  
100   // A type erased format argument 100   // A type erased format argument
101   class format_arg 101   class format_arg
102   { 102   {
103   void const* arg_; 103   void const* arg_;
104   void (*measure_)( 104   void (*measure_)(
105   format_parse_context&, 105   format_parse_context&,
106   measure_context&, 106   measure_context&,
107   grammar::lut_chars const&, 107   grammar::lut_chars const&,
108   void const* ); 108   void const* );
109   void (*fmt_)( 109   void (*fmt_)(
110   format_parse_context&, 110   format_parse_context&,
111   format_context&, 111   format_context&,
112   grammar::lut_chars const&, 112   grammar::lut_chars const&,
113   void const* ); 113   void const* );
114   core::string_view name_; 114   core::string_view name_;
115   std::size_t value_ = 0; 115   std::size_t value_ = 0;
116   bool ignore_ = false; 116   bool ignore_ = false;
117   117  
118   template <class A> 118   template <class A>
119   static 119   static
120   void 120   void
121   measure_impl( 121   measure_impl(
122   format_parse_context& pctx, 122   format_parse_context& pctx,
123   measure_context& mctx, 123   measure_context& mctx,
124   grammar::lut_chars const& cs, 124   grammar::lut_chars const& cs,
125   void const* a ); 125   void const* a );
126   126  
127   template <class A> 127   template <class A>
128   static 128   static
129   void 129   void
130   format_impl( 130   format_impl(
131   format_parse_context& pctx, 131   format_parse_context& pctx,
132   format_context& fctx, 132   format_context& fctx,
133   grammar::lut_chars const& cs, 133   grammar::lut_chars const& cs,
134   void const* a ); 134   void const* a );
135   135  
136   public: 136   public:
137   template<class A> 137   template<class A>
138   format_arg( A&& a ); 138   format_arg( A&& a );
139   139  
140   template<class A> 140   template<class A>
141   format_arg( named_arg<A>&& a ); 141   format_arg( named_arg<A>&& a );
142   142  
143   template<class A> 143   template<class A>
144   format_arg( core::string_view name, A&& a ); 144   format_arg( core::string_view name, A&& a );
145   145  
HITCBC 146   34 format_arg() 146   34 format_arg()
HITCBC 147   34 : format_arg(ignore_format{}) 147   34 : format_arg(ignore_format{})
HITCBC 148   34 {} 148   34 {}
149   149  
150   explicit 150   explicit
151   operator bool() const noexcept 151   operator bool() const noexcept
152   { 152   {
153   return !ignore_; 153   return !ignore_;
154   } 154   }
155   155  
156   void 156   void
HITCBC 157   290 measure( 157   290 measure(
158   format_parse_context& pctx, 158   format_parse_context& pctx,
159   measure_context& mctx, 159   measure_context& mctx,
160   grammar::lut_chars const& cs) 160   grammar::lut_chars const& cs)
161   { 161   {
HITCBC 162   290 measure_( pctx, mctx, cs, arg_ ); 162   290 measure_( pctx, mctx, cs, arg_ );
HITCBC 163   288 } 163   288 }
164   164  
165   void 165   void
HITCBC 166   286 format( 166   286 format(
167   format_parse_context& pctx, 167   format_parse_context& pctx,
168   format_context& fctx, 168   format_context& fctx,
169   grammar::lut_chars const& cs ) 169   grammar::lut_chars const& cs )
170   { 170   {
HITCBC 171   286 fmt_( pctx, fctx, cs, arg_ ); 171   286 fmt_( pctx, fctx, cs, arg_ );
HITCBC 172   286 } 172   286 }
173   173  
174   core::string_view 174   core::string_view
HITCBC 175   224 name() const 175   224 name() const
176   { 176   {
HITCBC 177   224 return name_; 177   224 return name_;
178   } 178   }
179   179  
180   std::size_t 180   std::size_t
HITCBC 181   28 value() const 181   28 value() const
182   { 182   {
HITCBC 183   28 return value_; 183   28 return value_;
184   } 184   }
185   }; 185   };
186   186  
187   // create temp stack storage for type erased args 187   // create temp stack storage for type erased args
188   template< class... Args > 188   template< class... Args >
189   std::array<format_arg, sizeof...(Args)> 189   std::array<format_arg, sizeof...(Args)>
HITCBC 190   159 make_format_args( Args&&... args ) 190   159 make_format_args( Args&&... args )
191   { 191   {
HITCBC 192   159 return {{ std::forward<Args>(args)... }}; 192   159 return {{ std::forward<Args>(args)... }};
193   } 193   }
194   194  
195   // reference to an array of format_args 195   // reference to an array of format_args
196   class format_args 196   class format_args
197   { 197   {
198   format_arg const* p_{nullptr}; 198   format_arg const* p_{nullptr};
199   std::size_t n_{0}; 199   std::size_t n_{0};
200   200  
201   public: 201   public:
HITCBC 202   6 format_args( 202   6 format_args(
203   detail::format_arg const* first, 203   detail::format_arg const* first,
204   detail::format_arg const* last ) noexcept 204   detail::format_arg const* last ) noexcept
HITCBC 205   6 : p_(first) 205   6 : p_(first)
HITCBC 206   6 , n_(static_cast<std::size_t>(last - first)) 206   6 , n_(static_cast<std::size_t>(last - first))
HITCBC 207   6 {} 207   6 {}
208   208  
209   template < std::size_t N > 209   template < std::size_t N >
HITCBC 210   159 format_args( std::array<format_arg, N> const& store ) noexcept 210   159 format_args( std::array<format_arg, N> const& store ) noexcept
HITCBC 211   159 : p_(store.data()) 211   159 : p_(store.data())
HITCBC 212   159 , n_(store.size()) 212   159 , n_(store.size())
HITCBC 213   159 {} 213   159 {}
214   214  
215   format_arg 215   format_arg
HITCBC 216   508 get( std::size_t i ) const noexcept 216   508 get( std::size_t i ) const noexcept
217   { 217   {
HITCBC 218   508 if (i < n_) 218   508 if (i < n_)
HITCBC 219   504 return p_[i]; 219   504 return p_[i];
HITCBC 220   4 return {}; 220   4 return {};
221   } 221   }
222   222  
223   format_arg 223   format_arg
HITCBC 224   96 get( core::string_view name ) const noexcept 224   96 get( core::string_view name ) const noexcept
225   { 225   {
HITCBC 226   226 for (std::size_t i = 0; i < n_; ++i) 226   226 for (std::size_t i = 0; i < n_; ++i)
227   { 227   {
HITCBC 228   224 if (p_[i].name() == name) 228   224 if (p_[i].name() == name)
HITCBC 229   94 return p_[i]; 229   94 return p_[i];
230   } 230   }
HITCBC 231   2 return {}; 231   2 return {};
232   } 232   }
233   }; 233   };
234   234  
235   // define the format_context after format_args 235   // define the format_context after format_args
236   class format_context 236   class format_context
237   { 237   {
238   format_args args_; 238   format_args args_;
239   char* out_; 239   char* out_;
240   240  
241   public: 241   public:
HITCBC 242   155 format_context( 242   155 format_context(
243   char* out, 243   char* out,
244   format_args args ) 244   format_args args )
HITCBC 245   155 : args_( args ) 245   155 : args_( args )
HITCBC 246   155 , out_( out ) 246   155 , out_( out )
HITCBC 247   155 {} 247   155 {}
248   248  
249   format_args 249   format_args
HITCBC 250   14 args() const noexcept 250   14 args() const noexcept
251   { 251   {
HITCBC 252   14 return args_; 252   14 return args_;
253   } 253   }
254   254  
255   format_arg 255   format_arg
HITCBC 256   243 arg( std::size_t id ) const noexcept 256   243 arg( std::size_t id ) const noexcept
257   { 257   {
HITCBC 258   243 return args_.get( id ); 258   243 return args_.get( id );
259   } 259   }
260   260  
261   format_arg 261   format_arg
HITCBC 262   43 arg( core::string_view name ) const noexcept 262   43 arg( core::string_view name ) const noexcept
263   { 263   {
HITCBC 264   43 return args_.get( name ); 264   43 return args_.get( name );
265   } 265   }
266   266  
267   char* 267   char*
HITCBC 268   1131 out() 268   1131 out()
269   { 269   {
HITCBC 270   1131 return out_; 270   1131 return out_;
271   } 271   }
272   272  
273   void 273   void
HITCBC 274   1131 advance_to( char* it ) 274   1131 advance_to( char* it )
275   { 275   {
HITCBC 276   1131 out_ = it; 276   1131 out_ = it;
HITCBC 277   1131 } 277   1131 }
278   }; 278   };
279   279  
280   // define the measure_context after format_args 280   // define the measure_context after format_args
281   class measure_context 281   class measure_context
282   { 282   {
283   format_args args_; 283   format_args args_;
284   std::size_t out_; 284   std::size_t out_;
285   285  
286   public: 286   public:
HITCBC 287   158 measure_context( 287   158 measure_context(
288   format_args args ) 288   format_args args )
HITCBC 289   158 : measure_context(0, args) 289   158 : measure_context(0, args)
HITCBC 290   158 {} 290   158 {}
291   291  
HITCBC 292   158 measure_context( 292   158 measure_context(
293   std::size_t out, 293   std::size_t out,
294   format_args args ) 294   format_args args )
HITCBC 295   158 : args_( args ) 295   158 : args_( args )
HITCBC 296   158 , out_( out ) 296   158 , out_( out )
HITCBC 297   158 {} 297   158 {}
298   298  
299   format_args 299   format_args
HITCBC 300   14 args() const noexcept 300   14 args() const noexcept
301   { 301   {
HITCBC 302   14 return args_; 302   14 return args_;
303   } 303   }
304   304  
305   format_arg 305   format_arg
HITCBC 306   247 arg( std::size_t id ) const noexcept 306   247 arg( std::size_t id ) const noexcept
307   { 307   {
HITCBC 308   247 return args_.get( id ); 308   247 return args_.get( id );
309   } 309   }
310   310  
311   format_arg 311   format_arg
HITCBC 312   43 arg( core::string_view name ) const noexcept 312   43 arg( core::string_view name ) const noexcept
313   { 313   {
HITCBC 314   43 return args_.get( name ); 314   43 return args_.get( name );
315   } 315   }
316   316  
317   std::size_t 317   std::size_t
HITCBC 318   1145 out() 318   1145 out()
319   { 319   {
HITCBC 320   1145 return out_; 320   1145 return out_;
321   } 321   }
322   322  
323   void 323   void
HITCBC 324   1145 advance_to( std::size_t n ) 324   1145 advance_to( std::size_t n )
325   { 325   {
HITCBC 326   1145 out_ = n; 326   1145 out_ = n;
HITCBC 327   1145 } 327   1145 }
328   }; 328   };
329   329  
330   // fwd declare the formatter 330   // fwd declare the formatter
331   template <class T, class = void> 331   template <class T, class = void>
332   struct formatter; 332   struct formatter;
333   333  
334   } // detail 334   } // detail
335   } // url 335   } // url
336   } // boost 336   } // boost
337   337  
338   #include <boost/url/detail/impl/format_args.hpp> 338   #include <boost/url/detail/impl/format_args.hpp>
339   339  
340   #endif 340   #endif