blob: 85f8d3c65cd958a09aeedab2f9e06215dd3e3847 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- ConstString.cpp -----------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include "lldb/Core/ConstString.h"
10#include "lldb/Core/Stream.h"
11#include "lldb/Host/Mutex.h"
12#include "llvm/ADT/StringMap.h"
13
Greg Claytonff48e4b2015-02-03 02:05:44 +000014#include <mutex> // std::once
Enrico Granata3cfc49f2014-12-16 02:34:13 +000015
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016using namespace lldb_private;
17
18
Chris Lattner30fdc8d2010-06-08 16:52:24 +000019class Pool
20{
21public:
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000022 typedef const char * StringPoolValueType;
23 typedef llvm::StringMap<StringPoolValueType, llvm::BumpPtrAllocator> StringPool;
24 typedef llvm::StringMapEntry<StringPoolValueType> StringPoolEntryType;
25
Chris Lattner30fdc8d2010-06-08 16:52:24 +000026 //------------------------------------------------------------------
27 // Default constructor
28 //
29 // Initialize the member variables and create the empty string.
30 //------------------------------------------------------------------
31 Pool () :
32 m_mutex (Mutex::eMutexTypeRecursive),
33 m_string_map ()
34 {
35 }
36
37 //------------------------------------------------------------------
38 // Destructor
39 //------------------------------------------------------------------
40 ~Pool ()
41 {
42 }
43
44
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000045 static StringPoolEntryType &
Chris Lattner30fdc8d2010-06-08 16:52:24 +000046 GetStringMapEntryFromKeyData (const char *keyData)
47 {
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000048 char *ptr = const_cast<char*>(keyData) - sizeof (StringPoolEntryType);
49 return *reinterpret_cast<StringPoolEntryType*>(ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000050 }
51
52 size_t
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000053 GetConstCStringLength (const char *ccstr) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +000054 {
55 if (ccstr)
56 {
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000057 const StringPoolEntryType&entry = GetStringMapEntryFromKeyData (ccstr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000058 return entry.getKey().size();
59 }
60 return 0;
61 }
62
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000063 StringPoolValueType
64 GetMangledCounterpart (const char *ccstr) const
65 {
66 if (ccstr)
67 return GetStringMapEntryFromKeyData (ccstr).getValue();
68 return 0;
69 }
70
71 bool
72 SetMangledCounterparts (const char *key_ccstr, const char *value_ccstr)
73 {
74 if (key_ccstr && value_ccstr)
75 {
76 GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr);
77 GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr);
78 return true;
79 }
80 return false;
81 }
82
Chris Lattner30fdc8d2010-06-08 16:52:24 +000083 const char *
84 GetConstCString (const char *cstr)
85 {
86 if (cstr)
Benjamin Kramereb9165c2010-06-22 15:28:34 +000087 return GetConstCStringWithLength (cstr, strlen (cstr));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000088 return NULL;
89 }
90
91 const char *
Greg Claytonc7bece562013-01-25 18:06:21 +000092 GetConstCStringWithLength (const char *cstr, size_t cstr_len)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000093 {
94 if (cstr)
95 {
96 Mutex::Locker locker (m_mutex);
97 llvm::StringRef string_ref (cstr, cstr_len);
Oleksiy Vyalovb92935b2014-11-19 17:24:58 +000098 StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first;
Greg Claytonc982c762010-07-09 20:39:50 +000099 return entry.getKeyData();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100 }
101 return NULL;
102 }
103
104 const char *
Greg Clayton1f746072012-08-29 21:13:06 +0000105 GetConstCStringWithStringRef (const llvm::StringRef &string_ref)
106 {
107 if (string_ref.data())
108 {
109 Mutex::Locker locker (m_mutex);
Oleksiy Vyalovb92935b2014-11-19 17:24:58 +0000110 StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first;
Greg Clayton1f746072012-08-29 21:13:06 +0000111 return entry.getKeyData();
112 }
113 return NULL;
114 }
115
116 const char *
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000117 GetConstCStringAndSetMangledCounterPart (const char *demangled_cstr, const char *mangled_ccstr)
118 {
119 if (demangled_cstr)
120 {
121 Mutex::Locker locker (m_mutex);
122 // Make string pool entry with the mangled counterpart already set
Oleksiy Vyalovb92935b2014-11-19 17:24:58 +0000123 StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (llvm::StringRef (demangled_cstr), mangled_ccstr)).first;
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000124
125 // Extract the const version of the demangled_cstr
126 const char *demangled_ccstr = entry.getKeyData();
127 // Now assign the demangled const string as the counterpart of the
128 // mangled const string...
129 GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr);
130 // Return the constant demangled C string
131 return demangled_ccstr;
132 }
133 return NULL;
134 }
135
136 const char *
Greg Claytonc7bece562013-01-25 18:06:21 +0000137 GetConstTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000138 {
139 if (cstr)
140 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000141 const size_t trimmed_len = std::min<size_t> (strlen (cstr), cstr_len);
Benjamin Kramereb9165c2010-06-22 15:28:34 +0000142 return GetConstCStringWithLength (cstr, trimmed_len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000143 }
144 return NULL;
145 }
146
147 //------------------------------------------------------------------
148 // Return the size in bytes that this object and any items in its
Greg Clayton24756642011-09-12 03:55:58 +0000149 // collection of uniqued strings + data count values takes in
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000150 // memory.
151 //------------------------------------------------------------------
152 size_t
153 MemorySize() const
154 {
155 Mutex::Locker locker (m_mutex);
156 size_t mem_size = sizeof(Pool);
157 const_iterator end = m_string_map.end();
158 for (const_iterator pos = m_string_map.begin(); pos != end; ++pos)
159 {
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000160 mem_size += sizeof(StringPoolEntryType) + pos->getKey().size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000161 }
162 return mem_size;
163 }
164
165protected:
166 //------------------------------------------------------------------
167 // Typedefs
168 //------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000169 typedef StringPool::iterator iterator;
170 typedef StringPool::const_iterator const_iterator;
171
172 //------------------------------------------------------------------
173 // Member variables
174 //------------------------------------------------------------------
175 mutable Mutex m_mutex;
176 StringPool m_string_map;
177};
178
179//----------------------------------------------------------------------
180// Frameworks and dylibs aren't supposed to have global C++
181// initializers so we hide the string pool in a static function so
182// that it will get initialized on the first call to this static
183// function.
Jim Ingham5ce45fd2012-05-09 18:37:10 +0000184//
185// Note, for now we make the string pool a pointer to the pool, because
186// we can't guarantee that some objects won't get destroyed after the
187// global destructor chain is run, and trying to make sure no destructors
188// touch ConstStrings is difficult. So we leak the pool instead.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000189//----------------------------------------------------------------------
190static Pool &
191StringPool()
192{
Enrico Granata3cfc49f2014-12-16 02:34:13 +0000193 static std::once_flag g_pool_initialization_flag;
Jim Ingham5ce45fd2012-05-09 18:37:10 +0000194 static Pool *g_string_pool = NULL;
195
Enrico Granata3cfc49f2014-12-16 02:34:13 +0000196 std::call_once(g_pool_initialization_flag, [] () {
197 g_string_pool = new Pool();
198 });
Jim Ingham5ce45fd2012-05-09 18:37:10 +0000199
200 return *g_string_pool;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000201}
202
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000203ConstString::ConstString (const char *cstr) :
204 m_string (StringPool().GetConstCString (cstr))
205{
206}
207
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000208ConstString::ConstString (const char *cstr, size_t cstr_len) :
209 m_string (StringPool().GetConstCStringWithLength (cstr, cstr_len))
210{
211}
212
Greg Clayton67cc0632012-08-22 17:17:09 +0000213ConstString::ConstString (const llvm::StringRef &s) :
214 m_string (StringPool().GetConstCStringWithLength (s.data(), s.size()))
215{
216}
217
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000218bool
219ConstString::operator < (const ConstString& rhs) const
220{
221 if (m_string == rhs.m_string)
222 return false;
223
224 llvm::StringRef lhs_string_ref (m_string, StringPool().GetConstCStringLength (m_string));
225 llvm::StringRef rhs_string_ref (rhs.m_string, StringPool().GetConstCStringLength (rhs.m_string));
226
227 // If both have valid C strings, then return the comparison
228 if (lhs_string_ref.data() && rhs_string_ref.data())
229 return lhs_string_ref < rhs_string_ref;
230
231 // Else one of them was NULL, so if LHS is NULL then it is less than
232 return lhs_string_ref.data() == NULL;
233}
234
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000235Stream&
236lldb_private::operator << (Stream& s, const ConstString& str)
237{
238 const char *cstr = str.GetCString();
239 if (cstr)
240 s << cstr;
241
242 return s;
243}
244
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000245size_t
246ConstString::GetLength () const
247{
248 return StringPool().GetConstCStringLength (m_string);
249}
250
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000251int
252ConstString::Compare (const ConstString& lhs, const ConstString& rhs)
253{
254 // If the iterators are the same, this is the same string
Eric Christopher2490f5c2013-08-30 17:50:57 +0000255 const char *lhs_cstr = lhs.m_string;
256 const char *rhs_cstr = rhs.m_string;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000257 if (lhs_cstr == rhs_cstr)
258 return 0;
259 if (lhs_cstr && rhs_cstr)
260 {
261 llvm::StringRef lhs_string_ref (lhs_cstr, StringPool().GetConstCStringLength (lhs_cstr));
262 llvm::StringRef rhs_string_ref (rhs_cstr, StringPool().GetConstCStringLength (rhs_cstr));
263 return lhs_string_ref.compare(rhs_string_ref);
264 }
265
266 if (lhs_cstr)
267 return +1; // LHS isn't NULL but RHS is
268 else
269 return -1; // LHS is NULL but RHS isn't
270}
271
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000272void
273ConstString::Dump(Stream *s, const char *fail_value) const
274{
Enrico Granata80fcdd42012-11-03 00:09:46 +0000275 if (s)
276 {
277 const char *cstr = AsCString (fail_value);
278 if (cstr)
279 s->PutCString (cstr);
280 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000281}
282
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000283void
284ConstString::DumpDebug(Stream *s) const
285{
286 const char *cstr = GetCString ();
287 size_t cstr_len = GetLength();
288 // Only print the parens if we have a non-NULL string
289 const char *parens = cstr ? "\"" : "";
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000290 s->Printf("%*p: ConstString, string = %s%s%s, length = %" PRIu64,
291 static_cast<int>(sizeof(void*) * 2),
292 static_cast<const void*>(this), parens, cstr, parens,
293 static_cast<uint64_t>(cstr_len));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000294}
295
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000296void
297ConstString::SetCString (const char *cstr)
298{
299 m_string = StringPool().GetConstCString (cstr);
300}
301
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000302void
Greg Clayton67cc0632012-08-22 17:17:09 +0000303ConstString::SetString (const llvm::StringRef &s)
304{
305 m_string = StringPool().GetConstCStringWithLength (s.data(), s.size());
306}
307
308void
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000309ConstString::SetCStringWithMangledCounterpart (const char *demangled, const ConstString &mangled)
310{
311 m_string = StringPool().GetConstCStringAndSetMangledCounterPart (demangled, mangled.m_string);
312}
313
314bool
315ConstString::GetMangledCounterpart (ConstString &counterpart) const
316{
317 counterpart.m_string = StringPool().GetMangledCounterpart(m_string);
Sean Callananddd7a2a2013-10-03 22:27:29 +0000318 return (bool)counterpart;
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000319}
320
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000321void
322ConstString::SetCStringWithLength (const char *cstr, size_t cstr_len)
323{
324 m_string = StringPool().GetConstCStringWithLength(cstr, cstr_len);
325}
326
327void
328ConstString::SetTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
329{
330 m_string = StringPool().GetConstTrimmedCStringWithLength (cstr, cstr_len);
331}
332
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000333size_t
334ConstString::StaticMemorySize()
335{
336 // Get the size of the static string pool
337 return StringPool().MemorySize();
338}