17db96d56Sopenharmony_ci"""
27db96d56Sopenharmony_ciPython implementation of the io module.
37db96d56Sopenharmony_ci"""
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_ciimport os
67db96d56Sopenharmony_ciimport abc
77db96d56Sopenharmony_ciimport codecs
87db96d56Sopenharmony_ciimport errno
97db96d56Sopenharmony_ciimport stat
107db96d56Sopenharmony_ciimport sys
117db96d56Sopenharmony_ci# Import _thread instead of threading to reduce startup cost
127db96d56Sopenharmony_cifrom _thread import allocate_lock as Lock
137db96d56Sopenharmony_ciif sys.platform in {'win32', 'cygwin'}:
147db96d56Sopenharmony_ci    from msvcrt import setmode as _setmode
157db96d56Sopenharmony_cielse:
167db96d56Sopenharmony_ci    _setmode = None
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ciimport io
197db96d56Sopenharmony_cifrom io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END)
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_civalid_seek_flags = {0, 1, 2}  # Hardwired values
227db96d56Sopenharmony_ciif hasattr(os, 'SEEK_HOLE') :
237db96d56Sopenharmony_ci    valid_seek_flags.add(os.SEEK_HOLE)
247db96d56Sopenharmony_ci    valid_seek_flags.add(os.SEEK_DATA)
257db96d56Sopenharmony_ci
267db96d56Sopenharmony_ci# open() uses st_blksize whenever we can
277db96d56Sopenharmony_ciDEFAULT_BUFFER_SIZE = 8 * 1024  # bytes
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_ci# NOTE: Base classes defined here are registered with the "official" ABCs
307db96d56Sopenharmony_ci# defined in io.py. We don't use real inheritance though, because we don't want
317db96d56Sopenharmony_ci# to inherit the C implementations.
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ci# Rebind for compatibility
347db96d56Sopenharmony_ciBlockingIOError = BlockingIOError
357db96d56Sopenharmony_ci
367db96d56Sopenharmony_ci# Does io.IOBase finalizer log the exception if the close() method fails?
377db96d56Sopenharmony_ci# The exception is ignored silently by default in release build.
387db96d56Sopenharmony_ci_IOBASE_EMITS_UNRAISABLE = (hasattr(sys, "gettotalrefcount") or sys.flags.dev_mode)
397db96d56Sopenharmony_ci# Does open() check its 'errors' argument?
407db96d56Sopenharmony_ci_CHECK_ERRORS = _IOBASE_EMITS_UNRAISABLE
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_cidef text_encoding(encoding, stacklevel=2):
447db96d56Sopenharmony_ci    """
457db96d56Sopenharmony_ci    A helper function to choose the text encoding.
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_ci    When encoding is not None, this function returns it.
487db96d56Sopenharmony_ci    Otherwise, this function returns the default text encoding
497db96d56Sopenharmony_ci    (i.e. "locale" or "utf-8" depends on UTF-8 mode).
507db96d56Sopenharmony_ci
517db96d56Sopenharmony_ci    This function emits an EncodingWarning if *encoding* is None and
527db96d56Sopenharmony_ci    sys.flags.warn_default_encoding is true.
537db96d56Sopenharmony_ci
547db96d56Sopenharmony_ci    This can be used in APIs with an encoding=None parameter
557db96d56Sopenharmony_ci    that pass it to TextIOWrapper or open.
567db96d56Sopenharmony_ci    However, please consider using encoding="utf-8" for new APIs.
577db96d56Sopenharmony_ci    """
587db96d56Sopenharmony_ci    if encoding is None:
597db96d56Sopenharmony_ci        if sys.flags.utf8_mode:
607db96d56Sopenharmony_ci            encoding = "utf-8"
617db96d56Sopenharmony_ci        else:
627db96d56Sopenharmony_ci            encoding = "locale"
637db96d56Sopenharmony_ci        if sys.flags.warn_default_encoding:
647db96d56Sopenharmony_ci            import warnings
657db96d56Sopenharmony_ci            warnings.warn("'encoding' argument not specified.",
667db96d56Sopenharmony_ci                          EncodingWarning, stacklevel + 1)
677db96d56Sopenharmony_ci    return encoding
687db96d56Sopenharmony_ci
697db96d56Sopenharmony_ci
707db96d56Sopenharmony_ci# Wrapper for builtins.open
717db96d56Sopenharmony_ci#
727db96d56Sopenharmony_ci# Trick so that open() won't become a bound method when stored
737db96d56Sopenharmony_ci# as a class variable (as dbm.dumb does).
747db96d56Sopenharmony_ci#
757db96d56Sopenharmony_ci# See init_set_builtins_open() in Python/pylifecycle.c.
767db96d56Sopenharmony_ci@staticmethod
777db96d56Sopenharmony_cidef open(file, mode="r", buffering=-1, encoding=None, errors=None,
787db96d56Sopenharmony_ci         newline=None, closefd=True, opener=None):
797db96d56Sopenharmony_ci
807db96d56Sopenharmony_ci    r"""Open file and return a stream.  Raise OSError upon failure.
817db96d56Sopenharmony_ci
827db96d56Sopenharmony_ci    file is either a text or byte string giving the name (and the path
837db96d56Sopenharmony_ci    if the file isn't in the current working directory) of the file to
847db96d56Sopenharmony_ci    be opened or an integer file descriptor of the file to be
857db96d56Sopenharmony_ci    wrapped. (If a file descriptor is given, it is closed when the
867db96d56Sopenharmony_ci    returned I/O object is closed, unless closefd is set to False.)
877db96d56Sopenharmony_ci
887db96d56Sopenharmony_ci    mode is an optional string that specifies the mode in which the file is
897db96d56Sopenharmony_ci    opened. It defaults to 'r' which means open for reading in text mode. Other
907db96d56Sopenharmony_ci    common values are 'w' for writing (truncating the file if it already
917db96d56Sopenharmony_ci    exists), 'x' for exclusive creation of a new file, and 'a' for appending
927db96d56Sopenharmony_ci    (which on some Unix systems, means that all writes append to the end of the
937db96d56Sopenharmony_ci    file regardless of the current seek position). In text mode, if encoding is
947db96d56Sopenharmony_ci    not specified the encoding used is platform dependent. (For reading and
957db96d56Sopenharmony_ci    writing raw bytes use binary mode and leave encoding unspecified.) The
967db96d56Sopenharmony_ci    available modes are:
977db96d56Sopenharmony_ci
987db96d56Sopenharmony_ci    ========= ===============================================================
997db96d56Sopenharmony_ci    Character Meaning
1007db96d56Sopenharmony_ci    --------- ---------------------------------------------------------------
1017db96d56Sopenharmony_ci    'r'       open for reading (default)
1027db96d56Sopenharmony_ci    'w'       open for writing, truncating the file first
1037db96d56Sopenharmony_ci    'x'       create a new file and open it for writing
1047db96d56Sopenharmony_ci    'a'       open for writing, appending to the end of the file if it exists
1057db96d56Sopenharmony_ci    'b'       binary mode
1067db96d56Sopenharmony_ci    't'       text mode (default)
1077db96d56Sopenharmony_ci    '+'       open a disk file for updating (reading and writing)
1087db96d56Sopenharmony_ci    ========= ===============================================================
1097db96d56Sopenharmony_ci
1107db96d56Sopenharmony_ci    The default mode is 'rt' (open for reading text). For binary random
1117db96d56Sopenharmony_ci    access, the mode 'w+b' opens and truncates the file to 0 bytes, while
1127db96d56Sopenharmony_ci    'r+b' opens the file without truncation. The 'x' mode implies 'w' and
1137db96d56Sopenharmony_ci    raises an `FileExistsError` if the file already exists.
1147db96d56Sopenharmony_ci
1157db96d56Sopenharmony_ci    Python distinguishes between files opened in binary and text modes,
1167db96d56Sopenharmony_ci    even when the underlying operating system doesn't. Files opened in
1177db96d56Sopenharmony_ci    binary mode (appending 'b' to the mode argument) return contents as
1187db96d56Sopenharmony_ci    bytes objects without any decoding. In text mode (the default, or when
1197db96d56Sopenharmony_ci    't' is appended to the mode argument), the contents of the file are
1207db96d56Sopenharmony_ci    returned as strings, the bytes having been first decoded using a
1217db96d56Sopenharmony_ci    platform-dependent encoding or using the specified encoding if given.
1227db96d56Sopenharmony_ci
1237db96d56Sopenharmony_ci    buffering is an optional integer used to set the buffering policy.
1247db96d56Sopenharmony_ci    Pass 0 to switch buffering off (only allowed in binary mode), 1 to select
1257db96d56Sopenharmony_ci    line buffering (only usable in text mode), and an integer > 1 to indicate
1267db96d56Sopenharmony_ci    the size of a fixed-size chunk buffer.  When no buffering argument is
1277db96d56Sopenharmony_ci    given, the default buffering policy works as follows:
1287db96d56Sopenharmony_ci
1297db96d56Sopenharmony_ci    * Binary files are buffered in fixed-size chunks; the size of the buffer
1307db96d56Sopenharmony_ci      is chosen using a heuristic trying to determine the underlying device's
1317db96d56Sopenharmony_ci      "block size" and falling back on `io.DEFAULT_BUFFER_SIZE`.
1327db96d56Sopenharmony_ci      On many systems, the buffer will typically be 4096 or 8192 bytes long.
1337db96d56Sopenharmony_ci
1347db96d56Sopenharmony_ci    * "Interactive" text files (files for which isatty() returns True)
1357db96d56Sopenharmony_ci      use line buffering.  Other text files use the policy described above
1367db96d56Sopenharmony_ci      for binary files.
1377db96d56Sopenharmony_ci
1387db96d56Sopenharmony_ci    encoding is the str name of the encoding used to decode or encode the
1397db96d56Sopenharmony_ci    file. This should only be used in text mode. The default encoding is
1407db96d56Sopenharmony_ci    platform dependent, but any encoding supported by Python can be
1417db96d56Sopenharmony_ci    passed.  See the codecs module for the list of supported encodings.
1427db96d56Sopenharmony_ci
1437db96d56Sopenharmony_ci    errors is an optional string that specifies how encoding errors are to
1447db96d56Sopenharmony_ci    be handled---this argument should not be used in binary mode. Pass
1457db96d56Sopenharmony_ci    'strict' to raise a ValueError exception if there is an encoding error
1467db96d56Sopenharmony_ci    (the default of None has the same effect), or pass 'ignore' to ignore
1477db96d56Sopenharmony_ci    errors. (Note that ignoring encoding errors can lead to data loss.)
1487db96d56Sopenharmony_ci    See the documentation for codecs.register for a list of the permitted
1497db96d56Sopenharmony_ci    encoding error strings.
1507db96d56Sopenharmony_ci
1517db96d56Sopenharmony_ci    newline is a string controlling how universal newlines works (it only
1527db96d56Sopenharmony_ci    applies to text mode). It can be None, '', '\n', '\r', and '\r\n'.  It works
1537db96d56Sopenharmony_ci    as follows:
1547db96d56Sopenharmony_ci
1557db96d56Sopenharmony_ci    * On input, if newline is None, universal newlines mode is
1567db96d56Sopenharmony_ci      enabled. Lines in the input can end in '\n', '\r', or '\r\n', and
1577db96d56Sopenharmony_ci      these are translated into '\n' before being returned to the
1587db96d56Sopenharmony_ci      caller. If it is '', universal newline mode is enabled, but line
1597db96d56Sopenharmony_ci      endings are returned to the caller untranslated. If it has any of
1607db96d56Sopenharmony_ci      the other legal values, input lines are only terminated by the given
1617db96d56Sopenharmony_ci      string, and the line ending is returned to the caller untranslated.
1627db96d56Sopenharmony_ci
1637db96d56Sopenharmony_ci    * On output, if newline is None, any '\n' characters written are
1647db96d56Sopenharmony_ci      translated to the system default line separator, os.linesep. If
1657db96d56Sopenharmony_ci      newline is '', no translation takes place. If newline is any of the
1667db96d56Sopenharmony_ci      other legal values, any '\n' characters written are translated to
1677db96d56Sopenharmony_ci      the given string.
1687db96d56Sopenharmony_ci
1697db96d56Sopenharmony_ci    closedfd is a bool. If closefd is False, the underlying file descriptor will
1707db96d56Sopenharmony_ci    be kept open when the file is closed. This does not work when a file name is
1717db96d56Sopenharmony_ci    given and must be True in that case.
1727db96d56Sopenharmony_ci
1737db96d56Sopenharmony_ci    The newly created file is non-inheritable.
1747db96d56Sopenharmony_ci
1757db96d56Sopenharmony_ci    A custom opener can be used by passing a callable as *opener*. The
1767db96d56Sopenharmony_ci    underlying file descriptor for the file object is then obtained by calling
1777db96d56Sopenharmony_ci    *opener* with (*file*, *flags*). *opener* must return an open file
1787db96d56Sopenharmony_ci    descriptor (passing os.open as *opener* results in functionality similar to
1797db96d56Sopenharmony_ci    passing None).
1807db96d56Sopenharmony_ci
1817db96d56Sopenharmony_ci    open() returns a file object whose type depends on the mode, and
1827db96d56Sopenharmony_ci    through which the standard file operations such as reading and writing
1837db96d56Sopenharmony_ci    are performed. When open() is used to open a file in a text mode ('w',
1847db96d56Sopenharmony_ci    'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open
1857db96d56Sopenharmony_ci    a file in a binary mode, the returned class varies: in read binary
1867db96d56Sopenharmony_ci    mode, it returns a BufferedReader; in write binary and append binary
1877db96d56Sopenharmony_ci    modes, it returns a BufferedWriter, and in read/write mode, it returns
1887db96d56Sopenharmony_ci    a BufferedRandom.
1897db96d56Sopenharmony_ci
1907db96d56Sopenharmony_ci    It is also possible to use a string or bytearray as a file for both
1917db96d56Sopenharmony_ci    reading and writing. For strings StringIO can be used like a file
1927db96d56Sopenharmony_ci    opened in a text mode, and for bytes a BytesIO can be used like a file
1937db96d56Sopenharmony_ci    opened in a binary mode.
1947db96d56Sopenharmony_ci    """
1957db96d56Sopenharmony_ci    if not isinstance(file, int):
1967db96d56Sopenharmony_ci        file = os.fspath(file)
1977db96d56Sopenharmony_ci    if not isinstance(file, (str, bytes, int)):
1987db96d56Sopenharmony_ci        raise TypeError("invalid file: %r" % file)
1997db96d56Sopenharmony_ci    if not isinstance(mode, str):
2007db96d56Sopenharmony_ci        raise TypeError("invalid mode: %r" % mode)
2017db96d56Sopenharmony_ci    if not isinstance(buffering, int):
2027db96d56Sopenharmony_ci        raise TypeError("invalid buffering: %r" % buffering)
2037db96d56Sopenharmony_ci    if encoding is not None and not isinstance(encoding, str):
2047db96d56Sopenharmony_ci        raise TypeError("invalid encoding: %r" % encoding)
2057db96d56Sopenharmony_ci    if errors is not None and not isinstance(errors, str):
2067db96d56Sopenharmony_ci        raise TypeError("invalid errors: %r" % errors)
2077db96d56Sopenharmony_ci    modes = set(mode)
2087db96d56Sopenharmony_ci    if modes - set("axrwb+t") or len(mode) > len(modes):
2097db96d56Sopenharmony_ci        raise ValueError("invalid mode: %r" % mode)
2107db96d56Sopenharmony_ci    creating = "x" in modes
2117db96d56Sopenharmony_ci    reading = "r" in modes
2127db96d56Sopenharmony_ci    writing = "w" in modes
2137db96d56Sopenharmony_ci    appending = "a" in modes
2147db96d56Sopenharmony_ci    updating = "+" in modes
2157db96d56Sopenharmony_ci    text = "t" in modes
2167db96d56Sopenharmony_ci    binary = "b" in modes
2177db96d56Sopenharmony_ci    if text and binary:
2187db96d56Sopenharmony_ci        raise ValueError("can't have text and binary mode at once")
2197db96d56Sopenharmony_ci    if creating + reading + writing + appending > 1:
2207db96d56Sopenharmony_ci        raise ValueError("can't have read/write/append mode at once")
2217db96d56Sopenharmony_ci    if not (creating or reading or writing or appending):
2227db96d56Sopenharmony_ci        raise ValueError("must have exactly one of read/write/append mode")
2237db96d56Sopenharmony_ci    if binary and encoding is not None:
2247db96d56Sopenharmony_ci        raise ValueError("binary mode doesn't take an encoding argument")
2257db96d56Sopenharmony_ci    if binary and errors is not None:
2267db96d56Sopenharmony_ci        raise ValueError("binary mode doesn't take an errors argument")
2277db96d56Sopenharmony_ci    if binary and newline is not None:
2287db96d56Sopenharmony_ci        raise ValueError("binary mode doesn't take a newline argument")
2297db96d56Sopenharmony_ci    if binary and buffering == 1:
2307db96d56Sopenharmony_ci        import warnings
2317db96d56Sopenharmony_ci        warnings.warn("line buffering (buffering=1) isn't supported in binary "
2327db96d56Sopenharmony_ci                      "mode, the default buffer size will be used",
2337db96d56Sopenharmony_ci                      RuntimeWarning, 2)
2347db96d56Sopenharmony_ci    raw = FileIO(file,
2357db96d56Sopenharmony_ci                 (creating and "x" or "") +
2367db96d56Sopenharmony_ci                 (reading and "r" or "") +
2377db96d56Sopenharmony_ci                 (writing and "w" or "") +
2387db96d56Sopenharmony_ci                 (appending and "a" or "") +
2397db96d56Sopenharmony_ci                 (updating and "+" or ""),
2407db96d56Sopenharmony_ci                 closefd, opener=opener)
2417db96d56Sopenharmony_ci    result = raw
2427db96d56Sopenharmony_ci    try:
2437db96d56Sopenharmony_ci        line_buffering = False
2447db96d56Sopenharmony_ci        if buffering == 1 or buffering < 0 and raw.isatty():
2457db96d56Sopenharmony_ci            buffering = -1
2467db96d56Sopenharmony_ci            line_buffering = True
2477db96d56Sopenharmony_ci        if buffering < 0:
2487db96d56Sopenharmony_ci            buffering = DEFAULT_BUFFER_SIZE
2497db96d56Sopenharmony_ci            try:
2507db96d56Sopenharmony_ci                bs = os.fstat(raw.fileno()).st_blksize
2517db96d56Sopenharmony_ci            except (OSError, AttributeError):
2527db96d56Sopenharmony_ci                pass
2537db96d56Sopenharmony_ci            else:
2547db96d56Sopenharmony_ci                if bs > 1:
2557db96d56Sopenharmony_ci                    buffering = bs
2567db96d56Sopenharmony_ci        if buffering < 0:
2577db96d56Sopenharmony_ci            raise ValueError("invalid buffering size")
2587db96d56Sopenharmony_ci        if buffering == 0:
2597db96d56Sopenharmony_ci            if binary:
2607db96d56Sopenharmony_ci                return result
2617db96d56Sopenharmony_ci            raise ValueError("can't have unbuffered text I/O")
2627db96d56Sopenharmony_ci        if updating:
2637db96d56Sopenharmony_ci            buffer = BufferedRandom(raw, buffering)
2647db96d56Sopenharmony_ci        elif creating or writing or appending:
2657db96d56Sopenharmony_ci            buffer = BufferedWriter(raw, buffering)
2667db96d56Sopenharmony_ci        elif reading:
2677db96d56Sopenharmony_ci            buffer = BufferedReader(raw, buffering)
2687db96d56Sopenharmony_ci        else:
2697db96d56Sopenharmony_ci            raise ValueError("unknown mode: %r" % mode)
2707db96d56Sopenharmony_ci        result = buffer
2717db96d56Sopenharmony_ci        if binary:
2727db96d56Sopenharmony_ci            return result
2737db96d56Sopenharmony_ci        encoding = text_encoding(encoding)
2747db96d56Sopenharmony_ci        text = TextIOWrapper(buffer, encoding, errors, newline, line_buffering)
2757db96d56Sopenharmony_ci        result = text
2767db96d56Sopenharmony_ci        text.mode = mode
2777db96d56Sopenharmony_ci        return result
2787db96d56Sopenharmony_ci    except:
2797db96d56Sopenharmony_ci        result.close()
2807db96d56Sopenharmony_ci        raise
2817db96d56Sopenharmony_ci
2827db96d56Sopenharmony_ci# Define a default pure-Python implementation for open_code()
2837db96d56Sopenharmony_ci# that does not allow hooks. Warn on first use. Defined for tests.
2847db96d56Sopenharmony_cidef _open_code_with_warning(path):
2857db96d56Sopenharmony_ci    """Opens the provided file with mode ``'rb'``. This function
2867db96d56Sopenharmony_ci    should be used when the intent is to treat the contents as
2877db96d56Sopenharmony_ci    executable code.
2887db96d56Sopenharmony_ci
2897db96d56Sopenharmony_ci    ``path`` should be an absolute path.
2907db96d56Sopenharmony_ci
2917db96d56Sopenharmony_ci    When supported by the runtime, this function can be hooked
2927db96d56Sopenharmony_ci    in order to allow embedders more control over code files.
2937db96d56Sopenharmony_ci    This functionality is not supported on the current runtime.
2947db96d56Sopenharmony_ci    """
2957db96d56Sopenharmony_ci    import warnings
2967db96d56Sopenharmony_ci    warnings.warn("_pyio.open_code() may not be using hooks",
2977db96d56Sopenharmony_ci                  RuntimeWarning, 2)
2987db96d56Sopenharmony_ci    return open(path, "rb")
2997db96d56Sopenharmony_ci
3007db96d56Sopenharmony_citry:
3017db96d56Sopenharmony_ci    open_code = io.open_code
3027db96d56Sopenharmony_ciexcept AttributeError:
3037db96d56Sopenharmony_ci    open_code = _open_code_with_warning
3047db96d56Sopenharmony_ci
3057db96d56Sopenharmony_ci
3067db96d56Sopenharmony_cidef __getattr__(name):
3077db96d56Sopenharmony_ci    if name == "OpenWrapper":
3087db96d56Sopenharmony_ci        # bpo-43680: Until Python 3.9, _pyio.open was not a static method and
3097db96d56Sopenharmony_ci        # builtins.open was set to OpenWrapper to not become a bound method
3107db96d56Sopenharmony_ci        # when set to a class variable. _io.open is a built-in function whereas
3117db96d56Sopenharmony_ci        # _pyio.open is a Python function. In Python 3.10, _pyio.open() is now
3127db96d56Sopenharmony_ci        # a static method, and builtins.open() is now io.open().
3137db96d56Sopenharmony_ci        import warnings
3147db96d56Sopenharmony_ci        warnings.warn('OpenWrapper is deprecated, use open instead',
3157db96d56Sopenharmony_ci                      DeprecationWarning, stacklevel=2)
3167db96d56Sopenharmony_ci        global OpenWrapper
3177db96d56Sopenharmony_ci        OpenWrapper = open
3187db96d56Sopenharmony_ci        return OpenWrapper
3197db96d56Sopenharmony_ci    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
3207db96d56Sopenharmony_ci
3217db96d56Sopenharmony_ci
3227db96d56Sopenharmony_ci# In normal operation, both `UnsupportedOperation`s should be bound to the
3237db96d56Sopenharmony_ci# same object.
3247db96d56Sopenharmony_citry:
3257db96d56Sopenharmony_ci    UnsupportedOperation = io.UnsupportedOperation
3267db96d56Sopenharmony_ciexcept AttributeError:
3277db96d56Sopenharmony_ci    class UnsupportedOperation(OSError, ValueError):
3287db96d56Sopenharmony_ci        pass
3297db96d56Sopenharmony_ci
3307db96d56Sopenharmony_ci
3317db96d56Sopenharmony_ciclass IOBase(metaclass=abc.ABCMeta):
3327db96d56Sopenharmony_ci
3337db96d56Sopenharmony_ci    """The abstract base class for all I/O classes.
3347db96d56Sopenharmony_ci
3357db96d56Sopenharmony_ci    This class provides dummy implementations for many methods that
3367db96d56Sopenharmony_ci    derived classes can override selectively; the default implementations
3377db96d56Sopenharmony_ci    represent a file that cannot be read, written or seeked.
3387db96d56Sopenharmony_ci
3397db96d56Sopenharmony_ci    Even though IOBase does not declare read or write because
3407db96d56Sopenharmony_ci    their signatures will vary, implementations and clients should
3417db96d56Sopenharmony_ci    consider those methods part of the interface. Also, implementations
3427db96d56Sopenharmony_ci    may raise UnsupportedOperation when operations they do not support are
3437db96d56Sopenharmony_ci    called.
3447db96d56Sopenharmony_ci
3457db96d56Sopenharmony_ci    The basic type used for binary data read from or written to a file is
3467db96d56Sopenharmony_ci    bytes. Other bytes-like objects are accepted as method arguments too.
3477db96d56Sopenharmony_ci    Text I/O classes work with str data.
3487db96d56Sopenharmony_ci
3497db96d56Sopenharmony_ci    Note that calling any method (even inquiries) on a closed stream is
3507db96d56Sopenharmony_ci    undefined. Implementations may raise OSError in this case.
3517db96d56Sopenharmony_ci
3527db96d56Sopenharmony_ci    IOBase (and its subclasses) support the iterator protocol, meaning
3537db96d56Sopenharmony_ci    that an IOBase object can be iterated over yielding the lines in a
3547db96d56Sopenharmony_ci    stream.
3557db96d56Sopenharmony_ci
3567db96d56Sopenharmony_ci    IOBase also supports the :keyword:`with` statement. In this example,
3577db96d56Sopenharmony_ci    fp is closed after the suite of the with statement is complete:
3587db96d56Sopenharmony_ci
3597db96d56Sopenharmony_ci    with open('spam.txt', 'r') as fp:
3607db96d56Sopenharmony_ci        fp.write('Spam and eggs!')
3617db96d56Sopenharmony_ci    """
3627db96d56Sopenharmony_ci
3637db96d56Sopenharmony_ci    ### Internal ###
3647db96d56Sopenharmony_ci
3657db96d56Sopenharmony_ci    def _unsupported(self, name):
3667db96d56Sopenharmony_ci        """Internal: raise an OSError exception for unsupported operations."""
3677db96d56Sopenharmony_ci        raise UnsupportedOperation("%s.%s() not supported" %
3687db96d56Sopenharmony_ci                                   (self.__class__.__name__, name))
3697db96d56Sopenharmony_ci
3707db96d56Sopenharmony_ci    ### Positioning ###
3717db96d56Sopenharmony_ci
3727db96d56Sopenharmony_ci    def seek(self, pos, whence=0):
3737db96d56Sopenharmony_ci        """Change stream position.
3747db96d56Sopenharmony_ci
3757db96d56Sopenharmony_ci        Change the stream position to byte offset pos. Argument pos is
3767db96d56Sopenharmony_ci        interpreted relative to the position indicated by whence.  Values
3777db96d56Sopenharmony_ci        for whence are ints:
3787db96d56Sopenharmony_ci
3797db96d56Sopenharmony_ci        * 0 -- start of stream (the default); offset should be zero or positive
3807db96d56Sopenharmony_ci        * 1 -- current stream position; offset may be negative
3817db96d56Sopenharmony_ci        * 2 -- end of stream; offset is usually negative
3827db96d56Sopenharmony_ci        Some operating systems / file systems could provide additional values.
3837db96d56Sopenharmony_ci
3847db96d56Sopenharmony_ci        Return an int indicating the new absolute position.
3857db96d56Sopenharmony_ci        """
3867db96d56Sopenharmony_ci        self._unsupported("seek")
3877db96d56Sopenharmony_ci
3887db96d56Sopenharmony_ci    def tell(self):
3897db96d56Sopenharmony_ci        """Return an int indicating the current stream position."""
3907db96d56Sopenharmony_ci        return self.seek(0, 1)
3917db96d56Sopenharmony_ci
3927db96d56Sopenharmony_ci    def truncate(self, pos=None):
3937db96d56Sopenharmony_ci        """Truncate file to size bytes.
3947db96d56Sopenharmony_ci
3957db96d56Sopenharmony_ci        Size defaults to the current IO position as reported by tell().  Return
3967db96d56Sopenharmony_ci        the new size.
3977db96d56Sopenharmony_ci        """
3987db96d56Sopenharmony_ci        self._unsupported("truncate")
3997db96d56Sopenharmony_ci
4007db96d56Sopenharmony_ci    ### Flush and close ###
4017db96d56Sopenharmony_ci
4027db96d56Sopenharmony_ci    def flush(self):
4037db96d56Sopenharmony_ci        """Flush write buffers, if applicable.
4047db96d56Sopenharmony_ci
4057db96d56Sopenharmony_ci        This is not implemented for read-only and non-blocking streams.
4067db96d56Sopenharmony_ci        """
4077db96d56Sopenharmony_ci        self._checkClosed()
4087db96d56Sopenharmony_ci        # XXX Should this return the number of bytes written???
4097db96d56Sopenharmony_ci
4107db96d56Sopenharmony_ci    __closed = False
4117db96d56Sopenharmony_ci
4127db96d56Sopenharmony_ci    def close(self):
4137db96d56Sopenharmony_ci        """Flush and close the IO object.
4147db96d56Sopenharmony_ci
4157db96d56Sopenharmony_ci        This method has no effect if the file is already closed.
4167db96d56Sopenharmony_ci        """
4177db96d56Sopenharmony_ci        if not self.__closed:
4187db96d56Sopenharmony_ci            try:
4197db96d56Sopenharmony_ci                self.flush()
4207db96d56Sopenharmony_ci            finally:
4217db96d56Sopenharmony_ci                self.__closed = True
4227db96d56Sopenharmony_ci
4237db96d56Sopenharmony_ci    def __del__(self):
4247db96d56Sopenharmony_ci        """Destructor.  Calls close()."""
4257db96d56Sopenharmony_ci        try:
4267db96d56Sopenharmony_ci            closed = self.closed
4277db96d56Sopenharmony_ci        except AttributeError:
4287db96d56Sopenharmony_ci            # If getting closed fails, then the object is probably
4297db96d56Sopenharmony_ci            # in an unusable state, so ignore.
4307db96d56Sopenharmony_ci            return
4317db96d56Sopenharmony_ci
4327db96d56Sopenharmony_ci        if closed:
4337db96d56Sopenharmony_ci            return
4347db96d56Sopenharmony_ci
4357db96d56Sopenharmony_ci        if _IOBASE_EMITS_UNRAISABLE:
4367db96d56Sopenharmony_ci            self.close()
4377db96d56Sopenharmony_ci        else:
4387db96d56Sopenharmony_ci            # The try/except block is in case this is called at program
4397db96d56Sopenharmony_ci            # exit time, when it's possible that globals have already been
4407db96d56Sopenharmony_ci            # deleted, and then the close() call might fail.  Since
4417db96d56Sopenharmony_ci            # there's nothing we can do about such failures and they annoy
4427db96d56Sopenharmony_ci            # the end users, we suppress the traceback.
4437db96d56Sopenharmony_ci            try:
4447db96d56Sopenharmony_ci                self.close()
4457db96d56Sopenharmony_ci            except:
4467db96d56Sopenharmony_ci                pass
4477db96d56Sopenharmony_ci
4487db96d56Sopenharmony_ci    ### Inquiries ###
4497db96d56Sopenharmony_ci
4507db96d56Sopenharmony_ci    def seekable(self):
4517db96d56Sopenharmony_ci        """Return a bool indicating whether object supports random access.
4527db96d56Sopenharmony_ci
4537db96d56Sopenharmony_ci        If False, seek(), tell() and truncate() will raise OSError.
4547db96d56Sopenharmony_ci        This method may need to do a test seek().
4557db96d56Sopenharmony_ci        """
4567db96d56Sopenharmony_ci        return False
4577db96d56Sopenharmony_ci
4587db96d56Sopenharmony_ci    def _checkSeekable(self, msg=None):
4597db96d56Sopenharmony_ci        """Internal: raise UnsupportedOperation if file is not seekable
4607db96d56Sopenharmony_ci        """
4617db96d56Sopenharmony_ci        if not self.seekable():
4627db96d56Sopenharmony_ci            raise UnsupportedOperation("File or stream is not seekable."
4637db96d56Sopenharmony_ci                                       if msg is None else msg)
4647db96d56Sopenharmony_ci
4657db96d56Sopenharmony_ci    def readable(self):
4667db96d56Sopenharmony_ci        """Return a bool indicating whether object was opened for reading.
4677db96d56Sopenharmony_ci
4687db96d56Sopenharmony_ci        If False, read() will raise OSError.
4697db96d56Sopenharmony_ci        """
4707db96d56Sopenharmony_ci        return False
4717db96d56Sopenharmony_ci
4727db96d56Sopenharmony_ci    def _checkReadable(self, msg=None):
4737db96d56Sopenharmony_ci        """Internal: raise UnsupportedOperation if file is not readable
4747db96d56Sopenharmony_ci        """
4757db96d56Sopenharmony_ci        if not self.readable():
4767db96d56Sopenharmony_ci            raise UnsupportedOperation("File or stream is not readable."
4777db96d56Sopenharmony_ci                                       if msg is None else msg)
4787db96d56Sopenharmony_ci
4797db96d56Sopenharmony_ci    def writable(self):
4807db96d56Sopenharmony_ci        """Return a bool indicating whether object was opened for writing.
4817db96d56Sopenharmony_ci
4827db96d56Sopenharmony_ci        If False, write() and truncate() will raise OSError.
4837db96d56Sopenharmony_ci        """
4847db96d56Sopenharmony_ci        return False
4857db96d56Sopenharmony_ci
4867db96d56Sopenharmony_ci    def _checkWritable(self, msg=None):
4877db96d56Sopenharmony_ci        """Internal: raise UnsupportedOperation if file is not writable
4887db96d56Sopenharmony_ci        """
4897db96d56Sopenharmony_ci        if not self.writable():
4907db96d56Sopenharmony_ci            raise UnsupportedOperation("File or stream is not writable."
4917db96d56Sopenharmony_ci                                       if msg is None else msg)
4927db96d56Sopenharmony_ci
4937db96d56Sopenharmony_ci    @property
4947db96d56Sopenharmony_ci    def closed(self):
4957db96d56Sopenharmony_ci        """closed: bool.  True iff the file has been closed.
4967db96d56Sopenharmony_ci
4977db96d56Sopenharmony_ci        For backwards compatibility, this is a property, not a predicate.
4987db96d56Sopenharmony_ci        """
4997db96d56Sopenharmony_ci        return self.__closed
5007db96d56Sopenharmony_ci
5017db96d56Sopenharmony_ci    def _checkClosed(self, msg=None):
5027db96d56Sopenharmony_ci        """Internal: raise a ValueError if file is closed
5037db96d56Sopenharmony_ci        """
5047db96d56Sopenharmony_ci        if self.closed:
5057db96d56Sopenharmony_ci            raise ValueError("I/O operation on closed file."
5067db96d56Sopenharmony_ci                             if msg is None else msg)
5077db96d56Sopenharmony_ci
5087db96d56Sopenharmony_ci    ### Context manager ###
5097db96d56Sopenharmony_ci
5107db96d56Sopenharmony_ci    def __enter__(self):  # That's a forward reference
5117db96d56Sopenharmony_ci        """Context management protocol.  Returns self (an instance of IOBase)."""
5127db96d56Sopenharmony_ci        self._checkClosed()
5137db96d56Sopenharmony_ci        return self
5147db96d56Sopenharmony_ci
5157db96d56Sopenharmony_ci    def __exit__(self, *args):
5167db96d56Sopenharmony_ci        """Context management protocol.  Calls close()"""
5177db96d56Sopenharmony_ci        self.close()
5187db96d56Sopenharmony_ci
5197db96d56Sopenharmony_ci    ### Lower-level APIs ###
5207db96d56Sopenharmony_ci
5217db96d56Sopenharmony_ci    # XXX Should these be present even if unimplemented?
5227db96d56Sopenharmony_ci
5237db96d56Sopenharmony_ci    def fileno(self):
5247db96d56Sopenharmony_ci        """Returns underlying file descriptor (an int) if one exists.
5257db96d56Sopenharmony_ci
5267db96d56Sopenharmony_ci        An OSError is raised if the IO object does not use a file descriptor.
5277db96d56Sopenharmony_ci        """
5287db96d56Sopenharmony_ci        self._unsupported("fileno")
5297db96d56Sopenharmony_ci
5307db96d56Sopenharmony_ci    def isatty(self):
5317db96d56Sopenharmony_ci        """Return a bool indicating whether this is an 'interactive' stream.
5327db96d56Sopenharmony_ci
5337db96d56Sopenharmony_ci        Return False if it can't be determined.
5347db96d56Sopenharmony_ci        """
5357db96d56Sopenharmony_ci        self._checkClosed()
5367db96d56Sopenharmony_ci        return False
5377db96d56Sopenharmony_ci
5387db96d56Sopenharmony_ci    ### Readline[s] and writelines ###
5397db96d56Sopenharmony_ci
5407db96d56Sopenharmony_ci    def readline(self, size=-1):
5417db96d56Sopenharmony_ci        r"""Read and return a line of bytes from the stream.
5427db96d56Sopenharmony_ci
5437db96d56Sopenharmony_ci        If size is specified, at most size bytes will be read.
5447db96d56Sopenharmony_ci        Size should be an int.
5457db96d56Sopenharmony_ci
5467db96d56Sopenharmony_ci        The line terminator is always b'\n' for binary files; for text
5477db96d56Sopenharmony_ci        files, the newlines argument to open can be used to select the line
5487db96d56Sopenharmony_ci        terminator(s) recognized.
5497db96d56Sopenharmony_ci        """
5507db96d56Sopenharmony_ci        # For backwards compatibility, a (slowish) readline().
5517db96d56Sopenharmony_ci        if hasattr(self, "peek"):
5527db96d56Sopenharmony_ci            def nreadahead():
5537db96d56Sopenharmony_ci                readahead = self.peek(1)
5547db96d56Sopenharmony_ci                if not readahead:
5557db96d56Sopenharmony_ci                    return 1
5567db96d56Sopenharmony_ci                n = (readahead.find(b"\n") + 1) or len(readahead)
5577db96d56Sopenharmony_ci                if size >= 0:
5587db96d56Sopenharmony_ci                    n = min(n, size)
5597db96d56Sopenharmony_ci                return n
5607db96d56Sopenharmony_ci        else:
5617db96d56Sopenharmony_ci            def nreadahead():
5627db96d56Sopenharmony_ci                return 1
5637db96d56Sopenharmony_ci        if size is None:
5647db96d56Sopenharmony_ci            size = -1
5657db96d56Sopenharmony_ci        else:
5667db96d56Sopenharmony_ci            try:
5677db96d56Sopenharmony_ci                size_index = size.__index__
5687db96d56Sopenharmony_ci            except AttributeError:
5697db96d56Sopenharmony_ci                raise TypeError(f"{size!r} is not an integer")
5707db96d56Sopenharmony_ci            else:
5717db96d56Sopenharmony_ci                size = size_index()
5727db96d56Sopenharmony_ci        res = bytearray()
5737db96d56Sopenharmony_ci        while size < 0 or len(res) < size:
5747db96d56Sopenharmony_ci            b = self.read(nreadahead())
5757db96d56Sopenharmony_ci            if not b:
5767db96d56Sopenharmony_ci                break
5777db96d56Sopenharmony_ci            res += b
5787db96d56Sopenharmony_ci            if res.endswith(b"\n"):
5797db96d56Sopenharmony_ci                break
5807db96d56Sopenharmony_ci        return bytes(res)
5817db96d56Sopenharmony_ci
5827db96d56Sopenharmony_ci    def __iter__(self):
5837db96d56Sopenharmony_ci        self._checkClosed()
5847db96d56Sopenharmony_ci        return self
5857db96d56Sopenharmony_ci
5867db96d56Sopenharmony_ci    def __next__(self):
5877db96d56Sopenharmony_ci        line = self.readline()
5887db96d56Sopenharmony_ci        if not line:
5897db96d56Sopenharmony_ci            raise StopIteration
5907db96d56Sopenharmony_ci        return line
5917db96d56Sopenharmony_ci
5927db96d56Sopenharmony_ci    def readlines(self, hint=None):
5937db96d56Sopenharmony_ci        """Return a list of lines from the stream.
5947db96d56Sopenharmony_ci
5957db96d56Sopenharmony_ci        hint can be specified to control the number of lines read: no more
5967db96d56Sopenharmony_ci        lines will be read if the total size (in bytes/characters) of all
5977db96d56Sopenharmony_ci        lines so far exceeds hint.
5987db96d56Sopenharmony_ci        """
5997db96d56Sopenharmony_ci        if hint is None or hint <= 0:
6007db96d56Sopenharmony_ci            return list(self)
6017db96d56Sopenharmony_ci        n = 0
6027db96d56Sopenharmony_ci        lines = []
6037db96d56Sopenharmony_ci        for line in self:
6047db96d56Sopenharmony_ci            lines.append(line)
6057db96d56Sopenharmony_ci            n += len(line)
6067db96d56Sopenharmony_ci            if n >= hint:
6077db96d56Sopenharmony_ci                break
6087db96d56Sopenharmony_ci        return lines
6097db96d56Sopenharmony_ci
6107db96d56Sopenharmony_ci    def writelines(self, lines):
6117db96d56Sopenharmony_ci        """Write a list of lines to the stream.
6127db96d56Sopenharmony_ci
6137db96d56Sopenharmony_ci        Line separators are not added, so it is usual for each of the lines
6147db96d56Sopenharmony_ci        provided to have a line separator at the end.
6157db96d56Sopenharmony_ci        """
6167db96d56Sopenharmony_ci        self._checkClosed()
6177db96d56Sopenharmony_ci        for line in lines:
6187db96d56Sopenharmony_ci            self.write(line)
6197db96d56Sopenharmony_ci
6207db96d56Sopenharmony_ciio.IOBase.register(IOBase)
6217db96d56Sopenharmony_ci
6227db96d56Sopenharmony_ci
6237db96d56Sopenharmony_ciclass RawIOBase(IOBase):
6247db96d56Sopenharmony_ci
6257db96d56Sopenharmony_ci    """Base class for raw binary I/O."""
6267db96d56Sopenharmony_ci
6277db96d56Sopenharmony_ci    # The read() method is implemented by calling readinto(); derived
6287db96d56Sopenharmony_ci    # classes that want to support read() only need to implement
6297db96d56Sopenharmony_ci    # readinto() as a primitive operation.  In general, readinto() can be
6307db96d56Sopenharmony_ci    # more efficient than read().
6317db96d56Sopenharmony_ci
6327db96d56Sopenharmony_ci    # (It would be tempting to also provide an implementation of
6337db96d56Sopenharmony_ci    # readinto() in terms of read(), in case the latter is a more suitable
6347db96d56Sopenharmony_ci    # primitive operation, but that would lead to nasty recursion in case
6357db96d56Sopenharmony_ci    # a subclass doesn't implement either.)
6367db96d56Sopenharmony_ci
6377db96d56Sopenharmony_ci    def read(self, size=-1):
6387db96d56Sopenharmony_ci        """Read and return up to size bytes, where size is an int.
6397db96d56Sopenharmony_ci
6407db96d56Sopenharmony_ci        Returns an empty bytes object on EOF, or None if the object is
6417db96d56Sopenharmony_ci        set not to block and has no data to read.
6427db96d56Sopenharmony_ci        """
6437db96d56Sopenharmony_ci        if size is None:
6447db96d56Sopenharmony_ci            size = -1
6457db96d56Sopenharmony_ci        if size < 0:
6467db96d56Sopenharmony_ci            return self.readall()
6477db96d56Sopenharmony_ci        b = bytearray(size.__index__())
6487db96d56Sopenharmony_ci        n = self.readinto(b)
6497db96d56Sopenharmony_ci        if n is None:
6507db96d56Sopenharmony_ci            return None
6517db96d56Sopenharmony_ci        del b[n:]
6527db96d56Sopenharmony_ci        return bytes(b)
6537db96d56Sopenharmony_ci
6547db96d56Sopenharmony_ci    def readall(self):
6557db96d56Sopenharmony_ci        """Read until EOF, using multiple read() call."""
6567db96d56Sopenharmony_ci        res = bytearray()
6577db96d56Sopenharmony_ci        while True:
6587db96d56Sopenharmony_ci            data = self.read(DEFAULT_BUFFER_SIZE)
6597db96d56Sopenharmony_ci            if not data:
6607db96d56Sopenharmony_ci                break
6617db96d56Sopenharmony_ci            res += data
6627db96d56Sopenharmony_ci        if res:
6637db96d56Sopenharmony_ci            return bytes(res)
6647db96d56Sopenharmony_ci        else:
6657db96d56Sopenharmony_ci            # b'' or None
6667db96d56Sopenharmony_ci            return data
6677db96d56Sopenharmony_ci
6687db96d56Sopenharmony_ci    def readinto(self, b):
6697db96d56Sopenharmony_ci        """Read bytes into a pre-allocated bytes-like object b.
6707db96d56Sopenharmony_ci
6717db96d56Sopenharmony_ci        Returns an int representing the number of bytes read (0 for EOF), or
6727db96d56Sopenharmony_ci        None if the object is set not to block and has no data to read.
6737db96d56Sopenharmony_ci        """
6747db96d56Sopenharmony_ci        self._unsupported("readinto")
6757db96d56Sopenharmony_ci
6767db96d56Sopenharmony_ci    def write(self, b):
6777db96d56Sopenharmony_ci        """Write the given buffer to the IO stream.
6787db96d56Sopenharmony_ci
6797db96d56Sopenharmony_ci        Returns the number of bytes written, which may be less than the
6807db96d56Sopenharmony_ci        length of b in bytes.
6817db96d56Sopenharmony_ci        """
6827db96d56Sopenharmony_ci        self._unsupported("write")
6837db96d56Sopenharmony_ci
6847db96d56Sopenharmony_ciio.RawIOBase.register(RawIOBase)
6857db96d56Sopenharmony_cifrom _io import FileIO
6867db96d56Sopenharmony_ciRawIOBase.register(FileIO)
6877db96d56Sopenharmony_ci
6887db96d56Sopenharmony_ci
6897db96d56Sopenharmony_ciclass BufferedIOBase(IOBase):
6907db96d56Sopenharmony_ci
6917db96d56Sopenharmony_ci    """Base class for buffered IO objects.
6927db96d56Sopenharmony_ci
6937db96d56Sopenharmony_ci    The main difference with RawIOBase is that the read() method
6947db96d56Sopenharmony_ci    supports omitting the size argument, and does not have a default
6957db96d56Sopenharmony_ci    implementation that defers to readinto().
6967db96d56Sopenharmony_ci
6977db96d56Sopenharmony_ci    In addition, read(), readinto() and write() may raise
6987db96d56Sopenharmony_ci    BlockingIOError if the underlying raw stream is in non-blocking
6997db96d56Sopenharmony_ci    mode and not ready; unlike their raw counterparts, they will never
7007db96d56Sopenharmony_ci    return None.
7017db96d56Sopenharmony_ci
7027db96d56Sopenharmony_ci    A typical implementation should not inherit from a RawIOBase
7037db96d56Sopenharmony_ci    implementation, but wrap one.
7047db96d56Sopenharmony_ci    """
7057db96d56Sopenharmony_ci
7067db96d56Sopenharmony_ci    def read(self, size=-1):
7077db96d56Sopenharmony_ci        """Read and return up to size bytes, where size is an int.
7087db96d56Sopenharmony_ci
7097db96d56Sopenharmony_ci        If the argument is omitted, None, or negative, reads and
7107db96d56Sopenharmony_ci        returns all data until EOF.
7117db96d56Sopenharmony_ci
7127db96d56Sopenharmony_ci        If the argument is positive, and the underlying raw stream is
7137db96d56Sopenharmony_ci        not 'interactive', multiple raw reads may be issued to satisfy
7147db96d56Sopenharmony_ci        the byte count (unless EOF is reached first).  But for
7157db96d56Sopenharmony_ci        interactive raw streams (XXX and for pipes?), at most one raw
7167db96d56Sopenharmony_ci        read will be issued, and a short result does not imply that
7177db96d56Sopenharmony_ci        EOF is imminent.
7187db96d56Sopenharmony_ci
7197db96d56Sopenharmony_ci        Returns an empty bytes array on EOF.
7207db96d56Sopenharmony_ci
7217db96d56Sopenharmony_ci        Raises BlockingIOError if the underlying raw stream has no
7227db96d56Sopenharmony_ci        data at the moment.
7237db96d56Sopenharmony_ci        """
7247db96d56Sopenharmony_ci        self._unsupported("read")
7257db96d56Sopenharmony_ci
7267db96d56Sopenharmony_ci    def read1(self, size=-1):
7277db96d56Sopenharmony_ci        """Read up to size bytes with at most one read() system call,
7287db96d56Sopenharmony_ci        where size is an int.
7297db96d56Sopenharmony_ci        """
7307db96d56Sopenharmony_ci        self._unsupported("read1")
7317db96d56Sopenharmony_ci
7327db96d56Sopenharmony_ci    def readinto(self, b):
7337db96d56Sopenharmony_ci        """Read bytes into a pre-allocated bytes-like object b.
7347db96d56Sopenharmony_ci
7357db96d56Sopenharmony_ci        Like read(), this may issue multiple reads to the underlying raw
7367db96d56Sopenharmony_ci        stream, unless the latter is 'interactive'.
7377db96d56Sopenharmony_ci
7387db96d56Sopenharmony_ci        Returns an int representing the number of bytes read (0 for EOF).
7397db96d56Sopenharmony_ci
7407db96d56Sopenharmony_ci        Raises BlockingIOError if the underlying raw stream has no
7417db96d56Sopenharmony_ci        data at the moment.
7427db96d56Sopenharmony_ci        """
7437db96d56Sopenharmony_ci
7447db96d56Sopenharmony_ci        return self._readinto(b, read1=False)
7457db96d56Sopenharmony_ci
7467db96d56Sopenharmony_ci    def readinto1(self, b):
7477db96d56Sopenharmony_ci        """Read bytes into buffer *b*, using at most one system call
7487db96d56Sopenharmony_ci
7497db96d56Sopenharmony_ci        Returns an int representing the number of bytes read (0 for EOF).
7507db96d56Sopenharmony_ci
7517db96d56Sopenharmony_ci        Raises BlockingIOError if the underlying raw stream has no
7527db96d56Sopenharmony_ci        data at the moment.
7537db96d56Sopenharmony_ci        """
7547db96d56Sopenharmony_ci
7557db96d56Sopenharmony_ci        return self._readinto(b, read1=True)
7567db96d56Sopenharmony_ci
7577db96d56Sopenharmony_ci    def _readinto(self, b, read1):
7587db96d56Sopenharmony_ci        if not isinstance(b, memoryview):
7597db96d56Sopenharmony_ci            b = memoryview(b)
7607db96d56Sopenharmony_ci        b = b.cast('B')
7617db96d56Sopenharmony_ci
7627db96d56Sopenharmony_ci        if read1:
7637db96d56Sopenharmony_ci            data = self.read1(len(b))
7647db96d56Sopenharmony_ci        else:
7657db96d56Sopenharmony_ci            data = self.read(len(b))
7667db96d56Sopenharmony_ci        n = len(data)
7677db96d56Sopenharmony_ci
7687db96d56Sopenharmony_ci        b[:n] = data
7697db96d56Sopenharmony_ci
7707db96d56Sopenharmony_ci        return n
7717db96d56Sopenharmony_ci
7727db96d56Sopenharmony_ci    def write(self, b):
7737db96d56Sopenharmony_ci        """Write the given bytes buffer to the IO stream.
7747db96d56Sopenharmony_ci
7757db96d56Sopenharmony_ci        Return the number of bytes written, which is always the length of b
7767db96d56Sopenharmony_ci        in bytes.
7777db96d56Sopenharmony_ci
7787db96d56Sopenharmony_ci        Raises BlockingIOError if the buffer is full and the
7797db96d56Sopenharmony_ci        underlying raw stream cannot accept more data at the moment.
7807db96d56Sopenharmony_ci        """
7817db96d56Sopenharmony_ci        self._unsupported("write")
7827db96d56Sopenharmony_ci
7837db96d56Sopenharmony_ci    def detach(self):
7847db96d56Sopenharmony_ci        """
7857db96d56Sopenharmony_ci        Separate the underlying raw stream from the buffer and return it.
7867db96d56Sopenharmony_ci
7877db96d56Sopenharmony_ci        After the raw stream has been detached, the buffer is in an unusable
7887db96d56Sopenharmony_ci        state.
7897db96d56Sopenharmony_ci        """
7907db96d56Sopenharmony_ci        self._unsupported("detach")
7917db96d56Sopenharmony_ci
7927db96d56Sopenharmony_ciio.BufferedIOBase.register(BufferedIOBase)
7937db96d56Sopenharmony_ci
7947db96d56Sopenharmony_ci
7957db96d56Sopenharmony_ciclass _BufferedIOMixin(BufferedIOBase):
7967db96d56Sopenharmony_ci
7977db96d56Sopenharmony_ci    """A mixin implementation of BufferedIOBase with an underlying raw stream.
7987db96d56Sopenharmony_ci
7997db96d56Sopenharmony_ci    This passes most requests on to the underlying raw stream.  It
8007db96d56Sopenharmony_ci    does *not* provide implementations of read(), readinto() or
8017db96d56Sopenharmony_ci    write().
8027db96d56Sopenharmony_ci    """
8037db96d56Sopenharmony_ci
8047db96d56Sopenharmony_ci    def __init__(self, raw):
8057db96d56Sopenharmony_ci        self._raw = raw
8067db96d56Sopenharmony_ci
8077db96d56Sopenharmony_ci    ### Positioning ###
8087db96d56Sopenharmony_ci
8097db96d56Sopenharmony_ci    def seek(self, pos, whence=0):
8107db96d56Sopenharmony_ci        new_position = self.raw.seek(pos, whence)
8117db96d56Sopenharmony_ci        if new_position < 0:
8127db96d56Sopenharmony_ci            raise OSError("seek() returned an invalid position")
8137db96d56Sopenharmony_ci        return new_position
8147db96d56Sopenharmony_ci
8157db96d56Sopenharmony_ci    def tell(self):
8167db96d56Sopenharmony_ci        pos = self.raw.tell()
8177db96d56Sopenharmony_ci        if pos < 0:
8187db96d56Sopenharmony_ci            raise OSError("tell() returned an invalid position")
8197db96d56Sopenharmony_ci        return pos
8207db96d56Sopenharmony_ci
8217db96d56Sopenharmony_ci    def truncate(self, pos=None):
8227db96d56Sopenharmony_ci        self._checkClosed()
8237db96d56Sopenharmony_ci        self._checkWritable()
8247db96d56Sopenharmony_ci
8257db96d56Sopenharmony_ci        # Flush the stream.  We're mixing buffered I/O with lower-level I/O,
8267db96d56Sopenharmony_ci        # and a flush may be necessary to synch both views of the current
8277db96d56Sopenharmony_ci        # file state.
8287db96d56Sopenharmony_ci        self.flush()
8297db96d56Sopenharmony_ci
8307db96d56Sopenharmony_ci        if pos is None:
8317db96d56Sopenharmony_ci            pos = self.tell()
8327db96d56Sopenharmony_ci        # XXX: Should seek() be used, instead of passing the position
8337db96d56Sopenharmony_ci        # XXX  directly to truncate?
8347db96d56Sopenharmony_ci        return self.raw.truncate(pos)
8357db96d56Sopenharmony_ci
8367db96d56Sopenharmony_ci    ### Flush and close ###
8377db96d56Sopenharmony_ci
8387db96d56Sopenharmony_ci    def flush(self):
8397db96d56Sopenharmony_ci        if self.closed:
8407db96d56Sopenharmony_ci            raise ValueError("flush on closed file")
8417db96d56Sopenharmony_ci        self.raw.flush()
8427db96d56Sopenharmony_ci
8437db96d56Sopenharmony_ci    def close(self):
8447db96d56Sopenharmony_ci        if self.raw is not None and not self.closed:
8457db96d56Sopenharmony_ci            try:
8467db96d56Sopenharmony_ci                # may raise BlockingIOError or BrokenPipeError etc
8477db96d56Sopenharmony_ci                self.flush()
8487db96d56Sopenharmony_ci            finally:
8497db96d56Sopenharmony_ci                self.raw.close()
8507db96d56Sopenharmony_ci
8517db96d56Sopenharmony_ci    def detach(self):
8527db96d56Sopenharmony_ci        if self.raw is None:
8537db96d56Sopenharmony_ci            raise ValueError("raw stream already detached")
8547db96d56Sopenharmony_ci        self.flush()
8557db96d56Sopenharmony_ci        raw = self._raw
8567db96d56Sopenharmony_ci        self._raw = None
8577db96d56Sopenharmony_ci        return raw
8587db96d56Sopenharmony_ci
8597db96d56Sopenharmony_ci    ### Inquiries ###
8607db96d56Sopenharmony_ci
8617db96d56Sopenharmony_ci    def seekable(self):
8627db96d56Sopenharmony_ci        return self.raw.seekable()
8637db96d56Sopenharmony_ci
8647db96d56Sopenharmony_ci    @property
8657db96d56Sopenharmony_ci    def raw(self):
8667db96d56Sopenharmony_ci        return self._raw
8677db96d56Sopenharmony_ci
8687db96d56Sopenharmony_ci    @property
8697db96d56Sopenharmony_ci    def closed(self):
8707db96d56Sopenharmony_ci        return self.raw.closed
8717db96d56Sopenharmony_ci
8727db96d56Sopenharmony_ci    @property
8737db96d56Sopenharmony_ci    def name(self):
8747db96d56Sopenharmony_ci        return self.raw.name
8757db96d56Sopenharmony_ci
8767db96d56Sopenharmony_ci    @property
8777db96d56Sopenharmony_ci    def mode(self):
8787db96d56Sopenharmony_ci        return self.raw.mode
8797db96d56Sopenharmony_ci
8807db96d56Sopenharmony_ci    def __getstate__(self):
8817db96d56Sopenharmony_ci        raise TypeError(f"cannot pickle {self.__class__.__name__!r} object")
8827db96d56Sopenharmony_ci
8837db96d56Sopenharmony_ci    def __repr__(self):
8847db96d56Sopenharmony_ci        modname = self.__class__.__module__
8857db96d56Sopenharmony_ci        clsname = self.__class__.__qualname__
8867db96d56Sopenharmony_ci        try:
8877db96d56Sopenharmony_ci            name = self.name
8887db96d56Sopenharmony_ci        except AttributeError:
8897db96d56Sopenharmony_ci            return "<{}.{}>".format(modname, clsname)
8907db96d56Sopenharmony_ci        else:
8917db96d56Sopenharmony_ci            return "<{}.{} name={!r}>".format(modname, clsname, name)
8927db96d56Sopenharmony_ci
8937db96d56Sopenharmony_ci    ### Lower-level APIs ###
8947db96d56Sopenharmony_ci
8957db96d56Sopenharmony_ci    def fileno(self):
8967db96d56Sopenharmony_ci        return self.raw.fileno()
8977db96d56Sopenharmony_ci
8987db96d56Sopenharmony_ci    def isatty(self):
8997db96d56Sopenharmony_ci        return self.raw.isatty()
9007db96d56Sopenharmony_ci
9017db96d56Sopenharmony_ci
9027db96d56Sopenharmony_ciclass BytesIO(BufferedIOBase):
9037db96d56Sopenharmony_ci
9047db96d56Sopenharmony_ci    """Buffered I/O implementation using an in-memory bytes buffer."""
9057db96d56Sopenharmony_ci
9067db96d56Sopenharmony_ci    # Initialize _buffer as soon as possible since it's used by __del__()
9077db96d56Sopenharmony_ci    # which calls close()
9087db96d56Sopenharmony_ci    _buffer = None
9097db96d56Sopenharmony_ci
9107db96d56Sopenharmony_ci    def __init__(self, initial_bytes=None):
9117db96d56Sopenharmony_ci        buf = bytearray()
9127db96d56Sopenharmony_ci        if initial_bytes is not None:
9137db96d56Sopenharmony_ci            buf += initial_bytes
9147db96d56Sopenharmony_ci        self._buffer = buf
9157db96d56Sopenharmony_ci        self._pos = 0
9167db96d56Sopenharmony_ci
9177db96d56Sopenharmony_ci    def __getstate__(self):
9187db96d56Sopenharmony_ci        if self.closed:
9197db96d56Sopenharmony_ci            raise ValueError("__getstate__ on closed file")
9207db96d56Sopenharmony_ci        return self.__dict__.copy()
9217db96d56Sopenharmony_ci
9227db96d56Sopenharmony_ci    def getvalue(self):
9237db96d56Sopenharmony_ci        """Return the bytes value (contents) of the buffer
9247db96d56Sopenharmony_ci        """
9257db96d56Sopenharmony_ci        if self.closed:
9267db96d56Sopenharmony_ci            raise ValueError("getvalue on closed file")
9277db96d56Sopenharmony_ci        return bytes(self._buffer)
9287db96d56Sopenharmony_ci
9297db96d56Sopenharmony_ci    def getbuffer(self):
9307db96d56Sopenharmony_ci        """Return a readable and writable view of the buffer.
9317db96d56Sopenharmony_ci        """
9327db96d56Sopenharmony_ci        if self.closed:
9337db96d56Sopenharmony_ci            raise ValueError("getbuffer on closed file")
9347db96d56Sopenharmony_ci        return memoryview(self._buffer)
9357db96d56Sopenharmony_ci
9367db96d56Sopenharmony_ci    def close(self):
9377db96d56Sopenharmony_ci        if self._buffer is not None:
9387db96d56Sopenharmony_ci            self._buffer.clear()
9397db96d56Sopenharmony_ci        super().close()
9407db96d56Sopenharmony_ci
9417db96d56Sopenharmony_ci    def read(self, size=-1):
9427db96d56Sopenharmony_ci        if self.closed:
9437db96d56Sopenharmony_ci            raise ValueError("read from closed file")
9447db96d56Sopenharmony_ci        if size is None:
9457db96d56Sopenharmony_ci            size = -1
9467db96d56Sopenharmony_ci        else:
9477db96d56Sopenharmony_ci            try:
9487db96d56Sopenharmony_ci                size_index = size.__index__
9497db96d56Sopenharmony_ci            except AttributeError:
9507db96d56Sopenharmony_ci                raise TypeError(f"{size!r} is not an integer")
9517db96d56Sopenharmony_ci            else:
9527db96d56Sopenharmony_ci                size = size_index()
9537db96d56Sopenharmony_ci        if size < 0:
9547db96d56Sopenharmony_ci            size = len(self._buffer)
9557db96d56Sopenharmony_ci        if len(self._buffer) <= self._pos:
9567db96d56Sopenharmony_ci            return b""
9577db96d56Sopenharmony_ci        newpos = min(len(self._buffer), self._pos + size)
9587db96d56Sopenharmony_ci        b = self._buffer[self._pos : newpos]
9597db96d56Sopenharmony_ci        self._pos = newpos
9607db96d56Sopenharmony_ci        return bytes(b)
9617db96d56Sopenharmony_ci
9627db96d56Sopenharmony_ci    def read1(self, size=-1):
9637db96d56Sopenharmony_ci        """This is the same as read.
9647db96d56Sopenharmony_ci        """
9657db96d56Sopenharmony_ci        return self.read(size)
9667db96d56Sopenharmony_ci
9677db96d56Sopenharmony_ci    def write(self, b):
9687db96d56Sopenharmony_ci        if self.closed:
9697db96d56Sopenharmony_ci            raise ValueError("write to closed file")
9707db96d56Sopenharmony_ci        if isinstance(b, str):
9717db96d56Sopenharmony_ci            raise TypeError("can't write str to binary stream")
9727db96d56Sopenharmony_ci        with memoryview(b) as view:
9737db96d56Sopenharmony_ci            n = view.nbytes  # Size of any bytes-like object
9747db96d56Sopenharmony_ci        if n == 0:
9757db96d56Sopenharmony_ci            return 0
9767db96d56Sopenharmony_ci        pos = self._pos
9777db96d56Sopenharmony_ci        if pos > len(self._buffer):
9787db96d56Sopenharmony_ci            # Inserts null bytes between the current end of the file
9797db96d56Sopenharmony_ci            # and the new write position.
9807db96d56Sopenharmony_ci            padding = b'\x00' * (pos - len(self._buffer))
9817db96d56Sopenharmony_ci            self._buffer += padding
9827db96d56Sopenharmony_ci        self._buffer[pos:pos + n] = b
9837db96d56Sopenharmony_ci        self._pos += n
9847db96d56Sopenharmony_ci        return n
9857db96d56Sopenharmony_ci
9867db96d56Sopenharmony_ci    def seek(self, pos, whence=0):
9877db96d56Sopenharmony_ci        if self.closed:
9887db96d56Sopenharmony_ci            raise ValueError("seek on closed file")
9897db96d56Sopenharmony_ci        try:
9907db96d56Sopenharmony_ci            pos_index = pos.__index__
9917db96d56Sopenharmony_ci        except AttributeError:
9927db96d56Sopenharmony_ci            raise TypeError(f"{pos!r} is not an integer")
9937db96d56Sopenharmony_ci        else:
9947db96d56Sopenharmony_ci            pos = pos_index()
9957db96d56Sopenharmony_ci        if whence == 0:
9967db96d56Sopenharmony_ci            if pos < 0:
9977db96d56Sopenharmony_ci                raise ValueError("negative seek position %r" % (pos,))
9987db96d56Sopenharmony_ci            self._pos = pos
9997db96d56Sopenharmony_ci        elif whence == 1:
10007db96d56Sopenharmony_ci            self._pos = max(0, self._pos + pos)
10017db96d56Sopenharmony_ci        elif whence == 2:
10027db96d56Sopenharmony_ci            self._pos = max(0, len(self._buffer) + pos)
10037db96d56Sopenharmony_ci        else:
10047db96d56Sopenharmony_ci            raise ValueError("unsupported whence value")
10057db96d56Sopenharmony_ci        return self._pos
10067db96d56Sopenharmony_ci
10077db96d56Sopenharmony_ci    def tell(self):
10087db96d56Sopenharmony_ci        if self.closed:
10097db96d56Sopenharmony_ci            raise ValueError("tell on closed file")
10107db96d56Sopenharmony_ci        return self._pos
10117db96d56Sopenharmony_ci
10127db96d56Sopenharmony_ci    def truncate(self, pos=None):
10137db96d56Sopenharmony_ci        if self.closed:
10147db96d56Sopenharmony_ci            raise ValueError("truncate on closed file")
10157db96d56Sopenharmony_ci        if pos is None:
10167db96d56Sopenharmony_ci            pos = self._pos
10177db96d56Sopenharmony_ci        else:
10187db96d56Sopenharmony_ci            try:
10197db96d56Sopenharmony_ci                pos_index = pos.__index__
10207db96d56Sopenharmony_ci            except AttributeError:
10217db96d56Sopenharmony_ci                raise TypeError(f"{pos!r} is not an integer")
10227db96d56Sopenharmony_ci            else:
10237db96d56Sopenharmony_ci                pos = pos_index()
10247db96d56Sopenharmony_ci            if pos < 0:
10257db96d56Sopenharmony_ci                raise ValueError("negative truncate position %r" % (pos,))
10267db96d56Sopenharmony_ci        del self._buffer[pos:]
10277db96d56Sopenharmony_ci        return pos
10287db96d56Sopenharmony_ci
10297db96d56Sopenharmony_ci    def readable(self):
10307db96d56Sopenharmony_ci        if self.closed:
10317db96d56Sopenharmony_ci            raise ValueError("I/O operation on closed file.")
10327db96d56Sopenharmony_ci        return True
10337db96d56Sopenharmony_ci
10347db96d56Sopenharmony_ci    def writable(self):
10357db96d56Sopenharmony_ci        if self.closed:
10367db96d56Sopenharmony_ci            raise ValueError("I/O operation on closed file.")
10377db96d56Sopenharmony_ci        return True
10387db96d56Sopenharmony_ci
10397db96d56Sopenharmony_ci    def seekable(self):
10407db96d56Sopenharmony_ci        if self.closed:
10417db96d56Sopenharmony_ci            raise ValueError("I/O operation on closed file.")
10427db96d56Sopenharmony_ci        return True
10437db96d56Sopenharmony_ci
10447db96d56Sopenharmony_ci
10457db96d56Sopenharmony_ciclass BufferedReader(_BufferedIOMixin):
10467db96d56Sopenharmony_ci
10477db96d56Sopenharmony_ci    """BufferedReader(raw[, buffer_size])
10487db96d56Sopenharmony_ci
10497db96d56Sopenharmony_ci    A buffer for a readable, sequential BaseRawIO object.
10507db96d56Sopenharmony_ci
10517db96d56Sopenharmony_ci    The constructor creates a BufferedReader for the given readable raw
10527db96d56Sopenharmony_ci    stream and buffer_size. If buffer_size is omitted, DEFAULT_BUFFER_SIZE
10537db96d56Sopenharmony_ci    is used.
10547db96d56Sopenharmony_ci    """
10557db96d56Sopenharmony_ci
10567db96d56Sopenharmony_ci    def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE):
10577db96d56Sopenharmony_ci        """Create a new buffered reader using the given readable raw IO object.
10587db96d56Sopenharmony_ci        """
10597db96d56Sopenharmony_ci        if not raw.readable():
10607db96d56Sopenharmony_ci            raise OSError('"raw" argument must be readable.')
10617db96d56Sopenharmony_ci
10627db96d56Sopenharmony_ci        _BufferedIOMixin.__init__(self, raw)
10637db96d56Sopenharmony_ci        if buffer_size <= 0:
10647db96d56Sopenharmony_ci            raise ValueError("invalid buffer size")
10657db96d56Sopenharmony_ci        self.buffer_size = buffer_size
10667db96d56Sopenharmony_ci        self._reset_read_buf()
10677db96d56Sopenharmony_ci        self._read_lock = Lock()
10687db96d56Sopenharmony_ci
10697db96d56Sopenharmony_ci    def readable(self):
10707db96d56Sopenharmony_ci        return self.raw.readable()
10717db96d56Sopenharmony_ci
10727db96d56Sopenharmony_ci    def _reset_read_buf(self):
10737db96d56Sopenharmony_ci        self._read_buf = b""
10747db96d56Sopenharmony_ci        self._read_pos = 0
10757db96d56Sopenharmony_ci
10767db96d56Sopenharmony_ci    def read(self, size=None):
10777db96d56Sopenharmony_ci        """Read size bytes.
10787db96d56Sopenharmony_ci
10797db96d56Sopenharmony_ci        Returns exactly size bytes of data unless the underlying raw IO
10807db96d56Sopenharmony_ci        stream reaches EOF or if the call would block in non-blocking
10817db96d56Sopenharmony_ci        mode. If size is negative, read until EOF or until read() would
10827db96d56Sopenharmony_ci        block.
10837db96d56Sopenharmony_ci        """
10847db96d56Sopenharmony_ci        if size is not None and size < -1:
10857db96d56Sopenharmony_ci            raise ValueError("invalid number of bytes to read")
10867db96d56Sopenharmony_ci        with self._read_lock:
10877db96d56Sopenharmony_ci            return self._read_unlocked(size)
10887db96d56Sopenharmony_ci
10897db96d56Sopenharmony_ci    def _read_unlocked(self, n=None):
10907db96d56Sopenharmony_ci        nodata_val = b""
10917db96d56Sopenharmony_ci        empty_values = (b"", None)
10927db96d56Sopenharmony_ci        buf = self._read_buf
10937db96d56Sopenharmony_ci        pos = self._read_pos
10947db96d56Sopenharmony_ci
10957db96d56Sopenharmony_ci        # Special case for when the number of bytes to read is unspecified.
10967db96d56Sopenharmony_ci        if n is None or n == -1:
10977db96d56Sopenharmony_ci            self._reset_read_buf()
10987db96d56Sopenharmony_ci            if hasattr(self.raw, 'readall'):
10997db96d56Sopenharmony_ci                chunk = self.raw.readall()
11007db96d56Sopenharmony_ci                if chunk is None:
11017db96d56Sopenharmony_ci                    return buf[pos:] or None
11027db96d56Sopenharmony_ci                else:
11037db96d56Sopenharmony_ci                    return buf[pos:] + chunk
11047db96d56Sopenharmony_ci            chunks = [buf[pos:]]  # Strip the consumed bytes.
11057db96d56Sopenharmony_ci            current_size = 0
11067db96d56Sopenharmony_ci            while True:
11077db96d56Sopenharmony_ci                # Read until EOF or until read() would block.
11087db96d56Sopenharmony_ci                chunk = self.raw.read()
11097db96d56Sopenharmony_ci                if chunk in empty_values:
11107db96d56Sopenharmony_ci                    nodata_val = chunk
11117db96d56Sopenharmony_ci                    break
11127db96d56Sopenharmony_ci                current_size += len(chunk)
11137db96d56Sopenharmony_ci                chunks.append(chunk)
11147db96d56Sopenharmony_ci            return b"".join(chunks) or nodata_val
11157db96d56Sopenharmony_ci
11167db96d56Sopenharmony_ci        # The number of bytes to read is specified, return at most n bytes.
11177db96d56Sopenharmony_ci        avail = len(buf) - pos  # Length of the available buffered data.
11187db96d56Sopenharmony_ci        if n <= avail:
11197db96d56Sopenharmony_ci            # Fast path: the data to read is fully buffered.
11207db96d56Sopenharmony_ci            self._read_pos += n
11217db96d56Sopenharmony_ci            return buf[pos:pos+n]
11227db96d56Sopenharmony_ci        # Slow path: read from the stream until enough bytes are read,
11237db96d56Sopenharmony_ci        # or until an EOF occurs or until read() would block.
11247db96d56Sopenharmony_ci        chunks = [buf[pos:]]
11257db96d56Sopenharmony_ci        wanted = max(self.buffer_size, n)
11267db96d56Sopenharmony_ci        while avail < n:
11277db96d56Sopenharmony_ci            chunk = self.raw.read(wanted)
11287db96d56Sopenharmony_ci            if chunk in empty_values:
11297db96d56Sopenharmony_ci                nodata_val = chunk
11307db96d56Sopenharmony_ci                break
11317db96d56Sopenharmony_ci            avail += len(chunk)
11327db96d56Sopenharmony_ci            chunks.append(chunk)
11337db96d56Sopenharmony_ci        # n is more than avail only when an EOF occurred or when
11347db96d56Sopenharmony_ci        # read() would have blocked.
11357db96d56Sopenharmony_ci        n = min(n, avail)
11367db96d56Sopenharmony_ci        out = b"".join(chunks)
11377db96d56Sopenharmony_ci        self._read_buf = out[n:]  # Save the extra data in the buffer.
11387db96d56Sopenharmony_ci        self._read_pos = 0
11397db96d56Sopenharmony_ci        return out[:n] if out else nodata_val
11407db96d56Sopenharmony_ci
11417db96d56Sopenharmony_ci    def peek(self, size=0):
11427db96d56Sopenharmony_ci        """Returns buffered bytes without advancing the position.
11437db96d56Sopenharmony_ci
11447db96d56Sopenharmony_ci        The argument indicates a desired minimal number of bytes; we
11457db96d56Sopenharmony_ci        do at most one raw read to satisfy it.  We never return more
11467db96d56Sopenharmony_ci        than self.buffer_size.
11477db96d56Sopenharmony_ci        """
11487db96d56Sopenharmony_ci        with self._read_lock:
11497db96d56Sopenharmony_ci            return self._peek_unlocked(size)
11507db96d56Sopenharmony_ci
11517db96d56Sopenharmony_ci    def _peek_unlocked(self, n=0):
11527db96d56Sopenharmony_ci        want = min(n, self.buffer_size)
11537db96d56Sopenharmony_ci        have = len(self._read_buf) - self._read_pos
11547db96d56Sopenharmony_ci        if have < want or have <= 0:
11557db96d56Sopenharmony_ci            to_read = self.buffer_size - have
11567db96d56Sopenharmony_ci            current = self.raw.read(to_read)
11577db96d56Sopenharmony_ci            if current:
11587db96d56Sopenharmony_ci                self._read_buf = self._read_buf[self._read_pos:] + current
11597db96d56Sopenharmony_ci                self._read_pos = 0
11607db96d56Sopenharmony_ci        return self._read_buf[self._read_pos:]
11617db96d56Sopenharmony_ci
11627db96d56Sopenharmony_ci    def read1(self, size=-1):
11637db96d56Sopenharmony_ci        """Reads up to size bytes, with at most one read() system call."""
11647db96d56Sopenharmony_ci        # Returns up to size bytes.  If at least one byte is buffered, we
11657db96d56Sopenharmony_ci        # only return buffered bytes.  Otherwise, we do one raw read.
11667db96d56Sopenharmony_ci        if size < 0:
11677db96d56Sopenharmony_ci            size = self.buffer_size
11687db96d56Sopenharmony_ci        if size == 0:
11697db96d56Sopenharmony_ci            return b""
11707db96d56Sopenharmony_ci        with self._read_lock:
11717db96d56Sopenharmony_ci            self._peek_unlocked(1)
11727db96d56Sopenharmony_ci            return self._read_unlocked(
11737db96d56Sopenharmony_ci                min(size, len(self._read_buf) - self._read_pos))
11747db96d56Sopenharmony_ci
11757db96d56Sopenharmony_ci    # Implementing readinto() and readinto1() is not strictly necessary (we
11767db96d56Sopenharmony_ci    # could rely on the base class that provides an implementation in terms of
11777db96d56Sopenharmony_ci    # read() and read1()). We do it anyway to keep the _pyio implementation
11787db96d56Sopenharmony_ci    # similar to the io implementation (which implements the methods for
11797db96d56Sopenharmony_ci    # performance reasons).
11807db96d56Sopenharmony_ci    def _readinto(self, buf, read1):
11817db96d56Sopenharmony_ci        """Read data into *buf* with at most one system call."""
11827db96d56Sopenharmony_ci
11837db96d56Sopenharmony_ci        # Need to create a memoryview object of type 'b', otherwise
11847db96d56Sopenharmony_ci        # we may not be able to assign bytes to it, and slicing it
11857db96d56Sopenharmony_ci        # would create a new object.
11867db96d56Sopenharmony_ci        if not isinstance(buf, memoryview):
11877db96d56Sopenharmony_ci            buf = memoryview(buf)
11887db96d56Sopenharmony_ci        if buf.nbytes == 0:
11897db96d56Sopenharmony_ci            return 0
11907db96d56Sopenharmony_ci        buf = buf.cast('B')
11917db96d56Sopenharmony_ci
11927db96d56Sopenharmony_ci        written = 0
11937db96d56Sopenharmony_ci        with self._read_lock:
11947db96d56Sopenharmony_ci            while written < len(buf):
11957db96d56Sopenharmony_ci
11967db96d56Sopenharmony_ci                # First try to read from internal buffer
11977db96d56Sopenharmony_ci                avail = min(len(self._read_buf) - self._read_pos, len(buf))
11987db96d56Sopenharmony_ci                if avail:
11997db96d56Sopenharmony_ci                    buf[written:written+avail] = \
12007db96d56Sopenharmony_ci                        self._read_buf[self._read_pos:self._read_pos+avail]
12017db96d56Sopenharmony_ci                    self._read_pos += avail
12027db96d56Sopenharmony_ci                    written += avail
12037db96d56Sopenharmony_ci                    if written == len(buf):
12047db96d56Sopenharmony_ci                        break
12057db96d56Sopenharmony_ci
12067db96d56Sopenharmony_ci                # If remaining space in callers buffer is larger than
12077db96d56Sopenharmony_ci                # internal buffer, read directly into callers buffer
12087db96d56Sopenharmony_ci                if len(buf) - written > self.buffer_size:
12097db96d56Sopenharmony_ci                    n = self.raw.readinto(buf[written:])
12107db96d56Sopenharmony_ci                    if not n:
12117db96d56Sopenharmony_ci                        break # eof
12127db96d56Sopenharmony_ci                    written += n
12137db96d56Sopenharmony_ci
12147db96d56Sopenharmony_ci                # Otherwise refill internal buffer - unless we're
12157db96d56Sopenharmony_ci                # in read1 mode and already got some data
12167db96d56Sopenharmony_ci                elif not (read1 and written):
12177db96d56Sopenharmony_ci                    if not self._peek_unlocked(1):
12187db96d56Sopenharmony_ci                        break # eof
12197db96d56Sopenharmony_ci
12207db96d56Sopenharmony_ci                # In readinto1 mode, return as soon as we have some data
12217db96d56Sopenharmony_ci                if read1 and written:
12227db96d56Sopenharmony_ci                    break
12237db96d56Sopenharmony_ci
12247db96d56Sopenharmony_ci        return written
12257db96d56Sopenharmony_ci
12267db96d56Sopenharmony_ci    def tell(self):
12277db96d56Sopenharmony_ci        return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_pos
12287db96d56Sopenharmony_ci
12297db96d56Sopenharmony_ci    def seek(self, pos, whence=0):
12307db96d56Sopenharmony_ci        if whence not in valid_seek_flags:
12317db96d56Sopenharmony_ci            raise ValueError("invalid whence value")
12327db96d56Sopenharmony_ci        with self._read_lock:
12337db96d56Sopenharmony_ci            if whence == 1:
12347db96d56Sopenharmony_ci                pos -= len(self._read_buf) - self._read_pos
12357db96d56Sopenharmony_ci            pos = _BufferedIOMixin.seek(self, pos, whence)
12367db96d56Sopenharmony_ci            self._reset_read_buf()
12377db96d56Sopenharmony_ci            return pos
12387db96d56Sopenharmony_ci
12397db96d56Sopenharmony_ciclass BufferedWriter(_BufferedIOMixin):
12407db96d56Sopenharmony_ci
12417db96d56Sopenharmony_ci    """A buffer for a writeable sequential RawIO object.
12427db96d56Sopenharmony_ci
12437db96d56Sopenharmony_ci    The constructor creates a BufferedWriter for the given writeable raw
12447db96d56Sopenharmony_ci    stream. If the buffer_size is not given, it defaults to
12457db96d56Sopenharmony_ci    DEFAULT_BUFFER_SIZE.
12467db96d56Sopenharmony_ci    """
12477db96d56Sopenharmony_ci
12487db96d56Sopenharmony_ci    def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE):
12497db96d56Sopenharmony_ci        if not raw.writable():
12507db96d56Sopenharmony_ci            raise OSError('"raw" argument must be writable.')
12517db96d56Sopenharmony_ci
12527db96d56Sopenharmony_ci        _BufferedIOMixin.__init__(self, raw)
12537db96d56Sopenharmony_ci        if buffer_size <= 0:
12547db96d56Sopenharmony_ci            raise ValueError("invalid buffer size")
12557db96d56Sopenharmony_ci        self.buffer_size = buffer_size
12567db96d56Sopenharmony_ci        self._write_buf = bytearray()
12577db96d56Sopenharmony_ci        self._write_lock = Lock()
12587db96d56Sopenharmony_ci
12597db96d56Sopenharmony_ci    def writable(self):
12607db96d56Sopenharmony_ci        return self.raw.writable()
12617db96d56Sopenharmony_ci
12627db96d56Sopenharmony_ci    def write(self, b):
12637db96d56Sopenharmony_ci        if isinstance(b, str):
12647db96d56Sopenharmony_ci            raise TypeError("can't write str to binary stream")
12657db96d56Sopenharmony_ci        with self._write_lock:
12667db96d56Sopenharmony_ci            if self.closed:
12677db96d56Sopenharmony_ci                raise ValueError("write to closed file")
12687db96d56Sopenharmony_ci            # XXX we can implement some more tricks to try and avoid
12697db96d56Sopenharmony_ci            # partial writes
12707db96d56Sopenharmony_ci            if len(self._write_buf) > self.buffer_size:
12717db96d56Sopenharmony_ci                # We're full, so let's pre-flush the buffer.  (This may
12727db96d56Sopenharmony_ci                # raise BlockingIOError with characters_written == 0.)
12737db96d56Sopenharmony_ci                self._flush_unlocked()
12747db96d56Sopenharmony_ci            before = len(self._write_buf)
12757db96d56Sopenharmony_ci            self._write_buf.extend(b)
12767db96d56Sopenharmony_ci            written = len(self._write_buf) - before
12777db96d56Sopenharmony_ci            if len(self._write_buf) > self.buffer_size:
12787db96d56Sopenharmony_ci                try:
12797db96d56Sopenharmony_ci                    self._flush_unlocked()
12807db96d56Sopenharmony_ci                except BlockingIOError as e:
12817db96d56Sopenharmony_ci                    if len(self._write_buf) > self.buffer_size:
12827db96d56Sopenharmony_ci                        # We've hit the buffer_size. We have to accept a partial
12837db96d56Sopenharmony_ci                        # write and cut back our buffer.
12847db96d56Sopenharmony_ci                        overage = len(self._write_buf) - self.buffer_size
12857db96d56Sopenharmony_ci                        written -= overage
12867db96d56Sopenharmony_ci                        self._write_buf = self._write_buf[:self.buffer_size]
12877db96d56Sopenharmony_ci                        raise BlockingIOError(e.errno, e.strerror, written)
12887db96d56Sopenharmony_ci            return written
12897db96d56Sopenharmony_ci
12907db96d56Sopenharmony_ci    def truncate(self, pos=None):
12917db96d56Sopenharmony_ci        with self._write_lock:
12927db96d56Sopenharmony_ci            self._flush_unlocked()
12937db96d56Sopenharmony_ci            if pos is None:
12947db96d56Sopenharmony_ci                pos = self.raw.tell()
12957db96d56Sopenharmony_ci            return self.raw.truncate(pos)
12967db96d56Sopenharmony_ci
12977db96d56Sopenharmony_ci    def flush(self):
12987db96d56Sopenharmony_ci        with self._write_lock:
12997db96d56Sopenharmony_ci            self._flush_unlocked()
13007db96d56Sopenharmony_ci
13017db96d56Sopenharmony_ci    def _flush_unlocked(self):
13027db96d56Sopenharmony_ci        if self.closed:
13037db96d56Sopenharmony_ci            raise ValueError("flush on closed file")
13047db96d56Sopenharmony_ci        while self._write_buf:
13057db96d56Sopenharmony_ci            try:
13067db96d56Sopenharmony_ci                n = self.raw.write(self._write_buf)
13077db96d56Sopenharmony_ci            except BlockingIOError:
13087db96d56Sopenharmony_ci                raise RuntimeError("self.raw should implement RawIOBase: it "
13097db96d56Sopenharmony_ci                                   "should not raise BlockingIOError")
13107db96d56Sopenharmony_ci            if n is None:
13117db96d56Sopenharmony_ci                raise BlockingIOError(
13127db96d56Sopenharmony_ci                    errno.EAGAIN,
13137db96d56Sopenharmony_ci                    "write could not complete without blocking", 0)
13147db96d56Sopenharmony_ci            if n > len(self._write_buf) or n < 0:
13157db96d56Sopenharmony_ci                raise OSError("write() returned incorrect number of bytes")
13167db96d56Sopenharmony_ci            del self._write_buf[:n]
13177db96d56Sopenharmony_ci
13187db96d56Sopenharmony_ci    def tell(self):
13197db96d56Sopenharmony_ci        return _BufferedIOMixin.tell(self) + len(self._write_buf)
13207db96d56Sopenharmony_ci
13217db96d56Sopenharmony_ci    def seek(self, pos, whence=0):
13227db96d56Sopenharmony_ci        if whence not in valid_seek_flags:
13237db96d56Sopenharmony_ci            raise ValueError("invalid whence value")
13247db96d56Sopenharmony_ci        with self._write_lock:
13257db96d56Sopenharmony_ci            self._flush_unlocked()
13267db96d56Sopenharmony_ci            return _BufferedIOMixin.seek(self, pos, whence)
13277db96d56Sopenharmony_ci
13287db96d56Sopenharmony_ci    def close(self):
13297db96d56Sopenharmony_ci        with self._write_lock:
13307db96d56Sopenharmony_ci            if self.raw is None or self.closed:
13317db96d56Sopenharmony_ci                return
13327db96d56Sopenharmony_ci        # We have to release the lock and call self.flush() (which will
13337db96d56Sopenharmony_ci        # probably just re-take the lock) in case flush has been overridden in
13347db96d56Sopenharmony_ci        # a subclass or the user set self.flush to something. This is the same
13357db96d56Sopenharmony_ci        # behavior as the C implementation.
13367db96d56Sopenharmony_ci        try:
13377db96d56Sopenharmony_ci            # may raise BlockingIOError or BrokenPipeError etc
13387db96d56Sopenharmony_ci            self.flush()
13397db96d56Sopenharmony_ci        finally:
13407db96d56Sopenharmony_ci            with self._write_lock:
13417db96d56Sopenharmony_ci                self.raw.close()
13427db96d56Sopenharmony_ci
13437db96d56Sopenharmony_ci
13447db96d56Sopenharmony_ciclass BufferedRWPair(BufferedIOBase):
13457db96d56Sopenharmony_ci
13467db96d56Sopenharmony_ci    """A buffered reader and writer object together.
13477db96d56Sopenharmony_ci
13487db96d56Sopenharmony_ci    A buffered reader object and buffered writer object put together to
13497db96d56Sopenharmony_ci    form a sequential IO object that can read and write. This is typically
13507db96d56Sopenharmony_ci    used with a socket or two-way pipe.
13517db96d56Sopenharmony_ci
13527db96d56Sopenharmony_ci    reader and writer are RawIOBase objects that are readable and
13537db96d56Sopenharmony_ci    writeable respectively. If the buffer_size is omitted it defaults to
13547db96d56Sopenharmony_ci    DEFAULT_BUFFER_SIZE.
13557db96d56Sopenharmony_ci    """
13567db96d56Sopenharmony_ci
13577db96d56Sopenharmony_ci    # XXX The usefulness of this (compared to having two separate IO
13587db96d56Sopenharmony_ci    # objects) is questionable.
13597db96d56Sopenharmony_ci
13607db96d56Sopenharmony_ci    def __init__(self, reader, writer, buffer_size=DEFAULT_BUFFER_SIZE):
13617db96d56Sopenharmony_ci        """Constructor.
13627db96d56Sopenharmony_ci
13637db96d56Sopenharmony_ci        The arguments are two RawIO instances.
13647db96d56Sopenharmony_ci        """
13657db96d56Sopenharmony_ci        if not reader.readable():
13667db96d56Sopenharmony_ci            raise OSError('"reader" argument must be readable.')
13677db96d56Sopenharmony_ci
13687db96d56Sopenharmony_ci        if not writer.writable():
13697db96d56Sopenharmony_ci            raise OSError('"writer" argument must be writable.')
13707db96d56Sopenharmony_ci
13717db96d56Sopenharmony_ci        self.reader = BufferedReader(reader, buffer_size)
13727db96d56Sopenharmony_ci        self.writer = BufferedWriter(writer, buffer_size)
13737db96d56Sopenharmony_ci
13747db96d56Sopenharmony_ci    def read(self, size=-1):
13757db96d56Sopenharmony_ci        if size is None:
13767db96d56Sopenharmony_ci            size = -1
13777db96d56Sopenharmony_ci        return self.reader.read(size)
13787db96d56Sopenharmony_ci
13797db96d56Sopenharmony_ci    def readinto(self, b):
13807db96d56Sopenharmony_ci        return self.reader.readinto(b)
13817db96d56Sopenharmony_ci
13827db96d56Sopenharmony_ci    def write(self, b):
13837db96d56Sopenharmony_ci        return self.writer.write(b)
13847db96d56Sopenharmony_ci
13857db96d56Sopenharmony_ci    def peek(self, size=0):
13867db96d56Sopenharmony_ci        return self.reader.peek(size)
13877db96d56Sopenharmony_ci
13887db96d56Sopenharmony_ci    def read1(self, size=-1):
13897db96d56Sopenharmony_ci        return self.reader.read1(size)
13907db96d56Sopenharmony_ci
13917db96d56Sopenharmony_ci    def readinto1(self, b):
13927db96d56Sopenharmony_ci        return self.reader.readinto1(b)
13937db96d56Sopenharmony_ci
13947db96d56Sopenharmony_ci    def readable(self):
13957db96d56Sopenharmony_ci        return self.reader.readable()
13967db96d56Sopenharmony_ci
13977db96d56Sopenharmony_ci    def writable(self):
13987db96d56Sopenharmony_ci        return self.writer.writable()
13997db96d56Sopenharmony_ci
14007db96d56Sopenharmony_ci    def flush(self):
14017db96d56Sopenharmony_ci        return self.writer.flush()
14027db96d56Sopenharmony_ci
14037db96d56Sopenharmony_ci    def close(self):
14047db96d56Sopenharmony_ci        try:
14057db96d56Sopenharmony_ci            self.writer.close()
14067db96d56Sopenharmony_ci        finally:
14077db96d56Sopenharmony_ci            self.reader.close()
14087db96d56Sopenharmony_ci
14097db96d56Sopenharmony_ci    def isatty(self):
14107db96d56Sopenharmony_ci        return self.reader.isatty() or self.writer.isatty()
14117db96d56Sopenharmony_ci
14127db96d56Sopenharmony_ci    @property
14137db96d56Sopenharmony_ci    def closed(self):
14147db96d56Sopenharmony_ci        return self.writer.closed
14157db96d56Sopenharmony_ci
14167db96d56Sopenharmony_ci
14177db96d56Sopenharmony_ciclass BufferedRandom(BufferedWriter, BufferedReader):
14187db96d56Sopenharmony_ci
14197db96d56Sopenharmony_ci    """A buffered interface to random access streams.
14207db96d56Sopenharmony_ci
14217db96d56Sopenharmony_ci    The constructor creates a reader and writer for a seekable stream,
14227db96d56Sopenharmony_ci    raw, given in the first argument. If the buffer_size is omitted it
14237db96d56Sopenharmony_ci    defaults to DEFAULT_BUFFER_SIZE.
14247db96d56Sopenharmony_ci    """
14257db96d56Sopenharmony_ci
14267db96d56Sopenharmony_ci    def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE):
14277db96d56Sopenharmony_ci        raw._checkSeekable()
14287db96d56Sopenharmony_ci        BufferedReader.__init__(self, raw, buffer_size)
14297db96d56Sopenharmony_ci        BufferedWriter.__init__(self, raw, buffer_size)
14307db96d56Sopenharmony_ci
14317db96d56Sopenharmony_ci    def seek(self, pos, whence=0):
14327db96d56Sopenharmony_ci        if whence not in valid_seek_flags:
14337db96d56Sopenharmony_ci            raise ValueError("invalid whence value")
14347db96d56Sopenharmony_ci        self.flush()
14357db96d56Sopenharmony_ci        if self._read_buf:
14367db96d56Sopenharmony_ci            # Undo read ahead.
14377db96d56Sopenharmony_ci            with self._read_lock:
14387db96d56Sopenharmony_ci                self.raw.seek(self._read_pos - len(self._read_buf), 1)
14397db96d56Sopenharmony_ci        # First do the raw seek, then empty the read buffer, so that
14407db96d56Sopenharmony_ci        # if the raw seek fails, we don't lose buffered data forever.
14417db96d56Sopenharmony_ci        pos = self.raw.seek(pos, whence)
14427db96d56Sopenharmony_ci        with self._read_lock:
14437db96d56Sopenharmony_ci            self._reset_read_buf()
14447db96d56Sopenharmony_ci        if pos < 0:
14457db96d56Sopenharmony_ci            raise OSError("seek() returned invalid position")
14467db96d56Sopenharmony_ci        return pos
14477db96d56Sopenharmony_ci
14487db96d56Sopenharmony_ci    def tell(self):
14497db96d56Sopenharmony_ci        if self._write_buf:
14507db96d56Sopenharmony_ci            return BufferedWriter.tell(self)
14517db96d56Sopenharmony_ci        else:
14527db96d56Sopenharmony_ci            return BufferedReader.tell(self)
14537db96d56Sopenharmony_ci
14547db96d56Sopenharmony_ci    def truncate(self, pos=None):
14557db96d56Sopenharmony_ci        if pos is None:
14567db96d56Sopenharmony_ci            pos = self.tell()
14577db96d56Sopenharmony_ci        # Use seek to flush the read buffer.
14587db96d56Sopenharmony_ci        return BufferedWriter.truncate(self, pos)
14597db96d56Sopenharmony_ci
14607db96d56Sopenharmony_ci    def read(self, size=None):
14617db96d56Sopenharmony_ci        if size is None:
14627db96d56Sopenharmony_ci            size = -1
14637db96d56Sopenharmony_ci        self.flush()
14647db96d56Sopenharmony_ci        return BufferedReader.read(self, size)
14657db96d56Sopenharmony_ci
14667db96d56Sopenharmony_ci    def readinto(self, b):
14677db96d56Sopenharmony_ci        self.flush()
14687db96d56Sopenharmony_ci        return BufferedReader.readinto(self, b)
14697db96d56Sopenharmony_ci
14707db96d56Sopenharmony_ci    def peek(self, size=0):
14717db96d56Sopenharmony_ci        self.flush()
14727db96d56Sopenharmony_ci        return BufferedReader.peek(self, size)
14737db96d56Sopenharmony_ci
14747db96d56Sopenharmony_ci    def read1(self, size=-1):
14757db96d56Sopenharmony_ci        self.flush()
14767db96d56Sopenharmony_ci        return BufferedReader.read1(self, size)
14777db96d56Sopenharmony_ci
14787db96d56Sopenharmony_ci    def readinto1(self, b):
14797db96d56Sopenharmony_ci        self.flush()
14807db96d56Sopenharmony_ci        return BufferedReader.readinto1(self, b)
14817db96d56Sopenharmony_ci
14827db96d56Sopenharmony_ci    def write(self, b):
14837db96d56Sopenharmony_ci        if self._read_buf:
14847db96d56Sopenharmony_ci            # Undo readahead
14857db96d56Sopenharmony_ci            with self._read_lock:
14867db96d56Sopenharmony_ci                self.raw.seek(self._read_pos - len(self._read_buf), 1)
14877db96d56Sopenharmony_ci                self._reset_read_buf()
14887db96d56Sopenharmony_ci        return BufferedWriter.write(self, b)
14897db96d56Sopenharmony_ci
14907db96d56Sopenharmony_ci
14917db96d56Sopenharmony_ciclass FileIO(RawIOBase):
14927db96d56Sopenharmony_ci    _fd = -1
14937db96d56Sopenharmony_ci    _created = False
14947db96d56Sopenharmony_ci    _readable = False
14957db96d56Sopenharmony_ci    _writable = False
14967db96d56Sopenharmony_ci    _appending = False
14977db96d56Sopenharmony_ci    _seekable = None
14987db96d56Sopenharmony_ci    _closefd = True
14997db96d56Sopenharmony_ci
15007db96d56Sopenharmony_ci    def __init__(self, file, mode='r', closefd=True, opener=None):
15017db96d56Sopenharmony_ci        """Open a file.  The mode can be 'r' (default), 'w', 'x' or 'a' for reading,
15027db96d56Sopenharmony_ci        writing, exclusive creation or appending.  The file will be created if it
15037db96d56Sopenharmony_ci        doesn't exist when opened for writing or appending; it will be truncated
15047db96d56Sopenharmony_ci        when opened for writing.  A FileExistsError will be raised if it already
15057db96d56Sopenharmony_ci        exists when opened for creating. Opening a file for creating implies
15067db96d56Sopenharmony_ci        writing so this mode behaves in a similar way to 'w'. Add a '+' to the mode
15077db96d56Sopenharmony_ci        to allow simultaneous reading and writing. A custom opener can be used by
15087db96d56Sopenharmony_ci        passing a callable as *opener*. The underlying file descriptor for the file
15097db96d56Sopenharmony_ci        object is then obtained by calling opener with (*name*, *flags*).
15107db96d56Sopenharmony_ci        *opener* must return an open file descriptor (passing os.open as *opener*
15117db96d56Sopenharmony_ci        results in functionality similar to passing None).
15127db96d56Sopenharmony_ci        """
15137db96d56Sopenharmony_ci        if self._fd >= 0:
15147db96d56Sopenharmony_ci            # Have to close the existing file first.
15157db96d56Sopenharmony_ci            try:
15167db96d56Sopenharmony_ci                if self._closefd:
15177db96d56Sopenharmony_ci                    os.close(self._fd)
15187db96d56Sopenharmony_ci            finally:
15197db96d56Sopenharmony_ci                self._fd = -1
15207db96d56Sopenharmony_ci
15217db96d56Sopenharmony_ci        if isinstance(file, float):
15227db96d56Sopenharmony_ci            raise TypeError('integer argument expected, got float')
15237db96d56Sopenharmony_ci        if isinstance(file, int):
15247db96d56Sopenharmony_ci            fd = file
15257db96d56Sopenharmony_ci            if fd < 0:
15267db96d56Sopenharmony_ci                raise ValueError('negative file descriptor')
15277db96d56Sopenharmony_ci        else:
15287db96d56Sopenharmony_ci            fd = -1
15297db96d56Sopenharmony_ci
15307db96d56Sopenharmony_ci        if not isinstance(mode, str):
15317db96d56Sopenharmony_ci            raise TypeError('invalid mode: %s' % (mode,))
15327db96d56Sopenharmony_ci        if not set(mode) <= set('xrwab+'):
15337db96d56Sopenharmony_ci            raise ValueError('invalid mode: %s' % (mode,))
15347db96d56Sopenharmony_ci        if sum(c in 'rwax' for c in mode) != 1 or mode.count('+') > 1:
15357db96d56Sopenharmony_ci            raise ValueError('Must have exactly one of create/read/write/append '
15367db96d56Sopenharmony_ci                             'mode and at most one plus')
15377db96d56Sopenharmony_ci
15387db96d56Sopenharmony_ci        if 'x' in mode:
15397db96d56Sopenharmony_ci            self._created = True
15407db96d56Sopenharmony_ci            self._writable = True
15417db96d56Sopenharmony_ci            flags = os.O_EXCL | os.O_CREAT
15427db96d56Sopenharmony_ci        elif 'r' in mode:
15437db96d56Sopenharmony_ci            self._readable = True
15447db96d56Sopenharmony_ci            flags = 0
15457db96d56Sopenharmony_ci        elif 'w' in mode:
15467db96d56Sopenharmony_ci            self._writable = True
15477db96d56Sopenharmony_ci            flags = os.O_CREAT | os.O_TRUNC
15487db96d56Sopenharmony_ci        elif 'a' in mode:
15497db96d56Sopenharmony_ci            self._writable = True
15507db96d56Sopenharmony_ci            self._appending = True
15517db96d56Sopenharmony_ci            flags = os.O_APPEND | os.O_CREAT
15527db96d56Sopenharmony_ci
15537db96d56Sopenharmony_ci        if '+' in mode:
15547db96d56Sopenharmony_ci            self._readable = True
15557db96d56Sopenharmony_ci            self._writable = True
15567db96d56Sopenharmony_ci
15577db96d56Sopenharmony_ci        if self._readable and self._writable:
15587db96d56Sopenharmony_ci            flags |= os.O_RDWR
15597db96d56Sopenharmony_ci        elif self._readable:
15607db96d56Sopenharmony_ci            flags |= os.O_RDONLY
15617db96d56Sopenharmony_ci        else:
15627db96d56Sopenharmony_ci            flags |= os.O_WRONLY
15637db96d56Sopenharmony_ci
15647db96d56Sopenharmony_ci        flags |= getattr(os, 'O_BINARY', 0)
15657db96d56Sopenharmony_ci
15667db96d56Sopenharmony_ci        noinherit_flag = (getattr(os, 'O_NOINHERIT', 0) or
15677db96d56Sopenharmony_ci                          getattr(os, 'O_CLOEXEC', 0))
15687db96d56Sopenharmony_ci        flags |= noinherit_flag
15697db96d56Sopenharmony_ci
15707db96d56Sopenharmony_ci        owned_fd = None
15717db96d56Sopenharmony_ci        try:
15727db96d56Sopenharmony_ci            if fd < 0:
15737db96d56Sopenharmony_ci                if not closefd:
15747db96d56Sopenharmony_ci                    raise ValueError('Cannot use closefd=False with file name')
15757db96d56Sopenharmony_ci                if opener is None:
15767db96d56Sopenharmony_ci                    fd = os.open(file, flags, 0o666)
15777db96d56Sopenharmony_ci                else:
15787db96d56Sopenharmony_ci                    fd = opener(file, flags)
15797db96d56Sopenharmony_ci                    if not isinstance(fd, int):
15807db96d56Sopenharmony_ci                        raise TypeError('expected integer from opener')
15817db96d56Sopenharmony_ci                    if fd < 0:
15827db96d56Sopenharmony_ci                        raise OSError('Negative file descriptor')
15837db96d56Sopenharmony_ci                owned_fd = fd
15847db96d56Sopenharmony_ci                if not noinherit_flag:
15857db96d56Sopenharmony_ci                    os.set_inheritable(fd, False)
15867db96d56Sopenharmony_ci
15877db96d56Sopenharmony_ci            self._closefd = closefd
15887db96d56Sopenharmony_ci            fdfstat = os.fstat(fd)
15897db96d56Sopenharmony_ci            try:
15907db96d56Sopenharmony_ci                if stat.S_ISDIR(fdfstat.st_mode):
15917db96d56Sopenharmony_ci                    raise IsADirectoryError(errno.EISDIR,
15927db96d56Sopenharmony_ci                                            os.strerror(errno.EISDIR), file)
15937db96d56Sopenharmony_ci            except AttributeError:
15947db96d56Sopenharmony_ci                # Ignore the AttributeError if stat.S_ISDIR or errno.EISDIR
15957db96d56Sopenharmony_ci                # don't exist.
15967db96d56Sopenharmony_ci                pass
15977db96d56Sopenharmony_ci            self._blksize = getattr(fdfstat, 'st_blksize', 0)
15987db96d56Sopenharmony_ci            if self._blksize <= 1:
15997db96d56Sopenharmony_ci                self._blksize = DEFAULT_BUFFER_SIZE
16007db96d56Sopenharmony_ci
16017db96d56Sopenharmony_ci            if _setmode:
16027db96d56Sopenharmony_ci                # don't translate newlines (\r\n <=> \n)
16037db96d56Sopenharmony_ci                _setmode(fd, os.O_BINARY)
16047db96d56Sopenharmony_ci
16057db96d56Sopenharmony_ci            self.name = file
16067db96d56Sopenharmony_ci            if self._appending:
16077db96d56Sopenharmony_ci                # For consistent behaviour, we explicitly seek to the
16087db96d56Sopenharmony_ci                # end of file (otherwise, it might be done only on the
16097db96d56Sopenharmony_ci                # first write()).
16107db96d56Sopenharmony_ci                try:
16117db96d56Sopenharmony_ci                    os.lseek(fd, 0, SEEK_END)
16127db96d56Sopenharmony_ci                except OSError as e:
16137db96d56Sopenharmony_ci                    if e.errno != errno.ESPIPE:
16147db96d56Sopenharmony_ci                        raise
16157db96d56Sopenharmony_ci        except:
16167db96d56Sopenharmony_ci            if owned_fd is not None:
16177db96d56Sopenharmony_ci                os.close(owned_fd)
16187db96d56Sopenharmony_ci            raise
16197db96d56Sopenharmony_ci        self._fd = fd
16207db96d56Sopenharmony_ci
16217db96d56Sopenharmony_ci    def __del__(self):
16227db96d56Sopenharmony_ci        if self._fd >= 0 and self._closefd and not self.closed:
16237db96d56Sopenharmony_ci            import warnings
16247db96d56Sopenharmony_ci            warnings.warn('unclosed file %r' % (self,), ResourceWarning,
16257db96d56Sopenharmony_ci                          stacklevel=2, source=self)
16267db96d56Sopenharmony_ci            self.close()
16277db96d56Sopenharmony_ci
16287db96d56Sopenharmony_ci    def __getstate__(self):
16297db96d56Sopenharmony_ci        raise TypeError(f"cannot pickle {self.__class__.__name__!r} object")
16307db96d56Sopenharmony_ci
16317db96d56Sopenharmony_ci    def __repr__(self):
16327db96d56Sopenharmony_ci        class_name = '%s.%s' % (self.__class__.__module__,
16337db96d56Sopenharmony_ci                                self.__class__.__qualname__)
16347db96d56Sopenharmony_ci        if self.closed:
16357db96d56Sopenharmony_ci            return '<%s [closed]>' % class_name
16367db96d56Sopenharmony_ci        try:
16377db96d56Sopenharmony_ci            name = self.name
16387db96d56Sopenharmony_ci        except AttributeError:
16397db96d56Sopenharmony_ci            return ('<%s fd=%d mode=%r closefd=%r>' %
16407db96d56Sopenharmony_ci                    (class_name, self._fd, self.mode, self._closefd))
16417db96d56Sopenharmony_ci        else:
16427db96d56Sopenharmony_ci            return ('<%s name=%r mode=%r closefd=%r>' %
16437db96d56Sopenharmony_ci                    (class_name, name, self.mode, self._closefd))
16447db96d56Sopenharmony_ci
16457db96d56Sopenharmony_ci    def _checkReadable(self):
16467db96d56Sopenharmony_ci        if not self._readable:
16477db96d56Sopenharmony_ci            raise UnsupportedOperation('File not open for reading')
16487db96d56Sopenharmony_ci
16497db96d56Sopenharmony_ci    def _checkWritable(self, msg=None):
16507db96d56Sopenharmony_ci        if not self._writable:
16517db96d56Sopenharmony_ci            raise UnsupportedOperation('File not open for writing')
16527db96d56Sopenharmony_ci
16537db96d56Sopenharmony_ci    def read(self, size=None):
16547db96d56Sopenharmony_ci        """Read at most size bytes, returned as bytes.
16557db96d56Sopenharmony_ci
16567db96d56Sopenharmony_ci        Only makes one system call, so less data may be returned than requested
16577db96d56Sopenharmony_ci        In non-blocking mode, returns None if no data is available.
16587db96d56Sopenharmony_ci        Return an empty bytes object at EOF.
16597db96d56Sopenharmony_ci        """
16607db96d56Sopenharmony_ci        self._checkClosed()
16617db96d56Sopenharmony_ci        self._checkReadable()
16627db96d56Sopenharmony_ci        if size is None or size < 0:
16637db96d56Sopenharmony_ci            return self.readall()
16647db96d56Sopenharmony_ci        try:
16657db96d56Sopenharmony_ci            return os.read(self._fd, size)
16667db96d56Sopenharmony_ci        except BlockingIOError:
16677db96d56Sopenharmony_ci            return None
16687db96d56Sopenharmony_ci
16697db96d56Sopenharmony_ci    def readall(self):
16707db96d56Sopenharmony_ci        """Read all data from the file, returned as bytes.
16717db96d56Sopenharmony_ci
16727db96d56Sopenharmony_ci        In non-blocking mode, returns as much as is immediately available,
16737db96d56Sopenharmony_ci        or None if no data is available.  Return an empty bytes object at EOF.
16747db96d56Sopenharmony_ci        """
16757db96d56Sopenharmony_ci        self._checkClosed()
16767db96d56Sopenharmony_ci        self._checkReadable()
16777db96d56Sopenharmony_ci        bufsize = DEFAULT_BUFFER_SIZE
16787db96d56Sopenharmony_ci        try:
16797db96d56Sopenharmony_ci            pos = os.lseek(self._fd, 0, SEEK_CUR)
16807db96d56Sopenharmony_ci            end = os.fstat(self._fd).st_size
16817db96d56Sopenharmony_ci            if end >= pos:
16827db96d56Sopenharmony_ci                bufsize = end - pos + 1
16837db96d56Sopenharmony_ci        except OSError:
16847db96d56Sopenharmony_ci            pass
16857db96d56Sopenharmony_ci
16867db96d56Sopenharmony_ci        result = bytearray()
16877db96d56Sopenharmony_ci        while True:
16887db96d56Sopenharmony_ci            if len(result) >= bufsize:
16897db96d56Sopenharmony_ci                bufsize = len(result)
16907db96d56Sopenharmony_ci                bufsize += max(bufsize, DEFAULT_BUFFER_SIZE)
16917db96d56Sopenharmony_ci            n = bufsize - len(result)
16927db96d56Sopenharmony_ci            try:
16937db96d56Sopenharmony_ci                chunk = os.read(self._fd, n)
16947db96d56Sopenharmony_ci            except BlockingIOError:
16957db96d56Sopenharmony_ci                if result:
16967db96d56Sopenharmony_ci                    break
16977db96d56Sopenharmony_ci                return None
16987db96d56Sopenharmony_ci            if not chunk: # reached the end of the file
16997db96d56Sopenharmony_ci                break
17007db96d56Sopenharmony_ci            result += chunk
17017db96d56Sopenharmony_ci
17027db96d56Sopenharmony_ci        return bytes(result)
17037db96d56Sopenharmony_ci
17047db96d56Sopenharmony_ci    def readinto(self, b):
17057db96d56Sopenharmony_ci        """Same as RawIOBase.readinto()."""
17067db96d56Sopenharmony_ci        m = memoryview(b).cast('B')
17077db96d56Sopenharmony_ci        data = self.read(len(m))
17087db96d56Sopenharmony_ci        n = len(data)
17097db96d56Sopenharmony_ci        m[:n] = data
17107db96d56Sopenharmony_ci        return n
17117db96d56Sopenharmony_ci
17127db96d56Sopenharmony_ci    def write(self, b):
17137db96d56Sopenharmony_ci        """Write bytes b to file, return number written.
17147db96d56Sopenharmony_ci
17157db96d56Sopenharmony_ci        Only makes one system call, so not all of the data may be written.
17167db96d56Sopenharmony_ci        The number of bytes actually written is returned.  In non-blocking mode,
17177db96d56Sopenharmony_ci        returns None if the write would block.
17187db96d56Sopenharmony_ci        """
17197db96d56Sopenharmony_ci        self._checkClosed()
17207db96d56Sopenharmony_ci        self._checkWritable()
17217db96d56Sopenharmony_ci        try:
17227db96d56Sopenharmony_ci            return os.write(self._fd, b)
17237db96d56Sopenharmony_ci        except BlockingIOError:
17247db96d56Sopenharmony_ci            return None
17257db96d56Sopenharmony_ci
17267db96d56Sopenharmony_ci    def seek(self, pos, whence=SEEK_SET):
17277db96d56Sopenharmony_ci        """Move to new file position.
17287db96d56Sopenharmony_ci
17297db96d56Sopenharmony_ci        Argument offset is a byte count.  Optional argument whence defaults to
17307db96d56Sopenharmony_ci        SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values
17317db96d56Sopenharmony_ci        are SEEK_CUR or 1 (move relative to current position, positive or negative),
17327db96d56Sopenharmony_ci        and SEEK_END or 2 (move relative to end of file, usually negative, although
17337db96d56Sopenharmony_ci        many platforms allow seeking beyond the end of a file).
17347db96d56Sopenharmony_ci
17357db96d56Sopenharmony_ci        Note that not all file objects are seekable.
17367db96d56Sopenharmony_ci        """
17377db96d56Sopenharmony_ci        if isinstance(pos, float):
17387db96d56Sopenharmony_ci            raise TypeError('an integer is required')
17397db96d56Sopenharmony_ci        self._checkClosed()
17407db96d56Sopenharmony_ci        return os.lseek(self._fd, pos, whence)
17417db96d56Sopenharmony_ci
17427db96d56Sopenharmony_ci    def tell(self):
17437db96d56Sopenharmony_ci        """tell() -> int.  Current file position.
17447db96d56Sopenharmony_ci
17457db96d56Sopenharmony_ci        Can raise OSError for non seekable files."""
17467db96d56Sopenharmony_ci        self._checkClosed()
17477db96d56Sopenharmony_ci        return os.lseek(self._fd, 0, SEEK_CUR)
17487db96d56Sopenharmony_ci
17497db96d56Sopenharmony_ci    def truncate(self, size=None):
17507db96d56Sopenharmony_ci        """Truncate the file to at most size bytes.
17517db96d56Sopenharmony_ci
17527db96d56Sopenharmony_ci        Size defaults to the current file position, as returned by tell().
17537db96d56Sopenharmony_ci        The current file position is changed to the value of size.
17547db96d56Sopenharmony_ci        """
17557db96d56Sopenharmony_ci        self._checkClosed()
17567db96d56Sopenharmony_ci        self._checkWritable()
17577db96d56Sopenharmony_ci        if size is None:
17587db96d56Sopenharmony_ci            size = self.tell()
17597db96d56Sopenharmony_ci        os.ftruncate(self._fd, size)
17607db96d56Sopenharmony_ci        return size
17617db96d56Sopenharmony_ci
17627db96d56Sopenharmony_ci    def close(self):
17637db96d56Sopenharmony_ci        """Close the file.
17647db96d56Sopenharmony_ci
17657db96d56Sopenharmony_ci        A closed file cannot be used for further I/O operations.  close() may be
17667db96d56Sopenharmony_ci        called more than once without error.
17677db96d56Sopenharmony_ci        """
17687db96d56Sopenharmony_ci        if not self.closed:
17697db96d56Sopenharmony_ci            try:
17707db96d56Sopenharmony_ci                if self._closefd:
17717db96d56Sopenharmony_ci                    os.close(self._fd)
17727db96d56Sopenharmony_ci            finally:
17737db96d56Sopenharmony_ci                super().close()
17747db96d56Sopenharmony_ci
17757db96d56Sopenharmony_ci    def seekable(self):
17767db96d56Sopenharmony_ci        """True if file supports random-access."""
17777db96d56Sopenharmony_ci        self._checkClosed()
17787db96d56Sopenharmony_ci        if self._seekable is None:
17797db96d56Sopenharmony_ci            try:
17807db96d56Sopenharmony_ci                self.tell()
17817db96d56Sopenharmony_ci            except OSError:
17827db96d56Sopenharmony_ci                self._seekable = False
17837db96d56Sopenharmony_ci            else:
17847db96d56Sopenharmony_ci                self._seekable = True
17857db96d56Sopenharmony_ci        return self._seekable
17867db96d56Sopenharmony_ci
17877db96d56Sopenharmony_ci    def readable(self):
17887db96d56Sopenharmony_ci        """True if file was opened in a read mode."""
17897db96d56Sopenharmony_ci        self._checkClosed()
17907db96d56Sopenharmony_ci        return self._readable
17917db96d56Sopenharmony_ci
17927db96d56Sopenharmony_ci    def writable(self):
17937db96d56Sopenharmony_ci        """True if file was opened in a write mode."""
17947db96d56Sopenharmony_ci        self._checkClosed()
17957db96d56Sopenharmony_ci        return self._writable
17967db96d56Sopenharmony_ci
17977db96d56Sopenharmony_ci    def fileno(self):
17987db96d56Sopenharmony_ci        """Return the underlying file descriptor (an integer)."""
17997db96d56Sopenharmony_ci        self._checkClosed()
18007db96d56Sopenharmony_ci        return self._fd
18017db96d56Sopenharmony_ci
18027db96d56Sopenharmony_ci    def isatty(self):
18037db96d56Sopenharmony_ci        """True if the file is connected to a TTY device."""
18047db96d56Sopenharmony_ci        self._checkClosed()
18057db96d56Sopenharmony_ci        return os.isatty(self._fd)
18067db96d56Sopenharmony_ci
18077db96d56Sopenharmony_ci    @property
18087db96d56Sopenharmony_ci    def closefd(self):
18097db96d56Sopenharmony_ci        """True if the file descriptor will be closed by close()."""
18107db96d56Sopenharmony_ci        return self._closefd
18117db96d56Sopenharmony_ci
18127db96d56Sopenharmony_ci    @property
18137db96d56Sopenharmony_ci    def mode(self):
18147db96d56Sopenharmony_ci        """String giving the file mode"""
18157db96d56Sopenharmony_ci        if self._created:
18167db96d56Sopenharmony_ci            if self._readable:
18177db96d56Sopenharmony_ci                return 'xb+'
18187db96d56Sopenharmony_ci            else:
18197db96d56Sopenharmony_ci                return 'xb'
18207db96d56Sopenharmony_ci        elif self._appending:
18217db96d56Sopenharmony_ci            if self._readable:
18227db96d56Sopenharmony_ci                return 'ab+'
18237db96d56Sopenharmony_ci            else:
18247db96d56Sopenharmony_ci                return 'ab'
18257db96d56Sopenharmony_ci        elif self._readable:
18267db96d56Sopenharmony_ci            if self._writable:
18277db96d56Sopenharmony_ci                return 'rb+'
18287db96d56Sopenharmony_ci            else:
18297db96d56Sopenharmony_ci                return 'rb'
18307db96d56Sopenharmony_ci        else:
18317db96d56Sopenharmony_ci            return 'wb'
18327db96d56Sopenharmony_ci
18337db96d56Sopenharmony_ci
18347db96d56Sopenharmony_ciclass TextIOBase(IOBase):
18357db96d56Sopenharmony_ci
18367db96d56Sopenharmony_ci    """Base class for text I/O.
18377db96d56Sopenharmony_ci
18387db96d56Sopenharmony_ci    This class provides a character and line based interface to stream
18397db96d56Sopenharmony_ci    I/O.
18407db96d56Sopenharmony_ci    """
18417db96d56Sopenharmony_ci
18427db96d56Sopenharmony_ci    def read(self, size=-1):
18437db96d56Sopenharmony_ci        """Read at most size characters from stream, where size is an int.
18447db96d56Sopenharmony_ci
18457db96d56Sopenharmony_ci        Read from underlying buffer until we have size characters or we hit EOF.
18467db96d56Sopenharmony_ci        If size is negative or omitted, read until EOF.
18477db96d56Sopenharmony_ci
18487db96d56Sopenharmony_ci        Returns a string.
18497db96d56Sopenharmony_ci        """
18507db96d56Sopenharmony_ci        self._unsupported("read")
18517db96d56Sopenharmony_ci
18527db96d56Sopenharmony_ci    def write(self, s):
18537db96d56Sopenharmony_ci        """Write string s to stream and returning an int."""
18547db96d56Sopenharmony_ci        self._unsupported("write")
18557db96d56Sopenharmony_ci
18567db96d56Sopenharmony_ci    def truncate(self, pos=None):
18577db96d56Sopenharmony_ci        """Truncate size to pos, where pos is an int."""
18587db96d56Sopenharmony_ci        self._unsupported("truncate")
18597db96d56Sopenharmony_ci
18607db96d56Sopenharmony_ci    def readline(self):
18617db96d56Sopenharmony_ci        """Read until newline or EOF.
18627db96d56Sopenharmony_ci
18637db96d56Sopenharmony_ci        Returns an empty string if EOF is hit immediately.
18647db96d56Sopenharmony_ci        """
18657db96d56Sopenharmony_ci        self._unsupported("readline")
18667db96d56Sopenharmony_ci
18677db96d56Sopenharmony_ci    def detach(self):
18687db96d56Sopenharmony_ci        """
18697db96d56Sopenharmony_ci        Separate the underlying buffer from the TextIOBase and return it.
18707db96d56Sopenharmony_ci
18717db96d56Sopenharmony_ci        After the underlying buffer has been detached, the TextIO is in an
18727db96d56Sopenharmony_ci        unusable state.
18737db96d56Sopenharmony_ci        """
18747db96d56Sopenharmony_ci        self._unsupported("detach")
18757db96d56Sopenharmony_ci
18767db96d56Sopenharmony_ci    @property
18777db96d56Sopenharmony_ci    def encoding(self):
18787db96d56Sopenharmony_ci        """Subclasses should override."""
18797db96d56Sopenharmony_ci        return None
18807db96d56Sopenharmony_ci
18817db96d56Sopenharmony_ci    @property
18827db96d56Sopenharmony_ci    def newlines(self):
18837db96d56Sopenharmony_ci        """Line endings translated so far.
18847db96d56Sopenharmony_ci
18857db96d56Sopenharmony_ci        Only line endings translated during reading are considered.
18867db96d56Sopenharmony_ci
18877db96d56Sopenharmony_ci        Subclasses should override.
18887db96d56Sopenharmony_ci        """
18897db96d56Sopenharmony_ci        return None
18907db96d56Sopenharmony_ci
18917db96d56Sopenharmony_ci    @property
18927db96d56Sopenharmony_ci    def errors(self):
18937db96d56Sopenharmony_ci        """Error setting of the decoder or encoder.
18947db96d56Sopenharmony_ci
18957db96d56Sopenharmony_ci        Subclasses should override."""
18967db96d56Sopenharmony_ci        return None
18977db96d56Sopenharmony_ci
18987db96d56Sopenharmony_ciio.TextIOBase.register(TextIOBase)
18997db96d56Sopenharmony_ci
19007db96d56Sopenharmony_ci
19017db96d56Sopenharmony_ciclass IncrementalNewlineDecoder(codecs.IncrementalDecoder):
19027db96d56Sopenharmony_ci    r"""Codec used when reading a file in universal newlines mode.  It wraps
19037db96d56Sopenharmony_ci    another incremental decoder, translating \r\n and \r into \n.  It also
19047db96d56Sopenharmony_ci    records the types of newlines encountered.  When used with
19057db96d56Sopenharmony_ci    translate=False, it ensures that the newline sequence is returned in
19067db96d56Sopenharmony_ci    one piece.
19077db96d56Sopenharmony_ci    """
19087db96d56Sopenharmony_ci    def __init__(self, decoder, translate, errors='strict'):
19097db96d56Sopenharmony_ci        codecs.IncrementalDecoder.__init__(self, errors=errors)
19107db96d56Sopenharmony_ci        self.translate = translate
19117db96d56Sopenharmony_ci        self.decoder = decoder
19127db96d56Sopenharmony_ci        self.seennl = 0
19137db96d56Sopenharmony_ci        self.pendingcr = False
19147db96d56Sopenharmony_ci
19157db96d56Sopenharmony_ci    def decode(self, input, final=False):
19167db96d56Sopenharmony_ci        # decode input (with the eventual \r from a previous pass)
19177db96d56Sopenharmony_ci        if self.decoder is None:
19187db96d56Sopenharmony_ci            output = input
19197db96d56Sopenharmony_ci        else:
19207db96d56Sopenharmony_ci            output = self.decoder.decode(input, final=final)
19217db96d56Sopenharmony_ci        if self.pendingcr and (output or final):
19227db96d56Sopenharmony_ci            output = "\r" + output
19237db96d56Sopenharmony_ci            self.pendingcr = False
19247db96d56Sopenharmony_ci
19257db96d56Sopenharmony_ci        # retain last \r even when not translating data:
19267db96d56Sopenharmony_ci        # then readline() is sure to get \r\n in one pass
19277db96d56Sopenharmony_ci        if output.endswith("\r") and not final:
19287db96d56Sopenharmony_ci            output = output[:-1]
19297db96d56Sopenharmony_ci            self.pendingcr = True
19307db96d56Sopenharmony_ci
19317db96d56Sopenharmony_ci        # Record which newlines are read
19327db96d56Sopenharmony_ci        crlf = output.count('\r\n')
19337db96d56Sopenharmony_ci        cr = output.count('\r') - crlf
19347db96d56Sopenharmony_ci        lf = output.count('\n') - crlf
19357db96d56Sopenharmony_ci        self.seennl |= (lf and self._LF) | (cr and self._CR) \
19367db96d56Sopenharmony_ci                    | (crlf and self._CRLF)
19377db96d56Sopenharmony_ci
19387db96d56Sopenharmony_ci        if self.translate:
19397db96d56Sopenharmony_ci            if crlf:
19407db96d56Sopenharmony_ci                output = output.replace("\r\n", "\n")
19417db96d56Sopenharmony_ci            if cr:
19427db96d56Sopenharmony_ci                output = output.replace("\r", "\n")
19437db96d56Sopenharmony_ci
19447db96d56Sopenharmony_ci        return output
19457db96d56Sopenharmony_ci
19467db96d56Sopenharmony_ci    def getstate(self):
19477db96d56Sopenharmony_ci        if self.decoder is None:
19487db96d56Sopenharmony_ci            buf = b""
19497db96d56Sopenharmony_ci            flag = 0
19507db96d56Sopenharmony_ci        else:
19517db96d56Sopenharmony_ci            buf, flag = self.decoder.getstate()
19527db96d56Sopenharmony_ci        flag <<= 1
19537db96d56Sopenharmony_ci        if self.pendingcr:
19547db96d56Sopenharmony_ci            flag |= 1
19557db96d56Sopenharmony_ci        return buf, flag
19567db96d56Sopenharmony_ci
19577db96d56Sopenharmony_ci    def setstate(self, state):
19587db96d56Sopenharmony_ci        buf, flag = state
19597db96d56Sopenharmony_ci        self.pendingcr = bool(flag & 1)
19607db96d56Sopenharmony_ci        if self.decoder is not None:
19617db96d56Sopenharmony_ci            self.decoder.setstate((buf, flag >> 1))
19627db96d56Sopenharmony_ci
19637db96d56Sopenharmony_ci    def reset(self):
19647db96d56Sopenharmony_ci        self.seennl = 0
19657db96d56Sopenharmony_ci        self.pendingcr = False
19667db96d56Sopenharmony_ci        if self.decoder is not None:
19677db96d56Sopenharmony_ci            self.decoder.reset()
19687db96d56Sopenharmony_ci
19697db96d56Sopenharmony_ci    _LF = 1
19707db96d56Sopenharmony_ci    _CR = 2
19717db96d56Sopenharmony_ci    _CRLF = 4
19727db96d56Sopenharmony_ci
19737db96d56Sopenharmony_ci    @property
19747db96d56Sopenharmony_ci    def newlines(self):
19757db96d56Sopenharmony_ci        return (None,
19767db96d56Sopenharmony_ci                "\n",
19777db96d56Sopenharmony_ci                "\r",
19787db96d56Sopenharmony_ci                ("\r", "\n"),
19797db96d56Sopenharmony_ci                "\r\n",
19807db96d56Sopenharmony_ci                ("\n", "\r\n"),
19817db96d56Sopenharmony_ci                ("\r", "\r\n"),
19827db96d56Sopenharmony_ci                ("\r", "\n", "\r\n")
19837db96d56Sopenharmony_ci               )[self.seennl]
19847db96d56Sopenharmony_ci
19857db96d56Sopenharmony_ci
19867db96d56Sopenharmony_ciclass TextIOWrapper(TextIOBase):
19877db96d56Sopenharmony_ci
19887db96d56Sopenharmony_ci    r"""Character and line based layer over a BufferedIOBase object, buffer.
19897db96d56Sopenharmony_ci
19907db96d56Sopenharmony_ci    encoding gives the name of the encoding that the stream will be
19917db96d56Sopenharmony_ci    decoded or encoded with. It defaults to locale.getencoding().
19927db96d56Sopenharmony_ci
19937db96d56Sopenharmony_ci    errors determines the strictness of encoding and decoding (see the
19947db96d56Sopenharmony_ci    codecs.register) and defaults to "strict".
19957db96d56Sopenharmony_ci
19967db96d56Sopenharmony_ci    newline can be None, '', '\n', '\r', or '\r\n'.  It controls the
19977db96d56Sopenharmony_ci    handling of line endings. If it is None, universal newlines is
19987db96d56Sopenharmony_ci    enabled.  With this enabled, on input, the lines endings '\n', '\r',
19997db96d56Sopenharmony_ci    or '\r\n' are translated to '\n' before being returned to the
20007db96d56Sopenharmony_ci    caller. Conversely, on output, '\n' is translated to the system
20017db96d56Sopenharmony_ci    default line separator, os.linesep. If newline is any other of its
20027db96d56Sopenharmony_ci    legal values, that newline becomes the newline when the file is read
20037db96d56Sopenharmony_ci    and it is returned untranslated. On output, '\n' is converted to the
20047db96d56Sopenharmony_ci    newline.
20057db96d56Sopenharmony_ci
20067db96d56Sopenharmony_ci    If line_buffering is True, a call to flush is implied when a call to
20077db96d56Sopenharmony_ci    write contains a newline character.
20087db96d56Sopenharmony_ci    """
20097db96d56Sopenharmony_ci
20107db96d56Sopenharmony_ci    _CHUNK_SIZE = 2048
20117db96d56Sopenharmony_ci
20127db96d56Sopenharmony_ci    # Initialize _buffer as soon as possible since it's used by __del__()
20137db96d56Sopenharmony_ci    # which calls close()
20147db96d56Sopenharmony_ci    _buffer = None
20157db96d56Sopenharmony_ci
20167db96d56Sopenharmony_ci    # The write_through argument has no effect here since this
20177db96d56Sopenharmony_ci    # implementation always writes through.  The argument is present only
20187db96d56Sopenharmony_ci    # so that the signature can match the signature of the C version.
20197db96d56Sopenharmony_ci    def __init__(self, buffer, encoding=None, errors=None, newline=None,
20207db96d56Sopenharmony_ci                 line_buffering=False, write_through=False):
20217db96d56Sopenharmony_ci        self._check_newline(newline)
20227db96d56Sopenharmony_ci        encoding = text_encoding(encoding)
20237db96d56Sopenharmony_ci
20247db96d56Sopenharmony_ci        if encoding == "locale":
20257db96d56Sopenharmony_ci            encoding = self._get_locale_encoding()
20267db96d56Sopenharmony_ci
20277db96d56Sopenharmony_ci        if not isinstance(encoding, str):
20287db96d56Sopenharmony_ci            raise ValueError("invalid encoding: %r" % encoding)
20297db96d56Sopenharmony_ci
20307db96d56Sopenharmony_ci        if not codecs.lookup(encoding)._is_text_encoding:
20317db96d56Sopenharmony_ci            msg = ("%r is not a text encoding; "
20327db96d56Sopenharmony_ci                   "use codecs.open() to handle arbitrary codecs")
20337db96d56Sopenharmony_ci            raise LookupError(msg % encoding)
20347db96d56Sopenharmony_ci
20357db96d56Sopenharmony_ci        if errors is None:
20367db96d56Sopenharmony_ci            errors = "strict"
20377db96d56Sopenharmony_ci        else:
20387db96d56Sopenharmony_ci            if not isinstance(errors, str):
20397db96d56Sopenharmony_ci                raise ValueError("invalid errors: %r" % errors)
20407db96d56Sopenharmony_ci            if _CHECK_ERRORS:
20417db96d56Sopenharmony_ci                codecs.lookup_error(errors)
20427db96d56Sopenharmony_ci
20437db96d56Sopenharmony_ci        self._buffer = buffer
20447db96d56Sopenharmony_ci        self._decoded_chars = ''  # buffer for text returned from decoder
20457db96d56Sopenharmony_ci        self._decoded_chars_used = 0  # offset into _decoded_chars for read()
20467db96d56Sopenharmony_ci        self._snapshot = None  # info for reconstructing decoder state
20477db96d56Sopenharmony_ci        self._seekable = self._telling = self.buffer.seekable()
20487db96d56Sopenharmony_ci        self._has_read1 = hasattr(self.buffer, 'read1')
20497db96d56Sopenharmony_ci        self._configure(encoding, errors, newline,
20507db96d56Sopenharmony_ci                        line_buffering, write_through)
20517db96d56Sopenharmony_ci
20527db96d56Sopenharmony_ci    def _check_newline(self, newline):
20537db96d56Sopenharmony_ci        if newline is not None and not isinstance(newline, str):
20547db96d56Sopenharmony_ci            raise TypeError("illegal newline type: %r" % (type(newline),))
20557db96d56Sopenharmony_ci        if newline not in (None, "", "\n", "\r", "\r\n"):
20567db96d56Sopenharmony_ci            raise ValueError("illegal newline value: %r" % (newline,))
20577db96d56Sopenharmony_ci
20587db96d56Sopenharmony_ci    def _configure(self, encoding=None, errors=None, newline=None,
20597db96d56Sopenharmony_ci                   line_buffering=False, write_through=False):
20607db96d56Sopenharmony_ci        self._encoding = encoding
20617db96d56Sopenharmony_ci        self._errors = errors
20627db96d56Sopenharmony_ci        self._encoder = None
20637db96d56Sopenharmony_ci        self._decoder = None
20647db96d56Sopenharmony_ci        self._b2cratio = 0.0
20657db96d56Sopenharmony_ci
20667db96d56Sopenharmony_ci        self._readuniversal = not newline
20677db96d56Sopenharmony_ci        self._readtranslate = newline is None
20687db96d56Sopenharmony_ci        self._readnl = newline
20697db96d56Sopenharmony_ci        self._writetranslate = newline != ''
20707db96d56Sopenharmony_ci        self._writenl = newline or os.linesep
20717db96d56Sopenharmony_ci
20727db96d56Sopenharmony_ci        self._line_buffering = line_buffering
20737db96d56Sopenharmony_ci        self._write_through = write_through
20747db96d56Sopenharmony_ci
20757db96d56Sopenharmony_ci        # don't write a BOM in the middle of a file
20767db96d56Sopenharmony_ci        if self._seekable and self.writable():
20777db96d56Sopenharmony_ci            position = self.buffer.tell()
20787db96d56Sopenharmony_ci            if position != 0:
20797db96d56Sopenharmony_ci                try:
20807db96d56Sopenharmony_ci                    self._get_encoder().setstate(0)
20817db96d56Sopenharmony_ci                except LookupError:
20827db96d56Sopenharmony_ci                    # Sometimes the encoder doesn't exist
20837db96d56Sopenharmony_ci                    pass
20847db96d56Sopenharmony_ci
20857db96d56Sopenharmony_ci    # self._snapshot is either None, or a tuple (dec_flags, next_input)
20867db96d56Sopenharmony_ci    # where dec_flags is the second (integer) item of the decoder state
20877db96d56Sopenharmony_ci    # and next_input is the chunk of input bytes that comes next after the
20887db96d56Sopenharmony_ci    # snapshot point.  We use this to reconstruct decoder states in tell().
20897db96d56Sopenharmony_ci
20907db96d56Sopenharmony_ci    # Naming convention:
20917db96d56Sopenharmony_ci    #   - "bytes_..." for integer variables that count input bytes
20927db96d56Sopenharmony_ci    #   - "chars_..." for integer variables that count decoded characters
20937db96d56Sopenharmony_ci
20947db96d56Sopenharmony_ci    def __repr__(self):
20957db96d56Sopenharmony_ci        result = "<{}.{}".format(self.__class__.__module__,
20967db96d56Sopenharmony_ci                                 self.__class__.__qualname__)
20977db96d56Sopenharmony_ci        try:
20987db96d56Sopenharmony_ci            name = self.name
20997db96d56Sopenharmony_ci        except AttributeError:
21007db96d56Sopenharmony_ci            pass
21017db96d56Sopenharmony_ci        else:
21027db96d56Sopenharmony_ci            result += " name={0!r}".format(name)
21037db96d56Sopenharmony_ci        try:
21047db96d56Sopenharmony_ci            mode = self.mode
21057db96d56Sopenharmony_ci        except AttributeError:
21067db96d56Sopenharmony_ci            pass
21077db96d56Sopenharmony_ci        else:
21087db96d56Sopenharmony_ci            result += " mode={0!r}".format(mode)
21097db96d56Sopenharmony_ci        return result + " encoding={0!r}>".format(self.encoding)
21107db96d56Sopenharmony_ci
21117db96d56Sopenharmony_ci    @property
21127db96d56Sopenharmony_ci    def encoding(self):
21137db96d56Sopenharmony_ci        return self._encoding
21147db96d56Sopenharmony_ci
21157db96d56Sopenharmony_ci    @property
21167db96d56Sopenharmony_ci    def errors(self):
21177db96d56Sopenharmony_ci        return self._errors
21187db96d56Sopenharmony_ci
21197db96d56Sopenharmony_ci    @property
21207db96d56Sopenharmony_ci    def line_buffering(self):
21217db96d56Sopenharmony_ci        return self._line_buffering
21227db96d56Sopenharmony_ci
21237db96d56Sopenharmony_ci    @property
21247db96d56Sopenharmony_ci    def write_through(self):
21257db96d56Sopenharmony_ci        return self._write_through
21267db96d56Sopenharmony_ci
21277db96d56Sopenharmony_ci    @property
21287db96d56Sopenharmony_ci    def buffer(self):
21297db96d56Sopenharmony_ci        return self._buffer
21307db96d56Sopenharmony_ci
21317db96d56Sopenharmony_ci    def reconfigure(self, *,
21327db96d56Sopenharmony_ci                    encoding=None, errors=None, newline=Ellipsis,
21337db96d56Sopenharmony_ci                    line_buffering=None, write_through=None):
21347db96d56Sopenharmony_ci        """Reconfigure the text stream with new parameters.
21357db96d56Sopenharmony_ci
21367db96d56Sopenharmony_ci        This also flushes the stream.
21377db96d56Sopenharmony_ci        """
21387db96d56Sopenharmony_ci        if (self._decoder is not None
21397db96d56Sopenharmony_ci                and (encoding is not None or errors is not None
21407db96d56Sopenharmony_ci                     or newline is not Ellipsis)):
21417db96d56Sopenharmony_ci            raise UnsupportedOperation(
21427db96d56Sopenharmony_ci                "It is not possible to set the encoding or newline of stream "
21437db96d56Sopenharmony_ci                "after the first read")
21447db96d56Sopenharmony_ci
21457db96d56Sopenharmony_ci        if errors is None:
21467db96d56Sopenharmony_ci            if encoding is None:
21477db96d56Sopenharmony_ci                errors = self._errors
21487db96d56Sopenharmony_ci            else:
21497db96d56Sopenharmony_ci                errors = 'strict'
21507db96d56Sopenharmony_ci        elif not isinstance(errors, str):
21517db96d56Sopenharmony_ci            raise TypeError("invalid errors: %r" % errors)
21527db96d56Sopenharmony_ci
21537db96d56Sopenharmony_ci        if encoding is None:
21547db96d56Sopenharmony_ci            encoding = self._encoding
21557db96d56Sopenharmony_ci        else:
21567db96d56Sopenharmony_ci            if not isinstance(encoding, str):
21577db96d56Sopenharmony_ci                raise TypeError("invalid encoding: %r" % encoding)
21587db96d56Sopenharmony_ci            if encoding == "locale":
21597db96d56Sopenharmony_ci                encoding = self._get_locale_encoding()
21607db96d56Sopenharmony_ci
21617db96d56Sopenharmony_ci        if newline is Ellipsis:
21627db96d56Sopenharmony_ci            newline = self._readnl
21637db96d56Sopenharmony_ci        self._check_newline(newline)
21647db96d56Sopenharmony_ci
21657db96d56Sopenharmony_ci        if line_buffering is None:
21667db96d56Sopenharmony_ci            line_buffering = self.line_buffering
21677db96d56Sopenharmony_ci        if write_through is None:
21687db96d56Sopenharmony_ci            write_through = self.write_through
21697db96d56Sopenharmony_ci
21707db96d56Sopenharmony_ci        self.flush()
21717db96d56Sopenharmony_ci        self._configure(encoding, errors, newline,
21727db96d56Sopenharmony_ci                        line_buffering, write_through)
21737db96d56Sopenharmony_ci
21747db96d56Sopenharmony_ci    def seekable(self):
21757db96d56Sopenharmony_ci        if self.closed:
21767db96d56Sopenharmony_ci            raise ValueError("I/O operation on closed file.")
21777db96d56Sopenharmony_ci        return self._seekable
21787db96d56Sopenharmony_ci
21797db96d56Sopenharmony_ci    def readable(self):
21807db96d56Sopenharmony_ci        return self.buffer.readable()
21817db96d56Sopenharmony_ci
21827db96d56Sopenharmony_ci    def writable(self):
21837db96d56Sopenharmony_ci        return self.buffer.writable()
21847db96d56Sopenharmony_ci
21857db96d56Sopenharmony_ci    def flush(self):
21867db96d56Sopenharmony_ci        self.buffer.flush()
21877db96d56Sopenharmony_ci        self._telling = self._seekable
21887db96d56Sopenharmony_ci
21897db96d56Sopenharmony_ci    def close(self):
21907db96d56Sopenharmony_ci        if self.buffer is not None and not self.closed:
21917db96d56Sopenharmony_ci            try:
21927db96d56Sopenharmony_ci                self.flush()
21937db96d56Sopenharmony_ci            finally:
21947db96d56Sopenharmony_ci                self.buffer.close()
21957db96d56Sopenharmony_ci
21967db96d56Sopenharmony_ci    @property
21977db96d56Sopenharmony_ci    def closed(self):
21987db96d56Sopenharmony_ci        return self.buffer.closed
21997db96d56Sopenharmony_ci
22007db96d56Sopenharmony_ci    @property
22017db96d56Sopenharmony_ci    def name(self):
22027db96d56Sopenharmony_ci        return self.buffer.name
22037db96d56Sopenharmony_ci
22047db96d56Sopenharmony_ci    def fileno(self):
22057db96d56Sopenharmony_ci        return self.buffer.fileno()
22067db96d56Sopenharmony_ci
22077db96d56Sopenharmony_ci    def isatty(self):
22087db96d56Sopenharmony_ci        return self.buffer.isatty()
22097db96d56Sopenharmony_ci
22107db96d56Sopenharmony_ci    def write(self, s):
22117db96d56Sopenharmony_ci        'Write data, where s is a str'
22127db96d56Sopenharmony_ci        if self.closed:
22137db96d56Sopenharmony_ci            raise ValueError("write to closed file")
22147db96d56Sopenharmony_ci        if not isinstance(s, str):
22157db96d56Sopenharmony_ci            raise TypeError("can't write %s to text stream" %
22167db96d56Sopenharmony_ci                            s.__class__.__name__)
22177db96d56Sopenharmony_ci        length = len(s)
22187db96d56Sopenharmony_ci        haslf = (self._writetranslate or self._line_buffering) and "\n" in s
22197db96d56Sopenharmony_ci        if haslf and self._writetranslate and self._writenl != "\n":
22207db96d56Sopenharmony_ci            s = s.replace("\n", self._writenl)
22217db96d56Sopenharmony_ci        encoder = self._encoder or self._get_encoder()
22227db96d56Sopenharmony_ci        # XXX What if we were just reading?
22237db96d56Sopenharmony_ci        b = encoder.encode(s)
22247db96d56Sopenharmony_ci        self.buffer.write(b)
22257db96d56Sopenharmony_ci        if self._line_buffering and (haslf or "\r" in s):
22267db96d56Sopenharmony_ci            self.flush()
22277db96d56Sopenharmony_ci        self._set_decoded_chars('')
22287db96d56Sopenharmony_ci        self._snapshot = None
22297db96d56Sopenharmony_ci        if self._decoder:
22307db96d56Sopenharmony_ci            self._decoder.reset()
22317db96d56Sopenharmony_ci        return length
22327db96d56Sopenharmony_ci
22337db96d56Sopenharmony_ci    def _get_encoder(self):
22347db96d56Sopenharmony_ci        make_encoder = codecs.getincrementalencoder(self._encoding)
22357db96d56Sopenharmony_ci        self._encoder = make_encoder(self._errors)
22367db96d56Sopenharmony_ci        return self._encoder
22377db96d56Sopenharmony_ci
22387db96d56Sopenharmony_ci    def _get_decoder(self):
22397db96d56Sopenharmony_ci        make_decoder = codecs.getincrementaldecoder(self._encoding)
22407db96d56Sopenharmony_ci        decoder = make_decoder(self._errors)
22417db96d56Sopenharmony_ci        if self._readuniversal:
22427db96d56Sopenharmony_ci            decoder = IncrementalNewlineDecoder(decoder, self._readtranslate)
22437db96d56Sopenharmony_ci        self._decoder = decoder
22447db96d56Sopenharmony_ci        return decoder
22457db96d56Sopenharmony_ci
22467db96d56Sopenharmony_ci    # The following three methods implement an ADT for _decoded_chars.
22477db96d56Sopenharmony_ci    # Text returned from the decoder is buffered here until the client
22487db96d56Sopenharmony_ci    # requests it by calling our read() or readline() method.
22497db96d56Sopenharmony_ci    def _set_decoded_chars(self, chars):
22507db96d56Sopenharmony_ci        """Set the _decoded_chars buffer."""
22517db96d56Sopenharmony_ci        self._decoded_chars = chars
22527db96d56Sopenharmony_ci        self._decoded_chars_used = 0
22537db96d56Sopenharmony_ci
22547db96d56Sopenharmony_ci    def _get_decoded_chars(self, n=None):
22557db96d56Sopenharmony_ci        """Advance into the _decoded_chars buffer."""
22567db96d56Sopenharmony_ci        offset = self._decoded_chars_used
22577db96d56Sopenharmony_ci        if n is None:
22587db96d56Sopenharmony_ci            chars = self._decoded_chars[offset:]
22597db96d56Sopenharmony_ci        else:
22607db96d56Sopenharmony_ci            chars = self._decoded_chars[offset:offset + n]
22617db96d56Sopenharmony_ci        self._decoded_chars_used += len(chars)
22627db96d56Sopenharmony_ci        return chars
22637db96d56Sopenharmony_ci
22647db96d56Sopenharmony_ci    def _get_locale_encoding(self):
22657db96d56Sopenharmony_ci        try:
22667db96d56Sopenharmony_ci            import locale
22677db96d56Sopenharmony_ci        except ImportError:
22687db96d56Sopenharmony_ci            # Importing locale may fail if Python is being built
22697db96d56Sopenharmony_ci            return "utf-8"
22707db96d56Sopenharmony_ci        else:
22717db96d56Sopenharmony_ci            return locale.getencoding()
22727db96d56Sopenharmony_ci
22737db96d56Sopenharmony_ci    def _rewind_decoded_chars(self, n):
22747db96d56Sopenharmony_ci        """Rewind the _decoded_chars buffer."""
22757db96d56Sopenharmony_ci        if self._decoded_chars_used < n:
22767db96d56Sopenharmony_ci            raise AssertionError("rewind decoded_chars out of bounds")
22777db96d56Sopenharmony_ci        self._decoded_chars_used -= n
22787db96d56Sopenharmony_ci
22797db96d56Sopenharmony_ci    def _read_chunk(self):
22807db96d56Sopenharmony_ci        """
22817db96d56Sopenharmony_ci        Read and decode the next chunk of data from the BufferedReader.
22827db96d56Sopenharmony_ci        """
22837db96d56Sopenharmony_ci
22847db96d56Sopenharmony_ci        # The return value is True unless EOF was reached.  The decoded
22857db96d56Sopenharmony_ci        # string is placed in self._decoded_chars (replacing its previous
22867db96d56Sopenharmony_ci        # value).  The entire input chunk is sent to the decoder, though
22877db96d56Sopenharmony_ci        # some of it may remain buffered in the decoder, yet to be
22887db96d56Sopenharmony_ci        # converted.
22897db96d56Sopenharmony_ci
22907db96d56Sopenharmony_ci        if self._decoder is None:
22917db96d56Sopenharmony_ci            raise ValueError("no decoder")
22927db96d56Sopenharmony_ci
22937db96d56Sopenharmony_ci        if self._telling:
22947db96d56Sopenharmony_ci            # To prepare for tell(), we need to snapshot a point in the
22957db96d56Sopenharmony_ci            # file where the decoder's input buffer is empty.
22967db96d56Sopenharmony_ci
22977db96d56Sopenharmony_ci            dec_buffer, dec_flags = self._decoder.getstate()
22987db96d56Sopenharmony_ci            # Given this, we know there was a valid snapshot point
22997db96d56Sopenharmony_ci            # len(dec_buffer) bytes ago with decoder state (b'', dec_flags).
23007db96d56Sopenharmony_ci
23017db96d56Sopenharmony_ci        # Read a chunk, decode it, and put the result in self._decoded_chars.
23027db96d56Sopenharmony_ci        if self._has_read1:
23037db96d56Sopenharmony_ci            input_chunk = self.buffer.read1(self._CHUNK_SIZE)
23047db96d56Sopenharmony_ci        else:
23057db96d56Sopenharmony_ci            input_chunk = self.buffer.read(self._CHUNK_SIZE)
23067db96d56Sopenharmony_ci        eof = not input_chunk
23077db96d56Sopenharmony_ci        decoded_chars = self._decoder.decode(input_chunk, eof)
23087db96d56Sopenharmony_ci        self._set_decoded_chars(decoded_chars)
23097db96d56Sopenharmony_ci        if decoded_chars:
23107db96d56Sopenharmony_ci            self._b2cratio = len(input_chunk) / len(self._decoded_chars)
23117db96d56Sopenharmony_ci        else:
23127db96d56Sopenharmony_ci            self._b2cratio = 0.0
23137db96d56Sopenharmony_ci
23147db96d56Sopenharmony_ci        if self._telling:
23157db96d56Sopenharmony_ci            # At the snapshot point, len(dec_buffer) bytes before the read,
23167db96d56Sopenharmony_ci            # the next input to be decoded is dec_buffer + input_chunk.
23177db96d56Sopenharmony_ci            self._snapshot = (dec_flags, dec_buffer + input_chunk)
23187db96d56Sopenharmony_ci
23197db96d56Sopenharmony_ci        return not eof
23207db96d56Sopenharmony_ci
23217db96d56Sopenharmony_ci    def _pack_cookie(self, position, dec_flags=0,
23227db96d56Sopenharmony_ci                           bytes_to_feed=0, need_eof=False, chars_to_skip=0):
23237db96d56Sopenharmony_ci        # The meaning of a tell() cookie is: seek to position, set the
23247db96d56Sopenharmony_ci        # decoder flags to dec_flags, read bytes_to_feed bytes, feed them
23257db96d56Sopenharmony_ci        # into the decoder with need_eof as the EOF flag, then skip
23267db96d56Sopenharmony_ci        # chars_to_skip characters of the decoded result.  For most simple
23277db96d56Sopenharmony_ci        # decoders, tell() will often just give a byte offset in the file.
23287db96d56Sopenharmony_ci        return (position | (dec_flags<<64) | (bytes_to_feed<<128) |
23297db96d56Sopenharmony_ci               (chars_to_skip<<192) | bool(need_eof)<<256)
23307db96d56Sopenharmony_ci
23317db96d56Sopenharmony_ci    def _unpack_cookie(self, bigint):
23327db96d56Sopenharmony_ci        rest, position = divmod(bigint, 1<<64)
23337db96d56Sopenharmony_ci        rest, dec_flags = divmod(rest, 1<<64)
23347db96d56Sopenharmony_ci        rest, bytes_to_feed = divmod(rest, 1<<64)
23357db96d56Sopenharmony_ci        need_eof, chars_to_skip = divmod(rest, 1<<64)
23367db96d56Sopenharmony_ci        return position, dec_flags, bytes_to_feed, bool(need_eof), chars_to_skip
23377db96d56Sopenharmony_ci
23387db96d56Sopenharmony_ci    def tell(self):
23397db96d56Sopenharmony_ci        if not self._seekable:
23407db96d56Sopenharmony_ci            raise UnsupportedOperation("underlying stream is not seekable")
23417db96d56Sopenharmony_ci        if not self._telling:
23427db96d56Sopenharmony_ci            raise OSError("telling position disabled by next() call")
23437db96d56Sopenharmony_ci        self.flush()
23447db96d56Sopenharmony_ci        position = self.buffer.tell()
23457db96d56Sopenharmony_ci        decoder = self._decoder
23467db96d56Sopenharmony_ci        if decoder is None or self._snapshot is None:
23477db96d56Sopenharmony_ci            if self._decoded_chars:
23487db96d56Sopenharmony_ci                # This should never happen.
23497db96d56Sopenharmony_ci                raise AssertionError("pending decoded text")
23507db96d56Sopenharmony_ci            return position
23517db96d56Sopenharmony_ci
23527db96d56Sopenharmony_ci        # Skip backward to the snapshot point (see _read_chunk).
23537db96d56Sopenharmony_ci        dec_flags, next_input = self._snapshot
23547db96d56Sopenharmony_ci        position -= len(next_input)
23557db96d56Sopenharmony_ci
23567db96d56Sopenharmony_ci        # How many decoded characters have been used up since the snapshot?
23577db96d56Sopenharmony_ci        chars_to_skip = self._decoded_chars_used
23587db96d56Sopenharmony_ci        if chars_to_skip == 0:
23597db96d56Sopenharmony_ci            # We haven't moved from the snapshot point.
23607db96d56Sopenharmony_ci            return self._pack_cookie(position, dec_flags)
23617db96d56Sopenharmony_ci
23627db96d56Sopenharmony_ci        # Starting from the snapshot position, we will walk the decoder
23637db96d56Sopenharmony_ci        # forward until it gives us enough decoded characters.
23647db96d56Sopenharmony_ci        saved_state = decoder.getstate()
23657db96d56Sopenharmony_ci        try:
23667db96d56Sopenharmony_ci            # Fast search for an acceptable start point, close to our
23677db96d56Sopenharmony_ci            # current pos.
23687db96d56Sopenharmony_ci            # Rationale: calling decoder.decode() has a large overhead
23697db96d56Sopenharmony_ci            # regardless of chunk size; we want the number of such calls to
23707db96d56Sopenharmony_ci            # be O(1) in most situations (common decoders, sensible input).
23717db96d56Sopenharmony_ci            # Actually, it will be exactly 1 for fixed-size codecs (all
23727db96d56Sopenharmony_ci            # 8-bit codecs, also UTF-16 and UTF-32).
23737db96d56Sopenharmony_ci            skip_bytes = int(self._b2cratio * chars_to_skip)
23747db96d56Sopenharmony_ci            skip_back = 1
23757db96d56Sopenharmony_ci            assert skip_bytes <= len(next_input)
23767db96d56Sopenharmony_ci            while skip_bytes > 0:
23777db96d56Sopenharmony_ci                decoder.setstate((b'', dec_flags))
23787db96d56Sopenharmony_ci                # Decode up to temptative start point
23797db96d56Sopenharmony_ci                n = len(decoder.decode(next_input[:skip_bytes]))
23807db96d56Sopenharmony_ci                if n <= chars_to_skip:
23817db96d56Sopenharmony_ci                    b, d = decoder.getstate()
23827db96d56Sopenharmony_ci                    if not b:
23837db96d56Sopenharmony_ci                        # Before pos and no bytes buffered in decoder => OK
23847db96d56Sopenharmony_ci                        dec_flags = d
23857db96d56Sopenharmony_ci                        chars_to_skip -= n
23867db96d56Sopenharmony_ci                        break
23877db96d56Sopenharmony_ci                    # Skip back by buffered amount and reset heuristic
23887db96d56Sopenharmony_ci                    skip_bytes -= len(b)
23897db96d56Sopenharmony_ci                    skip_back = 1
23907db96d56Sopenharmony_ci                else:
23917db96d56Sopenharmony_ci                    # We're too far ahead, skip back a bit
23927db96d56Sopenharmony_ci                    skip_bytes -= skip_back
23937db96d56Sopenharmony_ci                    skip_back = skip_back * 2
23947db96d56Sopenharmony_ci            else:
23957db96d56Sopenharmony_ci                skip_bytes = 0
23967db96d56Sopenharmony_ci                decoder.setstate((b'', dec_flags))
23977db96d56Sopenharmony_ci
23987db96d56Sopenharmony_ci            # Note our initial start point.
23997db96d56Sopenharmony_ci            start_pos = position + skip_bytes
24007db96d56Sopenharmony_ci            start_flags = dec_flags
24017db96d56Sopenharmony_ci            if chars_to_skip == 0:
24027db96d56Sopenharmony_ci                # We haven't moved from the start point.
24037db96d56Sopenharmony_ci                return self._pack_cookie(start_pos, start_flags)
24047db96d56Sopenharmony_ci
24057db96d56Sopenharmony_ci            # Feed the decoder one byte at a time.  As we go, note the
24067db96d56Sopenharmony_ci            # nearest "safe start point" before the current location
24077db96d56Sopenharmony_ci            # (a point where the decoder has nothing buffered, so seek()
24087db96d56Sopenharmony_ci            # can safely start from there and advance to this location).
24097db96d56Sopenharmony_ci            bytes_fed = 0
24107db96d56Sopenharmony_ci            need_eof = False
24117db96d56Sopenharmony_ci            # Chars decoded since `start_pos`
24127db96d56Sopenharmony_ci            chars_decoded = 0
24137db96d56Sopenharmony_ci            for i in range(skip_bytes, len(next_input)):
24147db96d56Sopenharmony_ci                bytes_fed += 1
24157db96d56Sopenharmony_ci                chars_decoded += len(decoder.decode(next_input[i:i+1]))
24167db96d56Sopenharmony_ci                dec_buffer, dec_flags = decoder.getstate()
24177db96d56Sopenharmony_ci                if not dec_buffer and chars_decoded <= chars_to_skip:
24187db96d56Sopenharmony_ci                    # Decoder buffer is empty, so this is a safe start point.
24197db96d56Sopenharmony_ci                    start_pos += bytes_fed
24207db96d56Sopenharmony_ci                    chars_to_skip -= chars_decoded
24217db96d56Sopenharmony_ci                    start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0
24227db96d56Sopenharmony_ci                if chars_decoded >= chars_to_skip:
24237db96d56Sopenharmony_ci                    break
24247db96d56Sopenharmony_ci            else:
24257db96d56Sopenharmony_ci                # We didn't get enough decoded data; signal EOF to get more.
24267db96d56Sopenharmony_ci                chars_decoded += len(decoder.decode(b'', final=True))
24277db96d56Sopenharmony_ci                need_eof = True
24287db96d56Sopenharmony_ci                if chars_decoded < chars_to_skip:
24297db96d56Sopenharmony_ci                    raise OSError("can't reconstruct logical file position")
24307db96d56Sopenharmony_ci
24317db96d56Sopenharmony_ci            # The returned cookie corresponds to the last safe start point.
24327db96d56Sopenharmony_ci            return self._pack_cookie(
24337db96d56Sopenharmony_ci                start_pos, start_flags, bytes_fed, need_eof, chars_to_skip)
24347db96d56Sopenharmony_ci        finally:
24357db96d56Sopenharmony_ci            decoder.setstate(saved_state)
24367db96d56Sopenharmony_ci
24377db96d56Sopenharmony_ci    def truncate(self, pos=None):
24387db96d56Sopenharmony_ci        self.flush()
24397db96d56Sopenharmony_ci        if pos is None:
24407db96d56Sopenharmony_ci            pos = self.tell()
24417db96d56Sopenharmony_ci        return self.buffer.truncate(pos)
24427db96d56Sopenharmony_ci
24437db96d56Sopenharmony_ci    def detach(self):
24447db96d56Sopenharmony_ci        if self.buffer is None:
24457db96d56Sopenharmony_ci            raise ValueError("buffer is already detached")
24467db96d56Sopenharmony_ci        self.flush()
24477db96d56Sopenharmony_ci        buffer = self._buffer
24487db96d56Sopenharmony_ci        self._buffer = None
24497db96d56Sopenharmony_ci        return buffer
24507db96d56Sopenharmony_ci
24517db96d56Sopenharmony_ci    def seek(self, cookie, whence=0):
24527db96d56Sopenharmony_ci        def _reset_encoder(position):
24537db96d56Sopenharmony_ci            """Reset the encoder (merely useful for proper BOM handling)"""
24547db96d56Sopenharmony_ci            try:
24557db96d56Sopenharmony_ci                encoder = self._encoder or self._get_encoder()
24567db96d56Sopenharmony_ci            except LookupError:
24577db96d56Sopenharmony_ci                # Sometimes the encoder doesn't exist
24587db96d56Sopenharmony_ci                pass
24597db96d56Sopenharmony_ci            else:
24607db96d56Sopenharmony_ci                if position != 0:
24617db96d56Sopenharmony_ci                    encoder.setstate(0)
24627db96d56Sopenharmony_ci                else:
24637db96d56Sopenharmony_ci                    encoder.reset()
24647db96d56Sopenharmony_ci
24657db96d56Sopenharmony_ci        if self.closed:
24667db96d56Sopenharmony_ci            raise ValueError("tell on closed file")
24677db96d56Sopenharmony_ci        if not self._seekable:
24687db96d56Sopenharmony_ci            raise UnsupportedOperation("underlying stream is not seekable")
24697db96d56Sopenharmony_ci        if whence == SEEK_CUR:
24707db96d56Sopenharmony_ci            if cookie != 0:
24717db96d56Sopenharmony_ci                raise UnsupportedOperation("can't do nonzero cur-relative seeks")
24727db96d56Sopenharmony_ci            # Seeking to the current position should attempt to
24737db96d56Sopenharmony_ci            # sync the underlying buffer with the current position.
24747db96d56Sopenharmony_ci            whence = 0
24757db96d56Sopenharmony_ci            cookie = self.tell()
24767db96d56Sopenharmony_ci        elif whence == SEEK_END:
24777db96d56Sopenharmony_ci            if cookie != 0:
24787db96d56Sopenharmony_ci                raise UnsupportedOperation("can't do nonzero end-relative seeks")
24797db96d56Sopenharmony_ci            self.flush()
24807db96d56Sopenharmony_ci            position = self.buffer.seek(0, whence)
24817db96d56Sopenharmony_ci            self._set_decoded_chars('')
24827db96d56Sopenharmony_ci            self._snapshot = None
24837db96d56Sopenharmony_ci            if self._decoder:
24847db96d56Sopenharmony_ci                self._decoder.reset()
24857db96d56Sopenharmony_ci            _reset_encoder(position)
24867db96d56Sopenharmony_ci            return position
24877db96d56Sopenharmony_ci        if whence != 0:
24887db96d56Sopenharmony_ci            raise ValueError("unsupported whence (%r)" % (whence,))
24897db96d56Sopenharmony_ci        if cookie < 0:
24907db96d56Sopenharmony_ci            raise ValueError("negative seek position %r" % (cookie,))
24917db96d56Sopenharmony_ci        self.flush()
24927db96d56Sopenharmony_ci
24937db96d56Sopenharmony_ci        # The strategy of seek() is to go back to the safe start point
24947db96d56Sopenharmony_ci        # and replay the effect of read(chars_to_skip) from there.
24957db96d56Sopenharmony_ci        start_pos, dec_flags, bytes_to_feed, need_eof, chars_to_skip = \
24967db96d56Sopenharmony_ci            self._unpack_cookie(cookie)
24977db96d56Sopenharmony_ci
24987db96d56Sopenharmony_ci        # Seek back to the safe start point.
24997db96d56Sopenharmony_ci        self.buffer.seek(start_pos)
25007db96d56Sopenharmony_ci        self._set_decoded_chars('')
25017db96d56Sopenharmony_ci        self._snapshot = None
25027db96d56Sopenharmony_ci
25037db96d56Sopenharmony_ci        # Restore the decoder to its state from the safe start point.
25047db96d56Sopenharmony_ci        if cookie == 0 and self._decoder:
25057db96d56Sopenharmony_ci            self._decoder.reset()
25067db96d56Sopenharmony_ci        elif self._decoder or dec_flags or chars_to_skip:
25077db96d56Sopenharmony_ci            self._decoder = self._decoder or self._get_decoder()
25087db96d56Sopenharmony_ci            self._decoder.setstate((b'', dec_flags))
25097db96d56Sopenharmony_ci            self._snapshot = (dec_flags, b'')
25107db96d56Sopenharmony_ci
25117db96d56Sopenharmony_ci        if chars_to_skip:
25127db96d56Sopenharmony_ci            # Just like _read_chunk, feed the decoder and save a snapshot.
25137db96d56Sopenharmony_ci            input_chunk = self.buffer.read(bytes_to_feed)
25147db96d56Sopenharmony_ci            self._set_decoded_chars(
25157db96d56Sopenharmony_ci                self._decoder.decode(input_chunk, need_eof))
25167db96d56Sopenharmony_ci            self._snapshot = (dec_flags, input_chunk)
25177db96d56Sopenharmony_ci
25187db96d56Sopenharmony_ci            # Skip chars_to_skip of the decoded characters.
25197db96d56Sopenharmony_ci            if len(self._decoded_chars) < chars_to_skip:
25207db96d56Sopenharmony_ci                raise OSError("can't restore logical file position")
25217db96d56Sopenharmony_ci            self._decoded_chars_used = chars_to_skip
25227db96d56Sopenharmony_ci
25237db96d56Sopenharmony_ci        _reset_encoder(cookie)
25247db96d56Sopenharmony_ci        return cookie
25257db96d56Sopenharmony_ci
25267db96d56Sopenharmony_ci    def read(self, size=None):
25277db96d56Sopenharmony_ci        self._checkReadable()
25287db96d56Sopenharmony_ci        if size is None:
25297db96d56Sopenharmony_ci            size = -1
25307db96d56Sopenharmony_ci        else:
25317db96d56Sopenharmony_ci            try:
25327db96d56Sopenharmony_ci                size_index = size.__index__
25337db96d56Sopenharmony_ci            except AttributeError:
25347db96d56Sopenharmony_ci                raise TypeError(f"{size!r} is not an integer")
25357db96d56Sopenharmony_ci            else:
25367db96d56Sopenharmony_ci                size = size_index()
25377db96d56Sopenharmony_ci        decoder = self._decoder or self._get_decoder()
25387db96d56Sopenharmony_ci        if size < 0:
25397db96d56Sopenharmony_ci            # Read everything.
25407db96d56Sopenharmony_ci            result = (self._get_decoded_chars() +
25417db96d56Sopenharmony_ci                      decoder.decode(self.buffer.read(), final=True))
25427db96d56Sopenharmony_ci            self._set_decoded_chars('')
25437db96d56Sopenharmony_ci            self._snapshot = None
25447db96d56Sopenharmony_ci            return result
25457db96d56Sopenharmony_ci        else:
25467db96d56Sopenharmony_ci            # Keep reading chunks until we have size characters to return.
25477db96d56Sopenharmony_ci            eof = False
25487db96d56Sopenharmony_ci            result = self._get_decoded_chars(size)
25497db96d56Sopenharmony_ci            while len(result) < size and not eof:
25507db96d56Sopenharmony_ci                eof = not self._read_chunk()
25517db96d56Sopenharmony_ci                result += self._get_decoded_chars(size - len(result))
25527db96d56Sopenharmony_ci            return result
25537db96d56Sopenharmony_ci
25547db96d56Sopenharmony_ci    def __next__(self):
25557db96d56Sopenharmony_ci        self._telling = False
25567db96d56Sopenharmony_ci        line = self.readline()
25577db96d56Sopenharmony_ci        if not line:
25587db96d56Sopenharmony_ci            self._snapshot = None
25597db96d56Sopenharmony_ci            self._telling = self._seekable
25607db96d56Sopenharmony_ci            raise StopIteration
25617db96d56Sopenharmony_ci        return line
25627db96d56Sopenharmony_ci
25637db96d56Sopenharmony_ci    def readline(self, size=None):
25647db96d56Sopenharmony_ci        if self.closed:
25657db96d56Sopenharmony_ci            raise ValueError("read from closed file")
25667db96d56Sopenharmony_ci        if size is None:
25677db96d56Sopenharmony_ci            size = -1
25687db96d56Sopenharmony_ci        else:
25697db96d56Sopenharmony_ci            try:
25707db96d56Sopenharmony_ci                size_index = size.__index__
25717db96d56Sopenharmony_ci            except AttributeError:
25727db96d56Sopenharmony_ci                raise TypeError(f"{size!r} is not an integer")
25737db96d56Sopenharmony_ci            else:
25747db96d56Sopenharmony_ci                size = size_index()
25757db96d56Sopenharmony_ci
25767db96d56Sopenharmony_ci        # Grab all the decoded text (we will rewind any extra bits later).
25777db96d56Sopenharmony_ci        line = self._get_decoded_chars()
25787db96d56Sopenharmony_ci
25797db96d56Sopenharmony_ci        start = 0
25807db96d56Sopenharmony_ci        # Make the decoder if it doesn't already exist.
25817db96d56Sopenharmony_ci        if not self._decoder:
25827db96d56Sopenharmony_ci            self._get_decoder()
25837db96d56Sopenharmony_ci
25847db96d56Sopenharmony_ci        pos = endpos = None
25857db96d56Sopenharmony_ci        while True:
25867db96d56Sopenharmony_ci            if self._readtranslate:
25877db96d56Sopenharmony_ci                # Newlines are already translated, only search for \n
25887db96d56Sopenharmony_ci                pos = line.find('\n', start)
25897db96d56Sopenharmony_ci                if pos >= 0:
25907db96d56Sopenharmony_ci                    endpos = pos + 1
25917db96d56Sopenharmony_ci                    break
25927db96d56Sopenharmony_ci                else:
25937db96d56Sopenharmony_ci                    start = len(line)
25947db96d56Sopenharmony_ci
25957db96d56Sopenharmony_ci            elif self._readuniversal:
25967db96d56Sopenharmony_ci                # Universal newline search. Find any of \r, \r\n, \n
25977db96d56Sopenharmony_ci                # The decoder ensures that \r\n are not split in two pieces
25987db96d56Sopenharmony_ci
25997db96d56Sopenharmony_ci                # In C we'd look for these in parallel of course.
26007db96d56Sopenharmony_ci                nlpos = line.find("\n", start)
26017db96d56Sopenharmony_ci                crpos = line.find("\r", start)
26027db96d56Sopenharmony_ci                if crpos == -1:
26037db96d56Sopenharmony_ci                    if nlpos == -1:
26047db96d56Sopenharmony_ci                        # Nothing found
26057db96d56Sopenharmony_ci                        start = len(line)
26067db96d56Sopenharmony_ci                    else:
26077db96d56Sopenharmony_ci                        # Found \n
26087db96d56Sopenharmony_ci                        endpos = nlpos + 1
26097db96d56Sopenharmony_ci                        break
26107db96d56Sopenharmony_ci                elif nlpos == -1:
26117db96d56Sopenharmony_ci                    # Found lone \r
26127db96d56Sopenharmony_ci                    endpos = crpos + 1
26137db96d56Sopenharmony_ci                    break
26147db96d56Sopenharmony_ci                elif nlpos < crpos:
26157db96d56Sopenharmony_ci                    # Found \n
26167db96d56Sopenharmony_ci                    endpos = nlpos + 1
26177db96d56Sopenharmony_ci                    break
26187db96d56Sopenharmony_ci                elif nlpos == crpos + 1:
26197db96d56Sopenharmony_ci                    # Found \r\n
26207db96d56Sopenharmony_ci                    endpos = crpos + 2
26217db96d56Sopenharmony_ci                    break
26227db96d56Sopenharmony_ci                else:
26237db96d56Sopenharmony_ci                    # Found \r
26247db96d56Sopenharmony_ci                    endpos = crpos + 1
26257db96d56Sopenharmony_ci                    break
26267db96d56Sopenharmony_ci            else:
26277db96d56Sopenharmony_ci                # non-universal
26287db96d56Sopenharmony_ci                pos = line.find(self._readnl)
26297db96d56Sopenharmony_ci                if pos >= 0:
26307db96d56Sopenharmony_ci                    endpos = pos + len(self._readnl)
26317db96d56Sopenharmony_ci                    break
26327db96d56Sopenharmony_ci
26337db96d56Sopenharmony_ci            if size >= 0 and len(line) >= size:
26347db96d56Sopenharmony_ci                endpos = size  # reached length size
26357db96d56Sopenharmony_ci                break
26367db96d56Sopenharmony_ci
26377db96d56Sopenharmony_ci            # No line ending seen yet - get more data'
26387db96d56Sopenharmony_ci            while self._read_chunk():
26397db96d56Sopenharmony_ci                if self._decoded_chars:
26407db96d56Sopenharmony_ci                    break
26417db96d56Sopenharmony_ci            if self._decoded_chars:
26427db96d56Sopenharmony_ci                line += self._get_decoded_chars()
26437db96d56Sopenharmony_ci            else:
26447db96d56Sopenharmony_ci                # end of file
26457db96d56Sopenharmony_ci                self._set_decoded_chars('')
26467db96d56Sopenharmony_ci                self._snapshot = None
26477db96d56Sopenharmony_ci                return line
26487db96d56Sopenharmony_ci
26497db96d56Sopenharmony_ci        if size >= 0 and endpos > size:
26507db96d56Sopenharmony_ci            endpos = size  # don't exceed size
26517db96d56Sopenharmony_ci
26527db96d56Sopenharmony_ci        # Rewind _decoded_chars to just after the line ending we found.
26537db96d56Sopenharmony_ci        self._rewind_decoded_chars(len(line) - endpos)
26547db96d56Sopenharmony_ci        return line[:endpos]
26557db96d56Sopenharmony_ci
26567db96d56Sopenharmony_ci    @property
26577db96d56Sopenharmony_ci    def newlines(self):
26587db96d56Sopenharmony_ci        return self._decoder.newlines if self._decoder else None
26597db96d56Sopenharmony_ci
26607db96d56Sopenharmony_ci
26617db96d56Sopenharmony_ciclass StringIO(TextIOWrapper):
26627db96d56Sopenharmony_ci    """Text I/O implementation using an in-memory buffer.
26637db96d56Sopenharmony_ci
26647db96d56Sopenharmony_ci    The initial_value argument sets the value of object.  The newline
26657db96d56Sopenharmony_ci    argument is like the one of TextIOWrapper's constructor.
26667db96d56Sopenharmony_ci    """
26677db96d56Sopenharmony_ci
26687db96d56Sopenharmony_ci    def __init__(self, initial_value="", newline="\n"):
26697db96d56Sopenharmony_ci        super(StringIO, self).__init__(BytesIO(),
26707db96d56Sopenharmony_ci                                       encoding="utf-8",
26717db96d56Sopenharmony_ci                                       errors="surrogatepass",
26727db96d56Sopenharmony_ci                                       newline=newline)
26737db96d56Sopenharmony_ci        # Issue #5645: make universal newlines semantics the same as in the
26747db96d56Sopenharmony_ci        # C version, even under Windows.
26757db96d56Sopenharmony_ci        if newline is None:
26767db96d56Sopenharmony_ci            self._writetranslate = False
26777db96d56Sopenharmony_ci        if initial_value is not None:
26787db96d56Sopenharmony_ci            if not isinstance(initial_value, str):
26797db96d56Sopenharmony_ci                raise TypeError("initial_value must be str or None, not {0}"
26807db96d56Sopenharmony_ci                                .format(type(initial_value).__name__))
26817db96d56Sopenharmony_ci            self.write(initial_value)
26827db96d56Sopenharmony_ci            self.seek(0)
26837db96d56Sopenharmony_ci
26847db96d56Sopenharmony_ci    def getvalue(self):
26857db96d56Sopenharmony_ci        self.flush()
26867db96d56Sopenharmony_ci        decoder = self._decoder or self._get_decoder()
26877db96d56Sopenharmony_ci        old_state = decoder.getstate()
26887db96d56Sopenharmony_ci        decoder.reset()
26897db96d56Sopenharmony_ci        try:
26907db96d56Sopenharmony_ci            return decoder.decode(self.buffer.getvalue(), final=True)
26917db96d56Sopenharmony_ci        finally:
26927db96d56Sopenharmony_ci            decoder.setstate(old_state)
26937db96d56Sopenharmony_ci
26947db96d56Sopenharmony_ci    def __repr__(self):
26957db96d56Sopenharmony_ci        # TextIOWrapper tells the encoding in its repr. In StringIO,
26967db96d56Sopenharmony_ci        # that's an implementation detail.
26977db96d56Sopenharmony_ci        return object.__repr__(self)
26987db96d56Sopenharmony_ci
26997db96d56Sopenharmony_ci    @property
27007db96d56Sopenharmony_ci    def errors(self):
27017db96d56Sopenharmony_ci        return None
27027db96d56Sopenharmony_ci
27037db96d56Sopenharmony_ci    @property
27047db96d56Sopenharmony_ci    def encoding(self):
27057db96d56Sopenharmony_ci        return None
27067db96d56Sopenharmony_ci
27077db96d56Sopenharmony_ci    def detach(self):
27087db96d56Sopenharmony_ci        # This doesn't make sense on StringIO.
27097db96d56Sopenharmony_ci        self._unsupported("detach")
2710