|
6 | 6 | #include <cstdint> |
7 | 7 | #include <cmath> |
8 | 8 | #include <locale> |
| 9 | +#include <vector> |
9 | 10 | #include <array> |
10 | 11 | #include <algorithm> |
11 | 12 | #include <optional> |
@@ -55,92 +56,95 @@ auto parse_ipv4_address(std::string_view input) |
55 | 56 | auto validation_error_flag = false; |
56 | 57 | auto validation_error = false; |
57 | 58 |
|
58 | | - std::array<std::string_view, 4> parts; |
59 | | - auto count = 0UL; |
60 | | - for (auto part : split(input, "."sv)) { |
61 | | - if (count >= parts.size()) { |
62 | | - return |
63 | | - std::make_pair( |
64 | | - tl::make_unexpected( |
65 | | - make_error_code( |
66 | | - ipv4_address_errc::too_many_segments)), true); |
| 59 | + std::vector<std::string> parts; |
| 60 | + parts.emplace_back(); |
| 61 | + for (auto ch : input) { |
| 62 | + if (ch == '.') { |
| 63 | + parts.emplace_back(); |
| 64 | + } else { |
| 65 | + parts.back().push_back(ch); |
67 | 66 | } |
| 67 | + } |
68 | 68 |
|
69 | | - parts[count] = part; // NOLINT |
70 | | - ++count; |
| 69 | + if (parts.back().empty()) { |
| 70 | + validation_error_flag = true; |
| 71 | + if (parts.size() > 1) { |
| 72 | + parts.pop_back(); |
| 73 | + } |
71 | 74 | } |
72 | 75 |
|
73 | | - if (count == 0) { |
74 | | - return std::make_pair( |
75 | | - tl::make_unexpected( |
76 | | - make_error_code( |
77 | | - ipv4_address_errc::empty_segment)), true); |
| 76 | + if (parts.size() > 4) { |
| 77 | + return |
| 78 | + std::make_pair( |
| 79 | + tl::make_unexpected( |
| 80 | + make_error_code( |
| 81 | + ipv4_address_errc::too_many_segments)), true); |
78 | 82 | } |
79 | 83 |
|
80 | | - auto numbers = std::array<std::uint64_t, 4>({0, 0, 0, 0}); |
| 84 | + auto numbers = std::vector<std::uint64_t>(); |
81 | 85 |
|
82 | | - for (auto i = 0UL; i < count; ++i) { |
83 | | - auto part = parts[i]; // NOLINT |
| 86 | + for (const auto &part : parts) { |
84 | 87 | if (part.empty()) { |
85 | 88 | return |
86 | | - std::make_pair( |
87 | | - tl::make_unexpected( |
88 | | - make_error_code( |
89 | | - ipv4_address_errc::empty_segment)), true); |
| 89 | + std::make_pair( |
| 90 | + tl::make_unexpected( |
| 91 | + make_error_code( |
| 92 | + ipv4_address_errc::empty_segment)), true); |
90 | 93 | } |
91 | 94 |
|
92 | | - auto number = parse_ipv4_number(part, validation_error_flag); |
| 95 | + auto number = parse_ipv4_number(std::string_view(part), validation_error_flag); |
93 | 96 | if (!number) { |
94 | 97 | return |
95 | | - std::make_pair( |
96 | | - tl::make_unexpected( |
97 | | - make_error_code( |
98 | | - ipv4_address_errc::invalid_segment_number)), validation_error_flag); |
| 98 | + std::make_pair( |
| 99 | + tl::make_unexpected( |
| 100 | + make_error_code( |
| 101 | + ipv4_address_errc::invalid_segment_number)), validation_error_flag); |
99 | 102 | } |
100 | 103 |
|
101 | | - numbers[i] = number.value(); // NOLINT |
| 104 | + numbers.push_back(number.value()); |
102 | 105 | } |
103 | 106 |
|
104 | 107 | if (validation_error_flag) { |
105 | 108 | validation_error = true; |
106 | 109 | } |
107 | 110 |
|
108 | | - constexpr static auto invalid_segment = [] (auto number) { return number > 255; }; |
109 | | - |
110 | | - auto numbers_first = begin(numbers), numbers_last = begin(numbers); |
111 | | - std::advance(numbers_last, count); |
| 111 | + auto numbers_first = begin(numbers), numbers_last = end(numbers); |
112 | 112 |
|
113 | | - auto numbers_it = std::find_if(numbers_first, numbers_last, invalid_segment); |
| 113 | + auto numbers_it = |
| 114 | + std::find_if(numbers_first, numbers_last, |
| 115 | + [](auto number) -> bool { return number > 255; }); |
114 | 116 | if (numbers_it != numbers_last) { |
115 | 117 | validation_error = true; |
116 | 118 | } |
117 | 119 |
|
118 | 120 | auto numbers_last_but_one = numbers_last; |
119 | | - std::advance(numbers_last_but_one, -1); |
| 121 | + --numbers_last_but_one; |
120 | 122 |
|
121 | | - numbers_it = std::find_if(numbers_first, numbers_last_but_one, invalid_segment); |
| 123 | + numbers_it = std::find_if(numbers_first, numbers_last_but_one, |
| 124 | + [](auto number) -> bool { return number > 255; }); |
122 | 125 | if (numbers_it != numbers_last_but_one) { |
123 | 126 | return |
124 | | - std::make_pair( |
125 | | - tl::make_unexpected( |
126 | | - make_error_code(ipv4_address_errc::overflow)), true); |
| 127 | + std::make_pair( |
| 128 | + tl::make_unexpected( |
| 129 | + make_error_code(ipv4_address_errc::overflow)), true); |
127 | 130 | } |
128 | 131 |
|
129 | | - if (numbers[count - 1] >= // NOLINT |
130 | | - static_cast<std::uint64_t>(std::pow(256, 5 - count))) { |
| 132 | + if (numbers.back() >= |
| 133 | + static_cast<std::uint64_t>(std::pow(256, 5 - numbers.size()))) { |
131 | 134 | return |
132 | | - std::make_pair( |
133 | | - tl::make_unexpected( |
134 | | - make_error_code(ipv4_address_errc::overflow)), true); |
| 135 | + std::make_pair( |
| 136 | + tl::make_unexpected( |
| 137 | + make_error_code(ipv4_address_errc::overflow)), true); |
135 | 138 | } |
136 | 139 |
|
137 | | - auto ipv4 = numbers[count - 1]; // NOLINT |
138 | | - --count; |
| 140 | + auto ipv4 = numbers.back(); |
| 141 | + numbers.pop_back(); |
139 | 142 |
|
140 | | - for (auto i = 0UL; i < count; ++i) { |
141 | | - ipv4 += numbers[i] * static_cast<std::uint64_t>(std::pow(256, 3 - i)); // NOLINT |
| 143 | + auto counter = 0UL; |
| 144 | + for (auto number : numbers) { |
| 145 | + ipv4 += number * static_cast<std::uint64_t>(std::pow(256, 3 - counter)); |
| 146 | + ++counter; |
142 | 147 | } |
143 | | - |
144 | 148 | return std::make_pair( |
145 | 149 | ipv4_address(static_cast<unsigned int>(ipv4)), validation_error); |
146 | 150 | } |
|
0 commit comments