aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-08-03 16:31:11 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-08-04 19:21:48 +0100
commit5a6f33463b1a396225696ba8c5ad7468fbea4e68 (patch)
tree1b0a710882226390d9b1312047f7fe89ae34576a
parent2d1137e5b4c0b29670dbf50d23d1001265745815 (diff)
downloadpaludis-5a6f33463b1a396225696ba8c5ad7468fbea4e68.tar.gz
paludis-5a6f33463b1a396225696ba8c5ad7468fbea4e68.tar.xz
Let ChangesToMakeDecision have ChangedChoices
-rw-r--r--paludis/resolver/decider.cc60
-rw-r--r--paludis/resolver/decider.hh8
-rw-r--r--paludis/resolver/decision.cc15
-rw-r--r--paludis/resolver/decision.hh8
-rw-r--r--paludis/resolver/orderer.cc1
-rw-r--r--paludis/resolver/sanitised_dependencies.cc41
-rw-r--r--paludis/resolver/sanitised_dependencies.hh4
-rw-r--r--src/clients/cave/resolve_common.cc1
8 files changed, 91 insertions, 47 deletions
diff --git a/paludis/resolver/decider.cc b/paludis/resolver/decider.cc
index 09db9a2..f4787d3 100644
--- a/paludis/resolver/decider.cc
+++ b/paludis/resolver/decider.cc
@@ -60,6 +60,7 @@
#include <paludis/action.hh>
#include <paludis/elike_slot_requirement.hh>
#include <paludis/dep_spec_flattener.hh>
+#include <paludis/package_id.hh>
#include <paludis/util/pimp-impl.hh>
@@ -1126,40 +1127,40 @@ namespace
{
struct DependenciesNecessityVisitor
{
- const std::shared_ptr<const PackageID> visit(const NothingNoChangeDecision &) const
+ const std::pair<std::shared_ptr<const PackageID>, std::shared_ptr<const ChangedChoices> > visit(const NothingNoChangeDecision &) const
{
- return make_null_shared_ptr();
+ return std::make_pair(make_null_shared_ptr(), make_null_shared_ptr());
}
- const std::shared_ptr<const PackageID> visit(const RemoveDecision &) const
+ const std::pair<std::shared_ptr<const PackageID>, std::shared_ptr<const ChangedChoices> > visit(const RemoveDecision &) const
{
- return make_null_shared_ptr();
+ return std::make_pair(make_null_shared_ptr(), make_null_shared_ptr());
}
- const std::shared_ptr<const PackageID> visit(const UnableToMakeDecision &) const
+ const std::pair<std::shared_ptr<const PackageID>, std::shared_ptr<const ChangedChoices> > visit(const UnableToMakeDecision &) const
{
- return make_null_shared_ptr();
+ return std::make_pair(make_null_shared_ptr(), make_null_shared_ptr());
}
- const std::shared_ptr<const PackageID> visit(const ExistingNoChangeDecision & decision) const
+ const std::pair<std::shared_ptr<const PackageID>, std::shared_ptr<const ChangedChoices> > visit(const ExistingNoChangeDecision & decision) const
{
if (decision.taken())
- return decision.existing_id();
+ return std::make_pair(decision.existing_id(), make_null_shared_ptr());
else
- return make_null_shared_ptr();
+ return std::make_pair(make_null_shared_ptr(), make_null_shared_ptr());
}
- const std::shared_ptr<const PackageID> visit(const ChangesToMakeDecision & decision) const
+ const std::pair<std::shared_ptr<const PackageID>, std::shared_ptr<const ChangedChoices> > visit(const ChangesToMakeDecision & decision) const
{
if (decision.taken())
- return decision.origin_id();
+ return std::make_pair(decision.origin_id(), make_null_shared_ptr());
else
- return make_null_shared_ptr();
+ return std::make_pair(make_null_shared_ptr(), make_null_shared_ptr());
}
- const std::shared_ptr<const PackageID> visit(const BreakDecision &) const
+ const std::pair<std::shared_ptr<const PackageID>, std::shared_ptr<const ChangedChoices> > visit(const BreakDecision &) const
{
- return make_null_shared_ptr();
+ return std::make_pair(make_null_shared_ptr(), make_null_shared_ptr());
}
};
}
@@ -1168,9 +1169,11 @@ void
Decider::_add_dependencies_if_necessary(
const std::shared_ptr<Resolution> & our_resolution)
{
- const std::shared_ptr<const PackageID> package_id(
- our_resolution->decision()->accept_returning<std::shared_ptr<const PackageID> >(
- DependenciesNecessityVisitor()));
+ std::shared_ptr<const PackageID> package_id;
+ std::shared_ptr<const ChangedChoices> changed_choices;
+ std::tie(package_id, changed_choices) = our_resolution->decision()->accept_returning<
+ std::pair<std::shared_ptr<const PackageID>, std::shared_ptr<const ChangedChoices> > >(DependenciesNecessityVisitor());
+
if (! package_id)
return;
@@ -1178,7 +1181,7 @@ Decider::_add_dependencies_if_necessary(
+ stringify(*package_id) + "':");
const std::shared_ptr<SanitisedDependencies> deps(std::make_shared<SanitisedDependencies>());
- deps->populate(_imp->env, *this, our_resolution, package_id);
+ deps->populate(_imp->env, *this, our_resolution, package_id, changed_choices);
for (SanitisedDependencies::ConstIterator s(deps->begin()), s_end(deps->end()) ;
s != s_end ; ++s)
@@ -1527,9 +1530,11 @@ Decider::_try_to_find_decision_for(
const bool try_masked_this_time) const
{
const std::shared_ptr<const PackageID> existing_id(_find_existing_id_for(resolution));
- std::pair<const std::shared_ptr<const PackageID>, bool> installable_id_best(_find_installable_id_for(resolution, try_masked_this_time));
- const std::shared_ptr<const PackageID> installable_id(installable_id_best.first);
- bool best(installable_id_best.second);
+
+ std::shared_ptr<const PackageID> installable_id;
+ std::shared_ptr<const ChangedChoices> changed_choices;
+ bool best;
+ std::tie(installable_id, changed_choices, best) = _find_installable_id_for(resolution, try_masked_this_time);
if (resolution->constraints()->nothing_is_fine_too())
{
@@ -1550,6 +1555,7 @@ Decider::_try_to_find_decision_for(
return std::make_shared<ChangesToMakeDecision>(
resolution->resolvent(),
installable_id,
+ changed_choices,
best,
last_ct,
! resolution->constraints()->all_untaken(),
@@ -1677,6 +1683,7 @@ Decider::_try_to_find_decision_for(
const std::shared_ptr<Decision> changes_to_make(std::make_shared<ChangesToMakeDecision>(
resolution->resolvent(),
installable_id,
+ changed_choices,
best,
last_ct,
! resolution->constraints()->all_untaken(),
@@ -1751,7 +1758,7 @@ const std::shared_ptr<const PackageID>
Decider::_find_existing_id_for(const std::shared_ptr<const Resolution> & resolution) const
{
const std::shared_ptr<const PackageIDSequence> ids(_installed_ids(resolution));
- return _find_id_for_from(resolution, ids).first;
+ return std::get<0>(_find_id_for_from(resolution, ids));
}
bool
@@ -1803,13 +1810,13 @@ Decider::_find_installable_id_candidates_for(
)];
}
-const std::pair<const std::shared_ptr<const PackageID>, bool>
+const Decider::FoundID
Decider::_find_installable_id_for(const std::shared_ptr<const Resolution> & resolution, const bool include_unmaskable) const
{
return _find_id_for_from(resolution, _find_installable_id_candidates_for(resolution, false, include_unmaskable));
}
-const std::pair<const std::shared_ptr<const PackageID>, bool>
+const Decider::FoundID
Decider::_find_id_for_from(
const std::shared_ptr<const Resolution> & resolution,
const std::shared_ptr<const PackageIDSequence> & ids) const
@@ -1836,10 +1843,10 @@ Decider::_find_id_for_from(
}
if (ok)
- return std::make_pair(*i, (*i)->version() == best_version->version());
+ return FoundID(*i, make_null_shared_ptr(), (*i)->version() == best_version->version());
}
- return std::make_pair(make_null_shared_ptr(), false);
+ return FoundID(make_null_shared_ptr(), make_null_shared_ptr(), false);
}
const std::shared_ptr<const Constraints>
@@ -1873,6 +1880,7 @@ Decider::_get_unmatching_constraints(
decision = std::make_shared<ChangesToMakeDecision>(
resolution->resolvent(),
id,
+ make_null_shared_ptr(),
false,
last_ct,
! (*c)->untaken(),
diff --git a/paludis/resolver/decider.hh b/paludis/resolver/decider.hh
index 17a2d82..62410a6 100644
--- a/paludis/resolver/decider.hh
+++ b/paludis/resolver/decider.hh
@@ -46,6 +46,8 @@
#include <paludis/repository-fwd.hh>
#include <paludis/filtered_generator-fwd.hh>
#include <paludis/generator-fwd.hh>
+#include <paludis/changed_choices-fwd.hh>
+#include <tuple>
namespace paludis
{
@@ -55,6 +57,8 @@ namespace paludis
private Pimp<Decider>
{
private:
+ typedef std::tuple<std::shared_ptr<const PackageID>, std::shared_ptr<const ChangedChoices>, bool> FoundID;
+
const std::shared_ptr<Resolution> _create_resolution_for_resolvent(const Resolvent &) const;
const std::shared_ptr<Resolution> _resolution_for_resolvent(const Resolvent &, const Tribool);
@@ -206,10 +210,10 @@ namespace paludis
const std::shared_ptr<const Resolution> &,
const bool include_errors,
const bool include_unmaskable) const;
- const std::pair<const std::shared_ptr<const PackageID>, bool> _find_installable_id_for(
+ const FoundID _find_installable_id_for(
const std::shared_ptr<const Resolution> &,
const bool include_unmaskable) const;
- const std::pair<const std::shared_ptr<const PackageID>, bool> _find_id_for_from(
+ const FoundID _find_id_for_from(
const std::shared_ptr<const Resolution> &,
const std::shared_ptr<const PackageIDSequence> &) const;
diff --git a/paludis/resolver/decision.cc b/paludis/resolver/decision.cc
index 118c381..842de00 100644
--- a/paludis/resolver/decision.cc
+++ b/paludis/resolver/decision.cc
@@ -30,6 +30,7 @@
#include <paludis/util/wrapped_forward_iterator.hh>
#include <paludis/util/make_null_shared_ptr.hh>
#include <paludis/serialise-impl.hh>
+#include <paludis/changed_choices.hh>
#include <sstream>
using namespace paludis;
@@ -121,6 +122,7 @@ ChangesToMakeDecision::deserialise(Deserialisation & d)
std::shared_ptr<ChangesToMakeDecision> result(std::make_shared<ChangesToMakeDecision>(
v.member<Resolvent>("resolvent"),
v.member<std::shared_ptr<const PackageID> >("origin_id"),
+ v.member<std::shared_ptr<const ChangedChoices> >("if_changed_choices"),
v.member<bool>("best"),
destringify<ChangeType>(v.member<std::string>("change_type")),
v.member<bool>("taken"),
@@ -329,6 +331,7 @@ namespace paludis
{
const Resolvent resolvent;
const std::shared_ptr<const PackageID> origin_id;
+ const std::shared_ptr<const ChangedChoices> changed_choices;
const bool best;
ChangeType change_type;
const bool taken;
@@ -339,12 +342,14 @@ namespace paludis
Imp(
const Resolvent & l,
const std::shared_ptr<const PackageID> & o,
+ const std::shared_ptr<const ChangedChoices> & h,
const bool b,
const ChangeType c,
const bool t,
const std::shared_ptr<const Destination> & d) :
resolvent(l),
origin_id(o),
+ changed_choices(h),
best(b),
change_type(c),
taken(t),
@@ -357,12 +362,13 @@ namespace paludis
ChangesToMakeDecision::ChangesToMakeDecision(
const Resolvent & r,
const std::shared_ptr<const PackageID> & o,
+ const std::shared_ptr<const ChangedChoices> & h,
const bool b,
const ChangeType c,
const bool t,
const std::shared_ptr<const Destination> & d,
const std::function<void (ChangesToMakeDecision &)> & f) :
- Pimp<ChangesToMakeDecision>(r, o, b, c, t, d)
+ Pimp<ChangesToMakeDecision>(r, o, h, b, c, t, d)
{
if (f)
f(*this);
@@ -402,6 +408,12 @@ ChangesToMakeDecision::origin_id() const
return _imp->origin_id;
}
+const std::shared_ptr<const ChangedChoices>
+ChangesToMakeDecision::if_changed_choices() const
+{
+ return _imp->changed_choices;
+}
+
ChangeType
ChangesToMakeDecision::change_type() const
{
@@ -450,6 +462,7 @@ ChangesToMakeDecision::serialise(Serialiser & s) const
s.object("ChangesToMakeDecision")
.member(SerialiserFlags<>(), "resolvent", resolvent())
.member(SerialiserFlags<serialise::might_be_null>(), "origin_id", origin_id())
+ .member(SerialiserFlags<serialise::might_be_null>(), "if_changed_choices", if_changed_choices())
.member(SerialiserFlags<>(), "best", best())
.member(SerialiserFlags<>(), "change_type", stringify(change_type()))
.member(SerialiserFlags<serialise::might_be_null>(), "destination", destination())
diff --git a/paludis/resolver/decision.hh b/paludis/resolver/decision.hh
index dbabf68..eab8fee 100644
--- a/paludis/resolver/decision.hh
+++ b/paludis/resolver/decision.hh
@@ -30,7 +30,9 @@
#include <paludis/util/simple_visitor.hh>
#include <paludis/util/type_list.hh>
#include <paludis/serialise-fwd.hh>
-#include <paludis/package_id.hh>
+#include <paludis/package_id-fwd.hh>
+#include <paludis/changed_choices-fwd.hh>
+#include <paludis/name-fwd.hh>
namespace paludis
{
@@ -150,6 +152,7 @@ namespace paludis
ChangesToMakeDecision(
const Resolvent &,
const std::shared_ptr<const PackageID> &,
+ const std::shared_ptr<const ChangedChoices> &,
const bool best,
const ChangeType,
const bool taken,
@@ -167,6 +170,9 @@ namespace paludis
const std::shared_ptr<const PackageID> origin_id() const
PALUDIS_ATTRIBUTE((warn_unused_result));
+ const std::shared_ptr<const ChangedChoices> if_changed_choices() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
const std::shared_ptr<const RepositoryName> if_via_new_binary_in() const
PALUDIS_ATTRIBUTE((warn_unused_result));
diff --git a/paludis/resolver/orderer.cc b/paludis/resolver/orderer.cc
index 2e98cdb..a2e1209 100644
--- a/paludis/resolver/orderer.cc
+++ b/paludis/resolver/orderer.cc
@@ -47,6 +47,7 @@
#include <paludis/util/enum_iterator.hh>
#include <paludis/environment.hh>
#include <paludis/notifier_callback.hh>
+#include <paludis/package_id.hh>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
diff --git a/paludis/resolver/sanitised_dependencies.cc b/paludis/resolver/sanitised_dependencies.cc
index 7cd60af..34f7367 100644
--- a/paludis/resolver/sanitised_dependencies.cc
+++ b/paludis/resolver/sanitised_dependencies.cc
@@ -60,6 +60,7 @@ namespace
struct MakeAnyOfStringVisitor
{
std::string result;
+ const std::shared_ptr<const ChangedChoices> changed_choices;
void visit(const DependencySpecTree::NodeType<NamedSetDepSpec>::Type & s)
{
@@ -83,9 +84,9 @@ namespace
void visit(const DependencySpecTree::NodeType<ConditionalDepSpec>::Type & node)
{
- if (node.spec()->condition_met())
+ if (changed_choices ? node.spec()->condition_would_be_met_when(*changed_choices) : node.spec()->condition_met())
{
- MakeAnyOfStringVisitor v;
+ MakeAnyOfStringVisitor v{"", changed_choices};
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(v));
result.append(" " + stringify(*node.spec()) + " (" + v.result + " )");
}
@@ -93,14 +94,14 @@ namespace
void visit(const DependencySpecTree::NodeType<AnyDepSpec>::Type & node)
{
- MakeAnyOfStringVisitor v;
+ MakeAnyOfStringVisitor v{"", changed_choices};
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(v));
result.append(" || (" + v.result + " )");
}
void visit(const DependencySpecTree::NodeType<AllDepSpec>::Type & node)
{
- MakeAnyOfStringVisitor v;
+ MakeAnyOfStringVisitor v{"", changed_choices};
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(v));
result.append(" (" + v.result + " )");
}
@@ -111,6 +112,7 @@ namespace
const Decider & decider;
const std::shared_ptr<const Resolution> our_resolution;
const std::shared_ptr<const PackageID> our_id;
+ const std::shared_ptr<const ChangedChoices> changed_choices;
const std::function<SanitisedDependency (const PackageOrBlockDepSpec &)> parent_make_sanitised;
bool super_complicated, nested;
@@ -122,10 +124,12 @@ namespace
AnyDepSpecChildHandler(const Decider & r, const std::shared_ptr<const Resolution> & q,
const std::shared_ptr<const PackageID> & o,
+ const std::shared_ptr<const ChangedChoices> & c,
const std::function<SanitisedDependency (const PackageOrBlockDepSpec &)> & f) :
decider(r),
our_resolution(q),
our_id(o),
+ changed_choices(c),
parent_make_sanitised(f),
super_complicated(false),
nested(false),
@@ -183,7 +187,7 @@ namespace
void visit(const DependencySpecTree::NodeType<ConditionalDepSpec>::Type & node)
{
- if (node.spec()->condition_met())
+ if (changed_choices ? node.spec()->condition_would_be_met_when(*changed_choices) : node.spec()->condition_met())
{
nested = true;
@@ -214,7 +218,7 @@ namespace
void visit(const DependencySpecTree::NodeType<AnyDepSpec>::Type & node)
{
- AnyDepSpecChildHandler h(decider, our_resolution, our_id, parent_make_sanitised);
+ AnyDepSpecChildHandler h(decider, our_resolution, our_id, changed_choices, parent_make_sanitised);
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(h));
std::list<SanitisedDependency> l;
h.commit(
@@ -302,6 +306,7 @@ namespace
const Decider & decider;
const std::shared_ptr<const Resolution> our_resolution;
const std::shared_ptr<const PackageID> & our_id;
+ const std::shared_ptr<const ChangedChoices> & changed_choices;
SanitisedDependencies & sanitised_dependencies;
const std::string raw_name;
const std::string human_name;
@@ -313,6 +318,7 @@ namespace
const Decider & r,
const std::shared_ptr<const Resolution> & q,
const std::shared_ptr<const PackageID> & f,
+ const std::shared_ptr<const ChangedChoices> & c,
SanitisedDependencies & s,
const std::shared_ptr<const DependenciesLabelSequence> & l,
const std::string & rn,
@@ -322,6 +328,7 @@ namespace
decider(r),
our_resolution(q),
our_id(f),
+ changed_choices(c),
sanitised_dependencies(s),
raw_name(rn),
human_name(hn),
@@ -371,7 +378,7 @@ namespace
void visit(const DependencySpecTree::NodeType<ConditionalDepSpec>::Type & node)
{
- if (node.spec()->condition_met())
+ if (changed_choices ? node.spec()->condition_would_be_met_when(*changed_choices) : node.spec()->condition_met())
{
labels_stack.push_front(*labels_stack.begin());
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
@@ -391,12 +398,12 @@ namespace
Save<std::string> save_original_specs_as_string(&original_specs_as_string);
{
- MakeAnyOfStringVisitor v;
+ MakeAnyOfStringVisitor v{"", changed_choices};
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(v));
original_specs_as_string = "|| (" + v.result + " )";
}
- AnyDepSpecChildHandler h(decider, our_resolution, our_id,
+ AnyDepSpecChildHandler h(decider, our_resolution, our_id, changed_choices,
std::bind(&Finder::make_sanitised, this, std::placeholders::_1));
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(h));
h.commit(
@@ -453,12 +460,13 @@ SanitisedDependencies::_populate_one(
const Decider & decider,
const std::shared_ptr<const Resolution> & resolution,
const std::shared_ptr<const PackageID> & id,
+ const std::shared_ptr<const ChangedChoices> & changed,
const std::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > (PackageID::* const pmf) () const
)
{
Context context("When finding dependencies for '" + stringify(*id) + "' from key '" + ((*id).*pmf)()->raw_name() + "':");
- Finder f(env, decider, resolution, id, *this, ((*id).*pmf)()->initial_labels(), ((*id).*pmf)()->raw_name(),
+ Finder f(env, decider, resolution, id, changed, *this, ((*id).*pmf)()->initial_labels(), ((*id).*pmf)()->raw_name(),
((*id).*pmf)()->human_name(), "");
((*id).*pmf)()->value()->root()->accept(f);
}
@@ -468,22 +476,23 @@ SanitisedDependencies::populate(
const Environment * const env,
const Decider & decider,
const std::shared_ptr<const Resolution> & resolution,
- const std::shared_ptr<const PackageID> & id)
+ const std::shared_ptr<const PackageID> & id,
+ const std::shared_ptr<const ChangedChoices> & changed)
{
Context context("When finding dependencies for '" + stringify(*id) + "':");
if (id->dependencies_key())
- _populate_one(env, decider, resolution, id, &PackageID::dependencies_key);
+ _populate_one(env, decider, resolution, id, changed, &PackageID::dependencies_key);
else
{
if (id->build_dependencies_key())
- _populate_one(env, decider, resolution, id, &PackageID::build_dependencies_key);
+ _populate_one(env, decider, resolution, id, changed, &PackageID::build_dependencies_key);
if (id->run_dependencies_key())
- _populate_one(env, decider, resolution, id, &PackageID::run_dependencies_key);
+ _populate_one(env, decider, resolution, id, changed, &PackageID::run_dependencies_key);
if (id->post_dependencies_key())
- _populate_one(env, decider, resolution, id, &PackageID::post_dependencies_key);
+ _populate_one(env, decider, resolution, id, changed, &PackageID::post_dependencies_key);
if (id->suggested_dependencies_key())
- _populate_one(env, decider, resolution, id, &PackageID::suggested_dependencies_key);
+ _populate_one(env, decider, resolution, id, changed, &PackageID::suggested_dependencies_key);
}
}
diff --git a/paludis/resolver/sanitised_dependencies.hh b/paludis/resolver/sanitised_dependencies.hh
index 57e8c6c..a81ae62 100644
--- a/paludis/resolver/sanitised_dependencies.hh
+++ b/paludis/resolver/sanitised_dependencies.hh
@@ -70,6 +70,7 @@ namespace paludis
const Decider &,
const std::shared_ptr<const Resolution> &,
const std::shared_ptr<const PackageID> &,
+ const std::shared_ptr<const ChangedChoices> &,
const std::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > (PackageID::* const) () const
);
@@ -81,7 +82,8 @@ namespace paludis
const Environment * const,
const Decider &,
const std::shared_ptr<const Resolution> &,
- const std::shared_ptr<const PackageID> &);
+ const std::shared_ptr<const PackageID> &,
+ const std::shared_ptr<const ChangedChoices> &);
void add(const SanitisedDependency & d);
diff --git a/src/clients/cave/resolve_common.cc b/src/clients/cave/resolve_common.cc
index 8f369d7..edd2682 100644
--- a/src/clients/cave/resolve_common.cc
+++ b/src/clients/cave/resolve_common.cc
@@ -77,6 +77,7 @@
#include <paludis/selection_cache.hh>
#include <paludis/package_dep_spec_properties.hh>
#include <paludis/elike_slot_requirement.hh>
+#include <paludis/package_id.hh>
#include <algorithm>
#include <iostream>