//===-- SBData.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/SBData.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBStream.h"

#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"


using namespace lldb;
using namespace lldb_private;

SBData::SBData () :
    m_opaque_sp(new DataExtractor())
{
}

SBData::SBData (const lldb::DataExtractorSP& data_sp) :
    m_opaque_sp (data_sp)
{
}

SBData::SBData(const SBData &rhs) :
    m_opaque_sp (rhs.m_opaque_sp)
{
}

const SBData &
SBData::operator = (const SBData &rhs)
{
    if (this != &rhs)
        m_opaque_sp = rhs.m_opaque_sp;
    return *this;
}

SBData::~SBData ()
{
}

void
SBData::SetOpaque (const lldb::DataExtractorSP &data_sp)
{
    m_opaque_sp = data_sp;
}

lldb_private::DataExtractor *
SBData::get() const
{
    return m_opaque_sp.get();
}

lldb_private::DataExtractor *
SBData::operator->() const
{
    return m_opaque_sp.operator->();
}

lldb::DataExtractorSP &
SBData::operator*()
{
    return m_opaque_sp;
}

const lldb::DataExtractorSP &
SBData::operator*() const
{
    return m_opaque_sp;
}

bool
SBData::IsValid()
{
    return m_opaque_sp.get() != NULL;
}

uint8_t
SBData::GetAddressByteSize ()
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    uint8_t value = 0;
    if (m_opaque_sp.get())
        value = m_opaque_sp->GetAddressByteSize();
    if (log)
        log->Printf ("SBData::GetAddressByteSize () => "
                     "(%i)", value);
    return value;
}

void
SBData::SetAddressByteSize (uint8_t addr_byte_size)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (m_opaque_sp.get())
        m_opaque_sp->SetAddressByteSize(addr_byte_size);
    if (log)
        log->Printf ("SBData::SetAddressByteSize (%i)", addr_byte_size);
}

void
SBData::Clear ()
{
    if (m_opaque_sp.get())
        m_opaque_sp->Clear();
}

size_t
SBData::GetByteSize ()
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    size_t value = 0;
    if (m_opaque_sp.get())
        value = m_opaque_sp->GetByteSize();
    if (log)
        log->Printf ("SBData::GetByteSize () => "
                     "(%lu)", value);
    return value;
}

lldb::ByteOrder
SBData::GetByteOrder ()
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    lldb::ByteOrder value = eByteOrderInvalid;
    if (m_opaque_sp.get())
        value = m_opaque_sp->GetByteOrder();
    if (log)
        log->Printf ("SBData::GetByteOrder () => "
                     "(%i)", value);
    return value;
}

void
SBData::SetByteOrder (lldb::ByteOrder endian)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (m_opaque_sp.get())
        m_opaque_sp->SetByteOrder(endian);
    if (log)
        log->Printf ("SBData::GetByteOrder (%i)", endian);
}


float
SBData::GetFloat (lldb::SBError& error, uint32_t offset)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    float value = 0;
    if (!m_opaque_sp.get())
    {
        error.SetErrorString("no value to read from");
    }
    else
    {
        uint32_t old_offset = offset;
        value = m_opaque_sp->GetFloat(&offset);
        if (offset == old_offset)
            error.SetErrorString("unable to read data");
    }
    if (log)
        log->Printf ("SBData::GetFloat (error=%p,offset=%d) => "
                     "(%f)", error.get(), offset, value);
    return value;
}

double
SBData::GetDouble (lldb::SBError& error, uint32_t offset)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    double value = 0;
    if (!m_opaque_sp.get())
    {
        error.SetErrorString("no value to read from");
    }
    else
    {
        uint32_t old_offset = offset;
        value = m_opaque_sp->GetDouble(&offset);
        if (offset == old_offset)
            error.SetErrorString("unable to read data");
    }
    if (log)
        log->Printf ("SBData::GetDouble (error=%p,offset=%d) => "
                     "(%f)", error.get(), offset, value);
    return value;
}

