Skip to content

Commit

Permalink
simplify URL comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
alandefreitas committed Dec 22, 2022
1 parent cbcfa6a commit f096d42
Show file tree
Hide file tree
Showing 3 changed files with 239 additions and 28 deletions.
134 changes: 134 additions & 0 deletions include/boost/url/authority_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,140 @@ class BOOST_SYMBOL_VISIBLE
pct_string_view
encoded_host_and_port() const noexcept;

//--------------------------------------------
//
// Comparison
//
//--------------------------------------------

/** Return the result of comparing this with another authority
This function compares two authorities
according to Syntax-Based comparison
algorithm.
@par Exception Safety
Throws nothing.
@return -1 if `*this < other`, 0 if
`this == other`, and 1 if `this > other`.
@par Specification
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2"
>6.2.2 Syntax-Based Normalization (rfc3986)</a>
*/
BOOST_URL_DECL
int
compare(authority_view const& other) const noexcept;

/** Return the result of comparing two authorities
The authorities are compared component
by component as if they were first
normalized.
@par Complexity
Linear in `min( a0.size(), a1.size() )`
@par Exception Safety
Throws nothing
*/
friend
bool
operator==(
authority_view const& a0,
authority_view const& a1) noexcept
{
return a0.compare(a1) == 0;
}

/** Return the result of comparing two authorities
The authorities are compared component
by component as if they were first
normalized.
@par Complexity
Linear in `min( a0.size(), a1.size() )`
@par Exception Safety
Throws nothing
*/
friend
bool
operator!=(
authority_view const& a0,
authority_view const& a1) noexcept
{
return ! (a0 == a1);
}

/** Return the result of comparing two authorities
The authorities are compared component
by component as if they were first
normalized.
@par Complexity
Linear in `min( a0.size(), a1.size() )`
@par Exception Safety
Throws nothing
*/
friend
bool
operator<(
authority_view const& a0,
authority_view const& a1) noexcept
{
return a0.compare(a1) < 0;
}

/** Return the result of comparing two authorities
The authorities are compared component
by component as if they were first
normalized.
@par Complexity
Linear in `min( a0.size(), a1.size() )`
@par Exception Safety
Throws nothing
*/
friend
bool
operator<=(
authority_view const& a0,
authority_view const& a1) noexcept
{
return a0.compare(a1) <= 0;
}

/** Return the result of comparing two authorities
The authorities are compared component
by component as if they were first
normalized.
@par Complexity
Linear in `min( a0.size(), a1.size() )`
@par Exception Safety
Throws nothing
*/
friend
bool
operator>(
authority_view const& a0,
authority_view const& a1) noexcept
{
return a0.compare(a1) > 0;
}

/** Return the result of comparing two authorities
The authorities are compared component
by component as if they were first
normalized.
@par Complexity
Linear in `min( a0.size(), a1.size() )`
@par Exception Safety
Throws nothing
*/
friend
bool
operator>=(
authority_view const& a0,
authority_view const& a1) noexcept
{
return a0.compare(a1) >= 0;
}

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

// hidden friend
Expand Down
61 changes: 61 additions & 0 deletions include/boost/url/impl/authority_view.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,67 @@ parse_authority(
return grammar::parse(s, authority_rule);
}

//------------------------------------------------
//
// Comparisons
//
//------------------------------------------------

int
authority_view::
compare(const authority_view& other) const noexcept
{
auto comp = static_cast<int>(has_userinfo()) -
static_cast<int>(other.has_userinfo());
if ( comp != 0 )
return comp;

if (has_userinfo())
{
comp = detail::compare_encoded(
encoded_user(),
other.encoded_user());
if ( comp != 0 )
return comp;

comp = static_cast<int>(has_password()) -
static_cast<int>(other.has_password());
if ( comp != 0 )
return comp;

if (has_password())
{
comp = detail::compare_encoded(
encoded_password(),
other.encoded_password());
if ( comp != 0 )
return comp;
}
}

comp = detail::ci_compare_encoded(
encoded_host(),
other.encoded_host());
if ( comp != 0 )
return comp;

comp = static_cast<int>(has_port()) -
static_cast<int>(other.has_port());
if ( comp != 0 )
return comp;

if (has_port())
{
comp = detail::compare(
port(),
other.port());
if ( comp != 0 )
return comp;
}

return 0;
}

} // urls
} // boost

Expand Down
72 changes: 44 additions & 28 deletions include/boost/url/impl/url_view_base.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -640,54 +640,70 @@ int
url_view_base::
compare(const url_view_base& other) const noexcept
{
int comp = detail::ci_compare(
scheme(),
other.scheme());
int comp =
static_cast<int>(has_scheme()) -
static_cast<int>(other.has_scheme());
if ( comp != 0 )
return comp;

comp = detail::compare_encoded(
encoded_user(),
other.encoded_user());
if ( comp != 0 )
return comp;

comp = detail::compare_encoded(
encoded_password(),
other.encoded_password());
if ( comp != 0 )
return comp;
if (has_scheme())
{
comp = detail::ci_compare(
scheme(),
other.scheme());
if ( comp != 0 )
return comp;
}

comp = detail::ci_compare_encoded(
encoded_host(),
other.encoded_host());
comp =
static_cast<int>(has_authority()) -
static_cast<int>(other.has_authority());
if ( comp != 0 )
return comp;

comp = detail::compare(
port(),
other.port());
if ( comp != 0 )
return comp;
if (has_authority())
{
comp = authority().compare(other.authority());
if ( comp != 0 )
return comp;
}

comp = detail::segments_compare(
encoded_segments(),
other.encoded_segments());
if ( comp != 0 )
return comp;

comp = detail::compare_encoded(
encoded_query(),
other.encoded_query());
comp =
static_cast<int>(has_query()) -
static_cast<int>(other.has_query());
if ( comp != 0 )
return comp;

comp = detail::compare_encoded(
encoded_fragment(),
other.encoded_fragment());
if (has_query())
{
comp = detail::compare_encoded(
encoded_query(),
other.encoded_query());
if ( comp != 0 )
return comp;
}

comp =
static_cast<int>(has_fragment()) -
static_cast<int>(other.has_fragment());
if ( comp != 0 )
return comp;

if (has_fragment())
{
comp = detail::compare_encoded(
encoded_fragment(),
other.encoded_fragment());
if ( comp != 0 )
return comp;
}

return 0;
}

Expand Down

0 comments on commit f096d42

Please sign in to comment.