| Index: runtime/bin/directory.cc
|
| diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc
|
| index 6ca4ac0b4b6bd169989b3b6d19a57cd59a1ccb57..6dd4406aa0be5368c30d050bb0cceb884f789586 100644
|
| --- a/runtime/bin/directory.cc
|
| +++ b/runtime/bin/directory.cc
|
| @@ -150,11 +150,11 @@ void FUNCTION_NAME(Directory_List)(Dart_NativeArguments args) {
|
| Dart_Null(),
|
| 0,
|
| NULL);
|
| - SyncDirectoryListing sync_listing(results);
|
| - Directory::List(DartUtils::GetStringValue(path),
|
| - DartUtils::GetBooleanValue(recursive),
|
| - DartUtils::GetBooleanValue(follow_links),
|
| - &sync_listing);
|
| + SyncDirectoryListing sync_listing(results,
|
| + DartUtils::GetStringValue(path),
|
| + DartUtils::GetBooleanValue(recursive),
|
| + DartUtils::GetBooleanValue(follow_links));
|
| + Directory::List(&sync_listing);
|
| Dart_SetReturnValue(args, results);
|
| Dart_ExitScope();
|
| }
|
| @@ -220,41 +220,64 @@ static CObject* DirectoryCreateTempRequest(const CObjectArray& request) {
|
| return CObject::IllegalArgumentError();
|
| }
|
|
|
| +static CObject* CreateIllegalArgumentError() {
|
| + // Respond with an illegal argument list error message.
|
| + CObjectArray* error = new CObjectArray(CObject::NewArray(3));
|
| + error->SetAt(0, new CObjectInt32(
|
| + CObject::NewInt32(AsyncDirectoryListing::kListError)));
|
| + error->SetAt(1, CObject::Null());
|
| + error->SetAt(2, CObject::IllegalArgumentError());
|
| + return error;
|
| +}
|
|
|
| -static CObject* DirectoryListRequest(const CObjectArray& request,
|
| - Dart_Port response_port) {
|
| +static CObject* DirectoryListStartRequest(const CObjectArray& request) {
|
| if (request.Length() == 4 &&
|
| request[1]->IsString() &&
|
| request[2]->IsBool() &&
|
| request[3]->IsBool()) {
|
| - AsyncDirectoryListing* dir_listing =
|
| - new AsyncDirectoryListing(response_port);
|
| CObjectString path(request[1]);
|
| CObjectBool recursive(request[2]);
|
| CObjectBool follow_links(request[3]);
|
| - bool completed = Directory::List(
|
| - path.CString(), recursive.Value(), follow_links.Value(), dir_listing);
|
| - delete dir_listing;
|
| - CObjectArray* response = new CObjectArray(CObject::NewArray(2));
|
| - response->SetAt(
|
| - 0,
|
| - new CObjectInt32(CObject::NewInt32(AsyncDirectoryListing::kListDone)));
|
| - response->SetAt(1, CObject::Bool(completed));
|
| + AsyncDirectoryListing* dir_listing =
|
| + new AsyncDirectoryListing(path.CString(),
|
| + recursive.Value(),
|
| + follow_links.Value());
|
| + // TODO(ajohnsen): Consider returning the first few results.
|
| + return new CObjectIntptr(CObject::NewIntptr(
|
| + reinterpret_cast<intptr_t>(dir_listing)));
|
| + }
|
| + return CreateIllegalArgumentError();
|
| +}
|
| +
|
| +
|
| +static CObject* DirectoryListNextRequest(const CObjectArray& request) {
|
| + if (request.Length() == 2 &&
|
| + request[1]->IsIntptr()) {
|
| + CObjectIntptr ptr(request[1]);
|
| + AsyncDirectoryListing* dir_listing =
|
| + reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
|
| + const int kArraySize = 128;
|
| + CObjectArray* response = new CObjectArray(CObject::NewArray(kArraySize));
|
| + dir_listing->SetArray(response, kArraySize);
|
| + Directory::List(dir_listing);
|
| + // In case the listing ended before it hit the buffer length, we need to
|
| + // override the array length.
|
| + response->AsApiCObject()->value.as_array.length = dir_listing->index();
|
| return response;
|
| }
|
| - // Respond with an illegal argument list error message.
|
| - CObjectArray* response = new CObjectArray(CObject::NewArray(3));
|
| - response->SetAt(0, new CObjectInt32(
|
| - CObject::NewInt32(AsyncDirectoryListing::kListError)));
|
| - response->SetAt(1, CObject::Null());
|
| - response->SetAt(2, CObject::IllegalArgumentError());
|
| - Dart_PostCObject(response_port, response->AsApiCObject());
|
| + return CreateIllegalArgumentError();
|
| +}
|
|
|
| - response = new CObjectArray(CObject::NewArray(2));
|
| - response->SetAt(
|
| - 0, new CObjectInt32(CObject::NewInt32(AsyncDirectoryListing::kListDone)));
|
| - response->SetAt(1, CObject::False());
|
| - return response;
|
| +
|
| +static CObject* DirectoryListStopRequest(const CObjectArray& request) {
|
| + if (request.Length() == 2 && request[1]->IsIntptr()) {
|
| + CObjectIntptr ptr(request[1]);
|
| + AsyncDirectoryListing* dir_listing =
|
| + reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
|
| + delete dir_listing;
|
| + return new CObjectBool(CObject::Bool(true));
|
| + }
|
| + return CreateIllegalArgumentError();
|
| }
|
|
|
|
|
| @@ -294,8 +317,14 @@ static void DirectoryService(Dart_Port dest_port_id,
|
| case Directory::kCreateTempRequest:
|
| response = DirectoryCreateTempRequest(request);
|
| break;
|
| - case Directory::kListRequest:
|
| - response = DirectoryListRequest(request, reply_port_id);
|
| + case Directory::kListStartRequest:
|
| + response = DirectoryListStartRequest(request);
|
| + break;
|
| + case Directory::kListNextRequest:
|
| + response = DirectoryListNextRequest(request);
|
| + break;
|
| + case Directory::kListStopRequest:
|
| + response = DirectoryListStopRequest(request);
|
| break;
|
| case Directory::kRenameRequest:
|
| response = DirectoryRenameRequest(request, reply_port_id);
|
| @@ -328,39 +357,46 @@ void FUNCTION_NAME(Directory_NewServicePort)(Dart_NativeArguments args) {
|
| }
|
|
|
|
|
| -CObjectArray* AsyncDirectoryListing::NewResponse(Response type, char* arg) {
|
| - CObjectArray* response = new CObjectArray(CObject::NewArray(2));
|
| - response->SetAt(0, new CObjectInt32(CObject::NewInt32(type)));
|
| - response->SetAt(1, new CObjectString(CObject::NewString(arg)));
|
| - return response;
|
| +bool AsyncDirectoryListing::AddFileSystemEntityToResponse(Response type,
|
| + char* arg) {
|
| + array_->SetAt(index_++, new CObjectInt32(CObject::NewInt32(type)));
|
| + if (arg != NULL) {
|
| + array_->SetAt(index_++, new CObjectString(CObject::NewString(arg)));
|
| + } else {
|
| + array_->SetAt(index_++, CObject::Null());
|
| + }
|
| + return index_ < length_;
|
| }
|
|
|
|
|
| bool AsyncDirectoryListing::HandleDirectory(char* dir_name) {
|
| - CObjectArray* response = NewResponse(kListDirectory, dir_name);
|
| - return Dart_PostCObject(response_port_, response->AsApiCObject());
|
| + return AddFileSystemEntityToResponse(kListDirectory, dir_name);
|
| }
|
|
|
|
|
| bool AsyncDirectoryListing::HandleFile(char* file_name) {
|
| - CObjectArray* response = NewResponse(kListFile, file_name);
|
| - return Dart_PostCObject(response_port_, response->AsApiCObject());
|
| + return AddFileSystemEntityToResponse(kListFile, file_name);
|
| }
|
|
|
|
|
| bool AsyncDirectoryListing::HandleLink(char* link_name) {
|
| - CObjectArray* response = NewResponse(kListLink, link_name);
|
| - return Dart_PostCObject(response_port_, response->AsApiCObject());
|
| + return AddFileSystemEntityToResponse(kListLink, link_name);
|
| +}
|
| +
|
| +void AsyncDirectoryListing::HandleDone() {
|
| + AddFileSystemEntityToResponse(kListDone, NULL);
|
| }
|
|
|
|
|
| bool AsyncDirectoryListing::HandleError(const char* dir_name) {
|
| + array_->SetAt(index_++, new CObjectInt32(CObject::NewInt32(kListError)));
|
| CObject* err = CObject::NewOSError();
|
| CObjectArray* response = new CObjectArray(CObject::NewArray(3));
|
| response->SetAt(0, new CObjectInt32(CObject::NewInt32(kListError)));
|
| response->SetAt(1, new CObjectString(CObject::NewString(dir_name)));
|
| response->SetAt(2, err);
|
| - return Dart_PostCObject(response_port_, response->AsApiCObject());
|
| + array_->SetAt(index_++, response);
|
| + return index_ < length_;
|
| }
|
|
|
| bool SyncDirectoryListing::HandleDirectory(char* dir_name) {
|
| @@ -401,5 +437,47 @@ bool SyncDirectoryListing::HandleError(const char* dir_name) {
|
| return true;
|
| }
|
|
|
| +
|
| +static bool ListNext(DirectoryListing* listing) {
|
| + switch (listing->top()->Next(listing)) {
|
| + case kListFile:
|
| + return listing->HandleFile(listing->CurrentPath());
|
| +
|
| + case kListLink:
|
| + return listing->HandleLink(listing->CurrentPath());
|
| +
|
| + case kListDirectory:
|
| + if (listing->recursive()) {
|
| + listing->Push(new DirectoryListingEntry(listing->top()));
|
| + }
|
| + return listing->HandleDirectory(listing->CurrentPath());
|
| +
|
| + case kListError:
|
| + return listing->HandleError(listing->CurrentPath());
|
| +
|
| + case kListDone:
|
| + listing->Pop();
|
| + if (listing->IsEmpty()) {
|
| + listing->HandleDone();
|
| + return false;
|
| + } else {
|
| + return true;
|
| + }
|
| +
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +void Directory::List(DirectoryListing* listing) {
|
| + if (listing->error()) {
|
| + listing->HandleError("Invalid path");
|
| + listing->HandleDone();
|
| + } else {
|
| + while (ListNext(listing)) {}
|
| + }
|
| +}
|
| +
|
| } // namespace bin
|
| } // namespace dart
|
|
|