mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-09 23:45:42 +00:00
Merge branch 'develop' into main
This commit is contained in:
commit
1fe2a26b7f
@ -11,6 +11,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- X10D: Added extension methods for `DateOnly`, for parity with `DateTime` and `DateTimeOffset`.
|
- X10D: Added extension methods for `DateOnly`, for parity with `DateTime` and `DateTimeOffset`.
|
||||||
- X10D: Added math-related extension methods for `BigInteger`.
|
- X10D: Added math-related extension methods for `BigInteger`.
|
||||||
- X10D: Added `Span<T>.Replace(T, T)`.
|
- X10D: Added `Span<T>.Replace(T, T)`.
|
||||||
|
- X10D: Added `CountDigits` for integer types.
|
||||||
|
- X10D: Added `TextWriter.WriteNoAlloc(int[, ReadOnlySpan<char>[, IFormatProvider]])`.
|
||||||
|
- X10D: Added `TextWriter.WriteNoAlloc(uint[, ReadOnlySpan<char>[, IFormatProvider]])`.
|
||||||
|
- X10D: Added `TextWriter.WriteNoAlloc(long[, ReadOnlySpan<char>[, IFormatProvider]])`.
|
||||||
|
- X10D: Added `TextWriter.WriteNoAlloc(ulong[, ReadOnlySpan<char>[, IFormatProvider]])`.
|
||||||
|
- X10D: Added `TextWriter.WriteLineNoAlloc(int[, ReadOnlySpan<char>[, IFormatProvider]])`.
|
||||||
|
- X10D: Added `TextWriter.WriteLineNoAlloc(uint[, ReadOnlySpan<char>[, IFormatProvider]])`.
|
||||||
|
- X10D: Added `TextWriter.WriteLineNoAlloc(long[, ReadOnlySpan<char>[, IFormatProvider]])`.
|
||||||
|
- X10D: Added `TextWriter.WriteLineNoAlloc(ulong[, ReadOnlySpan<char>[, IFormatProvider]])`.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- X10D: `DateTime.Age(DateTime)` and `DateTimeOffset.Age(DateTimeOffset)` parameter renamed from `asOf` to `referenceDate`.
|
- X10D: `DateTime.Age(DateTime)` and `DateTimeOffset.Age(DateTimeOffset)` parameter renamed from `asOf` to `referenceDate`.
|
||||||
|
131
X10D.Tests/src/IO/TextWriterTests.Int32.cs
Normal file
131
X10D.Tests/src/IO/TextWriterTests.Int32.cs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using X10D.IO;
|
||||||
|
|
||||||
|
namespace X10D.Tests.IO;
|
||||||
|
|
||||||
|
public partial class TextWriterTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldThrowArgumentNullException_GivenInt32_AndNullWriter()
|
||||||
|
{
|
||||||
|
TextWriter writer = null!;
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteNoAlloc(420));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteNoAlloc(420, "N0"));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteNoAlloc(420, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldThrowObjectDisposedException_GivenInt32_AndDisposedStream()
|
||||||
|
{
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
var writer = new StreamWriter(stream, Encoding.UTF8);
|
||||||
|
writer.Dispose();
|
||||||
|
stream.Dispose();
|
||||||
|
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteNoAlloc(420));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteNoAlloc(420, "N0"));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteNoAlloc(420, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldThrowArgumentNullException_GivenInt32_AndNullWriter()
|
||||||
|
{
|
||||||
|
TextWriter writer = null!;
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteLineNoAlloc(420));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteLineNoAlloc(420, "N0"));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteLineNoAlloc(420, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldThrowObjectDisposedException_GivenInt32_AndDisposedStream()
|
||||||
|
{
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
var writer = new StreamWriter(stream, Encoding.UTF8);
|
||||||
|
writer.Dispose();
|
||||||
|
stream.Dispose();
|
||||||
|
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteLineNoAlloc(420));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteLineNoAlloc(420, "N0"));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteLineNoAlloc(420, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldWriteTextValue_GivenInt32()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteNoAlloc(420);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
const string expected = "420";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldWriteTextValue_GivenInt32_AndFormatString()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteNoAlloc(420, "N0");
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
const string expected = "420";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldWriteTextValue_GivenInt32_AndFormatString_AndCultureInfo()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteNoAlloc(420, "N0", CultureInfo.CurrentCulture);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
const string expected = "420";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldWriteTextValue_GivenInt32()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteLineNoAlloc(420);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
var expected = $"420{Environment.NewLine}";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldWriteTextValue_GivenInt32_AndFormatString()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteLineNoAlloc(420, "N0");
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
var expected = $"420{Environment.NewLine}";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldWriteTextValue_GivenInt32_AndFormatString_AndCultureInfo()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteLineNoAlloc(420, "N0", CultureInfo.CurrentCulture);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
var expected = $"420{Environment.NewLine}";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
}
|
131
X10D.Tests/src/IO/TextWriterTests.Int64.cs
Normal file
131
X10D.Tests/src/IO/TextWriterTests.Int64.cs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using X10D.IO;
|
||||||
|
|
||||||
|
namespace X10D.Tests.IO;
|
||||||
|
|
||||||
|
public partial class TextWriterTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldThrowArgumentNullException_GivenInt64_AndNullWriter()
|
||||||
|
{
|
||||||
|
TextWriter writer = null!;
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteNoAlloc(420L));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteNoAlloc(420L, "N0"));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteNoAlloc(420L, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldThrowObjectDisposedException_GivenInt64_AndDisposedStream()
|
||||||
|
{
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
var writer = new StreamWriter(stream, Encoding.UTF8);
|
||||||
|
writer.Dispose();
|
||||||
|
stream.Dispose();
|
||||||
|
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteNoAlloc(420L));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteNoAlloc(420L, "N0"));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteNoAlloc(420L, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldThrowArgumentNullException_GivenInt64_AndNullWriter()
|
||||||
|
{
|
||||||
|
TextWriter writer = null!;
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteLineNoAlloc(420L));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteLineNoAlloc(420L, "N0"));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteLineNoAlloc(420L, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldThrowObjectDisposedException_GivenInt64_AndDisposedStream()
|
||||||
|
{
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
var writer = new StreamWriter(stream, Encoding.UTF8);
|
||||||
|
writer.Dispose();
|
||||||
|
stream.Dispose();
|
||||||
|
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteLineNoAlloc(420L));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteLineNoAlloc(420L, "N0"));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteLineNoAlloc(420L, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldWriteTextValue_GivenInt64()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteNoAlloc(420L);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
const string expected = "420";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldWriteTextValue_GivenInt64_AndFormatString()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteNoAlloc(420L, "N0");
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
const string expected = "420";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldWriteTextValue_GivenInt64_AndFormatString_AndCultureInfo()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteNoAlloc(420L, "N0", CultureInfo.CurrentCulture);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
const string expected = "420";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldWriteTextValue_GivenInt64()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteLineNoAlloc(420L);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
var expected = $"420{Environment.NewLine}";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldWriteTextValue_GivenInt64_AndFormatString()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteLineNoAlloc(420L, "N0");
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
var expected = $"420{Environment.NewLine}";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldWriteTextValue_GivenInt64_AndFormatString_AndCultureInfo()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteLineNoAlloc(420L, "N0", CultureInfo.CurrentCulture);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
var expected = $"420{Environment.NewLine}";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
}
|
131
X10D.Tests/src/IO/TextWriterTests.UInt32.cs
Normal file
131
X10D.Tests/src/IO/TextWriterTests.UInt32.cs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using X10D.IO;
|
||||||
|
|
||||||
|
namespace X10D.Tests.IO;
|
||||||
|
|
||||||
|
public partial class TextWriterTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldThrowArgumentNullException_GivenUInt32_AndNullWriter()
|
||||||
|
{
|
||||||
|
TextWriter writer = null!;
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteNoAlloc(420U));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteNoAlloc(420U, "N0"));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteNoAlloc(420U, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldThrowObjectDisposedException_GivenUInt32_AndDisposedStream()
|
||||||
|
{
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
var writer = new StreamWriter(stream, Encoding.UTF8);
|
||||||
|
writer.Dispose();
|
||||||
|
stream.Dispose();
|
||||||
|
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteNoAlloc(420U));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteNoAlloc(420U, "N0"));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteNoAlloc(420U, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldThrowArgumentNullException_GivenUInt32_AndNullWriter()
|
||||||
|
{
|
||||||
|
TextWriter writer = null!;
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteLineNoAlloc(420U));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteLineNoAlloc(420U, "N0"));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteLineNoAlloc(420U, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldThrowObjectDisposedException_GivenUInt32_AndDisposedStream()
|
||||||
|
{
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
var writer = new StreamWriter(stream, Encoding.UTF8);
|
||||||
|
writer.Dispose();
|
||||||
|
stream.Dispose();
|
||||||
|
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteLineNoAlloc(420U));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteLineNoAlloc(420U, "N0"));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteLineNoAlloc(420U, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldWriteTextValue_GivenUInt32()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteNoAlloc(420U);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
const string expected = "420";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldWriteTextValue_GivenUInt32_AndFormatString()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteNoAlloc(420U, "N0");
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
const string expected = "420";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldWriteTextValue_GivenUInt32_AndFormatString_AndCultureInfo()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteNoAlloc(420U, "N0", CultureInfo.CurrentCulture);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
const string expected = "420";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldWriteTextValue_GivenUInt32()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteLineNoAlloc(420U);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
var expected = $"420{Environment.NewLine}";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldWriteTextValue_GivenUInt32_AndFormatString()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteLineNoAlloc(420U, "N0");
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
var expected = $"420{Environment.NewLine}";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldWriteTextValue_GivenUInt32_AndFormatString_AndCultureInfo()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteLineNoAlloc(420U, "N0", CultureInfo.CurrentCulture);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
var expected = $"420{Environment.NewLine}";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
}
|
131
X10D.Tests/src/IO/TextWriterTests.UInt64.cs
Normal file
131
X10D.Tests/src/IO/TextWriterTests.UInt64.cs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using X10D.IO;
|
||||||
|
|
||||||
|
namespace X10D.Tests.IO;
|
||||||
|
|
||||||
|
public partial class TextWriterTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldThrowArgumentNullException_GivenUInt64_AndNullWriter()
|
||||||
|
{
|
||||||
|
TextWriter writer = null!;
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteNoAlloc(420UL));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteNoAlloc(420UL, "N0"));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteNoAlloc(420UL, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldThrowObjectDisposedException_GivenUInt64_AndDisposedStream()
|
||||||
|
{
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
var writer = new StreamWriter(stream, Encoding.UTF8);
|
||||||
|
writer.Dispose();
|
||||||
|
stream.Dispose();
|
||||||
|
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteNoAlloc(420UL));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteNoAlloc(420UL, "N0"));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteNoAlloc(420UL, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldThrowArgumentNullException_GivenUInt64_AndNullWriter()
|
||||||
|
{
|
||||||
|
TextWriter writer = null!;
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteLineNoAlloc(420UL));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteLineNoAlloc(420UL, "N0"));
|
||||||
|
Assert.Throws<ArgumentNullException>(() => writer.WriteLineNoAlloc(420UL, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldThrowObjectDisposedException_GivenUInt64_AndDisposedStream()
|
||||||
|
{
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
var writer = new StreamWriter(stream, Encoding.UTF8);
|
||||||
|
writer.Dispose();
|
||||||
|
stream.Dispose();
|
||||||
|
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteLineNoAlloc(420UL));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteLineNoAlloc(420UL, "N0"));
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => writer.WriteLineNoAlloc(420UL, "N0", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldWriteTextValue_GivenUInt64()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteNoAlloc(420UL);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
const string expected = "420";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldWriteTextValue_GivenUInt64_AndFormatString()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteNoAlloc(420UL, "N0");
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
const string expected = "420";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteNoAlloc_ShouldWriteTextValue_GivenUInt64_AndFormatString_AndCultureInfo()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteNoAlloc(420UL, "N0", CultureInfo.CurrentCulture);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
const string expected = "420";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldWriteTextValue_GivenUInt64()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteLineNoAlloc(420UL);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
var expected = $"420{Environment.NewLine}";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldWriteTextValue_GivenUInt64_AndFormatString()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteLineNoAlloc(420UL, "N0");
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
var expected = $"420{Environment.NewLine}";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WriteLineNoAlloc_ShouldWriteTextValue_GivenUInt64_AndFormatString_AndCultureInfo()
|
||||||
|
{
|
||||||
|
Assert.That(_stream.Length, Is.Zero);
|
||||||
|
_writer.WriteLineNoAlloc(420UL, "N0", CultureInfo.CurrentCulture);
|
||||||
|
_writer.Flush();
|
||||||
|
|
||||||
|
string actual = Encoding.UTF8.GetString(_stream.ToArray());
|
||||||
|
var expected = $"420{Environment.NewLine}";
|
||||||
|
|
||||||
|
Assert.That(actual, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
}
|
57
X10D.Tests/src/IO/TextWriterTests.cs
Normal file
57
X10D.Tests/src/IO/TextWriterTests.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace X10D.Tests.IO;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public partial class TextWriterTests
|
||||||
|
{
|
||||||
|
private MemoryStream _stream = null!;
|
||||||
|
private StreamWriter _writer = null!;
|
||||||
|
|
||||||
|
[OneTimeSetUp]
|
||||||
|
public void OneTimeSetup()
|
||||||
|
{
|
||||||
|
_stream = new MemoryStream();
|
||||||
|
_writer = new StreamWriter(_stream, Encoding.UTF8);
|
||||||
|
|
||||||
|
// When StreamWriter flushes for the first time, an encoding preamble is written to the stream,
|
||||||
|
// which is correctly mirrored by the behaviour of StreamReader.
|
||||||
|
// however, we're not using StreamReader, we read the contents of the stream
|
||||||
|
// using MemoryStream.ToArray(). This was causing one test to fail, as the first test
|
||||||
|
// that runs would cause the preamble to be written and not be accounted for when reading.
|
||||||
|
// Subsequent tests would pass since the preamble would not be written again.
|
||||||
|
// The following 4 lines ensure that the preamble is written by manually flushing the
|
||||||
|
// writer after writing a single space character. We then clear the stream, and allow
|
||||||
|
// unit tests to do their thing. This took me an HOUR AND A HALF to narrow down.
|
||||||
|
// I want to fucking die.
|
||||||
|
_writer.Write(' ');
|
||||||
|
_writer.Flush();
|
||||||
|
_stream.SetLength(0);
|
||||||
|
_stream.Position = 0;
|
||||||
|
|
||||||
|
Trace.Listeners.Add(new ConsoleTraceListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
[OneTimeTearDown]
|
||||||
|
public void OneTimeTearDown()
|
||||||
|
{
|
||||||
|
_writer.Dispose();
|
||||||
|
_stream.Dispose();
|
||||||
|
|
||||||
|
Trace.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_stream.SetLength(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public void TearDown()
|
||||||
|
{
|
||||||
|
_stream.SetLength(0);
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,61 @@ namespace X10D.Tests.Math;
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public partial class BigIntegerTests
|
public partial class BigIntegerTests
|
||||||
{
|
{
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given0()
|
||||||
|
{
|
||||||
|
BigInteger value = 0;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given1()
|
||||||
|
{
|
||||||
|
BigInteger value = 1;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_GivenNegative1()
|
||||||
|
{
|
||||||
|
BigInteger value = -1;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn2_Given10()
|
||||||
|
{
|
||||||
|
BigInteger value = 10;
|
||||||
|
const int expected = 2;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn3_Given199()
|
||||||
|
{
|
||||||
|
BigInteger value = 199;
|
||||||
|
const int expected = 3;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void DigitalRootShouldBeCorrect()
|
public void DigitalRootShouldBeCorrect()
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,50 @@ namespace X10D.Tests.Math;
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public partial class ByteTests
|
public partial class ByteTests
|
||||||
{
|
{
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given0()
|
||||||
|
{
|
||||||
|
const byte value = 0;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given1()
|
||||||
|
{
|
||||||
|
const byte value = 1;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn2_Given10()
|
||||||
|
{
|
||||||
|
const byte value = 10;
|
||||||
|
const int expected = 2;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn3_Given199()
|
||||||
|
{
|
||||||
|
const byte value = 199;
|
||||||
|
const int expected = 3;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void DigitalRootShouldBeCorrect()
|
public void DigitalRootShouldBeCorrect()
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,61 @@ namespace X10D.Tests.Math;
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public partial class Int16Tests
|
public partial class Int16Tests
|
||||||
{
|
{
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given0()
|
||||||
|
{
|
||||||
|
const short value = 0;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given1()
|
||||||
|
{
|
||||||
|
const short value = 1;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_GivenNegative1()
|
||||||
|
{
|
||||||
|
const short value = -1;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn2_Given10()
|
||||||
|
{
|
||||||
|
const short value = 10;
|
||||||
|
const int expected = 2;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn3_Given199()
|
||||||
|
{
|
||||||
|
const short value = 199;
|
||||||
|
const int expected = 3;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void DigitalRootShouldBeCorrect()
|
public void DigitalRootShouldBeCorrect()
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,61 @@ namespace X10D.Tests.Math;
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public partial class Int32Tests
|
public partial class Int32Tests
|
||||||
{
|
{
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given0()
|
||||||
|
{
|
||||||
|
const int value = 0;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given1()
|
||||||
|
{
|
||||||
|
const int value = 1;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_GivenNegative1()
|
||||||
|
{
|
||||||
|
const int value = -1;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn2_Given10()
|
||||||
|
{
|
||||||
|
const int value = 10;
|
||||||
|
const int expected = 2;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn3_Given199()
|
||||||
|
{
|
||||||
|
const int value = 199;
|
||||||
|
const int expected = 3;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void DigitalRootShouldBeCorrect()
|
public void DigitalRootShouldBeCorrect()
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,61 @@ namespace X10D.Tests.Math;
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public partial class Int64Tests
|
public partial class Int64Tests
|
||||||
{
|
{
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given0()
|
||||||
|
{
|
||||||
|
const long value = 0;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given1()
|
||||||
|
{
|
||||||
|
const long value = 1;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_GivenNegative1()
|
||||||
|
{
|
||||||
|
const long value = -1;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn2_Given10()
|
||||||
|
{
|
||||||
|
const long value = 10;
|
||||||
|
const int expected = 2;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn3_Given199()
|
||||||
|
{
|
||||||
|
const long value = 199;
|
||||||
|
const int expected = 3;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void DigitalRootShouldBeCorrect()
|
public void DigitalRootShouldBeCorrect()
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,61 @@ namespace X10D.Tests.Math;
|
|||||||
[CLSCompliant(false)]
|
[CLSCompliant(false)]
|
||||||
public partial class SByteTests
|
public partial class SByteTests
|
||||||
{
|
{
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given0()
|
||||||
|
{
|
||||||
|
const sbyte value = 0;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given1()
|
||||||
|
{
|
||||||
|
const sbyte value = 1;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_GivenNegative1()
|
||||||
|
{
|
||||||
|
const sbyte value = -1;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn2_Given10()
|
||||||
|
{
|
||||||
|
const sbyte value = 10;
|
||||||
|
const int expected = 2;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn3_Given127()
|
||||||
|
{
|
||||||
|
const sbyte value = 127;
|
||||||
|
const int expected = 3;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void DigitalRootShouldBeCorrect()
|
public void DigitalRootShouldBeCorrect()
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,50 @@ namespace X10D.Tests.Math;
|
|||||||
[CLSCompliant(false)]
|
[CLSCompliant(false)]
|
||||||
public partial class UInt16Tests
|
public partial class UInt16Tests
|
||||||
{
|
{
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given0()
|
||||||
|
{
|
||||||
|
const ushort value = 0;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given1()
|
||||||
|
{
|
||||||
|
const ushort value = 1;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn2_Given10()
|
||||||
|
{
|
||||||
|
const ushort value = 10;
|
||||||
|
const int expected = 2;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn3_Given199()
|
||||||
|
{
|
||||||
|
const ushort value = 199;
|
||||||
|
const int expected = 3;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void DigitalRootShouldBeCorrect()
|
public void DigitalRootShouldBeCorrect()
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,49 @@ namespace X10D.Tests.Math;
|
|||||||
[CLSCompliant(false)]
|
[CLSCompliant(false)]
|
||||||
public partial class UInt32Tests
|
public partial class UInt32Tests
|
||||||
{
|
{
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given0()
|
||||||
|
{
|
||||||
|
const uint value = 0;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given1()
|
||||||
|
{
|
||||||
|
const uint value = 1;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn2_Given10()
|
||||||
|
{
|
||||||
|
const uint value = 10;
|
||||||
|
const int expected = 2;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn3_Given199()
|
||||||
|
{
|
||||||
|
const uint value = 199;
|
||||||
|
const int expected = 3;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void DigitalRootShouldBeCorrect()
|
public void DigitalRootShouldBeCorrect()
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,50 @@ namespace X10D.Tests.Math;
|
|||||||
[CLSCompliant(false)]
|
[CLSCompliant(false)]
|
||||||
public partial class UInt64Tests
|
public partial class UInt64Tests
|
||||||
{
|
{
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given0()
|
||||||
|
{
|
||||||
|
const ulong value = 0;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn1_Given1()
|
||||||
|
{
|
||||||
|
const ulong value = 1;
|
||||||
|
const int expected = 1;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn2_Given10()
|
||||||
|
{
|
||||||
|
const ulong value = 10;
|
||||||
|
const int expected = 2;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CountDigits_ShouldReturn3_Given199()
|
||||||
|
{
|
||||||
|
const ulong value = 199;
|
||||||
|
const int expected = 3;
|
||||||
|
|
||||||
|
int result = value.CountDigits();
|
||||||
|
|
||||||
|
Assert.That(result, Is.EqualTo(expected));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void DigitalRootShouldBeCorrect()
|
public void DigitalRootShouldBeCorrect()
|
||||||
{
|
{
|
||||||
|
10
X10D.sln
10
X10D.sln
@ -22,7 +22,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceValidator", "tools\So
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X10D.Unity", "X10D.Unity\X10D.Unity.csproj", "{7EAB3F09-A9FD-4334-B4DB-0394DD0C6568}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X10D.Unity", "X10D.Unity\X10D.Unity.csproj", "{7EAB3F09-A9FD-4334-B4DB-0394DD0C6568}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X10D.SourceGenerator", "X10D.SourceGenerator\X10D.SourceGenerator.csproj", "{077A5D33-AD55-4C55-8A67-972CEBC32C7A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceGenerator", "tools\SourceGenerator\SourceGenerator.csproj", "{077A5D33-AD55-4C55-8A67-972CEBC32C7A}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X10D.DSharpPlus", "X10D.DSharpPlus\X10D.DSharpPlus.csproj", "{675D3B25-7EA0-4FC3-B513-8DF27874F2CF}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X10D.DSharpPlus", "X10D.DSharpPlus\X10D.DSharpPlus.csproj", "{675D3B25-7EA0-4FC3-B513-8DF27874F2CF}"
|
||||||
EndProject
|
EndProject
|
||||||
@ -47,6 +47,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{4B8969E6
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "tools\Benchmarks\Benchmarks.csproj", "{259450A0-9964-403A-91E1-E9111B92C293}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "tools\Benchmarks\Benchmarks.csproj", "{259450A0-9964-403A-91E1-E9111B92C293}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X10D.MetaServices", "tools\X10D.MetaServices\X10D.MetaServices.csproj", "{F57376C4-3591-43AF-BBED-447A1DE2B1FE}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -89,6 +91,10 @@ Global
|
|||||||
{259450A0-9964-403A-91E1-E9111B92C293}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{259450A0-9964-403A-91E1-E9111B92C293}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{259450A0-9964-403A-91E1-E9111B92C293}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{259450A0-9964-403A-91E1-E9111B92C293}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{259450A0-9964-403A-91E1-E9111B92C293}.Release|Any CPU.Build.0 = Release|Any CPU
|
{259450A0-9964-403A-91E1-E9111B92C293}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{F57376C4-3591-43AF-BBED-447A1DE2B1FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F57376C4-3591-43AF-BBED-447A1DE2B1FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F57376C4-3591-43AF-BBED-447A1DE2B1FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F57376C4-3591-43AF-BBED-447A1DE2B1FE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -100,5 +106,7 @@ Global
|
|||||||
{84750149-9068-4780-AFDE-CDA1AC57007D} = {4B8969E6-27D2-4357-964E-9979FF7CC805}
|
{84750149-9068-4780-AFDE-CDA1AC57007D} = {4B8969E6-27D2-4357-964E-9979FF7CC805}
|
||||||
{CCBF047D-1B01-45EC-8D89-B00B4AC482CA} = {4B8969E6-27D2-4357-964E-9979FF7CC805}
|
{CCBF047D-1B01-45EC-8D89-B00B4AC482CA} = {4B8969E6-27D2-4357-964E-9979FF7CC805}
|
||||||
{259450A0-9964-403A-91E1-E9111B92C293} = {4B8969E6-27D2-4357-964E-9979FF7CC805}
|
{259450A0-9964-403A-91E1-E9111B92C293} = {4B8969E6-27D2-4357-964E-9979FF7CC805}
|
||||||
|
{077A5D33-AD55-4C55-8A67-972CEBC32C7A} = {4B8969E6-27D2-4357-964E-9979FF7CC805}
|
||||||
|
{F57376C4-3591-43AF-BBED-447A1DE2B1FE} = {4B8969E6-27D2-4357-964E-9979FF7CC805}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -83,7 +83,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\X10D.SourceGenerator\X10D.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
|
<ProjectReference Include="..\tools\SourceGenerator\SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
|
||||||
|
<ProjectReference Include="..\tools\X10D.MetaServices\X10D.MetaServices.csproj" PrivateAssets="all"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(GITHUB_ACTIONS)' != 'true'">
|
<ItemGroup Condition="'$(GITHUB_ACTIONS)' != 'true'">
|
||||||
|
685
X10D/src/IO/TextWriterExtensions.cs
Normal file
685
X10D/src/IO/TextWriterExtensions.cs
Normal file
@ -0,0 +1,685 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using X10D.Math;
|
||||||
|
|
||||||
|
namespace X10D.IO;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IO-related extension methods for <see cref="TextWriter" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class TextWriterExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 4-byte signed integer to the text stream, without allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 4-byte signed integer to write.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
public static void WriteNoAlloc(this TextWriter writer, int value)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WriteNoAlloc(writer, value, "N0".AsSpan(), CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 4-byte signed integer to the text stream, without allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 4-byte signed integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
public static void WriteNoAlloc(this TextWriter writer, int value, ReadOnlySpan<char> format)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WriteNoAlloc(writer, value, format, CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 4-byte signed integer to the text stream, without allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 4-byte signed integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <param name="formatProvider">An object that supplies culture-specific formatting information.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
public static void WriteNoAlloc(this TextWriter writer, int value, ReadOnlySpan<char> format, IFormatProvider? formatProvider)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int digitCount = value.CountDigits();
|
||||||
|
Span<char> buffer = stackalloc char[System.Math.Max(value < 0 ? digitCount + 1 : digitCount, 1000)];
|
||||||
|
if (value.TryFormat(buffer, out int charsWritten, format, formatProvider))
|
||||||
|
{
|
||||||
|
Span<char> truncated = buffer[..charsWritten];
|
||||||
|
for (var index = 0; index < truncated.Length; index++)
|
||||||
|
{
|
||||||
|
writer.Write(truncated[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.Write(value.ToString(format.ToString(), formatProvider));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 4-byte unsigned integer to the text stream, without allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 4-byte unsigned integer to write.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
[CLSCompliant(false)]
|
||||||
|
public static void WriteNoAlloc(this TextWriter writer, uint value)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WriteNoAlloc(writer, value, "N0".AsSpan(), CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 4-byte unsigned integer to the text stream, without allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 4-byte unsigned integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
[CLSCompliant(false)]
|
||||||
|
public static void WriteNoAlloc(this TextWriter writer, uint value, ReadOnlySpan<char> format)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WriteNoAlloc(writer, value, format, CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 4-byte unsigned integer to the text stream, without allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 4-byte unsigned integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <param name="formatProvider">An object that supplies culture-specific formatting information.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
[CLSCompliant(false)]
|
||||||
|
public static void WriteNoAlloc(this TextWriter writer,
|
||||||
|
uint value,
|
||||||
|
ReadOnlySpan<char> format,
|
||||||
|
IFormatProvider? formatProvider)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int digitCount = value.CountDigits();
|
||||||
|
Span<char> buffer = stackalloc char[System.Math.Max(digitCount, 1000)];
|
||||||
|
if (value.TryFormat(buffer, out int charsWritten, format, formatProvider))
|
||||||
|
{
|
||||||
|
Span<char> truncated = buffer[..charsWritten];
|
||||||
|
for (var index = 0; index < truncated.Length; index++)
|
||||||
|
{
|
||||||
|
writer.Write(truncated[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.Write(value.ToString(format.ToString(), formatProvider));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 8-byte signed integer to the text stream, without allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 8-byte signed integer to write.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
public static void WriteNoAlloc(this TextWriter writer, long value)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WriteNoAlloc(writer, value, "N0".AsSpan(), CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 8-byte signed integer to the text stream, without allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 8-byte signed integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
public static void WriteNoAlloc(this TextWriter writer, long value, ReadOnlySpan<char> format)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WriteNoAlloc(writer, value, format, CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 8-byte signed integer to the text stream, without allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 8-byte signed integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <param name="formatProvider">An object that supplies culture-specific formatting information.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
public static void WriteNoAlloc(this TextWriter writer,
|
||||||
|
long value,
|
||||||
|
ReadOnlySpan<char> format,
|
||||||
|
IFormatProvider? formatProvider)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int digitCount = value.CountDigits();
|
||||||
|
Span<char> buffer = stackalloc char[System.Math.Max(value < 0 ? digitCount + 1 : digitCount, 1000)];
|
||||||
|
if (value.TryFormat(buffer, out int charsWritten, format, formatProvider))
|
||||||
|
{
|
||||||
|
Span<char> truncated = buffer[..charsWritten];
|
||||||
|
for (var index = 0; index < truncated.Length; index++)
|
||||||
|
{
|
||||||
|
writer.Write(truncated[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.Write(value.ToString(format.ToString(), formatProvider));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 8-byte unsigned integer to the text stream, without allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 8-byte unsigned integer to write.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
[CLSCompliant(false)]
|
||||||
|
public static void WriteNoAlloc(this TextWriter writer, ulong value)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WriteNoAlloc(writer, value, "N0".AsSpan(), CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 8-byte signed integer to the text stream, without allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 8-byte unsigned integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
[CLSCompliant(false)]
|
||||||
|
public static void WriteNoAlloc(this TextWriter writer, ulong value, ReadOnlySpan<char> format)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WriteNoAlloc(writer, value, format, CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 8-byte signed integer to the text stream, without allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 8-byte unsigned integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <param name="formatProvider">An object that supplies culture-specific formatting information.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
[CLSCompliant(false)]
|
||||||
|
public static void WriteNoAlloc(this TextWriter writer,
|
||||||
|
ulong value,
|
||||||
|
ReadOnlySpan<char> format,
|
||||||
|
IFormatProvider? formatProvider)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int digitCount = value.CountDigits();
|
||||||
|
Span<char> buffer = stackalloc char[System.Math.Max(digitCount, 1000)];
|
||||||
|
if (value.TryFormat(buffer, out int charsWritten, format, formatProvider))
|
||||||
|
{
|
||||||
|
Span<char> truncated = buffer[..charsWritten];
|
||||||
|
for (var index = 0; index < truncated.Length; index++)
|
||||||
|
{
|
||||||
|
writer.Write(truncated[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.Write(value.ToString(format.ToString(), formatProvider));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 4-byte signed integer to the text stream, followed by a line terminator, without
|
||||||
|
/// allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 4-byte signed integer to write.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
public static void WriteLineNoAlloc(this TextWriter writer, int value)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
writer.WriteLineNoAlloc(value, "N0".AsSpan(), CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 4-byte signed integer to the text stream, followed by a line terminator, without
|
||||||
|
/// allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 4-byte signed integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
public static void WriteLineNoAlloc(this TextWriter writer, int value, ReadOnlySpan<char> format)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
writer.WriteLineNoAlloc(value, format, CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 4-byte signed integer to the text stream, followed by a line terminator, without
|
||||||
|
/// allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 4-byte signed integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <param name="formatProvider">An object that supplies culture-specific formatting information.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
public static void WriteLineNoAlloc(this TextWriter writer, int value, ReadOnlySpan<char> format,
|
||||||
|
IFormatProvider? formatProvider)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
writer.WriteNoAlloc(value, format, formatProvider);
|
||||||
|
writer.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 4-byte unsigned integer to the text stream, followed by a line terminator, without
|
||||||
|
/// allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 4-byte unsigned integer to write.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
[CLSCompliant(false)]
|
||||||
|
public static void WriteLineNoAlloc(this TextWriter writer, uint value)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
writer.WriteLineNoAlloc(value, "N0".AsSpan(), CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 4-byte unsigned integer to the text stream, followed by a line terminator, without
|
||||||
|
/// allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 4-byte unsigned integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
[CLSCompliant(false)]
|
||||||
|
public static void WriteLineNoAlloc(this TextWriter writer, uint value, ReadOnlySpan<char> format)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
writer.WriteLineNoAlloc(value, format, CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 4-byte unsigned integer to the text stream, followed by a line terminator, without
|
||||||
|
/// allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 4-byte unsigned integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <param name="formatProvider">An object that supplies culture-specific formatting information.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
[CLSCompliant(false)]
|
||||||
|
public static void WriteLineNoAlloc(this TextWriter writer,
|
||||||
|
uint value,
|
||||||
|
ReadOnlySpan<char> format,
|
||||||
|
IFormatProvider? formatProvider)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
writer.WriteNoAlloc(value, format, formatProvider);
|
||||||
|
writer.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 8-byte signed integer to the text stream, followed by a line terminator, without
|
||||||
|
/// allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 8-byte signed integer to write.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
public static void WriteLineNoAlloc(this TextWriter writer, long value)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
writer.WriteLineNoAlloc(value, "N0".AsSpan(), CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 8-byte signed integer to the text stream, followed by a line terminator, without
|
||||||
|
/// allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 8-byte signed integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
public static void WriteLineNoAlloc(this TextWriter writer, long value, ReadOnlySpan<char> format)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
writer.WriteLineNoAlloc(value, format, CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 8-byte signed integer to the text stream, followed by a line terminator, without
|
||||||
|
/// allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 8-byte signed integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <param name="formatProvider">An object that supplies culture-specific formatting information.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
public static void WriteLineNoAlloc(this TextWriter writer,
|
||||||
|
long value,
|
||||||
|
ReadOnlySpan<char> format,
|
||||||
|
IFormatProvider? formatProvider)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
writer.WriteNoAlloc(value, format, formatProvider);
|
||||||
|
writer.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 8-byte unsigned integer to the text stream, followed by a line terminator, without
|
||||||
|
/// allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 8-byte unsigned integer to write.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
[CLSCompliant(false)]
|
||||||
|
public static void WriteLineNoAlloc(this TextWriter writer, ulong value)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
writer.WriteLineNoAlloc(value, "N0".AsSpan(), CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 8-byte signed integer to the text stream, followed by a line terminator, without
|
||||||
|
/// allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 8-byte unsigned integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
[CLSCompliant(false)]
|
||||||
|
public static void WriteLineNoAlloc(this TextWriter writer, ulong value, ReadOnlySpan<char> format)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
writer.WriteLineNoAlloc(value, format, CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the text representation of a 8-byte signed integer to the text stream, followed by a line terminator, without
|
||||||
|
/// allocating a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="TextWriter" /> to write to.</param>
|
||||||
|
/// <param name="value">The 8-byte unsigned integer to write.</param>
|
||||||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||||||
|
/// <param name="formatProvider">An object that supplies culture-specific formatting information.</param>
|
||||||
|
/// <remarks>This method may still allocate if the integer is too large to fit in a stack-allocated buffer.</remarks>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="writer" /> is <see langword="null" />.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The <see cref="TextWriter" /> is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||||
|
[CLSCompliant(false)]
|
||||||
|
public static void WriteLineNoAlloc(this TextWriter writer,
|
||||||
|
ulong value,
|
||||||
|
ReadOnlySpan<char> format,
|
||||||
|
IFormatProvider? formatProvider)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(writer);
|
||||||
|
#else
|
||||||
|
if (writer is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(writer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
writer.WriteNoAlloc(value, format, formatProvider);
|
||||||
|
writer.WriteLine();
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,21 @@ namespace X10D.Math;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class BigIntegerExtensions
|
public static class BigIntegerExtensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of digits in the current integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value whose digit count to compute.</param>
|
||||||
|
/// <returns>The number of digits in <paramref name="value" />.</returns>
|
||||||
|
public static int CountDigits(this BigInteger value)
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)(1 + BigInteger.Log10(BigInteger.Abs(value)));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes the digital root of this 8-bit integer.
|
/// Computes the digital root of this 8-bit integer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -9,6 +9,21 @@ namespace X10D.Math;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ByteExtensions
|
public static class ByteExtensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of digits in the current 8-bit unsigned integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value whose digit count to compute.</param>
|
||||||
|
/// <returns>The number of digits in <paramref name="value" />.</returns>
|
||||||
|
public static int CountDigits(this byte value)
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((ulong)value).CountDigits();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes the digital root of this 8-bit integer.
|
/// Computes the digital root of this 8-bit integer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -9,6 +9,21 @@ namespace X10D.Math;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class Int16Extensions
|
public static class Int16Extensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of digits in the current 16-bit signed integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value whose digit count to compute.</param>
|
||||||
|
/// <returns>The number of digits in <paramref name="value" />.</returns>
|
||||||
|
public static int CountDigits(this short value)
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((long)value).CountDigits();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes the digital root of this 16-bit integer.
|
/// Computes the digital root of this 16-bit integer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -9,6 +9,21 @@ namespace X10D.Math;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class Int32Extensions
|
public static class Int32Extensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of digits in the current 32-bit signed integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value whose digit count to compute.</param>
|
||||||
|
/// <returns>The number of digits in <paramref name="value" />.</returns>
|
||||||
|
public static int CountDigits(this int value)
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((long)value).CountDigits();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes the digital root of this 32-bit integer.
|
/// Computes the digital root of this 32-bit integer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -9,6 +9,21 @@ namespace X10D.Math;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class Int64Extensions
|
public static class Int64Extensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of digits in the current 64-bit signed integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value whose digit count to compute.</param>
|
||||||
|
/// <returns>The number of digits in <paramref name="value" />.</returns>
|
||||||
|
public static int CountDigits(this long value)
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1 + (int)System.Math.Floor(System.Math.Log10(System.Math.Abs(value)));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes the digital root of this 64-bit integer.
|
/// Computes the digital root of this 64-bit integer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -10,6 +10,21 @@ namespace X10D.Math;
|
|||||||
[CLSCompliant(false)]
|
[CLSCompliant(false)]
|
||||||
public static class SByteExtensions
|
public static class SByteExtensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of digits in the current 8-bit signed integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value whose digit count to compute.</param>
|
||||||
|
/// <returns>The number of digits in <paramref name="value" />.</returns>
|
||||||
|
public static int CountDigits(this sbyte value)
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((long)value).CountDigits();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes the digital root of this 32-bit integer.
|
/// Computes the digital root of this 32-bit integer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -10,6 +10,21 @@ namespace X10D.Math;
|
|||||||
[CLSCompliant(false)]
|
[CLSCompliant(false)]
|
||||||
public static class UInt16Extensions
|
public static class UInt16Extensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of digits in the current 16-bit signed integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value whose digit count to compute.</param>
|
||||||
|
/// <returns>The number of digits in <paramref name="value" />.</returns>
|
||||||
|
public static int CountDigits(this ushort value)
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((ulong)value).CountDigits();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes the digital root of the current 16-bit unsigned integer.
|
/// Computes the digital root of the current 16-bit unsigned integer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -10,6 +10,21 @@ namespace X10D.Math;
|
|||||||
[CLSCompliant(false)]
|
[CLSCompliant(false)]
|
||||||
public static class UInt32Extensions
|
public static class UInt32Extensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of digits in the current 32-bit unsigned integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value whose digit count to compute.</param>
|
||||||
|
/// <returns>The number of digits in <paramref name="value" />.</returns>
|
||||||
|
public static int CountDigits(this uint value)
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((ulong)value).CountDigits();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes the digital root of the current 32-bit unsigned integer.
|
/// Computes the digital root of the current 32-bit unsigned integer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -10,6 +10,21 @@ namespace X10D.Math;
|
|||||||
[CLSCompliant(false)]
|
[CLSCompliant(false)]
|
||||||
public static class UInt64Extensions
|
public static class UInt64Extensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of digits in the current 64-bit unsigned integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value whose digit count to compute.</param>
|
||||||
|
/// <returns>The number of digits in <paramref name="value" />.</returns>
|
||||||
|
public static int CountDigits(this ulong value)
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1 + (int)System.Math.Floor(System.Math.Log10(System.Math.Abs((double)value)));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes the digital root of the current 64-bit unsigned integer.
|
/// Computes the digital root of the current 64-bit unsigned integer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -3,7 +3,7 @@ using System.Text.RegularExpressions;
|
|||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.Text;
|
using Microsoft.CodeAnalysis.Text;
|
||||||
|
|
||||||
namespace X10D.SourceGenerator;
|
namespace SourceGenerator;
|
||||||
|
|
||||||
[Generator]
|
[Generator]
|
||||||
internal sealed class EmojiRegexGenerator : ISourceGenerator
|
internal sealed class EmojiRegexGenerator : ISourceGenerator
|
||||||
@ -47,8 +47,8 @@ internal sealed class EmojiRegexGenerator : ISourceGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
builder.AppendLine("// This file was auto-generated by X10D.SourceGenerator");
|
builder.AppendLine("// This file was auto-generated by the X10D source generator");
|
||||||
builder.AppendLine("// Do not edit this file manually");
|
builder.AppendLine("// Do not edit this file manually!");
|
||||||
builder.AppendLine();
|
builder.AppendLine();
|
||||||
|
|
||||||
builder.AppendLine("using System.Text.RegularExpressions;");
|
builder.AppendLine("using System.Text.RegularExpressions;");
|
22
tools/SourceGenerator/MethodOverloadGenerator.cs
Normal file
22
tools/SourceGenerator/MethodOverloadGenerator.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
|
namespace SourceGenerator;
|
||||||
|
|
||||||
|
[Generator]
|
||||||
|
internal sealed class MethodOverloadGenerator : ISourceGenerator
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Initialize(GeneratorInitializationContext context)
|
||||||
|
{
|
||||||
|
context.RegisterForSyntaxNotifications(() => new OverloadSyntaxReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
var syntaxReceiver = (OverloadSyntaxReceiver)context.SyntaxReceiver!;
|
||||||
|
IReadOnlyList<MethodDeclarationSyntax> candidateMethods = syntaxReceiver.CandidateMethods;
|
||||||
|
// TODO implement
|
||||||
|
}
|
||||||
|
}
|
41
tools/SourceGenerator/OverloadSyntaxReceiver.cs
Normal file
41
tools/SourceGenerator/OverloadSyntaxReceiver.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using X10D.MetaServices;
|
||||||
|
|
||||||
|
namespace SourceGenerator;
|
||||||
|
|
||||||
|
public class OverloadSyntaxReceiver : ISyntaxReceiver
|
||||||
|
{
|
||||||
|
private readonly List<MethodDeclarationSyntax> _candidateMethods = new();
|
||||||
|
|
||||||
|
public IReadOnlyList<MethodDeclarationSyntax> CandidateMethods
|
||||||
|
{
|
||||||
|
get => _candidateMethods.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
||||||
|
{
|
||||||
|
if (syntaxNode is not MethodDeclarationSyntax methodDeclarationSyntax)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (methodDeclarationSyntax.AttributeLists.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string attributeName = nameof(AutoOverloadAttribute).Replace("Attribute", string.Empty);
|
||||||
|
foreach (AttributeListSyntax attributeListSyntax in methodDeclarationSyntax.AttributeLists)
|
||||||
|
{
|
||||||
|
foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes)
|
||||||
|
{
|
||||||
|
if (attributeSyntax.Name.ToString() == attributeName)
|
||||||
|
{
|
||||||
|
_candidateMethods.Add(methodDeclarationSyntax);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,4 +17,8 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\X10D.MetaServices\X10D.MetaServices.csproj" PrivateAssets="all"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
4
tools/X10D.MetaServices/Assembly.cs
Normal file
4
tools/X10D.MetaServices/Assembly.cs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
[assembly: InternalsVisibleTo("X10D")]
|
||||||
|
[assembly: InternalsVisibleTo("SourceGenerator")]
|
6
tools/X10D.MetaServices/AutoOverloadAttribute.cs
Normal file
6
tools/X10D.MetaServices/AutoOverloadAttribute.cs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
namespace X10D.MetaServices;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
|
||||||
|
internal sealed class AutoOverloadAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
20
tools/X10D.MetaServices/OverloadTypeAttribute.cs
Normal file
20
tools/X10D.MetaServices/OverloadTypeAttribute.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
namespace X10D.MetaServices;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)]
|
||||||
|
internal sealed class OverloadTypeAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="OverloadTypeAttribute"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="types">The types to overload.</param>
|
||||||
|
public OverloadTypeAttribute(params Type[] types)
|
||||||
|
{
|
||||||
|
Types = (Type[])types.Clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an array of types to overload.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>An array of types to overload.</value>
|
||||||
|
public Type[] Types { get; }
|
||||||
|
}
|
10
tools/X10D.MetaServices/X10D.MetaServices.csproj
Normal file
10
tools/X10D.MetaServices/X10D.MetaServices.csproj
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<LangVersion>11.0</LangVersion>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
Loading…
Reference in New Issue
Block a user