mirror of
https://github.com/dhewm/dhewm3.git
synced 2024-11-30 16:11:11 +00:00
214 lines
6.8 KiB
Diff
214 lines
6.8 KiB
Diff
|
Index: framework/FileSystem.cpp
|
||
|
===================================================================
|
||
|
--- framework/FileSystem.cpp (revision 528)
|
||
|
+++ framework/FileSystem.cpp (working copy)
|
||
|
@@ -159,7 +159,7 @@
|
||
|
};
|
||
|
|
||
|
// 3 search patch (fs_savepath fs_basepath fs_cdpath)
|
||
|
-// .jpg then .tga for
|
||
|
+// often .jpg and .tga patterns
|
||
|
#define MAX_CACHED_DIRS 6
|
||
|
|
||
|
class idDEntry : public idStrList {
|
||
|
@@ -173,6 +173,11 @@
|
||
|
void Init(const char *directory, const char *extension, const idStrList &list );
|
||
|
};
|
||
|
|
||
|
+typedef struct {
|
||
|
+ idStr path;
|
||
|
+ idStr OSpath;
|
||
|
+} casematch_t;
|
||
|
+
|
||
|
class idFileSystem_local : public idFileSystem {
|
||
|
public:
|
||
|
idFileSystem_local( void );
|
||
|
@@ -227,11 +232,14 @@
|
||
|
int numServerPaks;
|
||
|
int serverPaks[MAX_SEARCH_PATHS];
|
||
|
|
||
|
- idDEntry dir_cache[MAX_CACHED_DIRS]; // fifo
|
||
|
+ idDEntry dir_cache[MAX_CACHED_DIRS]; // fifo
|
||
|
int dir_cache_index;
|
||
|
int dir_cache_count;
|
||
|
+
|
||
|
+ idList<casematch_t> dir_case; // match directories in a case insensitive way
|
||
|
|
||
|
private:
|
||
|
+ const char * CaseSearch(const char *in_dir);
|
||
|
void ReplaceSeparators( idStr &path, char sep = PATHSEPERATOR_CHAR );
|
||
|
long HashFileName( const char *fname ) const;
|
||
|
bool FilenameCompare( const char *s1, const char *s2 );
|
||
|
@@ -1118,6 +1126,89 @@
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
+idFileSystem_local::CaseSearch
|
||
|
+===============
|
||
|
+*/
|
||
|
+const char* idFileSystem_local::CaseSearch(const char *in_dir) {
|
||
|
+ const char *ret;
|
||
|
+ int i, j;
|
||
|
+ // FIXME: go faster with a hash?
|
||
|
+ for( i=0; i<dir_case.Num(); i++ ) {
|
||
|
+ if ( !dir_case[i].path.Cmp( in_dir ) ) {
|
||
|
+ ret = dir_case[i].OSpath.c_str();
|
||
|
+ Com_Printf("index %d: '%s' matched as '%s'\n", i, in_dir, ret);
|
||
|
+ if ( ret[0] == '\0' ) {
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ casematch_t entry;
|
||
|
+ entry.path = in_dir;
|
||
|
+ Com_Printf("CaseSearch not found: '%s'\n", in_dir);
|
||
|
+ // walk down the directory tree searching for a case insensitive match
|
||
|
+ // use StripFilename to bust out the chunks
|
||
|
+ idStrList dirs;
|
||
|
+ idStrList entries;
|
||
|
+ idStr walk_path = in_dir;
|
||
|
+ idStr current_dir;
|
||
|
+ int list_ret;
|
||
|
+ do {
|
||
|
+ walk_path.ExtractFileName(current_dir);
|
||
|
+ dirs.Append(current_dir);
|
||
|
+ walk_path.StripFilename(); // this is double work
|
||
|
+ Com_Printf("have walk_path: %s, current_dir: %s\n", walk_path.c_str(), current_dir.c_str());
|
||
|
+ } while ( walk_path.Length() && ( list_ret = Sys_ListFiles( walk_path.c_str(), "/", entries ) == -1 ) );
|
||
|
+ // we have walked up to the first directory
|
||
|
+ if ( list_ret == -1 ) {
|
||
|
+ Com_DPrintf("WARNING: didn't find any matching root directory for '%s'\n", in_dir);
|
||
|
+ dir_case.Append(entry);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+ // start walking down and doing matches
|
||
|
+ bool bMatched;
|
||
|
+ entry.OSpath = walk_path;
|
||
|
+ for( i=dirs.Num()-1 ; i>=0; i-- ) {
|
||
|
+ Com_Printf("chunk: %s\n", dirs[i].c_str() );
|
||
|
+ bMatched = false;
|
||
|
+ for( j=0 ; j<entries.Num() ; j++ ) {
|
||
|
+ Com_Printf("match %s and %s\n", dirs[i].c_str(), entries[j].c_str());
|
||
|
+ if ( !dirs[i].Icmp(entries[j]) ) {
|
||
|
+ Com_Printf("we have a match, add this to the path and go down\n");
|
||
|
+ bMatched = true;
|
||
|
+ break; // NOTE: we could keep scanning and detect conflicts?
|
||
|
+ }
|
||
|
+ }
|
||
|
+ // if we didn't match, abort
|
||
|
+ if (!bMatched) {
|
||
|
+ Com_Printf("no match\n");
|
||
|
+ entry.OSpath = "";
|
||
|
+ dir_case.Append(entry);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+ entry.OSpath += PATHSEPERATOR_STR;
|
||
|
+ entry.OSpath += entries[j];
|
||
|
+ // get the directory list
|
||
|
+ if ( Sys_ListFiles( entry.OSpath.c_str(), "/", entries ) == -1 ) {
|
||
|
+ Com_DPrintf("WARNING: didn't find entries in '%s' after successful icase match\n", entry.OSpath.c_str());
|
||
|
+ entry.OSpath = "";
|
||
|
+ dir_case.Append(entry);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ dir_case.Append(entry);
|
||
|
+ ret = dir_case[ dir_case.Num() - 1 ].OSpath.c_str();
|
||
|
+ Com_Printf("case matched '%s' as '%s'\n", in_dir, ret);
|
||
|
+ if ( ret[0] == '\0' ) {
|
||
|
+ Com_DPrintf("WARNING: unexpected empty entry after successful case walk for '%s'\n", in_dir);
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
+===============
|
||
|
idFileSystem_local::ListOSFiles
|
||
|
|
||
|
call to the OS for a listing of files in an OS directory
|
||
|
@@ -1156,10 +1247,19 @@
|
||
|
ret = Sys_ListFiles( directory, extension, list );
|
||
|
|
||
|
if ( ret == -1 ) {
|
||
|
- return -1;
|
||
|
+ // try a case insensitive directory walk
|
||
|
+ const char *cased_dir = CaseSearch(directory);
|
||
|
+ if (!cased_dir) {
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+ ret = Sys_ListFiles( cased_dir, extension, list );
|
||
|
+ if ( ret == -1 ) {
|
||
|
+ Com_DPrintf("idFileSystem_local::ListOSFiles: unexpected, Sys_ListFiles failed on case matched directory\n");
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
- // push a new entry
|
||
|
+ // push a new entry - (if case matched we are caching with the requested directory name)
|
||
|
dir_cache[dir_cache_index].Init( directory, extension, list );
|
||
|
dir_cache_index = (++dir_cache_index) % MAX_CACHED_DIRS;
|
||
|
if ( dir_cache_count < MAX_CACHED_DIRS ) {
|
||
|
@@ -1633,6 +1733,11 @@
|
||
|
|
||
|
dir_cache_index = 0;
|
||
|
dir_cache_count = 0;
|
||
|
+ for ( int i = 0 ; i < MAX_CACHED_DIRS ; i++ ) {
|
||
|
+ dir_cache[i].Clear();
|
||
|
+ }
|
||
|
+
|
||
|
+ dir_case.Clear();
|
||
|
|
||
|
// free everything
|
||
|
for ( sp = searchPaths; sp; sp = next ) {
|
||
|
Index: sys/linux/ChangeLog
|
||
|
===================================================================
|
||
|
--- sys/linux/ChangeLog (revision 528)
|
||
|
+++ sys/linux/ChangeLog (working copy)
|
||
|
@@ -81,6 +81,31 @@
|
||
|
renderer TODO:
|
||
|
- bring up logging capability on *nix (implies non-implicit GL dependency mode)
|
||
|
|
||
|
+case insensitive directory walk - NOTES:
|
||
|
+
|
||
|
+wrote the base stuff. keeps a list of attempted/not found dirs.
|
||
|
+with the case sensitive match if exists
|
||
|
+dumb lookup currently, probably a bit expensive in CPU and mem
|
||
|
+hash table would speed this up
|
||
|
+
|
||
|
+still not sure that's the right way to go with this. I think the client should send
|
||
|
+out warnings when it finds bad cased directory, and in the long run abort
|
||
|
+with an error. That would be the only way to safe keep portability.
|
||
|
+
|
||
|
+trying to find good test case for that stuff
|
||
|
+scary: 300 entries for game/admin?
|
||
|
+design the search tree some other way? binary tree? (yeah why not)
|
||
|
+grep "Couldn't load" run.log | grep -v nin
|
||
|
+
|
||
|
+WARNING: Couldn't load image: models/mapobjects/tables/udesk/udesk_local
|
||
|
+
|
||
|
+timo@slinky:~/Id/DoomBase.ftpfs/base$ ls models/mapobjects/tables/Udesk/
|
||
|
+udesk.lwo udesk2.tga udesk_local.tga work
|
||
|
+udesk.tga udesk_base.lwo udesk_s.tga
|
||
|
+
|
||
|
+Is there an entry point for a directory instead of a file? What happens?
|
||
|
+(i.e. last directory of the path is cased)
|
||
|
+
|
||
|
idBoneController
|
||
|
|
||
|
2003-05-09 TTimo <ttimo@idsoftware.com>
|
||
|
Index: sys/sys_public.h
|
||
|
===================================================================
|
||
|
--- sys/sys_public.h (revision 528)
|
||
|
+++ sys/sys_public.h (working copy)
|
||
|
@@ -137,6 +137,7 @@
|
||
|
|
||
|
// use fs_debug to verbose Sys_ListFiles
|
||
|
// returns -1 if directory was not found (the list is cleared)
|
||
|
+// if there is a / passed as extension, return directories
|
||
|
int Sys_ListFiles( const char *directory, const char *extension, idStrList &list);
|
||
|
|
||
|
// For the mac, we need to explicitly flush vertex buffer areas before using them
|