4.0 KiB
4.0 KiB
std.ascii
7-bit ASCII character classification and manipulation. Use std.unicode for
UTF encoding, decoding, validation, and codepoint iteration; it is not a
drop-in replacement for Unicode-aware classification, case conversion, or case
folding.
Character Classification
const std = @import("std");
const ascii = std.ascii;
// Character type checks (all return bool)
ascii.isAlphanumeric('a') // A-Z, a-z, 0-9
ascii.isAlphabetic('a') // A-Z, a-z
ascii.isDigit('5') // 0-9
ascii.isHex('F') // A-F, a-f, 0-9
ascii.isUpper('A') // A-Z
ascii.isLower('a') // a-z
ascii.isWhitespace(' ') // space, \t, \n, \r, \v, \f
ascii.isPrint('!') // printable 7-bit ASCII and not control
ascii.isControl('\n') // control characters (0x00-0x1F, 0x7F)
ascii.isAscii(c) // c < 128
ascii.isGraphical('!') // printable ASCII excluding space
ascii.isPunctuation('!') // ASCII punctuation
Case Conversion
// Single character
ascii.toUpper('a') // 'A'
ascii.toLower('A') // 'a'
// Strings - to buffer
var lower_buf: [100]u8 = undefined;
var upper_buf: [100]u8 = undefined;
const lower = ascii.lowerString(&lower_buf, "HeLLo"); // "hello"
const upper = ascii.upperString(&upper_buf, "HeLLo"); // "HELLO"
// Strings - allocating
const allocated_lower = try ascii.allocLowerString(allocator, "HeLLo");
defer allocator.free(allocated_lower); // "hello"
const allocated_upper = try ascii.allocUpperString(allocator, "HeLLo");
defer allocator.free(allocated_upper); // "HELLO"
Case-Insensitive Comparison
// Equality
ascii.eqlIgnoreCase("Hello", "HELLO") // true
// Prefix/suffix
ascii.startsWithIgnoreCase("Hello World", "hello") // true
ascii.endsWithIgnoreCase("Hello World", "WORLD") // true
// Search
ascii.findIgnoreCase("Hello World", "world") // ?usize = 6
// Lexicographical order
ascii.orderIgnoreCase("abc", "ABC") // .eq
ascii.lessThanIgnoreCase("abc", "abd") // true
Constants
// Character sets (as strings)
ascii.lowercase // "abcdefghijklmnopqrstuvwxyz"
ascii.uppercase // "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
ascii.letters // lowercase ++ uppercase
// Whitespace array (for use with std.mem.trim)
ascii.whitespace // [_]u8{ ' ', '\t', '\n', '\r', '\v', '\f' }
Control Codes
const cc = std.ascii.control_code;
// Common control codes
cc.nul // 0x00 Null
cc.bel // 0x07 Bell
cc.bs // 0x08 Backspace
cc.ht // 0x09 Horizontal Tab (\t)
cc.lf // 0x0A Line Feed (\n)
cc.vt // 0x0B Vertical Tab
cc.ff // 0x0C Form Feed
cc.cr // 0x0D Carriage Return (\r)
cc.esc // 0x1B Escape
cc.del // 0x7F Delete
// Flow control
cc.xon // 0x11 XON (alias for dc1)
cc.xoff // 0x13 XOFF (alias for dc3)
Hex Escape Formatting
Format bytes with non-printable characters escaped:
const data = "hello\xffworld";
// Format with hex escapes for non-printable bytes
try stdout.print("{f}\n", .{ascii.hexEscape(data, .lower)});
// Output: hello\xffworld
try stdout.print("{f}\n", .{ascii.hexEscape(data, .upper)});
// Output: hello\xFFworld
Common Patterns
Trim whitespace
const trimmed = std.mem.trim(u8, " hello ", &ascii.whitespace);
// "hello"
Validate ASCII string
fn isAsciiString(s: []const u8) bool {
for (s) |c| {
if (!ascii.isAscii(c)) return false;
}
return true;
}
Case-insensitive map lookup
// Use ascii.lowerString to normalize keys
var buf: [64]u8 = undefined;
if (user_input.len > buf.len) return error.InputTooLong;
const normalized = ascii.lowerString(&buf, user_input);
if (map.get(normalized)) |value| {
// found
}
Notes
- All functions handle bytes > 127 gracefully (return
falsefor classification) - Functions use
u8notu7for convenience - ASCII case/comparison helpers are not Unicode-aware;
std.unicodecovers UTF encoding/decoding rather than locale-aware casing lowerString/upperStringassert output buffer is large enough- Normalize stored keys and lookup keys with the same convention