mirror of
https://github.com/boostorg/url.git
synced 2026-02-13 12:52:14 +00:00
segments refactoring
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include <boost/url/pct_encoding_types.hpp>
|
||||
#include <boost/url/query_params_view.hpp>
|
||||
#include <boost/url/scheme.hpp>
|
||||
#include <boost/url/segments.hpp>
|
||||
#include <boost/url/segments_encoded.hpp>
|
||||
#include <boost/url/segments_encoded_view.hpp>
|
||||
#include <boost/url/segments_view.hpp>
|
||||
|
||||
34
include/boost/url/arrow_proxy.hpp
Normal file
34
include/boost/url/arrow_proxy.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/CPPAlliance/url
|
||||
//
|
||||
|
||||
#ifndef BOOST_URL_ARROW_PROXY_HPP
|
||||
#define BOOST_URL_ARROW_PROXY_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
// https://quuxplusone.github.io/blog/2019/02/06/arrow-proxy/
|
||||
|
||||
template<class T>
|
||||
struct arrow_proxy
|
||||
{
|
||||
T t;
|
||||
|
||||
T *operator->() noexcept
|
||||
{
|
||||
return &t;
|
||||
}
|
||||
};
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
@@ -169,6 +169,73 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
class plain_segs_iter_base
|
||||
{
|
||||
protected:
|
||||
BOOST_URL_DECL
|
||||
static
|
||||
void
|
||||
measure_impl(
|
||||
string_view s,
|
||||
std::size_t& n) noexcept;
|
||||
|
||||
BOOST_URL_DECL
|
||||
static
|
||||
void
|
||||
copy_impl(
|
||||
string_view s,
|
||||
char*& dest,
|
||||
char const* end) noexcept;
|
||||
};
|
||||
|
||||
// iterates segments in an
|
||||
// encoded segment range
|
||||
template<class FwdIt>
|
||||
class plain_segs_iter
|
||||
: public any_path_iter
|
||||
, public plain_segs_iter_base
|
||||
{
|
||||
FwdIt it_;
|
||||
FwdIt end_;
|
||||
|
||||
public:
|
||||
plain_segs_iter(
|
||||
FwdIt first,
|
||||
FwdIt last) noexcept
|
||||
: it_(first)
|
||||
, end_(last)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
measure(
|
||||
std::size_t& n,
|
||||
error_code&
|
||||
) noexcept override
|
||||
{
|
||||
if(it_ == end_)
|
||||
return false;
|
||||
measure_impl(*it_, n);
|
||||
++it_;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
copy(
|
||||
char*& dest,
|
||||
char const* end
|
||||
) noexcept override
|
||||
{
|
||||
copy_impl(*it_,
|
||||
dest, end);
|
||||
++it_;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class FwdIt>
|
||||
enc_segs_iter<FwdIt>
|
||||
make_enc_segs_iter(
|
||||
@@ -178,6 +245,15 @@ make_enc_segs_iter(
|
||||
first, last);
|
||||
}
|
||||
|
||||
template<class FwdIt>
|
||||
plain_segs_iter<FwdIt>
|
||||
make_plain_segs_iter(
|
||||
FwdIt first, FwdIt last)
|
||||
{
|
||||
return plain_segs_iter<FwdIt>(
|
||||
first, last);
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
#ifndef BOOST_URL_DETAIL_COPIED_STRINGS_HPP
|
||||
#define BOOST_URL_DETAIL_COPIED_STRINGS_HPP
|
||||
|
||||
#ifndef BOOST_URL_SOURCE
|
||||
#error
|
||||
#endif
|
||||
|
||||
#include <boost/url/string.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace urls {
|
||||
namespace detail {
|
||||
|
||||
any_path_iter::
|
||||
~any_path_iter() = default;
|
||||
~any_path_iter() noexcept = default;
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
@@ -91,6 +91,7 @@ copy(
|
||||
char*& dest,
|
||||
char const* end) noexcept
|
||||
{
|
||||
(void)end;
|
||||
BOOST_ASSERT(static_cast<
|
||||
std::size_t>(
|
||||
end - dest) >= n_);
|
||||
@@ -200,6 +201,7 @@ copy_impl(
|
||||
char*& dest,
|
||||
char const* end) noexcept
|
||||
{
|
||||
(void)end;
|
||||
BOOST_ASSERT(static_cast<
|
||||
std::size_t>(end - dest) >=
|
||||
s.size());
|
||||
@@ -213,6 +215,30 @@ copy_impl(
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
void
|
||||
plain_segs_iter_base::
|
||||
measure_impl(
|
||||
string_view s,
|
||||
std::size_t& n) noexcept
|
||||
{
|
||||
n += pct_encode_size(
|
||||
s, pchars);
|
||||
}
|
||||
|
||||
void
|
||||
plain_segs_iter_base::
|
||||
copy_impl(
|
||||
string_view s,
|
||||
char*& dest,
|
||||
char const* end) noexcept
|
||||
{
|
||||
dest = pct_encode(
|
||||
dest, end, s, {},
|
||||
pchars);
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
76
include/boost/url/detail/optional_allocator.hpp
Normal file
76
include/boost/url/detail/optional_allocator.hpp
Normal file
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/CPPAlliance/url
|
||||
//
|
||||
|
||||
#ifndef BOOST_URL_DETAIL_OPTIONAL_ALLOCATOR_HPP
|
||||
#define BOOST_URL_DETAIL_OPTIONAL_ALLOCATOR_HPP
|
||||
|
||||
#include <new>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
namespace detail {
|
||||
|
||||
// VFALCO This is so we can make
|
||||
// iterators default-constructible
|
||||
template<class Allocator>
|
||||
class optional_allocator
|
||||
{
|
||||
char buf_[sizeof(Allocator)];
|
||||
bool has_value_ = false;
|
||||
|
||||
public:
|
||||
~optional_allocator()
|
||||
{
|
||||
if(has_value_)
|
||||
(*(*this)).~Allocator();
|
||||
}
|
||||
|
||||
optional_allocator() = default;
|
||||
|
||||
explicit
|
||||
optional_allocator(
|
||||
Allocator const& a) noexcept
|
||||
: has_value_(true)
|
||||
{
|
||||
::new(buf_) Allocator(a);
|
||||
}
|
||||
|
||||
optional_allocator(
|
||||
optional_allocator const& other) noexcept
|
||||
: has_value_(other.has_value_)
|
||||
{
|
||||
if(has_value_)
|
||||
::new(buf_) Allocator(*other);
|
||||
}
|
||||
|
||||
optional_allocator&
|
||||
operator=(optional_allocator const& other
|
||||
) noexcept
|
||||
{
|
||||
if(has_value_)
|
||||
(*(*this)).~Allocator();
|
||||
has_value_ = other.has_value_;
|
||||
if(has_value_)
|
||||
::new(buf_) Allocator(*other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Allocator const&
|
||||
operator*() const noexcept
|
||||
{
|
||||
return *reinterpret_cast<
|
||||
Allocator const*>(buf_);
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
@@ -11,6 +11,7 @@
|
||||
#define BOOST_URL_DETAIL_OVER_ALLOCATOR_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/empty_value.hpp>
|
||||
#include <boost/type_traits/is_final.hpp>
|
||||
#include <boost/type_traits/type_with_alignment.hpp>
|
||||
|
||||
1099
include/boost/url/impl/segments.hpp
Normal file
1099
include/boost/url/impl/segments.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -44,6 +44,9 @@ public:
|
||||
reference&
|
||||
operator=(reference const& other)
|
||||
{
|
||||
if( u_ == other.u_ &&
|
||||
i_ == other.i_)
|
||||
return *this;
|
||||
*this = string_view(other);
|
||||
return *this;
|
||||
}
|
||||
@@ -108,100 +111,6 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Comparison
|
||||
|
||||
This function participates in overload
|
||||
resolution only if
|
||||
`is_stringlike<T>::value == true`.
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
is_stringlike<T>::value &&
|
||||
! std::is_same<reference, T>::value,
|
||||
bool>::type
|
||||
#endif
|
||||
>
|
||||
friend
|
||||
bool
|
||||
operator==(
|
||||
reference const& x1,
|
||||
T const& x2 ) noexcept
|
||||
{
|
||||
return
|
||||
string_view(x1) ==
|
||||
to_string_view(x2);
|
||||
}
|
||||
|
||||
/** Comparison
|
||||
|
||||
This function participates in overload
|
||||
resolution only if
|
||||
`is_stringlike<T>::value == true`.
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
is_stringlike<T>::value &&
|
||||
! std::is_same<reference, T>::value,
|
||||
bool>::type
|
||||
#endif
|
||||
>
|
||||
friend
|
||||
bool
|
||||
operator==(
|
||||
T const& x1,
|
||||
reference x2 ) noexcept
|
||||
{
|
||||
return
|
||||
to_string_view(x1) ==
|
||||
string_view(x2);
|
||||
}
|
||||
|
||||
/** Comparison
|
||||
|
||||
This function participates in overload
|
||||
resolution only if
|
||||
`is_stringlike<T>::value == true`.
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
is_stringlike<T>::value,
|
||||
bool>::type
|
||||
#endif
|
||||
>
|
||||
friend
|
||||
bool
|
||||
operator!=(
|
||||
reference const& x1,
|
||||
T const& x2 ) noexcept
|
||||
{
|
||||
return !( x1 == x2 );
|
||||
}
|
||||
|
||||
/** Comparison
|
||||
|
||||
This function participates in overload
|
||||
resolution only if
|
||||
`is_stringlike<T>::value == true`.
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
is_stringlike<T>::value,
|
||||
bool>::type
|
||||
#endif
|
||||
>
|
||||
friend
|
||||
bool
|
||||
operator!=(
|
||||
T const& x1,
|
||||
reference const& x2 ) noexcept
|
||||
{
|
||||
return !( x1 == x2);
|
||||
}
|
||||
|
||||
/** Swap two elements
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
@@ -266,100 +175,6 @@ public:
|
||||
return { s.data(), s.size() };
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Comparison
|
||||
|
||||
This function participates in overload
|
||||
resolution only if
|
||||
`is_stringlike<T>::value == true`.
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
is_stringlike<T>::value &&
|
||||
! std::is_same<reference, T>::value,
|
||||
bool>::type
|
||||
#endif
|
||||
>
|
||||
friend
|
||||
bool
|
||||
operator==(
|
||||
const_reference const& x1,
|
||||
T const& x2 ) noexcept
|
||||
{
|
||||
return
|
||||
string_view(x1) ==
|
||||
to_string_view(x2);
|
||||
}
|
||||
|
||||
/** Comparison
|
||||
|
||||
This function participates in overload
|
||||
resolution only if
|
||||
`is_stringlike<T>::value == true`.
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
is_stringlike<T>::value &&
|
||||
! std::is_same<reference, T>::value,
|
||||
bool>::type
|
||||
#endif
|
||||
>
|
||||
friend
|
||||
bool
|
||||
operator==(
|
||||
T const& x1,
|
||||
const_reference x2 ) noexcept
|
||||
{
|
||||
return
|
||||
to_string_view(x1) ==
|
||||
string_view(x2);
|
||||
}
|
||||
|
||||
/** Comparison
|
||||
|
||||
This function participates in overload
|
||||
resolution only if
|
||||
`is_stringlike<T>::value == true`.
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
is_stringlike<T>::value,
|
||||
bool>::type
|
||||
#endif
|
||||
>
|
||||
friend
|
||||
bool
|
||||
operator!=(
|
||||
const_reference const& x1,
|
||||
T const& x2 ) noexcept
|
||||
{
|
||||
return !( x1 == x2 );
|
||||
}
|
||||
|
||||
/** Comparison
|
||||
|
||||
This function participates in overload
|
||||
resolution only if
|
||||
`is_stringlike<T>::value == true`.
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
is_stringlike<T>::value,
|
||||
bool>::type
|
||||
#endif
|
||||
>
|
||||
friend
|
||||
bool
|
||||
operator!=(
|
||||
T const& x1,
|
||||
const_reference const& x2 ) noexcept
|
||||
{
|
||||
return !(x1 == x2);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
@@ -1006,52 +821,99 @@ operator=(
|
||||
const_reference const& other) ->
|
||||
reference&
|
||||
{
|
||||
if( u_ == other.u_ &&
|
||||
i_ == other.i_)
|
||||
return *this;
|
||||
*this = string_view(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
/** Comparison
|
||||
|
||||
This function participates in overload
|
||||
resolution only if
|
||||
`is_stringlike<T>::value == true`.
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
is_stringlike<T>::value>::type
|
||||
#endif
|
||||
>
|
||||
bool
|
||||
operator==(
|
||||
segments_encoded::
|
||||
const_reference const& c,
|
||||
segments_encoded::
|
||||
reference const& r) noexcept
|
||||
const_reference const& x1,
|
||||
T const& x2 ) noexcept
|
||||
{
|
||||
return string_view(c) == string_view(r);
|
||||
return
|
||||
string_view(x1) ==
|
||||
to_string_view(x2);
|
||||
}
|
||||
|
||||
inline
|
||||
/** Comparison
|
||||
|
||||
This function participates in overload
|
||||
resolution only if
|
||||
`is_stringlike<T>::value == true`.
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
is_stringlike<T>::value>::type
|
||||
#endif
|
||||
>
|
||||
bool
|
||||
operator==(
|
||||
T const& x1,
|
||||
segments_encoded::
|
||||
reference const& r,
|
||||
segments_encoded::
|
||||
const_reference const& c) noexcept
|
||||
const_reference const& x2 ) noexcept
|
||||
{
|
||||
return string_view(r) == string_view(c);
|
||||
return
|
||||
to_string_view(x1) ==
|
||||
string_view(x2);
|
||||
}
|
||||
|
||||
inline
|
||||
/** Comparison
|
||||
|
||||
This function participates in overload
|
||||
resolution only if
|
||||
`is_stringlike<T>::value == true`.
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
is_stringlike<T>::value>::type
|
||||
#endif
|
||||
>
|
||||
bool
|
||||
operator!=(
|
||||
segments_encoded::
|
||||
const_reference const& c,
|
||||
segments_encoded::
|
||||
reference const& r) noexcept
|
||||
const_reference const& x1,
|
||||
T const& x2 ) noexcept
|
||||
{
|
||||
return string_view(c) != string_view(r);
|
||||
return !( x1 == x2 );
|
||||
}
|
||||
|
||||
inline
|
||||
/** Comparison
|
||||
|
||||
This function participates in overload
|
||||
resolution only if
|
||||
`is_stringlike<T>::value == true`.
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
is_stringlike<T>::value>::type
|
||||
#endif
|
||||
>
|
||||
bool
|
||||
operator!=(
|
||||
T const& x1,
|
||||
segments_encoded::
|
||||
reference const& r,
|
||||
segments_encoded::
|
||||
const_reference const& c) noexcept
|
||||
const_reference const& x2 ) noexcept
|
||||
{
|
||||
return string_view(r) != string_view(c);
|
||||
return !(x1 == x2);
|
||||
}
|
||||
|
||||
} // urls
|
||||
|
||||
@@ -10,69 +10,67 @@
|
||||
#ifndef BOOST_URL_IMPL_SEGMENTS_VIEW_HPP
|
||||
#define BOOST_URL_IMPL_SEGMENTS_VIEW_HPP
|
||||
|
||||
#include <boost/url/segments_encoded_view.hpp>
|
||||
#include <boost/url/detail/except.hpp>
|
||||
#include <boost/url/detail/pct_encoding.hpp>
|
||||
#include <boost/url/rfc/paths_bnf.hpp>
|
||||
#include <cstdint>
|
||||
#include <boost/url/arrow_proxy.hpp>
|
||||
#include <boost/url/pct_encoding_types.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
template<class Alloc>
|
||||
class segments_view<Alloc>::
|
||||
class segments_view::
|
||||
iterator
|
||||
{
|
||||
std::size_t i_ = 0;
|
||||
string_type<Alloc> s_;
|
||||
char const* begin_ = nullptr;
|
||||
char const* pos_ = nullptr;
|
||||
char const* next_ = nullptr;
|
||||
char const* end_ = nullptr;
|
||||
string_value::allocator a_;
|
||||
pct_encoded_str t_;
|
||||
|
||||
friend segments_view;
|
||||
|
||||
explicit
|
||||
BOOST_URL_DECL
|
||||
iterator(
|
||||
string_view s,
|
||||
Alloc const& a);
|
||||
string_value::
|
||||
allocator const& a) noexcept;
|
||||
|
||||
// end ctor
|
||||
BOOST_URL_DECL
|
||||
iterator(
|
||||
std::size_t n,
|
||||
string_view s,
|
||||
Alloc const& a) noexcept;
|
||||
string_value::
|
||||
allocator const& a) noexcept;
|
||||
|
||||
public:
|
||||
using value_type = string_type<Alloc>;
|
||||
using value_type = string_value;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type const&;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
iterator() noexcept = default;
|
||||
BOOST_URL_DECL
|
||||
iterator() noexcept;
|
||||
|
||||
BOOST_URL_DECL
|
||||
iterator(
|
||||
iterator const&) noexcept = default;
|
||||
iterator& operator=(
|
||||
iterator const&) noexcept = default;
|
||||
iterator const&) noexcept;
|
||||
|
||||
std::size_t
|
||||
index() const noexcept
|
||||
{
|
||||
return i_;
|
||||
}
|
||||
BOOST_URL_DECL
|
||||
iterator&
|
||||
operator=(
|
||||
iterator const&) noexcept;
|
||||
|
||||
value_type const&
|
||||
operator*() const noexcept
|
||||
{
|
||||
return s_;
|
||||
}
|
||||
BOOST_URL_DECL
|
||||
string_value
|
||||
operator*() const noexcept;
|
||||
|
||||
value_type const*
|
||||
arrow_proxy<string_value>
|
||||
operator->() const noexcept
|
||||
{
|
||||
return &s_;
|
||||
return {**this};
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -93,9 +91,11 @@ public:
|
||||
end_ != other.end_;
|
||||
}
|
||||
|
||||
BOOST_URL_DECL
|
||||
iterator&
|
||||
operator++() noexcept;
|
||||
|
||||
BOOST_URL_DECL
|
||||
iterator&
|
||||
operator--() noexcept;
|
||||
|
||||
@@ -116,184 +116,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class Alloc>
|
||||
segments_view<Alloc>::
|
||||
segments_view(
|
||||
segments_encoded_view const& sv,
|
||||
Alloc const& a) noexcept
|
||||
: s_(sv.s_)
|
||||
, n_(sv.n_)
|
||||
, a_(a)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
template<class Alloc>
|
||||
segments_view<Alloc>::
|
||||
iterator::
|
||||
iterator(
|
||||
string_view s,
|
||||
Alloc const& a)
|
||||
: s_(a)
|
||||
, begin_(s.data())
|
||||
, pos_(s.data())
|
||||
, next_(s.data())
|
||||
, end_(s.data() + s.size())
|
||||
{
|
||||
using bnf::parse;
|
||||
using bnf_t = path_rootless_bnf;
|
||||
using detail::pct_decode_unchecked;
|
||||
if(next_ == end_)
|
||||
{
|
||||
next_ = nullptr;
|
||||
return;
|
||||
}
|
||||
error_code ec;
|
||||
if(*next_ == '/')
|
||||
{
|
||||
// "/" segment
|
||||
pct_encoded_str t;
|
||||
bnf_t::increment(next_,
|
||||
end_, ec, t);
|
||||
BOOST_ASSERT(! ec);
|
||||
s_ = pct_decode_unchecked(
|
||||
t.str, t.decoded_size, {},
|
||||
s_.get_allocator());
|
||||
}
|
||||
else
|
||||
{
|
||||
// segment-nz
|
||||
pct_encoded_str t;
|
||||
bnf_t::begin(next_,
|
||||
end_, ec, t);
|
||||
BOOST_ASSERT(! ec);
|
||||
s_ = pct_decode_unchecked(
|
||||
t.str, t.decoded_size, {},
|
||||
s_.get_allocator());
|
||||
}
|
||||
}
|
||||
|
||||
template<class Alloc>
|
||||
segments_view<Alloc>::
|
||||
iterator::
|
||||
iterator(
|
||||
std::size_t n,
|
||||
string_view s,
|
||||
Alloc const& a) noexcept
|
||||
: i_(n)
|
||||
, s_(a)
|
||||
, begin_(s.data())
|
||||
, pos_(s.data() + s.size())
|
||||
, end_(s.data() + s.size())
|
||||
{
|
||||
}
|
||||
|
||||
template<class Alloc>
|
||||
auto
|
||||
segments_view<Alloc>::
|
||||
iterator::
|
||||
operator++() noexcept ->
|
||||
iterator&
|
||||
{
|
||||
using bnf::parse;
|
||||
using bnf_t = path_rootless_bnf;
|
||||
using detail::pct_decode_unchecked;
|
||||
BOOST_ASSERT(next_ != nullptr);
|
||||
++i_;
|
||||
pos_ = next_;
|
||||
error_code ec;
|
||||
// "/" segment
|
||||
pct_encoded_str t;
|
||||
bnf_t::increment(
|
||||
next_, end_, ec, t);
|
||||
if(ec == error::end)
|
||||
{
|
||||
next_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
BOOST_ASSERT(! ec);
|
||||
s_ = pct_decode_unchecked(
|
||||
t.str, t.decoded_size, {},
|
||||
s_.get_allocator());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Alloc>
|
||||
auto
|
||||
segments_view<Alloc>::
|
||||
iterator::
|
||||
operator--() noexcept ->
|
||||
iterator&
|
||||
{
|
||||
using bnf::parse;
|
||||
using bnf_t = path_rootless_bnf;
|
||||
using detail::pct_decode_unchecked;
|
||||
BOOST_ASSERT(i_ != 0);
|
||||
BOOST_ASSERT(pos_ != begin_);
|
||||
--i_;
|
||||
error_code ec;
|
||||
while(--pos_ != begin_)
|
||||
{
|
||||
if(*pos_ != '/')
|
||||
continue;
|
||||
// "/" segment
|
||||
next_ = pos_;
|
||||
pct_encoded_str t;
|
||||
bnf_t::increment(next_,
|
||||
end_, ec, t);
|
||||
BOOST_ASSERT(! ec);
|
||||
s_ = pct_decode_unchecked(
|
||||
t.str, t.decoded_size, {},
|
||||
s_.get_allocator());
|
||||
return *this;
|
||||
}
|
||||
next_ = pos_;
|
||||
if(*next_ == '/')
|
||||
{
|
||||
// "/" segment
|
||||
pct_encoded_str t;
|
||||
bnf_t::increment(next_,
|
||||
end_, ec, t);
|
||||
BOOST_ASSERT(! ec);
|
||||
s_ = pct_decode_unchecked(
|
||||
t.str, t.decoded_size, {},
|
||||
s_.get_allocator());
|
||||
}
|
||||
else
|
||||
{
|
||||
// segment-nz
|
||||
pct_encoded_str t;
|
||||
bnf_t::begin(next_,
|
||||
end_, ec, t);
|
||||
BOOST_ASSERT(! ec);
|
||||
s_ = pct_decode_unchecked(
|
||||
t.str, t.decoded_size, {},
|
||||
s_.get_allocator());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Alloc>
|
||||
auto
|
||||
segments_view<Alloc>::
|
||||
begin() const noexcept ->
|
||||
iterator
|
||||
{
|
||||
return iterator(s_, a_);
|
||||
}
|
||||
|
||||
template<class Alloc>
|
||||
auto
|
||||
segments_view<Alloc>::
|
||||
end() const noexcept ->
|
||||
iterator
|
||||
{
|
||||
return iterator(n_, s_, a_);
|
||||
}
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
|
||||
193
include/boost/url/impl/segments_view.ipp
Normal file
193
include/boost/url/impl/segments_view.ipp
Normal file
@@ -0,0 +1,193 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/CPPAlliance/url
|
||||
//
|
||||
|
||||
#ifndef BOOST_URL_IMPL_SEGMENTS_VIEW_IPP
|
||||
#define BOOST_URL_IMPL_SEGMENTS_VIEW_IPP
|
||||
|
||||
#include <boost/url/segments_view.hpp>
|
||||
#include <boost/url/detail/pct_encoding.hpp>
|
||||
#include <boost/url/bnf/parse.hpp>
|
||||
#include <boost/url/rfc/paths_bnf.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
segments_view::
|
||||
segments_view(
|
||||
segments_view const&) noexcept = default;
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
segments_view::
|
||||
iterator::
|
||||
iterator(
|
||||
string_view s,
|
||||
string_value::allocator const& a) noexcept
|
||||
: begin_(s.data())
|
||||
, pos_(s.data())
|
||||
, next_(s.data())
|
||||
, end_(s.data() + s.size())
|
||||
, a_(a)
|
||||
{
|
||||
using bnf::parse;
|
||||
using bnf_t = path_rootless_bnf;
|
||||
using detail::pct_decode_unchecked;
|
||||
if(next_ == end_)
|
||||
{
|
||||
next_ = nullptr;
|
||||
return;
|
||||
}
|
||||
error_code ec;
|
||||
if(*next_ == '/')
|
||||
{
|
||||
// "/" segment
|
||||
bnf_t::increment(next_,
|
||||
end_, ec, t_);
|
||||
BOOST_ASSERT(! ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
// segment-nz
|
||||
bnf_t::begin(next_,
|
||||
end_, ec, t_);
|
||||
BOOST_ASSERT(! ec);
|
||||
}
|
||||
}
|
||||
|
||||
segments_view::
|
||||
iterator::
|
||||
iterator(
|
||||
std::size_t,
|
||||
string_view s,
|
||||
string_value::
|
||||
allocator const& a) noexcept
|
||||
: begin_(s.data())
|
||||
, pos_(s.data() + s.size())
|
||||
, end_(s.data() + s.size())
|
||||
, a_(a)
|
||||
{
|
||||
}
|
||||
|
||||
segments_view::
|
||||
iterator::
|
||||
iterator() noexcept = default;
|
||||
|
||||
segments_view::
|
||||
iterator::
|
||||
iterator(
|
||||
iterator const&) noexcept = default;
|
||||
|
||||
auto
|
||||
segments_view::
|
||||
iterator::
|
||||
operator=(
|
||||
iterator const&) noexcept ->
|
||||
iterator& = default;
|
||||
|
||||
string_value
|
||||
segments_view::
|
||||
iterator::
|
||||
operator*() const noexcept
|
||||
{
|
||||
char* dest;
|
||||
auto s = a_.make_string_value(
|
||||
t_.decoded_size, dest);
|
||||
detail::pct_decode_unchecked(
|
||||
dest,
|
||||
dest + t_.decoded_size,
|
||||
t_.str,
|
||||
{});
|
||||
return s;
|
||||
}
|
||||
|
||||
auto
|
||||
segments_view::
|
||||
iterator::
|
||||
operator++() noexcept ->
|
||||
iterator&
|
||||
{
|
||||
using bnf::parse;
|
||||
using bnf_t = path_rootless_bnf;
|
||||
using detail::pct_decode_unchecked;
|
||||
BOOST_ASSERT(next_ != nullptr);
|
||||
pos_ = next_;
|
||||
error_code ec;
|
||||
// "/" segment
|
||||
bnf_t::increment(
|
||||
next_, end_, ec, t_);
|
||||
if(ec == error::end)
|
||||
{
|
||||
next_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
BOOST_ASSERT(! ec);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto
|
||||
segments_view::
|
||||
iterator::
|
||||
operator--() noexcept ->
|
||||
iterator&
|
||||
{
|
||||
using bnf::parse;
|
||||
using bnf_t = path_rootless_bnf;
|
||||
using detail::pct_decode_unchecked;
|
||||
BOOST_ASSERT(pos_ != begin_);
|
||||
error_code ec;
|
||||
while(--pos_ != begin_)
|
||||
{
|
||||
if(*pos_ != '/')
|
||||
continue;
|
||||
// "/" segment
|
||||
next_ = pos_;
|
||||
bnf_t::increment(next_,
|
||||
end_, ec, t_);
|
||||
BOOST_ASSERT(! ec);
|
||||
return *this;
|
||||
}
|
||||
next_ = pos_;
|
||||
if(*next_ == '/')
|
||||
{
|
||||
// "/" segment
|
||||
bnf_t::increment(next_,
|
||||
end_, ec, t_);
|
||||
BOOST_ASSERT(! ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
// segment-nz
|
||||
bnf_t::begin(next_,
|
||||
end_, ec, t_);
|
||||
BOOST_ASSERT(! ec);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto
|
||||
segments_view::
|
||||
begin() const noexcept ->
|
||||
iterator
|
||||
{
|
||||
return iterator(s_, a_);
|
||||
}
|
||||
|
||||
auto
|
||||
segments_view::
|
||||
end() const noexcept ->
|
||||
iterator
|
||||
{
|
||||
return iterator(n_, s_, a_);
|
||||
}
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
@@ -16,90 +16,22 @@
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
struct basic_static_pool::item
|
||||
{
|
||||
void* p;
|
||||
std::size_t n;
|
||||
|
||||
bool
|
||||
in_use() const noexcept
|
||||
{
|
||||
return (reinterpret_cast<
|
||||
std::uintptr_t>(p) & 1) != 0;
|
||||
}
|
||||
|
||||
void
|
||||
use() noexcept
|
||||
{
|
||||
p = reinterpret_cast<
|
||||
void*>((reinterpret_cast<
|
||||
std::uintptr_t>(p) | 1));
|
||||
}
|
||||
|
||||
void
|
||||
free() noexcept
|
||||
{
|
||||
p = reinterpret_cast<
|
||||
void*>((reinterpret_cast<
|
||||
std::uintptr_t>(p) & ~1));
|
||||
}
|
||||
|
||||
void*
|
||||
ptr() const noexcept
|
||||
{
|
||||
return reinterpret_cast<
|
||||
void*>((reinterpret_cast<
|
||||
std::uintptr_t>(p) & ~1));
|
||||
}
|
||||
};
|
||||
|
||||
void*
|
||||
basic_static_pool::
|
||||
allocate(
|
||||
std::size_t bytes,
|
||||
std::size_t align)
|
||||
{
|
||||
if( align < 2)
|
||||
align = 2;
|
||||
bytes = alignment::align_up(
|
||||
auto n = alignment::align_up(
|
||||
bytes, align);
|
||||
item* it0 = reinterpret_cast<
|
||||
item*>(base_);
|
||||
item* it1 = it0 + n_;
|
||||
{
|
||||
// find best fit
|
||||
item* best = nullptr;
|
||||
std::size_t bestn =
|
||||
std::size_t(-1);
|
||||
auto it = it0;
|
||||
while(it != it1)
|
||||
{
|
||||
if( ! it->in_use() &&
|
||||
it->n >= bytes &&
|
||||
it->n < bestn)
|
||||
{
|
||||
best = it;
|
||||
bestn = it->n;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
if(best)
|
||||
{
|
||||
it->use();
|
||||
return it->p;
|
||||
}
|
||||
}
|
||||
auto const u0 = std::uintptr_t(top_);
|
||||
auto const u = align * (
|
||||
(u0 + align - 1) / align);
|
||||
auto const p =
|
||||
reinterpret_cast<char*>(u);
|
||||
if( u < u0 || bytes >
|
||||
capacity_ - (p - base_))
|
||||
auto p = reinterpret_cast<char*>(
|
||||
reinterpret_cast<
|
||||
std::uintptr_t>(top_ - n) &
|
||||
~(align - 1));
|
||||
if(p < begin_)
|
||||
detail::throw_bad_alloc(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
top_ = reinterpret_cast<
|
||||
char*>(p + bytes);
|
||||
++n_;
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -110,6 +42,11 @@ deallocate(
|
||||
std::size_t,
|
||||
std::size_t) noexcept
|
||||
{
|
||||
BOOST_ASSERT(n_ > 0);
|
||||
--n_;
|
||||
if(n_ > 0)
|
||||
return;
|
||||
top_ = end_;
|
||||
}
|
||||
|
||||
} // urls
|
||||
|
||||
241
include/boost/url/impl/string.hpp
Normal file
241
include/boost/url/impl/string.hpp
Normal file
@@ -0,0 +1,241 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/CPPAllinace/url
|
||||
//
|
||||
|
||||
#ifndef BOOST_URL_IMPL_STRING_HPP
|
||||
#define BOOST_URL_IMPL_STRING_HPP
|
||||
|
||||
#include <boost/url/detail/over_allocator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
struct string_value::base
|
||||
{
|
||||
std::size_t refs = 1;
|
||||
virtual void destroy() noexcept = 0;
|
||||
};
|
||||
|
||||
template<class Allocator>
|
||||
auto
|
||||
string_value::
|
||||
construct(
|
||||
std::size_t n,
|
||||
Allocator const& a,
|
||||
char*& dest) ->
|
||||
base*
|
||||
{
|
||||
class impl;
|
||||
|
||||
using allocator_type =
|
||||
detail::over_allocator<
|
||||
impl, Allocator>;
|
||||
|
||||
class impl : public base
|
||||
{
|
||||
allocator_type a_;
|
||||
|
||||
public:
|
||||
explicit
|
||||
impl(
|
||||
allocator_type const& a)
|
||||
: a_(a)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
destroy() noexcept override
|
||||
{
|
||||
auto a(a_);
|
||||
a.deallocate(this, 1);
|
||||
}
|
||||
};
|
||||
|
||||
if(n == 0)
|
||||
{
|
||||
dest = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
allocator_type al(n, a);
|
||||
auto p = ::new(
|
||||
al.allocate(1)) impl(al);
|
||||
dest = reinterpret_cast<
|
||||
char*>(p + 1);
|
||||
static_cast<string_view&>(
|
||||
*this) = { dest, n };
|
||||
return p;
|
||||
}
|
||||
|
||||
string_value::
|
||||
~string_value()
|
||||
{
|
||||
if( p_ &&
|
||||
--p_->refs == 0)
|
||||
p_->destroy();
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
string_value::
|
||||
string_value(
|
||||
std::size_t n,
|
||||
Allocator const& a,
|
||||
char*& dest)
|
||||
: p_(construct(n, a, dest))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
string_value::
|
||||
string_value(
|
||||
string_view s,
|
||||
Allocator const& a)
|
||||
{
|
||||
char* dest;
|
||||
p_ = construct(
|
||||
s.size(), a, dest);
|
||||
std::memcpy(dest,
|
||||
s.data(), s.size());
|
||||
}
|
||||
|
||||
string_value::
|
||||
string_value(
|
||||
string_value const& other) noexcept
|
||||
: string_view(other)
|
||||
, p_(other.p_)
|
||||
{
|
||||
if(p_)
|
||||
++p_->refs;
|
||||
}
|
||||
|
||||
string_value&
|
||||
string_value::
|
||||
operator=(
|
||||
string_value const& other) noexcept
|
||||
{
|
||||
if( p_ &&
|
||||
--p_->refs == 0)
|
||||
p_->destroy();
|
||||
p_ = other.p_;
|
||||
if(p_)
|
||||
++p_->refs;
|
||||
static_cast<string_view&>(
|
||||
*this) = other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
class string_value::allocator
|
||||
{
|
||||
struct base
|
||||
{
|
||||
std::size_t refs = 1;
|
||||
|
||||
virtual
|
||||
~base()
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
string_value
|
||||
alloc(
|
||||
std::size_t n,
|
||||
char*& dest) = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
destroy() noexcept = 0;
|
||||
};
|
||||
|
||||
base* p_ = nullptr;
|
||||
|
||||
public:
|
||||
~allocator()
|
||||
{
|
||||
if( p_ &&
|
||||
--p_->refs == 0)
|
||||
p_->destroy();
|
||||
}
|
||||
|
||||
allocator() = default;
|
||||
|
||||
allocator(
|
||||
allocator const& other) noexcept
|
||||
: p_(other.p_)
|
||||
{
|
||||
++p_->refs;
|
||||
}
|
||||
|
||||
allocator&
|
||||
operator=(
|
||||
allocator const& other) noexcept
|
||||
{
|
||||
if( p_ &&
|
||||
--p_->refs)
|
||||
p_->destroy();
|
||||
p_ = other.p_;
|
||||
if(p_)
|
||||
++p_->refs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
explicit
|
||||
allocator(Allocator const& a)
|
||||
{
|
||||
class impl;
|
||||
|
||||
using allocator_type = typename
|
||||
detail::allocator_traits<
|
||||
Allocator>::template
|
||||
rebind_alloc<impl>;
|
||||
|
||||
class impl : public base
|
||||
{
|
||||
allocator_type a_;
|
||||
|
||||
public:
|
||||
impl(allocator_type const& a)
|
||||
: a_(a)
|
||||
{
|
||||
}
|
||||
|
||||
string_value
|
||||
alloc(
|
||||
std::size_t n,
|
||||
char*& dest) override
|
||||
{
|
||||
return string_value(
|
||||
n, a_, dest);
|
||||
}
|
||||
|
||||
void
|
||||
destroy() noexcept override
|
||||
{
|
||||
auto a(a_);
|
||||
a.deallocate(this, 1);
|
||||
}
|
||||
};
|
||||
|
||||
allocator_type al(a);
|
||||
p_ = ::new(al.allocate(1)) impl(al);
|
||||
}
|
||||
|
||||
string_value
|
||||
make_string_value(
|
||||
std::size_t n,
|
||||
char*& dest) const
|
||||
{
|
||||
return p_->alloc(n, dest);
|
||||
}
|
||||
};
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
@@ -13,6 +13,15 @@
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
template<class Allocator>
|
||||
segments<Allocator>
|
||||
url::
|
||||
segments(Allocator const& a) noexcept
|
||||
{
|
||||
return urls::segments<Allocator>(
|
||||
*this, a);
|
||||
}
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
|
||||
@@ -715,6 +715,7 @@ set_encoded_host(string_view s)
|
||||
case urls::host_type::ipv6:
|
||||
return set_host(t.ipv6);
|
||||
|
||||
case urls::host_type::none:
|
||||
case urls::host_type::name:
|
||||
{
|
||||
auto dest =
|
||||
@@ -1296,26 +1297,12 @@ set_path(
|
||||
string_view
|
||||
url::
|
||||
encoded_segment(
|
||||
int index) const noexcept
|
||||
std::size_t i) const noexcept
|
||||
{
|
||||
std::size_t i;
|
||||
raw_segment r;
|
||||
if(index >= 0)
|
||||
{
|
||||
i = static_cast<
|
||||
std::size_t>(index);
|
||||
if(i >= nseg_)
|
||||
return empty_;
|
||||
r = get_segment(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = static_cast<
|
||||
std::size_t>(-index);
|
||||
if(i > nseg_)
|
||||
return empty_;
|
||||
r = get_segment(nseg_ - i);
|
||||
}
|
||||
if(i >= nseg_)
|
||||
return empty_;
|
||||
r = get_segment(i);
|
||||
string_view s = {
|
||||
s_ + r.pos, r.len };
|
||||
if(s.starts_with('/'))
|
||||
|
||||
@@ -384,29 +384,14 @@ segment_count() const noexcept
|
||||
string_view
|
||||
url_view::
|
||||
encoded_segment(
|
||||
int index) const noexcept
|
||||
std::size_t i) const noexcept
|
||||
{
|
||||
std::size_t i;
|
||||
if(index >= 0)
|
||||
{
|
||||
i = static_cast<
|
||||
std::size_t>(index);
|
||||
if(i >= nseg_)
|
||||
return empty_;
|
||||
auto pv = encoded_segments();
|
||||
auto it = pv.begin();
|
||||
while(i--)
|
||||
++it;
|
||||
return *it;
|
||||
}
|
||||
i = static_cast<
|
||||
std::size_t>(-index);
|
||||
if(i > nseg_)
|
||||
if(i >= nseg_)
|
||||
return empty_;
|
||||
auto pv = encoded_segments();
|
||||
auto it = pv.end();
|
||||
auto it = pv.begin();
|
||||
while(i--)
|
||||
--it;
|
||||
++it;
|
||||
return *it;
|
||||
}
|
||||
|
||||
|
||||
938
include/boost/url/segments.hpp
Normal file
938
include/boost/url/segments.hpp
Normal file
@@ -0,0 +1,938 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/CPPAlliance/url
|
||||
//
|
||||
|
||||
#ifndef BOOST_URL_SEGMENTS_HPP
|
||||
#define BOOST_URL_SEGMENTS_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/string.hpp>
|
||||
#include <boost/url/detail/except.hpp>
|
||||
#include <boost/url/detail/parts_base.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
class url;
|
||||
#endif
|
||||
|
||||
/** A reference-like container to modifiable URL segments
|
||||
|
||||
This class implements a <em>RandomAccessContainer</em>
|
||||
representing the path segments in a @ref url as
|
||||
percent-encoded strings. Ownership of the segments
|
||||
is not transferred; the container references the
|
||||
buffer in the url. Therefore, the lifetime of the
|
||||
url must remain valid until this container no
|
||||
longer exists.
|
||||
|
||||
Objects of this type are not constructed directly;
|
||||
Instead, call the corresponding non-const member
|
||||
function of @ref url to obtain an instance of
|
||||
the container:
|
||||
|
||||
@par Example
|
||||
@code
|
||||
url u = parse_relative_ref( "/path/to/file.txt" );
|
||||
|
||||
segments se = u.segments();
|
||||
|
||||
for( segments::value_type s : se )
|
||||
std::cout << s << std::endl;
|
||||
@endcode
|
||||
|
||||
The @ref reference and @ref const_reference
|
||||
nested types are defined as publicly accessible
|
||||
nested classes. They proxy the behavior of a
|
||||
reference to a percent-encoded string in the
|
||||
underlying URL. The primary use of these
|
||||
references is to provide l-values that can be
|
||||
returned from element-accessing operations.
|
||||
Any reads or writes which happen through a
|
||||
@ref reference or @ref const_reference
|
||||
potentially read or write the underlying
|
||||
@ref url.
|
||||
|
||||
@see
|
||||
@ref url.
|
||||
*/
|
||||
template<class Allocator>
|
||||
class segments
|
||||
: private detail::parts_base
|
||||
{
|
||||
url* u_ = nullptr;
|
||||
Allocator a_;
|
||||
|
||||
friend class url;
|
||||
|
||||
explicit
|
||||
segments(
|
||||
url& u,
|
||||
Allocator const& a) noexcept
|
||||
: u_(&u)
|
||||
, a_(a)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
#ifdef BOOST_URL_DOCS
|
||||
/** A random-access iterator referencing segments in a url path
|
||||
|
||||
When dereferenced, this iterator returns a
|
||||
proxy which allows conversion to stringlike
|
||||
types, assignments which change the underlying
|
||||
container, and comparisons.
|
||||
*/
|
||||
using iterator = __see_below__;
|
||||
|
||||
/** A random-access iterator referencing segments in a url path
|
||||
|
||||
When dereferenced, this iterator returns a
|
||||
proxy which allows conversion to stringlike
|
||||
types, and comparisons.
|
||||
*/
|
||||
using const_iterator = __see_below__;
|
||||
|
||||
/** A proxy for a percent-encoded path segment
|
||||
|
||||
This type is a proxy for a modifiable
|
||||
percent-encoded path segment. It supports
|
||||
assignment, conversion to stringlike types,
|
||||
and comparison.
|
||||
*/
|
||||
using reference = __see_below__;
|
||||
|
||||
/** A proxy for a percent-encoded path segment
|
||||
|
||||
This type is a proxy for a read-only
|
||||
percent-encoded path segment. It supports
|
||||
conversion to stringlike types, and comparison.
|
||||
*/
|
||||
using const_reference = __see_below__;
|
||||
#else
|
||||
class iterator;
|
||||
class const_iterator;
|
||||
class reference;
|
||||
class const_reference;
|
||||
#endif
|
||||
|
||||
/** A type which can represent a segment as a value
|
||||
|
||||
This type allows for making a copy of
|
||||
a segment where ownership is retained
|
||||
in the copy.
|
||||
*/
|
||||
using value_type = string_type<Allocator>;
|
||||
|
||||
/** An unsigned integer type
|
||||
*/
|
||||
using size_type = std::size_t;
|
||||
|
||||
/** A signed integer type
|
||||
*/
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
//--------------------------------------------
|
||||
//
|
||||
// Members
|
||||
//
|
||||
//--------------------------------------------
|
||||
|
||||
/** Replace the contents of the container
|
||||
|
||||
This function replaces the contents
|
||||
with an initializer list of
|
||||
percent-encoded strings.
|
||||
Each string must contain a valid
|
||||
percent-encoding or else an
|
||||
exception is thrown.
|
||||
The behavior is undefined any string
|
||||
refers to the contents of `*this`.
|
||||
All iterators and references to elements
|
||||
of the container are invalidated,
|
||||
including the @ref end iterator.
|
||||
|
||||
@par Requires
|
||||
@code
|
||||
is_stringlike< T >::value == true
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
@code
|
||||
url u = parse_relative_uri( "/path/to/file.txt" );
|
||||
|
||||
u.segments() = { "etc", "init.rc" };
|
||||
|
||||
assert( u.encoded_path() == "/etc/init.rc") );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Calls to allocate may throw.
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@param init An initializer list of strings.
|
||||
|
||||
@throw std::invalid_argument invalid percent-encoding
|
||||
*/
|
||||
template<class T>
|
||||
#ifdef BOOST_URL_DOCS
|
||||
segments&
|
||||
#else
|
||||
typename std::enable_if<
|
||||
is_stringlike<T>::value,
|
||||
segments&>::type
|
||||
#endif
|
||||
operator=(std::initializer_list<T> init)
|
||||
{
|
||||
assign(init);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Replace the contents of the container
|
||||
|
||||
This function replaces the contents
|
||||
with a range of percent-encoded
|
||||
strings.
|
||||
Each string must contain a valid
|
||||
percent-encoding or else an
|
||||
exception is thrown.
|
||||
The behavior is undefined if either
|
||||
argument is an iterator into `*this`.
|
||||
All iterators and references to elements
|
||||
of the container are invalidated,
|
||||
including the @ref end iterator.
|
||||
|
||||
@par Requires
|
||||
@code
|
||||
is_stringlike< std::iterator_traits< FwdIt >::value_type >::value == true
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
@code
|
||||
url u = parse_relative_uri( "/path/to/file.txt" );
|
||||
|
||||
segments se = u.segments();
|
||||
|
||||
std::vector< std::string > v = { "etc", "init.rc" };
|
||||
|
||||
se.insert( u.end() - 1, v.begin(), v.end() );
|
||||
|
||||
assert( u.encoded_path() == "/etc/init.rc") );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Calls to allocate may throw.
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@param first An iterator to the first
|
||||
element in the range
|
||||
|
||||
@param last An iterator to one past the
|
||||
last element in the range
|
||||
|
||||
@throw std::invalid_argument invalid percent-encoding
|
||||
*/
|
||||
template<class FwdIt>
|
||||
#ifdef BOOST_URL_DOCS
|
||||
void
|
||||
#else
|
||||
typename std::enable_if<
|
||||
is_stringlike<typename
|
||||
std::iterator_traits<
|
||||
FwdIt>::value_type>::value,
|
||||
void>::type
|
||||
#endif
|
||||
assign(FwdIt first, FwdIt last);
|
||||
|
||||
/** Replace the contents of the container
|
||||
|
||||
This function replaces the contents
|
||||
with an initializer list of
|
||||
percent-encoded strings.
|
||||
Each string must contain a valid
|
||||
percent-encoding or else an
|
||||
exception is thrown.
|
||||
The behavior is undefined any string
|
||||
refers to the contents of `*this`.
|
||||
All iterators and references to elements
|
||||
of the container are invalidated,
|
||||
including the @ref end iterator.
|
||||
|
||||
@par Requires
|
||||
@code
|
||||
is_stringlike< T >::value == true
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
@code
|
||||
url u = parse_relative_uri( "/path/to/file.txt" );
|
||||
|
||||
u.segments().assign( { "etc", "init.rc" } );
|
||||
|
||||
assert( u.encoded_path() == "/etc/init.rc") );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Calls to allocate may throw.
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@param init An initializer list of strings.
|
||||
|
||||
@throw std::invalid_argument invalid percent-encoding
|
||||
*/
|
||||
template<class T>
|
||||
#ifdef BOOST_URL_DOCS
|
||||
void
|
||||
#else
|
||||
typename std::enable_if<
|
||||
is_stringlike<T>::value,
|
||||
void>::type
|
||||
#endif
|
||||
assign(std::initializer_list<T> init)
|
||||
{
|
||||
assign(init.begin(), init.end());
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
//
|
||||
// Element Access
|
||||
//
|
||||
//--------------------------------------------
|
||||
|
||||
/** Return an element with bounds checking
|
||||
|
||||
This function returns a proxy reference
|
||||
to the i-th element. If i is greater than
|
||||
@ref size, an exception is thrown.
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Exception thrown on invalid parameter.
|
||||
|
||||
@throws std::out_of_range `i >= size()`
|
||||
|
||||
@return A proxy reference to the element.
|
||||
|
||||
@param i The zero-based index of the
|
||||
element.
|
||||
*/
|
||||
inline
|
||||
reference
|
||||
at(std::size_t i);
|
||||
|
||||
/** Return an element with bounds checking
|
||||
|
||||
This function returns a proxy reference
|
||||
to the i-th element. If i is greater than
|
||||
@ref size, an exception is thrown.
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Exception thrown on invalid parameter.
|
||||
|
||||
@throws std::out_of_range `i >= size()`
|
||||
|
||||
@return A proxy reference to the element.
|
||||
|
||||
@param i The zero-based index of the
|
||||
element.
|
||||
*/
|
||||
inline
|
||||
const_reference
|
||||
at(std::size_t i) const;
|
||||
|
||||
/** Return an element
|
||||
|
||||
This function returns a proxy reference
|
||||
to the i-th element.
|
||||
|
||||
@par Preconditions
|
||||
@code
|
||||
i < size()
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
|
||||
@return A proxy reference to the element.
|
||||
|
||||
@param i The zero-based index of the
|
||||
element.
|
||||
*/
|
||||
inline
|
||||
reference
|
||||
operator[](std::size_t i) noexcept;
|
||||
|
||||
/** Return an element
|
||||
|
||||
This function returns a proxy reference
|
||||
to the i-th element.
|
||||
|
||||
@par Preconditions
|
||||
@code
|
||||
i < size()
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
|
||||
@return A proxy reference to the element.
|
||||
|
||||
@param i The zero-based index of the
|
||||
element.
|
||||
*/
|
||||
inline
|
||||
const_reference
|
||||
operator[](std::size_t i) const noexcept;
|
||||
|
||||
/** Return the first element
|
||||
*/
|
||||
inline
|
||||
const_reference
|
||||
front() const;
|
||||
|
||||
/** Return the first element
|
||||
*/
|
||||
inline
|
||||
reference
|
||||
front();
|
||||
|
||||
/** Return the last element
|
||||
*/
|
||||
inline
|
||||
const_reference
|
||||
back() const;
|
||||
|
||||
/** Return the last element
|
||||
*/
|
||||
inline
|
||||
reference
|
||||
back();
|
||||
|
||||
//--------------------------------------------
|
||||
//
|
||||
// Iterators
|
||||
//
|
||||
//--------------------------------------------
|
||||
|
||||
/** Return an iterator to the beginning
|
||||
*/
|
||||
inline
|
||||
iterator
|
||||
begin() noexcept;
|
||||
|
||||
/** Return an iterator to the beginning
|
||||
*/
|
||||
inline
|
||||
const_iterator
|
||||
begin() const noexcept;
|
||||
|
||||
/** Return an iterator to the beginning
|
||||
*/
|
||||
inline
|
||||
const_iterator
|
||||
cbegin() const noexcept;
|
||||
|
||||
/** Return an iterator to the end
|
||||
*/
|
||||
inline
|
||||
iterator
|
||||
end() noexcept;
|
||||
|
||||
/** Return an iterator to the end
|
||||
*/
|
||||
inline
|
||||
const_iterator
|
||||
end() const noexcept;
|
||||
|
||||
/** Return an iterator to the end
|
||||
*/
|
||||
inline
|
||||
const_iterator
|
||||
cend() const noexcept;
|
||||
|
||||
//--------------------------------------------
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
//--------------------------------------------
|
||||
|
||||
/** Return true if the container is empty
|
||||
|
||||
This function returns true if there are
|
||||
no elements in the container. That is, if
|
||||
the underlying path is the empty string.
|
||||
*/
|
||||
bool
|
||||
empty() const noexcept
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/** Return the number of elements in the container
|
||||
|
||||
This function returns the number of
|
||||
elements in the underlying path. Empty
|
||||
segments count towards this total.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
std::size_t
|
||||
size() const noexcept;
|
||||
|
||||
//--------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//--------------------------------------------
|
||||
|
||||
private:
|
||||
template<class FwdIt>
|
||||
iterator
|
||||
insert(
|
||||
const_iterator before,
|
||||
FwdIt first,
|
||||
FwdIt last,
|
||||
std::input_iterator_tag) = delete;
|
||||
|
||||
template<class FwdIt>
|
||||
iterator
|
||||
insert(
|
||||
const_iterator before,
|
||||
FwdIt first,
|
||||
FwdIt last,
|
||||
std::forward_iterator_tag);
|
||||
public:
|
||||
|
||||
/** Remove the contents of the container
|
||||
|
||||
This function removes all the segments
|
||||
from the container, leaving the
|
||||
underlying URL with an empty path.
|
||||
|
||||
@par Postconditions
|
||||
@code
|
||||
empty() == true
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
inline
|
||||
void
|
||||
clear() noexcept;
|
||||
|
||||
/** Insert an element
|
||||
|
||||
This function inserts a segment specified
|
||||
by the percent-encoded string `s`, at the
|
||||
position preceding `before`.
|
||||
The string must contain a valid
|
||||
percent-encoding, or else an exception
|
||||
is thrown.
|
||||
All references and iterators starting
|
||||
from the newly inserted element and
|
||||
up to and including the last element
|
||||
and @ref end iterators are invalidated.
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Calls to allocate may throw.
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@return An iterator pointing to the
|
||||
inserted value.
|
||||
|
||||
@param before An iterator before which the
|
||||
new element should be inserted.
|
||||
|
||||
@param s A valid percent-encoded string
|
||||
to be inserted.
|
||||
|
||||
@throw std::invalid_argument invalid percent-encoding
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
iterator
|
||||
insert(
|
||||
const_iterator before,
|
||||
string_view s);
|
||||
|
||||
/** Insert an element
|
||||
|
||||
This function inserts a segment specified
|
||||
by the percent-encoded stringlike `t`,
|
||||
at the position preceding `before`.
|
||||
The stringlike must contain a valid
|
||||
percent-encoding, or else an exception
|
||||
is thrown.
|
||||
All references and iterators starting
|
||||
from the newly inserted element and
|
||||
up to and including the last element
|
||||
and @ref end iterators are invalidated.
|
||||
This function participates in overload
|
||||
resolution only if
|
||||
`is_stringlike<T>::value == true`.
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Calls to allocate may throw.
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@return An iterator pointing to the
|
||||
inserted value.
|
||||
|
||||
@param before An iterator before which the
|
||||
new element should be inserted.
|
||||
|
||||
@param t The stringlike value to insert.
|
||||
|
||||
@throw std::invalid_argument invalid percent-encoding
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
is_stringlike<T>::value,
|
||||
bool>::type
|
||||
#endif
|
||||
>
|
||||
iterator
|
||||
insert(
|
||||
const_iterator before,
|
||||
T const& t);
|
||||
|
||||
/** Insert a range of segments
|
||||
|
||||
This function inserts a range
|
||||
of percent-encoded strings.
|
||||
Each string must contain a valid
|
||||
percent-encoding or else an
|
||||
exception is thrown.
|
||||
The behavior is undefined if either
|
||||
argument is an iterator into `this`.
|
||||
All references and iterators starting
|
||||
from the newly inserted elements and
|
||||
up to and including the last element
|
||||
and @ref end iterators are invalidated.
|
||||
|
||||
@par Requires
|
||||
@code
|
||||
is_stringlike< std::iterator_traits< FwdIt >::value_type >::value == true
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
@code
|
||||
url u = parse_relative_uri( "/path/file.txt" );
|
||||
|
||||
segments se = u.segments();
|
||||
|
||||
std::vector< std::string > v = { "to", "the" };
|
||||
|
||||
se.insert( u.end() - 1, v.begin(), v.end() );
|
||||
|
||||
assert( u.encoded_path() == "/path/to/the/file.txt") );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Calls to allocate may throw.
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@return An iterator to one past the last
|
||||
newly inserted element or `before` if
|
||||
the range is empty.
|
||||
|
||||
@param before An iterator before which the
|
||||
new element should be inserted.
|
||||
|
||||
@param first An iterator to the first
|
||||
element to insert.
|
||||
|
||||
@param last An iterator to one past the
|
||||
last element to insert.
|
||||
|
||||
@throw std::invalid_argument invalid percent-encoding
|
||||
*/
|
||||
template<class FwdIt>
|
||||
#ifdef BOOST_URL_DOCS
|
||||
iterator
|
||||
#else
|
||||
typename std::enable_if<
|
||||
is_stringlike<typename
|
||||
std::iterator_traits<
|
||||
FwdIt>::value_type>::value,
|
||||
iterator>::type
|
||||
#endif
|
||||
insert(
|
||||
const_iterator before,
|
||||
FwdIt first,
|
||||
FwdIt last);
|
||||
|
||||
/** Insert a range of segments
|
||||
|
||||
This function inserts a range of
|
||||
percent-encoded strings passed as
|
||||
an initializer-list.
|
||||
Each string must contain a valid
|
||||
percent-encoding or else an exception
|
||||
is thrown.
|
||||
All references and iterators starting
|
||||
from the newly inserted elements and
|
||||
up to and including the last element
|
||||
and @ref end iterators are invalidated.
|
||||
|
||||
@par Requires
|
||||
@code
|
||||
is_stringlike< T >::value == true
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
@code
|
||||
url u = parse_relative_uri( "/path/file.txt" );
|
||||
|
||||
segments se = u.segments();
|
||||
|
||||
se.insert( u.end() - 1, { "to", "the" } );
|
||||
|
||||
assert( u.encoded_path() == "/path/to/the/file.txt") );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Calls to allocate may throw.
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@return An iterator to one past the last
|
||||
newly inserted element or `before` if
|
||||
the range is empty.
|
||||
|
||||
@param before An iterator before which the
|
||||
new elements should be inserted.
|
||||
|
||||
@param init The initializer list containing
|
||||
percent-encoded segments to insert.
|
||||
|
||||
@throw std::invalid_argument invalid percent-encoding
|
||||
*/
|
||||
template<class T>
|
||||
#ifdef BOOST_URL_DOCS
|
||||
iterator
|
||||
#else
|
||||
typename std::enable_if<
|
||||
is_stringlike<T>::value,
|
||||
iterator>::type
|
||||
#endif
|
||||
insert(
|
||||
const_iterator before,
|
||||
std::initializer_list<T> init);
|
||||
|
||||
/** Erase an element
|
||||
|
||||
This function erases the element pointed
|
||||
to by `pos`, which must be a valid
|
||||
iterator for the container.
|
||||
All references and iterators starting
|
||||
from pos and up to and including
|
||||
the last element and @ref end iterators
|
||||
are invalidated.
|
||||
|
||||
@par Preconditions
|
||||
`pos` points to a valid element in
|
||||
this container.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
url u = parse_relative_uri( "/path/to/file.txt" );
|
||||
|
||||
segments se = u.segments();
|
||||
|
||||
se.erase( se.begin() + 1 );
|
||||
|
||||
assert( u.encoded_path() == "/path/file.txt" );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
|
||||
@return An iterator following
|
||||
the last element erased.
|
||||
|
||||
@param pos An iterator to the
|
||||
element to erase.
|
||||
*/
|
||||
inline
|
||||
iterator
|
||||
erase(
|
||||
const_iterator pos) noexcept;
|
||||
|
||||
/** Erase a range of elements
|
||||
|
||||
This function erases the elements
|
||||
in the range `[first, last)`, which
|
||||
must be a valid range in the container.
|
||||
All references and iterators starting
|
||||
from `first` and up to and including
|
||||
the last element and @ref end iterators
|
||||
are invalidated.
|
||||
|
||||
@par Preconditions
|
||||
`[first, last)` is a valid range in
|
||||
this container.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
url u = parse_relative_uri( "/path/to/the/file.txt" );
|
||||
|
||||
segments se = u.segments();
|
||||
|
||||
se.erase( se.begin() + 1, se.begin() + 3 );
|
||||
|
||||
assert( u.encoded_path() == "/path/file.txt" );
|
||||
@endcode
|
||||
|
||||
@return An iterator following
|
||||
the last element erased.
|
||||
|
||||
@param first The beginning of the
|
||||
range to erase.
|
||||
|
||||
@param last The end of the range
|
||||
to erase.
|
||||
|
||||
@throw std::invalid_argument invalid percent-encoding
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
iterator
|
||||
erase(
|
||||
const_iterator first,
|
||||
const_iterator last) noexcept;
|
||||
|
||||
/** Add an element to the end
|
||||
|
||||
This function appends a segment
|
||||
containing the percent-encoded string
|
||||
`s` to the end of the container.
|
||||
The percent-encoding must be valid or
|
||||
else an exception is thrown.
|
||||
All @ref end iterators are invalidated.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
url u = parse_relative_uri( "/path/to" );
|
||||
|
||||
u.segments().push_back( "file.txt" );
|
||||
|
||||
assert( u.encoded_path() == "/path/to/file.txt" );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Calls to allocate may throw.
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@param s The string to add
|
||||
|
||||
@throw std::invalid_argument invalid percent-encoding
|
||||
*/
|
||||
inline
|
||||
void
|
||||
push_back(
|
||||
string_view s);
|
||||
|
||||
/** Add an element to the end
|
||||
|
||||
This function appends a segment
|
||||
containing the percent-encoded stringlike
|
||||
`t` to the end of the container.
|
||||
The percent-encoding must be valid
|
||||
or else an exception is thrown.
|
||||
All @ref end iterators are invalidated.
|
||||
The function participates in overload
|
||||
resolution only if
|
||||
`is_stringlike<T>::value == true`.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
url u = parse_relative_uri( "/path/to" );
|
||||
|
||||
u.segments().push_back( "file.txt" );
|
||||
|
||||
assert( u.encoded_path() == "/path/to/file.txt" );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Calls to allocate may throw.
|
||||
Exceptions thrown on invalid input.
|
||||
|
||||
@param t The stringlike to add
|
||||
|
||||
@throw std::invalid_argument invalid percent-encoding
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_URL_DOCS
|
||||
, class = typename std::enable_if<
|
||||
is_stringlike<T>::value,
|
||||
bool>::type
|
||||
#endif
|
||||
>
|
||||
void
|
||||
push_back(
|
||||
T const& t)
|
||||
{
|
||||
return push_back(
|
||||
to_string_view(t));
|
||||
}
|
||||
|
||||
/** Remove the last element
|
||||
|
||||
This function removes the last element
|
||||
from the container, which must not be
|
||||
empty or else undefined behavior occurs.
|
||||
Iterators and references to
|
||||
the last element, as well as the
|
||||
@ref end iterator, are invalidated.
|
||||
|
||||
@par Preconditions
|
||||
@code
|
||||
not empty()
|
||||
@endcode
|
||||
|
||||
@par Example
|
||||
@code
|
||||
url u = parse_relative_uri( "/path/to/file.txt" );
|
||||
|
||||
u.segments().pop_back();
|
||||
|
||||
assert( u.encoded_path() == "/path/to" );
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
*/
|
||||
inline
|
||||
void
|
||||
pop_back() noexcept;
|
||||
};
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
// VFALCO This include is at the bottom of
|
||||
// url.hpp because of a circular dependency
|
||||
//#include <boost/url/impl/segments.hpp>
|
||||
|
||||
#endif
|
||||
@@ -37,7 +37,6 @@ class segments_encoded_view
|
||||
string_view s_;
|
||||
std::size_t n_;
|
||||
|
||||
template<class Alloc>
|
||||
friend class segments_view;
|
||||
friend class url_view;
|
||||
|
||||
|
||||
@@ -12,50 +12,43 @@
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/string.hpp>
|
||||
#include <boost/url/detail/pct_encoding.hpp>
|
||||
#include <boost/url/rfc/pct_encoded_bnf.hpp>
|
||||
#include <cstddef>
|
||||
#include <iosfwd>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
class segments_encoded_view;
|
||||
|
||||
/** A BidirectionalRange view of read-only path segments with percent-decoding applied
|
||||
*/
|
||||
template<class Allocator>
|
||||
class segments_view
|
||||
{
|
||||
string_view s_;
|
||||
std::size_t n_;
|
||||
Allocator a_;
|
||||
string_value::allocator a_;
|
||||
|
||||
friend class url;
|
||||
friend class url_view;
|
||||
|
||||
template<class Allocator>
|
||||
segments_view(
|
||||
string_view s,
|
||||
std::size_t n,
|
||||
Allocator const& alloc) noexcept
|
||||
Allocator const& a)
|
||||
: s_(s)
|
||||
, n_(n)
|
||||
, a_(alloc)
|
||||
, a_(a)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
class iterator;
|
||||
|
||||
BOOST_URL_DECL
|
||||
segments_view(
|
||||
segments_view const&) noexcept = default;
|
||||
segments_view& operator=(
|
||||
segments_view const&) noexcept = default;
|
||||
segments_view const&) noexcept;
|
||||
|
||||
explicit
|
||||
segments_view(
|
||||
segments_encoded_view const& sv,
|
||||
Allocator const& = {}) noexcept;
|
||||
segments_view& operator=(
|
||||
segments_view const&) noexcept = delete;
|
||||
|
||||
/** Return true if the range contains no elements
|
||||
*/
|
||||
@@ -75,11 +68,13 @@ public:
|
||||
|
||||
/** Return an iterator to the beginning of the range
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
iterator
|
||||
begin() const noexcept;
|
||||
|
||||
/** Return an iterator to the end of the range
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
iterator
|
||||
end() const noexcept;
|
||||
};
|
||||
|
||||
@@ -37,6 +37,7 @@ in a translation unit of the program.
|
||||
#include <boost/url/impl/scheme.ipp>
|
||||
#include <boost/url/impl/segments_encoded.ipp>
|
||||
#include <boost/url/impl/segments_encoded_view.ipp>
|
||||
#include <boost/url/impl/segments_view.ipp>
|
||||
#include <boost/url/impl/static_pool.ipp>
|
||||
#include <boost/url/impl/static_url.ipp>
|
||||
#include <boost/url/impl/url.ipp>
|
||||
|
||||
@@ -21,13 +21,11 @@ namespace urls {
|
||||
*/
|
||||
class basic_static_pool
|
||||
{
|
||||
char* const base_;
|
||||
std::size_t const capacity_;
|
||||
char* begin_;
|
||||
char* end_;
|
||||
char* top_;
|
||||
std::size_t n_ = 0;
|
||||
|
||||
struct item;
|
||||
|
||||
BOOST_URL_DECL
|
||||
void*
|
||||
allocate(
|
||||
@@ -52,9 +50,9 @@ public:
|
||||
basic_static_pool(
|
||||
char* buffer,
|
||||
std::size_t size)
|
||||
: base_(buffer)
|
||||
, capacity_(size)
|
||||
, top_(buffer)
|
||||
: begin_(buffer)
|
||||
, end_(buffer + size)
|
||||
, top_(end_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/type_traits/make_void.hpp>
|
||||
#include <boost/utility/string_view.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
|
||||
#include <string_view>
|
||||
#define BOOST_URL_HAS_STRING_VIEW
|
||||
# include <string_view>
|
||||
# define BOOST_URL_HAS_STRING_VIEW
|
||||
#endif
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
@@ -160,7 +160,54 @@ to_string_view(
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
class string_value : public string_view
|
||||
{
|
||||
struct base;
|
||||
|
||||
base* p_ = nullptr;
|
||||
|
||||
template<class Allocator>
|
||||
base*
|
||||
construct(
|
||||
std::size_t n,
|
||||
Allocator const& a,
|
||||
char*& dest);
|
||||
|
||||
public:
|
||||
class allocator;
|
||||
|
||||
inline
|
||||
~string_value();
|
||||
|
||||
string_value() = default;
|
||||
|
||||
template<class Allocator>
|
||||
string_value(
|
||||
std::size_t n,
|
||||
Allocator const& a,
|
||||
char*& dest);
|
||||
|
||||
template< class Allocator =
|
||||
std::allocator<char> >
|
||||
explicit
|
||||
string_value(
|
||||
string_view s,
|
||||
Allocator const& a = {});
|
||||
|
||||
inline
|
||||
string_value(
|
||||
string_value const& other) noexcept;
|
||||
|
||||
inline
|
||||
string_value&
|
||||
operator=(string_value const& other) noexcept;
|
||||
};
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/impl/string.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <boost/url/ipv4_address.hpp>
|
||||
#include <boost/url/ipv6_address.hpp>
|
||||
#include <boost/url/scheme.hpp>
|
||||
#include <boost/url/segments.hpp>
|
||||
#include <boost/url/segments_encoded.hpp>
|
||||
#include <boost/url/url_view.hpp>
|
||||
#include <boost/url/detail/pct_encoding.hpp>
|
||||
@@ -57,8 +58,9 @@ struct any_path_iter;
|
||||
class BOOST_SYMBOL_VISIBLE url
|
||||
: public url_view
|
||||
{
|
||||
template<class Allocator>
|
||||
friend class urls::segments;
|
||||
friend class segments_encoded;
|
||||
friend class segments_encoded::reference;
|
||||
|
||||
#ifndef BOOST_URL_DOCS
|
||||
protected:
|
||||
@@ -946,43 +948,13 @@ public:
|
||||
|
||||
/** Return a path segment by index
|
||||
|
||||
This function returns an indexed
|
||||
path segment as a percent-encoded
|
||||
string. The behavior depends on
|
||||
`i`:
|
||||
This function returns a zero-based,
|
||||
indexed path segment as a percent-encoded
|
||||
string.
|
||||
|
||||
@li If `i` is 0 the first path
|
||||
segment is returned;
|
||||
|
||||
@li If `i` is positive, then
|
||||
the `i` + 1th path segment is
|
||||
returned. For example if `i == 2`
|
||||
then the third segment is returned.
|
||||
In other words, `i` is zero based.
|
||||
|
||||
@li If `i` is negative, then the
|
||||
function negates `i`, and counts from
|
||||
the end of the path rather than the
|
||||
beginning. For example if `i == -1`
|
||||
then the last path segment is returned.
|
||||
|
||||
If the `i` is out of range, an empty
|
||||
string is returned. To determine the
|
||||
number of segments, call @ref segment_count.
|
||||
|
||||
@par Example
|
||||
@par Preconditions
|
||||
@code
|
||||
url_view u = parse_relative_ref( "/path/to/the/file.txt" );
|
||||
|
||||
assert( u.encoded_segment( -2 ) == "the" );
|
||||
assert( u.encoded_segment( -1 ) == "file.txt" );
|
||||
assert( u.encoded_segment( 0 ) == "path" );
|
||||
assert( u.encoded_segment( 1 ) == "to" );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
path = [ "/" ] segment *( "/" segment )
|
||||
i < segment_count()
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
@@ -998,12 +970,17 @@ public:
|
||||
virtual
|
||||
string_view
|
||||
encoded_segment(
|
||||
int i) const noexcept override;
|
||||
std::size_t i) const noexcept override;
|
||||
|
||||
BOOST_URL_DECL
|
||||
segments_encoded
|
||||
encoded_segments() noexcept;
|
||||
|
||||
template<class Allocator =
|
||||
std::allocator<char>>
|
||||
urls::segments<Allocator>
|
||||
segments(Allocator const& = {}) noexcept;
|
||||
|
||||
//--------------------------------------------
|
||||
//
|
||||
// Query
|
||||
@@ -1237,6 +1214,8 @@ operator<<(std::ostream& os, url const& u);
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#include <boost/url/impl/segments.hpp>
|
||||
#include <boost/url/impl/segments_encoded.hpp>
|
||||
#include <boost/url/impl/url.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <boost/url/ipv4_address.hpp>
|
||||
#include <boost/url/ipv6_address.hpp>
|
||||
#include <boost/url/scheme.hpp>
|
||||
#include <boost/url/segments_encoded_view.hpp>
|
||||
#include <boost/url/segments_view.hpp>
|
||||
#include <boost/url/query_params_view.hpp>
|
||||
#include <boost/url/scheme.hpp>
|
||||
@@ -1344,44 +1345,10 @@ public:
|
||||
|
||||
/** Return a path segment by index
|
||||
|
||||
This function returns an indexed
|
||||
path segment as a percent-encoded
|
||||
string. The behavior depends on
|
||||
`i`:
|
||||
|
||||
@li If `i` is 0 the first path
|
||||
segment is returned;
|
||||
|
||||
@li If `i` is positive, then
|
||||
the `i` + 1th path segment is
|
||||
returned. For example if `i == 2`
|
||||
then the third segment is returned.
|
||||
In other words, `i` is zero based.
|
||||
|
||||
@li If `i` is negative, then the
|
||||
function negates `i`, and counts from
|
||||
the end of the path rather than the
|
||||
beginning. For example if `i == -1`
|
||||
then the last path segment is returned.
|
||||
|
||||
If the `i` is out of range, an empty
|
||||
string is returned. To determine the
|
||||
number of segments, call @ref segment_count.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
url_view u = parse_relative_ref( "/path/to/the/file.txt" );
|
||||
|
||||
assert( u.encoded_segment( -2 ) == "the" );
|
||||
assert( u.encoded_segment( -1 ) == "file.txt" );
|
||||
assert( u.encoded_segment( 0 ) == "path" );
|
||||
assert( u.encoded_segment( 1 ) == "to" );
|
||||
@endcode
|
||||
|
||||
@par BNF
|
||||
@code
|
||||
path = [ "/" ] segment *( "/" segment )
|
||||
@endcode
|
||||
This function returns a zero-based,
|
||||
indexed path segment as a percent-encoded
|
||||
string. If `i >= segment_count()`, an
|
||||
empty string is returned.
|
||||
|
||||
@par Exception Safety
|
||||
Throws nothing.
|
||||
@@ -1396,7 +1363,7 @@ public:
|
||||
virtual
|
||||
string_view
|
||||
encoded_segment(
|
||||
int i) const noexcept;
|
||||
std::size_t i) const noexcept;
|
||||
|
||||
/** Return a path segment by index
|
||||
|
||||
@@ -1502,10 +1469,10 @@ public:
|
||||
*/
|
||||
template<class Allocator =
|
||||
std::allocator<char>>
|
||||
segments_view<Allocator>
|
||||
segments_view
|
||||
segments(Allocator const& alloc = {}) const noexcept
|
||||
{
|
||||
return segments_view<Allocator>(
|
||||
return segments_view(
|
||||
encoded_path(), nseg_, alloc);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user