//===-- 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/Host/Mutex.h"
#include "lldb/Target/Target.h"


using namespace lldb;
using namespace lldb_private;


SBAddress::SBAddress () :
    m_opaque_ap ()
{
}

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

SBAddress::SBAddress (const SBAddress &rhs) :
    m_opaque_ap ()
{
    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()
{    
    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();
    }
    return *this;
}

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

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

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();
}

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

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

    lldb::addr_t addr = LLDB_INVALID_ADDRESS;
    TargetSP target_sp (target.GetSP());
    if (target_sp)
    {
        if (m_opaque_ap.get())
        {
            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", target_sp.get());
        else
            log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => 0x%llx", 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.get())
    {
        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.get())
        sb_section.SetSP (m_opaque_ap->GetSection());
    return sb_section;
}

lldb::addr_t
SBAddress::GetOffset ()
{
    if (m_opaque_ap.get())
        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.get())
    {
        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.get())
        sb_module.SetSP (m_opaque_ap->GetModule());
    return sb_module;
}

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

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

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

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

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

SBLineEntry
SBAddress::GetLineEntry ()
{
    SBLineEntry sb_line_entry;
    if (m_opaque_ap.get())
    {
        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.get())
        return m_opaque_ap->GetAddressClass();
    return eAddressClassInvalid;
}

