aboutsummaryrefslogtreecommitdiff
path: root/Utils/src/Extensions/IoExtensions.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Utils/src/Extensions/IoExtensions.cs')
-rw-r--r--Utils/src/Extensions/IoExtensions.cs345
1 files changed, 0 insertions, 345 deletions
diff --git a/Utils/src/Extensions/IoExtensions.cs b/Utils/src/Extensions/IoExtensions.cs
deleted file mode 100644
index f312203..0000000
--- a/Utils/src/Extensions/IoExtensions.cs
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Utils
-* File: IoExtensions.cs
-*
-* IoExtensions.cs is part of VNLib.Utils which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Utils is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published
-* by the Free Software Foundation, either version 2 of the License,
-* or (at your option) any later version.
-*
-* VNLib.Utils is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with VNLib.Utils. If not, see http://www.gnu.org/licenses/.
-*/
-
-using System;
-using System.IO;
-using System.Buffers;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Runtime.Versioning;
-using System.Runtime.CompilerServices;
-
-using VNLib.Utils.IO;
-using VNLib.Utils.Memory;
-
-using static VNLib.Utils.Memory.Memory;
-
-namespace VNLib.Utils.Extensions
-{
- /// <summary>
- /// Provieds extension methods for common IO operations
- /// </summary>
- public static class IoExtensions
- {
- /// <summary>
- /// Unlocks the entire file
- /// </summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- [UnsupportedOSPlatform("ios")]
- [UnsupportedOSPlatform("macos")]
- [UnsupportedOSPlatform("tvos")]
- public static void Unlock(this FileStream fs)
- {
- _ = fs ?? throw new ArgumentNullException(nameof(fs));
- //Unlock the entire file
- fs.Unlock(0, fs.Length);
- }
-
- /// <summary>
- /// Locks the entire file
- /// </summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- [UnsupportedOSPlatform("ios")]
- [UnsupportedOSPlatform("macos")]
- [UnsupportedOSPlatform("tvos")]
- public static void Lock(this FileStream fs)
- {
- _ = fs ?? throw new ArgumentNullException(nameof(fs));
- //Lock the entire length of the file
- fs.Lock(0, fs.Length);
- }
-
- /// <summary>
- /// Provides an async wrapper for copying data from the current stream to another using an unmanged
- /// buffer.
- /// </summary>
- /// <param name="source"></param>
- /// <param name="dest">The destination data stream to write data to</param>
- /// <param name="bufferSize">The size of the buffer to use while copying data. (Value will be clamped to the size of the stream if seeking is available)</param>
- /// <param name="heap">The <see cref="IUnmangedHeap"/> to allocate the buffer from</param>
- /// <param name="token">A token that may cancel asynchronous operations</param>
- /// <returns>A <see cref="ValueTask"/> that completes when the copy operation has completed</returns>
- /// <exception cref="IOException"></exception>
- /// <exception cref="ArgumentException"></exception>
- public static async ValueTask CopyToAsync(this Stream source, Stream dest, int bufferSize, IUnmangedHeap heap, CancellationToken token = default)
- {
- if (source.CanSeek)
- {
- bufferSize = (int)Math.Min(source.Length, bufferSize);
- }
- //Alloc a buffer
- using IMemoryOwner<byte> buffer = heap.DirectAlloc<byte>(bufferSize);
- //Wait for copy to complete
- await CopyToAsync(source, dest, buffer.Memory, token);
- }
- /// <summary>
- /// Provides an async wrapper for copying data from the current stream to another with a
- /// buffer from the <paramref name="heap"/>
- /// </summary>
- /// <param name="source"></param>
- /// <param name="dest">The destination data stream to write data to</param>
- /// <param name="bufferSize">The size of the buffer to use while copying data. (Value will be clamped to the size of the stream if seeking is available)</param>
- /// <param name="count">The number of bytes to copy from the current stream to destination stream</param>
- /// <param name="heap">The heap to alloc buffer from</param>
- /// <param name="token">A token that may cancel asynchronous operations</param>
- /// <returns>A <see cref="ValueTask"/> that completes when the copy operation has completed</returns>
- /// <exception cref="IOException"></exception>
- /// <exception cref="ArgumentException"></exception>
- public static async ValueTask CopyToAsync(this Stream source, Stream dest, long count, int bufferSize, IUnmangedHeap heap, CancellationToken token = default)
- {
- if (source.CanSeek)
- {
- bufferSize = (int)Math.Min(source.Length, bufferSize);
- }
- //Alloc a buffer
- using IMemoryOwner<byte> buffer = heap.DirectAlloc<byte>(bufferSize);
- //Wait for copy to complete
- await CopyToAsync(source, dest, buffer.Memory, count, token);
- }
-
- /// <summary>
- /// Copies data from one stream to another, using self managed buffers. May allocate up to 2MB.
- /// </summary>
- /// <param name="source">Source stream to read from</param>
- /// <param name="dest">Destination stream to write data to</param>
- /// <param name="heap">The heap to allocate buffers from</param>
- /// <exception cref="ArgumentException"></exception>
- /// <exception cref="ArgumentNullException"></exception>
- public static void CopyTo(this Stream source, Stream dest, IUnmangedHeap? heap = null)
- {
- if (!source.CanRead)
- {
- throw new ArgumentException("Source stream is unreadable", nameof(source));
- }
- if (!dest.CanWrite)
- {
- throw new ArgumentException("Destination stream is unwritable", nameof(dest));
- }
- heap ??= Shared;
- //Get a buffer size, maximum of 2mb buffer size if the stream supports seeking, otherwise, min buf size
- int bufSize = source.CanSeek ? (int)Math.Min(source.Length, MAX_BUF_SIZE) : MIN_BUF_SIZE;
- //Length must be 0, so return
- if (bufSize == 0)
- {
- return;
- }
- //Alloc a buffer
- using UnsafeMemoryHandle<byte> buffer = heap.UnsafeAlloc<byte>(bufSize);
- int read;
- do
- {
- //read
- read = source.Read(buffer.Span);
- //Guard
- if (read == 0)
- {
- break;
- }
- //write only the data that was read (slice)
- dest.Write(buffer.Span[..read]);
- } while (true);
- }
- /// <summary>
- /// Copies data from one stream to another, using self managed buffers. May allocate up to 2MB.
- /// </summary>
- /// <param name="source">Source stream to read from</param>
- /// <param name="dest">Destination stream to write data to</param>
- /// <param name="count">Number of bytes to read/write</param>
- /// <param name="heap">The heap to allocate buffers from</param>
- /// <exception cref="ArgumentException"></exception>
- /// <exception cref="ArgumentNullException"></exception>
- public static void CopyTo(this Stream source, Stream dest, long count, IUnmangedHeap? heap = null)
- {
- if (!source.CanRead)
- {
- throw new ArgumentException("Source stream is unreadable", nameof(source));
- }
- if (!dest.CanWrite)
- {
- throw new ArgumentException("Destination stream is unwritable", nameof(dest));
- }
- //Set default heap
- heap ??= Shared;
- //Get a buffer size, maximum of 2mb buffer size if the stream supports seeking, otherwise, min buf size
- int bufSize = source.CanSeek ? (int)Math.Min(source.Length, MAX_BUF_SIZE) : MIN_BUF_SIZE;
- //Length must be 0, so return
- if (bufSize == 0)
- {
- return;
- }
- //Alloc a buffer
- using UnsafeMemoryHandle<byte> buffer = heap.UnsafeAlloc<byte>(bufSize);
- //wrapper around offset pointer
- long total = 0;
- int read;
- do
- {
- Span<byte> wrapper = buffer.Span[..(int)Math.Min(bufSize, (count - total))];
- //read
- read = source.Read(wrapper);
- //Guard
- if (read == 0)
- {
- break;
- }
- //write only the data that was read (slice)
- dest.Write(wrapper[..read]);
- //Update total
- total += read;
- } while (true);
- }
-
- /// <summary>
- /// Copies data from the current stream to the destination stream using the supplied memory buffer
- /// </summary>
- /// <param name="source"></param>
- /// <param name="dest">The destination data stream to write data to</param>
- /// <param name="buffer">The buffer to use when copying data</param>
- /// <param name="token">A token that may cancel asynchronous operations</param>
- /// <returns>A <see cref="ValueTask"/> that completes when the copy operation has completed</returns>
- /// <exception cref="ArgumentException"></exception>
- public static async ValueTask CopyToAsync(this Stream source, Stream dest, Memory<byte> buffer, CancellationToken token = default)
- {
- //Make sure source can be read from, and dest can be written to
- if (!source.CanRead)
- {
- throw new ArgumentException("Source stream is unreadable", nameof(source));
- }
- if (!dest.CanWrite)
- {
- throw new ArgumentException("Destination stream is unwritable", nameof(dest));
- }
- //Read in loop
- int read;
- while (true)
- {
- //read
- read = await source.ReadAsync(buffer, token);
- //Guard
- if (read == 0)
- {
- break;
- }
- //write only the data that was read (slice)
- await dest.WriteAsync(buffer[..read], token);
- }
- }
-
- /// <summary>
- /// Copies data from the current stream to the destination stream using the supplied memory buffer
- /// </summary>
- /// <param name="source"></param>
- /// <param name="dest">The destination data stream to write data to</param>
- /// <param name="buffer">The buffer to use when copying data</param>
- /// <param name="count">The number of bytes to copy from the current stream to destination stream</param>
- /// <param name="token">A token that may cancel asynchronous operations</param>
- /// <returns>A <see cref="ValueTask"/> that completes when the copy operation has completed</returns>
- /// <exception cref="ArgumentException"></exception>
- public static async ValueTask CopyToAsync(this Stream source, Stream dest, Memory<byte> buffer, long count, CancellationToken token = default)
- {
- //Make sure source can be read from, and dest can be written to
- if (!source.CanRead)
- {
- throw new ArgumentException("Source stream is unreadable", nameof(source));
- }
- if (!dest.CanWrite)
- {
- throw new ArgumentException("Destination stream is unwritable", nameof(dest));
- }
- /*
- * Track total count so we copy the exect number of
- * bytes from the source
- */
- long total = 0;
- int bufferSize = buffer.Length;
- int read;
- while (true)
- {
- //get offset wrapper of the total buffer or remaining count
- Memory<byte> offset = buffer[..(int)Math.Min(bufferSize, count - total)];
- //read
- read = await source.ReadAsync(offset, token);
- //Guard
- if (read == 0)
- {
- break;
- }
- //write only the data that was read (slice)
- await dest.WriteAsync(offset[..read], token);
- //Update total
- total += read;
- }
- }
-
- /// <summary>
- /// Opens a file within the current directory
- /// </summary>
- /// <param name="dir"></param>
- /// <param name="fileName">The name of the file to open</param>
- /// <param name="mode">The <see cref="FileMode"/> to open the file with</param>
- /// <param name="access">The <see cref="FileAccess"/> to open the file with</param>
- /// <param name="share"></param>
- /// <param name="bufferSize">The size of the buffer to read/write with</param>
- /// <param name="options"></param>
- /// <returns>The <see cref="FileStream"/> of the opened file</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static FileStream OpenFile(this DirectoryInfo dir,
- string fileName,
- FileMode mode,
- FileAccess access,
- FileShare share = FileShare.None,
- int bufferSize = 4096,
- FileOptions options = FileOptions.None)
- {
- _ = dir ?? throw new ArgumentNullException(nameof(dir));
- string fullPath = Path.Combine(dir.FullName, fileName);
- return new FileStream(fullPath, mode, access, share, bufferSize, options);
- }
- /// <summary>
- /// Deletes the speicifed file from the current directory
- /// </summary>
- /// <param name="dir"></param>
- /// <param name="fileName">The name of the file to delete</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void DeleteFile(this DirectoryInfo dir, string fileName)
- {
- _ = dir ?? throw new ArgumentNullException(nameof(dir));
- string fullPath = Path.Combine(dir.FullName, fileName);
- File.Delete(fullPath);
- }
- /// <summary>
- /// Determines if a file exists within the current directory
- /// </summary>
- /// <param name="dir"></param>
- /// <param name="fileName">The name of the file to search for</param>
- /// <returns>True if the file is found and the user has permission to access the file, false otherwise</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool FileExists(this DirectoryInfo dir, string fileName)
- {
- _ = dir ?? throw new ArgumentNullException(nameof(dir));
- string fullPath = Path.Combine(dir.FullName, fileName);
- return FileOperations.FileExists(fullPath);
- }
- }
-} \ No newline at end of file