1 module bc..string.ascii; 2 3 /** 4 * Simplified ASCII strings case insensitve comparison. 5 * Returns: 6 * - < 0 - when first string is lesser that the second 7 * - = 0 - when both string are equal 8 * - > 0 - when first string is greater than the second 9 */ 10 int sicmp(const(char)[] a, const(char)[] b) @safe nothrow @nogc 11 { 12 immutable len = a.length > b.length ? b.length : a.length; 13 version (Posix) { 14 import core.sys.posix.strings : strncasecmp; 15 immutable diff = () @trusted { return strncasecmp(a.ptr, b.ptr, len); }(); 16 if (diff) return diff; 17 } else { 18 // TODO: manual loop unroll 19 immutable end = min(a.length, b.length); 20 for (int i=0; i < len; ++i) { 21 auto lhs = a[i].toLower; 22 auto rhs = b[i].toLower; 23 auto diff = lhs - rhs; 24 if (diff) return diff; 25 } 26 } 27 return (a.length > b.length) - (b.length > a.length); 28 } 29 30 @safe unittest 31 { 32 assert(sicmp("fOoo", "FoOo") == 0); 33 assert(sicmp("abcd", "efgh") < 0); 34 assert(sicmp("efgh", "abcd") > 0); 35 assert(sicmp("fOoox", "FoOo") > 0); 36 assert(sicmp("fOoo", "FoOox") < 0); 37 } 38 39 /// Converts ASCII characters 'A'..'Z' to a lower 'a'..'z'. 40 char toLower(char c) @safe pure nothrow @nogc 41 { 42 pragma(inline, true); 43 static immutable chmap = () 44 { 45 char[256] res = void; 46 47 for (int i=0; i < 256; ++i) { 48 if (i >= 'A' && i <= 'Z') res[i] = cast(char)(i+32); 49 else res[i] = cast(char)i; 50 } 51 return res; 52 }(); 53 54 return chmap[c]; 55 } 56 57 /// Converts ASCII characters 'a'..'z' to a upper 'A'..'Z'. 58 char toUpper(char c) @safe pure nothrow @nogc 59 { 60 pragma(inline, true); 61 static immutable chmap = () 62 { 63 char[256] res = void; 64 65 for (int i=0; i < 256; ++i) { 66 if (i >= 'a' && i <= 'z') res[i] = cast(char)(i-32); 67 else res[i] = cast(char)i; 68 } 69 return res; 70 }(); 71 72 return chmap[c]; 73 } 74 75 //@safe 76 unittest 77 { 78 assert('A'.toLower == 'a'); 79 assert('b'.toLower == 'b'); 80 assert('2'.toLower == '2'); 81 assert('Z'.toLower == 'z'); 82 83 assert('a'.toUpper == 'A'); 84 assert('B'.toUpper == 'B'); 85 assert('2'.toUpper == '2'); 86 assert('z'.toUpper == 'Z'); 87 } 88 89 /// Checks if character is a digit ('0'..'9') 90 bool isDigit(char c) @safe pure nothrow @nogc 91 { 92 pragma(inline, true); 93 static immutable chmap = () 94 { 95 bool[256] res = void; 96 97 for (int i=0; i < 256; ++i) { 98 if (i >= '0' && i <= '9') res[i] = true; 99 else res[i] = false; 100 } 101 return res; 102 }(); 103 104 return chmap[c]; 105 } 106 107 @safe unittest 108 { 109 assert('0'.isDigit); 110 assert('9'.isDigit); 111 assert(!'a'.isDigit); 112 assert(!'+'.isDigit); 113 }