File indexing completed on 2025-07-14 08:48:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_URL_DETAIL_IMPL_FORMAT_ARGS_HPP
0011 #define BOOST_URL_DETAIL_IMPL_FORMAT_ARGS_HPP
0012
0013 namespace boost {
0014 namespace urls {
0015 namespace detail {
0016
0017 template<
0018 class A,
0019 typename std::enable_if<
0020 !std::is_integral<
0021 typename std::decay<A>::type>::value,
0022 int>::type = 0>
0023 std::size_t
0024 get_uvalue( A&& )
0025 {
0026 return 0;
0027 }
0028
0029 template<
0030 class A,
0031 typename std::enable_if<
0032 std::is_integral<
0033 typename std::decay<A>::type>::value &&
0034 std::is_signed<
0035 typename std::decay<A>::type>::value,
0036 int>::type = 0>
0037 std::size_t
0038 get_uvalue( A&& a )
0039 {
0040 if (a > 0)
0041 return static_cast<std::size_t>(a);
0042 return 0;
0043 }
0044
0045 template<
0046 class A,
0047 typename std::enable_if<
0048 std::is_integral<
0049 typename std::decay<A>::type>::value &&
0050 std::is_unsigned<
0051 typename std::decay<A>::type>::value,
0052 int>::type = 0>
0053 std::size_t
0054 get_uvalue( A&& a )
0055 {
0056 return static_cast<std::size_t>(a);
0057 }
0058
0059 BOOST_URL_DECL
0060 std::size_t
0061 get_uvalue( core::string_view a );
0062
0063 BOOST_URL_DECL
0064 std::size_t
0065 get_uvalue( char a );
0066
0067 template<class A>
0068 format_arg::
0069 format_arg( A&& a )
0070 : arg_( &a )
0071 , measure_( &measure_impl<A> )
0072 , fmt_( &format_impl<A> )
0073 , value_( get_uvalue(std::forward<A>(a) ))
0074 , ignore_( std::is_same<A, ignore_format>::value )
0075 {}
0076
0077 template<class A>
0078 format_arg::
0079 format_arg( named_arg<A>&& a )
0080 : arg_( &a.value )
0081 , measure_( &measure_impl<A> )
0082 , fmt_( &format_impl<A> )
0083 , name_( a.name )
0084 , value_( get_uvalue(a.value))
0085 {}
0086
0087 template<class A>
0088 format_arg::
0089 format_arg( core::string_view name, A&& a )
0090 : arg_( &a )
0091 , measure_( &measure_impl<A> )
0092 , fmt_( &format_impl<A> )
0093 , name_( name )
0094 , value_( get_uvalue(a) )
0095 {}
0096
0097
0098
0099
0100 template <class A>
0101 void
0102 format_arg::
0103 measure_impl(
0104 format_parse_context& pctx,
0105 measure_context& mctx,
0106 grammar::lut_chars const& cs,
0107 void const* a )
0108 {
0109 using ref_t = typename std::remove_cv<
0110 typename std::remove_reference<A>::type>::type;
0111 A const& ref = *static_cast<ref_t*>(
0112 const_cast<void*>( a ) );
0113 formatter<ref_t> f;
0114 pctx.advance_to( f.parse(pctx) );
0115 mctx.advance_to( f.measure( ref, mctx, cs ) );
0116 }
0117
0118 template <class A>
0119 void
0120 format_arg::
0121 format_impl(
0122 format_parse_context& pctx,
0123 format_context& fctx,
0124 grammar::lut_chars const& cs,
0125 void const* a )
0126 {
0127 using ref_t = typename std::remove_cv<
0128 typename std::remove_reference<A>::type>::type;
0129 A const& ref = *static_cast<ref_t*>(
0130 const_cast<void*>( a ) );
0131 formatter<ref_t> f;
0132 pctx.advance_to( f.parse(pctx) );
0133 fctx.advance_to( f.format( ref, fctx, cs ) );
0134 }
0135
0136
0137
0138 template <>
0139 struct formatter<ignore_format>
0140 {
0141 public:
0142 char const*
0143 parse(format_parse_context& ctx) const
0144 {
0145 return parse_empty_spec(
0146 ctx.begin(), ctx.end());
0147 }
0148
0149 std::size_t
0150 measure(
0151 ignore_format,
0152 measure_context& ctx,
0153 grammar::lut_chars const&) const
0154 {
0155 return ctx.out();
0156 }
0157
0158 char*
0159 format(
0160 ignore_format,
0161 format_context& ctx,
0162 grammar::lut_chars const&) const
0163 {
0164 return ctx.out();
0165 }
0166
0167
0168
0169 static
0170 char const*
0171 parse_empty_spec(
0172 char const* it,
0173 char const* end)
0174 {
0175
0176 BOOST_ASSERT(it != end);
0177 ignore_unused(end);
0178
0179
0180 BOOST_ASSERT(*it == '}');
0181
0182
0183
0184
0185 return it;
0186 }
0187 };
0188
0189 inline
0190 std::size_t
0191 measure_one(
0192 char c,
0193 grammar::lut_chars const& unreserved)
0194 {
0195
0196 BOOST_ASSERT(! unreserved('%'));
0197 return 1 + !unreserved(c) * 2;
0198 }
0199
0200 inline
0201 void
0202 encode_one(
0203 char*& out,
0204 char c,
0205 grammar::lut_chars const& unreserved)
0206 {
0207
0208 BOOST_ASSERT(! unreserved('%'));
0209 if(unreserved(c))
0210 {
0211 *out++ = c;
0212 return;
0213 }
0214 *out++ = '%';
0215 *out++ = urls::detail::hexdigs[0][c>>4];
0216 *out++ = urls::detail::hexdigs[0][c&0xf];
0217 }
0218
0219
0220 BOOST_URL_DECL
0221 void
0222 get_width_from_args(
0223 std::size_t arg_idx,
0224 core::string_view arg_name,
0225 format_args args,
0226 std::size_t& w);
0227
0228
0229 template <>
0230 struct formatter<core::string_view>
0231 {
0232 private:
0233 char fill = ' ';
0234 char align = '\0';
0235 std::size_t width = 0;
0236 std::size_t width_idx = std::size_t(-1);
0237 core::string_view width_name;
0238
0239 public:
0240 BOOST_URL_DECL
0241 char const*
0242 parse(format_parse_context& ctx);
0243
0244 BOOST_URL_DECL
0245 std::size_t
0246 measure(
0247 core::string_view str,
0248 measure_context& ctx,
0249 grammar::lut_chars const& cs) const;
0250
0251 BOOST_URL_DECL
0252 char*
0253 format(
0254 core::string_view str,
0255 format_context& ctx,
0256 grammar::lut_chars const& cs) const;
0257 };
0258
0259
0260
0261 template <class T>
0262 struct formatter<
0263 T, typename std::enable_if<
0264 std::is_convertible<
0265 T, core::string_view>::value>::type>
0266 {
0267 formatter<core::string_view> impl_;
0268
0269 public:
0270 char const*
0271 parse(format_parse_context& ctx)
0272 {
0273 return impl_.parse(ctx);
0274 }
0275
0276 std::size_t
0277 measure(
0278 core::string_view str,
0279 measure_context& ctx,
0280 grammar::lut_chars const& cs) const
0281 {
0282 return impl_.measure(str, ctx, cs);
0283 }
0284
0285 char*
0286 format(core::string_view str, format_context& ctx, grammar::lut_chars const& cs) const
0287 {
0288 return impl_.format(str, ctx, cs);
0289 }
0290 };
0291
0292 template <>
0293 struct formatter<char>
0294 {
0295 formatter<core::string_view> impl_;
0296
0297 public:
0298 char const*
0299 parse(format_parse_context& ctx)
0300 {
0301 return impl_.parse(ctx);
0302 }
0303
0304 std::size_t
0305 measure(
0306 char c,
0307 measure_context& ctx,
0308 grammar::lut_chars const& cs) const
0309 {
0310 return impl_.measure({&c, 1}, ctx, cs);
0311 }
0312
0313 char*
0314 format(
0315 char c,
0316 format_context& ctx,
0317 grammar::lut_chars const& cs) const
0318 {
0319 return impl_.format({&c, 1}, ctx, cs);
0320 }
0321 };
0322
0323
0324 class integer_formatter_impl
0325 {
0326 char fill = ' ';
0327 char align = '\0';
0328 char sign = '-';
0329 bool zeros = false;
0330 std::size_t width = 0;
0331 std::size_t width_idx = std::size_t(-1);
0332 core::string_view width_name;
0333
0334 public:
0335 BOOST_URL_DECL
0336 char const*
0337 parse(format_parse_context& ctx);
0338
0339 BOOST_URL_DECL
0340 std::size_t
0341 measure(
0342 unsigned long long int v,
0343 measure_context& ctx,
0344 grammar::lut_chars const& cs) const;
0345
0346 BOOST_URL_DECL
0347 std::size_t
0348 measure(
0349 long long int v,
0350 measure_context& ctx,
0351 grammar::lut_chars const& cs) const;
0352
0353 BOOST_URL_DECL
0354 char*
0355 format(
0356 unsigned long long int v,
0357 format_context& ctx,
0358 grammar::lut_chars const& cs) const;
0359
0360 BOOST_URL_DECL
0361 char*
0362 format(
0363 long long int v,
0364 format_context& ctx,
0365 grammar::lut_chars const& cs) const;
0366 };
0367
0368 template <class T>
0369 struct formatter<
0370 T, typename std::enable_if<
0371 mp11::mp_contains<mp11::mp_list<
0372 short int,
0373 int,
0374 long int,
0375 long long int,
0376 unsigned short int,
0377 unsigned int,
0378 unsigned long int,
0379 unsigned long long int>, T>::value>::type>
0380 {
0381 private:
0382 integer_formatter_impl impl_;
0383 using base_value_type = typename std::conditional<
0384 std::is_unsigned<T>::value,
0385 unsigned long long int,
0386 long long int
0387 >::type;
0388
0389 public:
0390 char const*
0391 parse(format_parse_context& ctx)
0392 {
0393 return impl_.parse(ctx);
0394 }
0395
0396 std::size_t
0397 measure(
0398 T v,
0399 measure_context& ctx,
0400 grammar::lut_chars const& cs) const
0401 {
0402 return impl_.measure(
0403 static_cast<base_value_type>(v), ctx, cs);
0404 }
0405
0406 char*
0407 format(T v, format_context& ctx, grammar::lut_chars const& cs) const
0408 {
0409 return impl_.format(
0410 static_cast<base_value_type>(v), ctx, cs);
0411 }
0412 };
0413
0414 }
0415 }
0416 }
0417
0418 #endif