11#include <initializer_list>
22#include "swoc/ext/HashFNV.h"
24namespace swoc {
inline namespace SWOC_VERSION_NS {
35template <
typename... Args>
37what(std::string_view
const &fmt, Args &&...args) {
62 static constexpr std::hash<E> hasher;
128 using Default = std::variant<std::monostate, E, TextView, UnknownNameHandler, UnknownValueHandler>;
134 std::initializer_list<TextView>
const &
names;
140 using with = std::initializer_list<Pair>
const &;
141 using with_multi = std::initializer_list<Definition>
const &;
173 explicit Lexicon(with items, Default handler_1 = Default{}, Default handler_2 = Default{});
185 explicit Lexicon(Default handler_1, Default handler_2 = Default{});
187 Lexicon(self_type &&that) =
default;
194 TextView operator[](E
const &value)
const;
201 E operator[](TextView
const &name)
const;
206 template <
typename... Args> self_type &
define(E value, Args &&...names);
211 self_type &
define(E value,
const std::initializer_list<TextView> &names);
254 size_t count()
const;
388 struct ByNameHelper {
389 self_type
const &_lexicon;
390 ByNameHelper(self_type
const &self) : _lexicon(self) {}
393 return _lexicon.begin_names();
397 return _lexicon.end_names();
420 using NameDefault = std::variant<std::monostate, std::string_view, UnknownValueHandler>;
422 using ValueDefault = std::variant<std::monostate, E, UnknownNameHandler>;
431 throw std::domain_error(
"Lexicon: invalid enumeration value");
454 throw std::domain_error(
detail::what(
"Lexicon: Unknown name \"{}\"",
_name).data());
466 return handler(
_name);
486 Item *_next{
nullptr};
487 Item *_prev{
nullptr};
491 static std::string_view key_of(
Item *);
492 static uint32_t hash_of(std::string_view s);
493 static bool equal(std::string_view
const &lhs, std::string_view
const &rhs);
497 struct ValueLinkage {
498 Item *_next{
nullptr};
499 Item *_prev{
nullptr};
501 static Item *&next_ptr(Item *);
502 static Item *&prev_ptr(Item *);
503 static E key_of(Item *);
504 static size_t hash_of(E);
505 static bool equal(E lhs, E rhs);
511 TextView localize(TextView
const &name);
535 return item->_name_link._next;
541 return item->_name_link._prev;
546Lexicon<E>::Item::ValueLinkage::next_ptr(Item *item) -> Item *& {
547 return item->_value_link._next;
553 return item->_value_link._prev;
559 return item->_payload._name;
565 return item->_payload._value;
599 for (
auto const &item : items) {
600 this->
define(item.value, item.names);
603 for (
auto &&h : {handler_1, handler_2}) {
609 for (
auto const &item : items) {
613 for (
auto &&h : {handler_1, handler_2}) {
619 for (
auto &&h : {handler_1, handler_2}) {
627 auto span =
_arena.alloc_span<
char>(name.size());
629 return {span.data(), span.size()};
636 return spot->_payload._name;
645 return spot->_payload._value;
653 if (names.size() < 1) {
654 throw std::invalid_argument(
"A defined value must have at least a primary name");
656 for (
auto const &name : names) {
658 throw std::invalid_argument(
detail::what(
"Duplicate name '{}' in Lexicon", name));
671template <
typename... Args>
674 static_assert(
sizeof...(Args) > 0,
"A defined value must have at least a primary name");
675 return this->
define(value, {std::forward<Args>(names)...});
681 return this->
define(pair._value, pair._name);
687 return this->
define(init.value, init.names);
693 switch (handler.index()) {
735 return _item->_payload;
741 return &(
_item->_payload);
766 self_type tmp{*
this};
796 self_type tmp{*
this};
821 for (
auto &&[value, name] : lex) {
829 for (
auto &&[value, name] : lex) {
837 for (
auto &&[value, name] : lex) {
841 w.
print(
"[{},{}]", name,
unsigned(value));
852template <
size_t IDX,
typename E>
class tuple_element<IDX,
swoc::detail::lexicon_pair_type<E>> {
853 static_assert(
"swoc::Lexicon::Pair tuple index out of range");
856template <
typename E>
class tuple_element<0,
swoc::detail::lexicon_pair_type<E>> {
861template <
typename E>
class tuple_element<1,
swoc::detail::lexicon_pair_type<E>> {
866template <
size_t IDX,
typename E>
869 if constexpr (IDX == 0) {
871 }
else if constexpr (IDX == 1) {
std::string what(std::string_view const &fmt, Args &&...args)
BufferWriter & print(const TextView &fmt, Args &&...args)
virtual BufferWriter & write(char c)=0
bool operator!=(self_type const &that) const
Inequality.
bool operator==(self_type const &that) const
Equality.
value_type * pointer
Pointer to iteration value.
value_type & reference
Reference to iteration value.
reference operator*() const
Dereference.
ptrdiff_t difference_type
Type of difference between iterators.
std::bidirectional_iterator_tag iterator_category
base_iterator()=default
Default constructor (invalid iterator)
const Item * _item
Current location in the container.
const Pair value_type
Iteration value.
pointer operator->() const
Dereference.
self_type & operator=(self_type const &that)=default
Assignment.
name_iterator(self_type &&that)=default
Move constructor.
friend Lexicon
Internal constructor.
name_iterator()=default
Default constructor.
self_type & operator--()
Decrement.
name_iterator(self_type const &that)=default
Copy constructor.
self_type & operator++()
Increment.
self_type & operator=(self_type const &that)=default
Assignment.
self_type & operator--()
Decrement.
self_type & operator++()
Increment.
value_iterator(self_type &&that)=default
Move constructor.
friend Lexicon
Internal constructor.
value_iterator()=default
Default constructor.
value_iterator(self_type const &that)=default
Copy constructor.
std::function< E(TextView)> UnknownNameHandler
std::variant< std::monostate, E, UnknownNameHandler > ValueDefault
Handle providing a default value.
detail::lexicon_pair_type< E > Pair
IntrusiveHashMap< typename Item::NameLinkage > _by_name
Access by name.
TextView operator[](E const &value) const
self_type & define(E value, Args &&...names)
TextView localize(TextView const &name)
Copy name in to local storage.
std::function< TextView(E)> UnknownValueHandler
const_iterator end() const
Iteration end.
ByNameHelper by_names() const
std::variant< std::monostate, std::string_view, UnknownValueHandler > NameDefault
Handle providing a default name.
name_iterator end_names() const
Iteration over names - every value/name pair.
size_t count() const
Get the number of values with definitions.
NameDefault _name_default
Name to return if no value not found.
value_iterator const_iterator
Iterator over values (each with a primary name).
MemArena _arena
Storage for names.
name_iterator begin_names() const
Iteration over names - every value/name pair.
Lexicon()
Construct empty instance.
IntrusiveHashMap< typename Item::ValueLinkage > _by_value
Access by value.
static constexpr auto NAME_IDX
Index in Pair for name.
ValueDefault _value_default
Value to return if name not found.
self_type & set_default(Default const &handler)
std::variant< std::monostate, E, TextView, UnknownNameHandler, UnknownValueHandler > Default
const_iterator begin() const
Iteration begin.
static constexpr auto VALUE_IDX
Index in Pair for the enumeration value.
For template deduction guides.
BufferWriter & bwformat(BufferWriter &w, bwf::Spec const &spec, std::string_view sv)
std::string & bwprint_v(std::string &s, TextView fmt, std::tuple< Args... > const &args)
TransformView< X, V > transform_view_of(X const &xf, V const &src)
int strcasecmp(const std::string_view &lhs, const std::string_view &rhs)
std::initializer_list< TextView > const & names
Primary then secondary names.
const E & value
Value for definition.
Pair _payload
Enumeration and name.
Item(E value, TextView name)
Visitor functor for handling NameDefault.
std::string_view operator()(TextView const &name) const
Visitor - literal string.
E _value
Value to use for default.
std::string_view operator()(std::monostate const &) const
Visitor - invalid value type.
std::string_view operator()(UnknownValueHandler const &handler) const
Visitor - string generator.
Visitor functor for handling ValueDefault.
E operator()(E const &value) const
Visitor - value.
E operator()(std::monostate const &) const
Vistor - invalid value.
E operator()(UnknownNameHandler const &handler) const
Visitor - value generator.
std::string_view _name
Name of visited pair.
char _type
Type / radix indicator.
bool has_numeric_type() const
Check if the type in this is numeric.
lexicon_pair_type(E value, TextView name)