Partial fix for EXT-5071.
Changed the index on the keyword map in LLKeywords so that LLKeywords::findSegments() doesn't have to create LLWString objects to search the map. Reviewed by Richard.master
parent
d742b3e911
commit
3e8320201f
|
|
@ -218,6 +218,86 @@ void LLKeywords::addToken(LLKeywordToken::TOKEN_TYPE type,
|
|||
llassert(0);
|
||||
}
|
||||
}
|
||||
LLKeywords::WStringMapIndex::WStringMapIndex(const WStringMapIndex& other)
|
||||
{
|
||||
if(other.mOwner)
|
||||
{
|
||||
copyData(other.mData, other.mLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
mOwner = false;
|
||||
mLength = other.mLength;
|
||||
mData = other.mData;
|
||||
}
|
||||
}
|
||||
|
||||
LLKeywords::WStringMapIndex::WStringMapIndex(const LLWString& str)
|
||||
{
|
||||
copyData(str.data(), str.size());
|
||||
}
|
||||
|
||||
LLKeywords::WStringMapIndex::WStringMapIndex(const llwchar *start, size_t length):
|
||||
mData(start), mLength(length), mOwner(false)
|
||||
{
|
||||
}
|
||||
|
||||
LLKeywords::WStringMapIndex::~WStringMapIndex()
|
||||
{
|
||||
if(mOwner)
|
||||
delete[] mData;
|
||||
}
|
||||
|
||||
void LLKeywords::WStringMapIndex::copyData(const llwchar *start, size_t length)
|
||||
{
|
||||
llwchar *data = new llwchar[length];
|
||||
memcpy((void*)data, (const void*)start, length * sizeof(llwchar));
|
||||
|
||||
mOwner = true;
|
||||
mLength = length;
|
||||
mData = data;
|
||||
}
|
||||
|
||||
bool LLKeywords::WStringMapIndex::operator<(const LLKeywords::WStringMapIndex &other) const
|
||||
{
|
||||
// NOTE: Since this is only used to organize a std::map, it doesn't matter if it uses correct collate order or not.
|
||||
// The comparison only needs to strictly order all possible strings, and be stable.
|
||||
|
||||
bool result = false;
|
||||
const llwchar* self_iter = mData;
|
||||
const llwchar* self_end = mData + mLength;
|
||||
const llwchar* other_iter = other.mData;
|
||||
const llwchar* other_end = other.mData + other.mLength;
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(other_iter >= other_end)
|
||||
{
|
||||
// We've hit the end of other.
|
||||
// This covers two cases: other being shorter than self, or the strings being equal.
|
||||
// In either case, we want to return false.
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
else if(self_iter >= self_end)
|
||||
{
|
||||
// self is shorter than other.
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
else if(*self_iter != *other_iter)
|
||||
{
|
||||
// The current character differs. The strings are not equal.
|
||||
result = *self_iter < *other_iter;
|
||||
break;
|
||||
}
|
||||
|
||||
self_iter++;
|
||||
other_iter++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
LLColor3 LLKeywords::readColor( const std::string& s )
|
||||
{
|
||||
|
|
@ -429,7 +509,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
|
|||
S32 seg_len = p - cur;
|
||||
if( seg_len > 0 )
|
||||
{
|
||||
LLWString word( cur, 0, seg_len );
|
||||
WStringMapIndex word( cur, seg_len );
|
||||
word_token_map_t::iterator map_iter = mWordTokenMap.find(word);
|
||||
if( map_iter != mWordTokenMap.end() )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -92,8 +92,33 @@ public:
|
|||
const std::string& key,
|
||||
const LLColor3& color,
|
||||
const std::string& tool_tip = LLStringUtil::null);
|
||||
|
||||
// This class is here as a performance optimization.
|
||||
// The word token map used to be defined as std::map<LLWString, LLKeywordToken*>.
|
||||
// This worked, but caused a performance bottleneck due to memory allocation and string copies
|
||||
// because it's not possible to search such a map without creating an LLWString.
|
||||
// Using this class as the map index instead allows us to search using segments of an existing
|
||||
// text run without copying them first, which greatly reduces overhead in LLKeywords::findSegments().
|
||||
class WStringMapIndex
|
||||
{
|
||||
public:
|
||||
// copy constructor
|
||||
WStringMapIndex(const WStringMapIndex& other);
|
||||
// constructor from a string (copies the string's data into the new object)
|
||||
WStringMapIndex(const LLWString& str);
|
||||
// constructor from pointer and length
|
||||
// NOTE: does NOT copy data, caller must ensure that the lifetime of the pointer exceeds that of the new object!
|
||||
WStringMapIndex(const llwchar *start, size_t length);
|
||||
~WStringMapIndex();
|
||||
bool operator<(const WStringMapIndex &other) const;
|
||||
private:
|
||||
void copyData(const llwchar *start, size_t length);
|
||||
const llwchar *mData;
|
||||
size_t mLength;
|
||||
bool mOwner;
|
||||
};
|
||||
|
||||
typedef std::map<LLWString, LLKeywordToken*> word_token_map_t;
|
||||
typedef std::map<WStringMapIndex, LLKeywordToken*> word_token_map_t;
|
||||
typedef word_token_map_t::const_iterator keyword_iterator_t;
|
||||
keyword_iterator_t begin() const { return mWordTokenMap.begin(); }
|
||||
keyword_iterator_t end() const { return mWordTokenMap.end(); }
|
||||
|
|
|
|||
Loading…
Reference in New Issue