//===-- SBAddress.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/API/SBAddress.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBSection.h"
#include "lldb/API/SBStream.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Symbol/LineEntry.h"
#include "lldb/Target/Target.h"


using namespace lldb;
using namespace lldb_private;


SBAddress::SBAddress () :
    m_opaque_ap (new Address())
{
}

SBAddress::SBAddress (const Address *lldb_object_ptr) :
    m_opaque_ap (new Address())
{
    if (lldb_object_ptr)
        ref() = *lldb_object_ptr;
}

SBAddress::SBAddress (const SBAddress &rhs) :
    m_opaque_ap (new Address())
{
    if (rhs.IsValid())
        ref() = rhs.ref();
}


SBAddress::SBAddress (lldb::SBSection section, lldb::addr_t offset) :
    m_opaque_ap(new Address (section.GetSP(), offset))
{
}

// Create an address by resolving a load address using the supplied target
SBAddress::SBAddress (lldb::addr_t load_addr, lldb::SBTarget &target) :
    m_opaque_ap(new Address())
{    
    SetLoadAddress (load_addr, target);
}



SBAddress::~SBAddress ()
{
}

const SBAddress &
SBAddress::operator = (const SBAddress &rhs)
{
    if (this != &rhs)
    {
        if (rhs.IsValid())
            ref() = rhs.ref();
        else
            m_opaque_ap.reset (new Address());
    }
    return *this;
}

bool
SBAddress::IsValid () const
{
    return m_opaque_ap.get() != NULL && m_opaque_ap->IsValid();
}

void
SBAddress::Clear ()
{
    m_opaque_ap.reset (new Address());
}

void
SBAddress::SetAddress (lldb::SBSection section, lldb::addr_t offset)
{
    Address &addr = ref();
    addr.SetSection (section.GetSP());
    addr.SetOffset (offset);
}


void
SBAddress::SetAddress (const Address *lldb_object_ptr)
{
    if (lldb_object_ptr)
        ref() =  *lldb_object_ptr;
    else
        m_opaque_ap.reset (new Address());
}

lldb::addr_t
SBAddress::GetFileAddress () const
{
    if (m_opaque_ap->IsValid())
        return m_opaque_ap->GetFileAddress();
    else
        return LLDB_INVALID_ADDRESS;
}

lldb::addr_t
SBAddress::GetLoadAddress (const SBTarget &target) const
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    lldb::addr_t addr = LLDB_INVALID_ADDRESS;
    TargetSP target_sp (target.GetSP());
    if (target_sp)
    {
        if (m_opaque_ap->IsValid())
        {
            Mutex::Locker api_locker (target_sp->GetAPIMutex());
            addr = m_opaque_ap->GetLoadAddress (target_sp.get());
        }
    }

    if (log)
    {
        if (addr == LLDB_INVALID_ADDRESS)
            log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => LLDB_INVALID_ADDRESS",
                         static_cast<void*>(target_sp.get()));
        else
            log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => 0x%" PRIx64,
                         static_cast<void*>(target_sp.get()), addr);
    }

    return addr;
}

void
SBAddress::SetLoadAddress (lldb::addr_t load_addr, lldb::SBTarget &target)
{
    // Create the address object if we don't already have one
    ref();
    if (target.IsValid())
        *this = target.ResolveLoadAddress(load_addr);
    else
        m_opaque_ap->Clear();

    // Check if we weren't were able to resolve a section offset address.
    // If we weren't it is ok, the load address might be a location on the
    // stack or heap, so we should just have an address with no section and
    // a valid offset
    if (!m_opaque_ap->IsValid())
        m_opaque_ap->SetOffset(load_addr);
}

bool
SBAddress::OffsetAddress (addr_t offset)
{
    if (m_opaque_ap->IsValid())
    {
        addr_t addr_offset = m_opaque_ap->GetOffset();
        if (addr_offset != LLDB_INVALID_ADDRESS)
        {
            m_opaque_ap->SetOffset(addr_offset + offset);
            return true;
        }
    }
    return false;
}

