diff options
-rw-r--r-- | ept/CMakeLists.txt | 4 | ||||
-rw-r--r-- | ept/debtags/coll/TextFormat.cc | 87 | ||||
-rw-r--r-- | ept/debtags/coll/TextFormat.h | 53 | ||||
-rw-r--r-- | ept/debtags/coll/TextFormat.tcc | 176 | ||||
-rw-r--r-- | ept/debtags/coll/base.h | 333 | ||||
-rw-r--r-- | ept/debtags/coll/base.tcc | 191 | ||||
-rw-r--r-- | ept/debtags/coll/fast.cc | 254 | ||||
-rw-r--r-- | ept/debtags/coll/fast.h | 101 | ||||
-rw-r--r-- | ept/debtags/coll/fast.tcc | 326 | ||||
-rw-r--r-- | ept/debtags/coll/set.h | 7 | ||||
-rw-r--r-- | ept/debtags/debtags-test.cc | 1 | ||||
-rw-r--r-- | ept/debtags/debtags.cc | 18 | ||||
-rw-r--r-- | ept/debtags/debtags.h | 14 | ||||
-rw-r--r-- | ept/debtags/vocabulary-test.cc | 2 |
14 files changed, 402 insertions, 1165 deletions
diff --git a/ept/CMakeLists.txt b/ept/CMakeLists.txt index 3d2dadd..f5874bf 100644 --- a/ept/CMakeLists.txt +++ b/ept/CMakeLists.txt @@ -8,8 +8,8 @@ list(REMOVE_ITEM src ${tests}) # Find headers file( GLOB h_top *.h ) file( GLOB h_apt apt/*.h ) -file( GLOB h_debtags debtags/*.h debtags/*.tcc ) -file( GLOB h_debtags_maint debtags/maint/*.h debtags/maint/*.tcc ) +file( GLOB h_debtags debtags/*.h ) +file( GLOB h_debtags_maint debtags/maint/*.h ) file( GLOB h_axi axi/*.h ) file( GLOB h_utils utils/*.h ) diff --git a/ept/debtags/coll/TextFormat.cc b/ept/debtags/coll/TextFormat.cc index dac5696..98c94f8 100644 --- a/ept/debtags/coll/TextFormat.cc +++ b/ept/debtags/coll/TextFormat.cc @@ -19,13 +19,20 @@ */ #include "TextFormat.h" +#include "fast.h" +#include <wibble/exception.h> +#include <wibble/operators.h> #include <stdexcept> #include <system_error> +#include <set> using namespace std; using namespace wibble; +using namespace wibble::operators; -namespace tagcoll { +namespace ept { +namespace debtags { +namespace coll { namespace textformat { // Parse an element @@ -156,7 +163,83 @@ int parseElement(FILE* in, const std::string& pathname, string& item) return EOF; } +static void printTagset(const std::set<string>& ts, FILE* out) +{ + for (std::set<string>::const_iterator i = ts.begin(); + i != ts.end(); i++) + if (i == ts.begin()) + { + if (fprintf(out, "%s", i->c_str()) < 0) + throw wibble::exception::System("writing tagset"); + } + else + { + if (fprintf(out, ", %s", i->c_str()) < 0) + throw wibble::exception::System("writing tagset"); + } +} + +inline static void outString(const std::string& str, FILE* out, const char* what) +{ + if (fwrite(str.data(), str.size(), 1, out) != 1) + throw wibble::exception::System(string("writing ") + what); } + + +// item1, item2, item3: tag1, tag2, tag3 + +//#define TRACE_PARSE +void parse(FILE* in, const std::string& pathname, Fast& out) +{ + string item; + + std::set<string> itemset; + std::set<string> tagset; + int sep; + enum {ITEMS, TAGS} state = ITEMS; + int line = 1; + do + { + sep = parseElement(in, pathname, item); + + if (item.size() != 0) + { + if (state == ITEMS) + itemset |= item; + else + tagset |= item; + } + + switch (sep) + { + case '\n': + line++; + case EOF: + if (!(itemset.empty() && tagset.empty())) + { + if (itemset.empty()) + throw std::runtime_error("no elements before ':' separator"); + if (tagset.empty()) + out.insert(itemset, std::set<std::string>()); + else + out.insert(itemset, tagset); + } + itemset.clear(); + tagset.clear(); + state = ITEMS; + break; + case ':': + if (state == TAGS) + throw std::runtime_error("separator ':' appears twice"); + state = TAGS; + break; + default: + break; + } + } while (sep != EOF); } -#include "TextFormat.tcc" +} +} +} +} diff --git a/ept/debtags/coll/TextFormat.h b/ept/debtags/coll/TextFormat.h index 8b4c179..a35f664 100644 --- a/ept/debtags/coll/TextFormat.h +++ b/ept/debtags/coll/TextFormat.h @@ -26,53 +26,16 @@ #include <wibble/mixin.h> #include <wibble/empty.h> #include <wibble/singleton.h> -//#include <tagcoll/input/base.h> #include <cstdio> //#define TRACE_PARSE -namespace tagcoll -{ +namespace ept { +namespace debtags { +namespace coll { +struct Fast; -namespace textformat -{ - -/** - * TagcollConsumer that serializes its input to an output stream - * - * The format of the output is: - * lines of "comma+space"-separated items, followed by "colon+space", - * followed by the corresponding "comma+space"-separated tags. - * Examples: - * ITEM: - * ITEM: TAG - * ITEM: TAG1, TAG2, TAG3 - * ITEM1, ITEM2, ITEM3: - * ITEM1, ITEM2, ITEM3: TAG1, TAG2, TAG3 - */ -class StdioWriter : public wibble::mixin::OutputIterator<StdioWriter> -{ -protected: - FILE* out; - -public: - StdioWriter(FILE* out) : out(out) {} - - template<typename Items, typename Tags> - StdioWriter& operator=(const std::pair<Items, Tags>& data); -}; - -class OstreamWriter : public wibble::mixin::OutputIterator<OstreamWriter> -{ -protected: - std::ostream& out; - -public: - OstreamWriter(std::ostream& out) : out(out) {} - - template<typename Items, typename Tags> - OstreamWriter& operator=(const std::pair<Items, Tags>& data); -}; +namespace textformat { /** * Parse an element from input @@ -95,11 +58,11 @@ int parseElement(FILE* in, const std::string& pathname, std::string& item); * @param out * An output iterator accepting a std::pair<string, string> */ -template<typename OUT> -void parse(FILE* in, const std::string& pathname, OUT out); +void parse(FILE* in, const std::string& pathname, Fast& out); } } +} +} -// vim:set ts=4 sw=4: #endif diff --git a/ept/debtags/coll/TextFormat.tcc b/ept/debtags/coll/TextFormat.tcc deleted file mode 100644 index 2a153c9..0000000 --- a/ept/debtags/coll/TextFormat.tcc +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Serialize a tagged collection to a text file - * - * Copyright (C) 2003--2015 Enrico Zini <enrico@debian.org> - * - * This library 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 2.1 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TAGCOLL_TEXTFORMAT_TCC -#define TAGCOLL_TEXTFORMAT_TCC - -#include <ept/debtags/coll/TextFormat.h> -//#include <tagcoll/patch.h> - -#include <wibble/exception.h> -#include <wibble/empty.h> -#include <wibble/operators.h> - -#include <ostream> - -using namespace std; -using namespace wibble; -using namespace wibble::operators; - -static void printTagset(const std::set<string>& ts, FILE* out) -{ - for (std::set<string>::const_iterator i = ts.begin(); - i != ts.end(); i++) - if (i == ts.begin()) - { - if (fprintf(out, "%s", i->c_str()) < 0) - throw wibble::exception::System("writing tagset"); - } - else - { - if (fprintf(out, ", %s", i->c_str()) < 0) - throw wibble::exception::System("writing tagset"); - } -} - -namespace tagcoll { -namespace textformat { - -inline static void outString(const std::string& str, FILE* out, const char* what) -{ - if (fwrite(str.data(), str.size(), 1, out) != 1) - throw wibble::exception::System(string("writing ") + what); -} - -template<typename Items, typename Tags> -StdioWriter& StdioWriter::operator=(const std::pair<Items, Tags>& data) -{ - for (typename Items::const_iterator i = data.first.begin(); - i != data.first.end(); ++i) - { - if (i != data.first.begin()) - if (fputs(", ", out) == EOF) - throw wibble::exception::System("writing comma after item"); - outString(*i, out, "item"); - } - if (data.second.begin() != data.second.end()) - { - if (fputs(": ", out) == EOF) - throw wibble::exception::System("writing colon after items"); - for (typename Tags::const_iterator i = data.second.begin(); - i != data.second.end(); ++i) - { - if (i != data.second.begin()) - if (fputs(", ", out) == EOF) - throw wibble::exception::System("writing comma after tag"); - outString(*i, out, "tag"); - } - } - if (fputc('\n', out) == EOF) - throw wibble::exception::System("writing newline after tagset"); - return *this; -} - -template<typename Items, typename Tags> -OstreamWriter& OstreamWriter::operator=(const std::pair<Items, Tags>& data) -{ - for (typename Items::const_iterator i = data.first.begin(); - i != data.first.end(); ++i) - { - if (i != data.first.begin()) - out << ", "; - out << *i; - } - if (data.second.begin() != data.second.end()) - { - out << ": "; - for (typename Tags::const_iterator i = data.second.begin(); - i != data.second.end(); ++i) - { - if (i != data.second.begin()) - out << ", "; - out << *i; - } - } - out << endl; - return *this; -} - - - -// item1, item2, item3: tag1, tag2, tag3 - -//#define TRACE_PARSE -template<typename OUT> -void parse(FILE* in, const std::string& pathname, OUT out) -{ - string item; - - std::set<string> itemset; - std::set<string> tagset; - int sep; - enum {ITEMS, TAGS} state = ITEMS; - int line = 1; - do - { - sep = parseElement(in, pathname, item); - - if (item.size() != 0) - { - if (state == ITEMS) - itemset |= item; - else - tagset |= item; - } - - switch (sep) - { - case '\n': - line++; - case EOF: - if (!(itemset.empty() && tagset.empty())) - { - if (itemset.empty()) - throw std::runtime_error("no elements before ':' separator"); - if (tagset.empty()) - *out = make_pair(itemset, wibble::Empty<std::string>()); - else - *out = make_pair(itemset, tagset); - ++out; - } - itemset.clear(); - tagset.clear(); - state = ITEMS; - break; - case ':': - if (state == TAGS) - throw std::runtime_error("separator ':' appears twice"); - state = TAGS; - break; - default: - break; - } - } while (sep != EOF); -} - -} -} - -#endif diff --git a/ept/debtags/coll/base.h b/ept/debtags/coll/base.h deleted file mode 100644 index 02e59af..0000000 --- a/ept/debtags/coll/base.h +++ /dev/null @@ -1,333 +0,0 @@ -#ifndef TAGCOLL_COLL_BASE_H -#define TAGCOLL_COLL_BASE_H - -/** \file - * Base mixins for tagged collections - */ - -/* - * Copyright (C) 2003,2004,2005,2006 Enrico Zini <enrico@debian.org> - * - * This library 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 2.1 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <wibble/mixin.h> -#include <vector> - -namespace std { -template<typename A, typename B> class pair; -} - -namespace tagcoll { -namespace coll { - -template<typename T> -class coll_traits; - -/** - * Interface for all collections of tagged items. - * - * \note The point of a collection is to track the tags attached to items, and - * not to store the items themselves. This means that collections are not - * required to keep track of items with no tags. - */ -template<typename Self> -class ReadonlyCollection -{ - const Self& self() const { return *static_cast<const Self*>(this); } - - class CardinalityOrder - { - const Self& coll; - public: - CardinalityOrder(const Self& coll) : coll(coll) {} - bool operator()(const typename coll_traits<Self>::tag_type& t1, const typename coll_traits<Self>::tag_type& t2) - { - // Returns true if t1 precedes t2, and false otherwise - return coll.getCardinality(t1) < coll.getCardinality(t2); - } - }; - - class DiscriminanceOrder - { - const Self& coll; - public: - DiscriminanceOrder(const Self& coll) : coll(coll) {} - bool operator()(const typename coll_traits<Self>::tag_type& t1, const typename coll_traits<Self>::tag_type& t2) - { - // Returns true if t1 precedes t2, and false otherwise - return coll.getDiscriminance(t1) < coll.getDiscriminance(t2); - } - }; - - template<typename COLL> - class RelevanceOrder - { - const COLL& first; - const Self& second; - public: - RelevanceOrder(const COLL& first, const Self& second) - : first(first), second(second) {} - bool operator()(const typename coll_traits<Self>::tag_type& t1, const typename coll_traits<Self>::tag_type& t2); - }; - - /** - * Get the items which are tagged with at least the tag `tag' - * - * \return - * The items found, or an empty set if no items have that tag - */ - //virtual std::set<ITEM> getItemsHavingTag(const TAG& tag) const = 0; - - /** - * Get the tags attached to an item. - * - * \param item - * The item to query - * \return - * The set of tags, or an empty set if the item has no tags or it does - * not exist. - */ - //virtual std::set<TAG> getTagsOfItem(const ITEM& item) const = 0; - -public: - /** - * Check if the collection contains a tag - * - * \param tag - * The tag to look for - * \return - * true if the collection contains tag, false otherwise - */ - bool hasTag(const typename coll_traits<Self>::tag_type& tag) const; - - /** - * Get the tags of item `item'. Return an empty set if `item' does not exist - */ - //std::set<Self::tag_type> getTags(const typename Self::item_type& item) const = 0; - - /** - * Get all the tags attached to the items in a set. - * - * \param items - * The items to query - * \return - * The set of tags, or an empty set if the items have no tags or do not - * exist. - */ - template<typename ITEMS> - typename coll_traits<Self>::tagset_type getTagsOfItems(const ITEMS& items) const; - - /** - * Get the items with tag `tag'. Return an empty set if `tag' does not exist - */ - //std::set<typename Self::item_type> getItems(const TAG& tag) const { return getItemsHavingTag(tag); } - - /** - * Get the items which are tagged with at least the tags `tags' - * - * \return - * The items found, or an empty set if no items have that tag - */ - template<typename TAGS> - typename coll_traits<Self>::itemset_type getItemsHavingTags(const TAGS& tags) const; - - /** - * Get the set of all the items that have tags according to this collection - */ - //virtual std::set<Self::item_type> getTaggedItems() const = 0; - - /** - * Get the set of all the tags in this collection - */ - //virtual std::set<Self::tag_type> getAllTags() const = 0; - - /** - * Get all the tags in the collectin, as a vector - */ - std::vector<typename coll_traits<Self>::tag_type> getAllTagsAsVector() const; - - /** - * Get the cardinality of tag `tag' (that is, the number of items who have it) - */ - unsigned int getCardinality(const typename coll_traits<Self>::tag_type& tag) const; - - /** - * Return the discriminance value for this tag, that is, the minimum number - * of packages that would be eliminated by selecting only those tagged with - * this tag or only those not tagged with this tag. - */ - unsigned int getDiscriminance(const typename coll_traits<Self>::tag_type& tag) const - { - return self().getCardinality(tag) < self().tagCount() - self().getCardinality(tag) ? - self().getCardinality(tag) : - self().tagCount() - self().getCardinality(tag); - } - - /** - * Get the set of all tags in this collection that appear in tagsets - * containing `tags' - * - * Example: - * \code - * void refineSelection(const std::set<Tag>& selection) - * { - * std::set<Tag> extraTags = collection.getCompanionTags(selection); - * tagMenu.setAvailableOptions(extraTags); - * } - * \endcode - */ - template<typename TAGS> - typename coll_traits<Self>::tagset_type getCompanionTags(const TAGS& tags) const; - - /** - * Get the related items at the given maximum distance - * - * Examples: - * \code - * // Get the items related to a given one, at the given distance - * std::set<Item> getRelated(const Item& item, int distance) - * { - * std::set<Item> res = collection.getRelatedItems(collection.getTags(item), distance); - * return res - item; - * } - * - * // Get the items related to the given ones, at the given distance - * std::set<Item> getRelated(const std::set<Item>& items, int distance) - * { - * std::set<Item> res = collection.getRelatedItems(collection.getTags(items), distance); - * return res - items; - * } - * - * // Get the related items, increasing the distance until it finds at - * // least 'minimum' items - * std::set<Item> getRelated(const Item& item, int minimum) - * { - * std::set<Tag> tags = collection.getTags(item); - * std::set<Item> res; - * for (int i = 0; i < tags.size() && res.size() < minimum; i++) - * res += collection.getRelatedItems(tags, i); - * return res - item; - * } - * \endcode - */ - template<typename TAGS> - typename coll_traits<Self>::itemset_type getRelatedItems(const TAGS& tags, int maxdistance = 1) const; - - /** - * Output all the contents of the collection to an output iterator - */ - template<typename OUT> - void output(OUT out) const; - - /** - * Send to a consumer all the items which are tagged with at least the - * given tags - */ - template<typename TAGS, typename OUT> - void outputHavingTags(const TAGS& tags, OUT out) const; - - /** - * Get a vector containing all tags in this collection, sorted by - * increasing cardinality - */ - std::vector<typename coll_traits<Self>::tag_type> tagsInCardinalityOrder() const; - - /** - * Get a vector containing all tags in this collection, sorted by - * increasing discriminance value (@see getDiscriminance) - */ - std::vector<typename coll_traits<Self>::tag_type> tagsInDiscriminanceOrder() const; - - /** - * Get a vector containing all tags in this collection, sorted by - * increasing relevance to the filtering applied between coll and this - * collection - */ - template<typename COLL> - std::vector<typename coll_traits<Self>::tag_type> tagsInRelevanceOrder(const COLL& coll) const; -}; - - -/** - * Interface for all collections of tagged items. - * - * \note The point of a collection is to track the tags attached to items, and - * not to store the items themselves. This means that collections are not - * required to keep track of items with no tags. - */ -template<typename Self> -class Collection : public ReadonlyCollection<Self> -{ -//protected: - /* - * Implementation note: to avoid problems with classes implementing only - * some of the virtual methods, they are given different names. The common - * 'comsume' methods are just inlined calls to the right virtual functions, - * and are a way of keeping the unoverridden methods from being hidden. - */ - - //void consumeItemUntagged(const ITEM&) {} - //void consumeItemsUntagged(const std::set<ITEM>&) {} - -public: - //virtual ~Collection() {} - - /** - * Apply a patch to the collection - * - * Example: - * \code - * void perform(const PatchList<ITEM, TAG>& change) - * { - * collection.applyChange(change); - * undo.push_back(change.getReverse()); - * } - * \endcode - */ -// void applyChange( -// const PatchList< -// typename coll_traits<Self>::item_type, -// typename coll_traits<Self>::tag_type>& change); -}; - - -template<typename COLL> -class Inserter : public wibble::mixin::OutputIterator< Inserter<COLL> > -{ - COLL& coll; - -public: - Inserter(COLL& coll) : coll(coll) {} - - template<typename Items, typename Tags> - Inserter<COLL>& operator=(const std::pair<Items, Tags>& data) - { - coll.insert(data.first, data.second); - return *this; - } -}; - -template<typename COLL> -Inserter<COLL> inserter(COLL& target) -{ - return Inserter<COLL>(target); -} - -} -} - -// vim:set ts=4 sw=4: -#endif diff --git a/ept/debtags/coll/base.tcc b/ept/debtags/coll/base.tcc deleted file mode 100644 index 546a513..0000000 --- a/ept/debtags/coll/base.tcc +++ /dev/null @@ -1,191 +0,0 @@ -#ifndef TAGCOLL_COLL_BASE_TCC -#define TAGCOLL_COLL_BASE_TCC - -/** \file - * Base mixins for tagged collections - */ - -/* - * Copyright (C) 2003,2004,2005,2006 Enrico Zini <enrico@debian.org> - * - * This library 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 2.1 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <ept/debtags/coll/base.h> -#include <ept/debtags/coll/set.h> -#include <algorithm> - -namespace tagcoll { -namespace coll { - -template<typename T> -class coll_traits; - -template<typename Self> template<typename COLL> -bool ReadonlyCollection<Self>::RelevanceOrder<COLL>::operator()( - const typename coll_traits<Self>::tag_type& t1, - const typename coll_traits<Self>::tag_type& t2) -{ - // New cardinality divided by the square root of the old cardinality. - // The square root is used to downplay the very common tags a bit - int csub1 = second.getCardinality(t1); - float cfull1 = first.getCardinality(t1); - int csub2 = second.getCardinality(t2); - float cfull2 = first.getCardinality(t2); - float rel1 = (float)(csub1 * csub1) / cfull1; - float rel2 = (float)(csub2 * csub2) / cfull2; - - return rel1 < rel2; -// return 10000 * second.getCardinality(t1) / first.getCardinality(t1) -// < 10000 * second.getCardinality(t2) / first.getCardinality(t2); -} - - -template<typename Self> -bool ReadonlyCollection<Self>::hasTag(const typename coll_traits<Self>::tag_type& tag) const -{ - return !self().getItemsHavingTag(tag).empty(); -} - -template<typename Self> template<typename ITEMS> -typename coll_traits<Self>::tagset_type ReadonlyCollection<Self>::getTagsOfItems(const ITEMS& items) const -{ - using namespace wibble::operators; - typename coll_traits<Self>::tagset_type res; - for (typename ITEMS::const_iterator i = items.begin(); - i != items.end(); i++) - res |= self().getTagsOfItem(*i); - return res; -} - -template<typename Self> template<typename TAGS> -typename coll_traits<Self>::itemset_type ReadonlyCollection<Self>::getItemsHavingTags(const TAGS& tags) const -{ - using namespace wibble::operators; - if (tags.empty()) - return typename coll_traits<Self>::itemset_type(); - - typename TAGS::const_iterator i = tags.begin(); - typename coll_traits<Self>::itemset_type res = self().getItemsHavingTag(*i); - - for (++i ; i != tags.end(); ++i) - res &= self().getItemsHavingTag(*i); - - return res; -} - -template<typename Self> -std::vector<typename coll_traits<Self>::tag_type> ReadonlyCollection<Self>::getAllTagsAsVector() const -{ - std::set<typename coll_traits<Self>::tag_type> asSet = self().getAllTags(); - std::vector<typename coll_traits<Self>::tag_type> res; - res.reserve(asSet.size()); - std::copy(asSet.begin(), asSet.end(), back_inserter(res)); - return res; -} - -template<typename Self> -unsigned int ReadonlyCollection<Self>::getCardinality(const typename coll_traits<Self>::tag_type& tag) const -{ - return self().getItemsHavingTag(tag).size(); -} - -template<typename Self> template<typename TAGS> -typename coll_traits<Self>::tagset_type ReadonlyCollection<Self>::getCompanionTags(const TAGS& tags) const -{ - using namespace wibble::operators; - return self().getTagsOfItems(self().getItemsHavingTags(tags)) - tags; -} - -template<typename Self> template<typename TAGS> -typename coll_traits<Self>::itemset_type ReadonlyCollection<Self>::getRelatedItems(const TAGS& tags, int maxdistance) const -{ - using namespace wibble::operators; - - typename coll_traits<Self>::itemset_type packages; - typename coll_traits<Self>::itemset_type res; - - // First get a list of packages that have a non-empty intersection with `tags' - for (typename TAGS::const_iterator i = tags.begin(); i != tags.end(); i++) - packages |= self().getItemsHavingTag(*i); - - // Then keep only those within the given distance - for (typename coll_traits<Self>::itemset_type::const_iterator i = packages.begin(); i != packages.end(); i++) - { - int dist = utils::set_distance(tags, self().getTagsOfItem(*i)); - if (dist >= 0 && dist <= maxdistance) - res |= *i; - } - - return res; -} - -template<typename Self> template<typename OUT> -void ReadonlyCollection<Self>::output(OUT out) const -{ - for (typename Self::const_iterator i = self().begin(); - i != self().end(); ++i) - { - *out = make_pair(wibble::singleton(i->first), i->second); - ++out; - } -} - -template<typename Self> template<typename TAGS, typename OUT> -void ReadonlyCollection<Self>::outputHavingTags(const TAGS& tags, OUT out) const -{ - typename coll_traits<Self>::itemset_type items = self().getItemsHavingTags(tags); - for (typename coll_traits<Self>::itemset_type::const_iterator i = items.begin(); - i != items.end(); ++i) - { - *out = std::make_pair(wibble::singleton(*i), self().getTagsOfItem(*i)); - ++out; - } -} - -template<typename Self> -std::vector<typename coll_traits<Self>::tag_type> ReadonlyCollection<Self>::tagsInCardinalityOrder() const -{ - std::vector<typename coll_traits<Self>::tag_type> res = self().getAllTagsAsVector(); - std::sort(res.begin(), res.end(), CardinalityOrder(self())); - return res; -} - -template<typename Self> -std::vector<typename coll_traits<Self>::tag_type> ReadonlyCollection<Self>::tagsInDiscriminanceOrder() const -{ - std::vector<typename coll_traits<Self>::tag_type> res = self().getAllTagsAsVector(); - std::sort(res.begin(), res.end(), DiscriminanceOrder(self())); - return res; -} - -/** - * Get a vector containing all tags in this collection, sorted by - * increasing relevance to the filtering applied between coll and this - * collection - */ -template<typename Self> template<typename COLL> -std::vector<typename coll_traits<Self>::tag_type> ReadonlyCollection<Self>::tagsInRelevanceOrder(const COLL& coll) const -{ - std::vector<typename coll_traits<Self>::tag_type> res = self().getAllTagsAsVector(); - std::sort(res.begin(), res.end(), RelevanceOrder<COLL>(coll, self())); - return res; -} - -} -} - -// vim:set ts=4 sw=4: -#endif diff --git a/ept/debtags/coll/fast.cc b/ept/debtags/coll/fast.cc new file mode 100644 index 0000000..9032bf6 --- /dev/null +++ b/ept/debtags/coll/fast.cc @@ -0,0 +1,254 @@ +/* + * Fast index for tag data + * + * Copyright (C) 2005,2006 Enrico Zini <enrico@debian.org> + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <ept/debtags/coll/fast.h> +#include <ept/debtags/coll/set.h> +#include <wibble/operators.h> + +using namespace std; +using namespace wibble::operators; + +namespace ept { +namespace debtags { +namespace coll { + +void Fast::insert(const std::set<std::string>& items, const std::set<std::string>& tags) +{ + using namespace wibble::operators; + + if (tags.empty()) + return; + + for (const auto& i: items) + insert(i, tags); +} + +void Fast::insert(const std::string& item, const std::set<std::string>& tags) +{ + using namespace wibble::operators; + + if (tags.empty()) + return; + + auto iter = this->items.find(item); + if (iter == this->items.end()) + this->items.insert(std::make_pair(item, tags)); + else + iter->second |= tags; + + for (typename std::set<std::string>::const_iterator i = tags.begin(); + i != tags.end(); ++i) + { + typename std::map< std::string, std::set<std::string> >::iterator iter = this->tags.find(*i); + if (iter == this->tags.end()) + this->tags.insert(std::make_pair(*i, std::set<std::string>() | item)); + else + iter->second |= item; + } +} + +void Fast::insert(const std::set<std::string>& items, const std::string& tag) +{ + using namespace wibble::operators; + + for (typename std::set<std::string>::const_iterator i = items.begin(); + i != items.end(); ++i) + { + typename std::map< std::string, std::set<std::string> >::iterator iter = this->items.find(*i); + if (iter == this->items.end()) + this->items.insert(std::make_pair(*i, std::set<std::string>() | tag)); + else + iter->second |= tag; + } + + typename std::map< std::string, std::set<std::string> >::iterator iter = this->tags.find(tag); + if (iter == this->tags.end()) + this->tags.insert(std::make_pair(tag, items)); + else + iter->second |= items; +} + +std::set<std::string> Fast::getItemsHavingTag(const std::string& tag) const +{ + typename map<std::string, std::set<std::string> >::const_iterator i = tags.find(tag); + if (i != tags.end()) + return i->second; + else + return std::set<std::string>(); +} + +std::set<std::string> Fast::getItemsHavingTags(const std::set<std::string>& tags) const +{ + using namespace wibble::operators; + if (tags.empty()) + return std::set<std::string>(); + + auto i = tags.begin(); + auto res = getItemsHavingTag(*i); + + for (++i ; i != tags.end(); ++i) + res &= getItemsHavingTag(*i); + + return res; +} + + +std::set<std::string> Fast::getTagsOfItem(const std::string& item) const +{ + typename map<std::string, std::set<std::string> >::const_iterator i = items.find(item); + if (i != items.end()) + return i->second; + else + return std::set<std::string>(); +} + +std::set<std::string> Fast::getTaggedItems() const +{ + std::set<std::string> res; + for (typename map<std::string, std::set<std::string> >::const_iterator i = items.begin(); + i != items.end(); i++) + res |= i->first; + return res; +} + +std::set<std::string> Fast::getAllTags() const +{ + std::set<std::string> res; + for (typename map<std::string, std::set<std::string> >::const_iterator i = tags.begin(); + i != tags.end(); i++) + res |= i->first; + return res; +} + +std::vector<std::string> Fast::getAllTagsAsVector() const +{ + std::vector<std::string> res; + for (typename map<std::string, std::set<std::string> >::const_iterator i = tags.begin(); + i != tags.end(); i++) + res.push_back(i->first); + return res; +} + +std::set<std::string> Fast::getTagsImplying(const std::string& tag) const +{ + // tag1 implies tag2 if the itemset of tag1 is a subset of the itemset of tag2 + std::set<std::string> res; + std::set<std::string> itemsToCheck = getItemsHavingTag(tag); + // TODO: choose which one is the most efficient implementation +#if 0 + // Roughly: + // O(n[pkgs per tag] * log(nitems) * log(n[items per pkg]) + n[tags per item] * n[items per tag]) + std::set<std::string> tagsToCheck; + for (std::set<std::string>::const_iterator i = itemsToCheck.begin(); + i != itemsToCheck.end(); ++i) + tagsToCheck |= getTags(*i); + for (std::set<std::string>::const_iterator i = tagsToCheck.begin(); + i != tagsToCheck.end(); ++i) + if (utils::set_contains(itemsToCheck, getItems(*i))) + res |= *i; +#else + // O(ntags * n[items per tag]) + for (typename std::map<std::string, std::set<std::string> >::const_iterator i = tags.begin(); + i != tags.end(); ++i) + if (utils::set_contains(itemsToCheck, getItemsHavingTag(i->first))) + res |= i->first; +#endif + return res - tag; +} + +std::set<std::string> Fast::getItemsExactMatch(const std::set<std::string>& tags) const +{ + std::set<std::string> res = this->getItemsHavingTags(tags); + typename std::set<std::string>::iterator i = res.begin(); + while (i != res.end()) + { + typename std::map<std::string, std::set<std::string> >::const_iterator t = items.find(*i); + if (t != items.end() && t->second != tags) + { + typename std::set<std::string>::iterator j = i; + ++i; + res.erase(j); + } else + ++i; + } + return res; +} + +std::string Fast::findTagWithMaxCardinality(size_t& card) const +{ + card = 0; + std::string res = std::string(); + for (typename std::map<std::string, std::set<std::string> >::const_iterator i = tags.begin(); + i != tags.end(); ++i) + if (i->second.size() > card) + { + card = i->second.size(); + res = i->first; + } + return res; +} + +void Fast::removeTag(const std::string& tag) +{ + typename std::map<std::string, std::set<std::string> >::iterator itag = tags.find(tag); + for (typename std::set<std::string>::const_iterator iitemset = itag->second.begin(); + iitemset != itag->second.end(); ++iitemset) + { + typename std::map<std::string, std::set<std::string> >::iterator iitem = items.find(*iitemset); + iitem->second -= tag; + if (iitem->second.empty()) + items.erase(iitem); + } + tags.erase(itag); +} + +Fast Fast::getChildCollection(const std::string& tag) const +{ + Fast res; + + auto itag = tags.find(tag); + for (const auto& i: itag->second) + { + auto iitem = items.find(i); + res.insert(i, iitem->second); + } + + res.removeTag(tag); + return res; +} + +void Fast::removeTagsWithCardinalityLessThan(size_t card) +{ + typename std::map<std::string, std::set<std::string> >::const_iterator i = tags.begin(); + while (i != tags.end()) + { + if (i->second.size() < card) + { + typename std::map<std::string, std::set<std::string> >::const_iterator j = i; + ++i; + removeTag(j->first); + } else + ++i; + } +} + +} +} +} diff --git a/ept/debtags/coll/fast.h b/ept/debtags/coll/fast.h index 7a4c2b8..747cefc 100644 --- a/ept/debtags/coll/fast.h +++ b/ept/debtags/coll/fast.h @@ -1,5 +1,5 @@ -#ifndef TAGCOLL_COLL_FAST_H -#define TAGCOLL_COLL_FAST_H +#ifndef EPT_DEBTAGS_COLL_FAST_H +#define EPT_DEBTAGS_COLL_FAST_H /** \file * Fast index for tag data @@ -23,51 +23,38 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <wibble/singleton.h> -#include <ept/debtags/coll/base.h> #include <set> #include <map> +#include <string> +#include <vector> -namespace tagcoll { - +namespace ept { +namespace debtags { namespace coll { -template<typename ITEM, typename TAG> -class Fast; - -template<typename ITEM, typename TAG> -struct coll_traits< Fast<ITEM, TAG> > -{ - typedef ITEM item_type; - typedef TAG tag_type; - typedef std::set<ITEM> itemset_type; - typedef std::set<TAG> tagset_type; -}; /** * In-memory collection with both item->tags and tag->items mappings. */ -template<class ITEM, class TAG> -class Fast : public coll::Collection< Fast<ITEM, TAG> > +class Fast { protected: - std::map<ITEM, std::set<TAG> > items; - std::map<TAG, std::set<ITEM> > tags; + std::map<std::string, std::set<std::string>> items; + std::map<std::string, std::set<std::string>> tags; #if 0 - virtual void consumeItem(const ITEM& item, const std::set<TAG>& tags); - virtual void consumeItems(const std::set<ITEM>& items, const std::set<TAG>& tags); + virtual void consumeItem(const std::string& item, const std::set<std::string>& tags); + virtual void consumeItems(const std::set<std::string>& items, const std::set<std::string>& tags); - virtual std::set<ITEM> getItemsHavingTag(const TAG& tag) const; - virtual std::set<TAG> getTagsOfItem(const ITEM& item) const; + virtual std::set<std::string> getItemsHavingTag(const std::string& tag) const; + virtual std::set<std::string> getTagsOfItem(const std::string& item) const; #endif public: - typedef typename std::map< ITEM, std::set<TAG> >::const_iterator const_iterator; - typedef typename std::map< ITEM, std::set<TAG> >::iterator iterator; - typedef typename std::map< ITEM, std::set<TAG> >::value_type value_type; - - typedef typename std::map< TAG, std::set<ITEM> >::const_iterator const_tag_iterator; - typedef typename std::map< TAG, std::set<ITEM> >::iterator tag_iterator; + typedef std::map<std::string, std::set<std::string>>::const_iterator const_iterator; + typedef std::map<std::string, std::set<std::string>>::iterator iterator; + typedef std::map<std::string, std::set<std::string>>::value_type value_type; + typedef std::map<std::string, std::set<std::string>>::const_iterator const_tag_iterator; + typedef std::map<std::string, std::set<std::string>>::iterator tag_iterator; const_iterator begin() const { return items.begin(); } const_iterator end() const { return items.end(); } @@ -79,60 +66,58 @@ public: tag_iterator tagBegin() { return tags.begin(); } tag_iterator tagEnd() { return tags.end(); } - template<typename ITEMS, typename TAGS> - void insert(const ITEMS& items, const TAGS& tags); - - void insert(const wibble::Singleton<ITEM>& item, const std::set<TAG>& tags); - - void insert(const std::set<ITEM>& items, const wibble::Singleton<TAG>& tag); + void insert(const std::string& item, const std::set<std::string>& tags); + void insert(const std::set<std::string>& items, const std::string& tag); + void insert(const std::set<std::string>& items, const std::set<std::string>& tags); void clear() { items.clear(); tags.clear(); } - std::set<TAG> getTagsOfItem(const ITEM& item) const; - std::set<ITEM> getItemsHavingTag(const TAG& tag) const; + std::set<std::string> getTagsOfItem(const std::string& item) const; + std::set<std::string> getItemsHavingTag(const std::string& tag) const; + + /** + * Get the items which are tagged with at least the tags `tags' + * + * \return + * The items found, or an empty set if no items have that tag + */ + std::set<std::string> getItemsHavingTags(const std::set<std::string>& tags) const; bool empty() const { return items.empty(); } - bool hasItem(const ITEM& item) const { return items.find(item) != items.end(); } - bool hasTag(const TAG& tag) const { return tags.find(tag) != tags.end(); } - std::set<ITEM> getTaggedItems() const; - std::set<TAG> getAllTags() const; - std::vector<TAG> getAllTagsAsVector() const; + bool hasItem(const std::string& item) const { return items.find(item) != items.end(); } + bool hasTag(const std::string& tag) const { return tags.find(tag) != tags.end(); } + std::set<std::string> getTaggedItems() const; + std::set<std::string> getAllTags() const; + std::vector<std::string> getAllTagsAsVector() const; unsigned int itemCount() const { return items.size(); } unsigned int tagCount() const { return tags.size(); } - /** - * Output all the contents of the reversed collection to an output iterator - */ - template<typename OUT> - void outputReversed(OUT out) const; - #if 0 - void output(Consumer<ITEM, TAG>& consumer) const; + void output(Consumer<std::string, std::string>& consumer) const; #endif // tag1 implies tag2 if the itemset of tag1 is a subset of the itemset of // tag2 - std::set<TAG> getTagsImplying(const TAG& tag) const; + std::set<std::string> getTagsImplying(const std::string& tag) const; // Return the items which have the exact tagset 'tags' - std::set<ITEM> getItemsExactMatch(const std::set<TAG>& tags) const; + std::set<std::string> getItemsExactMatch(const std::set<std::string>& tags) const; - TAG findTagWithMaxCardinality(size_t& card) const; + std::string findTagWithMaxCardinality(size_t& card) const; /** * Return the collection with only those items that have this tag, but with * the given tag removed */ - Fast<ITEM, TAG> getChildCollection(const TAG& tag) const; + Fast getChildCollection(const std::string& tag) const; - void removeTag(const TAG& tag); + void removeTag(const std::string& tag); void removeTagsWithCardinalityLessThan(size_t card); }; } } - -// vim:set ts=4 sw=4: +} #endif diff --git a/ept/debtags/coll/fast.tcc b/ept/debtags/coll/fast.tcc deleted file mode 100644 index c8731c0..0000000 --- a/ept/debtags/coll/fast.tcc +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Fast index for tag data - * - * Copyright (C) 2005,2006 Enrico Zini <enrico@debian.org> - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TAGCOLL_COLL_FAST_TCC -#define TAGCOLL_COLL_FAST_TCC - -#include <ept/debtags/coll/fast.h> -#include <ept/debtags/coll/set.h> - -#include <wibble/operators.h> - -using namespace std; -using namespace wibble::operators; - -namespace tagcoll { -namespace coll { - -template<class ITEM, class TAG> template<typename ITEMS, typename TAGS> -void Fast<ITEM, TAG>::insert(const ITEMS& items, const TAGS& tags) -{ - using namespace wibble::operators; - - if (tags.empty()) - return; - - for (typename ITEMS::const_iterator i = items.begin(); - i != items.end(); ++i) - { - typename std::map< ITEM, std::set<TAG> >::iterator iter = this->items.find(*i); - if (iter == this->items.end()) - this->items.insert(std::make_pair(*i, std::set<TAG>() | tags)); - else - iter->second |= tags; - } - - for (typename TAGS::const_iterator i = tags.begin(); - i != tags.end(); ++i) - { - typename std::map< TAG, std::set<ITEM> >::iterator iter = this->tags.find(*i); - if (iter == this->tags.end()) - this->tags.insert(std::make_pair(*i, std::set<ITEM>() | items)); - else - iter->second |= items; - } -} - -template<class ITEM, class TAG> -void Fast<ITEM, TAG>::insert(const wibble::Singleton<ITEM>& item, const std::set<TAG>& tags) -{ - using namespace wibble::operators; - - if (tags.empty()) - return; - - typename std::map< ITEM, std::set<TAG> >::iterator iter = this->items.find(*item.begin()); - if (iter == this->items.end()) - this->items.insert(std::make_pair(*item.begin(), tags)); - else - iter->second |= tags; - - for (typename std::set<TAG>::const_iterator i = tags.begin(); - i != tags.end(); ++i) - { - typename std::map< TAG, std::set<ITEM> >::iterator iter = this->tags.find(*i); - if (iter == this->tags.end()) - this->tags.insert(std::make_pair(*i, std::set<ITEM>() | *item.begin())); - else - iter->second |= *item.begin(); - } -} - -template<class ITEM, class TAG> -void Fast<ITEM, TAG>::insert(const std::set<ITEM>& items, const wibble::Singleton<TAG>& tag) -{ - using namespace wibble::operators; - - for (typename std::set<ITEM>::const_iterator i = items.begin(); - i != items.end(); ++i) - { - typename std::map< ITEM, std::set<TAG> >::iterator iter = this->items.find(*i); - if (iter == this->items.end()) - this->items.insert(std::make_pair(*i, std::set<TAG>() | *tag.begin())); - else - iter->second |= *tag.begin(); - } - - typename std::map< TAG, std::set<ITEM> >::iterator iter = this->tags.find(*tag.begin()); - if (iter == this->tags.end()) - this->tags.insert(std::make_pair(*tag.begin(), items)); - else - iter->second |= items; -} - -template<class ITEM, class TAG> -std::set<ITEM> Fast<ITEM, TAG>::getItemsHavingTag(const TAG& tag) const -{ - typename map<TAG, std::set<ITEM> >::const_iterator i = tags.find(tag); - if (i != tags.end()) - return i->second; - else - return std::set<ITEM>(); -} - -template<class ITEM, class TAG> -std::set<TAG> Fast<ITEM, TAG>::getTagsOfItem(const ITEM& item) const -{ - typename map<ITEM, std::set<TAG> >::const_iterator i = items.find(item); - if (i != items.end()) - return i->second; - else - return std::set<TAG>(); -} - -template<class ITEM, class TAG> -std::set<ITEM> Fast<ITEM, TAG>::getTaggedItems() const -{ - std::set<ITEM> res; - for (typename map<ITEM, std::set<TAG> >::const_iterator i = items.begin(); - i != items.end(); i++) - res |= i->first; - return res; -} - -template<class ITEM, class TAG> -std::set<TAG> Fast<ITEM, TAG>::getAllTags() const -{ - std::set<TAG> res; - for (typename map<TAG, std::set<ITEM> >::const_iterator i = tags.begin(); - i != tags.end(); i++) - res |= i->first; - return res; -} - -template<class ITEM, class TAG> -std::vector<TAG> Fast<ITEM, TAG>::getAllTagsAsVector() const -{ - std::vector<TAG> res; - for (typename map<TAG, std::set<ITEM> >::const_iterator i = tags.begin(); - i != tags.end(); i++) - res.push_back(i->first); - return res; -} - -#if 0 -template<class ITEM, class TAG> -void Fast<ITEM, TAG>::output(Consumer<ITEM, TAG>& consumer) const -{ - for (typename map<ITEM, std::set<TAG> >::const_iterator i = items.begin(); - i != items.end(); i++) - consumer.consume(i->first, i->second); -} -#endif - -template<class ITEM, class TAG> template<typename OUT> -void Fast<ITEM, TAG>::outputReversed(OUT out) const -{ - for (typename std::map<TAG, std::set<ITEM> >::const_iterator i = tags.begin(); - i != tags.end(); ++i) - { - *out = make_pair(wibble::singleton(i->first), i->second); - ++out; - } -} - - -template<class ITEM, class TAG> -std::set<TAG> Fast<ITEM, TAG>::getTagsImplying(const TAG& tag) const -{ - // tag1 implies tag2 if the itemset of tag1 is a subset of the itemset of tag2 - std::set<TAG> res; - std::set<ITEM> itemsToCheck = getItemsHavingTag(tag); - // TODO: choose which one is the most efficient implementation -#if 0 - // Roughly: - // O(n[pkgs per tag] * log(nitems) * log(n[items per pkg]) + n[tags per item] * n[items per tag]) - std::set<TAG> tagsToCheck; - for (std::set<ITEM>::const_iterator i = itemsToCheck.begin(); - i != itemsToCheck.end(); ++i) - tagsToCheck |= getTags(*i); - for (std::set<TAG>::const_iterator i = tagsToCheck.begin(); - i != tagsToCheck.end(); ++i) - if (utils::set_contains(itemsToCheck, getItems(*i))) - res |= *i; -#else - // O(ntags * n[items per tag]) - for (typename std::map<TAG, std::set<ITEM> >::const_iterator i = tags.begin(); - i != tags.end(); ++i) - if (utils::set_contains(itemsToCheck, getItemsHavingTag(i->first))) - res |= i->first; -#endif - return res - tag; -} - -template<class ITEM, class TAG> -std::set<ITEM> Fast<ITEM, TAG>::getItemsExactMatch(const std::set<TAG>& tags) const -{ - std::set<ITEM> res = this->getItemsHavingTags(tags); - typename std::set<ITEM>::iterator i = res.begin(); - while (i != res.end()) - { - typename std::map<ITEM, std::set<TAG> >::const_iterator t = items.find(*i); - if (t != items.end() && t->second != tags) - { - typename std::set<ITEM>::iterator j = i; - ++i; - res.erase(j); - } else - ++i; - } - return res; -} - -template<class ITEM, class TAG> -TAG Fast<ITEM, TAG>::findTagWithMaxCardinality(size_t& card) const -{ - card = 0; - TAG res = TAG(); - for (typename std::map<TAG, std::set<ITEM> >::const_iterator i = tags.begin(); - i != tags.end(); ++i) - if (i->second.size() > card) - { - card = i->second.size(); - res = i->first; - } - return res; -} - -template<class ITEM, class TAG> -void Fast<ITEM, TAG>::removeTag(const TAG& tag) -{ - typename std::map<TAG, std::set<ITEM> >::iterator itag = tags.find(tag); - for (typename std::set<ITEM>::const_iterator iitemset = itag->second.begin(); - iitemset != itag->second.end(); ++iitemset) - { - typename std::map<ITEM, std::set<TAG> >::iterator iitem = items.find(*iitemset); - iitem->second -= tag; - if (iitem->second.empty()) - items.erase(iitem); - } - tags.erase(itag); -} - -template<class ITEM, class TAG> -Fast<ITEM, TAG> Fast<ITEM, TAG>::getChildCollection(const TAG& tag) const -{ - Fast<ITEM, TAG> res; - - typename std::map<TAG, std::set<ITEM> >::const_iterator itag = tags.find(tag); - for (typename std::set<ITEM>::const_iterator i = itag->second.begin(); - i != itag->second.end(); ++i) - { - typename std::map<ITEM, std::set<TAG> >::const_iterator iitem = items.find(*i); - res.insert(wibble::singleton(*i), iitem->second); - } - - res.removeTag(tag); - return res; -} - -template<class ITEM, class TAG> -void Fast<ITEM, TAG>::removeTagsWithCardinalityLessThan(size_t card) -{ - typename std::map<TAG, std::set<ITEM> >::const_iterator i = tags.begin(); - while (i != tags.end()) - { - if (i->second.size() < card) - { - typename std::map<TAG, std::set<ITEM> >::const_iterator j = i; - ++i; - removeTag(j->first); - } else - ++i; - } -} - - -#if 0 -template<class ITEM, class TAG> -void Fast<ITEM, TAG>::consumeItem(const ITEM& item, const std::set<TAG>& tags) -{ - // Add the tags to the item - items[item] |= tags; - - // Add the item to the tags - for (typename std::set<TAG>::const_iterator i = tags.begin(); i != tags.end(); i++) - this->tags[*i] |= item; -} - -template<class ITEM, class TAG> -void Fast<ITEM, TAG>::consumeItems(const std::set<ITEM>& items, const std::set<TAG>& tags) -{ - for (typename std::set<ITEM>::const_iterator i = items.begin(); i != items.end(); i++) - // Add the tags to the item - this->items[*i] |= tags; - - for (typename std::set<TAG>::const_iterator i = tags.begin(); i != tags.end(); i++) - // Add the items to the tag - this->tags[*i] |= items; -} -#endif - -} -} - -#include <ept/debtags/coll/base.tcc> - -#endif - -// vim:set ts=4 sw=4: diff --git a/ept/debtags/coll/set.h b/ept/debtags/coll/set.h index f78116f..cabd939 100644 --- a/ept/debtags/coll/set.h +++ b/ept/debtags/coll/set.h @@ -26,7 +26,9 @@ #include <wibble/operators.h> #include <set> -namespace tagcoll { +namespace ept { +namespace debtags { +namespace coll { namespace utils { template<typename T> @@ -83,6 +85,7 @@ bool set_contains(const std::set<T>& set1, const T& item) } } +} +} -// vim:set ts=4 sw=4: #endif diff --git a/ept/debtags/debtags-test.cc b/ept/debtags/debtags-test.cc index 3a8fca5..c03d3a2 100644 --- a/ept/debtags/debtags-test.cc +++ b/ept/debtags/debtags-test.cc @@ -3,7 +3,6 @@ #include <wibble/operators.h> #include <cstdio> -using namespace tagcoll; using namespace std; using namespace ept; using namespace ept::debtags; diff --git a/ept/debtags/debtags.cc b/ept/debtags/debtags.cc index b800c77..2fde09b 100644 --- a/ept/debtags/debtags.cc +++ b/ept/debtags/debtags.cc @@ -24,26 +24,18 @@ */ #include <ept/debtags/debtags.h> - -//#include <tagcoll/coll/simple.h> -//#include <tagcoll/input/stdio.h> #include "coll/TextFormat.h" - #include <wibble/sys/fs.h> #include <wibble/string.h> - #include <system_error> #include <iostream> #include <sstream> - #include <sys/wait.h> // WIFEXITED WEXITSTATUS #include <sys/types.h> // getpwuid, getuid #include <pwd.h> // getpwuid #include <unistd.h> // getuid - using namespace std; -using namespace tagcoll; using namespace wibble; namespace ept { @@ -73,7 +65,7 @@ void Debtags::load(const std::string& pathname) // Read the collection try { - tagcoll::textformat::parse(in, pathname, inserter(*this)); + coll::textformat::parse(in, pathname, *this); } catch (...) { fclose(in); throw; @@ -93,11 +85,3 @@ string Debtags::pathname() } } - -#include "coll/fast.tcc" -#include "coll/TextFormat.tcc" - -// Explicit template instantiations for our stuff -template class tagcoll::coll::Fast<std::string, std::string>; - -// vim:set ts=4 sw=4: diff --git a/ept/debtags/debtags.h b/ept/debtags/debtags.h index a23b209..52d9347 100644 --- a/ept/debtags/debtags.h +++ b/ept/debtags/debtags.h @@ -26,18 +26,11 @@ #ifndef EPT_DEBTAGS_DEBTAGS_H #define EPT_DEBTAGS_DEBTAGS_H -#include <ept/debtags/coll/base.h> #include <ept/debtags/coll/fast.h> #include <string> namespace ept { namespace debtags { -class Debtags; -} -} - -namespace ept { -namespace debtags { /** * Access the on-disk Debtags tag database. @@ -51,7 +44,7 @@ namespace debtags { * It is possible to get a reference to the Vocabulary object using the * vocabulary() method. */ -class Debtags : public tagcoll::coll::Fast<std::string, std::string> +class Debtags : public coll::Fast { protected: // User rc directory to store patches @@ -63,8 +56,8 @@ protected: void load(const std::string& pathname); public: - typedef tagcoll::coll::Fast<std::string, std::string> coll_type; - typedef std::pair< std::string, std::set<std::string> > value_type; + typedef ept::debtags::coll::Fast coll_type; + typedef std::pair< std::string, std::set<std::string> > value_type; /// Create a Debtags object, reading the system database Debtags(); @@ -90,7 +83,6 @@ public: static std::string pathname(); }; - } } diff --git a/ept/debtags/vocabulary-test.cc b/ept/debtags/vocabulary-test.cc index 51f46f9..682e521 100644 --- a/ept/debtags/vocabulary-test.cc +++ b/ept/debtags/vocabulary-test.cc @@ -4,7 +4,7 @@ #include "ept/test.h" using namespace std; -using namespace tagcoll::utils; +using namespace ept::debtags::coll::utils; using namespace ept::debtags; using namespace ept::tests; |