// Written in the D programming language.

/**
$(SCRIPT inhibitQuickIndex = 1;)
$(DIVC quickindex,
$(BOOKTABLE,
$(TR $(TH Category) $(TH Symbols))
$(TR $(TD File handles) $(TD
    $(MYREF __popen)
    $(MYREF File)
    $(MYREF isFileHandle)
    $(MYREF openNetwork)
    $(MYREF stderr)
    $(MYREF stdin)
    $(MYREF stdout)
))
$(TR $(TD Reading) $(TD
    $(MYREF chunks)
    $(MYREF lines)
    $(MYREF readf)
    $(MYREF readln)
))
$(TR $(TD Writing) $(TD
    $(MYREF toFile)
    $(MYREF write)
    $(MYREF writef)
    $(MYREF writefln)
    $(MYREF writeln)
))
$(TR $(TD Misc) $(TD
    $(MYREF KeepTerminator)
    $(MYREF LockType)
    $(MYREF StdioException)
))
))

Standard I/O functions that extend $(B core.stdc.stdio).  $(B core.stdc.stdio)
is $(D_PARAM public)ally imported when importing $(B std.stdio).

Source: $(PHOBOSSRC std/stdio.d)
Copyright: Copyright The D Language Foundation 2007-.
License:   $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
Authors:   $(HTTP digitalmars.com, Walter Bright),
           $(HTTP erdani.org, Andrei Alexandrescu),
           Alex Rønne Petersen
 */
module std.stdio;

import core.stdc.stddef : wchar_t;
public import core.stdc.stdio;
import std.algorithm.mutation : copy;
import std.meta : allSatisfy;
import std.range : ElementEncodingType, empty, front, isBidirectionalRange,
    isInputRange, isSomeFiniteCharInputRange, put;
import std.traits : isSomeChar, isSomeString, Unqual, isPointer;
import std.typecons : Flag, No, Yes;

/++
If flag `KeepTerminator` is set to `KeepTerminator.yes`, then the delimiter
is included in the strings returned.
+/
alias KeepTerminator = Flag!"keepTerminator";

version (CRuntime_Microsoft)
{
    version = MICROSOFT_STDIO;
}
else version (CRuntime_DigitalMars)
{
    // Specific to the way Digital Mars C does stdio
    version = DIGITAL_MARS_STDIO;
}
else version (CRuntime_Glibc)
{
    // Specific to the way Gnu C does stdio
    version = GCC_IO;
}
else version (CRuntime_Bionic)
{
    version = GENERIC_IO;
}
else version (CRuntime_Musl)
{
    version = GENERIC_IO;
}
else version (CRuntime_UClibc)
{
    // uClibc supports GCC IO
    version = GCC_IO;
}
else version (OSX)
{
    version = GENERIC_IO;
    version = Darwin;
}
else version (iOS)
{
    version = GENERIC_IO;
    version = Darwin;
}
else version (TVOS)
{
    version = GENERIC_IO;
    version = Darwin;
}
else version (WatchOS)
{
    version = GENERIC_IO;
    version = Darwin;
}
else version (FreeBSD)
{
    version = GENERIC_IO;
}
else version (NetBSD)
{
    version = GENERIC_IO;
}
else version (OpenBSD)
{
    version = GENERIC_IO;
}
else version (DragonFlyBSD)
{
    version = GENERIC_IO;
}
else version (Solaris)
{
    version = GENERIC_IO;
}

// Character type used for operating system filesystem APIs
version (Windows)
{
    private alias FSChar = wchar;
}
else
{
    private alias FSChar = char;
}


version (Windows)
{
    // core.stdc.stdio.fopen expects file names to be
    // encoded in CP_ACP on Windows instead of UTF-8.
    /+ Waiting for druntime pull 299
    +/
    extern (C) nothrow @nogc FILE* _wfopen(in wchar* filename, in wchar* mode);
    extern (C) nothrow @nogc FILE* _wfreopen(in wchar* filename, in wchar* mode, FILE* fp);

    import core.sys.windows.basetsd : HANDLE;
}

version (Posix)
{
    static import core.sys.posix.stdio; // getdelim, flockfile
}

version (DIGITAL_MARS_STDIO)
{
    private alias _FPUTC = _fputc_nlock;
    private alias _FPUTWC = _fputwc_nlock;
    private alias _FGETC = _fgetc_nlock;
    private alias _FGETWC = _fgetwc_nlock;
    private alias _FLOCK = __fp_lock;
    private alias _FUNLOCK = __fp_unlock;

    // Alias for MICROSOFT_STDIO compatibility.
    // @@@DEPRECATED_2.107@@@
    // Rename this back to _setmode once the deprecation phase has ended.
    private alias __setmode = setmode;

    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FPUTC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FPUTC = _fputc_nlock;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FPUTWC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FPUTWC = _fputwc_nlock;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FGETC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FGETC = _fgetc_nlock;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FGETWC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FGETWC = _fgetwc_nlock;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FLOCK was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FLOCK = __fp_lock;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FUNLOCK was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FUNLOCK = __fp_unlock;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias _setmode was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias _setmode = setmode;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal function _fileno was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    int _fileno(FILE* f) { return f._file; }
}
else version (MICROSOFT_STDIO)
{
    private alias _FPUTC = _fputc_nolock;
    private alias _FPUTWC = _fputwc_nolock;
    private alias _FGETC = _fgetc_nolock;
    private alias _FGETWC = _fgetwc_nolock;
    private alias _FLOCK = _lock_file;
    private alias _FUNLOCK = _unlock_file;

    // @@@DEPRECATED_2.107@@@
    // Remove this once the deprecation phase for DIGITAL_MARS_STDIO has ended.
    private alias __setmode = _setmode;

    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FPUTC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FPUTC = _fputc_nolock;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FPUTWC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FPUTWC = _fputwc_nolock;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FGETC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FGETC = _fgetc_nolock;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FGETWC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FGETWC = _fgetwc_nolock;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FLOCK was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FLOCK = _lock_file;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FUNLOCK was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FUNLOCK = _unlock_file;
}
else version (GCC_IO)
{
    private alias _FPUTC = fputc_unlocked;
    private alias _FPUTWC = fputwc_unlocked;
    private alias _FGETC = fgetc_unlocked;
    private alias _FGETWC = fgetwc_unlocked;
    private alias _FLOCK = core.sys.posix.stdio.flockfile;
    private alias _FUNLOCK = core.sys.posix.stdio.funlockfile;

    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FPUTC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FPUTC = fputc_unlocked;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FPUTWC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FPUTWC = fputwc_unlocked;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FGETC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FGETC = fgetc_unlocked;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FGETWC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FGETWC = fgetwc_unlocked;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FLOCK was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FLOCK = core.sys.posix.stdio.flockfile;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FUNLOCK was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FUNLOCK = core.sys.posix.stdio.funlockfile;
}
else version (GENERIC_IO)
{
    nothrow:
    @nogc:

    extern (C) private
    {
        static import core.stdc.wchar_;

        pragma(mangle, fputc.mangleof) int _FPUTC(int c, _iobuf* fp);
        pragma(mangle, core.stdc.wchar_.fputwc.mangleof) int _FPUTWC(wchar_t c, _iobuf* fp);
        pragma(mangle, fgetc.mangleof) int _FGETC(_iobuf* fp);
        pragma(mangle, core.stdc.wchar_.fgetwc.mangleof) int _FGETWC(_iobuf* fp);
    }

    version (Posix)
    {
        private alias _FLOCK = core.sys.posix.stdio.flockfile;
        private alias _FUNLOCK = core.sys.posix.stdio.funlockfile;
    }
    else
    {
        static assert(0, "don't know how to lock files on GENERIC_IO");
    }

    // @@@DEPRECATED_2.107@@@
    deprecated("internal function fputc_unlocked was unintentionally available "
               ~ "from std.stdio and will be removed afer 2.107")
    extern (C) pragma(mangle, fputc.mangleof) int fputc_unlocked(int c, _iobuf* fp);
    // @@@DEPRECATED_2.107@@@
    deprecated("internal function fputwc_unlocked was unintentionally available "
               ~ "from std.stdio and will be removed afer 2.107")
    extern (C) pragma(mangle, core.stdc.wchar_.fputwc.mangleof) int fputwc_unlocked(wchar_t c, _iobuf* fp);
    // @@@DEPRECATED_2.107@@@
    deprecated("internal function fgetc_unlocked was unintentionally available "
               ~ "from std.stdio and will be removed afer 2.107")
    extern (C) pragma(mangle, fgetc.mangleof) int fgetc_unlocked(_iobuf* fp);
    // @@@DEPRECATED_2.107@@@
    deprecated("internal function fgetwc_unlocked was unintentionally available "
               ~ "from std.stdio and will be removed afer 2.107")
    extern (C) pragma(mangle, core.stdc.wchar_.fgetwc.mangleof) int fgetwc_unlocked(_iobuf* fp);

    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FPUTC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FPUTC = fputc_unlocked;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FPUTWC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FPUTWC = fputwc_unlocked;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FGETC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FGETC = fgetc_unlocked;
    // @@@DEPRECATED_2.107@@@
    deprecated("internal alias FGETWC was unintentionally available from "
               ~ "std.stdio and will be removed afer 2.107")
    alias FGETWC = fgetwc_unlocked;

    version (Posix)
    {
        // @@@DEPRECATED_2.107@@@
        deprecated("internal alias FLOCK was unintentionally available from "
                   ~ "std.stdio and will be removed afer 2.107")
        alias FLOCK = core.sys.posix.stdio.flockfile;
        // @@@DEPRECATED_2.107@@@
        deprecated("internal alias FUNLOCK was unintentionally available from "
                   ~ "std.stdio and will be removed afer 2.107")
        alias FUNLOCK = core.sys.posix.stdio.funlockfile;
    }
}
else
{
    static assert(0, "unsupported C I/O system");
}

private extern (C) @nogc nothrow
{
    pragma(mangle, _FPUTC.mangleof) int trustedFPUTC(int ch, _iobuf* h) @trusted;

    version (DIGITAL_MARS_STDIO)
        pragma(mangle, _FPUTWC.mangleof) int trustedFPUTWC(int ch, _iobuf* h) @trusted;
    else
        pragma(mangle, _FPUTWC.mangleof) int trustedFPUTWC(wchar_t ch, _iobuf* h) @trusted;
}

static if (__traits(compiles, core.sys.posix.stdio.getdelim))
{
    extern(C) nothrow @nogc
    {
        // @@@DEPRECATED_2.104@@@
        deprecated("To be removed after 2.104. Use core.sys.posix.stdio.getdelim instead.")
        ptrdiff_t getdelim(char**, size_t*, int, FILE*);

        // @@@DEPRECATED_2.104@@@
        // getline() always comes together with getdelim()
        deprecated("To be removed after 2.104. Use core.sys.posix.stdio.getline instead.")
        ptrdiff_t getline(char**, size_t*, FILE*);
    }
}

//------------------------------------------------------------------------------
private struct ByRecordImpl(Fields...)
{
private:
    import std.typecons : Tuple;

    File file;
    char[] line;
    Tuple!(Fields) current;
    string format;

public:
    this(File f, string format)
    {
        assert(f.isOpen);
        file = f;
        this.format = format;
        popFront(); // prime the range
    }

    /// Range primitive implementations.
    @property bool empty()
    {
        return !file.isOpen;
    }

    /// Ditto
    @property ref Tuple!(Fields) front()
    {
        return current;
    }

    /// Ditto
    void popFront()
    {
        import std.conv : text;
        import std.exception : enforce;
        import std.format.read : formattedRead;
        import std.string : chomp;

        enforce(file.isOpen, "ByRecord: File must be open");
        file.readln(line);
        if (!line.length)
        {
            file.detach();
        }
        else
        {
            line = chomp(line);
            formattedRead(line, format, &current);
            enforce(line.empty, text("Leftover characters in record: `",
                            line, "'"));
        }
    }
}

template byRecord(Fields...)
{
    auto byRecord(File f, string format)
    {
        return typeof(return)(f, format);
    }
}

/**
Encapsulates a `FILE*`. Generally D does not attempt to provide
thin wrappers over equivalent functions in the C standard library, but
manipulating `FILE*` values directly is unsafe and error-prone in
many ways. The `File` type ensures safe manipulation, automatic
file closing, and a lot of convenience.

The underlying `FILE*` handle is maintained in a reference-counted
manner, such that as soon as the last `File` variable bound to a
given `FILE*` goes out of scope, the underlying `FILE*` is
automatically closed.

Example:
----
// test.d
import std.stdio;

void main(string[] args)
{
    auto f = File("test.txt", "w"); // open for writing
    f.write("Hello");
    if (args.length > 1)
    {
        auto g = f; // now g and f write to the same file
                    // internal reference count is 2
        g.write(", ", args[1]);
        // g exits scope, reference count decreases to 1
    }
    f.writeln("!");
    // f exits scope, reference count falls to zero,
    // underlying `FILE*` is closed.
}
----
$(CONSOLE
% rdmd test.d Jimmy
% cat test.txt
Hello, Jimmy!
% __
)
 */
struct File
{
    import core.atomic : atomicOp, atomicStore, atomicLoad;
    import std.range.primitives : ElementEncodingType;
    import std.traits : isScalarType, isArray;
    enum Orientation { unknown, narrow, wide }

    private struct Impl
    {
        FILE * handle = null; // Is null iff this Impl is closed by another File
        shared uint refs = uint.max / 2;
        bool isPopened; // true iff the stream has been created by popen()
        Orientation orientation;
    }
    private Impl* _p;
    private string _name;

    package this(FILE* handle, string name, uint refs = 1, bool isPopened = false) @trusted
    {
        import core.stdc.stdlib : malloc;
        import std.exception : enforce;

        assert(!_p);
        _p = cast(Impl*) enforce(malloc(Impl.sizeof), "Out of memory");
        initImpl(handle, name, refs, isPopened);
    }

    private void initImpl(FILE* handle, string name, uint refs = 1, bool isPopened = false)
    {
        assert(_p);
        _p.handle = handle;
        atomicStore(_p.refs, refs);
        _p.isPopened = isPopened;
        _p.orientation = Orientation.unknown;
        _name = name;
    }

/**
Constructor taking the name of the file to open and the open mode.

Copying one `File` object to another results in the two `File`
objects referring to the same underlying file.

The destructor automatically closes the file as soon as no `File`
object refers to it anymore.

Params:
    name = range or string representing the file _name
    stdioOpenmode = range or string represting the open mode
        (with the same semantics as in the C standard library
        $(HTTP cplusplus.com/reference/clibrary/cstdio/fopen.html, fopen)
        function)

Throws: `ErrnoException` if the file could not be opened.
 */
    this(string name, scope const(char)[] stdioOpenmode = "rb") @safe
    {
        import std.conv : text;
        import std.exception : errnoEnforce;

        this(errnoEnforce(_fopen(name, stdioOpenmode),
                        text("Cannot open file `", name, "' in mode `",
                                stdioOpenmode, "'")),
                name);

        // MSVCRT workaround (issue 14422)
        version (MICROSOFT_STDIO)
        {
            setAppendWin(stdioOpenmode);
        }
    }

    /// ditto
    this(R1, R2)(R1 name)
        if (isSomeFiniteCharInputRange!R1)
    {
        import std.conv : to;
        this(name.to!string, "rb");
    }

    /// ditto
    this(R1, R2)(R1 name, R2 mode)
        if (isSomeFiniteCharInputRange!R1 &&
            isSomeFiniteCharInputRange!R2)
    {
        import std.conv : to;
        this(name.to!string, mode.to!string);
    }

    @safe unittest
    {
        static import std.file;
        import std.utf : byChar;
        auto deleteme = testFilename();
        auto f = File(deleteme.byChar, "w".byChar);
        f.close();
        std.file.remove(deleteme);
    }

    ~this() @safe
    {
        detach();
    }

    this(this) @safe nothrow
    {
        if (!_p) return;
        assert(atomicLoad(_p.refs));
        atomicOp!"+="(_p.refs, 1);
    }

/**
Assigns a file to another. The target of the assignment gets detached
from whatever file it was attached to, and attaches itself to the new
file.
 */
    ref File opAssign(File rhs) @safe return
    {
        import std.algorithm.mutation : swap;

        swap(this, rhs);
        return this;
    }

     // https://issues.dlang.org/show_bug.cgi?id=20129
    @safe unittest
    {
        File[int] aa;
        aa.require(0, File.init);
    }

/**
Detaches from the current file (throwing on failure), and then attempts to
_open file `name` with mode `stdioOpenmode`. The mode has the
same semantics as in the C standard library $(HTTP
cplusplus.com/reference/clibrary/cstdio/fopen.html, fopen) function.

Throws: `ErrnoException` in case of error.
 */
    void open(string name, scope const(char)[] stdioOpenmode = "rb") @trusted
    {
        resetFile(name, stdioOpenmode, false);
    }

    // https://issues.dlang.org/show_bug.cgi?id=20585
    @system unittest
    {
        File f;
        try
            f.open("doesn't exist");
        catch (Exception _e)
        {
        }

        assert(!f.isOpen);

        f.close();  // to check not crash here
    }

    private void resetFile(string name, scope const(char)[] stdioOpenmode, bool isPopened) @trusted
    {
        import core.stdc.stdlib : malloc;
        import std.exception : enforce;
        import std.conv : text;
        import std.exception : errnoEnforce;

        if (_p !is null)
        {
            detach();
        }

        FILE* handle;
        version (Posix)
        {
            if (isPopened)
            {
                errnoEnforce(handle = _popen(name, stdioOpenmode),
                             "Cannot run command `"~name~"'");
            }
            else
            {
                errnoEnforce(handle = _fopen(name, stdioOpenmode),
                             text("Cannot open file `", name, "' in mode `",
                                  stdioOpenmode, "'"));
            }
        }
        else
        {
            assert(isPopened == false);
            errnoEnforce(handle = _fopen(name, stdioOpenmode),
                         text("Cannot open file `", name, "' in mode `",
                              stdioOpenmode, "'"));
        }
        _p = cast(Impl*) enforce(malloc(Impl.sizeof), "Out of memory");
        initImpl(handle, name, 1, isPopened);
        version (MICROSOFT_STDIO)
        {
            setAppendWin(stdioOpenmode);
        }
    }

    private void closeHandles() @trusted
    {
        assert(_p);
        import std.exception : errnoEnforce;

        version (Posix)
        {
            import core.sys.posix.stdio : pclose;
            import std.format : format;

            if (_p.isPopened)
            {
                auto res = pclose(_p.handle);
                errnoEnforce(res != -1,
                        "Could not close pipe `"~_name~"'");
                _p.handle = null;
                return;
            }
        }
        if (_p.handle)
        {
            auto handle = _p.handle;
            _p.handle = null;
            // fclose disassociates the FILE* even in case of error (issue 19751)
            errnoEnforce(.fclose(handle) == 0,
                    "Could not close file `"~_name~"'");
        }
    }

    version (MICROSOFT_STDIO)
    {
        private void setAppendWin(scope const(char)[] stdioOpenmode) @safe
        {
            bool append, update;
            foreach (c; stdioOpenmode)
                if (c == 'a')
                    append = true;
                else
                if (c == '+')
                    update = true;
            if (append && !update)
                seek(size);
        }
    }

/**
Reuses the `File` object to either open a different file, or change
the file mode. If `name` is `null`, the mode of the currently open
file is changed; otherwise, a new file is opened, reusing the C
`FILE*`. The function has the same semantics as in the C standard
library $(HTTP cplusplus.com/reference/cstdio/freopen/, freopen)
function.

Note: Calling `reopen` with a `null` `name` is not implemented
in all C runtimes.

Throws: `ErrnoException` in case of error.
 */
    void reopen(string name, scope const(char)[] stdioOpenmode = "rb") @trusted
    {
        import std.conv : text;
        import std.exception : enforce, errnoEnforce;
        import std.internal.cstring : tempCString;

        enforce(isOpen, "Attempting to reopen() an unopened file");

        auto namez = (name == null ? _name : name).tempCString!FSChar();
        auto modez = stdioOpenmode.tempCString!FSChar();

        FILE* fd = _p.handle;
        version (Windows)
            fd =  _wfreopen(namez, modez, fd);
        else
            fd = freopen(namez, modez, fd);

        errnoEnforce(fd, name
            ? text("Cannot reopen file `", name, "' in mode `", stdioOpenmode, "'")
            : text("Cannot reopen file in mode `", stdioOpenmode, "'"));

        if (name !is null)
            _name = name;
    }

    @system unittest // Test changing filename
    {
        import std.exception : assertThrown, assertNotThrown;
        static import std.file;

        auto deleteme = testFilename();
        std.file.write(deleteme, "foo");
        scope(exit) std.file.remove(deleteme);
        auto f = File(deleteme);
        assert(f.readln() == "foo");

        auto deleteme2 = testFilename();
        std.file.write(deleteme2, "bar");
        scope(exit) std.file.remove(deleteme2);
        f.reopen(deleteme2);
        assert(f.name == deleteme2);
        assert(f.readln() == "bar");
        f.close();
    }

    version (CRuntime_DigitalMars) {} else // Not implemented
    version (CRuntime_Microsoft) {} else // Not implemented
    @system unittest // Test changing mode
    {
        import std.exception : assertThrown, assertNotThrown;
        static import std.file;

        auto deleteme = testFilename();
        std.file.write(deleteme, "foo");
        scope(exit) std.file.remove(deleteme);
        auto f = File(deleteme, "r+");
        assert(f.readln() == "foo");
        f.reopen(null, "w");
        f.write("bar");
        f.seek(0);
        f.reopen(null, "a");
        f.write("baz");
        assert(f.name == deleteme);
        f.close();
        assert(std.file.readText(deleteme) == "barbaz");
    }

/**
Detaches from the current file (throwing on failure), and then runs a command
by calling the C standard library function $(HTTP
opengroup.org/onlinepubs/007908799/xsh/_popen.html, _popen).

Throws: `ErrnoException` in case of error.
 */
    version (Posix) void popen(string command, scope const(char)[] stdioOpenmode = "r") @safe
    {
        resetFile(command, stdioOpenmode ,true);
    }

/**
First calls `detach` (throwing on failure), then attempts to
associate the given file descriptor with the `File`, and sets the file's name to `null`.

The mode must be compatible with the mode of the file descriptor.

Throws: `ErrnoException` in case of error.
Params:
    fd = File descriptor to associate with this `File`.
    stdioOpenmode = Mode to associate with this File. The mode has the same semantics
        semantics as in the C standard library
        $(HTTP cplusplus.com/reference/cstdio/fopen/, fdopen) function, and must be compatible with `fd`.
 */
    void fdopen(int fd, scope const(char)[] stdioOpenmode = "rb") @safe
    {
        fdopen(fd, stdioOpenmode, null);
    }

    package void fdopen(int fd, scope const(char)[] stdioOpenmode, string name) @trusted
    {
        import std.exception : errnoEnforce;
        import std.internal.cstring : tempCString;

        auto modez = stdioOpenmode.tempCString();
        detach();

        version (DIGITAL_MARS_STDIO)
        {
            // This is a re-implementation of DMC's fdopen, but without the
            // mucking with the file descriptor.  POSIX standard requires the
            // new fdopen'd file to retain the given file descriptor's
            // position.
            auto fp = fopen("NUL", modez);
            errnoEnforce(fp, "Cannot open placeholder NUL stream");
            _FLOCK(fp);
            auto iob = cast(_iobuf*) fp;
            .close(iob._file);
            iob._file = fd;
            iob._flag &= ~_IOTRAN;
            _FUNLOCK(fp);
        }
        else
        {
            version (Windows) // MSVCRT
                auto fp = _fdopen(fd, modez);
            else version (Posix)
            {
                import core.sys.posix.stdio : fdopen;
                auto fp = fdopen(fd, modez);
            }
            errnoEnforce(fp);
        }
        this = File(fp, name);
    }

    // Declare a dummy HANDLE to allow generating documentation
    // for Windows-only methods.
    version (StdDdoc) { version (Windows) {} else alias HANDLE = int; }

/**
First calls `detach` (throwing on failure), and then attempts to
associate the given Windows `HANDLE` with the `File`. The mode must
be compatible with the access attributes of the handle. Windows only.

Throws: `ErrnoException` in case of error.
*/
    version (StdDdoc)
    void windowsHandleOpen(HANDLE handle, scope const(char)[] stdioOpenmode);

    version (Windows)
    void windowsHandleOpen(HANDLE handle, scope const(char)[] stdioOpenmode)
    {
        import core.stdc.stdint : intptr_t;
        import std.exception : errnoEnforce;
        import std.format : format;

        // Create file descriptors from the handles
        version (DIGITAL_MARS_STDIO)
            auto fd = _handleToFD(handle, FHND_DEVICE);
        else // MSVCRT
        {
            int mode;
            modeLoop:
            foreach (c; stdioOpenmode)
                switch (c)
                {
                    case 'r': mode |= _O_RDONLY; break;
                    case '+': mode &=~_O_RDONLY; break;
                    case 'a': mode |= _O_APPEND; break;
                    case 'b': mode |= _O_BINARY; break;
                    case 't': mode |= _O_TEXT;   break;
                    case ',': break modeLoop;
                    default: break;
                }

            auto fd = _open_osfhandle(cast(intptr_t) handle, mode);
        }

        errnoEnforce(fd >= 0, "Cannot open Windows HANDLE");
        fdopen(fd, stdioOpenmode, "HANDLE(%s)".format(handle));
    }


/** Returns `true` if the file is opened. */
    @property bool isOpen() const @safe pure nothrow
    {
        return _p !is null && _p.handle;
    }

/**
Returns `true` if the file is at end (see $(HTTP
cplusplus.com/reference/clibrary/cstdio/feof.html, feof)).

Throws: `Exception` if the file is not opened.
 */
    @property bool eof() const @trusted pure
    {
        import std.exception : enforce;

        enforce(_p && _p.handle, "Calling eof() against an unopened file.");
        return .feof(cast(FILE*) _p.handle) != 0;
    }

/**
 Returns the name last used to initialize this `File`, if any.

 Some functions that create or initialize the `File` set the name field to `null`.
 Examples include $(LREF tmpfile), $(LREF wrapFile), and $(LREF fdopen). See the
 documentation of those functions for details.

 Returns: The name last used to initialize this this file, or `null` otherwise.
 */
    @property string name() const @safe pure nothrow return
    {
        return _name;
    }

/**
If the file is closed or not yet opened, returns `true`. Otherwise, returns
$(HTTP cplusplus.com/reference/clibrary/cstdio/ferror.html, ferror) for
the file handle.
 */
    @property bool error() const @trusted pure nothrow
    {
        return !isOpen || .ferror(cast(FILE*) _p.handle);
    }

    @safe unittest
    {
        // https://issues.dlang.org/show_bug.cgi?id=12349
        static import std.file;
        auto deleteme = testFilename();
        auto f = File(deleteme, "w");
        scope(exit) std.file.remove(deleteme);

        f.close();
        assert(f.error);
    }

/**
Detaches from the underlying file. If the sole owner, calls `close`.

Throws: `ErrnoException` on failure if closing the file.
  */
    void detach() @trusted
    {
        import core.stdc.stdlib : free;

        if (!_p) return;
        scope(exit) _p = null;

        if (atomicOp!"-="(_p.refs, 1) == 0)
        {
            scope(exit) free(_p);
            closeHandles();
        }
    }

    @safe unittest
    {
        static import std.file;

        auto deleteme = testFilename();
        scope(exit) std.file.remove(deleteme);
        auto f = File(deleteme, "w");
        {
            auto f2 = f;
            f2.detach();
        }
        assert(f._p.refs == 1);
        f.close();
    }

/**
If the file was closed or not yet opened, succeeds vacuously. Otherwise
closes the file (by calling $(HTTP
cplusplus.com/reference/clibrary/cstdio/fclose.html, fclose)),
throwing on error. Even if an exception is thrown, afterwards the $(D
File) object is empty. This is different from `detach` in that it
always closes the file; consequently, all other `File` objects
referring to the same handle will see a closed file henceforth.

Throws: `ErrnoException` on error.
 */
    void close() @trusted
    {
        import core.stdc.stdlib : free;
        import std.exception : errnoEnforce;

        if (!_p) return; // succeed vacuously
        scope(exit)
        {
            if (atomicOp!"-="(_p.refs, 1) == 0)
                free(_p);
            _p = null; // start a new life
        }
        if (!_p.handle) return; // Impl is closed by another File

        scope(exit) _p.handle = null; // nullify the handle anyway
        closeHandles();
    }

/**
If the file is closed or not yet opened, succeeds vacuously. Otherwise, returns
$(HTTP cplusplus.com/reference/clibrary/cstdio/_clearerr.html,
_clearerr) for the file handle.
 */
    void clearerr() @safe pure nothrow
    {
        _p is null || _p.handle is null ||
        .clearerr(_p.handle);
    }

/**
Flushes the C `FILE` buffers.

Calls $(HTTP cplusplus.com/reference/clibrary/cstdio/_fflush.html, _fflush)
for the file handle.

Throws: `Exception` if the file is not opened or if the call to `fflush` fails.
 */
    void flush() @trusted
    {
        import std.exception : enforce, errnoEnforce;

        enforce(isOpen, "Attempting to flush() in an unopened file");
        errnoEnforce(.fflush(_p.handle) == 0);
    }

    @safe unittest
    {
        // https://issues.dlang.org/show_bug.cgi?id=12349
        import std.exception : assertThrown;
        static import std.file;

        auto deleteme = testFilename();
        auto f = File(deleteme, "w");
        scope(exit) std.file.remove(deleteme);

        f.close();
        assertThrown(f.flush());
    }

/**
Forces any data buffered by the OS to be written to disk.
Call $(LREF flush) before calling this function to flush the C `FILE` buffers first.

This function calls
$(HTTP msdn.microsoft.com/en-us/library/windows/desktop/aa364439%28v=vs.85%29.aspx,
`FlushFileBuffers`) on Windows,
$(HTTP developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html,
`F_FULLFSYNC fcntl`) on Darwin and
$(HTTP pubs.opengroup.org/onlinepubs/7908799/xsh/fsync.html,
`fsync`) on POSIX for the file handle.

Throws: `Exception` if the file is not opened or if the OS call fails.
 */
    void sync() @trusted
    {
        import std.exception : enforce;

        enforce(isOpen, "Attempting to sync() an unopened file");

        version (Windows)
        {
            import core.sys.windows.winbase : FlushFileBuffers;
            wenforce(FlushFileBuffers(windowsHandle), "FlushFileBuffers failed");
        }
        else version (Darwin)
        {
            import core.sys.darwin.fcntl : fcntl, F_FULLFSYNC;
            import std.exception : errnoEnforce;
            errnoEnforce(fcntl(fileno, F_FULLFSYNC, 0) != -1, "fcntl failed");
        }
        else
        {
            import core.sys.posix.unistd : fsync;
            import std.exception : errnoEnforce;
            errnoEnforce(fsync(fileno) == 0, "fsync failed");
        }
    }

/**
Calls $(HTTP cplusplus.com/reference/clibrary/cstdio/fread.html, fread) for the
file handle. The number of items to read and the size of
each item is inferred from the size and type of the input array, respectively.

Returns: The slice of `buffer` containing the data that was actually read.
This will be shorter than `buffer` if EOF was reached before the buffer
could be filled.

Throws: `Exception` if `buffer` is empty.
        `ErrnoException` if the file is not opened or the call to `fread` fails.

`rawRead` always reads in binary mode on Windows.
 */
    T[] rawRead(T)(T[] buffer)
    {
        import std.exception : enforce, errnoEnforce;

        if (!buffer.length)
            throw new Exception("rawRead must take a non-empty buffer");
        enforce(isOpen, "Attempting to read from an unopened file");
        version (Windows)
        {
            immutable fd = .fileno(_p.handle);
            immutable mode = .__setmode(fd, _O_BINARY);
            scope(exit) .__setmode(fd, mode);
            version (DIGITAL_MARS_STDIO)
            {
                import core.atomic : atomicOp;

                // https://issues.dlang.org/show_bug.cgi?id=4243
                immutable info = __fhnd_info[fd];
                atomicOp!"&="(__fhnd_info[fd], ~FHND_TEXT);
                scope(exit) __fhnd_info[fd] = info;
            }
        }
        immutable freadResult = trustedFread(_p.handle, buffer);
        assert(freadResult <= buffer.length); // fread return guarantee
        if (freadResult != buffer.length) // error or eof
        {
            errnoEnforce(!error);
            return buffer[0 .. freadResult];
        }
        return buffer;
    }

    ///
    @system unittest
    {
        static import std.file;

        auto testFile = std.file.deleteme();
        std.file.write(testFile, "\r\n\n\r\n");
        scope(exit) std.file.remove(testFile);

        auto f = File(testFile, "r");
        auto buf = f.rawRead(new char[5]);
        f.close();
        assert(buf == "\r\n\n\r\n");
    }

    // https://issues.dlang.org/show_bug.cgi?id=21729
    @system unittest
    {
        import std.exception : assertThrown;

        File f;
        ubyte[1] u;
        assertThrown(f.rawRead(u));
    }

    // https://issues.dlang.org/show_bug.cgi?id=21728
    @system unittest
    {
        static if (__traits(compiles, { import std.process : pipe; })) // not available for iOS
        {
            import std.process : pipe;
            import std.exception : assertThrown;

            auto p = pipe();
            p.readEnd.close;
            ubyte[1] u;
            assertThrown(p.readEnd.rawRead(u));
        }
    }

/**
Calls $(HTTP cplusplus.com/reference/clibrary/cstdio/fwrite.html, fwrite) for the file
handle. The number of items to write and the size of each
item is inferred from the size and type of the input array, respectively. An
error is thrown if the buffer could not be written in its entirety.

`rawWrite` always writes in binary mode on Windows.

Throws: `ErrnoException` if the file is not opened or if the call to `fwrite` fails.
 */
    void rawWrite(T)(in T[] buffer)
    {
        import std.conv : text;
        import std.exception : errnoEnforce;

        version (Windows)
        {
            immutable fd = .fileno(_p.handle);
            immutable oldMode = .__setmode(fd, _O_BINARY);

            if (oldMode != _O_BINARY)
            {
                // need to flush the data that was written with the original mode
                .__setmode(fd, oldMode);
                flush(); // before changing translation mode .__setmode(fd, _O_BINARY);
                .__setmode(fd, _O_BINARY);
            }

            version (DIGITAL_MARS_STDIO)
            {
                import core.atomic : atomicOp;

                // https://issues.dlang.org/show_bug.cgi?id=4243
                immutable info = __fhnd_info[fd];
                atomicOp!"&="(__fhnd_info[fd], ~FHND_TEXT);
                scope (exit) __fhnd_info[fd] = info;
            }

            scope (exit)
            {
                if (oldMode != _O_BINARY)
                {
                    flush();
                    .__setmode(fd, oldMode);
                }
            }
        }

        auto result = trustedFwrite(_p.handle, buffer);
        if (result == result.max) result = 0;
        errnoEnforce(result == buffer.length,
                text("Wrote ", result, " instead of ", buffer.length,
                        " objects of type ", T.stringof, " to file `",
                        _name, "'"));
    }

    ///
    @system unittest
    {
        static import std.file;

        auto testFile = std.file.deleteme();
        auto f = File(testFile, "w");
        scope(exit) std.file.remove(testFile);

        f.rawWrite("\r\n\n\r\n");
        f.close();
        assert(std.file.read(testFile) == "\r\n\n\r\n");
    }

/**
Calls $(HTTP cplusplus.com/reference/clibrary/cstdio/fseek.html, fseek)
for the file handle to move its position indicator.

Params:
    offset = Binary files: Number of bytes to offset from origin.$(BR)
             Text files: Either zero, or a value returned by $(LREF tell).
    origin = Binary files: Position used as reference for the offset, must be
             one of $(REF_ALTTEXT SEEK_SET, SEEK_SET, core,stdc,stdio),
             $(REF_ALTTEXT SEEK_CUR, SEEK_CUR, core,stdc,stdio) or
             $(REF_ALTTEXT SEEK_END, SEEK_END, core,stdc,stdio).$(BR)
             Text files: Shall necessarily be
             $(REF_ALTTEXT SEEK_SET, SEEK_SET, core,stdc,stdio).

Throws: `Exception` if the file is not opened.
        `ErrnoException` if the call to `fseek` fails.
 */
    void seek(long offset, int origin = SEEK_SET) @trusted
    {
        import std.conv : to, text;
        import std.exception : enforce, errnoEnforce;

        // Some libc sanitize the whence input (e.g. glibc), but some don't,
        // e.g. Microsoft runtime crashes on an invalid origin,
        // and Musl additionally accept SEEK_DATA & SEEK_HOLE (Linux extension).
        // To provide a consistent behavior cross platform, we use the glibc check
        // See also https://issues.dlang.org/show_bug.cgi?id=19797
        enforce(origin == SEEK_SET || origin == SEEK_CUR ||  origin == SEEK_END,
                "Invalid `origin` argument passed to `seek`, must be one of: SEEK_SET, SEEK_CUR, SEEK_END");

        enforce(isOpen, "Attempting to seek() in an unopened file");
        version (Windows)
        {
            version (CRuntime_Microsoft)
            {
                alias fseekFun = _fseeki64;
                alias off_t = long;
            }
            else
            {
                alias fseekFun = fseek;
                alias off_t = int;
            }
        }
        else version (Posix)
        {
            import core.sys.posix.stdio : fseeko, off_t;
            alias fseekFun = fseeko;
        }
        errnoEnforce(fseekFun(_p.handle, to!off_t(offset), origin) == 0,
                "Could not seek in file `"~_name~"'");
    }

    @system unittest
    {
        import std.conv : text;
        static import std.file;
        import std.exception;

        auto deleteme = testFilename();
        auto f = File(deleteme, "w+");
        scope(exit) { f.close(); std.file.remove(deleteme); }
        f.rawWrite("abcdefghijklmnopqrstuvwxyz");
        f.seek(7);
        assert(f.readln() == "hijklmnopqrstuvwxyz");

        version (CRuntime_DigitalMars)
            auto bigOffset = int.max - 100;
        else
        version (CRuntime_Bionic)
            auto bigOffset = int.max - 100;
        else
            auto bigOffset = cast(ulong) int.max + 100;
        f.seek(bigOffset);
        assert(f.tell == bigOffset, text(f.tell));
        // Uncomment the tests below only if you want to wait for
        // a long time
        // f.rawWrite("abcdefghijklmnopqrstuvwxyz");
        // f.seek(-3, SEEK_END);
        // assert(f.readln() == "xyz");

        assertThrown(f.seek(0, ushort.max));
    }

/**
Calls $(HTTP cplusplus.com/reference/clibrary/cstdio/ftell.html, ftell) for the
managed file handle.

Throws: `Exception` if the file is not opened.
        `ErrnoException` if the call to `ftell` fails.
 */
    @property ulong tell() const @trusted
    {
        import std.exception : enforce, errnoEnforce;

        enforce(isOpen, "Attempting to tell() in an unopened file");
        version (Windows)
        {
            version (CRuntime_Microsoft)
                immutable result = _ftelli64(cast(FILE*) _p.handle);
            else
                immutable result = ftell(cast(FILE*) _p.handle);
        }
        else version (Posix)
        {
            import core.sys.posix.stdio : ftello;
            immutable result = ftello(cast(FILE*) _p.handle);
        }
        errnoEnforce(result != -1,
                "Query ftell() failed for file `"~_name~"'");
        return result;
    }