long double
SBData::GetLongDouble (lldb::SBError& error, uint32_t offset)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    long double value = 0;
    if (!m_opaque_sp.get())
    {
        error.SetErrorString("no value to read from");
    }
    else
    {
        uint32_t old_offset = offset;
        value = m_opaque_sp->GetLongDouble(&offset);
        if (offset == old_offset)
            error.SetErrorString("unable to read data");
    }
    if (log)
        log->Printf ("SBData::GetLongDouble (error=%p,offset=%d) => "
                     "(%Lf)", error.get(), offset, value);
    return value;
}

lldb::addr_t
SBData::GetAddress (lldb::SBError& error, uint32_t offset)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    lldb::addr_t value = 0;
    if (!m_opaque_sp.get())
    {
        error.SetErrorString("no value to read from");
    }
    else
    {
        uint32_t old_offset = offset;
        value = m_opaque_sp->GetAddress(&offset);
        if (offset == old_offset)
            error.SetErrorString("unable to read data");
    }
    if (log)
        log->Printf ("SBData::GetAddress (error=%p,offset=%d) => "
                     "(%p)", error.get(), offset, (void*)value);
    return value;
}

uint8_t
SBData::GetUnsignedInt8 (lldb::SBError& error, uint32_t offset)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    uint8_t value = 0;
    if (!m_opaque_sp.get())
    {
        error.SetErrorString("no value to read from");
    }
    else
    {
        uint32_t old_offset = offset;
        value = m_opaque_sp->GetU8(&offset);
        if (offset == old_offset)
            error.SetErrorString("unable to read data");
    }
    if (log)
        log->Printf ("SBData::GetUnsignedInt8 (error=%p,offset=%d) => "
                     "(%c)", error.get(), offset, value);
    return value;
}

uint16_t
SBData::GetUnsignedInt16 (lldb::SBError& error, uint32_t offset)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    uint16_t value = 0;
    if (!m_opaque_sp.get())
    {
        error.SetErrorString("no value to read from");
    }
    else
    {
        uint32_t old_offset = offset;
        value = m_opaque_sp->GetU16(&offset);
        if (offset == old_offset)
            error.SetErrorString("unable to read data");
    }
    if (log)
        log->Printf ("SBData::GetUnsignedInt16 (error=%p,offset=%d) => "
                     "(%hd)", error.get(), offset, value);
    return value;
}

uint32_t
SBData::GetUnsignedInt32 (lldb::SBError& error, uint32_t offset)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    uint32_t value = 0;
    if (!m_opaque_sp.get())
    {
        error.SetErrorString("no value to read from");
    }
    else
    {
        uint32_t old_offset = offset;
        value = m_opaque_sp->GetU32(&offset);
        if (offset == old_offset)
            error.SetErrorString("unable to read data");
    }
    if (log)
        log->Printf ("SBData::GetUnsignedInt32 (error=%p,offset=%d) => "
                     "(%d)", error.get(), offset, value);
    return value;
}

uint64_t
SBData::GetUnsignedInt64 (lldb::SBError& error, uint32_t offset)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    uint64_t value = 0;
    if (!m_opaque_sp.get())
    {
        error.SetErrorString("no value to read from");
    }
    else
    {
        uint32_t old_offset = offset;
        value = m_opaque_sp->GetU64(&offset);
        if (offset == old_offset)
            error.SetErrorString("unable to read data");
    }
    if (log)
        log->Printf ("SBData::GetUnsignedInt64 (error=%p,offset=%d) => "
                     "(%lld)", error.get(), offset, value);
    return value;
}

int8_t
SBData::GetSignedInt8 (lldb::SBError& error, uint32_t offset)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    int8_t value = 0;
    if (!m_opaque_sp.get())
    {
        error.SetErrorString("no value to read from");
    }
    else
    {
        uint32_t old_offset = offset;
        value = (int8_t)m_opaque_sp->GetMaxS64(&offset, 1);
        if (offset == old_offset)
            error.SetErrorString("unable to read data");
    }
    if (log)
        log->Printf ("SBData::GetSignedInt8 (error=%p,offset=%d) => "
                     "(%c)", error.get(), offset, value);
    return value;
}

