Core: optimize string splitting
- Mainly affects item loading performance - Reduces guild loading time a lot --HG-- branch : trunk
This commit is contained in:
@@ -65,11 +65,11 @@ Channel::Channel(const std::string& name, uint32 channel_id, uint32 Team)
|
||||
|
||||
if (db_BannedList)
|
||||
{
|
||||
Tokens tokens = StrSplit(db_BannedList, " ");
|
||||
Tokens tokens(db_BannedList, ' ');
|
||||
Tokens::iterator iter;
|
||||
for (iter = tokens.begin(); iter != tokens.end(); ++iter)
|
||||
{
|
||||
uint64 banned_guid = atol((*iter).c_str());
|
||||
uint64 banned_guid = atol(*iter);
|
||||
if (banned_guid)
|
||||
{
|
||||
sLog.outDebug("Channel(%s) loaded banned guid:" UI64FMTD "",name.c_str(), banned_guid);
|
||||
|
||||
@@ -418,10 +418,10 @@ bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, Field* fields, uint32 entr
|
||||
need_save = true;
|
||||
}
|
||||
|
||||
Tokens tokens = StrSplit(fields[4].GetString(), " ");
|
||||
Tokens tokens(fields[4].GetString(), ' ', MAX_ITEM_PROTO_SPELLS);
|
||||
if (tokens.size() == MAX_ITEM_PROTO_SPELLS)
|
||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
|
||||
SetSpellCharges(i, atoi(tokens[i].c_str()));
|
||||
SetSpellCharges(i, atoi(tokens[i]));
|
||||
|
||||
SetUInt32Value(ITEM_FIELD_FLAGS, fields[5].GetUInt32());
|
||||
// Remove bind flag for items vs NO_BIND set
|
||||
|
||||
@@ -764,17 +764,13 @@ bool Object::LoadValues(const char* data)
|
||||
{
|
||||
if (!m_uint32Values) _InitValues();
|
||||
|
||||
Tokens tokens = StrSplit(data, " ");
|
||||
Tokens tokens(data, ' ');
|
||||
|
||||
if (tokens.size() != m_valuesCount)
|
||||
return false;
|
||||
|
||||
Tokens::iterator iter;
|
||||
int index;
|
||||
for (iter = tokens.begin(), index = 0; index < m_valuesCount; ++iter, ++index)
|
||||
{
|
||||
m_uint32Values[index] = atol((*iter).c_str());
|
||||
}
|
||||
for (uint16 index = 0; index < m_valuesCount; ++index)
|
||||
m_uint32Values[index] = atol(tokens[index]);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -784,17 +780,13 @@ void Object::_LoadIntoDataField(const char* data, uint32 startOffset, uint32 cou
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
Tokens tokens = StrSplit(data, " ");
|
||||
Tokens tokens(data, ' ', count);
|
||||
|
||||
if (tokens.size() != count)
|
||||
return;
|
||||
|
||||
Tokens::iterator iter;
|
||||
uint32 index;
|
||||
for (iter = tokens.begin(), index = 0; index < count; ++iter, ++index)
|
||||
{
|
||||
m_uint32Values[startOffset + index] = atol((*iter).c_str());
|
||||
}
|
||||
for (uint32 index = 0; index < count; ++index)
|
||||
m_uint32Values[startOffset + index] = atol(tokens[index]);
|
||||
}
|
||||
|
||||
void Object::_SetUpdateBits(UpdateMask *updateMask, Player* /*target*/) const
|
||||
|
||||
@@ -183,7 +183,7 @@ void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint8 level
|
||||
|
||||
void PlayerTaxi::LoadTaxiMask(const char* data)
|
||||
{
|
||||
Tokens tokens = StrSplit(data, " ");
|
||||
Tokens tokens(data, ' ');
|
||||
|
||||
uint8 index;
|
||||
Tokens::iterator iter;
|
||||
@@ -191,7 +191,7 @@ void PlayerTaxi::LoadTaxiMask(const char* data)
|
||||
(index < TaxiMaskSize) && (iter != tokens.end()); ++iter, ++index)
|
||||
{
|
||||
// load and set bits only for existed taxi nodes
|
||||
m_taximask[index] = sTaxiNodesMask[index] & uint32(atol((*iter).c_str()));
|
||||
m_taximask[index] = sTaxiNodesMask[index] & uint32(atol(*iter));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,11 +213,11 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString(const std::string& values, uint3
|
||||
{
|
||||
ClearTaxiDestinations();
|
||||
|
||||
Tokens tokens = StrSplit(values," ");
|
||||
Tokens tokens(values,' ');
|
||||
|
||||
for (Tokens::iterator iter = tokens.begin(); iter != tokens.end(); ++iter)
|
||||
{
|
||||
uint32 node = uint32(atol(iter->c_str()));
|
||||
uint32 node = uint32(atol(*iter));
|
||||
AddTaxiDestination(node);
|
||||
}
|
||||
|
||||
@@ -1697,7 +1697,7 @@ bool Player::BuildEnumData(QueryResult result, WorldPacket * p_data)
|
||||
*p_data << uint32(petFamily);
|
||||
}
|
||||
|
||||
Tokens data = StrSplit(fields[19].GetString(), " ");
|
||||
Tokens data(fields[19].GetString(), ' ');
|
||||
for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot)
|
||||
{
|
||||
uint32 visualbase = slot * 2;
|
||||
@@ -15997,7 +15997,7 @@ uint32 Player::GetUInt32ValueFromArray(Tokens const& data, uint16 index)
|
||||
if (index >= data.size())
|
||||
return 0;
|
||||
|
||||
return (uint32)atoi(data[index].c_str());
|
||||
return (uint32)atoi(data[index]);
|
||||
}
|
||||
|
||||
float Player::GetFloatValueFromArray(Tokens const& data, uint16 index)
|
||||
@@ -16953,10 +16953,10 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timediff)
|
||||
{
|
||||
Field* fields2 = result2->Fetch();
|
||||
std::string strGUID = fields2[0].GetString();
|
||||
Tokens GUIDlist = StrSplit(strGUID, " ");
|
||||
Tokens GUIDlist(strGUID, ' ');
|
||||
AllowedLooterSet looters;
|
||||
for (Tokens::iterator itr = GUIDlist.begin(); itr != GUIDlist.end(); ++itr)
|
||||
looters.insert(atol((*itr).c_str()));
|
||||
looters.insert(atol(*itr));
|
||||
item->SetSoulboundTradeable(&looters, this, true);
|
||||
m_itemSoulboundTradeable.push_back(item);
|
||||
}
|
||||
|
||||
@@ -13806,7 +13806,7 @@ void CharmInfo::LoadPetActionBar(const std::string& data)
|
||||
{
|
||||
InitPetActionBar();
|
||||
|
||||
Tokens tokens = StrSplit(data, " ");
|
||||
Tokens tokens(data, ' ');
|
||||
|
||||
if (tokens.size() != (ACTION_BAR_INDEX_END-ACTION_BAR_INDEX_START)*2)
|
||||
return; // non critical, will reset to default
|
||||
@@ -13816,9 +13816,9 @@ void CharmInfo::LoadPetActionBar(const std::string& data)
|
||||
for (iter = tokens.begin(), index = ACTION_BAR_INDEX_START; index < ACTION_BAR_INDEX_END; ++iter, ++index)
|
||||
{
|
||||
// use unsigned cast to avoid sign negative format use at long-> ActiveStates (int) conversion
|
||||
ActiveStates type = ActiveStates(atol(iter->c_str()));
|
||||
ActiveStates type = ActiveStates(atol(*iter));
|
||||
++iter;
|
||||
uint32 action = uint32(atol(iter->c_str()));
|
||||
uint32 action = uint32(atol(*iter));
|
||||
|
||||
PetActionBar[index].SetActionAndType(action, type);
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ bool InstanceSave::UnloadIfEmpty()
|
||||
|
||||
void InstanceSaveManager::_DelHelper(const char *fields, const char *table, const char *queryTail,...)
|
||||
{
|
||||
Tokens fieldTokens = StrSplit(fields, ", ");
|
||||
Tokens fieldTokens(fields, ',');
|
||||
ASSERT(fieldTokens.size() != 0);
|
||||
|
||||
va_list ap;
|
||||
|
||||
@@ -32,19 +32,18 @@ struct MySQLConnectionInfo
|
||||
MySQLConnectionInfo() {}
|
||||
MySQLConnectionInfo(const std::string& infoString)
|
||||
{
|
||||
Tokens tokens = StrSplit(infoString, ";");
|
||||
Tokens::iterator iter = tokens.begin();
|
||||
Tokens tokens(infoString, ';');
|
||||
|
||||
if (iter != tokens.end())
|
||||
host = *iter++;
|
||||
if (iter != tokens.end())
|
||||
port_or_socket = *iter++;
|
||||
if (iter != tokens.end())
|
||||
user = *iter++;
|
||||
if (iter != tokens.end())
|
||||
password = *iter++;
|
||||
if (iter != tokens.end())
|
||||
database = *iter++;
|
||||
if (tokens.size() != 5)
|
||||
return;
|
||||
|
||||
uint8 i = 0;
|
||||
|
||||
host.assign(tokens[i++]);
|
||||
port_or_socket.assign(tokens[i++]);
|
||||
user.assign(tokens[i++]);
|
||||
password.assign(tokens[i++]);
|
||||
database.assign(tokens[i++]);
|
||||
}
|
||||
|
||||
std::string user;
|
||||
|
||||
@@ -85,24 +85,38 @@ double rand_chance(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
Tokens StrSplit(const std::string &src, const std::string &sep)
|
||||
Tokens::Tokens(const std::string &src, const char sep, uint32 vectorReserve)
|
||||
{
|
||||
Tokens r;
|
||||
std::string s;
|
||||
for (std::string::const_iterator i = src.begin(); i != src.end(); i++)
|
||||
m_str = new char[src.length() + 1];
|
||||
memcpy(m_str, src.c_str(), src.length() + 1);
|
||||
|
||||
if (vectorReserve)
|
||||
reserve(vectorReserve);
|
||||
|
||||
char* posold = m_str;
|
||||
char* posnew = m_str;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (sep.find(*i) != std::string::npos)
|
||||
if (*posnew == sep)
|
||||
{
|
||||
if (s.length()) r.push_back(s);
|
||||
s = "";
|
||||
push_back(posold);
|
||||
posold = posnew + 1;
|
||||
|
||||
*posnew = 0x00;
|
||||
}
|
||||
else
|
||||
else if (*posnew == 0x00)
|
||||
{
|
||||
s += *i;
|
||||
// Hack like, but the old code accepted these kind of broken strings,
|
||||
// so changing it would break other things
|
||||
if (posold != posnew)
|
||||
push_back(posold);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
++posnew;
|
||||
}
|
||||
if (s.length()) r.push_back(s);
|
||||
return r;
|
||||
}
|
||||
|
||||
void stripLineInvisibleChars(std::string &str)
|
||||
|
||||
@@ -24,9 +24,13 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
typedef std::vector<std::string> Tokens;
|
||||
struct Tokens: public std::vector<char*>
|
||||
{
|
||||
Tokens(const std::string &src, const char sep, uint32 vectorReserve = 0);
|
||||
~Tokens() { delete m_str; }
|
||||
|
||||
Tokens StrSplit(const std::string &src, const std::string &sep);
|
||||
char* m_str;
|
||||
};
|
||||
|
||||
void stripLineInvisibleChars(std::string &src);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user