    ///
    @system unittest
    {
        import std.conv : text;
        static import std.file;

        auto testFile = std.file.deleteme();
        std.file.write(testFile, "abcdefghijklmnopqrstuvwqxyz");
        scope(exit) { std.file.remove(testFile); }

        auto f = File(testFile);
        auto a = new ubyte[4];
        f.rawRead(a);
        assert(f.tell == 4, text(f.tell));
    }

/**
Calls $(HTTP cplusplus.com/reference/clibrary/cstdio/_rewind.html, _rewind)
for the file handle.

Throws: `Exception` if the file is not opened.
 */
    void rewind() @safe
    {
        import std.exception : enforce;

        enforce(isOpen, "Attempting to rewind() an unopened file");
        .rewind(_p.handle);
    }

/**
Calls $(HTTP cplusplus.com/reference/clibrary/cstdio/_setvbuf.html, _setvbuf) for
the file handle.

Throws: `Exception` if the file is not opened.
        `ErrnoException` if the call to `setvbuf` fails.
 */
    void setvbuf(size_t size, int mode = _IOFBF) @trusted
    {
        import std.exception : enforce, errnoEnforce;

        enforce(isOpen, "Attempting to call setvbuf() on an unopened file");
        errnoEnforce(.setvbuf(_p.handle, null, mode, size) == 0,
                "Could not set buffering for file `"~_name~"'");
    }

/**
Calls $(HTTP cplusplus.com/reference/clibrary/cstdio/_setvbuf.html,
_setvbuf) for the file handle.

Throws: `Exception` if the file is not opened.
        `ErrnoException` if the call to `setvbuf` fails.
*/
    void setvbuf(void[] buf, int mode = _IOFBF) @trusted
    {
        import std.exception : enforce, errnoEnforce;

        enforce(isOpen, "Attempting to call setvbuf() on an unopened file");
        errnoEnforce(.setvbuf(_p.handle,
                        cast(char*) buf.ptr, mode, buf.length) == 0,
                "Could not set buffering for file `"~_name~"'");
    }


    version (Windows)
    {
        import core.sys.windows.winbase : OVERLAPPED;
        import core.sys.windows.winnt : BOOL, ULARGE_INTEGER;
        import std.windows.syserror : wenforce;

        private BOOL lockImpl(alias F, Flags...)(ulong start, ulong length,
            Flags flags)
        {
            if (!start && !length)
                length = ulong.max;
            ULARGE_INTEGER liStart = void, liLength = void;
            liStart.QuadPart = start;
            liLength.QuadPart = length;
            OVERLAPPED overlapped;
            overlapped.Offset = liStart.LowPart;
            overlapped.OffsetHigh = liStart.HighPart;
            overlapped.hEvent = null;
            return F(windowsHandle, flags, 0, liLength.LowPart,
                liLength.HighPart, &overlapped);
        }
    }
    version (Posix)
    {
        private int lockImpl(int operation, short l_type,
            ulong start, ulong length)
        {
            import core.sys.posix.fcntl : fcntl, flock, off_t;
            import core.sys.posix.unistd : getpid;
            import std.conv : to;

            flock fl = void;
            fl.l_type   = l_type;
            fl.l_whence = SEEK_SET;
            fl.l_start  = to!off_t(start);
            fl.l_len    = to!off_t(length);
            fl.l_pid    = getpid();
            return fcntl(fileno, operation, &fl);
        }
    }

/**
Locks the specified file segment. If the file segment is already locked
by another process, waits until the existing lock is released.
If both `start` and `length` are zero, the entire file is locked.

Locks created using `lock` and `tryLock` have the following properties:
$(UL
 $(LI All locks are automatically released when the process terminates.)
 $(LI Locks are not inherited by child processes.)
 $(LI Closing a file will release all locks associated with the file. On POSIX,
      even locks acquired via a different `File` will be released as well.)
 $(LI Not all NFS implementations correctly implement file locking.)
)
 */
    void lock(LockType lockType = LockType.readWrite,
        ulong start = 0, ulong length = 0)
    {
        import std.exception : enforce;

        enforce(isOpen, "Attempting to call lock() on an unopened file");
        version (Posix)
        {
            import core.sys.posix.fcntl : F_RDLCK, F_SETLKW, F_WRLCK;
            import std.exception : errnoEnforce;
            immutable short type = lockType == LockType.readWrite
                ? F_WRLCK : F_RDLCK;
            errnoEnforce(lockImpl(F_SETLKW, type, start, length) != -1,
                    "Could not set lock for file `"~_name~"'");
        }
        else
        version (Windows)
        {
            import core.sys.windows.winbase : LockFileEx, LOCKFILE_EXCLUSIVE_LOCK;
            immutable type = lockType == LockType.readWrite ?
                LOCKFILE_EXCLUSIVE_LOCK : 0;
            wenforce(lockImpl!LockFileEx(start, length, type),
                    "Could not set lock for file `"~_name~"'");
        }
        else
            static assert(false);
    }

/**
Attempts to lock the specified file segment.
If both `start` and `length` are zero, the entire file is locked.
Returns: `true` if the lock was successful, and `false` if the
specified file segment was already locked.
 */
    bool tryLock(LockType lockType = LockType.readWrite,
        ulong start = 0, ulong length = 0)
    {
        import std.exception : enforce;

        enforce(isOpen, "Attempting to call tryLock() on an unopened file");
        version (Posix)
        {
            import core.stdc.errno : EACCES, EAGAIN, errno;
            import core.sys.posix.fcntl : F_RDLCK, F_SETLK, F_WRLCK;
            import std.exception : errnoEnforce;
            immutable short type = lockType == LockType.readWrite
                ? F_WRLCK : F_RDLCK;
            immutable res = lockImpl(F_SETLK, type, start, length);
            if (res == -1 && (errno == EACCES || errno == EAGAIN))
                return false;
            errnoEnforce(res != -1, "Could not set lock for file `"~_name~"'");
            return true;
        }
        else
        version (Windows)
        {
            import core.sys.windows.winbase : GetLastError, LockFileEx, LOCKFILE_EXCLUSIVE_LOCK,
                LOCKFILE_FAIL_IMMEDIATELY;
            import core.sys.windows.winerror : ERROR_IO_PENDING, ERROR_LOCK_VIOLATION;
            immutable type = lockType == LockType.readWrite
                ? LOCKFILE_EXCLUSIVE_LOCK : 0;
            immutable res = lockImpl!LockFileEx(start, length,
                type | LOCKFILE_FAIL_IMMEDIATELY);
            if (!res && (GetLastError() == ERROR_IO_PENDING
                || GetLastError() == ERROR_LOCK_VIOLATION))
                return false;
            wenforce(res, "Could not set lock for file `"~_name~"'");
            return true;
        }
        else
            static assert(false);
    }

/**
Removes the lock over the specified file segment.
 */
    void unlock(ulong start = 0, ulong length = 0)
    {
        import std.exception : enforce;

        enforce(isOpen, "Attempting to call unlock() on an unopened file");
        version (Posix)
        {
            import core.sys.posix.fcntl : F_SETLK, F_UNLCK;
            import std.exception : errnoEnforce;
            errnoEnforce(lockImpl(F_SETLK, F_UNLCK, start, length) != -1,
                    "Could not remove lock for file `"~_name~"'");
        }
        else
        version (Windows)
        {
            import core.sys.windows.winbase : UnlockFileEx;
            wenforce(lockImpl!UnlockFileEx(start, length),
                "Could not remove lock for file `"~_name~"'");
        }
        else
            static assert(false);
    }

    version (Windows)
    @system unittest
    {
        static import std.file;
        auto deleteme = testFilename();
        scope(exit) std.file.remove(deleteme);
        auto f = File(deleteme, "wb");
        assert(f.tryLock());
        auto g = File(deleteme, "wb");
        assert(!g.tryLock());
        assert(!g.tryLock(LockType.read));
        f.unlock();
        f.lock(LockType.read);
        assert(!g.tryLock());
        assert(g.tryLock(LockType.read));
        f.unlock();
        g.unlock();
    }

    version (Posix)
    @system unittest
    {
    static if (__traits(compiles, { import std.process : spawnProcess; }))
    {
        static import std.file;
        auto deleteme = testFilename();
        scope(exit) std.file.remove(deleteme);

        // Since locks are per-process, we cannot test lock failures within
        // the same process. fork() is used to create a second process.
        static void runForked(void delegate() code)
        {
            import core.sys.posix.sys.wait : waitpid;
            import core.sys.posix.unistd : fork, _exit;
            int child, status;
            if ((child = fork()) == 0)
            {
                code();
                _exit(0);
            }
            else
            {
                assert(waitpid(child, &status, 0) != -1);
                assert(status == 0, "Fork crashed");
            }
        }

        auto f = File(deleteme, "w+b");

        runForked
        ({
            auto g = File(deleteme, "a+b");
            assert(g.tryLock());
            g.unlock();
            assert(g.tryLock(LockType.read));
        });

        assert(f.tryLock());
        runForked
        ({
            auto g = File(deleteme, "a+b");
            assert(!g.tryLock());
            assert(!g.tryLock(LockType.read));
        });
        f.unlock();

        f.lock(LockType.read);
        runForked
        ({
            auto g = File(deleteme, "a+b");
            assert(!g.tryLock());
            assert(g.tryLock(LockType.read));
            g.unlock();
        });
        f.unlock();
    } // static if
    } // unittest


/**
Writes its arguments in text format to the file.

Throws: `Exception` if the file is not opened.
        `ErrnoException` on an error writing to the file.
*/
    void write(S...)(S args)
    {
        import std.traits : isBoolean, isIntegral, isAggregateType;
        import std.utf : UTFException;
        auto w = lockingTextWriter();
        foreach (arg; args)
        {
            try
            {
                alias A = typeof(arg);
                static if (isAggregateType!A || is(A == enum))
                {
                    import std.format.write : formattedWrite;

                    formattedWrite(w, "%s", arg);
                }
                else static if (isSomeString!A)
                {
                    put(w, arg);
                }
                else static if (isIntegral!A)
                {
                    import std.conv : toTextRange;

                    toTextRange(arg, w);
                }
                else static if (isBoolean!A)
                {
                    put(w, arg ? "true" : "false");
                }
                else static if (isSomeChar!A)
                {
                    put(w, arg);
                }
                else
                {
                    import std.format.write : formattedWrite;

                    // Most general case
                    formattedWrite(w, "%s", arg);
                }
            }
            catch (UTFException e)
            {
                /* Reset the writer so that it doesn't throw another
                UTFException on destruction. */
                w.highSurrogate = '\0';
                throw e;
            }
        }
    }

/**
Writes its arguments in text format to the file, followed by a newline.

Throws: `Exception` if the file is not opened.
        `ErrnoException` on an error writing to the file.
*/
    void writeln(S...)(S args)
    {
        write(args, '\n');
    }

/**
Writes its arguments in text format to the file, according to the
format string fmt.

Params:
fmt = The $(REF_ALTTEXT format string, formattedWrite, std, _format).
When passed as a compile-time argument, the string will be statically checked
against the argument types passed.
args = Items to write.

Throws: `Exception` if the file is not opened.
        `ErrnoException` on an error writing to the file.
*/
    void writef(alias fmt, A...)(A args)
    if (isSomeString!(typeof(fmt)))
    {
        import std.format : checkFormatException;

        alias e = checkFormatException!(fmt, A);
        static assert(!e, e);
        return this.writef(fmt, args);
    }

    /// ditto
    void writef(Char, A...)(in Char[] fmt, A args)
    {
        import std.format.write : formattedWrite;

        formattedWrite(lockingTextWriter(), fmt, args);
    }

    /// Equivalent to `file.writef(fmt, args, '\n')`.
    void writefln(alias fmt, A...)(A args)
    if (isSomeString!(typeof(fmt)))
    {
        import std.format : checkFormatException;

        alias e = checkFormatException!(fmt, A);
        static assert(!e, e);
        return this.writefln(fmt, args);
    }

    /// ditto
    void writefln(Char, A...)(in Char[] fmt, A args)
    {
        import std.format.write : formattedWrite;

        auto w = lockingTextWriter();
        formattedWrite(w, fmt, args);
        w.put('\n');
    }

/**
Read line from the file handle and return it as a specified type.

This version manages its own read buffer, which means one memory allocation per call. If you are not
retaining a reference to the read data, consider the `File.readln(buf)` version, which may offer
better performance as it can reuse its read buffer.

Params:
    S = Template parameter; the type of the allocated buffer, and the type returned. Defaults to `string`.
    terminator = Line terminator (by default, `'\n'`).

Note:
    String terminators are not supported due to ambiguity with readln(buf) below.

Returns:
    The line that was read, including the line terminator character.

Throws:
    `StdioException` on I/O error, or `UnicodeException` on Unicode conversion error.

Example:
---
// Reads `stdin` and writes it to `stdout`.
import std.stdio;

void main()
{
    string line;
    while ((line = stdin.readln()) !is null)
        write(line);
}
---
*/
    S readln(S = string)(dchar terminator = '\n')
    if (isSomeString!S)
    {
        Unqual!(ElementEncodingType!S)[] buf;
        readln(buf, terminator);
        return cast(S) buf;
    }

    @system unittest
    {
        import std.algorithm.comparison : equal;
        static import std.file;
        import std.meta : AliasSeq;

        auto deleteme = testFilename();
        std.file.write(deleteme, "hello\nworld\n");
        scope(exit) std.file.remove(deleteme);
        static foreach (String; AliasSeq!(string, char[], wstring, wchar[], dstring, dchar[]))
        {{
            auto witness = [ "hello\n", "world\n" ];
            auto f = File(deleteme);
            uint i = 0;
            String buf;
            while ((buf = f.readln!String()).length)
            {
                assert(i < witness.length);
                assert(equal(buf, witness[i++]));
            }
            assert(i == witness.length);
        }}
    }

    @system unittest
    {
        static import std.file;
        import std.typecons : Tuple;

        auto deleteme = testFilename();
        std.file.write(deleteme, "cześć \U0002000D");
        scope(exit) std.file.remove(deleteme);
        uint[] lengths = [12,8,7];
        static foreach (uint i, C; Tuple!(char, wchar, dchar).Types)
        {{
            immutable(C)[] witness = "cześć \U0002000D";
            auto buf = File(deleteme).readln!(immutable(C)[])();
            assert(buf.length == lengths[i]);
            assert(buf == witness);
        }}
    }

/**
Read line from the file handle and write it to `buf[]`, including
terminating character.

This can be faster than $(D line = File.readln()) because you can reuse
the buffer for each call. Note that reusing the buffer means that you
must copy the previous contents if you wish to retain them.

Params:
buf = Buffer used to store the resulting line data. buf is
enlarged if necessary, then set to the slice exactly containing the line.
terminator = Line terminator (by default, `'\n'`). Use
$(REF newline, std,ascii) for portability (unless the file was opened in
text mode).

Returns:
0 for end of file, otherwise number of characters read.
The return value will always be equal to `buf.length`.

Throws: `StdioException` on I/O error, or `UnicodeException` on Unicode
conversion error.

Example:
---
// Read lines from `stdin` into a string
// Ignore lines starting with '#'
// Write the string to `stdout`
import std.stdio;

void main()
{
    string output;
    char[] buf;

    while (stdin.readln(buf))
    {
        if (buf[0] == '#')
            continue;

        output ~= buf;
    }

    write(output);
}
---

This method can be more efficient than the one in the previous example
because `stdin.readln(buf)` reuses (if possible) memory allocated
for `buf`, whereas $(D line = stdin.readln()) makes a new memory allocation
for every line.

For even better performance you can help `readln` by passing in a
large buffer to avoid memory reallocations. This can be done by reusing the
largest buffer returned by `readln`:

Example:
---
// Read lines from `stdin` and count words
import std.array, std.stdio;

void main()
{
    char[] buf;
    size_t words = 0;

    while (!stdin.eof)
    {
        char[] line = buf;
        stdin.readln(line);
        if (line.length > buf.length)
            buf = line;

        words += line.split.length;
    }

    writeln(words);
}
---
This is actually what $(LREF byLine) does internally, so its usage
is recommended if you want to process a complete file.
*/
    size_t readln(C)(ref C[] buf, dchar terminator = '\n')
    if (isSomeChar!C && is(Unqual!C == C) && !is(C == enum))
    {
        import std.exception : enforce;

        static if (is(C == char))
        {
            enforce(_p && _p.handle, "Attempt to read from an unopened file.");
            if (_p.orientation == Orientation.unknown)
            {
                import core.stdc.wchar_ : fwide;
                auto w = fwide(_p.handle, 0);
                if (w < 0) _p.orientation = Orientation.narrow;
                else if (w > 0) _p.orientation = Orientation.wide;
            }
            return readlnImpl(_p.handle, buf, terminator, _p.orientation);
        }
        else
        {
            string s = readln(terminator);
            if (!s.length)
            {
                buf = buf[0 .. 0];
                return 0;
            }

            import std.utf : codeLength;
            buf.length = codeLength!C(s);
            size_t idx;
            foreach (C c; s)
                buf[idx++] = c;

            return buf.length;
        }
    }

    @system unittest
    {
        // @system due to readln
        static import std.file;
        auto deleteme = testFilename();
        std.file.write(deleteme, "123\n456789");
        scope(exit) std.file.remove(deleteme);

        auto file = File(deleteme);
        char[] buffer = new char[10];
        char[] line = buffer;
        file.readln(line);
        auto beyond = line.length;
        buffer[beyond] = 'a';
        file.readln(line); // should not write buffer beyond line
        assert(buffer[beyond] == 'a');
    }

    // https://issues.dlang.org/show_bug.cgi?id=15293
    @system unittest
    {
        // @system due to readln
        static import std.file;
        auto deleteme = testFilename();
        std.file.write(deleteme, "a\n\naa");
        scope(exit) std.file.remove(deleteme);

        auto file = File(deleteme);
        char[] buffer;
        char[] line;

        file.readln(buffer, '\n');

        line = buffer;
        file.readln(line, '\n');

        line = buffer;
        file.readln(line, '\n');

        assert(line[0 .. 1].capacity == 0);
    }

/** ditto */
    size_t readln(C, R)(ref C[] buf, R terminator)
    if (isSomeChar!C && is(Unqual!C == C) && !is(C == enum) &&
        isBidirectionalRange!R && is(typeof(terminator.front == dchar.init)))
    {
        import std.algorithm.mutation : swap;
        import std.algorithm.searching : endsWith;
        import std.range.primitives : back;

        auto last = terminator.back;
        C[] buf2;
        swap(buf, buf2);
        for (;;)
        {
            if (!readln(buf2, last) || endsWith(buf2, terminator))
            {
                if (buf.empty)
                {
                    buf = buf2;
                }
                else
                {
                    buf ~= buf2;
                }
                break;
            }
            buf ~= buf2;
        }
        return buf.length;
    }

    @system unittest
    {
        static import std.file;
        import std.typecons : Tuple;

        auto deleteme = testFilename();
        std.file.write(deleteme, "hello\n\rworld\nhow\n\rare ya");
        scope(exit) std.file.remove(deleteme);
        foreach (C; Tuple!(char, wchar, dchar).Types)
        {
            immutable(C)[][] witness = [ "hello\n\r", "world\nhow\n\r", "are ya" ];
            auto f = File(deleteme);
            uint i = 0;
            C[] buf;
            while (f.readln(buf, "\n\r"))
            {
                assert(i < witness.length);
                assert(buf == witness[i++]);
            }
            assert(buf.length == 0);
        }
    }

