From 120bdfd713e34db69f2a235ff5d2a22e74952a93 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 24 Dec 2025 15:43:43 -0500 Subject: [PATCH] adding some ipv4 test --- tests/CMakeLists.txt | 1 + tests/ipv4_test.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 tests/ipv4_test.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d8ed6f4..a053581 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -94,6 +94,7 @@ endif() option(FASTFLOAT_EXHAUSTIVE "Exhaustive tests" OFF) if (FASTFLOAT_EXHAUSTIVE) + fast_float_add_cpp_test(ipv4_test) fast_float_add_cpp_test(short_random_string) fast_float_add_cpp_test(exhaustive32_midpoint) fast_float_add_cpp_test(random_string) diff --git a/tests/ipv4_test.cpp b/tests/ipv4_test.cpp new file mode 100644 index 0000000..82ddf9c --- /dev/null +++ b/tests/ipv4_test.cpp @@ -0,0 +1,92 @@ + +#include +#include +#include +#include +#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(ip >> 24), + static_cast(ip >> 16), + static_cast(ip >> 8), + static_cast(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(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; + } +} \ No newline at end of file