1 //===-- ConstString.cpp -----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
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"
14 using namespace lldb_private;
20 typedef const char * StringPoolValueType;
21 typedef llvm::StringMap<StringPoolValueType, llvm::BumpPtrAllocator> StringPool;
22 typedef llvm::StringMapEntry<StringPoolValueType> StringPoolEntryType;
24 //------------------------------------------------------------------
25 // Default constructor
27 // Initialize the member variables and create the empty string.
28 //------------------------------------------------------------------
30 m_mutex (Mutex::eMutexTypeRecursive),
35 //------------------------------------------------------------------
37 //------------------------------------------------------------------
43 static StringPoolEntryType &
44 GetStringMapEntryFromKeyData (const char *keyData)
46 char *ptr = const_cast<char*>(keyData) - sizeof (StringPoolEntryType);
47 return *reinterpret_cast<StringPoolEntryType*>(ptr);
51 GetConstCStringLength (const char *ccstr) const
55 const StringPoolEntryType&entry = GetStringMapEntryFromKeyData (ccstr);
56 return entry.getKey().size();
62 GetMangledCounterpart (const char *ccstr) const
65 return GetStringMapEntryFromKeyData (ccstr).getValue();
70 SetMangledCounterparts (const char *key_ccstr, const char *value_ccstr)
72 if (key_ccstr && value_ccstr)
74 GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr);
75 GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr);
82 GetConstCString (const char *cstr)
85 return GetConstCStringWithLength (cstr, strlen (cstr));
90 GetConstCStringWithLength (const char *cstr, size_t cstr_len)
94 Mutex::Locker locker (m_mutex);
95 llvm::StringRef string_ref (cstr, cstr_len);
96 StringPoolEntryType& entry = m_string_map.GetOrCreateValue (string_ref, (StringPoolValueType)NULL);
97 return entry.getKeyData();
103 GetConstCStringWithStringRef (const llvm::StringRef &string_ref)
105 if (string_ref.data())
107 Mutex::Locker locker (m_mutex);
108 StringPoolEntryType& entry = m_string_map.GetOrCreateValue (string_ref, (StringPoolValueType)NULL);
109 return entry.getKeyData();
115 GetConstCStringAndSetMangledCounterPart (const char *demangled_cstr, const char *mangled_ccstr)
119 Mutex::Locker locker (m_mutex);
120 // Make string pool entry with the mangled counterpart already set
121 StringPoolEntryType& entry = m_string_map.GetOrCreateValue (llvm::StringRef (demangled_cstr), mangled_ccstr);
123 // Extract the const version of the demangled_cstr
124 const char *demangled_ccstr = entry.getKeyData();
125 // Now assign the demangled const string as the counterpart of the
126 // mangled const string...
127 GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr);
128 // Return the constant demangled C string
129 return demangled_ccstr;
135 GetConstTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
139 const size_t trimmed_len = std::min<size_t> (strlen (cstr), cstr_len);
140 return GetConstCStringWithLength (cstr, trimmed_len);
145 //------------------------------------------------------------------
146 // Return the size in bytes that this object and any items in its
147 // collection of uniqued strings + data count values takes in
149 //------------------------------------------------------------------
153 Mutex::Locker locker (m_mutex);
154 size_t mem_size = sizeof(Pool);
155 const_iterator end = m_string_map.end();
156 for (const_iterator pos = m_string_map.begin(); pos != end; ++pos)
158 mem_size += sizeof(StringPoolEntryType) + pos->getKey().size();
164 //------------------------------------------------------------------
166 //------------------------------------------------------------------
167 typedef StringPool::iterator iterator;
168 typedef StringPool::const_iterator const_iterator;
170 //------------------------------------------------------------------
172 //------------------------------------------------------------------
173 mutable Mutex m_mutex;
174 StringPool m_string_map;
177 //----------------------------------------------------------------------
178 // Frameworks and dylibs aren't supposed to have global C++
179 // initializers so we hide the string pool in a static function so
180 // that it will get initialized on the first call to this static
183 // Note, for now we make the string pool a pointer to the pool, because
184 // we can't guarantee that some objects won't get destroyed after the
185 // global destructor chain is run, and trying to make sure no destructors
186 // touch ConstStrings is difficult. So we leak the pool instead.
188 // FIXME: If we are going to keep it this way we should come up with some
189 // abstraction to "pthread_once" so we don't have to check the pointer
191 //----------------------------------------------------------------------
195 static Mutex g_pool_initialization_mutex;
196 static Pool *g_string_pool = NULL;
198 if (g_string_pool == NULL)
200 Mutex::Locker initialization_locker(g_pool_initialization_mutex);
201 if (g_string_pool == NULL)
203 g_string_pool = new Pool();
207 return *g_string_pool;
210 ConstString::ConstString (const char *cstr) :
211 m_string (StringPool().GetConstCString (cstr))
215 ConstString::ConstString (const char *cstr, size_t cstr_len) :
216 m_string (StringPool().GetConstCStringWithLength (cstr, cstr_len))
220 ConstString::ConstString (const llvm::StringRef &s) :
221 m_string (StringPool().GetConstCStringWithLength (s.data(), s.size()))
226 ConstString::operator < (const ConstString& rhs) const
228 if (m_string == rhs.m_string)
231 llvm::StringRef lhs_string_ref (m_string, StringPool().GetConstCStringLength (m_string));
232 llvm::StringRef rhs_string_ref (rhs.m_string, StringPool().GetConstCStringLength (rhs.m_string));
234 // If both have valid C strings, then return the comparison
235 if (lhs_string_ref.data() && rhs_string_ref.data())
236 return lhs_string_ref < rhs_string_ref;
238 // Else one of them was NULL, so if LHS is NULL then it is less than
239 return lhs_string_ref.data() == NULL;
243 lldb_private::operator << (Stream& s, const ConstString& str)
245 const char *cstr = str.GetCString();
253 ConstString::GetLength () const
255 return StringPool().GetConstCStringLength (m_string);
259 ConstString::Compare (const ConstString& lhs, const ConstString& rhs)
261 // If the iterators are the same, this is the same string
262 const char *lhs_cstr = lhs.m_string;
263 const char *rhs_cstr = rhs.m_string;
264 if (lhs_cstr == rhs_cstr)
266 if (lhs_cstr && rhs_cstr)
268 llvm::StringRef lhs_string_ref (lhs_cstr, StringPool().GetConstCStringLength (lhs_cstr));
269 llvm::StringRef rhs_string_ref (rhs_cstr, StringPool().GetConstCStringLength (rhs_cstr));
270 return lhs_string_ref.compare(rhs_string_ref);
274 return +1; // LHS isn't NULL but RHS is
276 return -1; // LHS is NULL but RHS isn't
280 ConstString::Dump(Stream *s, const char *fail_value) const
284 const char *cstr = AsCString (fail_value);
286 s->PutCString (cstr);
291 ConstString::DumpDebug(Stream *s) const
293 const char *cstr = GetCString ();
294 size_t cstr_len = GetLength();
295 // Only print the parens if we have a non-NULL string
296 const char *parens = cstr ? "\"" : "";
297 s->Printf("%*p: ConstString, string = %s%s%s, length = %" PRIu64, (int)sizeof(void*) * 2, this, parens, cstr, parens, (uint64_t)cstr_len);
301 ConstString::SetCString (const char *cstr)
303 m_string = StringPool().GetConstCString (cstr);
307 ConstString::SetString (const llvm::StringRef &s)
309 m_string = StringPool().GetConstCStringWithLength (s.data(), s.size());
313 ConstString::SetCStringWithMangledCounterpart (const char *demangled, const ConstString &mangled)
315 m_string = StringPool().GetConstCStringAndSetMangledCounterPart (demangled, mangled.m_string);
319 ConstString::GetMangledCounterpart (ConstString &counterpart) const
321 counterpart.m_string = StringPool().GetMangledCounterpart(m_string);
322 return (bool)counterpart;
326 ConstString::SetCStringWithLength (const char *cstr, size_t cstr_len)
328 m_string = StringPool().GetConstCStringWithLength(cstr, cstr_len);
332 ConstString::SetTrimmedCStringWithLength (const char *cstr, size_t cstr_len)
334 m_string = StringPool().GetConstTrimmedCStringWithLength (cstr, cstr_len);
338 ConstString::StaticMemorySize()
340 // Get the size of the static string pool
341 return StringPool().MemorySize();