mirror of
https://github.com/love2d/love-android.git
synced 2026-08-19 20:20:25 +02:00
updated physfs to inofficial 2.1 version
This commit is contained in:
+58
@@ -0,0 +1,58 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly: AssemblyTitle("PhysFS.NET")]
|
||||
[assembly: AssemblyDescription("PhysFS Bindings for .NET")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("PhysFS.NET")]
|
||||
[assembly: AssemblyCopyright("(c)2003 Gregory S. Read")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
//
|
||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||
//
|
||||
// Use the attributes below to control which key is used for signing.
|
||||
//
|
||||
// Notes:
|
||||
// (*) If no key is specified, the assembly is not signed.
|
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||
// a key.
|
||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||
// following processing occurs:
|
||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||
// in the KeyFile is installed into the CSP and used.
|
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||
// When specifying the KeyFile, the location of the KeyFile should be
|
||||
// relative to the project output directory which is
|
||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||
// located in the project directory, you would specify the AssemblyKeyFile
|
||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||
// documentation for more information on this.
|
||||
//
|
||||
[assembly: AssemblyDelaySign(false)]
|
||||
[assembly: AssemblyKeyFile("")]
|
||||
[assembly: AssemblyKeyName("")]
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
<VisualStudioProject>
|
||||
<CSHARP
|
||||
ProjectType = "Local"
|
||||
ProductVersion = "7.0.9466"
|
||||
SchemaVersion = "1.0"
|
||||
ProjectGuid = "{C6205A43-3D4D-41E6-872C-96CD7BE55230}"
|
||||
>
|
||||
<Build>
|
||||
<Settings
|
||||
ApplicationIcon = ""
|
||||
AssemblyKeyContainerName = ""
|
||||
AssemblyName = "PhysFS.NET"
|
||||
AssemblyOriginatorKeyFile = ""
|
||||
DefaultClientScript = "JScript"
|
||||
DefaultHTMLPageLayout = "Grid"
|
||||
DefaultTargetSchema = "IE50"
|
||||
DelaySign = "false"
|
||||
OutputType = "Library"
|
||||
RootNamespace = "PhysFS.NET"
|
||||
StartupObject = ""
|
||||
>
|
||||
<Config
|
||||
Name = "Debug"
|
||||
AllowUnsafeBlocks = "true"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "DEBUG;TRACE"
|
||||
DocumentationFile = ""
|
||||
DebugSymbols = "true"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "true"
|
||||
Optimize = "false"
|
||||
OutputPath = "bin\Debug\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
<Config
|
||||
Name = "Release"
|
||||
AllowUnsafeBlocks = "true"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "TRACE"
|
||||
DocumentationFile = ""
|
||||
DebugSymbols = "false"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "false"
|
||||
Optimize = "true"
|
||||
OutputPath = "bin\Release\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
</Settings>
|
||||
<References>
|
||||
<Reference
|
||||
Name = "System"
|
||||
AssemblyName = "System"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Data"
|
||||
AssemblyName = "System.Data"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.XML"
|
||||
AssemblyName = "System.Xml"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Drawing"
|
||||
AssemblyName = "System.Drawing"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Drawing.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Windows.Forms"
|
||||
AssemblyName = "System.Windows.Forms"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Windows.Forms.dll"
|
||||
/>
|
||||
</References>
|
||||
</Build>
|
||||
<Files>
|
||||
<Include>
|
||||
<File
|
||||
RelPath = "AssemblyInfo.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "PhysFS.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "PhysFS_DLL.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "PhysFSFileStream.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
</Include>
|
||||
</Files>
|
||||
</CSHARP>
|
||||
</VisualStudioProject>
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 7.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhysFS.NET", "PhysFS.NET.csproj", "{C6205A43-3D4D-41E6-872C-96CD7BE55230}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
ConfigName.0 = Debug
|
||||
ConfigName.1 = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectDependencies) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Debug.ActiveCfg = Debug|.NET
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Debug.Build.0 = Debug|.NET
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Release.ActiveCfg = Release|.NET
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Release.Build.0 = Release|.NET
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Executable
+189
@@ -0,0 +1,189 @@
|
||||
/* PhysFS.cs - (c)2003 Gregory S. Read
|
||||
* Provides access to PhysFS API calls not specific to file handle access.
|
||||
*/
|
||||
using System;
|
||||
|
||||
namespace PhysFS_NET
|
||||
{
|
||||
public class PhysFS
|
||||
{
|
||||
/* Initialize
|
||||
* Inits the PhysFS API. This normally does not need to be called unless
|
||||
* the API has been manually deinitialized since the PhysFS_DLL class
|
||||
* initializes just before the first call is made into the DLL.
|
||||
* Parameters
|
||||
* none
|
||||
* Returns
|
||||
* none
|
||||
* Exceptions
|
||||
* PhysFSException - An error occured in the PhysFS API
|
||||
*/
|
||||
public static void Initialize()
|
||||
{
|
||||
// Initialize the physfs library, raise an exception if error
|
||||
if(PhysFS_DLL.PHYSFS_init("") == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
|
||||
/* Deinitialize
|
||||
* Deinits the PhysFS API. It is recommended that this method be called
|
||||
* by the application before exiting in order to gracefully deallocate
|
||||
* resources and close all filehandles, etc.
|
||||
* Parameters
|
||||
* none
|
||||
* Returns
|
||||
* none
|
||||
* Exceptions
|
||||
* PhysFSException - An error occured in the PhysFS API
|
||||
*/
|
||||
public static void Deinitialize()
|
||||
{
|
||||
// Deinit, raise an exception if an error occured
|
||||
if(PhysFS_DLL.PHYSFS_deinit() == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
|
||||
/* BaseDir
|
||||
* Gets the base directory configured for PhysFS. See the PhysFS API
|
||||
* documentation for more information.
|
||||
* Parameters
|
||||
* none
|
||||
* Returns
|
||||
* A string value representing the Base Directory
|
||||
* Exceptions
|
||||
* none
|
||||
*/
|
||||
public static string BaseDir
|
||||
{
|
||||
get
|
||||
{
|
||||
// Return the current base directory
|
||||
return PhysFS_DLL.PHYSFS_getBaseDir();
|
||||
}
|
||||
}
|
||||
|
||||
/* WriteDir
|
||||
* Gets or sets the write directory configured for PhysFS. See the PhysFS API
|
||||
* documentation for more information.
|
||||
* Parameters
|
||||
* set - Path to set the WriteDir property to
|
||||
* Returns
|
||||
* A string value representing the Write Directory
|
||||
* Exceptions
|
||||
* PhysFSException - An error occured in the PhysFS API when
|
||||
* settings the write directory.
|
||||
*/
|
||||
public static string WriteDir
|
||||
{
|
||||
get
|
||||
{
|
||||
// Return the current write directory
|
||||
return PhysFS_DLL.PHYSFS_getWriteDir();
|
||||
}
|
||||
set
|
||||
{
|
||||
// Set the write directory and raise an exception if an error occured
|
||||
if(PhysFS_DLL.PHYSFS_setWriteDir(value) == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
}
|
||||
|
||||
/* UserDir
|
||||
* Gets or sets the write directory configured for PhysFS. See the PhysFS API
|
||||
* documentation for more information.
|
||||
* Parameters
|
||||
* set - Path to set the WriteDir property to
|
||||
* Returns
|
||||
* A string value representing the Write Directory
|
||||
* Exceptions
|
||||
* PhysFSException - An error occured in the PhysFS API when
|
||||
* settings the write directory.
|
||||
*/
|
||||
public static string UserDir
|
||||
{
|
||||
get
|
||||
{
|
||||
// Return the current user directory
|
||||
return PhysFS_DLL.PHYSFS_getUserDir();
|
||||
}
|
||||
}
|
||||
public static void AddToSearchPath(string NewDir, bool Append)
|
||||
{
|
||||
if(PhysFS_DLL.PHYSFS_addToSearchPath(NewDir, Append?1:0) == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
public static void RemoveFromSearchPath(string OldDir)
|
||||
{
|
||||
if(PhysFS_DLL.PHYSFS_removeFromSearchPath(OldDir) == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
public unsafe static string[] GetSearchPath()
|
||||
{
|
||||
byte** p; // Searchpath list from PhysFS dll
|
||||
string[] pathlist; // List converted to an array
|
||||
|
||||
// Get the CDROM drive listing
|
||||
p = PhysFS_DLL.PHYSFS_getSearchPath();
|
||||
// Convert the C-style array to a .NET style array
|
||||
pathlist = PhysFS_DLL.BytePPToArray(p);
|
||||
// Free the original list since we're done with it
|
||||
PhysFS_DLL.PHYSFS_freeList(p);
|
||||
|
||||
return pathlist;
|
||||
}
|
||||
public unsafe static string[] GetCDROMDrives()
|
||||
{
|
||||
byte** p; // CDROM list from PhysFS dll
|
||||
string[] cdromlist; // List converted to an array
|
||||
|
||||
// Get the CDROM drive listing
|
||||
p = PhysFS_DLL.PHYSFS_getCdRomDirs();
|
||||
// Convert the C-style array to a .NET style array
|
||||
cdromlist = PhysFS_DLL.BytePPToArray(p);
|
||||
// Free the original list since we're done with it
|
||||
PhysFS_DLL.PHYSFS_freeList(p);
|
||||
|
||||
return cdromlist;
|
||||
}
|
||||
public static void MkDir(string Dirname)
|
||||
{
|
||||
if(PhysFS_DLL.PHYSFS_mkdir(Dirname) == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
public static void Delete(string Filename)
|
||||
{
|
||||
if(PhysFS_DLL.PHYSFS_delete(Filename) == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
public static string GetRealDir(string Filename)
|
||||
{
|
||||
string RetValue;
|
||||
|
||||
RetValue = PhysFS_DLL.PHYSFS_getRealDir(Filename);
|
||||
if(RetValue == null)
|
||||
throw new PhysFSException("File not found in search path.");
|
||||
|
||||
// Return the real file path of the specified filename
|
||||
return RetValue;
|
||||
}
|
||||
public unsafe static string[] EnumerateFiles(string Dirname)
|
||||
{
|
||||
byte** p; // File list from PhysFS dll
|
||||
string[] filelist; // List converted to an array
|
||||
|
||||
// Get the CDROM drive listing
|
||||
p = PhysFS_DLL.PHYSFS_enumerateFiles(Dirname);
|
||||
// Convert the C-style array to a .NET style array
|
||||
filelist = PhysFS_DLL.BytePPToArray(p);
|
||||
// Free the original list since we're done with it
|
||||
PhysFS_DLL.PHYSFS_freeList(p);
|
||||
|
||||
return filelist;
|
||||
}
|
||||
public static bool IsDirectory(string Filename)
|
||||
{
|
||||
// Return true if non-zero, otherwise return false
|
||||
return (PhysFS_DLL.PHYSFS_isDirectory(Filename) == 0)?false:true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
/* PhysFSFileStream.cs - (c)2003 Gregory S. Read */
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
|
||||
namespace PhysFS_NET
|
||||
{
|
||||
public enum PhysFSFileMode {Read, Write, Append};
|
||||
|
||||
// Our exception class we'll use for throwing all PhysFS API related exception
|
||||
public class PhysFSException : IOException
|
||||
{
|
||||
public PhysFSException(string Message) : base(Message) {}
|
||||
public PhysFSException() : base(PhysFS_DLL.PHYSFS_getLastError()) {}
|
||||
}
|
||||
|
||||
public unsafe class PhysFSFileStream : Stream
|
||||
{
|
||||
// ***Public properties***
|
||||
public override bool CanRead
|
||||
{
|
||||
get
|
||||
{
|
||||
// Reading is supported
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get
|
||||
{
|
||||
// Seek is supported
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get
|
||||
{
|
||||
// Writing is supported
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
long TempLength;
|
||||
TempLength = PhysFS_DLL.PHYSFS_fileLength(pHandle);
|
||||
|
||||
// If call returned an error, throw an exception
|
||||
if(TempLength == -1)
|
||||
throw new PhysFSException();
|
||||
|
||||
return TempLength;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
long TempPosition;
|
||||
TempPosition = PhysFS_DLL.PHYSFS_tell(pHandle);
|
||||
|
||||
// If call returned an error, throw an exception
|
||||
if(TempPosition == -1)
|
||||
throw new PhysFSException();
|
||||
|
||||
return TempPosition;
|
||||
}
|
||||
set
|
||||
{
|
||||
// Seek from beginning of file using the position value
|
||||
Seek(value, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
// ***Public methods***
|
||||
public PhysFSFileStream(string FileName, PhysFSFileMode FileMode, ulong BufferSize)
|
||||
{
|
||||
// Open the specified file with the appropriate file access
|
||||
switch(FileMode)
|
||||
{
|
||||
case PhysFSFileMode.Read:
|
||||
pHandle = PhysFS_DLL.PHYSFS_openRead(FileName);
|
||||
break;
|
||||
case PhysFSFileMode.Write:
|
||||
pHandle = PhysFS_DLL.PHYSFS_openWrite(FileName);
|
||||
break;
|
||||
case PhysFSFileMode.Append:
|
||||
pHandle = PhysFS_DLL.PHYSFS_openAppend(FileName);
|
||||
break;
|
||||
default:
|
||||
throw new PhysFSException("Invalid FileMode specified");
|
||||
}
|
||||
|
||||
// If handle is null, an error occured, so raise an exception
|
||||
//!!! Does object get created if exception is thrown?
|
||||
if(pHandle == null)
|
||||
throw new PhysFSException();
|
||||
|
||||
// Set buffer size, raise an exception if an error occured
|
||||
if(PhysFS_DLL.PHYSFS_setBuffer(pHandle, BufferSize) == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
|
||||
// This constructor sets the buffer size to 0 if not specified
|
||||
public PhysFSFileStream(string FileName, PhysFSFileMode FileMode) : this(FileName, FileMode, 0) {}
|
||||
|
||||
~PhysFSFileStream()
|
||||
{
|
||||
// Don't close the handle if they've specifically closed it already
|
||||
if(!Closed)
|
||||
Close();
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
if(PhysFS_DLL.PHYSFS_flush(pHandle) == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
long RetValue;
|
||||
|
||||
fixed(byte *pbytes = &buffer[offset])
|
||||
{
|
||||
// Read into our allocated pointer
|
||||
RetValue = PhysFS_DLL.PHYSFS_read(pHandle, pbytes, sizeof(byte), (uint)count);
|
||||
}
|
||||
|
||||
if(RetValue == -1)
|
||||
throw new PhysFSException();
|
||||
|
||||
// Return number of bytes read
|
||||
// Note: This cast should be safe since we are only reading 'count' items, which
|
||||
// is of type 'int'.
|
||||
return (int)RetValue;
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
long RetValue;
|
||||
|
||||
fixed(byte* pbytes = &buffer[offset])
|
||||
{
|
||||
// Write buffer
|
||||
RetValue = PhysFS_DLL.PHYSFS_write(pHandle, pbytes, sizeof(byte), (uint)count);
|
||||
}
|
||||
|
||||
if(RetValue == -1)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
// Only seeking from beginning is supported by PhysFS API
|
||||
if(origin != SeekOrigin.Begin)
|
||||
throw new PhysFSException("Only seek origin of \"Begin\" is supported");
|
||||
|
||||
// Seek to specified offset, raise an exception if error occured
|
||||
if(PhysFS_DLL.PHYSFS_seek(pHandle, (ulong)offset) == 0)
|
||||
throw new PhysFSException();
|
||||
|
||||
// Since we always seek from beginning, the offset is always
|
||||
// the absolute position.
|
||||
return offset;
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException("SetLength method not supported in PhysFSFileStream objects.");
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
// Close the handle
|
||||
if(PhysFS_DLL.PHYSFS_close(pHandle) == 0)
|
||||
throw new PhysFSException();
|
||||
|
||||
// File has been closed. Rock.
|
||||
Closed = true;
|
||||
}
|
||||
|
||||
// ***Private variables***
|
||||
private void *pHandle;
|
||||
private bool Closed = false;
|
||||
}
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/* PhysFS_DLL - (c)2003 Gregory S. Read
|
||||
* Internal class that provides direct access to the PhysFS DLL. It is
|
||||
* not accessible outside of the PhysFS.NET assembly.
|
||||
*/
|
||||
using System.Collections;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PhysFS_NET
|
||||
{
|
||||
internal class PhysFS_DLL
|
||||
{
|
||||
/* Static constructor
|
||||
* Initializes the PhysFS API before any method is called in this class. This
|
||||
* relieves the user from having to explicitly initialize the API.
|
||||
* Parameters
|
||||
* none
|
||||
* Returns
|
||||
* none
|
||||
* Exceptions
|
||||
* PhysFSException - An error occured in the PhysFS API
|
||||
*/
|
||||
static PhysFS_DLL()
|
||||
{
|
||||
if(PHYSFS_init("") == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
|
||||
/* BytePPToArray
|
||||
* Converts a C-style string array into a .NET managed string array
|
||||
* Parameters
|
||||
* C-style string array pointer returned from PhysFS
|
||||
* Returns
|
||||
* .NET managed string array
|
||||
* Exceptions
|
||||
* none
|
||||
*/
|
||||
public unsafe static string[] BytePPToArray(byte **bytearray)
|
||||
{
|
||||
byte** ptr;
|
||||
byte* c;
|
||||
string tempstr;
|
||||
ArrayList MyArrayList = new ArrayList();
|
||||
string[] RetArray;
|
||||
|
||||
for(ptr = bytearray; *ptr != null; ptr++)
|
||||
{
|
||||
tempstr = "";
|
||||
for(c = *ptr; *c != 0; c++)
|
||||
{
|
||||
tempstr += (char)*c;
|
||||
}
|
||||
|
||||
// Add string to our list
|
||||
MyArrayList.Add(tempstr);
|
||||
}
|
||||
|
||||
// Return a normal array of the list
|
||||
RetArray = new string[MyArrayList.Count];
|
||||
MyArrayList.CopyTo(RetArray, 0);
|
||||
return RetArray;
|
||||
}
|
||||
|
||||
// Name of DLL to import
|
||||
private const string PHYSFS_DLLNAME = "physfs.dll";
|
||||
|
||||
// DLL import declarations
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_init(string argv0);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_deinit();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe void PHYSFS_freeList(void *listVar);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getLastError();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getDirSeparator();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern void PHYSFS_permitSymbolicLinks(int allow);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe byte** PHYSFS_getCdRomDirs();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getBaseDir();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getUserDir();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getWriteDir();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_setWriteDir(string newDir);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_addToSearchPath(string newDir, int appendToPath);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_removeFromSearchPath(string oldDir);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe byte** PHYSFS_getSearchPath();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_setSaneConfig(string organization,
|
||||
string appName,
|
||||
string archiveExt,
|
||||
int includeCdRoms,
|
||||
int archivesFirst);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_mkdir(string dirName);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_delete(string filename);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getRealDir(string filename);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe byte** PHYSFS_enumerateFiles(string dir);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_exists(string fname);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_isDirectory(string fname);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_isSymbolicLink(string fname);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe void* PHYSFS_openWrite(string filename);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe void* PHYSFS_openAppend(string filename);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe void* PHYSFS_openRead(string filename);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_close(void* handle);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_getLastModTime(string filename);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_read(void* handle,
|
||||
void *buffer,
|
||||
uint objSize,
|
||||
uint objCount);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_write(void* handle,
|
||||
void *buffer,
|
||||
uint objSize,
|
||||
uint objCount);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_eof(void* handle);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_tell(void* handle);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_seek(void* handle, ulong pos);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_fileLength(void* handle);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_setBuffer(void* handle, ulong bufsize);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_flush(void* handle);
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
PhysFS.NET is a library that encapsulates the PhysFS API into a .NET assembly.
|
||||
|
||||
There are two class objects that are exposed in the assembly:
|
||||
PhysFS.cs
|
||||
This class exposes any non-filehandle specific functionality contained in
|
||||
the PhysFS library.
|
||||
PhysFSFileStream.cs
|
||||
A System.IO.Stream derived class which provides file access via the
|
||||
PhysFS API. Usage of this object is identical to a standard stream
|
||||
object.
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,58 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly: AssemblyTitle("")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
//
|
||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||
//
|
||||
// Use the attributes below to control which key is used for signing.
|
||||
//
|
||||
// Notes:
|
||||
// (*) If no key is specified, the assembly is not signed.
|
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||
// a key.
|
||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||
// following processing occurs:
|
||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||
// in the KeyFile is installed into the CSP and used.
|
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||
// When specifying the KeyFile, the location of the KeyFile should be
|
||||
// relative to the project output directory which is
|
||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||
// located in the project directory, you would specify the AssemblyKeyFile
|
||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||
// documentation for more information on this.
|
||||
//
|
||||
[assembly: AssemblyDelaySign(false)]
|
||||
[assembly: AssemblyKeyFile("")]
|
||||
[assembly: AssemblyKeyName("")]
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
<VisualStudioProject>
|
||||
<CSHARP
|
||||
ProjectType = "Local"
|
||||
ProductVersion = "7.0.9466"
|
||||
SchemaVersion = "1.0"
|
||||
ProjectGuid = "{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}"
|
||||
>
|
||||
<Build>
|
||||
<Settings
|
||||
ApplicationIcon = "App.ico"
|
||||
AssemblyKeyContainerName = ""
|
||||
AssemblyName = "TestApp"
|
||||
AssemblyOriginatorKeyFile = ""
|
||||
DefaultClientScript = "JScript"
|
||||
DefaultHTMLPageLayout = "Grid"
|
||||
DefaultTargetSchema = "IE50"
|
||||
DelaySign = "false"
|
||||
OutputType = "WinExe"
|
||||
RootNamespace = "TestApp"
|
||||
StartupObject = ""
|
||||
>
|
||||
<Config
|
||||
Name = "Debug"
|
||||
AllowUnsafeBlocks = "false"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "DEBUG;TRACE"
|
||||
DocumentationFile = ""
|
||||
DebugSymbols = "true"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "true"
|
||||
Optimize = "false"
|
||||
OutputPath = "bin\Debug\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
<Config
|
||||
Name = "Release"
|
||||
AllowUnsafeBlocks = "false"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "TRACE"
|
||||
DocumentationFile = ""
|
||||
DebugSymbols = "false"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "false"
|
||||
Optimize = "true"
|
||||
OutputPath = "bin\Release\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
</Settings>
|
||||
<References>
|
||||
<Reference
|
||||
Name = "System"
|
||||
AssemblyName = "System"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Data"
|
||||
AssemblyName = "System.Data"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Drawing"
|
||||
AssemblyName = "System.Drawing"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Drawing.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Windows.Forms"
|
||||
AssemblyName = "System.Windows.Forms"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Windows.Forms.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.XML"
|
||||
AssemblyName = "System.Xml"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "PhysFS.NET"
|
||||
Project = "{C6205A43-3D4D-41E6-872C-96CD7BE55230}"
|
||||
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
|
||||
/>
|
||||
</References>
|
||||
</Build>
|
||||
<Files>
|
||||
<Include>
|
||||
<File
|
||||
RelPath = "App.ico"
|
||||
BuildAction = "Content"
|
||||
/>
|
||||
<File
|
||||
RelPath = "AssemblyInfo.cs"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TestAppForm.cs"
|
||||
SubType = "Form"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TestAppForm.resx"
|
||||
DependentUpon = "TestAppForm.cs"
|
||||
BuildAction = "EmbeddedResource"
|
||||
/>
|
||||
</Include>
|
||||
</Files>
|
||||
</CSHARP>
|
||||
</VisualStudioProject>
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 7.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApp", "TestApp.csproj", "{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhysFS.NET", "..\PhysFS.NET.csproj", "{C6205A43-3D4D-41E6-872C-96CD7BE55230}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
ConfigName.0 = Debug
|
||||
ConfigName.1 = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectDependencies) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}.Debug.ActiveCfg = Debug|.NET
|
||||
{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}.Debug.Build.0 = Debug|.NET
|
||||
{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}.Release.ActiveCfg = Release|.NET
|
||||
{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}.Release.Build.0 = Release|.NET
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Debug.ActiveCfg = Debug|.NET
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Debug.Build.0 = Debug|.NET
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Release.ActiveCfg = Release|.NET
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Release.Build.0 = Release|.NET
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
+274
@@ -0,0 +1,274 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Collections;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using PhysFS_NET;
|
||||
|
||||
namespace TestApp
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for Form1.
|
||||
/// </summary>
|
||||
public class TestAppForm : System.Windows.Forms.Form
|
||||
{
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Button RefreshCDsButton;
|
||||
private System.Windows.Forms.ListBox CDDrivesList;
|
||||
private System.Windows.Forms.ListBox SearchPathList;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.TextBox EnumFilesPath;
|
||||
private System.Windows.Forms.ListBox EnumList;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.TextBox NewSearchPathText;
|
||||
private System.Windows.Forms.Button AddSearchPathButton;
|
||||
private System.Windows.Forms.Button RemovePathButton;
|
||||
private System.Windows.Forms.Button RefreshEnumList;
|
||||
private System.Windows.Forms.Button RefreshSearchPathButton;
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.Container components = null;
|
||||
|
||||
public TestAppForm()
|
||||
{
|
||||
//
|
||||
// Required for Windows Form Designer support
|
||||
//
|
||||
InitializeComponent();
|
||||
|
||||
//
|
||||
// TODO: Add any constructor code after InitializeComponent call
|
||||
//
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
protected override void Dispose( bool disposing )
|
||||
{
|
||||
if( disposing )
|
||||
{
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose( disposing );
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.RefreshCDsButton = new System.Windows.Forms.Button();
|
||||
this.CDDrivesList = new System.Windows.Forms.ListBox();
|
||||
this.SearchPathList = new System.Windows.Forms.ListBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.EnumFilesPath = new System.Windows.Forms.TextBox();
|
||||
this.EnumList = new System.Windows.Forms.ListBox();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.RefreshEnumList = new System.Windows.Forms.Button();
|
||||
this.NewSearchPathText = new System.Windows.Forms.TextBox();
|
||||
this.AddSearchPathButton = new System.Windows.Forms.Button();
|
||||
this.RemovePathButton = new System.Windows.Forms.Button();
|
||||
this.RefreshSearchPathButton = new System.Windows.Forms.Button();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.Location = new System.Drawing.Point(8, 8);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(136, 16);
|
||||
this.label2.TabIndex = 2;
|
||||
this.label2.Text = "Available CD-ROM Drives";
|
||||
//
|
||||
// RefreshCDsButton
|
||||
//
|
||||
this.RefreshCDsButton.Location = new System.Drawing.Point(8, 152);
|
||||
this.RefreshCDsButton.Name = "RefreshCDsButton";
|
||||
this.RefreshCDsButton.Size = new System.Drawing.Size(72, 24);
|
||||
this.RefreshCDsButton.TabIndex = 4;
|
||||
this.RefreshCDsButton.Text = "Refresh";
|
||||
this.RefreshCDsButton.Click += new System.EventHandler(this.RefreshCDsButton_Click);
|
||||
//
|
||||
// CDDrivesList
|
||||
//
|
||||
this.CDDrivesList.Location = new System.Drawing.Point(8, 24);
|
||||
this.CDDrivesList.Name = "CDDrivesList";
|
||||
this.CDDrivesList.Size = new System.Drawing.Size(136, 121);
|
||||
this.CDDrivesList.TabIndex = 7;
|
||||
//
|
||||
// SearchPathList
|
||||
//
|
||||
this.SearchPathList.Location = new System.Drawing.Point(152, 24);
|
||||
this.SearchPathList.Name = "SearchPathList";
|
||||
this.SearchPathList.Size = new System.Drawing.Size(248, 95);
|
||||
this.SearchPathList.TabIndex = 8;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.Location = new System.Drawing.Point(152, 8);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(136, 16);
|
||||
this.label1.TabIndex = 10;
|
||||
this.label1.Text = "Search Path";
|
||||
//
|
||||
// EnumFilesPath
|
||||
//
|
||||
this.EnumFilesPath.Location = new System.Drawing.Point(408, 128);
|
||||
this.EnumFilesPath.Name = "EnumFilesPath";
|
||||
this.EnumFilesPath.Size = new System.Drawing.Size(208, 20);
|
||||
this.EnumFilesPath.TabIndex = 11;
|
||||
this.EnumFilesPath.Text = "";
|
||||
//
|
||||
// EnumList
|
||||
//
|
||||
this.EnumList.Location = new System.Drawing.Point(408, 24);
|
||||
this.EnumList.Name = "EnumList";
|
||||
this.EnumList.Size = new System.Drawing.Size(208, 95);
|
||||
this.EnumList.TabIndex = 12;
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.Location = new System.Drawing.Point(408, 8);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(136, 16);
|
||||
this.label3.TabIndex = 13;
|
||||
this.label3.Text = "Enumerate Files";
|
||||
//
|
||||
// RefreshEnumList
|
||||
//
|
||||
this.RefreshEnumList.Location = new System.Drawing.Point(544, 152);
|
||||
this.RefreshEnumList.Name = "RefreshEnumList";
|
||||
this.RefreshEnumList.Size = new System.Drawing.Size(72, 24);
|
||||
this.RefreshEnumList.TabIndex = 14;
|
||||
this.RefreshEnumList.Text = "Refresh";
|
||||
this.RefreshEnumList.Click += new System.EventHandler(this.RefreshEnumList_Click);
|
||||
//
|
||||
// NewSearchPathText
|
||||
//
|
||||
this.NewSearchPathText.Location = new System.Drawing.Point(152, 128);
|
||||
this.NewSearchPathText.Name = "NewSearchPathText";
|
||||
this.NewSearchPathText.Size = new System.Drawing.Size(248, 20);
|
||||
this.NewSearchPathText.TabIndex = 15;
|
||||
this.NewSearchPathText.Text = "";
|
||||
//
|
||||
// AddSearchPathButton
|
||||
//
|
||||
this.AddSearchPathButton.Location = new System.Drawing.Point(152, 152);
|
||||
this.AddSearchPathButton.Name = "AddSearchPathButton";
|
||||
this.AddSearchPathButton.Size = new System.Drawing.Size(72, 24);
|
||||
this.AddSearchPathButton.TabIndex = 9;
|
||||
this.AddSearchPathButton.Text = "Add Path";
|
||||
this.AddSearchPathButton.Click += new System.EventHandler(this.AddSearchPathButton_Click);
|
||||
//
|
||||
// RemovePathButton
|
||||
//
|
||||
this.RemovePathButton.Location = new System.Drawing.Point(232, 152);
|
||||
this.RemovePathButton.Name = "RemovePathButton";
|
||||
this.RemovePathButton.Size = new System.Drawing.Size(88, 24);
|
||||
this.RemovePathButton.TabIndex = 16;
|
||||
this.RemovePathButton.Text = "Remove Path";
|
||||
this.RemovePathButton.Click += new System.EventHandler(this.RemovePathButton_Click);
|
||||
//
|
||||
// RefreshSearchPathButton
|
||||
//
|
||||
this.RefreshSearchPathButton.Location = new System.Drawing.Point(328, 152);
|
||||
this.RefreshSearchPathButton.Name = "RefreshSearchPathButton";
|
||||
this.RefreshSearchPathButton.Size = new System.Drawing.Size(72, 24);
|
||||
this.RefreshSearchPathButton.TabIndex = 17;
|
||||
this.RefreshSearchPathButton.Text = "Refresh";
|
||||
this.RefreshSearchPathButton.Click += new System.EventHandler(this.RefreshSearchPathButton_Click);
|
||||
//
|
||||
// TestAppForm
|
||||
//
|
||||
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
|
||||
this.ClientSize = new System.Drawing.Size(624, 309);
|
||||
this.Controls.AddRange(new System.Windows.Forms.Control[] {
|
||||
this.RefreshSearchPathButton,
|
||||
this.RemovePathButton,
|
||||
this.NewSearchPathText,
|
||||
this.RefreshEnumList,
|
||||
this.label3,
|
||||
this.EnumList,
|
||||
this.EnumFilesPath,
|
||||
this.label1,
|
||||
this.SearchPathList,
|
||||
this.CDDrivesList,
|
||||
this.RefreshCDsButton,
|
||||
this.label2,
|
||||
this.AddSearchPathButton});
|
||||
this.Name = "TestAppForm";
|
||||
this.Text = "PhysFS Test Application";
|
||||
this.Load += new System.EventHandler(this.TestAppForm_Load);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.Run(new TestAppForm());
|
||||
}
|
||||
|
||||
private void TestAppForm_Load(object sender, System.EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void RefreshCDsButton_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
// Clear ths listbox if it contains any items
|
||||
CDDrivesList.Items.Clear();
|
||||
// Add the items to the list
|
||||
CDDrivesList.Items.AddRange(PhysFS.GetCDROMDrives());
|
||||
}
|
||||
|
||||
private void RefreshSearchPathButton_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
// Clear ths listbox if it contains any items
|
||||
SearchPathList.Items.Clear();
|
||||
// Add the items to the list
|
||||
SearchPathList.Items.AddRange(PhysFS.GetSearchPath());
|
||||
}
|
||||
|
||||
private void AddSearchPathButton_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
// Add search path
|
||||
PhysFS.AddToSearchPath(NewSearchPathText.Text, false);
|
||||
// Clear ths listbox if it contains any items
|
||||
SearchPathList.Items.Clear();
|
||||
// Add the items to the list
|
||||
SearchPathList.Items.AddRange(PhysFS.GetSearchPath());
|
||||
}
|
||||
|
||||
private void RemovePathButton_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
if(SearchPathList.SelectedItem != null)
|
||||
{
|
||||
PhysFS.RemoveFromSearchPath(SearchPathList.SelectedItem.ToString());
|
||||
// Clear ths listbox if it contains any items
|
||||
SearchPathList.Items.Clear();
|
||||
// Add the items to the list
|
||||
SearchPathList.Items.AddRange(PhysFS.GetSearchPath());
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshEnumList_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
EnumList.Items.Clear();
|
||||
EnumList.Items.AddRange(PhysFS.EnumerateFiles(EnumFilesPath.Text));
|
||||
}
|
||||
}
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 1.3
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">1.3</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1">this is my long string</data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
[base64 mime encoded serialized .NET Framework object]
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="$this.Name">
|
||||
<value>TestAppForm</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* stdio/physfs abstraction layer 2003-04-02
|
||||
*
|
||||
* Adam D. Moss <adam@gimp.org> <aspirin@icculus.org>
|
||||
*
|
||||
* These wrapper macros and functions are designed to allow a program
|
||||
* to perform file I/O with identical semantics and syntax regardless
|
||||
* of whether PhysicsFS is being used or not.
|
||||
*/
|
||||
#ifndef _ABS_FILE_H
|
||||
#define _ABS_FILE_H
|
||||
/*
|
||||
PLEASE NOTE: This license applies to abs-file.h ONLY (to make it clear that
|
||||
you may embed this wrapper code within commercial software); PhysicsFS itself
|
||||
is (at the time of writing) released under a different license with
|
||||
additional restrictions.
|
||||
|
||||
Copyright (C) 2002-2003 Adam D. Moss (the "Author"). All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is fur-
|
||||
nished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
|
||||
NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
|
||||
NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of the Author of the
|
||||
Software shall not be used in advertising or otherwise to promote the sale,
|
||||
use or other dealings in this Software without prior written authorization
|
||||
from the Author.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* API:
|
||||
*
|
||||
* Macro/function use like stdio equivalent...
|
||||
* -------------- ----------------------------
|
||||
* MY_FILETYPE FILE
|
||||
* MY_OPEN_FOR_READ fopen(..., "rb")
|
||||
* MY_READ fread(...)
|
||||
* MY_CLOSE fclose(...)
|
||||
* MY_GETC fgetc(...)
|
||||
* MY_GETS fgets(...)
|
||||
* MY_ATEOF feof(...)
|
||||
* MY_TELL ftell(...)
|
||||
* MY_SEEK fseek(..., SEEK_SET)
|
||||
* MY_REWIND rewind(...)
|
||||
* MY_SETBUFFER (not a standard for stdio, does nothing there)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Important DEFINEs:
|
||||
* It is important to define these consistantly across the various
|
||||
* compilation modules of your program if you wish to exchange file
|
||||
* handles between them.
|
||||
*
|
||||
* USE_PHYSFS: Define USE_PHYSFS if PhysicsFS is being used; note that if
|
||||
* you do intend to use PhysicsFS then you will still need to initialize
|
||||
* PhysicsFS yourself and set up its search-paths.
|
||||
*
|
||||
* Optional DEFINEs:
|
||||
*
|
||||
* PHYSFS_DEFAULT_READ_BUFFER <bytes>: If set then abs-file.h sets the
|
||||
* PhysicsFS buffer size to this value whenever you open a file. You
|
||||
* may over-ride this on a per-filehandle basis by using the
|
||||
* MY_SETBUFFER() macro (which simply does nothing when not using
|
||||
* PhysicsFS). If you have not defined this value explicitly then
|
||||
* abs-file.h will default to the same default buffer size as used by
|
||||
* stdio if it can be determined, or 8192 bytes otherwise.
|
||||
*/
|
||||
#ifndef PHYSFS_DEFAULT_READ_BUFFER
|
||||
#ifdef BUFSIZ
|
||||
#define PHYSFS_DEFAULT_READ_BUFFER BUFSIZ
|
||||
#else
|
||||
#define PHYSFS_DEFAULT_READ_BUFFER 8192
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_PHYSFS
|
||||
|
||||
#include <physfs.h>
|
||||
#define MY_FILETYPE PHYSFS_File
|
||||
#define MY_SETBUFFER(fp,size) PHYSFS_setBuffer(fp,size)
|
||||
#define MY_READ(p,s,n,fp) PHYSFS_read(fp,p,s,n)
|
||||
#if PHYSFS_DEFAULT_READ_BUFFER
|
||||
static MY_FILETYPE* MY_OPEN_FOR_READ(const char *const filename)
|
||||
{
|
||||
MY_FILETYPE *const file = PHYSFS_openRead(filename);
|
||||
if (file) {
|
||||
MY_SETBUFFER(file, PHYSFS_DEFAULT_READ_BUFFER);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
#else
|
||||
#define MY_OPEN_FOR_READ(fn) PHYSFS_openRead(fn)
|
||||
#endif
|
||||
static int MY_GETC(MY_FILETYPE *const fp) {
|
||||
unsigned char c;
|
||||
/*if (PHYSFS_eof(fp)) {
|
||||
return EOF;
|
||||
}
|
||||
MY_READ(&c, 1, 1, fp);*/
|
||||
if (MY_READ(&c, 1, 1, fp) != 1) {
|
||||
return EOF;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
static char * MY_GETS(char * const str, const int size,
|
||||
MY_FILETYPE *const fp) {
|
||||
int i = 0;
|
||||
int c;
|
||||
do {
|
||||
if (i == size-1) {
|
||||
break;
|
||||
}
|
||||
c = MY_GETC(fp);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
str[i++] = c;
|
||||
} while (c != '\0' &&
|
||||
c != -1 &&
|
||||
c != '\n');
|
||||
str[i] = '\0';
|
||||
if (i == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
#define MY_CLOSE(fp) PHYSFS_close(fp)
|
||||
#define MY_ATEOF(fp) PHYSFS_eof(fp)
|
||||
#define MY_TELL(fp) PHYSFS_tell(fp)
|
||||
#define MY_SEEK(fp,o) PHYSFS_seek(fp,o)
|
||||
#define MY_REWIND(fp) MY_SEEK(fp,0)
|
||||
|
||||
#else
|
||||
|
||||
#define MY_FILETYPE FILE
|
||||
#define MY_READ(p,s,n,fp) fread(p,s,n,fp)
|
||||
#define MY_OPEN_FOR_READ(n) fopen(n, "rb")
|
||||
#define MY_GETC(fp) fgetc(fp)
|
||||
#define MY_GETS(str,size,fp) fgets(str,size,fp)
|
||||
#define MY_CLOSE(fp) fclose(fp)
|
||||
#define MY_ATEOF(fp) feof(fp)
|
||||
#define MY_TELL(fp) ftell(fp)
|
||||
#define MY_SEEK(fp,o) fseek(fp,o, SEEK_SET)
|
||||
#define MY_REWIND(fp) rewind(fp)
|
||||
/*static void MY_SETBUFFER(const MY_FILETYPE *const file, const int num) { }*/
|
||||
#define MY_SETBUFFER(fp,size)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,239 @@
|
||||
/** \file globbing.c */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "globbing.h"
|
||||
|
||||
/**
|
||||
* Please see globbing.h for details.
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* \author Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
|
||||
static int matchesPattern(const char *fname, const char *wildcard,
|
||||
int caseSensitive)
|
||||
{
|
||||
char x, y;
|
||||
const char *fnameptr = fname;
|
||||
const char *wildptr = wildcard;
|
||||
|
||||
while ((*wildptr) && (*fnameptr))
|
||||
{
|
||||
y = *wildptr;
|
||||
if (y == '*')
|
||||
{
|
||||
do
|
||||
{
|
||||
wildptr++; /* skip multiple '*' in a row... */
|
||||
} while (*wildptr == '*');
|
||||
|
||||
y = (caseSensitive) ? *wildptr : (char) tolower(*wildptr);
|
||||
|
||||
while (1)
|
||||
{
|
||||
x = (caseSensitive) ? *fnameptr : (char) tolower(*fnameptr);
|
||||
if ((!x) || (x == y))
|
||||
break;
|
||||
else
|
||||
fnameptr++;
|
||||
} /* while */
|
||||
} /* if */
|
||||
|
||||
else if (y == '?')
|
||||
{
|
||||
wildptr++;
|
||||
fnameptr++;
|
||||
} /* else if */
|
||||
|
||||
else
|
||||
{
|
||||
if (caseSensitive)
|
||||
x = *fnameptr;
|
||||
else
|
||||
{
|
||||
x = tolower(*fnameptr);
|
||||
y = tolower(y);
|
||||
} /* if */
|
||||
|
||||
wildptr++;
|
||||
fnameptr++;
|
||||
|
||||
if (x != y)
|
||||
return 0;
|
||||
} /* else */
|
||||
} /* while */
|
||||
|
||||
while (*wildptr == '*')
|
||||
wildptr++;
|
||||
|
||||
return (*fnameptr == *wildptr);
|
||||
} /* matchesPattern */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const PHYSFS_Allocator *allocator;
|
||||
const char *wildcard;
|
||||
int caseSensitive;
|
||||
PHYSFS_EnumFilesCallback callback;
|
||||
void *origData;
|
||||
} WildcardCallbackData;
|
||||
|
||||
|
||||
/*
|
||||
* This callback sits between the enumerator and the enduser callback,
|
||||
* filtering out files that don't match the wildcard pattern.
|
||||
*/
|
||||
static void wildcardCallback(void *_d, const char *origdir, const char *fname)
|
||||
{
|
||||
const WildcardCallbackData *data = (const WildcardCallbackData *) _d;
|
||||
if (matchesPattern(fname, data->wildcard, data->caseSensitive))
|
||||
data->callback(data->origData, origdir, fname);
|
||||
} /* wildcardCallback */
|
||||
|
||||
|
||||
void PHYSFSEXT_enumerateFilesCallbackWildcard(const char *dir,
|
||||
const char *wildcard,
|
||||
int caseSensitive,
|
||||
PHYSFS_EnumFilesCallback c,
|
||||
void *d)
|
||||
{
|
||||
WildcardCallbackData data;
|
||||
data.allocator = PHYSFS_getAllocator();
|
||||
data.wildcard = wildcard;
|
||||
data.caseSensitive = caseSensitive;
|
||||
data.callback = c;
|
||||
data.origData = d;
|
||||
PHYSFS_enumerateFilesCallback(dir, wildcardCallback, &data);
|
||||
} /* PHYSFSEXT_enumerateFilesCallbackWildcard */
|
||||
|
||||
|
||||
void PHYSFSEXT_freeEnumeration(char **list)
|
||||
{
|
||||
const PHYSFS_Allocator *allocator = PHYSFS_getAllocator();
|
||||
int i;
|
||||
if (list != NULL)
|
||||
{
|
||||
for (i = 0; list[i] != NULL; i++)
|
||||
allocator->Free(list[i]);
|
||||
allocator->Free(list);
|
||||
} /* if */
|
||||
} /* PHYSFSEXT_freeEnumeration */
|
||||
|
||||
|
||||
char **PHYSFSEXT_enumerateFilesWildcard(const char *dir, const char *wildcard,
|
||||
int caseSensitive)
|
||||
{
|
||||
const PHYSFS_Allocator *allocator = PHYSFS_getAllocator();
|
||||
char **list = PHYSFS_enumerateFiles(dir);
|
||||
char **retval = NULL;
|
||||
int totalmatches = 0;
|
||||
int matches = 0;
|
||||
char **i;
|
||||
|
||||
for (i = list; *i != NULL; i++)
|
||||
{
|
||||
#if 0
|
||||
printf("matchesPattern: '%s' vs '%s' (%s) ... %s\n", *i, wildcard,
|
||||
caseSensitive ? "case" : "nocase",
|
||||
matchesPattern(*i, wildcard, caseSensitive) ? "true" : "false");
|
||||
#endif
|
||||
if (matchesPattern(*i, wildcard, caseSensitive))
|
||||
totalmatches++;
|
||||
} /* for */
|
||||
|
||||
retval = (char **) allocator->Malloc(sizeof (char *) * (totalmatches+1));
|
||||
if (retval != NULL)
|
||||
{
|
||||
for (i = list; ((matches < totalmatches) && (*i != NULL)); i++)
|
||||
{
|
||||
if (matchesPattern(*i, wildcard, caseSensitive))
|
||||
{
|
||||
retval[matches] = (char *) allocator->Malloc(strlen(*i) + 1);
|
||||
if (retval[matches] == NULL)
|
||||
{
|
||||
while (matches--)
|
||||
allocator->Free(retval[matches]);
|
||||
allocator->Free(retval);
|
||||
retval = NULL;
|
||||
break;
|
||||
} /* if */
|
||||
strcpy(retval[matches], *i);
|
||||
matches++;
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
if (retval != NULL)
|
||||
{
|
||||
assert(totalmatches == matches);
|
||||
retval[matches] = NULL;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
PHYSFS_freeList(list);
|
||||
return retval;
|
||||
} /* PHYSFSEXT_enumerateFilesWildcard */
|
||||
|
||||
|
||||
#ifdef TEST_PHYSFSEXT_ENUMERATEFILESWILDCARD
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int rc;
|
||||
char **flist;
|
||||
char **i;
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
printf("USAGE: %s <pattern> <caseSen>\n"
|
||||
" where <caseSen> is 1 or 0.\n", argv[0]);
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_init(): %s\n", PHYSFS_getLastError());
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_addToSearchPath(".", 1))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_addToSearchPath(): %s\n", PHYSFS_getLastError());
|
||||
PHYSFS_deinit();
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
flist = PHYSFSEXT_enumerateFilesWildcard("/", argv[1], atoi(argv[2]));
|
||||
rc = 0;
|
||||
for (i = flist; *i; i++)
|
||||
{
|
||||
printf("%s\n", *i);
|
||||
rc++;
|
||||
} /* for */
|
||||
printf("\n total %d files.\n\n", rc);
|
||||
|
||||
PHYSFSEXT_freeEnumeration(flist);
|
||||
PHYSFS_deinit();
|
||||
|
||||
return 0;
|
||||
} /* main */
|
||||
#endif
|
||||
|
||||
/* end of globbing.c ... */
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
#ifndef INCL_PHYSFSEXT_GLOBBING_H
|
||||
#define INCL_PHYSFSEXT_GLOBBING_H
|
||||
|
||||
/** \file globbing.h */
|
||||
|
||||
#include "physfs.h"
|
||||
|
||||
/**
|
||||
* \mainpage PhysicsFS globbing
|
||||
*
|
||||
* This is an extension to PhysicsFS to let you search for files with basic
|
||||
* wildcard matching, regardless of what sort of filesystem or archive they
|
||||
* reside in. It does this by enumerating directories as needed and manually
|
||||
* locating matching entries.
|
||||
*
|
||||
* Usage: Set up PhysicsFS as you normally would, then use
|
||||
* PHYSFSEXT_enumerateFilesWildcard() when enumerating files. This is just
|
||||
* like PHYSFS_enumerateFiles(), but it returns a subset that matches your
|
||||
* wildcard pattern. You must call PHYSFSEXT_freeEnumeration() on the results,
|
||||
* just PHYSFS_enumerateFiles() would do with PHYSFS_freeList().
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the source's "docs" directory.
|
||||
*
|
||||
* \author Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \fn char **PHYSFS_enumerateFilesWildcard(const char *dir, const char *wildcard, int caseSensitive)
|
||||
* \brief Get a file listing of a search path's directory, filtered with a wildcard pattern.
|
||||
*
|
||||
* Matching directories are interpolated. That is, if "C:\mydir" is in the
|
||||
* search path and contains a directory "savegames" that contains "x.sav",
|
||||
* "y.Sav", and "z.txt", and there is also a "C:\userdir" in the search path
|
||||
* that has a "savegames" subdirectory with "w.sav", then the following code:
|
||||
*
|
||||
* \code
|
||||
* char **rc = PHYSFS_enumerateFilesWildcard("savegames", "*.sav", 0);
|
||||
* char **i;
|
||||
*
|
||||
* for (i = rc; *i != NULL; i++)
|
||||
* printf(" * We've got [%s].\n", *i);
|
||||
*
|
||||
* PHYSFS_freeList(rc);
|
||||
* \endcode
|
||||
*
|
||||
* ...will print:
|
||||
*
|
||||
* \verbatim
|
||||
* We've got [x.sav].
|
||||
* We've got [y.Sav].
|
||||
* We've got [w.sav].\endverbatim
|
||||
*
|
||||
* Feel free to sort the list however you like. We only promise there will
|
||||
* be no duplicates, but not what order the final list will come back in.
|
||||
*
|
||||
* Wildcard strings can use the '*' and '?' characters, currently.
|
||||
* Matches can be case-insensitive if you pass a zero for argument 3.
|
||||
*
|
||||
* Don't forget to call PHYSFSEXT_freeEnumerator() with the return value from
|
||||
* this function when you are done with it. As we use PhysicsFS's allocator
|
||||
* for this list, you must free it before calling PHYSFS_deinit().
|
||||
* Do not use PHYSFS_freeList() on the returned value!
|
||||
*
|
||||
* \param dir directory in platform-independent notation to enumerate.
|
||||
* \param wildcard Wildcard pattern to use for filtering.
|
||||
* \param caseSensitive Zero for case-insensitive matching,
|
||||
* non-zero for case-sensitive.
|
||||
* \return Null-terminated array of null-terminated strings.
|
||||
*
|
||||
* \sa PHYSFSEXT_freeEnumeration
|
||||
*/
|
||||
PHYSFS_DECL char **PHYSFSEXT_enumerateFilesWildcard(const char *dir,
|
||||
const char *wildcard,
|
||||
int caseSensitive);
|
||||
|
||||
/**
|
||||
* \fn void PHYSFSEXT_freeEnumeration(char **list)
|
||||
* \brief Free data returned by PHYSFSEXT_enumerateFilesWildcard
|
||||
*
|
||||
* Conceptually, this works like PHYSFS_freeList(), but is used with data
|
||||
* returned by PHYSFSEXT_enumerateFilesWildcard() only. Be sure to call this
|
||||
* on any returned data from that function before
|
||||
*
|
||||
* \param list Pointer previously returned by
|
||||
* PHYSFSEXT_enumerateFilesWildcard(). It is safe to pass a
|
||||
* NULL here.
|
||||
*
|
||||
* \sa PHYSFSEXT_enumerateFilesWildcard
|
||||
*/
|
||||
PHYSFS_DECL void PHYSFSEXT_freeEnumeration(char **list);
|
||||
|
||||
|
||||
/**
|
||||
* \fn void PHYSFSEXT_enumerateFilesCallbackWildcard(const char *dir, const char *wildcard, int caseSensitive, PHYSFS_EnumFilesCallback c, void *d);
|
||||
* \brief Get a file listing of a search path's directory, filtered with a wildcard pattern, using an application-defined callback.
|
||||
*
|
||||
* This function is equivalent to PHYSFSEXT_enumerateFilesWildcard(). It
|
||||
* reports file listings, filtered by a wildcard pattern.
|
||||
*
|
||||
* Unlike PHYSFS_enumerateFiles(), this function does not return an array.
|
||||
* Rather, it calls a function specified by the application once per
|
||||
* element of the search path:
|
||||
*
|
||||
* \code
|
||||
*
|
||||
* static void printDir(void *data, const char *origdir, const char *fname)
|
||||
* {
|
||||
* printf(" * We've got [%s] in [%s].\n", fname, origdir);
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
* PHYSFS_enumerateFilesCallbackWildcard("savegames","*.sav",0,printDir,NULL);
|
||||
* \endcode
|
||||
*
|
||||
* Items sent to the callback are not guaranteed to be in any order whatsoever.
|
||||
* There is no sorting done at this level, and if you need that, you should
|
||||
* probably use PHYSFS_enumerateFilesWildcard() instead, which guarantees
|
||||
* alphabetical sorting. This form reports whatever is discovered in each
|
||||
* archive before moving on to the next. Even within one archive, we can't
|
||||
* guarantee what order it will discover data. <em>Any sorting you find in
|
||||
* these callbacks is just pure luck. Do not rely on it.</em> As this walks
|
||||
* the entire list of archives, you may receive duplicate filenames.
|
||||
*
|
||||
* Wildcard strings can use the '*' and '?' characters, currently.
|
||||
* Matches can be case-insensitive if you pass a zero for argument 3.
|
||||
*
|
||||
* \param dir Directory, in platform-independent notation, to enumerate.
|
||||
* \param wildcard Wildcard pattern to use for filtering.
|
||||
* \param caseSensitive Zero for case-insensitive matching,
|
||||
* non-zero for case-sensitive.
|
||||
* \param c Callback function to notify about search path elements.
|
||||
* \param d Application-defined data passed to callback. Can be NULL.
|
||||
*
|
||||
* \sa PHYSFS_EnumFilesCallback
|
||||
* \sa PHYSFS_enumerateFiles
|
||||
*/
|
||||
PHYSFS_DECL void PHYSFSEXT_enumerateFilesCallbackWildcard(const char *dir,
|
||||
const char *wildcard,
|
||||
int caseSensitive,
|
||||
PHYSFS_EnumFilesCallback c,
|
||||
void *d);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* include-once blocker. */
|
||||
|
||||
/* end of globbing.h ... */
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
/** \file ignorecase.c */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "physfs.h"
|
||||
#include "ignorecase.h"
|
||||
|
||||
/**
|
||||
* Please see ignorecase.h for details.
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* \author Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
/* I'm not screwing around with stricmp vs. strcasecmp... */
|
||||
/* !!! FIXME: this will NOT work with UTF-8 strings in physfs2.0 */
|
||||
static int caseInsensitiveStringCompare(const char *x, const char *y)
|
||||
{
|
||||
int ux, uy;
|
||||
do
|
||||
{
|
||||
ux = toupper((int) *x);
|
||||
uy = toupper((int) *y);
|
||||
if (ux != uy)
|
||||
return ((ux > uy) ? 1 : -1);
|
||||
x++;
|
||||
y++;
|
||||
} while ((ux) && (uy));
|
||||
|
||||
return 0;
|
||||
} /* caseInsensitiveStringCompare */
|
||||
|
||||
|
||||
static int locateOneElement(char *buf)
|
||||
{
|
||||
char *ptr;
|
||||
char **rc;
|
||||
char **i;
|
||||
|
||||
if (PHYSFS_exists(buf))
|
||||
return 1; /* quick rejection: exists in current case. */
|
||||
|
||||
ptr = strrchr(buf, '/'); /* find entry at end of path. */
|
||||
if (ptr == NULL)
|
||||
{
|
||||
rc = PHYSFS_enumerateFiles("/");
|
||||
ptr = buf;
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
*ptr = '\0';
|
||||
rc = PHYSFS_enumerateFiles(buf);
|
||||
*ptr = '/';
|
||||
ptr++; /* point past dirsep to entry itself. */
|
||||
} /* else */
|
||||
|
||||
for (i = rc; *i != NULL; i++)
|
||||
{
|
||||
if (caseInsensitiveStringCompare(*i, ptr) == 0)
|
||||
{
|
||||
strcpy(ptr, *i); /* found a match. Overwrite with this case. */
|
||||
PHYSFS_freeList(rc);
|
||||
return 1;
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
/* no match at all... */
|
||||
PHYSFS_freeList(rc);
|
||||
return 0;
|
||||
} /* locateOneElement */
|
||||
|
||||
|
||||
int PHYSFSEXT_locateCorrectCase(char *buf)
|
||||
{
|
||||
int rc;
|
||||
char *ptr;
|
||||
char *prevptr;
|
||||
|
||||
while (*buf == '/') /* skip any '/' at start of string... */
|
||||
buf++;
|
||||
|
||||
ptr = prevptr = buf;
|
||||
if (*ptr == '\0')
|
||||
return 0; /* Uh...I guess that's success. */
|
||||
|
||||
while ( (ptr = strchr(ptr + 1, '/')) != NULL )
|
||||
{
|
||||
*ptr = '\0'; /* block this path section off */
|
||||
rc = locateOneElement(buf);
|
||||
*ptr = '/'; /* restore path separator */
|
||||
if (!rc)
|
||||
return -2; /* missing element in path. */
|
||||
} /* while */
|
||||
|
||||
/* check final element... */
|
||||
return locateOneElement(buf) ? 0 : -1;
|
||||
} /* PHYSFSEXT_locateCorrectCase */
|
||||
|
||||
|
||||
#ifdef TEST_PHYSFSEXT_LOCATECORRECTCASE
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int rc;
|
||||
char buf[128];
|
||||
PHYSFS_File *f;
|
||||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_init(): %s\n", PHYSFS_getLastError());
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_addToSearchPath(".", 1))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_addToSearchPath(): %s\n", PHYSFS_getLastError());
|
||||
PHYSFS_deinit();
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_setWriteDir("."))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_setWriteDir(): %s\n", PHYSFS_getLastError());
|
||||
PHYSFS_deinit();
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_mkdir("/a/b/c"))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_mkdir(): %s\n", PHYSFS_getLastError());
|
||||
PHYSFS_deinit();
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_mkdir("/a/b/C"))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_mkdir(): %s\n", PHYSFS_getLastError());
|
||||
PHYSFS_deinit();
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
f = PHYSFS_openWrite("/a/b/c/x.txt");
|
||||
PHYSFS_close(f);
|
||||
if (f == NULL)
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_openWrite(): %s\n", PHYSFS_getLastError());
|
||||
PHYSFS_deinit();
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
f = PHYSFS_openWrite("/a/b/C/X.txt");
|
||||
PHYSFS_close(f);
|
||||
if (f == NULL)
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_openWrite(): %s\n", PHYSFS_getLastError());
|
||||
PHYSFS_deinit();
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
strcpy(buf, "/a/b/c/x.txt");
|
||||
rc = PHYSFSEXT_locateCorrectCase(buf);
|
||||
if ((rc != 0) || (strcmp(buf, "/a/b/c/x.txt") != 0))
|
||||
printf("test 1 failed\n");
|
||||
|
||||
strcpy(buf, "/a/B/c/x.txt");
|
||||
rc = PHYSFSEXT_locateCorrectCase(buf);
|
||||
if ((rc != 0) || (strcmp(buf, "/a/b/c/x.txt") != 0))
|
||||
printf("test 2 failed\n");
|
||||
|
||||
strcpy(buf, "/a/b/C/x.txt");
|
||||
rc = PHYSFSEXT_locateCorrectCase(buf);
|
||||
if ((rc != 0) || (strcmp(buf, "/a/b/C/X.txt") != 0))
|
||||
printf("test 3 failed\n");
|
||||
|
||||
strcpy(buf, "/a/b/c/X.txt");
|
||||
rc = PHYSFSEXT_locateCorrectCase(buf);
|
||||
if ((rc != 0) || (strcmp(buf, "/a/b/c/x.txt") != 0))
|
||||
printf("test 4 failed\n");
|
||||
|
||||
strcpy(buf, "/a/b/c/z.txt");
|
||||
rc = PHYSFSEXT_locateCorrectCase(buf);
|
||||
if ((rc != -1) || (strcmp(buf, "/a/b/c/z.txt") != 0))
|
||||
printf("test 5 failed\n");
|
||||
|
||||
strcpy(buf, "/A/B/Z/z.txt");
|
||||
rc = PHYSFSEXT_locateCorrectCase(buf);
|
||||
if ((rc != -2) || (strcmp(buf, "/a/b/Z/z.txt") != 0))
|
||||
printf("test 6 failed\n");
|
||||
|
||||
printf("Testing completed.\n");
|
||||
printf(" If no errors were reported, you're good to go.\n");
|
||||
|
||||
PHYSFS_delete("/a/b/c/x.txt");
|
||||
PHYSFS_delete("/a/b/C/X.txt");
|
||||
PHYSFS_delete("/a/b/c");
|
||||
PHYSFS_delete("/a/b/C");
|
||||
PHYSFS_delete("/a/b");
|
||||
PHYSFS_delete("/a");
|
||||
PHYSFS_deinit();
|
||||
return 0;
|
||||
} /* main */
|
||||
#endif
|
||||
|
||||
/* end of ignorecase.c ... */
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
#ifndef INCL_PHYSFSEXT_IGNORECASE_H
|
||||
#define INCL_PHYSFSEXT_IGNORECASE_H
|
||||
|
||||
/** \file ignorecase.h */
|
||||
|
||||
/**
|
||||
* \mainpage PhysicsFS ignorecase
|
||||
*
|
||||
* This is an extension to PhysicsFS to let you handle files in a
|
||||
* case-insensitive manner, regardless of what sort of filesystem or
|
||||
* archive they reside in. It does this by enumerating directories as
|
||||
* needed and manually locating matching entries.
|
||||
*
|
||||
* Please note that this brings with it some caveats:
|
||||
* - On filesystems that are case-insensitive to start with, such as those
|
||||
* used on Windows or MacOS, you are adding extra overhead.
|
||||
* - On filesystems that are case-sensitive, you might select the wrong dir
|
||||
* or file (which brings security considerations and potential bugs). This
|
||||
* code favours exact case matches, but you will lose access to otherwise
|
||||
* duplicate filenames, or you might go down a wrong directory tree, etc.
|
||||
* In practive, this is rarely a problem, but you need to be aware of it.
|
||||
* - This doesn't do _anything_ with the write directory; you're on your
|
||||
* own for opening the right files for writing. You can sort of get around
|
||||
* this by adding your write directory to the search path, but then the
|
||||
* interpolated directory tree can screw you up even more.
|
||||
*
|
||||
* This code should be considered an aid for legacy code. New development
|
||||
* shouldn't do dumbass things that require this aid in the first place. :)
|
||||
*
|
||||
* Usage: Set up PhysicsFS as you normally would, then use
|
||||
* PHYSFSEXT_locateCorrectCase() to get a "correct" pathname to pass to
|
||||
* functions like PHYSFS_openRead(), etc.
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* \author Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \fn int PHYSFSEXT_locateCorrectCase(char *buf)
|
||||
* \brief Find an existing filename with matching case.
|
||||
*
|
||||
* This function will look for a path/filename that matches the passed in
|
||||
* buffer. Each element of the buffer's path is checked for a
|
||||
* case-insensitive match. The buffer must specify a null-terminated string
|
||||
* in platform-independent notation.
|
||||
*
|
||||
* Please note results may be skewed differently depending on whether symlinks
|
||||
* are enabled or not.
|
||||
*
|
||||
* Each element of the buffer is overwritten with the actual case of an
|
||||
* existing match. If there is no match, the search aborts and reports an
|
||||
* error. Exact matches are favored over case-insensitive matches.
|
||||
*
|
||||
* THIS IS RISKY. Please do not use this function for anything but crappy
|
||||
* legacy code.
|
||||
*
|
||||
* \param buf Buffer with null-terminated string of path/file to locate.
|
||||
* This buffer will be modified by this function.
|
||||
* \return zero if match was found, -1 if the final element (the file itself)
|
||||
* is missing, -2 if one of the parent directories is missing.
|
||||
*/
|
||||
int PHYSFSEXT_locateCorrectCase(char *buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* include-once blocker. */
|
||||
|
||||
/* end of ignorecase.h ... */
|
||||
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
print <<__EOF__;
|
||||
/*
|
||||
* This file is part of PhysicsFS (http://icculus.org/physfs/)
|
||||
*
|
||||
* This data generated by physfs/extras/makecasefoldhashtable.pl ...
|
||||
* Do not manually edit this file!
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*/
|
||||
|
||||
#ifndef __PHYSICSFS_INTERNAL__
|
||||
#error Do not include this header from your applications.
|
||||
#endif
|
||||
|
||||
__EOF__
|
||||
|
||||
|
||||
my @foldPairs;
|
||||
|
||||
for (my $i = 0; $i < 256; $i++) {
|
||||
$foldPairs[$i] = '';
|
||||
}
|
||||
|
||||
open(FH,'<','casefolding.txt') or die("failed to open casefolding.txt: $!\n");
|
||||
while (<FH>) {
|
||||
chomp;
|
||||
# strip comments from textfile...
|
||||
s/\#.*\Z//;
|
||||
|
||||
# strip whitespace...
|
||||
s/\A\s+//;
|
||||
s/\s+\Z//;
|
||||
|
||||
next if not /\A([a-fA-F0-9]+)\;\s*(.)\;\s*(.+)\;/;
|
||||
my ($code, $status, $mapping) = ($1, $2, $3);
|
||||
my $hexxed = hex($code);
|
||||
my $hashed = (($hexxed ^ ($hexxed >> 8)) & 0xFF);
|
||||
#print("// code '$code' status '$status' mapping '$mapping'\n");
|
||||
#print("// hexxed '$hexxed' hashed '$hashed'\n");
|
||||
|
||||
if (($status eq 'C') or ($status eq 'F')) {
|
||||
my ($map1, $map2, $map3) = ('0000', '0000', '0000');
|
||||
$map1 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
|
||||
$map2 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
|
||||
$map3 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
|
||||
die("mapping space too small for '$code'\n") if ($mapping ne '');
|
||||
$foldPairs[$hashed] .= " { 0x$code, 0x$map1, 0x$map2, 0x$map3 },\n";
|
||||
}
|
||||
}
|
||||
close(FH);
|
||||
|
||||
for (my $i = 0; $i < 256; $i++) {
|
||||
$foldPairs[$i] =~ s/,\n\Z//;
|
||||
my $str = $foldPairs[$i];
|
||||
next if $str eq '';
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold_${num}";
|
||||
print("static const CaseFoldMapping ${sym}[] = {\n$str\n};\n\n");
|
||||
}
|
||||
|
||||
print("\nstatic const CaseFoldHashBucket case_fold_hash[256] = {\n");
|
||||
|
||||
for (my $i = 0; $i < 256; $i++) {
|
||||
my $str = $foldPairs[$i];
|
||||
if ($str eq '') {
|
||||
print(" { 0, NULL },\n");
|
||||
} else {
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold_${num}";
|
||||
print(" { __PHYSFS_ARRAYLEN($sym), $sym },\n");
|
||||
}
|
||||
}
|
||||
print("};\n\n");
|
||||
|
||||
exit 0;
|
||||
|
||||
# end of makecashfoldhashtable.pl ...
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/* Metadata to generate the scripting language bindings. Please ignore. */
|
||||
%module physfs
|
||||
|
||||
%{
|
||||
#include "physfs.h"
|
||||
%}
|
||||
|
||||
/* I _think_ this is safe for now. */
|
||||
%warnfilter(451) PHYSFS_ArchiveInfo;
|
||||
|
||||
%ignore _INCLUDE_PHYSFS_H_; /* ignore the include-once blocker. */
|
||||
%ignore PHYSFS_DECL; /* ignore the export define. */
|
||||
%ignore PHYSFS_CALL; /* ignore the calling conventions define. */
|
||||
%ignore PHYSFS_DEPRECATED; /* ignore the deprecation define. */
|
||||
%ignore PHYSFS_file; /* legacy type define. */
|
||||
|
||||
/* Some bindings put everything in a namespace, so we don't need PHYSFS_ */
|
||||
#if defined(SWIGPERL) || defined(SWIGRUBY)
|
||||
%rename(File) PHYSFS_File;
|
||||
%rename(Version) PHYSFS_Version;
|
||||
%rename(ArchiveInfo) PHYSFS_ArchiveInfo;
|
||||
%rename(getLinkedVersion) PHYSFS_getLinkedVersion;
|
||||
%rename(init) PHYSFS_init;
|
||||
%rename(deinit) PHYSFS_deinit;
|
||||
%rename(supportedArchiveTypes) PHYSFS_supportedArchiveTypes;
|
||||
%rename(freeList) PHYSFS_freeList;
|
||||
%rename(getLastError) PHYSFS_getLastError;
|
||||
%rename(getDirSeparator) PHYSFS_getDirSeparator;
|
||||
%rename(permitSymbolicLinks) PHYSFS_permitSymbolicLinks;
|
||||
%rename(getCdRomDirs) PHYSFS_getCdRomDirs;
|
||||
%rename(getBaseDir) PHYSFS_getBaseDir;
|
||||
%rename(getUserDir) PHYSFS_getUserDir;
|
||||
%rename(getWriteDir) PHYSFS_getWriteDir;
|
||||
%rename(setWriteDir) PHYSFS_setWriteDir;
|
||||
%rename(addToSearchPath) PHYSFS_addToSearchPath;
|
||||
%rename(removeFromSearchPath) PHYSFS_removeFromSearchPath;
|
||||
%rename(getSearchPath) PHYSFS_getSearchPath;
|
||||
%rename(setSaneConfig) PHYSFS_setSaneConfig;
|
||||
%rename(mkdir) PHYSFS_mkdir;
|
||||
%rename(delete) PHYSFS_delete;
|
||||
%rename(getRealDir) PHYSFS_getRealDir;
|
||||
%rename(enumerateFiles) PHYSFS_enumerateFiles;
|
||||
%rename(exists) PHYSFS_exists;
|
||||
%rename(isDirectory) PHYSFS_isDirectory;
|
||||
%rename(isSymbolicLink) PHYSFS_isSymbolicLink;
|
||||
%rename(getLastModTime) PHYSFS_getLastModTime;
|
||||
%rename(openWrite) PHYSFS_openWrite;
|
||||
%rename(openAppend) PHYSFS_openAppend;
|
||||
%rename(openRead) PHYSFS_openRead;
|
||||
%rename(close) PHYSFS_close;
|
||||
%rename(read) PHYSFS_read;
|
||||
%rename(write) PHYSFS_write;
|
||||
%rename(eof) PHYSFS_eof;
|
||||
%rename(tell) PHYSFS_tell;
|
||||
%rename(seek) PHYSFS_seek;
|
||||
%rename(fileLength) PHYSFS_fileLength;
|
||||
%rename(setBuffer) PHYSFS_setBuffer;
|
||||
%rename(flush) PHYSFS_flush;
|
||||
%rename(readSLE16) PHYSFS_readSLE16;
|
||||
%rename(readULE16) PHYSFS_readULE16;
|
||||
%rename(readSBE16) PHYSFS_readSBE16;
|
||||
%rename(readUBE16) PHYSFS_readUBE16;
|
||||
%rename(readSLE32) PHYSFS_readSLE32;
|
||||
%rename(readULE32) PHYSFS_readULE32;
|
||||
%rename(readSBE32) PHYSFS_readSBE32;
|
||||
%rename(readUBE32) PHYSFS_readUBE32;
|
||||
%rename(readSLE64) PHYSFS_readSLE64;
|
||||
%rename(readULE64) PHYSFS_readULE64;
|
||||
%rename(readSBE64) PHYSFS_readSBE64;
|
||||
%rename(readUBE64) PHYSFS_readUBE64;
|
||||
%rename(writeSLE16) PHYSFS_writeSLE16;
|
||||
%rename(writeULE16) PHYSFS_writeULE16;
|
||||
%rename(writeSBE16) PHYSFS_writeSBE16;
|
||||
%rename(writeUBE16) PHYSFS_writeUBE16;
|
||||
%rename(writeSLE32) PHYSFS_writeSLE32;
|
||||
%rename(writeULE32) PHYSFS_writeULE32;
|
||||
%rename(writeSBE32) PHYSFS_writeSBE32;
|
||||
%rename(writeUBE32) PHYSFS_writeUBE32;
|
||||
%rename(writeSLE64) PHYSFS_writeSLE64;
|
||||
%rename(writeULE64) PHYSFS_writeULE64;
|
||||
%rename(writeSBE64) PHYSFS_writeSBE64;
|
||||
%rename(writeUBE64) PHYSFS_writeUBE64;
|
||||
%rename(isInit) PHYSFS_isInit;
|
||||
%rename(symbolicLinksPermitted) PHYSFS_symbolicLinksPermitted;
|
||||
%rename(mount) PHYSFS_mount;
|
||||
%rename(getMountPoint) PHYSFS_getMountPoint;
|
||||
%rename(Stat) PHYSFS_Stat; /* !!! FIXME: case insensitive script languages? */
|
||||
%rename(stat) PHYSFS_stat;
|
||||
%rename(readBytes) PHYSFS_readBytes;
|
||||
%rename(writeBytes) PHYSFS_writeBytes;
|
||||
%rename(unmount) PHYSFS_unmount;
|
||||
%rename(mountMemory) PHYSFS_mountMemory;
|
||||
%rename(mountHandle) PHYSFS_mountHandle;
|
||||
%rename(getPrefDir) PHYSFS_getPrefDir;
|
||||
#endif
|
||||
|
||||
%include "../src/physfs.h"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: PhysicsFS
|
||||
Description: PhysicsFS is a library to provide abstract access to various archives.
|
||||
URL: https://icculus.org/physfs/
|
||||
Version: @PHYSFS_VERSION@
|
||||
Libs: -L${libdir} -lphysfs
|
||||
Cflags: -I${includedir}
|
||||
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* This is a quick and dirty HTTP server that uses PhysicsFS to retrieve
|
||||
* files. It is not robust at all, probably buggy, and definitely poorly
|
||||
* designed. It's just meant to show that it can be done.
|
||||
*
|
||||
* Basically, you compile this code, and run it:
|
||||
* ./physfshttpd archive1.zip archive2.zip /path/to/a/real/dir etc...
|
||||
*
|
||||
* The files are appended in order to the PhysicsFS search path, and when
|
||||
* a client request comes it, it looks for the file in said search path.
|
||||
*
|
||||
* My goal was to make this work in less than 300 lines of C, so again, it's
|
||||
* not to be used for any serious purpose. Patches to make this application
|
||||
* suck less will be readily and gratefully accepted.
|
||||
*
|
||||
* Command line I used to build this on Linux:
|
||||
* gcc -Wall -Werror -g -o bin/physfshttpd extras/physfshttpd.c -lphysfs
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#ifndef LACKING_SIGNALS
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#ifndef LACKING_PROTOENT
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include "physfs.h"
|
||||
|
||||
|
||||
#define DEFAULT_PORTNUM 6667
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int sock;
|
||||
struct sockaddr *addr;
|
||||
socklen_t addrlen;
|
||||
} http_args;
|
||||
|
||||
|
||||
static char *txt404 =
|
||||
"HTTP/1.0 404 Not Found\n"
|
||||
"Connection: close\n"
|
||||
"Content-Type: text/html; charset=utf-8\n"
|
||||
"\n"
|
||||
"<html><head><title>404 Not Found</title></head>\n"
|
||||
"<body>Can't find that.</body></html>\n\n";
|
||||
|
||||
|
||||
static void feed_file_http(const char *ipstr, int sock, const char *fname)
|
||||
{
|
||||
PHYSFS_File *in = PHYSFS_openRead(fname);
|
||||
char buffer[1024];
|
||||
printf("%s: requested [%s].\n", ipstr, fname);
|
||||
if (in == NULL)
|
||||
{
|
||||
printf("%s: Can't open [%s]: %s.\n",
|
||||
ipstr, fname, PHYSFS_getLastError());
|
||||
write(sock, txt404, strlen(txt404)); /* !!! FIXME: Check retval */
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
PHYSFS_sint64 br = PHYSFS_read(in, buffer, 1, sizeof (buffer));
|
||||
if (br == -1)
|
||||
{
|
||||
printf("%s: Read error: %s.\n", ipstr, PHYSFS_getLastError());
|
||||
break;
|
||||
} /* if */
|
||||
|
||||
write(sock, buffer, (int) br); /* !!! FIXME: CHECK THIS RETVAL! */
|
||||
} while (!PHYSFS_eof(in));
|
||||
|
||||
PHYSFS_close(in);
|
||||
} /* else */
|
||||
} /* feed_file_http */
|
||||
|
||||
|
||||
static void *do_http(void *_args)
|
||||
{
|
||||
http_args *args = (http_args *) _args;
|
||||
char ipstr[128];
|
||||
char buffer[512];
|
||||
char *ptr;
|
||||
strncpy(ipstr, inet_ntoa(((struct sockaddr_in *) args->addr)->sin_addr),
|
||||
sizeof (ipstr));
|
||||
ipstr[sizeof (ipstr) - 1] = '\0';
|
||||
|
||||
printf("%s: connected.\n", ipstr);
|
||||
read(args->sock, buffer, sizeof (buffer));
|
||||
buffer[sizeof (buffer) - 1] = '\0';
|
||||
ptr = strchr(buffer, '\n');
|
||||
if (!ptr)
|
||||
printf("%s: potentially bogus request.\n", ipstr);
|
||||
else
|
||||
{
|
||||
*ptr = '\0';
|
||||
ptr = strchr(buffer, '\r');
|
||||
if (ptr != NULL)
|
||||
*ptr = '\0';
|
||||
|
||||
if ((toupper(buffer[0]) == 'G') &&
|
||||
(toupper(buffer[1]) == 'E') &&
|
||||
(toupper(buffer[2]) == 'T') &&
|
||||
(toupper(buffer[3]) == ' ') &&
|
||||
(toupper(buffer[4]) == '/'))
|
||||
{
|
||||
ptr = strchr(buffer + 5, ' ');
|
||||
if (ptr != NULL)
|
||||
*ptr = '\0';
|
||||
feed_file_http(ipstr, args->sock, buffer + 4);
|
||||
} /* if */
|
||||
} /* else */
|
||||
|
||||
/* !!! FIXME: Time the transfer. */
|
||||
printf("%s: closing connection.\n", ipstr);
|
||||
close(args->sock);
|
||||
free(args->addr);
|
||||
free(args);
|
||||
return NULL;
|
||||
} /* do_http */
|
||||
|
||||
|
||||
static void serve_http_request(int sock, struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
http_args *args = (http_args *) malloc(sizeof (http_args));
|
||||
if (args == NULL)
|
||||
{
|
||||
printf("out of memory.\n");
|
||||
return;
|
||||
} /* if */
|
||||
args->addr = (struct sockaddr *) malloc(addrlen);
|
||||
if (args->addr == NULL)
|
||||
{
|
||||
free(args);
|
||||
printf("out of memory.\n");
|
||||
return;
|
||||
} /* if */
|
||||
|
||||
args->sock = sock;
|
||||
args->addrlen = addrlen;
|
||||
memcpy(args->addr, addr, addrlen);
|
||||
|
||||
/* !!! FIXME: optionally spin a thread... */
|
||||
do_http((void *) args);
|
||||
} /* server_http_request */
|
||||
|
||||
|
||||
static int create_listen_socket(short portnum)
|
||||
{
|
||||
int retval = -1;
|
||||
int protocol = 0; /* pray this is right. */
|
||||
|
||||
#ifndef LACKING_PROTOENT
|
||||
struct protoent *prot;
|
||||
setprotoent(0);
|
||||
prot = getprotobyname("tcp");
|
||||
if (prot != NULL)
|
||||
protocol = prot->p_proto;
|
||||
#endif
|
||||
|
||||
retval = socket(PF_INET, SOCK_STREAM, protocol);
|
||||
if (retval >= 0)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(portnum);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
if ((bind(retval, &addr, (socklen_t) sizeof (addr)) == -1) ||
|
||||
(listen(retval, 5) == -1))
|
||||
{
|
||||
close(retval);
|
||||
retval = -1;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
return retval;
|
||||
} /* create_listen_socket */
|
||||
|
||||
|
||||
static int listensocket = -1;
|
||||
|
||||
void at_exit_cleanup(void)
|
||||
{
|
||||
/*
|
||||
* !!! FIXME: If thread support, signal threads to terminate and
|
||||
* !!! FIXME: wait for them to clean up.
|
||||
*/
|
||||
|
||||
if (listensocket >= 0)
|
||||
close(listensocket);
|
||||
|
||||
if (!PHYSFS_deinit())
|
||||
printf("PHYSFS_deinit() failed: %s\n", PHYSFS_getLastError());
|
||||
} /* at_exit_cleanup */
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
int portnum = DEFAULT_PORTNUM;
|
||||
|
||||
setbuf(stdout, NULL);
|
||||
setbuf(stderr, NULL);
|
||||
|
||||
#ifndef LACKING_SIGNALS
|
||||
/* I'm not sure if this qualifies as a cheap trick... */
|
||||
signal(SIGTERM, exit);
|
||||
signal(SIGINT, exit);
|
||||
signal(SIGFPE, exit);
|
||||
signal(SIGSEGV, exit);
|
||||
signal(SIGPIPE, exit);
|
||||
signal(SIGILL, exit);
|
||||
#endif
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
printf("USAGE: %s <archive1> [archive2 [... archiveN]]\n", argv[0]);
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
printf("PHYSFS_init() failed: %s\n", PHYSFS_getLastError());
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
/* normally, this is bad practice, but oh well. */
|
||||
atexit(at_exit_cleanup);
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (!PHYSFS_addToSearchPath(argv[i], 1))
|
||||
printf(" WARNING: failed to add [%s] to search path.\n", argv[i]);
|
||||
} /* else */
|
||||
|
||||
listensocket = create_listen_socket(portnum);
|
||||
if (listensocket < 0)
|
||||
{
|
||||
printf("listen socket failed to create.\n");
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
while (1) /* infinite loop for now. */
|
||||
{
|
||||
struct sockaddr addr;
|
||||
socklen_t len;
|
||||
int s = accept(listensocket, &addr, &len);
|
||||
if (s < 0)
|
||||
{
|
||||
printf("accept() failed: %s\n", strerror(errno));
|
||||
close(listensocket);
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
serve_http_request(s, &addr, len);
|
||||
} /* while */
|
||||
|
||||
return 0;
|
||||
} /* main */
|
||||
|
||||
/* end of physfshttpd.c ... */
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* This code provides a glue layer between PhysicsFS and Simple Directmedia
|
||||
* Layer's (SDL) RWops i/o abstraction.
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* SDL 1.2 falls under the LGPL license. SDL 1.3+ is zlib, like PhysicsFS.
|
||||
* You can get SDL at http://www.libsdl.org/
|
||||
*
|
||||
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
|
||||
*/
|
||||
|
||||
#include <stdio.h> /* used for SEEK_SET, SEEK_CUR, SEEK_END ... */
|
||||
#include "physfsrwops.h"
|
||||
|
||||
/* SDL's RWOPS interface changed a little in SDL 1.3... */
|
||||
#if defined(SDL_VERSION_ATLEAST)
|
||||
#if SDL_VERSION_ATLEAST(1, 3, 0)
|
||||
#define TARGET_SDL13 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if TARGET_SDL13
|
||||
static long SDLCALL physfsrwops_seek(struct SDL_RWops *rw, long offset, int whence)
|
||||
#else
|
||||
static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
|
||||
#endif
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
PHYSFS_sint64 pos = 0;
|
||||
|
||||
if (whence == SEEK_SET)
|
||||
pos = (PHYSFS_sint64) offset;
|
||||
|
||||
else if (whence == SEEK_CUR)
|
||||
{
|
||||
const PHYSFS_sint64 current = PHYSFS_tell(handle);
|
||||
if (current == -1)
|
||||
{
|
||||
SDL_SetError("Can't find position in file: %s",
|
||||
PHYSFS_getLastError());
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
if (offset == 0) /* this is a "tell" call. We're done. */
|
||||
{
|
||||
#if TARGET_SDL13
|
||||
return (long) current;
|
||||
#else
|
||||
return (int) current;
|
||||
#endif
|
||||
} /* if */
|
||||
|
||||
pos = current + ((PHYSFS_sint64) offset);
|
||||
} /* else if */
|
||||
|
||||
else if (whence == SEEK_END)
|
||||
{
|
||||
const PHYSFS_sint64 len = PHYSFS_fileLength(handle);
|
||||
if (len == -1)
|
||||
{
|
||||
SDL_SetError("Can't find end of file: %s", PHYSFS_getLastError());
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
pos = len + ((PHYSFS_sint64) offset);
|
||||
} /* else if */
|
||||
|
||||
else
|
||||
{
|
||||
SDL_SetError("Invalid 'whence' parameter.");
|
||||
return -1;
|
||||
} /* else */
|
||||
|
||||
if ( pos < 0 )
|
||||
{
|
||||
SDL_SetError("Attempt to seek past start of file.");
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_seek(handle, (PHYSFS_uint64) pos))
|
||||
{
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
#if TARGET_SDL13
|
||||
return (long) pos;
|
||||
#else
|
||||
return (int) pos;
|
||||
#endif
|
||||
} /* physfsrwops_seek */
|
||||
|
||||
|
||||
#if TARGET_SDL13
|
||||
static size_t SDLCALL physfsrwops_read(struct SDL_RWops *rw, void *ptr,
|
||||
size_t size, size_t maxnum)
|
||||
#else
|
||||
static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
|
||||
#endif
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
const PHYSFS_uint64 readlen = (PHYSFS_uint64) (maxnum * size);
|
||||
const PHYSFS_sint64 rc = PHYSFS_readBytes(handle, ptr, readlen);
|
||||
if (rc != ((PHYSFS_sint64) readlen))
|
||||
{
|
||||
if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
} /* if */
|
||||
|
||||
#if TARGET_SDL13
|
||||
return (size_t) rc;
|
||||
#else
|
||||
return (int) rc;
|
||||
#endif
|
||||
} /* physfsrwops_read */
|
||||
|
||||
|
||||
#if TARGET_SDL13
|
||||
static size_t SDLCALL physfsrwops_write(struct SDL_RWops *rw, const void *ptr,
|
||||
size_t size, size_t num)
|
||||
#else
|
||||
static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
|
||||
#endif
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
const PHYSFS_uint64 writelen = (PHYSFS_uint64) (num * size);
|
||||
const PHYSFS_sint64 rc = PHYSFS_writeBytes(handle, ptr, writelen);
|
||||
if (rc != ((PHYSFS_sint64) writelen))
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
|
||||
#if TARGET_SDL13
|
||||
return (size_t) rc;
|
||||
#else
|
||||
return (int) rc;
|
||||
#endif
|
||||
} /* physfsrwops_write */
|
||||
|
||||
|
||||
static int physfsrwops_close(SDL_RWops *rw)
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
if (!PHYSFS_close(handle))
|
||||
{
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
SDL_FreeRW(rw);
|
||||
return 0;
|
||||
} /* physfsrwops_close */
|
||||
|
||||
|
||||
static SDL_RWops *create_rwops(PHYSFS_File *handle)
|
||||
{
|
||||
SDL_RWops *retval = NULL;
|
||||
|
||||
if (handle == NULL)
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
else
|
||||
{
|
||||
retval = SDL_AllocRW();
|
||||
if (retval != NULL)
|
||||
{
|
||||
retval->seek = physfsrwops_seek;
|
||||
retval->read = physfsrwops_read;
|
||||
retval->write = physfsrwops_write;
|
||||
retval->close = physfsrwops_close;
|
||||
retval->hidden.unknown.data1 = handle;
|
||||
} /* if */
|
||||
} /* else */
|
||||
|
||||
return retval;
|
||||
} /* create_rwops */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle)
|
||||
{
|
||||
SDL_RWops *retval = NULL;
|
||||
if (handle == NULL)
|
||||
SDL_SetError("NULL pointer passed to PHYSFSRWOPS_makeRWops().");
|
||||
else
|
||||
retval = create_rwops(handle);
|
||||
|
||||
return retval;
|
||||
} /* PHYSFSRWOPS_makeRWops */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_openRead(const char *fname)
|
||||
{
|
||||
return create_rwops(PHYSFS_openRead(fname));
|
||||
} /* PHYSFSRWOPS_openRead */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname)
|
||||
{
|
||||
return create_rwops(PHYSFS_openWrite(fname));
|
||||
} /* PHYSFSRWOPS_openWrite */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname)
|
||||
{
|
||||
return create_rwops(PHYSFS_openAppend(fname));
|
||||
} /* PHYSFSRWOPS_openAppend */
|
||||
|
||||
|
||||
/* end of physfsrwops.c ... */
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* This code provides a glue layer between PhysicsFS and Simple Directmedia
|
||||
* Layer's (SDL) RWops i/o abstraction.
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* SDL falls under the LGPL license. You can get SDL at http://www.libsdl.org/
|
||||
*
|
||||
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_PHYSFSRWOPS_H_
|
||||
#define _INCLUDE_PHYSFSRWOPS_H_
|
||||
|
||||
#include "physfs.h"
|
||||
#include "SDL.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Open a platform-independent filename for reading, and make it accessible
|
||||
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
|
||||
* RWops is closed. PhysicsFS should be configured to your liking before
|
||||
* opening files through this method.
|
||||
*
|
||||
* @param filename File to open in platform-independent notation.
|
||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
PHYSFS_DECL SDL_RWops *PHYSFSRWOPS_openRead(const char *fname);
|
||||
|
||||
/**
|
||||
* Open a platform-independent filename for writing, and make it accessible
|
||||
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
|
||||
* RWops is closed. PhysicsFS should be configured to your liking before
|
||||
* opening files through this method.
|
||||
*
|
||||
* @param filename File to open in platform-independent notation.
|
||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
PHYSFS_DECL SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname);
|
||||
|
||||
/**
|
||||
* Open a platform-independent filename for appending, and make it accessible
|
||||
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
|
||||
* RWops is closed. PhysicsFS should be configured to your liking before
|
||||
* opening files through this method.
|
||||
*
|
||||
* @param filename File to open in platform-independent notation.
|
||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
PHYSFS_DECL SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname);
|
||||
|
||||
/**
|
||||
* Make a SDL_RWops from an existing PhysicsFS file handle. You should
|
||||
* dispose of any references to the handle after successful creation of
|
||||
* the RWops. The actual PhysicsFS handle will be destroyed when the
|
||||
* RWops is closed.
|
||||
*
|
||||
* @param handle a valid PhysicsFS file handle.
|
||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
PHYSFS_DECL SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* include-once blocker */
|
||||
|
||||
/* end of physfsrwops.h ... */
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "physfs.h"
|
||||
|
||||
|
||||
static int failure = 0;
|
||||
|
||||
static void modTimeToStr(PHYSFS_sint64 modtime, char *modstr, size_t strsize)
|
||||
{
|
||||
const char *str = "unknown modtime";
|
||||
if (modtime != -1)
|
||||
{
|
||||
time_t t = (time_t) modtime;
|
||||
str = ctime(&t);
|
||||
} /* if */
|
||||
|
||||
strncpy(modstr, str, strsize);
|
||||
modstr[strsize-1] = '\0';
|
||||
strsize = strlen(modstr);
|
||||
while ((modstr[strsize-1] == '\n') || (modstr[strsize-1] == '\r'))
|
||||
modstr[--strsize] = '\0';
|
||||
} /* modTimeToStr */
|
||||
|
||||
|
||||
static void fail(const char *what, const char *why)
|
||||
{
|
||||
if (why == NULL)
|
||||
why = PHYSFS_getLastError();
|
||||
fprintf(stderr, "%s failed: %s\n", what, why);
|
||||
failure = 1;
|
||||
} /* fail */
|
||||
|
||||
|
||||
static void dumpFile(const char *fname)
|
||||
{
|
||||
const int origfailure = failure;
|
||||
PHYSFS_File *out = NULL;
|
||||
PHYSFS_File *in = NULL;
|
||||
|
||||
failure = 0;
|
||||
|
||||
if ((in = PHYSFS_openRead(fname)) == NULL)
|
||||
fail("\nPHYSFS_openRead", NULL);
|
||||
else if ((out = PHYSFS_openWrite(fname)) == NULL)
|
||||
fail("\nPHYSFS_openWrite", NULL);
|
||||
else
|
||||
{
|
||||
char modstr[64];
|
||||
PHYSFS_sint64 size = PHYSFS_fileLength(in);
|
||||
|
||||
printf("(");
|
||||
if (size == -1)
|
||||
printf("?");
|
||||
else
|
||||
printf("%lld", (long long) size);
|
||||
printf(" bytes");
|
||||
|
||||
modTimeToStr(PHYSFS_getLastModTime(fname), modstr, sizeof (modstr));
|
||||
printf(", %s)\n", modstr);
|
||||
|
||||
while ( (!failure) && (!PHYSFS_eof(in)) )
|
||||
{
|
||||
static char buf[64 * 1024];
|
||||
PHYSFS_sint64 br = PHYSFS_read(in, buf, 1, sizeof (buf));
|
||||
if (br == -1)
|
||||
fail("PHYSFS_read", NULL);
|
||||
else
|
||||
{
|
||||
PHYSFS_sint64 bw = PHYSFS_write(out, buf, 1, br);
|
||||
if (bw != br)
|
||||
fail("PHYSFS_write", NULL);
|
||||
else
|
||||
size -= bw;
|
||||
} /* else */
|
||||
} /* while */
|
||||
|
||||
if ((!failure) && (size != 0))
|
||||
fail("PHYSFS_eof", "BUG! eof != PHYSFS_fileLength bytes!");
|
||||
} /* else */
|
||||
|
||||
if (in != NULL)
|
||||
PHYSFS_close(in);
|
||||
|
||||
if (out != NULL)
|
||||
{
|
||||
if (!PHYSFS_close(out))
|
||||
fail("PHYSFS_close", NULL);
|
||||
} /* if */
|
||||
|
||||
if (failure)
|
||||
PHYSFS_delete(fname);
|
||||
else
|
||||
failure = origfailure;
|
||||
} /* dumpFile */
|
||||
|
||||
|
||||
static void unpackCallback(void *_depth, const char *origdir, const char *str)
|
||||
{
|
||||
int depth = *((int *) _depth);
|
||||
const int len = strlen(origdir) + strlen(str) + 2;
|
||||
char *fname = (char *) malloc(len);
|
||||
if (fname == NULL)
|
||||
fail("malloc", "Out of memory!");
|
||||
else
|
||||
{
|
||||
if (strcmp(origdir, "/") == 0)
|
||||
origdir = "";
|
||||
|
||||
snprintf(fname, len, "%s/%s", origdir, str);
|
||||
|
||||
printf("%s ", fname);
|
||||
if (PHYSFS_isDirectory(fname))
|
||||
{
|
||||
depth++;
|
||||
printf("(directory)\n");
|
||||
if (!PHYSFS_mkdir(fname))
|
||||
fail("PHYSFS_mkdir", NULL);
|
||||
else
|
||||
PHYSFS_enumerateFilesCallback(fname, unpackCallback, &depth);
|
||||
} /* if */
|
||||
|
||||
else if (PHYSFS_isSymbolicLink(fname))
|
||||
{
|
||||
printf("(symlink)\n");
|
||||
/* !!! FIXME: ? if (!symlink(fname, */
|
||||
} /* else if */
|
||||
|
||||
else /* ...file. */
|
||||
{
|
||||
dumpFile(fname);
|
||||
} /* else */
|
||||
|
||||
free(fname);
|
||||
} /* else */
|
||||
} /* unpackCallback */
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int zero = 0;
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
fprintf(stderr, "USAGE: %s <archive> <unpackDirectory>\n", argv[0]);
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_init() failed: %s\n", PHYSFS_getLastError());
|
||||
return 2;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_setWriteDir(argv[2]))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_setWriteDir('%s') failed: %s\n",
|
||||
argv[2], PHYSFS_getLastError());
|
||||
return 3;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_mount(argv[1], NULL, 1))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_mount('%s') failed: %s\n",
|
||||
argv[1], PHYSFS_getLastError());
|
||||
return 4;
|
||||
} /* if */
|
||||
|
||||
PHYSFS_permitSymbolicLinks(1);
|
||||
PHYSFS_enumerateFilesCallback("/", unpackCallback, &zero);
|
||||
PHYSFS_deinit();
|
||||
if (failure)
|
||||
return 5;
|
||||
|
||||
return 0;
|
||||
} /* main */
|
||||
|
||||
/* end of physfsunpack.c ... */
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This code shows how to read a zipfile included in an app's binary.
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes. This code has
|
||||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Compile this program and then attach a .zip file to the end of the
|
||||
* compiled binary.
|
||||
*
|
||||
* On Linux, something like this will build the final binary:
|
||||
* gcc -o selfextract.tmp selfextract.c -lphysfs && \
|
||||
* cat selfextract.tmp myzipfile.zip >> selfextract && \
|
||||
* chmod a+x selfextract && \
|
||||
* rm -f selfextract.tmp
|
||||
*
|
||||
* This may not work on all platforms, and it probably only works with
|
||||
* .zip files, since they are designed to be appended to another file.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "physfs.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
printf("PHYSFS_init() failed: %s\n", PHYSFS_getLastError());
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
rc = PHYSFS_addToSearchPath(argv[0], 0);
|
||||
if (!rc)
|
||||
{
|
||||
printf("Couldn't find self-extract data: %s\n", PHYSFS_getLastError());
|
||||
printf("This might mean you didn't append a zipfile to the binary.\n");
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
char **files = PHYSFS_enumerateFiles("/");
|
||||
char **i;
|
||||
for (i = files; *i != NULL; i++)
|
||||
{
|
||||
const char *dirorfile = PHYSFS_isDirectory(*i) ? "Directory" : "File";
|
||||
printf(" * %s '%s' is in root of attached data.\n", dirorfile, *i);
|
||||
} /* for */
|
||||
PHYSFS_freeList(files);
|
||||
|
||||
return 0;
|
||||
} /* main */
|
||||
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ ! -f "./install_manifest.txt" ]; then
|
||||
echo "ERROR: This needs to be run from your CMake build directory after installing." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
xargs rm -vf < install_manifest.txt
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user