| |
| #include <charconv> |
| #include <cstdint> |
| #include <iostream> |
| #include <algorithm> |
| #include "fast_float/fast_float.h" |
| |
| char *uint8_to_chars_manual(char *ptr, uint8_t value) { |
| if (value == 0) { |
| *ptr++ = '0'; |
| return ptr; |
| } |
| char *start = ptr; |
| while (value > 0) { |
| *ptr++ = '0' + (value % 10); |
| value /= 10; |
| } |
| // Reverse the digits written so far |
| std::reverse(start, ptr); |
| return ptr; |
| } |
| |
| void uint32_to_ipv4_string(uint32_t ip, char *buffer) { |
| uint8_t octets[4] = {static_cast<uint8_t>(ip >> 24), |
| static_cast<uint8_t>(ip >> 16), |
| static_cast<uint8_t>(ip >> 8), static_cast<uint8_t>(ip)}; |
| |
| char *ptr = buffer; |
| |
| for (int i = 0; i < 4; ++i) { |
| ptr = uint8_to_chars_manual(ptr, octets[i]); |
| |
| if (i < 3) { |
| *ptr++ = '.'; |
| } |
| } |
| *ptr = '\0'; |
| } |
| |
| fastfloat_really_inline uint32_t ipv4_string_to_uint32(const char *str, |
| const char *end) { |
| uint32_t ip = 0; |
| const char *current = str; |
| |
| for (int i = 0; i < 4; ++i) { |
| uint8_t value; |
| auto r = fast_float::from_chars(current, end, value); |
| if (r.ec != std::errc()) { |
| throw std::invalid_argument("Invalid IP address format"); |
| } |
| current = r.ptr; |
| ip = (ip << 8) | value; |
| |
| if (i < 3) { |
| if (current == end || *current++ != '.') { |
| throw std::invalid_argument("Invalid IP address format"); |
| } |
| } |
| } |
| return ip; |
| } |
| |
| bool test_all_ipv4_conversions() { |
| std::cout << "Testing all IPv4 conversions... 0, 1000, 2000, 3000, 4000, " |
| "5000, 6000, 7000, 8000, 9000, ..." |
| << std::endl; |
| char buffer[16]; |
| for (uint64_t ip = 0; ip <= 0xFFFFFFFF; ip += 1000) { |
| if (ip % 10000000 == 0) { |
| std::cout << "." << std::flush; |
| } |
| uint32_to_ipv4_string(static_cast<uint32_t>(ip), buffer); |
| const char *end = buffer + strlen(buffer); |
| uint32_t parsed_ip = ipv4_string_to_uint32(buffer, end); |
| if (parsed_ip != ip) { |
| std::cerr << "Mismatch: original " << ip << ", parsed " << parsed_ip |
| << std::endl; |
| return false; |
| } |
| } |
| std::cout << std::endl; |
| return true; |
| } |
| |
| int main() { |
| if (test_all_ipv4_conversions()) { |
| std::cout << "All IPv4 conversions passed!" << std::endl; |
| return EXIT_SUCCESS; |
| } else { |
| std::cerr << "IPv4 conversion test failed!" << std::endl; |
| return EXIT_FAILURE; |
| } |
| } |