Add RandomAccessFile.read method and use it for file input stream.

I will deprecate the readList method completely as my next change.

R=sgjesse@google.com
BUG=

Review URL: https://codereview.chromium.org//11308226

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@15571 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
ager@google.com 2012-11-30 09:29:40 +00:00
parent 5928ec4ccb
commit 67f052fa04
6 changed files with 133 additions and 16 deletions

View file

@ -30,6 +30,7 @@
V(File_Close, 1) \
V(File_ReadByte, 1) \
V(File_WriteByte, 2) \
V(File_Read, 2) \
V(File_ReadList, 4) \
V(File_WriteList, 4) \
V(File_Position, 1) \

View file

@ -6,6 +6,7 @@
#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/io_buffer.h"
#include "bin/thread.h"
#include "bin/utils.h"
@ -158,6 +159,41 @@ void FUNCTION_NAME(File_WriteByte)(Dart_NativeArguments args) {
}
void FUNCTION_NAME(File_Read)(Dart_NativeArguments args) {
Dart_EnterScope();
intptr_t value =
DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
File* file = reinterpret_cast<File*>(value);
ASSERT(file != NULL);
Dart_Handle length_object = Dart_GetNativeArgument(args, 1);
int64_t length = 0;
if (DartUtils::GetInt64Value(length_object, &length)) {
uint8_t* buffer = NULL;
Dart_Handle external_array = IOBuffer::Allocate(length, &buffer);
int bytes_read = file->Read(reinterpret_cast<void*>(buffer), length);
if (bytes_read < 0) {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
} else {
if (bytes_read < length) {
// TODO(ager): cache the 'length' string if this becomes a bottle neck.
Dart_SetField(external_array,
DartUtils::NewString("length"),
Dart_NewInteger(bytes_read));
}
Dart_SetReturnValue(args, external_array);
}
} else {
OSError os_error(-1, "Invalid argument", OSError::kUnknown);
Dart_Handle err = DartUtils::NewDartOSError(&os_error);
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
Dart_ExitScope();
}
void FUNCTION_NAME(File_ReadList)(Dart_NativeArguments args) {
Dart_EnterScope();
intptr_t value =
@ -758,6 +794,39 @@ static void FinalizeExternalByteArray(void* peer) {
}
static CObject* FileReadRequest(const CObjectArray& request) {
if (request.Length() == 3 &&
request[1]->IsIntptr() &&
request[2]->IsInt32OrInt64()) {
File* file = CObjectToFilePointer(request[1]);
ASSERT(file != NULL);
if (!file->IsClosed()) {
int64_t length = CObjectInt32OrInt64ToInt64(request[2]);
uint8_t* buffer = new uint8_t[length];
int bytes_read = file->Read(buffer, length);
if (bytes_read >= 0) {
void* peer = reinterpret_cast<void*>(buffer);
CObject* external_array =
new CObjectExternalUint8Array(
CObject::NewExternalUint8Array(bytes_read,
buffer,
peer,
FinalizeExternalByteArray));
CObjectArray* result = new CObjectArray(CObject::NewArray(2));
result->SetAt(0, new CObjectIntptr(CObject::NewInt32(0)));
result->SetAt(1, external_array);
return result;
} else {
return CObject::NewOSError();
}
} else {
return CObject::FileClosedError();
}
}
return CObject::IllegalArgumentError();
}
static CObject* FileReadListRequest(const CObjectArray& request) {
if (request.Length() == 3 &&
request[1]->IsIntptr() &&
@ -897,6 +966,9 @@ void FileService(Dart_Port dest_port_id,
case File::kWriteByteRequest:
response = FileWriteByteRequest(request);
break;
case File::kReadRequest:
response = FileReadRequest(request);
break;
case File::kReadListRequest:
response = FileReadListRequest(request);
break;

View file

@ -60,8 +60,9 @@ class File {
kFlushRequest = 13,
kReadByteRequest = 14,
kWriteByteRequest = 15,
kReadListRequest = 16,
kWriteListRequest = 17
kReadRequest = 16,
kReadListRequest = 17,
kWriteListRequest = 18
};
~File();

View file

@ -21,6 +21,7 @@ patch class _File {
patch class _RandomAccessFile {
/* patch */ static int _close(int id) native "File_Close";
/* patch */ static _readByte(int id) native "File_ReadByte";
/* patch */ static _read(int id, int bytes) native "File_Read";
/* patch */ static _readList(int id, List<int> buffer, int offset, int bytes)
native "File_ReadList";
/* patch */ static _writeByte(int id, int value) native "File_WriteByte";

View file

@ -303,6 +303,17 @@ abstract class RandomAccessFile {
*/
int readByteSync();
/**
* Reads from a file and returns the result as a list of bytes.
*/
Future<List<int>> read(int bytes);
/**
* Synchronously reads from a file and returns the result in a
* list of bytes.
*/
List<int> readSync(int bytes);
/**
* Read a List<int> from the file. Returns a [:Future<int>:] that
* completes with an indication of how much was read.

View file

@ -65,22 +65,15 @@ class _FileInputStream extends _BaseDataInputStream implements InputStream {
_closeFile();
return;
}
// If there is currently a _fillBuffer call waiting on readList,
// If there is currently a _fillBuffer call waiting on read,
// let it fill the buffer instead of us.
if (_activeFillBufferCall) return;
_activeFillBufferCall = true;
if (_data.length != size) {
_data = new Uint8List(size);
// Maintain the invariant signalling that the buffer is empty.
_position = _data.length;
}
var future = _openedFile.readList(_data, 0, _data.length);
future.then((read) {
_filePosition += read;
if (read != _data.length) {
_data = _data.getRange(0, read);
}
var future = _openedFile.read(size);
future.then((data) {
_data = data;
_position = 0;
_filePosition += _data.length;
_activeFillBufferCall = false;
if (_fileLength == _filePosition) {
@ -319,8 +312,9 @@ const int _LAST_MODIFIED_REQUEST = 12;
const int _FLUSH_REQUEST = 13;
const int _READ_BYTE_REQUEST = 14;
const int _WRITE_BYTE_REQUEST = 15;
const int _READ_LIST_REQUEST = 16;
const int _WRITE_LIST_REQUEST = 17;
const int _READ_REQUEST = 16;
const int _READ_LIST_REQUEST = 17;
const int _WRITE_LIST_REQUEST = 18;
// Base class for _File and _RandomAccessFile with shared functions.
class _FileBase {
@ -787,6 +781,43 @@ class _RandomAccessFile extends _FileBase implements RandomAccessFile {
return result;
}
Future<List<int>> read(int bytes) {
_ensureFileService();
Completer<List<int>> completer = new Completer<List<int>>();
if (bytes is !int) {
// Complete asynchronously so the user has a chance to setup
// handlers without getting exceptions when registering the
// then handler.
new Timer(0, (t) {
completer.completeException(new FileIOException(
"Invalid arguments to read for file '$_name'"));
});
return completer.future;
};
if (closed) return _completeWithClosedException(completer);
List request = new List(3);
request[0] = _READ_REQUEST;
request[1] = _id;
request[2] = bytes;
return _fileService.call(request).transform((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response,
"read failed for file '$_name'");
}
return response[1];
});
}
external static _read(int id, int bytes);
List<int> readSync(int bytes) {
if (bytes is !int) {
throw new FileIOException(
"Invalid arguments to readSync for file '$_name'");
}
return _read(_id, bytes);
}
Future<int> readList(List<int> buffer, int offset, int bytes) {
_ensureFileService();
Completer<int> completer = new Completer<int>();