int16_t
SBData::GetSignedInt16 (lldb::SBError& error, uint32_t offset)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    int16_t value = 0;
    if (!m_opaque_sp.get())
    {
        error.SetErrorString("no value to read from");
    }
    else
    {
        uint32_t old_offset = offset;
        value = (int16_t)m_opaque_sp->GetMaxS64(&offset, 2);
        if (offset == old_offset)
            error.SetErrorString("unable to read data");
    }
    if (log)
        log->Printf ("SBData::GetSignedInt16 (error=%p,offset=%d) => "
                     "(%hd)", error.get(), offset, value);
    return value;
}

int32_t
SBData::GetSignedInt32 (lldb::SBError& error, uint32_t offset)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    int32_t value = 0;
    if (!m_opaque_sp.get())
    {
        error.SetErrorString("no value to read from");
    }
    else
    {
        uint32_t old_offset = offset;
        value = (int32_t)m_opaque_sp->GetMaxS64(&offset, 4);
        if (offset == old_offset)
            error.SetErrorString("unable to read data");
    }
    if (log)
        log->Printf ("SBData::GetSignedInt32 (error=%p,offset=%d) => "
                     "(%d)", error.get(), offset, value);
    return value;
}

int64_t
SBData::GetSignedInt64 (lldb::SBError& error, uint32_t offset)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    int64_t value = 0;
    if (!m_opaque_sp.get())
    {
        error.SetErrorString("no value to read from");
    }
    else
    {
        uint32_t old_offset = offset;
        value = (int64_t)m_opaque_sp->GetMaxS64(&offset, 8);
        if (offset == old_offset)
            error.SetErrorString("unable to read data");
    }
    if (log)
        log->Printf ("SBData::GetSignedInt64 (error=%p,offset=%d) => "
                     "(%lld)", error.get(), offset, value);
    return value;
}

const char*
SBData::GetString (lldb::SBError& error, uint32_t offset)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    const char* value = 0;
    if (!m_opaque_sp.get())
    {
        error.SetErrorString("no value to read from");
    }
    else
    {
        uint32_t old_offset = offset;
        value = m_opaque_sp->GetCStr(&offset);
        if (offset == old_offset || (value == NULL))
            error.SetErrorString("unable to read data");
    }
    if (log)
        log->Printf ("SBData::GetString (error=%p,offset=%d) => "
                     "(%p)", error.get(), offset, value);
    return value;
}

bool
SBData::GetDescription (lldb::SBStream &description, lldb::addr_t base_addr)
{
    Stream &strm = description.ref();

    if (m_opaque_sp)
    {
        m_opaque_sp->Dump (&strm,
                           0,
                           lldb::eFormatBytesWithASCII,
                           1,
                           m_opaque_sp->GetByteSize(),
                           16,
                           base_addr,
                           0,
                           0);
    }
    else
        strm.PutCString ("No value");
    
    return true;
}

size_t
SBData::ReadRawData (lldb::SBError& error,
                     uint32_t offset,
                     void *buf,
                     size_t size)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    void* ok = NULL;
    if (!m_opaque_sp.get())
    {
        error.SetErrorString("no value to read from");
    }
    else
    {
        uint32_t old_offset = offset;
        ok = m_opaque_sp->GetU8(&offset, buf, size);
        if ((offset == old_offset) || (ok == NULL))
            error.SetErrorString("unable to read data");
    }
    if (log)
        log->Printf ("SBData::ReadRawData (error=%p,offset=%d,buf=%p,size=%lu) => "
                     "(%p)", error.get(), offset, buf, size, ok);
    return ok ? size : 0;
}

void
SBData::SetData (lldb::SBError& error,
                 const void *buf,
                 size_t size,
                 lldb::ByteOrder endian,
                 uint8_t addr_size)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    if (!m_opaque_sp.get())
        m_opaque_sp.reset(new DataExtractor(buf, size, endian, addr_size));
    else
        m_opaque_sp->SetData(buf, size, endian);
    if (log)
        log->Printf ("SBData::SetData (error=%p,buf=%p,size=%lu,endian=%d,addr_size=%c) => "
                     "(%p)", error.get(), buf, size, endian, addr_size, m_opaque_sp.get());
}

bool
SBData::Append (const SBData& rhs)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    bool value = false;
    if (m_opaque_sp.get() && rhs.m_opaque_sp.get())
        value = m_opaque_sp.get()->Append(*rhs.m_opaque_sp);
    if (log)
        log->Printf ("SBData::Append (rhs=%p) => "
                     "(%s)", rhs.get(), value ? "true" : "false");
    return value;
}

lldb::SBData
SBData::CreateDataFromCString (lldb::ByteOrder endian, uint32_t addr_byte_size, const char* data)
{
    if (!data || !data[0])
        return SBData();
    
    uint32_t data_len = strlen(data);
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(data, data_len));
    lldb::DataExtractorSP data_sp(new DataExtractor(buffer_sp, endian, addr_byte_size));
    
    SBData ret(data_sp);
    
    return ret;
}

lldb::SBData
SBData::CreateDataFromUInt64Array (lldb::ByteOrder endian, uint32_t addr_byte_size, uint64_t* array, size_t array_len)
{
    if (!array || array_len == 0)
        return SBData();
    
    size_t data_len = array_len * sizeof(uint64_t);
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
    lldb::DataExtractorSP data_sp(new DataExtractor(buffer_sp, endian, addr_byte_size));
    
    SBData ret(data_sp);
    
    return ret;
}

lldb::SBData
SBData::CreateDataFromUInt32Array (lldb::ByteOrder endian, uint32_t addr_byte_size, uint32_t* array, size_t array_len)
{
    if (!array || array_len == 0)
        return SBData();
    
    size_t data_len = array_len * sizeof(uint32_t);
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
    lldb::DataExtractorSP data_sp(new DataExtractor(buffer_sp, endian, addr_byte_size));
    
    SBData ret(data_sp);
    
    return ret;
}

lldb::SBData
SBData::CreateDataFromSInt64Array (lldb::ByteOrder endian, uint32_t addr_byte_size, int64_t* array, size_t array_len)
{
    if (!array || array_len == 0)
        return SBData();
    
    size_t data_len = array_len * sizeof(int64_t);
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
    lldb::DataExtractorSP data_sp(new DataExtractor(buffer_sp, endian, addr_byte_size));
    
    SBData ret(data_sp);
    
    return ret;
}

lldb::SBData
SBData::CreateDataFromSInt32Array (lldb::ByteOrder endian, uint32_t addr_byte_size, int32_t* array, size_t array_len)
{
    if (!array || array_len == 0)
        return SBData();
    
    size_t data_len = array_len * sizeof(int32_t);
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
    lldb::DataExtractorSP data_sp(new DataExtractor(buffer_sp, endian, addr_byte_size));
    
    SBData ret(data_sp);
    
    return ret;
}

lldb::SBData
SBData::CreateDataFromDoubleArray (lldb::ByteOrder endian, uint32_t addr_byte_size, double* array, size_t array_len)
{
    if (!array || array_len == 0)
        return SBData();
    
    size_t data_len = array_len * sizeof(double);
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
    lldb::DataExtractorSP data_sp(new DataExtractor(buffer_sp, endian, addr_byte_size));
    
    SBData ret(data_sp);
    
    return ret;
}

