Add infos into target window
[ryzomcore.git] / ryzom / server / src / server_share / stat_db_tree.cpp
blob5419c6850c6f1e9195fed1b3d880356d3bb87ac8
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
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.
8 //
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/>.
18 #include "stdpch.h"
19 #include "stat_db_tree.h"
20 #include "game_share/utils.h"
22 using namespace std;
23 using namespace NLMISC;
26 // ****************************************************************************
27 // CStatDBTableLeaf
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;
38 // avoid overflow
39 if (val > 0 && (playerValue + val) < playerValue)
41 playerValue = 0x7FFFFFFF;
42 return;
45 // add the value and remove the entry if the result is <= 0
46 playerValue += val;
47 if (playerValue <= 0)
49 _PlayerValues.erase(it);
52 else
54 if (val > 0)
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
70 if (val > 0)
72 playerValue = val;
74 else
76 _PlayerValues.erase(it);
79 else
81 if (val > 0)
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;
96 // avoid overflow
97 if (val > 0 && (guildValue + val) < guildValue)
99 guildValue = 0x7FFFFFFF;
100 return;
103 // add the value and remove the entry if the result is <= 0
104 guildValue += val;
105 if (guildValue <= 0)
107 _GuildValues.erase(it);
110 else
112 if (val > 0)
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
128 if (val > 0)
130 guildValue = val;
132 else
134 _GuildValues.erase(it);
137 else
139 if (val > 0)
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())
151 return false;
153 val = (*it).second;
154 return true;
157 // ****************************************************************************
158 bool CStatDBTableLeaf::guildGet(EGSPD::TGuildId guildId, sint32 & val) const
160 TGuildValues::const_iterator it = _GuildValues.find(guildId);
161 if (it == _GuildValues.end())
162 return false;
164 val = (*it).second;
165 return true;
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 // ****************************************************************************
185 // CStatDBBranch
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);
194 string token;
195 string rest;
196 splitPath(path, token, rest);
198 if (!isValidToken(token))
199 return false;
201 if (rest.empty())
203 _Children.add(make_pair(token, node));
204 return true;
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));
214 else
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);
227 string token;
228 string rest;
229 splitPath(path, token, rest);
231 TChildren::iterator it = _Children.find(token);
232 if (it == _Children.end())
233 return NULL;
235 if (rest.empty())
236 return (*it).second;
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
249 string token;
250 string rest;
251 splitPath(pathPattern, token, rest);
253 string pathPrefix = currentPath;
254 if (!pathPrefix.empty())
255 pathPrefix += ".";
257 // check wildcard
258 if (token == "*")
260 if (rest.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);
270 else
272 for (TChildren::iterator it = _Children.begin(); it != _Children.end(); ++it)
274 (*it).second->getNodes(rest, matchingNodes, pathPrefix + (*it).first);
277 return;
280 TChildren::iterator it = _Children.find(token);
281 if (it == _Children.end())
282 return;
284 if (rest.empty())
286 CMatchingNode matchingNode;
287 matchingNode.Path = pathPrefix + (*it).first;
288 matchingNode.Node = (*it).second;
289 matchingNodes.push_back(matchingNode);
291 else
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);
302 string token;
303 string rest;
304 splitPath(path, token, rest);
306 TChildren::iterator it = _Children.find(token);
307 if (it == _Children.end())
308 return NULL;
310 if (rest.empty())
312 IStatDBNodePtr removedNode = (*it).second;
313 _Children.del(it);
314 return removedNode;
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
338 if (token.empty())
339 return false;
341 for (string::const_iterator it = token.begin(); it != token.end(); ++it)
343 if (!isalnum(*it) && (*it) != '_')
344 return false;
347 return true;
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)
356 token = path;
357 rest.clear();
359 else
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)
376 return;
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)
388 return;
391 _GuildsToRemove.push_back(guildId);
394 // ****************************************************************************
395 void CStatDBEntitiesRemoval::processRemoval(IStatDBNodePtr root)
397 nlassert(root != NULL);
399 if (_PlayersToRemove.empty() && _GuildsToRemove.empty())
400 return;
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]);