File indexing completed on 2025-01-18 09:53:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_URL_DETAIL_FORMAT_ARGS_HPP
0011 #define BOOST_URL_DETAIL_FORMAT_ARGS_HPP
0012
0013 #include <boost/url/detail/encode.hpp>
0014 #include <boost/url/grammar/lut_chars.hpp>
0015
0016 #include <boost/core/ignore_unused.hpp>
0017 #include <array>
0018
0019
0020
0021
0022 namespace boost {
0023 namespace urls {
0024 namespace detail {
0025
0026
0027
0028 class format_parse_context
0029 {
0030 char const* begin_;
0031 char const* end_;
0032 std::size_t arg_id_ = 0;
0033
0034 public:
0035 constexpr
0036 format_parse_context(
0037 char const* first,
0038 char const* last,
0039 std::size_t arg_id = 0)
0040 : begin_( first )
0041 , end_( last )
0042 , arg_id_( arg_id )
0043 {}
0044
0045 constexpr
0046 format_parse_context(
0047 core::string_view fmt,
0048 std::size_t arg_id = 0)
0049 : format_parse_context(
0050 fmt.data(),
0051 fmt.data() + fmt.size(),
0052 arg_id )
0053 {}
0054
0055 constexpr
0056 char const*
0057 begin() const noexcept
0058 {
0059 return begin_;
0060 }
0061
0062 constexpr
0063 char const*
0064 end() const noexcept
0065 {
0066 return end_;
0067 }
0068
0069 BOOST_CXX14_CONSTEXPR
0070 void
0071 advance_to( char const* it )
0072 {
0073 begin_ = it;
0074 }
0075
0076 std::size_t
0077 next_arg_id()
0078 {
0079 return arg_id_++;
0080 }
0081 };
0082
0083
0084 class format_context;
0085 class measure_context;
0086 struct ignore_format {};
0087
0088 template <class T>
0089 struct named_arg
0090 {
0091 core::string_view name;
0092 T const& value;
0093
0094 named_arg(core::string_view n, T const& v)
0095 : name(n)
0096 , value(v)
0097 {}
0098 };
0099
0100
0101 class format_arg
0102 {
0103 void const* arg_;
0104 void (*measure_)(
0105 format_parse_context&,
0106 measure_context&,
0107 grammar::lut_chars const&,
0108 void const* );
0109 void (*fmt_)(
0110 format_parse_context&,
0111 format_context&,
0112 grammar::lut_chars const&,
0113 void const* );
0114 core::string_view name_;
0115 std::size_t value_ = 0;
0116 bool ignore_ = false;
0117
0118 template <class A>
0119 static
0120 void
0121 measure_impl(
0122 format_parse_context& pctx,
0123 measure_context& mctx,
0124 grammar::lut_chars const& cs,
0125 void const* a );
0126
0127 template <class A>
0128 static
0129 void
0130 format_impl(
0131 format_parse_context& pctx,
0132 format_context& fctx,
0133 grammar::lut_chars const& cs,
0134 void const* a );
0135
0136 public:
0137 template<class A>
0138 format_arg( A&& a );
0139
0140 template<class A>
0141 format_arg( named_arg<A>&& a );
0142
0143 template<class A>
0144 format_arg( core::string_view name, A&& a );
0145
0146 format_arg()
0147 : format_arg(ignore_format{})
0148 {}
0149
0150 explicit
0151 operator bool() const noexcept
0152 {
0153 return !ignore_;
0154 }
0155
0156 void
0157 measure(
0158 format_parse_context& pctx,
0159 measure_context& mctx,
0160 grammar::lut_chars const& cs)
0161 {
0162 measure_( pctx, mctx, cs, arg_ );
0163 }
0164
0165 void
0166 format(
0167 format_parse_context& pctx,
0168 format_context& fctx,
0169 grammar::lut_chars const& cs )
0170 {
0171 fmt_( pctx, fctx, cs, arg_ );
0172 }
0173
0174 core::string_view
0175 name() const
0176 {
0177 return name_;
0178 }
0179
0180 std::size_t
0181 value() const
0182 {
0183 return value_;
0184 }
0185 };
0186
0187
0188 template< class... Args >
0189 std::array<format_arg, sizeof...(Args)>
0190 make_format_args( Args&&... args )
0191 {
0192 return {{ std::forward<Args>(args)... }};
0193 }
0194
0195
0196 class format_args
0197 {
0198 format_arg const* p_{nullptr};
0199 std::size_t n_{0};
0200
0201 public:
0202 format_args(
0203 detail::format_arg const* first,
0204 detail::format_arg const* last ) noexcept
0205 : p_(first)
0206 , n_(static_cast<std::size_t>(last - first))
0207 {}
0208
0209 template < std::size_t N >
0210 format_args( std::array<format_arg, N> const& store ) noexcept
0211 : p_(store.data())
0212 , n_(store.size())
0213 {}
0214
0215 format_arg
0216 get( std::size_t i ) const noexcept
0217 {
0218 if (i < n_)
0219 return p_[i];
0220 return {};
0221 }
0222
0223 format_arg
0224 get( core::string_view name ) const noexcept
0225 {
0226 for (std::size_t i = 0; i < n_; ++i)
0227 {
0228 if (p_[i].name() == name)
0229 return p_[i];
0230 }
0231 return {};
0232 }
0233 };
0234
0235
0236 class format_context
0237 {
0238 format_args args_;
0239 char* out_;
0240
0241 public:
0242 format_context(
0243 char* out,
0244 format_args args )
0245 : args_( args )
0246 , out_( out )
0247 {}
0248
0249 format_args
0250 args() const noexcept
0251 {
0252 return args_;
0253 }
0254
0255 format_arg
0256 arg( std::size_t id ) const noexcept
0257 {
0258 return args_.get( id );
0259 }
0260
0261 format_arg
0262 arg( core::string_view name ) const noexcept
0263 {
0264 return args_.get( name );
0265 }
0266
0267 char*
0268 out()
0269 {
0270 return out_;
0271 }
0272
0273 void
0274 advance_to( char* it )
0275 {
0276 out_ = it;
0277 }
0278 };
0279
0280
0281 class measure_context
0282 {
0283 format_args args_;
0284 std::size_t out_;
0285
0286 public:
0287 measure_context(
0288 format_args args )
0289 : measure_context(0, args)
0290 {}
0291
0292 measure_context(
0293 std::size_t out,
0294 format_args args )
0295 : args_( args )
0296 , out_( out )
0297 {}
0298
0299 format_args
0300 args() const noexcept
0301 {
0302 return args_;
0303 }
0304
0305 format_arg
0306 arg( std::size_t id ) const noexcept
0307 {
0308 return args_.get( id );
0309 }
0310
0311 format_arg
0312 arg( core::string_view name ) const noexcept
0313 {
0314 return args_.get( name );
0315 }
0316
0317 std::size_t
0318 out()
0319 {
0320 return out_;
0321 }
0322
0323 void
0324 advance_to( std::size_t n )
0325 {
0326 out_ = n;
0327 }
0328 };
0329
0330
0331 template <class T, class = void>
0332 struct formatter;
0333
0334 }
0335 }
0336 }
0337
0338 #include <boost/url/detail/impl/format_args.hpp>
0339
0340 #endif