97 lines
2.4 KiB
C++
97 lines
2.4 KiB
C++
|
/*
|
||
|
* 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
|
||
|
|
||
|
#include "log.hpp"
|
||
|
#include "introspection.hpp"
|
||
|
|
||
|
#include <map>
|
||
|
#include <stdexcept>
|
||
|
|
||
|
namespace cruft {
|
||
|
template <typename KeyT, typename FactoryT>
|
||
|
class registry {
|
||
|
public:
|
||
|
struct cookie {
|
||
|
explicit cookie (KeyT const &_key)
|
||
|
: m_key (_key)
|
||
|
{ ; }
|
||
|
|
||
|
explicit cookie (KeyT &&_key)
|
||
|
: m_key (std::move (_key))
|
||
|
{ ; }
|
||
|
|
||
|
cookie (cookie &&rhs) noexcept
|
||
|
: m_key (std::move (rhs.key))
|
||
|
{ ; }
|
||
|
|
||
|
cookie& operator= (cookie &&rhs) noexcept
|
||
|
{
|
||
|
std::swap (rhs.m_key, m_key);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
cookie (cookie const&) = delete;
|
||
|
cookie& operator= (cookie const&) = delete;
|
||
|
|
||
|
~cookie ()
|
||
|
{
|
||
|
registry::remove (m_key);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
KeyT m_key;
|
||
|
};
|
||
|
|
||
|
|
||
|
static cookie
|
||
|
add [[nodiscard]] (KeyT key, FactoryT &&factory)
|
||
|
{
|
||
|
auto const &[pos, success] = store ().insert (
|
||
|
{ key, std::move (factory) }
|
||
|
);
|
||
|
|
||
|
if (success) {
|
||
|
LOG_INFO ("Registered %! for %!", key, cruft::type_name<FactoryT> ());
|
||
|
return cookie { key };
|
||
|
} {
|
||
|
LOG_ERROR ("Unable to register %! for %!", key, cruft::type_name<FactoryT> ());
|
||
|
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;
|
||
|
}
|
||
|
};
|
||
|
}
|