diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f76e394 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*] +end_of_line = crlf + +[*.cs] +indent_style = space +indent_size = 2 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a1ce1d5..06d8732 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,4 +6,8 @@ ## Version 0.1.0 - *THIS VERSION INCLUDES MAJOR BREAKING CHANGES* -- The library is no longer static \ No newline at end of file +- The library is no longer static + +## Version 0.2.0 +- New dataless enumeration functions are available now, which do not cause GC havoc +- Unsafe enumeration functions are now marked obsolete \ No newline at end of file diff --git a/README.md b/README.md index 85bd7d4..4b1d10c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The documentation for the methods is copied from the original doxygen and only s ## Platform support -The library is designed to work regardlessly of the underlying OS, so it should work on Windows, Linux +The library is designed to work regardless of the underlying OS, so it should run on Windows, Linux and OSX equally well. I haven't tested the OSX port though, and I only superficially tried it on Linux. If anyone feels so inclined, he/she could contribute by testing it and reporting the results. This would @@ -21,4 +21,22 @@ be greatly appreciated. You can use this library by compiling it as described in the [wiki](https://github.com/frabert/SharpPhysFS/wiki) or by adding it as a reference using NuGet: - Install-Package SharpPhysFS \ No newline at end of file + Install-Package SharpPhysFS + +You should also include compiled shared library of physfs alongside your binary files to be loaded. + +## Usage + +````c# +using(var pfs = new PhysFS("")) // This ensures correct initialization and deinitialization +using(var stream = pfs.OpenRead("/helloworld.txt")) +{ + var reader = new StreamReader(stream); + var contents = reader.ReadToEnd(); +} +```` + +## Support on Beerpay +Hey dude! Help me out for a couple of :beers:! + +[![Beerpay](https://beerpay.io/frabert/SharpPhysFS/badge.svg?style=beer-square)](https://beerpay.io/frabert/SharpPhysFS) [![Beerpay](https://beerpay.io/frabert/SharpPhysFS/make-wish.svg?style=flat-square)](https://beerpay.io/frabert/SharpPhysFS?focus=wish) \ No newline at end of file diff --git a/SharpPhysFS.sln b/SharpPhysFS.sln index fb858ca..aa284c9 100644 --- a/SharpPhysFS.sln +++ b/SharpPhysFS.sln @@ -1,12 +1,13 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.26403.3 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpPhysFS", "SharpPhysFS\SharpPhysFS.csproj", "{AD6AA182-8C7F-4F3A-AAEF-7BD993D1D262}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{250EE88E-18B5-4433-ACF0-24A1D81429CF}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig CHANGELOG.md = CHANGELOG.md LICENSE.md = LICENSE.md README.md = README.md diff --git a/SharpPhysFS/Interop.cs b/SharpPhysFS/Interop.cs index 891a271..c531b7e 100644 --- a/SharpPhysFS/Interop.cs +++ b/SharpPhysFS/Interop.cs @@ -101,6 +101,7 @@ namespace SharpPhysFS class Interop : IDisposable { + InvalidOperationException initException = new InvalidOperationException("Callbacks not initialized yet"); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void FnGetLinkedVersion(ref Version v); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -147,51 +148,51 @@ namespace SharpPhysFS // When the callbacks are not yet initialized, instead of throwing a // null reference exception we explain the problem. // I think it makes for a more graceful failure. - public FnGetLinkedVersion PHYSFS_getLinkedVersion = (ref Version v) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnInit PHYSFS_init = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnDeinit PHYSFS_deinit = () => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnSupportedArchiveTypes PHYSFS_supportedArchiveTypes = () => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnFreeList PHYSFS_freeList = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnGetLastError PHYSFS_getLastError = () => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnGetLastError PHYSFS_getDirSeparator = () => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnPermitSymbolicLinks PHYSFS_permitSymbolicLinks = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnSupportedArchiveTypes PHYSFS_getCdRomDirs = () => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnGetLastError PHYSFS_getBaseDir = () => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnGetLastError PHYSFS_getUserDir = () => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnGetLastError PHYSFS_getWriteDir = () => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnSetWriteDir PHYSFS_setWriteDir = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnAddToSearchPath PHYSFS_addToSearchPath = (a, b) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnSetWriteDir PHYSFS_removeFromSearchPath = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnSupportedArchiveTypes PHYSFS_getSearchPath = () => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnSetSaneConfig PHYSFS_setSaneConfig = (a, b, c, d, e) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnSetWriteDir PHYSFS_mkdir = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnSetWriteDir PHYSFS_delete = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnEnumerateFiles PHYSFS_getRealDir = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnEnumerateFiles PHYSFS_enumerateFiles = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnSetWriteDir PHYSFS_exists = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnSetWriteDir PHYSFS_isDirectory = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnSetWriteDir PHYSFS_isSymbolicLink = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnGetLastModTime PHYSFS_getLastModTime = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnEnumerateFiles PHYSFS_openWrite = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnEnumerateFiles PHYSFS_openAppend = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnEnumerateFiles PHYSFS_openRead = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnClose PHYSFS_close = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnRead PHYSFS_read = (a, b, c, d) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnRead PHYSFS_write = (a, b, c,d ) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnClose PHYSFS_eof = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnTell PHYSFS_tell = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnSeek PHYSFS_seek = (a, b) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnFileLength PHYSFS_fileLength = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnSeek PHYSFS_setBuffer = (a, b) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnClose PHYSFS_flush = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnDeinit PHYSFS_isInit = () => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnDeinit PHYSFS_symbolicLinksPermitted = () => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnSetAllocator PHYSFS_setAllocator = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnMount PHYSFS_mount = (a, b, c) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnEnumerateFiles PHYSFS_getMountPoint = (a) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnGetCdRomDirsCallback PHYSFS_getCdRomDirsCallback = (a, b) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnGetCdRomDirsCallback PHYSFS_getSearchPathCallback = (a, b) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; - public FnEnumerateFilesCallback PHYSFS_enumerateFilesCallback = (a, b, c) => { throw new InvalidOperationException("Callbacks not initialized yet"); }; + public FnGetLinkedVersion PHYSFS_getLinkedVersion => throw initException; + public FnInit PHYSFS_init => throw initException; + public FnDeinit PHYSFS_deinit => throw initException; + public FnSupportedArchiveTypes PHYSFS_supportedArchiveTypes => throw initException; + public FnFreeList PHYSFS_freeList => throw initException; + public FnGetLastError PHYSFS_getLastError => throw initException; + public FnGetLastError PHYSFS_getDirSeparator => throw initException; + public FnPermitSymbolicLinks PHYSFS_permitSymbolicLinks => throw initException; + public FnSupportedArchiveTypes PHYSFS_getCdRomDirs => throw initException; + public FnGetLastError PHYSFS_getBaseDir => throw initException; + public FnGetLastError PHYSFS_getUserDir => throw initException; + public FnGetLastError PHYSFS_getWriteDir => throw initException; + public FnSetWriteDir PHYSFS_setWriteDir => throw initException; + public FnAddToSearchPath PHYSFS_addToSearchPath => throw initException; + public FnSetWriteDir PHYSFS_removeFromSearchPath => throw initException; + public FnSupportedArchiveTypes PHYSFS_getSearchPath => throw initException; + public FnSetSaneConfig PHYSFS_setSaneConfig => throw initException; + public FnSetWriteDir PHYSFS_mkdir => throw initException; + public FnSetWriteDir PHYSFS_delete => throw initException; + public FnEnumerateFiles PHYSFS_getRealDir => throw initException; + public FnEnumerateFiles PHYSFS_enumerateFiles => throw initException; + public FnSetWriteDir PHYSFS_exists => throw initException; + public FnSetWriteDir PHYSFS_isDirectory => throw initException; + public FnSetWriteDir PHYSFS_isSymbolicLink => throw initException; + public FnGetLastModTime PHYSFS_getLastModTime => throw initException; + public FnEnumerateFiles PHYSFS_openWrite => throw initException; + public FnEnumerateFiles PHYSFS_openAppend => throw initException; + public FnEnumerateFiles PHYSFS_openRead => throw initException; + public FnClose PHYSFS_close => throw initException; + public FnRead PHYSFS_read => throw initException; + public FnRead PHYSFS_write => throw initException; + public FnClose PHYSFS_eof => throw initException; + public FnTell PHYSFS_tell => throw initException; + public FnSeek PHYSFS_seek => throw initException; + public FnFileLength PHYSFS_fileLength => throw initException; + public FnSeek PHYSFS_setBuffer => throw initException; + public FnClose PHYSFS_flush => throw initException; + public FnDeinit PHYSFS_isInit => throw initException; + public FnDeinit PHYSFS_symbolicLinksPermitted => throw initException; + public FnSetAllocator PHYSFS_setAllocator => throw initException; + public FnMount PHYSFS_mount => throw initException; + public FnEnumerateFiles PHYSFS_getMountPoint => throw initException; + public FnGetCdRomDirsCallback PHYSFS_getCdRomDirsCallback => throw initException; + public FnGetCdRomDirsCallback PHYSFS_getSearchPathCallback => throw initException; + public FnEnumerateFilesCallback PHYSFS_enumerateFilesCallback => throw initException; public Interop() : this("physfs.dll", "libphysfs.dylib", "libphysfs.so") diff --git a/SharpPhysFS/PhysFS.LowLevel.cs b/SharpPhysFS/PhysFS.LowLevel.cs index d1db0b1..2c847db 100644 --- a/SharpPhysFS/PhysFS.LowLevel.cs +++ b/SharpPhysFS/PhysFS.LowLevel.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace SharpPhysFS { diff --git a/SharpPhysFS/PhysFS.cs b/SharpPhysFS/PhysFS.cs index 33aeaad..a9c5e72 100644 --- a/SharpPhysFS/PhysFS.cs +++ b/SharpPhysFS/PhysFS.cs @@ -178,10 +178,7 @@ namespace SharpPhysFS public string[] EnumerateFiles(string dir) { var list = new List(); - EnumerateFilesCallback(dir, (d, o, f) => - { - list.Add(f); - }, null); + EnumerateFilesCallback(dir, (o, f) => list.Add(f)); return list.ToArray(); } @@ -258,10 +255,7 @@ namespace SharpPhysFS public string[] GetCdRomDirs() { var list = new List(); - GetCdRomDirsCallback((d, s) => - { - list.Add(s); - }, null); + GetCdRomDirsCallback((s) => list.Add(s)); return list.ToArray(); } @@ -359,13 +353,8 @@ namespace SharpPhysFS /// public string[] GetSearchPath() { - //var dirs = Interop.PHYSFS_getSearchPath(); - //return GenEnumerable(dirs); var list = new List(); - GetSearchPathCallback((d, s) => - { - list.Add(s); - }, null); + GetSearchPathCallback((s) => list.Add(s)); return list.ToArray(); } @@ -616,6 +605,7 @@ namespace SharpPhysFS }; } + [Obsolete("The non-generic variant of GetCdRomDirsCallback is meant for internal use only. Consider using one of the generic alternatives.")] public void GetCdRomDirsCallback(StringCallback c, object data) { GCHandle objHandle = GCHandle.Alloc(data); @@ -626,6 +616,10 @@ namespace SharpPhysFS /// /// Enumerate CD-ROM directories, using an application-defined callback. /// + /// + /// if you don't need to pass + /// custom data to the callback. + /// /// Type of data passed to callback /// Callback function to notify about detected drives. /// Application-defined data passed to callback. Can be null. @@ -634,6 +628,16 @@ namespace SharpPhysFS GetCdRomDirsCallback(WrapStringCallback(c), data); } + /// + /// Enumerate CD-ROM directories, using an application-defined callback. + /// + /// Callback function to notify about detected drives. + public void GetCdRomDirsCallback(Action c) + { + interop.PHYSFS_getCdRomDirsCallback((p, s) => c(s), IntPtr.Zero); + } + + [Obsolete("The non-generic variant of GetSearchPathCallback is meant for internal use only. Consider using one of the generic alternatives.")] public void GetSearchPathCallback(StringCallback c, object data) { GCHandle objHandle = GCHandle.Alloc(data); @@ -644,6 +648,10 @@ namespace SharpPhysFS /// /// Enumerate the search path, using an application-defined callback. /// + /// + /// if you don't need to pass + /// custom data to the callback. + /// /// Type of data passed to callback /// Callback function to notify about search path elements. /// Application-defined data passed to callback. Can be null. @@ -652,6 +660,16 @@ namespace SharpPhysFS GetSearchPathCallback(WrapStringCallback(c), data); } + /// + /// Enumerate the search path, using an application-defined callback. + /// + /// Callback function to notify about search path elements. + public void GetSearchPathCallback(Action c) + { + interop.PHYSFS_getSearchPathCallback((p, s) => c(s), IntPtr.Zero); + } + + [Obsolete("The non-generic variant of EnumerateFilesCallback is meant for internal use only. Consider using one of the generic alternatives.")] public void EnumerateFilesCallback(string dir, EnumFilesCallback c, object data) { GCHandle objHandle = GCHandle.Alloc(data); @@ -662,6 +680,10 @@ namespace SharpPhysFS /// /// Get a file listing of a search path's directory, using an application-defined callback. /// + /// + /// if you don't need + /// to pass custom data to the callback. + /// /// Type of data passed to callback /// Directory, in platform-independent notation, to enumerate. /// Callback function to notify about search path elements. @@ -675,6 +697,16 @@ namespace SharpPhysFS }, data); } + /// + /// Get a file listing of a search path's directory, using an application-defined callback. + /// + /// Directory, in platform-independent notation, to enumerate. + /// Callback function to notify about search path elements. + public void EnumerateFilesCallback(string dir, Action c) + { + interop.PHYSFS_enumerateFilesCallback(dir, (data, origdir, fname) => c(origdir, fname), IntPtr.Zero); + } + public PhysFSStream OpenAppend(string file) { var handle = LowLevel.OpenAppend(file, this); diff --git a/SharpPhysFS/Properties/AssemblyInfo.cs b/SharpPhysFS/Properties/AssemblyInfo.cs index 78d475e..c752f54 100644 --- a/SharpPhysFS/Properties/AssemblyInfo.cs +++ b/SharpPhysFS/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.1.0.0")] -[assembly: AssemblyFileVersion("0.1.0.0")] +[assembly: AssemblyVersion("0.2.0.0")] +[assembly: AssemblyFileVersion("0.2.0.0")]