00001 #ifndef TAGCOLL_PATCHES_H
00002 #define TAGCOLL_PATCHES_H
00003
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00104 added -= ts;
00105
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
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
00204 #endif