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