mirror of
https://github.com/love2d/megasource.git
synced 2026-08-19 12:14:41 +02:00
Add PhysFS 2.0.3.
This commit is contained in:
@@ -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("")]
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
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("")]
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,159 @@
|
||||
/** \file globbing.c */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "physfs.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 LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* \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 */
|
||||
|
||||
|
||||
char **PHYSFSEXT_enumerateFilesWildcard(const char *dir, const char *wildcard,
|
||||
int caseSensitive)
|
||||
{
|
||||
char **rc = PHYSFS_enumerateFiles(dir);
|
||||
char **i = rc;
|
||||
char **j;
|
||||
|
||||
while (*i != NULL)
|
||||
{
|
||||
if (matchesPattern(*i, wildcard, caseSensitive))
|
||||
i++;
|
||||
else
|
||||
{
|
||||
/* FIXME: This counts on physfs's allocation method not changing! */
|
||||
free(*i);
|
||||
for (j = i; *j != NULL; j++)
|
||||
j[0] = j[1];
|
||||
} /* else */
|
||||
} /* for */
|
||||
|
||||
return(rc);
|
||||
} /* 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);
|
||||
|
||||
PHYSFS_freeList(flist);
|
||||
PHYSFS_deinit();
|
||||
|
||||
return(0);
|
||||
} /* main */
|
||||
#endif
|
||||
|
||||
/* end of globbing.c ... */
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
#ifndef INCL_PHYSFSEXT_GLOBBING_H
|
||||
#define INCL_PHYSFSEXT_GLOBBING_H
|
||||
|
||||
/** \file globbing.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_enumerateFilesPattern() when enumerating files. This is just
|
||||
* like PHYSFS_enumerateFiles(), but it returns a subset that matches your
|
||||
* wildcard pattern. You must call PHYSFS_freeList() on the results, just
|
||||
* like you would with PHYSFS_enumerateFiles().
|
||||
*
|
||||
* 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 char **PHYSFS_enumerateFilesWildcard(const char *dir, const char *wildcard, int caseSensitive)
|
||||
* \brief Get a file listing of a search path's directory.
|
||||
*
|
||||
* 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 PHYSFS_freeList() with the return value from this
|
||||
* function when you are done with it.
|
||||
*
|
||||
* \param dir directory in platform-independent notation to enumerate.
|
||||
* \return Null-terminated array of null-terminated strings.
|
||||
*/
|
||||
__EXPORT__ char **PHYSFSEXT_enumerateFilesWildcard(const char *dir,
|
||||
const char *wildcard,
|
||||
int caseSensitive);
|
||||
|
||||
#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 ... */
|
||||
|
||||
@@ -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,103 @@
|
||||
# $Id: installer.rb,v 1.3 2003/07/21 03:46:50 icculus Exp $
|
||||
|
||||
require 'rbconfig'
|
||||
require 'find'
|
||||
require 'ftools'
|
||||
|
||||
include Config
|
||||
|
||||
module Slimb
|
||||
class Installer
|
||||
def initialize target_dir = "", &user_skip
|
||||
@user_skip = user_skip or proc {|f| false}
|
||||
|
||||
@version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"]
|
||||
@libdir = File.join(CONFIG["libdir"], "ruby", @version)
|
||||
@sitedir = CONFIG["sitedir"] || File.join(@libdir, "site_ruby")
|
||||
@dest = File.join @sitedir, target_dir
|
||||
|
||||
File::makedirs @dest
|
||||
File::chmod 0755, @dest, true
|
||||
end
|
||||
|
||||
def skip? file
|
||||
@user_skip[file] or
|
||||
file[0] == ?. or file[-1] == ?~ or file[-1] == ?#
|
||||
end
|
||||
|
||||
def install_dir dir
|
||||
File::makedirs(File.join(@dest, dir))
|
||||
File::chmod(0755, File.join(@dest, dir), true)
|
||||
Dir.foreach(dir) {|file|
|
||||
next if skip? file
|
||||
|
||||
if File.ftype(File.join(dir, file)) == "directory"
|
||||
install_dir File.join(dir, file)
|
||||
else
|
||||
install_file File.join(dir, file)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def install_file file
|
||||
if file =~ /\.so$/
|
||||
install_so file
|
||||
else
|
||||
File::install file, File.join(@dest, file), 0644, true
|
||||
end
|
||||
end
|
||||
|
||||
def install_so file
|
||||
File::install file, File.join(CONFIG["sitearchdir"], file), 0644, true
|
||||
end
|
||||
|
||||
def uninstall_so file
|
||||
file = File.join(CONFIG["sitearchdir"], file)
|
||||
File::safe_unlink file
|
||||
end
|
||||
|
||||
def install something
|
||||
case something
|
||||
when Array
|
||||
something.each {|x|
|
||||
install x if x.is_a? String
|
||||
}
|
||||
when String
|
||||
if File.ftype(something) == "directory"
|
||||
install_dir something
|
||||
else
|
||||
install_file something
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def uninstall what = "*"
|
||||
case what
|
||||
when Array
|
||||
files = what.map {|x| File.join(@dest, x)}
|
||||
when String
|
||||
files = Dir[File.join(@dest, what)]
|
||||
end
|
||||
|
||||
files.each {|x|
|
||||
# FIXME: recursive uninstall is a must
|
||||
next if FileTest.directory? x
|
||||
File::safe_unlink x
|
||||
}
|
||||
end
|
||||
|
||||
def run files, argv
|
||||
if !argv.grep(/--uninstall/).empty?
|
||||
uninstall files
|
||||
else
|
||||
install files
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# self-installation
|
||||
if $0 == __FILE__
|
||||
$stderr.puts "Installing slimb installer..."
|
||||
Slimb::Installer.new("slimb").install File.basename(__FILE__)
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
require 'mkmf'
|
||||
|
||||
$CFLAGS += `sdl-config --cflags`.chomp
|
||||
$LDFLAGS += `sdl-config --libs`.chomp
|
||||
|
||||
have_library "physfs", "PHYSFS_init"
|
||||
have_library "SDL", "SDL_AllocRW"
|
||||
|
||||
create_makefile "physfs_so"
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/usr/local/bin/ruby
|
||||
|
||||
if __FILE__ == $0
|
||||
require 'slimb/installer'
|
||||
files = ["physfs.rb", "physfs_so.so"]
|
||||
installer = Slimb::Installer.new.run files, ARGV
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
ruby extconf.rb
|
||||
make
|
||||
cd ..
|
||||
ruby installer.rb
|
||||
cd physfs
|
||||
ruby install.rb
|
||||
cd test
|
||||
ruby test_physfs.rb
|
||||
@@ -0,0 +1,121 @@
|
||||
#
|
||||
# PhysicsFS - ruby interface
|
||||
#
|
||||
# Author: Ed Sinjiashvili (slimb@vlinkmail.com)
|
||||
# License: LGPL
|
||||
#
|
||||
|
||||
require 'physfs_so'
|
||||
|
||||
module PhysicsFS
|
||||
|
||||
class Version
|
||||
def initialize major, minor, patch
|
||||
@major = major
|
||||
@minor = minor
|
||||
@patch = patch
|
||||
end
|
||||
|
||||
attr_reader :major, :minor, :patch
|
||||
|
||||
def to_s
|
||||
"#@major.#@minor.#@patch"
|
||||
end
|
||||
end
|
||||
|
||||
class ArchiveInfo
|
||||
def initialize ext, desc, author, url
|
||||
@extension = ext
|
||||
@description = desc
|
||||
@author = author
|
||||
@url = url
|
||||
end
|
||||
|
||||
attr_reader :extension, :description
|
||||
attr_reader :author, :url
|
||||
|
||||
def to_s
|
||||
" * #@extension: #@description\n Written by #@author.\n #@url\n"
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# convenience methods
|
||||
#
|
||||
class << self
|
||||
|
||||
def init argv0 = $0
|
||||
init_internal argv0
|
||||
end
|
||||
|
||||
def append_search_path str
|
||||
add_to_search_path str, 1
|
||||
self
|
||||
end
|
||||
|
||||
def prepend_search_path str
|
||||
add_to_search_path str, 0
|
||||
self
|
||||
end
|
||||
|
||||
alias_method :<<, :append_search_path
|
||||
alias_method :push, :append_search_path
|
||||
alias_method :unshift, :prepend_search_path
|
||||
|
||||
def ls path = ""
|
||||
enumerate path
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# File - PhysicsFS abstract file - can be drawn from various sources
|
||||
#
|
||||
class File
|
||||
def write_str str
|
||||
write str, 1, str.length
|
||||
end
|
||||
|
||||
def cat
|
||||
prev_pos = tell
|
||||
seek 0
|
||||
r = read length, 1
|
||||
seek prev_pos
|
||||
r
|
||||
end
|
||||
|
||||
alias_method :size, :length
|
||||
end
|
||||
|
||||
#
|
||||
# RWops - general stdio like operations on file-like creatures
|
||||
#
|
||||
class RWops
|
||||
SEEK_SET = 0
|
||||
SEEK_CUR = 1
|
||||
SEEK_END = 2
|
||||
|
||||
# tell current position of RWopted entity
|
||||
def tell
|
||||
seek 0, SEEK_CUR
|
||||
end
|
||||
|
||||
# length of RWops abstracted entity
|
||||
def length
|
||||
cur = tell
|
||||
r = seek 0, SEEK_END
|
||||
seek cur, SEEK_SET
|
||||
r
|
||||
end
|
||||
|
||||
alias_method :size, :length
|
||||
|
||||
#
|
||||
# create rwops from PhysicsFS file object
|
||||
#
|
||||
def self.from_physfs file
|
||||
file.to_rwops
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# physfs.rb ends here #
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the GNU Lesser
|
||||
* General Public License: http://www.gnu.org/licenses/lgpl.txt
|
||||
*
|
||||
* SDL falls under the LGPL, too. 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"
|
||||
|
||||
static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
int pos = 0;
|
||||
|
||||
if (whence == SEEK_SET)
|
||||
{
|
||||
pos = offset;
|
||||
} /* if */
|
||||
|
||||
else if (whence == SEEK_CUR)
|
||||
{
|
||||
PHYSFS_sint64 current = PHYSFS_tell(handle);
|
||||
if (current == -1)
|
||||
{
|
||||
SDL_SetError("Can't find position in file: %s",
|
||||
PHYSFS_getLastError());
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
pos = (int) current;
|
||||
if ( ((PHYSFS_sint64) pos) != current )
|
||||
{
|
||||
SDL_SetError("Can't fit current file position in an int!");
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
if (offset == 0) /* this is a "tell" call. We're done. */
|
||||
return(pos);
|
||||
|
||||
pos += offset;
|
||||
} /* else if */
|
||||
|
||||
else if (whence == SEEK_END)
|
||||
{
|
||||
PHYSFS_sint64 len = PHYSFS_fileLength(handle);
|
||||
if (len == -1)
|
||||
{
|
||||
SDL_SetError("Can't find end of file: %s", PHYSFS_getLastError());
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
pos = (int) len;
|
||||
if ( ((PHYSFS_sint64) pos) != len )
|
||||
{
|
||||
SDL_SetError("Can't fit end-of-file position in an int!");
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
pos += 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 */
|
||||
|
||||
return(pos);
|
||||
} /* physfsrwops_seek */
|
||||
|
||||
|
||||
static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
PHYSFS_sint64 rc = PHYSFS_read(handle, ptr, size, maxnum);
|
||||
if (rc != maxnum)
|
||||
{
|
||||
if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
} /* if */
|
||||
|
||||
return((int) rc);
|
||||
} /* physfsrwops_read */
|
||||
|
||||
|
||||
static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
PHYSFS_sint64 rc = PHYSFS_write(handle, ptr, size, num);
|
||||
if (rc != num)
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
|
||||
return((int) rc);
|
||||
} /* 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,87 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the GNU Lesser
|
||||
* General Public License: http://www.gnu.org/licenses/lgpl.txt
|
||||
*
|
||||
* SDL falls under the LGPL, too. 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().
|
||||
*/
|
||||
__EXPORT__ 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().
|
||||
*/
|
||||
__EXPORT__ 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().
|
||||
*/
|
||||
__EXPORT__ 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().
|
||||
*/
|
||||
__EXPORT__ SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_file *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* include-once blocker */
|
||||
|
||||
/* end of physfsrwops.h ... */
|
||||
|
||||
@@ -0,0 +1,462 @@
|
||||
/*
|
||||
* PhysicsFS - ruby interface
|
||||
*
|
||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
||||
* License:: LGPL
|
||||
*/
|
||||
|
||||
#include "physfs.h"
|
||||
#include "ruby.h"
|
||||
|
||||
#include "rb_physfs.h"
|
||||
#include "rb_physfs_file.h"
|
||||
|
||||
VALUE modulePhysfs;
|
||||
|
||||
/*
|
||||
* PhysicsFS::init str
|
||||
*
|
||||
* initialize PhysicsFS
|
||||
*/
|
||||
VALUE physfs_init (VALUE self, VALUE str)
|
||||
{
|
||||
int result = PHYSFS_init (STR2CSTR(str));
|
||||
|
||||
if (result)
|
||||
return Qtrue;
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::deinit
|
||||
*/
|
||||
VALUE physfs_deinit (VALUE self)
|
||||
{
|
||||
if (PHYSFS_deinit ())
|
||||
return Qtrue;
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::version
|
||||
*
|
||||
* return PhysicsFS::Version object
|
||||
*/
|
||||
VALUE physfs_version (VALUE self)
|
||||
{
|
||||
char evalStr[200];
|
||||
PHYSFS_Version ver;
|
||||
|
||||
PHYSFS_getLinkedVersion (&ver);
|
||||
|
||||
sprintf (evalStr, "PhysicsFS::Version.new %d, %d, %d",
|
||||
ver.major, ver.minor, ver.patch);
|
||||
return rb_eval_string (evalStr);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::supported_archives
|
||||
*
|
||||
* return Array of PhysicsFS::ArchiveInfo objects
|
||||
*/
|
||||
VALUE physfs_supported_archives (VALUE self)
|
||||
{
|
||||
const PHYSFS_ArchiveInfo **info = PHYSFS_supportedArchiveTypes();
|
||||
VALUE klass = rb_const_get (modulePhysfs, rb_intern ("ArchiveInfo"));
|
||||
VALUE ary = rb_ary_new ();
|
||||
VALUE params[4];
|
||||
|
||||
while ( *info != 0 )
|
||||
{
|
||||
params[0] = rb_str_new2 ((*info)->extension);
|
||||
params[1] = rb_str_new2 ((*info)->description);
|
||||
params[2] = rb_str_new2 ((*info)->author);
|
||||
params[3] = rb_str_new2 ((*info)->url);
|
||||
|
||||
rb_ary_push (ary, rb_class_new_instance (4, params, klass));
|
||||
info++;
|
||||
}
|
||||
|
||||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::last_error
|
||||
*
|
||||
* return string representation of last PhysicsFS error
|
||||
*/
|
||||
VALUE physfs_last_error (VALUE self)
|
||||
{
|
||||
const char *last_error = PHYSFS_getLastError ();
|
||||
|
||||
if (last_error == 0)
|
||||
last_error = "";
|
||||
|
||||
return rb_str_new2 (last_error);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::dir_separator
|
||||
*
|
||||
* return platform directory separator
|
||||
*/
|
||||
VALUE physfs_dir_separator (VALUE self)
|
||||
{
|
||||
return rb_str_new2 (PHYSFS_getDirSeparator ());
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::permit_symlinks boolValue
|
||||
*
|
||||
* turn symlinks support on/off
|
||||
*/
|
||||
VALUE physfs_permit_symlinks (VALUE self, VALUE allow)
|
||||
{
|
||||
int p = 1;
|
||||
|
||||
if (allow == Qfalse || allow == Qnil)
|
||||
p = 0;
|
||||
|
||||
PHYSFS_permitSymbolicLinks (p);
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::cdrom_dirs
|
||||
*
|
||||
* return Array of strings containing available CDs
|
||||
*/
|
||||
VALUE physfs_cdrom_dirs (VALUE self)
|
||||
{
|
||||
char **cds = PHYSFS_getCdRomDirs();
|
||||
char **i;
|
||||
VALUE ary = rb_ary_new ();
|
||||
|
||||
for (i = cds; *i != 0; i++)
|
||||
rb_ary_push (ary, rb_str_new2 (*i));
|
||||
|
||||
PHYSFS_freeList (cds);
|
||||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::base_dir
|
||||
*
|
||||
* return base directory
|
||||
*/
|
||||
VALUE physfs_base_dir (VALUE self)
|
||||
{
|
||||
const char *base_dir = PHYSFS_getBaseDir ();
|
||||
if (base_dir == 0)
|
||||
base_dir = "";
|
||||
|
||||
return rb_str_new2 (base_dir);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::user_dir
|
||||
*
|
||||
* return user directory
|
||||
*/
|
||||
VALUE physfs_user_dir (VALUE self)
|
||||
{
|
||||
const char *user_dir = PHYSFS_getBaseDir ();
|
||||
if (user_dir == 0)
|
||||
user_dir = "";
|
||||
|
||||
return rb_str_new2 (user_dir);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::write_dir
|
||||
*
|
||||
* return write directory
|
||||
*/
|
||||
VALUE physfs_write_dir (VALUE self)
|
||||
{
|
||||
const char *write_dir = PHYSFS_getWriteDir ();
|
||||
if (write_dir == 0)
|
||||
return Qnil;
|
||||
|
||||
return rb_str_new2 (write_dir);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::write_dir= str
|
||||
*
|
||||
* set write directory to *str*
|
||||
*/
|
||||
VALUE physfs_set_write_dir (VALUE self, VALUE str)
|
||||
{
|
||||
int result = PHYSFS_setWriteDir (STR2CSTR(str));
|
||||
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::add_to_search_path str, append
|
||||
*
|
||||
* if append > 0 - append str to search path, otherwise prepend it
|
||||
*/
|
||||
VALUE physfs_add_search_path (VALUE self, VALUE str, VALUE append)
|
||||
{
|
||||
int result = PHYSFS_addToSearchPath (STR2CSTR(str), FIX2INT(append));
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::remove_from_search_path str
|
||||
*
|
||||
* removes str from search path
|
||||
*/
|
||||
VALUE physfs_remove_search_path (VALUE self, VALUE str)
|
||||
{
|
||||
int result = PHYSFS_removeFromSearchPath (STR2CSTR(str));
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::search_path
|
||||
*
|
||||
* return current search_path - as array of strings
|
||||
*/
|
||||
VALUE physfs_search_path (VALUE self)
|
||||
{
|
||||
char **path = PHYSFS_getSearchPath ();
|
||||
char **i;
|
||||
VALUE ary = rb_ary_new ();
|
||||
|
||||
for (i = path ; *i != 0; i++)
|
||||
rb_ary_push (ary, rb_str_new2 (*i));
|
||||
|
||||
PHYSFS_freeList (path);
|
||||
return ary;
|
||||
}
|
||||
|
||||
//
|
||||
VALUE physfs_setSaneConfig(VALUE self, VALUE org, VALUE app, VALUE ext,
|
||||
VALUE includeCdroms, VALUE archivesFirst)
|
||||
{
|
||||
int res = PHYSFS_setSaneConfig (STR2CSTR(org), STR2CSTR(app), STR2CSTR(ext),
|
||||
RTEST(includeCdroms), RTEST(archivesFirst));
|
||||
if (res)
|
||||
return Qtrue;
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::mkdir newdir
|
||||
*
|
||||
* create new directory
|
||||
*/
|
||||
VALUE physfs_mkdir (VALUE self, VALUE newdir)
|
||||
{
|
||||
int result = PHYSFS_mkdir (STR2CSTR(newdir));
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::delete name
|
||||
*
|
||||
* delete file with name
|
||||
*/
|
||||
VALUE physfs_delete (VALUE self, VALUE name)
|
||||
{
|
||||
int result = PHYSFS_delete (STR2CSTR(name));
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::real_dir name
|
||||
*
|
||||
* return real directory (in search path) of a name
|
||||
*/
|
||||
VALUE physfs_real_dir (VALUE self, VALUE name)
|
||||
{
|
||||
const char *path = PHYSFS_getRealDir (STR2CSTR(name));
|
||||
if (path == 0)
|
||||
return Qnil;
|
||||
|
||||
return rb_str_new2 (path);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::enumerate dir
|
||||
*
|
||||
* list a dir from a search path
|
||||
*/
|
||||
VALUE physfs_enumerate (VALUE self, VALUE dir)
|
||||
{
|
||||
char **files = PHYSFS_enumerateFiles (STR2CSTR(dir));
|
||||
char **i;
|
||||
VALUE ary = rb_ary_new ();
|
||||
|
||||
for (i = files; *i != 0; i++)
|
||||
rb_ary_push (ary, rb_str_new2 (*i));
|
||||
|
||||
PHYSFS_freeList (files);
|
||||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::exists? name
|
||||
*
|
||||
* does a file with name exist?
|
||||
*/
|
||||
VALUE physfs_exists (VALUE self, VALUE name)
|
||||
{
|
||||
int result = PHYSFS_exists (STR2CSTR(name));
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::is_directory? name
|
||||
*
|
||||
* return true if name is directory
|
||||
*/
|
||||
VALUE physfs_is_directory (VALUE self, VALUE name)
|
||||
{
|
||||
int result = PHYSFS_isDirectory (STR2CSTR(name));
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::is_symlink? name
|
||||
*
|
||||
* return true if name is symlink
|
||||
*/
|
||||
VALUE physfs_is_symlink (VALUE self, VALUE name)
|
||||
{
|
||||
int result = PHYSFS_isSymbolicLink (STR2CSTR(name));
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::last_mod_time name
|
||||
*
|
||||
* return last modification time of a file
|
||||
*/
|
||||
VALUE physfs_last_mod_time (VALUE self, VALUE name)
|
||||
{
|
||||
int result = PHYSFS_getLastModTime (STR2CSTR(name));
|
||||
|
||||
return INT2FIX(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::open_read name
|
||||
*
|
||||
* return +PhysicsFS::File+ ready for reading
|
||||
*/
|
||||
VALUE physfs_open_read (VALUE self, VALUE name)
|
||||
{
|
||||
PHYSFS_File *file = PHYSFS_openRead (STR2CSTR(name));
|
||||
return physfs_file_new (file);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::open_write name
|
||||
*
|
||||
* return PhysicsFS::File ready for writing
|
||||
*/
|
||||
VALUE physfs_open_write (VALUE self, VALUE name)
|
||||
{
|
||||
PHYSFS_File *file = PHYSFS_openWrite (STR2CSTR(name));
|
||||
return physfs_file_new (file);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::open_append name
|
||||
*
|
||||
* return PhysicsFS::File ready for appending
|
||||
*/
|
||||
VALUE physfs_open_append (VALUE self, VALUE name)
|
||||
{
|
||||
PHYSFS_File *file = PHYSFS_openAppend (STR2CSTR(name));
|
||||
return physfs_file_new (file);
|
||||
}
|
||||
|
||||
void Init_physfs_so (void)
|
||||
{
|
||||
modulePhysfs = rb_define_module ("PhysicsFS");
|
||||
|
||||
rb_define_singleton_method (modulePhysfs, "init_internal", physfs_init, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "deinit", physfs_deinit, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "version", physfs_version, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "supported_archives",
|
||||
physfs_supported_archives, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "last_error",
|
||||
physfs_last_error, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "dir_separator",
|
||||
physfs_dir_separator, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "permit_symlinks",
|
||||
physfs_permit_symlinks, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "cdrom_dirs",
|
||||
physfs_cdrom_dirs, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "base_dir", physfs_base_dir, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "user_dir", physfs_user_dir, 0);
|
||||
|
||||
rb_define_singleton_method (modulePhysfs, "write_dir", physfs_write_dir, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "write_dir=",
|
||||
physfs_set_write_dir, 1);
|
||||
|
||||
rb_define_singleton_method (modulePhysfs, "add_to_search_path",
|
||||
physfs_add_search_path, 2);
|
||||
rb_define_singleton_method (modulePhysfs, "remove_from_search_path",
|
||||
physfs_remove_search_path, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "search_path",
|
||||
physfs_search_path, 0);
|
||||
|
||||
rb_define_singleton_method (modulePhysfs, "set_sane_config",
|
||||
physfs_setSaneConfig, 5);
|
||||
|
||||
rb_define_singleton_method (modulePhysfs, "mkdir", physfs_mkdir, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "delete", physfs_delete, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "real_dir",
|
||||
physfs_real_dir, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "enumerate", physfs_enumerate, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "exists?", physfs_exists, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "is_directory?",
|
||||
physfs_is_directory, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "is_symlink?",
|
||||
physfs_is_symlink, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "last_mod_time",
|
||||
physfs_last_mod_time, 1);
|
||||
|
||||
rb_define_singleton_method (modulePhysfs, "open_read",
|
||||
physfs_open_read, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "open_write",
|
||||
physfs_open_write, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "open_append",
|
||||
physfs_open_append, 1);
|
||||
|
||||
init_physfs_file ();
|
||||
init_sdl_rwops ();
|
||||
}
|
||||
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-indentation-style: "stroustrup"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* PhysicsFS - ruby interface
|
||||
*
|
||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
||||
* License:: LGPL
|
||||
*/
|
||||
|
||||
#ifndef __RB__PHYSFS__H__
|
||||
#define __RB__PHYSFS__H__
|
||||
|
||||
extern VALUE modulePhysfs;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* PhysicsFS File abstraction - ruby interface
|
||||
*
|
||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
||||
* License:: LGPL
|
||||
*/
|
||||
|
||||
#include "physfs.h"
|
||||
#include "ruby.h"
|
||||
|
||||
#include "rb_physfs.h"
|
||||
#include "rb_physfs_file.h"
|
||||
#include "physfsrwops.h"
|
||||
|
||||
VALUE classPhysfsFile;
|
||||
|
||||
/*
|
||||
* construct new PhysicsFS::File object
|
||||
*/
|
||||
VALUE physfs_file_new (PHYSFS_File *file)
|
||||
{
|
||||
if (file == 0)
|
||||
return Qnil;
|
||||
|
||||
return Data_Wrap_Struct (classPhysfsFile, 0, 0, file);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#close
|
||||
*
|
||||
* Close the file. It's illegal to use the object after its closure.
|
||||
*/
|
||||
VALUE physfs_file_close (VALUE self)
|
||||
{
|
||||
int result;
|
||||
PHYSFS_File *file;
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
|
||||
if (file == 0)
|
||||
return Qfalse;
|
||||
|
||||
result = PHYSFS_close (file);
|
||||
DATA_PTR(self) = 0;
|
||||
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#read obj_size, num_objects
|
||||
*
|
||||
* Read *objCount* objects which are *objSize* each.
|
||||
* return String instance containing raw data or nil if failure.
|
||||
* #length of string will reflect real number of objects read.
|
||||
*/
|
||||
VALUE physfs_file_read (VALUE self, VALUE objSize, VALUE objCount)
|
||||
{
|
||||
int objRead;
|
||||
void *buffer;
|
||||
VALUE result;
|
||||
PHYSFS_File *file;
|
||||
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
if (file == 0)
|
||||
return Qnil; //wasted file - no read possible
|
||||
|
||||
buffer = malloc (FIX2UINT(objSize) * FIX2UINT(objCount));
|
||||
if (buffer == 0)
|
||||
return Qnil;
|
||||
|
||||
objRead = PHYSFS_read (file, buffer, FIX2UINT(objSize), FIX2UINT(objCount));
|
||||
if (objRead == -1)
|
||||
{
|
||||
free (buffer);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
result = rb_str_new (buffer, objRead * FIX2UINT(objSize));
|
||||
free (buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#write buffer, obj_size, num_objects
|
||||
*
|
||||
* return nil on failure or number of objects written.
|
||||
*/
|
||||
VALUE physfs_file_write (VALUE self, VALUE buf, VALUE objSize, VALUE objCount)
|
||||
{
|
||||
int result;
|
||||
PHYSFS_File *file;
|
||||
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
if (file == 0)
|
||||
return Qnil;
|
||||
|
||||
result = PHYSFS_write (file, STR2CSTR(buf),
|
||||
FIX2UINT(objSize), FIX2UINT(objCount));
|
||||
if (result == -1)
|
||||
return Qnil;
|
||||
|
||||
return INT2FIX(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#eof?
|
||||
*/
|
||||
VALUE physfs_file_eof (VALUE self)
|
||||
{
|
||||
int result;
|
||||
PHYSFS_File *file;
|
||||
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
if (file == 0)
|
||||
return Qnil;
|
||||
|
||||
result = PHYSFS_eof (file);
|
||||
|
||||
if (result)
|
||||
return Qtrue;
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#tell
|
||||
*
|
||||
* tells current position in file
|
||||
*/
|
||||
VALUE physfs_file_tell (VALUE self)
|
||||
{
|
||||
int result;
|
||||
PHYSFS_File *file;
|
||||
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
if (file == 0)
|
||||
return Qnil;
|
||||
|
||||
result = PHYSFS_tell (file);
|
||||
|
||||
if (result == -1)
|
||||
return Qnil;
|
||||
|
||||
return INT2FIX(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#seek pos
|
||||
*
|
||||
* seek to pos in file
|
||||
*/
|
||||
VALUE physfs_file_seek (VALUE self, VALUE pos)
|
||||
{
|
||||
int result;
|
||||
PHYSFS_File *file;
|
||||
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
if (file == 0)
|
||||
return Qnil;
|
||||
|
||||
result = PHYSFS_seek (file, FIX2LONG(pos));
|
||||
|
||||
if (result)
|
||||
return Qtrue;
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#length
|
||||
*/
|
||||
VALUE physfs_file_length (VALUE self)
|
||||
{
|
||||
int result;
|
||||
PHYSFS_File *file;
|
||||
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
if (file == 0)
|
||||
return Qnil;
|
||||
|
||||
result = PHYSFS_fileLength (file);
|
||||
|
||||
if (result == -1)
|
||||
return Qnil;
|
||||
|
||||
return INT2FIX(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#to_rwops
|
||||
*
|
||||
* File object is converted to RWops object.
|
||||
* File object becomes unusable after that - every operation
|
||||
* should be done through new-born RWops object.
|
||||
*/
|
||||
VALUE physfs_file_to_rwops (VALUE self)
|
||||
{
|
||||
PHYSFS_File *file;
|
||||
SDL_RWops *rwops;
|
||||
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
if (file == 0)
|
||||
return Qnil;
|
||||
|
||||
rwops = PHYSFSRWOPS_makeRWops (file);
|
||||
if (rwops == 0)
|
||||
return Qnil;
|
||||
|
||||
DATA_PTR(self) = 0; // oh, gosh, we've sacrificed ourselves!
|
||||
return sdl_rwops_new (rwops);
|
||||
}
|
||||
|
||||
void init_physfs_file (void)
|
||||
{
|
||||
classPhysfsFile = rb_define_class_under (modulePhysfs, "File", rb_cObject);
|
||||
|
||||
rb_define_method (classPhysfsFile, "close", physfs_file_close, 0);
|
||||
rb_define_method (classPhysfsFile, "eof?", physfs_file_eof, 0);
|
||||
rb_define_method (classPhysfsFile, "tell", physfs_file_tell, 0);
|
||||
rb_define_method (classPhysfsFile, "seek", physfs_file_seek, 1);
|
||||
rb_define_method (classPhysfsFile, "length", physfs_file_length, 0);
|
||||
rb_define_method (classPhysfsFile, "read", physfs_file_read, 2);
|
||||
rb_define_method (classPhysfsFile, "write", physfs_file_write, 3);
|
||||
rb_define_method (classPhysfsFile, "to_rwops", physfs_file_to_rwops, 0);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* PhysicsFS File abstraction - ruby interface
|
||||
*
|
||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
||||
* License:: LGPL
|
||||
*/
|
||||
|
||||
#ifndef __RB__PHYSFS__FILE__H__
|
||||
#define __RB__PHYSFS__FILE__H__
|
||||
|
||||
extern VALUE classPhysfsFile;
|
||||
|
||||
VALUE physfs_file_new (PHYSFS_file *file);
|
||||
VALUE physfs_file_close (VALUE self);
|
||||
VALUE physfs_file_read (VALUE self, VALUE objSize, VALUE objCount);
|
||||
VALUE physfs_file_write (VALUE self, VALUE buf, VALUE objSize, VALUE objCount);
|
||||
VALUE physfs_file_eof (VALUE self);
|
||||
VALUE physfs_file_tell (VALUE self);
|
||||
VALUE physfs_file_seek (VALUE self, VALUE pos);
|
||||
VALUE physfs_file_length (VALUE self);
|
||||
|
||||
void init_physfs_file (void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* SDL_RWops - ruby interface
|
||||
*
|
||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
||||
* License:: LGPL
|
||||
*/
|
||||
|
||||
#include "SDL_rwops.h"
|
||||
#include "ruby.h"
|
||||
|
||||
#include "rb_physfs.h"
|
||||
#include "rb_sdl_rwops.h"
|
||||
|
||||
VALUE classRWops;
|
||||
|
||||
/*
|
||||
* RWops constructor
|
||||
*/
|
||||
VALUE sdl_rwops_new (SDL_RWops *ops)
|
||||
{
|
||||
VALUE result;
|
||||
|
||||
if (ops == 0)
|
||||
return Qnil;
|
||||
|
||||
result = Data_Wrap_Struct (classRWops, 0, SDL_FreeRW, ops);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::RWops::from_file name, mode
|
||||
*
|
||||
* create RWops object from file
|
||||
*/
|
||||
VALUE sdl_rwops_from_file (VALUE self, VALUE name, VALUE mode)
|
||||
{
|
||||
SDL_RWops *ops = SDL_RWFromFile(STR2CSTR(name), STR2CSTR(mode));
|
||||
return sdl_rwops_new (ops);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::RWops::from_memory string
|
||||
*
|
||||
* create RWops object from memory
|
||||
*/
|
||||
VALUE sdl_rwops_from_mem (VALUE self, VALUE str)
|
||||
{
|
||||
int len = RSTRING(str)->len;
|
||||
void *mem = STR2CSTR(str);
|
||||
SDL_RWops *ops = SDL_RWFromMem(mem, len);
|
||||
|
||||
return sdl_rwops_new (ops);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::RWops#seek offset, whence
|
||||
*
|
||||
* position RWops object
|
||||
*/
|
||||
VALUE sdl_rwops_seek (VALUE self, VALUE offset, VALUE whence)
|
||||
{
|
||||
int result;
|
||||
SDL_RWops *ops;
|
||||
|
||||
Data_Get_Struct (self, SDL_RWops, ops);
|
||||
if (ops == 0)
|
||||
return Qnil;
|
||||
|
||||
result = SDL_RWseek(ops, FIX2INT(offset), FIX2INT(whence));
|
||||
return INT2FIX(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::RWops#close
|
||||
*
|
||||
* close RWops. No use of the object is possible after that.
|
||||
*/
|
||||
VALUE sdl_rwops_close (VALUE self)
|
||||
{
|
||||
int result;
|
||||
SDL_RWops *ops;
|
||||
|
||||
Data_Get_Struct (self, SDL_RWops, ops);
|
||||
if (ops == 0)
|
||||
return Qnil;
|
||||
|
||||
result = SDL_RWclose (ops);
|
||||
DATA_PTR(self) = 0;
|
||||
|
||||
return INT2FIX(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::RWops#read
|
||||
*
|
||||
* read from RWops object objCount objSize'd entities.
|
||||
* return string containing raw data or nil
|
||||
*/
|
||||
VALUE sdl_rwops_read (VALUE self, VALUE objSize, VALUE objCount)
|
||||
{
|
||||
int objRead;
|
||||
void *buffer;
|
||||
VALUE result;
|
||||
SDL_RWops *ops;
|
||||
|
||||
Data_Get_Struct (self, SDL_RWops, ops);
|
||||
if (ops == 0)
|
||||
return Qnil;
|
||||
|
||||
buffer = malloc (FIX2UINT(objSize) * FIX2UINT(objCount));
|
||||
if (buffer == 0)
|
||||
return Qnil;
|
||||
|
||||
objRead = SDL_RWread (ops, buffer, FIX2UINT(objSize), FIX2UINT(objCount));
|
||||
if (objRead == -1)
|
||||
{
|
||||
free (buffer);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
result = rb_str_new (buffer, objRead * FIX2UINT(objSize));
|
||||
free (buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::RWops#write buffer, size, n
|
||||
*
|
||||
* write raw string containing n objects size length each.
|
||||
* return number of objects written or nil
|
||||
*/
|
||||
VALUE sdl_rwops_write (VALUE self, VALUE buffer, VALUE size, VALUE n)
|
||||
{
|
||||
int result;
|
||||
SDL_RWops *ops;
|
||||
|
||||
Data_Get_Struct (self, SDL_RWops, ops);
|
||||
if (ops == 0)
|
||||
return Qnil;
|
||||
|
||||
result = SDL_RWwrite (ops, STR2CSTR(buffer), FIX2INT(size), FIX2INT(n));
|
||||
|
||||
if (result == -1)
|
||||
return Qnil;
|
||||
|
||||
return INT2FIX(result);
|
||||
}
|
||||
|
||||
void init_sdl_rwops (void)
|
||||
{
|
||||
classRWops = rb_define_class_under (modulePhysfs, "RWops", rb_cObject);
|
||||
|
||||
rb_define_method (classRWops, "seek", sdl_rwops_seek, 2);
|
||||
rb_define_method (classRWops, "read", sdl_rwops_read, 2);
|
||||
rb_define_method (classRWops, "write", sdl_rwops_write, 3);
|
||||
rb_define_method (classRWops, "close", sdl_rwops_close, 0);
|
||||
|
||||
rb_define_singleton_method (classRWops, "from_file",
|
||||
sdl_rwops_from_file, 2);
|
||||
rb_define_singleton_method (classRWops, "from_memory",
|
||||
sdl_rwops_from_mem, 1);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SDL_RWops - ruby interface
|
||||
*
|
||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
||||
* License:: LGPL
|
||||
*/
|
||||
|
||||
#ifndef __RB__SDL__RWOPS__H__
|
||||
#define __RB__SDL__RWOPS__H__
|
||||
|
||||
extern VALUE classRWops;
|
||||
|
||||
VALUE sdl_rwops_new (SDL_RWops *ops);
|
||||
void init_sdl_rwops (void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,358 @@
|
||||
#
|
||||
# PhysicsFS test program - mimics real physfs_test
|
||||
#
|
||||
require 'readline'
|
||||
require 'physfs'
|
||||
|
||||
def die msg
|
||||
puts "#{msg} - reason: #{PhysicsFS.last_error}"
|
||||
end
|
||||
|
||||
#
|
||||
# parse line to command and args
|
||||
#
|
||||
def parse line
|
||||
return false if line.nil?
|
||||
|
||||
if line.strip =~ /^(.*?) (?: (?:\s+(.*)) | $)/x
|
||||
run $1, $2
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# parse command args
|
||||
#
|
||||
def parse_args args
|
||||
args.strip!
|
||||
|
||||
dquoted = /^ " (.*?) "/x
|
||||
squoted = /^ ' (.*?) '/x
|
||||
unquoted = /^([^\s\'\"]+)/
|
||||
|
||||
regexps = [dquoted, squoted, unquoted]
|
||||
|
||||
result = []
|
||||
while args != ""
|
||||
regexps.each do |r|
|
||||
if args =~ r
|
||||
result << $1
|
||||
args.sub! r, ""
|
||||
args.sub!(/\s+/, "")
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def usage cmd, prefix = "usage: "
|
||||
print prefix
|
||||
args = Commands::HELP[cmd]
|
||||
if args
|
||||
print cmd
|
||||
args.scan(/\w+/).each {|x|
|
||||
print " <#{x}>"
|
||||
}
|
||||
puts
|
||||
else
|
||||
puts %|#{cmd} (no arguments)|
|
||||
end
|
||||
end
|
||||
|
||||
# commands go below
|
||||
module Commands
|
||||
HELP = {
|
||||
"init" => "argv0",
|
||||
"addarchive" => "archiveLocation append",
|
||||
"removearchive" => "archiveLocation",
|
||||
"enumerate" => "dirToEnumerate",
|
||||
"ls" => "dirToEnumerate",
|
||||
"setwritedir" => "newWriteDir",
|
||||
"permitsymlinks" => "1or0",
|
||||
"setsaneconfig" => "org appName arcExt includeCdRoms archivesFirst",
|
||||
"mkdir" => "dirToMk",
|
||||
"delete" => "dirToDelete",
|
||||
"getrealdir" => "fileToFind",
|
||||
"exists" => "fileToCheck",
|
||||
"isdir" => "fileToCheck",
|
||||
"issymlink" => "fileToCheck",
|
||||
"cat" => "fileToCat",
|
||||
"filelength" => "fileToCheck",
|
||||
"append" => "fileToAppend",
|
||||
"write" => "fileToCreateOrTrash",
|
||||
"getlastmodtime" => "fileToExamine"
|
||||
}
|
||||
|
||||
def quit_cmd
|
||||
exit
|
||||
end
|
||||
|
||||
alias q_cmd quit_cmd
|
||||
|
||||
def help_cmd
|
||||
commands = ::Commands.instance_methods.grep(/_cmd$/).sort
|
||||
puts "Commands:"
|
||||
commands.each do |c|
|
||||
usage c.sub("_cmd", ""), " - "
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def e val
|
||||
if val
|
||||
puts "Successful."
|
||||
else
|
||||
puts "Failure. reason: #{PhysicsFS.last_error}"
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def init_cmd arg
|
||||
e PhysicsFS.init(arg)
|
||||
end
|
||||
|
||||
def deinit_cmd
|
||||
e PhysicsFS.deinit
|
||||
end
|
||||
|
||||
def addarchive_cmd archive, append
|
||||
e PhysicsFS.add_to_search_path(archive, append)
|
||||
end
|
||||
|
||||
def removearchive_cmd archive
|
||||
e PhysicsFS.remove_from_search_path archive
|
||||
end
|
||||
|
||||
def enumerate_cmd path
|
||||
entries = PhysicsFS.enumerate(path)
|
||||
entries.each {|x|
|
||||
puts x
|
||||
}
|
||||
true
|
||||
end
|
||||
|
||||
alias ls_cmd enumerate_cmd
|
||||
|
||||
def getlasterror_cmd
|
||||
puts "Last error is [#{PhysicsFS.last_error}]"
|
||||
true
|
||||
end
|
||||
|
||||
def getdirsep_cmd
|
||||
puts "Directory separator is [#{PhysicsFS.dir_separator}]"
|
||||
true
|
||||
end
|
||||
|
||||
def getcdromdirs_cmd
|
||||
dirs = PhysicsFS.cdrom_dirs
|
||||
dirs.each {|x|
|
||||
puts x
|
||||
}
|
||||
puts " total [#{dirs.length}] drives."
|
||||
true
|
||||
end
|
||||
|
||||
def getsearchpath_cmd
|
||||
spath = PhysicsFS.search_path
|
||||
spath.each {|x|
|
||||
puts x
|
||||
}
|
||||
puts "total [#{spath.length}] directories."
|
||||
true
|
||||
end
|
||||
|
||||
def getbasedir_cmd
|
||||
dir = PhysicsFS.base_dir
|
||||
puts dir if dir
|
||||
true
|
||||
end
|
||||
|
||||
def getuserdir_cmd
|
||||
puts PhysicsFS.user_dir
|
||||
true
|
||||
end
|
||||
|
||||
def getwritedir_cmd
|
||||
dir = PhysicsFS.write_dir
|
||||
if dir
|
||||
puts "Write directory is [#{dir}]."
|
||||
else
|
||||
puts "No write directory defined."
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def setwritedir_cmd dir
|
||||
e(PhysicsFS.write_dir = dir)
|
||||
end
|
||||
|
||||
def permitsymlinks_cmd val
|
||||
if val.to_i == 1
|
||||
PhysicsFS.permit_symlinks true
|
||||
puts "Symlinks are now permitted"
|
||||
else
|
||||
PhysicsFS.permit_symlinks false
|
||||
puts "Symlinks are now forbidden"
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def setsaneconfig_cmd org, appname, ext, includeCdroms, archivesFirst
|
||||
includeCdroms = includeCdroms.to_i == 1
|
||||
archiveFirst = archivesFirst == 1
|
||||
e PhysicsFS.set_sane_config(org, appname, ext, includeCdroms, archivesFirst)
|
||||
end
|
||||
|
||||
def mkdir_cmd dir
|
||||
e PhysicsFS.mkdir(dir)
|
||||
end
|
||||
|
||||
def delete_cmd dir
|
||||
e PhysicsFS.delete(dir)
|
||||
end
|
||||
|
||||
def getrealdir_cmd file
|
||||
dir = PhysicsFS.real_dir file
|
||||
if dir
|
||||
puts "Found at [#{dir}]"
|
||||
else
|
||||
puts "Not found."
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def exists_cmd file
|
||||
if PhysicsFS.exists? file
|
||||
puts "File exists"
|
||||
else
|
||||
puts "File does not exist"
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def isdir_cmd file
|
||||
if PhysicsFS.is_directory? file
|
||||
puts "File is a directory"
|
||||
else
|
||||
puts "File is NOT a directory"
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def issymlink_cmd file
|
||||
if PhysicsFS.is_symlink? file
|
||||
puts "File is a symlink"
|
||||
else
|
||||
puts "File is NOT a symlink"
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def cat_cmd filename
|
||||
file = PhysicsFS.open_read filename
|
||||
if file.nil?
|
||||
puts "failed to open. reason: #{PhysicsFS.last_error}"
|
||||
return true
|
||||
end
|
||||
|
||||
puts file.cat
|
||||
true
|
||||
end
|
||||
|
||||
def filelength_cmd filename
|
||||
file = PhysicsFS.open_read filename
|
||||
if file.nil?
|
||||
puts "failed to open. reason: #{PhysicsFS.last_error}"
|
||||
return true
|
||||
end
|
||||
|
||||
puts file.length
|
||||
file.close
|
||||
true
|
||||
end
|
||||
|
||||
WRITE_STR = "Rubyfied PhysicsFS works just fine.\n\n"
|
||||
|
||||
def append_cmd filename
|
||||
file = PhysicsFS.open_append filename
|
||||
if file.nil?
|
||||
puts "failed to open. reason: #{PhysicsFS.last_error}"
|
||||
return true
|
||||
end
|
||||
|
||||
file.write WRITE_STR, 1, WRITE_STR.length
|
||||
file.close
|
||||
true
|
||||
end
|
||||
|
||||
def write_cmd filename
|
||||
file = PhysicsFS.open_write filename
|
||||
if file.nil?
|
||||
puts "failed to open. reason: #{PhysicsFS.last_error}"
|
||||
return true
|
||||
end
|
||||
|
||||
file.write_str WRITE_STR
|
||||
file.close
|
||||
true
|
||||
end
|
||||
|
||||
def getlastmodtime_cmd filename
|
||||
t = PhysicsFS.last_mod_time filename
|
||||
if t == -1
|
||||
puts "failed to determin. reason: #{PhysicsFS.last_error}"
|
||||
else
|
||||
puts "Last modified: #{Time.at(t)}"
|
||||
end
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
include Commands
|
||||
|
||||
def run command, args
|
||||
if args
|
||||
args = parse_args args
|
||||
else
|
||||
args = []
|
||||
end
|
||||
|
||||
begin
|
||||
cmd = method "#{command}_cmd"
|
||||
if args.length == cmd.arity
|
||||
return cmd.call *args
|
||||
else
|
||||
usage command
|
||||
true
|
||||
end
|
||||
rescue NameError
|
||||
puts 'Unknown command. Enter "help" for instructions.'
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
if __FILE__ == $0
|
||||
|
||||
PhysicsFS.init($0) or die "PhysicsFS init failed"
|
||||
|
||||
puts "PhysicsFS version: #{PhysicsFS.version}"
|
||||
puts
|
||||
|
||||
puts "Supported archives: "
|
||||
puts PhysicsFS.supported_archives
|
||||
puts
|
||||
|
||||
puts 'Enter commands. Enter "help" for instructions.'
|
||||
|
||||
loop {
|
||||
line = Readline::readline "physfs_rb> ", true
|
||||
break unless parse line
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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,193 @@
|
||||
/*
|
||||
* 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).
|
||||
*/
|
||||
|
||||
#include <stdio.h> /* used for SEEK_SET, SEEK_CUR, SEEK_END ... */
|
||||
#include "physfsrwops.h"
|
||||
|
||||
static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
int pos = 0;
|
||||
|
||||
if (whence == SEEK_SET)
|
||||
{
|
||||
pos = offset;
|
||||
} /* if */
|
||||
|
||||
else if (whence == SEEK_CUR)
|
||||
{
|
||||
PHYSFS_sint64 current = PHYSFS_tell(handle);
|
||||
if (current == -1)
|
||||
{
|
||||
SDL_SetError("Can't find position in file: %s",
|
||||
PHYSFS_getLastError());
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
pos = (int) current;
|
||||
if ( ((PHYSFS_sint64) pos) != current )
|
||||
{
|
||||
SDL_SetError("Can't fit current file position in an int!");
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
if (offset == 0) /* this is a "tell" call. We're done. */
|
||||
return(pos);
|
||||
|
||||
pos += offset;
|
||||
} /* else if */
|
||||
|
||||
else if (whence == SEEK_END)
|
||||
{
|
||||
PHYSFS_sint64 len = PHYSFS_fileLength(handle);
|
||||
if (len == -1)
|
||||
{
|
||||
SDL_SetError("Can't find end of file: %s", PHYSFS_getLastError());
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
pos = (int) len;
|
||||
if ( ((PHYSFS_sint64) pos) != len )
|
||||
{
|
||||
SDL_SetError("Can't fit end-of-file position in an int!");
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
pos += 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 */
|
||||
|
||||
return(pos);
|
||||
} /* physfsrwops_seek */
|
||||
|
||||
|
||||
static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
PHYSFS_sint64 rc = PHYSFS_read(handle, ptr, size, maxnum);
|
||||
if (rc != maxnum)
|
||||
{
|
||||
if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
} /* if */
|
||||
|
||||
return((int) rc);
|
||||
} /* physfsrwops_read */
|
||||
|
||||
|
||||
static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
PHYSFS_sint64 rc = PHYSFS_write(handle, ptr, size, num);
|
||||
if (rc != num)
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
|
||||
return((int) rc);
|
||||
} /* 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().
|
||||
*/
|
||||
__EXPORT__ 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().
|
||||
*/
|
||||
__EXPORT__ 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().
|
||||
*/
|
||||
__EXPORT__ 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().
|
||||
*/
|
||||
__EXPORT__ 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 */
|
||||
|
||||
Reference in New Issue
Block a user