* [committed 1/5] libstdc++: Optimize net::ip::address_v4::to_string()
@ 2023-02-24 14:28 Jonathan Wakely
2023-02-24 14:28 ` [committed 2/5] libstdc++: Fix conversion to/from net::ip::address_v4::bytes_type Jonathan Wakely
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Jonathan Wakely @ 2023-02-24 14:28 UTC (permalink / raw)
To: libstdc++, gcc-patches
Tested x86_64-linux. Pushed to trunk.
-- >8 --
This is an order of magnitude faster than calling inet_ntop (and not
only because we now avoid allocating a string that is one byte larger
than the SSO buffer).
libstdc++-v3/ChangeLog:
* include/experimental/internet (address_v4::to_string):
Optimize.
* testsuite/experimental/net/internet/address/v4/members.cc:
Check more addresses.
---
libstdc++-v3/include/experimental/internet | 28 +++++++++++++------
.../net/internet/address/v4/members.cc | 11 ++++++++
2 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/libstdc++-v3/include/experimental/internet b/libstdc++-v3/include/experimental/internet
index 707370d5611..08bd0db4bb2 100644
--- a/libstdc++-v3/include/experimental/internet
+++ b/libstdc++-v3/include/experimental/internet
@@ -44,6 +44,7 @@
#include <sstream>
#include <cstdint>
#include <experimental/string_view>
+#include <bits/charconv.h>
#ifdef _GLIBCXX_HAVE_UNISTD_H
# include <unistd.h>
#endif
@@ -241,17 +242,28 @@ namespace ip
__string_with<_Allocator>
to_string(const _Allocator& __a = _Allocator()) const
{
-#ifdef _GLIBCXX_HAVE_ARPA_INET_H
+ auto __write = [__addr = to_uint()](char* __p, size_t __n) {
+ auto __to_chars = [](char* __p, uint8_t __v) {
+ unsigned __n = __v >= 100u ? 3 : __v >= 10u ? 2 : 1;
+ std::__detail::__to_chars_10_impl(__p, __n, __v);
+ return __p + __n;
+ };
+ const auto __begin = __p;
+ __p = __to_chars(__p, uint8_t(__addr >> 24));
+ for (int __i = 2; __i >= 0; __i--) {
+ *__p++ = '.';
+ __p = __to_chars(__p, uint8_t(__addr >> (__i * 8)));
+ }
+ return __p - __begin;
+ };
__string_with<_Allocator> __str(__a);
- __str.resize(INET_ADDRSTRLEN);
- if (inet_ntop(AF_INET, &_M_addr, &__str.front(), __str.size()))
- __str.erase(__str.find('\0'));
- else
- __str.resize(0);
- return __str;
+#if __cpp_lib_string_resize_and_overwrite
+ __str.resize_and_overwrite(15, __write);
#else
- std::__throw_system_error((int)__unsupported_err());
+ __str.resize(15);
+ __str.resize(__write(&__str.front(), 15));
#endif
+ return __str;
}
// static members:
diff --git a/libstdc++-v3/testsuite/experimental/net/internet/address/v4/members.cc b/libstdc++-v3/testsuite/experimental/net/internet/address/v4/members.cc
index df19b11804d..c40a8103664 100644
--- a/libstdc++-v3/testsuite/experimental/net/internet/address/v4/members.cc
+++ b/libstdc++-v3/testsuite/experimental/net/internet/address/v4/members.cc
@@ -22,6 +22,7 @@
#include <experimental/internet>
#include <sstream>
#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
using std::experimental::net::ip::address_v4;
@@ -100,6 +101,16 @@ test04()
VERIFY( address_v4::any().to_string() == "0.0.0.0" );
VERIFY( address_v4::loopback().to_string() == "127.0.0.1" );
VERIFY( address_v4::broadcast().to_string() == "255.255.255.255" );
+ using b = address_v4::bytes_type;
+ VERIFY( address_v4(b(1, 23, 45, 67)).to_string() == "1.23.45.67" );
+ VERIFY( address_v4(b(12, 34, 56, 78)).to_string() == "12.34.56.78" );
+ VERIFY( address_v4(b(123, 4, 5, 6)).to_string() == "123.4.5.6" );
+ VERIFY( address_v4(b(123, 234, 124, 235)).to_string() == "123.234.124.235" );
+
+ __gnu_test::uneq_allocator<char> alloc(123);
+ auto str = address_v4(b(12, 34, 56, 78)).to_string(alloc);
+ VERIFY(str.get_allocator().get_personality() == alloc.get_personality());
+ VERIFY( str == "12.34.56.78" );
}
void
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [committed 2/5] libstdc++: Fix conversion to/from net::ip::address_v4::bytes_type
2023-02-24 14:28 [committed 1/5] libstdc++: Optimize net::ip::address_v4::to_string() Jonathan Wakely
@ 2023-02-24 14:28 ` Jonathan Wakely
2023-02-24 14:28 ` [committed 3/5] libstdc++: Fix members of net::ip::network_v4 Jonathan Wakely
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Jonathan Wakely @ 2023-02-24 14:28 UTC (permalink / raw)
To: libstdc++, gcc-patches
Tested x86_64-linux. Pushed to trunk.
-- >8 --
I messed up the endianness of the address_v4::bytes_type array, which
should always be in network byte order. We can just use bit_cast to
convert the _M_addr member to/from bytes_type.
libstdc++-v3/ChangeLog:
* include/experimental/internet (address_4(const bytes_type&)):
Use __builtin_bit_cast if available, otherwise convert to
network byte order.
(address_v4::to_bytes()): Likewise, but convert from network
byte order.
* testsuite/experimental/net/internet/address/v4/cons.cc: Fix
incorrect tests. Check for constexpr too.
* testsuite/experimental/net/internet/address/v4/creation.cc:
Likewise.
* testsuite/experimental/net/internet/address/v4/members.cc:
Check that bytes_type is a standard-layout type.
---
libstdc++-v3/include/experimental/internet | 20 ++++++++---
.../net/internet/address/v4/cons.cc | 33 ++++++++++++-------
.../net/internet/address/v4/creation.cc | 24 +++++++++++---
.../net/internet/address/v4/members.cc | 3 ++
4 files changed, 60 insertions(+), 20 deletions(-)
diff --git a/libstdc++-v3/include/experimental/internet b/libstdc++-v3/include/experimental/internet
index 08bd0db4bb2..3fd200251fa 100644
--- a/libstdc++-v3/include/experimental/internet
+++ b/libstdc++-v3/include/experimental/internet
@@ -198,7 +198,12 @@ namespace ip
constexpr
address_v4(const bytes_type& __b)
- : _M_addr((__b[0] << 24) | (__b[1] << 16) | (__b[2] << 8) | __b[3])
+#if __has_builtin(__builtin_bit_cast)
+ : _M_addr(__builtin_bit_cast(uint_type, __b))
+#else
+ : _M_addr(_S_hton_32((__b[0] << 24) | (__b[1] << 16)
+ | (__b[2] << 8) | __b[3]))
+#endif
{ }
explicit constexpr
@@ -227,12 +232,17 @@ namespace ip
constexpr bytes_type
to_bytes() const noexcept
{
+#if __has_builtin(__builtin_bit_cast)
+ return __builtin_bit_cast(bytes_type, _M_addr);
+#else
+ auto __host = to_uint();
return bytes_type{
- (_M_addr >> 24) & 0xFF,
- (_M_addr >> 16) & 0xFF,
- (_M_addr >> 8) & 0xFF,
- _M_addr & 0xFF
+ (__host >> 24) & 0xFF,
+ (__host >> 16) & 0xFF,
+ (__host >> 8) & 0xFF,
+ __host & 0xFF
};
+#endif
}
constexpr uint_type
diff --git a/libstdc++-v3/testsuite/experimental/net/internet/address/v4/cons.cc b/libstdc++-v3/testsuite/experimental/net/internet/address/v4/cons.cc
index 65f23642de4..af9fef2215e 100644
--- a/libstdc++-v3/testsuite/experimental/net/internet/address/v4/cons.cc
+++ b/libstdc++-v3/testsuite/experimental/net/internet/address/v4/cons.cc
@@ -24,41 +24,45 @@
using std::experimental::net::ip::address_v4;
-void
+#if __cplusplus < 202002L
+// Naughty, but operator== for std::array is not constexpr until C++20.
+constexpr bool
+operator==(const address_v4::bytes_type& lhs, const address_v4::bytes_type& rhs)
+{
+ return lhs[0] == rhs[0] && lhs[1] == rhs[1]
+ && lhs[2] == rhs[2] && lhs[3] == rhs[3];
+}
+#endif
+
+constexpr void
test01()
{
- bool test __attribute__((unused)) = false;
-
address_v4 a0;
VERIFY( a0.to_uint() == 0 );
VERIFY( a0.to_bytes() == address_v4::bytes_type{} );
}
-void
+constexpr void
test02()
{
- bool test __attribute__((unused)) = false;
-
address_v4 a0{ address_v4::bytes_type{} };
VERIFY( a0.to_uint() == 0 );
VERIFY( a0.to_bytes() == address_v4::bytes_type{} );
address_v4::bytes_type b1{ 1, 2, 3, 4 };
address_v4 a1{ b1 };
- VERIFY( a1.to_uint() == ntohl((1 << 24) | (2 << 16) | (3 << 8) | 4) );
+ VERIFY( a1.to_uint() == ((1 << 24) | (2 << 16) | (3 << 8) | 4) );
VERIFY( a1.to_bytes() == b1 );
}
-void
+constexpr void
test03()
{
- bool test __attribute__((unused)) = false;
-
address_v4 a0{ 0u };
VERIFY( a0.to_uint() == 0 );
VERIFY( a0.to_bytes() == address_v4::bytes_type{} );
- address_v4::uint_type u1 = ntohl((5 << 24) | (6 << 16) | (7 << 8) | 8);
+ address_v4::uint_type u1 = (5 << 24) | (6 << 16) | (7 << 8) | 8;
address_v4 a1{ u1 };
VERIFY( a1.to_uint() == u1 );
VERIFY( a1.to_bytes() == address_v4::bytes_type( 5, 6, 7, 8 ) );
@@ -70,4 +74,11 @@ main()
test01();
test02();
test03();
+
+ constexpr bool c = []{
+ test01();
+ test02();
+ test03();
+ return true;
+ };
}
diff --git a/libstdc++-v3/testsuite/experimental/net/internet/address/v4/creation.cc b/libstdc++-v3/testsuite/experimental/net/internet/address/v4/creation.cc
index 441c832bf54..84aebbb7adc 100644
--- a/libstdc++-v3/testsuite/experimental/net/internet/address/v4/creation.cc
+++ b/libstdc++-v3/testsuite/experimental/net/internet/address/v4/creation.cc
@@ -25,7 +25,17 @@
namespace net = std::experimental::net;
using net::ip::address_v4;
-void
+#if __cplusplus < 202002L
+// Naughty, but operator== for std::array is not constexpr until C++20.
+constexpr bool
+operator==(const address_v4::bytes_type& lhs, const address_v4::bytes_type& rhs)
+{
+ return lhs[0] == rhs[0] && lhs[1] == rhs[1]
+ && lhs[2] == rhs[2] && lhs[3] == rhs[3];
+}
+#endif
+
+constexpr void
test01()
{
auto a0 = make_address_v4( address_v4::bytes_type{} );
@@ -34,18 +44,18 @@ test01()
address_v4::bytes_type b1{ 1, 2, 3, 4 };
auto a1 = make_address_v4( b1 );
- VERIFY( a1.to_uint() == ntohl((1 << 24) | (2 << 16) | (3 << 8) | 4) );
+ VERIFY( a1.to_uint() == ((1 << 24) | (2 << 16) | (3 << 8) | 4) );
VERIFY( a1.to_bytes() == b1 );
}
-void
+constexpr void
test02()
{
auto a0 = net::ip::make_address_v4(0u);
VERIFY( a0.to_uint() == 0 );
VERIFY( a0.to_bytes() == address_v4::bytes_type{} );
- address_v4::uint_type u1 = ntohl((5 << 24) | (6 << 16) | (7 << 8) | 8);
+ address_v4::uint_type u1 = ((5 << 24) | (6 << 16) | (7 << 8) | 8);
auto a1 = net::ip::make_address_v4( u1 );
VERIFY( a1.to_uint() == u1 );
VERIFY( a1.to_bytes() == address_v4::bytes_type( 5, 6, 7, 8 ) );
@@ -84,4 +94,10 @@ main()
test01();
test02();
test03();
+
+ constexpr bool c = []{
+ test01();
+ test02();
+ return true;
+ };
}
diff --git a/libstdc++-v3/testsuite/experimental/net/internet/address/v4/members.cc b/libstdc++-v3/testsuite/experimental/net/internet/address/v4/members.cc
index c40a8103664..ac59405c599 100644
--- a/libstdc++-v3/testsuite/experimental/net/internet/address/v4/members.cc
+++ b/libstdc++-v3/testsuite/experimental/net/internet/address/v4/members.cc
@@ -26,6 +26,9 @@
using std::experimental::net::ip::address_v4;
+static_assert(std::is_standard_layout<address_v4::bytes_type>::value,
+ "net::ip::address_v4::bytes_type is a standard layout type");
+
constexpr bool
test01()
{
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [committed 3/5] libstdc++: Fix members of net::ip::network_v4
2023-02-24 14:28 [committed 1/5] libstdc++: Optimize net::ip::address_v4::to_string() Jonathan Wakely
2023-02-24 14:28 ` [committed 2/5] libstdc++: Fix conversion to/from net::ip::address_v4::bytes_type Jonathan Wakely
@ 2023-02-24 14:28 ` Jonathan Wakely
2023-02-24 14:28 ` [committed 4/5] libstdc++: Make net::ip::basic_endpoint comparisons constexpr Jonathan Wakely
2023-02-24 14:28 ` [committed 5/5] libstdc++: Constrain net::executor constructors Jonathan Wakely
3 siblings, 0 replies; 5+ messages in thread
From: Jonathan Wakely @ 2023-02-24 14:28 UTC (permalink / raw)
To: libstdc++, gcc-patches
Tested x86_64-linux. Pushed to trunk.
-- >8 --
libstdc++-v3/ChangeLog:
* include/experimental/internet (network_v4::netmask()): Avoid
undefined shift.
(network_v4::broadcast()): Optimize and fix for targets with
uint_least32_t wider than 32 bits.
(network_v4::to_string(const Allocator&)): Fix for custom
allocators and optimize using to_chars.
(operator==(const network_v4&, const network_v4&)): Add missing
constexpr.
(operator==(const network_v6&, const network_v6&)): Likewise.
* testsuite/experimental/net/internet/network/v4/cons.cc: New test.
* testsuite/experimental/net/internet/network/v4/members.cc: New test.
---
libstdc++-v3/include/experimental/internet | 41 ++--
.../net/internet/network/v4/cons.cc | 129 ++++++++++++
.../net/internet/network/v4/members.cc | 186 ++++++++++++++++++
3 files changed, 343 insertions(+), 13 deletions(-)
create mode 100644 libstdc++-v3/testsuite/experimental/net/internet/network/v4/cons.cc
create mode 100644 libstdc++-v3/testsuite/experimental/net/internet/network/v4/members.cc
diff --git a/libstdc++-v3/include/experimental/internet b/libstdc++-v3/include/experimental/internet
index 3fd200251fa..5336b8a8ce3 100644
--- a/libstdc++-v3/include/experimental/internet
+++ b/libstdc++-v3/include/experimental/internet
@@ -1219,10 +1219,10 @@ namespace ip
/// @}
- bool
+ constexpr bool
operator==(const network_v4& __a, const network_v4& __b) noexcept;
- bool
+ constexpr bool
operator==(const network_v6& __a, const network_v6& __b) noexcept;
@@ -1263,10 +1263,10 @@ namespace ip
constexpr address_v4
netmask() const noexcept
{
- address_v4::uint_type __val = address_v4::broadcast().to_uint();
- __val >>= (32 - _M_prefix_len);
- __val <<= (32 - _M_prefix_len);
- return address_v4{__val};
+ address_v4 __m;
+ if (_M_prefix_len)
+ __m = address_v4(0xFFFFFFFFu << (32 - _M_prefix_len));
+ return __m;
}
constexpr address_v4
@@ -1275,7 +1275,7 @@ namespace ip
constexpr address_v4
broadcast() const noexcept
- { return address_v4{_M_addr.to_uint() | ~netmask().to_uint()}; }
+ { return address_v4{_M_addr.to_uint() | (0xFFFFFFFFu >> _M_prefix_len)}; }
address_v4_range
hosts() const noexcept
@@ -1306,8 +1306,23 @@ namespace ip
__string_with<_Allocator>
to_string(const _Allocator& __a = _Allocator()) const
{
- return address().to_string(__a) + '/'
- + std::to_string(prefix_length());
+ auto __str = address().to_string(__a);
+ const unsigned __addrlen = __str.length();
+ const unsigned __preflen = prefix_length() >= 10 ? 2 : 1;
+ auto __write = [=](char* __p, size_t __n) {
+ __p[__addrlen] = '/';
+ std::__detail::__to_chars_10_impl(__p + __addrlen + 1, __preflen,
+ (unsigned char)prefix_length());
+ return __n;
+ };
+ const unsigned __len = __addrlen + 1 + __preflen;
+#if __cpp_lib_string_resize_and_overwrite
+ __str.resize_and_overwrite(__len, __write);
+#else
+ __str.resize(__len);
+ __write(&__str.front(), __len);
+#endif
+ return __str;
}
private:
@@ -1379,14 +1394,14 @@ namespace ip
* @{
*/
- inline bool
+ constexpr bool
operator==(const network_v4& __a, const network_v4& __b) noexcept
{
return __a.address() == __b.address()
&& __a.prefix_length() == __b.prefix_length();
}
- inline bool
+ constexpr bool
operator!=(const network_v4& __a, const network_v4& __b) noexcept
{ return !(__a == __b); }
@@ -1396,14 +1411,14 @@ namespace ip
* @{
*/
- inline bool
+ constexpr bool
operator==(const network_v6& __a, const network_v6& __b) noexcept
{
return __a.address() == __b.address()
&& __a.prefix_length() == __b.prefix_length();
}
- inline bool
+ constexpr bool
operator!=(const network_v6& __a, const network_v6& __b) noexcept
{ return !(__a == __b); }
diff --git a/libstdc++-v3/testsuite/experimental/net/internet/network/v4/cons.cc b/libstdc++-v3/testsuite/experimental/net/internet/network/v4/cons.cc
new file mode 100644
index 00000000000..7784b6f6f58
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/net/internet/network/v4/cons.cc
@@ -0,0 +1,129 @@
+// { dg-do run { target c++14 } }
+// { dg-require-effective-target net_ts_ip }
+// { dg-add-options net_ts }
+
+#include <experimental/internet>
+#include <stdexcept>
+#include <testsuite_hooks.h>
+
+using std::experimental::net::ip::network_v4;
+using std::experimental::net::ip::address_v4;
+
+constexpr void
+test01()
+{
+ network_v4 n0;
+ VERIFY( n0.address().is_unspecified() );
+ VERIFY( n0.prefix_length() == 0 );
+}
+
+constexpr void
+test02()
+{
+ address_v4 a0;
+ network_v4 n0{ a0, 0 };
+ VERIFY( n0.address() == a0 );
+ VERIFY( n0.prefix_length() == 0 );
+
+ address_v4 a1{ address_v4::bytes_type{ 1, 2, 3, 4 } };
+ network_v4 n1{ a1, 12};
+ VERIFY( n1.address() == a1 );
+ VERIFY( n1.prefix_length() == 12 );
+}
+
+void
+test02_errors()
+{
+ address_v4 a0;
+ try
+ {
+ network_v4{a0, -1};
+ VERIFY(false);
+ }
+ catch(const std::out_of_range&)
+ {
+ }
+
+ try
+ {
+ network_v4{a0, 33};
+ VERIFY(false);
+ }
+ catch(const std::out_of_range&)
+ {
+ }
+}
+
+constexpr void
+test03()
+{
+ address_v4 a0;
+ network_v4 n0{ a0, a0 };
+ VERIFY( n0.address() == a0 );
+ VERIFY( n0.prefix_length() == 0 );
+
+ address_v4 a1{ address_v4::bytes_type{ 1, 2, 3, 4 } };
+ network_v4 n1{ a1, address_v4::broadcast() };
+ VERIFY( n1.address() == a1 );
+ VERIFY( n1.prefix_length() == 32 );
+
+ network_v4 n2{ a1, address_v4::bytes_type(128, 0, 0, 0) };
+ VERIFY( n2.address() == a1 );
+ VERIFY( n2.prefix_length() == 1 );
+
+ network_v4 n3{ a1, address_v4::bytes_type(255, 255, 255, 192) };
+ VERIFY( n3.address() == a1 );
+ VERIFY( n3.prefix_length() == 26 );
+}
+
+void
+test03_errors()
+{
+ address_v4 a0;
+ try
+ {
+ // Contains non-contiguous non-zero bits.
+ network_v4{a0, address_v4::bytes_type(255, 1, 0, 0)};
+ VERIFY(false);
+ }
+ catch(const std::invalid_argument&)
+ {
+ }
+
+ try
+ {
+ // Most significant bit is zero and any other bits are non-zero.
+ network_v4{a0, address_v4::bytes_type(1, 0, 0, 0)};
+ VERIFY(false);
+ }
+ catch(const std::invalid_argument&)
+ {
+ }
+
+ try
+ {
+ // Most significant bit is zero and any other bits are non-zero.
+ network_v4{a0, address_v4::bytes_type(0, 1, 0, 0)};
+ VERIFY(false);
+ }
+ catch(const std::invalid_argument&)
+ {
+ }
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test02_errors();
+ test03();
+ test03_errors();
+
+ constexpr bool c = []{
+ test01();
+ test02();
+ test03();
+ return true;
+ };
+}
diff --git a/libstdc++-v3/testsuite/experimental/net/internet/network/v4/members.cc b/libstdc++-v3/testsuite/experimental/net/internet/network/v4/members.cc
new file mode 100644
index 00000000000..3ea65862649
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/net/internet/network/v4/members.cc
@@ -0,0 +1,186 @@
+// { dg-do run { target c++14 } }
+// { dg-require-effective-target net_ts_ip }
+// { dg-add-options net_ts }
+
+#include <experimental/internet>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using std::experimental::net::ip::network_v4;
+using std::experimental::net::ip::address_v4;
+
+constexpr void
+test_netmask()
+{
+ network_v4 n0;
+ VERIFY( n0.netmask() == address_v4() );
+
+ network_v4 n1({}, 1);
+ VERIFY( n1.netmask() == address_v4(address_v4::bytes_type(128)) );
+
+ network_v4 n2({}, 2);
+ VERIFY( n2.netmask() == address_v4(address_v4::bytes_type(192)) );
+
+ network_v4 n3({}, 3);
+ VERIFY( n3.netmask() == address_v4(address_v4::bytes_type(224)) );
+
+ network_v4 n4({}, 17);
+ VERIFY( n4.netmask() == address_v4(address_v4::bytes_type(255, 255, 128)) );
+}
+
+constexpr void
+test_network()
+{
+ network_v4 n0;
+ VERIFY( n0.network() == address_v4() );
+
+ network_v4 n1(address_v4::bytes_type{1, 2, 3, 4}, 1);
+ VERIFY( n1.network() == address_v4(address_v4::bytes_type(0, 0, 0, 0)) );
+
+ network_v4 n2(address_v4::bytes_type{1, 2, 3, 4}, 8);
+ VERIFY( n2.network() == address_v4(address_v4::bytes_type(1, 0, 0, 0)) );
+
+ network_v4 n3(address_v4::bytes_type{1, 2, 3, 4}, 15);
+ VERIFY( n3.network() == address_v4(address_v4::bytes_type(1, 2, 0, 0)) );
+
+ network_v4 n4(address_v4::bytes_type{1, 2, 3, 4}, 16);
+ VERIFY( n4.network() == address_v4(address_v4::bytes_type(1, 2, 0, 0)) );
+
+ network_v4 n5(address_v4::bytes_type{1, 2, 3, 4}, 23);
+ VERIFY( n5.network() == address_v4(address_v4::bytes_type(1, 2, 2, 0)) );
+
+ network_v4 n6(address_v4::bytes_type{1, 2, 3, 4}, 24);
+ VERIFY( n6.network() == address_v4(address_v4::bytes_type(1, 2, 3, 0)) );
+
+ network_v4 n7(address_v4::bytes_type{1, 2, 3, 4}, 29);
+ VERIFY( n7.network() == address_v4(address_v4::bytes_type(1, 2, 3, 0)) );
+
+ network_v4 n8(address_v4::bytes_type{1, 2, 3, 4}, 30);
+ VERIFY( n8.network() == address_v4(address_v4::bytes_type(1, 2, 3, 4)) );
+
+ network_v4 n9(address_v4::bytes_type{1, 2, 3, 4}, 32);
+ VERIFY( n9.network() == address_v4(address_v4::bytes_type(1, 2, 3, 4)) );
+}
+
+constexpr void
+test_broadcast()
+{
+ using b = address_v4::bytes_type;
+
+ network_v4 n0;
+ VERIFY( n0.broadcast() == address_v4::broadcast() );
+
+ network_v4 n1(b{1, 2, 3, 4}, 1);
+ VERIFY( n1.broadcast() == address_v4(b(127, 255, 255, 255)) );
+
+ network_v4 n2(b{1, 2, 3, 4}, 8);
+ VERIFY( n2.broadcast() == address_v4(b(1, 255, 255, 255)) );
+
+ network_v4 n3(b{1, 2, 3, 4}, 15);
+ VERIFY( n3.broadcast() == address_v4(b(1, 3, 255, 255)) );
+
+ network_v4 n4(b{1, 2, 3, 4}, 16);
+ VERIFY( n4.broadcast() == address_v4(b(1, 2, 255, 255)) );
+
+ network_v4 n5(b{1, 2, 3, 4}, 23);
+ VERIFY( n5.broadcast() == address_v4(b(1, 2, 3, 255)) );
+
+ network_v4 n6(b{1, 2, 3, 4}, 24);
+ VERIFY( n6.broadcast() == address_v4(b(1, 2, 3, 255)) );
+
+ network_v4 n7(b{1, 2, 3, 4}, 29);
+ VERIFY( n7.broadcast() == address_v4(b(1, 2, 3, 7)) );
+
+ network_v4 n8(b{1, 2, 3, 4}, 30);
+ VERIFY( n8.broadcast() == address_v4(b(1, 2, 3, 7)) );
+
+ network_v4 n9(b{1, 2, 3, 4}, 31);
+ VERIFY( n9.broadcast() == address_v4(b(1, 2, 3, 5)) );
+
+ network_v4 n10(b{1, 2, 3, 4}, 32);
+ VERIFY( n10.broadcast() == address_v4(b(1, 2, 3, 4)) );
+}
+
+constexpr void
+test_canonical()
+{
+ network_v4 n0;
+ VERIFY( n0.canonical() == network_v4(n0.network(), n0.prefix_length()) );
+
+ network_v4 n1(address_v4::bytes_type{1, 2, 3, 4}, 1);
+ VERIFY( n1.canonical() == network_v4(n1.network(), n1.prefix_length()) );
+
+ network_v4 n2(address_v4::bytes_type{1, 2, 3, 4}, 8);
+ VERIFY( n2.canonical() == network_v4(n2.network(), n2.prefix_length()) );
+
+ network_v4 n3(address_v4::bytes_type{1, 2, 3, 4}, 15);
+ VERIFY( n3.canonical() == network_v4(n3.network(), n3.prefix_length()) );
+
+ network_v4 n4(address_v4::bytes_type{1, 2, 3, 4}, 16);
+ VERIFY( n4.canonical() == network_v4(n4.network(), n4.prefix_length()) );
+
+ network_v4 n5(address_v4::bytes_type{1, 2, 3, 4}, 23);
+ VERIFY( n5.canonical() == network_v4(n5.network(), n5.prefix_length()) );
+
+ network_v4 n6(address_v4::bytes_type{1, 2, 3, 4}, 24);
+ VERIFY( n6.canonical() == network_v4(n6.network(), n6.prefix_length()) );
+
+ network_v4 n7(address_v4::bytes_type{1, 2, 3, 4}, 29);
+ VERIFY( n7.canonical() == network_v4(n7.network(), n7.prefix_length()) );
+
+ network_v4 n8(address_v4::bytes_type{1, 2, 3, 4}, 30);
+ VERIFY( n8.canonical() == network_v4(n8.network(), n8.prefix_length()) );
+
+ network_v4 n9(address_v4::bytes_type{1, 2, 3, 4}, 32);
+ VERIFY( n9.canonical() == network_v4(n9.network(), n9.prefix_length()) );
+}
+
+constexpr void
+test_is_host()
+{
+ network_v4 n0;
+ VERIFY( ! n0.is_host() );
+
+ network_v4 n1(address_v4::bytes_type{1, 2, 3, 4}, 1);
+ VERIFY( ! n1.is_host() );
+
+ network_v4 n2(address_v4::bytes_type{1, 2, 3, 4}, 8);
+ VERIFY( ! n2.is_host() );
+
+ network_v4 n3(address_v4::bytes_type{1, 2, 3, 4}, 32);
+ VERIFY( n3.is_host() );
+}
+
+void
+test_to_string()
+{
+ using b = address_v4::bytes_type;
+ __gnu_test::uneq_allocator<char> alloc(123);
+ auto str = network_v4(address_v4(b(12, 34, 56, 78)), 24).to_string(alloc);
+ VERIFY(str.get_allocator().get_personality() == alloc.get_personality());
+ VERIFY( str == "12.34.56.78/24" );
+
+ __gnu_test::uneq_allocator<char> alloc2(99);
+ auto str2 = network_v4(address_v4(b(87, 65, 43, 21)), 4).to_string(alloc2);
+ VERIFY(str2.get_allocator().get_personality() == alloc2.get_personality());
+ VERIFY( str2 == "87.65.43.21/4" );
+}
+
+int main()
+{
+ test_netmask();
+ test_network();
+ test_broadcast();
+ test_canonical();
+ test_is_host();
+ test_to_string();
+
+ constexpr bool c = []{
+ test_netmask();
+ test_network();
+ test_broadcast();
+ test_canonical();
+ test_is_host();
+ return true;
+ };
+}
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [committed 4/5] libstdc++: Make net::ip::basic_endpoint comparisons constexpr
2023-02-24 14:28 [committed 1/5] libstdc++: Optimize net::ip::address_v4::to_string() Jonathan Wakely
2023-02-24 14:28 ` [committed 2/5] libstdc++: Fix conversion to/from net::ip::address_v4::bytes_type Jonathan Wakely
2023-02-24 14:28 ` [committed 3/5] libstdc++: Fix members of net::ip::network_v4 Jonathan Wakely
@ 2023-02-24 14:28 ` Jonathan Wakely
2023-02-24 14:28 ` [committed 5/5] libstdc++: Constrain net::executor constructors Jonathan Wakely
3 siblings, 0 replies; 5+ messages in thread
From: Jonathan Wakely @ 2023-02-24 14:28 UTC (permalink / raw)
To: libstdc++, gcc-patches
Tested x86_64-linux. Pushed to trunk.
-- >8 --
libstdc++-v3/ChangeLog:
* include/experimental/internet (basic_endpoint): Add missing
constexpr to comparison operators.
* testsuite/experimental/net/internet/endpoint/cons.cc: New test.
---
libstdc++-v3/include/experimental/internet | 12 ++--
.../net/internet/endpoint/cons.cc | 66 +++++++++++++++++++
2 files changed, 72 insertions(+), 6 deletions(-)
create mode 100644 libstdc++-v3/testsuite/experimental/net/internet/endpoint/cons.cc
diff --git a/libstdc++-v3/include/experimental/internet b/libstdc++-v3/include/experimental/internet
index 5336b8a8ce3..cae07f466da 100644
--- a/libstdc++-v3/include/experimental/internet
+++ b/libstdc++-v3/include/experimental/internet
@@ -1626,19 +1626,19 @@ namespace ip
*/
template<typename _InternetProtocol>
- inline bool
+ constexpr bool
operator==(const basic_endpoint<_InternetProtocol>& __a,
const basic_endpoint<_InternetProtocol>& __b)
{ return __a.address() == __b.address() && __a.port() == __b.port(); }
template<typename _InternetProtocol>
- inline bool
+ constexpr bool
operator!=(const basic_endpoint<_InternetProtocol>& __a,
const basic_endpoint<_InternetProtocol>& __b)
{ return !(__a == __b); }
template<typename _InternetProtocol>
- inline bool
+ constexpr bool
operator< (const basic_endpoint<_InternetProtocol>& __a,
const basic_endpoint<_InternetProtocol>& __b)
{
@@ -1647,19 +1647,19 @@ namespace ip
}
template<typename _InternetProtocol>
- inline bool
+ constexpr bool
operator> (const basic_endpoint<_InternetProtocol>& __a,
const basic_endpoint<_InternetProtocol>& __b)
{ return __b < __a; }
template<typename _InternetProtocol>
- inline bool
+ constexpr bool
operator<=(const basic_endpoint<_InternetProtocol>& __a,
const basic_endpoint<_InternetProtocol>& __b)
{ return !(__b < __a); }
template<typename _InternetProtocol>
- inline bool
+ constexpr bool
operator>=(const basic_endpoint<_InternetProtocol>& __a,
const basic_endpoint<_InternetProtocol>& __b)
{ return !(__a < __b); }
diff --git a/libstdc++-v3/testsuite/experimental/net/internet/endpoint/cons.cc b/libstdc++-v3/testsuite/experimental/net/internet/endpoint/cons.cc
new file mode 100644
index 00000000000..1b5c92c0b58
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/net/internet/endpoint/cons.cc
@@ -0,0 +1,66 @@
+// { dg-do run { target c++14 } }
+// { dg-require-effective-target net_ts_ip }
+// { dg-add-options net_ts }
+
+#include <experimental/internet>
+#include <testsuite_hooks.h>
+
+using namespace std::experimental::net;
+
+constexpr void
+test_default()
+{
+ ip::tcp::endpoint t1;
+ VERIFY( t1.protocol() == ip::tcp::v4() );
+ VERIFY( t1.address() == ip::address() );
+ VERIFY( t1.port() == 0 );
+
+ ip::udp::endpoint t2;
+ VERIFY( t2.protocol() == ip::udp::v4() );
+ VERIFY( t2.address() == ip::address() );
+ VERIFY( t2.port() == 0 );
+}
+
+constexpr void
+test_proto()
+{
+ ip::tcp::endpoint t1(ip::tcp::v4(), 22);
+ VERIFY( t1.protocol() == ip::tcp::v4() );
+ VERIFY( t1.address() == ip::address_v4() );
+ VERIFY( t1.port() == 22 );
+
+ ip::tcp::endpoint t2(ip::tcp::v6(), 80);
+ VERIFY( t2.protocol() == ip::tcp::v6() );
+ VERIFY( t2.address() == ip::address_v6() );
+ VERIFY( t2.port() == 80 );
+}
+
+constexpr void
+test_addr()
+{
+ ip::address_v4 a1(ip::address_v4::bytes_type(1, 2, 3, 4));
+ ip::tcp::endpoint t1(a1, 22);
+ VERIFY( t1.protocol() == ip::tcp::v4() );
+ VERIFY( t1.address() == a1 );
+ VERIFY( t1.port() == 22 );
+
+ ip::address_v6 a2(ip::address_v6::bytes_type(21,22,23,24,25,26,27,28,29));
+ ip::tcp::endpoint t2(a2, 80);
+ VERIFY( t2.protocol() == ip::tcp::v6() );
+ VERIFY( t2.address() == a2 );
+ VERIFY( t2.port() == 80 );
+}
+
+int main()
+{
+ test_default();
+ test_proto();
+ test_addr();
+
+ constexpr bool c = [] {
+ test_default();
+ test_proto();
+ test_addr();
+ return true;
+ };
+}
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [committed 5/5] libstdc++: Constrain net::executor constructors
2023-02-24 14:28 [committed 1/5] libstdc++: Optimize net::ip::address_v4::to_string() Jonathan Wakely
` (2 preceding siblings ...)
2023-02-24 14:28 ` [committed 4/5] libstdc++: Make net::ip::basic_endpoint comparisons constexpr Jonathan Wakely
@ 2023-02-24 14:28 ` Jonathan Wakely
3 siblings, 0 replies; 5+ messages in thread
From: Jonathan Wakely @ 2023-02-24 14:28 UTC (permalink / raw)
To: libstdc++, gcc-patches
Tested x86_64-linux. Pushed to trunk.
-- >8 --
The TS says the arguments to these constructors shall meet the Executor
requirements, so it's undefined if they don't. Constraining on a subset
of those requirements won't affect valid cases, but prevents the
majority of invalid cases from trying to instantiate the constructor.
This prevents the non-explicit executor(Executor) constructor being a
candidate anywhere that a net::executor could be constructed e.g.
comparing ip::tcp::v4() == ip::udp::v4() would try to convert both
operands to executor using that constructor, then compare then using
operator==(const executor&, const executor&).
libstdc++-v3/ChangeLog:
* include/experimental/executor (executor): Constrain template
constructors.
---
libstdc++-v3/include/experimental/executor | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/libstdc++-v3/include/experimental/executor b/libstdc++-v3/include/experimental/executor
index cd75d99ddb3..1dae8925916 100644
--- a/libstdc++-v3/include/experimental/executor
+++ b/libstdc++-v3/include/experimental/executor
@@ -1012,6 +1012,9 @@ inline namespace v1
class executor
{
+ template<typename _Executor>
+ using _Context_t = decltype(std::declval<_Executor&>().context());
+
public:
// construct / copy / destroy:
@@ -1021,12 +1024,14 @@ inline namespace v1
executor(const executor&) noexcept = default;
executor(executor&&) noexcept = default;
- template<typename _Executor>
+ template<typename _Executor,
+ typename = _Require<is_lvalue_reference<_Context_t<_Executor>>>>
executor(_Executor __e)
: _M_target(make_shared<_Tgt1<_Executor>>(std::move(__e)))
{ }
- template<typename _Executor, typename _ProtoAlloc>
+ template<typename _Executor, typename _ProtoAlloc,
+ typename = _Require<is_lvalue_reference<_Context_t<_Executor>>>>
executor(allocator_arg_t, const _ProtoAlloc& __a, _Executor __e)
: _M_target(allocate_shared<_Tgt2<_Executor, _ProtoAlloc>>(__a,
std::move(__e), __a))
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-02-24 14:28 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-24 14:28 [committed 1/5] libstdc++: Optimize net::ip::address_v4::to_string() Jonathan Wakely
2023-02-24 14:28 ` [committed 2/5] libstdc++: Fix conversion to/from net::ip::address_v4::bytes_type Jonathan Wakely
2023-02-24 14:28 ` [committed 3/5] libstdc++: Fix members of net::ip::network_v4 Jonathan Wakely
2023-02-24 14:28 ` [committed 4/5] libstdc++: Make net::ip::basic_endpoint comparisons constexpr Jonathan Wakely
2023-02-24 14:28 ` [committed 5/5] libstdc++: Constrain net::executor constructors Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).