- Timestamp:
- 06/02/04 17:32:42 (21 years ago)
- File:
-
- 1 edited
-
ps/trunk/source/lib/res/vfs.cpp (modified) (17 diffs)
Legend:
- Unmodified
- Added
- Removed
-
ps/trunk/source/lib/res/vfs.cpp
r334 r354 217 217 // memory allocations / no need to free them. 218 218 // 219 // *_add guard against a subdir and file of the same name.220 221 typedef std::map<const std::string, FileLoc*> Files;219 // add_* aborts if a subdir or file of the same name already exists. 220 221 typedef std::map<const std::string, const FileLoc*> Files; 222 222 typedef Files::iterator FileIt; 223 223 // notes: … … 235 235 struct Dir 236 236 { 237 int file_add(const char* name, const FileLoc* loc);238 FileLoc* file_find(const char* name);239 240 int subdir_add(const char* name);241 Dir* subdir_find(const char* name);237 int add_file(const char* name, const FileLoc* loc); 238 const FileLoc* find_file(const char* name); 239 240 int add_subdir(const char* name); 241 Dir* find_subdir(const char* name); 242 242 243 243 void clearR(); … … 248 248 249 249 250 int Dir:: subdir_add(const char* const fn)251 { 252 if(fi le_find(fn) || subdir_find(fn))250 int Dir::add_subdir(const char* const fn) 251 { 252 if(find_file(fn) || find_subdir(fn)) 253 253 { 254 254 debug_warn("dir_add: file or subdirectory of same name already exists"); … … 263 263 264 264 265 Dir* Dir:: subdir_find(const char* const fn)265 Dir* Dir::find_subdir(const char* const fn) 266 266 { 267 267 SubDirIt it = subdirs.find(fn); … … 272 272 273 273 274 int Dir:: file_add(const char* const fn, const FileLoc* const loc)275 { 276 if( subdir_find(fn))274 int Dir::add_file(const char* const fn, const FileLoc* const loc) 275 { 276 if(find_subdir(fn)) 277 277 { 278 278 debug_warn("dir_add: file of same name already exists"); … … 282 282 // default pointer ctor sets it to 0 => 283 283 // if fn wasn't already in the container, old_loc is 0. 284 const FileLoc*& old_loc = files[fn]; 284 typedef const FileLoc* Data; 285 // for absolute clarity; the container holds const FileLoc* objects. 286 // operator[] returns a reference to that. 287 // need this typedef to work around a GCC bug? 288 Data& old_loc = files[fn]; 285 289 // old loc exists and is higher priority - keep it. 286 290 if(old_loc && old_loc->pri > loc->pri) … … 292 296 293 297 294 FileLoc* Dir::file_find(const char* const fn)298 const FileLoc* Dir::find_file(const char* const fn) 295 299 { 296 300 FileIt it = files.find(fn); … … 323 327 { 324 328 LF_DEFAULT = 0, 325 LF_CREATE_MISSING_COMPONENTS = 1 329 330 LF_CREATE_MISSING_COMPONENTS = 1, 331 332 LF_LAST = 2 326 333 }; 327 334 328 335 329 336 // starts in VFS root directory (path = ""). 330 // path doesn't need to, and shouldn't, start with'/'.337 // path may specify a file or directory; it need not end in '/'. 331 338 static int tree_lookup(const char* path, const FileLoc** const loc = 0, Dir** const dir = 0, LookupFlags flags = LF_DEFAULT) 332 339 { 333 340 CHECK_PATH(path); 341 assert(loc != 0 || dir != 0); 342 assert(flags < LF_LAST); 343 344 const bool create_missing_components = flags & LF_CREATE_MISSING_COMPONENTS; 334 345 335 346 // copy into (writeable) buffer so we can 'tokenize' path components 336 // by replacing '/' with '\0'. 337 // note: CHECK_PATH does length checking 347 // by replacing '/' with '\0'. length check done by CHECK_PATH. 338 348 char buf[VFS_MAX_PATH]; 339 349 strcpy(buf, path); 350 351 Dir* cur_dir = &vfs_root; 340 352 const char* cur_component = buf; 341 342 const bool create_missing_components = flags & LF_CREATE_MISSING_COMPONENTS; 343 344 Dir* cur_dir = &vfs_root; 345 346 // for each path component: 353 bool is_last_component = false; 354 355 // subdirectory traverse logic 356 // valid: 357 // "" (root dir), 358 // "*file", 359 // "*dir[/]" 360 // invalid: 361 // "/*" (caught by CHECK_PATH), 362 // "*file/*" (subdir switch will fail) 363 // 364 // a bit tricky: make sure we go through the directory checks for the 365 // last component - it may either be a file or directory name. 366 // we don't require a trailing '/' for dir names because appending it 367 // to a given dir name would be more (unnecessary) work for the caller. 368 369 // successively navigate to the next subdirectory in <path>. 347 370 for(;;) 348 371 { 372 // "extract" cur_component string (0-terminate by replacing '/') 349 373 char* slash = strchr(cur_component, '/'); 350 // done, cur_component is the filename or "" if <path> is a directory 351 if(!slash) 374 if(slash) 375 *slash = 0; 376 // allow root dir ("") and trailing '/' if looking up a dir 377 if(*cur_component == '\0' && loc == 0) 352 378 break; 353 *slash = 0; // 0-terminate cur_component 354 const char* subdir_name = cur_component; 355 356 // create <subdir_name> 357 // (note: no-op if it already exists 379 is_last_component = (slash == 0); 380 381 // create <cur_component> subdir (no-op if it already exists) 358 382 if(create_missing_components) 359 cur_dir-> subdir_add(subdir_name);360 361 // switch to < subdir_name>362 Dir* subdir = cur_dir-> subdir_find(subdir_name);383 cur_dir->add_subdir(cur_component); 384 385 // switch to <cur_component> 386 Dir* subdir = cur_dir->find_subdir(cur_component); 363 387 if(!subdir) 364 return ERR_PATH_NOT_FOUND; 388 { 389 // this last component is a filename. 390 if(is_last_component && loc != 0) 391 break; 392 // otherwise, we had an (invalid) subdir name - fail. 393 return -ENOENT; 394 } 395 cur_dir = subdir; // don't assign if invalid - need cur_dir below. 365 396 366 397 // next component 367 cur_dir = subdir; 398 if(is_last_component) 399 break; 368 400 cur_component = slash+1; 369 401 } 370 402 371 // we have followed all path components. 372 373 // caller wants pointer to file location returned 403 // caller wants a file (possibly in addition to its dir) 374 404 if(loc) 375 405 { 376 *loc = cur_dir->fi le_find(cur_component);406 *loc = cur_dir->find_file(cur_component); 377 407 // .. but the file doesn't exist 378 408 if(!*loc) 379 return ERR_FILE_NOT_FOUND; 380 } 381 // caller wants pointer to this dir returned 409 return -ENOENT; 410 } 411 412 // if loc != 0, we know cur_dir is correct, because it contains 413 // the desired file (otherwise, the find_file above will have failed). 414 // if loc == 0, path is a dir name, and we have successfully traversed 415 // all path components (subdirectories) in the loop. 382 416 if(dir) 383 417 *dir = cur_dir; 418 384 419 return 0; 385 420 } … … 397 432 { 398 433 Dir* const dir; 399 const FileLoc* loc; 434 const FileLoc* const loc; 435 FileCBParams(Dir* _dir, const FileLoc* _loc) 436 : dir(_dir), loc(_loc) {} 400 437 }; 401 438 … … 414 451 { 415 452 const FileCBParams* const params = (FileCBParams*)user; 416 Dir* const cur_dir = params->dir;453 Dir* const cur_dir = params->dir; 417 454 const FileLoc* const cur_loc = params->loc; 418 455 … … 421 458 // directory 422 459 if(flags & LOC_DIR) 423 err = cur_dir-> subdir_add(fn);460 err = cur_dir->add_subdir(fn); 424 461 // file 425 462 else 426 err = cur_dir-> file_add(fn, cur_loc);463 err = cur_dir->add_file(fn, cur_loc); 427 464 428 465 if(err < 0) … … 437 474 438 475 // add files and subdirs to vdir 439 const FileCBParams params = { dir, loc };476 const FileCBParams params(dir, loc); 440 477 file_enum(f_path, add_dirent_cb, (uintptr_t)¶ms); 441 478 … … 459 496 if(loc->archive > 0) 460 497 { 461 FileCBParams params = { dir, loc };498 const FileCBParams params(dir, loc); 462 499 return zip_enum(loc->archive, add_dirent_cb, (uintptr_t)¶ms); 463 500 } … … 480 517 // (we keep and pass around pointers to Mount.archive_locs elements) 481 518 // see below. 519 // 520 // not const, because we h_free a handle in FileLoc 521 // (it resets the handle to 0) 482 522 typedef std::list<FileLoc> Locs; 483 523 typedef Locs::iterator LocIt; … … 511 551 Mount(const char* _v_path, const char* _f_name, uint _pri) 512 552 : v_path(_v_path), f_name(_f_name), pri(_pri), 513 dir_loc(0, "", 0), archive_locs(), is_single_archive(false)553 dir_loc(0, _f_name, 0), archive_locs(), is_single_archive(false) 514 554 { 515 555 } … … 583 623 const char* const f_name = m.f_name.c_str(); 584 624 const uint pri = m.pri; 585 FileLoc& dir_loc= m.dir_loc;625 const FileLoc& dir_loc = m.dir_loc; 586 626 Locs& archive_locs = m.archive_locs; 587 627 … … 610 650 } 611 651 612 613 dir_loc.dir = f_name;614 652 err = tree_add_loc(dir, &dir_loc); 615 653 if(err < 0)
Note:
See TracChangeset
for help on using the changeset viewer.
