#ifndef __bootstrap_stl_hpp #define __bootstrap_stl_hpp__ #include "dispatchkit.hpp" #include "register_function.hpp" namespace dispatchkit { template struct Input_Range { Input_Range(Container &c) : m_begin(c.begin()), m_end(c.end()) { } Input_Range(typename Container::iterator itr) : m_begin(itr), m_end(itr) { } Input_Range(const std::pair &t_p) : m_begin(t_p.first), m_end(t_p.second) { } bool empty() const { return m_begin == m_end; } void pop_front() { if (empty()) { throw std::range_error("Range empty"); } ++m_begin; } typename std::iterator_traits::reference front() const { if (empty()) { throw std::range_error("Range empty"); } return *m_begin; } typename Container::iterator m_begin; typename Container::iterator m_end; }; template void bootstrap_input_range(Dispatch_Engine &system, const std::string &type) { system.register_type >(type+"_Range"); system.register_type(type+"_Iterator"); system.register_function(build_constructor, ContainerType &>(), "range"); system.register_function(build_constructor, typename ContainerType::iterator>(), "range"); typedef std::pair ItrPair; system.register_function(build_constructor, const ItrPair &>(), "range"); system.register_type(type+"_Iterator_Pair"); register_function(system, &Input_Range::empty, "empty"); register_function(system, &Input_Range::pop_front, "pop_front"); register_function(system, &Input_Range::front, "front"); system.register_function(build_constructor, const Input_Range &>(), "clone"); } template void bootstrap_reversible_container(Dispatch_Engine &/*system*/, const std::string &/*type*/) { } template void bootstrap_random_access_container(Dispatch_Engine &system, const std::string &type) { bootstrap_reversible_container(system, type); typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t); //In the interest of runtime safety for the system, we prefer the at() method for [] access, //to throw an exception in an out of bounds condition. system.register_function( boost::function(indexoper(&ContainerType::at)), "[]"); system.register_function( boost::function(indexoper(&ContainerType::operator[])), "at"); } template void bootstrap_assignable(Dispatch_Engine &system, const std::string &type) { add_basic_constructors(system, type); add_oper_assign(system); } template void bootstrap_container(Dispatch_Engine &system, const std::string &type) { bootstrap_assignable(system, type); register_function(system, &ContainerType::size, "size"); register_function(system, &ContainerType::max_size, "max_size"); register_function(system, &ContainerType::empty, "empty"); } template void bootstrap_forward_container(Dispatch_Engine &system, const std::string &type) { bootstrap_input_range(system, type); bootstrap_container(system, type); } template void bootstrap_default_constructible(Dispatch_Engine &system, const std::string &type) { system.register_function(build_constructor(), type); } template void insert_at(Type &container, int pos, const typename Type::value_type &v) { typename Type::iterator itr = container.begin(); typename Type::iterator end = container.end(); if (pos < 0 || std::distance(itr, end) < pos) { throw std::range_error("Cannot insert past end of range"); } std::advance(itr, pos); container.insert(itr, v); } template void erase_at(Type &container, int pos) { typename Type::iterator itr = container.begin(); typename Type::iterator end = container.end(); if (pos < 0 || std::distance(itr, end) < (pos-1)) { throw std::range_error("Cannot erase past end of range"); } std::advance(itr, pos); container.erase(itr); } template void bootstrap_sequence(Dispatch_Engine &system, const std::string &type) { bootstrap_forward_container(system, type); bootstrap_default_constructible(system, type); std::string insert_name; if (typeid(typename SequenceType::value_type) == typeid(Boxed_Value)) { insert_name = "insert_ref_at"; } else { insert_name = "insert_at"; } register_function(system, &insert_at, insert_name); register_function(system, &erase_at, "erase_at"); } template void bootstrap_back_insertion_sequence(Dispatch_Engine &system, const std::string &type) { bootstrap_sequence(system, type); typedef typename SequenceType::reference (SequenceType::*backptr)(); system.register_function(boost::function(backptr(&SequenceType::back)), "back"); std::string push_back_name; if (typeid(typename SequenceType::value_type) == typeid(Boxed_Value)) { push_back_name = "push_back_ref"; } else { push_back_name = "push_back"; } register_function(system, &SequenceType::push_back, push_back_name); register_function(system, &SequenceType::pop_back, "pop_back"); } template void bootstrap_vector(Dispatch_Engine &system, const std::string &type) { system.register_type(type); bootstrap_random_access_container(system, type); bootstrap_back_insertion_sequence(system, type); } template void bootstrap_associative_container(Dispatch_Engine &system, const std::string &type) { bootstrap_forward_container(system, type); bootstrap_default_constructible(system, type); } template void bootstrap_pair(Dispatch_Engine &system, const std::string &type) { system.register_type(type); register_member(system, &PairType::first, "first"); register_member(system, &PairType::second, "second"); system.register_function(build_constructor(), type); system.register_function(build_constructor(), type); system.register_function(build_constructor(), "clone"); system.register_function(build_constructor(), type); } template void bootstrap_pair_associative_container(Dispatch_Engine &system, const std::string &type) { bootstrap_associative_container(system, type); bootstrap_pair(system, type + "_Pair"); } template void bootstrap_unique_associative_container(Dispatch_Engine &system, const std::string &type) { bootstrap_associative_container(system, type); register_function(system, &ContainerType::count, "count"); } template void bootstrap_sorted_associative_container(Dispatch_Engine &system, const std::string &type) { typedef std::pair (ContainerType::*eq_range)(const typename ContainerType::key_type &); bootstrap_reversible_container(system, type); bootstrap_associative_container(system, type); register_function(system, eq_range(&ContainerType::equal_range), "equal_range"); } template void bootstrap_unique_sorted_associative_container(Dispatch_Engine &system, const std::string &type) { bootstrap_sorted_associative_container(system, type); bootstrap_unique_associative_container(system, type); } template void bootstrap_map(Dispatch_Engine &system, const std::string &type) { system.register_type(type); register_function(system, &MapType::operator[], "[]"); bootstrap_unique_sorted_associative_container(system, type); bootstrap_pair_associative_container(system, type); } template void bootstrap_string(Dispatch_Engine &system, const std::string &type) { system.register_type(type); add_oper_add(system); add_oper_add_equals(system); add_opers_comparison(system); bootstrap_random_access_container(system, type); bootstrap_sequence(system, type); typedef typename String::size_type (String::*find_func)(const String &, typename String::size_type) const; register_function(system, find_func(&String::find), "find"); register_function(system, find_func(&String::rfind), "rfind"); register_function(system, find_func(&String::find_first_of), "find_first_of"); register_function(system, find_func(&String::find_last_of), "find_last_of"); register_function(system, find_func(&String::find_first_not_of), "find_first_not_of"); register_function(system, find_func(&String::find_last_not_of), "find_last_not_of"); } } #endif