'Decodes data from the stream self.stream and returns the
resulting object.
chars indicates the number of characters to read from the
stream. read() will never return more than chars
characters, but it might return less, if there are not enough
characters available.
size indicates the approximate maximum number of bytes to
read from the stream for decoding purposes. The decoder
can modify this setting as appropriate. The default value
-1 indicates to read and decode as much as possible.  size
is intended to prevent having to decode huge files in one
step.
If firstline is true, and a UnicodeDecodeError happens
after the first line terminator in the input only the first line
will be returned, the rest of the input will be kept until the
next call to read().
The method should use a greedy read strategy meaning that
it should read as much data as is allowed within the
definition of the encoding and the given size, e.g.  if
optional encoding endings or state markers are available
on the stream, these should be read too.'

def read(self, size=(-1), chars=(-1), firstline=False):

    if self.linebuffer:
        self.charbuffer = ''.join(self.linebuffer)
        self.linebuffer = None
    while True:
        if (chars < 0):
            if (size < 0):
                if self.charbuffer:
                    break
            elif (len(self.charbuffer) >= size):
                break
        elif (len(self.charbuffer) >= chars):
            break
        if (size < 0):
            newdata = self.stream.read()
        else:
            newdata = self.stream.read(size)
        data = (self.bytebuffer + newdata)
        try:
            (newchars, decodedbytes) = self.decode(data, self.errors)
        except UnicodeDecodeError as exc:
            if firstline:
                (newchars, decodedbytes) = self.decode(data[:exc.start], self.errors)
                lines = newchars.splitlines(True)
                if (len(lines) <= 1):
                    raise
            else:
                raise
        self.bytebuffer = data[decodedbytes:]
        self.charbuffer += newchars
        if (not newdata):
            break
    if (chars < 0):
        result = self.charbuffer
        self.charbuffer = ''
    else:
        result = self.charbuffer[:chars]
        self.charbuffer = self.charbuffer[chars:]
    return result
