header_utils
Loading...
Searching...
No Matches
symbol.h
1
4
5#pragma once
6
7#include <string>
8#include <string_view>
9#include <set>
10
11namespace ghassanpl
12{
13 template <typename SYMBOL_PROVIDER>
14 struct symbol_base
15 {
16 using symbol_provider = SYMBOL_PROVIDER;
17 using internal_value_type = typename symbol_provider::internal_value_type;
18 using hash_type = typename symbol_provider::hash_type;
19
20 internal_value_type value = symbol_provider::empty_value();
21
22 explicit symbol_base(std::string_view val) : value{ symbol_provider::insert(val) } { }
23 symbol_base() noexcept = default;
24
25 hash_type get_hash() const noexcept { return symbol_provider::hash_for(value); }
26 std::string_view get_string() const noexcept { return symbol_provider::string_for(value); }
27 explicit operator std::string_view() const noexcept { return symbol_provider::string_for(value); }
28
29 auto operator->() const noexcept requires std::is_pointer_v<internal_value_type> { return value; }
30
31 bool operator==(symbol_base const& other) const noexcept { return value == other.value || symbol_provider::compare(value, other.value) == 0; }
32 auto operator<=>(symbol_base const& other) const noexcept { return symbol_provider::compare(value, other.value); }
33
34 friend bool operator==(std::string_view a, symbol_base const& b) noexcept { return a == b.get_string(); }
35 friend auto operator<=>(std::string_view a, symbol_base const& b) noexcept { return a <=> b.get_string(); }
36
37 friend std::ostream& operator<<(std::ostream& o, const symbol_base& ptr)
38 {
39 o << ptr.get_string();
40 return o;
41 }
42 };
43}
44
45template <typename SYMBOL_PROVIDER>
46struct std::hash<ghassanpl::symbol_base<SYMBOL_PROVIDER>> {
47 size_t operator()(const ghassanpl::symbol_base<SYMBOL_PROVIDER>& x) const noexcept { return x.get_hash(); }
48};
49
50namespace ghassanpl
51{
52
53 template <typename T>
54 concept symbol_provider =
55 std::is_class_v<T>
56 && requires {
57 typename T::internal_value_type;
58 typename T::hash_type;
59 { T::empty_value() } noexcept -> std::same_as<typename T::internal_value_type>;
60 { T::insert(std::string_view{}) } -> std::same_as<typename T::internal_value_type>;
61 { T::string_for(typename T::internal_value_type{}) } noexcept -> std::same_as<std::string_view>;
62 { T::hash_for(typename T::internal_value_type{}) } noexcept -> std::same_as<typename T::hash_type>;
63 { T::compare(typename T::internal_value_type{}, typename T::internal_value_type{}) } noexcept -> std::same_as<std::strong_ordering>;
64 }
65 && std::three_way_comparable<typename T::internal_value_type>
66 && std::regular<typename T::internal_value_type>
67 ;
68
69 template <typename TAG = void>
70 struct default_symbol_provider_t
71 {
72 static default_symbol_provider_t& instance() noexcept
73 {
74 static default_symbol_provider_t inst;
75 return inst;
76 }
77
78 using internal_value_type = std::string const*;
79 using hash_type = size_t;
80 static internal_value_type empty_value() noexcept { return instance().m_empty_string; }
81 static internal_value_type insert(std::string_view val)
82 {
83 if (val.empty())
84 return empty_value();
85
86 auto& values = instance().m_values;
87 if (auto v = values.find(val); v == values.end())
88 return &*values.insert(std::string{ val }).first;
89 else
90 return &*v;
91 }
92 static std::string_view string_for(internal_value_type val) noexcept { return val ? std::string_view{ *val } : std::string_view{}; }
93 static hash_type hash_for(internal_value_type val) noexcept { return std::hash<const void*>{}(val); }
94
95 static std::strong_ordering compare(internal_value_type a, internal_value_type b) noexcept {
96 return (a == b) ? std::strong_ordering::equal : (*a <=> *b);
97 }
98
100
101 void clear() noexcept
102 {
103 m_values.clear();
104 m_values.insert(std::string{});
105 m_empty_string = &*m_values.begin();
106 }
107
108 size_t size() const noexcept { return m_values.size(); }
109 size_t count() const noexcept { return size(); }
110
111 auto const& values() const noexcept { return m_values; }
112 auto empty_string() const noexcept { return m_empty_string; }
113
114 protected:
115
116 std::set<std::string, std::less<>> m_values{ std::string{} };
117 std::string const* m_empty_string = &*m_values.begin();
118 };
119
120 using default_symbol_provider = default_symbol_provider_t<void>;
121 using symbol = symbol_base<default_symbol_provider>;
122}
123
constexpr auto bit_count
Equal to the number of bits in the type.
Definition bits.h:33
Primary namespace for everything in this library.
Definition align+rec2.h:10