diff options
Diffstat (limited to 'libs/kstd/include')
| -rw-r--r-- | libs/kstd/include/kstd/flat_map | 27 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/vector | 39 |
2 files changed, 66 insertions, 0 deletions
diff --git a/libs/kstd/include/kstd/flat_map b/libs/kstd/include/kstd/flat_map index 3b13754..f12b1b5 100644 --- a/libs/kstd/include/kstd/flat_map +++ b/libs/kstd/include/kstd/flat_map @@ -256,6 +256,33 @@ namespace kstd }; } + //! Try to insert a element for the given key into this map. + //! + //! This function does nothing if the key is already present. + //! + //! @param key The key to insert a value for. + //! @param args The arguments to use to construct the mapped value. + template<typename... Args> + auto try_emplace(key_type const & key, Args &&... args) -> std::pair<iterator, bool> + { + auto found = std::ranges::lower_bound(m_containers.keys, key, m_comparator); + if (found != m_containers.keys.cend() && !m_comparator(*found, key) && !m_comparator(key, *found)) + { + return {found, false}; + } + + auto offset = std::distance(m_containers.keys.cbegin(), found); + auto intersertion_point = m_containers.value.begin() + offset; + + auto inserted_key = m_containers.keys.emplace(key); + auto inserted_mapped = m_containers.values.emplace(std::forward<Args>(args)...); + + return { + iterator{inserted_key, inserted_mapped}, + true + }; + } + //! Find an element with an equivalent key. //! //! @param key The key to look up. diff --git a/libs/kstd/include/kstd/vector b/libs/kstd/include/kstd/vector index 79593c6..e1b8b38 100644 --- a/libs/kstd/include/kstd/vector +++ b/libs/kstd/include/kstd/vector @@ -728,6 +728,45 @@ namespace kstd return begin() + prefix_size; } + template<typename... Args> + constexpr auto emplace(const_iterator position, Args &&... args) -> iterator + { + auto prefix_size = std::ranges::distance(begin(), position); + auto suffix_size = std::ranges::distance(position, end()); + + if (position == end()) + { + emplace_back(std::forward<Args>(args)...); + return begin() + prefix_size; + } + + if (m_capacity == m_size) + { + auto new_capacity = m_capacity == 0 ? 1 : m_capacity * 2; + auto new_data = allocate_n(new_capacity); + auto old_size = size(); + std::allocator_traits<allocator_type>::construct(m_allocator, new_data + prefix_size, + std::forward<Args>(args)...); + uninitialized_move_with_allocator(begin(), new_data, prefix_size); + uninitialized_move_with_allocator(begin() + prefix_size, new_data + prefix_size + 1, suffix_size); + destroy_n(begin(), old_size); + deallocate(); + m_data = new_data; + m_capacity = new_capacity; + m_size = old_size; + } + else + { + auto insert_position = begin() + prefix_size; + std::allocator_traits<allocator_type>::construct(m_allocator, end(), std::move(*(end() - 1))); + std::ranges::move_backward(insert_position, end() - 1, end()); + *insert_position = value_type{std::forward<Args>(args)...}; + } + + ++m_size; + return begin() + prefix_size; + } + //! Erase an element at a given position. //! //! @note This function will panic if position == end() |
