include/boost/corosio/local_endpoint.hpp

100.0% Lines (17/17) 100.0% List of functions (6/7) 75.0% Branches (9/12)
local_endpoint.hpp
f(x) Functions (7)
Line Branch 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 @par Thread Safety
39 Distinct objects: Safe.@n
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 7441x char path_[104]{};
47 7441x 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 22323x local_endpoint() noexcept = default;
55
56 /** Construct from a path.
57
58 An over-long path is a precondition violation: the limit is
59 the public @ref max_path_length constant, so callers with
60 runtime-derived paths can check
61 `path.size() <= max_path_length` before constructing.
62
63 @param path The filesystem path for the socket.
64 Must not exceed @ref max_path_length bytes.
65
66 @throws std::system_error `errc::filename_too_long` if the
67 path is too long.
68 */
69 explicit local_endpoint(std::string_view path);
70
71 /** Return the socket path.
72
73 For abstract sockets, the returned view includes the
74 leading null byte.
75
76 @return A view over the stored path bytes.
77 */
78 243x std::string_view path() const noexcept
79 {
80 243x return std::string_view(path_, len_);
81 }
82
83 /** Check if this is an abstract socket (Linux-only).
84
85 Abstract sockets live in a kernel namespace rather than
86 the filesystem. They are identified by a leading null byte
87 in the path.
88
89 @return `true` if the path starts with '\\0'.
90 */
91 222x bool is_abstract() const noexcept
92 {
93
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 221 times.
222x return len_ > 0 && path_[0] == '\0';
94 }
95
96 /// Return true if the endpoint has no path.
97 26x bool empty() const noexcept
98 {
99 26x return len_ == 0;
100 }
101
102 /// Compare endpoints for equality.
103 friend bool
104 9x operator==(local_endpoint const& a, local_endpoint const& b) noexcept
105 {
106
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
9x return a.len_ == b.len_ && std::memcmp(a.path_, b.path_, a.len_) == 0;
107 }
108
109 /** Format the endpoint for stream output.
110
111 Non-abstract paths are printed as-is. Abstract paths
112 (leading null byte) are printed as `[abstract:name]`.
113 Empty endpoints produce no output.
114
115 @param os The output stream.
116 @param ep The endpoint to format.
117
118 @return A reference to @p os.
119 */
120 friend BOOST_COROSIO_DECL std::ostream&
121 operator<<(std::ostream& os, local_endpoint const& ep);
122
123 /// Lexicographic ordering on stored path bytes.
124 friend std::strong_ordering
125 40x operator<=>(local_endpoint const& a, local_endpoint const& b) noexcept
126 {
127
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40x auto common = (std::min)(a.len_, b.len_);
128
3/4
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 25 times.
40x if (int cmp = std::memcmp(a.path_, b.path_, common); cmp != 0)
129 15x return cmp <=> 0;
130 25x return a.len_ <=> b.len_;
131 40x }
132 };
133
134 } // namespace boost::corosio
135
136 #endif // BOOST_COROSIO_LOCAL_ENDPOINT_HPP
137