Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: use spaceship operator in SocketAddress #56059

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 3 additions & 16 deletions src/node_sockaddr-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,22 +172,9 @@ bool SocketAddress::operator!=(const SocketAddress& other) const {
return !(*this == other);
}

bool SocketAddress::operator<(const SocketAddress& other) const {
return compare(other) == CompareResult::LESS_THAN;
}

bool SocketAddress::operator>(const SocketAddress& other) const {
return compare(other) == CompareResult::GREATER_THAN;
}

bool SocketAddress::operator<=(const SocketAddress& other) const {
CompareResult c = compare(other);
return c == CompareResult::NOT_COMPARABLE ? false :
c <= CompareResult::SAME;
}

bool SocketAddress::operator>=(const SocketAddress& other) const {
return compare(other) >= CompareResult::SAME;
std::partial_ordering SocketAddress::operator<=>(
const SocketAddress& other) const {
return compare(other);
}

template <typename T>
Expand Down
65 changes: 30 additions & 35 deletions src/node_sockaddr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,8 @@ bool is_match_ipv4_ipv6(
sizeof(uint32_t)) == 0;
}

SocketAddress::CompareResult compare_ipv4(
const SocketAddress& one,
const SocketAddress& two) {
std::partial_ordering compare_ipv4(const SocketAddress& one,
const SocketAddress& two) {
const sockaddr_in* one_in =
reinterpret_cast<const sockaddr_in*>(one.data());
const sockaddr_in* two_in =
Expand All @@ -165,31 +164,29 @@ SocketAddress::CompareResult compare_ipv4(
const uint32_t s_addr_two = ntohl(two_in->sin_addr.s_addr);

if (s_addr_one < s_addr_two)
return SocketAddress::CompareResult::LESS_THAN;
return std::partial_ordering::less;
else if (s_addr_one == s_addr_two)
return SocketAddress::CompareResult::SAME;
return std::partial_ordering::equivalent;
else
return SocketAddress::CompareResult::GREATER_THAN;
return std::partial_ordering::greater;
}

SocketAddress::CompareResult compare_ipv6(
const SocketAddress& one,
const SocketAddress& two) {
std::partial_ordering compare_ipv6(const SocketAddress& one,
const SocketAddress& two) {
const sockaddr_in6* one_in =
reinterpret_cast<const sockaddr_in6*>(one.data());
const sockaddr_in6* two_in =
reinterpret_cast<const sockaddr_in6*>(two.data());
int ret = memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16);
if (ret < 0)
return SocketAddress::CompareResult::LESS_THAN;
return std::partial_ordering::less;
else if (ret > 0)
return SocketAddress::CompareResult::GREATER_THAN;
return SocketAddress::CompareResult::SAME;
return std::partial_ordering::greater;
return std::partial_ordering::equivalent;
}

SocketAddress::CompareResult compare_ipv4_ipv6(
const SocketAddress& ipv4,
const SocketAddress& ipv6) {
std::partial_ordering compare_ipv4_ipv6(const SocketAddress& ipv4,
const SocketAddress& ipv6) {
const sockaddr_in* ipv4_in =
reinterpret_cast<const sockaddr_in*>(ipv4.data());
const sockaddr_in6 * ipv6_in =
Expand All @@ -199,18 +196,18 @@ SocketAddress::CompareResult compare_ipv4_ipv6(
reinterpret_cast<const uint8_t*>(&ipv6_in->sin6_addr);

if (memcmp(ptr, mask, sizeof(mask)) != 0)
return SocketAddress::CompareResult::NOT_COMPARABLE;
return std::partial_ordering::unordered;

int ret = memcmp(
&ipv4_in->sin_addr,
ptr + sizeof(mask),
sizeof(uint32_t));

if (ret < 0)
return SocketAddress::CompareResult::LESS_THAN;
return std::partial_ordering::less;
else if (ret > 0)
return SocketAddress::CompareResult::GREATER_THAN;
return SocketAddress::CompareResult::SAME;
return std::partial_ordering::greater;
return std::partial_ordering::equivalent;
}

bool in_network_ipv4(
Expand All @@ -235,7 +232,7 @@ bool in_network_ipv6(
// Special case, if prefix == 128, then just do a
// straight comparison.
if (prefix == 128)
return compare_ipv6(ip, net) == SocketAddress::CompareResult::SAME;
return compare_ipv6(ip, net) == std::partial_ordering::equivalent;

uint8_t r = prefix % 8;
int len = (prefix - r) / 8;
Expand Down Expand Up @@ -263,7 +260,7 @@ bool in_network_ipv4_ipv6(
int prefix) {

if (prefix == 128)
return compare_ipv4_ipv6(ip, net) == SocketAddress::CompareResult::SAME;
return compare_ipv4_ipv6(ip, net) == std::partial_ordering::equivalent;

uint8_t r = prefix % 8;
int len = (prefix - r) / 8;
Expand Down Expand Up @@ -293,7 +290,7 @@ bool in_network_ipv6_ipv4(
const SocketAddress& net,
int prefix) {
if (prefix == 32)
return compare_ipv4_ipv6(net, ip) == SocketAddress::CompareResult::SAME;
return compare_ipv4_ipv6(net, ip) == std::partial_ordering::equivalent;

uint32_t m = ((1ull << prefix) - 1) << (32 - prefix);

Expand Down Expand Up @@ -337,8 +334,7 @@ bool SocketAddress::is_match(const SocketAddress& other) const {
return false;
}

SocketAddress::CompareResult SocketAddress::compare(
const SocketAddress& other) const {
std::partial_ordering SocketAddress::compare(const SocketAddress& other) const {
switch (family()) {
case AF_INET:
switch (other.family()) {
Expand All @@ -349,24 +345,23 @@ SocketAddress::CompareResult SocketAddress::compare(
case AF_INET6:
switch (other.family()) {
case AF_INET: {
CompareResult c = compare_ipv4_ipv6(other, *this);
switch (c) {
case SocketAddress::CompareResult::NOT_COMPARABLE:
// Fall through
case SocketAddress::CompareResult::SAME:
return c;
case SocketAddress::CompareResult::GREATER_THAN:
return SocketAddress::CompareResult::LESS_THAN;
case SocketAddress::CompareResult::LESS_THAN:
return SocketAddress::CompareResult::GREATER_THAN;
auto c = compare_ipv4_ipv6(other, *this);
if (c == std::partial_ordering::unordered) {
return std::partial_ordering::unordered;
} else if (c == std::partial_ordering::equivalent) {
return std::partial_ordering::equivalent;
} else if (c == std::partial_ordering::less) {
return std::partial_ordering::greater;
} else if (c == std::partial_ordering::greater) {
return std::partial_ordering::less;
}
break;
}
case AF_INET6: return compare_ipv6(*this, other);
}
break;
}
return SocketAddress::CompareResult::NOT_COMPARABLE;
return std::partial_ordering::unordered;
}

bool SocketAddress::is_in_network(
Expand Down
17 changes: 4 additions & 13 deletions src/node_sockaddr.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
#include "uv.h"
#include "v8.h"

#include <compare>
#include <list>
#include <memory>
#include <string>
#include <list>
#include <unordered_map>

namespace node {
Expand All @@ -22,24 +23,14 @@ class Environment;

class SocketAddress : public MemoryRetainer {
public:
enum class CompareResult {
NOT_COMPARABLE = -2,
LESS_THAN,
SAME,
GREATER_THAN
};

struct Hash {
size_t operator()(const SocketAddress& addr) const;
};

inline bool operator==(const SocketAddress& other) const;
inline bool operator!=(const SocketAddress& other) const;

inline bool operator<(const SocketAddress& other) const;
inline bool operator>(const SocketAddress& other) const;
inline bool operator<=(const SocketAddress& other) const;
inline bool operator>=(const SocketAddress& other) const;
inline std::partial_ordering operator<=>(const SocketAddress& other) const;

inline static bool is_numeric_host(const char* hostname);
inline static bool is_numeric_host(const char* hostname, int family);
Expand Down Expand Up @@ -102,7 +93,7 @@ class SocketAddress : public MemoryRetainer {
bool is_match(const SocketAddress& other) const;

// Compares this SocketAddress to the given other SocketAddress.
CompareResult compare(const SocketAddress& other) const;
std::partial_ordering compare(const SocketAddress& other) const;

// Returns true if this SocketAddress is within the subnet
// identified by the given network address and CIDR prefix.
Expand Down
24 changes: 12 additions & 12 deletions test/cctest/test_sockaddr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -145,19 +145,19 @@ TEST(SocketAddress, Comparison) {
SocketAddress addr5(reinterpret_cast<const sockaddr*>(&storage[4]));
SocketAddress addr6(reinterpret_cast<const sockaddr*>(&storage[5]));

CHECK_EQ(addr1.compare(addr1), SocketAddress::CompareResult::SAME);
CHECK_EQ(addr1.compare(addr2), SocketAddress::CompareResult::LESS_THAN);
CHECK_EQ(addr2.compare(addr1), SocketAddress::CompareResult::GREATER_THAN);
CHECK_EQ(addr1.compare(addr1), std::partial_ordering::equivalent);
CHECK_EQ(addr1.compare(addr2), std::partial_ordering::less);
CHECK_EQ(addr2.compare(addr1), std::partial_ordering::greater);
CHECK(addr1 <= addr1);
CHECK(addr1 < addr2);
CHECK(addr1 <= addr2);
CHECK(addr2 >= addr2);
CHECK(addr2 > addr1);
CHECK(addr2 >= addr1);

CHECK_EQ(addr3.compare(addr3), SocketAddress::CompareResult::SAME);
CHECK_EQ(addr3.compare(addr4), SocketAddress::CompareResult::LESS_THAN);
CHECK_EQ(addr4.compare(addr3), SocketAddress::CompareResult::GREATER_THAN);
CHECK_EQ(addr3.compare(addr3), std::partial_ordering::equivalent);
CHECK_EQ(addr3.compare(addr4), std::partial_ordering::less);
CHECK_EQ(addr4.compare(addr3), std::partial_ordering::greater);
CHECK(addr3 <= addr3);
CHECK(addr3 < addr4);
CHECK(addr3 <= addr4);
Expand All @@ -166,8 +166,8 @@ TEST(SocketAddress, Comparison) {
CHECK(addr4 >= addr3);

// Not comparable
CHECK_EQ(addr1.compare(addr3), SocketAddress::CompareResult::NOT_COMPARABLE);
CHECK_EQ(addr3.compare(addr1), SocketAddress::CompareResult::NOT_COMPARABLE);
CHECK_EQ(addr1.compare(addr3), std::partial_ordering::unordered);
CHECK_EQ(addr3.compare(addr1), std::partial_ordering::unordered);
CHECK(!(addr1 < addr3));
CHECK(!(addr1 > addr3));
CHECK(!(addr1 >= addr3));
Expand All @@ -178,10 +178,10 @@ TEST(SocketAddress, Comparison) {
CHECK(!(addr3 <= addr1));

// Comparable
CHECK_EQ(addr1.compare(addr5), SocketAddress::CompareResult::SAME);
CHECK_EQ(addr2.compare(addr6), SocketAddress::CompareResult::SAME);
CHECK_EQ(addr1.compare(addr6), SocketAddress::CompareResult::LESS_THAN);
CHECK_EQ(addr6.compare(addr1), SocketAddress::CompareResult::GREATER_THAN);
CHECK_EQ(addr1.compare(addr5), std::partial_ordering::equivalent);
CHECK_EQ(addr2.compare(addr6), std::partial_ordering::equivalent);
CHECK_EQ(addr1.compare(addr6), std::partial_ordering::less);
CHECK_EQ(addr6.compare(addr1), std::partial_ordering::greater);
CHECK(addr1 <= addr5);
CHECK(addr1 <= addr6);
CHECK(addr1 < addr6);
Expand Down
Loading