import lldb
import lldb.formatters.Logger

# libcxx STL formatters for LLDB
# These formatters are based upon the implementation of libc++ that
# ships with current releases of OS X - They will not work for other implementations
# of the standard C++ library - and they are bound to use the
# libc++-specific namespace

# the std::string summary is just an example for your convenience
# the actual summary that LLDB uses is C++ code inside the debugger's own core

# this could probably be made more efficient but since it only reads a handful of bytes at a time
# we probably don't need to worry too much about this for the time being


def make_string(F, L):
    strval = ''
    G = F.GetData().uint8
    for X in range(L):
        V = G[X]
        if V == 0:
            break
        strval = strval + chr(V % 256)
    return '"' + strval + '"'

# if we ever care about big-endian, these two functions might need to change


def is_short_string(value):
    return True if (value & 1) == 0 else False


def extract_short_size(value):
    return ((value >> 1) % 256)

# some of the members of libc++ std::string are anonymous or have internal names that convey
# no external significance - we access them by index since this saves a name lookup that would add
# no information for readers of the code, but when possible try to use
# meaningful variable names


def stdstring_SummaryProvider(valobj, dict):
    logger = lldb.formatters.Logger.Logger()
    r = valobj.GetChildAtIndex(0)
    B = r.GetChildAtIndex(0)
    first = B.GetChildAtIndex(0)
    D = first.GetChildAtIndex(0)
    l = D.GetChildAtIndex(0)
    s = D.GetChildAtIndex(1)
    D20 = s.GetChildAtIndex(0)
    size_mode = D20.GetChildAtIndex(0).GetValueAsUnsigned(0)
    if is_short_string(size_mode):
        size = extract_short_size(size_mode)
        return make_string(s.GetChildAtIndex(1), size)
    else:
        data_ptr = l.GetChildAtIndex(2)
        size_vo = l.GetChildAtIndex(1)
        # the NULL terminator must be accounted for
        size = size_vo.GetValueAsUnsigned(0) + 1
        if size <= 1 or size is None:  # should never be the case
            return '""'
        try:
            data = data_ptr.GetPointeeData(0, size)
        except:
            return '""'
        error = lldb.SBError()
        strval = data.GetString(error, 0)
        if error.Fail():
            return '<error:' + error.GetCString() + '>'
        else:
            return '"' + strval + '"'


class stdvector_SynthProvider:

    def __init__(self, valobj, dict):
        logger = lldb.formatters.Logger.Logger()
        self.valobj = valobj

    def num_children(self):
        logger = lldb.formatters.Logger.Logger()
        try:
            start_val = self.start.GetValueAsUnsigned(0)
            finish_val = self.finish.GetValueAsUnsigned(0)
            # Before a vector has been constructed, it will contain bad values
            # so we really need to be careful about the length we return since
            # uninitialized data can cause us to return a huge number. We need
            # to also check for any of the start, finish or end of storage values
            # being zero (NULL). If any are, then this vector has not been
            # initialized yet and we should return zero

            # Make sure nothing is NULL
            if start_val == 0 or finish_val == 0:
                return 0
            # Make sure start is less than finish
            if start_val >= finish_val:
                return 0

            num_children = (finish_val - start_val)
            if (num_children % self.data_size) != 0:
                return 0
            else:
                num_children = num_children / self.data_size
            return num_children
        except:
            return 0

    def get_child_index(self, name):
        logger = lldb.formatters.Logger.Logger()
        try:
            return int(name.lstrip('[').rstrip(']'))
        except:
            return -1

    def get_child_at_index(self, index):
        logger = lldb.formatters.Logger.Logger()
        logger >> "Retrieving child " + str(index)
        if index < 0:
            return None
        if index >= self.num_children():
            return None
        try:
            offset = index * self.data_size
            return self.start.CreateChildAtOffset(
                '[' + str(index) + ']', offset, self.data_type)
        except:
            return None

    def update(self):
        logger = lldb.formatters.Logger.Logger()
        try:
            self.start = self.valobj.GetChildMemberWithName('__begin_')
            self.finish = self.valobj.GetChildMemberWithName('__end_')
            # the purpose of this field is unclear, but it is the only field whose type is clearly T* for a vector<T>
            # if this ends up not being correct, we can use the APIs to get at
            # template arguments
            data_type_finder = self.valobj.GetChildMemberWithName(
                '__end_cap_').GetChildMemberWithName('__first_')
            self.data_type = data_type_finder.GetType().GetPointeeType()
            self.data_size = self.data_type.GetByteSize()
        except:
            pass

    def has_children(self):
        return True

# Just an example: the actual summary is produced by a summary string:
# size=${svar%#}


def stdvector_SummaryProvider(valobj, dict):
    prov = stdvector_SynthProvider(valobj, None)
    return 'size=' + str(prov.num_children())


class stdlist_entry:

    def __init__(self, entry):
        logger = lldb.formatters.Logger.Logger()
        self.entry = entry

    def _next_impl(self):
        logger = lldb.formatters.Logger.Logger()
        return stdlist_entry(self.entry.GetChildMemberWithName('__next_'))

    def _prev_impl(self):
        logger = lldb.formatters.Logger.Logger()
        return stdlist_entry(self.entry.GetChildMemberWithName('__prev_'))

    def _value_impl(self):
        logger = lldb.formatters.Logger.Logger()
        return self.entry.GetValueAsUnsigned(0)

    def _isnull_impl(self):
        logger = lldb.formatters.Logger.Logger()
        return self._value_impl() == 0

    def _sbvalue_impl(self):
        logger = lldb.formatters.Logger.Logger()
        return self.entry

    next = property(_next_impl, None)
    value = property(_value_impl, None)
    is_null = property(_isnull_impl, None)
    sbvalue = property(_sbvalue_impl, None)


class stdlist_iterator:

    def increment_node(self, node):
        logger = lldb.formatters.Logger.Logger()
        if node.is_null:
            return None
        return node.next

    def __init__(self, node):
        logger = lldb.formatters.Logger.Logger()
        # we convert the SBValue to an internal node object on entry
        self.node = stdlist_entry(node)

    def value(self):
        logger = lldb.formatters.Logger.Logger()
        return self.node.sbvalue  # and return the SBValue back on exit

    def next(self):
        logger = lldb.formatters.Logger.Logger()
        node = self.increment_node(self.node)
        if node is not None and node.sbvalue.IsValid() and not(node.is_null):
            self.node = node
            return self.value()
        else:
            return None

    def advance(self, N):
        logger = lldb.formatters.Logger.Logger()
        if N < 0:
            return None
        if N == 0:
            return self.value()
        if N == 1:
            return self.next()
        while N > 0:
            self.next()
            N = N - 1
        return self.value()


