File indexing completed on 2025-01-18 09:53:26
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_reference<A>::type;
0110 A const& ref = *static_cast<ref_t*>(
0111 const_cast<void*>( a ) );
0112 formatter<ref_t> f;
0113 pctx.advance_to( f.parse(pctx) );
0114 mctx.advance_to( f.measure( ref, mctx, cs ) );
0115 }
0116
0117 template <class A>
0118 void
0119 format_arg::
0120 format_impl(
0121 format_parse_context& pctx,
0122 format_context& fctx,
0123 grammar::lut_chars const& cs,
0124 void const* a )
0125 {
0126 using ref_t = typename std::remove_reference<A>::type;
0127 A const& ref = *static_cast<ref_t*>(
0128 const_cast<void*>( a ) );
0129 formatter<ref_t> f;
0130 pctx.advance_to( f.parse(pctx) );
0131 fctx.advance_to( f.format( ref, fctx, cs ) );
0132 }
0133
0134
0135
0136 template <>
0137 struct formatter<ignore_format>
0138 {
0139 public:
0140 char const*
0141 parse(format_parse_context& ctx) const
0142 {
0143 return parse_empty_spec(
0144 ctx.begin(), ctx.end());
0145 }
0146
0147 std::size_t
0148 measure(
0149 ignore_format,
0150 measure_context& ctx,
0151 grammar::lut_chars const&) const
0152 {
0153 return ctx.out();
0154 }
0155
0156 char*
0157 format(
0158 ignore_format,
0159 format_context& ctx,
0160 grammar::lut_chars const&) const
0161 {
0162 return ctx.out();
0163 }
0164
0165
0166
0167 static
0168 char const*
0169 parse_empty_spec(
0170 char const* it,
0171 char const* end)
0172 {
0173
0174 BOOST_ASSERT(it != end);
0175 ignore_unused(end);
0176
0177
0178 BOOST_ASSERT(*it == '}');
0179
0180
0181
0182
0183 return it;
0184 }
0185 };
0186
0187 inline
0188 std::size_t
0189 measure_one(
0190 char c,
0191 grammar::lut_chars const& unreserved)
0192 {
0193
0194 BOOST_ASSERT(! unreserved('%'));
0195 return 1 + !unreserved(c) * 2;
0196 }
0197
0198 inline
0199 void
0200 encode_one(
0201 char*& out,
0202 char c,
0203 grammar::lut_chars const& unreserved)
0204 {
0205
0206 BOOST_ASSERT(! unreserved('%'));
0207 if(unreserved(c))
0208 {
0209 *out++ = c;
0210 return;
0211 }
0212 *out++ = '%';
0213 *out++ = urls::detail::hexdigs[0][c>>4];
0214 *out++ = urls::detail::hexdigs[0][c&0xf];
0215 }
0216
0217
0218 BOOST_URL_DECL
0219 void
0220 get_width_from_args(
0221 std::size_t arg_idx,
0222 core::string_view arg_name,
0223 format_args args,
0224 std::size_t& w);
0225
0226
0227 template <>
0228 struct formatter<core::string_view>
0229 {
0230 private:
0231 char fill = ' ';
0232 char align = '\0';
0233 std::size_t width = 0;
0234 std::size_t width_idx = std::size_t(-1);
0235 core::string_view width_name;
0236
0237 public:
0238 BOOST_URL_DECL
0239 char const*
0240 parse(format_parse_context& ctx);
0241
0242 BOOST_URL_DECL
0243 std::size_t
0244 measure(
0245 core::string_view str,
0246 measure_context& ctx,
0247 grammar::lut_chars const& cs) const;
0248
0249 BOOST_URL_DECL
0250 char*
0251 format(
0252 core::string_view str,
0253 format_context& ctx,
0254 grammar::lut_chars const& cs) const;
0255 };
0256
0257
0258
0259 template <class T>
0260 struct formatter<
0261 T, typename std::enable_if<
0262 std::is_convertible<
0263 T, core::string_view>::value>::type>
0264 {
0265 formatter<core::string_view> impl_;
0266
0267 public:
0268 char const*
0269 parse(format_parse_context& ctx)
0270 {
0271 return impl_.parse(ctx);
0272 }
0273
0274 std::size_t
0275 measure(
0276 core::string_view str,
0277 measure_context& ctx,
0278 grammar::lut_chars const& cs) const
0279 {
0280 return impl_.measure(str, ctx, cs);
0281 }
0282
0283 char*
0284 format(core::string_view str, format_context& ctx, grammar::lut_chars const& cs) const
0285 {
0286 return impl_.format(str, ctx, cs);
0287 }
0288 };
0289
0290 template <>
0291 struct formatter<char>
0292 {
0293 formatter<core::string_view> impl_;
0294
0295 public:
0296 char const*
0297 parse(format_parse_context& ctx)
0298 {
0299 return impl_.parse(ctx);
0300 }
0301
0302 std::size_t
0303 measure(
0304 char c,
0305 measure_context& ctx,
0306 grammar::lut_chars const& cs) const
0307 {
0308 return impl_.measure({&c, 1}, ctx, cs);
0309 }
0310
0311 char*
0312 format(
0313 char c,
0314 format_context& ctx,
0315 grammar::lut_chars const& cs) const
0316 {
0317 return impl_.format({&c, 1}, ctx, cs);
0318 }
0319 };
0320
0321
0322 class integer_formatter_impl
0323 {
0324 char fill = ' ';
0325 char align = '\0';
0326 char sign = '-';
0327 bool zeros = false;
0328 std::size_t width = 0;
0329 std::size_t width_idx = std::size_t(-1);
0330 core::string_view width_name;
0331
0332 public:
0333 BOOST_URL_DECL
0334 char const*
0335 parse(format_parse_context& ctx);
0336
0337 BOOST_URL_DECL
0338 std::size_t
0339 measure(
0340 unsigned long long int v,
0341 measure_context& ctx,
0342 grammar::lut_chars const& cs) const;
0343
0344 BOOST_URL_DECL
0345 std::size_t
0346 measure(
0347 long long int v,
0348 measure_context& ctx,
0349 grammar::lut_chars const& cs) const;
0350
0351 BOOST_URL_DECL
0352 char*
0353 format(
0354 unsigned long long int v,
0355 format_context& ctx,
0356 grammar::lut_chars const& cs) const;
0357
0358 BOOST_URL_DECL
0359 char*
0360 format(
0361 long long int v,
0362 format_context& ctx,
0363 grammar::lut_chars const& cs) const;
0364 };
0365
0366 template <class T>
0367 struct formatter<
0368 T, typename std::enable_if<
0369 mp11::mp_contains<mp11::mp_list<
0370 short int,
0371 int,
0372 long int,
0373 long long int,
0374 unsigned short int,
0375 unsigned int,
0376 unsigned long int,
0377 unsigned long long int>, T>::value>::type>
0378 {
0379 private:
0380 integer_formatter_impl impl_;
0381 using base_value_type = typename std::conditional<
0382 std::is_unsigned<T>::value,
0383 unsigned long long int,
0384 long long int
0385 >::type;
0386
0387 public:
0388 char const*
0389 parse(format_parse_context& ctx)
0390 {
0391 return impl_.parse(ctx);
0392 }
0393
0394 std::size_t
0395 measure(
0396 T v,
0397 measure_context& ctx,
0398 grammar::lut_chars const& cs) const
0399 {
0400 return impl_.measure(
0401 static_cast<base_value_type>(v), ctx, cs);
0402 }
0403
0404 char*
0405 format(T v, format_context& ctx, grammar::lut_chars const& cs) const
0406 {
0407 return impl_.format(
0408 static_cast<base_value_type>(v), ctx, cs);
0409 }
0410 };
0411
0412 }
0413 }
0414 }
0415
0416 #endif