VIPA 0.1.0
Header-only C++23 SIMD-assisted IPv4/IPv6 text parser.
Loading...
Searching...
No Matches
ipv4.hxx
Go to the documentation of this file.
1#pragma once
2
3#include <bit>
4#include <cstdint>
5#include <optional>
6#include <string_view>
7
8#include "address.hxx"
9#include "detail/simd.hxx"
10
11namespace llmx::vipa {
12
13namespace detail {
14
16struct IPv4Scan {
18 uint32_t dot_mask{};
19};
20
21#if VIPA_USE_AVX2
28inline auto scan_ipv4_avx2(std::string_view text, IPv4Scan& scan) noexcept
29 -> bool {
30 const auto full_words = text.size() / 4u;
31 const auto load_mask =
32 _mm_setr_epi32(full_words > 0 ? -1 : 0, full_words > 1 ? -1 : 0,
33 full_words > 2 ? -1 : 0, 0);
34 const auto chunk =
35 _mm_maskload_epi32(reinterpret_cast<const int*>(text.data()), load_mask);
36 const auto dots = _mm_cmpeq_epi8(chunk, _mm_set1_epi8('.'));
37
38 const auto full_bytes = full_words * 4u;
39 scan.dot_mask = static_cast<uint32_t>(_mm_movemask_epi8(dots)) &
40 ((uint32_t{1} << full_bytes) - 1u);
41 for (std::size_t i = full_bytes; i < text.size(); ++i) {
42 if (text[i] == '.')
43 scan.dot_mask |= uint32_t{1} << i;
44 }
45 return true;
46}
47#endif
48
50inline auto scan_ipv4_scalar(std::string_view text, IPv4Scan& scan) noexcept
51 -> bool {
52 for (std::size_t i = 0; i < text.size(); ++i) {
53 if (text[i] == '.')
54 scan.dot_mask |= uint32_t{1} << i;
55 }
56 return true;
57}
58
60inline auto scan_ipv4(std::string_view text, IPv4Scan& scan) noexcept -> bool {
61#if VIPA_USE_AVX2
62 return scan_ipv4_avx2(text, scan);
63#else
64 return scan_ipv4_scalar(text, scan);
65#endif
66}
67
74inline auto parse_ipv4_from_scan(std::string_view text, IPv4Scan scan) noexcept
75 -> std::optional<IPv4Address> {
76 if (std::popcount(scan.dot_mask) != 3) {
77 return std::nullopt;
78 }
79
80 IPv4Address out{};
81 std::size_t begin = 0;
82 uint8_t part = 0;
83 uint32_t remaining_dots = scan.dot_mask;
84
85 while (part < 4) {
86 const std::size_t end =
87 remaining_dots == 0 ? text.size() : std::countr_zero(remaining_dots);
88 const std::size_t digits = end - begin;
89 if (digits == 0 || digits > 3)
90 return std::nullopt;
91 if (digits > 1 && text[begin] == '0')
92 return std::nullopt;
93
94 uint32_t value = 0;
95 for (std::size_t i = begin; i < end; ++i) {
96 const char c = text[i];
97 if (c < '0' || c > '9')
98 return std::nullopt;
99 value = value * 10u + static_cast<uint32_t>(c - '0');
100 }
101 if (value > 255u)
102 return std::nullopt;
103
104 out.bytes[part] = static_cast<uint8_t>(value);
105 ++part;
106 if (remaining_dots == 0)
107 break;
108
109 remaining_dots &= remaining_dots - 1u;
110 begin = end + 1;
111 }
112
113 if (part != 4)
114 return std::nullopt;
115 return out;
116}
117
118} // namespace detail
119
129[[nodiscard]] inline auto parse_ipv4(std::string_view text) noexcept
130 -> std::optional<IPv4Address> {
131 if (text.empty() || text.size() > 15) {
132 return std::nullopt;
133 }
134
135 detail::IPv4Scan scan{};
136 if (!detail::scan_ipv4(text, scan))
137 return std::nullopt;
138
139 return detail::parse_ipv4_from_scan(text, scan);
140}
141
147template <std::size_t N>
148[[nodiscard]] inline auto parse_ipv4(const char (&text)[N]) noexcept
149 -> std::optional<IPv4Address> {
150 static_assert(N > 0);
151 const std::size_t length = text[N - 1] == '\0' ? N - 1 : N;
152 return parse_ipv4(std::string_view{text, length});
153}
154
155} // namespace llmx::vipa
Definition classify.hxx:5
auto scan_ipv4_scalar(std::string_view text, IPv4Scan &scan) noexcept -> bool
Scan IPv4 text for dot positions with portable scalar code.
Definition ipv4.hxx:50
auto parse_ipv4_from_scan(std::string_view text, IPv4Scan scan) noexcept -> std::optional< IPv4Address >
Parse IPv4 bytes after dot positions have been collected.
Definition ipv4.hxx:74
auto scan_ipv4(std::string_view text, IPv4Scan &scan) noexcept -> bool
Scan IPv4 text with the best enabled implementation.
Definition ipv4.hxx:60
Definition address.hxx:8
auto parse_ipv4(std::string_view text) noexcept -> std::optional< IPv4Address >
Parse strict dotted-decimal IPv4 text.
Definition ipv4.hxx:129
SIMD feature detection and include for VIPA.
Parsed IPv4 address in network byte order.
Definition address.hxx:14
std::array< uint8_t, 4 > bytes
Definition address.hxx:17
Character-position masks collected while scanning IPv4 text.
Definition ipv4.hxx:16
uint32_t dot_mask
Definition ipv4.hxx:18