]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/sys/linux/casedir.patch
Various Mac OS X tweaks to get this to build. Probably breaking things.
[icculus/iodoom3.git] / neo / sys / linux / casedir.patch
1 Index: framework/FileSystem.cpp
2 ===================================================================
3 --- framework/FileSystem.cpp    (revision 528)
4 +++ framework/FileSystem.cpp    (working copy)
5 @@ -159,7 +159,7 @@
6  };
7  
8  // 3 search patch (fs_savepath fs_basepath fs_cdpath)
9 -// .jpg then .tga for 
10 +// often .jpg and .tga patterns
11  #define MAX_CACHED_DIRS 6
12  
13  class idDEntry : public idStrList {
14 @@ -173,6 +173,11 @@
15         void Init(const char *directory, const char *extension, const idStrList &list );
16  };
17  
18 +typedef struct {
19 +       idStr path;
20 +       idStr OSpath;
21 +} casematch_t;
22 +
23  class idFileSystem_local : public idFileSystem {
24  public:
25                                                 idFileSystem_local( void );
26 @@ -227,11 +232,14 @@
27         int                                     numServerPaks;
28         int                                     serverPaks[MAX_SEARCH_PATHS];
29  
30 -       idDEntry                        dir_cache[MAX_CACHED_DIRS]; // fifo
31 +       idDEntry                dir_cache[MAX_CACHED_DIRS]; // fifo
32         int                                     dir_cache_index;
33         int                                     dir_cache_count;
34 +       
35 +       idList<casematch_t> dir_case; // match directories in a case insensitive way
36  
37  private:
38 +       const char *    CaseSearch(const char *in_dir);
39         void                            ReplaceSeparators( idStr &path, char sep = PATHSEPERATOR_CHAR );
40         long                            HashFileName( const char *fname ) const;
41         bool                            FilenameCompare( const char *s1, const char *s2 );
42 @@ -1118,6 +1126,89 @@
43  
44  /*
45  ===============
46 +idFileSystem_local::CaseSearch
47 +===============
48 +*/
49 +const char* idFileSystem_local::CaseSearch(const char *in_dir) {
50 +       const char *ret;
51 +       int i, j;
52 +       // FIXME: go faster with a hash?
53 +       for( i=0; i<dir_case.Num(); i++ ) {
54 +               if ( !dir_case[i].path.Cmp( in_dir ) ) {
55 +                       ret = dir_case[i].OSpath.c_str();
56 +                       Com_Printf("index %d: '%s' matched as '%s'\n", i, in_dir, ret);
57 +                       if ( ret[0] == '\0' ) {
58 +                               return NULL;
59 +                       }
60 +                       return ret;
61 +               }
62 +       }
63 +       casematch_t entry;
64 +       entry.path = in_dir;
65 +       Com_Printf("CaseSearch not found: '%s'\n", in_dir);
66 +       // walk down the directory tree searching for a case insensitive match
67 +       // use StripFilename to bust out the chunks
68 +       idStrList dirs;
69 +       idStrList entries;
70 +       idStr walk_path = in_dir;
71 +       idStr current_dir;
72 +       int list_ret;
73 +       do {
74 +               walk_path.ExtractFileName(current_dir);
75 +               dirs.Append(current_dir);
76 +               walk_path.StripFilename(); // this is double work
77 +               Com_Printf("have walk_path: %s, current_dir: %s\n", walk_path.c_str(), current_dir.c_str());            
78 +       } while ( walk_path.Length() && ( list_ret = Sys_ListFiles( walk_path.c_str(), "/", entries ) == -1 ) );
79 +       // we have walked up to the first directory
80 +       if ( list_ret == -1 ) {
81 +               Com_DPrintf("WARNING: didn't find any matching root directory for '%s'\n", in_dir);
82 +               dir_case.Append(entry);
83 +               return NULL;
84 +       }
85 +       // start walking down and doing matches
86 +       bool bMatched;
87 +       entry.OSpath = walk_path;
88 +       for( i=dirs.Num()-1 ; i>=0; i-- ) {
89 +               Com_Printf("chunk: %s\n", dirs[i].c_str() );
90 +               bMatched = false;
91 +               for( j=0 ; j<entries.Num() ; j++ ) {
92 +                       Com_Printf("match %s and %s\n", dirs[i].c_str(), entries[j].c_str());
93 +                       if ( !dirs[i].Icmp(entries[j]) ) {
94 +                               Com_Printf("we have a match, add this to the path and go down\n");
95 +                               bMatched = true;
96 +                               break; // NOTE: we could keep scanning and detect conflicts?
97 +                       }
98 +               }
99 +               // if we didn't match, abort            
100 +               if (!bMatched) {
101 +                       Com_Printf("no match\n");
102 +                       entry.OSpath = "";
103 +                       dir_case.Append(entry);
104 +                       return NULL;
105 +               }
106 +               entry.OSpath += PATHSEPERATOR_STR;
107 +               entry.OSpath += entries[j];
108 +               // get the directory list
109 +               if ( Sys_ListFiles( entry.OSpath.c_str(), "/", entries ) == -1 ) {
110 +                       Com_DPrintf("WARNING: didn't find entries in '%s' after successful icase match\n", entry.OSpath.c_str());
111 +                       entry.OSpath = "";
112 +                       dir_case.Append(entry);
113 +                       return NULL;
114 +               }               
115 +       }
116 +
117 +       dir_case.Append(entry);
118 +       ret = dir_case[ dir_case.Num() - 1 ].OSpath.c_str();
119 +       Com_Printf("case matched '%s' as '%s'\n", in_dir, ret);
120 +       if ( ret[0] == '\0' ) {
121 +               Com_DPrintf("WARNING: unexpected empty entry after successful case walk for '%s'\n", in_dir);
122 +               return NULL;
123 +       }
124 +       return ret;
125 +}
126 +
127 +/*
128 +===============
129  idFileSystem_local::ListOSFiles
130  
131   call to the OS for a listing of files in an OS directory
132 @@ -1156,10 +1247,19 @@
133         ret = Sys_ListFiles( directory, extension, list );
134  
135         if ( ret == -1 ) {
136 -               return -1;
137 +               // try a case insensitive directory walk
138 +               const char *cased_dir = CaseSearch(directory);
139 +               if (!cased_dir) {
140 +                       return -1;
141 +               }
142 +               ret = Sys_ListFiles( cased_dir, extension, list );
143 +               if ( ret == -1 ) {
144 +                       Com_DPrintf("idFileSystem_local::ListOSFiles: unexpected, Sys_ListFiles failed on case matched directory\n");
145 +                       return -1;
146 +               }
147         }
148  
149 -       // push a new entry
150 +       // push a new entry - (if case matched we are caching with the requested directory name)
151         dir_cache[dir_cache_index].Init( directory, extension, list );
152         dir_cache_index = (++dir_cache_index) % MAX_CACHED_DIRS;
153         if ( dir_cache_count < MAX_CACHED_DIRS ) {
154 @@ -1633,6 +1733,11 @@
155  
156         dir_cache_index = 0;
157         dir_cache_count = 0;
158 +       for ( int i = 0 ; i < MAX_CACHED_DIRS ; i++ ) {
159 +               dir_cache[i].Clear();
160 +       }
161 +       
162 +       dir_case.Clear();
163  
164         // free everything
165         for ( sp = searchPaths; sp; sp = next ) {
166 Index: sys/linux/ChangeLog
167 ===================================================================
168 --- sys/linux/ChangeLog (revision 528)
169 +++ sys/linux/ChangeLog (working copy)
170 @@ -81,6 +81,31 @@
171  renderer TODO:
172         - bring up logging capability on *nix (implies non-implicit GL dependency mode)
173  
174 +case insensitive directory walk - NOTES:
175 +
176 +wrote the base stuff. keeps a list of attempted/not found dirs. 
177 +with the case sensitive match if exists
178 +dumb lookup currently, probably a bit expensive in CPU and mem
179 +hash table would speed this up
180 +
181 +still not sure that's the right way to go with this. I think the client should send
182 +out warnings when it finds bad cased directory, and in the long run abort
183 +with an error. That would be the only way to safe keep portability.
184 +
185 +trying to find good test case for that stuff
186 +scary: 300 entries for game/admin?
187 +design the search tree some other way? binary tree? (yeah why not)
188 +grep "Couldn't load" run.log  | grep -v nin
189 +
190 +WARNING: Couldn't load image: models/mapobjects/tables/udesk/udesk_local
191 +
192 +timo@slinky:~/Id/DoomBase.ftpfs/base$ ls models/mapobjects/tables/Udesk/
193 +udesk.lwo  udesk2.tga      udesk_local.tga  work
194 +udesk.tga  udesk_base.lwo  udesk_s.tga
195 +
196 +Is there an entry point for a directory instead of a file? What happens?
197 +(i.e. last directory of the path is cased)
198 +
199  idBoneController
200  
201  2003-05-09 TTimo <ttimo@idsoftware.com>
202 Index: sys/sys_public.h
203 ===================================================================
204 --- sys/sys_public.h    (revision 528)
205 +++ sys/sys_public.h    (working copy)
206 @@ -137,6 +137,7 @@
207  
208  // use fs_debug to verbose Sys_ListFiles
209  // returns -1 if directory was not found (the list is cleared)
210 +// if there is a / passed as extension, return directories
211  int                            Sys_ListFiles( const char *directory, const char *extension, idStrList &list);
212  
213  // For the mac, we need to explicitly flush vertex buffer areas before using them