class stdlist_SynthProvider:

    def __init__(self, valobj, dict):
        logger = lldb.formatters.Logger.Logger()
        self.valobj = valobj
        self.count = None

    def next_node(self, node):
        logger = lldb.formatters.Logger.Logger()
        return node.GetChildMemberWithName('__next_')

    def value(self, node):
        logger = lldb.formatters.Logger.Logger()
        return node.GetValueAsUnsigned()

    # Floyd's cycle-finding algorithm
    # try to detect if this list has a loop
    def has_loop(self):
        global _list_uses_loop_detector
        logger = lldb.formatters.Logger.Logger()
        if not _list_uses_loop_detector:
            logger >> "Asked not to use loop detection"
            return False
        slow = stdlist_entry(self.head)
        fast1 = stdlist_entry(self.head)
        fast2 = stdlist_entry(self.head)
        while slow.next.value != self.node_address:
            slow_value = slow.value
            fast1 = fast2.next
            fast2 = fast1.next
            if fast1.value == slow_value or fast2.value == slow_value:
                return True
            slow = slow.next
        return False

    def num_children(self):
        global _list_capping_size
        logger = lldb.formatters.Logger.Logger()
        if self.count is None:
            self.count = self.num_children_impl()
            if self.count > _list_capping_size:
                self.count = _list_capping_size
        return self.count

    def num_children_impl(self):
        global _list_capping_size
        logger = lldb.formatters.Logger.Logger()
        try:
            next_val = self.head.GetValueAsUnsigned(0)
            prev_val = self.tail.GetValueAsUnsigned(0)
            # After a std::list has been initialized, both next and prev will
            # be non-NULL
            if next_val == 0 or prev_val == 0:
                return 0
            if next_val == self.node_address:
                return 0
            if next_val == prev_val:
                return 1
            if self.has_loop():
                return 0
            size = 2
            current = stdlist_entry(self.head)
            while current.next.value != self.node_address:
                size = size + 1
                current = current.next
                if size > _list_capping_size:
                    return _list_capping_size
            return (size - 1)
        except:
            return 0

    def get_child_index(self, name):
        logger = lldb.formatters.Logger.Logger()
        try:
            return int(name.lstrip('[').rstrip(']'))
        except:
            return -1

    def get_child_at_index(self, index):
        logger = lldb.formatters.Logger.Logger()
        logger >> "Fetching child " + str(index)
        if index < 0:
            return None
        if index >= self.num_children():
            return None
        try:
            current = stdlist_iterator(self.head)
            current = current.advance(index)
            # we do not return __value_ because then all our children would be named __value_
            # we need to make a copy of __value__ with the right name -
            # unfortunate
            obj = current.GetChildMemberWithName('__value_')
            obj_data = obj.GetData()
            return self.valobj.CreateValueFromData(
                '[' + str(index) + ']', obj_data, self.data_type)
        except:
            return None

    def extract_type(self):
        logger = lldb.formatters.Logger.Logger()
        list_type = self.valobj.GetType().GetUnqualifiedType()
        if list_type.IsReferenceType():
            list_type = list_type.GetDereferencedType()
        if list_type.GetNumberOfTemplateArguments() > 0:
            data_type = list_type.GetTemplateArgumentType(0)
        else:
            data_type = None
        return data_type

    def update(self):
        logger = lldb.formatters.Logger.Logger()
        self.count = None
        try:
            impl = self.valobj.GetChildMemberWithName('__end_')
            self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0)
            self.head = impl.GetChildMemberWithName('__next_')
            self.tail = impl.GetChildMemberWithName('__prev_')
            self.data_type = self.extract_type()
            self.data_size = self.data_type.GetByteSize()
        except:
            pass

    def has_children(self):
        return True


# Just an example: the actual summary is produced by a summary string:
# size=${svar%#}
def stdlist_SummaryProvider(valobj, dict):
    prov = stdlist_SynthProvider(valobj, None)
    return 'size=' + str(prov.num_children())

# a tree node - this class makes the syntax in the actual iterator nicer
# to read and maintain


class stdmap_iterator_node:

    def _left_impl(self):
        logger = lldb.formatters.Logger.Logger()
        return stdmap_iterator_node(
            self.node.GetChildMemberWithName("__left_"))

    def _right_impl(self):
        logger = lldb.formatters.Logger.Logger()
        return stdmap_iterator_node(
            self.node.GetChildMemberWithName("__right_"))

    def _parent_impl(self):
        logger = lldb.formatters.Logger.Logger()
        return stdmap_iterator_node(
            self.node.GetChildMemberWithName("__parent_"))

    def _value_impl(self):
        logger = lldb.formatters.Logger.Logger()
        return self.node.GetValueAsUnsigned(0)

    def _sbvalue_impl(self):
        logger = lldb.formatters.Logger.Logger()
        return self.node

    def _null_impl(self):
        logger = lldb.formatters.Logger.Logger()
        return self.value == 0

    def __init__(self, node):
        logger = lldb.formatters.Logger.Logger()
        self.node = node

    left = property(_left_impl, None)
    right = property(_right_impl, None)
    parent = property(_parent_impl, None)
    value = property(_value_impl, None)
    is_null = property(_null_impl, None)
    sbvalue = property(_sbvalue_impl, None)

# a Python implementation of the tree iterator used by libc++


class stdmap_iterator:

    def tree_min(self, x):
        logger = lldb.formatters.Logger.Logger()
        steps = 0
        if x.is_null:
            return None
        while (not x.left.is_null):
            x = x.left
            steps += 1
            if steps > self.max_count:
                logger >> "Returning None - we overflowed"
                return None
        return x

    def tree_max(self, x):
        logger = lldb.formatters.Logger.Logger()
        if x.is_null:
            return None
        while (not x.right.is_null):
            x = x.right
        return x

    def tree_is_left_child(self, x):
        logger = lldb.formatters.Logger.Logger()
        if x.is_null:
            return None
        return True if x.value == x.parent.left.value else False

    def increment_node(self, node):
        logger = lldb.formatters.Logger.Logger()
        if node.is_null:
            return None
        if not node.right.is_null:
            return self.tree_min(node.right)
        steps = 0
        while (not self.tree_is_left_child(node)):
            steps += 1
            if steps > self.max_count:
                logger >> "Returning None - we overflowed"
                return None
            node = node.parent
        return node.parent

    def __init__(self, node, max_count=0):
        logger = lldb.formatters.Logger.Logger()
        # we convert the SBValue to an internal node object on entry
        self.node = stdmap_iterator_node(node)
        self.max_count = max_count

    def value(self):
        logger = lldb.formatters.Logger.Logger()
        return self.node.sbvalue  # and return the SBValue back on exit

    def next(self):
        logger = lldb.formatters.Logger.Logger()
        node = self.increment_node(self.node)
        if node is not None and node.sbvalue.IsValid() and not(node.is_null):
            self.node = node
            return self.value()
        else:
            return None

    def advance(self, N):
        logger = lldb.formatters.Logger.Logger()
        if N < 0:
            return None
        if N == 0:
            return self.value()
        if N == 1:
            return self.next()
        while N > 0:
            if self.next() is None:
                return None
            N = N - 1
        return self.value()


class stdmap_SynthProvider:

    def __init__(self, valobj, dict):
        logger = lldb.formatters.Logger.Logger()
        self.valobj = valobj
        self.pointer_size = self.valobj.GetProcess().GetAddressByteSize()
        self.count = None

    def update(self):
        logger = lldb.formatters.Logger.Logger()
        self.count = None
        try:
            # we will set this to True if we find out that discovering a node in the map takes more steps than the overall size of the RB tree
            # if this gets set to True, then we will merrily return None for
            # any child from that moment on
            self.garbage = False
            self.tree = self.valobj.GetChildMemberWithName('__tree_')
            self.root_node = self.tree.GetChildMemberWithName('__begin_node_')
            # this data is either lazily-calculated, or cannot be inferred at this moment
            # we still need to mark it as None, meaning "please set me ASAP"
            self.data_type = None
            self.data_size = None
            self.skip_size = None
        except:
            pass

    def num_children(self):
        global _map_capping_size
        logger = lldb.formatters.Logger.Logger()
        if self.count is None:
            self.count = self.num_children_impl()
            if self.count > _map_capping_size:
                self.count = _map_capping_size
        return self.count

    def num_children_impl(self):
        logger = lldb.formatters.Logger.Logger()
        try:
            return self.valobj.GetChildMemberWithName('__tree_').GetChildMemberWithName(
                '__pair3_').GetChildMemberWithName('__first_').GetValueAsUnsigned()
        except:
            return 0

    def has_children(self):
        return True

    def get_data_type(self):
        logger = lldb.formatters.Logger.Logger()
        if self.data_type is None or self.data_size is None:
            if self.num_children() == 0:
                return False
            deref = self.root_node.Dereference()
            if not(deref.IsValid()):
                return False
            value = deref.GetChildMemberWithName('__value_')
            if not(value.IsValid()):
                return False
            self.data_type = value.GetType()
            self.data_size = self.data_type.GetByteSize()
            self.skip_size = None
            return True
        else:
            return True

    def get_value_offset(self, node):
        logger = lldb.formatters.Logger.Logger()
        if self.skip_size is None:
            node_type = node.GetType()
            fields_count = node_type.GetNumberOfFields()
            for i in range(fields_count):
                field = node_type.GetFieldAtIndex(i)
                if field.GetName() == '__value_':
                    self.skip_size = field.GetOffsetInBytes()
                    break
        return (self.skip_size is not None)

    def get_child_index(self, name):
        logger = lldb.formatters.Logger.Logger()
        try:
            return int(name.lstrip('[').rstrip(']'))
        except:
            return -1

    def get_child_at_index(self, index):
        logger = lldb.formatters.Logger.Logger()
        logger >> "Retrieving child " + str(index)
        if index < 0:
            return None
        if index >= self.num_children():
            return None
        if self.garbage:
            logger >> "Returning None since this tree is garbage"
            return None
        try:
            iterator = stdmap_iterator(
                self.root_node, max_count=self.num_children())
            # the debug info for libc++ std::map is such that __begin_node_ has a very nice and useful type
            # out of which we can grab the information we need - every other node has a less informative
            # type which omits all value information and only contains housekeeping information for the RB tree
            # hence, we need to know if we are at a node != 0, so that we can
            # still get at the data
            need_to_skip = (index > 0)
            current = iterator.advance(index)
            if current is None:
                logger >> "Tree is garbage - returning None"
                self.garbage = True
                return None
            if self.get_data_type():
                if not(need_to_skip):
                    current = current.Dereference()
                    obj = current.GetChildMemberWithName('__value_')
                    obj_data = obj.GetData()
                    # make sure we have a valid offset for the next items
                    self.get_value_offset(current)
                    # we do not return __value_ because then we would end up with a child named
                    # __value_ instead of [0]
                    return self.valobj.CreateValueFromData(
                        '[' + str(index) + ']', obj_data, self.data_type)
                else:
                    # FIXME we need to have accessed item 0 before accessing
                    # any other item!
                    if self.skip_size is None:
                        logger >> "You asked for item > 0 before asking for item == 0, I will fetch 0 now then retry"
                        if self.get_child_at_index(0):
                            return self.get_child_at_index(index)
                        else:
                            logger >> "item == 0 could not be found. sorry, nothing can be done here."
                            return None
                    return current.CreateChildAtOffset(
                        '[' + str(index) + ']', self.skip_size, self.data_type)
            else:
                logger >> "Unable to infer data-type - returning None (should mark tree as garbage here?)"
                return None
        except Exception as err:
            logger >> "Hit an exception: " + str(err)
            return None

# Just an example: the actual summary is produced by a summary string:
# size=${svar%#}


def stdmap_SummaryProvider(valobj, dict):
    prov = stdmap_SynthProvider(valobj, None)
    return 'size=' + str(prov.num_children())


