| ... | ... | @@ -1059,6 +1059,16 @@ pub const ParseIntError = error{ |
| 1059 | 1059 | InvalidCharacter, |
| 1060 | 1060 | }; |
| 1061 | 1061 | |
| 1062 | /// Parses the string `buf` as signed or unsigned representation in the |
| 1063 | /// specified radix of an integral value of type `T`. |
| 1064 | /// |
| 1065 | /// When `radix` is zero the string prefix is examined to detect the true radix: |
| 1066 | /// * A prefix of "0b" implies radix=2, |
| 1067 | /// * A prefix of "0o" implies radix=8, |
| 1068 | /// * A prefix of "0x" implies radix=16, |
| 1069 | /// * Otherwise radix=10 is assumed. |
| 1070 | /// |
| 1071 | /// See also `parseUnsigned`. |
| 1062 | 1072 | pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) ParseIntError!T { |
| 1063 | 1073 | if (buf.len == 0) return error.InvalidCharacter; |
| 1064 | 1074 | if (buf[0] == '+') return parseWithSign(T, buf[1..], radix, .Pos); |
| ... | ... | @@ -1091,6 +1101,20 @@ test "parseInt" { |
| 1091 | 1101 | std.testing.expectError(error.InvalidCharacter, parseInt(i32, "+", 10)); |
| 1092 | 1102 | std.testing.expectError(error.InvalidCharacter, parseInt(u32, "-", 10)); |
| 1093 | 1103 | std.testing.expectError(error.InvalidCharacter, parseInt(i32, "-", 10)); |
| 1104 | |
| 1105 | // autodectect the radix |
| 1106 | std.testing.expect((try parseInt(i32, "111", 0)) == 111); |
| 1107 | std.testing.expect((try parseInt(i32, "+0b111", 0)) == 7); |
| 1108 | std.testing.expect((try parseInt(i32, "+0o111", 0)) == 73); |
| 1109 | std.testing.expect((try parseInt(i32, "+0x111", 0)) == 273); |
| 1110 | std.testing.expect((try parseInt(i32, "-0b111", 0)) == -7); |
| 1111 | std.testing.expect((try parseInt(i32, "-0o111", 0)) == -73); |
| 1112 | std.testing.expect((try parseInt(i32, "-0x111", 0)) == -273); |
| 1113 | |
| 1114 | // bare binary/octal/decimal prefix is invalid |
| 1115 | std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0b", 0)); |
| 1116 | std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0o", 0)); |
| 1117 | std.testing.expectError(error.InvalidCharacter, parseInt(u32, "0x", 0)); |
| 1094 | 1118 | } |
| 1095 | 1119 | |
| 1096 | 1120 | fn parseWithSign( |
| ... | ... | @@ -1101,6 +1125,31 @@ fn parseWithSign( |
| 1101 | 1125 | ) ParseIntError!T { |
| 1102 | 1126 | if (buf.len == 0) return error.InvalidCharacter; |
| 1103 | 1127 | |
| 1128 | var buf_radix = radix; |
| 1129 | var buf_start = buf; |
| 1130 | if (radix == 0) { |
| 1131 | // Treat is as a decimal number by default. |
| 1132 | buf_radix = 10; |
| 1133 | // Detect the radix by looking at buf prefix. |
| 1134 | if (buf.len > 2 and buf[0] == '0') { |
| 1135 | switch (buf[1]) { |
| 1136 | 'b' => { |
| 1137 | buf_radix = 2; |
| 1138 | buf_start = buf[2..]; |
| 1139 | }, |
| 1140 | 'o' => { |
| 1141 | buf_radix = 8; |
| 1142 | buf_start = buf[2..]; |
| 1143 | }, |
| 1144 | 'x' => { |
| 1145 | buf_radix = 16; |
| 1146 | buf_start = buf[2..]; |
| 1147 | }, |
| 1148 | else => {}, |
| 1149 | } |
| 1150 | } |
| 1151 | } |
| 1152 | |
| 1104 | 1153 | const add = switch (sign) { |
| 1105 | 1154 | .Pos => math.add, |
| 1106 | 1155 | .Neg => math.sub, |
| ... | ... | @@ -1108,16 +1157,26 @@ fn parseWithSign( |
| 1108 | 1157 | |
| 1109 | 1158 | var x: T = 0; |
| 1110 | 1159 | |
| 1111 | | for (buf) |c| { |
| 1112 | | const digit = try charToDigit(c, radix); |
| 1160 | for (buf_start) |c| { |
| 1161 | const digit = try charToDigit(c, buf_radix); |
| 1113 | 1162 | |
| 1114 | | if (x != 0) x = try math.mul(T, x, try math.cast(T, radix)); |
| 1163 | if (x != 0) x = try math.mul(T, x, try math.cast(T, buf_radix)); |
| 1115 | 1164 | x = try add(T, x, try math.cast(T, digit)); |
| 1116 | 1165 | } |
| 1117 | 1166 | |
| 1118 | 1167 | return x; |
| 1119 | 1168 | } |
| 1120 | 1169 | |
| 1170 | /// Parses the string `buf` as unsigned representation in the specified radix |
| 1171 | /// of an integral value of type `T`. |
| 1172 | /// |
| 1173 | /// When `radix` is zero the string prefix is examined to detect the true radix: |
| 1174 | /// * A prefix of "0b" implies radix=2, |
| 1175 | /// * A prefix of "0o" implies radix=8, |
| 1176 | /// * A prefix of "0x" implies radix=16, |
| 1177 | /// * Otherwise radix=10 is assumed. |
| 1178 | /// |
| 1179 | /// See also `parseInt`. |
| 1121 | 1180 | pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseIntError!T { |
| 1122 | 1181 | return parseWithSign(T, buf, radix, .Pos); |
| 1123 | 1182 | } |