import lldb.formatters.Logger

# C++ STL formatters for LLDB
# As there are many versions of the libstdc++, you are encouraged to look at the STL
# implementation for your platform before relying on these formatters to do the right
# thing for your setup

def ForwardListSummaryProvider(valobj, dict):
    list_capping_size = valobj.GetTarget().GetMaximumNumberOfChildrenToDisplay()
    text = "size=" + str(valobj.GetNumChildren())
    if valobj.GetNumChildren() > list_capping_size:
        return "(capped) " + text
    else:
        return text

def StdOptionalSummaryProvider(valobj, dict):
    has_value = valobj.GetNumChildren() > 0
    # We add wrapping spaces for consistency with the libcxx formatter
    return " Has Value=" + ("true" if has_value else "false") + " "


class StdOptionalSynthProvider:
    def __init__(self, valobj, dict):
        self.valobj = valobj

    def update(self):
        try:
            self.payload = self.valobj.GetChildMemberWithName('_M_payload')
            self.value = self.payload.GetChildMemberWithName('_M_payload')
            self.has_value = self.payload.GetChildMemberWithName('_M_engaged').GetValueAsUnsigned(0) != 0
        except:
            self.has_value = False
        return False


    def num_children(self):
        return 1 if self.has_value else 0

    def get_child_index(self, name):
        return 0

    def get_child_at_index(self, index):
        # some versions of libstdcpp have an additional _M_value child with the actual value
        possible_value = self.value.GetChildMemberWithName('_M_value')
        if possible_value.IsValid():
            return possible_value.Clone('Value')
        return self.value.Clone('Value')

"""
 This formatter can be applied to all
 unordered map-like structures (unordered_map, unordered_multimap, unordered_set, unordered_multiset)
"""
class StdUnorderedMapSynthProvider:
    def __init__(self, valobj, dict):
        self.valobj = valobj
        self.count = None
        self.kind = self.get_object_kind(valobj)

    def get_object_kind(self, valobj):
        type_name = valobj.GetTypeName()
        return "set" if "set" in type_name else "map"

    def extract_type(self):
        type = self.valobj.GetType()
        # type of std::pair<key, value> is the first template
        # argument type of the 4th template argument to std::map and
        # 3rd template argument for std::set. That's why
        # we need to know kind of the object
        template_arg_num = 4 if self.kind == "map" else 3
        allocator_type = type.GetTemplateArgumentType(template_arg_num)
        data_type = allocator_type.GetTemplateArgumentType(0)
        return data_type

    def update(self):
        # preemptively setting this to None - we might end up changing our mind
        # later
        self.count = None
        try:
            self.head = self.valobj.GetChildMemberWithName('_M_h')
            self.before_begin = self.head.GetChildMemberWithName('_M_before_begin')
            self.next = self.before_begin.GetChildMemberWithName('_M_nxt')
            self.data_type = self.extract_type()
            self.skip_size = self.next.GetType().GetByteSize()
            self.data_size = self.data_type.GetByteSize()
            if (not self.data_type.IsValid()) or (not self.next.IsValid()):
                self.count = 0
        except:
            self.count = 0
        return False

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

    def get_child_at_index(self, index):
        logger = lldb.formatters.Logger.Logger()
        logger >> "Being asked to fetch child[" + str(index) + "]"
        if index < 0:
            return None
        if index >= self.num_children():
            return None
        try:
            offset = index
            current = self.next
            while offset > 0:
                current = current.GetChildMemberWithName('_M_nxt')
                offset = offset - 1
            return current.CreateChildAtOffset( '[' + str(index) + ']', self.skip_size, self.data_type)

        except:
            logger >> "Cannot get child"
            return None

    def num_children(self):
        if self.count is None:
            self.count = self.num_children_impl()
        return self.count

    def num_children_impl(self):
        logger = lldb.formatters.Logger.Logger()
        try:
            count = self.head.GetChildMemberWithName('_M_element_count').GetValueAsUnsigned(0)
            return count
        except:
            logger >> "Could not determine the size"
            return 0


class AbstractListSynthProvider:
    def __init__(self, valobj, dict, has_prev):
        '''
        :param valobj: The value object of the list
        :param dict: A dict with metadata provided by LLDB
        :param has_prev: Whether the list supports a 'prev' pointer besides a 'next' one
        '''
        logger = lldb.formatters.Logger.Logger()
        self.valobj = valobj
        self.count = None
        self.has_prev = has_prev
        self.list_capping_size = self.valobj.GetTarget().GetMaximumNumberOfChildrenToDisplay()
        logger >> "Providing synthetic children for a list named " + \
            str(valobj.GetName())

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

    def is_valid(self, node):
        logger = lldb.formatters.Logger.Logger()
        valid = self.value(self.next_node(node)) != self.get_end_of_list_address()
        if valid:
            logger >> "%s is valid" % str(self.valobj.GetName())
        else:
            logger >> "synthetic value is not valid"
        return valid

    def value(self, node):
        logger = lldb.formatters.Logger.Logger()
        value = node.GetValueAsUnsigned()
        logger >> "synthetic value for {}: {}".format(
            str(self.valobj.GetName()), value)
        return value

    # 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 = self.next
        fast1 = self.next
        fast2 = self.next
        while self.is_valid(slow):
            slow_value = self.value(slow)
            fast1 = self.next_node(fast2)
            fast2 = self.next_node(fast1)
            if self.value(fast1) == slow_value or self.value(
                    fast2) == slow_value:
                return True
            slow = self.next_node(slow)
        return False

    def num_children(self):
        logger = lldb.formatters.Logger.Logger()
        if self.count is None:
            # libstdc++ 6.0.21 added dedicated count field.
            count_child = self.node.GetChildMemberWithName('_M_data')
            if count_child and count_child.IsValid():
                self.count = count_child.GetValueAsUnsigned(0)
            if self.count is None:
                self.count = self.num_children_impl()
        return self.count

    def num_children_impl(self):
        logger = lldb.formatters.Logger.Logger()
        try:
            # After a std::list has been initialized, both next and prev will
            # be non-NULL
            next_val = self.next.GetValueAsUnsigned(0)
            if next_val == 0:
                return 0
            if self.has_loop():
                return 0
            if self.has_prev:
                prev_val = self.prev.GetValueAsUnsigned(0)
                if prev_val == 0:
                    return 0
                if next_val == self.node_address:
                    return 0
                if next_val == prev_val:
                    return 1
            size = 1
            current = self.next
            while current.GetChildMemberWithName(
                    '_M_next').GetValueAsUnsigned(0) != self.get_end_of_list_address():
                current = current.GetChildMemberWithName('_M_next')
                if not current.IsValid():
                    break
                size = size + 1
                if size >= self.list_capping_size:
                    break

            return size
        except:
            logger >> "Error determining the size"
            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:
            offset = index
            current = self.next
            while offset > 0:
                current = current.GetChildMemberWithName('_M_next')
                offset = offset - 1
            # C++ lists store the data of a node after its pointers. In the case of a forward list, there's just one pointer (next), and
            # in the case of a double-linked list, there's an additional pointer (prev).
            return current.CreateChildAtOffset(
                '[' + str(index) + ']',
               (2 if self.has_prev else 1) * current.GetType().GetByteSize(),
                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:
            return list_type.GetTemplateArgumentType(0)
        return lldb.SBType()

    def update(self):
        logger = lldb.formatters.Logger.Logger()
        # preemptively setting this to None - we might end up changing our mind
        # later
        self.count = None
        try:
            self.impl = self.valobj.GetChildMemberWithName('_M_impl')
            self.data_type = self.extract_type()
            if (not self.data_type.IsValid()) or (not self.impl.IsValid()):
                self.count = 0
            elif not self.updateNodes():
                self.count = 0
            else:
                self.data_size = self.data_type.GetByteSize()
        except:
            self.count = 0
        return False

    '''
    Method is used to extract the list pointers into the variables (e.g self.node, self.next, and optionally to self.prev)
    and is mandatory to be overriden in each AbstractListSynthProvider subclass.
    This should return True or False depending on wheter it found valid data.
    '''
    def updateNodes(self):
        raise NotImplementedError

    def has_children(self):
        return True

    '''
     Method is used to identify if a node traversal has reached its end
     and is mandatory to be overriden in each AbstractListSynthProvider subclass
    '''
    def get_end_of_list_address(self):
        raise NotImplementedError


class StdForwardListSynthProvider(AbstractListSynthProvider):

    def __init__(self, valobj, dict):
        has_prev = False
        super().__init__(valobj, dict, has_prev)

    def updateNodes(self):
        self.node = self.impl.GetChildMemberWithName('_M_head')
        self.next = self.node.GetChildMemberWithName('_M_next')
        if (not self.node.IsValid()) or (not self.next.IsValid()):
            return False
        return True

    def get_end_of_list_address(self):
        return 0


class StdListSynthProvider(AbstractListSynthProvider):

    def __init__(self, valobj, dict):
        has_prev = True
        super().__init__(valobj, dict, has_prev)

    def updateNodes(self):
        self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0)
        self.node = self.impl.GetChildMemberWithName('_M_node')
        self.prev = self.node.GetChildMemberWithName('_M_prev')
        self.next = self.node.GetChildMemberWithName('_M_next')
        if self.node_address == 0 or (not self.node.IsValid()) or (not self.next.IsValid()) or (not self.prev.IsValid()):
            return False
        return True

    def get_end_of_list_address(self):
        return self.node_address


class StdVectorSynthProvider:

    class StdVectorImplementation(object):

        def __init__(self, valobj):
            self.valobj = valobj
            self.count = None

        def num_children(self):
            if self.count is None:
                self.count = self.num_children_impl()
            return self.count

        def num_children_impl(self):
            try:
                start_val = self.start.GetValueAsUnsigned(0)
                finish_val = self.finish.GetValueAsUnsigned(0)
                end_val = self.end.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 or end_val == 0:
                    return 0
                # Make sure start is less than finish
                if start_val >= finish_val:
                    return 0
                # Make sure finish is less than or equal to end of storage
                if finish_val > end_val:
                    return 0

                # if we have a struct (or other data type that the compiler pads to native word size)
                # this check might fail, unless the sizeof() we get is itself incremented to take the
                # padding bytes into account - on current clang it looks like
                # this is the case
                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_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):
            # preemptively setting this to None - we might end up changing our
            # mind later
            self.count = None
            try:
                impl = self.valobj.GetChildMemberWithName('_M_impl')
                self.start = impl.GetChildMemberWithName('_M_start')
                self.finish = impl.GetChildMemberWithName('_M_finish')
                self.end = impl.GetChildMemberWithName('_M_end_of_storage')
                self.data_type = self.start.GetType().GetPointeeType()
                self.data_size = self.data_type.GetByteSize()
                # if any of these objects is invalid, it means there is no
                # point in trying to fetch anything
                if self.start.IsValid() and self.finish.IsValid(
                ) and self.end.IsValid() and self.data_type.IsValid():
                    self.count = None
                else:
                    self.count = 0
            except:
                self.count = 0
            return False

    class StdVBoolImplementation(object):

        def __init__(self, valobj, bool_type):
            self.valobj = valobj
            self.bool_type = bool_type
            self.valid = False

        def num_children(self):
            if self.valid:
                start = self.start_p.GetValueAsUnsigned(0)
                finish = self.finish_p.GetValueAsUnsigned(0)
                offset = self.offset.GetValueAsUnsigned(0)
                if finish >= start:
                    return (finish - start) * 8 + offset
            return 0

        def get_child_at_index(self, index):
            if index >= self.num_children():
                return None
            element_type = self.start_p.GetType().GetPointeeType()
            element_bits = 8 * element_type.GetByteSize()
            element_offset = (index // element_bits) * \
                element_type.GetByteSize()
            bit_offset = index % element_bits
            element = self.start_p.CreateChildAtOffset(
                '[' + str(index) + ']', element_offset, element_type)
            bit = element.GetValueAsUnsigned(0) & (1 << bit_offset)
            if bit != 0:
                value_expr = "(bool)true"
            else:
                value_expr = "(bool)false"
            return self.valobj.CreateValueFromExpression(
                "[%d]" % index, value_expr)

        def update(self):
            try:
                m_impl = self.valobj.GetChildMemberWithName('_M_impl')
                self.m_start = m_impl.GetChildMemberWithName('_M_start')
                self.m_finish = m_impl.GetChildMemberWithName('_M_finish')
                self.start_p = self.m_start.GetChildMemberWithName('_M_p')
                self.finish_p = self.m_finish.GetChildMemberWithName('_M_p')
                self.offset = self.m_finish.GetChildMemberWithName('_M_offset')
                if self.offset.IsValid() and self.start_p.IsValid() and self.finish_p.IsValid():
                    self.valid = True
                else:
                    self.valid = False
            except:
                self.valid = False
            return False

    def __init__(self, valobj, dict):
        logger = lldb.formatters.Logger.Logger()
        first_template_arg_type = valobj.GetType().GetTemplateArgumentType(0)
        if str(first_template_arg_type.GetName()) == "bool":
            self.impl = self.StdVBoolImplementation(
                valobj, first_template_arg_type)
        else:
            self.impl = self.StdVectorImplementation(valobj)
        logger >> "Providing synthetic children for a vector named " + \
            str(valobj.GetName())

    def num_children(self):
        return self.impl.num_children()

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

    def get_child_at_index(self, index):
        return self.impl.get_child_at_index(index)

    def update(self):
        return self.impl.update()

    def has_children(self):
        return True

    """
     This formatter can be applied to all
     map-like structures (map, multimap, set, multiset)
    """
class StdMapLikeSynthProvider:

    def __init__(self, valobj, dict):
        logger = lldb.formatters.Logger.Logger()
        self.valobj = valobj
        self.count = None
        self.kind = self.get_object_kind(valobj)
        logger >> "Providing synthetic children for a " + self.kind + " named " + \
            str(valobj.GetName())

    def get_object_kind(self, valobj):
        type_name = valobj.GetTypeName()
        for kind in ["multiset", "multimap", "set", "map"]:
           if kind in type_name:
              return kind
        return type_name

    # we need this function as a temporary workaround for rdar://problem/10801549
    # which prevents us from extracting the std::pair<K,V> SBType out of the template
    # arguments for _Rep_Type _M_t in the object itself - because we have to make up the
    # typename and then find it, we may hit the situation were std::string has multiple
    # names but only one is actually referenced in the debug information. hence, we need
    # to replace the longer versions of std::string with the shorter one in order to be able
    # to find the type name
    def fixup_class_name(self, class_name):
        logger = lldb.formatters.Logger.Logger()
        if class_name == 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >':
            return 'std::basic_string<char>', True
        if class_name == 'basic_string<char, std::char_traits<char>, std::allocator<char> >':
            return 'std::basic_string<char>', True
        if class_name == 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >':
            return 'std::basic_string<char>', True
        if class_name == 'basic_string<char, std::char_traits<char>, std::allocator<char> >':
            return 'std::basic_string<char>', True
        return class_name, False

    def update(self):
        logger = lldb.formatters.Logger.Logger()
        # preemptively setting this to None - we might end up changing our mind
        # later
        self.count = None
        try:
            # we will set this to True if we find out that discovering a node in the object 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.Mt = self.valobj.GetChildMemberWithName('_M_t')
            self.Mimpl = self.Mt.GetChildMemberWithName('_M_impl')
            self.Mheader = self.Mimpl.GetChildMemberWithName('_M_header')
            if not self.Mheader.IsValid():
                self.count = 0
            else:
                map_type = self.valobj.GetType()
                if map_type.IsReferenceType():
                    logger >> "Dereferencing type"
                    map_type = map_type.GetDereferencedType()

                # Get the type of std::pair<key, value>. It is the first template
                # argument type of the 4th template argument to std::map.
                allocator_type = map_type.GetTemplateArgumentType(3)
                self.data_type = allocator_type.GetTemplateArgumentType(0)
                if not self.data_type:
                    # GCC does not emit DW_TAG_template_type_parameter for
                    # std::allocator<...>. For such a case, get the type of
                    # std::pair from a member of std::map.
                    rep_type = self.valobj.GetChildMemberWithName('_M_t').GetType()
                    self.data_type = rep_type.GetTypedefedType().GetTemplateArgumentType(1)

                # from libstdc++ implementation of _M_root for rbtree
                self.Mroot = self.Mheader.GetChildMemberWithName('_M_parent')
                self.data_size = self.data_type.GetByteSize()
                self.skip_size = self.Mheader.GetType().GetByteSize()
        except:
            self.count = 0
        return False

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

    def num_children_impl(self):
        logger = lldb.formatters.Logger.Logger()
        try:
            root_ptr_val = self.node_ptr_value(self.Mroot)
            if root_ptr_val == 0:
                return 0
            count = self.Mimpl.GetChildMemberWithName(
                '_M_node_count').GetValueAsUnsigned(0)
            logger >> "I have " + str(count) + " children available"
            return count
        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 >> "Being asked to fetch child[" + str(index) + "]"
        if index < 0:
            return None
        if index >= self.num_children():
            return None
        if self.garbage:
            logger >> "Returning None since we are a garbage tree"
            return None
        try:
            offset = index
            current = self.left(self.Mheader)
            while offset > 0:
                current = self.increment_node(current)
                offset = offset - 1
            # skip all the base stuff and get at the data
            return current.CreateChildAtOffset(
                '[' + str(index) + ']', self.skip_size, self.data_type)
        except:
            return None

    # utility functions
    def node_ptr_value(self, node):
        logger = lldb.formatters.Logger.Logger()
        return node.GetValueAsUnsigned(0)

    def right(self, node):
        logger = lldb.formatters.Logger.Logger()
        return node.GetChildMemberWithName("_M_right")

    def left(self, node):
        logger = lldb.formatters.Logger.Logger()
        return node.GetChildMemberWithName("_M_left")

    def parent(self, node):
        logger = lldb.formatters.Logger.Logger()
        return node.GetChildMemberWithName("_M_parent")

    # from libstdc++ implementation of iterator for rbtree
    def increment_node(self, node):
        logger = lldb.formatters.Logger.Logger()
        max_steps = self.num_children()
        if self.node_ptr_value(self.right(node)) != 0:
            x = self.right(node)
            max_steps -= 1
            while self.node_ptr_value(self.left(x)) != 0:
                x = self.left(x)
                max_steps -= 1
                logger >> str(max_steps) + " more to go before giving up"
                if max_steps <= 0:
                    self.garbage = True
                    return None
            return x
        else:
            x = node
            y = self.parent(x)
            max_steps -= 1
            while(self.node_ptr_value(x) == self.node_ptr_value(self.right(y))):
                x = y
                y = self.parent(y)
                max_steps -= 1
                logger >> str(max_steps) + " more to go before giving up"
                if max_steps <= 0:
                    self.garbage = True
                    return None
            if self.node_ptr_value(self.right(x)) != self.node_ptr_value(y):
                x = y
            return x

    def has_children(self):
        return True

_list_uses_loop_detector = True

class StdDequeSynthProvider:
    def __init__(self, valobj, d):
        self.valobj = valobj
        self.pointer_size = self.valobj.GetProcess().GetAddressByteSize()
        self.count = None
        self.block_size = -1
        self.element_size = -1
        self.find_block_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)
        if not self.element_type.IsValid():
            return
        self.element_size = self.element_type.GetByteSize()
        # The block size (i.e. number of elements per subarray) is defined in
        # this piece of code, so we need to replicate it.
        #
        # #define _GLIBCXX_DEQUE_BUF_SIZE 512
        #
        # return (__size < _GLIBCXX_DEQUE_BUF_SIZE
	    #   ? size_t(_GLIBCXX_DEQUE_BUF_SIZE / __size) : size_t(1));
        if self.element_size < 512:
            self.block_size = 512 // self.element_size
        else:
            self.block_size = 1

    def num_children(self):
        if self.count is None:
            return 0
        return self.count

    def has_children(self):
        return True

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

    def get_child_at_index(self, index):
        if index < 0 or self.count is None:
            return None
        if index >= self.num_children():
            return None
        try:
            name = '[' + str(index) + ']'
            # We first look for the element in the first subarray,
            # which might be incomplete.
            if index < self.first_node_size:
                # The following statement is valid because self.first_elem is the pointer
                # to the first element
                return self.first_elem.CreateChildAtOffset(name, index * self.element_size, self.element_type)

            # Now the rest of the subarrays except for maybe the last one
            # are going to be complete, so the final expression is simpler
            i, j = divmod(index - self.first_node_size, self.block_size)

            # We first move to the beginning of the node/subarray were our element is
            node = self.start_node.CreateChildAtOffset(
                '',
                (1 + i) * self.valobj.GetProcess().GetAddressByteSize(),
                self.element_type.GetPointerType())
            return node.CreateChildAtOffset(name, j * self.element_size, self.element_type)

        except:
            return None

    def update(self):
        logger = lldb.formatters.Logger.Logger()
        self.count = 0
        try:
            # A deque is effectively a two-dim array, with fixed width.
            # 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 '_M_start' and
            # '_M_finish'.
            #
            # To find the elements that are actually constructed, the 'start'
            # variable tells which element in this NxM array is the 0th
            # one.
            if self.block_size < 0 or self.element_size < 0:
                return False

            count = 0

            impl = self.valobj.GetChildMemberWithName('_M_impl')

            # we calculate the size of the first node (i.e. first internal array)
            self.start = impl.GetChildMemberWithName('_M_start')
            self.start_node = self.start.GetChildMemberWithName('_M_node')
            first_node_address = self.start_node.GetValueAsUnsigned(0)
            first_node_last_elem = self.start.GetChildMemberWithName('_M_last').GetValueAsUnsigned(0)
            self.first_elem = self.start.GetChildMemberWithName('_M_cur')
            first_node_first_elem = self.first_elem.GetValueAsUnsigned(0)


            finish = impl.GetChildMemberWithName('_M_finish')
            last_node_address = finish.GetChildMemberWithName('_M_node').GetValueAsUnsigned(0)
            last_node_first_elem = finish.GetChildMemberWithName('_M_first').GetValueAsUnsigned(0)
            last_node_last_elem = finish.GetChildMemberWithName('_M_cur').GetValueAsUnsigned(0)

            if first_node_first_elem == 0 or first_node_last_elem == 0 or first_node_first_elem > first_node_last_elem:
                return False
            if last_node_first_elem == 0 or last_node_last_elem == 0 or last_node_first_elem > last_node_last_elem:
                return False


            if last_node_address == first_node_address:
                self.first_node_size = (last_node_last_elem - first_node_first_elem) // self.element_size
                count += self.first_node_size
            else:
                self.first_node_size = (first_node_last_elem - first_node_first_elem) // self.element_size
                count += self.first_node_size

                # we calculate the size of the last node
                finish = impl.GetChildMemberWithName('_M_finish')
                last_node_address = finish.GetChildMemberWithName('_M_node').GetValueAsUnsigned(0)
                count += (last_node_last_elem - last_node_first_elem) // self.element_size

                # we calculate the size of the intermediate nodes
                num_intermediate_nodes = (last_node_address - first_node_address - 1) // self.valobj.GetProcess().GetAddressByteSize()
                count += self.block_size * num_intermediate_nodes
            self.count = count
        except:
            pass
        return False
