blob: 1caf843a3d3c91cc8e5b18f3caafa6bb9250ef9b [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:
35 //------------------------------------------------------------------
36 // Default constructor
37 //
38 // Initialize the member variables and create the empty string.
39 //------------------------------------------------------------------
40 Pool () :
41 m_mutex (Mutex::eMutexTypeRecursive),
42 m_string_map ()
43 {
44 }
45
46 //------------------------------------------------------------------
47 // Destructor
48 //------------------------------------------------------------------
49 ~Pool ()
50 {
51 }
52
53
54 static llvm::StringMapEntry<uint32_t> &
55 GetStringMapEntryFromKeyData (const char *keyData)
56 {
57 char *ptr = const_cast<char*>(keyData) - sizeof (llvm::StringMapEntry<uint32_t>);
58 return *reinterpret_cast<llvm::StringMapEntry<uint32_t>*>(ptr);
59 }
60
61 size_t
62 GetConstCStringLength (const char *ccstr)
63 {
64 if (ccstr)
65 {
66 llvm::StringMapEntry<uint32_t>&entry = GetStringMapEntryFromKeyData (ccstr);
67 return entry.getKey().size();
68 }
69 return 0;
70 }
71
72 const char *
73 GetConstCString (const char *cstr)
74 {
75 if (cstr)
Benjamin Kramereb9165c2010-06-22 15:28:34 +000076 return GetConstCStringWithLength (cstr, strlen (cstr));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000077 return NULL;
78 }
79
80 const char *
81 GetConstCStringWithLength (const char *cstr, int cstr_len)
82 {
83 if (cstr)
84 {
85 Mutex::Locker locker (m_mutex);
86 llvm::StringRef string_ref (cstr, cstr_len);
87 llvm::StringMapEntry<uint32_t>& entry = m_string_map.GetOrCreateValue (string_ref);
Greg Claytonc982c762010-07-09 20:39:50 +000088 return entry.getKeyData();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000089 }
90 return NULL;
91 }
92
93 const char *
94 GetConstTrimmedCStringWithLength (const char *cstr, int cstr_len)
95 {
96 if (cstr)
97 {
Benjamin Kramereb9165c2010-06-22 15:28:34 +000098 int trimmed_len = std::min<int> (strlen (cstr), cstr_len);
99 return GetConstCStringWithLength (cstr, trimmed_len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100 }
101 return NULL;
102 }
103
104 //------------------------------------------------------------------
105 // Return the size in bytes that this object and any items in its
106 // collection of uniqued strings + reference count values takes in
107 // memory.
108 //------------------------------------------------------------------
109 size_t
110 MemorySize() const
111 {
112 Mutex::Locker locker (m_mutex);
113 size_t mem_size = sizeof(Pool);
114 const_iterator end = m_string_map.end();
115 for (const_iterator pos = m_string_map.begin(); pos != end; ++pos)
116 {
117 mem_size += sizeof(llvm::StringMapEntry<uint32_t>) + pos->getKey().size();
118 }
119 return mem_size;
120 }
121
122protected:
123 //------------------------------------------------------------------
124 // Typedefs
125 //------------------------------------------------------------------
126 typedef llvm::StringMap<uint32_t, llvm::BumpPtrAllocator> StringPool;
127 typedef StringPool::iterator iterator;
128 typedef StringPool::const_iterator const_iterator;
129
130 //------------------------------------------------------------------
131 // Member variables
132 //------------------------------------------------------------------
133 mutable Mutex m_mutex;
134 StringPool m_string_map;
135};
136
137//----------------------------------------------------------------------
138// Frameworks and dylibs aren't supposed to have global C++
139// initializers so we hide the string pool in a static function so
140// that it will get initialized on the first call to this static
141// function.
142//----------------------------------------------------------------------
143static Pool &
144StringPool()
145{
146 static Pool string_pool;
147 return string_pool;
148}
149
150//----------------------------------------------------------------------
151// Default constructor
152//
153// Initializes the string to an empty string.
154//----------------------------------------------------------------------
155ConstString::ConstString () :
156 m_string (NULL)
157{
158}
159
160//----------------------------------------------------------------------
161// Copy constructor
162//
163// Copies the string value in "rhs" and retains an extra reference
164// to the string value in the string pool.
165//----------------------------------------------------------------------
166ConstString::ConstString (const ConstString& rhs) :
167 m_string (rhs.m_string)
168{
169}
170
171//----------------------------------------------------------------------
172// Construct with C String value
173//
174// Constructs this object with a C string by looking to see if the
175// C string already exists in the global string pool. If it does
176// exist, it retains an extra reference to the string in the string
177// pool. If it doesn't exist, it is added to the string pool with
178// a reference count of 1.
179//----------------------------------------------------------------------
180ConstString::ConstString (const char *cstr) :
181 m_string (StringPool().GetConstCString (cstr))
182{
183}
184
185//----------------------------------------------------------------------
186// Construct with C String value with max length
187//
188// Constructs this object with a C string with a length. If
189// the length of the string is greather than "cstr_len", the
190// string length will be truncated. This allows substrings to be
191// created without the need to NULL terminate the string as it
192// is passed into this function.
193//
194// If the C string already exists in the global string pool, it
195// retains an extra reference to the string in the string
196// pool. If it doesn't exist, it is added to the string pool with
197// a reference count of 1.
198//----------------------------------------------------------------------
199ConstString::ConstString (const char *cstr, size_t cstr_len) :
200 m_string (StringPool().GetConstCStringWithLength (cstr, cstr_len))
201{
202}
203
204//----------------------------------------------------------------------
205// Destructor
206//
207// Decrements the reference count on the contained string, and if
208// the resulting reference count is zero, then the string is removed
209// from the string pool. If the reference count is still greater
210// than zero, the string will remain in the string pool
211//----------------------------------------------------------------------
212ConstString::~ConstString ()
213{
214}
215
216//----------------------------------------------------------------------
217// Convert to pointer operator. This allows code to check any
218// ConstString objects to see if they contain anything (not empty)
219// valid using code such as:
220//
221// ConstString str(...);
222// if (str)
223// { ...
224//----------------------------------------------------------------------
225ConstString::operator void*() const
226{
227 return IsEmpty() ? NULL : const_cast<ConstString*>(this);
228}
229
230//----------------------------------------------------------------------
231// Assignment operator
232//
233// Assigns the string in this object with the value from "rhs"
234// and increments the reference count of that string.
235//
236// The previously contained string will be get its reference count
237// decremented and removed from the string pool if its reference
238// count reaches zero.
239//----------------------------------------------------------------------
240const ConstString&
241ConstString::operator=(const ConstString& rhs)
242{
243 m_string = rhs.m_string;
244 return *this;
245}
246
247//----------------------------------------------------------------------
248// Equal to operator
249//
250// Returns true if this string is equal to that in "rhs". This is
251// very fast as it results in a pointer comparison since all strings
252// are in a uniqued and reference counted string pool.
253//------------------------------------------------------------------
254bool
255ConstString::operator == (const ConstString& rhs) const
256{
257 // We can do a pointer compare to compare these strings since they
258 // must come from the same pool in order to be equal.
259 return m_string == rhs.m_string;
260}
261
262bool
263ConstString::operator != (const ConstString& rhs) const
264{
265 return m_string != rhs.m_string;
266}
267
268bool
269ConstString::operator < (const ConstString& rhs) const
270{
271 if (m_string == rhs.m_string)
272 return false;
273
274 llvm::StringRef lhs_string_ref (m_string, StringPool().GetConstCStringLength (m_string));
275 llvm::StringRef rhs_string_ref (rhs.m_string, StringPool().GetConstCStringLength (rhs.m_string));
276
277 // If both have valid C strings, then return the comparison
278 if (lhs_string_ref.data() && rhs_string_ref.data())
279 return lhs_string_ref < rhs_string_ref;
280
281 // Else one of them was NULL, so if LHS is NULL then it is less than
282 return lhs_string_ref.data() == NULL;
283}
284
285//----------------------------------------------------------------------
286// Stream the string value "str" to the stream "s"
287//----------------------------------------------------------------------
288Stream&
289lldb_private::operator << (Stream& s, const ConstString& str)
290{
291 const char *cstr = str.GetCString();
292 if (cstr)
293 s << cstr;
294
295 return s;
296}
297
298//----------------------------------------------------------------------
299// Get the value of the contained string as a NULL terminated C
300// string value. Return "fail_value" if the string is empty.
301//----------------------------------------------------------------------
302const char *
303ConstString::AsCString(const char *fail_value) const
304{
305 if (m_string == NULL)
306 return fail_value;
307 return m_string;
308}
309
310const char *
311ConstString::GetCString () const
312{
313 return m_string;
314}
315
316size_t
317ConstString::GetLength () const
318{
319 return StringPool().GetConstCStringLength (m_string);
320}
321
322
323//----------------------------------------------------------------------
324// Clear any contained string and reset the value to the an empty
325// string value.
326//
327// The previously contained string will be get its reference count
328// decremented and removed from the string pool if its reference
329// count reaches zero.
330//----------------------------------------------------------------------
331void
332ConstString::Clear ()
333{
334 m_string = NULL;
335}
336
337//----------------------------------------------------------------------
338// Compare two string objects.
339//
340// Returns:
341// -1 if a < b
342// 0 if a == b
343// 1 if a > b
344//----------------------------------------------------------------------
345int
346ConstString::Compare (const ConstString& lhs, const ConstString& rhs)
347{
348 // If the iterators are the same, this is the same string
349 register const char *lhs_cstr = lhs.m_string;
350 register const char *rhs_cstr = rhs.m_string;
351 if (lhs_cstr == rhs_cstr)
352 return 0;
353 if (lhs_cstr && rhs_cstr)
354 {
355 llvm::StringRef lhs_string_ref (lhs_cstr, StringPool().GetConstCStringLength (lhs_cstr));
356 llvm::StringRef rhs_string_ref (rhs_cstr, StringPool().GetConstCStringLength (rhs_cstr));
357 return lhs_string_ref.compare(rhs_string_ref);
358 }
359
360 if (lhs_cstr)
361 return +1; // LHS isn't NULL but RHS is
362 else
363 return -1; // LHS is NULL but RHS isn't
364}
365
366//----------------------------------------------------------------------
367// Dump the string value to the stream "s". If the contained string
368// is empty, print "fail_value" to the stream instead. If
369// "fail_value" is NULL, then nothing will be dumped to the
370// stream.
371//----------------------------------------------------------------------
372void
373ConstString::Dump(Stream *s, const char *fail_value) const
374{
375 const char *cstr = AsCString (fail_value);
376 if (cstr)
377 s->PutCString (cstr);
378}
379
380//----------------------------------------------------------------------
381// Dump extra debug information to the stream "s".
382//----------------------------------------------------------------------
383void
384ConstString::DumpDebug(Stream *s) const
385{
386 const char *cstr = GetCString ();
387 size_t cstr_len = GetLength();
388 // Only print the parens if we have a non-NULL string
389 const char *parens = cstr ? "\"" : "";
390 s->Printf("%*p: ConstString, string = %s%s%s, length = %zu", (int)sizeof(void*) * 2, this, parens, cstr, parens, cstr_len);
391}
392
393//----------------------------------------------------------------------
394// Returns true if the contained string is empty.
395//----------------------------------------------------------------------
396bool
397ConstString::IsEmpty() const
398{
399 return m_string == NULL || m_string[0] == '\0';
400}
401
402//----------------------------------------------------------------------
403// Set the string value in the object by uniquing the "cstr" string
404// value in our global string pool.
405//
406// If the C string already exists in the global string pool, it
407// retains an extra reference to the string in the string
408// pool. If it doesn't exist, it is added to the string pool with
409// a reference count of 1.
410//----------------------------------------------------------------------
411void
412ConstString::SetCString (const char *cstr)
413{
414 m_string = StringPool().GetConstCString (cstr);
415}
416
417//----------------------------------------------------------------------
418// Set the string value in the object by uniquing "cstr_len" bytes
419// starting at the "cstr" string value in our global string pool.
420// If trim is true, then "cstr_len" indicates a maximum length of
421// the CString and if the actual length of the string is less, then
422// it will be trimmed. If trim is false, then this allows strings
423// with NULL characters ('\0') to be added to the string pool.
424//
425// If the C string already exists in the global string pool, it
426// retains an extra reference to the string in the string
427// pool. If it doesn't exist, it is added to the string pool with
428// a reference count of 1.
429//----------------------------------------------------------------------
430void
431ConstString::SetCStringWithLength (const char *cstr, size_t cstr_len)
432{
433 m_string = StringPool().GetConstCStringWithLength(cstr, cstr_len);
434}
435
436void
437ConstString::SetTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
438{
439 m_string = StringPool().GetConstTrimmedCStringWithLength (cstr, cstr_len);
440}
441
442//----------------------------------------------------------------------
443// Return the size in bytes that this object takes in memory. The
444// resulting size will not include any of the C string values from
445// the global string pool (see StaticMemorySize ()).
446//----------------------------------------------------------------------
447size_t
448ConstString::MemorySize() const
449{
450 return sizeof(ConstString);
451}
452
453//----------------------------------------------------------------------
454// Reports the the size in bytes of all shared C string values,
455// containers and reference count values as a byte size for the
456// entire string pool.
457//----------------------------------------------------------------------
458size_t
459ConstString::StaticMemorySize()
460{
461 // Get the size of the static string pool
462 return StringPool().MemorySize();
463}