diff --git a/uppsrc/Core/String.cpp b/uppsrc/Core/String.cpp index 546798161..f3cb1316d 100644 --- a/uppsrc/Core/String.cpp +++ b/uppsrc/Core/String.cpp @@ -2,6 +2,112 @@ NAMESPACE_UPP +#ifdef CPU_X86 // Use unaligned access + +inline +bool equal_back_8(const char *a, const char *b, int len) +{ + while(len > 8) { + len -= 8; + if(Peek64le(a + len) != Peek64le(b + len)) + return false; + } + return true; +} + +template // Template parameter to be a constant +int t_find(const char *ptr, int slen, const char *p, int len, int from) +{ + ASSERT(from >= 0 && from <= slen); + int l = slen - len - from; + if(l < 0) + return -1; + const char *s = ptr + from; + const char *e = s + l; + if(len <= 8) { + if(len > 4) { + len -= 4; + int32 p0 = Peek32le(p); + int32 p1 = Peek32le(p + len); + while(s <= e) { + if(Peek32le(s) == p0 && Peek32le(s + len) == p1) + return (int)(s - ptr); + s += step; + } + } + else + if(len == 4) { + int32 p0 = Peek32le(p); + while(s <= e) { + if(Peek32le(s) == p0) + return (int)(s - ptr); + s += step; + } + } + else + if(len == 3) { + int16 p0 = Peek16le(p); + char p1 = p[2]; + while(s <= e) { + if(Peek16le(s) == p0 && s[2] == p1) + return (int)(s - ptr); + s += step; + } + } + else + if(len == 2) { + int16 p0 = Peek16le(p); + while(s <= e) { + if(Peek16le(s) == p0) + return (int)(s - ptr); + s += step; + } + } + else + if(len == 1) { + char p0 = p[0]; + while(s <= e) { + if(*s == p0) + return (int)(s - ptr); + s += step; + } + } + else + return true; + } + else { + int64 p0 = Peek64le(p); + if(len <= 16) { + len -= 8; + int64 p1 = Peek64le(p + len); + while(s <= e) { + if(Peek64le(s) == p0 && Peek64le(s + len) == p1) + return (int)(s - ptr); + s += step; + } + } + else + while(s <= e) { + if(Peek64le(s) == p0 && equal_back_8(s, p, len)) + return (int)(s - ptr); + s += step; + } + } + return -1; +} + +int find(const char *text, int len, const char *needle, int nlen, int from) +{ + return t_find<1>(text, len, needle, nlen, from); +} + +int find(const wchar *text, int len, const wchar *needle, int nlen, int from) +{ + return t_find<2>((const char *)text, 2 * len, (const char *)needle, 2 * nlen, from) / 2; +} + +#else + template int t_find(const tchar *ptr, int plen, const tchar *s, int len, int from) { @@ -79,6 +185,8 @@ int find(const wchar *text, int len, const wchar *needle, int nlen, int from) { return t_find(text, len, needle, nlen, from); } +#endif + #ifdef _DEBUG void String0::Dsyn()