From 9f962123be30da94add3f966bb46962f8bfdea88 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 24 Sep 2009 21:50:11 +0200 Subject: UserList: Encapsulate list --- src/Common/CMakeLists.txt | 2 +- src/Common/UserLists/UserList.cpp | 129 ++++++++++++++++++++++++++++++++++++++ src/Common/UserLists/UserList.h | 125 +++++++++++++++++++++++++++++++++++- src/Common/UserLists/Util.cpp | 4 +- 4 files changed, 256 insertions(+), 4 deletions(-) create mode 100644 src/Common/UserLists/UserList.cpp (limited to 'src/Common') diff --git a/src/Common/CMakeLists.txt b/src/Common/CMakeLists.txt index a99f9be..d82c0d9 100644 --- a/src/Common/CMakeLists.txt +++ b/src/Common/CMakeLists.txt @@ -18,7 +18,7 @@ mad_library(Common Requests/SimpleRequest.cpp Requests/SimpleRequest.h Requests/StatusRequest.h - UserLists/UserList.h + UserLists/UserList.cpp UserLists/UserList.h UserLists/UserListDiff.cpp UserLists/UserListDiff.h UserLists/UserListEntry.h UserLists/Util.cpp UserLists/Util.h diff --git a/src/Common/UserLists/UserList.cpp b/src/Common/UserLists/UserList.cpp new file mode 100644 index 0000000..a14111d --- /dev/null +++ b/src/Common/UserLists/UserList.cpp @@ -0,0 +1,129 @@ +/* + * UserList.cpp + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#include "UserList.h" + +namespace Mad { +namespace Common { +namespace UserLists { + +std::list::iterator UserList::findEntry(const std::string &name) { + for(std::list::iterator it = list.begin(); it != list.end(); ++it) { + if(it->getName() == name) { + return it; + } + } + + return list.end(); +} + +std::list::const_iterator UserList::findEntry(const std::string &name) const { + for(std::list::const_iterator it = list.begin(); it != list.end(); ++it) { + if(it->getName() == name) { + return it; + } + } + + return list.end(); +} + +UserList::iterator UserList::find(const std::string &name) { + if(!names.count(name)) + return end(); + + return iterator(findEntry(name)); +} + +UserList::const_iterator UserList::find(const std::string &name) const { + if(!names.count(name)) + return end(); + + return const_iterator(findEntry(name)); +} + +void UserList::registerEntry(const UserListEntry &entry) { + std::set details = entry.getDetailList(); + + for(std::set::iterator detail = details.begin(); detail != details.end(); ++detail) { + std::map::iterator it = detailCounts.find(*detail); + if(it == detailCounts.end()) + detailCounts.insert(make_pair(*detail, 1)); + else + ++it->second; + } +} + +void UserList::unregisterEntry(const UserListEntry &entry) { + std::set details = entry.getDetailList(); + + for(std::set::iterator detail = details.begin(); detail != details.end(); ++detail) { + std::map::iterator it = detailCounts.find(*detail); + // TODO Assert + if(it == detailCounts.end()) + continue; + + if(it->second > 1) + --it->second; + else + detailCounts.erase(it); + } +} + + +bool UserList::addUser(const UserListEntry &entry) { + return insertUser(entry, end()); +} + +bool UserList::insertUser(const UserListEntry &entry, iterator after) { + if(!names.insert(entry.getName()).second) + return false; + + list.insert(after.it, entry); + registerEntry(entry); + return true; +} + +bool UserList::removeUser(const std::string &name) { + if(!names.erase(name)) + return false; + + std::list::iterator it = findEntry(name); + // TODO Assert + + unregisterEntry(*it); + list.erase(it); + return true; +} + +bool UserList::updateUser(const UserListEntry &entry) { + if(!names.count(entry.getName())) + return false; + + std::list::iterator it = findEntry(entry.getName()); + // TODO Assert + + unregisterEntry(*it); + *it = entry; + registerEntry(entry); + return true; +} + +} +} +} diff --git a/src/Common/UserLists/UserList.h b/src/Common/UserLists/UserList.h index e80abaf..9c5985d 100644 --- a/src/Common/UserLists/UserList.h +++ b/src/Common/UserLists/UserList.h @@ -20,16 +20,139 @@ #ifndef MAD_COMMON_USERLISTS_USERLIST_H_ #define MAD_COMMON_USERLISTS_USERLIST_H_ +#include "../export.h" + #include "UserListEntry.h" #include +#include +#include namespace Mad { namespace Common { namespace UserLists { -class UserList : public std::list { +class MAD_COMMON_EXPORT UserList { + private: + template + class iterator_base { + public: + friend class UserList; + + typedef Type value_type; + + typedef value_type &reference; + typedef value_type *pointer; + + typedef long difference_type; + + private: + IteratorType it; + + iterator_base(IteratorType it0) : it(it0) {} + + public: + iterator_base() {} + + reference operator*() const { + return *it; + } + + iterator_base operator++(int) { + return iterator(it++); + } + + iterator_base& operator++() { + ++it; + return *this; + } + + iterator_base operator--(int) { + return iterator(it--); + } + + iterator_base& operator--() { + --it; + return *this; + } + + bool operator==(const iterator_base &it2) { + return it2.it == it; + } + + bool operator!=(const iterator_base &it2) { + return it2.it != it; + } + + pointer operator->() const { + return &*it; + } + }; + + std::set names; + std::list list; + + std::map detailCounts; + + void registerEntry(const UserListEntry &entry); + void unregisterEntry(const UserListEntry &entry); + + std::list::iterator findEntry(const std::string &name); + std::list::const_iterator findEntry(const std::string &name) const; + public: + typedef iterator_base::iterator> iterator; + typedef iterator_base::const_iterator> const_iterator; + + iterator find(const std::string &name); + const_iterator find(const std::string &name) const; + + iterator begin() { + return iterator(list.begin()); + } + + const_iterator begin() const { + return const_iterator(list.begin()); + } + + iterator end() { + return list.end(); + } + + const_iterator end() const { + return const_iterator(list.end()); + } + + bool isEmpty() const { + return list.empty(); + } + + size_t getLength() const { + return list.size(); + } + + std::set getDetails() const { + std::set ret; + + for(std::map::const_iterator it = detailCounts.begin(); it != detailCounts.end(); ++it) + ret.insert(it->first); + + return ret; + } + + unsigned getDetailUsage(const std::string &detail) const { + std::map::const_iterator it = detailCounts.find(detail); + if(it == detailCounts.end()) + return 0; + else + return it->second; + } + + bool addUser(const UserListEntry &entry); + bool insertUser(const UserListEntry &entry, iterator after); + bool removeUser(const std::string &name); + bool updateUser(const UserListEntry &entry); + UserList() {} }; diff --git a/src/Common/UserLists/Util.cpp b/src/Common/UserLists/Util.cpp index 812c2c7..3c15956 100644 --- a/src/Common/UserLists/Util.cpp +++ b/src/Common/UserLists/Util.cpp @@ -39,7 +39,7 @@ UserListEntry Util::deserializeUserListEntry(XmlData::List::const_iterator entry std::set details = entry->getChildren(); for(std::set::iterator detail = details.begin(); detail != details.end(); ++detail) { - if(*detail == "user" || *detail == "group") + if(*detail == "name" || *detail == "group") continue; user.setDetail(*detail, entry->get(*detail)); @@ -62,7 +62,7 @@ boost::shared_ptr Util::deserializeUserList(const XmlData *data) { if(userList) { for(XmlData::List::const_iterator user = userList->begin(); user != userList->end(); ++user) - users->push_back(deserializeUserListEntry(user)); + users->addUser(deserializeUserListEntry(user)); } return users; -- cgit v1.2.3