summaryrefslogtreecommitdiff
path: root/boost/beast/http/impl/rfc7230.ipp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/beast/http/impl/rfc7230.ipp')
-rw-r--r--boost/beast/http/impl/rfc7230.ipp572
1 files changed, 572 insertions, 0 deletions
diff --git a/boost/beast/http/impl/rfc7230.ipp b/boost/beast/http/impl/rfc7230.ipp
new file mode 100644
index 0000000000..96ec902ceb
--- /dev/null
+++ b/boost/beast/http/impl/rfc7230.ipp
@@ -0,0 +1,572 @@
+//
+// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Official repository: https://github.com/boostorg/beast
+//
+
+#ifndef BOOST_BEAST_HTTP_IMPL_RFC7230_IPP
+#define BOOST_BEAST_HTTP_IMPL_RFC7230_IPP
+
+#include <boost/beast/http/detail/rfc7230.hpp>
+#include <iterator>
+
+namespace boost {
+namespace beast {
+namespace http {
+
+class param_list::const_iterator
+{
+ using iter_type = string_view::const_iterator;
+
+ std::string s_;
+ detail::param_iter pi_;
+
+public:
+ using value_type = param_list::value_type;
+ using pointer = value_type const*;
+ using reference = value_type const&;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::input_iterator_tag;
+
+ const_iterator() = default;
+
+ bool
+ operator==(const_iterator const& other) const
+ {
+ return
+ other.pi_.it == pi_.it &&
+ other.pi_.last == pi_.last &&
+ other.pi_.first == pi_.first;
+ }
+
+ bool
+ operator!=(const_iterator const& other) const
+ {
+ return !(*this == other);
+ }
+
+ reference
+ operator*() const
+ {
+ return pi_.v;
+ }
+
+ pointer
+ operator->() const
+ {
+ return &*(*this);
+ }
+
+ const_iterator&
+ operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ const_iterator
+ operator++(int)
+ {
+ auto temp = *this;
+ ++(*this);
+ return temp;
+ }
+
+private:
+ friend class param_list;
+
+ const_iterator(iter_type first, iter_type last)
+ {
+ pi_.it = first;
+ pi_.first = first;
+ pi_.last = last;
+ increment();
+ }
+
+ template<class = void>
+ static
+ std::string
+ unquote(string_view sr);
+
+ template<class = void>
+ void
+ increment();
+};
+
+inline
+auto
+param_list::
+begin() const ->
+ const_iterator
+{
+ return const_iterator{s_.begin(), s_.end()};
+}
+
+inline
+auto
+param_list::
+end() const ->
+ const_iterator
+{
+ return const_iterator{s_.end(), s_.end()};
+}
+
+inline
+auto
+param_list::
+cbegin() const ->
+ const_iterator
+{
+ return const_iterator{s_.begin(), s_.end()};
+}
+
+inline
+auto
+param_list::
+cend() const ->
+ const_iterator
+{
+ return const_iterator{s_.end(), s_.end()};
+}
+
+template<class>
+std::string
+param_list::const_iterator::
+unquote(string_view sr)
+{
+ std::string s;
+ s.reserve(sr.size());
+ auto it = sr.begin() + 1;
+ auto end = sr.end() - 1;
+ while(it != end)
+ {
+ if(*it == '\\')
+ ++it;
+ s.push_back(*it);
+ ++it;
+ }
+ return s;
+}
+
+template<class>
+void
+param_list::const_iterator::
+increment()
+{
+ s_.clear();
+ pi_.increment();
+ if(pi_.empty())
+ {
+ pi_.it = pi_.last;
+ pi_.first = pi_.last;
+ }
+ else if(! pi_.v.second.empty() &&
+ pi_.v.second.front() == '"')
+ {
+ s_ = unquote(pi_.v.second);
+ pi_.v.second = string_view{
+ s_.data(), s_.size()};
+ }
+}
+
+//------------------------------------------------------------------------------
+
+class ext_list::const_iterator
+{
+ ext_list::value_type v_;
+ iter_type it_;
+ iter_type first_;
+ iter_type last_;
+
+public:
+ using value_type = ext_list::value_type;
+ using pointer = value_type const*;
+ using reference = value_type const&;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::forward_iterator_tag;
+
+ const_iterator() = default;
+
+ bool
+ operator==(const_iterator const& other) const
+ {
+ return
+ other.it_ == it_ &&
+ other.first_ == first_ &&
+ other.last_ == last_;
+ }
+
+ bool
+ operator!=(const_iterator const& other) const
+ {
+ return !(*this == other);
+ }
+
+ reference
+ operator*() const
+ {
+ return v_;
+ }
+
+ pointer
+ operator->() const
+ {
+ return &*(*this);
+ }
+
+ const_iterator&
+ operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ const_iterator
+ operator++(int)
+ {
+ auto temp = *this;
+ ++(*this);
+ return temp;
+ }
+
+private:
+ friend class ext_list;
+
+ const_iterator(iter_type begin, iter_type end)
+ {
+ it_ = begin;
+ first_ = begin;
+ last_ = end;
+ increment();
+ }
+
+ template<class = void>
+ void
+ increment();
+};
+
+inline
+auto
+ext_list::
+begin() const ->
+ const_iterator
+{
+ return const_iterator{s_.begin(), s_.end()};
+}
+
+inline
+auto
+ext_list::
+end() const ->
+ const_iterator
+{
+ return const_iterator{s_.end(), s_.end()};
+}
+
+inline
+auto
+ext_list::
+cbegin() const ->
+ const_iterator
+{
+ return const_iterator{s_.begin(), s_.end()};
+}
+
+inline
+auto
+ext_list::
+cend() const ->
+ const_iterator
+{
+ return const_iterator{s_.end(), s_.end()};
+}
+
+template<class T>
+auto
+ext_list::
+find(T const& s) ->
+ const_iterator
+{
+ return std::find_if(begin(), end(),
+ [&s](value_type const& v)
+ {
+ return iequals(s, v.first);
+ });
+}
+
+template<class T>
+bool
+ext_list::
+exists(T const& s)
+{
+ return find(s) != end();
+}
+
+template<class>
+void
+ext_list::const_iterator::
+increment()
+{
+ /*
+ ext-list = *( "," OWS ) ext *( OWS "," [ OWS ext ] )
+ ext = token param-list
+ param-list = *( OWS ";" OWS param )
+ param = token OWS "=" OWS ( token / quoted-string )
+
+ chunked;a=b;i=j,gzip;windowBits=12
+ x,y
+ ,,,,,chameleon
+ */
+ auto const err =
+ [&]
+ {
+ it_ = last_;
+ first_ = last_;
+ };
+ auto need_comma = it_ != first_;
+ v_.first = {};
+ first_ = it_;
+ for(;;)
+ {
+ detail::skip_ows(it_, last_);
+ if(it_ == last_)
+ return err();
+ auto const c = *it_;
+ if(detail::is_token_char(c))
+ {
+ if(need_comma)
+ return err();
+ auto const p0 = it_;
+ for(;;)
+ {
+ ++it_;
+ if(it_ == last_)
+ break;
+ if(! detail::is_token_char(*it_))
+ break;
+ }
+ v_.first = string_view{&*p0,
+ static_cast<std::size_t>(it_ - p0)};
+ detail::param_iter pi;
+ pi.it = it_;
+ pi.first = it_;
+ pi.last = last_;
+ for(;;)
+ {
+ pi.increment();
+ if(pi.empty())
+ break;
+ }
+ v_.second = param_list{string_view{&*it_,
+ static_cast<std::size_t>(pi.it - it_)}};
+ it_ = pi.it;
+ return;
+ }
+ if(c != ',')
+ return err();
+ need_comma = false;
+ ++it_;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+class token_list::const_iterator
+{
+ token_list::value_type v_;
+ iter_type it_;
+ iter_type first_;
+ iter_type last_;
+
+public:
+ using value_type = token_list::value_type;
+ using pointer = value_type const*;
+ using reference = value_type const&;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::forward_iterator_tag;
+
+ const_iterator() = default;
+
+ bool
+ operator==(const_iterator const& other) const
+ {
+ return
+ other.it_ == it_ &&
+ other.first_ == first_ &&
+ other.last_ == last_;
+ }
+
+ bool
+ operator!=(const_iterator const& other) const
+ {
+ return !(*this == other);
+ }
+
+ reference
+ operator*() const
+ {
+ return v_;
+ }
+
+ pointer
+ operator->() const
+ {
+ return &*(*this);
+ }
+
+ const_iterator&
+ operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ const_iterator
+ operator++(int)
+ {
+ auto temp = *this;
+ ++(*this);
+ return temp;
+ }
+
+private:
+ friend class token_list;
+
+ const_iterator(iter_type begin, iter_type end)
+ {
+ it_ = begin;
+ first_ = begin;
+ last_ = end;
+ increment();
+ }
+
+ template<class = void>
+ void
+ increment();
+};
+
+inline
+auto
+token_list::
+begin() const ->
+ const_iterator
+{
+ return const_iterator{s_.begin(), s_.end()};
+}
+
+inline
+auto
+token_list::
+end() const ->
+ const_iterator
+{
+ return const_iterator{s_.end(), s_.end()};
+}
+
+inline
+auto
+token_list::
+cbegin() const ->
+ const_iterator
+{
+ return const_iterator{s_.begin(), s_.end()};
+}
+
+inline
+auto
+token_list::
+cend() const ->
+ const_iterator
+{
+ return const_iterator{s_.end(), s_.end()};
+}
+
+template<class>
+void
+token_list::const_iterator::
+increment()
+{
+ /*
+ token-list = *( "," OWS ) token *( OWS "," [ OWS ext ] )
+ */
+ auto const err =
+ [&]
+ {
+ it_ = last_;
+ first_ = last_;
+ };
+ auto need_comma = it_ != first_;
+ v_ = {};
+ first_ = it_;
+ for(;;)
+ {
+ detail::skip_ows(it_, last_);
+ if(it_ == last_)
+ return err();
+ auto const c = *it_;
+ if(detail::is_token_char(c))
+ {
+ if(need_comma)
+ return err();
+ auto const p0 = it_;
+ for(;;)
+ {
+ ++it_;
+ if(it_ == last_)
+ break;
+ if(! detail::is_token_char(*it_))
+ break;
+ }
+ v_ = string_view{&*p0,
+ static_cast<std::size_t>(it_ - p0)};
+ return;
+ }
+ if(c != ',')
+ return err();
+ need_comma = false;
+ ++it_;
+ }
+}
+
+template<class T>
+bool
+token_list::
+exists(T const& s)
+{
+ return std::find_if(begin(), end(),
+ [&s](value_type const& v)
+ {
+ return iequals(s, v);
+ }
+ ) != end();
+}
+
+template<class Policy>
+bool
+validate_list(detail::basic_parsed_list<
+ Policy> const& list)
+{
+ auto const last = list.end();
+ auto it = list.begin();
+ if(it.error())
+ return false;
+ while(it != last)
+ {
+ ++it;
+ if(it.error())
+ return false;
+ if(it == last)
+ break;
+ }
+ return true;
+}
+
+} // http
+} // beast
+} // boost
+
+#endif
+