1 template <class B>
2 force_inline
Insert(int pos,const char * s)3 void AString<B>::Insert(int pos, const char *s)
4 {
5 	Insert(pos, s, strlen__(s));
6 }
7 
8 template <class B>
Cat(int c,int count)9 void AString<B>::Cat(int c, int count)
10 {
11 	tchar *s = B::Insert(GetLength(), count, NULL);
12 	while(count--)
13 		*s++ = c;
14 }
15 
16 template <class B>
17 force_inline
Cat(const tchar * s)18 void AString<B>::Cat(const tchar *s)
19 {
20 	Cat(s, strlen__(s));
21 }
22 
23 template <class B>
Compare(const tchar * b) const24 int AString<B>::Compare(const tchar *b) const
25 {
26 	const tchar *a = B::Begin();
27 	const tchar *ae = End();
28 	for(;;) {
29 		if(a >= ae)
30 			return *b == 0 ? 0 : -1;
31 		if(*b == 0)
32 			return 1;
33 		int q = cmpval__(*a++) - cmpval__(*b++);
34 		if(q)
35 			return q;
36 	}
37 }
38 
39 template <class B>
Mid(int from,int count) const40 typename AString<B>::String AString<B>::Mid(int from, int count) const
41 {
42 	int l = GetLength();
43 	if(from > l) from = l;
44 	if(from < 0) from = 0;
45 	if(count < 0)
46 		count = 0;
47 	if(from + count > l)
48 		count = l - from;
49 	return String(B::Begin() + from, count);
50 }
51 
52 template <class B>
Find(int chr,int from) const53 int AString<B>::Find(int chr, int from) const
54 {
55 	ASSERT(from >= 0 && from <= GetLength());
56 	const tchar *e = End();
57 	const tchar *ptr = B::Begin();
58 	for(const tchar *s = ptr + from; s < e; s++)
59 		if(*s == chr)
60 			return (int)(s - ptr);
61 	return -1;
62 }
63 
64 template <class B>
ReverseFind(int chr,int from) const65 int AString<B>::ReverseFind(int chr, int from) const
66 {
67 	ASSERT(from >= 0 && from <= GetLength());
68 	if(from < GetLength()) {
69 		const tchar *ptr = B::Begin();
70 		for(const tchar *s = ptr + from; s >= ptr; s--)
71 			if(*s == chr)
72 				return (int)(s - ptr);
73 	}
74 	return -1;
75 }
76 
77 template <class B>
ReverseFind(int len,const tchar * s,int from) const78 int AString<B>::ReverseFind(int len, const tchar *s, int from) const
79 {
80 	ASSERT(from >= 0 && from <= GetLength());
81 	if(from < GetLength()) {
82 		const tchar *ptr = B::Begin();
83 		const tchar *p = ptr + from - len + 1;
84 		len *= sizeof(tchar);
85 		while(p >= ptr) {
86 			if(*s == *p && memcmp(s, p, len) == 0)
87 				return (int)(p - ptr);
88 			p--;
89 		}
90 	}
91 	return -1;
92 }
93 
94 template <class B>
ReverseFindAfter(int len,const tchar * s,int from) const95 int AString<B>::ReverseFindAfter(int len, const tchar *s, int from) const
96 {
97 	int q = ReverseFind(len, s, from);
98 	return q >= 0 ? q + len : -1;
99 }
100 
101 template <class B>
Replace(const tchar * find,int findlen,const tchar * replace,int replacelen)102 void AString<B>::Replace(const tchar *find, int findlen, const tchar *replace, int replacelen)
103 {
104 	if(findlen == 0)
105 		return;
106 	String r;
107 	int i = 0;
108 	const tchar *p = B::Begin();
109 	for(;;) {
110 		int j = Find(findlen, find, i);
111 		if(j < 0)
112 			break;
113 		r.Cat(p + i, j - i);
114 		r.Cat(replace, replacelen);
115 		i = j + findlen;
116 	}
117 	r.Cat(p + i, B::GetCount() - i);
118 	B::Free();
119 	B::Set0(r);
120 }
121 
122 template <class B>
ReverseFind(const tchar * s,int from) const123 int AString<B>::ReverseFind(const tchar *s, int from) const
124 {
125 	return ReverseFind(strlen__(s), s, from);
126 }
127 
128 template <class B>
ReverseFindAfter(const tchar * s,int from) const129 int AString<B>::ReverseFindAfter(const tchar *s, int from) const
130 {
131 	return ReverseFindAfter(strlen__(s), s, from);
132 }
133 
134 template <class B>
ReverseFind(int chr) const135 int AString<B>::ReverseFind(int chr) const
136 {
137 	return B::GetCount() ? ReverseFind(chr, B::GetCount() - 1) : -1;
138 }
139 
140 template <class B>
Replace(const String & find,const String & replace)141 void AString<B>::Replace(const String& find, const String& replace)
142 {
143 	Replace(~find, find.GetCount(), ~replace, replace.GetCount());
144 }
145 
146 template <class B>
147 force_inline
Replace(const tchar * find,const tchar * replace)148 void AString<B>::Replace(const tchar *find, const tchar *replace)
149 {
150 	Replace(find, (int)strlen__(find), replace, (int)strlen__(replace));
151 }
152 
153 template <class B>
154 force_inline
Replace(const String & find,const tchar * replace)155 void AString<B>::Replace(const String& find, const tchar *replace)
156 {
157 	Replace(~find, find.GetCount(), replace, (int)strlen__(replace));
158 }
159 
160 template <class B>
161 force_inline
Replace(const tchar * find,const String & replace)162 void AString<B>::Replace(const tchar *find, const String& replace)
163 {
164 	Replace(find, (int)strlen__(find), ~replace, replace.GetCount());
165 }
166 
167 template <class B>
StartsWith(const tchar * s,int len) const168 bool AString<B>::StartsWith(const tchar *s, int len) const
169 {
170 	if(len > GetLength()) return false;
171 	return memcmp(s, B::Begin(), len * sizeof(tchar)) == 0;
172 }
173 
174 template <class B>
175 force_inline
StartsWith(const tchar * s) const176 bool AString<B>::StartsWith(const tchar *s) const
177 {
178 	return StartsWith(s, strlen__(s));
179 }
180 
181 template <class B>
EndsWith(const tchar * s,int len) const182 bool AString<B>::EndsWith(const tchar *s, int len) const
183 {
184 	int l = GetLength();
185 	if(len > l) return false;
186 	return memcmp(s, B::Begin() + l - len, len * sizeof(tchar)) == 0;
187 }
188 
189 template <class B>
190 force_inline
EndsWith(const tchar * s) const191 bool AString<B>::EndsWith(const tchar *s) const
192 {
193 	return EndsWith(s, strlen__(s));
194 }
195 
196 template <class B>
FindFirstOf(int len,const tchar * s,int from) const197 int AString<B>::FindFirstOf(int len, const tchar *s, int from) const
198 {
199 	ASSERT(from >= 0 && from <= GetLength());
200 	const tchar *ptr = B::Begin();
201 	const tchar *e = B::End();
202 	const tchar *se = s + len;
203 	if(len == 1) {
204 		tchar c1 = s[0];
205 		for(const tchar *bs = ptr + from; bs < e; bs++) {
206 			if(*bs == c1)
207 				return (int)(bs - ptr);
208 		}
209 		return -1;
210 	}
211 	if(len == 2) {
212 		tchar c1 = s[0];
213 		tchar c2 = s[1];
214 		for(const tchar *bs = ptr + from; bs < e; bs++) {
215 			tchar ch = *bs;
216 			if(ch == c1 || ch == c2)
217 				return (int)(bs - ptr);
218 		}
219 		return -1;
220 	}
221 	if(len == 3) {
222 		tchar c1 = s[0];
223 		tchar c2 = s[1];
224 		tchar c3 = s[2];
225 		for(const tchar *bs = ptr + from; bs < e; bs++) {
226 			tchar ch = *bs;
227 			if(ch == c1 || ch == c2 || ch == c3)
228 				return (int)(bs - ptr);
229 		}
230 		return -1;
231 	}
232 	if(len == 4) {
233 		tchar c1 = s[0];
234 		tchar c2 = s[1];
235 		tchar c3 = s[2];
236 		tchar c4 = s[3];
237 		for(const tchar *bs = ptr + from; bs < e; bs++) {
238 			tchar ch = *bs;
239 			if(ch == c1 || ch == c2 || ch == c3 || ch == c4)
240 				return (int)(bs - ptr);
241 		}
242 		return -1;
243 	}
244 	for(const tchar *bs = ptr + from; bs < e; bs++)
245 		for(const tchar *ss = s; ss < se; ss++)
246 			if(*bs == *ss)
247 				return (int)(bs - ptr);
248 	return -1;
249 }
250 
251 force_inline
Set(const char * s,int len)252 void String0::Set(const char *s, int len)
253 {
254 	Clear();
255 	if(len < 14) {
256 		memcpy8(chr, s, len);
257 		SLen() = len;
258 		Dsyn();
259 		return;
260 	}
261 	SetL(s, len);
262 	Dsyn();
263 }
264 
265 inline
IsEqual(const char * s) const266 bool String0::IsEqual(const char *s) const
267 { // This optimized for comparison with string literals...
268 	size_t len = strlen(s);
269 	const void *p;
270 	if(IsSmall()) {
271 		if(len > 14 || len != (size_t)chr[SLEN]) return false; // len > 14 fixes issue with GCC warning, might improves performance too
272 		p = chr;
273 	}
274 	else {
275 		if(len != (size_t)w[LLEN]) return false;
276 		p = ptr;
277 	}
278 	return memcmp(p, s, len) == 0; // compiler is happy to optimize memcmp out with up to 64bit comparisons for literals...
279 }
280 
281 force_inline
operator =(const char * s)282 String& String::operator=(const char *s)
283 {
284 	AssignLen(s, strlen__(s));
285 	return *this;
286 }
287 
288 force_inline
String(const char * s)289 String::String(const char *s)
290 {
291 	String0::Set0(s, strlen__(s));
292 }
293 
294 force_inline
Strlen()295 void StringBuffer::Strlen()
296 {
297 	SetLength((int)strlen__(pbegin));
298 }
299 
300 inline
Cat(const char * s,int l)301 void StringBuffer::Cat(const char *s, int l)
302 {
303 	if(pend + l > limit)
304 		ReallocL(s, l);
305 	else {
306 		memcpy8(pend, s, l);
307 		pend += l;
308 	}
309 }
310 
311 inline
Cat(int c,int l)312 void StringBuffer::Cat(int c, int l)
313 {
314 	if(pend + l > limit)
315 		ReallocL(NULL, l);
316 	memset8(pend, c, l);
317 	pend += l;
318 }
319 
320 force_inline
Cat(const char * s)321 void StringBuffer::Cat(const char *s)
322 {
323 	Cat(s, (int)strlen__(s));
324 }
325