Skip to content

Commit 5be2d4f

Browse files
authored
Merge pull request #1821 from joto/find-by-name
Add find_by_name() utility function
2 parents f9765bc + 2a32f46 commit 5be2d4f

File tree

4 files changed

+65
-18
lines changed

4 files changed

+65
-18
lines changed

src/flex-table-column.cpp

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "flex-table-column.hpp"
1111
#include "format.hpp"
12+
#include "util.hpp"
1213

1314
#include <algorithm>
1415
#include <array>
@@ -19,8 +20,10 @@
1920

2021
struct column_type_lookup
2122
{
22-
char const *name;
23+
char const *m_name;
2324
table_column_type type;
25+
26+
char const *name() const noexcept { return m_name; }
2427
};
2528

2629
static std::array<column_type_lookup, 26> const column_types = {
@@ -51,22 +54,14 @@ static std::array<column_type_lookup, 26> const column_types = {
5154
{"id_type", table_column_type::id_type},
5255
{"id_num", table_column_type::id_num}}};
5356

54-
static table_column_type
55-
get_column_type_from_string(std::string const &type)
57+
static table_column_type get_column_type_from_string(std::string const &type)
5658
{
57-
// Because it doesn't work with MSVC:
58-
// NOLINTNEXTLINE(llvm-qualified-auto,readability-qualified-auto)
59-
auto const it =
60-
std::find_if(std::begin(column_types), std::end(column_types),
61-
[&type](column_type_lookup name_type) {
62-
return type == name_type.name;
63-
});
64-
65-
if (it == std::end(column_types)) {
59+
auto const *column_type = util::find_by_name(column_types, type);
60+
if (!column_type) {
6661
throw std::runtime_error{"Unknown column type '{}'."_format(type)};
6762
}
6863

69-
return it->type;
64+
return column_type->type;
7065
}
7166

7267
static std::string lowercase(std::string const &str)

src/output-flex.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,11 +1006,7 @@ flex_table_t &output_flex_t::create_flex_table()
10061006

10071007
check_identifier(table_name, "table names");
10081008

1009-
auto const it = std::find_if(m_tables->cbegin(), m_tables->cend(),
1010-
[&table_name](flex_table_t const &table) {
1011-
return table.name() == table_name;
1012-
});
1013-
if (it != m_tables->cend()) {
1009+
if (util::find_by_name(*m_tables, table_name)) {
10141010
throw std::runtime_error{
10151011
"Table with name '{}' already exists."_format(table_name)};
10161012
}

src/util.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "format.hpp"
1414
#include "osmtypes.hpp"
1515

16+
#include <algorithm>
1617
#include <array>
1718
#include <cassert>
1819
#include <chrono>
@@ -129,6 +130,31 @@ std::string human_readable_duration(std::chrono::milliseconds ms);
129130

130131
std::string get_password();
131132

133+
/**
134+
* Helper function that finds items in a container by name. The items must have
135+
* a name() member function (with a result comparable to std::string) for this
136+
* to work.
137+
*
138+
* \tparam CONTAINER Any kind of container type (must support std::begin/end).
139+
* \param container The container to look through.
140+
* \param name The name to look for.
141+
* \returns Pointer to item, nullptr if not found.
142+
*/
143+
template <typename CONTAINER>
144+
auto find_by_name(CONTAINER &container, std::string const &name)
145+
-> decltype(&*std::begin(container))
146+
{
147+
auto const it =
148+
std::find_if(std::begin(container), std::end(container),
149+
[&name](auto const &item) { return item.name() == name; });
150+
151+
if (it == std::end(container)) {
152+
return nullptr;
153+
}
154+
155+
return &*it;
156+
}
157+
132158
} // namespace util
133159

134160
#endif // OSM2PGSQL_UTIL_HPP

tests/test-util.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
#include <cstring>
1515
#include <limits>
16+
#include <string>
17+
#include <vector>
1618

1719
TEST_CASE("integer_to_buffer 1", "[NoDB]")
1820
{
@@ -82,3 +84,31 @@ TEST_CASE("human readable time durations", "[NoDB]")
8284
REQUIRE(util::human_readable_duration(152592) == "152592s (42h 23m 12s)");
8385
}
8486

87+
TEST_CASE("find_by_name()", "[NoDB]")
88+
{
89+
class test_class
90+
{
91+
public:
92+
explicit test_class(std::string n) : m_name(std::move(n)) {}
93+
std::string name() const noexcept { return m_name; }
94+
95+
private:
96+
std::string m_name;
97+
};
98+
99+
std::vector<test_class> t;
100+
101+
REQUIRE(util::find_by_name(t, "") == nullptr);
102+
REQUIRE(util::find_by_name(t, "foo") == nullptr);
103+
REQUIRE(util::find_by_name(t, "nothing") == nullptr);
104+
105+
t.emplace_back("foo");
106+
t.emplace_back("bar");
107+
t.emplace_back("baz");
108+
109+
REQUIRE(util::find_by_name(t, "") == nullptr);
110+
REQUIRE(util::find_by_name(t, "foo") == &t[0]);
111+
REQUIRE(util::find_by_name(t, "bar") == &t[1]);
112+
REQUIRE(util::find_by_name(t, "baz") == &t[2]);
113+
REQUIRE(util::find_by_name(t, "nothing") == nullptr);
114+
}

0 commit comments

Comments
 (0)