Advertisement
Guest User

Untitled

a guest
Nov 15th, 2019
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 24.68 KB | None | 0 0
  1. #pragma once
  2. #include <functional>
  3. #include <memory>
  4. #include <utility>
  5. #include <iostream>
  6. #include <memory>
  7.  
  8. #include <useful/base.hpp>
  9.  
  10. using namespace uf::sized;
  11.  
  12. namespace hm
  13. {
  14.     template<typename Tp, typename Allocator = std::allocator<Tp>>
  15.     class storage
  16.     {
  17.     public:
  18.         using value_type = Tp;
  19.         using pointer = value_type*;
  20.         using const_pointer = const value_type*;
  21.         using allocator_type = Allocator;
  22.         using size_type = u64;
  23.  
  24.     private:
  25.         allocator_type m_allocator;
  26.         std::vector<u8, allocator_type> m_constructed;
  27.         pointer m_data = nullptr;
  28.         size_type m_constructed_count = 0;
  29.  
  30.     public:
  31.         storage() = default;
  32.  
  33.         template<typename A>
  34.         storage(const storage& other, A&& allocator) : m_allocator(std::forward<A>(allocator)), m_constructed(other.m_constructed), m_data(m_allocator.allocate(other.size()))
  35.         {
  36.             for (size_type i = 0; i < size(); ++i)
  37.                 if (m_constructed[i])
  38.                     construct(i, other.m_data[i]);
  39.         }
  40.  
  41.         storage(const storage& other) : storage(other, std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.get_allocator())) { }
  42.  
  43.         template<typename A>
  44.         storage(storage&& other, A&& allocator) noexcept : m_allocator(std::forward<A>(allocator)), m_constructed(std::move(other.m_constructed)), m_data(std::move(other.m_data))
  45.         {
  46.             other.self_destruction();
  47.         }
  48.  
  49.         storage(storage&& other) noexcept : storage(std::move(other), std::move(other.m_allocator)) { }
  50.  
  51.         template<typename A>
  52.         storage(A&& allocator, size_type size) : m_allocator(std::forward<A>(allocator)),  m_constructed(size, 0, m_allocator), m_data(m_allocator.allocate(size)) { }
  53.  
  54.         template<typename A>
  55.         storage(A&& allocator) : storage(std::forward<A>(allocator), 0) { }
  56.  
  57.         storage(size_type size) : storage(Allocator(), size) { }
  58.  
  59.         storage& operator=(const storage& other)
  60.         {
  61.             if (std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value || m_allocator == other.m_allocator)
  62.             {
  63.                 m_allocator = other.m_allocator;
  64.                 self_destruction();
  65.             }
  66.             else
  67.             {
  68.                 self_destruction();
  69.                 m_allocator = other.m_allocator;
  70.             }
  71.             m_data = m_allocator.allocate(other.m_constructed.size());
  72.             m_constructed = other.m_constructed;
  73.             for (size_type i = 0; i < m_constructed.size(); ++i)
  74.                 if (m_constructed[i])
  75.                     new(m_data + i) value_type(other.m_data[i]);
  76.             return *this;
  77.         }
  78.  
  79.         storage& operator=(storage&& other) noexcept
  80.         {
  81.             if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
  82.             {
  83.                 m_allocator = other.m_allocator;
  84.                 self_destruction();
  85.             }
  86.             else
  87.             {
  88.                 if (m_allocator == other.m_allocator)
  89.                 {
  90.                     m_allocator = std::move(other.m_allocator);
  91.                     self_destruction();
  92.                 }
  93.                 else
  94.                 {
  95.                     self_destruction();
  96.                     m_allocator = std::move(other.m_allocator);
  97.                 }
  98.             }
  99.             m_data = std::move(other.m_data);
  100.             m_constructed = std::move(other.m_constructed);
  101.             other.m_data = nullptr;
  102.             return *this;
  103.         }
  104.  
  105.         ~storage() noexcept
  106.         {
  107.             self_destruction();
  108.         }
  109.  
  110.         void resize(size_type size)
  111.         {
  112.             if (size <= m_constructed.size())
  113.                 return; // TODO
  114.             auto new_data = m_allocator.allocate(size);
  115.             for (size_type i = 0; i < m_constructed.size(); ++i)
  116.             {
  117.                 if (m_constructed[i])
  118.                 {
  119.                     new(new_data + i) value_type(m_data[i]);
  120.                     destruct(i);
  121.                 }
  122.             }
  123.             m_constructed.resize(size, 0);
  124.             m_allocator.deallocate(m_data);
  125.             m_data = new_data;
  126.         }
  127.  
  128.         template<typename... Args>
  129.         void construct(size_type index, Args&&... args)
  130.         {
  131.             new(m_data + index) value_type(std::forward<Args>(args)...);
  132.             m_constructed[index] = 1;
  133.             ++m_constructed_count;
  134.         }
  135.  
  136.         template<typename... Args>
  137.         void assign(size_type index, Args&&... args)
  138.         {
  139.             m_data[index] = value_type(std::forward<Args>(args)...);
  140.         }
  141.  
  142.         template<typename... Args>
  143.         void construct_or_assign(size_type index, Args&&... args)
  144.         {
  145.             if (is_constructed(index))
  146.                 assign(index, std::forward<Args>(args)...);
  147.             else
  148.                 construct(index, std::forward<Args>(args)...);
  149.         }
  150.  
  151.         void destruct(size_type index) noexcept
  152.         {
  153.             if (!m_constructed[index])
  154.                 return;
  155.             std::destroy_at(m_data + index);
  156.             m_constructed[index] = 0;
  157.             --m_constructed_count;
  158.         }
  159.  
  160.         bool is_constructed(size_type index) const noexcept
  161.         {
  162.             return m_constructed[index];
  163.         }
  164.  
  165.         allocator_type get_allocator() const noexcept
  166.         {
  167.             return m_allocator;
  168.         }
  169.  
  170.         size_type size() const noexcept
  171.         {
  172.             return m_constructed.size();
  173.         }
  174.  
  175.         size_type constructed_count() const noexcept
  176.         {
  177.             return m_constructed_count;
  178.         }
  179.  
  180.         const Tp* data() const noexcept
  181.         {
  182.             return m_data;
  183.         }
  184.  
  185.         Tp* data() noexcept
  186.         {
  187.             return m_data;
  188.         }
  189.  
  190.         const Tp& operator[](u64 index) const noexcept
  191.         {
  192.             return m_data[index];
  193.         }
  194.  
  195.         Tp& operator[](u64 index) noexcept
  196.         {
  197.             return m_data[index];
  198.         }
  199.  
  200.     private:
  201.         void self_destruction() noexcept
  202.         {
  203.             if (!m_data)
  204.                 return;
  205.             for (size_type i = 0; i < size(); ++i)
  206.                 if (m_constructed[i])
  207.                     destruct(i);
  208.             m_allocator.deallocate(m_data, size());
  209.             m_data = nullptr;
  210.         }
  211.     };
  212.  
  213.     template<typename T>
  214.     class allocator
  215.     {
  216.     public:
  217.         using size_type = std::size_t;
  218.         using difference_type = std::ptrdiff_t;
  219.         using pointer = T*;
  220.         using const_pointer = const T*;
  221.         using reference = typename std::add_lvalue_reference<T>::type;
  222.         using const_reference = typename std::add_lvalue_reference<const T>::type;
  223.         using value_type = T;
  224.  
  225.     public:
  226.         allocator() noexcept = default;
  227.  
  228.         allocator(const allocator&) noexcept = default;
  229.  
  230.         template <class U>
  231.         allocator(const allocator<U>&) noexcept { }
  232.  
  233.         ~allocator() = default;
  234.  
  235.         pointer allocate(size_type n)
  236.         {
  237.             return static_cast<pointer>(::operator new(n * sizeof(value_type)));
  238.         }
  239.  
  240.         void deallocate(pointer p, size_type) noexcept
  241.         {
  242.             ::operator delete(p);
  243.         }
  244.  
  245.         bool operator==(const allocator&)
  246.         {
  247.             return true;
  248.         }
  249.  
  250.         bool operator!=(const allocator&)
  251.         {
  252.             return true;
  253.         }
  254.     };
  255.  
  256.     enum class cell_state : u8
  257.     {
  258.         presented, erased, non_init
  259.     };
  260.  
  261.     template<typename Tp>
  262.     class hash_map_iterator
  263.     {
  264.     public:
  265.         using iterator_category = std::forward_iterator_tag;
  266.         using value_type = Tp;
  267.         using difference_type = std::ptrdiff_t;
  268.         using reference = value_type&;
  269.         using pointer = value_type*;
  270.         using size_type = u64;
  271.  
  272.     private:
  273.         const std::vector<cell_state>& m_states;
  274.         value_type* m_base;
  275.         size_type m_pos;
  276.  
  277.     public:
  278.         reference operator*() const
  279.         {
  280.             return m_base[m_pos];
  281.         }
  282.  
  283.         pointer operator->() const
  284.         {
  285.             return m_base + m_pos;
  286.         }
  287.  
  288.         hash_map_iterator& operator++()
  289.         {
  290.             ++m_pos;
  291.             for (; m_pos < m_states.size(); ++m_pos)
  292.                 if (m_states[m_pos] == cell_state::presented)
  293.                     break;
  294.             return *this;
  295.         }
  296.  
  297.         hash_map_iterator operator++(int)
  298.         {
  299.             hash_map_iterator result(*this);
  300.             this->operator++();
  301.             return result;
  302.         }
  303.  
  304.         friend bool operator==(const hash_map_iterator<value_type>& a, const hash_map_iterator<value_type>& b)
  305.         {
  306.             return a.m_base == b.m_base && a.m_pos == b.m_pos;
  307.         }
  308.  
  309.         friend bool operator!=(const hash_map_iterator<value_type>& a, const hash_map_iterator<value_type>& b)
  310.         {
  311.             return !operator==(a, b);
  312.         }
  313.  
  314.     private:
  315.         // TODO check variadic
  316.         template<typename, typename, typename, typename, typename>
  317.         friend class hash_map;
  318.  
  319.         template<typename>
  320.         friend class hash_map_const_iterator;
  321.  
  322.         hash_map_iterator(const std::vector<cell_state>& states, value_type* base, size_type pos) : m_states(states), m_base(base), m_pos(pos) { }
  323.     };
  324.  
  325.     template<typename Tp>
  326.     class hash_map_const_iterator
  327.     {
  328.     public:
  329.         using iterator_category = std::forward_iterator_tag;
  330.         using value_type = Tp;
  331.         using difference_type = std::ptrdiff_t;
  332.         using reference = const value_type&;
  333.         using pointer = const value_type*;
  334.         using size_type = u64;
  335.  
  336.     private:
  337.         const std::vector<cell_state>& m_states;
  338.         value_type* m_base;
  339.         size_type m_pos;
  340.  
  341.     public:
  342.         hash_map_const_iterator() = default;
  343.  
  344.         hash_map_const_iterator(const hash_map_iterator<value_type>& other) : m_states(other.m_states), m_base(other.m_base), m_pos(other.m_pos) { }
  345.  
  346.         reference operator*() const
  347.         {
  348.             return *m_base;
  349.         }
  350.  
  351.         pointer operator->() const
  352.         {
  353.             return m_base;
  354.         }
  355.  
  356.         hash_map_const_iterator& operator++()
  357.         {
  358.             ++m_pos;
  359.             for (; m_pos < m_states.size(); ++m_pos)
  360.                 if (m_states == cell_state::presented)
  361.                     break;
  362.             return *this;
  363.         }
  364.  
  365.         hash_map_const_iterator operator++(int)
  366.         {
  367.             hash_map_iterator result(*this);
  368.             this->operator++();
  369.             return result;
  370.         }
  371.  
  372.         friend bool operator==(const hash_map_const_iterator<value_type>& a, const hash_map_const_iterator<value_type>& b)
  373.         {
  374.             return a.m_states.data() == b.m_states.data() && a.m_pos == b.m_pos;
  375.         }
  376.  
  377.         friend bool operator!=(const hash_map_const_iterator<value_type>& a, const hash_map_const_iterator<value_type>& b)
  378.         {
  379.             return !operator==(a, b);
  380.         }
  381.  
  382.     private:
  383.         // TODO check variadic
  384.         template<typename, typename, typename, typename, typename>
  385.         friend class hash_map;
  386.  
  387.         hash_map_const_iterator(const std::vector<cell_state>& states, value_type* base, size_type pos) : m_states(states), m_base(base), m_pos(pos) { }
  388.     };
  389.  
  390.     template<typename K, typename T, typename Hash = std::hash<K>, typename Pred = std::equal_to<K>, typename Alloc = allocator<std::pair<const K, T>>>
  391.     class hash_map
  392.     {
  393.     public:
  394.         using key_type = K;
  395.         using mapped_type = T;
  396.         using hasher = Hash;
  397.         using key_equal = Pred;
  398.         using allocator_type = Alloc;
  399.         using value_type = std::pair<const key_type, mapped_type>;
  400.         using pointer = typename std::allocator_traits<allocator_type>::pointer;
  401.         using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
  402.         using reference = value_type&;
  403.         using const_reference = const value_type&;
  404.         using iterator = hash_map_iterator<value_type>;
  405.         using const_iterator = hash_map_const_iterator<value_type>;
  406.         using size_type = std::size_t;
  407.  
  408.     private:
  409.         float m_max_load_factor = 0.5f;
  410.         u64 m_size = 0;
  411.         hasher m_hash;
  412.         key_equal m_key_equal;
  413.         storage<value_type, allocator_type> m_storage;
  414.         std::vector<cell_state> m_states;
  415.  
  416.     public:
  417.         hash_map() = default;
  418.  
  419.         explicit hash_map(size_type n) : m_storage(n), m_states(n, cell_state::non_init) { }
  420.  
  421.         explicit hash_map(const allocator_type& allocator) : m_storage(allocator) { }
  422.  
  423.         template<typename InputIterator>
  424.         hash_map(InputIterator first, InputIterator last, size_type n = 0) : hash_map(n)
  425.         {
  426.             std::for_each(first, last, [this](const value_type& v){ insert(v); });
  427.         }
  428.  
  429.         hash_map(std::initializer_list<value_type> l, size_type n = 0) : hash_map(l.begin(), l.end(), n) { }
  430.  
  431.         hash_map(const hash_map& other, const allocator_type& allocator) : m_max_load_factor(other.m_max_load_factor), m_size(other.m_size),
  432.                                                                            m_hash(other.m_hash), m_key_equal(other.m_key_equal),
  433.                                                                            m_storage(other.m_storage, allocator) { }
  434.  
  435.         hash_map(hash_map&& other, const allocator_type& allocator) : m_max_load_factor(other.m_max_load_factor), m_size(other.m_size),
  436.                                                                       m_hash(std::move(other.m_hash)), m_key_equal(std::move(other.m_key_equal)),
  437.                                                                       m_storage(std::move(other.m_storage), allocator) { }
  438.  
  439.         hash_map& operator=(std::initializer_list<value_type> l)
  440.         {
  441.             *this = hash_map<K, T, Hash, Pred, Alloc>(l);
  442.         }
  443.  
  444.         allocator_type get_allocator() const noexcept
  445.         {
  446.             return m_storage.m_allocator;
  447.         }
  448.  
  449.         bool empty() const noexcept
  450.         {
  451.             return !m_size;
  452.         }
  453.  
  454.         size_type size() const noexcept
  455.         {
  456.             return m_size;
  457.         }
  458.  
  459.         size_type max_size() const noexcept
  460.         {
  461.             return std::numeric_limits<size_type>::max();
  462.         }
  463.  
  464.         iterator begin() noexcept
  465.         {
  466.             size_type index = 0;
  467.             for (; index < m_storage.size(); ++index)
  468.                 if (m_states[index] == cell_state::presented)
  469.                     break;
  470.             return hash_map_iterator<value_type>(m_states, m_storage.data(), index);
  471.         }
  472.  
  473.         const_iterator begin() const noexcept;
  474.  
  475.         const_iterator cbegin() const noexcept;
  476.  
  477.         iterator end() noexcept
  478.         {
  479.             return hash_map_iterator<value_type>(m_states, m_storage.data(), m_storage.size());
  480.         }
  481.  
  482.         const_iterator end() const noexcept;
  483.  
  484.         const_iterator cend() const noexcept;
  485.  
  486.         template<typename... Args>
  487.         std::pair<iterator, bool> emplace(Args&&... args)
  488.         {
  489.             static_assert (sizeof...(Args) == 2);
  490.             const auto cell = get_key_cell(std::get<0>(std::tuple<Args&...>(args...)));
  491.             const auto prev_state = m_states[cell];
  492.             raw_insert_cell(cell, std::forward<Args>(args)...);
  493.             return {create_iterator(cell), prev_state != cell_state::presented};
  494.         }
  495.  
  496.         template <typename... Args>
  497.         std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args)
  498.         {
  499.             return perform_try_emplace(k, std::forward<Args>(args)...);
  500.         }
  501.  
  502.         template <typename... Args>
  503.         std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args)
  504.         {
  505.             return perform_try_emplace(std::move(k), std::forward<Args>(args)...);
  506.         }
  507.  
  508.         std::pair<iterator, bool> insert(const value_type& x)
  509.         {
  510.             const auto cell = raw_insert(x.first, x.second);
  511.             return create_iterator(cell);
  512.         }
  513.  
  514.         std::pair<iterator, bool> insert(value_type&& x)
  515.         {
  516.             const auto cell = raw_insert(std::move(x.first), std::move(x.second));
  517.             return create_iterator(cell);
  518.         }
  519.  
  520.         template<typename InputIterator>
  521.         void insert(InputIterator first, InputIterator last)
  522.         {
  523.             for (; first != last; ++first)
  524.                 raw_insert(first->first, first->second);
  525.         }
  526.  
  527.         void insert(std::initializer_list<value_type> l)
  528.         {
  529.             for (const auto& [k, v] : l)
  530.                 raw_insert(k, v);
  531.         }
  532.  
  533.         template <typename Value>
  534.         std::pair<iterator, bool> insert_or_assign(const key_type& k, Value&& v)
  535.         {
  536.             return perform_insert_or_assign(k, std::forward<Value>(v));
  537.         }
  538.  
  539.         template <typename Value>
  540.         std::pair<iterator, bool> insert_or_assign(key_type&& k, Value&& v)
  541.         {
  542.             return perform_insert_or_assign(std::move(k), std::forward<Value>(v));
  543.         }
  544.  
  545.         template<typename K1, typename T1, typename Hash1, typename Pred1, typename Alloc1>
  546.         friend bool operator==(const hash_map<K1, T1, Hash1, Pred1, Alloc1>&, const hash_map<K1, T1, Hash1, Pred1, Alloc1>&);
  547.  
  548.         Hash hash_function() const
  549.         {
  550.             return m_hash;
  551.         }
  552.  
  553.         Pred key_eq() const
  554.         {
  555.             return m_key_equal;
  556.         }
  557.  
  558.         size_type count(const key_type& k) const
  559.         {
  560.             return contains(k);
  561.         }
  562.  
  563.         bool contains(const key_type& k) const
  564.         {
  565.             return m_states[get_key_cell(k)] == cell_state::presented;
  566.         }
  567.  
  568.         mapped_type& operator[](const key_type& k)
  569.         {
  570.             return perform_brackets_operator(k);
  571.         }
  572.  
  573.         mapped_type& operator[](key_type&& k)
  574.         {
  575.             return perform_brackets_operator(std::move(k));
  576.         }
  577.  
  578.         const mapped_type& at(const key_type& k) const
  579.         {
  580.             auto cell = get_key_cell(k);
  581.             if (m_states[cell] != cell_state::presented)
  582.                 throw std::out_of_range("Key is not presented in a hash_map");
  583.             return get_value(cell);
  584.         }
  585.  
  586.         mapped_type& at(const key_type& k)
  587.         {
  588.             return const_cast<mapped_type&>(static_cast<const hash_map&>(*this).at(k));
  589.         }
  590.  
  591.         size_type bucket_count() const noexcept
  592.         {
  593.             return m_storage.size();
  594.         }
  595.  
  596.         size_type bucket(const key_type& k) const
  597.         {
  598.             const auto cell = get_key_cell(k);
  599.             if (m_states[cell] == cell_state::presented)
  600.                 return cell;
  601.             return npos;
  602.         }
  603.  
  604.         iterator erase(const_iterator position);
  605.  
  606.         iterator erase(iterator position);
  607.  
  608.         size_type erase(const key_type& x);
  609.  
  610.         iterator erase(const_iterator first, const_iterator last);
  611.  
  612.         void clear() noexcept;
  613.  
  614.         void swap(hash_map& x);
  615.  
  616.         template<typename _H2, typename _P2>
  617.         void merge(hash_map<K, T, _H2, _P2, Alloc>& source);
  618.  
  619.         template<typename _H2, typename _P2>
  620.         void merge(hash_map<K, T, _H2, _P2, Alloc>&& source);
  621.  
  622.         iterator find(const key_type& x);
  623.  
  624.         const_iterator find(const key_type& x) const;
  625.  
  626.         void rehash(size_type n)
  627.         {
  628.             if (n <= m_storage.size())
  629.                 return;
  630.             storage<value_type, allocator_type> new_storage(m_storage.get_allocator(), n);
  631.             std::vector<cell_state> new_states(n, cell_state::non_init);
  632.             for (size_type i = 0; i < m_storage.size(); ++i)
  633.             {
  634.                 if (m_states[i] != cell_state::presented)
  635.                     continue;
  636.                 const auto new_cell = m_hash(get_key(i)) % n;
  637.                 new_storage.construct(new_cell, m_storage[i]);
  638.                 new_states[new_cell] = cell_state::presented;
  639.             }
  640.             m_states = std::move(new_states);
  641.             m_storage = std::move(new_storage);
  642.         }
  643.  
  644.         void reserve(size_type n)
  645.         {
  646.             // TODO problem with m_storage.size()
  647.         }
  648.  
  649.         float load_factor() const noexcept
  650.         {
  651.             return static_cast<float>(m_storage.constructed_count()) / m_storage.size();
  652.         }
  653.  
  654.         float max_load_factor() const noexcept
  655.         {
  656.             return m_max_load_factor;
  657.         }
  658.  
  659.         void max_load_factor(float z)
  660.         {
  661.             m_max_load_factor = z;
  662.             if (load_factor() <= m_max_load_factor)
  663.                 return;
  664.             rehash(load_factor() / m_max_load_factor * 1.66);
  665.         }
  666.  
  667.     private:
  668.         /* std functions fwd analogs */
  669.  
  670.         template<typename Key, typename Value>
  671.         std::pair<iterator, bool> perform_insert_or_assign(Key&& k, Value&& v)
  672.         {
  673.             const auto cell = get_key_cell(k);
  674.             const auto prev_state = m_states[cell];
  675.             raw_insert_cell(cell, std::forward<Key>(k), std::forward<Value>(v), true);
  676.             return {create_iterator(cell), prev_state != cell_state::presented};
  677.         }
  678.  
  679.         template <typename Key, typename... Args>
  680.         std::pair<iterator, bool> perform_try_emplace(Key&& k, Args&&... args)
  681.         {
  682.             const auto cell = get_key_cell(k);
  683.             if (m_states[cell] == cell_state::presented)
  684.                 return {create_iterator(cell), false};
  685.             m_storage.destruct(cell);
  686.             m_storage.construct(cell, std::piecewise_construct, std::forward_as_tuple(std::forward<Key>(k)), std::forward_as_tuple(std::forward<Args...>(args)...));
  687.             m_states[cell] = cell_state::presented;
  688.             return {create_iterator(cell), true};
  689.         }
  690.  
  691.         template<typename Key>
  692.         mapped_type& perform_brackets_operator(Key&& key)
  693.         {
  694.             const auto cell = get_key_cell(key);
  695.             if (m_states[cell] == cell_state::non_init)
  696.                 raw_insert(std::forward<Key>(key), mapped_type());
  697.             else if (m_states[cell] == cell_state::erased)
  698.                 raw_insert(std::forward<Key>(key), mapped_type(), true);
  699.             return get_value(cell);
  700.         }
  701.  
  702.         /* end */
  703.  
  704.         static constexpr size_type npos = std::numeric_limits<size_type>::max();
  705.  
  706.         size_type get_key_cell(const key_type& k) const
  707.         {
  708.             const auto index = m_hash(k) % m_storage.size();
  709.             auto i = index;
  710.             do
  711.             {
  712.                 if (m_states[i] == cell_state::non_init)
  713.                     return i;
  714.                 if (m_key_equal(k, get_key(i)))
  715.                     return i;
  716.                 if (++i == m_storage.size())
  717.                     i = 0;
  718.             } while (i != index);
  719.             return npos;
  720.         }
  721.  
  722.         template<typename Key, typename Value>
  723.         void raw_insert_cell(size_type cell, Key&& key, Value&& value, bool replace_if_exist = false)
  724.         {
  725.             if (m_states[cell] == cell_state::non_init)
  726.                 create_pair(cell, std::forward<Key>(key), std::forward<Value>(value));
  727.             else if (m_states[cell] == cell_state::erased || replace_if_exist)
  728.                 replace_value(cell, std::forward<Value>(value));
  729.         }
  730.  
  731.         template<typename Key, typename Value>
  732.         size_type raw_insert(Key&& key, Value&& value, bool replace_if_exist = false)
  733.         {
  734.             const auto cell = get_key_cell(key);
  735.             raw_insert_cell(cell, std::forward<Key>(key), std::forward<Value>(value), replace_if_exist);
  736.             return cell;
  737.         }
  738.  
  739.         template<typename Key, typename Value>
  740.         void create_pair(size_type index, Key&& key, Value&& value)
  741.         {
  742.             m_states[index] = cell_state::presented;
  743.             m_storage.construct(index, std::pair(std::forward<Key>(key), std::forward<Value>(value)));
  744.         }
  745.  
  746.         template<typename Value>
  747.         void replace_value(size_type index, Value&& value)
  748.         {
  749.             m_states[index] = cell_state::presented;
  750.             m_storage[index].second = std::forward<Value>(value);
  751.         }
  752.  
  753.         void erase_index(size_type index)
  754.         {
  755.             m_states[index] = cell_state::erased;
  756.         }
  757.  
  758.         const key_type& get_key(size_type index) const
  759.         {
  760.             return m_storage[index].first;
  761.         }
  762.  
  763.         mapped_type& get_value(size_type index)
  764.         {
  765.             return m_storage[index].second;
  766.         }
  767.  
  768.         iterator create_iterator(size_type index)
  769.         {
  770.             return hash_map_iterator(m_states, m_storage.data(), index);
  771.         }
  772.     };
  773. }
  774. // namespace hm
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement