[Debtags-commits] [svn] r1711 - in tagcoll/2.0: . tagcoll tools
Enrico Zini
enrico at costa.debian.org
Tue May 9 00:07:43 UTC 2006
Author: enrico
Date: Tue May 9 00:07:38 2006
New Revision: 1711
Modified:
tagcoll/2.0/ (props changed)
tagcoll/2.0/tagcoll/Implications.h
tagcoll/2.0/tagcoll/TDBIndexer.h
tagcoll/2.0/tagcoll/filters.h
tagcoll/2.0/tools/tagcoll.cc
Log:
r2598 at viaza: enrico | 2006-05-07 02:46:29 -0500
Added NullFilter and UngroupItems filter.
Updated some of the tagcoll.cc code
Modified: tagcoll/2.0/tagcoll/Implications.h
==============================================================================
--- tagcoll/2.0/tagcoll/Implications.h (original)
+++ tagcoll/2.0/tagcoll/Implications.h Tue May 9 00:07:38 2006
@@ -58,6 +58,8 @@
public:
virtual ~Implications() {}
+
+ bool empty() const { return implications.empty(); }
/// Expand a single tag
std::set<TAG> expand(const TAG& tag) const
Modified: tagcoll/2.0/tagcoll/TDBIndexer.h
==============================================================================
--- tagcoll/2.0/tagcoll/TDBIndexer.h (original)
+++ tagcoll/2.0/tagcoll/TDBIndexer.h Tue May 9 00:07:38 2006
@@ -55,30 +55,14 @@
public:
virtual ~TDBIndexer() {}
+ virtual bool empty() const { return items.empty(); }
+
virtual bool hasItem(const ITEM& item) const { return items.find(item) != items.end(); }
virtual bool hasTag(const TAG& tag) const { return tags.find(tag) != tags.end(); }
virtual std::set<ITEM> getTaggedItems() const;
virtual std::set<TAG> getAllTags() const;
virtual void output(Consumer<ITEM, TAG>& consumer) const;
virtual void applyChange(const PatchList<ITEM, TAG>& change);
-
- /**
- * Write all collected informations to a disk index
- *
- * \param itemconv
- * Converter than can convert an ITEM to a string
- * \param tagconv
- * Converter than can convert a TAG to a string
- * \param pkgidx
- * File name for the package index to write
- * \param tagidx
- * File name for the tag index to write
- */
- void writeIndex(
- Converter<ITEM, std::string>& itemconv,
- Converter<TAG, std::string>& tagconv,
- const std::string& pkgidx,
- const std::string& tagidx) const;
};
};
Modified: tagcoll/2.0/tagcoll/filters.h
==============================================================================
--- tagcoll/2.0/tagcoll/filters.h (original)
+++ tagcoll/2.0/tagcoll/filters.h Tue May 9 00:07:38 2006
@@ -24,6 +24,7 @@
*/
#include <wibble/mixin.h>
+#include <wibble/singleton.h>
#include <wibble/empty.h>
#include <set>
#include <map>
@@ -33,6 +34,26 @@
{
/**
+ * Filter that does nothing and just passes on the data
+ */
+template<typename OUT>
+class NullFilter : public wibble::mixin::OutputIterator< NullFilter<OUT> >
+{
+ OUT out;
+
+public:
+ NullFilter(const OUT& out) : out(out) {}
+
+ template<typename ITEMS, typename TAGS>
+ NullFilter<OUT>& operator=(const std::pair<ITEMS, TAGS>& data)
+ {
+ *out = data;
+ ++out;
+ return *this;
+ }
+};
+
+/**
* Store a list of substitutions to operate on std::set
*
* It uses a Consumer interface to allow to be populated using a decoder for
@@ -296,6 +317,33 @@
return Reverser<OUT, TAG>(out, reversedNull);
}
+template<typename OUT>
+class UngroupItems : public wibble::mixin::OutputIterator< UngroupItems<OUT> >
+{
+ OUT out;
+
+public:
+ UngroupItems(const OUT& out) : out(out) {}
+
+ template<typename ITEMS, typename TAGS>
+ UngroupItems<OUT>& operator=(const std::pair<ITEMS, TAGS>& data)
+ {
+ for (typename ITEMS::const_iterator i = data.first.begin();
+ i != data.first.end(); ++i)
+ {
+ *out = make_pair(wibble::singleton(*i), data.second);
+ ++out;
+ }
+ return *this;
+ }
+};
+
+template<typename OUT>
+UngroupItems<OUT> ungroupItems(const OUT& out)
+{
+ return UngroupItems<OUT>(out);
+}
+
};
// vim:set ts=4 sw=4:
Modified: tagcoll/2.0/tools/tagcoll.cc
==============================================================================
--- tagcoll/2.0/tools/tagcoll.cc (original)
+++ tagcoll/2.0/tools/tagcoll.cc Tue May 9 00:07:38 2006
@@ -49,6 +49,7 @@
#include <tagcoll/Implications.h>
#include <tagcoll/Patches.h>
#include <tagcoll/DerivedTags.h>
+#include <tagcoll/TDBIndexer.h>
#include <tagcoll/StdioParserInput.h>
#include <tagcoll/TextFormat.h>
@@ -111,20 +112,22 @@
return items;
}
-void readCollection(const string& file, Consumer<string, string>& builder)
+template<typename OUT>
+void readCollection(const string& file, const OUT& out)
{
if (file == "-")
{
StdioParserInput input(stdin, "<stdin>");
- textformat::parse(input, consumer(builder));
+ textformat::parse(input, out);
}
else
{
StdioParserInput input(file);
- textformat::parse(input, consumer(builder));
+ textformat::parse(input, out);
}
}
+
PatchList<string, string> readPatches(const string& file)
{
TrivialConverter<string, string> conv;
@@ -245,166 +248,275 @@
}
}
-class Reader
+// Break filtering into generic steps that are abstracted by a virtual function
+
+class FilterStep : public wibble::mixin::OutputIterator<FilterStep>
{
- // Prepare the input filter chain
- FilterChain<string, string> filters;
- Substitute<string, string> substitutions;
- PatchList<string, string> patches;
- Implications<string> implications;
- DerivedTags derivedTags;
+public:
+ virtual ~FilterStep() {}
+ virtual FilterStep& operator=(const pair< set<string>, set<string> >& data) = 0;
+ virtual FilterStep& operator=(const pair< wibble::Singleton<string>, set<string> >& data) = 0;
+ virtual FilterStep& operator=(const pair< set<string>, wibble::Empty<string> >& data) = 0;
+ virtual FilterStep& operator=(const pair< wibble::Singleton<string>, wibble::Empty<string> >& data) = 0;
+};
- AddImplied<string, string> addImplied;
- RemoveImplied<string, string> removeImplied;
- AddDerived<string> addDerived;
- RemoveDerived<string> removeDerived;
- UnfacetedRemover<string> unfacetedRemover;
- FilterTagsByExpression<string, string> filterByExpression;
+template<typename OUT>
+class StringFilterStep : public FilterStep
+{
+ OUT out;
public:
- Reader(wibble::commandline::TagcollParser& opts)
- : addImplied(implications), removeImplied(implications),
- addDerived(derivedTags), removeDerived(derivedTags),
- unfacetedRemover("::"), filterByExpression("")
+ StringFilterStep(const OUT& out) : out(out) {}
+ virtual ~StringFilterStep() {}
+
+ virtual FilterStep& operator=(const pair< set<string>, set<string> >& data)
{
- if (opts.in_rename->boolValue())
- {
- readCollection(opts.in_rename->stringValue(), substitutions.substitutions());
- filters.appendFilter(substitutions);
- }
- if (opts.in_patch->boolValue())
- {
- patches = readPatches(opts.in_patch->stringValue());
- filters.appendFilter(patches);
- }
+ *out = data;
+ ++out;
+ return *this;
+ }
+ virtual FilterStep& operator=(const pair< wibble::Singleton<string>, set<string> >& data)
+ {
+ *out = data;
+ ++out;
+ return *this;
+ }
+ virtual FilterStep& operator=(const pair< set<string>, wibble::Empty<string> >& data)
+ {
+ *out = data;
+ ++out;
+ return *this;
+ }
+ virtual FilterStep& operator=(const pair< wibble::Singleton<string>, wibble::Empty<string> >& data)
+ {
+ *out = data;
+ ++out;
+ return *this;
+ }
+};
- if (opts.in_extimpl->boolValue())
- {
- readCollection(opts.in_extimpl->stringValue(), implications);
- // Pack the structure for faster expansions
- implications.pack();
- }
- if (opts.in_derived->boolValue())
- readDerivedTags(opts.in_derived->stringValue(), derivedTags);
+template<typename OUT>
+FilterStep* filterStep(const OUT& out)
+{
+ return new StringFilterStep<OUT>(out);
+}
- // Intermix implications and derived tags as seems best
- bool compressOutput = (opts.foundCommand() == opts.copy && !opts.out_redundant->boolValue());
- bool hasImpl = opts.in_extimpl->boolValue();
- bool hasDerv = opts.in_derived->boolValue();
+class FilterForwarder : public wibble::mixin::OutputIterator<FilterForwarder>
+{
+ FilterStep* out;
- if (compressOutput)
- {
- if (hasDerv)
- {
- // Expand implications
- if (hasImpl) filters.appendFilter(addImplied);
+public:
+ FilterForwarder(FilterStep* out) : out(out) {}
- // Remove derived tags computing them using the expanded tag set
- filters.appendFilter(removeDerived);
- }
+ template<typename ITEMS, typename TAGS>
+ FilterForwarder& operator=(const pair<ITEMS, TAGS>& data)
+ {
+ **out = data;
+ ++out;
+ return *this;
+ }
+};
- // Compress implications
- if (hasImpl) filters.appendFilter(removeImplied);
- } else {
- // Expand implications
- if (hasImpl) filters.appendFilter(addImplied);
+class FilterStepManager
+{
+ std::set<FilterStep*> m_managed;
+public:
+ ~FilterStepManager()
+ {
+ for (std::set<FilterStep*>::const_iterator i = m_managed.begin();
+ i != m_managed.end(); ++i)
+ if (*i)
+ delete *i;
+ }
- // Add derived tags computing them using the expanded tag set
- if (hasDerv)
- {
- filters.appendFilter(addDerived);
+ FilterStep* manage(FilterStep* fs)
+ {
+ m_managed.insert(fs);
+ return fs;
+ }
+};
- // Add further tags implicated by the derived tags
- if (hasImpl) filters.appendFilter(addImplied);
- }
- }
+// Construct the elaborate readers and writers by chunks, to avoid having a
+// virtual layer among each and every filtering step
+class Tagcoll
+{
+ wibble::commandline::TagcollParser& opts;
+ TDBIndexer<string, string> grouper;
- if (opts.in_rmunfaceted->boolValue())
- filters.appendFilter(unfacetedRemover);
+ FilterStepManager wman;
+ FilterStep* m_writer;
- if (opts.in_rmtags->boolValue())
- {
- filterByExpression.setExpression(not Expression(opts.in_rmtags->stringValue()));
- filters.appendFilter(filterByExpression);
- }
- }
- void output(const string& file, Consumer<string, string>& cons)
+ // Support structures for the input filter chain
+ Implications<string> implications;
+ DerivedTags derivedTags;
+ Substitutions<string> substitutions;
+ PatchList<string, string> patches;
+
+ FilterStep* makeReaderHead(FilterStep* out)
{
- filters.setConsumer(cons);
- readCollection(file, filters);
+ if (opts.in_patch->boolValue())
+ if (opts.in_rename->boolValue())
+ return filterStep(
+ patcher(patches,
+ substitute(substitutions,
+ FilterForwarder(out))));
+ else
+ return filterStep(
+ patcher(patches,
+ FilterForwarder(out)));
+ else
+ if (opts.in_rename->boolValue())
+ return filterStep(
+ substitute(substitutions,
+ FilterForwarder(out)));
+ else
+ return out;
}
- void output(wibble::commandline::TagcollParser& opts, Consumer<string, string>& cons)
+
+ FilterStep* makeReaderMain(FilterStep* out)
{
- if (opts.hasNext())
- while (opts.hasNext())
- output(opts.next(), cons);
+ bool hasImpl = opts.in_extimpl->boolValue();
+ bool hasDerv = opts.in_derived->boolValue();
+
+ if (hasImpl)
+ if (hasDerv)
+ // Add derived tags computing them using the expanded tag set,
+ // then adding further tags implicated by the derived tags
+ return filterStep(
+ addImplied(implications,
+ addDerived(derivedTags,
+ addImplied(implications, FilterForwarder(out)))));
+ else
+ return filterStep(addImplied(implications, FilterForwarder(out)));
else
- output("-", cons);
+ if (hasDerv)
+ return filterStep(addDerived(derivedTags, FilterForwarder(out)));
+ else
+ return out;
}
-};
-class Writer : public Consumer<string, string>
-{
- TrivialConverter<string, string> conv;
- TextFormat<string, string> output;
- ItemGrouper<string, string>* grouper;
- bool itemsOnly;
-
-protected:
- /// Process an untagged item
- virtual void consumeItemUntagged(const string& item)
+ template<typename OUT>
+ FilterStep* makeReaderTail(const OUT& out)
{
- if (grouper)
- grouper->consume(item);
+ if (opts.in_rmunfaceted->boolValue())
+ if (opts.in_rmtags->boolValue())
+ return filterStep(
+ unfacetedRemover(
+ filterTagsByExpression(
+ not Expression(opts.in_rmtags->stringValue()), out)));
+ else
+ return filterStep(unfacetedRemover(out));
else
- output.consume(item);
+ if (opts.in_rmtags->boolValue())
+ return filterStep(
+ filterTagsByExpression(
+ not Expression(opts.in_rmtags->stringValue()), out));
+ else
+ return filterStep(out);
}
- /// Process a tagged item, with its tags
- virtual void consumeItem(const string& item, const std::set<string>& tags)
+ FilterStep* makeWriterHead(FilterStep* out)
{
- if (itemsOnly)
- consumeItemUntagged(item);
- else if (grouper)
- grouper->consume(item, tags);
+ // Intermix implications and derived tags as seems best
+ if (!opts.out_redundant->boolValue())
+ if (derivedTags.empty())
+ if (implications.empty())
+ return out;
+ else
+ return filterStep(removeImplied(implications, FilterForwarder(out)));
+ else
+ if (implications.empty())
+ return filterStep(removeDerived(derivedTags, FilterForwarder(out)));
+ else
+ // Expand implications, then remove derived tags computing
+ // them using the expanded tag set
+ return filterStep(
+ addImplied(implications,
+ removeDerived(derivedTags,
+ removeImplied(implications,
+ FilterForwarder(out)))));
+ }
+
+ FilterStep* makeWriterTail()
+ {
+ if (opts.out_itemsOnly->boolValue())
+ if (opts.out_group->boolValue())
+ return filterStep(itemsOnly(consumer(grouper)));
+ else
+ return filterStep(itemsOnly(ungroupItems(textformat::StdioWriter(stdout))));
else
- output.consume(item, tags);
+ if (opts.out_group->boolValue())
+ return filterStep(consumer(grouper));
+ else
+ return filterStep(ungroupItems(textformat::StdioWriter(stdout)));
}
- /// Process a set of items, all with no tags
- virtual void consumeItemsUntagged(const std::set<string>& items)
+public:
+ Tagcoll(wibble::commandline::TagcollParser& opts)
+ : opts(opts), m_writer(0)
{
- if (grouper)
- grouper->consume(items);
- else
- // Explicitly split groups
- for (std::set<string>::const_iterator i = items.begin();
- i != items.end(); i++)
- output.consume(*i);
+ if (opts.in_extimpl->boolValue())
+ {
+ readCollection(opts.in_extimpl->stringValue(), consumer(implications));
+ // Pack the structure for faster expansions
+ implications.pack();
+ }
+ if (opts.in_derived->boolValue())
+ readDerivedTags(opts.in_derived->stringValue(), derivedTags);
+ if (opts.in_rename->boolValue())
+ readCollection(opts.in_rename->stringValue(), substitutions.inserter());
+ if (opts.in_patch->boolValue())
+ patches = readPatches(opts.in_patch->stringValue());
}
+ ~Tagcoll()
+ {
+ if (!grouper.empty())
+ grouper.output(forwarder(textformat::StdioWriter(stdout)));
+ }
+
+ template<typename OUT>
+ void outputFile(const string& file, const OUT& out)
+ {
+ FilterStepManager m;
+ FilterStep* reader =
+ m.manage(makeReaderHead(
+ m.manage(makeReaderMain(
+ m.manage(makeReaderTail(out))))));
- /// Process a set of items identically tagged, with their tags
- virtual void consumeItems(const std::set<string>& items, const std::set<string>& tags)
- {
- if (itemsOnly)
- consumeItemsUntagged(items);
- else if (grouper)
- grouper->consume(items, tags);
+ readCollection(file, FilterForwarder(reader));
+ }
+
+ template<typename OUT>
+ void outputAll(const OUT& out)
+ {
+ FilterStepManager m;
+ FilterStep* reader =
+ m.manage(makeReaderHead(
+ m.manage(makeReaderMain(
+ m.manage(makeReaderTail(out))))));
+
+ if (opts.hasNext())
+ while (opts.hasNext())
+ readCollection(opts.next(), FilterForwarder(reader));
else
- // Explicitly split groups
- for (std::set<string>::const_iterator i = items.begin();
- i != items.end(); i++)
- output.consume(*i, tags);
+ readCollection("-", FilterForwarder(reader));
}
-public:
- Writer(wibble::commandline::TagcollParser& opts)
- : output(conv, conv, stdout), grouper(0)
+ FilterForwarder writer()
{
- if (opts.out_group->boolValue())
- grouper = new ItemGrouper<string, string>;
- itemsOnly = opts.out_itemsOnly->boolValue();
+ if (!m_writer)
+ m_writer =
+ wman.manage(makeWriterHead(
+ wman.manage(makeWriterTail())));
+ return FilterForwarder(m_writer);
}
+};
+
+#if 0
+TODO:
+ - output the grouped data
+
+public:
~Writer()
{
// Flush output if needed
@@ -415,6 +527,7 @@
}
}
};
+#endif
int main(int argc, const char* argv[])
{
More information about the Debtags-commits
mailing list