//===-- SWIG Interface for SBBreakpoint -------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
namespace lldb {

%feature("docstring",
"Represents a logical breakpoint and its associated settings.

For example (from test/functionalities/breakpoint/breakpoint_ignore_count/
TestBreakpointIgnoreCount.py),::

    def breakpoint_ignore_count_python(self):
        '''Use Python APIs to set breakpoint ignore count.'''
        exe = os.path.join(os.getcwd(), 'a.out')

        # Create a target by the debugger.
        target = self.dbg.CreateTarget(exe)
        self.assertTrue(target, VALID_TARGET)

        # Now create a breakpoint on main.c by name 'c'.
        breakpoint = target.BreakpointCreateByName('c', 'a.out')
        self.assertTrue(breakpoint and
                        breakpoint.GetNumLocations() == 1,
                        VALID_BREAKPOINT)

        # Get the breakpoint location from breakpoint after we verified that,
        # indeed, it has one location.
        location = breakpoint.GetLocationAtIndex(0)
        self.assertTrue(location and
                        location.IsEnabled(),
                        VALID_BREAKPOINT_LOCATION)

        # Set the ignore count on the breakpoint location.
        location.SetIgnoreCount(2)
        self.assertTrue(location.GetIgnoreCount() == 2,
                        'SetIgnoreCount() works correctly')

        # Now launch the process, and do not stop at entry point.
        process = target.LaunchSimple(None, None, os.getcwd())
        self.assertTrue(process, PROCESS_IS_VALID)

        # Frame#0 should be on main.c:37, frame#1 should be on main.c:25, and
        # frame#2 should be on main.c:48.
        #lldbutil.print_stacktraces(process)
        from lldbutil import get_stopped_thread
        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
        self.assertTrue(thread != None, 'There should be a thread stopped due to breakpoint')
        frame0 = thread.GetFrameAtIndex(0)
        frame1 = thread.GetFrameAtIndex(1)
        frame2 = thread.GetFrameAtIndex(2)
        self.assertTrue(frame0.GetLineEntry().GetLine() == self.line1 and
                        frame1.GetLineEntry().GetLine() == self.line3 and
                        frame2.GetLineEntry().GetLine() == self.line4,
                        STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT)

        # The hit count for the breakpoint should be 3.
        self.assertTrue(breakpoint.GetHitCount() == 3)

        process.Continue()

SBBreakpoint supports breakpoint location iteration, for example,::

    for bl in breakpoint:
        print('breakpoint location load addr: %s' % hex(bl.GetLoadAddress()))
        print('breakpoint location condition: %s' % hex(bl.GetCondition()))

and rich comparison methods which allow the API program to use,::

    if aBreakpoint == bBreakpoint:
        ...

to compare two breakpoints for equality."
) SBBreakpoint;
class SBBreakpoint
{
public:

    SBBreakpoint ();

    SBBreakpoint (const lldb::SBBreakpoint& rhs);

    ~SBBreakpoint();

    bool operator==(const lldb::SBBreakpoint &rhs);

    bool operator!=(const lldb::SBBreakpoint &rhs);

    break_id_t
    GetID () const;

    bool
    IsValid() const;

    explicit operator bool() const;

    void
    ClearAllBreakpointSites ();

    lldb::SBTarget
    GetTarget() const;

    lldb::SBBreakpointLocation
    FindLocationByAddress (lldb::addr_t vm_addr);

    lldb::break_id_t
    FindLocationIDByAddress (lldb::addr_t vm_addr);

    lldb::SBBreakpointLocation
    FindLocationByID (lldb::break_id_t bp_loc_id);

    lldb::SBBreakpointLocation
    GetLocationAtIndex (uint32_t index);

    void
    SetEnabled (bool enable);

    bool
    IsEnabled ();

    void
    SetOneShot (bool one_shot);

    bool
    IsOneShot ();

    bool
    IsInternal ();

    uint32_t
    GetHitCount () const;

    void
    SetIgnoreCount (uint32_t count);

    uint32_t
    GetIgnoreCount () const;

    %feature("docstring", "
    The breakpoint stops only if the condition expression evaluates to true.") SetCondition;
    void
    SetCondition (const char *condition);

    %feature("docstring", "
    Get the condition expression for the breakpoint.") GetCondition;
    const char *
    GetCondition ();

    void SetAutoContinue(bool auto_continue);

    bool GetAutoContinue();

    void
    SetThreadID (lldb::tid_t sb_thread_id);

    lldb::tid_t
    GetThreadID ();

    void
    SetThreadIndex (uint32_t index);

    uint32_t
    GetThreadIndex() const;

    void
    SetThreadName (const char *thread_name);

    const char *
    GetThreadName () const;

    void
    SetQueueName (const char *queue_name);

    const char *
    GetQueueName () const;

    %feature("docstring", "
    Set the name of the script function to be called when the breakpoint is hit.") SetScriptCallbackFunction;
    void
    SetScriptCallbackFunction (const char *callback_function_name);

    %feature("docstring", "
    Set the name of the script function to be called when the breakpoint is hit.
    To use this variant, the function should take (frame, bp_loc, extra_args, internal_dict) and
    when the breakpoint is hit the extra_args will be passed to the callback function.") SetScriptCallbackFunction;
    SBError
    SetScriptCallbackFunction (const char *callback_function_name,
                               SBStructuredData &extra_args);

    %feature("docstring", "
    Provide the body for the script function to be called when the breakpoint is hit.
    The body will be wrapped in a function, which be passed two arguments:
    'frame' - which holds the bottom-most SBFrame of the thread that hit the breakpoint
    'bpno'  - which is the SBBreakpointLocation to which the callback was attached.

    The error parameter is currently ignored, but will at some point hold the Python
    compilation diagnostics.
    Returns true if the body compiles successfully, false if not.") SetScriptCallbackBody;
    SBError
    SetScriptCallbackBody (const char *script_body_text);

    void SetCommandLineCommands(SBStringList &commands);

    bool GetCommandLineCommands(SBStringList &commands);

    bool
    AddName (const char *new_name);

    SBError
    AddNameWithErrorHandling (const char *new_name);

    void
    RemoveName (const char *name_to_remove);

    bool
    MatchesName (const char *name);

    void
    GetNames (SBStringList &names);

    size_t
    GetNumResolvedLocations() const;

    size_t
    GetNumLocations() const;

    bool
    GetDescription (lldb::SBStream &description);

    bool
    GetDescription(lldb::SBStream &description, bool include_locations);

    // Can only be called from a ScriptedBreakpointResolver...
    SBError
    AddLocation(SBAddress &address);

    SBStructuredData SBBreakpoint::SerializeToStructuredData();

    static bool
    EventIsBreakpointEvent (const lldb::SBEvent &event);

    static lldb::BreakpointEventType
    GetBreakpointEventTypeFromEvent (const lldb::SBEvent& event);

    static lldb::SBBreakpoint
    GetBreakpointFromEvent (const lldb::SBEvent& event);

    static lldb::SBBreakpointLocation
    GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx);

    static uint32_t
    GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event_sp);

    bool
    IsHardware ();

    STRING_EXTENSION(SBBreakpoint)

#ifdef SWIGPYTHON
    %pythoncode %{

        class locations_access(object):
            '''A helper object that will lazily hand out locations for a breakpoint when supplied an index.'''
            def __init__(self, sbbreakpoint):
                self.sbbreakpoint = sbbreakpoint

            def __len__(self):
                if self.sbbreakpoint:
                    return int(self.sbbreakpoint.GetNumLocations())
                return 0

            def __getitem__(self, key):
                if type(key) is int and key < len(self):
                    return self.sbbreakpoint.GetLocationAtIndex(key)
                return None

        def get_locations_access_object(self):
            '''An accessor function that returns a locations_access() object which allows lazy location access from a lldb.SBBreakpoint object.'''
            return self.locations_access (self)

        def get_breakpoint_location_list(self):
            '''An accessor function that returns a list() that contains all locations in a lldb.SBBreakpoint object.'''
            locations = []
            accessor = self.get_locations_access_object()
            for idx in range(len(accessor)):
                locations.append(accessor[idx])
            return locations

        def __iter__(self):
            '''Iterate over all breakpoint locations in a lldb.SBBreakpoint
            object.'''
            return lldb_iter(self, 'GetNumLocations', 'GetLocationAtIndex')

        def __len__(self):
            '''Return the number of breakpoint locations in a lldb.SBBreakpoint
            object.'''
            return self.GetNumLocations()

        locations = property(get_breakpoint_location_list, None, doc='''A read only property that returns a list() of lldb.SBBreakpointLocation objects for this breakpoint.''')
        location = property(get_locations_access_object, None, doc='''A read only property that returns an object that can access locations by index (not location ID) (location = bkpt.location[12]).''')
        id = property(GetID, None, doc='''A read only property that returns the ID of this breakpoint.''')
        enabled = property(IsEnabled, SetEnabled, doc='''A read/write property that configures whether this breakpoint is enabled or not.''')
        one_shot = property(IsOneShot, SetOneShot, doc='''A read/write property that configures whether this breakpoint is one-shot (deleted when hit) or not.''')
        num_locations = property(GetNumLocations, None, doc='''A read only property that returns the count of locations of this breakpoint.''')
    %}
#endif


};

class SBBreakpointListImpl;


%feature("docstring",
"Represents a list of :py:class:`SBBreakpoint`."
) SBBreakpointList;
class LLDB_API SBBreakpointList
{
public:
  SBBreakpointList(SBTarget &target);

  ~SBBreakpointList();

  size_t GetSize() const;

  SBBreakpoint
  GetBreakpointAtIndex(size_t idx);

  SBBreakpoint
  FindBreakpointByID(lldb::break_id_t);

  void Append(const SBBreakpoint &sb_bkpt);

  bool AppendIfUnique(const SBBreakpoint &sb_bkpt);

  void AppendByID (lldb::break_id_t id);

  void Clear();
private:
  std::shared_ptr<SBBreakpointListImpl> m_opaque_sp;
};

} // namespace lldb
