mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-27 06:02:11 +00:00
performance improvement in directory/pk3 structure reading
This commit is contained in:
parent
88b1cacf2e
commit
4f95c98be2
9 changed files with 481 additions and 182 deletions
|
@ -679,6 +679,8 @@
|
|||
<EmbeddedResource Include="Resources\ThingBox.png" />
|
||||
<EmbeddedResource Include="Resources\Nothing.png" />
|
||||
<EmbeddedResource Include="Resources\UnknownThing.png" />
|
||||
<Compile Include="IO\DirectoryFileEntry.cs" />
|
||||
<Compile Include="IO\DirectoryFilesList.cs" />
|
||||
<Compile Include="Types\AngleDegreesFloatHandler.cs" />
|
||||
<Compile Include="Types\AngleDegreesHandler.cs" />
|
||||
<Compile Include="Types\AngleRadiansHandler.cs" />
|
||||
|
|
|
@ -179,6 +179,12 @@ namespace CodeImp.DoomBuilder.Config
|
|||
|
||||
#region ================== Methods
|
||||
|
||||
// This sorts the category, if preferred
|
||||
internal void SortIfNeeded()
|
||||
{
|
||||
if(sorted) things.Sort();
|
||||
}
|
||||
|
||||
// This adds a thing to the category
|
||||
internal void AddThing(ThingTypeInfo t)
|
||||
{
|
||||
|
|
|
@ -32,7 +32,7 @@ using CodeImp.DoomBuilder.Decorate;
|
|||
|
||||
namespace CodeImp.DoomBuilder.Config
|
||||
{
|
||||
public class ThingTypeInfo
|
||||
public class ThingTypeInfo : IComparable<ThingTypeInfo>
|
||||
{
|
||||
#region ================== Constants
|
||||
|
||||
|
@ -229,6 +229,12 @@ namespace CodeImp.DoomBuilder.Config
|
|||
hangs = actor.GetFlagValue("spawnceiling", false);
|
||||
blocking = actor.GetFlagValue("solid", false) ? 2 : 0;
|
||||
}
|
||||
|
||||
// This is used for sorting
|
||||
public int CompareTo(ThingTypeInfo other)
|
||||
{
|
||||
return string.Compare(this.title, other.title, true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -235,7 +235,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Make DataLocation.type of type Type and assign the
|
||||
// types of the desired reader classes.
|
||||
|
||||
try
|
||||
//try
|
||||
{
|
||||
// Choose container type
|
||||
switch(dl.type)
|
||||
|
@ -256,6 +256,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
catch(Exception e)
|
||||
{
|
||||
// Unable to load resource
|
||||
|
@ -264,6 +265,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
General.ShowErrorMessage("Unable to load resources from location \"" + dl.location + "\". Please make sure the location is accessible and not in use by another program.", MessageBoxButtons.OK);
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
// Add container
|
||||
if(c != null) containers.Add(c);
|
||||
|
@ -281,6 +283,9 @@ namespace CodeImp.DoomBuilder.Data
|
|||
texturenames.Sort();
|
||||
flatnames.Sort();
|
||||
|
||||
// Sort things
|
||||
foreach(ThingCategory tc in thingcategories) tc.SortIfNeeded();
|
||||
|
||||
// Update the used textures
|
||||
General.Map.Data.UpdateUsedTextures();
|
||||
|
||||
|
@ -666,7 +671,10 @@ namespace CodeImp.DoomBuilder.Data
|
|||
internal Stream GetPatchData(string pname)
|
||||
{
|
||||
Stream patch;
|
||||
|
||||
if(pname.ToUpperInvariant() == "WALL57_1")
|
||||
{
|
||||
int t = 5;
|
||||
}
|
||||
// Go for all opened containers
|
||||
for(int i = containers.Count - 1; i >= 0; i--)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@ using System.Text;
|
|||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using CodeImp.DoomBuilder.IO;
|
||||
|
||||
#endregion
|
||||
|
@ -32,15 +33,22 @@ namespace CodeImp.DoomBuilder.Data
|
|||
{
|
||||
internal sealed class DirectoryReader : PK3StructuredReader
|
||||
{
|
||||
#region ================== Constructor / Disposer
|
||||
#region ================== Variables
|
||||
|
||||
private DirectoryFilesList files;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor / Disposer
|
||||
|
||||
// Constructor
|
||||
public DirectoryReader(DataLocation dl) : base(dl)
|
||||
{
|
||||
General.WriteLogLine("Opening directory resource '" + location.location + "'");
|
||||
|
||||
// Initialize
|
||||
Initialize(dl.location);
|
||||
files = new DirectoryFilesList(dl.location, true);
|
||||
Initialize();
|
||||
|
||||
// We have no destructor
|
||||
GC.SuppressFinalize(this);
|
||||
|
@ -66,74 +74,53 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// This creates an image
|
||||
protected override ImageData CreateImage(string name, string filename, bool flat)
|
||||
{
|
||||
return new FileImage(name, filename, flat);
|
||||
return new FileImage(name, Path.Combine(location.location, filename), flat);
|
||||
}
|
||||
|
||||
// This returns true if the specified file exists
|
||||
protected override bool FileExists(string filename)
|
||||
{
|
||||
return File.Exists(filename);
|
||||
return files.FileExists(filename);
|
||||
}
|
||||
|
||||
// This returns all files in a given directory
|
||||
protected override string[] GetAllFiles(string path, bool subfolders)
|
||||
{
|
||||
if(Directory.Exists(path))
|
||||
{
|
||||
if(subfolders)
|
||||
return Directory.GetFiles(path, "*", SearchOption.AllDirectories);
|
||||
else
|
||||
return Directory.GetFiles(path, "*", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
else
|
||||
return new string[0];
|
||||
return files.GetAllFiles(path, subfolders).ToArray();
|
||||
}
|
||||
|
||||
// This returns all files in a given directory that match the given extension
|
||||
protected override string[] GetFilesWithExt(string path, string extension, bool subfolders)
|
||||
{
|
||||
if(Directory.Exists(path))
|
||||
{
|
||||
if(subfolders)
|
||||
return Directory.GetFiles(path, "*." + extension, SearchOption.AllDirectories);
|
||||
else
|
||||
return Directory.GetFiles(path, "*." + extension, SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
else
|
||||
return new string[0];
|
||||
return files.GetAllFiles(path, extension, subfolders).ToArray();
|
||||
}
|
||||
|
||||
// This finds the first file that has the specific name, regardless of file extension
|
||||
protected override string FindFirstFile(string beginswith, bool subfolders)
|
||||
{
|
||||
return files.GetFirstFile(beginswith, subfolders);
|
||||
}
|
||||
|
||||
// This finds the first file that has the specific name, regardless of file extension
|
||||
protected override string FindFirstFile(string path, string beginswith, bool subfolders)
|
||||
{
|
||||
string[] files = GetAllFiles(path, subfolders);
|
||||
foreach(string f in files)
|
||||
{
|
||||
if(string.Compare(Path.GetFileNameWithoutExtension(f), beginswith, true) == 0)
|
||||
return f;
|
||||
}
|
||||
|
||||
return null;
|
||||
return files.GetFirstFile(path, beginswith, subfolders);
|
||||
}
|
||||
|
||||
// This finds the first file that has the specific name
|
||||
protected override string FindFirstFileWithExt(string path, string beginswith, bool subfolders)
|
||||
{
|
||||
string[] files = GetAllFiles(path, subfolders);
|
||||
foreach(string f in files)
|
||||
{
|
||||
if(string.Compare(Path.GetFileName(f), beginswith, true) == 0)
|
||||
return f;
|
||||
}
|
||||
|
||||
return null;
|
||||
string title = Path.GetFileNameWithoutExtension(beginswith);
|
||||
string ext = Path.GetExtension(beginswith);
|
||||
if(ext.Length > 1) ext = ext.Substring(1); else ext = "";
|
||||
return files.GetFirstFile(path, title, subfolders, ext);
|
||||
}
|
||||
|
||||
// This loads an entire file in memory and returns the stream
|
||||
// NOTE: Callers are responsible for disposing the stream!
|
||||
protected override MemoryStream LoadFile(string filename)
|
||||
{
|
||||
return new MemoryStream(File.ReadAllBytes(filename));
|
||||
return new MemoryStream(File.ReadAllBytes(Path.Combine(location.location, filename)));
|
||||
}
|
||||
|
||||
// This creates a temp file for the speciied file and return the absolute path to the temp file
|
||||
|
@ -142,7 +129,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
{
|
||||
// Just copy the file
|
||||
string tempfile = General.MakeTempFilename(General.Map.TempPath, "wad");
|
||||
File.Copy(filename, tempfile);
|
||||
File.Copy(Path.Combine(location.location, filename), tempfile);
|
||||
return tempfile;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
{
|
||||
#region ================== Variables
|
||||
|
||||
private List<string> fileslist;
|
||||
private DirectoryFilesList files;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -50,22 +50,25 @@ namespace CodeImp.DoomBuilder.Data
|
|||
ZipInputStream zipstream = OpenPK3File();
|
||||
|
||||
// Make list of all files
|
||||
fileslist = new List<string>();
|
||||
List<DirectoryFileEntry> fileentries = new List<DirectoryFileEntry>();
|
||||
ZipEntry entry = zipstream.GetNextEntry();
|
||||
while(entry != null)
|
||||
{
|
||||
if(entry.IsFile) fileslist.Add(entry.Name.ToLowerInvariant());
|
||||
if(entry.IsFile) fileentries.Add(new DirectoryFileEntry(entry.Name));
|
||||
|
||||
// Next
|
||||
entry = zipstream.GetNextEntry();
|
||||
}
|
||||
|
||||
// Make files list
|
||||
files = new DirectoryFilesList(fileentries);
|
||||
|
||||
// Done with the zip file
|
||||
zipstream.Close();
|
||||
zipstream.Dispose();
|
||||
|
||||
// Initialize without path (because we use paths relative to the PK3 file)
|
||||
Initialize("");
|
||||
Initialize();
|
||||
|
||||
// We have no destructor
|
||||
GC.SuppressFinalize(this);
|
||||
|
@ -109,120 +112,40 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// This returns true if the specified file exists
|
||||
protected override bool FileExists(string filename)
|
||||
{
|
||||
string lowfile = filename.ToLowerInvariant();
|
||||
foreach(string f in fileslist)
|
||||
{
|
||||
if((string.Compare(f, lowfile) == 0)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return files.FileExists(filename);
|
||||
}
|
||||
|
||||
|
||||
// This returns all files in a given directory
|
||||
protected override string[] GetAllFiles(string path, bool subfolders)
|
||||
{
|
||||
List<string> matches = new List<string>();
|
||||
string lowpath = path.ToLowerInvariant();
|
||||
if(subfolders)
|
||||
{
|
||||
foreach(string f in fileslist)
|
||||
{
|
||||
if(Path.GetDirectoryName(f).StartsWith(lowpath, true, CultureInfo.InvariantCulture) &&
|
||||
(Path.GetFileName(f).Length > 0))
|
||||
matches.Add(f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach(string f in fileslist)
|
||||
{
|
||||
if((string.Compare(Path.GetDirectoryName(f), lowpath) == 0) &&
|
||||
(Path.GetFileName(f).Length > 0))
|
||||
matches.Add(f);
|
||||
}
|
||||
}
|
||||
|
||||
return matches.ToArray();
|
||||
return files.GetAllFiles(path, subfolders).ToArray();
|
||||
}
|
||||
|
||||
// This returns all files in a given directory that match the given extension
|
||||
protected override string[] GetFilesWithExt(string path, string extension, bool subfolders)
|
||||
{
|
||||
List<string> matches = new List<string>();
|
||||
string lowpath = path.ToLowerInvariant();
|
||||
string lowext = "." + extension.ToLowerInvariant();
|
||||
if(subfolders)
|
||||
{
|
||||
foreach(string f in fileslist)
|
||||
{
|
||||
if(Path.GetDirectoryName(f).StartsWith(lowpath, true, CultureInfo.InvariantCulture) && f.EndsWith(lowext))
|
||||
matches.Add(f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach(string f in fileslist)
|
||||
{
|
||||
if((string.Compare(Path.GetDirectoryName(f), lowpath) == 0) && f.EndsWith(lowext))
|
||||
matches.Add(f);
|
||||
}
|
||||
}
|
||||
|
||||
return matches.ToArray();
|
||||
return files.GetAllFiles(path, extension, subfolders).ToArray();
|
||||
}
|
||||
|
||||
// This finds the first file that has the specific name, regardless of file extension
|
||||
protected override string FindFirstFile(string beginswith, bool subfolders)
|
||||
{
|
||||
return files.GetFirstFile(beginswith, subfolders);
|
||||
}
|
||||
|
||||
// This finds the first file that has the specific name, regardless of file extension
|
||||
protected override string FindFirstFile(string path, string beginswith, bool subfolders)
|
||||
{
|
||||
string lowpath = path.ToLowerInvariant();
|
||||
string lowbegin = beginswith.ToLowerInvariant();
|
||||
if(subfolders)
|
||||
{
|
||||
foreach(string f in fileslist)
|
||||
{
|
||||
if(Path.GetDirectoryName(f).StartsWith(lowpath, true, CultureInfo.InvariantCulture) &&
|
||||
(string.Compare(Path.GetFileNameWithoutExtension(f), lowbegin) == 0))
|
||||
return f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach(string f in fileslist)
|
||||
{
|
||||
if((string.Compare(Path.GetDirectoryName(f), lowpath) == 0) &&
|
||||
(string.Compare(Path.GetFileNameWithoutExtension(f), lowbegin) == 0))
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return files.GetFirstFile(path, beginswith, subfolders);
|
||||
}
|
||||
|
||||
// This finds the first file that has the specific name
|
||||
protected override string FindFirstFileWithExt(string path, string beginswith, bool subfolders)
|
||||
{
|
||||
string lowpath = path.ToLowerInvariant();
|
||||
string lowbegin = beginswith.ToLowerInvariant();
|
||||
if(subfolders)
|
||||
{
|
||||
foreach(string f in fileslist)
|
||||
{
|
||||
if(Path.GetDirectoryName(f).StartsWith(lowpath, true, CultureInfo.InvariantCulture) &&
|
||||
(string.Compare(Path.GetFileName(f), lowbegin) == 0))
|
||||
return f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach(string f in fileslist)
|
||||
{
|
||||
if((string.Compare(Path.GetDirectoryName(f), lowpath) == 0) &&
|
||||
(string.Compare(Path.GetFileName(f), lowbegin) == 0))
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
string title = Path.GetFileNameWithoutExtension(beginswith);
|
||||
string ext = Path.GetExtension(beginswith);
|
||||
if(ext.Length > 1) ext = ext.Substring(1); else ext = "";
|
||||
return files.GetFirstFile(path, title, subfolders, ext);
|
||||
}
|
||||
|
||||
// This loads an entire file in memory and returns the stream
|
||||
|
@ -238,19 +161,24 @@ namespace CodeImp.DoomBuilder.Data
|
|||
ZipEntry entry = zipstream.GetNextEntry();
|
||||
while(entry != null)
|
||||
{
|
||||
// Is this the entry we are looking for?
|
||||
if(string.Compare(entry.Name, filename, true) == 0)
|
||||
if(entry.IsFile)
|
||||
{
|
||||
int expectedsize = (int)entry.Size;
|
||||
if(expectedsize < 1) expectedsize = 1024;
|
||||
filedata = new MemoryStream(expectedsize);
|
||||
int readsize = zipstream.Read(copybuffer, 0, copybuffer.Length);
|
||||
while(readsize > 0)
|
||||
string entryname = entry.Name.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
||||
|
||||
// Is this the entry we are looking for?
|
||||
if(string.Compare(entryname, filename, true) == 0)
|
||||
{
|
||||
filedata.Write(copybuffer, 0, readsize);
|
||||
readsize = zipstream.Read(copybuffer, 0, copybuffer.Length);
|
||||
int expectedsize = (int)entry.Size;
|
||||
if(expectedsize < 1) expectedsize = 1024;
|
||||
filedata = new MemoryStream(expectedsize);
|
||||
int readsize = zipstream.Read(copybuffer, 0, copybuffer.Length);
|
||||
while(readsize > 0)
|
||||
{
|
||||
filedata.Write(copybuffer, 0, readsize);
|
||||
readsize = zipstream.Read(copybuffer, 0, copybuffer.Length);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Next
|
||||
|
|
|
@ -48,14 +48,6 @@ namespace CodeImp.DoomBuilder.Data
|
|||
private bool roottextures;
|
||||
private bool rootflats;
|
||||
|
||||
// Paths
|
||||
protected string rootpath;
|
||||
protected string patchespath;
|
||||
protected string texturespath;
|
||||
protected string flatspath;
|
||||
protected string hirespath;
|
||||
protected string spritespath;
|
||||
|
||||
// WAD files that must be loaded as well
|
||||
private List<WADReader> wads;
|
||||
|
||||
|
@ -76,18 +68,10 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
// Call this to initialize this class
|
||||
protected virtual void Initialize(string rootpath)
|
||||
protected virtual void Initialize()
|
||||
{
|
||||
// Initialize
|
||||
this.rootpath = rootpath;
|
||||
this.patchespath = Path.Combine(rootpath, PATCHES_DIR);
|
||||
this.texturespath = Path.Combine(rootpath, TEXTURES_DIR);
|
||||
this.flatspath = Path.Combine(rootpath, FLATS_DIR);
|
||||
this.hirespath = Path.Combine(rootpath, HIRES_DIR);
|
||||
this.spritespath = Path.Combine(rootpath, SPRITES_DIR);
|
||||
|
||||
// Load all WAD files in the root as WAD resources
|
||||
string[] wadfiles = GetFilesWithExt(rootpath, "wad", false);
|
||||
string[] wadfiles = GetFilesWithExt("", "wad", false);
|
||||
wads = new List<WADReader>(wadfiles.Length);
|
||||
foreach(string w in wadfiles)
|
||||
{
|
||||
|
@ -181,19 +165,19 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Should we load the images in this directory as textures?
|
||||
if(roottextures)
|
||||
{
|
||||
collection = LoadDirectoryImages(rootpath, false);
|
||||
collection = LoadDirectoryImages("", false);
|
||||
AddImagesToList(images, collection);
|
||||
}
|
||||
|
||||
// TODO: Add support for hires texture here
|
||||
|
||||
// Add images from texture directory
|
||||
collection = LoadDirectoryImages(texturespath, false);
|
||||
collection = LoadDirectoryImages(TEXTURES_DIR, false);
|
||||
AddImagesToList(images, collection);
|
||||
|
||||
// Load TEXTURE1 lump file
|
||||
List<ImageData> imgset = new List<ImageData>();
|
||||
string texture1file = FindFirstFile(rootpath, "TEXTURE1", false);
|
||||
string texture1file = FindFirstFile("TEXTURE1", false);
|
||||
if((texture1file != null) && FileExists(texture1file))
|
||||
{
|
||||
MemoryStream filedata = LoadFile(texture1file);
|
||||
|
@ -202,7 +186,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
// Load TEXTURE2 lump file
|
||||
string texture2file = FindFirstFile(rootpath, "TEXTURE2", false);
|
||||
string texture2file = FindFirstFile("TEXTURE2", false);
|
||||
if((texture2file != null) && FileExists(texture2file))
|
||||
{
|
||||
MemoryStream filedata = LoadFile(texture2file);
|
||||
|
@ -234,7 +218,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
// If none of the wads provides patch names, let's see if we can
|
||||
string pnamesfile = FindFirstFile(rootpath, "PNAMES", false);
|
||||
string pnamesfile = FindFirstFile("PNAMES", false);
|
||||
if((pnamesfile != null) && FileExists(pnamesfile))
|
||||
{
|
||||
MemoryStream pnamesdata = LoadFile(pnamesfile);
|
||||
|
@ -261,7 +245,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
// Find in patches directory
|
||||
string filename = FindFirstFile(patchespath, pname, true);
|
||||
string filename = FindFirstFile(PATCHES_DIR, pname, true);
|
||||
if((filename != null) && FileExists(filename))
|
||||
{
|
||||
return LoadFile(filename);
|
||||
|
@ -295,12 +279,12 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Should we load the images in this directory as flats?
|
||||
if(rootflats)
|
||||
{
|
||||
collection = LoadDirectoryImages(rootpath, true);
|
||||
collection = LoadDirectoryImages("", true);
|
||||
AddImagesToList(images, collection);
|
||||
}
|
||||
|
||||
// Add images from flats directory
|
||||
collection = LoadDirectoryImages(flatspath, true);
|
||||
collection = LoadDirectoryImages(FLATS_DIR, true);
|
||||
AddImagesToList(images, collection);
|
||||
|
||||
return images;
|
||||
|
@ -326,7 +310,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
// Find in sprites directory
|
||||
string filename = FindFirstFile(spritespath, pfilename, true);
|
||||
string filename = FindFirstFile(SPRITES_DIR, pfilename, true);
|
||||
if((filename != null) && FileExists(filename))
|
||||
{
|
||||
return LoadFile(filename);
|
||||
|
@ -351,7 +335,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
}
|
||||
|
||||
// Find in sprites directory
|
||||
string filename = FindFirstFile(spritespath, pfilename, true);
|
||||
string filename = FindFirstFile(SPRITES_DIR, pfilename, true);
|
||||
if((filename != null) && FileExists(filename))
|
||||
{
|
||||
return true;
|
||||
|
@ -381,8 +365,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Find in root directory
|
||||
string filename = Path.GetFileName(pname);
|
||||
string pathname = Path.GetDirectoryName(pname);
|
||||
string fullpath = Path.Combine(rootpath, pathname);
|
||||
string foundfile = filename.IndexOf('.') > -1 ? FindFirstFileWithExt(fullpath, filename, false) : FindFirstFile(fullpath, filename, false);
|
||||
string foundfile = (filename.IndexOf('.') > -1) ? FindFirstFileWithExt(pathname, filename, false) : FindFirstFile(pathname, filename, false);
|
||||
if((foundfile != null) && FileExists(foundfile))
|
||||
{
|
||||
return LoadFile(foundfile);
|
||||
|
@ -453,6 +436,9 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// This must return all files in a given directory that match the given extension
|
||||
protected abstract string[] GetFilesWithExt(string path, string extension, bool subfolders);
|
||||
|
||||
// This must find the first file that has the specific name, regardless of file extension
|
||||
protected abstract string FindFirstFile(string beginswith, bool subfolders);
|
||||
|
||||
// This must find the first file that has the specific name, regardless of file extension
|
||||
protected abstract string FindFirstFile(string path, string beginswith, bool subfolders);
|
||||
|
||||
|
@ -466,6 +452,26 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// This must create a temp file for the speciied file and return the absolute path to the temp file
|
||||
// NOTE: Callers are responsible for removing the temp file when done!
|
||||
protected abstract string CreateTempFile(string filename);
|
||||
|
||||
// This makes the path relative to the directory, if needed
|
||||
protected virtual string MakeRelativePath(string anypath)
|
||||
{
|
||||
if(Path.IsPathRooted(anypath))
|
||||
{
|
||||
// Make relative
|
||||
string lowpath = anypath.ToLowerInvariant();
|
||||
string lowlocation = location.location.ToLowerInvariant();
|
||||
if((lowpath.Length > (lowlocation.Length + 1)) && lowpath.StartsWith(lowlocation))
|
||||
return anypath.Substring(lowlocation.Length + 1);
|
||||
else
|
||||
return anypath;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Path is already relative
|
||||
return anypath;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
90
Source/IO/DirectoryFileEntry.cs
Normal file
90
Source/IO/DirectoryFileEntry.cs
Normal file
|
@ -0,0 +1,90 @@
|
|||
|
||||
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
||||
* This program is released under GNU General Public License
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.IO
|
||||
{
|
||||
internal struct DirectoryFileEntry
|
||||
{
|
||||
// Example for: C:\WADs\Foo\Bar.WAD
|
||||
// Created from: C:\WADs
|
||||
// Members
|
||||
public string filename; // bar.wad
|
||||
public string filetitle; // bar
|
||||
public string extension; // wad
|
||||
public string path; // foo
|
||||
public string filepathname; // Foo\Bar.WAD
|
||||
public string filepathtitle; // Foo\Bar
|
||||
|
||||
// Constructor
|
||||
public DirectoryFileEntry(string fullname, string frompath)
|
||||
{
|
||||
// Get the information we need
|
||||
filename = Path.GetFileName(fullname);
|
||||
filetitle = Path.GetFileNameWithoutExtension(fullname);
|
||||
extension = Path.GetExtension(fullname);
|
||||
if(extension.Length > 1)
|
||||
extension = extension.Substring(1);
|
||||
else
|
||||
extension = "";
|
||||
path = Path.GetDirectoryName(fullname);
|
||||
if(path.Length > (frompath.Length + 1))
|
||||
path = path.Substring(frompath.Length + 1);
|
||||
else
|
||||
path = "";
|
||||
filepathname = Path.Combine(path, filename);
|
||||
filepathtitle = Path.Combine(path, filetitle);
|
||||
|
||||
// Make some lowercase
|
||||
filename = filename.ToLowerInvariant();
|
||||
filetitle = filetitle.ToLowerInvariant();
|
||||
extension = extension.ToLowerInvariant();
|
||||
path = path.ToLowerInvariant();
|
||||
}
|
||||
|
||||
// Constructor
|
||||
public DirectoryFileEntry(string fullname)
|
||||
{
|
||||
// Get the information we need
|
||||
filename = Path.GetFileName(fullname);
|
||||
filetitle = Path.GetFileNameWithoutExtension(fullname);
|
||||
extension = Path.GetExtension(fullname);
|
||||
if(extension.Length > 1)
|
||||
extension = extension.Substring(1);
|
||||
else
|
||||
extension = "";
|
||||
path = Path.GetDirectoryName(fullname);
|
||||
filepathname = Path.Combine(path, filename);
|
||||
filepathtitle = Path.Combine(path, filetitle);
|
||||
|
||||
// Make some lowercase
|
||||
filename = filename.ToLowerInvariant();
|
||||
filetitle = filetitle.ToLowerInvariant();
|
||||
extension = extension.ToLowerInvariant();
|
||||
path = path.ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
}
|
266
Source/IO/DirectoryFilesList.cs
Normal file
266
Source/IO/DirectoryFilesList.cs
Normal file
|
@ -0,0 +1,266 @@
|
|||
|
||||
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
||||
* This program is released under GNU General Public License
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.IO
|
||||
{
|
||||
internal sealed class DirectoryFilesList
|
||||
{
|
||||
#region ================== Variables
|
||||
|
||||
private DirectoryFileEntry[] entries;
|
||||
private Dictionary<string, DirectoryFileEntry> hashedentries;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
||||
public int Count { get { return entries.Length; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor / Disposer
|
||||
|
||||
// Constructor to fill list from directory and optionally subdirectories
|
||||
public DirectoryFilesList(string path, bool subdirectories)
|
||||
{
|
||||
path = Path.GetFullPath(path);
|
||||
string[] files = Directory.GetFiles(path, "*", subdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
|
||||
entries = new DirectoryFileEntry[files.Length];
|
||||
hashedentries = new Dictionary<string, DirectoryFileEntry>(files.Length);
|
||||
for(int i = 0; i < files.Length; i++)
|
||||
{
|
||||
entries[i] = new DirectoryFileEntry(files[i], path);
|
||||
hashedentries.Add(entries[i].filepathname.ToLowerInvariant(), entries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Constructor for custom list
|
||||
public DirectoryFilesList(ICollection<DirectoryFileEntry> sourceentries)
|
||||
{
|
||||
int index = 0;
|
||||
entries = new DirectoryFileEntry[sourceentries.Count];
|
||||
hashedentries = new Dictionary<string, DirectoryFileEntry>(sourceentries.Count);
|
||||
foreach(DirectoryFileEntry e in sourceentries)
|
||||
{
|
||||
entries[index] = e;
|
||||
hashedentries.Add(e.filepathname.ToLowerInvariant(), e);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Methods
|
||||
|
||||
// This checks if a given file exists
|
||||
// The given file path must not be absolute
|
||||
public bool FileExists(string filepathname)
|
||||
{
|
||||
return hashedentries.ContainsKey(filepathname.ToLowerInvariant());
|
||||
}
|
||||
|
||||
// This returns file information for the given file
|
||||
// The given file path must not be absolute
|
||||
public DirectoryFileEntry GetFileInfo(string filepathname)
|
||||
{
|
||||
return hashedentries[filepathname.ToLowerInvariant()];
|
||||
}
|
||||
|
||||
// This returns a list of all files (filepathname)
|
||||
public List<string> GetAllFiles()
|
||||
{
|
||||
List<string> files = new List<string>(entries.Length);
|
||||
for(int i = 0; i < entries.Length; i++) files.Add(entries[i].filepathname);
|
||||
return files;
|
||||
}
|
||||
|
||||
// This returns a list of all files optionally with subdirectories included
|
||||
public List<string> GetAllFiles(bool subdirectories)
|
||||
{
|
||||
if(subdirectories)
|
||||
return GetAllFiles();
|
||||
else
|
||||
{
|
||||
List<string> files = new List<string>(entries.Length);
|
||||
for(int i = 0; i < entries.Length; i++)
|
||||
if(entries[i].path.Length == 0) files.Add(entries[i].filepathname);
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
||||
// This returns a list of all files that are in the given path and optionally in subdirectories
|
||||
public List<string> GetAllFiles(string path, bool subdirectories)
|
||||
{
|
||||
path = CorrectPath(path).ToLowerInvariant();
|
||||
if(subdirectories)
|
||||
{
|
||||
List<string> files = new List<string>(entries.Length);
|
||||
for(int i = 0; i < entries.Length; i++)
|
||||
if(entries[i].path == path) files.Add(entries[i].filepathname);
|
||||
return files;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<string> files = new List<string>(entries.Length);
|
||||
for(int i = 0; i < entries.Length; i++)
|
||||
if(entries[i].path == path) files.Add(entries[i].filepathname);
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
||||
// This returns a list of all files that are in the given path and subdirectories and have the given extension
|
||||
public List<string> GetAllFiles(string path, string extension)
|
||||
{
|
||||
path = CorrectPath(path).ToLowerInvariant();
|
||||
extension = extension.ToLowerInvariant();
|
||||
List<string> files = new List<string>(entries.Length);
|
||||
for(int i = 0; i < entries.Length; i++)
|
||||
if(entries[i].path.StartsWith(path) && (entries[i].extension == extension))
|
||||
files.Add(entries[i].filepathname);
|
||||
return files;
|
||||
}
|
||||
|
||||
// This returns a list of all files that are in the given path (optionally in subdirectories) and have the given extension
|
||||
public List<string> GetAllFiles(string path, string extension, bool subdirectories)
|
||||
{
|
||||
if(subdirectories)
|
||||
return GetAllFiles(path, extension);
|
||||
else
|
||||
{
|
||||
path = CorrectPath(path).ToLowerInvariant();
|
||||
extension = extension.ToLowerInvariant();
|
||||
List<string> files = new List<string>(entries.Length);
|
||||
for(int i = 0; i < entries.Length; i++)
|
||||
if((entries[i].path == path) && (entries[i].extension == extension))
|
||||
files.Add(entries[i].filepathname);
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
||||
// This finds the first file that has the specified name, regardless of file extension
|
||||
public string GetFirstFile(string title, bool subdirectories)
|
||||
{
|
||||
title = title.ToLowerInvariant();
|
||||
if(subdirectories)
|
||||
{
|
||||
for(int i = 0; i < entries.Length; i++)
|
||||
if(entries[i].filetitle == title)
|
||||
return entries[i].filepathname;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < entries.Length; i++)
|
||||
if((entries[i].filetitle == title) && (entries[i].path.Length == 0))
|
||||
return entries[i].filepathname;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// This finds the first file that has the specified name and extension
|
||||
public string GetFirstFile(string title, bool subdirectories, string extension)
|
||||
{
|
||||
title = title.ToLowerInvariant();
|
||||
extension = extension.ToLowerInvariant();
|
||||
if(subdirectories)
|
||||
{
|
||||
for(int i = 0; i < entries.Length; i++)
|
||||
if((entries[i].filetitle == title) && (entries[i].extension == extension))
|
||||
return entries[i].filepathname;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < entries.Length; i++)
|
||||
if((entries[i].filetitle == title) && (entries[i].path.Length == 0) && (entries[i].extension == extension))
|
||||
return entries[i].filepathname;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// This finds the first file that has the specified name, regardless of file extension, and is in the given path
|
||||
public string GetFirstFile(string path, string title, bool subdirectories)
|
||||
{
|
||||
title = title.ToLowerInvariant();
|
||||
path = CorrectPath(path).ToLowerInvariant();
|
||||
if(subdirectories)
|
||||
{
|
||||
for(int i = 0; i < entries.Length; i++)
|
||||
if((entries[i].filetitle == title) && entries[i].path.StartsWith(path))
|
||||
return entries[i].filepathname;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < entries.Length; i++)
|
||||
if((entries[i].filetitle == title) && (entries[i].path == path))
|
||||
return entries[i].filepathname;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// This finds the first file that has the specified name, is in the given path and has the given extension
|
||||
public string GetFirstFile(string path, string title, bool subdirectories, string extension)
|
||||
{
|
||||
title = title.ToLowerInvariant();
|
||||
path = CorrectPath(path).ToLowerInvariant();
|
||||
extension = extension.ToLowerInvariant();
|
||||
if(subdirectories)
|
||||
{
|
||||
for(int i = 0; i < entries.Length; i++)
|
||||
if((entries[i].filetitle == title) && entries[i].path.StartsWith(path) && (entries[i].extension == extension))
|
||||
return entries[i].filepathname;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < entries.Length; i++)
|
||||
if((entries[i].filetitle == title) && (entries[i].path == path) && (entries[i].extension == extension))
|
||||
return entries[i].filepathname;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// This fixes a path so that it doesn't have the \ at the end
|
||||
private string CorrectPath(string path)
|
||||
{
|
||||
if(path.Length > 0)
|
||||
{
|
||||
if((path[path.Length - 1] == Path.DirectorySeparatorChar) || (path[path.Length - 1] == Path.AltDirectorySeparatorChar))
|
||||
return path.Substring(0, path.Length - 1);
|
||||
else
|
||||
return path;
|
||||
}
|
||||
else
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue