aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-05-26 21:44:22 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2023-05-26 21:44:22 -0400
commit858773acf273567bcb7eb5b18c45c9d8e6a97349 (patch)
tree8fc955a54ff7c686f865fc6c62ec523a9fc229c4 /lib
parentfc6cb7a1e66aa96ab468b8ad7ff12329d992e35f (diff)
Minior refactor
Diffstat (limited to 'lib')
-rw-r--r--lib/Hashing.Portable/src/IdentityUtility/JsonWebToken.cs2
-rw-r--r--lib/Net.Http/src/Core/HttpCookie.cs2
-rw-r--r--lib/Net.Http/src/Core/Request/HttpRequest.cs2
-rw-r--r--lib/Net.Http/src/Core/Response/ChunkedStream.cs4
-rw-r--r--lib/Net.Http/src/Core/Response/HttpResponse.cs2
-rw-r--r--lib/Net.Messaging.FBM/src/Client/FBMRequest.cs6
-rw-r--r--lib/Utils/src/IO/ArrayPoolStreamBuffer.cs52
-rw-r--r--lib/Utils/src/IO/FileOperations.cs47
-rw-r--r--lib/Utils/src/IO/IStreamBufferFactory.cs41
-rw-r--r--lib/Utils/src/IO/SlidingWindowBufferExtensions.cs11
-rw-r--r--lib/Utils/src/IO/VnStreamReader.cs84
-rw-r--r--lib/Utils/src/IO/VnStreamWriter.cs87
-rw-r--r--lib/Utils/src/IO/WriteOnlyBufferedStream.cs61
-rw-r--r--lib/Utils/src/Memory/ForwardOnlyMemoryReader.cs7
-rw-r--r--lib/Utils/src/Memory/ForwardOnlyMemoryWriter.cs9
-rw-r--r--lib/Utils/src/Memory/ForwardOnlyReader.cs6
-rw-r--r--lib/Utils/src/Memory/ForwardOnlyWriter.cs9
-rw-r--r--lib/Utils/src/Memory/IStringSerializeable.cs6
-rw-r--r--lib/Utils/src/Memory/MemoryUtil.cs47
19 files changed, 349 insertions, 136 deletions
diff --git a/lib/Hashing.Portable/src/IdentityUtility/JsonWebToken.cs b/lib/Hashing.Portable/src/IdentityUtility/JsonWebToken.cs
index ef313ca..c5409a8 100644
--- a/lib/Hashing.Portable/src/IdentityUtility/JsonWebToken.cs
+++ b/lib/Hashing.Portable/src/IdentityUtility/JsonWebToken.cs
@@ -310,7 +310,7 @@ namespace VNLib.Hashing.IdentityUtility
///<inheritdoc/>
///<exception cref="ObjectDisposedException"></exception>
- public virtual ERRNO Compile(in Span<char> buffer)
+ public virtual ERRNO Compile(Span<char> buffer)
{
ForwardOnlyWriter<char> writer = new(buffer);
Compile(ref writer);
diff --git a/lib/Net.Http/src/Core/HttpCookie.cs b/lib/Net.Http/src/Core/HttpCookie.cs
index c48ad00..e0e5406 100644
--- a/lib/Net.Http/src/Core/HttpCookie.cs
+++ b/lib/Net.Http/src/Core/HttpCookie.cs
@@ -103,7 +103,7 @@ namespace VNLib.Net.Http.Core
writer.Append("; Secure");
}
}
- public ERRNO Compile(in Span<char> buffer)
+ public ERRNO Compile(Span<char> buffer)
{
ForwardOnlyWriter<char> writer = new(buffer);
Compile(ref writer);
diff --git a/lib/Net.Http/src/Core/Request/HttpRequest.cs b/lib/Net.Http/src/Core/Request/HttpRequest.cs
index f638ac9..b036680 100644
--- a/lib/Net.Http/src/Core/Request/HttpRequest.cs
+++ b/lib/Net.Http/src/Core/Request/HttpRequest.cs
@@ -270,7 +270,7 @@ namespace VNLib.Net.Http.Core
writer.Append("\r\n");
}
- public ERRNO Compile(in Span<char> buffer)
+ public ERRNO Compile(Span<char> buffer)
{
ForwardOnlyWriter<char> writer = new(buffer);
Compile(ref writer);
diff --git a/lib/Net.Http/src/Core/Response/ChunkedStream.cs b/lib/Net.Http/src/Core/Response/ChunkedStream.cs
index 1b4f7de..3aa4330 100644
--- a/lib/Net.Http/src/Core/Response/ChunkedStream.cs
+++ b/lib/Net.Http/src/Core/Response/ChunkedStream.cs
@@ -93,7 +93,7 @@ namespace VNLib.Net.Http.Core
}
//Init reader
- ForwardOnlyReader<byte> reader = new(in chunk);
+ ForwardOnlyReader<byte> reader = new(chunk);
try
{
do
@@ -147,7 +147,7 @@ namespace VNLib.Net.Http.Core
try
{
//Init reader
- ForwardOnlyMemoryReader<byte> reader = new(in chunk);
+ ForwardOnlyMemoryReader<byte> reader = new(chunk);
do
{
diff --git a/lib/Net.Http/src/Core/Response/HttpResponse.cs b/lib/Net.Http/src/Core/Response/HttpResponse.cs
index 952311d..6d974ed 100644
--- a/lib/Net.Http/src/Core/Response/HttpResponse.cs
+++ b/lib/Net.Http/src/Core/Response/HttpResponse.cs
@@ -382,7 +382,7 @@ namespace VNLib.Net.Http.Core
writer.Append(HttpHelpers.CRLF);
}
- public ERRNO Compile(in Span<char> buffer)
+ public ERRNO Compile(Span<char> buffer)
{
ForwardOnlyWriter<char> writer = new(buffer);
Compile(ref writer);
diff --git a/lib/Net.Messaging.FBM/src/Client/FBMRequest.cs b/lib/Net.Messaging.FBM/src/Client/FBMRequest.cs
index bffa1ca..c4fb493 100644
--- a/lib/Net.Messaging.FBM/src/Client/FBMRequest.cs
+++ b/lib/Net.Messaging.FBM/src/Client/FBMRequest.cs
@@ -126,9 +126,11 @@ namespace VNLib.Net.Messaging.FBM.Client
///<inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void WriteHeader(HeaderCommand header, ReadOnlySpan<char> value) => WriteHeader((byte)header, value);
+
///<inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void WriteHeader(byte header, ReadOnlySpan<char> value) => Helpers.WriteHeader(Buffer.RequestBuffer, header, value, Helpers.DefaultEncoding);
+
///<inheritdoc/>
public void WriteBody(ReadOnlySpan<byte> body, ContentType contentType = ContentType.Binary)
{
@@ -244,7 +246,7 @@ namespace VNLib.Net.Messaging.FBM.Client
using UnsafeMemoryHandle<char> buffer = MemoryUtil.UnsafeAlloc<char>(charSize + 128);
- ERRNO count = Compile(buffer.Span);
+ ERRNO count = Compile(buffer);
return buffer.AsSpan(0, count).ToString();
}
@@ -258,7 +260,7 @@ namespace VNLib.Net.Messaging.FBM.Client
Helpers.DefaultEncoding.GetChars(requestData.Span, ref writer);
}
///<inheritdoc/>
- public ERRNO Compile(in Span<char> buffer)
+ public ERRNO Compile(Span<char> buffer)
{
ForwardOnlyWriter<char> writer = new(buffer);
Compile(ref writer);
diff --git a/lib/Utils/src/IO/ArrayPoolStreamBuffer.cs b/lib/Utils/src/IO/ArrayPoolStreamBuffer.cs
index df366e3..b62412f 100644
--- a/lib/Utils/src/IO/ArrayPoolStreamBuffer.cs
+++ b/lib/Utils/src/IO/ArrayPoolStreamBuffer.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -27,32 +27,46 @@ using System.Buffers;
namespace VNLib.Utils.IO
{
+
internal class ArrayPoolStreamBuffer<T> : ISlindingWindowBuffer<T>
{
+ /// <summary>
+ /// The shared <see cref="IStreamBufferFactory{T}"/> instance to allocate buffers
+ /// from
+ /// </summary>
+ public static IStreamBufferFactory<T> Shared { get; } = new DefaultFactory();
+
private readonly ArrayPool<T> _pool;
private T[] _buffer;
- public ArrayPoolStreamBuffer(ArrayPool<T> pool, int bufferSize)
+ /// <summary>
+ /// Creates a new <see cref="ArrayPoolStreamBuffer{T}"/> from the
+ /// given array instance and <see cref="ArrayPool{T}"/> it came from.
+ /// </summary>
+ /// <param name="array">The rented array to use</param>
+ /// <param name="pool">The pool to return the array to when completed</param>
+ public ArrayPoolStreamBuffer(T[] array, ArrayPool<T> pool)
{
_pool = pool;
- _buffer = _pool.Rent(bufferSize);
+ _buffer = array;
}
+ ///<inheritdoc/>
public int WindowStartPos { get; set; }
+
+ ///<inheritdoc/>
public int WindowEndPos { get; set; }
-
+
+ ///<inheritdoc/>
public Memory<T> Buffer => _buffer.AsMemory();
- public void Advance(int count)
- {
- WindowEndPos += count;
- }
+ ///<inheritdoc/>
+ public void Advance(int count) => WindowEndPos += count;
- public void AdvanceStart(int count)
- {
- WindowStartPos += count;
- }
+ ///<inheritdoc/>
+ public void AdvanceStart(int count) => WindowStartPos += count;
+ ///<inheritdoc/>
public void Close()
{
//Return buffer to pool
@@ -60,11 +74,25 @@ namespace VNLib.Utils.IO
_buffer = null;
}
+ ///<inheritdoc/>
public void Reset()
{
//Reset window positions
WindowStartPos = 0;
WindowEndPos = 0;
}
+
+ private sealed class DefaultFactory : IStreamBufferFactory<T>
+ {
+ ///<inheritdoc/>
+ public ISlindingWindowBuffer<T> CreateBuffer(int bufferSize)
+ {
+ //rent buffer
+ T[] array = ArrayPool<T>.Shared.Rent(bufferSize);
+
+ //return wrapper
+ return new ArrayPoolStreamBuffer<T>(array, ArrayPool<T>.Shared);
+ }
+ }
}
} \ No newline at end of file
diff --git a/lib/Utils/src/IO/FileOperations.cs b/lib/Utils/src/IO/FileOperations.cs
index e040da4..a8cd258 100644
--- a/lib/Utils/src/IO/FileOperations.cs
+++ b/lib/Utils/src/IO/FileOperations.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -27,7 +27,8 @@ using System.IO;
using System.Runtime.InteropServices;
namespace VNLib.Utils.IO
-{
+{
+
/// <summary>
/// Contains cross-platform optimized filesystem operations.
/// </summary>
@@ -38,13 +39,15 @@ namespace VNLib.Utils.IO
[DllImport("Shlwapi", SetLastError = true, CharSet = CharSet.Auto)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
[return:MarshalAs(UnmanagedType.Bool)]
- private static unsafe extern bool PathFileExists(char* path);
+ private static unsafe extern bool PathFileExists([MarshalAs(UnmanagedType.LPWStr)] string path);
+
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
[return:MarshalAs(UnmanagedType.I4)]
- private static unsafe extern int GetFileAttributes(char* path);
+ private static unsafe extern int GetFileAttributes([MarshalAs(UnmanagedType.LPWStr)] string path);
static readonly bool IsWindows = OperatingSystem.IsWindows();
+
/// <summary>
/// Determines if a file exists. If application is current running in the Windows operating system, Shlwapi.PathFileExists is invoked,
/// otherwise <see cref="File.Exists(string?)"/> is invoked
@@ -58,15 +61,9 @@ namespace VNLib.Utils.IO
{
return File.Exists(filePath);
}
- unsafe
- {
- //Get a char pointer to the file path
- fixed (char* path = filePath)
- {
- //Invoke the winap file function
- return PathFileExists(path);
- }
- }
+
+ //Invoke the winapi file function
+ return PathFileExists(filePath);
}
/// <summary>
@@ -84,22 +81,18 @@ namespace VNLib.Utils.IO
{
return File.GetAttributes(filePath);
}
- unsafe
+
+ //Invoke the winapi file function and cast the returned int value to file attributes
+ int attr = GetFileAttributes(filePath);
+
+ //Check for error
+ if (attr == INVALID_FILE_ATTRIBUTES)
{
- //Get a char pointer to the file path
- fixed (char* path = filePath)
- {
- //Invoke the winap file function and cast the returned int value to file attributes
- int attr = GetFileAttributes(path);
- //Check for error
- if (attr == INVALID_FILE_ATTRIBUTES)
- {
- throw new FileNotFoundException("The requested file was not found", filePath);
- }
- //Cast to file attributes and return
- return (FileAttributes)attr;
- }
+ throw new FileNotFoundException("The requested file was not found", filePath);
}
+
+ //Cast to file attributes and return
+ return (FileAttributes)attr;
}
}
} \ No newline at end of file
diff --git a/lib/Utils/src/IO/IStreamBufferFactory.cs b/lib/Utils/src/IO/IStreamBufferFactory.cs
new file mode 100644
index 0000000..f8cfe2d
--- /dev/null
+++ b/lib/Utils/src/IO/IStreamBufferFactory.cs
@@ -0,0 +1,41 @@
+/*
+* Copyright (c) 2023 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Utils
+* File: VnStreamReader.cs
+*
+* VnStreamReader.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/.
+*/
+
+namespace VNLib.Utils.IO
+{
+ /// <summary>
+ /// An interface that allows creating a <see cref="ISlindingWindowBuffer{T}"/> of the specified type
+ /// for stream reading/writing
+ /// </summary>
+ /// <typeparam name="T">The buffer element type</typeparam>
+ public interface IStreamBufferFactory<T>
+ {
+ /// <summary>
+ /// Creates a new <see cref="ISlindingWindowBuffer{T}"/> of the specified size
+ /// </summary>
+ /// <param name="bufferSize">The minimum size of the buffer to allocate</param>
+ /// <returns>The buffer instance</returns>
+ ISlindingWindowBuffer<T> CreateBuffer(int bufferSize);
+ }
+} \ No newline at end of file
diff --git a/lib/Utils/src/IO/SlidingWindowBufferExtensions.cs b/lib/Utils/src/IO/SlidingWindowBufferExtensions.cs
index 0509061..c8c62d3 100644
--- a/lib/Utils/src/IO/SlidingWindowBufferExtensions.cs
+++ b/lib/Utils/src/IO/SlidingWindowBufferExtensions.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -26,10 +26,10 @@ using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
+using System.Runtime.CompilerServices;
using VNLib.Utils.Memory;
using VNLib.Utils.Extensions;
-using System.Runtime.CompilerServices;
namespace VNLib.Utils.IO
{
@@ -49,7 +49,7 @@ namespace VNLib.Utils.IO
//Nothing to compact if the starting data pointer is at the beining of the window
if (sBuf.WindowStartPos > 0)
{
- //Get span over engire buffer
+ //Get span over entire buffer
Span<T> buffer = sBuf.Buffer.Span;
//Get data within window
Span<T> usedData = sBuf.Accumulated;
@@ -79,6 +79,7 @@ namespace VNLib.Utils.IO
//Advance by 1
sBuf.Advance(1);
}
+
/// <summary>
/// Appends the specified data to the end of the buffer
/// </summary>
@@ -92,6 +93,7 @@ namespace VNLib.Utils.IO
val.CopyTo(sBuf.Remaining);
sBuf.Advance(val.Length);
}
+
/// <summary>
/// Formats and appends a value type to the accumulator with proper endianess
/// </summary>
@@ -165,7 +167,7 @@ namespace VNLib.Utils.IO
/// <param name="sBuf"></param>
/// <param name="buffer">The output buffer to write data to</param>
/// <returns>The number of elements written to the buffer</returns>
- public static ERRNO Read<T>(this ISlindingWindowBuffer<T> sBuf, in Span<T> buffer)
+ public static ERRNO Read<T>(this ISlindingWindowBuffer<T> sBuf, Span<T> buffer)
{
//Calculate the amount of data to copy
int dataToCopy = Math.Min(buffer.Length, sBuf.AccumulatedSize);
@@ -194,6 +196,7 @@ namespace VNLib.Utils.IO
//Update the end of the buffer window to the end of the read data
accumulator.Advance(read);
}
+
/// <summary>
/// Fills the remaining window space of the current accumulator with
/// data from the specified stream.
diff --git a/lib/Utils/src/IO/VnStreamReader.cs b/lib/Utils/src/IO/VnStreamReader.cs
index 70b9734..a03a1de 100644
--- a/lib/Utils/src/IO/VnStreamReader.cs
+++ b/lib/Utils/src/IO/VnStreamReader.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -33,6 +33,7 @@ using VNLib.Utils.Extensions;
namespace VNLib.Utils.IO
{
+
/// <summary>
/// Binary based buffered text reader, optimized for reading network streams
/// </summary>
@@ -41,8 +42,10 @@ namespace VNLib.Utils.IO
private bool disposedValue;
private readonly ISlindingWindowBuffer<byte> _buffer;
+
///<inheritdoc/>
public virtual Stream BaseStream { get; }
+
///<inheritdoc/>
public Encoding Encoding { get; }
@@ -50,33 +53,56 @@ namespace VNLib.Utils.IO
/// Number of available bytes of buffered data within the current buffer window
/// </summary>
public int Available => _buffer.AccumulatedSize;
+
/// <summary>
/// Gets or sets the line termination used to deliminate a line of data
/// </summary>
public ReadOnlyMemory<byte> LineTermination { get; set; }
- Span<byte> IVnTextReader.BufferedDataWindow => _buffer.Accumulated;
+
+ ///<inheritdoc/>
+ public Span<byte> BufferedDataWindow => _buffer.Accumulated;
/// <summary>
- /// Creates a new <see cref="TextReader"/> that reads encoded data from the base.
- /// Internal buffers will be alloced from <see cref="ArrayPool{T}.Shared"/>
+ /// Creates a new <see cref="TextReader"/> that reads encoded data from the base stream
+ /// and allocates a new buffer of the specified size from the shared <see cref="ArrayPool{T}"/>
/// </summary>
/// <param name="baseStream">The underlying stream to read data from</param>
- /// <param name="enc">The <see cref="Encoding"/> to use when reading from the stream</param>
+ /// <param name="encoding">The <see cref="Encoding"/> to use when reading from the stream</param>
/// <param name="bufferSize">The size of the internal binary buffer</param>
- public VnStreamReader(Stream baseStream, Encoding enc, int bufferSize)
+ /// <exception cref="ArgumentNullException"></exception>
+ public VnStreamReader(Stream baseStream, Encoding encoding, int bufferSize)
+ : this(baseStream, encoding, bufferSize, ArrayPoolStreamBuffer<byte>.Shared)
{
- BaseStream = baseStream;
- Encoding = enc;
- //Init a new buffer
- _buffer = InitializeBuffer(bufferSize);
}
/// <summary>
- /// Invoked by the constuctor method to allocte the internal buffer with the specified buffer size.
+ /// Creates a new <see cref="TextReader"/> that reads encoded data from the base stream
+ /// and allocates a new buffer of the specified size from the supplied buffer factory.
/// </summary>
- /// <param name="bufferSize">The requested size of the buffer to alloc</param>
- /// <remarks>By default requests the buffer from the <see cref="ArrayPool{T}.Shared"/> instance</remarks>
- protected virtual ISlindingWindowBuffer<byte> InitializeBuffer(int bufferSize) => new ArrayPoolStreamBuffer<byte>(ArrayPool<byte>.Shared, bufferSize);
+ /// <param name="baseStream">The underlying stream to read data from</param>
+ /// <param name="encoding">The <see cref="Encoding"/> to use when reading from the stream</param>
+ /// <param name="bufferSize">The size of the internal binary buffer</param>
+ /// <param name="bufferFactory">The buffer factory to create the buffer from</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ public VnStreamReader(Stream baseStream, Encoding encoding, int bufferSize, IStreamBufferFactory<byte> bufferFactory)
+ :this(baseStream, encoding, bufferFactory?.CreateBuffer(bufferSize)!)
+ {
+ }
+
+ /// <summary>
+ /// Creates a new <see cref="TextReader"/> that reads encoded data from the base stream
+ /// and uses the specified buffer.
+ /// </summary>
+ /// <param name="baseStream">The underlying stream to read data from</param>
+ /// <param name="encoding">The <see cref="Encoding"/> to use when reading from the stream</param>
+ /// <param name="buffer">The internal <see cref="ISlindingWindowBuffer{T}"/> to use</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ public VnStreamReader(Stream baseStream, Encoding encoding, ISlindingWindowBuffer<byte> buffer)
+ {
+ BaseStream = baseStream ?? throw new ArgumentNullException(nameof(buffer));
+ Encoding = encoding ?? throw new ArgumentNullException(nameof(encoding));
+ _buffer = buffer ?? throw new ArgumentNullException(nameof(buffer));
+ }
///<inheritdoc/>
public override async Task<string?> ReadLineAsync()
@@ -86,42 +112,53 @@ namespace VNLib.Utils.IO
{
//Get current buffer window
Memory<byte> buffered = _buffer.AccumulatedBuffer;
+
//search for line termination in current buffer
int term = buffered.IndexOf(LineTermination);
+
//Termination found in buffer window
if (term > -1)
{
//Capture the line from the begining of the window to the termination
Memory<byte> line = buffered[..term];
+
//Shift the window to the end of the line (excluding the termination)
_buffer.AdvanceStart(term + LineTermination.Length);
+
//Decode the line to a string
return Encoding.GetString(line.Span);
}
//Termination not found
}
+
//Compact the buffer window and see if space is avialble to buffer more data
if (_buffer.CompactBufferWindow())
{
//There is room, so buffer more data
await _buffer.AccumulateDataAsync(BaseStream, CancellationToken.None);
+
//Check again to see if more data is buffered
if (Available <= 0)
{
//No string found
return null;
}
+
//Get current buffer window
Memory<byte> buffered = _buffer.AccumulatedBuffer;
+
//search for line termination in current buffer
int term = buffered.IndexOf(LineTermination);
+
//Termination found in buffer window
if (term > -1)
{
//Capture the line from the begining of the window to the termination
Memory<byte> line = buffered[..term];
+
//Shift the window to the end of the line (excluding the termination)
_buffer.AdvanceStart(term + LineTermination.Length);
+
//Decode the line to a string
return Encoding.GetString(line.Span);
}
@@ -136,6 +173,7 @@ namespace VNLib.Utils.IO
///<inheritdoc/>
public override int Read(char[] buffer, int index, int count) => Read(buffer.AsSpan(index, count));
+
///<inheritdoc/>
public override int Read(Span<char> buffer)
{
@@ -143,17 +181,23 @@ namespace VNLib.Utils.IO
{
return 0;
}
+
//Get current buffer window
Span<byte> buffered = _buffer.Accumulated;
+
//Convert all avialable data
int encoded = Encoding.GetChars(buffered, buffer);
+
//Shift buffer window to the end of the converted data
_buffer.AdvanceStart(encoded);
+
//return the number of chars written
return Encoding.GetCharCount(buffered);
}
+
///<inheritdoc/>
public override void Close() => _buffer.Close();
+
///<inheritdoc/>
protected override void Dispose(bool disposing)
{
@@ -173,8 +217,14 @@ namespace VNLib.Utils.IO
_buffer.Reset();
}
- void IVnTextReader.Advance(int count) => _buffer.AdvanceStart(count);
- void IVnTextReader.FillBuffer() => _buffer.AccumulateData(BaseStream);
- ERRNO IVnTextReader.CompactBufferWindow() => _buffer.CompactBufferWindow();
+
+ ///<inheritdoc/>
+ public void Advance(int count) => _buffer.AdvanceStart(count);
+
+ ///<inheritdoc/>
+ public void FillBuffer() => _buffer.AccumulateData(BaseStream);
+
+ ///<inheritdoc/>
+ public ERRNO CompactBufferWindow() => _buffer.CompactBufferWindow();
}
} \ No newline at end of file
diff --git a/lib/Utils/src/IO/VnStreamWriter.cs b/lib/Utils/src/IO/VnStreamWriter.cs
index f875932..03b0a6e 100644
--- a/lib/Utils/src/IO/VnStreamWriter.cs
+++ b/lib/Utils/src/IO/VnStreamWriter.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -51,6 +51,7 @@ namespace VNLib.Utils.IO
/// Gets the underlying stream that interfaces with the backing store
/// </summary>
public virtual Stream BaseStream { get; }
+
///<inheritdoc/>
public override Encoding Encoding { get; }
@@ -58,36 +59,60 @@ namespace VNLib.Utils.IO
/// Line termination to use when writing lines to the output
/// </summary>
public ReadOnlyMemory<byte> LineTermination { get; set; }
+
///<inheritdoc/>
public override string NewLine
{
get => Encoding.GetString(LineTermination.Span);
set => LineTermination = Encoding.GetBytes(value);
}
-
+
+
+ /// <summary>
+ /// Creates a new <see cref="VnStreamWriter"/> that writes encoded data to the base stream
+ /// and allocates a new buffer of the specified size from the shared <see cref="ArrayPool{T}"/>
+ /// </summary>
+ /// <param name="baseStream">The underlying stream to write data to</param>
+ /// <param name="encoding">The <see cref="Encoding"/> to use when writing to the stream</param>
+ /// <param name="bufferSize">The size of the internal binary buffer</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ public VnStreamWriter(Stream baseStream, Encoding encoding, int bufferSize)
+ : this(baseStream, encoding, bufferSize, ArrayPoolStreamBuffer<byte>.Shared)
+ {
+ }
+
/// <summary>
- /// Creates a new <see cref="VnStreamWriter"/> that writes formatted data
- /// to the specified base stream
+ /// Creates a new <see cref="VnStreamWriter"/> that writes encoded data to the base stream
+ /// and allocates a new buffer of the specified size from the supplied buffer factory.
/// </summary>
- /// <param name="baseStream">The stream to write data to</param>
- /// <param name="encoding">The <see cref="Encoding"/> to use when writing data</param>
- /// <param name="bufferSize">The size of the internal buffer used to buffer binary data before writing to the base stream</param>
- public VnStreamWriter(Stream baseStream, Encoding encoding, int bufferSize = 1024)
+ /// <param name="baseStream">The underlying stream to write data to</param>
+ /// <param name="encoding">The <see cref="Encoding"/> to use when writing to the stream</param>
+ /// <param name="bufferSize">The size of the internal binary buffer</param>
+ /// <param name="bufferFactory">The buffer factory to create the buffer from</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ public VnStreamWriter(Stream baseStream, Encoding encoding, int bufferSize, IStreamBufferFactory<byte> bufferFactory)
+ : this(baseStream, encoding, bufferFactory?.CreateBuffer(bufferSize)!)
{
- //Store base stream
- BaseStream = baseStream ?? throw new ArgumentNullException(nameof(baseStream));
+ }
+
+ /// <summary>
+ /// Creates a new <see cref="VnStreamWriter"/> that writes encoded data to the base stream
+ /// and uses the specified buffer.
+ /// </summary>
+ /// <param name="baseStream">The underlying stream to write data to</param>
+ /// <param name="encoding">The <see cref="Encoding"/> to use when writing to the stream</param>
+ /// <param name="buffer">The internal <see cref="ISlindingWindowBuffer{T}"/> to use</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ public VnStreamWriter(Stream baseStream, Encoding encoding, ISlindingWindowBuffer<byte> buffer)
+ {
+ BaseStream = baseStream ?? throw new ArgumentNullException(nameof(buffer));
Encoding = encoding ?? throw new ArgumentNullException(nameof(encoding));
+ _buffer = buffer ?? throw new ArgumentNullException(nameof(buffer));
+
//Get an encoder
Enc = encoding.GetEncoder();
- _buffer = InitializeBuffer(bufferSize);
}
- /// <summary>
- /// Invoked by the constuctor method to allocte the internal buffer with the specified buffer size.
- /// </summary>
- /// <param name="bufferSize">The requested size of the buffer to alloc</param>
- /// <remarks>By default requests the buffer from the <see cref="MemoryPool{T}.Shared"/> instance</remarks>
- protected virtual ISlindingWindowBuffer<byte> InitializeBuffer(int bufferSize) => new ArrayPoolStreamBuffer<byte>(ArrayPool<byte>.Shared, bufferSize);
///<inheritdoc/>
public void Write(byte value)
{
@@ -97,19 +122,24 @@ namespace VNLib.Utils.IO
//There is not enough room to store the single byte
Flush();
}
+
//Store at the end of the window
_buffer.Append(value);
}
+
///<inheritdoc/>
public override void Write(char value)
{
ReadOnlySpan<char> tbuf = MemoryMarshal.CreateSpan(ref value, 0x01);
Write(tbuf);
}
+
///<inheritdoc/>
public override void Write(object? value) => Write(value?.ToString());
+
///<inheritdoc/>
public override void Write(string? value) => Write(value.AsSpan());
+
///<inheritdoc/>
public override void Write(ReadOnlySpan<char> buffer)
{
@@ -123,8 +153,10 @@ namespace VNLib.Utils.IO
{
//Get an available buffer window to store characters in and convert the characters to binary
Enc.Convert(reader.Window, _buffer.Remaining, true, out int charsUsed, out int bytesUsed, out completed);
+
//Update byte position
_buffer.Advance(bytesUsed);
+
//Update char position
reader.Advance(charsUsed);
@@ -136,31 +168,40 @@ namespace VNLib.Utils.IO
}
} while (!completed);
+
//Reset the encoder
Enc.Reset();
}
+
///<inheritdoc/>
public override async Task WriteAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default)
{
Check();
+
+ ForwardOnlyMemoryReader<char> reader = new(buffer);
+
//Create a variable for a character buffer window
bool completed;
- ForwardOnlyMemoryReader<char> reader = new(buffer);
do
{
//Get an available buffer window to store characters in and convert the characters to binary
Enc.Convert(reader.Window.Span, _buffer.Remaining, true, out int charsUsed, out int bytesUsed, out completed);
+
//Update byte position
_buffer.Advance(bytesUsed);
+
//Update char position
reader.Advance(charsUsed);
+
//Converting did not complete because the buffer was too small
if (!completed || reader.WindowSize == 0)
{
//Flush the buffer and continue
await FlushWriterAsync(cancellationToken);
}
+
} while (!completed);
+
//Reset the encoder
Enc.Reset();
}
@@ -169,18 +210,23 @@ namespace VNLib.Utils.IO
public override void WriteLine()
{
Check();
+
//See if there is room in the binary buffer
if (_buffer.RemainingSize < LineTermination.Length)
{
//There is not enough room to store the termination, so we need to flush the buffer
Flush();
}
+
_buffer.Append(LineTermination.Span);
}
+
///<inheritdoc/>
public override void WriteLine(object? value) => WriteLine(value?.ToString());
+
///<inheritdoc/>
public override void WriteLine(string? value) => WriteLine(value.AsSpan());
+
///<inheritdoc/>
public override void WriteLine(ReadOnlySpan<char> buffer)
{
@@ -204,6 +250,7 @@ namespace VNLib.Utils.IO
_buffer.Reset();
}
}
+
/// <summary>
/// Asynchronously flushes the internal buffers to the <see cref="BaseStream"/>, and resets the internal buffer state
/// </summary>
@@ -212,6 +259,7 @@ namespace VNLib.Utils.IO
public async ValueTask FlushWriterAsync(CancellationToken cancellationToken = default)
{
Check();
+
if (_buffer.AccumulatedSize > 0)
{
//Flush current window to the stream
@@ -232,6 +280,7 @@ namespace VNLib.Utils.IO
_buffer.Reset();
Enc.Reset();
}
+
///<inheritdoc/>
public override void Close()
{
@@ -252,6 +301,7 @@ namespace VNLib.Utils.IO
closed = true;
}
}
+
///<inheritdoc/>
protected override void Dispose(bool disposing)
{
@@ -267,6 +317,7 @@ namespace VNLib.Utils.IO
throw new ObjectDisposedException("The stream is closed");
}
}
+
///<inheritdoc/>
public override async ValueTask DisposeAsync()
{
diff --git a/lib/Utils/src/IO/WriteOnlyBufferedStream.cs b/lib/Utils/src/IO/WriteOnlyBufferedStream.cs
index 5e7faa1..e6e138e 100644
--- a/lib/Utils/src/IO/WriteOnlyBufferedStream.cs
+++ b/lib/Utils/src/IO/WriteOnlyBufferedStream.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -24,7 +24,6 @@
using System;
using System.IO;
-using System.Buffers;
using System.Threading;
using System.Threading.Tasks;
@@ -46,28 +45,45 @@ namespace VNLib.Utils.IO
public Stream BaseStream { get; init; }
/// <summary>
- /// Initalizes a new <see cref="WriteOnlyBufferedStream"/> using the
- /// specified backing stream, using the specified buffer size, and
- /// optionally leaves the stream open
+ /// Initalizes a new <see cref="WriteOnlyBufferedStream"/> using the specified backing
+ /// stream, allocating a pooled buffer of the specified size, and optionally leaves the stream open.
/// </summary>
/// <param name="baseStream">The backing stream to write buffered data to</param>
/// <param name="bufferSize">The size of the internal buffer</param>
/// <param name="leaveOpen">A value indicating of the stream should be left open when the buffered stream is closed</param>
+ /// <exception cref="ArgumentNullException"></exception>
public WriteOnlyBufferedStream(Stream baseStream, int bufferSize, bool leaveOpen = false)
+ : this(baseStream, bufferSize, ArrayPoolStreamBuffer<byte>.Shared, leaveOpen)
+ {
+ }
+
+ /// <summary>
+ /// Creates a new <see cref="WriteOnlyBufferedStream"/> that writes encoded data to the base stream
+ /// and allocates a new buffer of the specified size from the supplied buffer factory.
+ /// </summary>
+ /// <param name="baseStream">The underlying stream to write data to</param>
+ /// <param name="bufferSize">The size of the internal binary buffer</param>
+ /// <param name="bufferFactory">The buffer factory to create the buffer from</param>
+ /// <param name="leaveOpen">A value indicating of the stream should be left open when the buffered stream is closed</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ public WriteOnlyBufferedStream(Stream baseStream, int bufferSize, IStreamBufferFactory<byte> bufferFactory, bool leaveOpen = false)
+ : this(baseStream, bufferFactory?.CreateBuffer(bufferSize)!, leaveOpen)
{
- BaseStream = baseStream;
- //Create buffer
- _buffer = InitializeBuffer(bufferSize);
- LeaveOpen = leaveOpen;
}
+
/// <summary>
- /// Invoked by the constuctor method to allocte the internal buffer with the specified buffer size.
+ /// Creates a new <see cref="WriteOnlyBufferedStream"/> that writes encoded data to the base stream
+ /// and uses the specified buffer.
/// </summary>
- /// <param name="bufferSize">The requested size of the buffer to alloc</param>
- /// <remarks>By default requests the buffer from the <see cref="ArrayPool{T}.Shared"/> instance</remarks>
- protected virtual ISlindingWindowBuffer<byte> InitializeBuffer(int bufferSize)
+ /// <param name="baseStream">The underlying stream to write data to</param>
+ /// <param name="buffer">The internal <see cref="ISlindingWindowBuffer{T}"/> to use</param>
+ /// <param name="leaveOpen">A value indicating of the stream should be left open when the buffered stream is closed</param>
+ /// <exception cref="ArgumentNullException"></exception>
+ public WriteOnlyBufferedStream(Stream baseStream, ISlindingWindowBuffer<byte> buffer, bool leaveOpen = false)
{
- return new ArrayPoolStreamBuffer<byte>(ArrayPool<byte>.Shared, bufferSize);
+ BaseStream = baseStream ?? throw new ArgumentNullException(nameof(buffer));
+ _buffer = buffer ?? throw new ArgumentNullException(nameof(buffer));
+ LeaveOpen = leaveOpen;
}
///<inheritdoc/>
@@ -89,6 +105,7 @@ namespace VNLib.Utils.IO
_buffer.Close();
}
}
+
///<inheritdoc/>
public override async ValueTask DisposeAsync()
{
@@ -115,6 +132,7 @@ namespace VNLib.Utils.IO
///<inheritdoc/>
public override void Flush() => WriteBuffer();
+
///<inheritdoc/>
public override Task FlushAsync(CancellationToken cancellationToken) => WriteBufferAsync(cancellationToken).AsTask();
@@ -138,6 +156,7 @@ namespace VNLib.Utils.IO
_buffer.Reset();
}
}
+
///<inheritdoc/>
public override void Write(byte[] buffer, int offset, int count) => Write(buffer.AsSpan(offset, count));
@@ -182,6 +201,7 @@ namespace VNLib.Utils.IO
{
//Buffer is full and needs to be flushed
await WriteBufferAsync(cancellationToken);
+
//Advance reader and continue to buffer
reader.Advance(buffered);
continue;
@@ -197,23 +217,28 @@ namespace VNLib.Utils.IO
/// Always false
/// </summary>
public override bool CanRead => false;
+
/// <summary>
/// Always returns false
/// </summary>
public override bool CanSeek => false;
+
/// <summary>
/// Always true
/// </summary>
public override bool CanWrite => true;
+
/// <summary>
/// Returns the size of the underlying buffer
/// </summary>
public override long Length => _buffer.AccumulatedSize;
+
/// <summary>
/// Always throws <see cref="NotSupportedException"/>
/// </summary>
/// <exception cref="NotSupportedException"></exception>
public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
+
/// <summary>
/// Always throws <see cref="NotSupportedException"/>
/// </summary>
@@ -242,11 +267,19 @@ namespace VNLib.Utils.IO
throw new NotSupportedException();
}
+ /// <summary>
+ /// Always throws <see cref="NotSupportedException"/>
+ /// </summary>
+ /// <exception cref="NotSupportedException"></exception>
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
+ /// <summary>
+ /// Always throws <see cref="NotSupportedException"/>
+ /// </summary>
+ /// <exception cref="NotSupportedException"></exception>
public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
diff --git a/lib/Utils/src/Memory/ForwardOnlyMemoryReader.cs b/lib/Utils/src/Memory/ForwardOnlyMemoryReader.cs
index 39c9594..53d3d77 100644
--- a/lib/Utils/src/Memory/ForwardOnlyMemoryReader.cs
+++ b/lib/Utils/src/Memory/ForwardOnlyMemoryReader.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -31,7 +31,7 @@ namespace VNLib.Utils.Memory
/// reader for a memory segment
/// </summary>
/// <typeparam name="T">The element type</typeparam>
- public struct ForwardOnlyMemoryReader<T>
+ public record struct ForwardOnlyMemoryReader<T>
{
private readonly ReadOnlyMemory<T> _segment;
private readonly int _size;
@@ -43,7 +43,7 @@ namespace VNLib.Utils.Memory
/// of the specified type using the specified internal buffer
/// </summary>
/// <param name="buffer">The buffer to read from</param>
- public ForwardOnlyMemoryReader(in ReadOnlyMemory<T> buffer)
+ public ForwardOnlyMemoryReader(ReadOnlyMemory<T> buffer)
{
_segment = buffer;
_size = buffer.Length;
@@ -54,6 +54,7 @@ namespace VNLib.Utils.Memory
/// The remaining data window
/// </summary>
public readonly ReadOnlyMemory<T> Window => _segment[_position..];
+
/// <summary>
/// The number of elements remaining in the window
/// </summary>
diff --git a/lib/Utils/src/Memory/ForwardOnlyMemoryWriter.cs b/lib/Utils/src/Memory/ForwardOnlyMemoryWriter.cs
index 4f5286d..e0fbe41 100644
--- a/lib/Utils/src/Memory/ForwardOnlyMemoryWriter.cs
+++ b/lib/Utils/src/Memory/ForwardOnlyMemoryWriter.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -29,16 +29,18 @@ namespace VNLib.Utils.Memory
/// <summary>
/// Provides a mutable sliding buffer writer
/// </summary>
- public struct ForwardOnlyMemoryWriter<T>
+ public record struct ForwardOnlyMemoryWriter<T>
{
/// <summary>
/// The buffer for writing output data to
/// </summary>
public readonly Memory<T> Buffer { get; }
+
/// <summary>
/// The number of characters written to the buffer
/// </summary>
public int Written { readonly get; set; }
+
/// <summary>
/// The number of characters remaining in the buffer
/// </summary>
@@ -53,7 +55,7 @@ namespace VNLib.Utils.Memory
/// Creates a new <see cref="ForwardOnlyWriter{T}"/> assigning the specified buffer
/// </summary>
/// <param name="buffer">The buffer to write data to</param>
- public ForwardOnlyMemoryWriter(in Memory<T> buffer)
+ public ForwardOnlyMemoryWriter(Memory<T> buffer)
{
Buffer = buffer;
Written = 0;
@@ -83,6 +85,7 @@ namespace VNLib.Utils.Memory
//update char position
Written += data.Length;
}
+
/// <summary>
/// Appends a single item to the buffer
/// </summary>
diff --git a/lib/Utils/src/Memory/ForwardOnlyReader.cs b/lib/Utils/src/Memory/ForwardOnlyReader.cs
index 9829df3..c109e4b 100644
--- a/lib/Utils/src/Memory/ForwardOnlyReader.cs
+++ b/lib/Utils/src/Memory/ForwardOnlyReader.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -43,7 +43,7 @@ namespace VNLib.Utils.Memory
/// of the specified type using the specified internal buffer
/// </summary>
/// <param name="buffer">The buffer to read from</param>
- public ForwardOnlyReader(in ReadOnlySpan<T> buffer)
+ public ForwardOnlyReader(ReadOnlySpan<T> buffer)
{
_segment = buffer;
_size = buffer.Length;
@@ -57,7 +57,7 @@ namespace VNLib.Utils.Memory
/// </summary>
/// <param name="buffer">The buffer to read from</param>
/// <param name="offset">The offset within the supplied buffer to begin the reader at</param>
- public ForwardOnlyReader(in ReadOnlySpan<T> buffer, int offset)
+ public ForwardOnlyReader(ReadOnlySpan<T> buffer, int offset)
{
_segment = buffer[offset..];
_size = _segment.Length;
diff --git a/lib/Utils/src/Memory/ForwardOnlyWriter.cs b/lib/Utils/src/Memory/ForwardOnlyWriter.cs
index efd7f2b..aa14a5f 100644
--- a/lib/Utils/src/Memory/ForwardOnlyWriter.cs
+++ b/lib/Utils/src/Memory/ForwardOnlyWriter.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -35,10 +35,12 @@ namespace VNLib.Utils.Memory
/// The buffer for writing output data to
/// </summary>
public readonly Span<T> Buffer { get; }
+
/// <summary>
/// The number of characters written to the buffer
/// </summary>
public int Written { readonly get; set; }
+
/// <summary>
/// The number of characters remaining in the buffer
/// </summary>
@@ -53,7 +55,7 @@ namespace VNLib.Utils.Memory
/// Creates a new <see cref="ForwardOnlyWriter{T}"/> assigning the specified buffer
/// </summary>
/// <param name="buffer">The buffer to write data to</param>
- public ForwardOnlyWriter(in Span<T> buffer)
+ public ForwardOnlyWriter(Span<T> buffer)
{
Buffer = buffer;
Written = 0;
@@ -65,7 +67,7 @@ namespace VNLib.Utils.Memory
/// </summary>
/// <param name="buffer">The buffer to write data to</param>
/// <param name="offset">The offset to begin the writer at</param>
- public ForwardOnlyWriter(in Span<T> buffer, int offset)
+ public ForwardOnlyWriter(Span<T> buffer, int offset)
{
Buffer = buffer[offset..];
Written = 0;
@@ -95,6 +97,7 @@ namespace VNLib.Utils.Memory
//update char position
Written += data.Length;
}
+
/// <summary>
/// Appends a single item to the buffer
/// </summary>
diff --git a/lib/Utils/src/Memory/IStringSerializeable.cs b/lib/Utils/src/Memory/IStringSerializeable.cs
index 12cfe52..13b0fd6 100644
--- a/lib/Utils/src/Memory/IStringSerializeable.cs
+++ b/lib/Utils/src/Memory/IStringSerializeable.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -37,6 +37,7 @@ namespace VNLib.Utils.Memory
/// </summary>
/// <returns>A string of the desired representation of the current instance</returns>
string Compile();
+
/// <summary>
/// Compiles the current instance into its safe string representation, and writes its
/// contents to the specified buffer writer
@@ -44,12 +45,13 @@ namespace VNLib.Utils.Memory
/// <param name="writer">The ouput writer to write the serialized representation to</param>
/// <exception cref="OutOfMemoryException"></exception>
void Compile(ref ForwardOnlyWriter<char> writer);
+
/// <summary>
/// Compiles the current instance into its safe string representation, and writes its
/// contents to the specified buffer writer
/// </summary>
/// <param name="buffer">The buffer to write the serialized representation to</param>
/// <returns>The number of characters written to the buffer</returns>
- ERRNO Compile(in Span<char> buffer);
+ ERRNO Compile(Span<char> buffer);
}
}
diff --git a/lib/Utils/src/Memory/MemoryUtil.cs b/lib/Utils/src/Memory/MemoryUtil.cs
index 26adf85..7369fc0 100644
--- a/lib/Utils/src/Memory/MemoryUtil.cs
+++ b/lib/Utils/src/Memory/MemoryUtil.cs
@@ -506,34 +506,37 @@ namespace VNLib.Utils.Memory
//Check dest bounts
CheckBounds(dest, destOffset, count);
+ //Check if 64bit
+ if(sizeof(nuint) == 8)
+ {
+ //Get the number of bytes to copy
+ nuint byteCount = ByteCount<T>(count);
-#if TARGET_64BIT
- //Get the number of bytes to copy
- nuint byteCount = ByteCount<T>(count);
+ //Get memory handle from source
+ using MemoryHandle srcHandle = source.Pin(0);
- //Get memory handle from source
- using MemoryHandle srcHandle = source.Pin(0);
+ //get source offset
+ T* src = (T*)srcHandle.Pointer + offset;
- //get source offset
- T* src = (T*)srcHandle.Pointer + offset;
+ //pin array
+ fixed (T* dst = dest)
+ {
+ //Offset dest ptr
+ T* dstOffset = dst + destOffset;
- //pin array
- fixed (T* dst = dest)
+ //Copy src to set
+ Buffer.MemoryCopy(src, dstOffset, byteCount, byteCount);
+ }
+ }
+ else
{
- //Offset dest ptr
- T* dstOffset = dst + destOffset;
+ //If 32bit its safe to use spans
- //Copy src to set
- Buffer.MemoryCopy(src, dstOffset, byteCount, byteCount);
+ Span<T> src = source.AsSpan((int)offset, (int)count);
+ Span<T> dst = dest.AsSpan((int)destOffset, (int)count);
+ //Copy
+ src.CopyTo(dst);
}
-#else
- //If 32bit its safe to use spans
-
- Span<T> src = source.Span.Slice((int)offset, (int)count);
- Span<T> dst = dest.AsSpan((int)destOffset, (int)count);
- //Copy
- src.CopyTo(dst);
-#endif
}
#endregion
@@ -645,7 +648,7 @@ namespace VNLib.Utils.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CheckBounds<T>(T[] block, nuint offset, nuint count)
{
- if (((nuint)block.LongLength - offset) <= count)
+ if (offset + count > (ulong)block.LongLength)
{
throw new ArgumentOutOfRangeException("The offset or count is outside of the range of the block of memory");
}