| ... | ... | @@ -84,7 +84,7 @@ pub fn binNameAlloc( |
| 84 | 84 | /// Slice must be valid utf8 starting and ending with "'" and exactly one codepoint in between. |
| 85 | 85 | pub fn parseCharLiteral( |
| 86 | 86 | slice: []const u8, |
| 87 | | bad_index: *usize, // populated if error.InvalidCharacter is returned) |
| 87 | bad_index: *usize, // populated if error.InvalidCharacter is returned |
| 88 | 88 | ) error{InvalidCharacter}!u32 { |
| 89 | 89 | std.debug.assert(slice.len >= 3 and slice[0] == '\'' and slice[slice.len - 1] == '\''); |
| 90 | 90 | |
| ... | ... | @@ -101,24 +101,23 @@ pub fn parseCharLiteral( |
| 101 | 101 | bad_index.* = slice.len - 2; |
| 102 | 102 | return error.InvalidCharacter; |
| 103 | 103 | } |
| 104 | | |
| 105 | 104 | var value: u32 = 0; |
| 106 | 105 | for (slice[3..5]) |c, i| { |
| 107 | | switch (slice[3]) { |
| 106 | switch (c) { |
| 108 | 107 | '0'...'9' => { |
| 109 | 108 | value *= 16; |
| 110 | 109 | value += c - '0'; |
| 111 | 110 | }, |
| 112 | 111 | 'a'...'f' => { |
| 113 | 112 | value *= 16; |
| 114 | | value += c - 'a'; |
| 113 | value += c - 'a' + 10; |
| 115 | 114 | }, |
| 116 | 115 | 'A'...'F' => { |
| 117 | 116 | value *= 16; |
| 118 | | value += c - 'a'; |
| 117 | value += c - 'A' + 10; |
| 119 | 118 | }, |
| 120 | 119 | else => { |
| 121 | | bad_index.* = i; |
| 120 | bad_index.* = 3 + i; |
| 122 | 121 | return error.InvalidCharacter; |
| 123 | 122 | }, |
| 124 | 123 | } |
| ... | ... | @@ -126,16 +125,12 @@ pub fn parseCharLiteral( |
| 126 | 125 | return value; |
| 127 | 126 | }, |
| 128 | 127 | 'u' => { |
| 129 | | if (slice.len < 6 or slice[3] != '{') { |
| 128 | if (slice.len < "'\\u{0}'".len or slice[3] != '{' or slice[slice.len - 2] != '}') { |
| 130 | 129 | bad_index.* = 2; |
| 131 | 130 | return error.InvalidCharacter; |
| 132 | 131 | } |
| 133 | 132 | var value: u32 = 0; |
| 134 | | for (slice[4..]) |c, i| { |
| 135 | | if (value > 0x10ffff) { |
| 136 | | bad_index.* = i; |
| 137 | | return error.InvalidCharacter; |
| 138 | | } |
| 133 | for (slice[4 .. slice.len - 2]) |c, i| { |
| 139 | 134 | switch (c) { |
| 140 | 135 | '0'...'9' => { |
| 141 | 136 | value *= 16; |
| ... | ... | @@ -143,25 +138,28 @@ pub fn parseCharLiteral( |
| 143 | 138 | }, |
| 144 | 139 | 'a'...'f' => { |
| 145 | 140 | value *= 16; |
| 146 | | value += c - 'a'; |
| 141 | value += c - 'a' + 10; |
| 147 | 142 | }, |
| 148 | 143 | 'A'...'F' => { |
| 149 | 144 | value *= 16; |
| 150 | | value += c - 'A'; |
| 145 | value += c - 'A' + 10; |
| 151 | 146 | }, |
| 152 | | '}' => break, |
| 153 | 147 | else => { |
| 154 | | bad_index.* = i; |
| 148 | bad_index.* = 4 + i; |
| 155 | 149 | return error.InvalidCharacter; |
| 156 | 150 | }, |
| 157 | 151 | } |
| 152 | if (value > 0x10ffff) { |
| 153 | bad_index.* = 4 + i; |
| 154 | return error.InvalidCharacter; |
| 155 | } |
| 158 | 156 | } |
| 159 | 157 | return value; |
| 160 | 158 | }, |
| 161 | 159 | else => { |
| 162 | 160 | bad_index.* = 2; |
| 163 | 161 | return error.InvalidCharacter; |
| 164 | | } |
| 162 | }, |
| 165 | 163 | } |
| 166 | 164 | } |
| 167 | 165 | return std.unicode.utf8Decode(slice[1 .. slice.len - 1]) catch unreachable; |
| ... | ... | @@ -172,13 +170,23 @@ test "parseCharLiteral" { |
| 172 | 170 | std.testing.expectEqual(try parseCharLiteral("'a'", &bad_index), 'a'); |
| 173 | 171 | std.testing.expectEqual(try parseCharLiteral("'ä'", &bad_index), 'ä'); |
| 174 | 172 | std.testing.expectEqual(try parseCharLiteral("'\\x00'", &bad_index), 0); |
| 173 | std.testing.expectEqual(try parseCharLiteral("'\\x4f'", &bad_index), 0x4f); |
| 174 | std.testing.expectEqual(try parseCharLiteral("'\\x4F'", &bad_index), 0x4f); |
| 175 | 175 | std.testing.expectEqual(try parseCharLiteral("'ぁ'", &bad_index), 0x3041); |
| 176 | std.testing.expectEqual(try parseCharLiteral("'\\u{0}'", &bad_index), 0); |
| 176 | 177 | std.testing.expectEqual(try parseCharLiteral("'\\u{3041}'", &bad_index), 0x3041); |
| 178 | std.testing.expectEqual(try parseCharLiteral("'\\u{7f}'", &bad_index), 0x7f); |
| 179 | std.testing.expectEqual(try parseCharLiteral("'\\u{7FFF}'", &bad_index), 0x7FFF); |
| 177 | 180 | |
| 178 | 181 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\x0'", &bad_index)); |
| 182 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\x000'", &bad_index)); |
| 179 | 183 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\y'", &bad_index)); |
| 180 | 184 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u'", &bad_index)); |
| 185 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\uFFFF'", &bad_index)); |
| 186 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u{}'", &bad_index)); |
| 181 | 187 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u{FFFFFF}'", &bad_index)); |
| 188 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u{FFFF'", &bad_index)); |
| 189 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u{FFFF}x'", &bad_index)); |
| 182 | 190 | } |
| 183 | 191 | |
| 184 | 192 | test "" { |