template force_inline void AString::Insert(int pos, const char *s) { Insert(pos, s, strlen__(s)); } template void AString::Cat(int c, int count) { tchar *s = B::Insert(GetLength(), count, NULL); while(count--) *s++ = c; } template force_inline void AString::Cat(const tchar *s) { Cat(s, strlen__(s)); } template int AString::Compare(const tchar *b) const { const tchar *a = B::Begin(); const tchar *ae = End(); for(;;) { if(a >= ae) return *b == 0 ? 0 : -1; if(*b == 0) return 1; int q = cmpval__(*a++) - cmpval__(*b++); if(q) return q; } } template typename AString::String AString::Mid(int from, int count) const { int l = GetLength(); if(from > l) from = l; if(from < 0) from = 0; if(count < 0) count = 0; if(from + count > l) count = l - from; return String(B::Begin() + from, count); } template int AString::Find(int chr, int from) const { ASSERT(from >= 0 && from <= GetLength()); const tchar *e = End(); const tchar *ptr = B::Begin(); for(const tchar *s = ptr + from; s < e; s++) if(*s == chr) return (int)(s - ptr); return -1; } template int AString::ReverseFind(int chr, int from) const { ASSERT(from >= 0 && from <= GetLength()); if(from < GetLength()) { const tchar *ptr = B::Begin(); for(const tchar *s = ptr + from; s >= ptr; s--) if(*s == chr) return (int)(s - ptr); } return -1; } template int AString::ReverseFind(int len, const tchar *s, int from) const { ASSERT(from >= 0 && from <= GetLength()); if(from < GetLength()) { const tchar *ptr = B::Begin(); const tchar *p = ptr + from - len + 1; len *= sizeof(tchar); while(p >= ptr) { if(*s == *p && memcmp(s, p, len) == 0) return (int)(p - ptr); p--; } } return -1; } template int AString::ReverseFindAfter(int len, const tchar *s, int from) const { int q = ReverseFind(len, s, from); return q >= 0 ? q + len : -1; } template void AString::Replace(const tchar *find, int findlen, const tchar *replace, int replacelen) { if(findlen == 0) return; String r; int i = 0; const tchar *p = B::Begin(); for(;;) { int j = Find(findlen, find, i); if(j < 0) break; r.Cat(p + i, j - i); r.Cat(replace, replacelen); i = j + findlen; } r.Cat(p + i, B::GetCount() - i); B::Free(); B::Set0(r); } template int AString::ReverseFind(const tchar *s, int from) const { return ReverseFind(strlen__(s), s, from); } template int AString::ReverseFindAfter(const tchar *s, int from) const { return ReverseFindAfter(strlen__(s), s, from); } template int AString::ReverseFind(int chr) const { return B::GetCount() ? ReverseFind(chr, B::GetCount() - 1) : -1; } template void AString::Replace(const String& find, const String& replace) { Replace(~find, find.GetCount(), ~replace, replace.GetCount()); } template force_inline void AString::Replace(const tchar *find, const tchar *replace) { Replace(find, (int)strlen__(find), replace, (int)strlen__(replace)); } template force_inline void AString::Replace(const String& find, const tchar *replace) { Replace(~find, find.GetCount(), replace, (int)strlen__(replace)); } template force_inline void AString::Replace(const tchar *find, const String& replace) { Replace(find, (int)strlen__(find), ~replace, replace.GetCount()); } template bool AString::StartsWith(const tchar *s, int len) const { if(len > GetLength()) return false; return memcmp(s, B::Begin(), len * sizeof(tchar)) == 0; } template force_inline bool AString::StartsWith(const tchar *s) const { return StartsWith(s, strlen__(s)); } template bool AString::EndsWith(const tchar *s, int len) const { int l = GetLength(); if(len > l) return false; return memcmp(s, B::Begin() + l - len, len * sizeof(tchar)) == 0; } template force_inline bool AString::EndsWith(const tchar *s) const { return EndsWith(s, strlen__(s)); } template int AString::FindFirstOf(int len, const tchar *s, int from) const { ASSERT(from >= 0 && from <= GetLength()); const tchar *ptr = B::Begin(); const tchar *e = B::End(); const tchar *se = s + len; if(len == 1) { tchar c1 = s[0]; for(const tchar *bs = ptr + from; bs < e; bs++) { if(*bs == c1) return (int)(bs - ptr); } return -1; } if(len == 2) { tchar c1 = s[0]; tchar c2 = s[1]; for(const tchar *bs = ptr + from; bs < e; bs++) { tchar ch = *bs; if(ch == c1 || ch == c2) return (int)(bs - ptr); } return -1; } if(len == 3) { tchar c1 = s[0]; tchar c2 = s[1]; tchar c3 = s[2]; for(const tchar *bs = ptr + from; bs < e; bs++) { tchar ch = *bs; if(ch == c1 || ch == c2 || ch == c3) return (int)(bs - ptr); } return -1; } if(len == 4) { tchar c1 = s[0]; tchar c2 = s[1]; tchar c3 = s[2]; tchar c4 = s[3]; for(const tchar *bs = ptr + from; bs < e; bs++) { tchar ch = *bs; if(ch == c1 || ch == c2 || ch == c3 || ch == c4) return (int)(bs - ptr); } return -1; } for(const tchar *bs = ptr + from; bs < e; bs++) for(const tchar *ss = s; ss < se; ss++) if(*bs == *ss) return (int)(bs - ptr); return -1; } inline int String0::Compare(const String0& s) const { #ifdef FAST_STRING_COMPARE if((chr[KIND] | s.chr[KIND]) == 0) { #ifdef CPU_64 uint64 a64 = q[0]; uint64 b64 = s.q[0]; if(a64 != b64) return SwapEndian64(a64) < SwapEndian64(b64) ? -1 : 1; uint32 a32 = w[2]; uint32 b32 = s.w[2]; if(a32 != b32) return SwapEndian32(a32) < SwapEndian32(b32) ? -1 : 1; #else uint32 a32 = w[0]; uint32 b32 = s.w[0]; if(a32 != b32) return SwapEndian32(a32) < SwapEndian32(b32) ? -1 : 1; a32 = w[1]; b32 = s.w[1]; if(a32 != b32) return SwapEndian32(a32) < SwapEndian32(b32) ? -1 : 1; a32 = w[2]; b32 = s.w[2]; if(a32 != b32) return SwapEndian32(a32) < SwapEndian32(b32) ? -1 : 1; #endif uint16 a16 = v[6]; uint16 b16 = s.v[6]; if(a16 != b16) return SwapEndian16(a16) < SwapEndian16(b16) ? -1 : 1; return 0; } #endif return LCompare(s); } force_inline void String0::Set(const char *s, int len) { Clear(); if(len < 14) { SVO_MEMCPY(chr, s, len); SLen() = len; Dsyn(); return; } SetL(s, len); Dsyn(); } force_inline String& String::operator=(const char *s) { AssignLen(s, strlen__(s)); return *this; } force_inline String::String(const char *s) { String0::Set0(s, strlen__(s)); } force_inline void StringBuffer::Strlen() { SetLength((int)strlen__(pbegin)); } force_inline void StringBuffer::Cat(const char *s) { Cat(s, (int)strlen__(s)); }