    /**
     * Reads formatted _data from the file using $(REF formattedRead, std,_format).
     * Params:
     * format = The $(REF_ALTTEXT format string, formattedWrite, std, _format).
     * When passed as a compile-time argument, the string will be statically checked
     * against the argument types passed.
     * data = Items to be read.
     * Returns:
     *      Same as `formattedRead`: The number of variables filled. If the input range `r` ends early,
     *      this number will be less than the number of variables provided.
     * Example:
----
// test.d
void main()
{
    import std.stdio;
    auto f = File("input");
    foreach (_; 0 .. 3)
    {
        int a;
        f.readf!" %d"(a);
        writeln(++a);
    }
}
----
$(CONSOLE
% echo "1 2 3" > input
% rdmd test.d
2
3
4
)
     */
    uint readf(alias format, Data...)(auto ref Data data)
    if (isSomeString!(typeof(format)))
    {
        import std.format : checkFormatException;

        alias e = checkFormatException!(format, Data);
        static assert(!e, e);
        return this.readf(format, data);
    }

    /// ditto
    uint readf(Data...)(scope const(char)[] format, auto ref Data data)
    {
        import std.format.read : formattedRead;

        assert(isOpen);
        auto input = LockingTextReader(this);
        return formattedRead(input, format, data);
    }

    ///
    @system unittest
    {
        static import std.file;

        auto deleteme = std.file.deleteme();
        std.file.write(deleteme, "hello\nworld\ntrue\nfalse\n");
        scope(exit) std.file.remove(deleteme);
        string s;
        auto f = File(deleteme);
        f.readf!"%s\n"(s);
        assert(s == "hello", "["~s~"]");
        f.readf("%s\n", s);
        assert(s == "world", "["~s~"]");

        bool b1, b2;
        f.readf("%s\n%s\n", b1, b2);
        assert(b1 == true && b2 == false);
    }

    // backwards compatibility with pointers
    @system unittest
    {
        // @system due to readf
        static import std.file;

        auto deleteme = testFilename();
        std.file.write(deleteme, "hello\nworld\ntrue\nfalse\n");
        scope(exit) std.file.remove(deleteme);
        string s;
        auto f = File(deleteme);
        f.readf("%s\n", &s);
        assert(s == "hello", "["~s~"]");
        f.readf("%s\n", &s);
        assert(s == "world", "["~s~"]");

        // https://issues.dlang.org/show_bug.cgi?id=11698
        bool b1, b2;
        f.readf("%s\n%s\n", &b1, &b2);
        assert(b1 == true && b2 == false);
    }

    // backwards compatibility (mixed)
    @system unittest
    {
        // @system due to readf
        static import std.file;

        auto deleteme = testFilename();
        std.file.write(deleteme, "hello\nworld\ntrue\nfalse\n");
        scope(exit) std.file.remove(deleteme);
        string s1, s2;
        auto f = File(deleteme);
        f.readf("%s\n%s\n", s1, &s2);
        assert(s1 == "hello");
        assert(s2 == "world");

        // https://issues.dlang.org/show_bug.cgi?id=11698
        bool b1, b2;
        f.readf("%s\n%s\n", &b1, b2);
        assert(b1 == true && b2 == false);
    }

    // Nice error of std.stdio.readf with newlines
    // https://issues.dlang.org/show_bug.cgi?id=12260
    @system unittest
    {
        static import std.file;

        auto deleteme = testFilename();
        std.file.write(deleteme, "1\n2");
        scope(exit) std.file.remove(deleteme);
        int input;
        auto f = File(deleteme);
        f.readf("%s", &input);

        import std.conv : ConvException;
        import std.exception : collectException;
        assert(collectException!ConvException(f.readf("%s", &input)).msg ==
            "Unexpected '\\n' when converting from type LockingTextReader to type int");
    }

/**
 Returns a temporary file by calling
 $(HTTP cplusplus.com/reference/clibrary/cstdio/_tmpfile.html, _tmpfile).
 Note that the created file has no $(LREF name).*/
    static File tmpfile() @safe
    {
        import std.exception : errnoEnforce;

        return File(errnoEnforce(.tmpfile(),
                "Could not create temporary file with tmpfile()"),
            null);
    }

/**
Unsafe function that wraps an existing `FILE*`. The resulting $(D
File) never takes the initiative in closing the file.
Note that the created file has no $(LREF name)*/
    /*private*/ static File wrapFile(FILE* f) @safe
    {
        import std.exception : enforce;

        return File(enforce(f, "Could not wrap null FILE*"),
            null, /*uint.max / 2*/ 9999);
    }

/**
Returns the `FILE*` corresponding to this object.
 */
    FILE* getFP() @safe pure
    {
        import std.exception : enforce;

        enforce(_p && _p.handle,
                "Attempting to call getFP() on an unopened file");
        return _p.handle;
    }

    @system unittest
    {
        static import core.stdc.stdio;
        assert(stdout.getFP() == core.stdc.stdio.stdout);
    }

/**
Returns the file number corresponding to this object.
 */
    @property int fileno() const @trusted
    {
        import std.exception : enforce;

        enforce(isOpen, "Attempting to call fileno() on an unopened file");
        return .fileno(cast(FILE*) _p.handle);
    }

/**
Returns the underlying operating system `HANDLE` (Windows only).
*/
    version (StdDdoc)
    @property HANDLE windowsHandle();

    version (Windows)
    @property HANDLE windowsHandle()
    {
        version (DIGITAL_MARS_STDIO)
            return _fdToHandle(fileno);
        else
            return cast(HANDLE)_get_osfhandle(fileno);
    }


// Note: This was documented until 2013/08
/*
Range that reads one line at a time.  Returned by $(LREF byLine).

Allows to directly use range operations on lines of a file.
*/
    private struct ByLineImpl(Char, Terminator)
    {
    private:
        import std.typecons : RefCounted, RefCountedAutoInitialize;

        /* Ref-counting stops the source range's Impl
         * from getting out of sync after the range is copied, e.g.
         * when accessing range.front, then using std.range.take,
         * then accessing range.front again. */
        alias PImpl = RefCounted!(Impl, RefCountedAutoInitialize.no);
        PImpl impl;

        static if (isScalarType!Terminator)
            enum defTerm = '\n';
        else
            enum defTerm = cast(Terminator)"\n";

    public:
        this(File f, KeepTerminator kt = No.keepTerminator,
                Terminator terminator = defTerm)
        {
            impl = PImpl(f, kt, terminator);
        }

        @property bool empty()
        {
            return impl.refCountedPayload.empty;
        }

        @property Char[] front()
        {
            return impl.refCountedPayload.front;
        }

        void popFront()
        {
            impl.refCountedPayload.popFront();
        }

    private:
        struct Impl
        {
        private:
            File file;
            Char[] line;
            Char[] buffer;
            Terminator terminator;
            KeepTerminator keepTerminator;
            bool haveLine;

        public:
            this(File f, KeepTerminator kt, Terminator terminator)
            {
                file = f;
                this.terminator = terminator;
                keepTerminator = kt;
            }

            // Range primitive implementations.
            @property bool empty()
            {
                needLine();
                return line is null;
            }

            @property Char[] front()
            {
                needLine();
                return line;
            }

            void popFront()
            {
                needLine();
                haveLine = false;
            }

        private:
            void needLine()
            {
                if (haveLine)
                    return;
                import std.algorithm.searching : endsWith;
                assert(file.isOpen);
                line = buffer;
                file.readln(line, terminator);
                if (line.length > buffer.length)
                {
                    buffer = line;
                }
                if (line.empty)
                {
                    file.detach();
                    line = null;
                }
                else if (keepTerminator == No.keepTerminator
                        && endsWith(line, terminator))
                {
                    static if (isScalarType!Terminator)
                        enum tlen = 1;
                    else static if (isArray!Terminator)
                    {
                        static assert(
                            is(immutable ElementEncodingType!Terminator == immutable Char));
                        const tlen = terminator.length;
                    }
                    else
                        static assert(false);
                    line = line[0 .. line.length - tlen];
                }
                haveLine = true;
            }
        }
    }

/**
Returns an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
set up to read from the file handle one line at a time.

The element type for the range will be `Char[]`. Range primitives
may throw `StdioException` on I/O error.

Note:
Each `front` will not persist after $(D
popFront) is called, so the caller must copy its contents (e.g. by
calling `to!string`) when retention is needed. If the caller needs
to retain a copy of every line, use the $(LREF byLineCopy) function
instead.

Params:
Char = Character type for each line, defaulting to `char`.
keepTerminator = Use `Yes.keepTerminator` to include the
terminator at the end of each line.
terminator = Line separator (`'\n'` by default). Use
$(REF newline, std,ascii) for portability (unless the file was opened in
text mode).

Example:
----
import std.algorithm, std.stdio, std.string;
// Count words in a file using ranges.
void main()
{
    auto file = File("file.txt"); // Open for reading
    const wordCount = file.byLine()            // Read lines
                          .map!split           // Split into words
                          .map!(a => a.length) // Count words per line
                          .sum();              // Total word count
    writeln(wordCount);
}
----

Example:
----
import std.range, std.stdio;
// Read lines using foreach.
void main()
{
    auto file = File("file.txt"); // Open for reading
    auto range = file.byLine();
    // Print first three lines
    foreach (line; range.take(3))
        writeln(line);
    // Print remaining lines beginning with '#'
    foreach (line; range)
    {
        if (!line.empty && line[0] == '#')
            writeln(line);
    }
}
----
Notice that neither example accesses the line data returned by
`front` after the corresponding `popFront` call is made (because
the contents may well have changed).
*/
    auto byLine(Terminator = char, Char = char)
            (KeepTerminator keepTerminator = No.keepTerminator,
            Terminator terminator = '\n')
    if (isScalarType!Terminator)
    {
        return ByLineImpl!(Char, Terminator)(this, keepTerminator, terminator);
    }

/// ditto
    auto byLine(Terminator, Char = char)
            (KeepTerminator keepTerminator, Terminator terminator)
    if (is(immutable ElementEncodingType!Terminator == immutable Char))
    {
        return ByLineImpl!(Char, Terminator)(this, keepTerminator, terminator);
    }

    @system unittest
    {
        static import std.file;
        auto deleteme = testFilename();
        std.file.write(deleteme, "hi");
        scope(success) std.file.remove(deleteme);

        import std.meta : AliasSeq;
        static foreach (T; AliasSeq!(char, wchar, dchar))
        {{
            auto blc = File(deleteme).byLine!(T, T);
            assert(blc.front == "hi");
            // check front is cached
            assert(blc.front is blc.front);
        }}
    }

    // https://issues.dlang.org/show_bug.cgi?id=19980
    @system unittest
    {
        static import std.file;
        auto deleteme = testFilename();
        std.file.write(deleteme, "Line 1\nLine 2\nLine 3\n");
        scope(success) std.file.remove(deleteme);

        auto f = File(deleteme);
        f.byLine();
        f.byLine();
        assert(f.byLine().front == "Line 1");
    }

    private struct ByLineCopy(Char, Terminator)
    {
    private:
        import std.typecons : RefCounted, RefCountedAutoInitialize;

        /* Ref-counting stops the source range's ByLineCopyImpl
         * from getting out of sync after the range is copied, e.g.
         * when accessing range.front, then using std.range.take,
         * then accessing range.front again. */
        alias Impl = RefCounted!(ByLineCopyImpl!(Char, Terminator),
            RefCountedAutoInitialize.no);
        Impl impl;

    public:
        this(File f, KeepTerminator kt, Terminator terminator)
        {
            impl = Impl(f, kt, terminator);
        }

        @property bool empty()
        {
            return impl.refCountedPayload.empty;
        }

        @property Char[] front()
        {
            return impl.refCountedPayload.front;
        }

        void popFront()
        {
            impl.refCountedPayload.popFront();
        }
    }

    private struct ByLineCopyImpl(Char, Terminator)
    {
        ByLineImpl!(Unqual!Char, Terminator).Impl impl;
        bool gotFront;
        Char[] line;

    public:
        this(File f, KeepTerminator kt, Terminator terminator)
        {
            impl = ByLineImpl!(Unqual!Char, Terminator).Impl(f, kt, terminator);
        }

        @property bool empty()
        {
            return impl.empty;
        }

        @property front()
        {
            if (!gotFront)
            {
                line = impl.front.dup;
                gotFront = true;
            }
            return line;
        }

        void popFront()
        {
            impl.popFront();
            gotFront = false;
        }
    }

/**
Returns an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
set up to read from the file handle one line
at a time. Each line will be newly allocated. `front` will cache
its value to allow repeated calls without unnecessary allocations.

Note: Due to caching byLineCopy can be more memory-efficient than
`File.byLine.map!idup`.

The element type for the range will be `Char[]`. Range
primitives may throw `StdioException` on I/O error.

Params:
Char = Character type for each line, defaulting to $(D immutable char).
keepTerminator = Use `Yes.keepTerminator` to include the
terminator at the end of each line.
terminator = Line separator (`'\n'` by default). Use
$(REF newline, std,ascii) for portability (unless the file was opened in
text mode).

Example:
----
import std.algorithm, std.array, std.stdio;
// Print sorted lines of a file.
void main()
{
    auto sortedLines = File("file.txt")   // Open for reading
                       .byLineCopy()      // Read persistent lines
                       .array()           // into an array
                       .sort();           // then sort them
    foreach (line; sortedLines)
        writeln(line);
}
----
See_Also:
$(REF readText, std,file)
*/
    auto byLineCopy(Terminator = char, Char = immutable char)
            (KeepTerminator keepTerminator = No.keepTerminator,
            Terminator terminator = '\n')
    if (isScalarType!Terminator)
    {
        return ByLineCopy!(Char, Terminator)(this, keepTerminator, terminator);
    }

/// ditto
    auto byLineCopy(Terminator, Char = immutable char)
            (KeepTerminator keepTerminator, Terminator terminator)
    if (is(immutable ElementEncodingType!Terminator == immutable Char))
    {
        return ByLineCopy!(Char, Terminator)(this, keepTerminator, terminator);
    }

    @safe unittest
    {
        static assert(is(typeof(File("").byLine.front) == char[]));
        static assert(is(typeof(File("").byLineCopy.front) == string));
        static assert(
            is(typeof(File("").byLineCopy!(char, char).front) == char[]));
    }

    @system unittest
    {
        import std.algorithm.comparison : equal;
        static import std.file;

        scope(failure) printf("Failed test at line %d\n", __LINE__);
        auto deleteme = testFilename();
        std.file.write(deleteme, "");
        scope(success) std.file.remove(deleteme);

        // Test empty file
        auto f = File(deleteme);
        foreach (line; f.byLine())
        {
            assert(false);
        }
        f.detach();
        assert(!f.isOpen);

        void test(Terminator)(string txt, in string[] witness,
                KeepTerminator kt, Terminator term, bool popFirstLine = false)
        {
            import std.algorithm.sorting : sort;
            import std.array : array;
            import std.conv : text;
            import std.range.primitives : walkLength;

            uint i;
            std.file.write(deleteme, txt);
            auto f = File(deleteme);
            scope(exit)
            {
                f.close();
                assert(!f.isOpen);
            }
            auto lines = f.byLine(kt, term);
            if (popFirstLine)
            {
                lines.popFront();
                i = 1;
            }
            assert(lines.empty || lines.front is lines.front);
            foreach (line; lines)
            {
                assert(line == witness[i++]);
            }
            assert(i == witness.length, text(i, " != ", witness.length));

            // https://issues.dlang.org/show_bug.cgi?id=11830
            auto walkedLength = File(deleteme).byLine(kt, term).walkLength;
            assert(walkedLength == witness.length, text(walkedLength, " != ", witness.length));

            // test persistent lines
            assert(File(deleteme).byLineCopy(kt, term).array.sort() == witness.dup.sort());
        }

        KeepTerminator kt = No.keepTerminator;
        test("", null, kt, '\n');
        test("\n", [ "" ], kt, '\n');
        test("asd\ndef\nasdf", [ "asd", "def", "asdf" ], kt, '\n');
        test("asd\ndef\nasdf", [ "asd", "def", "asdf" ], kt, '\n', true);
        test("asd\ndef\nasdf\n", [ "asd", "def", "asdf" ], kt, '\n');
        test("foo", [ "foo" ], kt, '\n', true);
        test("bob\r\nmarge\r\nsteve\r\n", ["bob", "marge", "steve"],
            kt, "\r\n");
        test("sue\r", ["sue"], kt, '\r');

        kt = Yes.keepTerminator;
        test("", null, kt, '\n');
        test("\n", [ "\n" ], kt, '\n');
        test("asd\ndef\nasdf", [ "asd\n", "def\n", "asdf" ], kt, '\n');
        test("asd\ndef\nasdf\n", [ "asd\n", "def\n", "asdf\n" ], kt, '\n');
        test("asd\ndef\nasdf\n", [ "asd\n", "def\n", "asdf\n" ], kt, '\n', true);
        test("foo", [ "foo" ], kt, '\n');
        test("bob\r\nmarge\r\nsteve\r\n", ["bob\r\n", "marge\r\n", "steve\r\n"],
            kt, "\r\n");
        test("sue\r", ["sue\r"], kt, '\r');
    }

    @system unittest
    {
        import std.algorithm.comparison : equal;
        import std.range : drop, take;

        version (Win64)
        {
            static import std.file;

            /* the C function tmpfile doesn't seem to work, even when called from C */
            auto deleteme = testFilename();
            auto file = File(deleteme, "w+");
            scope(success) std.file.remove(deleteme);
        }
        else version (CRuntime_Bionic)
        {
            static import std.file;

            /* the C function tmpfile doesn't work when called from a shared
               library apk:
               https://code.google.com/p/android/issues/detail?id=66815 */
            auto deleteme = testFilename();
            auto file = File(deleteme, "w+");
            scope(success) std.file.remove(deleteme);
        }
        else
            auto file = File.tmpfile();
        file.write("1\n2\n3\n");

        // https://issues.dlang.org/show_bug.cgi?id=9599
        file.rewind();
        File.ByLineImpl!(char, char) fbl = file.byLine();
        auto fbl2 = fbl;
        assert(fbl.front == "1");
        assert(fbl.front is fbl2.front);
        assert(fbl.take(1).equal(["1"]));
        assert(fbl.equal(["2", "3"]));
        assert(fbl.empty);
        assert(file.isOpen); // we still have a valid reference

        file.rewind();
        fbl = file.byLine();
        assert(!fbl.drop(2).empty);
        assert(fbl.equal(["3"]));
        assert(fbl.empty);
        assert(file.isOpen);

        file.detach();
        assert(!file.isOpen);
    }

    @system unittest
    {
        static import std.file;
        auto deleteme = testFilename();
        std.file.write(deleteme, "hi");
        scope(success) std.file.remove(deleteme);

        auto blc = File(deleteme).byLineCopy;
        assert(!blc.empty);
        // check front is cached
        assert(blc.front is blc.front);
    }

    /**
    Creates an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
    set up to parse one line at a time from the file into a tuple.

    Range primitives may throw `StdioException` on I/O error.

    Params:
        format = tuple record $(REF_ALTTEXT _format, formattedRead, std, _format)

    Returns:
        The input range set up to parse one line at a time into a record tuple.

    See_Also:

        It is similar to $(LREF byLine) and uses
        $(REF_ALTTEXT _format, formattedRead, std, _format) under the hood.
    */
    template byRecord(Fields...)
    {
        auto byRecord(string format)
        {
            return ByRecordImpl!(Fields)(this, format);
        }
    }

    ///
    @system unittest
    {
         static import std.file;
         import std.typecons : tuple;

         // prepare test file
         auto testFile = std.file.deleteme();
         scope(failure) printf("Failed test at line %d\n", __LINE__);
         std.file.write(testFile, "1 2\n4 1\n5 100");
         scope(exit) std.file.remove(testFile);

         File f = File(testFile);
         scope(exit) f.close();

         auto expected = [tuple(1, 2), tuple(4, 1), tuple(5, 100)];
         uint i;
         foreach (e; f.byRecord!(int, int)("%s %s"))
         {
             assert(e == expected[i++]);
         }
    }

