microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
boost_net.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Jarosław Pelczar <jarek@jpelczar.com>
2//
3// SPDX-License-Identifier: BSD-2-Clause
4
5#pragma once
6
9#include "../microfmt.hpp"
10#include <boost/asio/ip/address.hpp>
11#include <boost/asio/ip/basic_endpoint.hpp>
12#include <cstddef>
13#include <cstdint>
14
15namespace microfmt {
16namespace detail {
17
18inline void format_boost_address_v4(const boost::asio::ip::address_v4 &address, const sink &out) noexcept {
19 const auto bytes = address.to_bytes();
20 microfmt::format_to(out, "{}.{}.{}.{}", bytes[0], bytes[1], bytes[2], bytes[3]);
21}
22
23inline void format_boost_address_v6(const boost::asio::ip::address_v6 &address, const sink &out) noexcept {
24 const auto bytes = address.to_bytes();
25 // NOLINTNEXTLINE(reloco-no-c-array): fixed-size buffer/table for span APIs
26 uint16_t words[8]{};
27 RELOCO_BEGIN_UNSAFE_BUFFER_USAGE;
28 for (std::size_t index = 0; index < 8; ++index) {
29 words[index] = static_cast<uint16_t>((static_cast<uint16_t>(bytes[index * 2]) << 8) | bytes[index * 2 + 1]);
30 }
31
32 std::size_t best_start = 8;
33 std::size_t best_length = 0;
34 for (std::size_t index = 0; index < 8;) {
35 if (words[index] != 0) {
36 ++index;
37 continue;
38 }
39 const std::size_t start = index;
40 while (index < 8 && words[index] == 0) {
41 ++index;
42 }
43 const std::size_t length = index - start;
44 if (length >= 2 && length > best_length) {
45 best_start = start;
46 best_length = length;
47 }
48 }
49
50 for (std::size_t index = 0; index < 8;) {
51 if (index == best_start) {
52 out.write("::");
53 index += best_length;
54 continue;
55 }
56 if (index != 0 && index != best_start + best_length) {
57 out.put(':');
58 }
59 detail::format_unsigned<detail::radix::hex>(out, words[index], false, 0);
60 ++index;
61 }
62 RELOCO_END_UNSAFE_BUFFER_USAGE;
63
64 if (address.scope_id() != 0) {
65 out.put('%');
66 detail::format_unsigned<detail::radix::decimal>(out, address.scope_id(), false, 0);
67 }
68}
69
70} // namespace detail
71
72template <> struct formatter<boost::asio::ip::address_v4> {
73 constexpr void parse(format_parse_context &) noexcept {}
74
75 void format(const boost::asio::ip::address_v4 &address, const sink &out) const noexcept {
77 }
78};
79
80template <> struct formatter<boost::asio::ip::address_v6> {
81 constexpr void parse(format_parse_context &) noexcept {}
82
83 void format(const boost::asio::ip::address_v6 &address, const sink &out) const noexcept {
85 }
86};
87
88template <> struct formatter<boost::asio::ip::address> {
89 constexpr void parse(format_parse_context &) noexcept {}
90
91 void format(const boost::asio::ip::address &address, const sink &out) const noexcept {
92 if (address.is_v4()) {
93 detail::format_boost_address_v4(address.to_v4(), out);
94 } else {
95 detail::format_boost_address_v6(address.to_v6(), out);
96 }
97 }
98};
99
100template <typename InternetProtocol> struct formatter<boost::asio::ip::basic_endpoint<InternetProtocol>> {
101 constexpr void parse(format_parse_context &) noexcept {}
102
103 void format(const boost::asio::ip::basic_endpoint<InternetProtocol> &endpoint, const sink &out) const noexcept {
104 const auto address = endpoint.address();
105 if (address.is_v6()) {
106 out.put('[');
107 detail::format_boost_address_v6(address.to_v6(), out);
108 out.put(']');
109 } else {
110 detail::format_boost_address_v4(address.to_v4(), out);
111 }
112 out.put(':');
113 detail::format_unsigned<detail::radix::decimal>(out, endpoint.port(), false, 0);
114 }
115};
116
117} // namespace microfmt
Definition microfmt.hpp:881
void format_boost_address_v6(const boost::asio::ip::address_v6 &address, const sink &out) noexcept
Definition boost_net.hpp:23
void format_boost_address_v4(const boost::asio::ip::address_v4 &address, const sink &out) noexcept
Definition boost_net.hpp:18
Definition assert.hpp:19
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
RELOCO_CONSTEXPR20 void format_to(const sink &out, microfmt::string_view fmt, const Args &...args) noexcept
Definition microfmt.hpp:1766
constexpr bytes_view bytes(uint64_t count) noexcept
Definition format_helpers.hpp:82
void format(const boost::asio::ip::address &address, const sink &out) const noexcept
Definition boost_net.hpp:91
constexpr void parse(format_parse_context &) noexcept
Definition boost_net.hpp:89
constexpr void parse(format_parse_context &) noexcept
Definition boost_net.hpp:73
void format(const boost::asio::ip::address_v4 &address, const sink &out) const noexcept
Definition boost_net.hpp:75
void format(const boost::asio::ip::address_v6 &address, const sink &out) const noexcept
Definition boost_net.hpp:83
constexpr void parse(format_parse_context &) noexcept
Definition boost_net.hpp:81
void format(const boost::asio::ip::basic_endpoint< InternetProtocol > &endpoint, const sink &out) const noexcept
Definition boost_net.hpp:103
constexpr void parse(format_parse_context &) noexcept
Definition boost_net.hpp:101
Definition microfmt.hpp:985