hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

ctype.ha (3500B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 def U: u8 = 0o1;
      5 def L: u8 = 0o2;
      6 def N: u8 = 0o4;
      7 def S: u8 = 0o10;
      8 def P: u8 = 0o20;
      9 def C: u8 = 0o40;
     10 def B: u8 = 0o100;
     11 def X: u8 = 0o200;
     12 
     13 // LUT of bitfields with character attributes
     14 const cclass: []u8 = [
     15 //	 0	 1	 2	 3	 4	 5	 6	 7
     16 	C,	C,	C,	C,	C,	C,	C,	C,	// 0
     17 	C,	S|C,	S|C,	S|C,	S|C,	S|C,	C,	C,	// 10
     18 	C,	C,	C,	C,	C,	C,	C,	C,	// 20
     19 	C,	C,	C,	C,	C,	C,	C,	C,	// 30
     20 	S|B,	P,	P,	P,	P,	P,	P,	P,	// 40
     21 	P,	P,	P,	P,	P,	P,	P,	P,	// 50
     22 	N|X,	N|X,	N|X,	N|X,	N|X,	N|X,	N|X,	N|X,	// 60
     23 	N|X,	N|X,	P,	P,	P,	P,	P,	P,	// 70
     24 	P,	U|X,	U|X,	U|X,	U|X,	U|X,	U|X,	U,	// 100
     25 	U,	U,	U,	U,	U,	U,	U,	U,	// 110
     26 	U,	U,	U,	U,	U,	U,	U,	U,	// 120
     27 	U,	U,	U,	P,	P,	P,	P,	P,	// 130
     28 	P,	L|X,	L|X,	L|X,	L|X,	L|X,	L|X,	L,	// 140
     29 	L,	L,	L,	L,	L,	L,	L,	L,	// 150
     30 	L,	L,	L,	L,	L,	L,	L,	L,	// 160
     31 	L,	L,	L,	P,	P,	P,	P,	C,	// 170
     32 ];
     33 
     34 // Returns true if an ASCII character is a letter.
     35 export fn isalpha(c: rune) bool =
     36 	if (!valid(c)) false else cclass[c: u32] & (U | L) > 0;
     37 
     38 // Returns true if an ASCII character is uppercase.
     39 export fn isupper(c: rune) bool =
     40 	if (!valid(c)) false else cclass[c: u32] & U > 0;
     41 
     42 // Returns true if an ASCII character is lowercase.
     43 export fn islower(c: rune) bool =
     44 	if (!valid(c)) false else cclass[c: u32] & L > 0;
     45 
     46 // Returns true if an ASCII character is a digit.
     47 export fn isdigit(c: rune) bool =
     48 	if (!valid(c)) false else cclass[c: u32] & N > 0;
     49 
     50 // Returns true if an ASCII character is a hexadecimal digit.
     51 export fn isxdigit(c: rune) bool =
     52 	if (!valid(c)) false else cclass[c: u32] & X > 0;
     53 
     54 // Returns true if an ASCII character is a white-space character -
     55 // one of '\f', '\n', '\r', '\t', '\v', ' '.
     56 export fn isspace(c: rune) bool =
     57 	if (!valid(c)) false else cclass[c: u32] & S > 0;
     58 
     59 // Returns true if an ASCII character is punctuation.
     60 export fn ispunct(c: rune) bool =
     61 	if (!valid(c)) false else cclass[c: u32] & P > 0;
     62 
     63 // Returns true if an ASCII character is alphanumeric.
     64 export fn isalnum(c: rune) bool =
     65 	if (!valid(c)) false else cclass[c: u32] & (U | L | N) > 0;
     66 
     67 // Returns true if an ASCII character is printable.
     68 export fn isprint(c: rune) bool =
     69 	if (!valid(c)) false else cclass[c: u32] & (P | U | L | N | B ) > 0;
     70 
     71 // Returns true if an ASCII character is any printable character other than
     72 // space.
     73 export fn isgraph(c: rune) bool =
     74 	if (!valid(c)) false else cclass[c: u32] & (P | U | L | N) > 0;
     75 
     76 // Returns true if an ASCII character is a control character.
     77 export fn iscntrl(c: rune) bool =
     78 	if (!valid(c)) false else cclass[c: u32] & C > 0;
     79 
     80 // Returns true if a rune is a space or a tab.
     81 export fn isblank(c: rune) bool = (c == ' ' || c == '\t');
     82 
     83 // Returns the uppercase form of an ASCII character, or the original character
     84 // if it was not a lowercase letter (or was not ASCII).
     85 export fn toupper(c: rune) rune = {
     86 	return if (islower(c)) {
     87 		yield (c: u32 - 'a' + 'A'): rune;
     88 	} else c;
     89 };
     90 
     91 // Returns the lowercase form of an ASCII character, or the original character
     92 // if it was not an uppercase letter (or was not ASCII).
     93 export fn tolower(c: rune) rune = {
     94 	return if (isupper(c)) {
     95 		yield (c: u32 - 'A' + 'a'): rune;
     96 	} else c;
     97 };
     98 
     99 @test fn ctype() void = {
    100 	// Just some simple tests
    101 	assert(isspace(' ') && !isspace('x') && !isspace('こ'));
    102 	assert(isalnum('a') && isalnum('8') && !isalnum('こ'));
    103 	assert(!ispunct('\0') && iscntrl('\b'));
    104 	assert(tolower('A') == 'a' && tolower('こ') == 'こ');
    105 	assert(isblank(' ') && isblank('\t') && !isblank('6'));
    106 };