Files
c3c/lib/std/core/ascii.c3

115 lines
5.2 KiB
Plaintext

<*
This module contains utils for handling ASCII characters. They only operate on
characters corresponding to 0-127.
*>
module std::core::ascii;
macro bool @is_lower(c) => ASCII_LOOKUP[c].lower; // Is a-z
macro bool @is_upper(c) => ASCII_LOOKUP[c].upper; // Is A-Z
macro bool @is_digit(c) => ASCII_LOOKUP[c].digit; // Is 0-9
macro bool @is_bdigit(c) => ASCII_LOOKUP[c].bin_digit; // Is 0-1
macro bool @is_odigit(c) => ASCII_LOOKUP[c].oct_digit; // Is 0-7
macro bool @is_xdigit(c) => ASCII_LOOKUP[c].hex_digit; // Is 0-9 or a-f or A-F
macro bool @is_alpha(c) => ASCII_LOOKUP[c].alpha; // Is a-z or A-Z
macro bool @is_print(c) => ASCII_LOOKUP[c].printable; // Is a printable character (space or higher and < 127
macro bool @is_graph(c) => ASCII_LOOKUP[c].graph; // Does it show any graphics (printable but not space)
macro bool @is_space(c) => ASCII_LOOKUP[c].space; // Is it a space character: space, tab, linefeed etc
macro bool @is_alnum(c) => ASCII_LOOKUP[c].alphanum; // Is it alpha or digit
macro bool @is_punct(c) => ASCII_LOOKUP[c].punct; // Is it "graph" but not digit or letter
macro bool @is_blank(c) => ASCII_LOOKUP[c].blank; // Is it a blank space: space or tab
macro bool @is_cntrl(c) => ASCII_LOOKUP[c].control; // Is it a control character: before space or 127
macro char @to_lower(c) => c + TO_LOWER[c]; // Convert A-Z to a-z if found
macro char @to_upper(c) => c - TO_UPPER[c]; // Convert a-z to A-Z if found
fn bool is_lower(char c) => @is_lower(c); // Is a-z
fn bool is_upper(char c) => @is_upper(c); // Is A-Z
fn bool is_digit(char c) => @is_digit(c); // Is 0-9
fn bool is_bdigit(char c) => @is_bdigit(c); // Is 0-1
fn bool is_odigit(char c) => @is_odigit(c); // Is 0-7
fn bool is_xdigit(char c) => @is_xdigit(c); // Is 0-9 or a-f or A-F
fn bool is_alpha(char c) => @is_alpha(c); // Is a-z or A-Z
fn bool is_print(char c) => @is_print(c); // Is a printable character (space or higher and < 127
fn bool is_graph(char c) => @is_graph(c); // Does it show any graphics (printable but not space)
fn bool is_space(char c) => @is_space(c); // Is it a space character: space, tab, linefeed etc
fn bool is_alnum(char c) => @is_alnum(c); // Is it alpha or digit
fn bool is_punct(char c) => @is_punct(c); // Is it "graph" but not digit or letter
fn bool is_blank(char c) => @is_blank(c); // Is it a blank space: space or tab
fn bool is_cntrl(char c) => @is_cntrl(c); // Is it a control character: before space or 127
fn char to_lower(char c) => @to_lower(c); // Convert A-Z to a-z if found
fn char to_upper(char c) => @to_upper(c); // Convert a-z to A-Z if found
// The following methods are macro methods for the same functions
macro bool char.is_lower(char c) => @is_lower(c);
macro bool char.is_upper(char c) => @is_upper(c);
macro bool char.is_digit(char c) => @is_digit(c);
macro bool char.is_bdigit(char c) => @is_bdigit(c);
macro bool char.is_odigit(char c) => @is_odigit(c);
macro bool char.is_xdigit(char c) => @is_xdigit(c);
macro bool char.is_alpha(char c) => @is_alpha(c);
macro bool char.is_print(char c) => @is_print(c);
macro bool char.is_graph(char c) => @is_graph(c);
macro bool char.is_space(char c) => @is_space(c);
macro bool char.is_alnum(char c) => @is_alnum(c);
macro bool char.is_punct(char c) => @is_punct(c);
macro bool char.is_blank(char c) => @is_blank(c);
macro bool char.is_cntrl(char c) => @is_cntrl(c);
macro char char.to_lower(char c) => @to_lower(c);
macro char char.to_upper(char c) => @to_upper(c);
<*
Convert a-f/A-F/0-9 to the appropriate hex value.
@require c.is_xdigit()
@ensure return >= 0 && return <= 15
*>
macro char char.from_hex(char c) => HEX_VALUE[c];
<*
Bitstruct containing the different properties of a character
*>
bitstruct CharType : ushort @private
{
bool lower;
bool upper;
bool digit;
bool bin_digit;
bool hex_digit;
bool oct_digit;
bool alpha;
bool alphanum;
bool space;
bool printable;
bool blank;
bool punct;
bool control;
bool graph;
}
const CharType[256] ASCII_LOOKUP @private = {
[0..31] = { .control },
[9..13] = { .control, .space },
['\t'] = { .control, .space, .blank },
[' '] = { .space, .printable, .blank },
[33..126] = { .printable, .graph, .punct },
['0'..'9'] = { .printable, .graph, .alphanum, .hex_digit, .digit },
['2'..'7'] = { .printable, .graph, .alphanum, .hex_digit, .digit, .oct_digit },
['0'..'1'] = { .printable, .graph, .alphanum, .hex_digit, .digit, .oct_digit, .bin_digit },
['A'..'Z'] = { .printable, .graph, .alphanum, .alpha, .upper },
['A'..'F'] = { .printable, .graph, .alphanum, .alpha, .upper, .hex_digit },
['a'..'z'] = { .printable, .graph, .alphanum, .alpha, .lower },
['a'..'f'] = { .printable, .graph, .alphanum, .alpha, .lower, .hex_digit },
[127] = { .control },
};
const char[256] HEX_VALUE = {
['0'] = 0, ['1'] = 1, ['2'] = 2, ['3'] = 3, ['4'] = 4,
['5'] = 5, ['6'] = 6, ['7'] = 7, ['8'] = 8, ['9'] = 9,
['A'] = 10, ['B'] = 11, ['C'] = 12, ['D'] = 13, ['E'] = 14,
['F'] = 15, ['a'] = 10, ['b'] = 11, ['c'] = 12, ['d'] = 13,
['e'] = 14, ['f'] = 15
};
const char[256] TO_UPPER @private = { ['a'..'z'] = 'a' - 'A' };
const char[256] TO_LOWER @private = { ['A'..'Z'] = 'a' - 'A' };