September Morn Update
This commit is contained in:
parent
4e2d22a71d
commit
aac6731f2c
6856 changed files with 141342 additions and 21127 deletions
|
|
@ -1,7 +1,7 @@
|
|||
The purpose of this task is to demonstrate parsing of text-format IP addresses, using IPv4 and IPv6.
|
||||
|
||||
Taking the following as inputs:
|
||||
{| border="1" cellspacing="0" cellpadding=2
|
||||
::: {| border="5" cellspacing="0" cellpadding=2
|
||||
|-
|
||||
|127.0.0.1
|
||||
|The "localhost" IPv4 address
|
||||
|
|
@ -22,6 +22,7 @@ Taking the following as inputs:
|
|||
|Rosetta Code's primary server's public IPv6 address, with a specified port (80)
|
||||
|}
|
||||
|
||||
|
||||
Emit each described IP address as a hexadecimal integer representing the address, the address space, and the port number specified, if any. In languages where variant result types are clumsy, the result should be ipv4 or ipv6 address number, something which says which address space was represented, port number and something that says if the port was specified.
|
||||
|
||||
For example 127.0.0.1 has the address number 7F000001 (2130706433 decimal) in the ipv4 address space. ::ffff:127.0.0.1 represents the same address in the ipv6 address space where it has the address number FFFF7F000001 (281472812449793 decimal). Meanwhile ::1 has address number 1 and serves the same purpose in the ipv6 address space that 127.0.0.1 serves in the ipv4 address space.
|
||||
|
|
|
|||
1
Task/Parse-an-IP-Address/00META.yaml
Normal file
1
Task/Parse-an-IP-Address/00META.yaml
Normal file
|
|
@ -0,0 +1 @@
|
|||
--- {}
|
||||
|
|
@ -15,16 +15,16 @@ grammar IP_Addr {
|
|||
| <h16> +% ':' <?{ $<h16> == 8 }>
|
||||
{ @*by16 = @$<h16> }
|
||||
|
||||
| [ (<h16>) +% ':']? '::' (<h16>) +% ':' <?{ @$0 + @$1 <= 8 }>
|
||||
{ @*by16 = @$0, '0' xx 8 - (@$0 + @$1), @$1 }
|
||||
| [ (<h16>) +% ':']? '::' [ (<h16>) +% ':' ]? <?{ @$0 + @$1 ≤ 8 }>
|
||||
{ @*by16 = |@$0, |('0' xx 8 - (@$0 + @$1)), |@$1 }
|
||||
|
||||
| '::ffff:' <IPv4>
|
||||
{ @*by16 = '0' xx 5, 'ffff', by8to16 @*by8 }
|
||||
{ @*by16 = |('0' xx 5), 'ffff', |(by8to16 @*by8) }
|
||||
}
|
||||
|
||||
token d8 { (\d+) <?{ $0 < 256 }> }
|
||||
token d16 { (\d+) <?{ $0 < 65536 }> }
|
||||
token h16 { (<:hexdigit>+) <?{ @$0 <= 4 }> }
|
||||
token h16 { (<:hexdigit>+) <?{ @$0 ≤ 4 }> }
|
||||
|
||||
token port {
|
||||
':' <d16> { $*port = +$<d16> }
|
||||
|
|
@ -70,7 +70,7 @@ for @cases -> $addr {
|
|||
|
||||
say $addr;
|
||||
if @*by16 {
|
||||
say " IPv6: ", @*by16».map({:16(~$_)})».fmt("%04x").join;
|
||||
say " IPv6: ", @*by16.map({:16(~$_)})».fmt("%04x").join;
|
||||
say " Port: ", $*port if $*port;
|
||||
}
|
||||
elsif @*by8 {
|
||||
|
|
|
|||
147
Task/Parse-an-IP-Address/Phix/parse-an-ip-address.phix
Normal file
147
Task/Parse-an-IP-Address/Phix/parse-an-ip-address.phix
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
function parse_ip(string txt)
|
||||
sequence r
|
||||
integer dot = find('.',txt),
|
||||
colon = find(':',txt),
|
||||
openbr = find('[',txt),
|
||||
closebr = find(']',txt)
|
||||
if colon=5 and txt[1..4] = "http" then
|
||||
txt = trim(txt[6..$],"/")
|
||||
return parse_ip(txt)
|
||||
end if
|
||||
bool ipv6 = openbr or dot=0 or (colon and colon<dot)
|
||||
if ipv6 then
|
||||
sequence res = repeat(0,8)
|
||||
if openbr then
|
||||
if openbr!=1 or closebr<openbr then return 0 end if
|
||||
r = scanf(txt[closebr+1..$],":%d")
|
||||
if length(r)!=1 then return 0 end if
|
||||
atom port = r[1][1]
|
||||
if port<0 or port>65535 then return 0 end if
|
||||
res &= port
|
||||
txt = txt[2..closebr-1]
|
||||
end if
|
||||
if dot then
|
||||
colon = rfind(':',txt)
|
||||
if colon>dot then return 0 end if
|
||||
object r4 = parse_ip(txt[colon+1..$])
|
||||
if not sequence(r4) or length(r4)!=4 then return 0 end if
|
||||
res[7] = r4[1]*#100+r4[2]
|
||||
res[8] = r4[3]*#100+r4[4]
|
||||
txt = txt[1..colon-1+(txt[colon-1]=':')]
|
||||
dot = 2
|
||||
end if
|
||||
sequence r8 = {}
|
||||
integer ip = 0
|
||||
while length(txt) do
|
||||
colon = find(':',txt)
|
||||
if colon=1 then
|
||||
if ip then return 0 end if
|
||||
ip = length(r8)+1
|
||||
txt = txt[2+(length(r8)=0)..$]
|
||||
else
|
||||
r = scanf(txt[1..colon-1],"%x")
|
||||
if length(r)!=1 then return 0 end if
|
||||
atom r11 = r[1][1]
|
||||
if r11<0 or r11>#FFFF then return 0 end if
|
||||
r8 &= r11
|
||||
if colon=0 then exit end if
|
||||
txt = txt[colon+1..$]
|
||||
end if
|
||||
end while
|
||||
if ip then
|
||||
if length(r8)>=(8-dot) then return 0 end if
|
||||
r8[ip..ip-1] = repeat(0,(8-dot)-length(r8))
|
||||
else
|
||||
if length(r8)!=8-dot then return 0 end if
|
||||
end if
|
||||
res[1..8-dot] = r8
|
||||
return res
|
||||
end if
|
||||
-- ipv4:
|
||||
if dot=0 or (colon and colon<dot) then return 0 end if
|
||||
r = scanf(txt[1..colon-1],"%d.%d.%d.%d")
|
||||
if length(r)!=1 then return 0 end if
|
||||
r = r[1]
|
||||
for i=1 to length(r) do
|
||||
if r[i]<0 or r[i]>255 then return 0 end if
|
||||
end for
|
||||
if colon then
|
||||
sequence r2 = scanf(txt[colon+1..$],"%d")
|
||||
if length(r2)!=1 then return 0 end if
|
||||
atom port = r2[1][1]
|
||||
if port<0 or port>65535 then return 0 end if
|
||||
r &= port
|
||||
end if
|
||||
return r
|
||||
end function
|
||||
|
||||
constant tests = {{"127.0.0.1",{127,0,0,1}},
|
||||
{"127.0.0.1:80",{127,0,0,1,80}},
|
||||
{"::1",{0,0,0,0,0,0,0,1}},
|
||||
{"[::1]:80",{0,0,0,0,0,0,0,1,80}},
|
||||
{"2605:2700:0:3::4713:93e3",{#2605,#2700,0,3,0,0,#4713,#93e3}},
|
||||
{"[2605:2700:0:3::4713:93e3]:80",{#2605,#2700,0,3,0,0,#4713,#93e3,80}},
|
||||
{"::ffff:192.168.173.22",{0,0,0,0,0,#ffff,#c0a8,#ad16}},
|
||||
{"[::ffff:192.168.173.22]:80",{0,0,0,0,0,#ffff,#c0a8,#ad16,80}},
|
||||
{"1::",{1,0,0,0,0,0,0,0}},
|
||||
{"[1::]:80",{1,0,0,0,0,0,0,0,80}},
|
||||
{"::",{0,0,0,0,0,0,0,0}},
|
||||
{"[::]:80",{0,0,0,0,0,0,0,0,80}},
|
||||
{"192.168.0.1",{192,168,0,1}},
|
||||
{"2001:db8:85a3:0:0:8a2e:370:7334",{#2001,#db8,#85a3,0,0,#8a2e,#370,#7334}},
|
||||
{"2001:db8:85a3::8a2e:370:7334",{#2001,#db8,#85a3,0,0,#8a2e,#370,#7334}},
|
||||
{"[2001:db8:85a3:8d3:1319:8a2e:370:7334]:443",{#2001,#db8,#85a3,#8d3,#1319,#8a2e,#370,#7334,443}},
|
||||
{"256.0.0.0",0},
|
||||
{"g::1",0},
|
||||
{"::ffff:127.0.0.0.1",0},
|
||||
{"a::b::1",0},
|
||||
{"0000",0},
|
||||
{"0000:0000",0},
|
||||
{"0000:0000:0000:0000:0000:0000:0000:0000",{0,0,0,0,0,0,0,0}},
|
||||
{"0000:0000:0000::0000:0000",{0,0,0,0,0,0,0,0}},
|
||||
{"0000::0000::0000:0000",0},
|
||||
{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",{#ffff,#ffff,#ffff,#ffff,#ffff,#ffff,#ffff,#ffff}},
|
||||
{"ffff:ffff:ffff:fffg:ffff:ffff:ffff:ffff",0},
|
||||
{"fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",{#fff,#ffff,#ffff,#ffff,#ffff,#ffff,#ffff,#ffff}},
|
||||
{"fff:ffff:0:ffff:ffff:ffff:ffff:ffff",{#fff,#ffff,0,#ffff,#ffff,#ffff,#ffff,#ffff}},
|
||||
{"2001:0db8:0:0:0:0:1428:57ab",{#2001,#0db8,0,0,0,0,#1428,#57ab}},
|
||||
{"2001:0db8::1428:57ab",{#2001,#0db8,0,0,0,0,#1428,#57ab}},
|
||||
{"2001:0db8:0:0:8d3:0:0:0",{#2001,#0db8,0,0,#8d3,0,0,0}},
|
||||
{"2001:0db8:0:0:8d3::",{#2001,#0db8,0,0,#8d3,0,0,0}},
|
||||
{"2001:0db8::8d3:0:0:0",{#2001,#0db8,0,0,#8d3,0,0,0}},
|
||||
{"http://127.0.0.1/",{127,0,0,1}},
|
||||
{"http:",0},
|
||||
{"http:/2001:db8:3:4::127.0.2.0",{#2001,#db8,3,4,0,0,#7F00,#200}},
|
||||
{"::192.168.0.1",{0,0,0,0,0,0,#C0A8,1}},
|
||||
{"::ffff:0:255.255.255.255",{0,0,0,0,#ffff,0,#ffff,#ffff}},
|
||||
{"",0},
|
||||
{"ffffffffffffffffffffffffffffffff::",0},
|
||||
{"[1::]:9999999999999999999999999999",0},
|
||||
{"I think that's enough tests for now",0}}
|
||||
|
||||
for i=1 to length(tests) do
|
||||
{string ip, object expected} = tests[i]
|
||||
object actual = parse_ip(ip)
|
||||
if actual!=expected then
|
||||
?{ip,actual,expected}
|
||||
?9/0
|
||||
end if
|
||||
string addr
|
||||
if actual=0 then
|
||||
addr = "**not a valid ip address**"
|
||||
else
|
||||
if remainder(length(actual),2) then
|
||||
actual[$] = sprintf(", port %d",actual[$])
|
||||
else
|
||||
actual = append(actual,"")
|
||||
end if
|
||||
if length(actual)=5 then
|
||||
addr = sprintf("ivp4 address: %02x%02x%02x%02x%s",actual)
|
||||
elsif length(actual)=9 then
|
||||
addr = sprintf("ivp6 address: %04x%04x%04x%04x%04x%04x%04x%04x%s",actual)
|
||||
else
|
||||
?9/0
|
||||
end if
|
||||
end if
|
||||
printf(1,"%45s %s\n",{ip,addr})
|
||||
end for
|
||||
Loading…
Add table
Add a link
Reference in a new issue