roar
Loading...
Searching...
No Matches
ipv6.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <roar/url/ipv6.hpp>
6
7#include <boost/spirit/home/x3.hpp>
8
9namespace Roar::Parser
10{
11 // Only needed for parsing:
13 {
14 std::vector<uint16_t> segmentsBefore{};
15 std::vector<uint16_t> segmentsAfter{};
16 bool endsWithIpv4{false};
17 };
18} // namespace Roar::Parser
19
20BOOST_FUSION_ADAPT_STRUCT(Roar::Parser::Ipv6SegmentContainer, segmentsBefore, segmentsAfter, endsWithIpv4)
21
22namespace Roar::Parser
23{
24 namespace x3 = boost::spirit::x3;
25 using x3::repeat;
26 using x3::lit;
27 using x3::uint_parser;
28 using boost::fusion::at_c;
29
30 struct Ipv6Tag;
31 const auto ipv6 = x3::rule<Ipv6Tag, Ipv6>{"ipv6"};
32
33 // IPv6 (RFC5954), names are directly from the standard for recognition.
34 struct H16Tag;
35 const auto h16 = x3::rule<H16Tag, uint16_t>{"h16"} = uint_parser<uint16_t, 16, 1, 4>{} - ipv4;
36
37 struct Ls32Tag;
38 const auto ls32 = x3::rule<Ls32Tag, Ipv6SegmentContainer>{"ls32"} =
39 ipv4[([](auto& ctx) {
40 _val(ctx).segmentsAfter = _attr(ctx).toIpv6Segments();
41 _val(ctx).endsWithIpv4 = true;
42 })] |
43 (h16 >> ':' >> h16)[([](auto& ctx) {
44 _val(ctx).segmentsAfter.push_back(at_c<0>(_attr(ctx)));
45 _val(ctx).segmentsAfter.push_back(at_c<1>(_attr(ctx)));
46 _val(ctx).endsWithIpv4 = false;
47 })];
48
49 const auto repeatedSegmentSectionActionBefore = [](auto& ctx) {
50 _val(ctx).segmentsBefore = _attr(ctx);
51 };
52 const auto repeatedSegmentSectionActionAfter = [](auto& ctx) {
53 _val(ctx).segmentsAfter = _attr(ctx);
54 };
55 const auto ls32Action = [](auto& ctx) {
56 concatContainers(_val(ctx).segmentsAfter, _attr(ctx).segmentsAfter);
57 _val(ctx).endsWithIpv4 = _attr(ctx).endsWithIpv4;
58 };
59 const auto h16ActionBefore = [](auto& ctx) {
60 _val(ctx).segmentsBefore.push_back(_attr(ctx));
61 };
62 const auto h16ActionAfter = [](auto& ctx) {
63 _val(ctx).segmentsAfter.push_back(_attr(ctx));
64 };
65 struct Ipv6IntermediateTag;
66
67 const auto beforeAbbreviationParser = [](int count) {
68 return repeat(count)[h16 >> ':'][repeatedSegmentSectionActionBefore] >> h16[h16ActionBefore];
69 };
70 const auto afterAbbreviationParser = [](int count) {
71 return (repeat(0, count)[h16 >> ':'][repeatedSegmentSectionActionAfter] >>
74 };
75 const auto abbreviationParser = [](int count) {
76 return "::" >> -afterAbbreviationParser(count);
77 };
78
79#define MAKE_BEFORE_ABBREVIATION_RULE(count) \
80 struct BeforeAbbreviation##count##Tag; \
81 const auto beforeAbbreviation##count = \
82 x3::rule<BeforeAbbreviation##count##Tag, Ipv6SegmentContainer>{"beforeAbbreviation" #count} = \
83 beforeAbbreviationParser(count);
84
93
94#define MAKE_ABBREVIATION_RULE(count) \
95 struct Abbreviation##count##Tag; \
96 const auto abbreviation##count = x3::rule<Abbreviation##count##Tag, Ipv6SegmentContainer>{"abbreviation" #count} = \
97 abbreviationParser(count);
98
106
107 // parses as vector first,
108 // which is later transformed to the proper structure struct Ipv6IntermediateTag;
109 const auto beforeAbbreviationAction = [](auto& ctx) {
110 _val(ctx).segmentsBefore = _attr(ctx).segmentsBefore;
111 };
112 const auto abbreviationAction = [](auto& ctx) {
113 concatContainers(_val(ctx).segmentsAfter, _attr(ctx).segmentsAfter);
114 _val(ctx).endsWithIpv4 = _attr(ctx).endsWithIpv4;
115 };
116 const auto ipv6Intermediate = x3::rule<Ipv6IntermediateTag, Ipv6SegmentContainer>{"ipv6Intermediate"} =
117 beforeAbbreviation7[beforeAbbreviationAction] | (beforeAbbreviation6[beforeAbbreviationAction] >> lit("::")) |
118 (beforeAbbreviation5[beforeAbbreviationAction] >> lit("::") >> -h16[h16ActionAfter]) |
119 (repeat(6)[h16 >> ':'][repeatedSegmentSectionActionBefore] >> ls32[ls32Action]) |
120 (beforeAbbreviation4[beforeAbbreviationAction] >> abbreviation0[abbreviationAction]) |
121 (beforeAbbreviation3[beforeAbbreviationAction] >> abbreviation1[abbreviationAction]) |
122 (beforeAbbreviation2[beforeAbbreviationAction] >> abbreviation2[abbreviationAction]) |
123 (beforeAbbreviation1[beforeAbbreviationAction] >> abbreviation3[abbreviationAction]) |
124 (beforeAbbreviation0[beforeAbbreviationAction] >> abbreviation4[abbreviationAction]) |
125 (abbreviation5[abbreviationAction]) | (abbreviation6[abbreviationAction]);
126
127 const auto ipv6_def = ipv6Intermediate[([](auto& ctx) {
128 decltype(Ipv6::segments) segments{};
129 auto const& segmentsBefore = _attr(ctx).segmentsBefore;
130 auto const& segmentsAfter = _attr(ctx).segmentsAfter;
131
132 // pessimistic check, to avoid segfaults.
133 if (segmentsBefore.size() + segmentsAfter.size() > segments.size())
134 {
135 _pass(ctx) = false;
136 return;
137 }
138
139 for (std::size_t i = 0; i != segmentsBefore.size(); ++i)
140 segments[i] = segmentsBefore[i];
141 for (std::size_t i = 0; i != segmentsAfter.size(); ++i)
142 segments[i + segments.size() - segmentsAfter.size()] = segmentsAfter[i];
143
144 _val(ctx) = Ipv6{
145 .segments = std::move(segments),
146 .endsWithIpv4 = _attr(ctx).endsWithIpv4,
147 };
148 })];
149
151} // namespace Roar::Parser
Definition ipv4.hpp:10
const auto afterAbbreviationParser
Definition ipv6.hpp:70
const auto abbreviationAction
Definition ipv6.hpp:112
const auto abbreviationParser
Definition ipv6.hpp:75
const auto ipv6Intermediate
Definition ipv6.hpp:116
const auto h16
Definition ipv6.hpp:35
const auto repeatedSegmentSectionActionAfter
Definition ipv6.hpp:52
const auto ipv4
Definition ipv4.hpp:12
const auto beforeAbbreviationAction
Definition ipv6.hpp:109
const auto ipv6
Definition ipv6.hpp:31
const auto ls32
Definition ipv6.hpp:38
const auto h16ActionBefore
Definition ipv6.hpp:59
const auto repeatedSegmentSectionActionBefore
Definition ipv6.hpp:49
const auto h16ActionAfter
Definition ipv6.hpp:62
const auto beforeAbbreviationParser
Definition ipv6.hpp:67
BOOST_SPIRIT_DEFINE(ipv4)
const auto ipv6_def
Definition ipv6.hpp:127
const auto ls32Action
Definition ipv6.hpp:55
void concatContainers(ContainerType< ElementType > &lhs, ContainerType< ElementType > const &rhs)
Definition concat_containers.hpp:8
#define MAKE_BEFORE_ABBREVIATION_RULE(count)
Definition ipv6.hpp:79
#define MAKE_ABBREVIATION_RULE(count)
Definition ipv6.hpp:94
Definition ipv6.hpp:12
std::array< uint16_t, 8 > segments
Definition ipv6.hpp:13
std::vector< uint16_t > segmentsAfter
Definition ipv6.hpp:15
std::vector< uint16_t > segmentsBefore
Definition ipv6.hpp:14
bool endsWithIpv4
Definition ipv6.hpp:16