Data update
This commit is contained in:
parent
ed705008a8
commit
0df55f9f24
2196 changed files with 32999 additions and 3075 deletions
137
Task/Parse-an-IP-Address/C-sharp/parse-an-ip-address.cs
Normal file
137
Task/Parse-an-IP-Address/C-sharp/parse-an-ip-address.cs
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Text;
|
||||
|
||||
class ParseIPAddress
|
||||
{
|
||||
private static readonly Regex IPV4_PAT = new Regex(@"^(\d+)\.(\d+)\.(\d+)\.(\d+)(?::(\d+)){0,1}$");
|
||||
private static readonly Regex IPV6_DOUBL_COL_PAT = new Regex(@"^\[{0,1}([0-9a-f:]*)::([0-9a-f:]*)(?:\]:(\d+)){0,1}$");
|
||||
private static readonly Regex IPV6_PAT;
|
||||
|
||||
static ParseIPAddress()
|
||||
{
|
||||
string ipv6Pattern = @"^\[{0,1}";
|
||||
for (int i = 1; i <= 7; i++)
|
||||
{
|
||||
ipv6Pattern += @"([0-9a-f]+):";
|
||||
}
|
||||
ipv6Pattern += @"([0-9a-f]+)(?:\]:(\d+)){0,1}$";
|
||||
IPV6_PAT = new Regex(ipv6Pattern);
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
string[] tests = new string[] { "192.168.0.1", "127.0.0.1", "256.0.0.1", "127.0.0.1:80", "::1", "[::1]:80", "[32e::12f]:80", "2605:2700:0:3::4713:93e3", "[2605:2700:0:3::4713:93e3]:80", "2001:db8:85a3:0:0:8a2e:370:7334" };
|
||||
Console.WriteLine(String.Format("{0,-40} {1,-32} {2}", "Test Case", "Hex Address", "Port"));
|
||||
foreach (var ip in tests)
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] parsed = ParseIP(ip);
|
||||
Console.WriteLine(String.Format("{0,-40} {1,-32} {2}", ip, parsed[0], parsed[1]));
|
||||
}
|
||||
catch (ArgumentException e)
|
||||
{
|
||||
Console.WriteLine(String.Format("{0,-40} Invalid address: {1}", ip, e.Message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static string[] ParseIP(string ip)
|
||||
{
|
||||
string hex = "";
|
||||
string port = "";
|
||||
|
||||
// IPV4
|
||||
Match ipv4Matcher = IPV4_PAT.Match(ip);
|
||||
if (ipv4Matcher.Success)
|
||||
{
|
||||
for (int i = 1; i <= 4; i++)
|
||||
{
|
||||
hex += ToHex4(ipv4Matcher.Groups[i].Value);
|
||||
}
|
||||
if (ipv4Matcher.Groups[5].Success)
|
||||
{
|
||||
port = ipv4Matcher.Groups[5].Value;
|
||||
}
|
||||
return new string[] { hex, port };
|
||||
}
|
||||
|
||||
// IPV6, double colon
|
||||
Match ipv6DoubleColonMatcher = IPV6_DOUBL_COL_PAT.Match(ip);
|
||||
if (ipv6DoubleColonMatcher.Success)
|
||||
{
|
||||
string p1 = ipv6DoubleColonMatcher.Groups[1].Value;
|
||||
if (p1 == "")
|
||||
{
|
||||
p1 = "0";
|
||||
}
|
||||
string p2 = ipv6DoubleColonMatcher.Groups[2].Value;
|
||||
if (p2 == "")
|
||||
{
|
||||
p2 = "0";
|
||||
}
|
||||
ip = p1 + GetZero(8 - NumCount(p1) - NumCount(p2)) + p2;
|
||||
if (ipv6DoubleColonMatcher.Groups[3].Success)
|
||||
{
|
||||
ip = "[" + ip + "]:" + ipv6DoubleColonMatcher.Groups[3].Value;
|
||||
}
|
||||
}
|
||||
|
||||
// IPV6
|
||||
Match ipv6Matcher = IPV6_PAT.Match(ip);
|
||||
if (ipv6Matcher.Success)
|
||||
{
|
||||
for (int i = 1; i <= 8; i++)
|
||||
{
|
||||
hex += String.Format("{0,4}", ToHex6(ipv6Matcher.Groups[i].Value)).Replace(" ", "0");
|
||||
}
|
||||
if (ipv6Matcher.Groups[9].Success)
|
||||
{
|
||||
port = ipv6Matcher.Groups[9].Value;
|
||||
}
|
||||
return new string[] { hex, port };
|
||||
}
|
||||
|
||||
throw new ArgumentException("ERROR 103: Unknown address: " + ip);
|
||||
}
|
||||
|
||||
private static int NumCount(string s)
|
||||
{
|
||||
return s.Split(':').Length;
|
||||
}
|
||||
|
||||
private static string GetZero(int count)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append(":");
|
||||
while (count > 0)
|
||||
{
|
||||
sb.Append("0:");
|
||||
count--;
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static string ToHex4(string s)
|
||||
{
|
||||
int val = int.Parse(s);
|
||||
if (val < 0 || val > 255)
|
||||
{
|
||||
throw new ArgumentException("ERROR 101: Invalid value : " + s);
|
||||
}
|
||||
return val.ToString("X2");
|
||||
}
|
||||
|
||||
private static string ToHex6(string s)
|
||||
{
|
||||
int val = int.Parse(s, System.Globalization.NumberStyles.HexNumber);
|
||||
if (val < 0 || val > 65536)
|
||||
{
|
||||
throw new ArgumentException("ERROR 102: Invalid hex value : " + s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
222
Task/Parse-an-IP-Address/Jq/parse-an-ip-address.jq
Normal file
222
Task/Parse-an-IP-Address/Jq/parse-an-ip-address.jq
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
# Generic preliminaries
|
||||
|
||||
# To take advantage of gojq's arbitrary-precision integer arithmetic:
|
||||
def power($b): . as $in | reduce range(0;$b) as $i (1; . * $in);
|
||||
|
||||
# To take advantage of gojq's arbitrary-precision integer arithmetic:
|
||||
# if the input and $j are integers, then the result will be an integer.
|
||||
def div($j):
|
||||
(. - (. % j)) / $j;
|
||||
|
||||
# integer to stream of 0s and 1s, least significant bit first
|
||||
def bitwise:
|
||||
recurse( if . >= 2 then div(2) else empty end) | . % 2;
|
||||
|
||||
# inverse of `bitwise`
|
||||
def stream_to_integer(stream):
|
||||
reduce stream as $c ( {power:1 , ans: 0};
|
||||
.ans += ($c * .power) | .power *= 2 )
|
||||
| .ans;
|
||||
|
||||
# Input determines the max number of bits to be retained
|
||||
# $x and $y are two integers
|
||||
def xorBits($x;$y):
|
||||
def lxor(a;b):
|
||||
if (a==1 or b==1) and ((a==1 and b==1)|not) then 1
|
||||
elif a == null then b
|
||||
elif b == null then a
|
||||
else 0
|
||||
end;
|
||||
if $x == 0 then $y
|
||||
elif $y == 0 then $x
|
||||
else
|
||||
[if . then limit(.; $x|bitwise) else $x|bitwise end] as $s
|
||||
| [if . then limit(.; $y|bitwise) else $y|bitwise end] as $t
|
||||
| stream_to_integer(
|
||||
range(0; [($s|length), ($t|length)] | max) as $i
|
||||
| lxor($s[$i]; $t[$i]) )
|
||||
end ;
|
||||
|
||||
# $x and $y are two integers
|
||||
def xor($x;$y):
|
||||
null | xorBits($x;$y);
|
||||
|
||||
def count(stream): reduce stream as $i (0; .+1);
|
||||
|
||||
# Input: an array
|
||||
def insert($i; $x): .[:$i] + [$x] + .[$i:];
|
||||
|
||||
# Input: a non-negative integer
|
||||
def tobase($b):
|
||||
def digit: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[.:.+1];
|
||||
def mod: . % $b;
|
||||
def div: ((. - mod) / $b);
|
||||
def digits: recurse( select(. > 0) | div) | mod ;
|
||||
# For jq it would be wise to protect against `infinite` as input, but using `isinfinite` confuses gojq
|
||||
select( (tostring|test("^[0-9]+$")) and 2 <= $b and $b <= 36)
|
||||
| if . == 0 then "0"
|
||||
else [digits | digit] | reverse[1:] | add
|
||||
end;
|
||||
|
||||
# Input: a string in base $b
|
||||
# Output: its decimal value
|
||||
def frombase($b):
|
||||
def decimalValue:
|
||||
if 48 <= . and . <= 57 then . - 48
|
||||
elif 65 <= . and . <= 90 then . - 55 # (10+.-65)
|
||||
elif 97 <= . and . <= 122 then . - 87 # (10+.-97)
|
||||
else "decimalValue <- \(.)" | error
|
||||
end;
|
||||
reduce (explode|reverse[]|decimalValue) as $x ({p:1};
|
||||
.value += (.p * $x)
|
||||
| .p *= $b)
|
||||
| .value ;
|
||||
|
||||
### Parse an IP address
|
||||
|
||||
# An IPAddress is represented by an object {"address", "addressSpace", "port"}
|
||||
# where addressSpace is one of "IPv4", "IPv6", "Invalid"
|
||||
# and a port of -1 denotes 'not specified'.
|
||||
|
||||
def INVALID: {address: 0, addressSpace: "Invalid", port: 0};
|
||||
|
||||
def ipAddressParse:
|
||||
|
||||
# Helper for octet1
|
||||
# Assumes .len == (.hextets|length)
|
||||
def fixhextets:
|
||||
.insertions = (8 - .len)
|
||||
| .i = 0
|
||||
| until(.i == 8;
|
||||
if .hextets[.i] == ""
|
||||
then .hextets[.i] = "0"
|
||||
| until( .insertions <= 0;
|
||||
.insertions += -1
|
||||
| .i as $i
|
||||
| .hextets |= insert($i; "0") )
|
||||
| .i = 8
|
||||
else .i += 1
|
||||
end ) ;
|
||||
|
||||
# Handle the case when octet length is 4
|
||||
def octet4:
|
||||
(.octets[0] | split(":")) as $split
|
||||
| if $split|length == 2
|
||||
then ($split[1]|tonumber? // null) as $temp
|
||||
| if $temp | (. == null or . < 0 or . > 65535)
|
||||
then .return = INVALID
|
||||
else .port = $temp
|
||||
| .octets[0] = $split[0]
|
||||
end
|
||||
else .
|
||||
end
|
||||
| if .return then .
|
||||
else reduce range(0;4) as $i (.;
|
||||
if .return then .
|
||||
else (.octets[$i] | tonumber? // null) as $num
|
||||
| if $num | (. == null or . < 0 or . > 255) then .return = INVALID
|
||||
else .address = xor(.address; $num * (2 | power($i * 8)))
|
||||
end
|
||||
end)
|
||||
end
|
||||
| if .return then .
|
||||
elif .trans
|
||||
then .address += 281470681743360 # "ffff00000000"
|
||||
else .
|
||||
end ;
|
||||
|
||||
# Handle the case when octet length is 1
|
||||
def octet1:
|
||||
.addressSpace = "IPv6"
|
||||
| if .ipa[0:1] == "["
|
||||
then .ipa |= .[1:]
|
||||
| (.ipa | split("]:")) as $split
|
||||
| if $split|length != 2 then .return = INVALID
|
||||
else ($split[1] | tonumber? // null) as $temp
|
||||
| if $temp | (. == null or . < 0 or . > 65535) then .return = INVALID
|
||||
else .port = $temp
|
||||
| .ipa |= .[0: (-2 - ($split[1]|length))]
|
||||
end
|
||||
end
|
||||
else .
|
||||
end
|
||||
| if .return then .
|
||||
else .hextets = (.ipa | split(":")|reverse)
|
||||
| .len = (.hextets|length)
|
||||
| if .ipa|startswith("::")
|
||||
then .hextets[-1] = "0"
|
||||
elif .ipa|endswith("::")
|
||||
then .hextets[0] = "0"
|
||||
else .
|
||||
end
|
||||
| if .ipa == "::" then .hextets[1] = "0" else . end
|
||||
| if .len > 8 or (.len == 8 and any(.hextets[]; . == "")) or count(.hextets[] | select(. == "")) > 1
|
||||
then .return = INVALID
|
||||
else .
|
||||
end
|
||||
end
|
||||
| if .return then .
|
||||
elif .len < 8
|
||||
then fixhextets
|
||||
else .
|
||||
end
|
||||
| if .return then .
|
||||
else reduce range(0; 8) as $j (.;
|
||||
if .return then .
|
||||
else (.hextets[$j] | frombase(16)) as $num
|
||||
| if $num > 65535 then .return = INVALID
|
||||
else .address = xor(.address; $num * (2 | power($j * 16)))
|
||||
end
|
||||
end)
|
||||
end ;
|
||||
|
||||
{ addressSpace: "IPv4",
|
||||
ipa: ascii_downcase,
|
||||
port: -1,
|
||||
trans: false }
|
||||
| if (.ipa|startswith("::ffff:")) and (.ipa|test("[.]"))
|
||||
then .addressSpace = "IPv6"
|
||||
| .trans = true
|
||||
| .ipa |= .[7:]
|
||||
elif (.ipa|startswith("[::ffff:")) and (.ipa|test("[.]"))
|
||||
then .addressSpace = "IPv6"
|
||||
| .trans = true
|
||||
| .ipa |= (.[8:] | gsub("]";""))
|
||||
else .
|
||||
end
|
||||
| .octets = (.ipa | split(".") | reverse)
|
||||
| .address = 0
|
||||
| if .octets|length == 4
|
||||
then octet4
|
||||
elif .octets|length == 1
|
||||
then octet1
|
||||
else .return = INVALID
|
||||
end
|
||||
| if .return then .return
|
||||
else {address, addressSpace, port}
|
||||
end ;
|
||||
|
||||
# Examples
|
||||
def ipas:
|
||||
"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",
|
||||
"::ffff:192.168.173.22",
|
||||
"[::ffff:192.168.173.22]:80",
|
||||
"1::",
|
||||
"::",
|
||||
"256.0.0.0",
|
||||
"::ffff:127.0.0.0.1"
|
||||
;
|
||||
|
||||
ipas
|
||||
| "IP address : \(.)",
|
||||
( ipAddressParse
|
||||
| "Address : \(.address|tobase(16))",
|
||||
"Address Space : \(.addressSpace)",
|
||||
"Port : \(if .port == -1 then "not specified" else .port end)",
|
||||
""
|
||||
)
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import "/dynamic" for Enum, Tuple
|
||||
import "/big" for BigInt
|
||||
import "/str" for Str
|
||||
import "/fmt" for Conv, Fmt
|
||||
import "./dynamic" for Enum, Tuple
|
||||
import "./big" for BigInt
|
||||
import "./str" for Str
|
||||
import "./fmt" for Conv, Fmt
|
||||
|
||||
var AddressSpace = Enum.create("AddressSpace", ["IPv4", "IPv6", "Invalid"])
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue