mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Add FlatSet implementation.
This is a flat set implemented using a sorted vector for storage.pull/14219/head
parent
2355d67e11
commit
6070f8d4f3
|
@ -7,6 +7,7 @@ add_files(
|
||||||
convertible_through_base.hpp
|
convertible_through_base.hpp
|
||||||
endian_func.hpp
|
endian_func.hpp
|
||||||
enum_type.hpp
|
enum_type.hpp
|
||||||
|
flatset_type.hpp
|
||||||
format.hpp
|
format.hpp
|
||||||
geometry_func.cpp
|
geometry_func.cpp
|
||||||
geometry_func.hpp
|
geometry_func.hpp
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file flatset_type.hpp Flat set container implementation. */
|
||||||
|
|
||||||
|
#ifndef FLATSET_TYPE_HPP
|
||||||
|
#define FLATSET_TYPE_HPP
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flat set implementation that uses a sorted vector for storage.
|
||||||
|
* This is subset of functionality implemented by std::flat_set in c++23.
|
||||||
|
* @tparam Tkey key type.
|
||||||
|
* @tparam Tcompare key comparator.
|
||||||
|
*/
|
||||||
|
template <class Tkey, class Tcompare = std::less<>>
|
||||||
|
class FlatSet {
|
||||||
|
std::vector<Tkey> data; ///< Sorted vector. of values.
|
||||||
|
public:
|
||||||
|
using const_iterator = std::vector<Tkey>::const_iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a key into the set.
|
||||||
|
* @param key Key to insert.
|
||||||
|
*/
|
||||||
|
void insert(const Tkey &key)
|
||||||
|
{
|
||||||
|
auto it = std::ranges::lower_bound(this->data, key, Tcompare{});
|
||||||
|
if (it == std::end(this->data) || *it != key) this->data.emplace(it, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erase a key from the set.
|
||||||
|
* @param key Key to erase.
|
||||||
|
* @return number of elements removed.
|
||||||
|
*/
|
||||||
|
size_t erase(const Tkey &key)
|
||||||
|
{
|
||||||
|
auto it = std::ranges::lower_bound(this->data, key, Tcompare{});
|
||||||
|
if (it == std::end(this->data) || *it != key) return 0;
|
||||||
|
|
||||||
|
this->data.erase(it);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if a key exists in the set.
|
||||||
|
* @param key Key to test.
|
||||||
|
* @return true iff the key exists in the set.
|
||||||
|
*/
|
||||||
|
bool contains(const Tkey &key)
|
||||||
|
{
|
||||||
|
return std::ranges::binary_search(this->data, key, Tcompare{});
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator begin() const { return std::cbegin(this->data); }
|
||||||
|
const_iterator end() const { return std::cend(this->data); }
|
||||||
|
|
||||||
|
const_iterator cbegin() const { return std::cbegin(this->data); }
|
||||||
|
const_iterator cend() const { return std::cend(this->data); }
|
||||||
|
|
||||||
|
size_t size() const { return std::size(this->data); }
|
||||||
|
bool empty() const { return this->data.empty(); }
|
||||||
|
|
||||||
|
void clear() { this->data.clear(); }
|
||||||
|
|
||||||
|
auto operator<=>(const FlatSet<Tkey, Tcompare> &) const = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FLATSET_TYPE_HPP */
|
|
@ -1,6 +1,7 @@
|
||||||
add_test_files(
|
add_test_files(
|
||||||
bitmath_func.cpp
|
bitmath_func.cpp
|
||||||
enum_over_optimisation.cpp
|
enum_over_optimisation.cpp
|
||||||
|
flatset_type.cpp
|
||||||
landscape_partial_pixel_z.cpp
|
landscape_partial_pixel_z.cpp
|
||||||
math_func.cpp
|
math_func.cpp
|
||||||
mock_environment.h
|
mock_environment.h
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file string_consumer.cpp Test functionality from core/string_consumer. */
|
||||||
|
|
||||||
|
#include "../stdafx.h"
|
||||||
|
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
|
#include "../3rdparty/catch2/catch.hpp"
|
||||||
|
|
||||||
|
#include "../core/flatset_type.hpp"
|
||||||
|
|
||||||
|
#include "../safeguards.h"
|
||||||
|
|
||||||
|
TEST_CASE("FlatSet - basic")
|
||||||
|
{
|
||||||
|
/* Sorted array of expected values. */
|
||||||
|
const auto values = std::to_array<uint8_t>({5, 10, 15, 20, 25});
|
||||||
|
|
||||||
|
FlatSet<uint8_t> set;
|
||||||
|
|
||||||
|
/* Set should be empty. */
|
||||||
|
CHECK(set.empty());
|
||||||
|
|
||||||
|
/* Insert in a random order,. */
|
||||||
|
set.insert(values[1]);
|
||||||
|
set.insert(values[2]);
|
||||||
|
set.insert(values[4]);
|
||||||
|
set.insert(values[3]);
|
||||||
|
set.insert(values[0]);
|
||||||
|
CHECK(set.size() == 5);
|
||||||
|
CHECK(set.contains(values[0]));
|
||||||
|
CHECK(set.contains(values[1]));
|
||||||
|
CHECK(set.contains(values[2]));
|
||||||
|
CHECK(set.contains(values[3]));
|
||||||
|
CHECK(set.contains(values[4]));
|
||||||
|
CHECK(std::ranges::equal(set, values));
|
||||||
|
|
||||||
|
/* Test inserting an existing value does not affect order. */
|
||||||
|
set.insert(values[1]);
|
||||||
|
CHECK(set.size() == 5);
|
||||||
|
CHECK(set.contains(values[0]));
|
||||||
|
CHECK(set.contains(values[1]));
|
||||||
|
CHECK(set.contains(values[2]));
|
||||||
|
CHECK(set.contains(values[3]));
|
||||||
|
CHECK(set.contains(values[4]));
|
||||||
|
CHECK(std::ranges::equal(set, values));
|
||||||
|
|
||||||
|
/* Insert a value multiple times. */
|
||||||
|
set.insert(0);
|
||||||
|
set.insert(0);
|
||||||
|
set.insert(0);
|
||||||
|
CHECK(set.size() == 6);
|
||||||
|
CHECK(set.contains(0));
|
||||||
|
|
||||||
|
/* Remove a value multiple times. */
|
||||||
|
set.erase(0);
|
||||||
|
set.erase(0);
|
||||||
|
set.erase(0);
|
||||||
|
CHECK(set.size() == 5);
|
||||||
|
CHECK(!set.contains(0));
|
||||||
|
}
|
Loading…
Reference in New Issue