Skip to content

Commit

Permalink
[FOLD] rebase and adjust to new containers
Browse files Browse the repository at this point in the history
  • Loading branch information
alandefreitas committed Oct 5, 2022
1 parent 72a53be commit 559dc25
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 100 deletions.
12 changes: 0 additions & 12 deletions include/boost/url/impl/url.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -139,18 +139,6 @@ reserve_impl(
impl_.cs_ = s_;
}

result<void>
relative(
url_view_base const& base,
url_view_base const& href,
url_base& dest)
{
BOOST_ASSERT(&dest != &base);
BOOST_ASSERT(&dest != &href);
dest.copy(base);
return dest.relative(href);
}

void
url::
cleanup(
Expand Down
42 changes: 23 additions & 19 deletions include/boost/url/impl/url_base.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -1403,28 +1403,32 @@ relative(

// Resolve new path
// 0. Get segments
auto segs0 = dynamic_cast<url_view_base*>(this)->segments();
auto segs1 = href.segments();
auto segs0 = dynamic_cast<url_view_base*>(this)->encoded_segments();
auto segs1 = href.encoded_segments();

// Reference iterators
auto const begin0 = segs0.begin();
auto it0 = begin0;
auto const end0 = segs0.end();
auto const last0 = begin0 != end0 ? std::prev(end0) : end0;

auto const begin1 = segs1.begin();
auto it1 = begin1;
auto const end1 = segs1.end();
auto const last1 = begin1 != end1 ? std::prev(end1) : end1;

// Function to advance the dotdot segments
decode_view dotdot("..");
decode_view dot(".");
pct_string_view dotdot_str("..");
pct_string_view dot_str(".");
decode_view dotdot(dotdot_str);
decode_view dot(dot_str);

auto consume_dots = [dotdot, dot](
segments_view::iterator& first,
segments_view::iterator last)
segments_encoded_view::iterator& first,
segments_encoded_view::iterator last)
{
if (*first == dotdot ||
*first == dot)
if (decode_view(*first) == dotdot ||
decode_view(*first) == dot)
{
++first;
return true;
Expand All @@ -1433,7 +1437,7 @@ relative(
std::size_t l = 1;
while (it != last)
{
if (*it == dotdot)
if (decode_view(*it) == dotdot)
{
if (--l == 0)
{
Expand All @@ -1442,7 +1446,7 @@ relative(
break;
}
}
else if (*it != dot)
else if (decode_view(*it) != dot)
{
++l;
}
Expand All @@ -1460,7 +1464,7 @@ relative(
continue;
if (consume_dots(it1, last1))
continue;
if (*it0 == *it1)
if (decode_view(*it0) == decode_view(*it1))
{
++it0;
++it1;
Expand All @@ -1476,7 +1480,7 @@ relative(
it1 == last1 &&
it0 != end0 &&
it1 != end1 &&
*it0 == *it1)
decode_view(*it0) == decode_view(*it1))
{
// Return empty path
if (href.has_query())
Expand All @@ -1497,12 +1501,12 @@ relative(
{
while (it0 != last0)
{
if (*it0 == dotdot)
if (decode_view(*it0) == dotdot)
{
if (n != 0)
--n;
}
else if (*it0 != dot)
else if (decode_view(*it0) != dot)
{
++n;
}
Expand All @@ -1511,23 +1515,23 @@ relative(
}
set_encoded_path({});
set_path_absolute(false);
segments_encoded segs = encoded_segments();
segments_encoded_ref segs = encoded_segments();
while (n--)
{
segs.push_back(dotdot.encoded());
segs.push_back(dotdot_str);
}

// 3. Append segments left from the reference
while (it1 != end1)
{
if (*it1 == dotdot)
if (decode_view(*it1) == dotdot)
{
if (!segs.empty())
segs.pop_back();
}
else if (*it1 != dot)
else if (decode_view(*it1) != dot)
{
segs.push_back((*it1).encoded());
segs.push_back(*it1);
}
++it1;
}
Expand Down
67 changes: 0 additions & 67 deletions include/boost/url/url.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,73 +410,6 @@ class BOOST_SYMBOL_VISIBLE url

//----------------------------------------------------------

/** Compares two absolute paths and make one relative to the other
This function compares the absolute paths in
two urls. It returns a new url with a relative
path that references the target path relative
to the base path.
Unlike @ref resolve, this function takes
two absolute paths to create a relative
path.
If the input URLs contain schemes and
authorities, these are resolved. If the
schemes and authorities are the same, they
are removed before the relative path is
calculated. If they are different, only
the relative path of the reference URL
is returned.
Given the input base URL, this function
resolves the reference URL as if performing
the following steps:
@li Normalize both URLs
@li Remove the longest common path from both paths
@li Replace each segment in the base path with ".."
@li Append the reference path
This function places the result of the
resolution into `dest`, which can be
any of the url containers that inherit
from @ref url_base.
If the function fails, an error is returned.
@par Example
@code
url dest;
error_code ec;
relative("/relative/sub/foo/sub/file", "/relative/path", dest, ec);
assert( dest.str() == "../../../path" );
@endcode
@par Exception Safety
Basic guarantee.
Calls to allocate may throw.
@param base The base URL to resolve against.
@param href The target URL the relative URL should point to
@param dest The container where the relative result
is written, upon success.
@param ec Set to the error if any occurred.
@see
@ref url,
@ref url_view.
*/
BOOST_URL_DECL
result<void>
relative(
url_view_base const& base,
url_view_base const& href,
url_base& dest);

} // urls
} // boost

Expand Down
80 changes: 80 additions & 0 deletions include/boost/url/url_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2616,6 +2616,13 @@ class BOOST_SYMBOL_VISIBLE
url_view_base const& ref,
url_base& dest);

friend
result<void>
relative(
url_view_base const& base,
url_view_base const& href,
url_base& dest);

private:
//--------------------------------------------
//
Expand Down Expand Up @@ -2768,6 +2775,79 @@ resolve(
return dest.resolve(ref);
}

/** Compares two absolute paths and make one relative to the other
This function compares the absolute paths in
two urls. It returns a new url with a relative
path that references the target path relative
to the base path.
Unlike @ref resolve, this function takes
two absolute paths to create a relative
path.
If the input URLs contain schemes and
authorities, these are resolved. If the
schemes and authorities are the same, they
are removed before the relative path is
calculated. If they are different, only
the relative path of the reference URL
is returned.
Given the input base URL, this function
resolves the reference URL as if performing
the following steps:
@li Normalize both URLs
@li Remove the longest common path from both paths
@li Replace each segment in the base path with ".."
@li Append the reference path
This function places the result of the
resolution into `dest`, which can be
any of the url containers that inherit
from @ref url_base.
If the function fails, an error is returned.
@par Example
@code
url dest;
error_code ec;
relative("/relative/sub/foo/sub/file", "/relative/path", dest, ec);
assert( dest.str() == "../../../path" );
@endcode
@par Exception Safety
Basic guarantee.
Calls to allocate may throw.
@param base The base URL to resolve against.
@param href The target URL the relative URL should point to
@param dest The container where the relative result
is written, upon success.
@param ec Set to the error if any occurred.
@see
@ref url,
@ref url_view.
*/
inline
result<void>
relative(
url_view_base const& base,
url_view_base const& href,
url_base& dest)
{
BOOST_ASSERT(&dest != &href);
if (&dest != &base)
dest.copy(base);
return dest.relative(href);
}

} // urls
} // boost

Expand Down
4 changes: 2 additions & 2 deletions test/unit/url.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -877,13 +877,13 @@ struct url_test
url dest = parse_uri_reference("x/y" ).value();
auto rv = relative(ub, ur, dest);
BOOST_TEST(!rv.has_error());
BOOST_TEST_EQ(dest.string(), e);
BOOST_TEST_EQ(dest.buffer(), e);

// in place
url base( ub );
rv = base.relative( ur );
BOOST_TEST(!rv.has_error());
BOOST_TEST_EQ(base.string(), e);
BOOST_TEST_EQ(base.buffer(), e);
};

// relative URL / absolute paths
Expand Down

0 comments on commit 559dc25

Please sign in to comment.