diff --git a/src/formula/callable.hpp b/src/formula/callable.hpp index 82c183fe95f4..8522db9a1584 100644 --- a/src/formula/callable.hpp +++ b/src/formula/callable.hpp @@ -24,20 +24,6 @@ namespace wfl { -enum FORMULA_ACCESS_TYPE { FORMULA_READ_ONLY, FORMULA_WRITE_ONLY, FORMULA_READ_WRITE }; - -struct formula_input -{ - explicit formula_input(const std::string& name, FORMULA_ACCESS_TYPE access = FORMULA_READ_WRITE) - : name(name), access(access) - {} - - std::string name; - FORMULA_ACCESS_TYPE access; -}; - -using formula_input_vector = std::vector; - // Interface for objects that can have formulae run on them class formula_callable { diff --git a/src/formula/callable_fwd.hpp b/src/formula/callable_fwd.hpp index 44ff75135d53..5cccb705c4cf 100644 --- a/src/formula/callable_fwd.hpp +++ b/src/formula/callable_fwd.hpp @@ -23,6 +23,17 @@ namespace wfl class formula_callable; class formula_debugger; +enum FORMULA_ACCESS_TYPE { FORMULA_READ_ONLY, FORMULA_WRITE_ONLY, FORMULA_READ_WRITE }; + +struct formula_input { + explicit formula_input(const std::string& name, FORMULA_ACCESS_TYPE access = FORMULA_READ_WRITE) + : name(name), access(access) {} + + std::string name; + FORMULA_ACCESS_TYPE access; +}; + +using formula_input_vector = std::vector; using formula_callable_ptr = std::shared_ptr; using const_formula_callable_ptr = std::shared_ptr; using formula_seen_stack = std::vector; diff --git a/src/formula/variant.cpp b/src/formula/variant.cpp index 3892c816c729..64fa7b222810 100644 --- a/src/formula/variant.cpp +++ b/src/formula/variant.cpp @@ -119,14 +119,14 @@ variant_iterator variant_iterator::operator++(int) variant_iterator& variant_iterator::operator--() { - container_->iterator_inc(iter_); + container_->iterator_dec(iter_); return *this; } variant_iterator variant_iterator::operator--(int) { variant_iterator temp(*this); - container_->iterator_inc(iter_); + container_->iterator_dec(iter_); return temp; } diff --git a/src/formula/variant_value.cpp b/src/formula/variant_value.cpp index 040e4a0bdbcd..cc0e5c33e9e0 100644 --- a/src/formula/variant_value.cpp +++ b/src/formula/variant_value.cpp @@ -147,35 +147,30 @@ boost::iterator_range variant_callable::make_iterator() const return variant_value_base::make_iterator(); } - std::shared_ptr inputs; - inputs.reset(new formula_input_vector(callable_->inputs())); + if(inputs.empty()) { + callable_->get_inputs(inputs); + } - return {variant_iterator(this, std::make_pair(inputs, inputs->cbegin())), variant_iterator(this, std::make_pair(inputs, inputs->cend()))}; + return {variant_iterator(this, inputs.cbegin()), variant_iterator(this, inputs.cend())}; } -using callable_iter = std::pair, formula_input_vector::const_iterator>; - variant variant_callable::deref_iterator(const boost::any& iter) const { if(!callable_) { return variant(); } - return callable_->query_value(boost::any_cast(iter).second->name); + return callable_->query_value(boost::any_cast(iter)->name); } -boost::any variant_callable::iterator_inc(const boost::any& iter) const +void variant_callable::iterator_inc(boost::any& iter) const { - callable_iter new_iter = boost::any_cast(iter); - ++new_iter.second; - return new_iter; + ++boost::any_cast(iter); } -boost::any variant_callable::iterator_dec(const boost::any& iter) const +void variant_callable::iterator_dec(boost::any& iter) const { - callable_iter new_iter = boost::any_cast(iter); - --new_iter.second; - return new_iter; + --boost::any_cast(iter); } std::string variant_string::get_serialized_string() const @@ -257,19 +252,26 @@ std::string variant_container::get_debug_string(formula_seen_stack& seen, boo } template -boost::any variant_container::iterator_inc(const boost::any& iter) const +void variant_container::iterator_inc(boost::any& iter) const { - typename T::const_iterator new_iter = boost::any_cast(iter); - ++new_iter; - return new_iter; + ++boost::any_cast(iter); } template -boost::any variant_container::iterator_dec(const boost::any& iter) const +void variant_container::iterator_dec(boost::any& iter) const { - typename T::const_iterator new_iter = boost::any_cast(iter); - --new_iter; - return new_iter; + --boost::any_cast(iter); +} + +template +boost::iterator_range variant_container::make_iterator() const +{ + return {variant_iterator(this, get_container().cbegin()), variant_iterator(this, get_container().cend())}; +} + +template +bool variant_container::iterator_equals(const boost::any& first, const boost::any& second) const { + return boost::any_cast(first) == boost::any_cast(second); } // Force compilation of the following template instantiations @@ -326,14 +328,9 @@ bool variant_list::less_than(variant_value_base& other) const return num_elements() < other.num_elements(); } -boost::iterator_range variant_list::make_iterator() const -{ - return {variant_iterator(this, get_container().cbegin()), variant_iterator(this, get_container().cend())}; -} - variant variant_list::deref_iterator(const boost::any& iter) const { - return *boost::any_cast(iter); + return *boost::any_cast(iter); } std::string variant_map::to_string_detail(const variant_map_raw::value_type& container_val, mod_func_t mod_func) const @@ -357,14 +354,9 @@ bool variant_map::less_than(variant_value_base& other) const return get_container() < value_ref_cast(other).get_container(); } -boost::iterator_range variant_map::make_iterator() const -{ - return {variant_iterator(this, get_container().cbegin()), variant_iterator(this, get_container().cend())}; -} - variant variant_map::deref_iterator(const boost::any& iter) const { - const variant_map_raw::value_type& p = *boost::any_cast(iter); + const variant_map_raw::value_type& p = *boost::any_cast(iter); key_value_pair* the_pair = new key_value_pair(p.first, p.second); return variant(the_pair); } diff --git a/src/formula/variant_value.hpp b/src/formula/variant_value.hpp index c5f239023b99..32f9e573baf8 100644 --- a/src/formula/variant_value.hpp +++ b/src/formula/variant_value.hpp @@ -31,7 +31,6 @@ namespace wfl { -class formula_callable; class variant_value_base; class variant_iterator; class variant; @@ -153,17 +152,44 @@ class variant_value_base } /** - * Iterator interface. + * Creates an iterator pair that can be used for iteration. + * For an iterable type, it should use the two-argument constructor of variant-iterator, + * passing the underlying iterator as the boost::any parameter. * - * These implement functionality used by @ref variant_iterator to operator on - * iterators of the given value type - hence the use of boost::any here. + * This creates both the begin and end iterator, but the variant implementation + * discards one of the two. */ virtual boost::iterator_range make_iterator() const; + /** + * Implements the dereference functionality of @ref variant_iterator + * for a value of this type. + * + * @param iter The opaque reference that was passed to the variant_iterator by @ref make_iterator. + */ virtual variant deref_iterator(const boost::any& iter) const; - - virtual boost::any iterator_inc(const boost::any& iter) const { return iter; } - virtual boost::any iterator_dec(const boost::any& iter) const { return iter; } - + /** + * Implements the increment functionality of @ref variant_iterator + * for a value of this type. + * + * @param iter The opaque reference that was passed to the variant_iterator by @ref make_iterator. + */ + virtual void iterator_inc(boost::any&) const {} + /** + * Implements the decrement functionality of @ref variant_iterator + * for a value of this type. + * + * @param iter The opaque reference that was passed to the variant_iterator by @ref make_iterator. + */ + virtual void iterator_dec(boost::any&) const {} + /** + * Implements the equality functionality of @ref variant_iterator + * for a value of this type. + * + * Note that this is only called if the two iterators are already known to be of the same type. + * + * @param first The opaque reference that was passed to the variant_iterator by @ref make_iterator. + * @param second The opaque reference that was passed to the variant_iterator by @ref make_iterator. + */ virtual bool iterator_equals(const boost::any& /*first*/, const boost::any& /*second*/) const { return true; @@ -320,8 +346,8 @@ class variant_callable : public variant_value_base virtual boost::iterator_range make_iterator() const override; virtual variant deref_iterator(const boost::any& iter) const override; - virtual boost::any iterator_inc(const boost::any& iter) const override; - virtual boost::any iterator_dec(const boost::any& iter) const override; + virtual void iterator_inc(boost::any& iter) const override; + virtual void iterator_dec(boost::any& iter) const override; virtual bool iterator_equals(const boost::any& /*first*/, const boost::any& /*second*/) const { @@ -330,6 +356,7 @@ class variant_callable : public variant_value_base private: const formula_callable* callable_; + mutable formula_input_vector inputs; // for iteration }; @@ -440,14 +467,11 @@ class variant_container : public variant_value_base } // We implement these in the here since the interface is the same for all - // specializations and leave the other functions to the derived classes. - virtual boost::any iterator_inc(const boost::any&) const override; - virtual boost::any iterator_dec(const boost::any&) const override; - - virtual bool iterator_equals(const boost::any& first, const boost::any& second) const override - { - return boost::any_cast(first) == boost::any_cast(second); - } + // specializations and leave the deref function to the derived classes. + virtual boost::iterator_range make_iterator() const override; + virtual void iterator_inc(boost::any&) const override; + virtual void iterator_dec(boost::any&) const override; + virtual bool iterator_equals(const boost::any& first, const boost::any& second) const override; protected: using mod_func_t = std::function; @@ -488,7 +512,6 @@ class variant_list : public variant_container return type; } - virtual boost::iterator_range make_iterator() const override; virtual variant deref_iterator(const boost::any&) const override; private: @@ -515,7 +538,6 @@ class variant_map : public variant_container return type; } - virtual boost::iterator_range make_iterator() const; virtual variant deref_iterator(const boost::any&) const; private: