//===-- SWIG Interface for SBValue ------------------------------*- 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 the value of a variable, a register, or an expression.

SBValue supports iteration through its child, which in turn is represented
as an SBValue.  For example, we can get the general purpose registers of a
frame as an SBValue, and iterate through all the registers,::

    registerSet = frame.registers # Returns an SBValueList.
    for regs in registerSet:
        if 'general purpose registers' in regs.name.lower():
            GPRs = regs
            break

    print('%s (number of children = %d):' % (GPRs.name, GPRs.num_children))
    for reg in GPRs:
        print('Name: ', reg.name, ' Value: ', reg.value)

produces the output: ::

    General Purpose Registers (number of children = 21):
    Name:  rax  Value:  0x0000000100000c5c
    Name:  rbx  Value:  0x0000000000000000
    Name:  rcx  Value:  0x00007fff5fbffec0
    Name:  rdx  Value:  0x00007fff5fbffeb8
    Name:  rdi  Value:  0x0000000000000001
    Name:  rsi  Value:  0x00007fff5fbffea8
    Name:  rbp  Value:  0x00007fff5fbffe80
    Name:  rsp  Value:  0x00007fff5fbffe60
    Name:  r8  Value:  0x0000000008668682
    Name:  r9  Value:  0x0000000000000000
    Name:  r10  Value:  0x0000000000001200
    Name:  r11  Value:  0x0000000000000206
    Name:  r12  Value:  0x0000000000000000
    Name:  r13  Value:  0x0000000000000000
    Name:  r14  Value:  0x0000000000000000
    Name:  r15  Value:  0x0000000000000000
    Name:  rip  Value:  0x0000000100000dae
    Name:  rflags  Value:  0x0000000000000206
    Name:  cs  Value:  0x0000000000000027
    Name:  fs  Value:  0x0000000000000010
    Name:  gs  Value:  0x0000000000000048

See also linked_list_iter() for another perspective on how to iterate through an
SBValue instance which interprets the value object as representing the head of a
linked list."
) SBValue;
class SBValue
{
public:
    SBValue ();

    SBValue (const SBValue &rhs);

    ~SBValue ();

    bool
    IsValid();

    explicit operator bool() const;

    void
    Clear();

    SBError
    GetError();

    lldb::user_id_t
    GetID ();

    const char *
    GetName();

    const char *
    GetTypeName ();

    const char *
    GetDisplayTypeName ();

    size_t
    GetByteSize ();

    bool
    IsInScope ();

    lldb::Format
    GetFormat ();

    void
    SetFormat (lldb::Format format);

    const char *
    GetValue ();

    int64_t
    GetValueAsSigned(SBError& error, int64_t fail_value=0);

    uint64_t
    GetValueAsUnsigned(SBError& error, uint64_t fail_value=0);

    int64_t
    GetValueAsSigned(int64_t fail_value=0);

    uint64_t
    GetValueAsUnsigned(uint64_t fail_value=0);

    ValueType
    GetValueType ();

    bool
    GetValueDidChange ();

    const char *
    GetSummary ();

    const char *
    GetSummary (lldb::SBStream& stream,
                lldb::SBTypeSummaryOptions& options);

    const char *
    GetObjectDescription ();

    lldb::SBValue
    GetDynamicValue (lldb::DynamicValueType use_dynamic);

    lldb::SBValue
    GetStaticValue ();

    lldb::SBValue
    GetNonSyntheticValue ();

    lldb::DynamicValueType
    GetPreferDynamicValue ();

    void
    SetPreferDynamicValue (lldb::DynamicValueType use_dynamic);

    bool
    GetPreferSyntheticValue ();

    void
    SetPreferSyntheticValue (bool use_synthetic);

    bool
    IsDynamic();

    bool
    IsSynthetic ();

    bool
    IsSyntheticChildrenGenerated ();

    void
    SetSyntheticChildrenGenerated (bool);

    const char *
    GetLocation ();

    bool
    SetValueFromCString (const char *value_str);

    bool
    SetValueFromCString (const char *value_str, lldb::SBError& error);

    lldb::SBTypeFormat
    GetTypeFormat ();

    lldb::SBTypeSummary
    GetTypeSummary ();

    lldb::SBTypeFilter
    GetTypeFilter ();

    lldb::SBTypeSynthetic
    GetTypeSynthetic ();

    lldb::SBValue
    GetChildAtIndex (uint32_t idx);

    %feature("docstring", "
    Get a child value by index from a value.

    Structs, unions, classes, arrays and pointers have child
    values that can be access by index.

    Structs and unions access child members using a zero based index
    for each child member. For

    Classes reserve the first indexes for base classes that have
    members (empty base classes are omitted), and all members of the
    current class will then follow the base classes.

    Pointers differ depending on what they point to. If the pointer
    points to a simple type, the child at index zero
    is the only child value available, unless synthetic_allowed
    is true, in which case the pointer will be used as an array
    and can create 'synthetic' child values using positive or
    negative indexes. If the pointer points to an aggregate type
    (an array, class, union, struct), then the pointee is
    transparently skipped and any children are going to be the indexes
    of the child values within the aggregate type. For example if
    we have a 'Point' type and we have a SBValue that contains a
    pointer to a 'Point' type, then the child at index zero will be
    the 'x' member, and the child at index 1 will be the 'y' member
    (the child at index zero won't be a 'Point' instance).

    If you actually need an SBValue that represents the type pointed
    to by a SBValue for which GetType().IsPointeeType() returns true,
    regardless of the pointee type, you can do that with the SBValue.Dereference
    method (or the equivalent deref property).

    Arrays have a preset number of children that can be accessed by
    index and will returns invalid child values for indexes that are
    out of bounds unless the synthetic_allowed is true. In this
    case the array can create 'synthetic' child values for indexes
    that aren't in the array bounds using positive or negative
    indexes.

    @param[in] idx
        The index of the child value to get

    @param[in] use_dynamic
        An enumeration that specifies whether to get dynamic values,
        and also if the target can be run to figure out the dynamic
        type of the child value.

    @param[in] synthetic_allowed
        If true, then allow child values to be created by index
        for pointers and arrays for indexes that normally wouldn't
        be allowed.

    @return
        A new SBValue object that represents the child member value.") GetChildAtIndex;
    lldb::SBValue
    GetChildAtIndex (uint32_t idx,
                     lldb::DynamicValueType use_dynamic,
                     bool can_create_synthetic);

    lldb::SBValue
    CreateChildAtOffset (const char *name, uint32_t offset, lldb::SBType type);

    lldb::SBValue
    SBValue::Cast (lldb::SBType type);

    lldb::SBValue
    CreateValueFromExpression (const char *name, const char* expression);

    lldb::SBValue
    CreateValueFromExpression (const char *name, const char* expression, SBExpressionOptions &options);

    lldb::SBValue
    CreateValueFromAddress(const char* name, lldb::addr_t address, lldb::SBType type);

  lldb::SBValue
  CreateValueFromData (const char* name,
                       lldb::SBData data,
                       lldb::SBType type);

    lldb::SBType
    GetType();

    %feature("docstring", "
    Returns the child member index.

    Matches children of this object only and will match base classes and
    member names if this is a clang typed object.

    @param[in] name
        The name of the child value to get

    @return
        An index to the child member value.") GetIndexOfChildWithName;
    uint32_t
    GetIndexOfChildWithName (const char *name);

    lldb::SBValue
    GetChildMemberWithName (const char *name);

    %feature("docstring", "
    Returns the child member value.

    Matches child members of this object and child members of any base
    classes.

    @param[in] name
        The name of the child value to get

    @param[in] use_dynamic
        An enumeration that specifies whether to get dynamic values,
        and also if the target can be run to figure out the dynamic
        type of the child value.

    @return
        A new SBValue object that represents the child member value.") GetChildMemberWithName;
    lldb::SBValue
    GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dynamic);

    %feature("docstring", "Expands nested expressions like .a->b[0].c[1]->d."
    ) GetValueForExpressionPath;
    lldb::SBValue
    GetValueForExpressionPath(const char* expr_path);

    lldb::SBDeclaration
    GetDeclaration ();

    bool
    MightHaveChildren ();

    bool
    IsRuntimeSupportValue ();

    uint32_t
    GetNumChildren ();

    %feature("doctstring", "
    Returns the number for children.

    @param[in] max
        If max is less the lldb.UINT32_MAX, then the returned value is
        capped to max.

    @return
        An integer value capped to the argument max.") GetNumChildren;
    uint32_t
    GetNumChildren (uint32_t max);

    void *
    GetOpaqueType();

    lldb::SBValue
    Dereference ();

    lldb::SBValue
    AddressOf();

    bool
    TypeIsPointerType ();

    lldb::SBTarget
    GetTarget();

    lldb::SBProcess
    GetProcess();

    lldb::SBThread
    GetThread();

    lldb::SBFrame
    GetFrame();

    %feature("docstring", "
    Find and watch a variable.
    It returns an SBWatchpoint, which may be invalid.") Watch;
    lldb::SBWatchpoint
    Watch (bool resolve_location, bool read, bool write, SBError &error);

    %feature("docstring", "
    Find and watch the location pointed to by a variable.
    It returns an SBWatchpoint, which may be invalid.") WatchPointee;
    lldb::SBWatchpoint
    WatchPointee (bool resolve_location, bool read, bool write, SBError &error);

    bool
    GetDescription (lldb::SBStream &description);

    bool
    GetExpressionPath (lldb::SBStream &description);

  %feature("docstring", "
    Get an SBData wrapping what this SBValue points to.

    This method will dereference the current SBValue, if its
    data type is a ``T\*`` or ``T[]``, and extract ``item_count`` elements
    of type ``T`` from it, copying their contents in an :py:class:`SBData`.

    :param item_idx: The index of the first item to retrieve. For an array
        this is equivalent to array[item_idx], for a pointer
        to ``\*(pointer + item_idx)``. In either case, the measurement
        unit for item_idx is the ``sizeof(T)`` rather than the byte
    :param item_count: How many items should be copied into the output. By default
        only one item is copied, but more can be asked for.
    :return: The contents of the copied items on success. An empty :py:class:`SBData` otherwise.
    :rtype: SBData
    ") GetPointeeData;
  lldb::SBData
  GetPointeeData (uint32_t item_idx = 0,
          uint32_t item_count = 1);

    %feature("docstring", "
    Get an SBData wrapping the contents of this SBValue.

    This method will read the contents of this object in memory
    and copy them into an SBData for future use.

    @return
        An SBData with the contents of this SBValue, on success.
        An empty SBData otherwise.") GetData;
    lldb::SBData
    GetData ();

    bool
    SetData (lldb::SBData &data, lldb::SBError& error);

  lldb::addr_t
  GetLoadAddress();

  lldb::SBAddress
  GetAddress();

    lldb::SBValue
    Persist ();

    %feature("docstring", "Returns an expression path for this value."
    ) GetExpressionPath;
    bool
    GetExpressionPath (lldb::SBStream &description, bool qualify_cxx_base_classes);

    lldb::SBValue
    EvaluateExpression(const char *expr) const;

    lldb::SBValue
    EvaluateExpression(const char *expr,
                       const SBExpressionOptions &options) const;

    lldb::SBValue
    EvaluateExpression(const char *expr,
                       const SBExpressionOptions &options,
                       const char *name) const;

    STRING_EXTENSION(SBValue)

#ifdef SWIGPYTHON
    %pythoncode %{
        def __get_dynamic__ (self):
            '''Helper function for the "SBValue.dynamic" property.'''
            return self.GetDynamicValue (eDynamicCanRunTarget)

        class children_access(object):
            '''A helper object that will lazily hand out thread for a process when supplied an index.'''

            def __init__(self, sbvalue):
                self.sbvalue = sbvalue

            def __len__(self):
                if self.sbvalue:
                    return int(self.sbvalue.GetNumChildren())
                return 0

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

        def get_child_access_object(self):
            '''An accessor function that returns a children_access() object which allows lazy member variable access from a lldb.SBValue object.'''
            return self.children_access (self)

        def get_value_child_list(self):
            '''An accessor function that returns a list() that contains all children in a lldb.SBValue object.'''
            children = []
            accessor = self.get_child_access_object()
            for idx in range(len(accessor)):
                children.append(accessor[idx])
            return children

        def __iter__(self):
            '''Iterate over all child values of a lldb.SBValue object.'''
            return lldb_iter(self, 'GetNumChildren', 'GetChildAtIndex')

        def __len__(self):
            '''Return the number of child values of a lldb.SBValue object.'''
            return self.GetNumChildren()

        children = property(get_value_child_list, None, doc='''A read only property that returns a list() of lldb.SBValue objects for the children of the value.''')
        child = property(get_child_access_object, None, doc='''A read only property that returns an object that can access children of a variable by index (child_value = value.children[12]).''')
        name = property(GetName, None, doc='''A read only property that returns the name of this value as a string.''')
        type = property(GetType, None, doc='''A read only property that returns a lldb.SBType object that represents the type for this value.''')
        size = property(GetByteSize, None, doc='''A read only property that returns the size in bytes of this value.''')
        is_in_scope = property(IsInScope, None, doc='''A read only property that returns a boolean value that indicates whether this value is currently lexically in scope.''')
        format = property(GetName, SetFormat, doc='''A read/write property that gets/sets the format used for lldb.SBValue().GetValue() for this value. See enumerations that start with "lldb.eFormat".''')
        value = property(GetValue, SetValueFromCString, doc='''A read/write property that gets/sets value from a string.''')
        value_type = property(GetValueType, None, doc='''A read only property that returns an lldb enumeration value (see enumerations that start with "lldb.eValueType") that represents the type of this value (local, argument, global, register, etc.).''')
        changed = property(GetValueDidChange, None, doc='''A read only property that returns a boolean value that indicates if this value has changed since it was last updated.''')
        data = property(GetData, None, doc='''A read only property that returns an lldb object (lldb.SBData) that represents the bytes that make up the value for this object.''')
        load_addr = property(GetLoadAddress, None, doc='''A read only property that returns the load address of this value as an integer.''')
        addr = property(GetAddress, None, doc='''A read only property that returns an lldb.SBAddress that represents the address of this value if it is in memory.''')
        deref = property(Dereference, None, doc='''A read only property that returns an lldb.SBValue that is created by dereferencing this value.''')
        address_of = property(AddressOf, None, doc='''A read only property that returns an lldb.SBValue that represents the address-of this value.''')
        error = property(GetError, None, doc='''A read only property that returns the lldb.SBError that represents the error from the last time the variable value was calculated.''')
        summary = property(GetSummary, None, doc='''A read only property that returns the summary for this value as a string''')
        description = property(GetObjectDescription, None, doc='''A read only property that returns the language-specific description of this value as a string''')
        dynamic = property(__get_dynamic__, None, doc='''A read only property that returns an lldb.SBValue that is created by finding the dynamic type of this value.''')
        location = property(GetLocation, None, doc='''A read only property that returns the location of this value as a string.''')
        target = property(GetTarget, None, doc='''A read only property that returns the lldb.SBTarget that this value is associated with.''')
        process = property(GetProcess, None, doc='''A read only property that returns the lldb.SBProcess that this value is associated with, the returned value might be invalid and should be tested.''')
        thread = property(GetThread, None, doc='''A read only property that returns the lldb.SBThread that this value is associated with, the returned value might be invalid and should be tested.''')
        frame = property(GetFrame, None, doc='''A read only property that returns the lldb.SBFrame that this value is associated with, the returned value might be invalid and should be tested.''')
        num_children = property(GetNumChildren, None, doc='''A read only property that returns the number of child lldb.SBValues that this value has.''')
        unsigned = property(GetValueAsUnsigned, None, doc='''A read only property that returns the value of this SBValue as an usigned integer.''')
        signed = property(GetValueAsSigned, None, doc='''A read only property that returns the value of this SBValue as a signed integer.''')

        def get_expr_path(self):
            s = SBStream()
            self.GetExpressionPath (s)
            return s.GetData()

        path = property(get_expr_path, None, doc='''A read only property that returns the expression path that one can use to reach this value in an expression.''')

        def synthetic_child_from_expression(self, name, expr, options=None):
            if options is None: options = lldb.SBExpressionOptions()
            child = self.CreateValueFromExpression(name, expr, options)
            child.SetSyntheticChildrenGenerated(True)
            return child

        def synthetic_child_from_data(self, name, data, type):
            child = self.CreateValueFromData(name, data, type)
            child.SetSyntheticChildrenGenerated(True)
            return child

        def synthetic_child_from_address(self, name, addr, type):
            child = self.CreateValueFromAddress(name, addr, type)
            child.SetSyntheticChildrenGenerated(True)
            return child

        def __eol_test(val):
            """Default function for end of list test takes an SBValue object.

            Return True if val is invalid or it corresponds to a null pointer.
            Otherwise, return False.
            """
            if not val or val.GetValueAsUnsigned() == 0:
                return True
            else:
                return False

        # ==================================================
        # Iterator for lldb.SBValue treated as a linked list
        # ==================================================
        def linked_list_iter(self, next_item_name, end_of_list_test=__eol_test):
            """Generator adaptor to support iteration for SBValue as a linked list.

            linked_list_iter() is a special purpose iterator to treat the SBValue as
            the head of a list data structure, where you specify the child member
            name which points to the next item on the list and you specify the
            end-of-list test function which takes an SBValue for an item and returns
            True if EOL is reached and False if not.

            linked_list_iter() also detects infinite loop and bails out early.

            The end_of_list_test arg, if omitted, defaults to the __eol_test
            function above.

            For example,

            # Get Frame #0.
            ...

            # Get variable 'task_head'.
            task_head = frame0.FindVariable('task_head')
            ...

            for t in task_head.linked_list_iter('next'):
                print t
            """
            if end_of_list_test(self):
                return
            item = self
            visited = set()
            try:
                while not end_of_list_test(item) and not item.GetValueAsUnsigned() in visited:
                    visited.add(item.GetValueAsUnsigned())
                    yield item
                    # Prepare for the next iteration.
                    item = item.GetChildMemberWithName(next_item_name)
            except:
                # Exception occurred.  Stop the generator.
                pass

            return
    %}
#endif

};

} // namespace lldb
