1+ #if !defined(SYMBOL_HXX)
2+ #define SYMBOL_HXX
3+
4+ #include < cstdint>
5+ #include < deque>
6+ #include < string>
7+ #include < string_view>
8+ #include < unordered_map>
9+ #include < utility>
10+ #include " wheel_parser/config.hxx"
11+ #include " wheel_parser/allocator.hxx"
12+
13+ WHEEL_PARSER_AST_NAMESPACE
14+ using SymbolID = uint32_t ;
15+
16+ inline constexpr SymbolID INVALID_SYMBOL_ID = static_cast <SymbolID>(-1 );
17+
18+ struct SymbolHash {
19+ using is_transparent = void ;
20+
21+ [[nodiscard]] size_t operator ()(std::string_view text) const noexcept {
22+ return std::hash<std::string_view>{}(text);
23+ }
24+
25+ [[nodiscard]] size_t operator ()(const std::string &text) const noexcept {
26+ return std::hash<std::string_view>{}(text);
27+ }
28+ };
29+
30+ struct SymbolEqual {
31+ using is_transparent = void ;
32+
33+ [[nodiscard]] bool operator ()(std::string_view lhs, std::string_view rhs) const noexcept {
34+ return lhs == rhs;
35+ }
36+
37+ [[nodiscard]] bool operator ()(const std::string &lhs, const std::string &rhs) const noexcept {
38+ return lhs == rhs;
39+ }
40+
41+ [[nodiscard]] bool operator ()(const std::string &lhs, std::string_view rhs) const noexcept {
42+ return lhs == rhs;
43+ }
44+
45+ [[nodiscard]] bool operator ()(std::string_view lhs, const std::string &rhs) const noexcept {
46+ return lhs == rhs;
47+ }
48+ };
49+
50+ class StringInterner {
51+ private:
52+ std::deque<std::string> m_storage;
53+ std::unordered_map<std::string_view, SymbolID, SymbolHash, SymbolEqual> m_index;
54+
55+ private:
56+ void rebuild_index () {
57+ m_index.clear ();
58+ for (SymbolID id = 0 ; id < static_cast <SymbolID>(m_storage.size ()); ++id) {
59+ m_index.emplace (std::string_view (m_storage[id]), id);
60+ }
61+ }
62+
63+ public:
64+ StringInterner () = default ;
65+ ~StringInterner () = default ;
66+ StringInterner (const StringInterner&) = delete ;
67+ StringInterner& operator =(const StringInterner&) = delete ;
68+
69+ StringInterner (StringInterner&& other) noexcept :
70+ m_storage (std::move(other.m_storage)),
71+ m_index () {
72+
73+ rebuild_index ();
74+ }
75+
76+ StringInterner &operator =(StringInterner&& other) noexcept {
77+ if (this != &other) {
78+ m_storage = std::move (other.m_storage );
79+ rebuild_index ();
80+ }
81+
82+ return *this ;
83+ }
84+
85+ [[nodiscard]] SymbolID intern (std::string_view text) {
86+ auto found = m_index.find (text);
87+ if (found != m_index.end ()) {
88+ return found->second ;
89+ }
90+
91+ const SymbolID symbol_id = static_cast <SymbolID>(m_storage.size ());
92+ m_storage.emplace_back (text);
93+ m_index.emplace (std::string_view (m_storage.back ()), symbol_id);
94+
95+ return symbol_id;
96+ }
97+
98+ [[nodiscard]] std::string_view resolve (SymbolID symbol_id) const noexcept {
99+ if (symbol_id >= m_storage.size ()) {
100+ return {};
101+ }
102+
103+ return m_storage[symbol_id];
104+ }
105+
106+ [[nodiscard]] size_t size () const noexcept {
107+ return m_storage.size ();
108+ }
109+ };
110+
111+ WHEEL_PARSER_END_NAMESPACE
112+
113+ #endif // SYMBOL_HXX
0 commit comments