! @brief Add a block of data to be programmed.

        @note Programming does not start until the method program() is called.
        
        @param self
        @param addr Base address of the block of data passed to this method. The entire block of
            data must be contained within the flash memory region associated with this instance.
        @param data Data to be programmed. Should be a list of byte values.
        
        @exception FlashFailure Address range of added data is outside the address range of the
            flash region associated with the builder.
        @exception ValueError Attempt to add overlapping data.

def add_data(self, addr, data):
        """! @brief Add a block of data to be programmed.

        @note Programming does not start until the method program() is called.
        
        @param self
        @param addr Base address of the block of data passed to this method. The entire block of
            data must be contained within the flash memory region associated with this instance.
        @param data Data to be programmed. Should be a list of byte values.
        
        @exception FlashFailure Address range of added data is outside the address range of the
            flash region associated with the builder.
        @exception ValueError Attempt to add overlapping data.
        """
        # Ignore empty data.
        if len(data) == 0:
            return
        
        # Sanity check
        if not self.flash.region.contains_range(start=addr, length=len(data)):
            raise FlashFailure("Flash address range 0x%x-0x%x is not contained within region '%s'" %
                (addr, addr + len(data) - 1, self.flash.region.name))

        # Add operation to list
        self.flash_operation_list.append(_FlashOperation(addr, data))
        self.buffered_data_size += len(data)

        # Keep list sorted
        self.flash_operation_list = sorted(self.flash_operation_list, key=lambda operation: operation.addr)
        
        # Verify this does not overlap
        prev_flash_operation = None
        for operation in self.flash_operation_list:
            if prev_flash_operation is not None:
                if prev_flash_operation.addr + len(prev_flash_operation.data) > operation.addr:
                    raise ValueError("Error adding data - Data at 0x%x..0x%x overlaps with 0x%x..0x%x"
                            % (prev_flash_operation.addr, prev_flash_operation.addr + len(prev_flash_operation.data),
                               operation.addr, operation.addr + len(operation.data)))
            prev_flash_operation = operation