bool
SBData::SetDataFromCString (const char* data)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    
    if (!data)
    {
        if (log)
            log->Printf ("SBData::SetDataFromCString (data=%p) => "
                         "false", data);
        return false;
    }
    
    size_t data_len = strlen(data);
        
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(data, data_len));
    
    if (!m_opaque_sp.get())
        m_opaque_sp.reset(new DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()));
    else
        m_opaque_sp->SetData(buffer_sp);
    
    if (log)
        log->Printf ("SBData::SetDataFromCString (data=%p) => "
                     "true", data);
    
    return true;
}

bool
SBData::SetDataFromUInt64Array (uint64_t* array, size_t array_len)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    
    if (!array || array_len == 0)
    {
        if (log)
            log->Printf ("SBData::SetDataFromUInt64Array (array=%p, array_len = %lu) => "
                         "false", array, array_len);
        return false;
    }

    size_t data_len = array_len * sizeof(uint64_t);
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
    
    if (!m_opaque_sp.get())
        m_opaque_sp.reset(new DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()));
    else
        m_opaque_sp->SetData(buffer_sp);
    
    if (log)
        log->Printf ("SBData::SetDataFromUInt64Array (array=%p, array_len = %lu) => "
                     "true", array, array_len);
    
    return true;
}

bool
SBData::SetDataFromUInt32Array (uint32_t* array, size_t array_len)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    
    if (!array || array_len == 0)
    {
        if (log)
            log->Printf ("SBData::SetDataFromUInt32Array (array=%p, array_len = %lu) => "
                         "false", array, array_len);
        return false;
    }
    
    size_t data_len = array_len * sizeof(uint32_t);
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
    
    if (!m_opaque_sp.get())
        m_opaque_sp.reset(new DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()));
    else
        m_opaque_sp->SetData(buffer_sp);
    
    if (log)
        log->Printf ("SBData::SetDataFromUInt32Array (array=%p, array_len = %lu) => "
                     "true", array, array_len);
    
    return true;
}

bool
SBData::SetDataFromSInt64Array (int64_t* array, size_t array_len)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    
    if (!array || array_len == 0)
    {
        if (log)
            log->Printf ("SBData::SetDataFromSInt64Array (array=%p, array_len = %lu) => "
                         "false", array, array_len);
        return false;
    }
    
    size_t data_len = array_len * sizeof(int64_t);
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
    
    if (!m_opaque_sp.get())
        m_opaque_sp.reset(new DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()));
    else
        m_opaque_sp->SetData(buffer_sp);
    
    if (log)
        log->Printf ("SBData::SetDataFromSInt64Array (array=%p, array_len = %lu) => "
                     "true", array, array_len);
    
    return true;
}

bool
SBData::SetDataFromSInt32Array (int32_t* array, size_t array_len)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    
    if (!array || array_len == 0)
    {
        if (log)
            log->Printf ("SBData::SetDataFromSInt32Array (array=%p, array_len = %lu) => "
                         "false", array, array_len);
        return false;
    }
    
    size_t data_len = array_len * sizeof(int32_t);
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
    
    if (!m_opaque_sp.get())
        m_opaque_sp.reset(new DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()));
    else
        m_opaque_sp->SetData(buffer_sp);
    
    if (log)
        log->Printf ("SBData::SetDataFromSInt32Array (array=%p, array_len = %lu) => "
                     "true", array, array_len);
    
    return true;
}

bool
SBData::SetDataFromDoubleArray (double* array, size_t array_len)
{
    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    
    if (!array || array_len == 0)
    {
        if (log)
            log->Printf ("SBData::SetDataFromDoubleArray (array=%p, array_len = %lu) => "
                         "false", array, array_len);
        return false;
    }
    
    size_t data_len = array_len * sizeof(double);
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(array, data_len));
    
    if (!m_opaque_sp.get())
        m_opaque_sp.reset(new DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()));
    else
        m_opaque_sp->SetData(buffer_sp);
    
    if (log)
        log->Printf ("SBData::SetDataFromDoubleArray (array=%p, array_len = %lu) => "
                     "true", array, array_len);
    
    return true;
}
