performance improvement in directory/pk3 structure reading

This commit is contained in:
codeimp 2009-01-22 22:22:02 +00:00
parent 88b1cacf2e
commit 4f95c98be2
9 changed files with 481 additions and 182 deletions

View file

@ -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" />

View file

@ -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)
{

View file

@ -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
}

View file

@ -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--)
{

View file

@ -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;
}

View file

@ -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

View file

@ -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
}

View 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();
}
}
}

View 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
}
}