summaryrefslogtreecommitdiffstats
path: root/src/svnfrontend/cacheentry.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/svnfrontend/cacheentry.h')
-rw-r--r--src/svnfrontend/cacheentry.h581
1 files changed, 581 insertions, 0 deletions
diff --git a/src/svnfrontend/cacheentry.h b/src/svnfrontend/cacheentry.h
new file mode 100644
index 0000000..2ab422b
--- /dev/null
+++ b/src/svnfrontend/cacheentry.h
@@ -0,0 +1,581 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 by Rajko Albrecht *
+ * *
+ * 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 <map>
+#include <algorithm>
+#include <qstring.h>
+#include <qstringlist.h>
+
+namespace helpers {
+
+/**
+ Class for fast search of path based items.
+
+ @author Rajko Albrecht <[email protected]>
+*/
+template<class C> class cacheEntry {
+public:
+ typedef cacheEntry<C> cache_type;
+ typedef typename std::map<QString,cache_type> 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<C>&other);
+
+ virtual ~cacheEntry(){};
+
+ virtual bool find(QStringList&,QLIST<C>&)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<class T> void listsubs_if(QStringList&_what,T&oper)const;
+
+ virtual void appendValidSub(QLIST<C>&)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 "<<key<<endl;
+ m_key = key;
+ m_isValid=true;
+ m_content=st;
+ }
+ virtual bool hasValidSubs()const;
+ virtual void markInvalid() {
+ m_content=C();
+ m_isValid=false;
+ }
+ const QString&key()const {
+ return m_key;
+ }
+
+ cacheEntry<C>& operator=(const cacheEntry<C>&other);
+#if 0
+ void dump_tree(int level=0)const
+ {
+ QString pre;
+ pre.fill('-',level);
+ std::map<QString,cacheEntry>::const_iterator it;
+ for (it=m_subMap.begin();it!=m_subMap.end();++it) {
+ std::cout<<pre.latin1()<<it->first.latin1() << " (" << it->second.m_key.latin1() << ")"<<std::endl;
+ it->second.dump_tree(level+1);
+ }
+ }
+#endif
+};
+
+typedef cacheEntry<svn::StatusPtr> statusEntry;
+
+template<class C> inline cacheEntry<C>::cacheEntry()
+ : m_key(""),m_isValid(false),m_content()
+{
+}
+
+template<class C> inline cacheEntry<C>::cacheEntry(const QString&key)
+ : m_key(key),m_isValid(false),m_content()
+{
+}
+
+template<class C> inline cacheEntry<C>::cacheEntry(const cacheEntry<C>&other)
+ : m_key(other.m_key),m_isValid(other.m_isValid),
+ m_content(other.m_content),m_subMap(other.m_subMap)
+{
+}
+
+template<class C> inline cacheEntry<C>& cacheEntry<C>::operator=(const cacheEntry<C>&other)
+{
+ m_key=other.m_key;
+ m_isValid = other.m_isValid;
+ m_content = other.m_content;
+ m_subMap = other.m_subMap;
+ return *this;
+}
+
+template<class C> inline bool cacheEntry<C>::find(QStringList&what,QLIST<C>&t)const
+{
+ if (what.count()==0) {
+ return false;
+ }
+ citer it;
+ it = m_subMap.find(what[0]);
+ if (it==m_subMap.end()) {
+ // kdDebug()<<what[0]<< " not found in tree"<<endl;
+ return false;
+ }
+ // kdDebug()<<what[0]<< " found in tree"<<endl;
+ if (what.count()==1) {
+ // kdDebug()<<"Seems last item in stage "<< m_key << " - " << what[0] << endl;
+// if (it->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"<<endl;
+ it->second.appendValidSub(t);
+ // kdDebug()<<"Appended valid subs"<<endl;
+ return true;
+// }
+ return false;
+ }
+ what.erase(what.begin());
+ // kdDebug()<<"Searching "<<what<<" in next stage"<<endl;
+ return it->second.find(what,t);
+}
+
+template<class C> inline bool cacheEntry<C>::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<class C> inline bool cacheEntry<C>::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..."<<endl;
+ return false;
+ }
+ if (what.count()==1) {
+ //kdDebug()<<"Found here and set content. "<<it->second.isValid()<<endl;
+ t=it->second.content();
+ return it->second.isValid();
+ }
+ what.erase(what.begin());
+ //kdDebug()<<"Search next stage down..."<<endl;
+ return it->second.findSingleValid(what,t);
+}
+
+template<class C> inline bool cacheEntry<C>::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<class C> inline void cacheEntry<C>::appendValidSub(QLIST<C>&t)const
+{
+ citer it;
+ for (it=m_subMap.begin();it!=m_subMap.end();++it) {
+ if (it->second.isValid()) {
+ // kdDebug()<<"Appending single sub"<<endl;
+ t.append(it->second.content());
+ } else {
+ // kdDebug()<<it->second.key()<<" isnt valid"<<endl;
+ }
+ it->second.appendValidSub(t);
+ }
+}
+
+template<class C> inline bool cacheEntry<C>::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<class C> inline bool cacheEntry<C>::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<class C> inline void cacheEntry<C>::insertKey(QStringList&what,const C&st)
+{
+ if (what.count()==0) {
+ return;
+ }
+ //kdDebug()<<"inserting "<<what<< "into " << m_key << endl;
+ QString m = what[0];
+
+ if (m_subMap.find(m)==m_subMap.end()) {
+ m_subMap[m].m_key=m;
+ }
+ if (what.count()==1) {
+ // kdDebug()<<"Inserting valid key "<< m << endl;
+ m_subMap[m].setValidContent(m,st);
+ // kdDebug()<<"Inserting valid key done"<< endl;
+ return;
+ }
+ what.erase(what.begin());
+ //kdDebug()<<"Go into loop"<<endl;
+ m_subMap[m].insertKey(what,st);
+}
+
+template<class C> template<class T> inline void cacheEntry<C>::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 C> class itemCache
+{
+public:
+ typedef cacheEntry<C> cache_type;
+ typedef typename std::map<QString,cache_type> 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<C>&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<C>&)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;
+
+ template<class T>void listsubs_if(const QString&what,T&oper)const;
+
+ void dump_tree();
+};
+
+template<class C> inline void itemCache<C>::setContent(const QLIST<C>&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<class C> inline void itemCache<C>::insertKey(const C&st,const QString&path)
+{
+ // kdDebug()<<"Inserting "<<st.path()<<endl;
+ QStringList _keys = QStringList::split("/",path);
+ if (_keys.count()==0) {
+ return;
+ }
+ iter it=m_contentMap.find(_keys[0]);
+
+ if (it==m_contentMap.end()) {
+ m_contentMap[_keys[0]]=cache_type(_keys[0]);
+ }
+ if (_keys.count()==1) {
+ m_contentMap[_keys[0]].setValidContent(_keys[0],st);
+ } else {
+ QString m = _keys[0];
+ _keys.erase(_keys.begin());
+ m_contentMap[m].insertKey(_keys,st);
+ }
+}
+
+template<class C> inline bool itemCache<C>::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<class C> inline bool itemCache<C>::find(const QString&_what,QLIST<C>&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) "<<what<<endl;
+ return it->second.find(what,dlist);
+}
+
+template<class C> inline void itemCache<C>::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<class C> inline void itemCache<C>::dump_tree()
+{
+ citer it;
+ for (it=m_contentMap.begin();it!=m_contentMap.end();++it) {
+// std::cout<<it->first.latin1() << " (" << it->second.key().latin1() << ")"<<std::endl;
+// it->second.dump_tree(1);
+ }
+}
+
+template<class C> inline bool itemCache<C>::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: "<<what << endl;
+ citer it=m_contentMap.find(what[0]);
+ if (it==m_contentMap.end()) {
+ //kdDebug()<<"Entry in cache not found"<<endl;
+ return false;
+ }
+ if (what.count()==1) {
+ if (it->second.isValid()) {
+ st=it->second.content();
+ return true;
+ }
+ return false;
+ }
+ //kdDebug()<<"Stage down"<<endl;
+ what.erase(what.begin());
+ return it->second.findSingleValid(what,st);
+}
+
+template<class C> inline bool itemCache<C>::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<class C> template<class T> inline void itemCache<C>::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<svn::StatusPtr> ptrEntry;
+typedef itemCache<svn::StatusPtr> statusCache;
+
+class ValidRemoteOnly
+{
+ svn::StatusEntries m_List;
+public:
+ ValidRemoteOnly():m_List(){}
+ void operator()(const std::pair<QString,helpers::ptrEntry>&_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