ref: b7267a73ef2d703263173152bb219955aaffa76e
dir: /libstd/ipparse.myr/
use "die.use" use "intparse.use" use "option.use" use "strfind.use" use "types.use" use "chartype.use" /* FIXME: needed for decls which should be pulled in as hidden */ use "hasprefix.use" use "utf.use" pkg std = type netaddr = union `Ipv4 byte[4] `Ipv6 byte[16] ;; const ipparse : (ip : byte[:] -> option(netaddr)) const ip4parse : (ip : byte[:] -> option(netaddr)) const ip6parse : (ip : byte[:] -> option(netaddr)) ;; const ipparse = {ip match strfind(ip, ":") | `Some _: -> ip6parse(ip) | `None: -> ip4parse(ip) ;; } const ip4parse = {ip var a, b, c, d var ok /* var addr var last : size var x : option(int32) var val : int32 /* need int32 to check for overflow */ var i var j : size */ (a, ip, ok) = octet(ip, 10, true) (ip, ok) = dot(ip, ok) (b, ip, ok) = octet(ip, 10, ok) (ip, ok) = dot(ip, ok) (c, ip, ok) = octet(ip, 10, ok) (ip, ok) = dot(ip, ok) (d, ip, ok) = octet(ip, 10, ok) if ok && ip.len == 0 -> `Some (`Ipv4 [a, b,c,d]) else -> `None ;; } const ip6parse = {ip -> `None } const dot = {ip, ok if ip.len > 0 && ip[0] == '.' castto(byte) -> (ip[1:], ok) else -> ("", false) ;; } const octet = {ip, base, ok var len if !ok -> (0, "", false) ;; for len = 0; len < ip.len; len++ if ip[len] == '.' castto(byte) break ;; ;; match intparsebase(ip[:len], base) | `std.Some v: if v < 0 || v > 255 -> (0, "", false) ;; -> (v castto(byte), ip[len:], true) | `std.None: -> (0, "", false) ;; }