This Trac instance is not used for development anymore!

We migrated our development workflow to git and Gitea.
To test the future redirection, replace trac by ariadne in the page URL.

Changeset 354 for ps


Ignore:
Timestamp:
06/02/04 17:32:42 (21 years ago)
Author:
janwas
Message:

fixed tree_lookup - now allows dir names (with optional trailing slash)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • ps/trunk/source/lib/res/vfs.cpp

    r334 r354  
    217217//   memory allocations / no need to free them.
    218218//
    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
     221typedef std::map<const std::string, const FileLoc*> Files;
    222222typedef Files::iterator FileIt;
    223223    // notes:
     
    235235struct Dir
    236236{
    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);
    242242
    243243    void clearR();
     
    248248
    249249
    250 int Dir::subdir_add(const char* const fn)
    251 {
    252     if(file_find(fn) || subdir_find(fn))
     250int Dir::add_subdir(const char* const fn)
     251{
     252    if(find_file(fn) || find_subdir(fn))
    253253    {
    254254        debug_warn("dir_add: file or subdirectory of same name already exists");
     
    263263
    264264
    265 Dir* Dir::subdir_find(const char* const fn)
     265Dir* Dir::find_subdir(const char* const fn)
    266266{
    267267    SubDirIt it = subdirs.find(fn);
     
    272272
    273273
    274 int Dir::file_add(const char* const fn, const FileLoc* const loc)
    275 {
    276     if(subdir_find(fn))
     274int Dir::add_file(const char* const fn, const FileLoc* const loc)
     275{
     276    if(find_subdir(fn))
    277277    {
    278278        debug_warn("dir_add: file of same name already exists");
     
    282282    // default pointer ctor sets it to 0 =>
    283283    // 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];
    285289    // old loc exists and is higher priority - keep it.
    286290    if(old_loc && old_loc->pri > loc->pri)
     
    292296
    293297
    294 FileLoc* Dir::file_find(const char* const fn)
     298const FileLoc* Dir::find_file(const char* const fn)
    295299{
    296300    FileIt it = files.find(fn);
     
    323327{
    324328    LF_DEFAULT                   = 0,
    325     LF_CREATE_MISSING_COMPONENTS = 1
     329
     330    LF_CREATE_MISSING_COMPONENTS = 1,
     331
     332    LF_LAST                      = 2
    326333};
    327334
    328335
    329336// 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 '/'.
    331338static int tree_lookup(const char* path, const FileLoc** const loc = 0, Dir** const dir = 0, LookupFlags flags = LF_DEFAULT)
    332339{
    333340    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;
    334345
    335346    // 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.
    338348    char buf[VFS_MAX_PATH];
    339349    strcpy(buf, path);
     350
     351    Dir* cur_dir = &vfs_root;
    340352    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>.
    347370    for(;;)
    348371    {
     372        // "extract" cur_component string (0-terminate by replacing '/')
    349373        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)
    352378            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)
    358382        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);
    363387        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.
    365396
    366397        // next component
    367         cur_dir = subdir;
     398        if(is_last_component)
     399            break;
    368400        cur_component = slash+1;
    369401    }
    370402
    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)
    374404    if(loc)
    375405    {
    376         *loc = cur_dir->file_find(cur_component);
     406        *loc = cur_dir->find_file(cur_component);
    377407        // .. but the file doesn't exist
    378408        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.
    382416    if(dir)
    383417        *dir = cur_dir;
     418
    384419    return 0;
    385420}
     
    397432{
    398433    Dir* const dir;
    399     const FileLoc* loc;
     434    const FileLoc* const loc;
     435    FileCBParams(Dir* _dir, const FileLoc* _loc)
     436        : dir(_dir), loc(_loc) {}
    400437};
    401438
     
    414451{
    415452    const FileCBParams* const params = (FileCBParams*)user;
    416     Dir* const cur_dir = params->dir;
     453    Dir* const cur_dir           = params->dir;
    417454    const FileLoc* const cur_loc = params->loc;
    418455
     
    421458    // directory
    422459    if(flags & LOC_DIR)
    423         err = cur_dir->subdir_add(fn);
     460        err = cur_dir->add_subdir(fn);
    424461    // file
    425462    else
    426         err = cur_dir->file_add(fn, cur_loc);
     463        err = cur_dir->add_file(fn, cur_loc);
    427464
    428465    if(err < 0)
     
    437474
    438475    // add files and subdirs to vdir
    439     const FileCBParams params = { dir, loc };
     476    const FileCBParams params(dir, loc);
    440477    file_enum(f_path, add_dirent_cb, (uintptr_t)&params);
    441478
     
    459496    if(loc->archive > 0)
    460497    {
    461         FileCBParams params = { dir, loc };
     498        const FileCBParams params(dir, loc);
    462499        return zip_enum(loc->archive, add_dirent_cb, (uintptr_t)&params);
    463500    }
     
    480517// (we keep and pass around pointers to Mount.archive_locs elements)
    481518// see below.
     519//
     520// not const, because we h_free a handle in FileLoc
     521// (it resets the handle to 0)
    482522typedef std::list<FileLoc> Locs;
    483523typedef Locs::iterator LocIt;
     
    511551    Mount(const char* _v_path, const char* _f_name, uint _pri)
    512552        : 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)
    514554    {
    515555    }
     
    583623    const char* const f_name = m.f_name.c_str();
    584624    const uint pri           = m.pri;
    585     FileLoc& dir_loc         = m.dir_loc;
     625    const FileLoc& dir_loc   = m.dir_loc;
    586626    Locs& archive_locs       = m.archive_locs;
    587627
     
    610650    }
    611651
    612 
    613     dir_loc.dir = f_name;
    614652    err = tree_add_loc(dir, &dir_loc);
    615653    if(err < 0)
Note: See TracChangeset for help on using the changeset viewer.