<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def add_string(self, data):
 """Process some data splitting it into complete lines and buffering the rest Args: data: A `str` in Python 2 or `bytes` in Python 3 Returns: list of complete lines ending with a carriage return (eg. a progress bar) or a newline. """

        lines = []
        while data:
            match = self._line_end_re.search(data)
            if match is None:
                chunk = data
            else:
                chunk = data[:match.end()]

            data = data[len(chunk):]

            if self._buf and self._buf[-1].endswith(b('\r')) and not chunk.startswith(b('\n')):
                # if we get a carriage return followed by something other than
                # a newline then we assume that we're overwriting the current
                # line (ie. a progress bar)
                #
                # We don't terminate lines that end with a carriage return until
                # we see what's coming next so we can distinguish between a
                # progress bar situation and a Windows line terminator.
                #
                # TODO(adrian): some day these hacks should be replaced with
                # real terminal emulation
                lines.append(self._finish_line())

            self._buf.append(chunk)
            if chunk.endswith(b('\n')):
                lines.append(self._finish_line())

        return lines