shithub: mc

ref: b7267a73ef2d703263173152bb219955aaffa76e
dir: /libstd/ipparse.myr/

View raw version
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)
	;;
}