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 ] = {static_cast <uint8_t >(ip >> 24 ),
25+ static_cast <uint8_t >(ip >> 16 ),
26+ static_cast <uint8_t >(ip >> 8 ), static_cast <uint8_t >(ip)};
27+
28+ char *ptr = buffer;
29+
30+ for (int i = 0 ; i < 4 ; ++i) {
31+ ptr = uint8_to_chars_manual (ptr, octets[i]);
32+
33+ if (i < 3 ) {
34+ *ptr++ = ' .' ;
35+ }
36+ }
37+ *ptr = ' \0 ' ;
38+ }
39+
40+ fastfloat_really_inline uint32_t ipv4_string_to_uint32 (const char *str,
41+ const char *end) {
42+ uint32_t ip = 0 ;
43+ const char *current = str;
44+
45+ for (int i = 0 ; i < 4 ; ++i) {
46+ uint8_t value;
47+ auto r = fast_float::from_chars (current, end, value);
48+ if (r.ec != std::errc ()) {
49+ throw std::invalid_argument (" Invalid IP address format" );
50+ }
51+ current = r.ptr ;
52+ ip = (ip << 8 ) | value;
53+
54+ if (i < 3 ) {
55+ if (current == end || *current++ != ' .' ) {
56+ throw std::invalid_argument (" Invalid IP address format" );
57+ }
58+ }
59+ }
60+ return ip;
61+ }
62+
63+ bool test_all_ipv4_conversions () {
64+ std::cout << " Testing all IPv4 conversions... 0, 1000, 2000, 3000, 4000, "
65+ " 5000, 6000, 7000, 8000, 9000, ..."
66+ << 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
77+ << std::endl;
78+ return false ;
79+ }
80+ }
81+ std::cout << std::endl;
82+ return true ;
83+ }
84+
85+ int main () {
86+ if (test_all_ipv4_conversions ()) {
87+ std::cout << " All IPv4 conversions passed!" << std::endl;
88+ return EXIT_SUCCESS;
89+ } else {
90+ std::cerr << " IPv4 conversion test failed!" << std::endl;
91+ return EXIT_FAILURE;
92+ }
93+ }
0 commit comments