started vfs enumerate directory support, not finished or functional
This was SVN commit r292.
This commit is contained in:
parent
246662f01f
commit
1c5a2d8f10
@ -406,10 +406,9 @@ Handle h_alloc(H_Type type, const char* fn, uint flags, ...)
|
|||||||
|
|
||||||
if(key)
|
if(key)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
// object already loaded?
|
// object already loaded?
|
||||||
Handle h = h_find(type, key);
|
Handle h = h_find(type, key);
|
||||||
if(h)
|
if(h > 0)
|
||||||
{
|
{
|
||||||
hd = h_data(h, type);
|
hd = h_data(h, type);
|
||||||
if(hd->refs == REF_MAX)
|
if(hd->refs == REF_MAX)
|
||||||
@ -421,7 +420,6 @@ Handle h_alloc(H_Type type, const char* fn, uint flags, ...)
|
|||||||
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = alloc_idx(idx, hd);
|
err = alloc_idx(idx, hd);
|
||||||
@ -540,6 +538,20 @@ int h_reload(const char* fn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: more efficient search; currently linear
|
||||||
|
Handle h_find(H_Type type, uintptr_t key)
|
||||||
|
{
|
||||||
|
for(i32 i = 0; i < last_in_use; i++)
|
||||||
|
{
|
||||||
|
HDATA* hd = h_data(i);
|
||||||
|
if(hd)
|
||||||
|
if(hd->type == type && hd->key == key)
|
||||||
|
return handle(i, hd->tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int res_cur_scope;
|
int res_cur_scope;
|
||||||
|
@ -169,11 +169,10 @@ enum
|
|||||||
extern Handle h_alloc(H_Type type, const char* fn, uint flags = 0, ...);
|
extern Handle h_alloc(H_Type type, const char* fn, uint flags = 0, ...);
|
||||||
extern int h_free(Handle& h, H_Type type);
|
extern int h_free(Handle& h, H_Type type);
|
||||||
|
|
||||||
/*
|
|
||||||
// find and return a handle by key (typically filename hash)
|
// find and return a handle by key (typically filename hash)
|
||||||
// currently O(n).
|
// currently O(n).
|
||||||
extern Handle h_find(H_Type type, uintptr_t key);
|
extern Handle h_find(H_Type type, uintptr_t key);
|
||||||
*/
|
|
||||||
|
|
||||||
// return a pointer to handle data, or 0 on error
|
// return a pointer to handle data, or 0 on error
|
||||||
extern void* h_user_data(Handle h, H_Type type);
|
extern void* h_user_data(Handle h, H_Type type);
|
||||||
|
@ -693,6 +693,10 @@ static void Tex_dtor(Tex* t)
|
|||||||
|
|
||||||
static int tex_upload(Tex* t, const char* const fn)
|
static int tex_upload(Tex* t, const char* const fn)
|
||||||
{
|
{
|
||||||
|
// someone's requesting upload, but has already been uploaded.
|
||||||
|
// this happens if a cached texture is "loaded". no work to do.
|
||||||
|
if(t->id && t->hm <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
// data we will take from Tex
|
// data we will take from Tex
|
||||||
GLsizei w;
|
GLsizei w;
|
||||||
|
@ -211,9 +211,9 @@ struct Loc
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct VDir;
|
struct TreeDir;
|
||||||
|
|
||||||
typedef std::map<std::string, VDir*> SubDirs;
|
typedef std::map<std::string, TreeDir*> SubDirs;
|
||||||
typedef SubDirs::iterator SubDirIt;
|
typedef SubDirs::iterator SubDirIt;
|
||||||
|
|
||||||
typedef std::map<std::string, const Loc*> Files;
|
typedef std::map<std::string, const Loc*> Files;
|
||||||
@ -223,7 +223,7 @@ typedef Files::iterator FileIt;
|
|||||||
// but it's a bit more clumsy (map filename to struct {pri, Loc*}).
|
// but it's a bit more clumsy (map filename to struct {pri, Loc*}).
|
||||||
// revisit if file lookup open is too slow (unlikely).
|
// revisit if file lookup open is too slow (unlikely).
|
||||||
|
|
||||||
struct VDir
|
struct TreeDir
|
||||||
{
|
{
|
||||||
std::string v_name;
|
std::string v_name;
|
||||||
|
|
||||||
@ -267,13 +267,13 @@ struct VDir
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
VDir* subdir_add(const char* name)
|
TreeDir* subdir_add(const char* name)
|
||||||
{
|
{
|
||||||
VDir* vdir = new VDir;
|
TreeDir* vdir = new TreeDir;
|
||||||
const std::string _name(name);
|
const std::string _name(name);
|
||||||
vdir->v_name = _name;
|
vdir->v_name = _name;
|
||||||
|
|
||||||
std::pair<std::string, VDir*> item = std::make_pair(_name, vdir);
|
std::pair<std::string, TreeDir*> item = std::make_pair(_name, vdir);
|
||||||
std::pair<SubDirIt, bool> res;
|
std::pair<SubDirIt, bool> res;
|
||||||
res = subdirs.insert(item);
|
res = subdirs.insert(item);
|
||||||
// already in container
|
// already in container
|
||||||
@ -284,7 +284,7 @@ struct VDir
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
VDir* subdir_find(const char* name)
|
TreeDir* subdir_find(const char* name)
|
||||||
{
|
{
|
||||||
const std::string _name(name);
|
const std::string _name(name);
|
||||||
SubDirIt it = subdirs.find(_name);
|
SubDirIt it = subdirs.find(_name);
|
||||||
@ -300,7 +300,7 @@ struct VDir
|
|||||||
subdirs.clear();
|
subdirs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
friend void tree_clearR(VDir*);
|
friend void tree_clearR(TreeDir*);
|
||||||
|
|
||||||
SubDirs subdirs; // can't make private; needed for iterator
|
SubDirs subdirs; // can't make private; needed for iterator
|
||||||
Files files;
|
Files files;
|
||||||
@ -312,7 +312,7 @@ private:;
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static VDir vfs_root;
|
static TreeDir vfs_root;
|
||||||
|
|
||||||
|
|
||||||
enum LookupFlags
|
enum LookupFlags
|
||||||
@ -324,7 +324,7 @@ enum LookupFlags
|
|||||||
|
|
||||||
// starts in VFS root directory (path = "").
|
// starts in VFS root directory (path = "").
|
||||||
// path doesn't need to, and shouldn't, start with '/'.
|
// path doesn't need to, and shouldn't, start with '/'.
|
||||||
static int tree_lookup(const char* path, const Loc** const loc = 0, VDir** const dir = 0, LookupFlags flags = LF_DEFAULT)
|
static int tree_lookup(const char* path, const Loc** const loc = 0, TreeDir** const dir = 0, LookupFlags flags = LF_DEFAULT)
|
||||||
{
|
{
|
||||||
CHECK_PATH(path);
|
CHECK_PATH(path);
|
||||||
|
|
||||||
@ -337,7 +337,7 @@ static int tree_lookup(const char* path, const Loc** const loc = 0, VDir** const
|
|||||||
|
|
||||||
const bool create_missing_components = flags & LF_CREATE_MISSING_COMPONENTS;
|
const bool create_missing_components = flags & LF_CREATE_MISSING_COMPONENTS;
|
||||||
|
|
||||||
VDir* cur_dir = &vfs_root;
|
TreeDir* cur_dir = &vfs_root;
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
@ -367,7 +367,7 @@ static int tree_lookup(const char* path, const Loc** const loc = 0, VDir** const
|
|||||||
const char* subdir_name = cur_component;
|
const char* subdir_name = cur_component;
|
||||||
*slash = 0;
|
*slash = 0;
|
||||||
|
|
||||||
VDir* subdir = cur_dir->subdir_find(subdir_name);
|
TreeDir* subdir = cur_dir->subdir_find(subdir_name);
|
||||||
if(!subdir)
|
if(!subdir)
|
||||||
{
|
{
|
||||||
if(create_missing_components)
|
if(create_missing_components)
|
||||||
@ -383,12 +383,12 @@ static int tree_lookup(const char* path, const Loc** const loc = 0, VDir** const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void tree_clearR(VDir* const dir)
|
static void tree_clearR(TreeDir* const dir)
|
||||||
{
|
{
|
||||||
SubDirIt it;
|
SubDirIt it;
|
||||||
for(it = dir->subdirs.begin(); it != dir->subdirs.end(); ++it)
|
for(it = dir->subdirs.begin(); it != dir->subdirs.end(); ++it)
|
||||||
{
|
{
|
||||||
VDir* subdir = it->second;
|
TreeDir* subdir = it->second;
|
||||||
tree_clearR(subdir);
|
tree_clearR(subdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,7 +405,7 @@ static inline void tree_clear()
|
|||||||
|
|
||||||
struct FileCBParams
|
struct FileCBParams
|
||||||
{
|
{
|
||||||
VDir* dir;
|
TreeDir* dir;
|
||||||
const Loc* loc;
|
const Loc* loc;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -423,7 +423,7 @@ struct FileCBParams
|
|||||||
static int add_dirent_cb(const char* const fn, const uint flags, const ssize_t size, const uintptr_t user)
|
static int add_dirent_cb(const char* const fn, const uint flags, const ssize_t size, const uintptr_t user)
|
||||||
{
|
{
|
||||||
const FileCBParams* const params = (FileCBParams*)user;
|
const FileCBParams* const params = (FileCBParams*)user;
|
||||||
VDir* const cur_dir = params->dir;
|
TreeDir* const cur_dir = params->dir;
|
||||||
const Loc* const cur_loc = params->loc;
|
const Loc* const cur_loc = params->loc;
|
||||||
|
|
||||||
// directory
|
// directory
|
||||||
@ -437,7 +437,7 @@ static int add_dirent_cb(const char* const fn, const uint flags, const ssize_t s
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int tree_add_dirR(VDir* const vdir, const char* const f_path, const Loc* const loc)
|
static int tree_add_dirR(TreeDir* const vdir, const char* const f_path, const Loc* const loc)
|
||||||
{
|
{
|
||||||
CHECK_PATH(f_path);
|
CHECK_PATH(f_path);
|
||||||
|
|
||||||
@ -451,7 +451,7 @@ static int tree_add_dirR(VDir* const vdir, const char* const f_path, const Loc*
|
|||||||
|
|
||||||
for(SubDirIt it = vdir->subdirs.begin(); it != vdir->subdirs.end(); ++it)
|
for(SubDirIt it = vdir->subdirs.begin(); it != vdir->subdirs.end(); ++it)
|
||||||
{
|
{
|
||||||
VDir* const vsubdir = it->second;
|
TreeDir* const vsubdir = it->second;
|
||||||
|
|
||||||
char f_subdir_path[VFS_MAX_PATH];
|
char f_subdir_path[VFS_MAX_PATH];
|
||||||
const char* const v_subdir_name_c = vsubdir->v_name.c_str();
|
const char* const v_subdir_name_c = vsubdir->v_name.c_str();
|
||||||
@ -464,7 +464,7 @@ static int tree_add_dirR(VDir* const vdir, const char* const f_path, const Loc*
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int tree_add_loc(VDir* const vdir, const Loc* const loc)
|
static int tree_add_loc(TreeDir* const vdir, const Loc* const loc)
|
||||||
{
|
{
|
||||||
if(loc->archive > 0)
|
if(loc->archive > 0)
|
||||||
{
|
{
|
||||||
@ -595,7 +595,7 @@ static int remount(Mount& m)
|
|||||||
Loc& dir_loc = m.dir_loc;
|
Loc& dir_loc = m.dir_loc;
|
||||||
Locs& archive_locs = m.archive_locs;
|
Locs& archive_locs = m.archive_locs;
|
||||||
|
|
||||||
VDir* vdir;
|
TreeDir* vdir;
|
||||||
CHECK_ERR(tree_lookup(v_path, 0, &vdir, LF_CREATE_MISSING_COMPONENTS));
|
CHECK_ERR(tree_lookup(v_path, 0, &vdir, LF_CREATE_MISSING_COMPONENTS));
|
||||||
|
|
||||||
// check if target is a single Zip archive
|
// check if target is a single Zip archive
|
||||||
@ -668,6 +668,16 @@ int vfs_mount(const char* const vfs_mount_point, const char* const name, const u
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// disallow . because "./" isn't supported on Windows.
|
||||||
|
// the more important reason is that mount points must not overlap
|
||||||
|
// (i.e. mount $install/data and then $install/data/mods/official -
|
||||||
|
// mods/official would also be accessible from the first mount point).
|
||||||
|
if(!strcmp(name, ".") || !strcmp(name, "./"))
|
||||||
|
{
|
||||||
|
debug_warn("vfs_mount: mounting . not allowed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
mounts.push_back(Mount(vfs_mount_point, name, pri));
|
mounts.push_back(Mount(vfs_mount_point, name, pri));
|
||||||
|
|
||||||
// actually mount the entry
|
// actually mount the entry
|
||||||
@ -754,6 +764,75 @@ int vfs_stat(const char* fn, struct stat* s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct VDir
|
||||||
|
{
|
||||||
|
TreeDir* dir;
|
||||||
|
FileIt it;
|
||||||
|
};
|
||||||
|
|
||||||
|
H_TYPE_DEFINE(VDir);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void VDir_init(VDir* vd, va_list args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void VDir_dtor(VDir* vd)
|
||||||
|
{
|
||||||
|
// remove reference to TreeDir, unlock it for further use
|
||||||
|
}
|
||||||
|
|
||||||
|
static int VDir_reload(VDir* vd, const char* path)
|
||||||
|
{
|
||||||
|
// check if actually reloaded, and why it happened?
|
||||||
|
// hmm, if TreeDir changes while handle is open, we are screwed.
|
||||||
|
// need a lock.
|
||||||
|
|
||||||
|
CHECK_ERR(tree_lookup(path, 0, &vd->dir));
|
||||||
|
|
||||||
|
vd->it = vd->dir->files.begin();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle vfs_open_dir(const char* const path)
|
||||||
|
{
|
||||||
|
return h_alloc(H_VDir, path, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vfs_close_dir(Handle& hd)
|
||||||
|
{
|
||||||
|
return h_free(hd, H_VDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vfs_next_dirent(const Handle hd, vfsDirEnt* ent, const char* const filter)
|
||||||
|
{
|
||||||
|
// make sure filter is valid
|
||||||
|
// interpret filter, decide if they want files or subdirs
|
||||||
|
|
||||||
|
// until no more entries, or one matches filter
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
H_DEREF(hd, VDir, vd);
|
||||||
|
if(vd->it == vd->dir->files.end())
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
const std::string& fn_s = vd->it->first;
|
||||||
|
const char* const fn = fn_s.c_str();
|
||||||
|
|
||||||
|
if(filter)
|
||||||
|
{
|
||||||
|
char* ext = strrchr(fn, '.');
|
||||||
|
if(!ext || strcmp(ext, filter) != 0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// found matching entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// file
|
// file
|
||||||
|
@ -44,6 +44,23 @@ extern int vfs_close(Handle& h);
|
|||||||
extern Handle vfs_map(Handle hf, uint flags, void*& p, size_t& size);
|
extern Handle vfs_map(Handle hf, uint flags, void*& p, size_t& size);
|
||||||
|
|
||||||
|
|
||||||
|
struct vfsDirEnt
|
||||||
|
{
|
||||||
|
// the filename is currently stored internally as std::string. returning as char* for C compat
|
||||||
|
// stored internally as std::string. returning as char* for C compat
|
||||||
|
// would mean we have to return a copy. we try to avoid fixed-size
|
||||||
|
// buffers, so that leaves a reference.
|
||||||
|
const char* name;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern Handle vfs_open_dir(const char* path);
|
||||||
|
extern int vfs_close_dir(Handle& hd);
|
||||||
|
extern int vfs_next_dirent(Handle hd, vfsDirEnt* ent, const char* filter);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern int vfs_rebuild();
|
extern int vfs_rebuild();
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user