Files
sdk/runtime/bin/file.cc
T
asiva@google.com ebbb7c4134 - Represent strings internally in UTF-16 format, this makes it
compatible with webkit and will allow for easy externalization of
  strings. One byte strings are retained for pure ASCII strings.
  (The language specification was changed recently to reflect this as
   follows "A string is a sequence of UTF-16 code units").
- Remove four byte string class and all references to it.
- Rename some of the string functions in Dart API to make them
  consistent and better describe the underlying functionality
  Dart_NewString => Dart_NewStringFromCString
  Dart_NewString8 => Dart_NewStringFromUTF8
  Dart_NewString16 => Dart_NewStringFromUTF16
  Dart_NewString32 => Dart_NewStringFromUTF32
  Dart_NewExternalString8 => Dart_NewExternalUTF8String
  Dart_NewExternalString16 => Dart_NewExternalUTF16String
  Dart_NewExternalString32 => Dart_NewExternalUTF32String
  Dart_StringGet8 => Dart_StringToUTF8
  Dart_StringGet16 => Dart_StringToUTF16
  Dart_StringToCString => Dart_StringToCString
  Dart_IsString8 => Removed
  Dart_IsString16 -> Removed
  Dart_StringToBytes -> Removed
  Dart_StringGet32 -> Removed
Review URL: https://codereview.chromium.org//11318018

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@14357 260f80e4-7a28-3924-810f-c04153c831b5
2012-10-31 17:56:46 +00:00

