Files
rippled/include/xrpl/protocol/KnownFormats.h
Bart 1d42c4f6de refactor: Remove unnecessary copyright notices already covered by LICENSE.md (#5929)
Per XLS-0095, we are taking steps to rename ripple(d) to xrpl(d).

This change specifically removes all copyright notices referencing Ripple, XRPLF, and certain affiliated contributors upon mutual agreement, so the notice in the LICENSE.md file applies throughout. Copyright notices referencing external contributions remain as-is. Duplicate verbiage is also removed.
2025-11-04 08:33:42 +00:00

189 lines
4.8 KiB
C++

#ifndef XRPL_PROTOCOL_KNOWNFORMATS_H_INCLUDED
#define XRPL_PROTOCOL_KNOWNFORMATS_H_INCLUDED
#include <xrpl/basics/contract.h>
#include <xrpl/beast/type_name.h>
#include <xrpl/protocol/SOTemplate.h>
#include <boost/container/flat_map.hpp>
#include <algorithm>
#include <forward_list>
namespace ripple {
/** Manages a list of known formats.
Each format has a name, an associated KeyType (typically an enumeration),
and a predefined @ref SOElement.
@tparam KeyType The type of key identifying the format.
*/
template <class KeyType, class Derived>
class KnownFormats
{
public:
/** A known format.
*/
class Item
{
public:
Item(
char const* name,
KeyType type,
std::initializer_list<SOElement> uniqueFields,
std::initializer_list<SOElement> commonFields)
: soTemplate_(uniqueFields, commonFields), name_(name), type_(type)
{
// Verify that KeyType is appropriate.
static_assert(
std::is_enum<KeyType>::value ||
std::is_integral<KeyType>::value,
"KnownFormats KeyType must be integral or enum.");
}
/** Retrieve the name of the format.
*/
std::string const&
getName() const
{
return name_;
}
/** Retrieve the transaction type this format represents.
*/
KeyType
getType() const
{
return type_;
}
SOTemplate const&
getSOTemplate() const
{
return soTemplate_;
}
private:
SOTemplate soTemplate_;
std::string const name_;
KeyType const type_;
};
/** Create the known formats object.
Derived classes will load the object with all the known formats.
*/
KnownFormats() : name_(beast::type_name<Derived>())
{
}
/** Destroy the known formats object.
The defined formats are deleted.
*/
virtual ~KnownFormats() = default;
KnownFormats(KnownFormats const&) = delete;
KnownFormats&
operator=(KnownFormats const&) = delete;
/** Retrieve the type for a format specified by name.
If the format name is unknown, an exception is thrown.
@param name The name of the type.
@return The type.
*/
KeyType
findTypeByName(std::string const& name) const
{
if (auto const result = findByName(name))
return result->getType();
Throw<std::runtime_error>(
name_ + ": Unknown format name '" +
name.substr(0, std::min(name.size(), std::size_t(32))) + "'");
}
/** Retrieve a format based on its type.
*/
Item const*
findByType(KeyType type) const
{
auto const itr = types_.find(type);
if (itr == types_.end())
return nullptr;
return itr->second;
}
// begin() and end() are provided for testing purposes.
typename std::forward_list<Item>::const_iterator
begin() const
{
return formats_.begin();
}
typename std::forward_list<Item>::const_iterator
end() const
{
return formats_.end();
}
protected:
/** Retrieve a format based on its name.
*/
Item const*
findByName(std::string const& name) const
{
auto const itr = names_.find(name);
if (itr == names_.end())
return nullptr;
return itr->second;
}
/** Add a new format.
@param name The name of this format.
@param type The type of this format.
@param uniqueFields An std::initializer_list of unique fields
@param commonFields An std::initializer_list of common fields
@return The created format.
*/
Item const&
add(char const* name,
KeyType type,
std::initializer_list<SOElement> uniqueFields,
std::initializer_list<SOElement> commonFields = {})
{
if (auto const item = findByType(type))
{
LogicError(
std::string("Duplicate key for item '") + name +
"': already maps to " + item->getName());
}
formats_.emplace_front(name, type, uniqueFields, commonFields);
Item const& item{formats_.front()};
names_[name] = &item;
types_[type] = &item;
return item;
}
private:
std::string name_;
// One of the situations where a std::forward_list is useful. We want to
// store each Item in a place where its address won't change. So a node-
// based container is appropriate. But we don't need searchability.
std::forward_list<Item> formats_;
boost::container::flat_map<std::string, Item const*> names_;
boost::container::flat_map<KeyType, Item const*> types_;
};
} // namespace ripple
#endif