aboutsummaryrefslogtreecommitdiff
path: root/gdbsupport/string-set.h
diff options
context:
space:
mode:
Diffstat (limited to 'gdbsupport/string-set.h')
-rw-r--r--gdbsupport/string-set.h129
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 */