Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(479)

Side by Side Diff: runtime/bin/directory.cc

Issue 16813006: Make Directory.list pull-based, making it possible to pause, resume and cancel directory listing. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add test and review fixes. Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "bin/directory.h" 5 #include "bin/directory.h"
6 6
7 #include "bin/dartutils.h" 7 #include "bin/dartutils.h"
8 #include "bin/thread.h" 8 #include "bin/thread.h"
9 #include "include/dart_api.h" 9 #include "include/dart_api.h"
10 #include "platform/assert.h" 10 #include "platform/assert.h"
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 // Create the list to hold the directory listing here, and pass it to the 143 // Create the list to hold the directory listing here, and pass it to the
144 // SyncDirectoryListing object, which adds elements to it. 144 // SyncDirectoryListing object, which adds elements to it.
145 Dart_Handle follow_links = Dart_GetNativeArgument(args, 2); 145 Dart_Handle follow_links = Dart_GetNativeArgument(args, 2);
146 // Create the list to hold the directory listing here, and pass it to the 146 // Create the list to hold the directory listing here, and pass it to the
147 // SyncDirectoryListing object, which adds elements to it. 147 // SyncDirectoryListing object, which adds elements to it.
148 Dart_Handle results = 148 Dart_Handle results =
149 Dart_New(DartUtils::GetDartClass(DartUtils::kCoreLibURL, "List"), 149 Dart_New(DartUtils::GetDartClass(DartUtils::kCoreLibURL, "List"),
150 Dart_Null(), 150 Dart_Null(),
151 0, 151 0,
152 NULL); 152 NULL);
153 SyncDirectoryListing sync_listing(results); 153 SyncDirectoryListing sync_listing(results,
154 Directory::List(DartUtils::GetStringValue(path), 154 DartUtils::GetStringValue(path),
155 DartUtils::GetBooleanValue(recursive), 155 DartUtils::GetBooleanValue(recursive),
156 DartUtils::GetBooleanValue(follow_links), 156 DartUtils::GetBooleanValue(follow_links));
157 &sync_listing); 157 Directory::List(&sync_listing);
158 Dart_SetReturnValue(args, results); 158 Dart_SetReturnValue(args, results);
159 Dart_ExitScope(); 159 Dart_ExitScope();
160 } 160 }
161 161
162 162
163 static CObject* DirectoryCreateRequest(const CObjectArray& request) { 163 static CObject* DirectoryCreateRequest(const CObjectArray& request) {
164 if (request.Length() == 2 && request[1]->IsString()) { 164 if (request.Length() == 2 && request[1]->IsString()) {
165 CObjectString path(request[1]); 165 CObjectString path(request[1]);
166 if (Directory::Create(path.CString())) { 166 if (Directory::Create(path.CString())) {
167 return CObject::True(); 167 return CObject::True();
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 free(result); 214 free(result);
215 return temp_dir; 215 return temp_dir;
216 } else { 216 } else {
217 return CObject::NewOSError(); 217 return CObject::NewOSError();
218 } 218 }
219 } 219 }
220 return CObject::IllegalArgumentError(); 220 return CObject::IllegalArgumentError();
221 } 221 }
222 222
223 223
224 static CObject* DirectoryListRequest(const CObjectArray& request, 224 static CObject* DirectoryListStartRequest(const CObjectArray& request) {
225 Dart_Port response_port) {
226 if (request.Length() == 4 && 225 if (request.Length() == 4 &&
227 request[1]->IsString() && 226 request[1]->IsString() &&
228 request[2]->IsBool() && 227 request[2]->IsBool() &&
229 request[3]->IsBool()) { 228 request[3]->IsBool()) {
230 AsyncDirectoryListing* dir_listing =
231 new AsyncDirectoryListing(response_port);
232 CObjectString path(request[1]); 229 CObjectString path(request[1]);
233 CObjectBool recursive(request[2]); 230 CObjectBool recursive(request[2]);
234 CObjectBool follow_links(request[3]); 231 CObjectBool follow_links(request[3]);
235 bool completed = Directory::List( 232 AsyncDirectoryListing* dir_listing =
236 path.CString(), recursive.Value(), follow_links.Value(), dir_listing); 233 new AsyncDirectoryListing(path.CString(),
237 delete dir_listing; 234 recursive.Value(),
238 CObjectArray* response = new CObjectArray(CObject::NewArray(2)); 235 follow_links.Value());
239 response->SetAt( 236 return new CObjectIntptr(CObject::NewIntptr(
240 0, 237 reinterpret_cast<intptr_t>(dir_listing)));
Søren Gjesse 2013/06/17 06:37:47 We should consider piggy-bagging the first next re
Anders Johnsen 2013/06/17 07:27:11 Added todo.
241 new CObjectInt32(CObject::NewInt32(AsyncDirectoryListing::kListDone))); 238 }
242 response->SetAt(1, CObject::Bool(completed)); 239 // Respond with an illegal argument list error message.
Søren Gjesse 2013/06/17 06:37:47 This illegal argument code is duplicated in three
Anders Johnsen 2013/06/17 07:27:11 Done.
240 CObjectArray* response = new CObjectArray(CObject::NewArray(3));
241 response->SetAt(0, new CObjectInt32(
242 CObject::NewInt32(AsyncDirectoryListing::kListError)));
243 response->SetAt(1, CObject::Null());
244 response->SetAt(2, CObject::IllegalArgumentError());
245 return response;
246 }
247
248
249 static CObject* DirectoryListNextRequest(const CObjectArray& request) {
250 if (request.Length() == 2 &&
251 request[1]->IsIntptr()) {
252 CObjectIntptr ptr(request[1]);
253 AsyncDirectoryListing* dir_listing =
254 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
255 const int kArraySize = 128;
256 CObjectArray* response = new CObjectArray(CObject::NewArray(kArraySize));
257 dir_listing->SetArray(response, kArraySize);
258 Directory::List(dir_listing);
Søren Gjesse 2013/06/17 06:37:47 Add a comment here regarding changing the length.
Anders Johnsen 2013/06/17 07:27:11 Done.
259 response->AsApiCObject()->value.as_array.length = dir_listing->index();
243 return response; 260 return response;
244 } 261 }
245 // Respond with an illegal argument list error message. 262 // Respond with an illegal argument list error message.
246 CObjectArray* response = new CObjectArray(CObject::NewArray(3)); 263 CObjectArray* response = new CObjectArray(CObject::NewArray(3));
247 response->SetAt(0, new CObjectInt32( 264 response->SetAt(0, new CObjectInt32(
248 CObject::NewInt32(AsyncDirectoryListing::kListError))); 265 CObject::NewInt32(AsyncDirectoryListing::kListError)));
249 response->SetAt(1, CObject::Null()); 266 response->SetAt(1, CObject::Null());
250 response->SetAt(2, CObject::IllegalArgumentError()); 267 response->SetAt(2, CObject::IllegalArgumentError());
251 Dart_PostCObject(response_port, response->AsApiCObject());
252
253 response = new CObjectArray(CObject::NewArray(2));
254 response->SetAt(
255 0, new CObjectInt32(CObject::NewInt32(AsyncDirectoryListing::kListDone)));
256 response->SetAt(1, CObject::False());
257 return response; 268 return response;
258 } 269 }
259 270
271
272 static CObject* DirectoryListStopRequest(const CObjectArray& request) {
273 if (request.Length() == 2 && request[1]->IsIntptr()) {
274 CObjectIntptr ptr(request[1]);
275 AsyncDirectoryListing* dir_listing =
276 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
277 delete dir_listing;
278 return new CObjectBool(CObject::Bool(true));
279 }
280 // Respond with an illegal argument list error message.
281 CObjectArray* response = new CObjectArray(CObject::NewArray(3));
282 response->SetAt(0, new CObjectInt32(
283 CObject::NewInt32(AsyncDirectoryListing::kListError)));
284 response->SetAt(1, CObject::Null());
285 response->SetAt(2, CObject::IllegalArgumentError());
286 return response;
287 }
288
260 289
261 static CObject* DirectoryRenameRequest(const CObjectArray& request, 290 static CObject* DirectoryRenameRequest(const CObjectArray& request,
262 Dart_Port response_port) { 291 Dart_Port response_port) {
263 if (request.Length() == 3 && 292 if (request.Length() == 3 &&
264 request[1]->IsString() && 293 request[1]->IsString() &&
265 request[2]->IsString()) { 294 request[2]->IsString()) {
266 CObjectString path(request[1]); 295 CObjectString path(request[1]);
267 CObjectString new_path(request[2]); 296 CObjectString new_path(request[2]);
268 bool completed = Directory::Rename(path.CString(), new_path.CString()); 297 bool completed = Directory::Rename(path.CString(), new_path.CString());
269 if (completed) return CObject::True(); 298 if (completed) return CObject::True();
(...skipping 17 matching lines...) Expand all
287 break; 316 break;
288 case Directory::kDeleteRequest: 317 case Directory::kDeleteRequest:
289 response = DirectoryDeleteRequest(request); 318 response = DirectoryDeleteRequest(request);
290 break; 319 break;
291 case Directory::kExistsRequest: 320 case Directory::kExistsRequest:
292 response = DirectoryExistsRequest(request); 321 response = DirectoryExistsRequest(request);
293 break; 322 break;
294 case Directory::kCreateTempRequest: 323 case Directory::kCreateTempRequest:
295 response = DirectoryCreateTempRequest(request); 324 response = DirectoryCreateTempRequest(request);
296 break; 325 break;
297 case Directory::kListRequest: 326 case Directory::kListStartRequest:
298 response = DirectoryListRequest(request, reply_port_id); 327 response = DirectoryListStartRequest(request);
328 break;
329 case Directory::kListNextRequest:
330 response = DirectoryListNextRequest(request);
331 break;
332 case Directory::kListStopRequest:
333 response = DirectoryListStopRequest(request);
299 break; 334 break;
300 case Directory::kRenameRequest: 335 case Directory::kRenameRequest:
301 response = DirectoryRenameRequest(request, reply_port_id); 336 response = DirectoryRenameRequest(request, reply_port_id);
302 break; 337 break;
303 default: 338 default:
304 UNREACHABLE(); 339 UNREACHABLE();
305 } 340 }
306 } 341 }
307 } 342 }
308 343
(...skipping 12 matching lines...) Expand all
321 Dart_Port service_port = Directory::GetServicePort(); 356 Dart_Port service_port = Directory::GetServicePort();
322 if (service_port != ILLEGAL_PORT) { 357 if (service_port != ILLEGAL_PORT) {
323 // Return a send port for the service port. 358 // Return a send port for the service port.
324 Dart_Handle send_port = Dart_NewSendPort(service_port); 359 Dart_Handle send_port = Dart_NewSendPort(service_port);
325 Dart_SetReturnValue(args, send_port); 360 Dart_SetReturnValue(args, send_port);
326 } 361 }
327 Dart_ExitScope(); 362 Dart_ExitScope();
328 } 363 }
329 364
330 365
331 CObjectArray* AsyncDirectoryListing::NewResponse(Response type, char* arg) { 366 bool AsyncDirectoryListing::AddFileSystemEntityToResponse(Response type,
332 CObjectArray* response = new CObjectArray(CObject::NewArray(2)); 367 char* arg) {
333 response->SetAt(0, new CObjectInt32(CObject::NewInt32(type))); 368 array_->SetAt(index_++, new CObjectInt32(CObject::NewInt32(type)));
334 response->SetAt(1, new CObjectString(CObject::NewString(arg))); 369 if (arg != NULL) {
335 return response; 370 array_->SetAt(index_++, new CObjectString(CObject::NewString(arg)));
371 } else {
372 array_->SetAt(index_++, CObject::Null());
373 }
374 return index_ < length_;
336 } 375 }
337 376
338 377
339 bool AsyncDirectoryListing::HandleDirectory(char* dir_name) { 378 bool AsyncDirectoryListing::HandleDirectory(char* dir_name) {
340 CObjectArray* response = NewResponse(kListDirectory, dir_name); 379 return AddFileSystemEntityToResponse(kListDirectory, dir_name);
341 return Dart_PostCObject(response_port_, response->AsApiCObject());
342 } 380 }
343 381
344 382
345 bool AsyncDirectoryListing::HandleFile(char* file_name) { 383 bool AsyncDirectoryListing::HandleFile(char* file_name) {
346 CObjectArray* response = NewResponse(kListFile, file_name); 384 return AddFileSystemEntityToResponse(kListFile, file_name);
347 return Dart_PostCObject(response_port_, response->AsApiCObject());
348 } 385 }
349 386
350 387
351 bool AsyncDirectoryListing::HandleLink(char* link_name) { 388 bool AsyncDirectoryListing::HandleLink(char* link_name) {
352 CObjectArray* response = NewResponse(kListLink, link_name); 389 return AddFileSystemEntityToResponse(kListLink, link_name);
353 return Dart_PostCObject(response_port_, response->AsApiCObject()); 390 }
391
392 void AsyncDirectoryListing::HandleDone() {
393 AddFileSystemEntityToResponse(kListDone, NULL);
354 } 394 }
355 395
356 396
357 bool AsyncDirectoryListing::HandleError(const char* dir_name) { 397 bool AsyncDirectoryListing::HandleError(const char* dir_name) {
398 array_->SetAt(index_++, new CObjectInt32(CObject::NewInt32(kListError)));
358 CObject* err = CObject::NewOSError(); 399 CObject* err = CObject::NewOSError();
359 CObjectArray* response = new CObjectArray(CObject::NewArray(3)); 400 CObjectArray* response = new CObjectArray(CObject::NewArray(3));
360 response->SetAt(0, new CObjectInt32(CObject::NewInt32(kListError))); 401 response->SetAt(0, new CObjectInt32(CObject::NewInt32(kListError)));
361 response->SetAt(1, new CObjectString(CObject::NewString(dir_name))); 402 response->SetAt(1, new CObjectString(CObject::NewString(dir_name)));
362 response->SetAt(2, err); 403 response->SetAt(2, err);
363 return Dart_PostCObject(response_port_, response->AsApiCObject()); 404 array_->SetAt(index_++, response);
405 return index_ < length_;
364 } 406 }
365 407
366 bool SyncDirectoryListing::HandleDirectory(char* dir_name) { 408 bool SyncDirectoryListing::HandleDirectory(char* dir_name) {
367 Dart_Handle dir_name_dart = DartUtils::NewString(dir_name); 409 Dart_Handle dir_name_dart = DartUtils::NewString(dir_name);
368 Dart_Handle dir = 410 Dart_Handle dir =
369 Dart_New(directory_class_, Dart_Null(), 1, &dir_name_dart); 411 Dart_New(directory_class_, Dart_Null(), 1, &dir_name_dart);
370 Dart_Invoke(results_, add_string_, 1, &dir); 412 Dart_Invoke(results_, add_string_, 1, &dir);
371 return true; 413 return true;
372 } 414 }
373 415
(...skipping 20 matching lines...) Expand all
394 args[1] = DartUtils::NewString(dir_name); 436 args[1] = DartUtils::NewString(dir_name);
395 args[2] = dart_os_error; 437 args[2] = dart_os_error;
396 Dart_ThrowException(Dart_New( 438 Dart_ThrowException(Dart_New(
397 DartUtils::GetDartClass(DartUtils::kIOLibURL, "DirectoryException"), 439 DartUtils::GetDartClass(DartUtils::kIOLibURL, "DirectoryException"),
398 Dart_Null(), 440 Dart_Null(),
399 3, 441 3,
400 args)); 442 args));
401 return true; 443 return true;
402 } 444 }
403 445
446
447 static bool ListNext(DirectoryListing* listing) {
448 switch (listing->top()->Next(listing)) {
449 case kListFile:
450 return listing->HandleFile(listing->CurrentPath());
451
452 case kListLink:
453 return listing->HandleLink(listing->CurrentPath());
454
455 case kListDirectory:
456 if (listing->recursive()) {
457 listing->Push(new DirectoryListingEntry(listing->top()));
458 }
459 return listing->HandleDirectory(listing->CurrentPath());
460
461 case kListError:
462 return listing->HandleError(listing->CurrentPath());
463
464 case kListDone:
465 listing->Pop();
466 if (listing->IsEmpty()) {
467 listing->HandleDone();
468 return false;
469 } else {
470 return true;
471 }
472
473 default:
474 UNREACHABLE();
475 }
476 return false;
477 }
478
479 void Directory::List(DirectoryListing* listing) {
480 if (listing->error()) {
481 listing->HandleError("Invalid path");
482 listing->HandleDone();
483 } else {
484 while (ListNext(listing)) {}
485 }
486 }
487
404 } // namespace bin 488 } // namespace bin
405 } // namespace dart 489 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698