libabigail
abg-interned-str.h
Go to the documentation of this file.
1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2016-2023 Red Hat, Inc.
5 //
6 // Author: Dodji Seketeli
7 
8 /// @file
9 ///
10 /// Declaration of types pertaining to the interned string pool used
11 /// throughout Libabigail, for performance reasons.
12 ///
13 /// For the record, the concept of the String Interning method is
14 /// explained at https://en.wikipedia.org/wiki/String_interning.
15 
16 #ifndef __ABG_INTERNED_STR_H__
17 #define __ABG_INTERNED_STR_H__
18 
19 #include <functional>
20 #include <memory>
21 #include <ostream>
22 #include <string>
23 #include <unordered_set>
24 
25 
26 namespace abigail
27 {
28 // Inject some std types into this namespace.
29 using std::unordered_set;
30 using std::string;
31 using std::ostream;
32 
33 /// The abstraction of an interned string.
34 ///
35 /// It's a wrapper around a pointer to a std::string, along with a set
36 /// of method that helps make this string integrate with std::string
37 /// seamlessly. For instance, the type provides equality operators
38 /// that help compare it against std::string.
39 ///
40 /// Note that this @ref interned_string type is design to have the
41 /// same size as a pointer to a string.
43 {
44  std::string* raw_;
45 
46  /// Constructor.
47  ///
48  /// @param raw the pointer to string that this interned_string
49  /// wraps.
50  interned_string(string* raw)
51  : raw_(raw)
52  {}
53 
54 public:
55 
56  /// Default constructor.
57  ///
58  /// Constructs an empty pointer to string.
60  : raw_()
61  {}
62 
63  /// Copy constructor.
64  ///
65  /// @param o the other instance to copy from.
67  {raw_ = o.raw_;}
68 
69  /// Assignment operator.
70  ///
71  /// @param o the other instance to assign to the current one.
74  {
75  raw_ = o.raw_;
76  return *this;
77  }
78 
79  /// Clear the string.
80  void
82  {raw_ = 0;}
83 
84  /// Test if the current instance of @ref interned_string is empty.
85  ///
86  /// @return true iff the currentisntance of @ref interned_string is
87  /// empty.
88  bool
89  empty() const
90  {return !raw_;}
91 
92  /// Return the underlying pointer to std::string that this
93  /// interned_string wraps.
94  ///
95  /// @return a pointer to the underlying std::string, or 0 if this
96  /// interned_string is empty.
97  const string*
98  raw() const
99  {return raw_;}
100 
101  /// Compare the current instance of @ref interned_string against
102  /// another instance of @ref interned_string.
103  ///
104  /// Note that this comparison is done in O(1), because it compares
105  /// the pointer values of the two underlying pointers to std::string
106  /// held by each instances of @ref interned_string.
107  ///
108  /// @param o the other @ref interned_string to compare against.
109  ///
110  /// @return true iff the current instance equals @p o.
111  bool
112  operator==(const interned_string& o) const
113  {return raw_ == o.raw_;}
114 
115  /// Inequality operator.
116  ///
117  /// @param o the other @ref interned_string to compare the current
118  /// instance against.
119  ///
120  /// @return true iff the current instance is different from the @p
121  /// o.
122  bool
123  operator!=(const interned_string& o) const
124  {return !operator==(o);}
125 
126  /// Compare the current instance of @ref interned_string against
127  /// an instance of std::string.
128  ///
129  /// Note that this comparison is done in O(N), N being the size (in
130  /// number of characters) of the strings being compared.
131  ///
132  /// @param o the instance of std::string to compare against.
133  ///
134  /// @return true iff the current instance equals @p o.
135  bool
136  operator==(const string& o) const
137  {
138  if (raw_)
139  return *raw_ == o;
140  return o.empty();
141  }
142 
143  /// Inequality operator.
144  ///
145  /// Takes the current instance of @ref interned_string and an
146  /// instance of std::string.
147  ///
148  /// @param o the instance of std::string to compare the current
149  /// instance of @ref interned_string against.
150  ///
151  /// @return true if the current instance of @ref interned_string is
152  /// different from @p o.
153  bool
154  operator!=(const string& o) const
155  {return ! operator==(o);}
156 
157  /// "Less than" operator.
158  ///
159  /// Lexicographically compares the current instance of @ref
160  /// interned_string against another instance.
161  ///
162  /// @param o the other instance of @ref interned_string to compare
163  /// against.
164  ///
165  /// @return true iff the current instance of interned_string is
166  /// lexicographycally less than the string @p o.
167  bool
168  operator<(const interned_string& o) const
169  {return static_cast<string>(*this) < static_cast<std::string>(o);}
170 
171  /// Conversion operator to string.
172  ///
173  /// @return the underlying string this instance refers too.
174  operator string() const
175  {
176  if (!raw_)
177  return "";
178  return *raw_;
179  }
180 
181  friend class interned_string_pool;
182 }; // end class interned_string
183 
184 bool
185 operator==(const string& l, const interned_string& r);
186 
187 bool
188 operator!=(const string& l, const interned_string& r);
189 
190 ostream&
191 operator<<(ostream& o, const interned_string& s);
192 
193 string
194 operator+(const interned_string& s1,const string& s2);
195 
196 string
197 operator+(const string& s1, const interned_string& s2);
198 
199 /// A functor to hash instances of @ref interned_string.
201 {
202  /// The hash operator.
203  ///
204  /// It's super fast because hashing an interned string amounts to
205  /// hashing the pointer to it's underlying string. It's because
206  /// every distinct string is present only in one copy in the
207  /// environment.
208  ///
209  /// @param s the instance of @ref interned_string to hash.
210  ///
211  /// @return the returned hash value.
212  size_t
213  operator()(const interned_string& s) const
214  {
215  std::hash<size_t> hash_size_t;
216  return hash_size_t(reinterpret_cast<size_t>(s.raw()));
217  }
218 }; // end struct hash_interned_string
219 
220 
221 /// The interned string pool.
222 ///
223 /// This is where all the distinct strings represented by the interned
224 /// strings leave. The pool is the actor responsible for creating
225 /// interned strings.
227 {
228  struct priv;
229  std::unique_ptr<priv> priv_;
230 
231 public:
232 
234 
236  create_string(const std::string&);
237 
238  bool
239  has_string(const char* s) const;
240 
241  const char*
242  get_string(const char* s) const;
243 
245 }; // end class interned_string_pool
246 
247 /// Convenience typedef for a set of @ref interned_string
248 typedef unordered_set<interned_string,
250 
251 } // end namespace abigail
252 
253 #endif // __ABG_INTERNED_STR_H__
The interned string pool.
bool has_string(const char *s) const
Test if the interned string pool already contains a string with a given value.
Definition: abg-ir.cc:97
const char * get_string(const char *s) const
Get a pointer to the interned string which has a given value.
Definition: abg-ir.cc:107
interned_string create_string(const std::string &)
Create an interned string with a given value.
Definition: abg-ir.cc:124
interned_string_pool()
Default constructor.
Definition: abg-ir.cc:84
~interned_string_pool()
Destructor.
Definition: abg-ir.cc:133
The abstraction of an interned string.
bool operator<(const interned_string &o) const
"Less than" operator.
interned_string()
Default constructor.
const string * raw() const
Return the underlying pointer to std::string that this interned_string wraps.
bool operator==(const string &o) const
Compare the current instance of interned_string against an instance of std::string.
bool empty() const
Test if the current instance of interned_string is empty.
bool operator!=(const string &o) const
Inequality operator.
interned_string(const interned_string &o)
Copy constructor.
void clear()
Clear the string.
bool operator!=(const interned_string &o) const
Inequality operator.
bool operator==(const interned_string &o) const
Compare the current instance of interned_string against another instance of interned_string.
interned_string & operator=(const interned_string &o)
Assignment operator.
Toplevel namespace for libabigail.
std::string operator+(const interned_string &s1, const std::string &s2)
Concatenation operator.
Definition: abg-ir.cc:186
unordered_set< interned_string, hash_interned_string > interned_string_set_type
Convenience typedef for a set of interned_string.
bool operator==(const std::string &l, const interned_string &r)
Equality operator.
Definition: abg-ir.cc:152
std::ostream & operator<<(std::ostream &o, const interned_string &s)
Streaming operator.
Definition: abg-ir.cc:169
A functor to hash instances of interned_string.
size_t operator()(const interned_string &s) const
The hash operator.