//===-- DNBBreakpoint.cpp ---------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  Created by Greg Clayton on 6/29/07.
//
//===----------------------------------------------------------------------===//

#include "DNBBreakpoint.h"
#include <algorithm>
#include "DNBLog.h"


#pragma mark -- DNBBreakpoint
DNBBreakpoint::DNBBreakpoint(nub_addr_t addr, nub_size_t byte_size, nub_thread_t tid, bool hardware) :
    m_breakID(GetNextID()),
    m_tid(tid),
    m_byte_size(byte_size),
    m_opcode(),
    m_addr(addr),
    m_enabled(0),
    m_hw_preferred(hardware),
    m_is_watchpoint(0),
    m_watch_read(0),
    m_watch_write(0),
    m_hw_index(INVALID_NUB_HW_INDEX),
    m_hit_count(0),
    m_ignore_count(0),
    m_callback(NULL),
    m_callback_baton(NULL)
{
}

DNBBreakpoint::~DNBBreakpoint()
{
}

nub_break_t
DNBBreakpoint::GetNextID()
{
    static uint32_t g_nextBreakID = 0;
    return ++g_nextBreakID;
}

void
DNBBreakpoint::SetCallback(DNBCallbackBreakpointHit callback, void *callback_baton)
{
    m_callback = callback;
    m_callback_baton = callback_baton;
}


// RETURNS - true if we should stop at this breakpoint, false if we
// should continue.

bool
DNBBreakpoint::BreakpointHit(nub_process_t pid, nub_thread_t tid)
{
    m_hit_count++;

    if (m_hit_count > m_ignore_count)
    {
        if (m_callback)
            return m_callback(pid, tid, GetID(), m_callback_baton);
        return true;
    }
    return false;
}

void
DNBBreakpoint::Dump() const
{
    if (IsBreakpoint())
    {
        DNBLog("DNBBreakpoint %u: tid = %4.4x  addr = %8.8p  state = %s  type = %s breakpoint  hw_index = %i  hit_count = %-4u  ignore_count = %-4u  callback = %8.8p baton = %8.8p",
            m_breakID,
            m_tid,
            m_addr,
            m_enabled ? "enabled " : "disabled",
            IsHardware() ? "hardware" : "software",
            GetHardwareIndex(),
            GetHitCount(),
            GetIgnoreCount(),
            m_callback,
            m_callback_baton);
    }
    else
    {
        DNBLog("DNBBreakpoint %u: tid = %4.4x  addr = %8.8p  size = %u  state = %s  type = %s watchpoint (%s%s)  hw_index = %i  hit_count = %-4u  ignore_count = %-4u  callback = %8.8p baton = %8.8p",
            m_breakID,
            m_tid,
            m_addr,
            m_byte_size,
            m_enabled ? "enabled " : "disabled",
            IsHardware() ? "hardware" : "software",
            m_watch_read ? "r" : "",
            m_watch_write ? "w" : "",
            GetHardwareIndex(),
            GetHitCount(),
            GetIgnoreCount(),
            m_callback,
            m_callback_baton);
    }
}

#pragma mark -- DNBBreakpointList

DNBBreakpointList::DNBBreakpointList()
{
}

DNBBreakpointList::~DNBBreakpointList()
{
}


nub_break_t
DNBBreakpointList::Add(const DNBBreakpoint& bp)
{
    m_breakpoints.push_back(bp);
    return m_breakpoints.back().GetID();
}

bool
DNBBreakpointList::ShouldStop(nub_process_t pid, nub_thread_t tid, nub_break_t breakID)
{
    DNBBreakpoint *bp = FindByID (breakID);
    if (bp)
    {
        // Let the breakpoint decide if it should stop here (could not have
        // reached it's target hit count yet, or it could have a callback
        // that decided it shouldn't stop (shared library loads/unloads).
        return bp->BreakpointHit(pid, tid);
    }
    // We should stop here since this breakpoint isn't valid anymore or it
    // doesn't exist.
    return true;
}

