def read(self, size=None):
        """
        read([size]) -> read at most size bytes, returned as a string.

        If the size argument is negative or None, read until EOF is reached.
        Return an empty string at EOF.
        """
        if size is None or size < 0:
            return "".join(list(self))
        else:
            data_chunks = []
            data_readed = 0
            try:
                while data_readed < size:
                    chunk = self.next_chunk()
                    data_chunks.append(chunk)
                    data_readed += len(chunk)
            except StopIteration:
                pass

            if data_readed > size:
                last_chunk = data_chunks.pop()
                extra_length = data_readed - size
                last_chunk, extra_data = last_chunk[:-extra_length], last_chunk[-extra_length:]
                self.unshift(extra_data)
                data_chunks.append(last_chunk)
            return "".join(data_chunks)