blob: ea8443467e5bdc5df651d7299e3b587cb4baeb3f [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
14using namespace lldb_private;
15
16
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017class Pool
18{
19public:
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000020 typedef const char * StringPoolValueType;
21 typedef llvm::StringMap<StringPoolValueType, llvm::BumpPtrAllocator> StringPool;
22 typedef llvm::StringMapEntry<StringPoolValueType> StringPoolEntryType;
23
Chris Lattner30fdc8d2010-06-08 16:52:24 +000024 //------------------------------------------------------------------
25 // Default constructor
26 //
27 // Initialize the member variables and create the empty string.
28 //------------------------------------------------------------------
29 Pool () :
30 m_mutex (Mutex::eMutexTypeRecursive),
31 m_string_map ()
32 {
33 }
34
35 //------------------------------------------------------------------
36 // Destructor
37 //------------------------------------------------------------------
38 ~Pool ()
39 {
40 }
41
42
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000043 static StringPoolEntryType &
Chris Lattner30fdc8d2010-06-08 16:52:24 +000044 GetStringMapEntryFromKeyData (const char *keyData)
45 {
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000046 char *ptr = const_cast<char*>(keyData) - sizeof (StringPoolEntryType);
47 return *reinterpret_cast<StringPoolEntryType*>(ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000048 }
49
50 size_t
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000051 GetConstCStringLength (const char *ccstr) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +000052 {
53 if (ccstr)
54 {
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000055 const StringPoolEntryType&entry = GetStringMapEntryFromKeyData (ccstr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000056 return entry.getKey().size();
57 }
58 return 0;
59 }
60
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000061 StringPoolValueType
62 GetMangledCounterpart (const char *ccstr) const
63 {
64 if (ccstr)
65 return GetStringMapEntryFromKeyData (ccstr).getValue();
66 return 0;
67 }
68
69 bool
70 SetMangledCounterparts (const char *key_ccstr, const char *value_ccstr)
71 {
72 if (key_ccstr && value_ccstr)
73 {
74 GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr);
75 GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr);
76 return true;
77 }
78 return false;
79 }
80
Chris Lattner30fdc8d2010-06-08 16:52:24 +000081 const char *
82 GetConstCString (const char *cstr)
83 {
84 if (cstr)
Benjamin Kramereb9165c2010-06-22 15:28:34 +000085 return GetConstCStringWithLength (cstr, strlen (cstr));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000086 return NULL;
87 }
88
89 const char *
90 GetConstCStringWithLength (const char *cstr, int cstr_len)
91 {
92 if (cstr)
93 {
94 Mutex::Locker locker (m_mutex);
95 llvm::StringRef string_ref (cstr, cstr_len);
Greg Clayton40df35e2011-06-10 00:00:19 +000096 StringPoolEntryType& entry = m_string_map.GetOrCreateValue (string_ref, (StringPoolValueType)NULL);
Greg Claytonc982c762010-07-09 20:39:50 +000097 return entry.getKeyData();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000098 }
99 return NULL;
100 }
101
102 const char *
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000103 GetConstCStringAndSetMangledCounterPart (const char *demangled_cstr, const char *mangled_ccstr)
104 {
105 if (demangled_cstr)
106 {
107 Mutex::Locker locker (m_mutex);
108 // Make string pool entry with the mangled counterpart already set
109 StringPoolEntryType& entry = m_string_map.GetOrCreateValue (llvm::StringRef (demangled_cstr), mangled_ccstr);
110
111 // Extract the const version of the demangled_cstr
112 const char *demangled_ccstr = entry.getKeyData();
113 // Now assign the demangled const string as the counterpart of the
114 // mangled const string...
115 GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr);
116 // Return the constant demangled C string
117 return demangled_ccstr;
118 }
119 return NULL;
120 }
121
122 const char *
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000123 GetConstTrimmedCStringWithLength (const char *cstr, int cstr_len)
124 {
125 if (cstr)
126 {
Benjamin Kramereb9165c2010-06-22 15:28:34 +0000127 int trimmed_len = std::min<int> (strlen (cstr), cstr_len);
128 return GetConstCStringWithLength (cstr, trimmed_len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000129 }
130 return NULL;
131 }
132
133 //------------------------------------------------------------------
134 // Return the size in bytes that this object and any items in its
Greg Clayton24756642011-09-12 03:55:58 +0000135 // collection of uniqued strings + data count values takes in
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000136 // memory.
137 //------------------------------------------------------------------
138 size_t
139 MemorySize() const
140 {
141 Mutex::Locker locker (m_mutex);
142 size_t mem_size = sizeof(Pool);
143 const_iterator end = m_string_map.end();
144 for (const_iterator pos = m_string_map.begin(); pos != end; ++pos)
145 {
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000146 mem_size += sizeof(StringPoolEntryType) + pos->getKey().size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000147 }
148 return mem_size;
149 }
150
151protected:
152 //------------------------------------------------------------------
153 // Typedefs
154 //------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000155 typedef StringPool::iterator iterator;
156 typedef StringPool::const_iterator const_iterator;
157
158 //------------------------------------------------------------------
159 // Member variables
160 //------------------------------------------------------------------
161 mutable Mutex m_mutex;
162 StringPool m_string_map;
163};
164
165//----------------------------------------------------------------------
166// Frameworks and dylibs aren't supposed to have global C++
167// initializers so we hide the string pool in a static function so
168// that it will get initialized on the first call to this static
169// function.
Jim Ingham5ce45fd2012-05-09 18:37:10 +0000170//
171// Note, for now we make the string pool a pointer to the pool, because
172// we can't guarantee that some objects won't get destroyed after the
173// global destructor chain is run, and trying to make sure no destructors
174// touch ConstStrings is difficult. So we leak the pool instead.
175//
176// FIXME: If we are going to keep it this way we should come up with some
177// abstraction to "pthread_once" so we don't have to check the pointer
178// every time.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000179//----------------------------------------------------------------------
180static Pool &
181StringPool()
182{
Jim Ingham5ce45fd2012-05-09 18:37:10 +0000183 static Mutex g_pool_initialization_mutex;
184 static Pool *g_string_pool = NULL;
185
186 if (g_string_pool == NULL)
187 {
188 Mutex::Locker initialization_locker(g_pool_initialization_mutex);
189 if (g_string_pool == NULL)
190 {
191 g_string_pool = new Pool();
192 }
193 }
194
195 return *g_string_pool;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000196}
197
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000198ConstString::ConstString (const char *cstr) :
199 m_string (StringPool().GetConstCString (cstr))
200{
201}
202
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000203ConstString::ConstString (const char *cstr, size_t cstr_len) :
204 m_string (StringPool().GetConstCStringWithLength (cstr, cstr_len))
205{
206}
207
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000208bool
209ConstString::operator < (const ConstString& rhs) const
210{
211 if (m_string == rhs.m_string)
212 return false;
213
214 llvm::StringRef lhs_string_ref (m_string, StringPool().GetConstCStringLength (m_string));
215 llvm::StringRef rhs_string_ref (rhs.m_string, StringPool().GetConstCStringLength (rhs.m_string));
216
217 // If both have valid C strings, then return the comparison
218 if (lhs_string_ref.data() && rhs_string_ref.data())
219 return lhs_string_ref < rhs_string_ref;
220
221 // Else one of them was NULL, so if LHS is NULL then it is less than
222 return lhs_string_ref.data() == NULL;
223}
224
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000225Stream&
226lldb_private::operator << (Stream& s, const ConstString& str)
227{
228 const char *cstr = str.GetCString();
229 if (cstr)
230 s << cstr;
231
232 return s;
233}
234
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000235size_t
236ConstString::GetLength () const
237{
238 return StringPool().GetConstCStringLength (m_string);
239}
240
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000241int
242ConstString::Compare (const ConstString& lhs, const ConstString& rhs)
243{
244 // If the iterators are the same, this is the same string
245 register const char *lhs_cstr = lhs.m_string;
246 register const char *rhs_cstr = rhs.m_string;
247 if (lhs_cstr == rhs_cstr)
248 return 0;
249 if (lhs_cstr && rhs_cstr)
250 {
251 llvm::StringRef lhs_string_ref (lhs_cstr, StringPool().GetConstCStringLength (lhs_cstr));
252 llvm::StringRef rhs_string_ref (rhs_cstr, StringPool().GetConstCStringLength (rhs_cstr));
253 return lhs_string_ref.compare(rhs_string_ref);
254 }
255
256 if (lhs_cstr)
257 return +1; // LHS isn't NULL but RHS is
258 else
259 return -1; // LHS is NULL but RHS isn't
260}
261
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000262void
263ConstString::Dump(Stream *s, const char *fail_value) const
264{
265 const char *cstr = AsCString (fail_value);
266 if (cstr)
267 s->PutCString (cstr);
268}
269
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000270void
271ConstString::DumpDebug(Stream *s) const
272{
273 const char *cstr = GetCString ();
274 size_t cstr_len = GetLength();
275 // Only print the parens if we have a non-NULL string
276 const char *parens = cstr ? "\"" : "";
277 s->Printf("%*p: ConstString, string = %s%s%s, length = %zu", (int)sizeof(void*) * 2, this, parens, cstr, parens, cstr_len);
278}
279
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000280void
281ConstString::SetCString (const char *cstr)
282{
283 m_string = StringPool().GetConstCString (cstr);
284}
285
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000286void
287ConstString::SetCStringWithMangledCounterpart (const char *demangled, const ConstString &mangled)
288{
289 m_string = StringPool().GetConstCStringAndSetMangledCounterPart (demangled, mangled.m_string);
290}
291
292bool
293ConstString::GetMangledCounterpart (ConstString &counterpart) const
294{
295 counterpart.m_string = StringPool().GetMangledCounterpart(m_string);
296 return counterpart;
297}
298
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000299void
300ConstString::SetCStringWithLength (const char *cstr, size_t cstr_len)
301{
302 m_string = StringPool().GetConstCStringWithLength(cstr, cstr_len);
303}
304
305void
306ConstString::SetTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
307{
308 m_string = StringPool().GetConstTrimmedCStringWithLength (cstr, cstr_len);
309}
310
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000311size_t
312ConstString::StaticMemorySize()
313{
314 // Get the size of the static string pool
315 return StringPool().MemorySize();
316}