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