    // Note: This was documented until 2013/08
    /*
     * Range that reads a chunk at a time.
     */
    private struct ByChunkImpl
    {
    private:
        File    file_;
        ubyte[] chunk_;

        void prime()
        {
            chunk_ = file_.rawRead(chunk_);
            if (chunk_.length == 0)
                file_.detach();
        }

    public:
        this(File file, size_t size)
        {
            this(file, new ubyte[](size));
        }

        this(File file, ubyte[] buffer)
        {
            import std.exception : enforce;
            enforce(buffer.length, "size must be larger than 0");
            file_ = file;
            chunk_ = buffer;
            prime();
        }

        // `ByChunk`'s input range primitive operations.
        @property nothrow
        bool empty() const
        {
            return !file_.isOpen;
        }

        /// Ditto
        @property nothrow
        ubyte[] front()
        {
            version (assert)
            {
                import core.exception : RangeError;
                if (empty)
                    throw new RangeError();
            }
            return chunk_;
        }

        /// Ditto
        void popFront()
        {
            version (assert)
            {
                import core.exception : RangeError;
                if (empty)
                    throw new RangeError();
            }
            prime();
        }
    }

/**
Returns an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
set up to read from the file handle a chunk at a time.

The element type for the range will be `ubyte[]`. Range primitives
may throw `StdioException` on I/O error.

Example:
---------
void main()
{
    // Read standard input 4KB at a time
    foreach (ubyte[] buffer; stdin.byChunk(4096))
    {
        ... use buffer ...
    }
}
---------

The parameter may be a number (as shown in the example above) dictating the
size of each chunk. Alternatively, `byChunk` accepts a
user-provided buffer that it uses directly.

Example:
---------
void main()
{
    // Read standard input 4KB at a time
    foreach (ubyte[] buffer; stdin.byChunk(new ubyte[4096]))
    {
        ... use buffer ...
    }
}
---------

In either case, the content of the buffer is reused across calls. That means
`front` will not persist after `popFront` is called, so if retention is
needed, the caller must copy its contents (e.g. by calling `buffer.dup`).

In the  example above, `buffer.length` is 4096 for all iterations, except
for the last one, in which case `buffer.length` may be less than 4096 (but
always greater than zero).

With the mentioned limitations, `byChunk` works with any algorithm
compatible with input ranges.

Example:
---
// Efficient file copy, 1MB at a time.
import std.algorithm, std.stdio;
void main()
{
    stdin.byChunk(1024 * 1024).copy(stdout.lockingTextWriter());
}
---

$(REF joiner, std,algorithm,iteration) can be used to join chunks together into
a single range lazily.
Example:
---
import std.algorithm, std.stdio;
void main()
{
    //Range of ranges
    static assert(is(typeof(stdin.byChunk(4096).front) == ubyte[]));
    //Range of elements
    static assert(is(typeof(stdin.byChunk(4096).joiner.front) == ubyte));
}
---

Returns: A call to `byChunk` returns a range initialized with the `File`
object and the appropriate buffer.

Throws: If the user-provided size is zero or the user-provided buffer
is empty, throws an `Exception`. In case of an I/O error throws
`StdioException`.
 */
    auto byChunk(size_t chunkSize)
    {
        return ByChunkImpl(this, chunkSize);
    }
/// Ditto
    auto byChunk(ubyte[] buffer)
    {
        return ByChunkImpl(this, buffer);
    }

    @system unittest
    {
        static import std.file;

        scope(failure) printf("Failed test at line %d\n", __LINE__);

        auto deleteme = testFilename();
        std.file.write(deleteme, "asd\ndef\nasdf");

        auto witness = ["asd\n", "def\n", "asdf" ];
        auto f = File(deleteme);
        scope(exit)
        {
            f.close();
            assert(!f.isOpen);
            std.file.remove(deleteme);
        }

        uint i;
        foreach (chunk; f.byChunk(4))
            assert(chunk == cast(ubyte[]) witness[i++]);

        assert(i == witness.length);
    }

    @system unittest
    {
        static import std.file;

        scope(failure) printf("Failed test at line %d\n", __LINE__);

        auto deleteme = testFilename();
        std.file.write(deleteme, "asd\ndef\nasdf");

        auto witness = ["asd\n", "def\n", "asdf" ];
        auto f = File(deleteme);
        scope(exit)
        {
            f.close();
            assert(!f.isOpen);
            std.file.remove(deleteme);
        }

        uint i;
        foreach (chunk; f.byChunk(new ubyte[4]))
            assert(chunk == cast(ubyte[]) witness[i++]);

        assert(i == witness.length);
    }

    // Note: This was documented until 2013/08
/*
`Range` that locks the file and allows fast writing to it.
 */
    struct LockingTextWriter
    {
    private:
        import std.range.primitives : ElementType, isInfinite, isInputRange;
        // Access the FILE* handle through the 'file_' member
        // to keep the object alive through refcounting
        File file_;

        // the unshared version of FILE* handle, extracted from the File object
        @property _iobuf* handle_() @trusted { return cast(_iobuf*) file_._p.handle; }

        // the file's orientation (byte- or wide-oriented)
        int orientation_;

        // Buffers for when we need to transcode.
        wchar highSurrogate = '\0'; // '\0' indicates empty
        void highSurrogateShouldBeEmpty() @safe
        {
            import std.utf : UTFException;
            if (highSurrogate != '\0')
                throw new UTFException("unpaired surrogate UTF-16 value");
        }
        char[4] rbuf8;
        size_t rbuf8Filled = 0;
    public:

        this(ref File f) @trusted
        {
            import std.exception : enforce;

            enforce(f._p && f._p.handle, "Attempting to write to closed File");
            file_ = f;
            FILE* fps = f._p.handle;

            version (MICROSOFT_STDIO)
            {
                // Microsoft doesn't implement fwide. Instead, there's the
                // concept of ANSI/UNICODE mode. fputc doesn't work in UNICODE
                // mode; fputwc has to be used. So that essentially means
                // "wide-oriented" for us.
                immutable int mode = __setmode(f.fileno, _O_TEXT);
                    // Set some arbitrary mode to obtain the previous one.
                __setmode(f.fileno, mode); // Restore previous mode.
                if (mode & (_O_WTEXT | _O_U16TEXT | _O_U8TEXT))
                {
                    orientation_ = 1; // wide
                }
            }
            else
            {
                import core.stdc.wchar_ : fwide;
                orientation_ = fwide(fps, 0);
            }

            _FLOCK(fps);
        }

        ~this() @trusted
        {
            if (auto p = file_._p)
            {
                if (p.handle) _FUNLOCK(p.handle);
            }
            file_ = File.init;
                /* Destroy file_ before possibly throwing. Else it wouldn't be
                destroyed, and its reference count would be wrong. */
            highSurrogateShouldBeEmpty();
        }

        this(this) @trusted
        {
            if (auto p = file_._p)
            {
                if (p.handle) _FLOCK(p.handle);
            }
        }

        /// Range primitive implementations.
        void put(A)(scope A writeme)
            if ((isSomeChar!(ElementType!A) ||
                  is(ElementType!A : const(ubyte))) &&
                isInputRange!A &&
                !isInfinite!A)
        {
            import std.exception : errnoEnforce;

            alias C = ElementEncodingType!A;
            static assert(!is(C == void));
            static if (isSomeString!A && C.sizeof == 1 || is(A : const(ubyte)[]))
            {
                if (orientation_ <= 0)
                {
                    //file.write(writeme); causes infinite recursion!!!
                    //file.rawWrite(writeme);
                    auto result = trustedFwrite(file_._p.handle, writeme);
                    if (result != writeme.length) errnoEnforce(0);
                    return;
                }
            }

            // put each element in turn.
            foreach (c; writeme)
            {
                put(c);
            }
        }

        /// ditto
        void put(C)(scope C c) @safe if (isSomeChar!C || is(C : const(ubyte)))
        {
            import std.utf : decodeFront, encode, stride;

            static if (c.sizeof == 1)
            {
                highSurrogateShouldBeEmpty();
                if (orientation_ <= 0) trustedFPUTC(c, handle_);
                else if (c <= 0x7F) trustedFPUTWC(c, handle_);
                else if (c >= 0b1100_0000) // start byte of multibyte sequence
                {
                    rbuf8[0] = c;
                    rbuf8Filled = 1;
                }
                else // continuation byte of multibyte sequence
                {
                    rbuf8[rbuf8Filled] = c;
                    ++rbuf8Filled;
                    if (stride(rbuf8[]) == rbuf8Filled) // sequence is complete
                    {
                        char[] str = rbuf8[0 .. rbuf8Filled];
                        immutable dchar d = decodeFront(str);
                        wchar_t[4 / wchar_t.sizeof] wbuf;
                        immutable size = encode(wbuf, d);
                        foreach (i; 0 .. size)
                            trustedFPUTWC(wbuf[i], handle_);
                        rbuf8Filled = 0;
                    }
                }
            }
            else static if (c.sizeof == 2)
            {
                import std.utf : decode;

                if (c <= 0x7F)
                {
                    highSurrogateShouldBeEmpty();
                    if (orientation_ <= 0) trustedFPUTC(c, handle_);
                    else trustedFPUTWC(c, handle_);
                }
                else if (0xD800 <= c && c <= 0xDBFF) // high surrogate
                {
                    highSurrogateShouldBeEmpty();
                    highSurrogate = c;
                }
                else // standalone or low surrogate
                {
                    dchar d = c;
                    if (highSurrogate != '\0')
                    {
                        immutable wchar[2] rbuf = [highSurrogate, c];
                        size_t index = 0;
                        d = decode(rbuf[], index);
                        highSurrogate = 0;
                    }
                    if (orientation_ <= 0)
                    {
                        char[4] wbuf;
                        immutable size = encode(wbuf, d);
                        foreach (i; 0 .. size)
                            trustedFPUTC(wbuf[i], handle_);
                    }
                    else
                    {
                        wchar_t[4 / wchar_t.sizeof] wbuf;
                        immutable size = encode(wbuf, d);
                        foreach (i; 0 .. size)
                            trustedFPUTWC(wbuf[i], handle_);
                    }
                    rbuf8Filled = 0;
                }
            }
            else // 32-bit characters
            {
                import std.utf : encode;

                highSurrogateShouldBeEmpty();
                if (orientation_ <= 0)
                {
                    if (c <= 0x7F)
                    {
                        trustedFPUTC(c, handle_);
                    }
                    else
                    {
                        char[4] buf = void;
                        immutable len = encode(buf, c);
                        foreach (i ; 0 .. len)
                            trustedFPUTC(buf[i], handle_);
                    }
                }
                else
                {
                    version (Windows)
                    {
                        import std.utf : isValidDchar;

                        assert(isValidDchar(c));
                        if (c <= 0xFFFF)
                        {
                            trustedFPUTWC(cast(wchar_t) c, handle_);
                        }
                        else
                        {
                            trustedFPUTWC(cast(wchar_t)
                                    ((((c - 0x10000) >> 10) & 0x3FF)
                                            + 0xD800), handle_);
                            trustedFPUTWC(cast(wchar_t)
                                    (((c - 0x10000) & 0x3FF) + 0xDC00),
                                    handle_);
                        }
                    }
                    else version (Posix)
                    {
                        trustedFPUTWC(cast(wchar_t) c, handle_);
                    }
                    else
                    {
                        static assert(0);
                    }
                }
            }
        }
    }

    /**
     * Output range which locks the file when created, and unlocks the file when it goes
     * out of scope.
     *
     * Returns: An $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
     * which accepts string types, `ubyte[]`, individual character types, and
     * individual `ubyte`s.
     *
     * Note: Writing either arrays of `char`s or `ubyte`s is faster than
     * writing each character individually from a range. For large amounts of data,
     * writing the contents in chunks using an intermediary array can result
     * in a speed increase.
     *
     * Throws: $(REF UTFException, std, utf) if the data given is a `char` range
     * and it contains malformed UTF data.
     *
     * See_Also: $(LREF byChunk) for an example.
     */
    auto lockingTextWriter() @safe
    {
        return LockingTextWriter(this);
    }

    // An output range which optionally locks the file and puts it into
    // binary mode (similar to rawWrite). Because it needs to restore
    // the file mode on destruction, it is RefCounted on Windows.
    struct BinaryWriterImpl(bool locking)
    {
        import std.traits : hasIndirections;
    private:
        // Access the FILE* handle through the 'file_' member
        // to keep the object alive through refcounting
        File file_;
        string name;

        version (Windows)
        {
            int fd, oldMode;
            version (DIGITAL_MARS_STDIO)
                ubyte oldInfo;
        }

    public:
        // Don't use this, but `File.lockingBinaryWriter()` instead.
        // Must be public for RefCounted and emplace() in druntime.
        this(scope ref File f)
        {
            import std.exception : enforce;
            file_ = f;
            enforce(f._p && f._p.handle);
            name = f._name;
            FILE* fps = f._p.handle;
            static if (locking)
                _FLOCK(fps);

            version (Windows)
            {
                .fflush(fps); // before changing translation mode
                fd = .fileno(fps);
                oldMode = .__setmode(fd, _O_BINARY);
                version (DIGITAL_MARS_STDIO)
                {
                    import core.atomic : atomicOp;

                    // https://issues.dlang.org/show_bug.cgi?id=4243
                    oldInfo = __fhnd_info[fd];
                    atomicOp!"&="(__fhnd_info[fd], ~FHND_TEXT);
                }
            }
        }

        ~this()
        {
            if (!file_._p || !file_._p.handle)
                return;

            FILE* fps = file_._p.handle;

            version (Windows)
            {
                .fflush(fps); // before restoring translation mode
                version (DIGITAL_MARS_STDIO)
                {
                    // https://issues.dlang.org/show_bug.cgi?id=4243
                    __fhnd_info[fd] = oldInfo;
                }
                .__setmode(fd, oldMode);
            }

            _FUNLOCK(fps);
        }

        void rawWrite(T)(in T[] buffer)
        {
            import std.conv : text;
            import std.exception : errnoEnforce;

            auto result = trustedFwrite(file_._p.handle, buffer);
            if (result == result.max) result = 0;
            errnoEnforce(result == buffer.length,
                    text("Wrote ", result, " instead of ", buffer.length,
                            " objects of type ", T.stringof, " to file `",
                            name, "'"));
        }

        version (Windows)
        {
            @disable this(this);
        }
        else
        {
            this(this)
            {
                if (auto p = file_._p)
                {
                    if (p.handle) _FLOCK(p.handle);
                }
            }
        }

        void put(T)(auto ref scope const T value)
        if (!hasIndirections!T &&
            !isInputRange!T)
        {
            rawWrite((&value)[0 .. 1]);
        }

        void put(T)(scope const(T)[] array)
        if (!hasIndirections!T &&
            !isInputRange!T)
        {
            rawWrite(array);
        }
    }

/** Returns an output range that locks the file and allows fast writing to it.

Example:
Produce a grayscale image of the $(LINK2 https://en.wikipedia.org/wiki/Mandelbrot_set, Mandelbrot set)
in binary $(LINK2 https://en.wikipedia.org/wiki/Netpbm_format, Netpbm format) to standard output.
---
import std.algorithm, std.complex, std.range, std.stdio;

void main()
{
    enum size = 500;
    writef("P5\n%d %d %d\n", size, size, ubyte.max);

    iota(-1, 3, 2.0/size).map!(y =>
        iota(-1.5, 0.5, 2.0/size).map!(x =>
            cast(ubyte)(1+
                recurrence!((a, n) => x + y * complex(0, 1) + a[n-1]^^2)(complex(0))
                .take(ubyte.max)
                .countUntil!(z => z.re^^2 + z.im^^2 > 4))
        )
    )
    .copy(stdout.lockingBinaryWriter);
}
---
*/
    auto lockingBinaryWriter()
    {
        alias LockingBinaryWriterImpl = BinaryWriterImpl!true;

        version (Windows)
        {
            import std.typecons : RefCounted;
            alias LockingBinaryWriter = RefCounted!LockingBinaryWriterImpl;
        }
        else
            alias LockingBinaryWriter = LockingBinaryWriterImpl;

        return LockingBinaryWriter(this);
    }

    @system unittest
    {
        import std.algorithm.mutation : reverse;
        import std.exception : collectException;
        static import std.file;
        import std.range : only, retro;
        import std.string : format;

        auto deleteme = testFilename();
        scope(exit) collectException(std.file.remove(deleteme));

        {
            auto writer = File(deleteme, "wb").lockingBinaryWriter();
            auto input = File(deleteme, "rb");

            ubyte[1] byteIn = [42];
            writer.rawWrite(byteIn);
            destroy(writer);

            ubyte[1] byteOut = input.rawRead(new ubyte[1]);
            assert(byteIn[0] == byteOut[0]);
        }

        auto output = File(deleteme, "wb");
        auto writer = output.lockingBinaryWriter();
        auto input = File(deleteme, "rb");

        T[] readExact(T)(T[] buf)
        {
            auto result = input.rawRead(buf);
            assert(result.length == buf.length,
                "Read %d out of %d bytes"
                .format(result.length, buf.length));
            return result;
        }

        // test raw values
        ubyte byteIn = 42;
        byteIn.only.copy(writer); output.flush();
        ubyte byteOut = readExact(new ubyte[1])[0];
        assert(byteIn == byteOut);

        // test arrays
        ubyte[] bytesIn = [1, 2, 3, 4, 5];
        bytesIn.copy(writer); output.flush();
        ubyte[] bytesOut = readExact(new ubyte[bytesIn.length]);
        scope(failure) .writeln(bytesOut);
        assert(bytesIn == bytesOut);

        // test ranges of values
        bytesIn.retro.copy(writer); output.flush();
        bytesOut = readExact(bytesOut);
        bytesOut.reverse();
        assert(bytesIn == bytesOut);

        // test string
        "foobar".copy(writer); output.flush();
        char[] charsOut = readExact(new char[6]);
        assert(charsOut == "foobar");

        // test ranges of arrays
        only("foo", "bar").copy(writer); output.flush();
        charsOut = readExact(charsOut);
        assert(charsOut == "foobar");

        // test that we are writing arrays as is,
        // without UTF-8 transcoding
        "foo"d.copy(writer); output.flush();
        dchar[] dcharsOut = readExact(new dchar[3]);
        assert(dcharsOut == "foo");
    }

/** Returns the size of the file in bytes, ulong.max if file is not searchable or throws if the operation fails.
Example:
---
import std.stdio, std.file;

void main()
{
    string deleteme = "delete.me";
    auto file_handle = File(deleteme, "w");
    file_handle.write("abc"); //create temporary file
    scope(exit) deleteme.remove; //remove temporary file at scope exit

    assert(file_handle.size() == 3); //check if file size is 3 bytes
}
---
*/
    @property ulong size() @safe
    {
        import std.exception : collectException;

        ulong pos = void;
        if (collectException(pos = tell)) return ulong.max;
        scope(exit) seek(pos);
        seek(0, SEEK_END);
        return tell;
    }
}

