From 51ff437d4972edd50ad4382efe72fd3deb3fd28e Mon Sep 17 00:00:00 2001 From: cxl Date: Sun, 2 Mar 2014 10:01:14 +0000 Subject: [PATCH] Core: String::Find(String) optimizations, refactoring git-svn-id: svn://ultimatepp.org/upp/trunk@6977 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Core/AString.hpp | 56 ----------------------------- uppsrc/Core/Defs.h | 32 +++++++++++++++++ uppsrc/Core/String.cpp | 78 +++++++++++++++++++++++++++++++++++++++++ uppsrc/Core/String.h | 7 ++-- 4 files changed, 115 insertions(+), 58 deletions(-) diff --git a/uppsrc/Core/AString.hpp b/uppsrc/Core/AString.hpp index a19abb079..e1c2d6e73 100644 --- a/uppsrc/Core/AString.hpp +++ b/uppsrc/Core/AString.hpp @@ -121,56 +121,6 @@ int AString::ReverseFind(int chr) const return B::GetCount() ? ReverseFind(chr, B::GetCount() - 1) : -1; } -template -int AString::Find(int len, const tchar *s, int from) const -{ - ASSERT(from >= 0 && from <= GetLength()); - int l = GetLength() - len - from; - if(l < 0) - return -1; - if(len == 0) - return from; - const tchar *ptr = B::Begin(); - const tchar *p = ptr + from; - const tchar *e = p + l; - if(len > 4) { - len -= 4; - while(p <= e) { - if(s[0] == p[0] && s[1] == p[1] && s[2] == p[2] && s[3] == p[3] && memcmp(s + 4, p + 4, len * sizeof(tchar)) == 0) - return (int)(p - ptr); - p++; - } - } - else - if(len == 4) - while(p <= e) { - if(s[0] == p[0] && s[1] == p[1] && s[2] == p[2] && s[3] == p[3]) - return (int)(p - ptr); - p++; - } - else - if(len == 3) - while(p <= e) { - if(s[0] == p[0] && s[1] == p[1] && s[2] == p[2]) - return (int)(p - ptr); - p++; - } - else - if(len == 2) - while(p <= e) { - if(s[0] == p[0] && s[1] == p[1]) - return (int)(p - ptr); - p++; - } - else - while(p <= e) { - if(*s == *p) - return (int)(p - ptr); - p++; - } - return -1; -} - template void AString::Replace(const String& find, const String& replace) { @@ -227,12 +177,6 @@ bool AString::EndsWith(const tchar *s) const return EndsWith(s, strlen__(s)); } -template -int AString::Find(const tchar *s, int from) const -{ - return Find(strlen__(s), s, from); -} - template int AString::FindFirstOf(int len, const tchar *s, int from) const { diff --git a/uppsrc/Core/Defs.h b/uppsrc/Core/Defs.h index b64986043..6119f9940 100644 --- a/uppsrc/Core/Defs.h +++ b/uppsrc/Core/Defs.h @@ -712,6 +712,38 @@ do { \ } \ } while(false) +template +force_inline bool svo_memeq(const tchar *a, const tchar *b, int len) +{ + if(len > 11) + return memcmp(a, b, len) == 0; + switch(len) { + case 11: + if(a[10] != b[10]) return false; + case 10: + if(a[9] != b[9]) return false; + case 9: + if(a[8] != b[8]) return false; + case 8: + if(a[7] != b[7]) return false; + case 7: + if(a[6] != b[6]) return false; + case 6: + if(a[5] != b[5]) return false; + case 5: + if(a[4] != b[4]) return false; + case 4: + if(a[3] != b[3]) return false; + case 3: + if(a[2] != b[2]) return false; + case 2: + if(a[1] != b[1]) return false; + case 1: + if(a[0] != b[0]) return false; + } + return true; +} + //Quick fix.... #ifdef PLATFORM_WINCE const char *FromSysChrSet(const wchar *s); diff --git a/uppsrc/Core/String.cpp b/uppsrc/Core/String.cpp index 7542a711d..7e1878026 100644 --- a/uppsrc/Core/String.cpp +++ b/uppsrc/Core/String.cpp @@ -2,6 +2,84 @@ NAMESPACE_UPP +template +int t_find(const tchar *ptr, int plen, const tchar *s, int len, int from) +{ + ASSERT(from >= 0 && from <= plen); + int l = plen - len - from; + if(l < 0) + return -1; + if(len == 0) + return from; + const tchar *p = ptr + from; + const tchar *e = p + l; + if(len > 4) { + tchar s0 = s[0]; + tchar s1 = s[1]; + tchar s2 = s[2]; + tchar sl = s[len - 1]; + int l_1 = len - 1; + while(p <= e) { + if(s0 == p[0] && sl == p[l_1] && s1 == p[1] && s2 == p[2] && + svo_memeq(s + 4, p + 4, len - 5)) + return (int)(p - ptr); + p++; + } + } + else + if(len == 4) { + tchar s0 = s[0]; + tchar s1 = s[1]; + tchar s2 = s[2]; + tchar s3 = s[3]; + while(p <= e) { + if(s0 == p[0] && s3 == p[3] && s1 == p[1] && s2 == p[2]) + return (int)(p - ptr); + p++; + } + } + else + if(len == 3) { + tchar s0 = s[0]; + tchar s1 = s[1]; + tchar s2 = s[2]; + while(p <= e) { + if(s0 == p[0] && s2 == p[2] && s1 == p[1]) + return (int)(p - ptr); + p++; + } + } + else + if(len == 2) { + tchar s0 = s[0]; + tchar s1 = s[1]; + while(p <= e) { + if(s0 == p[0] && s1 == p[1]) + return (int)(p - ptr); + p++; + } + } + else { + tchar s0 = s[0]; + while(p <= e) { + if(s0 == *p) + return (int)(p - ptr); + p++; + } + } + return -1; +} + +int find(const char *text, int len, const char *needle, int nlen, int from) +{ + return t_find(text, len, needle, nlen, from); +} + +int find(const wchar *text, int len, const wchar *needle, int nlen, int from) +{ + return t_find(text, len, needle, nlen, from); +} + #ifdef _DEBUG void String0::Dsyn() { diff --git a/uppsrc/Core/String.h b/uppsrc/Core/String.h index d9a3f5ce6..dabeff14e 100644 --- a/uppsrc/Core/String.h +++ b/uppsrc/Core/String.h @@ -23,6 +23,9 @@ inline int strlen__(const wchar *s) { return s ? (int)wstrlen(s) : 0; } inline int cmpval__(char x) { return (byte)x; } inline int cmpval__(wchar x) { return (word)x; } +int find(const char *text, int len, const char *needle, int nlen, int from); +int find(const wchar *text, int len, const wchar *needle, int nlen, int from); + class String; class WString; class StringBuffer; @@ -85,8 +88,8 @@ public: int ReverseFind(int chr, int from) const; int ReverseFind(int chr) const; - int Find(int len, const tchar *s, int from) const; - int Find(const tchar *s, int from = 0) const; + int Find(int len, const tchar *s, int from) const { return find(B::Begin(), B::GetCount(), s, len, from); } + int Find(const tchar *s, int from = 0) const { return Find(strlen__(s), s, from); } int Find(const String& s, int from = 0) const { return Find(s.GetCount(), ~s, from); } int ReverseFind(int len, const tchar *s, int from) const;