//===-- 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"

#include <mutex> // std::once

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.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first;
            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.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first;
            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.insert (std::make_pair (llvm::StringRef (demangled_cstr), mangled_ccstr)).first;

            // 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.
//----------------------------------------------------------------------
static Pool &
StringPool()
{
    static std::once_flag g_pool_initialization_flag;
    static Pool *g_string_pool = NULL;

    std::call_once(g_pool_initialization_flag, [] () {
        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
    const char *lhs_cstr = lhs.m_string;
    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,
              static_cast<int>(sizeof(void*) * 2),
              static_cast<const void*>(this), parens, cstr, parens,
              static_cast<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 (bool)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();
}
