blob: 23679f41a87138458650d70ea4c7cdf2078b0fe0 [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
17//----------------------------------------------------------------------
18// The global string pool is implemented as a hash_map that maps
19// std::string objects to a uint32_t reference count.
20//
21// In debug builds the value that is stored in the ConstString objects is
22// a C string that is owned by one of the std::string objects in the
23// hash map. This was done for visibility purposes when debugging as
24// gcc was often generating insufficient debug info for the
25// iterator objects.
26//
27// In release builds, the value that is stored in the ConstString objects
28// is the iterator into the ConstString::HashMap. This is much faster when
29// it comes to modifying the reference count, and removing strings from
30// the pool.
31//----------------------------------------------------------------------
32class Pool
33{
34public:
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000035 typedef const char * StringPoolValueType;
36 typedef llvm::StringMap<StringPoolValueType, llvm::BumpPtrAllocator> StringPool;
37 typedef llvm::StringMapEntry<StringPoolValueType> StringPoolEntryType;
38
Chris Lattner30fdc8d2010-06-08 16:52:24 +000039 //------------------------------------------------------------------
40 // Default constructor
41 //
42 // Initialize the member variables and create the empty string.
43 //------------------------------------------------------------------
44 Pool () :
45 m_mutex (Mutex::eMutexTypeRecursive),
46 m_string_map ()
47 {
48 }
49
50 //------------------------------------------------------------------
51 // Destructor
52 //------------------------------------------------------------------
53 ~Pool ()
54 {
55 }
56
57
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000058 static StringPoolEntryType &
Chris Lattner30fdc8d2010-06-08 16:52:24 +000059 GetStringMapEntryFromKeyData (const char *keyData)
60 {
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000061 char *ptr = const_cast<char*>(keyData) - sizeof (StringPoolEntryType);
62 return *reinterpret_cast<StringPoolEntryType*>(ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000063 }
64
65 size_t
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000066 GetConstCStringLength (const char *ccstr) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +000067 {
68 if (ccstr)
69 {
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000070 const StringPoolEntryType&entry = GetStringMapEntryFromKeyData (ccstr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000071 return entry.getKey().size();
72 }
73 return 0;
74 }
75
Greg Claytonc3ae1ce2011-06-09 22:34:34 +000076 StringPoolValueType
77 GetMangledCounterpart (const char *ccstr) const
78 {
79 if (ccstr)
80 return GetStringMapEntryFromKeyData (ccstr).getValue();
81 return 0;
82 }
83
84 bool
85 SetMangledCounterparts (const char *key_ccstr, const char *value_ccstr)
86 {
87 if (key_ccstr && value_ccstr)
88 {
89 GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr);
90 GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr);
91 return true;
92 }
93 return false;
94 }
95
Chris Lattner30fdc8d2010-06-08 16:52:24 +000096 const char *
97 GetConstCString (const char *cstr)
98 {
99 if (cstr)
Benjamin Kramereb9165c2010-06-22 15:28:34 +0000100 return GetConstCStringWithLength (cstr, strlen (cstr));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101 return NULL;
102 }
103
104 const char *
105 GetConstCStringWithLength (const char *cstr, int cstr_len)
106 {
107 if (cstr)
108 {
109 Mutex::Locker locker (m_mutex);
110 llvm::StringRef string_ref (cstr, cstr_len);
Greg Clayton40df35e2011-06-10 00:00:19 +0000111 StringPoolEntryType& entry = m_string_map.GetOrCreateValue (string_ref, (StringPoolValueType)NULL);
Greg Claytonc982c762010-07-09 20:39:50 +0000112 return entry.getKeyData();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113 }
114 return NULL;
115 }
116
117 const char *
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000118 GetConstCStringAndSetMangledCounterPart (const char *demangled_cstr, const char *mangled_ccstr)
119 {
120 if (demangled_cstr)
121 {
122 Mutex::Locker locker (m_mutex);
123 // Make string pool entry with the mangled counterpart already set
124 StringPoolEntryType& entry = m_string_map.GetOrCreateValue (llvm::StringRef (demangled_cstr), mangled_ccstr);
125
126 // Extract the const version of the demangled_cstr
127 const char *demangled_ccstr = entry.getKeyData();
128 // Now assign the demangled const string as the counterpart of the
129 // mangled const string...
130 GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr);
131 // Return the constant demangled C string
132 return demangled_ccstr;
133 }
134 return NULL;
135 }
136
137 const char *
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000138 GetConstTrimmedCStringWithLength (const char *cstr, int cstr_len)
139 {
140 if (cstr)
141 {
Benjamin Kramereb9165c2010-06-22 15:28:34 +0000142 int trimmed_len = std::min<int> (strlen (cstr), cstr_len);
143 return GetConstCStringWithLength (cstr, trimmed_len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000144 }
145 return NULL;
146 }
147
148 //------------------------------------------------------------------
149 // Return the size in bytes that this object and any items in its
150 // collection of uniqued strings + reference count values takes in
151 // memory.
152 //------------------------------------------------------------------
153 size_t
154 MemorySize() const
155 {
156 Mutex::Locker locker (m_mutex);
157 size_t mem_size = sizeof(Pool);
158 const_iterator end = m_string_map.end();
159 for (const_iterator pos = m_string_map.begin(); pos != end; ++pos)
160 {
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000161 mem_size += sizeof(StringPoolEntryType) + pos->getKey().size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000162 }
163 return mem_size;
164 }
165
166protected:
167 //------------------------------------------------------------------
168 // Typedefs
169 //------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000170 typedef StringPool::iterator iterator;
171 typedef StringPool::const_iterator const_iterator;
172
173 //------------------------------------------------------------------
174 // Member variables
175 //------------------------------------------------------------------
176 mutable Mutex m_mutex;
177 StringPool m_string_map;
178};
179
180//----------------------------------------------------------------------
181// Frameworks and dylibs aren't supposed to have global C++
182// initializers so we hide the string pool in a static function so
183// that it will get initialized on the first call to this static
184// function.
185//----------------------------------------------------------------------
186static Pool &
187StringPool()
188{
189 static Pool string_pool;
190 return string_pool;
191}
192
193//----------------------------------------------------------------------
194// Default constructor
195//
196// Initializes the string to an empty string.
197//----------------------------------------------------------------------
198ConstString::ConstString () :
199 m_string (NULL)
200{
201}
202
203//----------------------------------------------------------------------
204// Copy constructor
205//
206// Copies the string value in "rhs" and retains an extra reference
207// to the string value in the string pool.
208//----------------------------------------------------------------------
209ConstString::ConstString (const ConstString& rhs) :
210 m_string (rhs.m_string)
211{
212}
213
214//----------------------------------------------------------------------
215// Construct with C String value
216//
217// Constructs this object with a C string by looking to see if the
218// C string already exists in the global string pool. If it does
219// exist, it retains an extra reference to the string in the string
220// pool. If it doesn't exist, it is added to the string pool with
221// a reference count of 1.
222//----------------------------------------------------------------------
223ConstString::ConstString (const char *cstr) :
224 m_string (StringPool().GetConstCString (cstr))
225{
226}
227
228//----------------------------------------------------------------------
229// Construct with C String value with max length
230//
231// Constructs this object with a C string with a length. If
232// the length of the string is greather than "cstr_len", the
233// string length will be truncated. This allows substrings to be
234// created without the need to NULL terminate the string as it
235// is passed into this function.
236//
237// If the C string already exists in the global string pool, it
238// retains an extra reference to the string in the string
239// pool. If it doesn't exist, it is added to the string pool with
240// a reference count of 1.
241//----------------------------------------------------------------------
242ConstString::ConstString (const char *cstr, size_t cstr_len) :
243 m_string (StringPool().GetConstCStringWithLength (cstr, cstr_len))
244{
245}
246
247//----------------------------------------------------------------------
248// Destructor
249//
250// Decrements the reference count on the contained string, and if
251// the resulting reference count is zero, then the string is removed
252// from the string pool. If the reference count is still greater
253// than zero, the string will remain in the string pool
254//----------------------------------------------------------------------
255ConstString::~ConstString ()
256{
257}
258
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000259bool
260ConstString::operator < (const ConstString& rhs) const
261{
262 if (m_string == rhs.m_string)
263 return false;
264
265 llvm::StringRef lhs_string_ref (m_string, StringPool().GetConstCStringLength (m_string));
266 llvm::StringRef rhs_string_ref (rhs.m_string, StringPool().GetConstCStringLength (rhs.m_string));
267
268 // If both have valid C strings, then return the comparison
269 if (lhs_string_ref.data() && rhs_string_ref.data())
270 return lhs_string_ref < rhs_string_ref;
271
272 // Else one of them was NULL, so if LHS is NULL then it is less than
273 return lhs_string_ref.data() == NULL;
274}
275
276//----------------------------------------------------------------------
277// Stream the string value "str" to the stream "s"
278//----------------------------------------------------------------------
279Stream&
280lldb_private::operator << (Stream& s, const ConstString& str)
281{
282 const char *cstr = str.GetCString();
283 if (cstr)
284 s << cstr;
285
286 return s;
287}
288
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000289size_t
290ConstString::GetLength () const
291{
292 return StringPool().GetConstCStringLength (m_string);
293}
294
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000295//----------------------------------------------------------------------
296// Compare two string objects.
297//
298// Returns:
299// -1 if a < b
300// 0 if a == b
301// 1 if a > b
302//----------------------------------------------------------------------
303int
304ConstString::Compare (const ConstString& lhs, const ConstString& rhs)
305{
306 // If the iterators are the same, this is the same string
307 register const char *lhs_cstr = lhs.m_string;
308 register const char *rhs_cstr = rhs.m_string;
309 if (lhs_cstr == rhs_cstr)
310 return 0;
311 if (lhs_cstr && rhs_cstr)
312 {
313 llvm::StringRef lhs_string_ref (lhs_cstr, StringPool().GetConstCStringLength (lhs_cstr));
314 llvm::StringRef rhs_string_ref (rhs_cstr, StringPool().GetConstCStringLength (rhs_cstr));
315 return lhs_string_ref.compare(rhs_string_ref);
316 }
317
318 if (lhs_cstr)
319 return +1; // LHS isn't NULL but RHS is
320 else
321 return -1; // LHS is NULL but RHS isn't
322}
323
324//----------------------------------------------------------------------
325// Dump the string value to the stream "s". If the contained string
326// is empty, print "fail_value" to the stream instead. If
327// "fail_value" is NULL, then nothing will be dumped to the
328// stream.
329//----------------------------------------------------------------------
330void
331ConstString::Dump(Stream *s, const char *fail_value) const
332{
333 const char *cstr = AsCString (fail_value);
334 if (cstr)
335 s->PutCString (cstr);
336}
337
338//----------------------------------------------------------------------
339// Dump extra debug information to the stream "s".
340//----------------------------------------------------------------------
341void
342ConstString::DumpDebug(Stream *s) const
343{
344 const char *cstr = GetCString ();
345 size_t cstr_len = GetLength();
346 // Only print the parens if we have a non-NULL string
347 const char *parens = cstr ? "\"" : "";
348 s->Printf("%*p: ConstString, string = %s%s%s, length = %zu", (int)sizeof(void*) * 2, this, parens, cstr, parens, cstr_len);
349}
350
351//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000352// Set the string value in the object by uniquing the "cstr" string
353// value in our global string pool.
354//
355// If the C string already exists in the global string pool, it
356// retains an extra reference to the string in the string
357// pool. If it doesn't exist, it is added to the string pool with
358// a reference count of 1.
359//----------------------------------------------------------------------
360void
361ConstString::SetCString (const char *cstr)
362{
363 m_string = StringPool().GetConstCString (cstr);
364}
365
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000366void
367ConstString::SetCStringWithMangledCounterpart (const char *demangled, const ConstString &mangled)
368{
369 m_string = StringPool().GetConstCStringAndSetMangledCounterPart (demangled, mangled.m_string);
370}
371
372bool
373ConstString::GetMangledCounterpart (ConstString &counterpart) const
374{
375 counterpart.m_string = StringPool().GetMangledCounterpart(m_string);
376 return counterpart;
377}
378
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000379//----------------------------------------------------------------------
380// Set the string value in the object by uniquing "cstr_len" bytes
381// starting at the "cstr" string value in our global string pool.
382// If trim is true, then "cstr_len" indicates a maximum length of
383// the CString and if the actual length of the string is less, then
384// it will be trimmed. If trim is false, then this allows strings
385// with NULL characters ('\0') to be added to the string pool.
386//
387// If the C string already exists in the global string pool, it
388// retains an extra reference to the string in the string
389// pool. If it doesn't exist, it is added to the string pool with
390// a reference count of 1.
391//----------------------------------------------------------------------
392void
393ConstString::SetCStringWithLength (const char *cstr, size_t cstr_len)
394{
395 m_string = StringPool().GetConstCStringWithLength(cstr, cstr_len);
396}
397
398void
399ConstString::SetTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
400{
401 m_string = StringPool().GetConstTrimmedCStringWithLength (cstr, cstr_len);
402}
403
404//----------------------------------------------------------------------
405// Return the size in bytes that this object takes in memory. The
406// resulting size will not include any of the C string values from
407// the global string pool (see StaticMemorySize ()).
408//----------------------------------------------------------------------
409size_t
410ConstString::MemorySize() const
411{
412 return sizeof(ConstString);
413}
414
415//----------------------------------------------------------------------
416// Reports the the size in bytes of all shared C string values,
417// containers and reference count values as a byte size for the
418// entire string pool.
419//----------------------------------------------------------------------
420size_t
421ConstString::StaticMemorySize()
422{
423 // Get the size of the static string pool
424 return StringPool().MemorySize();
425}