You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
885 lines
18 KiB
885 lines
18 KiB
/*==LICENSE==* |
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools |
|
Copyright (C) 2011 Cyan Worlds, Inc. |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
Additional permissions under GNU GPL version 3 section 7 |
|
|
|
If you modify this Program, or any covered work, by linking or |
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
(or a modified version of those libraries), |
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
licensors of this Program grant you additional |
|
permission to convey the resulting work. Corresponding Source for a |
|
non-source form of such a combination shall include the source code for |
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
work. |
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
or by snail mail at: |
|
Cyan Worlds, Inc. |
|
14617 N Newport Hwy |
|
Mead, WA 99021 |
|
|
|
*==LICENSE==*/ |
|
// UserPropMgr.cpp |
|
|
|
#include "hsTypes.h" |
|
#include "UserPropMgr.h" |
|
#include "hsStringTokenizer.h" |
|
#include "hsUtils.h" |
|
#include "hsHashTable.h" |
|
|
|
#define REFMSG_USERPROP (REFMSG_USER + 1) |
|
|
|
const UInt32 UserPropMgr::kQuickSize = 150001;//199999; |
|
|
|
UserPropMgr gUserPropMgr(GetCOREInterface()); |
|
|
|
UserPropMgr::UserPropMgr(Interface *ip) : |
|
nm(0) |
|
{ |
|
this->ip = ip; |
|
|
|
fQuickTable = nil; |
|
fQuickNode = nil; |
|
|
|
vProps = false; |
|
} |
|
|
|
UserPropMgr::~UserPropMgr() |
|
{ |
|
CloseQuickTable(); |
|
} |
|
|
|
void UserPropMgr::SetUserPropFlag(INode *node, const char *name, const BOOL setFlag, const Int32 hFlag) |
|
{ |
|
if (setFlag) SetUserProp(node,name,NULL,hFlag); |
|
else ClearUserProp(node,name,hFlag); |
|
} |
|
|
|
void UserPropMgr::ClearUserPropALL(const char *name, const Int32 hFlag) |
|
{ |
|
for (int i=0; i<GetSelNodeCount(); i++) |
|
{ |
|
ClearUserProp(GetSelNode(i),name,hFlag); |
|
} |
|
} |
|
|
|
void UserPropMgr::SelectUserPropFlagALL(INode *node, const char *name, const BOOL flag) { |
|
if (node) |
|
{ |
|
if (UserPropExists(node,name) == flag) ip->SelectNode(node,false); |
|
} else node = ip->GetRootNode(); |
|
|
|
for (int i=0; i<node->NumberOfChildren(); i++) { |
|
SelectUserPropFlagALL(node->GetChildNode(i),name,flag); |
|
} |
|
} |
|
|
|
|
|
void UserPropMgr::DeSelectWithOut(const char *name, const char *value) { |
|
BOOL oldProps = vProps; |
|
vProps=false; |
|
TSTR val; |
|
INode *nodes[1]; |
|
INodeTab nodeTab; |
|
for (int i=0; i<GetSelNodeCount(); i++) { |
|
if (value) { |
|
if (!(GetUserProp(GetSelNode(i),name,val) && !stricmp(val,value))) { |
|
nodes[0] = GetSelNode(i); |
|
nodeTab.Append(1,nodes); |
|
} |
|
} else if (!UserPropExists(GetSelNode(i),name)) { |
|
nodes[0] = GetSelNode(i); |
|
nodeTab.Append(1,nodes); |
|
} |
|
} |
|
vProps=oldProps; |
|
if (nodeTab.Count() > 0) ip->SelectNodeTab(nodeTab,false,false); |
|
|
|
} |
|
|
|
void UserPropMgr::RecursiveSelectAll(INode *node) { |
|
if (node) { |
|
if (!node->Selected()) ip->SelectNode(node,false); |
|
} else node = ip->GetRootNode(); |
|
|
|
for (int i=0; i<node->NumberOfChildren(); i++) { |
|
RecursiveSelectAll(node->GetChildNode(i)); |
|
} |
|
} |
|
|
|
|
|
void UserPropMgr::DeSelectUnAlike(INode *node) { |
|
theHold.Begin(); |
|
|
|
ip->ThawSelection(); |
|
|
|
RecursiveSelectAll(); |
|
|
|
TSTR buf; |
|
GetUserPropBuffer(node,buf); |
|
|
|
hsStringTokenizer toker(buf," \r\n"); |
|
toker.ParseQuotes(TRUE); |
|
char *tok; |
|
TSTR name; |
|
bool isName = true; |
|
while (tok=toker.next()) { |
|
if (isName) { |
|
if (*tok != '=') { |
|
name = tok; |
|
tok = toker.next(); |
|
if (tok && *tok == '=') { |
|
tok = toker.next(); |
|
} else tok = NULL; |
|
DeSelectWithOut(name,tok); |
|
} else isName = false; |
|
} else { |
|
isName = true; |
|
} |
|
} |
|
|
|
|
|
TSTR undostr; undostr.printf("Select"); |
|
theHold.Accept(undostr); |
|
|
|
ip->FreezeSelection(); |
|
|
|
ip->RedrawViews(ip->GetTime()); |
|
} |
|
|
|
|
|
|
|
int UserPropMgr::RecursiveCountAlike(INode *node, BOOL MatchAll) { |
|
int count=0; |
|
if (node) { |
|
if (!node->IsNodeHidden() && !node->IsFrozen() && IsAlike(node,MatchAll)) count++; |
|
} else node = ip->GetRootNode(); |
|
|
|
for (int i=0; i<node->NumberOfChildren(); i++) { |
|
count += RecursiveCountAlike(node->GetChildNode(i),MatchAll); |
|
} |
|
return count; |
|
} |
|
|
|
|
|
int UserPropMgr::CountAlike(BOOL MatchAll) { |
|
return RecursiveCountAlike(NULL, MatchAll); |
|
} |
|
|
|
BOOL UserPropMgr::IsMatch(const char *val1, const char *val2) { |
|
if (!stricmp(val1,val2)) return true; |
|
hsStringTokenizer toker(val1," ,@"); |
|
char *tok; |
|
|
|
while (tok=toker.next()) { |
|
hsStringTokenizer toker2(val2," ,@"); |
|
BOOL found = false; |
|
char *tok2; |
|
while ((tok2=toker2.next()) && !found) { |
|
if (tok[0] >= '1' && tok[0] <= '0') { |
|
if (!stricmp(tok,tok2)) found = true; |
|
} else if (toker.HasMoreTokens()) { |
|
if (!stricmp(tok,tok2)) found = true;if (!stricmp(tok,tok2)) found = true; |
|
} else { |
|
if (!strnicmp(tok,tok2,strlen(tok))) found = true; |
|
} |
|
} |
|
if (!found) return false; |
|
} |
|
return true; |
|
} |
|
|
|
|
|
BOOL UserPropMgr::IsAlike(INode *node, BOOL MatchAll) { |
|
TSTR buf; |
|
GetUserPropBuffer(node,buf); |
|
|
|
BOOL oldProps = vProps; |
|
vProps=false; |
|
|
|
hsStringTokenizer toker(buf," \r\n"); |
|
toker.ParseQuotes(TRUE); |
|
char *tok; |
|
TSTR name; |
|
TSTR value; |
|
TSTR tval; |
|
BOOL match = MatchAll; |
|
bool isName = true; |
|
tok = toker.next(); |
|
while (tok && (match==MatchAll)) { |
|
if (isName) { |
|
if (*tok != '=') { |
|
name = tok; |
|
tok = toker.next(); |
|
if (tok && *tok == '=') { |
|
tok = toker.next(); |
|
if (tok) value = tok; |
|
else value = ""; |
|
tok = toker.next(); |
|
} else value = ""; |
|
if (GetUserProp(node,name,tval)) match = IsMatch(value,tval); |
|
else match = false; |
|
continue; |
|
} else isName = false; |
|
} else { |
|
isName = true; |
|
} |
|
tok=toker.next(); |
|
} |
|
|
|
if (match==MatchAll) { |
|
if (!vname.isNull()) match = IsMatch(vname,node->GetName()); |
|
} |
|
|
|
vProps = oldProps; |
|
return match; |
|
} |
|
|
|
int UserPropMgr::GetUserPropCount(INode *node) { |
|
TSTR buf; |
|
|
|
GetUserPropBuffer(node,buf); |
|
|
|
int numProps = 0; |
|
|
|
hsStringTokenizer toker(buf," \r\n"); |
|
toker.ParseQuotes(TRUE); |
|
char *tok; |
|
bool isName = true; |
|
while (tok=toker.next()) { |
|
if (isName) { |
|
if (*tok != '=') { |
|
numProps++; |
|
} else isName = false; |
|
} else { |
|
isName = true; |
|
} |
|
} |
|
|
|
return numProps; |
|
} |
|
|
|
void UserPropMgr::GetUserPropBuffer(INode *node, TSTR &buf) { |
|
if (vProps) buf = vbuf; |
|
else if (node) node->GetUserPropBuffer(buf); |
|
else buf = ""; |
|
} |
|
|
|
void UserPropMgr::SetUserPropBuffer(INode *node, const TSTR &buf) |
|
{ |
|
// QuickTable invalidate |
|
if (node && node == fQuickNode) |
|
{ |
|
fQuickNode = nil; |
|
} |
|
|
|
if (vProps) |
|
{ |
|
vbuf = buf; |
|
} |
|
else if (node) |
|
{ |
|
node->SetUserPropBuffer(buf); |
|
node->NotifyDependents(FOREVER, PART_ALL, REFMSG_USERPROP); |
|
} |
|
} |
|
|
|
void UserPropMgr::SetUserPropFlagALL(const char *name, const BOOL setFlag, const Int32 hFlag) |
|
{ |
|
for (int i=0; i<GetSelNodeCount();i++) |
|
{ |
|
SetUserPropFlag(GetSelNode(i),name,setFlag,hFlag); |
|
} |
|
} |
|
BOOL UserPropMgr::GetUserPropFlagALL(const char *name, BOOL &isSet, const Int32 hFlag) |
|
{ |
|
isSet = UserPropMgr::UserPropExists(GetSelNode(0),name,hFlag); |
|
|
|
for (int i=0; i<GetSelNodeCount(); i++) { |
|
if (isSet != UserPropMgr::UserPropExists(GetSelNode(i),name,hFlag)) return FALSE; |
|
} |
|
return TRUE; |
|
} |
|
|
|
INode* UserPropMgr::GetAncestorIfNeeded(INode* node, const Int32 hFlag) |
|
{ |
|
if (hFlag == kParent) |
|
{ |
|
if (!(node->IsRootNode() || node->GetParentNode()->IsRootNode())) |
|
node = node->GetParentNode(); |
|
} |
|
else |
|
if (hFlag == kRoot) |
|
{ |
|
while (!(node->IsRootNode() || node->GetParentNode()->IsRootNode())) |
|
node = node->GetParentNode(); |
|
} |
|
return node; |
|
} |
|
|
|
|
|
void UserPropMgr::ClearUserProp(INode *node, const char *name, const Int32 hFlag) |
|
{ |
|
node = GetAncestorIfNeeded(node,hFlag); |
|
|
|
// QuickTable invalidate |
|
if (node && node == fQuickNode) |
|
{ |
|
fQuickNode = nil; |
|
} |
|
|
|
TSTR buf; |
|
GetUserPropBuffer(node,buf); |
|
|
|
hsStringTokenizer toker(buf," \r\n"); |
|
toker.ParseQuotes(TRUE); |
|
char *tok; |
|
bool isName = true; |
|
while (tok=toker.next()) |
|
{ |
|
if (isName) |
|
{ |
|
if (*tok != '=') |
|
{ |
|
if (!stricmp(tok,name)) |
|
{ |
|
char *tok2 = toker.next(); |
|
if (tok2) |
|
{ |
|
if (*tok2 == '=') |
|
{ |
|
tok2 = toker.next(); |
|
if (tok2) |
|
{ |
|
tok2 = toker.next(); |
|
if (tok2) |
|
{ |
|
buf.remove(tok-toker.fString,tok2-tok); |
|
} |
|
else |
|
{ |
|
buf.remove(tok-toker.fString); |
|
} |
|
} |
|
else |
|
{ |
|
buf.remove(tok-toker.fString); |
|
} |
|
} |
|
else |
|
{ |
|
buf.remove(tok-toker.fString,tok2-tok); |
|
} |
|
} |
|
else |
|
{ |
|
buf.remove(tok-toker.fString); |
|
} |
|
break; |
|
} |
|
} |
|
else |
|
{ |
|
isName = false; |
|
} |
|
} |
|
else |
|
{ |
|
isName = true; |
|
} |
|
} |
|
if (vProps) |
|
{ |
|
vbuf = buf; |
|
} |
|
else |
|
{ |
|
node->SetUserPropBuffer(buf); |
|
node->NotifyDependents(FOREVER, PART_ALL, REFMSG_USERPROP); |
|
} |
|
}; |
|
|
|
BOOL UserPropMgr::GetUserProp(INode *node, const char *name, TSTR &value, const Int32 hFlag) |
|
{ |
|
node = GetAncestorIfNeeded(node,hFlag); |
|
|
|
// QuickTable lookup |
|
if (node && fQuickTable) |
|
{ |
|
if (node != fQuickNode) |
|
IBuildQuickTable(node); |
|
return ICheckQuickEntry(name,value); |
|
} |
|
|
|
TSTR buf; |
|
GetUserPropBuffer(node,buf); |
|
|
|
hsStringTokenizer toker(buf," \r\n"); |
|
toker.ParseQuotes(TRUE); |
|
char *tok; |
|
bool isName = true; |
|
while (tok=toker.next()) |
|
{ |
|
if (isName) |
|
{ |
|
if (*tok != '=') |
|
{ |
|
if (!stricmp(tok,name)) |
|
{ |
|
tok = toker.next(); |
|
if (tok && *tok == '=') |
|
{ |
|
tok = toker.next(); |
|
if (tok) value = tok; |
|
else value = ""; |
|
return true; |
|
} |
|
else |
|
{ |
|
value = ""; |
|
return true; |
|
} |
|
} |
|
} |
|
else |
|
isName = false; |
|
} |
|
else |
|
{ |
|
isName = true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
void UserPropMgr::SetUserProp(INode *node, const char *name, const char *value, const Int32 hFlag) |
|
{ |
|
node = GetAncestorIfNeeded(node,hFlag); |
|
|
|
// QuickTable invalidate |
|
if (node && node == fQuickNode) |
|
{ |
|
fQuickNode = nil; |
|
} |
|
|
|
TSTR buf; |
|
GetUserPropBuffer(node,buf); |
|
|
|
hsStringTokenizer toker(buf," \r\n"); |
|
toker.ParseQuotes(TRUE); |
|
char *tok; |
|
bool isName = true; |
|
while (tok=toker.next()) |
|
{ |
|
if (isName) |
|
{ |
|
if (*tok != '=') |
|
{ |
|
if (!stricmp(tok,name)) |
|
{ |
|
char *tok2 = toker.next(); |
|
if (tok2) |
|
{ |
|
if (*tok2 == '=') |
|
{ |
|
tok2 = toker.next(); |
|
if (tok2) |
|
{ |
|
tok2 = toker.next(); |
|
if (tok2) |
|
{ |
|
buf.remove(tok-toker.fString,tok2-tok); |
|
} |
|
else |
|
{ |
|
buf.remove(tok-toker.fString); |
|
} |
|
} |
|
else |
|
{ |
|
buf.remove(tok-toker.fString); |
|
} |
|
} |
|
else |
|
{ |
|
buf.remove(tok-toker.fString,tok2-tok); |
|
} |
|
} |
|
else |
|
{ |
|
buf.remove(tok-toker.fString); |
|
} |
|
break; |
|
} |
|
} |
|
else |
|
{ |
|
isName = false; |
|
} |
|
} |
|
else |
|
{ |
|
isName = true; |
|
} |
|
} |
|
if (buf.last('\n') < buf.length()-1) |
|
{ |
|
// better start with a separator |
|
buf += "\r\n"; |
|
} |
|
buf += name; |
|
if (value && *value) |
|
{ |
|
buf += " = "; |
|
if (strchr(value,' ')) |
|
{ |
|
buf += "\""; |
|
buf += value; |
|
buf += "\""; |
|
} |
|
else |
|
{ |
|
buf += value; |
|
} |
|
} |
|
buf += "\r\n"; |
|
if (vProps) |
|
{ |
|
vbuf = buf; |
|
} |
|
else |
|
{ |
|
node->SetUserPropBuffer(buf); |
|
node->NotifyDependents(FOREVER, PART_ALL, REFMSG_USERPROP); |
|
} |
|
} |
|
|
|
|
|
BOOL UserPropMgr::GetUserPropString(INode *node, const char *name, TSTR &value, const Int32 hFlag) |
|
{ |
|
return GetUserProp(node,name,value,hFlag); |
|
} |
|
void UserPropMgr::SetUserPropString(INode *node, const char *name, const char *value, const Int32 hFlag) |
|
{ |
|
SetUserProp(node,name,value,hFlag); |
|
} |
|
BOOL UserPropMgr::GetUserPropFloat(INode *node, const char *name, float &value, const Int32 hFlag) |
|
{ |
|
TSTR valStr; |
|
if (GetUserProp(node,name,valStr,hFlag)) |
|
{ |
|
value = (float)atof(valStr); |
|
return TRUE; |
|
} |
|
return FALSE; |
|
} |
|
void UserPropMgr::SetUserPropFloat(INode *node, const char *name, const float value, const Int32 hFlag) |
|
{ |
|
char valStr[50]; |
|
if (sprintf(valStr,"%g",value)) SetUserProp(node,name,valStr,hFlag); |
|
} |
|
BOOL UserPropMgr::GetUserPropInt(INode *node, const char *name, int &value, const Int32 hFlag) |
|
{ |
|
TSTR valStr; |
|
if (GetUserProp(node,name,valStr,hFlag)) { |
|
value = atoi(valStr); |
|
return TRUE; |
|
} |
|
return FALSE; |
|
} |
|
void UserPropMgr::SetUserPropInt(INode *node, const char *name, const int value, const Int32 hFlag) |
|
{ |
|
char valStr[50]; |
|
if (sprintf(valStr,"%d",value)) SetUserProp(node,name,valStr,hFlag); |
|
} |
|
|
|
BOOL UserPropMgr::UserPropExists(INode *node, const char *name, const Int32 hFlag) |
|
{ |
|
TSTR value; |
|
return GetUserProp(node,name,value,hFlag); |
|
} |
|
|
|
BOOL UserPropMgr::GetUserPropStringList(INode *node, const char *name, int &num, TSTR list[]) { |
|
TSTR sdata; |
|
if (UserPropMgr::GetUserPropString(node,name,sdata)) { |
|
num=0; |
|
hsStringTokenizer toker(sdata,", "); |
|
char *tok; |
|
while ( tok = toker.next() ) { |
|
list[num] = tok; |
|
num++; |
|
} |
|
return true; |
|
} else return false; |
|
} |
|
|
|
BOOL UserPropMgr::GetUserPropIntList(INode *node, const char *name, int &num, int list[]) { |
|
TSTR sdata; |
|
if (UserPropMgr::GetUserPropString(node,name,sdata)) { |
|
num=0; |
|
hsStringTokenizer toker(sdata,", "); |
|
char *tok; |
|
while ( tok = toker.next() ) { |
|
list[num] = atoi(tok); |
|
num++; |
|
} |
|
return true; |
|
} else return false; |
|
} |
|
|
|
BOOL UserPropMgr::GetUserPropFloatList(INode *node, const char *name, int &num, float list[]) { |
|
TSTR sdata; |
|
if (UserPropMgr::GetUserPropString(node,name,sdata)) { |
|
num=0; |
|
hsStringTokenizer toker(sdata,", "); |
|
char *tok; |
|
while ( tok = toker.next() ) { |
|
list[num] = (float)atof(tok); |
|
num++; |
|
} |
|
return true; |
|
} else return false; |
|
} |
|
|
|
BOOL UserPropMgr::GetUserPropStringALL(const char *name, TSTR &value, const Int32 hFlag) |
|
{ |
|
BOOL propSet = UserPropMgr::GetUserPropString(GetSelNode(0),name,value,hFlag); |
|
|
|
TSTR tvalue; |
|
int i=1; |
|
BOOL propMixed = FALSE; |
|
while (i < GetSelNodeCount() && !propMixed) { |
|
if (propSet ^ UserPropMgr::GetUserPropString(GetSelNode(i),name,tvalue,hFlag)) propMixed = TRUE; |
|
propMixed = (!(value == tvalue)); |
|
i++; |
|
} |
|
|
|
return (!propMixed); |
|
} |
|
void UserPropMgr::SetUserPropStringALL(const char *name, const char *value, const Int32 hFlag) |
|
{ |
|
for (int i=0; i<GetSelNodeCount(); i++) { |
|
UserPropMgr::SetUserPropString(GetSelNode(i),name,value,hFlag); |
|
} |
|
} |
|
|
|
BOOL UserPropMgr::GetUserPropStringListALL(const char *name, int &num, TSTR list[]) { |
|
TSTR val; |
|
GetUserPropStringList(GetSelNode(0),name,num,list); |
|
return GetUserPropStringALL(name,val); |
|
} |
|
|
|
BOOL UserPropMgr::GetUserPropIntListALL(const char *name, int &num, int *list) { |
|
TSTR val; |
|
GetUserPropIntList(GetSelNode(0),name,num,list); |
|
return GetUserPropStringALL(name,val); |
|
} |
|
|
|
BOOL UserPropMgr::GetUserPropFloatListALL(const char *name, int &num, float *list) { |
|
TSTR val; |
|
GetUserPropFloatList(GetSelNode(0),name,num,list); |
|
return GetUserPropStringALL(name,val); |
|
} |
|
|
|
BOOL UserPropMgr::GetNodeNameALL(TSTR &name) { |
|
if (vProps) name = vname; |
|
else if (ip->GetSelNodeCount() == 1) name = ip->GetSelNode(0)->GetName(); |
|
else return false; |
|
|
|
return true; |
|
} |
|
|
|
void UserPropMgr::SetNodeNameALL(const char *name) { |
|
if (vProps) { |
|
vname = name; |
|
} else { |
|
if (ip->GetSelNodeCount() > 1) { |
|
TSTR uName; |
|
for (int i=0; i<ip->GetSelNodeCount(); i++) { |
|
uName = name; |
|
ip->MakeNameUnique(uName); |
|
ip->GetSelNode(i)->SetName(uName); |
|
} |
|
} else ip->GetSelNode(0)->SetName((char*)name); |
|
} |
|
} |
|
|
|
|
|
void UserPropMgr::LoadVirtualProps(BOOL reset) { |
|
if (reset) |
|
{ |
|
vbuf = ""; |
|
vname = ""; |
|
} |
|
vProps = true; |
|
} |
|
void UserPropMgr::DestroyVirtualProps() { |
|
vProps = false; |
|
} |
|
BOOL UserPropMgr::IsVirtual() { |
|
return vProps; |
|
} |
|
|
|
int UserPropMgr::GetSelNodeCount() { |
|
if (vProps) return 1; |
|
else return ip->GetSelNodeCount(); |
|
} |
|
INode *UserPropMgr::GetSelNode(int i) { |
|
if (vProps) return NULL; |
|
else return ip->GetSelNode(i); |
|
} |
|
|
|
|
|
void UserPropMgr::OpenQuickTable() |
|
{ |
|
if (!fQuickTable) |
|
{ |
|
fQuickTable = TRACKED_NEW hsHashTable<QuickPair>(kQuickSize); |
|
} |
|
fQuickNode = nil; |
|
} |
|
|
|
void UserPropMgr::CloseQuickTable() |
|
{ |
|
#ifdef HS_DEBUGGING |
|
if (fQuickNode && fQuickTable) |
|
{ |
|
char str[256]; |
|
sprintf(str,"%d Hash Collisions reported\n",fQuickTable->CollisionCount()); |
|
hsStatusMessage(str); |
|
} |
|
#endif |
|
|
|
delete fQuickTable; |
|
fQuickTable = nil; |
|
fQuickNode = nil; |
|
QuickPair::SetBuffer(nil); |
|
} |
|
|
|
void UserPropMgr::IBuildQuickTable(INode* node) |
|
{ |
|
if (fQuickTable && fQuickNode != node) |
|
{ |
|
fQuickNode = node; |
|
|
|
// clear old QuickTable |
|
fQuickTable->clear(); |
|
|
|
// build new one |
|
TSTR buf; |
|
GetUserPropBuffer(node,buf); |
|
|
|
hsStringTokenizer toker(buf," \r\n"); |
|
toker.ParseQuotes(TRUE); |
|
|
|
char *tok; |
|
bool inName = false; |
|
bool isName = true; |
|
while ( inName || (tok=toker.next()) ) |
|
{ |
|
if (isName) |
|
{ |
|
if (*tok != '=') |
|
{ |
|
QuickPair qPair; |
|
qPair.SetKey(tok); |
|
|
|
tok = toker.next(); |
|
if (tok && *tok == '=') |
|
{ |
|
tok = toker.next(); |
|
qPair.SetVal(tok); |
|
|
|
inName = false; |
|
} |
|
else |
|
{ |
|
qPair.SetVal(nil); |
|
inName = (tok != 0); |
|
} |
|
|
|
fQuickTable->insert(qPair); |
|
} |
|
else |
|
{ |
|
isName = false; |
|
} |
|
} |
|
else |
|
{ |
|
isName = true; |
|
} |
|
} |
|
|
|
// QuickPair owns the tok'd buffer now |
|
QuickPair::SetBuffer(toker.fString); |
|
toker.fString = nil; |
|
} |
|
} |
|
|
|
BOOL UserPropMgr::ICheckQuickEntry(const char *key, TSTR &value) |
|
{ |
|
QuickPair q; |
|
q.SetKey(key); |
|
hsHashTableIterator<QuickPair> it = fQuickTable->find(q); |
|
return it->GetVal(value); |
|
} |
|
|
|
|
|
char* UserPropMgr::QuickPair::fBuffer = nil; |
|
|
|
void UserPropMgr::QuickPair::SetBuffer(char* buf) |
|
{ |
|
delete [] fBuffer; |
|
fBuffer = buf; |
|
} |
|
|
|
UInt32 UserPropMgr::QuickPair::GetHash() const |
|
{ |
|
const char * k = fKey; |
|
int len = k ? strlen(k) : 0; |
|
int h; |
|
for (h=len; len--;) |
|
{ |
|
h = ((h<<5)^(h>>27))^tolower(*k++); |
|
} |
|
return h; |
|
} |
|
|
|
hsBool UserPropMgr::QuickPair::GetVal(TSTR& value) |
|
{ |
|
if (fKey) |
|
{ |
|
value = fVal ? fVal : ""; |
|
return true; |
|
} |
|
else |
|
{ |
|
return false; |
|
} |
|
} |
|
|
|
bool UserPropMgr::QuickPair::operator==(const QuickPair& other) const |
|
{ |
|
return !_stricmp(fKey,other.fKey); |
|
}
|
|
|