include/boost/corosio/local_endpoint.hpp

100.0% Lines (15/15) 100.0% List of functions (6/6)
local_endpoint.hpp
f(x) Functions (6)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Michael Vandeberg
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/corosio
8 //
9
10 #ifndef BOOST_COROSIO_LOCAL_ENDPOINT_HPP
11 #define BOOST_COROSIO_LOCAL_ENDPOINT_HPP
12
13 #include <boost/corosio/detail/config.hpp>
14
15 #include <algorithm>
16 #include <compare>
17 #include <cstddef>
18 #include <cstdint>
19 #include <cstring>
20 #include <iosfwd>
21 #include <string_view>
22 #include <system_error>
23
24 namespace boost::corosio {
25
26 /* A Unix domain socket endpoint (filesystem path).
27
28 Stores the path in a fixed-size buffer, avoiding heap
29 allocation. The object is trivially copyable.
30
31 Abstract sockets (Linux-only) are represented by paths whose
32 first character is '\0'. The full path including the leading
33 null byte is stored.
34
35 The library does NOT automatically unlink the socket path on
36 close — callers are responsible for cleanup.
37
38 Thread Safety:
39 Distinct objects: Safe.
40 Shared objects: Safe.
41 */
42 class BOOST_COROSIO_DECL local_endpoint
43 {
44 // sun_path is 108 on Linux, 104 on macOS/FreeBSD. Use the
45 // minimum so local_endpoint is portable across all three.
46 char path_[104]{};
47 std::uint8_t len_ = 0;
48
49 public:
50 /// Maximum path length for a Unix domain socket (excluding null terminator).
51 static constexpr std::size_t max_path_length = 103;
52
53 /// Default constructor. Creates an empty (unbound) endpoint.
54 828x local_endpoint() noexcept = default;
55
56 /** Construct from a path.
57
58 @param path The filesystem path for the socket.
59 Must not exceed @ref max_path_length bytes.
60
61 @throws std::system_error if the path is too long.
62 */
63 explicit local_endpoint(std::string_view path);
64
65 /** Construct from a path (no-throw).
66
67 @param path The filesystem path for the socket.
68 @param ec Set to an error if the path is too long.
69 */
70 local_endpoint(std::string_view path, std::error_code& ec) noexcept;
71
72 /// Return the socket path.
73 52x std::string_view path() const noexcept
74 {
75 52x return std::string_view(path_, len_);
76 }
77
78 /** Check if this is an abstract socket (Linux-only).
79
80 Abstract sockets live in a kernel namespace rather than
81 the filesystem. They are identified by a leading null byte
82 in the path.
83
84 @return `true` if the path starts with '\\0'.
85 */
86 48x bool is_abstract() const noexcept
87 {
88 48x return len_ > 0 && path_[0] == '\0';
89 }
90
91 /// Return true if the endpoint has no path.
92 10x bool empty() const noexcept
93 {
94 10x return len_ == 0;
95 }
96
97 /// Compare endpoints for equality.
98 friend bool
99 4x operator==(local_endpoint const& a, local_endpoint const& b) noexcept
100 {
101 8x return a.len_ == b.len_ &&
102 8x std::memcmp(a.path_, b.path_, a.len_) == 0;
103 }
104
105 /** Format the endpoint for stream output.
106
107 Non-abstract paths are printed as-is. Abstract paths
108 (leading null byte) are printed as `[abstract:name]`.
109 Empty endpoints produce no output.
110 */
111 friend BOOST_COROSIO_DECL std::ostream&
112 operator<<(std::ostream& os, local_endpoint const& ep);
113
114 /// Lexicographic ordering on stored path bytes.
115 friend std::strong_ordering
116 18x operator<=>(local_endpoint const& a, local_endpoint const& b) noexcept
117 {
118 18x auto common = (std::min)(a.len_, b.len_);
119 18x if (int cmp = std::memcmp(a.path_, b.path_, common); cmp != 0)
120 6x return cmp <=> 0;
121 12x return a.len_ <=> b.len_;
122 }
123 };
124
125 } // namespace boost::corosio
126
127 #endif // BOOST_COROSIO_LOCAL_ENDPOINT_HPP
128