1+
2+ #include < charconv>
3+ #include < cstdint>
4+ #include < iostream>
5+ #include < algorithm>
6+ #include " fast_float/fast_float.h"
7+
8+ char * uint8_to_chars_manual (char * ptr, uint8_t value) {
9+ if (value == 0 ) {
10+ *ptr++ = ' 0' ;
11+ return ptr;
12+ }
13+ char * start = ptr;
14+ while (value > 0 ) {
15+ *ptr++ = ' 0' + (value % 10 );
16+ value /= 10 ;
17+ }
18+ // Reverse the digits written so far
19+ std::reverse (start, ptr);
20+ return ptr;
21+ }
22+
23+ void uint32_to_ipv4_string (uint32_t ip, char * buffer) {
24+ uint8_t octets[4 ] = {
25+ static_cast <uint8_t >(ip >> 24 ),
26+ static_cast <uint8_t >(ip >> 16 ),
27+ static_cast <uint8_t >(ip >> 8 ),
28+ static_cast <uint8_t >(ip)
29+ };
30+
31+ char * ptr = buffer;
32+
33+ for (int i = 0 ; i < 4 ; ++i) {
34+ ptr = uint8_to_chars_manual (ptr, octets[i]);
35+
36+ if (i < 3 ) {
37+ *ptr++ = ' .' ;
38+ }
39+ }
40+ *ptr = ' \0 ' ;
41+ }
42+
43+ fastfloat_really_inline uint32_t ipv4_string_to_uint32 (const char * str, const char * end) {
44+ uint32_t ip = 0 ;
45+ const char * current = str;
46+
47+ for (int i = 0 ; i < 4 ; ++i) {
48+ uint8_t value;
49+ auto r = fast_float::from_chars (current, end, value);
50+ if (r.ec != std::errc ()) {
51+ throw std::invalid_argument (" Invalid IP address format" );
52+ }
53+ current = r.ptr ;
54+ ip = (ip << 8 ) | value;
55+
56+ if (i < 3 ) {
57+ if (current == end || *current++ != ' .' ) {
58+ throw std::invalid_argument (" Invalid IP address format" );
59+ }
60+ }
61+ }
62+ return ip;
63+ }
64+
65+ bool test_all_ipv4_conversions () {
66+ std::cout << " Testing all IPv4 conversions... 0, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, ..." << std::endl;
67+ char buffer[16 ];
68+ for (uint64_t ip = 0 ; ip <= 0xFFFFFFFF ; ip+=1000 ) {
69+ if (ip % 10000000 == 0 ) {
70+ std::cout << " ." << std::flush;
71+ }
72+ uint32_to_ipv4_string (static_cast <uint32_t >(ip), buffer);
73+ const char * end = buffer + strlen (buffer);
74+ uint32_t parsed_ip = ipv4_string_to_uint32 (buffer, end);
75+ if (parsed_ip != ip) {
76+ std::cerr << " Mismatch: original " << ip << " , parsed " << parsed_ip << std::endl;
77+ return false ;
78+ }
79+ }
80+ std::cout << std::endl;
81+ return true ;
82+ }
83+
84+ int main () {
85+ if (test_all_ipv4_conversions ()) {
86+ std::cout << " All IPv4 conversions passed!" << std::endl;
87+ return EXIT_SUCCESS;
88+ } else {
89+ std::cerr << " IPv4 conversion test failed!" << std::endl;
90+ return EXIT_FAILURE;
91+ }
92+ }
0 commit comments