Chromium Code Reviews| Index: runtime/bin/file.cc |
| diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc |
| index 9eedc8579206a092f6931360747e25c844317c87..d48a65d18323927926c106d0f5b7b000a200bcac 100644 |
| --- a/runtime/bin/file.cc |
| +++ b/runtime/bin/file.cc |
| @@ -40,25 +40,26 @@ bool File::WriteFully(const void* buffer, int64_t num_bytes) { |
| } |
| -void FUNCTION_NAME(File_Open)(Dart_NativeArguments args) { |
| - // These values have to be kept in sync with the mode values of |
| - // FileMode.READ, FileMode.WRITE and FileMode.APPEND in file.dart. |
| - static const int kRead = 0; |
| - static const int kWrite = 1; |
| - static const int kAppend = 2; |
| +File::FileOpenMode File::DartModeToFileMode(int 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)); |
| - ASSERT(mode == kRead || mode == kWrite || mode == kAppend); |
| - File::FileOpenMode file_mode = File::kRead; |
| - if (mode == kWrite) { |
| - file_mode = File::kWriteTruncate; |
| - } |
| - if (mode == kAppend) { |
| - file_mode = File::kWrite; |
| - } |
| + File::FileOpenMode file_mode = File::DartModeToFileMode(mode); |
| File* file = File::Open(filename, file_mode); |
| Dart_SetReturnValue(args, Dart_NewInteger(reinterpret_cast<intptr_t>(file))); |
| Dart_ExitScope(); |
| @@ -342,3 +343,349 @@ void FUNCTION_NAME(File_GetStdioHandleType)(Dart_NativeArguments args) { |
| 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; |
| +} |
| + |
| + |
| +template <class T> |
| +T* CObjectToPointer(CObject* cobject) { |
|
Mads Ager (google)
2012/02/20 13:50:31
Can't we just have a:
static File* CObjectToFileP
Søren Gjesse
2012/02/21 14:22:39
Done.
|
| + CObjectIntptr value(cobject); |
| + return reinterpret_cast<T*>(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::False(); |
| +} |
| + |
| + |
| +static CObject* FileCreateRequest(const CObjectArray& request) { |
| + if (request.Length() == 2 && request[1]->IsString()) { |
| + CObjectString filename(request[1]); |
| + bool result = File::Create(filename.CString()); |
| + return CObject::Bool(result); |
| + } |
| + return CObject::False(); |
| +} |
| + |
| + |
| +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::FileOpenMode file_mode = File::DartModeToFileMode(mode.Value()); |
| + file = File::Open(filename.CString(), file_mode); |
| + } |
| + return new CObjectIntptr( |
| + CObject::NewIntptr(reinterpret_cast<intptr_t>(file))); |
| +} |
| + |
| + |
| +static CObject* FileDeleteRequest(const CObjectArray& request) { |
| + if (request.Length() == 2 && request[1]->IsString()) { |
| + CObjectString filename(request[1]); |
| + bool result = File::Delete(filename.CString()); |
| + return CObject::Bool(result); |
| + } |
| + return CObject::False(); |
| +} |
| + |
| + |
| +static CObject* FileFullPathRequest(const CObjectArray& request) { |
| + if (request.Length() == 2 && request[1]->IsString()) { |
| + CObjectString filename(request[1]); |
| + char* path = File::GetCanonicalPath(filename.CString()); |
| + return new CObjectString(CObject::NewString(path)); |
| + } |
| + return CObject::Null(); |
| +} |
| + |
| + |
| +static CObject* FileCloseRequest(const CObjectArray& request) { |
| + intptr_t return_value = -1; |
| + if (request.Length() == 2 && request[1]->IsIntptr()) { |
| + File* file = CObjectToPointer<File>(request[1]); |
| + if (file != NULL) { |
| + delete file; |
| + return_value = 0; |
| + } |
| + } |
| + return new CObjectIntptr(CObject::NewIntptr(return_value)); |
| +} |
| + |
| + |
| +static CObject* FilePositionRequest(const CObjectArray& request) { |
| + intptr_t return_value = -1; |
| + if (request.Length() == 2 && request[1]->IsIntptr()) { |
| + File* file = CObjectToPointer<File>(request[1]); |
| + if (file != NULL) { |
| + return_value = file->Position(); |
| + } |
| + } |
| + return new CObjectIntptr(CObject::NewIntptr(return_value)); |
| +} |
| + |
| + |
| +static CObject* FileSetPositionRequest(const CObjectArray& request) { |
| + bool return_value = false; |
| + if (request.Length() == 3 && |
| + request[1]->IsIntptr() && |
| + request[2]->IsInt32OrInt64()) { |
| + File* file = CObjectToPointer<File>(request[1]); |
| + if (file != NULL) { |
| + int64_t position = CObjectInt32OrInt64ToInt64(request[2]); |
| + return_value = file->SetPosition(position); |
| + } |
| + } |
| + return CObject::Bool(return_value); |
| +} |
| + |
| + |
| +static CObject* FileTruncateRequest(const CObjectArray& request) { |
| + bool return_value = false; |
| + if (request.Length() == 3 && |
| + request[1]->IsIntptr() && |
| + request[2]->IsInt32OrInt64()) { |
| + File* file = CObjectToPointer<File>(request[1]); |
| + if (file != NULL) { |
| + int64_t length = CObjectInt32OrInt64ToInt64(request[2]); |
| + return_value = file->Truncate(length); |
| + } |
| + } |
| + return CObject::Bool(return_value); |
| +} |
| + |
| + |
| +static CObject* FileLengthRequest(const CObjectArray& request) { |
| + intptr_t return_value = -1; |
| + if (request.Length() == 2 && request[1]->IsIntptr()) { |
| + File* file = CObjectToPointer<File>(request[1]); |
| + if (file != NULL) { |
| + return_value = file->Length(); |
| + } |
| + } |
| + return new CObjectIntptr(CObject::NewIntptr(return_value)); |
| +} |
| + |
| + |
| +static CObject* FileFlushRequest(const CObjectArray& request) { |
| + intptr_t return_value = -1; |
| + if (request.Length() == 2 && request[1]->IsIntptr()) { |
| + File* file = CObjectToPointer<File>(request[1]); |
| + if (file != NULL) { |
| + file->Flush(); |
| + return_value = 0; |
| + } |
| + } |
| + return new CObjectIntptr(CObject::NewIntptr(return_value)); |
| +} |
| + |
| + |
| +static CObject* FileReadByteRequest(const CObjectArray& request) { |
| + intptr_t return_value = -1; |
| + if (request.Length() == 2 && request[1]->IsIntptr()) { |
| + File* file = CObjectToPointer<File>(request[1]); |
| + if (file != NULL) { |
| + uint8_t buffer; |
| + int bytes_read = file->Read(reinterpret_cast<void*>(&buffer), 1); |
| + if (bytes_read == 1) { |
| + return_value = static_cast<intptr_t>(buffer); |
| + } else { |
| + return_value = -1; |
| + } |
| + } |
| + } |
| + return new CObjectIntptr(CObject::NewIntptr(return_value)); |
| +} |
| + |
| +static CObject* FileWriteByteRequest(const CObjectArray& request) { |
| + intptr_t return_value = -1; |
| + if (request.Length() == 3 && |
| + request[1]->IsIntptr() && |
| + request[2]->IsInt32OrInt64()) { |
| + File* file = CObjectToPointer<File>(request[1]); |
| + if (file != NULL) { |
| + 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_value = bytes_written; |
| + } |
| + } |
| + } |
| + return new CObjectIntptr(CObject::NewIntptr(return_value)); |
| +} |
| + |
| +static CObject* FileReadListRequest(const CObjectArray& request) { |
| + if (request.Length() == 3 && |
| + request[1]->IsIntptr() && |
| + request[2]->IsInt32OrInt64()) { |
| + File* file = CObjectToPointer<File>(request[1]); |
| + int64_t length = CObjectInt32OrInt64ToInt64(request[2]); |
| + CObjectByteArray* byte_array = |
| + new CObjectByteArray(CObject::NewByteArray(length)); |
| + int total_bytes_read = |
| + file->Read(reinterpret_cast<void*>(byte_array->Buffer()), |
|
Mads Ager (google)
2012/02/20 13:50:31
It might be more readable to do the casting outsid
Søren Gjesse
2012/02/21 14:22:39
Done.
|
| + byte_array->Length()); |
| + CObjectArray* result = new CObjectArray(CObject::NewArray(2)); |
| + result->SetAt(0, new CObjectIntptr(CObject::NewIntptr(total_bytes_read))); |
| + result->SetAt(1, byte_array); |
| + return result; |
| + } |
| + return CObject::Null(); |
| +} |
| + |
| + |
| +static CObject* FileWriteListRequest(const CObjectArray& request) { |
| + if (request.Length() == 5 && |
| + request[1]->IsIntptr() && |
| + (request[2]->IsByteArray() || request[2]->IsArray()) && |
| + request[3]->IsInt32OrInt64() && |
| + request[4]->IsInt32OrInt64()) { |
| + File* file = CObjectToPointer<File>(request[1]); |
| + int64_t offset = CObjectInt32OrInt64ToInt64(request[3]); |
| + int64_t length = CObjectInt32OrInt64ToInt64(request[4]); |
| + uint8_t* buffer_start; |
| + if (request[2]->IsByteArray()) { |
| + CObjectByteArray byte_array(request[2]); |
| + buffer_start = byte_array.Buffer() + offset; |
| + } else { |
| + CObjectArray array(request[2]); |
| + uint8_t* 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 { |
| + // TODO(sgjesse): Return error. |
|
Mads Ager (google)
2012/02/20 13:50:31
Is this new or did we handle this the same way bef
Søren Gjesse
2012/02/21 14:22:39
Before we used Dart_ListGetAsBytes and if there is
|
| + buffer_start[i] = 0; |
| + } |
| + } |
| + offset = 0; |
| + } |
| + int64_t total_bytes_written = |
| + file->Write(reinterpret_cast<void*>(buffer_start), length); |
| + ASSERT(total_bytes_written == length); |
| + return new CObjectInt64(CObject::NewInt64(total_bytes_written)); |
| + } |
| + return CObject::Null(); |
| +} |
| + |
| + |
| +static CObject* FileWriteStringRequest(const CObjectArray& request) { |
| + if (request.Length() == 3 && |
| + request[1]->IsIntptr() && |
| + request[2]->IsString()) { |
| + File* file = CObjectToPointer<File>(request[1]); |
| + CObjectString str(request[2]); |
| + int64_t total_bytes_written = |
| + file->Write(reinterpret_cast<const void*>(str.CString()), |
|
Mads Ager (google)
2012/02/20 13:50:31
Might be more readable to do the casting on a line
Søren Gjesse
2012/02/21 14:22:39
Done.
|
| + str.Length()); |
| + ASSERT(total_bytes_written == str.Length()); |
| + return new CObjectInt64(CObject::NewInt64(total_bytes_written)); |
| + } |
| + return CObject::Null(); |
| +} |
| + |
| + |
| +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::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::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; |
| + case File::kWriteStringRequest: |
| + response = FileWriteStringRequest(request); |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + } |
| + } |
| + } |
| + |
| + Dart_PostCObject(reply_port_id, response->AsApiCObject()); |
| +} |
| + |
| + |
| +void FUNCTION_NAME(File_NewServicePort)(Dart_NativeArguments args) { |
| + Dart_EnterScope(); |
| + Dart_SetReturnValue(args, Dart_Null()); |
| + Dart_Port service_port = kIllegalPort; |
| + service_port = Dart_NewNativePort("FileService", |
|
Mads Ager (google)
2012/02/20 13:50:31
Are there two spaces after '=' here?
Søren Gjesse
2012/02/21 14:22:39
Yes, removed one.
|
| + FileService, |
| + true); |
| + if (service_port != kIllegalPort) { |
| + // Return a send port for the service port. |
| + Dart_Handle send_port = Dart_NewSendPort(service_port); |
| + Dart_SetReturnValue(args, send_port); |
| + } |
| + Dart_ExitScope(); |
| +} |