(self, address: int, size: int, sort: str, idx: int)
Determines whether the block specified by (address, size) should be merged with adjacent blocks.

        :param address: Starting address of the block to be merged.
        :param size: Size of the block to be merged.
        :param sort: Type of the block.
        :param idx: ID of the address.
Determines whether the block specified by (address, size) should be merged with adjacent blocks.
Determines whether the block specified by ( address size ) should be merged with adjacent blocks .
def _insert_and_merge(self, address: int, size: int, sort: str, idx: int) -> None:
        """
        Determines whether the block specified by (address, size) should be merged with adjacent blocks.

        :param address: Starting address of the block to be merged.
        :param size: Size of the block to be merged.
        :param sort: Type of the block.
        :param idx: ID of the address.
        """

        # sanity check
        if idx > 0 and address + size <= self._list[idx - 1].start:
            # There is a bug, since _list[idx] must be the closest one that is less than the current segment
            l.warning("BUG FOUND: new segment should always be greater than _list[idx].")
            # Anyways, let's fix it.
            self._insert_and_merge(address, size, sort, idx - 1)
            return

        # Insert the block first
        # The new block might be overlapping with other blocks. _insert_and_merge_core will fix the overlapping.
        if idx == len(self._list):
            self._list.append(Segment(address, address + size, sort))
        else:
            self._list.insert(idx, Segment(address, address + size, sort))
        # Apparently _bytes_occupied will be wrong if the new block overlaps with any existing block. We will fix it
        # later
        self._bytes_occupied += size

        # Search forward to merge blocks if necessary
        pos = idx
        while pos < len(self._list):
            merged, pos, bytes_change = self._insert_and_merge_core(pos, "forward")

            if not merged:
                break

            self._bytes_occupied += bytes_change

        # Search backward to merge blocks if necessary
        pos = idx

        while pos > 0:
            merged, pos, bytes_change = self._insert_and_merge_core(pos, "backward")

            if not merged:
                break

            self._bytes_occupied += bytes_change
def _insert_and_merge ( self , address : int , size : int , sort : str , idx : int ) -> None : # sanity check if idx > 0 and address + size <= self . _list [ idx - 1 ] . start : # There is a bug, since _list[idx] must be the closest one that is less than the current segment l . warning ( "BUG FOUND: new segment should always be greater than _list[idx]." ) # Anyways, let's fix it. self . _insert_and_merge ( address , size , sort , idx - 1 ) return # Insert the block first # The new block might be overlapping with other blocks. _insert_and_merge_core will fix the overlapping. if idx == len ( self . _list ) : self . _list . append ( Segment ( address , address + size , sort ) ) else : self . _list . insert ( idx , Segment ( address , address + size , sort ) ) # Apparently _bytes_occupied will be wrong if the new block overlaps with any existing block. We will fix it # later self . _bytes_occupied += size # Search forward to merge blocks if necessary pos = idx while pos < len ( self . _list ) : merged , pos , bytes_change = self . _insert_and_merge_core ( pos , "forward" ) if not merged : break self . _bytes_occupied += bytes_change # Search backward to merge blocks if necessary pos = idx while pos > 0 : merged , pos , bytes_change = self . _insert_and_merge_core ( pos , "backward" ) if not merged : break self . _bytes_occupied += bytes_change