Skip to content

Commit

Permalink
Merge pull request #1821 from joto/find-by-name
Browse files Browse the repository at this point in the history
Add find_by_name() utility function
  • Loading branch information
lonvia authored Nov 10, 2022
2 parents f9765bc + 2a32f46 commit 5be2d4f
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 18 deletions.
21 changes: 8 additions & 13 deletions src/flex-table-column.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "flex-table-column.hpp"
#include "format.hpp"
#include "util.hpp"

#include <algorithm>
#include <array>
Expand All @@ -19,8 +20,10 @@

struct column_type_lookup
{
char const *name;
char const *m_name;
table_column_type type;

char const *name() const noexcept { return m_name; }
};

static std::array<column_type_lookup, 26> const column_types = {
Expand Down Expand Up @@ -51,22 +54,14 @@ static std::array<column_type_lookup, 26> const column_types = {
{"id_type", table_column_type::id_type},
{"id_num", table_column_type::id_num}}};

static table_column_type
get_column_type_from_string(std::string const &type)
static table_column_type get_column_type_from_string(std::string const &type)
{
// Because it doesn't work with MSVC:
// NOLINTNEXTLINE(llvm-qualified-auto,readability-qualified-auto)
auto const it =
std::find_if(std::begin(column_types), std::end(column_types),
[&type](column_type_lookup name_type) {
return type == name_type.name;
});

if (it == std::end(column_types)) {
auto const *column_type = util::find_by_name(column_types, type);
if (!column_type) {
throw std::runtime_error{"Unknown column type '{}'."_format(type)};
}

return it->type;
return column_type->type;
}

static std::string lowercase(std::string const &str)
Expand Down
6 changes: 1 addition & 5 deletions src/output-flex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1006,11 +1006,7 @@ flex_table_t &output_flex_t::create_flex_table()

check_identifier(table_name, "table names");

auto const it = std::find_if(m_tables->cbegin(), m_tables->cend(),
[&table_name](flex_table_t const &table) {
return table.name() == table_name;
});
if (it != m_tables->cend()) {
if (util::find_by_name(*m_tables, table_name)) {
throw std::runtime_error{
"Table with name '{}' already exists."_format(table_name)};
}
Expand Down
26 changes: 26 additions & 0 deletions src/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "format.hpp"
#include "osmtypes.hpp"

#include <algorithm>
#include <array>
#include <cassert>
#include <chrono>
Expand Down Expand Up @@ -129,6 +130,31 @@ std::string human_readable_duration(std::chrono::milliseconds ms);

std::string get_password();

/**
* Helper function that finds items in a container by name. The items must have
* a name() member function (with a result comparable to std::string) for this
* to work.
*
* \tparam CONTAINER Any kind of container type (must support std::begin/end).
* \param container The container to look through.
* \param name The name to look for.
* \returns Pointer to item, nullptr if not found.
*/
template <typename CONTAINER>
auto find_by_name(CONTAINER &container, std::string const &name)
-> decltype(&*std::begin(container))
{
auto const it =
std::find_if(std::begin(container), std::end(container),
[&name](auto const &item) { return item.name() == name; });

if (it == std::end(container)) {
return nullptr;
}

return &*it;
}

} // namespace util

#endif // OSM2PGSQL_UTIL_HPP
30 changes: 30 additions & 0 deletions tests/test-util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

#include <cstring>
#include <limits>
#include <string>
#include <vector>

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

TEST_CASE("find_by_name()", "[NoDB]")
{
class test_class
{
public:
explicit test_class(std::string n) : m_name(std::move(n)) {}
std::string name() const noexcept { return m_name; }

private:
std::string m_name;
};

std::vector<test_class> t;

REQUIRE(util::find_by_name(t, "") == nullptr);
REQUIRE(util::find_by_name(t, "foo") == nullptr);
REQUIRE(util::find_by_name(t, "nothing") == nullptr);

t.emplace_back("foo");
t.emplace_back("bar");
t.emplace_back("baz");

REQUIRE(util::find_by_name(t, "") == nullptr);
REQUIRE(util::find_by_name(t, "foo") == &t[0]);
REQUIRE(util::find_by_name(t, "bar") == &t[1]);
REQUIRE(util::find_by_name(t, "baz") == &t[2]);
REQUIRE(util::find_by_name(t, "nothing") == nullptr);
}

0 comments on commit 5be2d4f

Please sign in to comment.