lldb::SBSection
SBAddress::GetSection ()
{
    lldb::SBSection sb_section;
    if (m_opaque_ap->IsValid())
        sb_section.SetSP (m_opaque_ap->GetSection());
    return sb_section;
}

lldb::addr_t
SBAddress::GetOffset ()
{
    if (m_opaque_ap->IsValid())
        return m_opaque_ap->GetOffset();
    return 0;
}

Address *
SBAddress::operator->()
{
    return m_opaque_ap.get();
}

const Address *
SBAddress::operator->() const
{
    return m_opaque_ap.get();
}

Address &
SBAddress::ref ()
{
    if (m_opaque_ap.get() == NULL)
        m_opaque_ap.reset (new Address());
    return *m_opaque_ap;
}

const Address &
SBAddress::ref () const
{
    // This object should already have checked with "IsValid()" 
    // prior to calling this function. In case you didn't we will assert
    // and die to let you know.
    assert (m_opaque_ap.get());
    return *m_opaque_ap;
}

Address *
SBAddress::get ()
{
    return m_opaque_ap.get();
}

bool
SBAddress::GetDescription (SBStream &description)
{
    // Call "ref()" on the stream to make sure it creates a backing stream in
    // case there isn't one already...
    Stream &strm = description.ref();
    if (m_opaque_ap->IsValid())
    {
        m_opaque_ap->Dump (&strm,
                           NULL,
                           Address::DumpStyleResolvedDescription,
                           Address::DumpStyleModuleWithFileAddress,
                           4);
        StreamString sstrm;
//        m_opaque_ap->Dump (&sstrm, NULL, Address::DumpStyleResolvedDescription, Address::DumpStyleInvalid, 4);
//        if (sstrm.GetData())
//            strm.Printf (" (%s)", sstrm.GetData());
    }
    else
        strm.PutCString ("No value");

    return true;
}

SBModule
SBAddress::GetModule ()
{
    SBModule sb_module;
    if (m_opaque_ap->IsValid())
        sb_module.SetSP (m_opaque_ap->GetModule());
    return sb_module;
}

SBSymbolContext
SBAddress::GetSymbolContext (uint32_t resolve_scope)
{
    SBSymbolContext sb_sc;
    if (m_opaque_ap->IsValid())
        m_opaque_ap->CalculateSymbolContext (&sb_sc.ref(), resolve_scope);
    return sb_sc;
}

SBCompileUnit
SBAddress::GetCompileUnit ()
{
    SBCompileUnit sb_comp_unit;
    if (m_opaque_ap->IsValid())
        sb_comp_unit.reset(m_opaque_ap->CalculateSymbolContextCompileUnit());
    return sb_comp_unit;
}

SBFunction
SBAddress::GetFunction ()
{
    SBFunction sb_function;
    if (m_opaque_ap->IsValid())
        sb_function.reset(m_opaque_ap->CalculateSymbolContextFunction());
    return sb_function;
}

SBBlock
SBAddress::GetBlock ()
{
    SBBlock sb_block;
    if (m_opaque_ap->IsValid())
        sb_block.SetPtr(m_opaque_ap->CalculateSymbolContextBlock());
    return sb_block;
}

SBSymbol
SBAddress::GetSymbol ()
{
    SBSymbol sb_symbol;
    if (m_opaque_ap->IsValid())
        sb_symbol.reset(m_opaque_ap->CalculateSymbolContextSymbol());
    return sb_symbol;
}

SBLineEntry
SBAddress::GetLineEntry ()
{
    SBLineEntry sb_line_entry;
    if (m_opaque_ap->IsValid())
    {
        LineEntry line_entry;
        if (m_opaque_ap->CalculateSymbolContextLineEntry (line_entry))
            sb_line_entry.SetLineEntry (line_entry);
    }
    return sb_line_entry;
}

AddressClass
SBAddress::GetAddressClass ()
{
    if (m_opaque_ap->IsValid())
        return m_opaque_ap->GetAddressClass();
    return eAddressClassInvalid;
}