@system unittest
{
    @system struct SystemToString
    {
        string toString()
        {
            return "system";
        }
    }

    @trusted struct TrustedToString
    {
        string toString()
        {
            return "trusted";
        }
    }

    @safe struct SafeToString
    {
        string toString()
        {
            return "safe";
        }
    }

    @system void systemTests()
    {
        //system code can write to files/stdout with anything!
        if (false)
        {
            auto f = File();

            f.write("just a string");
            f.write("string with arg: ", 47);
            f.write(SystemToString());
            f.write(TrustedToString());
            f.write(SafeToString());

            write("just a string");
            write("string with arg: ", 47);
            write(SystemToString());
            write(TrustedToString());
            write(SafeToString());

            f.writeln("just a string");
            f.writeln("string with arg: ", 47);
            f.writeln(SystemToString());
            f.writeln(TrustedToString());
            f.writeln(SafeToString());

            writeln("just a string");
            writeln("string with arg: ", 47);
            writeln(SystemToString());
            writeln(TrustedToString());
            writeln(SafeToString());

            f.writef("string with arg: %s", 47);
            f.writef("%s", SystemToString());
            f.writef("%s", TrustedToString());
            f.writef("%s", SafeToString());

            writef("string with arg: %s", 47);
            writef("%s", SystemToString());
            writef("%s", TrustedToString());
            writef("%s", SafeToString());

            f.writefln("string with arg: %s", 47);
            f.writefln("%s", SystemToString());
            f.writefln("%s", TrustedToString());
            f.writefln("%s", SafeToString());

            writefln("string with arg: %s", 47);
            writefln("%s", SystemToString());
            writefln("%s", TrustedToString());
            writefln("%s", SafeToString());
        }
    }

    @safe void safeTests()
    {
        auto f = File();

        //safe code can write to files only with @safe and @trusted code...
        if (false)
        {
            f.write("just a string");
            f.write("string with arg: ", 47);
            f.write(TrustedToString());
            f.write(SafeToString());

            write("just a string");
            write("string with arg: ", 47);
            write(TrustedToString());
            write(SafeToString());

            f.writeln("just a string");
            f.writeln("string with arg: ", 47);
            f.writeln(TrustedToString());
            f.writeln(SafeToString());

            writeln("just a string");
            writeln("string with arg: ", 47);
            writeln(TrustedToString());
            writeln(SafeToString());

            f.writef("string with arg: %s", 47);
            f.writef("%s", TrustedToString());
            f.writef("%s", SafeToString());

            writef("string with arg: %s", 47);
            writef("%s", TrustedToString());
            writef("%s", SafeToString());

            f.writefln("string with arg: %s", 47);
            f.writefln("%s", TrustedToString());
            f.writefln("%s", SafeToString());

            writefln("string with arg: %s", 47);
            writefln("%s", TrustedToString());
            writefln("%s", SafeToString());
        }

        static assert(!__traits(compiles, f.write(SystemToString().toString())));
        static assert(!__traits(compiles, f.writeln(SystemToString())));
        static assert(!__traits(compiles, f.writef("%s", SystemToString())));
        static assert(!__traits(compiles, f.writefln("%s", SystemToString())));

        static assert(!__traits(compiles, write(SystemToString().toString())));
        static assert(!__traits(compiles, writeln(SystemToString())));
        static assert(!__traits(compiles, writef("%s", SystemToString())));
        static assert(!__traits(compiles, writefln("%s", SystemToString())));
    }

    systemTests();
    safeTests();
}

@safe unittest
{
    import std.exception : collectException;
    static import std.file;

    auto deleteme = testFilename();
    scope(exit) collectException(std.file.remove(deleteme));
    std.file.write(deleteme, "1 2 3");
    auto f = File(deleteme);
    assert(f.size == 5);
    assert(f.tell == 0);
}

@system unittest
{
    // @system due to readln
    static import std.file;
    import std.range : chain, only, repeat;
    import std.range.primitives : isOutputRange;

    auto deleteme = testFilename();
    scope(exit) std.file.remove(deleteme);

    {
        auto writer = File(deleteme, "w").lockingTextWriter();
        static assert(isOutputRange!(typeof(writer), dchar));
        writer.put("日本語");
        writer.put("日本語"w);
        writer.put("日本語"d);
        writer.put('日');
        writer.put(chain(only('本'), only('語')));
        // https://issues.dlang.org/show_bug.cgi?id=11945
        writer.put(repeat('#', 12));
        // https://issues.dlang.org/show_bug.cgi?id=17229
        writer.put(cast(immutable(ubyte)[])"日本語");
    }
    assert(File(deleteme).readln() == "日本語日本語日本語日本語############日本語");
}

@safe unittest // wchar -> char
{
    static import std.file;
    import std.exception : assertThrown;
    import std.utf : UTFException;

    auto deleteme = testFilename();
    scope(exit) std.file.remove(deleteme);

    {
        auto writer = File(deleteme, "w").lockingTextWriter();
        writer.put("\U0001F608"w);
    }
    assert(std.file.readText!string(deleteme) == "\U0001F608");

    // Test invalid input: unpaired high surrogate
    {
        immutable wchar surr = "\U0001F608"w[0];
        auto f = File(deleteme, "w");
        assertThrown!UTFException(() {
            auto writer = f.lockingTextWriter();
            writer.put('x');
            writer.put(surr);
            assertThrown!UTFException(writer.put(char('y')));
            assertThrown!UTFException(writer.put(wchar('y')));
            assertThrown!UTFException(writer.put(dchar('y')));
            assertThrown!UTFException(writer.put(surr));
            // First `surr` is still unpaired at this point. `writer` gets
            // destroyed now, and the destructor throws a UTFException for
            // the unpaired surrogate.
        } ());
    }
    assert(std.file.readText!string(deleteme) == "x");

    // Test invalid input: unpaired low surrogate
    {
        immutable wchar surr = "\U0001F608"w[1];
        auto writer = File(deleteme, "w").lockingTextWriter();
        assertThrown!UTFException(writer.put(surr));
        writer.put('y');
        assertThrown!UTFException(writer.put(surr));
    }
    assert(std.file.readText!string(deleteme) == "y");
}

@safe unittest // issue 18801
{
    static import std.file;
    import std.string : stripLeft;

    auto deleteme = testFilename();
    scope(exit) std.file.remove(deleteme);

    {
        auto writer = File(deleteme, "w,ccs=UTF-8").lockingTextWriter();
        writer.put("foo");
    }
    assert(std.file.readText!string(deleteme).stripLeft("\uFEFF") == "foo");

    {
        auto writer = File(deleteme, "a,ccs=UTF-8").lockingTextWriter();
        writer.put("bar");
    }
    assert(std.file.readText!string(deleteme).stripLeft("\uFEFF") == "foobar");
}
@safe unittest // char/wchar -> wchar_t
{
    import core.stdc.locale : LC_CTYPE, setlocale;
    import core.stdc.wchar_ : fwide;
    import core.stdc.string : strlen;
    import std.algorithm.searching : any, endsWith;
    import std.conv : text;
    import std.meta : AliasSeq;
    import std.string : fromStringz, stripLeft;
    static import std.file;
    auto deleteme = testFilename();
    scope(exit) std.file.remove(deleteme);
    const char* oldCt = () @trusted {
        const(char)* p = setlocale(LC_CTYPE, null);
        // Subsequent calls to `setlocale` might invalidate this return value,
        // so duplicate it.
        // See: https://github.com/dlang/phobos/pull/7660
        return p ? p[0 .. strlen(p) + 1].idup.ptr : null;
    }();
    const utf8 = ["en_US.UTF-8", "C.UTF-8", ".65001"].any!((loc) @trusted {
        return setlocale(LC_CTYPE, loc.ptr).fromStringz.endsWith(loc);
    });
    scope(exit) () @trusted { setlocale(LC_CTYPE, oldCt); } ();
    version (DIGITAL_MARS_STDIO) // DM can't handle Unicode above U+07FF.
    {
        alias strs = AliasSeq!("xä\u07FE", "yö\u07FF"w);
    }
    else
    {
        alias strs = AliasSeq!("xä\U0001F607", "yö\U0001F608"w);
    }
    {
        auto f = File(deleteme, "w");
        version (MICROSOFT_STDIO)
        {
            () @trusted { __setmode(fileno(f.getFP()), _O_U8TEXT); } ();
        }
        else
        {
            assert(fwide(f.getFP(), 1) == 1);
        }
        auto writer = f.lockingTextWriter();
        assert(writer.orientation_ == 1);
        static foreach (s; strs) writer.put(s);
    }
    assert(std.file.readText!string(deleteme).stripLeft("\uFEFF") ==
        text(strs));
}
@safe unittest // https://issues.dlang.org/show_bug.cgi?id=18789
{
    static import std.file;
    auto deleteme = testFilename();
    scope(exit) std.file.remove(deleteme);
    // converting to char
    {
        auto f = File(deleteme, "w");
        f.writeln("\U0001F608"w); // UTFException
    }
    // converting to wchar_t
    {
        auto f = File(deleteme, "w,ccs=UTF-16LE");
        // from char
        f.writeln("ö"); // writes garbage
        f.writeln("\U0001F608"); // ditto
        // from wchar
        f.writeln("\U0001F608"w); // leads to ErrnoException
    }
}

@safe unittest
{
    import std.exception : collectException;
    auto e = collectException({ File f; f.writeln("Hello!"); }());
    assert(e && e.msg == "Attempting to write to closed File");
}

@safe unittest // https://issues.dlang.org/show_bug.cgi?id=21592
{
    import std.exception : collectException;
    import std.utf : UTFException;
    static import std.file;
    auto deleteme = testFilename();
    scope(exit) std.file.remove(deleteme);
    auto f = File(deleteme, "w");
    auto e = collectException!UTFException(f.writeln(wchar(0xD801)));
    assert(e.next is null);
}

version (StdStressTest)
{
    // https://issues.dlang.org/show_bug.cgi?id=15768
    @system unittest
    {
        import std.parallelism : parallel;
        import std.range : iota;

        auto deleteme = testFilename();
        stderr = File(deleteme, "w");

        foreach (t; 1_000_000.iota.parallel)
        {
            stderr.write("aaa");
        }
    }
}

/// Used to specify the lock type for `File.lock` and `File.tryLock`.
enum LockType
{
    /**
     * Specifies a _read (shared) lock. A _read lock denies all processes
     * write access to the specified region of the file, including the
     * process that first locks the region. All processes can _read the
     * locked region. Multiple simultaneous _read locks are allowed, as
     * long as there are no exclusive locks.
     */
    read,

    /**
     * Specifies a read/write (exclusive) lock. A read/write lock denies all
     * other processes both read and write access to the locked file region.
     * If a segment has an exclusive lock, it may not have any shared locks
     * or other exclusive locks.
     */
    readWrite
}

struct LockingTextReader
{
    private File _f;
    private char _front;
    private bool _hasChar;

    this(File f)
    {
        import std.exception : enforce;
        enforce(f.isOpen, "LockingTextReader: File must be open");
        _f = f;
        _FLOCK(_f._p.handle);
    }

    this(this)
    {
        _FLOCK(_f._p.handle);
    }

    ~this()
    {
        if (_hasChar)
            ungetc(_front, cast(FILE*)_f._p.handle);

        // File locking has its own reference count
        if (_f.isOpen) _FUNLOCK(_f._p.handle);
    }

    void opAssign(LockingTextReader r)
    {
        import std.algorithm.mutation : swap;
        swap(this, r);
    }

    @property bool empty()
    {
        if (!_hasChar)
        {
            if (!_f.isOpen || _f.eof)
                return true;
            immutable int c = _FGETC(cast(_iobuf*) _f._p.handle);
            if (c == EOF)
            {
                .destroy(_f);
                return true;
            }
            _front = cast(char) c;
            _hasChar = true;
        }
        return false;
    }

    @property char front()
    {
        if (!_hasChar)
        {
            version (assert)
            {
                import core.exception : RangeError;
                if (empty)
                    throw new RangeError();
            }
            else
            {
                empty;
            }
        }
        return _front;
    }

    void popFront()
    {
        if (!_hasChar)
            empty;
        _hasChar = false;
    }
}

@system unittest
{
    // @system due to readf
    static import std.file;
    import std.range.primitives : isInputRange;

    static assert(isInputRange!LockingTextReader);
    auto deleteme = testFilename();
    std.file.write(deleteme, "1 2 3");
    scope(exit) std.file.remove(deleteme);
    int x;
    auto f = File(deleteme);
    f.readf("%s ", &x);
    assert(x == 1);
    f.readf("%d ", &x);
    assert(x == 2);
    f.readf("%d ", &x);
    assert(x == 3);
}

// https://issues.dlang.org/show_bug.cgi?id=13686
@system unittest
{
    import std.algorithm.comparison : equal;
    static import std.file;
    import std.utf : byDchar;

    auto deleteme = testFilename();
    std.file.write(deleteme, "Тест");
    scope(exit) std.file.remove(deleteme);

    string s;
    File(deleteme).readf("%s", &s);
    assert(s == "Тест");

    auto ltr = LockingTextReader(File(deleteme)).byDchar;
    assert(equal(ltr, "Тест".byDchar));
}

// https://issues.dlang.org/show_bug.cgi?id=12320
@system unittest
{
    static import std.file;
    auto deleteme = testFilename();
    std.file.write(deleteme, "ab");
    scope(exit) std.file.remove(deleteme);
    auto ltr = LockingTextReader(File(deleteme));
    assert(ltr.front == 'a');
    ltr.popFront();
    assert(ltr.front == 'b');
    ltr.popFront();
    assert(ltr.empty);
}

// https://issues.dlang.org/show_bug.cgi?id=14861
@system unittest
{
    // @system due to readf
    static import std.file;
    auto deleteme = testFilename();
    File fw = File(deleteme, "w");
    for (int i; i != 5000; i++)
        fw.writeln(i, ";", "Иванов;Пётр;Петрович");
    fw.close();
    scope(exit) std.file.remove(deleteme);
    // Test read
    File fr = File(deleteme, "r");
    scope (exit) fr.close();
    int nom; string fam, nam, ot;
    // Error format read
    while (!fr.eof)
        fr.readf("%s;%s;%s;%s\n", &nom, &fam, &nam, &ot);
}

/**
 * Indicates whether `T` is a file handle, i.e. the type
 * is implicitly convertable to $(LREF File) or a pointer to a
 * $(REF FILE, core,stdc,stdio).
 *
 * Returns:
 *      `true` if `T` is a file handle, `false` otherwise.
 */
template isFileHandle(T)
{
    enum isFileHandle = is(T : FILE*) ||
        is(T : File);
}

///
@safe unittest
{
    static assert(isFileHandle!(FILE*));
    static assert(isFileHandle!(File));
}

/**
 * Property used by writeln/etc. so it can infer @safe since stdout is __gshared
 */
private @property File trustedStdout() @trusted
{
    return stdout;
}

/***********************************
Writes its arguments in text format to standard output (without a trailing newline).

Params:
    args = the items to write to `stdout`

Throws: In case of an I/O error, throws an `StdioException`.

Example:
    Reads `stdin` and writes it to `stdout` with an argument
    counter.
---
import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         write("Input ", count, ": ", line, "\n");
    }
}
---
 */
void write(T...)(T args)
if (!is(T[0] : File))
{
    trustedStdout.write(args);
}

@system unittest
{
    static import std.file;

    scope(failure) printf("Failed test at line %d\n", __LINE__);
    void[] buf;
    if (false) write(buf);
    // test write
    auto deleteme = testFilename();
    auto f = File(deleteme, "w");
    f.write("Hello, ",  "world number ", 42, "!");
    f.close();
    scope(exit) { std.file.remove(deleteme); }
    assert(cast(char[]) std.file.read(deleteme) == "Hello, world number 42!");
}

/***********************************
 * Equivalent to `write(args, '\n')`.  Calling `writeln` without
 * arguments is valid and just prints a newline to the standard
 * output.
 *
 * Params:
 *      args = the items to write to `stdout`
 *
 * Throws:
 *      In case of an I/O error, throws an $(LREF StdioException).
 * Example:
 *        Reads `stdin` and writes it to `stdout` with an argument
 *        counter.
---
import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
---
 */
void writeln(T...)(T args)
{
    static if (T.length == 0)
    {
        import std.exception : enforce;

        enforce(fputc('\n', .trustedStdout._p.handle) != EOF, "fputc failed");
    }
    else static if (T.length == 1 &&
                    is(T[0] : const(char)[]) &&
                    (is(T[0] == U[], U) || __traits(isStaticArray, T[0])))
    {
        // Specialization for strings - a very frequent case
        auto w = .trustedStdout.lockingTextWriter();

        static if (__traits(isStaticArray, T[0]))
        {
            w.put(args[0][]);
        }
        else
        {
            w.put(args[0]);
        }
        w.put('\n');
    }
    else
    {
        // Most general instance
        trustedStdout.write(args, '\n');
    }
}

@safe unittest
{
    // Just make sure the call compiles
    if (false) writeln();

    if (false) writeln("wyda");

    // https://issues.dlang.org/show_bug.cgi?id=8040
    if (false) writeln(null);
    if (false) writeln(">", null, "<");

    // https://issues.dlang.org/show_bug.cgi?id=14041
    if (false)
    {
        char[8] a;
        writeln(a);
        immutable b = a;
        b.writeln;
        const c = a[];
        c.writeln;
    }
}

@system unittest
{
    static import std.file;

    scope(failure) printf("Failed test at line %d\n", __LINE__);

    // test writeln
    auto deleteme = testFilename();
    auto f = File(deleteme, "w");
    scope(exit) { std.file.remove(deleteme); }
    f.writeln("Hello, ",  "world number ", 42, "!");
    f.close();
    version (Windows)
        assert(cast(char[]) std.file.read(deleteme) ==
                "Hello, world number 42!\r\n");
    else
        assert(cast(char[]) std.file.read(deleteme) ==
                "Hello, world number 42!\n");

    // test writeln on stdout
    auto saveStdout = stdout;
    scope(exit) stdout = saveStdout;
    stdout.open(deleteme, "w");
    writeln("Hello, ",  "world number ", 42, "!");
    stdout.close();
    version (Windows)
        assert(cast(char[]) std.file.read(deleteme) ==
                "Hello, world number 42!\r\n");
    else
        assert(cast(char[]) std.file.read(deleteme) ==
                "Hello, world number 42!\n");

    stdout.open(deleteme, "w");
    writeln("Hello!"c);
    writeln("Hello!"w);    // https://issues.dlang.org/show_bug.cgi?id=8386
    writeln("Hello!"d);    // https://issues.dlang.org/show_bug.cgi?id=8386
    writeln("embedded\0null"c); // https://issues.dlang.org/show_bug.cgi?id=8730
    stdout.close();
    version (Windows)
        assert(cast(char[]) std.file.read(deleteme) ==
            "Hello!\r\nHello!\r\nHello!\r\nembedded\0null\r\n");
    else
        assert(cast(char[]) std.file.read(deleteme) ==
            "Hello!\nHello!\nHello!\nembedded\0null\n");
}

@system unittest
{
    static import std.file;

    auto deleteme = testFilename();
    auto f = File(deleteme, "w");
    scope(exit) { std.file.remove(deleteme); }

    enum EI : int    { A, B }
    enum ED : double { A = 0, B } // NOTE: explicit initialization to 0 required during Enum init deprecation cycle
    enum EC : char   { A = 0, B } // NOTE: explicit initialization to 0 required during Enum init deprecation cycle
    enum ES : string { A = "aaa", B = "bbb" }

    f.writeln(EI.A);  // false, but A on 2.058
    f.writeln(EI.B);  // true, but B on 2.058

    f.writeln(ED.A);  // A
    f.writeln(ED.B);  // B

    f.writeln(EC.A);  // A
    f.writeln(EC.B);  // B

    f.writeln(ES.A);  // A
    f.writeln(ES.B);  // B

    f.close();
    version (Windows)
        assert(cast(char[]) std.file.read(deleteme) ==
                "A\r\nB\r\nA\r\nB\r\nA\r\nB\r\nA\r\nB\r\n");
    else
        assert(cast(char[]) std.file.read(deleteme) ==
                "A\nB\nA\nB\nA\nB\nA\nB\n");
}

@system unittest
{
    static auto useInit(T)(T ltw)
    {
        T val;
        val = ltw;
        val = T.init;
        return val;
    }
    useInit(stdout.lockingTextWriter());
}

@system unittest
{
    // https://issues.dlang.org/show_bug.cgi?id=21920
    void function(string) printer = &writeln!string;
    if (false) printer("Hello");
}