nub_break_t
DNBBreakpointList::FindIDByAddress (nub_addr_t addr)
{
    DNBBreakpoint *bp = FindByAddress (addr);
    if (bp)
    {
        DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBBreakpointList::%s ( addr = 0x%16.16llx ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID());
        return bp->GetID();
    }
    DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBBreakpointList::%s ( addr = 0x%16.16llx ) => NONE", __FUNCTION__, (uint64_t)addr);
    return INVALID_NUB_BREAK_ID;
}

bool
DNBBreakpointList::Remove (nub_break_t breakID)
{
    iterator pos = GetBreakIDIterator(breakID);    // Predicate
    if (pos != m_breakpoints.end())
    {
        m_breakpoints.erase(pos);
        return true;
    }
    return false;
}


class BreakpointIDMatches
{
public:
    BreakpointIDMatches (nub_break_t breakID) : m_breakID(breakID) {}
    bool operator() (const DNBBreakpoint& bp) const
    {
        return m_breakID == bp.GetID();
    }
 private:
   const nub_break_t m_breakID;
};

class BreakpointAddressMatches
{
public:
    BreakpointAddressMatches (nub_addr_t addr) : m_addr(addr) {}
    bool operator() (const DNBBreakpoint& bp) const
    {
        return m_addr == bp.Address();
    }
 private:
   const nub_addr_t m_addr;
};

DNBBreakpointList::iterator
DNBBreakpointList::GetBreakIDIterator (nub_break_t breakID)
{
    return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range
                        BreakpointIDMatches(breakID));              // Predicate
}

DNBBreakpointList::const_iterator
DNBBreakpointList::GetBreakIDConstIterator (nub_break_t breakID) const
{
    return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range
                        BreakpointIDMatches(breakID));              // Predicate
}

DNBBreakpoint *
DNBBreakpointList::FindByID (nub_break_t breakID)
{
    iterator pos = GetBreakIDIterator(breakID);
    if (pos != m_breakpoints.end())
        return &(*pos);

    return NULL;
}

const DNBBreakpoint *
DNBBreakpointList::FindByID (nub_break_t breakID) const
{
    const_iterator pos = GetBreakIDConstIterator(breakID);
    if (pos != m_breakpoints.end())
        return &(*pos);

    return NULL;
}

DNBBreakpoint *
DNBBreakpointList::FindByAddress (nub_addr_t addr)
{
    iterator end = m_breakpoints.end();
    iterator pos = std::find_if(m_breakpoints.begin(), end,             // Search full range
                                BreakpointAddressMatches(addr));        // Predicate
    if (pos != end)
        return &(*pos);

    return NULL;
}

const DNBBreakpoint *
DNBBreakpointList::FindByAddress (nub_addr_t addr) const
{
    const_iterator end = m_breakpoints.end();
    const_iterator pos = std::find_if(m_breakpoints.begin(), end,       // Search full range
                                      BreakpointAddressMatches(addr));  // Predicate
    if (pos != end)
        return &(*pos);

    return NULL;
}

bool
DNBBreakpointList::SetCallback(nub_break_t breakID, DNBCallbackBreakpointHit callback, void *callback_baton)
{
    DNBBreakpoint *bp = FindByID (breakID);
    if (bp)
    {
        bp->SetCallback(callback, callback_baton);
        return true;
    }
    return false;
}


void
DNBBreakpointList::Dump() const
{
    const_iterator pos;
    const_iterator end = m_breakpoints.end();
    for (pos = m_breakpoints.begin(); pos != end; ++pos)
        (*pos).Dump();
}


DNBBreakpoint *
DNBBreakpointList::GetByIndex (uint32_t i)
{
    iterator end = m_breakpoints.end();
    iterator pos;
    uint32_t curr_i = 0;
    for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
    {
        if (curr_i == i)
            return &(*pos);
    }
    return NULL;
}

const DNBBreakpoint *
DNBBreakpointList::GetByIndex (uint32_t i) const
{
    const_iterator end = m_breakpoints.end();
    const_iterator pos;
    uint32_t curr_i = 0;
    for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
    {
        if (curr_i == i)
            return &(*pos);
    }
    return NULL;
}

