11# include <absl/container/flat_hash_map.h>
12# include <absl/container/flat_hash_set.h>
14# include <unordered_map>
15# include <unordered_set>
20static_assert(std::endian::native == std::endian::little || std::endian::native == std::endian::big,
21 "mixed endianess not supported");
55 for (
size_t i = 0, e = s1->
size; res && i != e; ++i) res &= s1->
chars[i] == s2->
chars[i];
62 return std::hash<std::string_view>()(std::string_view(s->
chars, s->
size));
67 template<
class H>
friend H AbslHashValue(H h,
const String*
string) {
68 return H::combine(std::move(h), std::string_view(string->chars, string->size));
73 static_assert(
sizeof(String) ==
sizeof(size_t),
"String.chars should be 0");
80 Sym() noexcept = default;
84 bool empty()
const {
return ptr_ == 0; }
86 if (
empty())
return 0;
88 return ((
const String*)ptr_)->size;
98 char front()
const {
return (*
this)[0]; }
99 char back()
const {
return (*
this)[
size() - 1]; }
108 auto rbegin()
const {
return std::reverse_iterator(
end()); }
109 auto rend()
const {
return std::reverse_iterator(
begin()); }
121 if (s == 0)
return std::strong_ordering::less;
122 auto cmp = (*this)[0] <=> c;
123 if (s == 1)
return cmp;
124 return cmp == 0 ? std::strong_ordering::greater : cmp;
133 operator const char*()
const {
return c_str(); }
135 std::string_view
view()
const {
136 if (
empty())
return {(
const char*)&ptr_, 0};
139 uintptr_t offset = std::endian::native == std::endian::little ? 1 : 0;
141 return std::string_view(((
const String*)ptr_)->chars, ((
const String*)ptr_)->
size);
143 operator std::string_view()
const {
return view(); }
148 std::string
str()
const {
return std::string(
view()); }
149 explicit operator std::string()
const {
return str(); }
151 explicit operator bool()
const {
return ptr_; }
155 template<
class H>
friend H AbslHashValue(H h,
Sym sym) {
return H::combine(std::move(h), sym.ptr_); }
157 friend struct ::std::hash<fe::Sym>;
171template<>
struct std::hash<
fe::Sym> {
172 size_t operator()(
fe::Sym sym)
const {
return std::hash<uintptr_t>()(sym.ptr_); }
182template<
class V>
using SymMap = absl::flat_hash_map<Sym, V>;
183using SymSet = absl::flat_hash_set<Sym>;
185template<
class V>
using SymMap = std::unordered_map<Sym, V>;
203 : pool_(container_.allocator<const
String*>()) {}
215 if (s.empty())
return Sym();
216 auto size = s.size();
219 uintptr_t ptr = size;
222 if constexpr (std::endian::native == std::endian::little)
223 for (uintptr_t i = 0, shift = 8; i != size; ++i, shift += 8) ptr |= (uintptr_t(s[i]) << shift);
226 ptr |= (uintptr_t(s[i]) << shift);
230 auto state = strings_.
state();
232 new (ptr)
String(s.size());
233 *std::copy(s.begin(), s.end(), ptr->chars) =
'\0';
234 auto [i, ins] = pool_.emplace(ptr);
235 if (ins)
return Sym((uintptr_t)ptr);
237 return Sym((uintptr_t)*i);
239 Sym sym(
const std::string& s) {
return sym((std::string_view)s); }
241 Sym sym(
const char* s) {
return s ==
nullptr || *s ==
'\0' ?
Sym() :
sym(std::string_view(s, strlen(s))); }
248 swap(p1.strings_, p2.strings_ );
250 swap(p1.container_, p2.container_);
252 swap(p1.pool_, p2.pool_ );
259 absl::flat_hash_set<const String*, absl::Hash<const String*>, String::Equal> pool_;
262 std::unordered_set<const String*, String::Hash, String::Equal, Arena::Allocator<const String*>> pool_;
An arena pre-allocates so-called pages of size Arena::page_size_.
Arena & align(size_t a)
Align next allocate(size_t) to a.
void deallocate(size_t num_bytes)
void * allocate(size_t num_bytes)
Get n bytes of fresh memory.
Hash set where all strings - wrapped in Symbol - live in.
Sym sym(const char *s)
s is a null-terminated C-string.
Sym sym(std::string_view s)
SymPool & operator=(SymPool)=delete
SymPool(const SymPool &)=delete
Sym sym(const std::string &s)
SymPool(SymPool &&other) noexcept
friend void swap(SymPool &p1, SymPool &p2) noexcept
A Symbol just wraps a pointer to Sym::String, so pass Sym itself around as value.
const char * c_str() const
std::string str() const
This involves a copy.
auto operator<=>(char c) const
static constexpr size_t Short_String_Mask
static constexpr size_t Short_String_Bytes
std::string_view operator*() const
bool operator==(Sym other) const
friend std::ostream & operator<<(std::ostream &o, Sym sym)
auto operator!=(char c) const
auto operator==(char c) const
char operator[](size_t i) const
std::string_view view() const
auto operator<=>(Sym other) const
bool operator!=(Sym other) const
std::unordered_map< Sym, V > SymMap
std::unordered_set< Sym > SymSet
bool operator()(const String *s1, const String *s2) const
size_t operator()(const String *s) const
String() noexcept=default