/***********************************
Writes formatted data to standard output (without a trailing newline).

Params:
fmt = The $(REF_ALTTEXT format string, formattedWrite, std, _format).
When passed as a compile-time argument, the string will be statically checked
against the argument types passed.
args = Items to write.

Note: In older versions of Phobos, it used to be possible to write:

------
writef(stderr, "%s", "message");
------

to print a message to `stderr`. This syntax is no longer supported, and has
been superceded by:

------
stderr.writef("%s", "message");
------

*/
void writef(alias fmt, A...)(A args)
if (isSomeString!(typeof(fmt)))
{
    import std.format : checkFormatException;

    alias e = checkFormatException!(fmt, A);
    static assert(!e, e);
    return .writef(fmt, args);
}

/// ditto
void writef(Char, A...)(in Char[] fmt, A args)
{
    trustedStdout.writef(fmt, args);
}

@system unittest
{
    static import std.file;

    scope(failure) printf("Failed test at line %d\n", __LINE__);

    // test writef
    auto deleteme = testFilename();
    auto f = File(deleteme, "w");
    scope(exit) { std.file.remove(deleteme); }
    f.writef!"Hello, %s world number %s!"("nice", 42);
    f.close();
    assert(cast(char[]) std.file.read(deleteme) ==  "Hello, nice world number 42!");
    // test write on stdout
    auto saveStdout = stdout;
    scope(exit) stdout = saveStdout;
    stdout.open(deleteme, "w");
    writef!"Hello, %s world number %s!"("nice", 42);
    stdout.close();
    assert(cast(char[]) std.file.read(deleteme) == "Hello, nice world number 42!");
}

/***********************************
 * Equivalent to $(D writef(fmt, args, '\n')).
 */
void writefln(alias fmt, A...)(A args)
if (isSomeString!(typeof(fmt)))
{
    import std.format : checkFormatException;

    alias e = checkFormatException!(fmt, A);
    static assert(!e, e);
    return .writefln(fmt, args);
}

/// ditto
void writefln(Char, A...)(in Char[] fmt, A args)
{
    trustedStdout.writefln(fmt, args);
}

@system unittest
{
    static import std.file;

    scope(failure) printf("Failed test at line %d\n", __LINE__);

    // test File.writefln
    auto deleteme = testFilename();
    auto f = File(deleteme, "w");
    scope(exit) { std.file.remove(deleteme); }
    f.writefln!"Hello, %s world number %s!"("nice", 42);
    f.close();
    version (Windows)
        assert(cast(char[]) std.file.read(deleteme) ==
                "Hello, nice world number 42!\r\n");
    else
        assert(cast(char[]) std.file.read(deleteme) ==
                "Hello, nice world number 42!\n",
                cast(char[]) std.file.read(deleteme));

    // test writefln
    auto saveStdout = stdout;
    scope(exit) stdout = saveStdout;
    stdout.open(deleteme, "w");
    writefln!"Hello, %s world number %s!"("nice", 42);
    stdout.close();
    version (Windows)
        assert(cast(char[]) std.file.read(deleteme) ==
                "Hello, nice world number 42!\r\n");
    else
        assert(cast(char[]) std.file.read(deleteme) ==
                "Hello, nice world number 42!\n");
}

/**
 * Reads formatted data from `stdin` using $(REF formattedRead, std,_format).
 * Params:
 * format = The $(REF_ALTTEXT format string, formattedWrite, std, _format).
 * When passed as a compile-time argument, the string will be statically checked
 * against the argument types passed.
 * args = Items to be read.
 * Returns:
 *      Same as `formattedRead`: The number of variables filled. If the input range `r` ends early,
 *      this number will be less than the number of variables provided.
 * Example:
----
// test.d
void main()
{
    import std.stdio;
    foreach (_; 0 .. 3)
    {
        int a;
        readf!" %d"(a);
        writeln(++a);
    }
}
----
$(CONSOLE
% echo "1 2 3" | rdmd test.d
2
3
4
)
 */
uint readf(alias format, A...)(auto ref A args)
if (isSomeString!(typeof(format)))
{
    import std.format : checkFormatException;

    alias e = checkFormatException!(format, A);
    static assert(!e, e);
    return .readf(format, args);
}

/// ditto
uint readf(A...)(scope const(char)[] format, auto ref A args)
{
    return stdin.readf(format, args);
}

@system unittest
{
    float f;
    if (false) readf("%s", &f);

    char a;
    wchar b;
    dchar c;
    if (false) readf("%s %s %s", a, b, c);
    // backwards compatibility with pointers
    if (false) readf("%s %s %s", a, &b, c);
    if (false) readf("%s %s %s", &a, &b, &c);
}

/**********************************
 * Read line from `stdin`.
 *
 * This version manages its own read buffer, which means one memory allocation per call. If you are not
 * retaining a reference to the read data, consider the `readln(buf)` version, which may offer
 * better performance as it can reuse its read buffer.
 *
 * Returns:
 *        The line that was read, including the line terminator character.
 * Params:
 *        S = Template parameter; the type of the allocated buffer, and the type returned. Defaults to `string`.
 *        terminator = Line terminator (by default, `'\n'`).
 * Note:
 *        String terminators are not supported due to ambiguity with readln(buf) below.
 * Throws:
 *        `StdioException` on I/O error, or `UnicodeException` on Unicode conversion error.
 * Example:
 *        Reads `stdin` and writes it to `stdout`.
---
import std.stdio;

void main()
{
    string line;
    while ((line = readln()) !is null)
        write(line);
}
---
*/
S readln(S = string)(dchar terminator = '\n')
if (isSomeString!S)
{
    return stdin.readln!S(terminator);
}

/**********************************
 * Read line from `stdin` and write it to buf[], including terminating character.
 *
 * This can be faster than $(D line = readln()) because you can reuse
 * the buffer for each call. Note that reusing the buffer means that you
 * must copy the previous contents if you wish to retain them.
 *
 * Returns:
 *        `size_t` 0 for end of file, otherwise number of characters read
 * Params:
 *        buf = Buffer used to store the resulting line data. buf is resized as necessary.
 *        terminator = Line terminator (by default, `'\n'`). Use $(REF newline, std,ascii)
 *        for portability (unless the file was opened in text mode).
 * Throws:
 *        `StdioException` on I/O error, or `UnicodeException` on Unicode conversion error.
 * Example:
 *        Reads `stdin` and writes it to `stdout`.
---
import std.stdio;

void main()
{
    char[] buf;
    while (readln(buf))
        write(buf);
}
---
*/
size_t readln(C)(ref C[] buf, dchar terminator = '\n')
if (isSomeChar!C && is(Unqual!C == C) && !is(C == enum))
{
    return stdin.readln(buf, terminator);
}

/** ditto */
size_t readln(C, R)(ref C[] buf, R terminator)
if (isSomeChar!C && is(Unqual!C == C) && !is(C == enum) &&
    isBidirectionalRange!R && is(typeof(terminator.front == dchar.init)))
{
    return stdin.readln(buf, terminator);
}

@safe unittest
{
    import std.meta : AliasSeq;

    //we can't actually test readln, so at the very least,
    //we test compilability
    void foo()
    {
        readln();
        readln('\t');
        static foreach (String; AliasSeq!(string, char[], wstring, wchar[], dstring, dchar[]))
        {
            readln!String();
            readln!String('\t');
        }
        static foreach (String; AliasSeq!(char[], wchar[], dchar[]))
        {{
            String buf;
            readln(buf);
            readln(buf, '\t');
            readln(buf, "<br />");
        }}
    }
}

/*
 * Convenience function that forwards to `core.sys.posix.stdio.fopen`
 * (to `_wfopen` on Windows)
 * with appropriately-constructed C-style strings.
 */
private FILE* _fopen(R1, R2)(R1 name, R2 mode = "r")
if ((isSomeFiniteCharInputRange!R1 || isSomeString!R1) &&
    (isSomeFiniteCharInputRange!R2 || isSomeString!R2))
{
    import std.internal.cstring : tempCString;

    auto namez = name.tempCString!FSChar();
    auto modez = mode.tempCString!FSChar();

    static _fopenImpl(scope const(FSChar)* namez, scope const(FSChar)* modez) @trusted nothrow @nogc
    {
        version (Windows)
        {
            return _wfopen(namez, modez);
        }
        else version (Posix)
        {
            /*
             * The new opengroup large file support API is transparently
             * included in the normal C bindings. http://opengroup.org/platform/lfs.html#1.0
             * if _FILE_OFFSET_BITS in druntime is 64, off_t is 64 bit and
             * the normal functions work fine. If not, then large file support
             * probably isn't available. Do not use the old transitional API
             * (the native extern(C) fopen64, http://www.unix.org/version2/whatsnew/lfs20mar.html#3.0)
             */
            import core.sys.posix.stdio : fopen;
            return fopen(namez, modez);
        }
        else
        {
            return fopen(namez, modez);
        }
    }
    return _fopenImpl(namez, modez);
}

version (Posix)
{
    /***********************************
     * Convenience function that forwards to `core.sys.posix.stdio.popen`
     * with appropriately-constructed C-style strings.
     */
    FILE* _popen(R1, R2)(R1 name, R2 mode = "r") @trusted nothrow @nogc
    if ((isSomeFiniteCharInputRange!R1 || isSomeString!R1) &&
        (isSomeFiniteCharInputRange!R2 || isSomeString!R2))
    {
        import std.internal.cstring : tempCString;

        auto namez = name.tempCString!FSChar();
        auto modez = mode.tempCString!FSChar();

        static popenImpl(const(FSChar)* namez, const(FSChar)* modez) @trusted nothrow @nogc
        {
            import core.sys.posix.stdio : popen;
            return popen(namez, modez);
        }
        return popenImpl(namez, modez);
    }
}

/*
 * Convenience function that forwards to `core.stdc.stdio.fwrite`
 */
private auto trustedFwrite(T)(FILE* f, const T[] obj) @trusted
{
    return fwrite(obj.ptr, T.sizeof, obj.length, f);
}

/*
 * Convenience function that forwards to `core.stdc.stdio.fread`
 */
private auto trustedFread(T)(FILE* f, T[] obj) @trusted
{
    return fread(obj.ptr, T.sizeof, obj.length, f);
}

/**
 * Iterates through the lines of a file by using `foreach`.
 *
 * Example:
 *
---------
void main()
{
  foreach (string line; lines(stdin))
  {
    ... use line ...
  }
}
---------
The line terminator (`'\n'` by default) is part of the string read (it
could be missing in the last line of the file). Several types are
supported for `line`, and the behavior of `lines`
changes accordingly:

$(OL $(LI If `line` has type `string`, $(D
wstring), or `dstring`, a new string of the respective type
is allocated every read.) $(LI If `line` has type $(D
char[]), `wchar[]`, `dchar[]`, the line's content
will be reused (overwritten) across reads.) $(LI If `line`
has type `immutable(ubyte)[]`, the behavior is similar to
case (1), except that no UTF checking is attempted upon input.) $(LI
If `line` has type `ubyte[]`, the behavior is
similar to case (2), except that no UTF checking is attempted upon
input.))

In all cases, a two-symbols versions is also accepted, in which case
the first symbol (of integral type, e.g. `ulong` or $(D
uint)) tracks the zero-based number of the current line.

Example:
----
  foreach (ulong i, string line; lines(stdin))
  {
    ... use line ...
  }
----

 In case of an I/O error, an `StdioException` is thrown.

See_Also:
$(LREF byLine)
 */

struct lines
{
    private File f;
    private dchar terminator = '\n';

    /**
    Constructor.
    Params:
    f = File to read lines from.
    terminator = Line separator (`'\n'` by default).
    */
    this(File f, dchar terminator = '\n')
    {
        this.f = f;
        this.terminator = terminator;
    }

    int opApply(D)(scope D dg)
    {
        import std.traits : Parameters;
        alias Parms = Parameters!(dg);
        static if (isSomeString!(Parms[$ - 1]))
        {
            int result = 0;
            static if (is(Parms[$ - 1] : const(char)[]))
                alias C = char;
            else static if (is(Parms[$ - 1] : const(wchar)[]))
                alias C = wchar;
            else static if (is(Parms[$ - 1] : const(dchar)[]))
                alias C = dchar;
            C[] line;
            static if (Parms.length == 2)
                Parms[0] i = 0;
            for (;;)
            {
                import std.conv : to;

                if (!f.readln(line, terminator)) break;
                auto copy = to!(Parms[$ - 1])(line);
                static if (Parms.length == 2)
                {
                    result = dg(i, copy);
                    ++i;
                }
                else
                {
                    result = dg(copy);
                }
                if (result != 0) break;
            }
            return result;
        }
        else
        {
            // raw read
            return opApplyRaw(dg);
        }
    }
    // no UTF checking
    int opApplyRaw(D)(scope D dg)
    {
        import std.conv : to;
        import std.exception : assumeUnique;
        import std.traits : Parameters;

        alias Parms = Parameters!(dg);
        enum duplicate = is(Parms[$ - 1] : immutable(ubyte)[]);
        int result = 1;
        int c = void;
        _FLOCK(f._p.handle);
        scope(exit) _FUNLOCK(f._p.handle);
        ubyte[] buffer;
        static if (Parms.length == 2)
            Parms[0] line = 0;
        while ((c = _FGETC(cast(_iobuf*) f._p.handle)) != -1)
        {
            buffer ~= to!(ubyte)(c);
            if (c == terminator)
            {
                static if (duplicate)
                    auto arg = assumeUnique(buffer);
                else
                    alias arg = buffer;
                // unlock the file while calling the delegate
                _FUNLOCK(f._p.handle);
                scope(exit) _FLOCK(f._p.handle);
                static if (Parms.length == 1)
                {
                    result = dg(arg);
                }
                else
                {
                    result = dg(line, arg);
                    ++line;
                }
                if (result) break;
                static if (!duplicate)
                    buffer.length = 0;
            }
        }
        // can only reach when _FGETC returned -1
        if (!f.eof) throw new StdioException("Error in reading file"); // error occured
        return result;
    }
}

@system unittest
{
    static import std.file;
    import std.meta : AliasSeq;

    scope(failure) printf("Failed test at line %d\n", __LINE__);

    auto deleteme = testFilename();
    scope(exit) { std.file.remove(deleteme); }

    alias TestedWith =
          AliasSeq!(string, wstring, dstring,
                    char[], wchar[], dchar[]);
    foreach (T; TestedWith)
    {
        // test looping with an empty file
        std.file.write(deleteme, "");
        auto f = File(deleteme, "r");
        foreach (T line; lines(f))
        {
            assert(false);
        }
        f.close();

        // test looping with a file with three lines
        std.file.write(deleteme, "Line one\nline two\nline three\n");
        f.open(deleteme, "r");
        uint i = 0;
        foreach (T line; lines(f))
        {
            if (i == 0) assert(line == "Line one\n");
            else if (i == 1) assert(line == "line two\n");
            else if (i == 2) assert(line == "line three\n");
            else assert(false);
            ++i;
        }
        f.close();

        // test looping with a file with three lines, last without a newline
        std.file.write(deleteme, "Line one\nline two\nline three");
        f.open(deleteme, "r");
        i = 0;
        foreach (T line; lines(f))
        {
            if (i == 0) assert(line == "Line one\n");
            else if (i == 1) assert(line == "line two\n");
            else if (i == 2) assert(line == "line three");
            else assert(false);
            ++i;
        }
        f.close();
    }

    // test with ubyte[] inputs
    alias TestedWith2 = AliasSeq!(immutable(ubyte)[], ubyte[]);
    foreach (T; TestedWith2)
    {
        // test looping with an empty file
        std.file.write(deleteme, "");
        auto f = File(deleteme, "r");
        foreach (T line; lines(f))
        {
            assert(false);
        }
        f.close();

        // test looping with a file with three lines
        std.file.write(deleteme, "Line one\nline two\nline three\n");
        f.open(deleteme, "r");
        uint i = 0;
        foreach (T line; lines(f))
        {
            if (i == 0) assert(cast(char[]) line == "Line one\n");
            else if (i == 1) assert(cast(char[]) line == "line two\n",
                T.stringof ~ " " ~ cast(char[]) line);
            else if (i == 2) assert(cast(char[]) line == "line three\n");
            else assert(false);
            ++i;
        }
        f.close();

        // test looping with a file with three lines, last without a newline
        std.file.write(deleteme, "Line one\nline two\nline three");
        f.open(deleteme, "r");
        i = 0;
        foreach (T line; lines(f))
        {
            if (i == 0) assert(cast(char[]) line == "Line one\n");
            else if (i == 1) assert(cast(char[]) line == "line two\n");
            else if (i == 2) assert(cast(char[]) line == "line three");
            else assert(false);
            ++i;
        }
        f.close();

    }

    static foreach (T; AliasSeq!(ubyte[]))
    {
        // test looping with a file with three lines, last without a newline
        // using a counter too this time
        std.file.write(deleteme, "Line one\nline two\nline three");
        auto f = File(deleteme, "r");
        uint i = 0;
        foreach (ulong j, T line; lines(f))
        {
            if (i == 0) assert(cast(char[]) line == "Line one\n");
            else if (i == 1) assert(cast(char[]) line == "line two\n");
            else if (i == 2) assert(cast(char[]) line == "line three");
            else assert(false);
            ++i;
        }
        f.close();
    }
}

/**
Iterates through a file a chunk at a time by using `foreach`.

Example:

---------
void main()
{
    foreach (ubyte[] buffer; chunks(stdin, 4096))
    {
        ... use buffer ...
    }
}
---------

The content of `buffer` is reused across calls. In the
 example above, `buffer.length` is 4096 for all iterations,
 except for the last one, in which case `buffer.length` may
 be less than 4096 (but always greater than zero).

 In case of an I/O error, an `StdioException` is thrown.
*/
auto chunks(File f, size_t size)
{
    return ChunksImpl(f, size);
}
private struct ChunksImpl
{
    private File f;
    private size_t size;
    // private string fileName; // Currently, no use

    this(File f, size_t size)
    in
    {
        assert(size, "size must be larger than 0");
    }
    do
    {
        this.f = f;
        this.size = size;
    }

    int opApply(D)(scope D dg)
    {
        import core.stdc.stdlib : alloca;
        import std.exception : enforce;

        enforce(f.isOpen, "Attempting to read from an unopened file");
        enum maxStackSize = 1024 * 16;
        ubyte[] buffer = void;
        if (size < maxStackSize)
            buffer = (cast(ubyte*) alloca(size))[0 .. size];
        else
            buffer = new ubyte[size];
        size_t r = void;
        int result = 1;
        uint tally = 0;
        while ((r = trustedFread(f._p.handle, buffer)) > 0)
        {
            assert(r <= size);
            if (r != size)
            {
                // error occured
                if (!f.eof) throw new StdioException(null);
                buffer.length = r;
            }
            static if (is(typeof(dg(tally, buffer))))
            {
                if ((result = dg(tally, buffer)) != 0) break;
            }
            else
            {
                if ((result = dg(buffer)) != 0) break;
            }
            ++tally;
        }
        return result;
    }
}

@system unittest
{
    static import std.file;

    scope(failure) printf("Failed test at line %d\n", __LINE__);

    auto deleteme = testFilename();
    scope(exit) { std.file.remove(deleteme); }

    // test looping with an empty file
    std.file.write(deleteme, "");
    auto f = File(deleteme, "r");
    foreach (ubyte[] line; chunks(f, 4))
    {
        assert(false);
    }
    f.close();

    // test looping with a file with three lines
    std.file.write(deleteme, "Line one\nline two\nline three\n");
    f = File(deleteme, "r");
    uint i = 0;
    foreach (ubyte[] line; chunks(f, 3))
    {
        if (i == 0) assert(cast(char[]) line == "Lin");
        else if (i == 1) assert(cast(char[]) line == "e o");
        else if (i == 2) assert(cast(char[]) line == "ne\n");
        else break;
        ++i;
    }
    f.close();
}

// Issue 21730 - null ptr dereferenced in ChunksImpl.opApply (SIGSEGV)
@system unittest
{
    import std.exception : assertThrown;
    static import std.file;

    auto deleteme = testFilename();
    scope(exit) { if (std.file.exists(deleteme)) std.file.remove(deleteme); }

    auto err1 = File(deleteme, "w+x");
    err1.close;
    std.file.remove(deleteme);
    assertThrown(() {foreach (ubyte[] buf; chunks(err1, 4096)) {}}());
}

/**
Writes an array or range to a file.
Shorthand for $(D data.copy(File(fileName, "wb").lockingBinaryWriter)).
Similar to $(REF write, std,file), strings are written as-is,
rather than encoded according to the `File`'s $(HTTP
en.cppreference.com/w/c/io#Narrow_and_wide_orientation,
orientation).
*/
void toFile(T)(T data, string fileName)
if (is(typeof(copy(data, stdout.lockingBinaryWriter))))
{
    copy(data, File(fileName, "wb").lockingBinaryWriter);
}

@system unittest
{
    static import std.file;

    auto deleteme = testFilename();
    scope(exit) { std.file.remove(deleteme); }

    "Test".toFile(deleteme);
    assert(std.file.readText(deleteme) == "Test");
}

/*********************
 * Thrown if I/O errors happen.
 */
class StdioException : Exception
{
    static import core.stdc.errno;
    /// Operating system error code.
    uint errno;

/**
Initialize with a message and an error code.
*/
    this(string message, uint e = core.stdc.errno.errno) @trusted
    {
        import std.exception : errnoString;
        errno = e;
        auto sysmsg = errnoString(errno);
        // If e is 0, we don't use the system error message.  (The message
        // is "Success", which is rather pointless for an exception.)
        super(e == 0 ? message
                     : (message ? message ~ " (" ~ sysmsg ~ ")" : sysmsg));
    }

/** Convenience functions that throw an `StdioException`. */
    static void opCall(string msg)
    {
        throw new StdioException(msg);
    }

/// ditto
    static void opCall()
    {
        throw new StdioException(null, core.stdc.errno.errno);
    }
}

enum StdFileHandle: string
{
    stdin  = "core.stdc.stdio.stdin",
    stdout = "core.stdc.stdio.stdout",
    stderr = "core.stdc.stdio.stderr",
}

// Undocumented but public because the std* handles are aliasing it.
@property ref File makeGlobal(StdFileHandle _iob)()
{
    __gshared File.Impl impl;
    __gshared File result;

    // Use an inline spinlock to make sure the initializer is only run once.
    // We assume there will be at most uint.max / 2 threads trying to initialize
    // `handle` at once and steal the high bit to indicate that the globals have
    // been initialized.
    static shared uint spinlock;
    import core.atomic : atomicLoad, atomicOp, MemoryOrder;
    if (atomicLoad!(MemoryOrder.acq)(spinlock) <= uint.max / 2)
    {
        for (;;)
        {
            if (atomicLoad!(MemoryOrder.acq)(spinlock) > uint.max / 2)
                break;
            if (atomicOp!"+="(spinlock, 1) == 1)
            {
                with (StdFileHandle)
                    assert(_iob == stdin || _iob == stdout || _iob == stderr);
                impl.handle = mixin(_iob);
                result._p = &impl;
                atomicOp!"+="(spinlock, uint.max / 2);
                break;
            }
            atomicOp!"-="(spinlock, 1);
        }
    }
    return result;
}

/** The standard input stream.

    Returns:
        stdin as a $(LREF File).

    Note:
        The returned $(LREF File) wraps $(REF stdin,core,stdc,stdio), and
        is therefore thread global. Reassigning `stdin` to a different
        `File` must be done in a single-threaded or locked context in
        order to avoid race conditions.

        All reading from `stdin` automatically locks the file globally,
        and will cause all other threads calling `read` to wait until
        the lock is released.
*/
alias stdin = makeGlobal!(StdFileHandle.stdin);

///
@safe unittest
{
    // Read stdin, sort lines, write to stdout
    import std.algorithm.mutation : copy;
    import std.algorithm.sorting : sort;
    import std.array : array;
    import std.typecons : Yes;

    void main()
    {
        stdin                       // read from stdin
        .byLineCopy(Yes.keepTerminator) // copying each line
        .array()                    // convert to array of lines
        .sort()                     // sort the lines
        .copy(                      // copy output of .sort to an OutputRange
            stdout.lockingTextWriter()); // the OutputRange
    }
}

/**
    The standard output stream.

    Returns:
        stdout as a $(LREF File).

    Note:
        The returned $(LREF File) wraps $(REF stdout,core,stdc,stdio), and
        is therefore thread global. Reassigning `stdout` to a different
        `File` must be done in a single-threaded or locked context in
        order to avoid race conditions.

        All writing to `stdout` automatically locks the file globally,
        and will cause all other threads calling `write` to wait until
        the lock is released.
*/
alias stdout = makeGlobal!(StdFileHandle.stdout);

///
@safe unittest
{
    void main()
    {
        stdout.writeln("Write a message to stdout.");
    }
}

///
@safe unittest
{
    void main()
    {
        import std.algorithm.iteration : filter, map, sum;
        import std.format : format;
        import std.range : iota, tee;

        int len;
        const r = 6.iota
                  .filter!(a => a % 2) // 1 3 5
                  .map!(a => a * 2) // 2 6 10
                  .tee!(_ => stdout.writefln("len: %d", len++))
                  .sum;

        assert(r == 18);
    }
}

///
@safe unittest
{
    void main()
    {
        import std.algorithm.mutation : copy;
        import std.algorithm.iteration : map;
        import std.format : format;
        import std.range : iota;

        10.iota
        .map!(e => "N: %d".format(e))
        .copy(stdout.lockingTextWriter()); // the OutputRange
    }
}

/**
    The standard error stream.

    Returns:
        stderr as a $(LREF File).

    Note:
        The returned $(LREF File) wraps $(REF stderr,core,stdc,stdio), and
        is therefore thread global. Reassigning `stderr` to a different
        `File` must be done in a single-threaded or locked context in
        order to avoid race conditions.

        All writing to `stderr` automatically locks the file globally,
        and will cause all other threads calling `write` to wait until
        the lock is released.
*/
alias stderr = makeGlobal!(StdFileHandle.stderr);

///
@safe unittest
{
    void main()
    {
        stderr.writeln("Write a message to stderr.");
    }
}

@system unittest
{
    static import std.file;
    import std.typecons : tuple;

    scope(failure) printf("Failed test at line %d\n", __LINE__);
    auto deleteme = testFilename();

    std.file.write(deleteme, "1 2\n4 1\n5 100");
    scope(exit) std.file.remove(deleteme);
    {
        File f = File(deleteme);
        scope(exit) f.close();
        auto t = [ tuple(1, 2), tuple(4, 1), tuple(5, 100) ];
        uint i;
        foreach (e; f.byRecord!(int, int)("%s %s"))
        {
            //writeln(e);
            assert(e == t[i++]);
        }
        assert(i == 3);
    }
}

@safe unittest
{
    // Retain backwards compatibility
    // https://issues.dlang.org/show_bug.cgi?id=17472
    static assert(is(typeof(stdin) == File));
    static assert(is(typeof(stdout) == File));
    static assert(is(typeof(stderr) == File));
}

// roll our own appender, but with "safe" arrays
private struct ReadlnAppender
{
    char[] buf;
    size_t pos;
    bool safeAppend = false;

    void initialize(char[] b)
    {
        buf = b;
        pos = 0;
    }
    @property char[] data() @trusted
    {
        if (safeAppend)
            assumeSafeAppend(buf.ptr[0 .. pos]);
        return buf.ptr[0 .. pos];
    }

    bool reserveWithoutAllocating(size_t n)
    {
        if (buf.length >= pos + n) // buf is already large enough
            return true;

        immutable curCap = buf.capacity;
        if (curCap >= pos + n)
        {
            buf.length = curCap;
            /* Any extra capacity we end up not using can safely be claimed
            by someone else. */
            safeAppend = true;
            return true;
        }

        return false;
    }
    void reserve(size_t n) @trusted
    {
        import core.stdc.string : memcpy;
        if (!reserveWithoutAllocating(n))
        {
            size_t ncap = buf.length * 2 + 128 + n;
            char[] nbuf = new char[ncap];
            memcpy(nbuf.ptr, buf.ptr, pos);
            buf = nbuf;
            // Allocated a new buffer. No one else knows about it.
            safeAppend = true;
        }
    }
    void putchar(char c) @trusted
    {
        reserve(1);
        buf.ptr[pos++] = c;
    }
    void putdchar(dchar dc) @trusted
    {
        import std.utf : encode, UseReplacementDchar;

        char[4] ubuf;
        immutable size = encode!(UseReplacementDchar.yes)(ubuf, dc);
        reserve(size);
        foreach (c; ubuf)
            buf.ptr[pos++] = c;
    }
    void putonly(char[] b) @trusted
    {
        import core.stdc.string : memcpy;
        assert(pos == 0);   // assume this is the only put call
        if (reserveWithoutAllocating(b.length))
            memcpy(buf.ptr + pos, b.ptr, b.length);
        else
            buf = b.dup;
        pos = b.length;
    }
}

// Private implementation of readln
private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation orientation)
{
    version (DIGITAL_MARS_STDIO)
    {
        _FLOCK(fps);
        scope(exit) _FUNLOCK(fps);

        /* Since fps is now locked, we can create an "unshared" version
         * of fp.
         */
        auto fp = cast(_iobuf*) fps;

        ReadlnAppender app;
        app.initialize(buf);

        if (__fhnd_info[fp._file] & FHND_WCHAR)
        {   /* Stream is in wide characters.
             * Read them and convert to chars.
             */
            static assert(wchar_t.sizeof == 2);
            for (int c = void; (c = _FGETWC(fp)) != -1; )
            {
                if ((c & ~0x7F) == 0)
                {
                    app.putchar(cast(char) c);
                    if (c == terminator)
                        break;
                }
                else
                {
                    if (c >= 0xD800 && c <= 0xDBFF)
                    {
                        int c2 = void;
                        if ((c2 = _FGETWC(fp)) != -1 ||
                                c2 < 0xDC00 && c2 > 0xDFFF)
                        {
                            StdioException("unpaired UTF-16 surrogate");
                        }
                        c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00);
                    }
                    app.putdchar(cast(dchar) c);
                }
            }
            if (ferror(fps))
                StdioException();
        }

        else if (fp._flag & _IONBF)
        {
            /* Use this for unbuffered I/O, when running
             * across buffer boundaries, or for any but the common
             * cases.
             */
        L1:
            int c;
            while ((c = _FGETC(fp)) != -1)
            {
                app.putchar(cast(char) c);
                if (c == terminator)
                {
                    buf = app.data;
                    return buf.length;
                }

            }

            if (ferror(fps))
                StdioException();
        }
        else
        {
            int u = fp._cnt;
            char* p = fp._ptr;
            int i;
            if (fp._flag & _IOTRAN)
            {   /* Translated mode ignores \r and treats ^Z as end-of-file
                 */
                char c;
                while (1)
                {
                    if (i == u)         // if end of buffer
                        goto L1;        // give up
                    c = p[i];
                    i++;
                    if (c != '\r')
                    {
                        if (c == terminator)
                            break;
                        if (c != 0x1A)
                            continue;
                        goto L1;
                    }
                    else
                    {   if (i != u && p[i] == terminator)
                            break;
                        goto L1;
                    }
                }
                app.putonly(p[0 .. i]);
                app.buf[i - 1] = cast(char) terminator;
                if (terminator == '\n' && c == '\r')
                    i++;
            }
            else
            {
                while (1)
                {
                    if (i == u)         // if end of buffer
                        goto L1;        // give up
                    auto c = p[i];
                    i++;
                    if (c == terminator)
                        break;
                }
                app.putonly(p[0 .. i]);
            }
            fp._cnt -= i;
            fp._ptr += i;
        }

        buf = app.data;
        return buf.length;
    }
    else version (MICROSOFT_STDIO)
    {
        _FLOCK(fps);
        scope(exit) _FUNLOCK(fps);

        /* Since fps is now locked, we can create an "unshared" version
         * of fp.
         */
        auto fp = cast(_iobuf*) fps;

        ReadlnAppender app;
        app.initialize(buf);

        int c;
        while ((c = _FGETC(fp)) != -1)
        {
            app.putchar(cast(char) c);
            if (c == terminator)
            {
                buf = app.data;
                return buf.length;
            }

        }

        if (ferror(fps))
            StdioException();
        buf = app.data;
        return buf.length;
    }
    else static if (__traits(compiles, core.sys.posix.stdio.getdelim))
    {
        import core.stdc.stdlib : free;
        import core.stdc.wchar_ : fwide;

        if (orientation == File.Orientation.wide)
        {
            /* Stream is in wide characters.
             * Read them and convert to chars.
             */
            _FLOCK(fps);
            scope(exit) _FUNLOCK(fps);
            auto fp = cast(_iobuf*) fps;
            version (Windows)
            {
                buf.length = 0;
                for (int c = void; (c = _FGETWC(fp)) != -1; )
                {
                    if ((c & ~0x7F) == 0)
                    {   buf ~= c;
                        if (c == terminator)
                            break;
                    }
                    else
                    {
                        if (c >= 0xD800 && c <= 0xDBFF)
                        {
                            int c2 = void;
                            if ((c2 = _FGETWC(fp)) != -1 ||
                                    c2 < 0xDC00 && c2 > 0xDFFF)
                            {
                                StdioException("unpaired UTF-16 surrogate");
                            }
                            c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00);
                        }
                        import std.utf : encode;
                        encode(buf, c);
                    }
                }
                if (ferror(fp))
                    StdioException();
                return buf.length;
            }
            else version (Posix)
            {
                buf.length = 0;
                for (int c; (c = _FGETWC(fp)) != -1; )
                {
                    import std.utf : encode;

                    if ((c & ~0x7F) == 0)
                        buf ~= cast(char) c;
                    else
                        encode(buf, cast(dchar) c);
                    if (c == terminator)
                        break;
                }
                if (ferror(fps))
                    StdioException();
                return buf.length;
            }
            else
            {
                static assert(0);
            }
        }

        static char *lineptr = null;
        static size_t n = 0;
        scope(exit)
        {
            if (n > 128 * 1024)
            {
                // Bound memory used by readln
                free(lineptr);
                lineptr = null;
                n = 0;
            }
        }

        auto s = core.sys.posix.stdio.getdelim(&lineptr, &n, terminator, fps);
        if (s < 0)
        {
            if (ferror(fps))
                StdioException();
            buf.length = 0;                // end of file
            return 0;
        }

        if (s <= buf.length)
        {
            buf = buf[0 .. s];
            buf[] = lineptr[0 .. s];
        }
        else
        {
            buf = lineptr[0 .. s].dup;
        }
        return s;
    }
    else // version (NO_GETDELIM)
    {
        import core.stdc.wchar_ : fwide;

        _FLOCK(fps);
        scope(exit) _FUNLOCK(fps);
        auto fp = cast(_iobuf*) fps;
        if (orientation == File.Orientation.wide)
        {
            /* Stream is in wide characters.
             * Read them and convert to chars.
             */
            version (Windows)
            {
                buf.length = 0;
                for (int c; (c = _FGETWC(fp)) != -1; )
                {
                    if ((c & ~0x7F) == 0)
                    {   buf ~= c;
                        if (c == terminator)
                            break;
                    }
                    else
                    {
                        if (c >= 0xD800 && c <= 0xDBFF)
                        {
                            int c2 = void;
                            if ((c2 = _FGETWC(fp)) != -1 ||
                                    c2 < 0xDC00 && c2 > 0xDFFF)
                            {
                                StdioException("unpaired UTF-16 surrogate");
                            }
                            c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00);
                        }
                        import std.utf : encode;
                        encode(buf, c);
                    }
                }
                if (ferror(fp))
                    StdioException();
                return buf.length;
            }
            else version (Posix)
            {
                import std.utf : encode;
                buf.length = 0;
                for (int c; (c = _FGETWC(fp)) != -1; )
                {
                    if ((c & ~0x7F) == 0)
                        buf ~= cast(char) c;
                    else
                        encode(buf, cast(dchar) c);
                    if (c == terminator)
                        break;
                }
                if (ferror(fps))
                    StdioException();
                return buf.length;
            }
            else
            {
                static assert(0);
            }
        }

        // Narrow stream
        // First, fill the existing buffer
        for (size_t bufPos = 0; bufPos < buf.length; )
        {
            immutable c = _FGETC(fp);
            if (c == -1)
            {
                buf.length = bufPos;
                goto endGame;
            }
            buf[bufPos++] = cast(char) c;
            if (c == terminator)
            {
                // No need to test for errors in file
                buf.length = bufPos;
                return bufPos;
            }
        }
        // Then, append to it
        for (int c; (c = _FGETC(fp)) != -1; )
        {
            buf ~= cast(char) c;
            if (c == terminator)
            {
                // No need to test for errors in file
                return buf.length;
            }
        }

    endGame:
        if (ferror(fps))
            StdioException();
        return buf.length;
    }
}

@system unittest
{
    static import std.file;
    auto deleteme = testFilename();
    scope(exit) std.file.remove(deleteme);

    std.file.write(deleteme, "abcd\n0123456789abcde\n1234\n");
    File f = File(deleteme, "rb");

    char[] ln = new char[2];
    f.readln(ln);

    assert(ln == "abcd\n");
    char[] t = ln[0 .. 2];
    t ~= 't';
    assert(t == "abt");
    // https://issues.dlang.org/show_bug.cgi?id=13856: ln stomped to "abtd"
    assert(ln == "abcd\n");

    // it can also stomp the array length
    ln = new char[4];
    f.readln(ln);
    assert(ln == "0123456789abcde\n");

    char[100] buf;
    ln = buf[];
    f.readln(ln);
    assert(ln == "1234\n");
    assert(ln.ptr == buf.ptr); // avoid allocation, buffer is good enough
}

/** Experimental network access via the File interface

        Opens a TCP connection to the given host and port, then returns
        a File struct with read and write access through the same interface
        as any other file (meaning writef and the byLine ranges work!).

        Authors:
                Adam D. Ruppe

        Bugs:
                Only works on Linux
*/
version (linux)
{
    File openNetwork(string host, ushort port)
    {
        import core.stdc.string : memcpy;
        import core.sys.posix.arpa.inet : htons;
        import core.sys.posix.netdb : gethostbyname;
        import core.sys.posix.netinet.in_ : sockaddr_in;
        static import core.sys.posix.unistd;
        static import sock = core.sys.posix.sys.socket;
        import std.conv : to;
        import std.exception : enforce;
        import std.internal.cstring : tempCString;

        auto h = enforce( gethostbyname(host.tempCString()),
            new StdioException("gethostbyname"));

        int s = sock.socket(sock.AF_INET, sock.SOCK_STREAM, 0);
        enforce(s != -1, new StdioException("socket"));

        scope(failure)
        {
            // want to make sure it doesn't dangle if something throws. Upon
            // normal exit, the File struct's reference counting takes care of
            // closing, so we don't need to worry about success
            core.sys.posix.unistd.close(s);
        }

        sockaddr_in addr;

        addr.sin_family = sock.AF_INET;
        addr.sin_port = htons(port);
        memcpy(&addr.sin_addr.s_addr, h.h_addr, h.h_length);

        enforce(sock.connect(s, cast(sock.sockaddr*) &addr, addr.sizeof) != -1,
            new StdioException("Connect failed"));

        File f;
        f.fdopen(s, "w+", host ~ ":" ~ to!string(port));
        return f;
    }
}

version (StdUnittest) private string testFilename(string file = __FILE__, size_t line = __LINE__) @safe
{
    import std.conv : text;
    import std.file : deleteme;
    import std.path : baseName;

    // filename intentionally contains non-ASCII (Russian) characters for
    // https://issues.dlang.org/show_bug.cgi?id=7648
    return text(deleteme, "-детка.", baseName(file), ".", line);
}
