patch.h

Go to the documentation of this file.
00001 #ifndef TAGCOLL_PATCHES_H
00002 #define TAGCOLL_PATCHES_H
00003 
00008 /*
00009  * Copyright (C) 2003,2004,2005,2006  Enrico Zini <enrico@debian.org>
00010  *
00011  * This library is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU Lesser General Public
00013  * License as published by the Free Software Foundation; either
00014  * version 2.1 of the License, or (at your option) any later version.
00015  *
00016  * This library is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with this library; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00024  */
00025 
00026 #include <wibble/operators.h>
00027 #include <wibble/mixin.h>
00028 #include <map>
00029 #include <string>
00030 
00031 namespace tagcoll
00032 {
00033 
00037 template <typename ITEM, typename TAG>
00038 struct Patch
00039 {
00040     ITEM item;
00041     std::set<TAG> added;
00042     std::set<TAG> removed;
00043 
00044     Patch(const Patch<ITEM, TAG>& p) : item(p.item), added(p.added), removed(p.removed) {}
00045     Patch(const ITEM& item) : item(item) {}
00046     Patch(const ITEM& item, const std::set<TAG>& added, const std::set<TAG>& removed);
00047     template<typename CONTA, typename CONTB>
00048     Patch(const ITEM& item, const CONTA& added, const CONTB& removed);
00049     ~Patch() {}
00050 
00051     void add(const TAG& tag)
00052     {
00053         using namespace wibble::operators;
00054         added |= tag; removed -= tag;
00055     }
00056     void add(const std::set<TAG>& tags)
00057     {
00058         using namespace wibble::operators;
00059         added |= tags; removed -= tags;
00060     }
00061     void remove(const TAG& tag)
00062     {
00063         using namespace wibble::operators;
00064         removed |= tag; added -= tag;
00065     }
00066     void remove(const std::set<TAG>& tags)
00067     {
00068         using namespace wibble::operators;
00069         removed |= tags; added -= tags;
00070     }
00071 
00072     Patch<ITEM, TAG> getReverse() const
00073     {
00074         return Patch<ITEM, TAG>(item, removed, added);
00075     }
00076 
00077     void mergeWith(const Patch<ITEM, TAG>& patch)
00078     {
00079         add(patch.added);
00080         remove(patch.removed);
00081     }
00082 
00083     std::set<TAG> apply(const std::set<TAG>& ts) const
00084     {
00085         using namespace wibble::operators;
00086         return (ts | added) - removed;
00087     }
00088 
00089     template<typename TAGS>
00090     std::set<TAG> apply(const TAGS& tags) const
00091     {
00092         using namespace wibble::operators;
00093         std::set<TAG> ts;
00094         for (typename TAGS::const_iterator i = tags.begin();
00095                 i != tags.end(); ++i)
00096             ts.insert(*i);
00097         return (ts | added) - removed;
00098     }
00099 
00100     void removeRedundant(const std::set<TAG> ts)
00101     {
00102         using namespace wibble::operators;
00103         // Don't add what already exists
00104         added -= ts;
00105         // Don't remove what does not exist
00106         removed -= (removed - ts);
00107     }
00108 
00109     bool operator==(const Patch<ITEM, TAG>& p) const
00110     {
00111         return p.item == item && p.added == added && p.removed == removed;
00112     }
00113     bool operator!=(const Patch<ITEM, TAG>& p) const
00114     {
00115         return p.item != item || p.added != added || p.removed != removed;
00116     }
00117 };
00118 
00122 template <class ITEM, class TAG>
00123 class PatchList : public std::map<ITEM, Patch<ITEM, TAG> >
00124 {
00125 public:
00126     PatchList() {}
00127     PatchList(const PatchList& pl) : std::map<ITEM, Patch<ITEM, TAG> >(pl) {}
00128 
00129     typedef typename std::map<ITEM, Patch<ITEM, TAG> >::const_iterator const_iterator;
00130     typedef typename std::map<ITEM, Patch<ITEM, TAG> >::iterator iterator;
00131 
00135     template<typename COLL1, typename COLL2>
00136     void addPatch(const COLL1& im1, const COLL2& im2);
00137 
00141     void addPatch(const Patch<ITEM, TAG>& patch);
00142 
00146     void addPatch(const PatchList<ITEM, TAG>& patches);
00147 
00152     void addPatchInverted(const Patch<TAG, ITEM>& patch);
00153 
00158     void addPatchInverted(const PatchList<TAG, ITEM>& patches);
00159 
00164     void removeRedundant(const ITEM& item, const std::set<TAG>& tags);
00165 
00172     std::set<TAG> patch(const ITEM& item, const std::set<TAG>& tagset) const;
00173 
00174     // Output the patch list to a TagcollConsumer
00175     template<typename OUT>
00176     void output(OUT out) const;
00177 
00178     PatchList<ITEM, TAG> getReverse() const;
00179 };
00180 
00181 template<typename ITEM, typename TAG>
00182 class Inserter : public wibble::mixin::OutputIterator< Inserter<ITEM, TAG> >
00183 {
00184     PatchList<ITEM, TAG>& patches;
00185 public:
00186     Inserter(PatchList<ITEM, TAG>& patches) : patches(patches) {}
00187 
00188     Inserter<ITEM, TAG>& operator=(const Patch<ITEM, TAG>& patch)
00189     {
00190         patches.addPatch(patch);
00191         return *this;
00192     }
00193 };
00194 
00195 template<typename ITEM, typename TAG>
00196 Inserter<ITEM, TAG> inserter(PatchList<ITEM, TAG>& patches)
00197 {
00198     return Inserter<ITEM, TAG>(patches);
00199 }
00200 
00201 }
00202 
00203 // vim:set ts=4 sw=4:
00204 #endif

Generated on Fri Feb 8 10:50:41 2008 for libtagcoll by  doxygen 1.5.4