class stddeque_SynthProvider:

    def __init__(self, valobj, d):
        logger = lldb.formatters.Logger.Logger()
        logger.write("init")
        self.valobj = valobj
        self.pointer_size = self.valobj.GetProcess().GetAddressByteSize()
        self.count = None
        try:
            self.find_block_size()
        except:
            self.block_size = -1
            self.element_size = -1
        logger.write(
            "block_size=%d, element_size=%d" %
            (self.block_size, self.element_size))

    def find_block_size(self):
        # in order to use the deque we must have the block size, or else
        # it's impossible to know what memory addresses are valid
        self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
        self.element_size = self.element_type.GetByteSize()
        # The code says this, but there must be a better way:
        # template <class _Tp, class _Allocator>
        # class __deque_base {
        #    static const difference_type __block_size = sizeof(value_type) < 256 ? 4096 / sizeof(value_type) : 16;
        # }
        if self.element_size < 256:
            self.block_size = 4096 / self.element_size
        else:
            self.block_size = 16

    def num_children(self):
        global _deque_capping_size
        logger = lldb.formatters.Logger.Logger()
        if self.count is None:
            return 0
        return min(self.count, _deque_capping_size)

    def has_children(self):
        return True

    def get_child_index(self, name):
        logger = lldb.formatters.Logger.Logger()
        try:
            return int(name.lstrip('[').rstrip(']'))
        except:
            return -1

    def get_child_at_index(self, index):
        logger = lldb.formatters.Logger.Logger()
        logger.write("Fetching child " + str(index))
        if index < 0 or self.count is None:
            return None
        if index >= self.num_children():
            return None
        try:
            i, j = divmod(self.start + index, self.block_size)
            return self.first.CreateValueFromExpression(
                '[' + str(index) + ']', '*(*(%s + %d) + %d)' %
                (self.first.get_expr_path(), i, j))
        except:
            return None

    def _get_value_of_compressed_pair(self, pair):
        value = pair.GetChildMemberWithName("__value_")
        if not value.IsValid():
            # pre-r300140 member name
            value = pair.GetChildMemberWithName("__first_")
        return value.GetValueAsUnsigned(0)

    def update(self):
        logger = lldb.formatters.Logger.Logger()
        try:
            # A deque is effectively a two-dim array, with fixed width.
            # 'map' contains pointers to the rows of this array. The
            # full memory area allocated by the deque is delimited
            # by 'first' and 'end_cap'. However, only a subset of this
            # memory contains valid data since a deque may have some slack
            # at the front and back in order to have O(1) insertion at
            # both ends. The rows in active use are delimited by
            # 'begin' and 'end'.
            #
            # To find the elements that are actually constructed, the 'start'
            # variable tells which element in this NxM array is the 0th
            # one, and the 'size' element gives the number of elements
            # in the deque.
            count = self._get_value_of_compressed_pair(
                    self.valobj.GetChildMemberWithName('__size_'))
            # give up now if we cant access memory reliably
            if self.block_size < 0:
                logger.write("block_size < 0")
                return
            map_ = self.valobj.GetChildMemberWithName('__map_')
            start = self.valobj.GetChildMemberWithName(
                '__start_').GetValueAsUnsigned(0)
            first = map_.GetChildMemberWithName('__first_')
            map_first = first.GetValueAsUnsigned(0)
            map_begin = map_.GetChildMemberWithName(
                '__begin_').GetValueAsUnsigned(0)
            map_end = map_.GetChildMemberWithName(
                '__end_').GetValueAsUnsigned(0)
            map_endcap = self._get_value_of_compressed_pair(
                    map_.GetChildMemberWithName( '__end_cap_'))
            # check consistency
            if not map_first <= map_begin <= map_end <= map_endcap:
                logger.write("map pointers are not monotonic")
                return
            total_rows, junk = divmod(
                map_endcap - map_first, self.pointer_size)
            if junk:
                logger.write("endcap-first doesnt align correctly")
                return
            active_rows, junk = divmod(map_end - map_begin, self.pointer_size)
            if junk:
                logger.write("end-begin doesnt align correctly")
                return
            start_row, junk = divmod(map_begin - map_first, self.pointer_size)
            if junk:
                logger.write("begin-first doesnt align correctly")
                return
            if not start_row * \
                    self.block_size <= start < (start_row + 1) * self.block_size:
                logger.write("0th element must be in the 'begin' row")
                return
            end_row = start_row + active_rows
            if not count:
                if active_rows:
                    logger.write("empty deque but begin!=end")
                    return
            elif not (end_row - 1) * self.block_size <= start + count < end_row * self.block_size:
                logger.write("nth element must be before the 'end' row")
                return
            logger.write(
                "update success: count=%r, start=%r, first=%r" %
                (count, start, first))
            # if consistent, save all we really need:
            self.count = count
            self.start = start
            self.first = first
        except:
            self.count = None
            self.start = None
            self.map_first = None
            self.map_begin = None


