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 }