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}