2019-04-16 11:02:26 +10:00
|
|
|
/*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*
|
|
|
|
* Copyright 2019 Danny Robson <danny@nerdcruft.net>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2019-10-10 15:52:37 +11:00
|
|
|
#include "log/log.hpp"
|
2020-09-24 15:41:58 +10:00
|
|
|
#include "introspection/name.hpp"
|
2019-04-16 11:02:26 +10:00
|
|
|
|
|
|
|
#include <map>
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
|
|
namespace cruft {
|
|
|
|
template <typename KeyT, typename FactoryT>
|
|
|
|
class registry {
|
|
|
|
public:
|
|
|
|
struct cookie {
|
2024-08-06 14:48:56 +10:00
|
|
|
private:
|
|
|
|
KeyT m_key;
|
|
|
|
|
|
|
|
public:
|
2019-04-16 11:02:26 +10:00
|
|
|
explicit cookie (KeyT const &_key)
|
|
|
|
: m_key (_key)
|
|
|
|
{ ; }
|
|
|
|
|
|
|
|
explicit cookie (KeyT &&_key)
|
|
|
|
: m_key (std::move (_key))
|
|
|
|
{ ; }
|
|
|
|
|
|
|
|
cookie (cookie &&rhs) noexcept
|
2024-08-06 14:48:56 +10:00
|
|
|
: m_key (std::move (rhs.m_key))
|
2019-04-16 11:02:26 +10:00
|
|
|
{ ; }
|
|
|
|
|
|
|
|
cookie& operator= (cookie &&rhs) noexcept
|
|
|
|
{
|
|
|
|
std::swap (rhs.m_key, m_key);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
cookie (cookie const&) = delete;
|
|
|
|
cookie& operator= (cookie const&) = delete;
|
|
|
|
|
|
|
|
~cookie ()
|
|
|
|
{
|
2021-04-19 14:52:22 +10:00
|
|
|
try {
|
|
|
|
registry::remove (m_key);
|
|
|
|
} catch (std::exception const &err) {
|
|
|
|
LOG_ERROR ("Unable to remove registration for {}", m_key);
|
|
|
|
}
|
2019-04-16 11:02:26 +10:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static cookie
|
|
|
|
add [[nodiscard]] (KeyT key, FactoryT &&factory)
|
|
|
|
{
|
|
|
|
auto const &[pos, success] = store ().insert (
|
|
|
|
{ key, std::move (factory) }
|
|
|
|
);
|
|
|
|
|
|
|
|
if (success) {
|
2020-09-24 15:41:58 +10:00
|
|
|
LOG_INFO (
|
2021-04-14 10:23:33 +10:00
|
|
|
"Registered {} for {}",
|
2020-09-24 15:41:58 +10:00
|
|
|
key,
|
|
|
|
cruft::introspection::name::full<FactoryT> ()
|
|
|
|
);
|
2019-04-16 11:02:26 +10:00
|
|
|
return cookie { key };
|
|
|
|
} {
|
2020-09-24 15:41:58 +10:00
|
|
|
LOG_ERROR (
|
2021-04-14 10:23:33 +10:00
|
|
|
"Unable to register {} for {}",
|
2020-09-24 15:41:58 +10:00
|
|
|
key,
|
|
|
|
cruft::introspection::name::full<FactoryT> ()
|
|
|
|
);
|
2019-04-16 11:02:26 +10:00
|
|
|
throw std::runtime_error ("Unable to register type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static FactoryT remove (KeyT const &key)
|
|
|
|
{
|
|
|
|
auto &s_factory = store ();
|
|
|
|
|
|
|
|
auto pos = s_factory.find (key);
|
|
|
|
if (pos == s_factory.cend ())
|
|
|
|
throw std::invalid_argument ("Key not found");
|
|
|
|
|
|
|
|
auto val = s_factory.extract (pos);
|
|
|
|
return std::move (val.mapped ());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static FactoryT& at (KeyT const &key)
|
|
|
|
{
|
|
|
|
return store ().at (key);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
static auto&
|
|
|
|
store (void)
|
|
|
|
{
|
|
|
|
static std::map<KeyT,FactoryT> s_factory;
|
|
|
|
return s_factory;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|