1254721Semaste//===-- ConstString.cpp -----------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste#include "lldb/Core/ConstString.h"
10254721Semaste#include "lldb/Core/Stream.h"
11254721Semaste#include "lldb/Host/Mutex.h"
12254721Semaste#include "llvm/ADT/StringMap.h"
13254721Semaste
14254721Semasteusing namespace lldb_private;
15254721Semaste
16254721Semaste
17254721Semasteclass Pool
18254721Semaste{
19254721Semastepublic:
20254721Semaste    typedef const char * StringPoolValueType;
21254721Semaste    typedef llvm::StringMap<StringPoolValueType, llvm::BumpPtrAllocator> StringPool;
22254721Semaste    typedef llvm::StringMapEntry<StringPoolValueType> StringPoolEntryType;
23254721Semaste
24254721Semaste    //------------------------------------------------------------------
25254721Semaste    // Default constructor
26254721Semaste    //
27254721Semaste    // Initialize the member variables and create the empty string.
28254721Semaste    //------------------------------------------------------------------
29254721Semaste    Pool () :
30254721Semaste        m_mutex (Mutex::eMutexTypeRecursive),
31254721Semaste        m_string_map ()
32254721Semaste    {
33254721Semaste    }
34254721Semaste
35254721Semaste    //------------------------------------------------------------------
36254721Semaste    // Destructor
37254721Semaste    //------------------------------------------------------------------
38254721Semaste    ~Pool ()
39254721Semaste    {
40254721Semaste    }
41254721Semaste
42254721Semaste
43254721Semaste    static StringPoolEntryType &
44254721Semaste    GetStringMapEntryFromKeyData (const char *keyData)
45254721Semaste    {
46254721Semaste        char *ptr = const_cast<char*>(keyData) - sizeof (StringPoolEntryType);
47254721Semaste        return *reinterpret_cast<StringPoolEntryType*>(ptr);
48254721Semaste    }
49254721Semaste
50254721Semaste    size_t
51254721Semaste    GetConstCStringLength (const char *ccstr) const
52254721Semaste    {
53254721Semaste        if (ccstr)
54254721Semaste        {
55254721Semaste            const StringPoolEntryType&entry = GetStringMapEntryFromKeyData (ccstr);
56254721Semaste            return entry.getKey().size();
57254721Semaste        }
58254721Semaste        return 0;
59254721Semaste    }
60254721Semaste
61254721Semaste    StringPoolValueType
62254721Semaste    GetMangledCounterpart (const char *ccstr) const
63254721Semaste    {
64254721Semaste        if (ccstr)
65254721Semaste            return GetStringMapEntryFromKeyData (ccstr).getValue();
66254721Semaste        return 0;
67254721Semaste    }
68254721Semaste
69254721Semaste    bool
70254721Semaste    SetMangledCounterparts (const char *key_ccstr, const char *value_ccstr)
71254721Semaste    {
72254721Semaste        if (key_ccstr && value_ccstr)
73254721Semaste        {
74254721Semaste            GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr);
75254721Semaste            GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr);
76254721Semaste            return true;
77254721Semaste        }
78254721Semaste        return false;
79254721Semaste    }
80254721Semaste
81254721Semaste    const char *
82254721Semaste    GetConstCString (const char *cstr)
83254721Semaste    {
84254721Semaste        if (cstr)
85254721Semaste            return GetConstCStringWithLength (cstr, strlen (cstr));
86254721Semaste        return NULL;
87254721Semaste    }
88254721Semaste
89254721Semaste    const char *
90254721Semaste    GetConstCStringWithLength (const char *cstr, size_t cstr_len)
91254721Semaste    {
92254721Semaste        if (cstr)
93254721Semaste        {
94254721Semaste            Mutex::Locker locker (m_mutex);
95254721Semaste            llvm::StringRef string_ref (cstr, cstr_len);
96254721Semaste            StringPoolEntryType& entry = m_string_map.GetOrCreateValue (string_ref, (StringPoolValueType)NULL);
97254721Semaste            return entry.getKeyData();
98254721Semaste        }
99254721Semaste        return NULL;
100254721Semaste    }
101254721Semaste
102254721Semaste    const char *
103254721Semaste    GetConstCStringWithStringRef (const llvm::StringRef &string_ref)
104254721Semaste    {
105254721Semaste        if (string_ref.data())
106254721Semaste        {
107254721Semaste            Mutex::Locker locker (m_mutex);
108254721Semaste            StringPoolEntryType& entry = m_string_map.GetOrCreateValue (string_ref, (StringPoolValueType)NULL);
109254721Semaste            return entry.getKeyData();
110254721Semaste        }
111254721Semaste        return NULL;
112254721Semaste    }
113254721Semaste
114254721Semaste    const char *
115254721Semaste    GetConstCStringAndSetMangledCounterPart (const char *demangled_cstr, const char *mangled_ccstr)
116254721Semaste    {
117254721Semaste        if (demangled_cstr)
118254721Semaste        {
119254721Semaste            Mutex::Locker locker (m_mutex);
120254721Semaste            // Make string pool entry with the mangled counterpart already set
121254721Semaste            StringPoolEntryType& entry = m_string_map.GetOrCreateValue (llvm::StringRef (demangled_cstr), mangled_ccstr);
122254721Semaste
123254721Semaste            // Extract the const version of the demangled_cstr
124254721Semaste            const char *demangled_ccstr = entry.getKeyData();
125254721Semaste            // Now assign the demangled const string as the counterpart of the
126254721Semaste            // mangled const string...
127254721Semaste            GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr);
128254721Semaste            // Return the constant demangled C string
129254721Semaste            return demangled_ccstr;
130254721Semaste        }
131254721Semaste        return NULL;
132254721Semaste    }
133254721Semaste
134254721Semaste    const char *
135254721Semaste    GetConstTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
136254721Semaste    {
137254721Semaste        if (cstr)
138254721Semaste        {
139254721Semaste            const size_t trimmed_len = std::min<size_t> (strlen (cstr), cstr_len);
140254721Semaste            return GetConstCStringWithLength (cstr, trimmed_len);
141254721Semaste        }
142254721Semaste        return NULL;
143254721Semaste    }
144254721Semaste
145254721Semaste    //------------------------------------------------------------------
146254721Semaste    // Return the size in bytes that this object and any items in its
147254721Semaste    // collection of uniqued strings + data count values takes in
148254721Semaste    // memory.
149254721Semaste    //------------------------------------------------------------------
150254721Semaste    size_t
151254721Semaste    MemorySize() const
152254721Semaste    {
153254721Semaste        Mutex::Locker locker (m_mutex);
154254721Semaste        size_t mem_size = sizeof(Pool);
155254721Semaste        const_iterator end = m_string_map.end();
156254721Semaste        for (const_iterator pos = m_string_map.begin(); pos != end; ++pos)
157254721Semaste        {
158254721Semaste            mem_size += sizeof(StringPoolEntryType) + pos->getKey().size();
159254721Semaste        }
160254721Semaste        return mem_size;
161254721Semaste    }
162254721Semaste
163254721Semasteprotected:
164254721Semaste    //------------------------------------------------------------------
165254721Semaste    // Typedefs
166254721Semaste    //------------------------------------------------------------------
167254721Semaste    typedef StringPool::iterator iterator;
168254721Semaste    typedef StringPool::const_iterator const_iterator;
169254721Semaste
170254721Semaste    //------------------------------------------------------------------
171254721Semaste    // Member variables
172254721Semaste    //------------------------------------------------------------------
173254721Semaste    mutable Mutex m_mutex;
174254721Semaste    StringPool m_string_map;
175254721Semaste};
176254721Semaste
177254721Semaste//----------------------------------------------------------------------
178254721Semaste// Frameworks and dylibs aren't supposed to have global C++
179254721Semaste// initializers so we hide the string pool in a static function so
180254721Semaste// that it will get initialized on the first call to this static
181254721Semaste// function.
182254721Semaste//
183254721Semaste// Note, for now we make the string pool a pointer to the pool, because
184254721Semaste// we can't guarantee that some objects won't get destroyed after the
185254721Semaste// global destructor chain is run, and trying to make sure no destructors
186254721Semaste// touch ConstStrings is difficult.  So we leak the pool instead.
187254721Semaste//
188254721Semaste// FIXME: If we are going to keep it this way we should come up with some
189254721Semaste// abstraction to "pthread_once" so we don't have to check the pointer
190254721Semaste// every time.
191254721Semaste//----------------------------------------------------------------------
192254721Semastestatic Pool &
193254721SemasteStringPool()
194254721Semaste{
195254721Semaste    static Mutex g_pool_initialization_mutex;
196254721Semaste    static Pool *g_string_pool = NULL;
197254721Semaste
198254721Semaste    if (g_string_pool == NULL)
199254721Semaste    {
200254721Semaste        Mutex::Locker initialization_locker(g_pool_initialization_mutex);
201254721Semaste        if (g_string_pool == NULL)
202254721Semaste        {
203254721Semaste            g_string_pool = new Pool();
204254721Semaste        }
205254721Semaste    }
206254721Semaste
207254721Semaste    return *g_string_pool;
208254721Semaste}
209254721Semaste
210254721SemasteConstString::ConstString (const char *cstr) :
211254721Semaste    m_string (StringPool().GetConstCString (cstr))
212254721Semaste{
213254721Semaste}
214254721Semaste
215254721SemasteConstString::ConstString (const char *cstr, size_t cstr_len) :
216254721Semaste    m_string (StringPool().GetConstCStringWithLength (cstr, cstr_len))
217254721Semaste{
218254721Semaste}
219254721Semaste
220254721SemasteConstString::ConstString (const llvm::StringRef &s) :
221254721Semaste    m_string (StringPool().GetConstCStringWithLength (s.data(), s.size()))
222254721Semaste{
223254721Semaste}
224254721Semaste
225254721Semastebool
226254721SemasteConstString::operator < (const ConstString& rhs) const
227254721Semaste{
228254721Semaste    if (m_string == rhs.m_string)
229254721Semaste        return false;
230254721Semaste
231254721Semaste    llvm::StringRef lhs_string_ref (m_string, StringPool().GetConstCStringLength (m_string));
232254721Semaste    llvm::StringRef rhs_string_ref (rhs.m_string, StringPool().GetConstCStringLength (rhs.m_string));
233254721Semaste
234254721Semaste    // If both have valid C strings, then return the comparison
235254721Semaste    if (lhs_string_ref.data() && rhs_string_ref.data())
236254721Semaste        return lhs_string_ref < rhs_string_ref;
237254721Semaste
238254721Semaste    // Else one of them was NULL, so if LHS is NULL then it is less than
239254721Semaste    return lhs_string_ref.data() == NULL;
240254721Semaste}
241254721Semaste
242254721SemasteStream&
243254721Semastelldb_private::operator << (Stream& s, const ConstString& str)
244254721Semaste{
245254721Semaste    const char *cstr = str.GetCString();
246254721Semaste    if (cstr)
247254721Semaste        s << cstr;
248254721Semaste
249254721Semaste    return s;
250254721Semaste}
251254721Semaste
252254721Semastesize_t
253254721SemasteConstString::GetLength () const
254254721Semaste{
255254721Semaste    return StringPool().GetConstCStringLength (m_string);
256254721Semaste}
257254721Semaste
258254721Semasteint
259254721SemasteConstString::Compare (const ConstString& lhs, const ConstString& rhs)
260254721Semaste{
261254721Semaste    // If the iterators are the same, this is the same string
262254721Semaste    register const char *lhs_cstr = lhs.m_string;
263254721Semaste    register const char *rhs_cstr = rhs.m_string;
264254721Semaste    if (lhs_cstr == rhs_cstr)
265254721Semaste        return 0;
266254721Semaste    if (lhs_cstr && rhs_cstr)
267254721Semaste    {
268254721Semaste        llvm::StringRef lhs_string_ref (lhs_cstr, StringPool().GetConstCStringLength (lhs_cstr));
269254721Semaste        llvm::StringRef rhs_string_ref (rhs_cstr, StringPool().GetConstCStringLength (rhs_cstr));
270254721Semaste        return lhs_string_ref.compare(rhs_string_ref);
271254721Semaste    }
272254721Semaste
273254721Semaste    if (lhs_cstr)
274254721Semaste        return +1;  // LHS isn't NULL but RHS is
275254721Semaste    else
276254721Semaste        return -1;  // LHS is NULL but RHS isn't
277254721Semaste}
278254721Semaste
279254721Semastevoid
280254721SemasteConstString::Dump(Stream *s, const char *fail_value) const
281254721Semaste{
282254721Semaste    if (s)
283254721Semaste    {
284254721Semaste        const char *cstr = AsCString (fail_value);
285254721Semaste        if (cstr)
286254721Semaste            s->PutCString (cstr);
287254721Semaste    }
288254721Semaste}
289254721Semaste
290254721Semastevoid
291254721SemasteConstString::DumpDebug(Stream *s) const
292254721Semaste{
293254721Semaste    const char *cstr = GetCString ();
294254721Semaste    size_t cstr_len = GetLength();
295254721Semaste    // Only print the parens if we have a non-NULL string
296254721Semaste    const char *parens = cstr ? "\"" : "";
297254721Semaste    s->Printf("%*p: ConstString, string = %s%s%s, length = %" PRIu64, (int)sizeof(void*) * 2, this, parens, cstr, parens, (uint64_t)cstr_len);
298254721Semaste}
299254721Semaste
300254721Semastevoid
301254721SemasteConstString::SetCString (const char *cstr)
302254721Semaste{
303254721Semaste    m_string = StringPool().GetConstCString (cstr);
304254721Semaste}
305254721Semaste
306254721Semastevoid
307254721SemasteConstString::SetString (const llvm::StringRef &s)
308254721Semaste{
309254721Semaste    m_string = StringPool().GetConstCStringWithLength (s.data(), s.size());
310254721Semaste}
311254721Semaste
312254721Semastevoid
313254721SemasteConstString::SetCStringWithMangledCounterpart (const char *demangled, const ConstString &mangled)
314254721Semaste{
315254721Semaste    m_string = StringPool().GetConstCStringAndSetMangledCounterPart (demangled, mangled.m_string);
316254721Semaste}
317254721Semaste
318254721Semastebool
319254721SemasteConstString::GetMangledCounterpart (ConstString &counterpart) const
320254721Semaste{
321254721Semaste    counterpart.m_string = StringPool().GetMangledCounterpart(m_string);
322254721Semaste    return counterpart;
323254721Semaste}
324254721Semaste
325254721Semastevoid
326254721SemasteConstString::SetCStringWithLength (const char *cstr, size_t cstr_len)
327254721Semaste{
328254721Semaste    m_string = StringPool().GetConstCStringWithLength(cstr, cstr_len);
329254721Semaste}
330254721Semaste
331254721Semastevoid
332254721SemasteConstString::SetTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
333254721Semaste{
334254721Semaste    m_string = StringPool().GetConstTrimmedCStringWithLength (cstr, cstr_len);
335254721Semaste}
336254721Semaste
337254721Semastesize_t
338254721SemasteConstString::StaticMemorySize()
339254721Semaste{
340254721Semaste    // Get the size of the static string pool
341254721Semaste    return StringPool().MemorySize();
342254721Semaste}
343