/************************************************************************************ * * * Copyright (c) 2014 - 2018 Axel Menzel * * * * This file is part of RTTR (Run Time Type Reflection) * * License: MIT License * * * * Permission is hereby granted, free of charge, to any person obtaining * * a copy of this software and associated documentation files (the "Software"), * * to deal in the Software without restriction, including without limitation * * the rights to use, copy, modify, merge, publish, distribute, sublicense, * * and/or sell copies of the Software, and to permit persons to whom the * * Software is furnished to do so, subject to the following conditions: * * * * The above copyright notice and this permission notice shall be included in * * all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * * SOFTWARE. * * * *************************************************************************************/ #ifndef RTTR_ASSOCIATIVE_MAPPER_IMPL_H_ #define RTTR_ASSOCIATIVE_MAPPER_IMPL_H_ #include "rttr/detail/base/core_prerequisites.h" #include "rttr/detail/misc/iterator_wrapper.h" #include "rttr/argument.h" #include "rttr/variant.h" #include #include #include #include #include namespace rttr { namespace detail { ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// template::value, typename associative_container_mapper::const_itr_t, typename associative_container_mapper::itr_t>> struct associative_container_mapper_wrapper : iterator_wrapper_base { using base_class = associative_container_mapper; using key_t = typename base_class::key_t; using value_t = typename base_class::value_t; using itr_t = typename base_class::itr_t; using const_itr_t = typename base_class::const_itr_t; using itr_wrapper = iterator_wrapper_base; static ConstType& get_container(void* container) { return *reinterpret_cast(container); } static variant get_key(const iterator_data& itr) { auto& it = itr_wrapper::get_iterator(itr); return variant(std::ref(base_class::get_key(it))); } template::value, int> = 0> static variant get_value(const iterator_data& itr) { auto& it = itr_wrapper::get_iterator(itr); return variant(std::ref(base_class::get_value(it))); } template::value, int> = 0> static variant get_value(const iterator_data& itr) { return variant(); } static void begin(void* container, iterator_data& itr) { itr_wrapper::create(itr, base_class::begin(get_container(container))); } static void end(void* container, iterator_data& itr) { itr_wrapper::create(itr, base_class::end(get_container(container))); } static bool is_empty(void* container) { return base_class::is_empty(get_container(container)); } static std::size_t get_size(void* container) { return base_class::get_size(get_container(container)); } static void find(void* container, iterator_data& itr, argument& key) { if (key.get_type() == ::rttr::type::get()) itr_wrapper::create(itr, base_class::find(get_container(container), key.get_value())); else end(container, itr); } ///////////////////////////////////////////////////////////////////////// template::value, int> = 0> static void clear(void* container) { base_class::clear(get_container(container)); } template::value, int> = 0> static void clear(void* container) { // cannot clear a const container... } ///////////////////////////////////////////////////////////////////////// static void equal_range(void* container, argument& key, iterator_data& itr_begin, iterator_data& itr_end) { if (key.get_type() == ::rttr::type::get()) { auto ret = base_class::equal_range(get_container(container), key.get_value()); itr_wrapper::create(itr_begin, ret.first); itr_wrapper::create(itr_end, ret.second); } else { end(container, itr_begin); end(container, itr_end); } } ///////////////////////////////////////////////////////////////////////// template::value, int> = 0> static std::size_t erase(void* container, argument& key) { if (key.get_type() == ::rttr::type::get()) { return base_class::erase(get_container(container), key.get_value()); } else { return 0; } } template::value, int> = 0> static std::size_t erase(void* container, argument& key) { return 0; } ///////////////////////////////////////////////////////////////////////// template::value && !std::is_const::value, int> = 0> static bool insert_key(void* container, argument& key, iterator_data& itr) { if (key.get_type() == ::rttr::type::get()) { auto ret = base_class::insert_key(get_container(container), key.get_value()); itr_wrapper::create(itr, ret.first); return ret.second; } else { end(container, itr); return false; } } template::value || std::is_const::value, int> = 0> static bool insert_key(void* container, argument& key, iterator_data& itr) { end(container, itr); return false; } ///////////////////////////////////////////////////////////////////////// template::value && !std::is_const::value, int> = 0> static bool insert_key_value(void* container, argument& key, argument& value, iterator_data& itr) { if (key.get_type() == ::rttr::type::get() && value.get_type() == ::rttr::type::get()) { auto ret = base_class::insert_key_value(get_container(container), key.get_value(), value.get_value()); itr_wrapper::create(itr, ret.first); return ret.second; } else { end(container, itr); return false; } } template::value || std::is_const::value, int> = 0> static bool insert_key_value(void* container, argument& key, argument& value, iterator_data& itr) { end(container, itr); return false; } }; ////////////////////////////////////////////////////////////////////////////////////////// template struct associative_container_base { using container_t = T; using key_t = typename T::key_type; using value_t = typename associative_container_value_t::type; using itr_t = typename T::iterator; using const_itr_t = typename T::const_iterator; static const key_t& get_key(const const_itr_t& itr) { return itr->first; } ///////////////////////////////////////////////////////////////////////////////////// static itr_t begin(container_t& container) { return container.begin(); } static const_itr_t begin(const container_t& container) { return container.begin(); } ///////////////////////////////////////////////////////////////////////////////////// static itr_t end(container_t& container) { return container.end(); } static const_itr_t end(const container_t& container) { return container.end(); } ///////////////////////////////////////////////////////////////////////////////////// static itr_t find(container_t& container, const key_t& key) { return container.find(key); } static const_itr_t find(const container_t& container, const key_t& key) { return container.find(key); } ///////////////////////////////////////////////////////////////////////////////////// static std::pair equal_range(container_t& container, const key_t& key) { return container.equal_range(key); } static std::pair equal_range(const container_t& container, const key_t& key) { return container.equal_range(key); } ///////////////////////////////////////////////////////////////////////////////////// static void clear(container_t& container) { container.clear(); } static bool is_empty(const container_t& container) { return container.empty(); } static std::size_t get_size(const container_t& container) { return container.size(); } static std::size_t erase(container_t& container, const key_t& key) { return container.erase(key); } static std::pair insert_key(container_t& container, const key_t& key) { return {container.end(), false}; } }; ////////////////////////////////////////////////////////////////////////////////////// template struct associative_container_map_base : associative_container_base { using container_t = typename associative_container_base::container_t; using key_t = typename associative_container_base::key_t; using value_t = typename associative_container_base::value_t; using itr_t = typename associative_container_base::itr_t; using const_itr_t = typename associative_container_base::const_itr_t; static value_t& get_value(itr_t& itr) { return itr->second; } static const value_t& get_value(const const_itr_t& itr) { return itr->second; } static std::pair insert_key_value(container_t& container, const key_t& key, const value_t& value) { return container.insert(std::make_pair(key, value)); } }; ////////////////////////////////////////////////////////////////////////////////////// template struct associative_container_key_base : associative_container_base { using container_t = typename associative_container_base::container_t; using key_t = typename T::key_type; using value_t = void; using itr_t = typename T::iterator; using const_itr_t = typename T::const_iterator; static const key_t& get_key(const const_itr_t& itr) { return *itr; } static std::pair insert_key(container_t& container, const key_t& key) { return container.insert(key); } }; ////////////////////////////////////////////////////////////////////////////////////// template struct associative_container_base_multi : associative_container_base { using container_t = typename associative_container_base::container_t; using key_t = typename T::key_type; using value_t = typename T::mapped_type; using itr_t = typename T::iterator; using const_itr_t = typename T::const_iterator; static value_t& get_value(itr_t& itr) { return itr->second; } static const value_t& get_value(const const_itr_t& itr) { return itr->second; } static std::pair insert_key_value(container_t& container, const key_t& key, const value_t& value) { return {container.insert(std::make_pair(key, value)), true}; } }; ////////////////////////////////////////////////////////////////////////////////////// template struct associative_container_key_base_multi : associative_container_key_base { using container_t = typename associative_container_key_base::container_t; using key_t = typename T::key_type; using itr_t = typename T::iterator; static std::pair insert_key(container_t& container, const key_t& key) { return {container.insert(key), true}; } }; ////////////////////////////////////////////////////////////////////////////////////// } // end namespace detail ////////////////////////////////////////////////////////////////////////////////////// template struct associative_container_mapper> : detail::associative_container_key_base> {}; ////////////////////////////////////////////////////////////////////////////////////// template struct associative_container_mapper> : detail::associative_container_key_base_multi> {}; ////////////////////////////////////////////////////////////////////////////////////// template struct associative_container_mapper> : detail::associative_container_map_base> { }; ////////////////////////////////////////////////////////////////////////////////////// template struct associative_container_mapper> : detail::associative_container_base_multi> {}; ////////////////////////////////////////////////////////////////////////////////////// template struct associative_container_mapper> : detail::associative_container_key_base> {}; ////////////////////////////////////////////////////////////////////////////////////// template struct associative_container_mapper> : detail::associative_container_map_base> {}; ////////////////////////////////////////////////////////////////////////////////////// template struct associative_container_mapper> : detail::associative_container_key_base_multi> {}; ////////////////////////////////////////////////////////////////////////////////////// template struct associative_container_mapper> : detail::associative_container_base_multi> {}; ////////////////////////////////////////////////////////////////////////////////////// namespace detail { struct associative_container_empty { static void create(iterator_data& itr_tgt, const iterator_data& src) { } static void advance(iterator_data& itr, std::ptrdiff_t idx) { } static void destroy(iterator_data& itr) { } static bool equal(const iterator_data& lhs_itr, const iterator_data& rhs_itr) RTTR_NOEXCEPT { return true; } static variant get_key(const iterator_data& itr) { return variant(); } static variant get_value(const iterator_data& itr) { return variant(); } static void begin(void* container, iterator_data& itr) { } static bool is_empty(void* container) { return true; } static std::size_t get_size(void* container) { return 0; } static void find(void* container, iterator_data& itr, argument& arg) { } static std::size_t erase(void* container, argument& arg) { return 0; } static void clear(void* container) { } static void equal_range(void* container, argument& key, iterator_data& itr_begin, iterator_data& itr_end) { } static bool insert_key(void* container, argument& key, iterator_data& itr) { return false; } static bool insert_key_value(void* container, argument& key, argument& value, iterator_data& itr) { return false; } }; } // end namespace detail } // end namespace rttr #endif // RTTR_ASSOCIATIVE_MAPPER_H_