optimized ReplaceText: one copy at most; text with no replacements reduces to one search

This commit is contained in:
Glenn Maynard
2005-07-06 00:51:26 +00:00
parent 0137a20389
commit 3a304e251c
+44 -12
View File
@@ -317,32 +317,64 @@ static void InitCharAliases()
for(aliasmap::const_iterator i = CharAliases.begin(); i != CharAliases.end(); ++i) for(aliasmap::const_iterator i = CharAliases.begin(); i != CharAliases.end(); ++i)
{ {
CString from = ssprintf("&%s;", i->first.c_str()); CString from = i->first;
CString to = WcharToUTF8(i->second); CString to = WcharToUTF8(i->second);
from.MakeUpper(); from.MakeUpper();
CharAliasRepl[from] = to; CharAliasRepl[from] = to;
} }
} }
void ReplaceText( CString &Text, const map<CString,CString> &m ) static void ReplaceText( CString &sText, const map<CString,CString> &m )
{ {
basic_string<char,char_traits_char_nocase> txt(Text); CString sRet;
for(map<CString,CString>::const_iterator it = m.begin(); it != m.end(); ++it) size_t iOffset = 0;
while( iOffset != sText.size() )
{ {
size_t start = 0; size_t iStart = sText.find( '&', iOffset );
while(1) if( iStart == sText.npos )
{ {
size_t pos = txt.find(it->first, start); /* Optimization: if we didn't replace anything at all, do nothing. */
if(pos == txt.npos) if( iOffset == 0 )
break; return;
txt.replace(pos, it->first.size(), it->second); // Append the rest of the string.
start = pos+it->second.size(); sRet.append( sText, iOffset, sRet.npos );
break;
} }
// Append the text between iOffset and iStart.
sRet.append( sText, iOffset, iStart-iOffset );
iOffset += iStart-iOffset;
// Optimization: stop early on "&", so "&&&&&&&&&&&" isn't n^2.
size_t iEnd = sText.find_first_of( "&;", iStart+1 );
if( iEnd == sText.npos || sText[iEnd] == '&' )
{
/* & with no matching ;, or two & in a row. Append the & and
* continue. */
sRet.append( sText, iStart, 1 );
++iOffset;
continue;
}
CString sElement = sText.substr( iStart+1, iEnd-iStart-1 );
sElement.MakeUpper();
map<CString,CString>::const_iterator it = m.find( sElement );
if( it == m.end() )
{
sRet.append( sText, iStart, iEnd-iStart+1 );
iOffset = iEnd + 1;
continue;
}
const CString &sTo = it->second;
sRet.append( sTo );
iOffset = iEnd + 1;
} }
Text = txt.c_str(); sText = sRet;
} }
/* Replace all &markers; and &#NNNN;s with UTF-8. */ /* Replace all &markers; and &#NNNN;s with UTF-8. */