def METHOD_NAME(self, size=-1):
    data = self.buffer
    if size < 0:
        # Read until \n or EOF, whichever comes first
        nl = data.find('\n')
        if nl >= 0:
            nl += 1
            self.buffer = data[nl:]
            return data[:nl]
        buffers = []
        if data:
            buffers.append(data)
        self.buffer = ""
        while True:
            data = self.istream_read(self.buffer_size)
            if not data:
                break
            buffers.append(data)
            nl = data.find('\n')
            if nl >= 0:
                nl += 1
                self.buffer = data[nl:]
                buffers[-1] = data[:nl]
                break
        return "".join(buffers)
    else:
        # Read until size bytes or \n or EOF seen, whichever comes first
        nl = data.find('\n', 0, size)
        if nl >= 0:
            nl += 1
            self.buffer = data[nl:]
            return data[:nl]
        buf_len = len(data)
        if buf_len >= size:
            self.buffer = data[size:]
            return data[:size]
        buffers = []
        if data:
            buffers.append(data)
        self.buffer = ""
        while True:
            data = self.istream_read(self.buffer_size)
            if not data:
                break
            buffers.append(data)
            left = size - buf_len
            nl = data.find('\n', 0, left)
            if nl >= 0:
                nl += 1
                self.buffer = data[nl:]
                buffers[-1] = data[:nl]
                break
            n = len(data)
            if n >= left:
                self.buffer = data[left:]
                buffers[-1] = data[:left]
                break
            buf_len += n
        return "".join(buffers)