authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-10 14:53:41-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-12-10 14:53:41-05:00
log023b597ab4a74adbbe658bd7476fa5d20b02a133
tree3b6234ccf647312eb55561218555a08f2ea35e8a
parentac0488430fd4ab35cab972d6409a0e244ad9637c
parenta01993e908b636835d4c2905928af700da23ea8e
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #13370 from r00ster91/newascii

std.ascii: remove LUT and deprecations

9 files changed, 89 insertions(+), 284 deletions(-)

lib/std/SemanticVersion.zig+2-2
...@@ -114,7 +114,7 @@ pub fn parse(text: []const u8) !Version {...@@ -114,7 +114,7 @@ pub fn parse(text: []const u8) !Version {
114 if (id.len == 0) return error.InvalidVersion;114 if (id.len == 0) return error.InvalidVersion;
115115
116 // Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-].116 // Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-].
117 for (id) |c| if (!std.ascii.isAlNum(c) and c != '-') return error.InvalidVersion;117 for (id) |c| if (!std.ascii.isAlphanumeric(c) and c != '-') return error.InvalidVersion;
118118
119 // Numeric identifiers MUST NOT include leading zeroes.119 // Numeric identifiers MUST NOT include leading zeroes.
120 const is_num = for (id) |c| {120 const is_num = for (id) |c| {
...@@ -133,7 +133,7 @@ pub fn parse(text: []const u8) !Version {...@@ -133,7 +133,7 @@ pub fn parse(text: []const u8) !Version {
133 if (id.len == 0) return error.InvalidVersion;133 if (id.len == 0) return error.InvalidVersion;
134134
135 // Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-].135 // Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-].
136 for (id) |c| if (!std.ascii.isAlNum(c) and c != '-') return error.InvalidVersion;136 for (id) |c| if (!std.ascii.isAlphanumeric(c) and c != '-') return error.InvalidVersion;
137 }137 }
138 }138 }
139139
lib/std/ascii.zig+72-268
...@@ -10,83 +10,10 @@...@@ -10,83 +10,10 @@
1010
11const std = @import("std");11const std = @import("std");
1212
13// TODO: remove all decls marked as DEPRECATED after 0.10.0's release
14
15/// The C0 control codes of the ASCII encoding.13/// The C0 control codes of the ASCII encoding.
16///14///
17/// See also: https://en.wikipedia.org/wiki/C0_and_C1_control_codes and `isControl`.15/// See also: https://en.wikipedia.org/wiki/C0_and_C1_control_codes and `isControl`
18pub const control_code = struct {16pub const control_code = struct {
19 // DEPRECATED: use the lowercase variant
20 pub const NUL = 0x00;
21 // DEPRECATED: use the lowercase variant
22 pub const SOH = 0x01;
23 // DEPRECATED: use the lowercase variant
24 pub const STX = 0x02;
25 // DEPRECATED: use the lowercase variant
26 pub const ETX = 0x03;
27 // DEPRECATED: use the lowercase variant
28 pub const EOT = 0x04;
29 // DEPRECATED: use the lowercase variant
30 pub const ENQ = 0x05;
31 // DEPRECATED: use the lowercase variant
32 pub const ACK = 0x06;
33 // DEPRECATED: use the lowercase variant
34 pub const BEL = 0x07;
35 // DEPRECATED: use the lowercase variant
36 pub const BS = 0x08;
37 // DEPRECATED: use `ht`
38 pub const TAB = 0x09;
39 // DEPRECATED: use the lowercase variant
40 pub const LF = 0x0A;
41 // DEPRECATED: use the lowercase variant
42 pub const VT = 0x0B;
43 // DEPRECATED: use the lowercase variant
44 pub const FF = 0x0C;
45 // DEPRECATED: use the lowercase variant
46 pub const CR = 0x0D;
47 // DEPRECATED: use the lowercase variant
48 pub const SO = 0x0E;
49 // DEPRECATED: use the lowercase variant
50 pub const SI = 0x0F;
51 // DEPRECATED: use the lowercase variant
52 pub const DLE = 0x10;
53 // DEPRECATED: use the lowercase variant
54 pub const DC1 = 0x11;
55 // DEPRECATED: use the lowercase variant
56 pub const DC2 = 0x12;
57 // DEPRECATED: use the lowercase variant
58 pub const DC3 = 0x13;
59 // DEPRECATED: use the lowercase variant
60 pub const DC4 = 0x14;
61 // DEPRECATED: use the lowercase variant
62 pub const NAK = 0x15;
63 // DEPRECATED: use the lowercase variant
64 pub const SYN = 0x16;
65 // DEPRECATED: use the lowercase variant
66 pub const ETB = 0x17;
67 // DEPRECATED: use the lowercase variant
68 pub const CAN = 0x18;
69 // DEPRECATED: use the lowercase variant
70 pub const EM = 0x19;
71 // DEPRECATED: use the lowercase variant
72 pub const SUB = 0x1A;
73 // DEPRECATED: use the lowercase variant
74 pub const ESC = 0x1B;
75 // DEPRECATED: use the lowercase variant
76 pub const FS = 0x1C;
77 // DEPRECATED: use the lowercase variant
78 pub const GS = 0x1D;
79 // DEPRECATED: use the lowercase variant
80 pub const RS = 0x1E;
81 // DEPRECATED: use the lowercase variant
82 pub const US = 0x1F;
83 // DEPRECATED: use the lowercase variant
84 pub const DEL = 0x7F;
85 // DEPRECATED: use the lowercase variant
86 pub const XON = 0x11;
87 // DEPRECATED: use the lowercase variant
88 pub const XOFF = 0x13;
89
90 /// Null.17 /// Null.
91 pub const nul = 0x00;18 pub const nul = 0x00;
92 /// Start of Heading.19 /// Start of Heading.
...@@ -161,211 +88,63 @@ pub const control_code = struct {...@@ -161,211 +88,63 @@ pub const control_code = struct {
161 pub const xoff = dc3;88 pub const xoff = dc3;
162};89};
16390
164const tIndex = enum(u3) {91/// Returns whether the character is alphanumeric: A-Z, a-z, or 0-9.
165 Alpha,
166 Hex,
167 Space,
168 Digit,
169 Lower,
170 Upper,
171 // Ctrl, < 0x20 || == DEL
172 // Print, = Graph || == ' '. NOT '\t' et cetera
173 Punct,
174 Graph,
175 //ASCII, | ~0b01111111
176 //isBlank, == ' ' || == '\x09'
177};
178
179const combinedTable = init: {
180 comptime var table: [256]u8 = undefined;
181
182 const mem = std.mem;
183
184 const alpha = [_]u1{
185 // 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
186 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
187 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
188 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
190
191 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
192 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
193 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
194 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
195 };
196 const lower = [_]u1{
197 // 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
198 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
199 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
200 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
202
203 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
204 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
205 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
206 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
207 };
208 const upper = [_]u1{
209 // 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
210 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
211 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
212 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
213 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
214
215 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
216 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
217 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
219 };
220 const digit = [_]u1{
221 // 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
222 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
223 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
224 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
225 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
226
227 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
228 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
229 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
230 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
231 };
232 const hex = [_]u1{
233 // 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
234 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
235 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
236 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
237 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
238
239 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
240 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
241 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
242 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
243 };
244 const space = [_]u1{
245 // 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
246 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
247 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
248 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
249 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
250
251 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
252 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
253 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
254 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
255 };
256 const punct = [_]u1{
257 // 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
258 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
259 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
260 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
261 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
262
263 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
264 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
265 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
266 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
267 };
268 const graph = [_]u1{
269 // 0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,10,11,12,13,14,15
270 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
271 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
272 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
273 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
274
275 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
276 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
277 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
278 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
279 };
280
281 comptime var i = 0;
282 inline while (i < 128) : (i += 1) {
283 table[i] =
284 @as(u8, alpha[i]) << @enumToInt(tIndex.Alpha) |
285 @as(u8, hex[i]) << @enumToInt(tIndex.Hex) |
286 @as(u8, space[i]) << @enumToInt(tIndex.Space) |
287 @as(u8, digit[i]) << @enumToInt(tIndex.Digit) |
288 @as(u8, lower[i]) << @enumToInt(tIndex.Lower) |
289 @as(u8, upper[i]) << @enumToInt(tIndex.Upper) |
290 @as(u8, punct[i]) << @enumToInt(tIndex.Punct) |
291 @as(u8, graph[i]) << @enumToInt(tIndex.Graph);
292 }
293 mem.set(u8, table[128..256], 0);
294 break :init table;
295};
296
297fn inTable(c: u8, t: tIndex) bool {
298 return (combinedTable[c] & (@as(u8, 1) << @enumToInt(t))) != 0;
299}
300
301/// DEPRECATED: use `isAlphanumeric`
302pub const isAlNum = isAlphanumeric;
303/// DEPRECATED: use `isAlphabetic`
304pub const isAlpha = isAlphabetic;
305/// DEPRECATED: use `isControl`
306pub const isCntrl = isControl;
307/// DEPRECATED: use `isWhitespace`.
308pub const isSpace = isWhitespace;
309/// DEPRECATED: use `whitespace`.
310pub const spaces = whitespace;
311/// DEPRECATED: use `isHex`.
312pub const isXDigit = isHex;
313
314/// Returns whether the character is alphanumeric.
315pub fn isAlphanumeric(c: u8) bool {92pub fn isAlphanumeric(c: u8) bool {
316 return (combinedTable[c] & ((@as(u8, 1) << @enumToInt(tIndex.Alpha)) |93 return switch (c) {
317 @as(u8, 1) << @enumToInt(tIndex.Digit))) != 0;94 '0'...'9', 'A'...'Z', 'a'...'z' => true,
95 else => false,
96 };
318}97}
31998
320/// Returns whether the character is alphabetic.99/// Returns whether the character is alphabetic: A-Z or a-z.
321pub fn isAlphabetic(c: u8) bool {100pub fn isAlphabetic(c: u8) bool {
322 return inTable(c, tIndex.Alpha);101 return switch (c) {
102 'A'...'Z', 'a'...'z' => true,
103 else => false,
104 };
323}105}
324106
325/// Returns whether the character is a control character.107/// Returns whether the character is a control character.
326/// This is the same as `!isPrint(c)`.
327///108///
328/// See also: `control_code`.109/// See also: `control_code`
329pub fn isControl(c: u8) bool {110pub fn isControl(c: u8) bool {
330 return c <= control_code.us or c == control_code.del;111 return c <= control_code.us or c == control_code.del;
331}112}
332113
333/// Returns whether the character is a digit.114/// Returns whether the character is a digit.
334pub fn isDigit(c: u8) bool {115pub fn isDigit(c: u8) bool {
335 return inTable(c, tIndex.Digit);116 return switch (c) {
336}117 '0'...'9' => true,
337118 else => false,
338/// DEPRECATED: use `isPrint(c) and c != ' '` instead119 };
339pub fn isGraph(c: u8) bool {
340 return inTable(c, tIndex.Graph);
341}120}
342121
343/// Returns whether the character is a lowercased letter.122/// Returns whether the character is a lowercase letter.
344pub fn isLower(c: u8) bool {123pub fn isLower(c: u8) bool {
345 return inTable(c, tIndex.Lower);124 return switch (c) {
125 'a'...'z' => true,
126 else => false,
127 };
346}128}
347129
348/// Returns whether the character has some graphical representation and can be printed.130/// Returns whether the character is printable and has some graphical representation,
349/// This also returns `true` for the space character.131/// including the space character.
350/// This is the same as `!isControl(c)`.
351pub fn isPrint(c: u8) bool {132pub fn isPrint(c: u8) bool {
352 return inTable(c, tIndex.Graph) or c == ' ';133 return isASCII(c) and !isControl(c);
353}
354
355/// DEPRECATED: create your own function based on your needs and what you want to do.
356pub fn isPunct(c: u8) bool {
357 return inTable(c, tIndex.Punct);
358}134}
359135
360/// Returns whether this character is included in `whitespace`.136/// Returns whether this character is included in `whitespace`.
361pub fn isWhitespace(c: u8) bool {137pub fn isWhitespace(c: u8) bool {
362 return inTable(c, tIndex.Space);138 return for (whitespace) |other| {
139 if (c == other)
140 break true;
141 } else false;
363}142}
364143
365/// Whitespace for general use.144/// Whitespace for general use.
366/// This may be used with e.g. `std.mem.trim` to trim whitespace.145/// This may be used with e.g. `std.mem.trim` to trim whitespace.
367///146///
368/// See also: `isWhitespace`.147/// See also: `isWhitespace`
369pub const whitespace = [_]u8{ ' ', '\t', '\n', '\r', control_code.vt, control_code.ff };148pub const whitespace = [_]u8{ ' ', '\t', '\n', '\r', control_code.vt, control_code.ff };
370149
371test "whitespace" {150test "whitespace" {
...@@ -377,14 +156,20 @@ test "whitespace" {...@@ -377,14 +156,20 @@ test "whitespace" {
377 }156 }
378}157}
379158
380/// Returns whether the character is an uppercased letter.159/// Returns whether the character is an uppercase letter.
381pub fn isUpper(c: u8) bool {160pub fn isUpper(c: u8) bool {
382 return inTable(c, tIndex.Upper);161 return switch (c) {
162 'A'...'Z' => true,
163 else => false,
164 };
383}165}
384166
385/// Returns whether the character is a hexadecimal digit. This is case-insensitive.167/// Returns whether the character is a hexadecimal digit: A-F, a-f, or 0-9.
386pub fn isHex(c: u8) bool {168pub fn isHex(c: u8) bool {
387 return inTable(c, tIndex.Hex);169 return switch (c) {
170 '0'...'9', 'A'...'F', 'a'...'f' => true,
171 else => false,
172 };
388}173}
389174
390/// Returns whether the character is a 7-bit ASCII character.175/// Returns whether the character is a 7-bit ASCII character.
...@@ -392,12 +177,7 @@ pub fn isASCII(c: u8) bool {...@@ -392,12 +177,7 @@ pub fn isASCII(c: u8) bool {
392 return c < 128;177 return c < 128;
393}178}
394179
395/// DEPRECATED: use `c == ' ' or c == '\t'` or try `isWhitespace`180/// Uppercases the character and returns it as-is if already uppercase or not a letter.
396pub fn isBlank(c: u8) bool {
397 return (c == ' ') or (c == '\x09');
398}
399
400/// Uppercases the character and returns it as-is if it's already uppercased or not a letter.
401pub fn toUpper(c: u8) u8 {181pub fn toUpper(c: u8) u8 {
402 if (isLower(c)) {182 if (isLower(c)) {
403 return c & 0b11011111;183 return c & 0b11011111;
...@@ -406,7 +186,7 @@ pub fn toUpper(c: u8) u8 {...@@ -406,7 +186,7 @@ pub fn toUpper(c: u8) u8 {
406 }186 }
407}187}
408188
409/// Lowercases the character and returns it as-is if it's already lowercased or not a letter.189/// Lowercases the character and returns it as-is if already lowercase or not a letter.
410pub fn toLower(c: u8) u8 {190pub fn toLower(c: u8) u8 {
411 if (isUpper(c)) {191 if (isUpper(c)) {
412 return c | 0b00100000;192 return c | 0b00100000;
...@@ -415,53 +195,77 @@ pub fn toLower(c: u8) u8 {...@@ -415,53 +195,77 @@ pub fn toLower(c: u8) u8 {
415 }195 }
416}196}
417197
418test "ascii character classes" {198test "ASCII character classes" {
419 const testing = std.testing;199 const testing = std.testing;
420200
421 try testing.expect(!isControl('a'));201 try testing.expect(!isControl('a'));
422 try testing.expect(!isControl('z'));202 try testing.expect(!isControl('z'));
203 try testing.expect(!isControl(' '));
423 try testing.expect(isControl(control_code.nul));204 try testing.expect(isControl(control_code.nul));
424 try testing.expect(isControl(control_code.ff));205 try testing.expect(isControl(control_code.ff));
425 try testing.expect(isControl(control_code.us));206 try testing.expect(isControl(control_code.us));
207 try testing.expect(isControl(control_code.del));
208 try testing.expect(!isControl(0x80));
209 try testing.expect(!isControl(0xff));
426210
427 try testing.expect('C' == toUpper('c'));211 try testing.expect('C' == toUpper('c'));
428 try testing.expect(':' == toUpper(':'));212 try testing.expect(':' == toUpper(':'));
429 try testing.expect('\xab' == toUpper('\xab'));213 try testing.expect('\xab' == toUpper('\xab'));
430 try testing.expect(!isUpper('z'));214 try testing.expect(!isUpper('z'));
215 try testing.expect(!isUpper(0x80));
216 try testing.expect(!isUpper(0xff));
431217
432 try testing.expect('c' == toLower('C'));218 try testing.expect('c' == toLower('C'));
433 try testing.expect(':' == toLower(':'));219 try testing.expect(':' == toLower(':'));
434 try testing.expect('\xab' == toLower('\xab'));220 try testing.expect('\xab' == toLower('\xab'));
435 try testing.expect(!isLower('Z'));221 try testing.expect(!isLower('Z'));
222 try testing.expect(!isLower(0x80));
223 try testing.expect(!isLower(0xff));
436224
437 try testing.expect(isAlphanumeric('Z'));225 try testing.expect(isAlphanumeric('Z'));
438 try testing.expect(isAlphanumeric('z'));226 try testing.expect(isAlphanumeric('z'));
439 try testing.expect(isAlphanumeric('5'));227 try testing.expect(isAlphanumeric('5'));
440 try testing.expect(isAlphanumeric('5'));228 try testing.expect(isAlphanumeric('a'));
441 try testing.expect(!isAlphanumeric('!'));229 try testing.expect(!isAlphanumeric('!'));
230 try testing.expect(!isAlphanumeric(0x80));
231 try testing.expect(!isAlphanumeric(0xff));
442232
443 try testing.expect(!isAlpha('5'));233 try testing.expect(!isAlphabetic('5'));
444 try testing.expect(isAlpha('c'));234 try testing.expect(isAlphabetic('c'));
445 try testing.expect(!isAlpha('5'));235 try testing.expect(!isAlphabetic('@'));
236 try testing.expect(isAlphabetic('Z'));
237 try testing.expect(!isAlphabetic(0x80));
238 try testing.expect(!isAlphabetic(0xff));
446239
447 try testing.expect(isWhitespace(' '));240 try testing.expect(isWhitespace(' '));
448 try testing.expect(isWhitespace('\t'));241 try testing.expect(isWhitespace('\t'));
449 try testing.expect(isWhitespace('\r'));242 try testing.expect(isWhitespace('\r'));
450 try testing.expect(isWhitespace('\n'));243 try testing.expect(isWhitespace('\n'));
244 try testing.expect(isWhitespace(control_code.ff));
451 try testing.expect(!isWhitespace('.'));245 try testing.expect(!isWhitespace('.'));
246 try testing.expect(!isWhitespace(control_code.us));
247 try testing.expect(!isWhitespace(0x80));
248 try testing.expect(!isWhitespace(0xff));
452249
453 try testing.expect(!isHex('g'));250 try testing.expect(!isHex('g'));
454 try testing.expect(isHex('b'));251 try testing.expect(isHex('b'));
252 try testing.expect(isHex('F'));
455 try testing.expect(isHex('9'));253 try testing.expect(isHex('9'));
254 try testing.expect(!isHex(0x80));
255 try testing.expect(!isHex(0xff));
456256
457 try testing.expect(!isDigit('~'));257 try testing.expect(!isDigit('~'));
458 try testing.expect(isDigit('0'));258 try testing.expect(isDigit('0'));
459 try testing.expect(isDigit('9'));259 try testing.expect(isDigit('9'));
260 try testing.expect(!isDigit(0x80));
261 try testing.expect(!isDigit(0xff));
460262
461 try testing.expect(isPrint(' '));263 try testing.expect(isPrint(' '));
462 try testing.expect(isPrint('@'));264 try testing.expect(isPrint('@'));
463 try testing.expect(isPrint('~'));265 try testing.expect(isPrint('~'));
464 try testing.expect(!isPrint(control_code.esc));266 try testing.expect(!isPrint(control_code.esc));
267 try testing.expect(!isPrint(0x80));
268 try testing.expect(!isPrint(0xff));
465}269}
466270
467/// Writes a lower case copy of `ascii_string` to `output`.271/// Writes a lower case copy of `ascii_string` to `output`.
...@@ -541,7 +345,7 @@ pub fn startsWithIgnoreCase(haystack: []const u8, needle: []const u8) bool {...@@ -541,7 +345,7 @@ pub fn startsWithIgnoreCase(haystack: []const u8, needle: []const u8) bool {
541 return if (needle.len > haystack.len) false else eqlIgnoreCase(haystack[0..needle.len], needle);345 return if (needle.len > haystack.len) false else eqlIgnoreCase(haystack[0..needle.len], needle);
542}346}
543347
544test "ascii.startsWithIgnoreCase" {348test "startsWithIgnoreCase" {
545 try std.testing.expect(startsWithIgnoreCase("boB", "Bo"));349 try std.testing.expect(startsWithIgnoreCase("boB", "Bo"));
546 try std.testing.expect(!startsWithIgnoreCase("Needle in hAyStAcK", "haystack"));350 try std.testing.expect(!startsWithIgnoreCase("Needle in hAyStAcK", "haystack"));
547}351}
...@@ -550,7 +354,7 @@ pub fn endsWithIgnoreCase(haystack: []const u8, needle: []const u8) bool {...@@ -550,7 +354,7 @@ pub fn endsWithIgnoreCase(haystack: []const u8, needle: []const u8) bool {
550 return if (needle.len > haystack.len) false else eqlIgnoreCase(haystack[haystack.len - needle.len ..], needle);354 return if (needle.len > haystack.len) false else eqlIgnoreCase(haystack[haystack.len - needle.len ..], needle);
551}355}
552356
553test "ascii.endsWithIgnoreCase" {357test "endsWithIgnoreCase" {
554 try std.testing.expect(endsWithIgnoreCase("Needle in HaYsTaCk", "haystack"));358 try std.testing.expect(endsWithIgnoreCase("Needle in HaYsTaCk", "haystack"));
555 try std.testing.expect(!endsWithIgnoreCase("BoB", "Bo"));359 try std.testing.expect(!endsWithIgnoreCase("BoB", "Bo"));
556}360}
lib/std/fmt.zig+2-1
...@@ -2198,8 +2198,9 @@ test "slice" {...@@ -2198,8 +2198,9 @@ test "slice" {
2198}2198}
21992199
2200test "escape non-printable" {2200test "escape non-printable" {
2201 try expectFmt("abc", "{s}", .{fmtSliceEscapeLower("abc")});2201 try expectFmt("abc 123", "{s}", .{fmtSliceEscapeLower("abc 123")});
2202 try expectFmt("ab\\xffc", "{s}", .{fmtSliceEscapeLower("ab\xffc")});2202 try expectFmt("ab\\xffc", "{s}", .{fmtSliceEscapeLower("ab\xffc")});
2203 try expectFmt("abc 123", "{s}", .{fmtSliceEscapeUpper("abc 123")});
2203 try expectFmt("ab\\xFFc", "{s}", .{fmtSliceEscapeUpper("ab\xffc")});2204 try expectFmt("ab\\xFFc", "{s}", .{fmtSliceEscapeUpper("ab\xffc")});
2204}2205}
22052206
lib/std/net.zig+1-1
...@@ -1192,7 +1192,7 @@ pub fn isValidHostName(hostname: []const u8) bool {...@@ -1192,7 +1192,7 @@ pub fn isValidHostName(hostname: []const u8) bool {
1192 if (hostname.len >= 254) return false;1192 if (hostname.len >= 254) return false;
1193 if (!std.unicode.utf8ValidateSlice(hostname)) return false;1193 if (!std.unicode.utf8ValidateSlice(hostname)) return false;
1194 for (hostname) |byte| {1194 for (hostname) |byte| {
1195 if (byte >= 0x80 or byte == '.' or byte == '-' or std.ascii.isAlNum(byte)) {1195 if (!std.ascii.isASCII(byte) or byte == '.' or byte == '-' or std.ascii.isAlphanumeric(byte)) {
1196 continue;1196 continue;
1197 }1197 }
1198 return false;1198 return false;
lib/std/zig/parse.zig+2-2
...@@ -1531,7 +1531,7 @@ const Parser = struct {...@@ -1531,7 +1531,7 @@ const Parser = struct {
1531 // without types we don't know if '&&' was intended as 'bitwise_and address_of', or a c-style logical_and1531 // without types we don't know if '&&' was intended as 'bitwise_and address_of', or a c-style logical_and
1532 // The best the parser can do is recommend changing it to 'and' or ' & &'1532 // The best the parser can do is recommend changing it to 'and' or ' & &'
1533 try p.warnMsg(.{ .tag = .invalid_ampersand_ampersand, .token = oper_token });1533 try p.warnMsg(.{ .tag = .invalid_ampersand_ampersand, .token = oper_token });
1534 } else if (std.ascii.isSpace(char_before) != std.ascii.isSpace(char_after)) {1534 } else if (std.ascii.isWhitespace(char_before) != std.ascii.isWhitespace(char_after)) {
1535 try p.warnMsg(.{ .tag = .mismatched_binary_op_whitespace, .token = oper_token });1535 try p.warnMsg(.{ .tag = .mismatched_binary_op_whitespace, .token = oper_token });
1536 }1536 }
1537 }1537 }
...@@ -1728,7 +1728,7 @@ const Parser = struct {...@@ -1728,7 +1728,7 @@ const Parser = struct {
1728 var sentinel: Node.Index = 0;1728 var sentinel: Node.Index = 0;
1729 if (p.eatToken(.identifier)) |ident| {1729 if (p.eatToken(.identifier)) |ident| {
1730 const ident_slice = p.source[p.token_starts[ident]..p.token_starts[ident + 1]];1730 const ident_slice = p.source[p.token_starts[ident]..p.token_starts[ident + 1]];
1731 if (!std.mem.eql(u8, std.mem.trimRight(u8, ident_slice, &std.ascii.spaces), "c")) {1731 if (!std.mem.eql(u8, std.mem.trimRight(u8, ident_slice, &std.ascii.whitespace), "c")) {
1732 p.tok_i -= 1;1732 p.tok_i -= 1;
1733 }1733 }
1734 } else if (p.eatToken(.colon)) |_| {1734 } else if (p.eatToken(.colon)) |_| {
lib/std/zig/render.zig+4-4
...@@ -2648,7 +2648,7 @@ fn renderComments(ais: *Ais, tree: Ast, start: usize, end: usize) Error!bool {...@@ -2648,7 +2648,7 @@ fn renderComments(ais: *Ais, tree: Ast, start: usize, end: usize) Error!bool {
2648 const newline = if (newline_index) |i| comment_start + i else null;2648 const newline = if (newline_index) |i| comment_start + i else null;
26492649
2650 const untrimmed_comment = tree.source[comment_start .. newline orelse tree.source.len];2650 const untrimmed_comment = tree.source[comment_start .. newline orelse tree.source.len];
2651 const trimmed_comment = mem.trimRight(u8, untrimmed_comment, &std.ascii.spaces);2651 const trimmed_comment = mem.trimRight(u8, untrimmed_comment, &std.ascii.whitespace);
26522652
2653 // Don't leave any whitespace at the start of the file2653 // Don't leave any whitespace at the start of the file
2654 if (index != 0) {2654 if (index != 0) {
...@@ -2669,7 +2669,7 @@ fn renderComments(ais: *Ais, tree: Ast, start: usize, end: usize) Error!bool {...@@ -2669,7 +2669,7 @@ fn renderComments(ais: *Ais, tree: Ast, start: usize, end: usize) Error!bool {
26692669
2670 index = 1 + (newline orelse end - 1);2670 index = 1 + (newline orelse end - 1);
26712671
2672 const comment_content = mem.trimLeft(u8, trimmed_comment["//".len..], &std.ascii.spaces);2672 const comment_content = mem.trimLeft(u8, trimmed_comment["//".len..], &std.ascii.whitespace);
2673 if (ais.disabled_offset != null and mem.eql(u8, comment_content, "zig fmt: on")) {2673 if (ais.disabled_offset != null and mem.eql(u8, comment_content, "zig fmt: on")) {
2674 // Write the source for which formatting was disabled directly2674 // Write the source for which formatting was disabled directly
2675 // to the underlying writer, fixing up invaild whitespace.2675 // to the underlying writer, fixing up invaild whitespace.
...@@ -2716,7 +2716,7 @@ fn renderExtraNewlineToken(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex) Er...@@ -2716,7 +2716,7 @@ fn renderExtraNewlineToken(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex) Er
2716 // non-whitespace character is encountered or two newlines have been found.2716 // non-whitespace character is encountered or two newlines have been found.
2717 var i = token_start - 1;2717 var i = token_start - 1;
2718 var newlines: u2 = 0;2718 var newlines: u2 = 0;
2719 while (std.ascii.isSpace(tree.source[i])) : (i -= 1) {2719 while (std.ascii.isWhitespace(tree.source[i])) : (i -= 1) {
2720 if (tree.source[i] == '\n') newlines += 1;2720 if (tree.source[i] == '\n') newlines += 1;
2721 if (newlines == 2) return ais.insertNewline();2721 if (newlines == 2) return ais.insertNewline();
2722 if (i == prev_token_end) break;2722 if (i == prev_token_end) break;
...@@ -2778,7 +2778,7 @@ fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {...@@ -2778,7 +2778,7 @@ fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {
2778 ret.len -= 1;2778 ret.len -= 1;
2779 },2779 },
2780 .container_doc_comment, .doc_comment => {2780 .container_doc_comment, .doc_comment => {
2781 ret = mem.trimRight(u8, ret, &std.ascii.spaces);2781 ret = mem.trimRight(u8, ret, &std.ascii.whitespace);
2782 },2782 },
2783 else => {},2783 else => {},
2784 }2784 }
lib/std/zig/tokenizer.zig+1-1
...@@ -1232,7 +1232,7 @@ pub const Tokenizer = struct {...@@ -1232,7 +1232,7 @@ pub const Tokenizer = struct {
1232 fn getInvalidCharacterLength(self: *Tokenizer) u3 {1232 fn getInvalidCharacterLength(self: *Tokenizer) u3 {
1233 const c0 = self.buffer[self.index];1233 const c0 = self.buffer[self.index];
1234 if (std.ascii.isASCII(c0)) {1234 if (std.ascii.isASCII(c0)) {
1235 if (std.ascii.isCntrl(c0)) {1235 if (std.ascii.isControl(c0)) {
1236 // ascii control codes are never allowed1236 // ascii control codes are never allowed
1237 // (note that \n was checked before we got here)1237 // (note that \n was checked before we got here)
1238 return 1;1238 return 1;
src/DepTokenizer.zig+4-4
...@@ -866,7 +866,7 @@ test "error target - continuation expecting end-of-line" {...@@ -866,7 +866,7 @@ test "error target - continuation expecting end-of-line" {
866 );866 );
867 try depTokenizer("foo.o: \\ ",867 try depTokenizer("foo.o: \\ ",
868 \\target = {foo.o}868 \\target = {foo.o}
869 \\ERROR: illegal char \x20 at position 8: continuation expecting end-of-line869 \\ERROR: illegal char ' ' at position 8: continuation expecting end-of-line
870 );870 );
871 try depTokenizer("foo.o: \\x",871 try depTokenizer("foo.o: \\x",
872 \\target = {foo.o}872 \\target = {foo.o}
...@@ -1053,10 +1053,10 @@ fn printCharValues(out: anytype, bytes: []const u8) !void {...@@ -1053,10 +1053,10 @@ fn printCharValues(out: anytype, bytes: []const u8) !void {
1053}1053}
10541054
1055fn printUnderstandableChar(out: anytype, char: u8) !void {1055fn printUnderstandableChar(out: anytype, char: u8) !void {
1056 if (!std.ascii.isPrint(char) or char == ' ') {1056 if (std.ascii.isPrint(char)) {
1057 try out.print("\\x{X:0>2}", .{char});1057 try out.print("'{c}'", .{char});
1058 } else {1058 } else {
1059 try out.print("'{c}'", .{printable_char_tab[char]});1059 try out.print("\\x{X:0>2}", .{char});
1060 }1060 }
1061}1061}
10621062
src/translate_c.zig+1-1
...@@ -5738,7 +5738,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {...@@ -5738,7 +5738,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
5738 if (mem.indexOfScalar(u8, lit_bytes, '.')) |dot_index| {5738 if (mem.indexOfScalar(u8, lit_bytes, '.')) |dot_index| {
5739 if (dot_index == 2) {5739 if (dot_index == 2) {
5740 lit_bytes = try std.fmt.allocPrint(c.arena, "0x0{s}", .{lit_bytes[2..]});5740 lit_bytes = try std.fmt.allocPrint(c.arena, "0x0{s}", .{lit_bytes[2..]});
5741 } else if (dot_index + 1 == lit_bytes.len or !std.ascii.isXDigit(lit_bytes[dot_index + 1])) {5741 } else if (dot_index + 1 == lit_bytes.len or !std.ascii.isHex(lit_bytes[dot_index + 1])) {
5742 // If the literal lacks a digit after the `.`, we need to5742 // If the literal lacks a digit after the `.`, we need to
5743 // add one since `0x1.p10` would be invalid syntax in Zig.5743 // add one since `0x1.p10` would be invalid syntax in Zig.
5744 lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}0{s}", .{5744 lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}0{s}", .{