authorgravatar for dbandstra@protonmail.comdbandstra <dbandstra@protonmail.com> 2020-08-19 13:10:05-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-19 16:30:42-04:00
loga237283d90ea6799331a7268f474511f352a23d7
tree770d5650e4359e331f4a9c39137e79d821340297
parent083c0f1cebc763e4e43529b50f6df9839c32c1c7

fixes and improvements for parseCharLiteral


1 files changed, 25 insertions(+), 17 deletions(-)

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