/*************************************************************************** * Copyright (C) 2005-2007 by Rajko Albrecht * * ral@alwins-world.de * * * * 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 2 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef HELPERSCACHEENTRY_H #define HELPERSCACHEENTRY_H #include "src/svnqt/svnqttypes.hpp" #include "src/svnqt/shared_pointer.hpp" #include "src/svnqt/status.hpp" // std::map 'cause QMap isn't usable #include #include #include #include namespace helpers { /** Class for fast search of path based items. @author Rajko Albrecht */ template class cacheEntry { public: typedef cacheEntry cache_type; typedef typename std::map cache_map_type; typedef typename cache_map_type::const_iterator citer; typedef typename cache_map_type::iterator iter; protected: QString m_key; bool m_isValid; C m_content; cache_map_type m_subMap; public: cacheEntry(); cacheEntry(const QString&key); cacheEntry(const cacheEntry&other); virtual ~cacheEntry(){}; virtual bool find(QStringList&,QLIST&)const; //! Checks if cache contains a specific item /*! * the keylist will manipulated - so copy-operations aren't needed. * \param what Stringlist containing the components to search for * \return true if found (may or may not valid!) otherwise false */ virtual bool find(QStringList&what)const; //! Checks if cache contains a specific valid item /*! * if yes, the content will stored in st * \param what the keylist to search for * \param st target status to store content if found * \return true if found */ virtual bool findSingleValid(QStringList&what,C&st)const; //! Checks if cache contains a specific valid item /*! * in difference to virtual bool find(QStringList&,svn::StatusEntries&)const no copy operations * are made inside so it works much faster for simple find. * \param what the keylist to search for * \param check_valid_subs if true, return true if a subitem is valid even the item isn't valid * \return true if found */ virtual bool findSingleValid(QStringList&what,bool check_valid_subs)const; template void listsubs_if(QStringList&_what,T&oper)const; virtual void appendValidSub(QLIST&)const; virtual bool isValid()const { return m_isValid; } virtual const C&content()const { return m_content; } virtual bool deleteKey(QStringList&,bool exact); virtual void insertKey(QStringList&,const C&); virtual void setValidContent(const QString&key,const C&st) { kdDebug()<<"Insert for "<& operator=(const cacheEntry&other); #if 0 void dump_tree(int level=0)const { QString pre; pre.fill('-',level); std::map::const_iterator it; for (it=m_subMap.begin();it!=m_subMap.end();++it) { std::cout<first.latin1() << " (" << it->second.m_key.latin1() << ")"<second.dump_tree(level+1); } } #endif }; typedef cacheEntry statusEntry; template inline cacheEntry::cacheEntry() : m_key(""),m_isValid(false),m_content() { } template inline cacheEntry::cacheEntry(const QString&key) : m_key(key),m_isValid(false),m_content() { } template inline cacheEntry::cacheEntry(const cacheEntry&other) : m_key(other.m_key),m_isValid(other.m_isValid), m_content(other.m_content),m_subMap(other.m_subMap) { } template inline cacheEntry& cacheEntry::operator=(const cacheEntry&other) { m_key=other.m_key; m_isValid = other.m_isValid; m_content = other.m_content; m_subMap = other.m_subMap; return *this; } template inline bool cacheEntry::find(QStringList&what,QLIST&t)const { if (what.count()==0) { return false; } citer it; it = m_subMap.find(what[0]); if (it==m_subMap.end()) { // kdDebug()<second.m_key == what[0]) { /* the item itself */ if (it->second.isValid()) { t.append(it->second.content()); } /* and now check valid subitems */ // kdDebug()<<"Appending valid subs"<second.appendValidSub(t); // kdDebug()<<"Appended valid subs"<second.find(what,t); } template inline bool cacheEntry::find(QStringList&what)const { if (what.count()==0) { return false; } citer it = m_subMap.find(what[0]); if (it==m_subMap.end()) { return false; } if (what.count()==1) { return true; } what.erase(what.begin()); return it->second.find(what); } template inline bool cacheEntry::findSingleValid(QStringList&what,C&t)const { if (what.count()==0) { return false; } //kdDebug()<<"cacheEntry::findSingleValid(QStringList&what,C&t)"<< what << endl; citer it; it = m_subMap.find(what[0]); if (it==m_subMap.end()) { //kdDebug()<<"Not found here..."<second.isValid()<second.content(); return it->second.isValid(); } what.erase(what.begin()); //kdDebug()<<"Search next stage down..."<second.findSingleValid(what,t); } template inline bool cacheEntry::findSingleValid(QStringList&what,bool check_valid_subs)const { if (what.count()==0) { return false; } // kdDebug()<<"cacheEntry::findSingleValid(QStringList&what,svn::Status&t)"<< what << endl; citer it = m_subMap.find(what[0]); if (it==m_subMap.end()) { return false; } if (what.count()==1) { return it->second.isValid()||(check_valid_subs&&it->second.hasValidSubs()); } what.erase(what.begin()); return it->second.findSingleValid(what,check_valid_subs); } template inline void cacheEntry::appendValidSub(QLIST&t)const { citer it; for (it=m_subMap.begin();it!=m_subMap.end();++it) { if (it->second.isValid()) { // kdDebug()<<"Appending single sub"<second.content()); } else { // kdDebug()<second.key()<<" isnt valid"<second.appendValidSub(t); } } template inline bool cacheEntry::deleteKey(QStringList&what,bool exact) { if (what.count()==0) { return true; } iter it=m_subMap.find(what[0]); if (it==m_subMap.end()) { return true; } bool caller_must_check = false; /* first stage - we are the one holding the right key */ if (what.count()==1){ if (!exact || !it->second.hasValidSubs()) { m_subMap.erase(it); caller_must_check = true; } else { it->second.markInvalid(); } } else { /* otherwise go trough tree */ what.erase(what.begin()); bool b = it->second.deleteKey(what,exact); if (b && !it->second.hasValidSubs()) { m_subMap.erase(it); caller_must_check = true; } } return caller_must_check; } template inline bool cacheEntry::hasValidSubs()const { citer it; for (it=m_subMap.begin();it!=m_subMap.end();++it) { if (it->second.isValid()||it->second.hasValidSubs()) { return true; } } return false; } template inline void cacheEntry::insertKey(QStringList&what,const C&st) { if (what.count()==0) { return; } //kdDebug()<<"inserting "< template inline void cacheEntry::listsubs_if(QStringList&what,T&oper)const { if (what.count()==0) { /* we are the one to get the list for*/ oper = for_each(m_subMap.begin(),m_subMap.end(),oper); return; } /* otherwise find next */ citer it = m_subMap.find(what[0]); if (it==m_subMap.end()) { /* not found */ return; } what.erase(what.begin()); it->second.listsubs_if(what,oper); } template class itemCache { public: typedef cacheEntry cache_type; typedef typename std::map cache_map_type; typedef typename cache_map_type::const_iterator citer; typedef typename cache_map_type::iterator iter; protected: cache_map_type m_contentMap; public: itemCache():m_contentMap(){} virtual ~itemCache(){}; void setContent(const QLIST&dlist); void clear(){m_contentMap.clear();} //! Checks if cache contains a specific item /*! * the keylist will manipulated - so copy-operations aren't needed. * \param what Stringlist containing the components to search for * \return true if found (may or may not valid!) otherwise false */ virtual bool find(const QString&what)const; virtual bool find(const QString&,QLIST&)const; virtual void deleteKey(const QString&what,bool exact); virtual void insertKey(const C&,const QString&path); virtual bool findSingleValid(const QString&what,C&)const; virtual bool findSingleValid(const QString&what,bool check_valid_subs)const; templatevoid listsubs_if(const QString&what,T&oper)const; void dump_tree(); }; template inline void itemCache::setContent(const QLIST&dlist) { m_contentMap.clear(); citer it; for (it=dlist.begin();it!=dlist.end();++it) { QStringList _keys = QStringList::split("/",(*it).path()); if (_keys.count()==0) { continue; } m_contentMap[_keys[0]]=statusEntry(_keys[0]); if (_keys.count()==1) { m_contentMap[_keys[0]].setValidContent(_keys[0],(*it)); } else { _keys.erase(_keys.begin()); m_contentMap[_keys[0]].insertKey(_keys,(*it)); } } } template inline void itemCache::insertKey(const C&st,const QString&path) { // kdDebug()<<"Inserting "< inline bool itemCache::find(const QString&what)const { if (m_contentMap.size()==0) { return false; } QStringList _keys = QStringList::split("/",what); if (_keys.count()==0) { return false; } citer it=m_contentMap.find(_keys[0]); if (it==m_contentMap.end()) { return false; } if (_keys.count()==1) { return true; } _keys.erase(_keys.begin()); return it->second.find(_keys); } template inline bool itemCache::find(const QString&_what,QLIST&dlist)const { if (m_contentMap.size()==0) { return false; } QStringList what = QStringList::split("/",_what); if (what.count()==0) { return false; } citer it=m_contentMap.find(what[0]); if (it==m_contentMap.end()) { return false; } what.erase(what.begin()); // kdDebug()<<"itemCache::find(const QString&_what,svn::StatusEntries&dlist) "<second.find(what,dlist); } template inline void itemCache::deleteKey(const QString&_what,bool exact) { if (m_contentMap.size()==0) { return; } QStringList what = QStringList::split("/",_what); if (what.count()==0) { return; } iter it=m_contentMap.find(what[0]); if (it==m_contentMap.end()) { return; } /* first stage - we are the one holding the right key */ if (what.count()==1){ if (!exact || !it->second.hasValidSubs()) { /* if it has no valid subs delete it */ m_contentMap.erase(it); } else { /* otherwise mark as invalid */ it->second.markInvalid(); } return; } else { /* otherwise go trough tree */ what.erase(what.begin()); bool b = it->second.deleteKey(what,exact); if (b && !it->second.hasValidSubs()) { m_contentMap.erase(it); } } } template inline void itemCache::dump_tree() { citer it; for (it=m_contentMap.begin();it!=m_contentMap.end();++it) { // std::cout<first.latin1() << " (" << it->second.key().latin1() << ")"<second.dump_tree(1); } } template inline bool itemCache::findSingleValid(const QString&_what,C&st)const { if (m_contentMap.size()==0) { return false; } QStringList what = QStringList::split("/",_what); if (what.count()==0) { return false; } //kdDebug()<<"Itemcache What: "<second.isValid()) { st=it->second.content(); return true; } return false; } //kdDebug()<<"Stage down"<second.findSingleValid(what,st); } template inline bool itemCache::findSingleValid(const QString&_what,bool check_valid_subs)const { if (m_contentMap.size()==0) { return false; } QStringList what = QStringList::split("/",_what); if (what.count()==0) { return false; } citer it=m_contentMap.find(what[0]); if (it==m_contentMap.end()) { return false; } if (what.count()==1) { return it->second.isValid()||(check_valid_subs&&it->second.hasValidSubs()); } what.erase(what.begin()); return it->second.findSingleValid(what,check_valid_subs); } template template inline void itemCache::listsubs_if(const QString&_what,T&oper)const { if (m_contentMap.size()==0) { return; } QStringList what = QStringList::split("/",_what); if (what.count()==0) { return; } citer it=m_contentMap.find(what[0]); if (it==m_contentMap.end()) { return; } if (what.count()==1) { oper = for_each(m_contentMap.begin(),m_contentMap.end(),oper); return; } what.erase(what.begin()); it->second.listsubs_if(what,oper); } typedef cacheEntry ptrEntry; typedef itemCache statusCache; class ValidRemoteOnly { svn::StatusEntries m_List; public: ValidRemoteOnly():m_List(){} void operator()(const std::pair&_data) { if(_data.second.isValid() && _data.second.content()->validReposStatus()&&!_data.second.content()->validLocalStatus()) { m_List.push_back(_data.second.content()); } } const svn::StatusEntries&liste()const{return m_List;} }; } #endif