summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/generic/problemresolver/choice_set.h73
-rw-r--r--tests/test_choice_set.cc37
2 files changed, 110 insertions, 0 deletions
diff --git a/src/generic/problemresolver/choice_set.h b/src/generic/problemresolver/choice_set.h
index 45f51767..e2e2146d 100644
--- a/src/generic/problemresolver/choice_set.h
+++ b/src/generic/problemresolver/choice_set.h
@@ -69,6 +69,64 @@ private:
typedef typename PackageUniverse::version version;
typedef typename PackageUniverse::dep dep;
+public:
+ /** \brief A slow but convenient way to iterate over this set. */
+ class const_iterator
+ {
+ friend class generic_choice_set;
+
+ typename imm::map<package, choice>::const_iterator install_version_iter;
+ typename imm::map<package, choice>::const_iterator install_version_end_iter;
+ typename imm::set<choice>::const_iterator not_install_version_iter;
+
+ const_iterator(const typename imm::map<package, choice>::const_iterator _install_version_iter,
+ const typename imm::map<package, choice>::const_iterator _install_version_end_iter,
+ const typename imm::set<choice>::const_iterator _not_install_version_iter)
+ : install_version_iter(_install_version_iter),
+ install_version_end_iter(_install_version_end_iter),
+ not_install_version_iter(_not_install_version_iter)
+ {
+ }
+
+ public:
+ bool operator==(const const_iterator &other) const
+ {
+ return install_version_iter == other.install_version_iter &&
+ not_install_version_iter == other.not_install_version_iter;
+ }
+
+ bool operator!=(const const_iterator &other) const
+ {
+ return !((*this) == other);
+ }
+
+ const choice &operator*() const
+ {
+ if(install_version_iter != install_version_end_iter)
+ return install_version_iter->second;
+ else
+ return *not_install_version_iter;
+ }
+
+ const_iterator &operator++()
+ {
+ if(install_version_iter != install_version_end_iter)
+ ++install_version_iter;
+ else
+ ++not_install_version_iter;
+
+ return *this;
+ }
+
+ const_iterator operator++(int)
+ {
+ const_iterator rval(*this);
+ ++(*this);
+ return rval;
+ }
+ };
+
+private:
// Note: no iterators on this structure because they'd be a pain to
// write and they should never be used (use for_each instead, it's a
// lot more efficient).
@@ -82,6 +140,7 @@ private:
// would be more efficient or not.
imm::set<choice> not_install_version_choices;
+
friend std::ostream &operator<< <PackageUniverse>(std::ostream &out, const generic_choice_set<PackageUniverse> &choices);
// Used to apply a for_each on choices to each element of the
@@ -213,6 +272,20 @@ public:
{
}
+ const_iterator begin() const
+ {
+ return const_iterator(install_version_choices.begin(),
+ install_version_choices.end(),
+ not_install_version_choices.begin());
+ }
+
+ const_iterator end() const
+ {
+ return const_iterator(install_version_choices.end(),
+ install_version_choices.end(),
+ not_install_version_choices.end());
+ }
+
/** \brief Insert every choice in the given set into this set,
* overriding more general options with more specific ones.
*/
diff --git a/tests/test_choice_set.cc b/tests/test_choice_set.cc
index f3bd4e54..d8a7936d 100644
--- a/tests/test_choice_set.cc
+++ b/tests/test_choice_set.cc
@@ -86,6 +86,36 @@ class Choice_Set_Test : public CppUnit::TestFixture
}
};
+ struct contents_enumerator
+ {
+ std::vector<choice> &rval;
+
+ contents_enumerator(std::vector<choice> &_rval)
+ : rval(_rval)
+ {
+ }
+
+ bool operator()(const choice &c) const
+ {
+ rval.push_back(c);
+ return true;
+ }
+ };
+
+ void test_contents_iterator(const choice_set &s)
+ {
+ std::vector<choice> expected, observed;
+
+ s.for_each(contents_enumerator(expected));
+
+ for(choice_set::const_iterator it = s.begin(); it != s.end(); ++it)
+ observed.push_back(*it);
+
+ CPPUNIT_ASSERT_EQUAL(expected.size(), observed.size());
+ for(std::vector<choice>::size_type i = 0; i < expected.size(); ++i)
+ CPPUNIT_ASSERT_EQUAL(expected[i], observed[i]);
+ };
+
static imm::set<choice> get_contents(const choice_set &s)
{
imm::set<choice> rval;
@@ -153,6 +183,7 @@ public:
CPPUNIT_ASSERT_EQUAL(expected, get_contents(s));
CPPUNIT_ASSERT_EQUAL(expected, get_contents(make_choice_set_narrow(expected)));
CPPUNIT_ASSERT_EQUAL(s, make_choice_set_narrow(expected));
+ test_contents_iterator(s);
const choice c1(make_install_version(av2));
s.insert_or_narrow(c1);
@@ -162,6 +193,7 @@ public:
CPPUNIT_ASSERT_EQUAL(expected, get_contents(s));
CPPUNIT_ASSERT_EQUAL(expected, get_contents(make_choice_set_narrow(expected)));
CPPUNIT_ASSERT_EQUAL(s, make_choice_set_narrow(expected));
+ test_contents_iterator(s);
const choice c2(make_install_version_from_dep_source(av2, av3d1));
expected.erase(c1);
@@ -172,6 +204,7 @@ public:
CPPUNIT_ASSERT_EQUAL(expected, get_contents(s));
CPPUNIT_ASSERT_EQUAL(expected, get_contents(make_choice_set_narrow(expected)));
CPPUNIT_ASSERT_EQUAL(s, make_choice_set_narrow(expected));
+ test_contents_iterator(s);
const choice c3(make_break_soft_dep(av2d1));
s.insert_or_narrow(c3);
@@ -180,6 +213,7 @@ public:
CPPUNIT_ASSERT_EQUAL(expected, get_contents(s));
CPPUNIT_ASSERT_EQUAL(expected, get_contents(make_choice_set_narrow(expected)));
CPPUNIT_ASSERT_EQUAL(s, make_choice_set_narrow(expected));
+ test_contents_iterator(s);
const choice c4(make_install_version_from_dep_source(bv1, bv2d1));
s.insert_or_narrow(c4);
@@ -189,6 +223,7 @@ public:
CPPUNIT_ASSERT_EQUAL(expected, get_contents(s));
CPPUNIT_ASSERT_EQUAL(expected, get_contents(make_choice_set_narrow(expected)));
CPPUNIT_ASSERT_EQUAL(s, make_choice_set_narrow(expected));
+ test_contents_iterator(s);
const choice c5(make_install_version(bv1));
s.insert_or_narrow(c5);
@@ -197,6 +232,7 @@ public:
CPPUNIT_ASSERT_EQUAL(expected, get_contents(s));
CPPUNIT_ASSERT_EQUAL(expected, get_contents(make_choice_set_narrow(expected)));
CPPUNIT_ASSERT_EQUAL(s, make_choice_set_narrow(expected));
+ test_contents_iterator(s);
const choice c6(make_break_soft_dep(av3d1));
@@ -206,6 +242,7 @@ public:
CPPUNIT_ASSERT_EQUAL(expected, get_contents(s));
CPPUNIT_ASSERT_EQUAL(expected, get_contents(make_choice_set_narrow(expected)));
CPPUNIT_ASSERT_EQUAL(s, make_choice_set_narrow(expected));
+ test_contents_iterator(s);
}
void testContainsChoice()