class stdsharedptr_SynthProvider:

    def __init__(self, valobj, d):
        logger = lldb.formatters.Logger.Logger()
        logger.write("init")
        self.valobj = valobj
        #self.element_ptr_type = self.valobj.GetType().GetTemplateArgumentType(0).GetPointerType()
        self.ptr = None
        self.cntrl = None
        process = valobj.GetProcess()
        self.endianness = process.GetByteOrder()
        self.pointer_size = process.GetAddressByteSize()
        self.count_type = valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)

    def num_children(self):
        return 1

    def has_children(self):
        return True

    def get_child_index(self, name):
        if name == "__ptr_":
            return 0
        if name == "count":
            return 1
        if name == "weak_count":
            return 2
        return -1

    def get_child_at_index(self, index):
        if index == 0:
            return self.ptr
        if index == 1:
            if self.cntrl is None:
                count = 0
            else:
                count = 1 + \
                    self.cntrl.GetChildMemberWithName('__shared_owners_').GetValueAsSigned()
            return self.valobj.CreateValueFromData(
                "count", lldb.SBData.CreateDataFromUInt64Array(
                    self.endianness, self.pointer_size, [count]), self.count_type)
        if index == 2:
            if self.cntrl is None:
                count = 0
            else:
                count = 1 + \
                    self.cntrl.GetChildMemberWithName('__shared_weak_owners_').GetValueAsSigned()
            return self.valobj.CreateValueFromData(
                "weak_count", lldb.SBData.CreateDataFromUInt64Array(
                    self.endianness, self.pointer_size, [count]), self.count_type)
        return None

    def update(self):
        logger = lldb.formatters.Logger.Logger()
        self.ptr = self.valobj.GetChildMemberWithName(
            '__ptr_')  # .Cast(self.element_ptr_type)
        cntrl = self.valobj.GetChildMemberWithName('__cntrl_')
        if cntrl.GetValueAsUnsigned(0):
            self.cntrl = cntrl.Dereference()
        else:
            self.cntrl = None

# we can use two different categories for old and new formatters - type names are different enough that we should make no confusion
# talking with libc++ developer: "std::__1::class_name is set in stone
# until we decide to change the ABI. That shouldn't happen within a 5 year
# time frame"


def __lldb_init_module(debugger, dict):
    debugger.HandleCommand(
        'type summary add -F libcxx.stdstring_SummaryProvider "std::__1::string" -w libcxx')
    debugger.HandleCommand(
        'type summary add -F libcxx.stdstring_SummaryProvider "std::__1::basic_string<char, class std::__1::char_traits<char>, class std::__1::allocator<char> >" -w libcxx')
    debugger.HandleCommand(
        'type synthetic add -l libcxx.stdvector_SynthProvider -x "^(std::__1::)vector<.+>$" -w libcxx')
    debugger.HandleCommand(
        'type summary add -F libcxx.stdvector_SummaryProvider -e -x "^(std::__1::)vector<.+>$" -w libcxx')
    debugger.HandleCommand(
        'type synthetic add -l libcxx.stdlist_SynthProvider -x "^(std::__1::)list<.+>$" -w libcxx')
    debugger.HandleCommand(
        'type summary add -F libcxx.stdlist_SummaryProvider -e -x "^(std::__1::)list<.+>$" -w libcxx')
    debugger.HandleCommand(
        'type synthetic add -l libcxx.stdmap_SynthProvider -x "^(std::__1::)map<.+> >$" -w libcxx')
    debugger.HandleCommand(
        'type summary add -F libcxx.stdmap_SummaryProvider -e -x "^(std::__1::)map<.+> >$" -w libcxx')
    debugger.HandleCommand("type category enable libcxx")
    debugger.HandleCommand(
        'type synthetic add -l libcxx.stddeque_SynthProvider -x "^(std::__1::)deque<.+>$" -w libcxx')
    debugger.HandleCommand(
        'type synthetic add -l libcxx.stdsharedptr_SynthProvider -x "^(std::__1::)shared_ptr<.+>$" -w libcxx')
    # turns out the structs look the same, so weak_ptr can be handled the same!
    debugger.HandleCommand(
        'type synthetic add -l libcxx.stdsharedptr_SynthProvider -x "^(std::__1::)weak_ptr<.+>$" -w libcxx')

_map_capping_size = 255
_list_capping_size = 255
_list_uses_loop_detector = True
_deque_capping_size = 255
