diff options
Diffstat (limited to 'source/Core/ConstString.cpp')
-rw-r--r-- | source/Core/ConstString.cpp | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/source/Core/ConstString.cpp b/source/Core/ConstString.cpp new file mode 100644 index 0000000..8751694 --- /dev/null +++ b/source/Core/ConstString.cpp @@ -0,0 +1,342 @@ +//===-- ConstString.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Stream.h" +#include "lldb/Host/Mutex.h" +#include "llvm/ADT/StringMap.h" + +using namespace lldb_private; + + +class Pool +{ +public: + typedef const char * StringPoolValueType; + typedef llvm::StringMap<StringPoolValueType, llvm::BumpPtrAllocator> StringPool; + typedef llvm::StringMapEntry<StringPoolValueType> StringPoolEntryType; + + //------------------------------------------------------------------ + // Default constructor + // + // Initialize the member variables and create the empty string. + //------------------------------------------------------------------ + Pool () : + m_mutex (Mutex::eMutexTypeRecursive), + m_string_map () + { + } + + //------------------------------------------------------------------ + // Destructor + //------------------------------------------------------------------ + ~Pool () + { + } + + + static StringPoolEntryType & + GetStringMapEntryFromKeyData (const char *keyData) + { + char *ptr = const_cast<char*>(keyData) - sizeof (StringPoolEntryType); + return *reinterpret_cast<StringPoolEntryType*>(ptr); + } + + size_t + GetConstCStringLength (const char *ccstr) const + { + if (ccstr) + { + const StringPoolEntryType&entry = GetStringMapEntryFromKeyData (ccstr); + return entry.getKey().size(); + } + return 0; + } + + StringPoolValueType + GetMangledCounterpart (const char *ccstr) const + { + if (ccstr) + return GetStringMapEntryFromKeyData (ccstr).getValue(); + return 0; + } + + bool + SetMangledCounterparts (const char *key_ccstr, const char *value_ccstr) + { + if (key_ccstr && value_ccstr) + { + GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr); + GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr); + return true; + } + return false; + } + + const char * + GetConstCString (const char *cstr) + { + if (cstr) + return GetConstCStringWithLength (cstr, strlen (cstr)); + return NULL; + } + + const char * + GetConstCStringWithLength (const char *cstr, size_t cstr_len) + { + if (cstr) + { + Mutex::Locker locker (m_mutex); + llvm::StringRef string_ref (cstr, cstr_len); + StringPoolEntryType& entry = m_string_map.GetOrCreateValue (string_ref, (StringPoolValueType)NULL); + return entry.getKeyData(); + } + return NULL; + } + + const char * + GetConstCStringWithStringRef (const llvm::StringRef &string_ref) + { + if (string_ref.data()) + { + Mutex::Locker locker (m_mutex); + StringPoolEntryType& entry = m_string_map.GetOrCreateValue (string_ref, (StringPoolValueType)NULL); + return entry.getKeyData(); + } + return NULL; + } + + const char * + GetConstCStringAndSetMangledCounterPart (const char *demangled_cstr, const char *mangled_ccstr) + { + if (demangled_cstr) + { + Mutex::Locker locker (m_mutex); + // Make string pool entry with the mangled counterpart already set + StringPoolEntryType& entry = m_string_map.GetOrCreateValue (llvm::StringRef (demangled_cstr), mangled_ccstr); + + // Extract the const version of the demangled_cstr + const char *demangled_ccstr = entry.getKeyData(); + // Now assign the demangled const string as the counterpart of the + // mangled const string... + GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr); + // Return the constant demangled C string + return demangled_ccstr; + } + return NULL; + } + + const char * + GetConstTrimmedCStringWithLength (const char *cstr, size_t cstr_len) + { + if (cstr) + { + const size_t trimmed_len = std::min<size_t> (strlen (cstr), cstr_len); + return GetConstCStringWithLength (cstr, trimmed_len); + } + return NULL; + } + + //------------------------------------------------------------------ + // Return the size in bytes that this object and any items in its + // collection of uniqued strings + data count values takes in + // memory. + //------------------------------------------------------------------ + size_t + MemorySize() const + { + Mutex::Locker locker (m_mutex); + size_t mem_size = sizeof(Pool); + const_iterator end = m_string_map.end(); + for (const_iterator pos = m_string_map.begin(); pos != end; ++pos) + { + mem_size += sizeof(StringPoolEntryType) + pos->getKey().size(); + } + return mem_size; + } + +protected: + //------------------------------------------------------------------ + // Typedefs + //------------------------------------------------------------------ + typedef StringPool::iterator iterator; + typedef StringPool::const_iterator const_iterator; + + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + mutable Mutex m_mutex; + StringPool m_string_map; +}; + +//---------------------------------------------------------------------- +// Frameworks and dylibs aren't supposed to have global C++ +// initializers so we hide the string pool in a static function so +// that it will get initialized on the first call to this static +// function. +// +// Note, for now we make the string pool a pointer to the pool, because +// we can't guarantee that some objects won't get destroyed after the +// global destructor chain is run, and trying to make sure no destructors +// touch ConstStrings is difficult. So we leak the pool instead. +// +// FIXME: If we are going to keep it this way we should come up with some +// abstraction to "pthread_once" so we don't have to check the pointer +// every time. +//---------------------------------------------------------------------- +static Pool & +StringPool() +{ + static Mutex g_pool_initialization_mutex; + static Pool *g_string_pool = NULL; + + if (g_string_pool == NULL) + { + Mutex::Locker initialization_locker(g_pool_initialization_mutex); + if (g_string_pool == NULL) + { + g_string_pool = new Pool(); + } + } + + return *g_string_pool; +} + +ConstString::ConstString (const char *cstr) : + m_string (StringPool().GetConstCString (cstr)) +{ +} + +ConstString::ConstString (const char *cstr, size_t cstr_len) : + m_string (StringPool().GetConstCStringWithLength (cstr, cstr_len)) +{ +} + +ConstString::ConstString (const llvm::StringRef &s) : + m_string (StringPool().GetConstCStringWithLength (s.data(), s.size())) +{ +} + +bool +ConstString::operator < (const ConstString& rhs) const +{ + if (m_string == rhs.m_string) + return false; + + llvm::StringRef lhs_string_ref (m_string, StringPool().GetConstCStringLength (m_string)); + llvm::StringRef rhs_string_ref (rhs.m_string, StringPool().GetConstCStringLength (rhs.m_string)); + + // If both have valid C strings, then return the comparison + if (lhs_string_ref.data() && rhs_string_ref.data()) + return lhs_string_ref < rhs_string_ref; + + // Else one of them was NULL, so if LHS is NULL then it is less than + return lhs_string_ref.data() == NULL; +} + +Stream& +lldb_private::operator << (Stream& s, const ConstString& str) +{ + const char *cstr = str.GetCString(); + if (cstr) + s << cstr; + + return s; +} + +size_t +ConstString::GetLength () const +{ + return StringPool().GetConstCStringLength (m_string); +} + +int +ConstString::Compare (const ConstString& lhs, const ConstString& rhs) +{ + // If the iterators are the same, this is the same string + register const char *lhs_cstr = lhs.m_string; + register const char *rhs_cstr = rhs.m_string; + if (lhs_cstr == rhs_cstr) + return 0; + if (lhs_cstr && rhs_cstr) + { + llvm::StringRef lhs_string_ref (lhs_cstr, StringPool().GetConstCStringLength (lhs_cstr)); + llvm::StringRef rhs_string_ref (rhs_cstr, StringPool().GetConstCStringLength (rhs_cstr)); + return lhs_string_ref.compare(rhs_string_ref); + } + + if (lhs_cstr) + return +1; // LHS isn't NULL but RHS is + else + return -1; // LHS is NULL but RHS isn't +} + +void +ConstString::Dump(Stream *s, const char *fail_value) const +{ + if (s) + { + const char *cstr = AsCString (fail_value); + if (cstr) + s->PutCString (cstr); + } +} + +void +ConstString::DumpDebug(Stream *s) const +{ + const char *cstr = GetCString (); + size_t cstr_len = GetLength(); + // Only print the parens if we have a non-NULL string + const char *parens = cstr ? "\"" : ""; + s->Printf("%*p: ConstString, string = %s%s%s, length = %" PRIu64, (int)sizeof(void*) * 2, this, parens, cstr, parens, (uint64_t)cstr_len); +} + +void +ConstString::SetCString (const char *cstr) +{ + m_string = StringPool().GetConstCString (cstr); +} + +void +ConstString::SetString (const llvm::StringRef &s) +{ + m_string = StringPool().GetConstCStringWithLength (s.data(), s.size()); +} + +void +ConstString::SetCStringWithMangledCounterpart (const char *demangled, const ConstString &mangled) +{ + m_string = StringPool().GetConstCStringAndSetMangledCounterPart (demangled, mangled.m_string); +} + +bool +ConstString::GetMangledCounterpart (ConstString &counterpart) const +{ + counterpart.m_string = StringPool().GetMangledCounterpart(m_string); + return counterpart; +} + +void +ConstString::SetCStringWithLength (const char *cstr, size_t cstr_len) +{ + m_string = StringPool().GetConstCStringWithLength(cstr, cstr_len); +} + +void +ConstString::SetTrimmedCStringWithLength (const char *cstr, size_t cstr_len) +{ + m_string = StringPool().GetConstTrimmedCStringWithLength (cstr, cstr_len); +} + +size_t +ConstString::StaticMemorySize() +{ + // Get the size of the static string pool + return StringPool().MemorySize(); +} |