Task: Parse an IP Address


C++: #include <boost/asio/ip/address.hpp>
#include <cstdint>
#include <iostream>
#include <iomanip>
#include <limits>
#include <string>

using boost::asio::ip::address;
using boost::asio::ip::address_v4;
using boost::asio::ip::address_v6;
using boost::asio::ip::make_address;
using boost::asio::ip::make_address_v4;
using boost::asio::ip::make_address_v6;

template<typename uint>
bool parse_int(const std::string& str, int base, uint& n) {
    try {
        size_t pos = 0;
        unsigned long u = stoul(str, &pos, base);
        if (pos != str.length() || u > std::numeric_limits<uint>::max())
            return false;
        n = static_cast<uint>(u);
        return true;
    } catch (const std::exception& ex) {
        return false;
    }
}












void parse_ip_address_and_port(const std::string& input, address& addr, uint16_t& port) {
    size_t pos = input.rfind(':');
    if (pos != std::string::npos && pos > 1 && pos + 1 < input.length()
        && parse_int(input.substr(pos + 1), 10, port) && port > 0) {
        if (input[0] == '[' && input[pos - 1] == ']') {
            
            addr = make_address_v6(input.substr(1, pos - 2));
            return;
        } else {
            try {
                
                addr = make_address_v4(input.substr(0, pos));
                return;
            } catch (const std::exception& ex) {
                
            }
        }
    }
    port = 0;
    addr = make_address(input);
}

void print_address_and_port(const address& addr, uint16_t port) {
    std::cout << std::hex << std::uppercase << std::setfill('0');
    if (addr.is_v4()) {
        address_v4 addr4 = addr.to_v4();
        std::cout << "address family: IPv4\n";
        std::cout << "address number: " << std::setw(8) << addr4.to_uint() << '\n';
    } else if (addr.is_v6()) {
        address_v6 addr6 = addr.to_v6();
        address_v6::bytes_type bytes(addr6.to_bytes());
        std::cout << "address family: IPv6\n";
        std::cout << "address number: ";
        for (unsigned char byte : bytes)
            std::cout << std::setw(2) << static_cast<unsigned int>(byte);
        std::cout << '\n';
    }
    if (port != 0)
        std::cout << "port: " << std::dec << port << '\n';
    else
        std::cout << "port not specified\n";
}

void test(const std::string& input) {
    std::cout << "input: " << input << '\n';
    try {
        address addr;
        uint16_t port = 0;
        parse_ip_address_and_port(input, addr, port);
        print_address_and_port(addr, port);
    } catch (const std::exception& ex) {
        std::cout << "parsing failed\n";
    }
    std::cout << '\n';
}

int main(int argc, char** argv) {
    test("127.0.0.1");
    test("127.0.0.1:80");
    test("::ffff:127.0.0.1");
    test("::1");
    test("[::1]:80");
    test("1::80");
    test("2605:2700:0:3::4713:93e3");
    test("[2605:2700:0:3::4713:93e3]:80");
    return 0;
}







VB: Function parse_ip(addr)
    
    Set ipv4_pattern = New RegExp
    ipv4_pattern.Global = True
    ipv4_pattern.Pattern = "(\d{1,3}\.){3}\d{1,3}"
    
    Set ipv6_pattern = New RegExp
    ipv6_pattern.Global = True
    ipv6_pattern.Pattern = "([0-9a-fA-F]{0,4}:){2}[0-9a-fA-F]{0,4}"
    
    If ipv4_pattern.Test(addr) Then
        port = Split(addr,":")
        octet = Split(port(0),".")
        ipv4_hex = ""
        For i = 0 To UBound(octet)
            If octet(i) <= 255 And octet(i) >= 0 Then
                ipv4_hex = ipv4_hex & Right("0" & Hex(octet(i)),2)
            Else
                ipv4_hex = "Erroneous Address"
                Exit For
            End If 
        Next
        parse_ip = "Test Case: " & addr & vbCrLf &_
                   "Address: " & ipv4_hex & vbCrLf
        If UBound(port) = 1 Then
            If port(1) <= 65535 And port(1) >= 0 Then
                parse_ip = parse_ip & "Port: " & port(1) & vbCrLf
            Else
                parse_ip = parse_ip & "Port: Invalid" & vbCrLf
            End If
        End If
    End If
    
    If ipv6_pattern.Test(addr) Then
        parse_ip = "Test Case: " & addr & vbCrLf
        port_v6 = "Port: "
        ipv6_hex = ""
        
        If InStr(1,addr,"[") Then
            
            port_v6 = port_v6 & Mid(addr,InStrRev(addr,"]")+2,Len(addr)-Len(Mid(addr,1,InStrRev(addr,"]")+1)))
            
            addr = Mid(addr,InStrRev(addr,"[")+1,InStrRev(addr,"]")-(InStrRev(addr,"[")+1))
        End If
        word = Split(addr,":")
        word_count = 0
        For i = 0 To UBound(word)
            If word(i) = "" Then
                If i < UBound(word) Then
                    If Int((7-(i+1))/2) = 1 Then
                        k = 1
                    ElseIf UBound(word) < 6 Then
                        k = Int((7-(i+1))/2)
                    ElseIf UBound(word) >= 6 Then
                        k = Int((7-(i+1))/2)-1
                    End If
                    For j = 0 To k
                        ipv6_hex = ipv6_hex & "0000"
                        word_count = word_count + 1
                    Next
                Else
                    For j = 0 To (7-word_count)
                        ipv6_hex = ipv6_hex & "0000"
                    Next
                End If
            Else
                ipv6_hex = ipv6_hex & Right("0000" & word(i),4)
                word_count = word_count + 1
            End If
        Next
        parse_ip = parse_ip & "Address: " & ipv6_hex &_
                vbCrLf & port_v6 & vbCrLf
    End If
    
    If ipv4_pattern.Test(addr) = False And ipv6_pattern.Test(addr) = False Then
        parse_ip = "Test Case: " & addr & vbCrLf &_
                   "Address: Invalid Address" & vbCrLf
    End If
End Function


ip_arr = Array("127.0.0.1","127.0.0.1:80","::1",_
    "[::1]:80","2605:2700:0:3::4713:93e3","[2605:2700:0:3::4713:93e3]:80","RosettaCode")

For n = 0 To UBound(ip_arr)
    WScript.StdOut.Write parse_ip(ip_arr(n)) & vbCrLf
Next