ConstString.cpp revision 448bd2fe5693c3ef591743d460b8b830607cfa09
1//===-- 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    typedef const char * StringPoolValueType;
36    typedef llvm::StringMap<StringPoolValueType, llvm::BumpPtrAllocator> StringPool;
37    typedef llvm::StringMapEntry<StringPoolValueType> StringPoolEntryType;
38
39    //------------------------------------------------------------------
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
58    static StringPoolEntryType &
59    GetStringMapEntryFromKeyData (const char *keyData)
60    {
61        char *ptr = const_cast<char*>(keyData) - sizeof (StringPoolEntryType);
62        return *reinterpret_cast<StringPoolEntryType*>(ptr);
63    }
64
65    size_t
66    GetConstCStringLength (const char *ccstr) const
67    {
68        if (ccstr)
69        {
70            const StringPoolEntryType&entry = GetStringMapEntryFromKeyData (ccstr);
71            return entry.getKey().size();
72        }
73        return 0;
74    }
75
76    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
96    const char *
97    GetConstCString (const char *cstr)
98    {
99        if (cstr)
100            return GetConstCStringWithLength (cstr, strlen (cstr));
101        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);
111            StringPoolEntryType& entry = m_string_map.GetOrCreateValue (string_ref, (StringPoolValueType)NULL);
112            return entry.getKeyData();
113        }
114        return NULL;
115    }
116
117    const char *
118    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 *
138    GetConstTrimmedCStringWithLength (const char *cstr, int cstr_len)
139    {
140        if (cstr)
141        {
142            int trimmed_len = std::min<int> (strlen (cstr), cstr_len);
143            return GetConstCStringWithLength (cstr, trimmed_len);
144        }
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        {
161            mem_size += sizeof(StringPoolEntryType) + pos->getKey().size();
162        }
163        return mem_size;
164    }
165
166protected:
167    //------------------------------------------------------------------
168    // Typedefs
169    //------------------------------------------------------------------
170    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// Construct with C String value
195//
196// Constructs this object with a C string by looking to see if the
197// C string already exists in the global string pool. If it does
198// exist, it 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) :
203    m_string (StringPool().GetConstCString (cstr))
204{
205}
206
207//----------------------------------------------------------------------
208// Construct with C String value with max length
209//
210// Constructs this object with a C string with a length. If
211// the length of the string is greather than "cstr_len", the
212// string length will be truncated. This allows substrings to be
213// created without the need to NULL terminate the string as it
214// is passed into this function.
215//
216// If the C string already exists in the global string pool, it
217// retains an extra reference to the string in the string
218// pool. If it doesn't exist, it is added to the string pool with
219// a reference count of 1.
220//----------------------------------------------------------------------
221ConstString::ConstString (const char *cstr, size_t cstr_len) :
222    m_string (StringPool().GetConstCStringWithLength (cstr, cstr_len))
223{
224}
225
226bool
227ConstString::operator < (const ConstString& rhs) const
228{
229    if (m_string == rhs.m_string)
230        return false;
231
232    llvm::StringRef lhs_string_ref (m_string, StringPool().GetConstCStringLength (m_string));
233    llvm::StringRef rhs_string_ref (rhs.m_string, StringPool().GetConstCStringLength (rhs.m_string));
234
235    // If both have valid C strings, then return the comparison
236    if (lhs_string_ref.data() && rhs_string_ref.data())
237        return lhs_string_ref < rhs_string_ref;
238
239    // Else one of them was NULL, so if LHS is NULL then it is less than
240    return lhs_string_ref.data() == NULL;
241}
242
243//----------------------------------------------------------------------
244// Stream the string value "str" to the stream "s"
245//----------------------------------------------------------------------
246Stream&
247lldb_private::operator << (Stream& s, const ConstString& str)
248{
249    const char *cstr = str.GetCString();
250    if (cstr)
251        s << cstr;
252
253    return s;
254}
255
256size_t
257ConstString::GetLength () const
258{
259    return StringPool().GetConstCStringLength (m_string);
260}
261
262//----------------------------------------------------------------------
263// Compare two string objects.
264//
265// Returns:
266//  -1 if a < b
267//   0 if a == b
268//   1 if a > b
269//----------------------------------------------------------------------
270int
271ConstString::Compare (const ConstString& lhs, const ConstString& rhs)
272{
273    // If the iterators are the same, this is the same string
274    register const char *lhs_cstr = lhs.m_string;
275    register const char *rhs_cstr = rhs.m_string;
276    if (lhs_cstr == rhs_cstr)
277        return 0;
278    if (lhs_cstr && rhs_cstr)
279    {
280        llvm::StringRef lhs_string_ref (lhs_cstr, StringPool().GetConstCStringLength (lhs_cstr));
281        llvm::StringRef rhs_string_ref (rhs_cstr, StringPool().GetConstCStringLength (rhs_cstr));
282        return lhs_string_ref.compare(rhs_string_ref);
283    }
284
285    if (lhs_cstr)
286        return +1;  // LHS isn't NULL but RHS is
287    else
288        return -1;  // LHS is NULL but RHS isn't
289}
290
291//----------------------------------------------------------------------
292// Dump the string value to the stream "s". If the contained string
293// is empty, print "fail_value" to the stream instead. If
294// "fail_value" is NULL, then nothing will be dumped to the
295// stream.
296//----------------------------------------------------------------------
297void
298ConstString::Dump(Stream *s, const char *fail_value) const
299{
300    const char *cstr = AsCString (fail_value);
301    if (cstr)
302        s->PutCString (cstr);
303}
304
305//----------------------------------------------------------------------
306// Dump extra debug information to the stream "s".
307//----------------------------------------------------------------------
308void
309ConstString::DumpDebug(Stream *s) const
310{
311    const char *cstr = GetCString ();
312    size_t cstr_len = GetLength();
313    // Only print the parens if we have a non-NULL string
314    const char *parens = cstr ? "\"" : "";
315    s->Printf("%*p: ConstString, string = %s%s%s, length = %zu", (int)sizeof(void*) * 2, this, parens, cstr, parens, cstr_len);
316}
317
318//----------------------------------------------------------------------
319// Set the string value in the object by uniquing the "cstr" string
320// value in our global string pool.
321//
322// If the C string already exists in the global string pool, it
323// retains an extra reference to the string in the string
324// pool. If it doesn't exist, it is added to the string pool with
325// a reference count of 1.
326//----------------------------------------------------------------------
327void
328ConstString::SetCString (const char *cstr)
329{
330    m_string = StringPool().GetConstCString (cstr);
331}
332
333void
334ConstString::SetCStringWithMangledCounterpart (const char *demangled, const ConstString &mangled)
335{
336    m_string = StringPool().GetConstCStringAndSetMangledCounterPart (demangled, mangled.m_string);
337}
338
339bool
340ConstString::GetMangledCounterpart (ConstString &counterpart) const
341{
342    counterpart.m_string = StringPool().GetMangledCounterpart(m_string);
343    return counterpart;
344}
345
346//----------------------------------------------------------------------
347// Set the string value in the object by uniquing "cstr_len" bytes
348// starting at the "cstr" string value in our global string pool.
349// If trim is true, then "cstr_len" indicates a maximum length of
350// the CString and if the actual length of the string is less, then
351// it will be trimmed. If trim is false, then this allows strings
352// with NULL characters ('\0') to be added to the string pool.
353//
354// If the C string already exists in the global string pool, it
355// retains an extra reference to the string in the string
356// pool. If it doesn't exist, it is added to the string pool with
357// a reference count of 1.
358//----------------------------------------------------------------------
359void
360ConstString::SetCStringWithLength (const char *cstr, size_t cstr_len)
361{
362    m_string = StringPool().GetConstCStringWithLength(cstr, cstr_len);
363}
364
365void
366ConstString::SetTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
367{
368    m_string = StringPool().GetConstTrimmedCStringWithLength (cstr, cstr_len);
369}
370
371//----------------------------------------------------------------------
372// Reports the the size in bytes of all shared C string values,
373// containers and reference count values as a byte size for the
374// entire string pool.
375//----------------------------------------------------------------------
376size_t
377ConstString::StaticMemorySize()
378{
379    // Get the size of the static string pool
380    return StringPool().MemorySize();
381}
382