952 lines
29 KiB
C++

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "bin/file.h"
#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/thread.h"
#include "bin/utils.h"
#include "include/dart_api.h"
static const int kMSPerSecond = 1000;
dart::Mutex File::mutex_;
int File::service_ports_size_ = 0;
Dart_Port* File::service_ports_ = NULL;
int File::service_ports_index_ = 0;
bool File::ReadFully(void* buffer, int64_t num_bytes) {
int64_t remaining = num_bytes;
char* current_buffer = reinterpret_cast<char*>(buffer);
while (remaining > 0) {
int bytes_read = Read(current_buffer, remaining);
if (bytes_read <= 0) {
return false;
}
remaining -= bytes_read; // Reduce the number of remaining bytes.
current_buffer += bytes_read; // Move the buffer forward.
}
return true;
}
bool File::WriteFully(const void* buffer, int64_t num_bytes) {
int64_t remaining = num_bytes;
const char* current_buffer = reinterpret_cast<const char*>(buffer);
while (remaining > 0) {
int bytes_read = Write(current_buffer, remaining);
if (bytes_read < 0) {
return false;
}
remaining -= bytes_read; // Reduce the number of remaining bytes.
current_buffer += bytes_read; // Move the buffer forward.
}
return true;
}
File::FileOpenMode File::DartModeToFileMode(DartFileOpenMode mode) {
ASSERT(mode == File::kDartRead ||
mode == File::kDartWrite ||
mode == File::kDartAppend);
if (mode == File::kDartWrite) {
return File::kWriteTruncate;
}
if (mode == File::kDartAppend) {
return File::kWrite;
}
return File::kRead;
}
void FUNCTION_NAME(File_Open)(Dart_NativeArguments args) {
Dart_EnterScope();
const char* filename =
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
int mode = DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 1));
File::DartFileOpenMode dart_file_mode =
static_cast<File::DartFileOpenMode>(mode);
File::FileOpenMode file_mode = File::DartModeToFileMode(dart_file_mode);
// Check that the file exists before opening it only for
// reading. This is to prevent the opening of directories as
// files. Directories can be opened for reading using the posix
// 'open' call.
File* file = NULL;
file = File::Open(filename, file_mode);
if (file != NULL) {
Dart_SetReturnValue(args,
Dart_NewInteger(reinterpret_cast<intptr_t>(file)));
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
Dart_ExitScope();
}
void FUNCTION_NAME(File_Exists)(Dart_NativeArguments args) {
Dart_EnterScope();
const char* filename =
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
bool exists = File::Exists(filename);
Dart_SetReturnValue(args, Dart_NewBoolean(exists));
Dart_ExitScope();
}
void FUNCTION_NAME(File_Close)(Dart_NativeArguments args) {
Dart_EnterScope();
intptr_t value =
DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
File* file = reinterpret_cast<File*>(value);
ASSERT(file != NULL);
delete file;
Dart_SetReturnValue(args, Dart_NewInteger(0));
Dart_ExitScope();
}
void FUNCTION_NAME(File_ReadByte)(Dart_NativeArguments args) {
Dart_EnterScope();
intptr_t value =
DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
File* file = reinterpret_cast<File*>(value);
ASSERT(file != NULL);
uint8_t buffer;
int bytes_read = file->Read(reinterpret_cast<void*>(&buffer), 1);
if (bytes_read == 1) {
Dart_SetReturnValue(args, Dart_NewInteger(buffer));
} else if (bytes_read == 0) {
Dart_SetReturnValue(args, Dart_NewInteger(-1));
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
Dart_ExitScope();
}
void FUNCTION_NAME(File_WriteByte)(Dart_NativeArguments args) {
Dart_EnterScope();
intptr_t file_ptr =
DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
File* file = reinterpret_cast<File*>(file_ptr);
ASSERT(file != NULL);
int64_t value = 0;
if (DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 1), &value)) {
uint8_t buffer = static_cast<uint8_t>(value & 0xff);
int bytes_written = file->Write(reinterpret_cast<void*>(&buffer), 1);
if (bytes_written >= 0) {
Dart_SetReturnValue(args, Dart_NewInteger(bytes_written));
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
} 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 =
DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
File* file = reinterpret_cast<File*>(value);
ASSERT(file != NULL);
Dart_Handle buffer_obj = Dart_GetNativeArgument(args, 1);
ASSERT(Dart_IsList(buffer_obj));
// Offset and length arguments are checked in Dart code to be
// integers and have the property that (offset + length) <=
// list.length. Therefore, it is safe to extract their value as
// 64-bit integers.
int64_t offset =
DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 2));
int64_t length =
DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 3));
intptr_t array_len = 0;
Dart_Handle result = Dart_ListLength(buffer_obj, &array_len);
if (Dart_IsError(result)) Dart_PropagateError(result);
ASSERT((offset + length) <= array_len);
uint8_t* buffer = new uint8_t[length];
int bytes_read = file->Read(reinterpret_cast<void*>(buffer), length);
if (bytes_read >= 0) {
result = Dart_ListSetAsBytes(buffer_obj, offset, buffer, bytes_read);
if (Dart_IsError(result)) {
delete[] buffer;
Dart_PropagateError(result);
}
Dart_SetReturnValue(args, Dart_NewInteger(bytes_read));
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
delete[] buffer;
Dart_ExitScope();
}
void FUNCTION_NAME(File_WriteList)(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 buffer_obj = Dart_GetNativeArgument(args, 1);
ASSERT(Dart_IsList(buffer_obj));
// Offset and length arguments are checked in Dart code to be
// integers and have the property that (offset + length) <=
// list.length. Therefore, it is safe to extract their value as
// 64-bit integers.
int64_t offset =
DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 2));
int64_t length =
DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 3));
intptr_t buffer_len = 0;
Dart_Handle result = Dart_ListLength(buffer_obj, &buffer_len);
if (Dart_IsError(result)) Dart_PropagateError(result);
ASSERT((offset + length) <= buffer_len);
uint8_t* buffer = new uint8_t[length];
result = Dart_ListGetAsBytes(buffer_obj, offset, buffer, length);
if (Dart_IsError(result)) {
delete[] buffer;
Dart_PropagateError(result);
}
int bytes_written = file->Write(reinterpret_cast<void*>(buffer), length);
if (bytes_written >= 0) {
Dart_SetReturnValue(args, Dart_NewInteger(bytes_written));
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
delete[] buffer;
Dart_ExitScope();
}
void FUNCTION_NAME(File_Position)(Dart_NativeArguments args) {
Dart_EnterScope();
intptr_t value =
DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
File* file = reinterpret_cast<File*>(value);
ASSERT(file != NULL);
intptr_t return_value = file->Position();
if (return_value >= 0) {
Dart_SetReturnValue(args, Dart_NewInteger(return_value));
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
Dart_ExitScope();
}
void FUNCTION_NAME(File_SetPosition)(Dart_NativeArguments args) {
Dart_EnterScope();
intptr_t value =
DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
File* file = reinterpret_cast<File*>(value);
ASSERT(file != NULL);
int64_t position = 0;
if (DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 1), &position)) {
if (file->SetPosition(position)) {
Dart_SetReturnValue(args, Dart_True());
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
} 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_Truncate)(Dart_NativeArguments args) {
Dart_EnterScope();
intptr_t value =
DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
File* file = reinterpret_cast<File*>(value);
ASSERT(file != NULL);
int64_t length = 0;
if (DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 1), &length)) {
if (file->Truncate(length)) {
Dart_SetReturnValue(args, Dart_True());
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
} 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_Length)(Dart_NativeArguments args) {
Dart_EnterScope();
intptr_t value =
DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
File* file = reinterpret_cast<File*>(value);
ASSERT(file != NULL);
intptr_t return_value = file->Length();
if (return_value >= 0) {
Dart_SetReturnValue(args, Dart_NewInteger(return_value));
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
Dart_ExitScope();
}
void FUNCTION_NAME(File_LengthFromName)(Dart_NativeArguments args) {
Dart_EnterScope();
const char* name =
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
intptr_t return_value = File::LengthFromName(name);
if (return_value >= 0) {
Dart_SetReturnValue(args, Dart_NewInteger(return_value));
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
Dart_ExitScope();
}
void FUNCTION_NAME(File_LastModified)(Dart_NativeArguments args) {
Dart_EnterScope();
const char* name =
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
int64_t return_value = File::LastModified(name);
if (return_value >= 0) {
Dart_SetReturnValue(args, Dart_NewInteger(return_value * kMSPerSecond));
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
Dart_ExitScope();
}
void FUNCTION_NAME(File_Flush)(Dart_NativeArguments args) {
Dart_EnterScope();
intptr_t value =
DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
File* file = reinterpret_cast<File*>(value);
ASSERT(file != NULL);
if (file->Flush()) {
Dart_SetReturnValue(args, Dart_True());
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
Dart_ExitScope();
}
void FUNCTION_NAME(File_Create)(Dart_NativeArguments args) {
Dart_EnterScope();
const char* str =
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
bool result = File::Create(str);
if (result) {
Dart_SetReturnValue(args, Dart_NewBoolean(result));
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
Dart_ExitScope();
}
void FUNCTION_NAME(File_Delete)(Dart_NativeArguments args) {
Dart_EnterScope();
const char* str =
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
bool result = File::Delete(str);
if (result) {
Dart_SetReturnValue(args, Dart_NewBoolean(result));
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
Dart_ExitScope();
}
void FUNCTION_NAME(File_Directory)(Dart_NativeArguments args) {
Dart_EnterScope();
const char* str =
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
char* str_copy = strdup(str);
char* path = File::GetContainingDirectory(str_copy);
free(str_copy);
if (path != NULL) {
Dart_SetReturnValue(args, DartUtils::NewString(path));
free(path);
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
Dart_ExitScope();
}
void FUNCTION_NAME(File_FullPath)(Dart_NativeArguments args) {
Dart_EnterScope();
const char* str =
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
char* path = File::GetCanonicalPath(str);
if (path != NULL) {
Dart_SetReturnValue(args, DartUtils::NewString(path));
free(path);
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
Dart_ExitScope();
}
void FUNCTION_NAME(File_OpenStdio)(Dart_NativeArguments args) {
Dart_EnterScope();
int fd = DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
File* file = File::OpenStdio(fd);
Dart_SetReturnValue(args, Dart_NewInteger(reinterpret_cast<intptr_t>(file)));
Dart_ExitScope();
}
void FUNCTION_NAME(File_GetStdioHandleType)(Dart_NativeArguments args) {
Dart_EnterScope();
int fd = DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
File::StdioHandleType type = File::GetStdioHandleType(fd);
Dart_SetReturnValue(args, Dart_NewInteger(type));
Dart_ExitScope();
}
static int64_t CObjectInt32OrInt64ToInt64(CObject* cobject) {
ASSERT(cobject->IsInt32OrInt64());
int64_t result;
if (cobject->IsInt32()) {
CObjectInt32 value(cobject);
result = value.Value();
} else {
CObjectInt64 value(cobject);
result = value.Value();
}
return result;
}
File* CObjectToFilePointer(CObject* cobject) {
CObjectIntptr value(cobject);
return reinterpret_cast<File*>(value.Value());
}
static CObject* FileExistsRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsString()) {
CObjectString filename(request[1]);
bool result = File::Exists(filename.CString());
return CObject::Bool(result);
}
return CObject::IllegalArgumentError();
}
static CObject* FileCreateRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsString()) {
CObjectString filename(request[1]);
bool result = File::Create(filename.CString());
if (result) {
return CObject::True();
} else {
return CObject::NewOSError();
}
}
return CObject::IllegalArgumentError();
}
static CObject* FileOpenRequest(const CObjectArray& request) {
File* file = NULL;
if (request.Length() == 3 &&
request[1]->IsString() &&
request[2]->IsInt32()) {
CObjectString filename(request[1]);
CObjectInt32 mode(request[2]);
File::DartFileOpenMode dart_file_mode =
static_cast<File::DartFileOpenMode>(mode.Value());
File::FileOpenMode file_mode = File::DartModeToFileMode(dart_file_mode);
file = File::Open(filename.CString(), file_mode);
if (file != NULL) {
return new CObjectIntptr(
CObject::NewIntptr(reinterpret_cast<intptr_t>(file)));
} else {
return CObject::NewOSError();
}
}
return CObject::IllegalArgumentError();
}
static CObject* FileDeleteRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsString()) {
CObjectString filename(request[1]);
bool result = File::Delete(filename.CString());
if (result) {
return CObject::True();
} else {
return CObject::NewOSError();
}
}
return CObject::False();
}
static CObject* FileFullPathRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsString()) {
CObjectString filename(request[1]);
char* result = File::GetCanonicalPath(filename.CString());
if (result != NULL) {
CObject* path = new CObjectString(CObject::NewString(result));
free(result);
return path;
} else {
return CObject::NewOSError();
}
}
return CObject::IllegalArgumentError();
}
static CObject* FileDirectoryRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsString()) {
CObjectString filename(request[1]);
char* str_copy = strdup(filename.CString());
char* path = File::GetContainingDirectory(str_copy);
free(str_copy);
if (path != NULL) {
CObject* result = new CObjectString(CObject::NewString(path));
free(path);
return result;
} else {
return CObject::NewOSError();
}
}
return CObject::Null();
}
static CObject* FileCloseRequest(const CObjectArray& request) {
intptr_t return_value = -1;
if (request.Length() == 2 && request[1]->IsIntptr()) {
File* file = CObjectToFilePointer(request[1]);
ASSERT(file != NULL);
delete file;
return_value = 0;
}
return new CObjectIntptr(CObject::NewIntptr(return_value));
}
static CObject* FilePositionRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsIntptr()) {
File* file = CObjectToFilePointer(request[1]);
ASSERT(file != NULL);
if (!file->IsClosed()) {
intptr_t return_value = file->Position();
if (return_value >= 0) {
return new CObjectIntptr(CObject::NewIntptr(return_value));
} else {
return CObject::NewOSError();
}
} else {
return CObject::FileClosedError();
}
}
return CObject::IllegalArgumentError();
}
static CObject* FileSetPositionRequest(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 position = CObjectInt32OrInt64ToInt64(request[2]);
if (file->SetPosition(position)) {
return CObject::True();
} else {
return CObject::NewOSError();
}
} else {
return CObject::FileClosedError();
}
}
return CObject::IllegalArgumentError();
}
static CObject* FileTruncateRequest(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]);
if (file->Truncate(length)) {
return CObject::True();
} else {
return CObject::NewOSError();
}
} else {
return CObject::FileClosedError();
}
}
return CObject::IllegalArgumentError();
}
static CObject* FileLengthRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsIntptr()) {
File* file = CObjectToFilePointer(request[1]);
ASSERT(file != NULL);
if (!file->IsClosed()) {
intptr_t return_value = file->Length();
if (return_value >= 0) {
return new CObjectIntptr(CObject::NewIntptr(return_value));
} else {
return CObject::NewOSError();
}
} else {
return CObject::FileClosedError();
}
}
return CObject::IllegalArgumentError();
}
static CObject* FileLengthFromNameRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsString()) {
CObjectString filename(request[1]);
intptr_t return_value = File::LengthFromName(filename.CString());
if (return_value >= 0) {
return new CObjectIntptr(CObject::NewIntptr(return_value));
} else {
return CObject::NewOSError();
}
}
return CObject::IllegalArgumentError();
}
static CObject* FileLastModifiedRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsString()) {
CObjectString filename(request[1]);
int64_t return_value = File::LastModified(filename.CString());
if (return_value >= 0) {
return new CObjectIntptr(CObject::NewInt64(return_value * kMSPerSecond));
} else {
return CObject::NewOSError();
}
}
return CObject::IllegalArgumentError();
}
static CObject* FileFlushRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsIntptr()) {
File* file = CObjectToFilePointer(request[1]);
ASSERT(file != NULL);
if (!file->IsClosed()) {
if (file->Flush()) {
return CObject::True();
} else {
return CObject::NewOSError();
}
} else {
return CObject::FileClosedError();
}
}
return CObject::IllegalArgumentError();
}
static CObject* FileReadByteRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsIntptr()) {
File* file = CObjectToFilePointer(request[1]);
ASSERT(file != NULL);
if (!file->IsClosed()) {
uint8_t buffer;
int bytes_read = file->Read(reinterpret_cast<void*>(&buffer), 1);
if (bytes_read > 0) {
return new CObjectIntptr(CObject::NewIntptr(buffer));
} else if (bytes_read == 0) {
return new CObjectIntptr(CObject::NewIntptr(-1));
} else {
return CObject::NewOSError();
}
} else {
return CObject::FileClosedError();
}
}
return CObject::IllegalArgumentError();
}
static CObject* FileWriteByteRequest(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 byte = CObjectInt32OrInt64ToInt64(request[2]);
uint8_t buffer = static_cast<uint8_t>(byte & 0xff);
int bytes_written = file->Write(reinterpret_cast<void*>(&buffer), 1);
if (bytes_written > 0) {
return new CObjectIntptr(CObject::NewIntptr(bytes_written));
} else {
return CObject::NewOSError();
}
} else {
return CObject::FileClosedError();
}
}
return CObject::IllegalArgumentError();
}
static void FinalizeExternalByteArray(void* peer) {
delete[] reinterpret_cast<uint8_t*>(peer);
}
static CObject* FileReadListRequest(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(length,
buffer,
peer,
FinalizeExternalByteArray));
CObjectArray* result = new CObjectArray(CObject::NewArray(3));
result->SetAt(0, new CObjectIntptr(CObject::NewInt32(0)));
result->SetAt(1, new CObjectIntptr(CObject::NewIntptr(bytes_read)));
result->SetAt(2, external_array);
return result;
} else {
return CObject::NewOSError();
}
} else {
return CObject::FileClosedError();
}
}
return CObject::IllegalArgumentError();
}
static CObject* FileWriteListRequest(const CObjectArray& request) {
if (request.Length() == 5 &&
request[1]->IsIntptr() &&
(request[2]->IsUint8Array() || request[2]->IsArray()) &&
request[3]->IsInt32OrInt64() &&
request[4]->IsInt32OrInt64()) {
File* file = CObjectToFilePointer(request[1]);
ASSERT(file != NULL);
if (!file->IsClosed()) {
int64_t offset = CObjectInt32OrInt64ToInt64(request[3]);
int64_t length = CObjectInt32OrInt64ToInt64(request[4]);
uint8_t* buffer_start;
if (request[2]->IsUint8Array()) {
CObjectUint8Array byte_array(request[2]);
buffer_start = byte_array.Buffer() + offset;
} else {
CObjectArray array(request[2]);
buffer_start = new uint8_t[length];
for (int i = 0; i < length; i++) {
if (array[i + offset]->IsInt32OrInt64()) {
int64_t value = CObjectInt32OrInt64ToInt64(array[i + offset]);
buffer_start[i] = value & 0xFF;
} else {
// Unsupported type.
delete[] buffer_start;
return CObject::IllegalArgumentError();
}
}
offset = 0;
}
int64_t bytes_written =
file->Write(reinterpret_cast<void*>(buffer_start), length);
if (!request[2]->IsUint8Array()) {
delete[] buffer_start;
}
if (bytes_written >= 0) {
return new CObjectIntptr(CObject::NewIntptr(bytes_written));
} else {
return CObject::NewOSError();
}
} else {
return CObject::FileClosedError();
}
}
return CObject::IllegalArgumentError();
}
void FileService(Dart_Port dest_port_id,
Dart_Port reply_port_id,
Dart_CObject* message) {
CObject* response = CObject::False();
CObjectArray request(message);
if (message->type == Dart_CObject::kArray) {
if (request.Length() > 1 && request[0]->IsInt32()) {
CObjectInt32 requestType(request[0]);
switch (requestType.Value()) {
case File::kExistsRequest:
response = FileExistsRequest(request);
break;
case File::kCreateRequest:
response = FileCreateRequest(request);
break;
case File::kOpenRequest:
response = FileOpenRequest(request);
break;
case File::kDeleteRequest:
response = FileDeleteRequest(request);
break;
case File::kFullPathRequest:
response = FileFullPathRequest(request);
break;
case File::kDirectoryRequest:
response = FileDirectoryRequest(request);
break;
case File::kCloseRequest:
response = FileCloseRequest(request);
break;
case File::kPositionRequest:
response = FilePositionRequest(request);
break;
case File::kSetPositionRequest:
response = FileSetPositionRequest(request);
break;
case File::kTruncateRequest:
response = FileTruncateRequest(request);
break;
case File::kLengthRequest:
response = FileLengthRequest(request);
break;
case File::kLengthFromNameRequest:
response = FileLengthFromNameRequest(request);
break;
case File::kLastModifiedRequest:
response = FileLastModifiedRequest(request);
break;
case File::kFlushRequest:
response = FileFlushRequest(request);
break;
case File::kReadByteRequest:
response = FileReadByteRequest(request);
break;
case File::kWriteByteRequest:
response = FileWriteByteRequest(request);
break;
case File::kReadListRequest:
response = FileReadListRequest(request);
break;
case File::kWriteListRequest:
response = FileWriteListRequest(request);
break;
default:
UNREACHABLE();
}
}
}
Dart_PostCObject(reply_port_id, response->AsApiCObject());
}
Dart_Port File::GetServicePort() {
MutexLocker lock(&mutex_);
if (service_ports_size_ == 0) {
ASSERT(service_ports_ == NULL);
service_ports_size_ = 16;
service_ports_ = new Dart_Port[service_ports_size_];
service_ports_index_ = 0;
for (int i = 0; i < service_ports_size_; i++) {
service_ports_[i] = ILLEGAL_PORT;
}
}
Dart_Port result = service_ports_[service_ports_index_];
if (result == ILLEGAL_PORT) {
result = Dart_NewNativePort("FileService",
FileService,
true);
ASSERT(result != ILLEGAL_PORT);
service_ports_[service_ports_index_] = result;
}
service_ports_index_ = (service_ports_index_ + 1) % service_ports_size_;
return result;
}
void FUNCTION_NAME(File_NewServicePort)(Dart_NativeArguments args) {
Dart_EnterScope();
Dart_SetReturnValue(args, Dart_Null());
Dart_Port service_port = File::GetServicePort();
if (service_port != ILLEGAL_PORT) {
// Return a send port for the service port.
Dart_Handle send_port = Dart_NewSendPort(service_port);
Dart_SetReturnValue(args, send_port);
}
Dart_ExitScope();
}