Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add java.io.FileDescriptor #124

Open
wants to merge 3 commits into
base: 4.7
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 184 additions & 0 deletions base/src/java/io/FileDescriptor.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
module java.io.FileDescriptor;

version(Posix) {
import core.stdc.errno : errno;
import core.stdc.string : strerror;
import core.sys.posix.unistd : fsync;
} else version(Windows) {
import core.sys.windows.core;
}

import std.string : fromStringz;

import java.io.SyncFailedException;

/**
* Instances of the file descriptor class serve as an opaque handle to the
* underlying machine-specific structure representing an open file, an open
* socket, or another source or sink of bytes.
*
* The main practical use for a file descriptor is to create a
* `FileInputStream` or `FileOutputStream` to contain it.
*
* Applications should not create their own file descriptors.
*
* See_Also: FileInputStream, FileOutputStream
*/
public final class FileDescriptor
{
private int fFD;
private void* fHandle;

/// UNIX file descriptor
package int getFD()
{
return fFD;
}

/// Windows file HANDLE
package void* getHandle()
{
return fHandle;
}
Comment on lines +33 to +42
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these be const as well? Otherwise they cannot be on the constants below.


/**
* A handle to the standard input stream.
*
* Usually, this file descriptor is not used directly, but rather via the
* output stream known as `System.in`.
*/
public static const FileDescriptor in_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if there are other static variables which are objects in the code base, but these are thread local storage, do we want that?


/**
* A handle to the standard output stream.
*
* Usually, this file descriptor is not used directly, but rather via the
* output stream known as `System.out`.
*/
public static const FileDescriptor out_;

/**
* A handle to the standard error stream.
*
* Usually, this file descriptor is not used directly, but rather via the
* output stream known as `System.err`.
*/
public static const FileDescriptor err;

static this()
{
in_ = new FileDescriptor(0);
out_ = new FileDescriptor(1);
err = new FileDescriptor(2);
}

/**
* Construct an (invalid) FileDescriptor object.
*/
public this()
{
fFD = -1;
fHandle = null;
}

private this(int fd)
{
fFD = fd;
version (Posix) {
fHandle = null;
} else version(Windows) {
if (fd == 0) {
fHandle = GetStdHandle(STD_INPUT_HANDLE);
} else if (fd == 1) {
fHandle = GetStdHandle(STD_OUTPUT_HANDLE);
} else if (fd == 2) {
fHandle = GetStdHandle(STD_ERROR_HANDLE);
}
}
}

/**
* Tests if this file descriptor object is valid.
*
* Returns: `true` if the file descriptor object represents a valid, open
* file, socket, or other active I/O connection; `false` otherwise.
*/
public bool valid() const
{
version (Posix) {
return fFD >= 0;
} else version (Windows) {
return (fFD >= 0) && (fHandle !is null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is fFD ever used on Windows?

}
}

/**
* Force all system buffers to syncrhonize with the underlying device.
*
* This method returns after all modified data and attributes of this
* FileDescriptor have been written to the relevant device(s). In
* particular, if this FileDescriptor refers to a physical storage medium,
* such as a file in a file system, sync will not return until all
* in-memory modified copies of buffers associated with this FileDescriptor
* have been written to the physical medium. sync is meant to be used by
* code that requires physical storage (such as a file) to be in a known
* state. For example, a class that provided a simple transaction facility
* might use sync to ensure that all changes to a file caused by a given
* transaction were recorded on a storage medium. sync only affects
* buffers downstream of this FileDescriptor. If any in-memory buffering
* is being done by the application (for example, by a BufferedOutputStream
* object), those buffers must be flushed into the FileDescriptor (for
* example, by invoking OutputStream.flush) before that data will be
* affected by sync.
*
* Throws: SyncFailedException when the buffer cannot be flushed, or
* because the system cannot guarantee that all buffers have been
* synchronized with physical media.
*/
public void sync() const
{
version(Posix) {
int res = fsync(fFD);
if (res != 0) {
throw new SyncFailedException(getLastError());
}
} else version(Windows) {
const res = FlushFileBuffers(cast(void*)fHandle);
if (res == 0) {
throw new SyncFailedException(getLastError());
}
}
}


version(Posix) {
private string getLastError() const
{
return fromStringz(strerror(errno)).dup;
}
} else version(Windows) {
private string getLastError() const
{
import java.lang.String : String_valueOf, fromString16z;

LPWSTR buffer;
DWORD errorCode = GetLastError();

FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
null,
errorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
cast(LPWSTR)&buffer,
0,
null);

wstring result = fromString16z(buffer);
LocalFree(buffer);

return String_valueOf(result);
}
}
}
22 changes: 22 additions & 0 deletions base/src/java/io/SyncFailedException.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module java.io.SyncFailedException;

import java.lang.exceptions : IOException;

/**
* Signals that a sync operation has failed.
*/
public class SyncFailedException : IOException
{
/**
* Constructs a SyncFailedException with a detail message.
*
* A detail message is a String that describes this particular exception.
*
* Params:
* desc = a String describing the exception.
*/
this(string desc)
{
super(msg);
}
}