1 module diet.internal..string; 2 3 import memutils.vector; 4 import memutils.scoped; 5 import diet.defs; 6 7 @safe nothrow: 8 Vector!string ctsplit(string s, char c) { 9 Vector!string ret; 10 int i, j; 11 for (i = 0; i < s.length; i++) { 12 if (s[i] == c) { 13 if (i > j+1) // ignore consecutive instances of c 14 ret ~= s[j .. i]; 15 i++; 16 j = i; 17 } 18 } 19 if (j < s.length) ret ~= s[j .. $]; // remainder 20 return ret.move(); 21 } 22 23 string dstringEscape(in string str) 24 { 25 Vector!char ret; 26 size_t new_len = str.length; 27 foreach( ch; str ) { 28 switch (ch) { 29 default: break; 30 case '\\': new_len++; break; 31 case '\r': new_len++; break; 32 case '\n': new_len++; break; 33 case '\t': new_len++; break; 34 case '\"': new_len++; break; 35 } 36 } 37 ret.reserve(new_len); 38 foreach( ch; str ) { 39 switch (ch) { 40 default: ret ~= ch; break; 41 case '\\': ret ~= "\\\\"; break; 42 case '\r': ret ~= "\\r"; break; 43 case '\n': ret ~= "\\n"; break; 44 case '\t': ret ~= "\\t"; break; 45 case '\"': ret ~= "\\\""; break; 46 } 47 } 48 return ret[].copy(); 49 } 50 51 string dstringUnescape(in string str) 52 { 53 Vector!char ret; 54 size_t i, start = 0; 55 for( i = 0; i < str.length; i++ ) 56 if( str[i] == '\\' ){ 57 if( i > start ){ 58 if( start > 0 ) ret ~= str[start .. i]; 59 else ret[] = str[0 .. i]; 60 } 61 assert(i+1 < str.length, format!"The string ends with the escape char: %s"(str)); 62 switch(str[i+1]){ 63 default: ret ~= str[i+1]; break; 64 case 'r': ret ~= '\r'; break; 65 case 'n': ret ~= '\n'; break; 66 case 't': ret ~= '\t'; break; 67 } 68 i++; 69 start = i+1; 70 } 71 72 if( i > start ){ 73 if( start == 0 ) return str; 74 else ret ~= str[start .. i]; 75 } 76 return ret[].copy(); 77 } 78 string sanitizeEscaping(string str) 79 { 80 str = dstringUnescape(str); 81 return dstringEscape(str); 82 } 83 pure: 84 85 86 bool ctcanFind(T, U)(T items, U needle) { 87 foreach(item; items) { 88 if (item == needle) { 89 return true; 90 } 91 } 92 return false; 93 } 94 95 96 string ctstrip(string s) 97 { 98 size_t strt = 0, end = s.length; 99 while (strt < s.length && s[strt].isWhite) strt++; 100 while (end > 0 && s[end-1].isWhite) end--; 101 return strt < end ? s[strt .. end] : null; 102 } 103 104 string ctstripLeft(string s) 105 { 106 size_t i = 0; 107 while (i < s.length && s[i].isWhite) i++; 108 return s[i .. $]; 109 } 110 111 bool ctstartsWith(string s, string compare) { 112 if (s.length < compare.length) return false; 113 return s[0 .. compare.length] == compare; 114 } 115 bool ctstartsWith(string s, char compare) { 116 if (s.length < 1) return false; 117 return s[0] == compare; 118 } 119 bool ctendsWith(string s, string compare) { 120 if (s.length < compare.length) return false; 121 return s[$-compare.length .. $] == compare; 122 } 123 124 string ctstripRight(string s) 125 { 126 size_t i = s.length; 127 while (i > 0 && s[i-1].isWhite) i--; 128 return s[0 .. i]; 129 } 130 131 132 string stripUTF8BOM(string input) 133 { 134 char[3] comp = [0xEF, 0xBB, 0xBF]; 135 if (input.length >= 3 && input[0 .. 3] == comp) 136 return input[3 .. $]; 137 return input; 138 } 139 140 bool isWhite(dchar c) @safe pure nothrow @nogc 141 { 142 return c == ' ' || (c >= 0x09 && c <= 0x0D); 143 }