τau / strconv /

strconv.tau

source
/Users/niconex/Documents/tau/stdlib/strconv/strconv.tau
1# strconv - conversions between strings and numbers.2#3# The int() and float() builtins convert without complaining: int("abc") is 0.4# These functions return an error instead, so that a parser can tell a real5# zero from garbage.67digits = "0123456789abcdefghijklmnopqrstuvwxyz"89digitValue = fn(c) {10	for i = 0; i < len(digits); ++i {11		if c == digits[i] {12			return i13		}14	}15	return -116}1718lower = fn(s) {19	out = ""20	for i = 0; i < len(s); ++i {21		c = s[i]22		if c >= "A" && c <= "Z" {23			out = out + digits[10 + (bytes(c)[0] - 65)]24		} else {25			out = out + c26		}27	}28	return out29}3031# ParseInt interprets s in the given base (2 to 36) and returns its value, or32# an error if s is not a whole number in that base.33ParseInt = fn(s, base) {34	if type(s) != "string" {35		return error("strconv: ParseInt expects a string, got {type(s)}")36	}37	if base < 2 || base > 36 {38		return error("strconv: invalid base {base}")39	}40	if len(s) == 0 {41		return error("strconv: empty string")42	}4344	i = 045	sign = 146	if s[0] == "-" {47		sign = -148		i = 149	} else if s[0] == "+" {50		i = 151	}52	if i == len(s) {53		return error("strconv: invalid number \"{s}\"")54	}5556	str = lower(s)57	n = 058	for i < len(str) {59		d = digitValue(str[i])60		if d < 0 || d >= base {61			return error("strconv: invalid number \"{s}\"")62		}63		n = n * base + d64		++i65	}6667	return sign * n68}6970# Atoi is ParseInt in base 10.71Atoi = fn(s) { ParseInt(s, 10) }7273# ParseFloat returns the value of s as a float, or an error if s is not a74# number. It accepts the forms 12, 12.5, .5 and -12.5.75ParseFloat = fn(s) {76	if type(s) != "string" {77		return error("strconv: ParseFloat expects a string, got {type(s)}")78	}79	if len(s) == 0 {80		return error("strconv: empty string")81	}8283	i = 084	sign = 1.085	if s[0] == "-" {86		sign = -1.087		i = 188	} else if s[0] == "+" {89		i = 190	}9192	intPart = 0.093	fracPart = 0.094	scale = 1.095	ndigits = 096	seenDot = false9798	for i < len(s) {99		c = s[i]100		++i101102		if c == "." {103			if seenDot {104				return error("strconv: invalid number \"{s}\"")105			}106			seenDot = true107			continue108		}109110		d = digitValue(c)111		if d < 0 || d > 9 {112			return error("strconv: invalid number \"{s}\"")113		}114		++ndigits115116		if seenDot {117			scale = scale / 10.0118			fracPart = fracPart + float(d) * scale119		} else {120			intPart = intPart * 10.0 + float(d)121		}122	}123124	if ndigits == 0 {125		return error("strconv: invalid number \"{s}\"")126	}127128	return sign * (intPart + fracPart)129}130131# FormatFloat returns f written with prec digits after the point. A negative132# prec gives the shortest representation that reads back as the same value,133# which is what string(f) does.134FormatFloat = fn(f, prec) {135	if prec < 0 {136		return string(float(f))137	}138139	f = float(f)140	neg = f < 0.0141	if neg {142		f = -f143	}144145	scale = 1146	for i = 0; i < prec; ++i {147		scale = scale * 10148	}149150	# Round at the last digit kept.151	scaled = int(f * float(scale) + 0.5)152	whole = int(scaled / scale)153	out = string(whole)154155	if prec > 0 {156		digits = string(scaled - whole * scale)157		for len(digits) < prec {158			digits = "0" + digits159		}160		out = out + "." + digits161	}162163	return if neg { "-" + out } else { out }164}165166# Itoa returns the decimal representation of the integer i.167Itoa = fn(i) { string(i) }168169# FormatInt returns the representation of i in the given base (2 to 36).170FormatInt = fn(i, base) {171	if base < 2 || base > 36 {172		return error("strconv: invalid base {base}")173	}174	if i == 0 {175		return "0"176	}177178	neg = i < 0179	if neg {180		i = -i181	}182183	out = ""184	for i > 0 {185		out = digits[i % base] + out186		i = i / base187	}188189	if neg {190		return "-" + out191	}192	return out193}