diff options
Diffstat (limited to 'gdbsupport/string-set.h')
-rw-r--r-- | gdbsupport/string-set.h | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/gdbsupport/string-set.h b/gdbsupport/string-set.h new file mode 100644 index 0000000..c9078fc --- /dev/null +++ b/gdbsupport/string-set.h @@ -0,0 +1,129 @@ +/* String-interning set + + Copyright (C) 2025 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef GDBSUPPORT_STRING_SET_H +#define GDBSUPPORT_STRING_SET_H + +#include "gdbsupport/unordered_set.h" +#include <string_view> + +namespace gdb +{ + +/* This is a string-interning set. It manages storage for strings, + ensuring that just a single copy of a given string is kept. The + underlying C string will remain valid for the lifetime of this + object. */ + +class string_set +{ +public: + + /* Insert STR into this set. Returns a pointer to the interned + string. */ + const char *insert (const char *str) + { + /* We need to take the length to hash the string anyway, so it's + convenient to just wrap it here. */ + return insert (std::string_view (str)); + } + + /* An overload accepting a string view. */ + const char *insert (std::string_view str) + { + return m_set.insert (str).first->get (); + } + + /* An overload that takes ownership of the string. */ + const char *insert (gdb::unique_xmalloc_ptr<char> str) + { + return m_set.insert (local_string (std::move (str))).first->get (); + } + +private: + + /* The type of string we store. Note that we do not store + std::string here to avoid the small-string optimization + invalidating a pointer on rehash. */ + struct local_string + { + explicit local_string (std::string_view str) + : contents (xstrndup (str.data (), str.size ())), + len (str.size ()) + { } + + explicit local_string (gdb::unique_xmalloc_ptr<char> str) + : contents (std::move (str)), + len (strlen (contents.get ())) + { } + + const char *get () const + { return contents.get (); } + + std::string_view as_view () const + { return std::string_view (contents.get (), len); } + + /* \0-terminated string contents. */ + gdb::unique_xmalloc_ptr<char> contents; + /* Length of the string. */ + size_t len; + }; + + /* Equality object for the set. */ + struct str_eq + { + using is_transparent = void; + + bool operator() (std::string_view lhs, const local_string &rhs) + const noexcept + { + return lhs == rhs.as_view (); + } + + bool operator() (const local_string &lhs, const local_string &rhs) + const noexcept + { + return (*this) (lhs.as_view (), rhs); + } + }; + + /* Hash object for the set. */ + struct str_hash + { + using is_transparent = void; + using is_avalanching = void; + + uint64_t operator() (const local_string &rhs) const noexcept + { + return (*this) (rhs.as_view ()); + } + + uint64_t operator() (std::string_view rhs) const noexcept + { + return ankerl::unordered_dense::hash<std::string_view> () (rhs); + } + }; + + /* The strings. */ + gdb::unordered_set<local_string, str_hash, str_eq> m_set; +}; + +} + +#endif /* GDBSUPPORT_STRING_SET_H */ |