ゴミ箱
parser.hpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
8 //
9 
10 #ifndef BOOST_BEAST_HTTP_PARSER_HPP
11 #define BOOST_BEAST_HTTP_PARSER_HPP
12 
13 #include <boost/beast/config.hpp>
17 #include <boost/optional.hpp>
18 #include <boost/throw_exception.hpp>
19 #include <functional>
20 #include <memory>
21 #include <type_traits>
22 #include <utility>
23 
24 namespace boost {
25 namespace beast {
26 namespace http {
27 
45 template<
46  bool isRequest,
47  class Body,
48  class Allocator = std::allocator<char>>
49 class parser
50  : public basic_parser<isRequest,
51  parser<isRequest, Body, Allocator>>
52 {
53  static_assert(is_body<Body>::value,
54  "Body requirements not met");
55 
56  static_assert(is_body_writer<Body>::value,
57  "BodyWriter requirements not met");
58 
59  template<bool, class, class>
60  friend class parser;
61 
62  using base_type = basic_parser<isRequest,
64 
66  typename Body::writer wr_;
67  bool wr_inited_ = false;
68 
69  std::function<void(
70  std::uint64_t,
72  error_code&)> cb_h_;
73 
74  std::function<std::size_t(
75  std::uint64_t,
77  error_code&)> cb_b_;
78 
79 public:
81  using value_type =
83 
85  ~parser() = default;
86 
88  parser();
89 
91  parser(parser const&) = delete;
92 
94  parser& operator=(parser const&) = delete;
95 
101  parser(parser&& other) = default;
102 
112 #if BOOST_BEAST_DOXYGEN
113  template<class... Args>
114  explicit
115  parser(Args&&... args);
116 #else
117  template<class Arg1, class... ArgN,
118  class = typename std::enable_if<
119  ! detail::is_parser<typename
120  std::decay<Arg1>::type>::value>::type>
121  explicit
122  parser(Arg1&& arg1, ArgN&&... argn);
123 #endif
124 
156 #if BOOST_BEAST_DOXYGEN
157  template<class OtherBody, class... Args>
158 #else
159  template<class OtherBody, class... Args,
160  class = typename std::enable_if<
161  ! std::is_same<Body, OtherBody>::value>::type>
162 #endif
163  explicit
164  parser(parser<isRequest, OtherBody,
165  Allocator>&& parser, Args&&... args);
166 
172  value_type const&
173  get() const
174  {
175  return m_;
176  }
177 
183  value_type&
184  get()
185  {
186  return m_;
187  }
188 
199  value_type
201  {
202  static_assert(std::is_move_constructible<decltype(m_)>::value,
203  "MoveConstructible requirements not met");
204  return std::move(m_);
205  }
206 
241  template<class Callback>
242  void
243  on_chunk_header(Callback& cb)
244  {
245  // Callback may not be constant, caller is responsible for
246  // managing the lifetime of the callback. Copies are not made.
247  BOOST_STATIC_ASSERT(! std::is_const<Callback>::value);
248 
249  // Can't set the callback after receiving any chunk data!
250  BOOST_ASSERT(! wr_inited_);
251 
252  cb_h_ = std::ref(cb);
253  }
254 
289  template<class Callback>
290  void
291  on_chunk_body(Callback& cb)
292  {
293  // Callback may not be constant, caller is responsible for
294  // managing the lifetime of the callback. Copies are not made.
295  BOOST_STATIC_ASSERT(! std::is_const<Callback>::value);
296 
297  // Can't set the callback after receiving any chunk data!
298  BOOST_ASSERT(! wr_inited_);
299 
300  cb_b_ = std::ref(cb);
301  }
302 
303 private:
304  friend class basic_parser<isRequest, parser>;
305 
306  void
307  on_request_impl(
308  verb method,
309  string_view method_str,
310  string_view target,
311  int version,
312  error_code& ec)
313  {
314  try
315  {
316  m_.target(target);
317  if(method != verb::unknown)
318  m_.method(method);
319  else
320  m_.method_string(method_str);
321  ec.assign(0, ec.category());
322  }
323  catch(std::bad_alloc const&)
324  {
325  ec = error::bad_alloc;
326  }
327  m_.version = version;
328  }
329 
330  void
331  on_response_impl(
332  int code,
333  string_view reason,
334  int version,
335  error_code& ec)
336  {
337  m_.result(code);
338  m_.version = version;
339  try
340  {
341  m_.reason(reason);
342  ec.assign(0, ec.category());
343  }
344  catch(std::bad_alloc const&)
345  {
346  ec = error::bad_alloc;
347  }
348  }
349 
350  void
351  on_field_impl(
352  field name,
353  string_view name_string,
354  string_view value,
355  error_code& ec)
356  {
357  try
358  {
359  m_.insert(name, name_string, value);
360  ec.assign(0, ec.category());
361  }
362  catch(std::bad_alloc const&)
363  {
364  ec = error::bad_alloc;
365  }
366  }
367 
368  void
369  on_header_impl(error_code& ec)
370  {
371  ec.assign(0, ec.category());
372  }
373 
374  void
375  on_body_init_impl(
376  boost::optional<std::uint64_t> const& content_length,
377  error_code& ec)
378  {
379  wr_.init(content_length, ec);
380  wr_inited_ = true;
381  }
382 
383  std::size_t
384  on_body_impl(
385  string_view body,
386  error_code& ec)
387  {
388  return wr_.put(boost::asio::buffer(
389  body.data(), body.size()), ec);
390  }
391 
392  void
393  on_chunk_header_impl(
394  std::uint64_t size,
395  string_view extensions,
396  error_code& ec)
397  {
398  if(cb_h_)
399  return cb_h_(size, extensions, ec);
400  ec.assign(0, ec.category());
401  }
402 
403  std::size_t
404  on_chunk_body_impl(
405  std::uint64_t remain,
406  string_view body,
407  error_code& ec)
408  {
409  if(cb_b_)
410  return cb_b_(remain, body, ec);
411  return wr_.put(boost::asio::buffer(
412  body.data(), body.size()), ec);
413  }
414 
415  void
416  on_finish_impl(error_code& ec)
417  {
418  wr_.finish(ec);
419  }
420 };
421 
423 template<class Body, class Allocator = std::allocator<char>>
425 
427 template<class Body, class Allocator = std::allocator<char>>
429 
430 } // http
431 } // beast
432 } // boost
433 
435 
436 #endif
Definition: async_result.hpp:20
field
Definition: field.hpp:21
Definition: type_traits.hpp:25
void on_chunk_header(Callback &cb)
Definition: parser.hpp:243
verb
Definition: verb.hpp:26
Definition: beast_common.hpp:6
Definition: type_traits.hpp:125
boost::system::error_code error_code
The type of error code used by the library.
Definition: error.hpp:21
Definition: type_traits.hpp:47
parser()
Constructor.
Definition: parser.ipp:22
parser & operator=(parser const &)=delete
Assignment.
~parser()=default
Destructor.
Definition: type_traits.hpp:28
boost::string_ref string_view
The type of string view used by the library.
Definition: string.hpp:36
void on_chunk_body(Callback &cb)
Definition: parser.hpp:291
Definition: basic_parser.hpp:172
value_type release()
Definition: parser.hpp:200