ACAV f0ba4b7c9529
Abstract Syntax Tree (AST) visualization tool for C, C++, and Objective-C
Loading...
Searching...
No Matches
InternedString.h
Go to the documentation of this file.
1/*$!{
2* Aurora Clang AST Viewer (ACAV)
3*
4* Copyright (c) 2026 Min Liu
5* Copyright (c) 2026 Michael David Adams
6*
7* SPDX-License-Identifier: GPL-2.0-or-later
8*
9* This program is free software; you can redistribute it and/or modify
10* it under the terms of the GNU General Public License as published by
11* the Free Software Foundation; either version 2 of the License, or
12* (at your option) any later version.
13*
14* This program is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17* GNU General Public License for more details.
18*
19* You should have received a copy of the GNU General Public License along
20* with this program; if not, see <https://www.gnu.org/licenses/>.
21}$!*/
22
25#pragma once
26
27#include "Config.h"
28
29#include <cstdint>
30#include <mutex>
31#include <string>
32#include <string_view>
33#include <unordered_set>
34
35namespace acav {
36
37#ifdef ACAV_ENABLE_STRING_STATS
39struct StringInterningStats {
40 std::size_t uniqueStrings;
41 std::size_t totalReferences;
42 std::size_t poolMemoryBytes;
43 std::size_t poolOverheadBytes;
44 std::size_t withoutInterningBytes;
45 std::size_t savedBytes;
46 double savingsPercent;
47};
48#endif
49
55class InternedString {
56public:
57 using value_type = std::string::value_type;
58
59 InternedString() = default;
61 explicit InternedString(const std::string &v);
63 explicit InternedString(std::string &&v);
65 InternedString(const char *v);
67 explicit InternedString(std::string_view v);
69 InternedString(std::size_t n, char c);
70
71 InternedString(const InternedString &other);
72 InternedString &operator=(const InternedString &other);
73 InternedString(InternedString &&other) noexcept;
74 InternedString &operator=(InternedString &&other) noexcept;
75 ~InternedString();
76
78 const std::string &str() const;
80 bool empty() const noexcept;
82 std::size_t size() const noexcept;
83
84 using const_iterator = std::string::const_iterator;
85 const_iterator begin() const noexcept;
86 const_iterator end() const noexcept;
87
88 const char &operator[](std::size_t pos) const;
89 char &operator[](std::size_t pos);
90 const char &back() const;
91 const char *c_str() const;
92 const char *data() const;
93
95 void clear();
96
97 void push_back(char c);
98 InternedString &append(const char *s, std::size_t n);
99 InternedString &operator+=(const InternedString &other);
100 void resize(std::size_t n, char c = '\0');
101
102 bool operator==(const InternedString &other) const noexcept;
103 bool operator!=(const InternedString &other) const noexcept;
104 friend bool operator<(const InternedString &lhs,
105 const InternedString &rhs) noexcept;
106
108 static std::size_t poolSize();
110 std::size_t refCount() const noexcept;
112 static void displayPool();
113
114#ifdef ACAV_ENABLE_STRING_STATS
116 static StringInterningStats getStats();
118 static void printStats(const char *label = nullptr);
120 static void resetStats();
121#endif
122
123private:
124 // Internal storage: holds the actual string and reference count
125 struct StringData {
126 explicit StringData(const std::string &v);
127 explicit StringData(std::string &&v);
128 std::string value_;
129 std::size_t refCount_ = 0;
130 };
131
132 // Hash functor for unordered_set with transparent lookup
133 struct Hash {
134 using is_transparent = void;
135 std::size_t operator()(const StringData *s) const noexcept;
136 std::size_t operator()(const std::string &s) const noexcept;
137 std::size_t operator()(std::string_view s) const noexcept;
138 };
139
140 // Equality functor for unordered_set with transparent lookup
141 struct Equal {
142 using is_transparent = void;
143 bool operator()(const StringData *a, const StringData *b) const noexcept;
144 bool operator()(const StringData *a, const std::string &b) const noexcept;
145 bool operator()(const std::string &a, const StringData *b) const noexcept;
146 bool operator()(const StringData *a, std::string_view b) const noexcept;
147 bool operator()(std::string_view a, const StringData *b) const noexcept;
148 };
149
150 // Release current data (decrement refcount, delete if zero)
151 void release();
152
153 // Find or create string in pool (thread-safe)
154 static StringData *internString(const std::string &v);
155 static StringData *internString(std::string &&v);
156 static StringData *internString(std::string_view v);
157
158 // Global pool of all interned strings (thread-safe)
159 static std::unordered_set<StringData *, Hash, Equal> pool_;
160 static std::mutex poolMutex_;
161
162 // Pointer to the shared string data
163 StringData *data_ = nullptr;
164};
165
166} // namespace acav
167
168// Support for std::format (C++20)
169#include <format>
170namespace std {
171template <> struct formatter<acav::InternedString> : formatter<string_view> {
172 auto format(const acav::InternedString &value, format_context &ctx) const {
173 return formatter<string_view>::format(value.str(), ctx);
174 }
175};
176} // namespace std
Immutable string with automatic deduplication via global pool.
static void displayPool()
Display all strings in pool (for debugging).
std::size_t refCount() const noexcept
Get reference count for this string.
std::size_t size() const noexcept
Get string length.
bool empty() const noexcept
Check if the string is empty.
const std::string & str() const
Get the underlying string value.
static std::size_t poolSize()
Get current pool size (for debugging).
void clear()
Clear the string (sets to empty interned string).