1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "stat_db_tree.h"
20 #include "game_share/utils.h"
23 using namespace NLMISC
;
26 // ****************************************************************************
28 // ****************************************************************************
30 // ****************************************************************************
31 void CStatDBTableLeaf::playerAdd(NLMISC::CEntityId playerId
, sint32 val
)
33 TPlayerValues::iterator it
= _PlayerValues
.find(playerId
);
34 if (it
!= _PlayerValues
.end())
36 sint32
& playerValue
= (*it
).second
;
39 if (val
> 0 && (playerValue
+ val
) < playerValue
)
41 playerValue
= 0x7FFFFFFF;
45 // add the value and remove the entry if the result is <= 0
49 _PlayerValues
.erase(it
);
56 _PlayerValues
[playerId
] = val
;
61 // ****************************************************************************
62 void CStatDBTableLeaf::playerSet(NLMISC::CEntityId playerId
, sint32 val
)
64 TPlayerValues::iterator it
= _PlayerValues
.find(playerId
);
65 if (it
!= _PlayerValues
.end())
67 sint32
& playerValue
= (*it
).second
;
69 // set the value and remove the entry if the result is <= 0
76 _PlayerValues
.erase(it
);
83 _PlayerValues
[playerId
] = val
;
88 // ****************************************************************************
89 void CStatDBTableLeaf::guildAdd(EGSPD::TGuildId guildId
, sint32 val
)
91 TGuildValues::iterator it
= _GuildValues
.find(guildId
);
92 if (it
!= _GuildValues
.end())
94 sint32
& guildValue
= (*it
).second
;
97 if (val
> 0 && (guildValue
+ val
) < guildValue
)
99 guildValue
= 0x7FFFFFFF;
103 // add the value and remove the entry if the result is <= 0
107 _GuildValues
.erase(it
);
114 _GuildValues
[guildId
] = val
;
119 // ****************************************************************************
120 void CStatDBTableLeaf::guildSet(EGSPD::TGuildId guildId
, sint32 val
)
122 TGuildValues::iterator it
= _GuildValues
.find(guildId
);
123 if (it
!= _GuildValues
.end())
125 sint32
& guildValue
= (*it
).second
;
127 // set the value and remove the entry if the result is <= 0
134 _GuildValues
.erase(it
);
141 _GuildValues
[guildId
] = val
;
146 // ****************************************************************************
147 bool CStatDBTableLeaf::playerGet(NLMISC::CEntityId playerId
, sint32
& val
) const
149 TPlayerValues::const_iterator it
= _PlayerValues
.find(playerId
);
150 if (it
== _PlayerValues
.end())
157 // ****************************************************************************
158 bool CStatDBTableLeaf::guildGet(EGSPD::TGuildId guildId
, sint32
& val
) const
160 TGuildValues::const_iterator it
= _GuildValues
.find(guildId
);
161 if (it
== _GuildValues
.end())
168 // ****************************************************************************
169 void CStatDBTableLeaf::removePlayer(NLMISC::CEntityId playerId
)
171 TPlayerValues::iterator it
= _PlayerValues
.find(playerId
);
172 if (it
!= _PlayerValues
.end())
173 _PlayerValues
.erase(it
);
176 // ****************************************************************************
177 void CStatDBTableLeaf::removeGuild(EGSPD::TGuildId guildId
)
179 TGuildValues::iterator it
= _GuildValues
.find(guildId
);
180 if (it
!= _GuildValues
.end())
181 _GuildValues
.erase(it
);
184 // ****************************************************************************
186 // ****************************************************************************
188 // ****************************************************************************
189 bool CStatDBBranch::setNode(const std::string
& path
, IStatDBNodePtr node
)
191 BOMB_IF(path
.empty(), "empty path!", return false);
192 BOMB_IF(node
== NULL
, "NULL node!", return false);
196 splitPath(path
, token
, rest
);
198 if (!isValidToken(token
))
203 _Children
.add(make_pair(token
, node
));
207 IStatDBNodePtr nextNode
;
208 TChildren::iterator it
= _Children
.find(token
);
209 if (it
== _Children
.end())
211 nextNode
= new CStatDBBranch
;
212 _Children
.add(make_pair(token
, nextNode
));
216 nextNode
= (*it
).second
;
219 return nextNode
->setNode(rest
, node
);
222 // ****************************************************************************
223 IStatDBNodePtr
CStatDBBranch::getNode(const std::string
& path
)
225 BOMB_IF(path
.empty(), "empty path!", return NULL
);
229 splitPath(path
, token
, rest
);
231 TChildren::iterator it
= _Children
.find(token
);
232 if (it
== _Children
.end())
238 return (*it
).second
->getNode(rest
);
241 // ****************************************************************************
242 void CStatDBBranch::getNodes(const std::string
& pathPattern
, std::vector
<CMatchingNode
> & matchingNodes
,
243 const std::string
& currentPath
)
245 BOMB_IF(pathPattern
.empty(), "empty path!", return);
247 // DO NOT clear the vector 'matchingNodes' here because this method is recursive
251 splitPath(pathPattern
, token
, rest
);
253 string pathPrefix
= currentPath
;
254 if (!pathPrefix
.empty())
262 for (TChildren::iterator it
= _Children
.begin(); it
!= _Children
.end(); ++it
)
264 CMatchingNode matchingNode
;
265 matchingNode
.Path
= pathPrefix
+ (*it
).first
;
266 matchingNode
.Node
= (*it
).second
;
267 matchingNodes
.push_back(matchingNode
);
272 for (TChildren::iterator it
= _Children
.begin(); it
!= _Children
.end(); ++it
)
274 (*it
).second
->getNodes(rest
, matchingNodes
, pathPrefix
+ (*it
).first
);
280 TChildren::iterator it
= _Children
.find(token
);
281 if (it
== _Children
.end())
286 CMatchingNode matchingNode
;
287 matchingNode
.Path
= pathPrefix
+ (*it
).first
;
288 matchingNode
.Node
= (*it
).second
;
289 matchingNodes
.push_back(matchingNode
);
293 (*it
).second
->getNodes(rest
, matchingNodes
, pathPrefix
+ (*it
).first
);
297 // ****************************************************************************
298 IStatDBNodePtr
CStatDBBranch::removeNode(const std::string
& path
)
300 BOMB_IF(path
.empty(), "empty path!", return NULL
);
304 splitPath(path
, token
, rest
);
306 TChildren::iterator it
= _Children
.find(token
);
307 if (it
== _Children
.end())
312 IStatDBNodePtr removedNode
= (*it
).second
;
317 return (*it
).second
->removeNode(rest
);
320 // ****************************************************************************
321 void CStatDBBranch::acceptVisitor(CStatDBNodeVisitor
& visitor
, const std::string
& currentPath
)
323 string childPathPrefix
;
324 if (!currentPath
.empty())
325 childPathPrefix
= currentPath
+ ".";
327 visitor
.visitBranch(this, currentPath
);
329 for (TChildren::iterator it
= _Children
.begin(); it
!= _Children
.end(); ++it
)
331 (*it
).second
->acceptVisitor(visitor
, childPathPrefix
+ (*it
).first
);
335 // ****************************************************************************
336 bool CStatDBBranch::isValidToken(const std::string
& token
) const
341 for (string::const_iterator it
= token
.begin(); it
!= token
.end(); ++it
)
343 if (!isalnum(*it
) && (*it
) != '_')
350 // ****************************************************************************
351 void CStatDBBranch::splitPath(const std::string
& path
, std::string
& token
, std::string
& rest
) const
353 string::size_type i
= path
.find('.');
354 if (i
== string::npos
)
361 token
= path
.substr(0, i
);
362 rest
= path
.substr(i
+1);
366 // ****************************************************************************
367 // CStatDBEntitiesRemoval
368 // ****************************************************************************
370 // ****************************************************************************
371 void CStatDBEntitiesRemoval::addPlayerToRemove(NLMISC::CEntityId playerId
)
373 for (uint i
= 0; i
< _PlayersToRemove
.size(); i
++)
375 if (_PlayersToRemove
[i
] == playerId
)
379 _PlayersToRemove
.push_back(playerId
);
382 // ****************************************************************************
383 void CStatDBEntitiesRemoval::addGuildToRemove(EGSPD::TGuildId guildId
)
385 for (uint i
= 0; i
< _GuildsToRemove
.size(); i
++)
387 if (_GuildsToRemove
[i
] == guildId
)
391 _GuildsToRemove
.push_back(guildId
);
394 // ****************************************************************************
395 void CStatDBEntitiesRemoval::processRemoval(IStatDBNodePtr root
)
397 nlassert(root
!= NULL
);
399 if (_PlayersToRemove
.empty() && _GuildsToRemove
.empty())
402 root
->acceptVisitor(*this, "");
404 _PlayersToRemove
.clear();
405 _GuildsToRemove
.clear();
408 // ****************************************************************************
409 void CStatDBEntitiesRemoval::visitTableLeaf(CStatDBTableLeaf
* tableLeaf
, const std::string
& path
)
411 for (uint i
= 0; i
< _PlayersToRemove
.size(); i
++)
413 tableLeaf
->removePlayer(_PlayersToRemove
[i
]);
416 for (uint i
= 0; i
< _GuildsToRemove
.size(); i
++)
418 tableLeaf
->removeGuild(_GuildsToRemove
[i
]);