diff --git a/src/J2N/IO/Buffer.cs b/src/J2N/IO/Buffer.cs
index 6b8455e8..090a1a2c 100644
--- a/src/J2N/IO/Buffer.cs
+++ b/src/J2N/IO/Buffer.cs
@@ -68,6 +68,8 @@ namespace J2N.IO
///
public abstract class Buffer
{
+ internal const int ByteStackBufferSize = 128;
+
///
/// UnsetMark means the mark has not been set.
///
diff --git a/src/J2N/IO/ByteBuffer.cs b/src/J2N/IO/ByteBuffer.cs
index 117bb943..8fbdb342 100644
--- a/src/J2N/IO/ByteBuffer.cs
+++ b/src/J2N/IO/ByteBuffer.cs
@@ -16,7 +16,9 @@
*/
#endregion
+using J2N.Buffers;
using System;
+using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Text;
@@ -301,6 +303,8 @@ public int ArrayOffset
/// equals to other; a positive value if this is greater
/// than other.
///
+ /// Note to inheritors: This implementation reads bytes one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public virtual int CompareTo(ByteBuffer? other)
{
if (other is null) return 1; // Using 1 if other is null as specified here: https://stackoverflow.com/a/4852537
@@ -354,6 +358,8 @@ public virtual int CompareTo(ByteBuffer? other)
/// true if this byte buffer is equal to ,
/// false otherwise.
///
+ /// Note to inheritors: This implementation reads bytes one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public override bool Equals(object? other)
{
if (other is null || !(other is ByteBuffer otherBuffer))
@@ -416,6 +422,8 @@ public virtual ByteBuffer Get(byte[] destination)
/// greater than destination.Length - offset
///
/// This buffer.
+ /// Note to inheritors: This implementation reads bytes one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
///
/// plus indicates a position not within this instance.
///
@@ -447,9 +455,35 @@ public virtual ByteBuffer Get(byte[] destination, int offset, int length) // J2N
return this;
}
+ ///
+ /// Reads bytes from the current position into the specified span,
+ /// and increases the position by the number of bytes read.
+ ///
+ /// The property is used to determine
+ /// how many bytes to read.
+ ///
+ /// The target span, sliced to the proper position, if necessary.
+ /// This buffer.
+ /// Note to inheritors: This implementation reads bytes one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
+ /// If is greater than
+ /// .
+ public virtual ByteBuffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ {
+ throw new BufferUnderflowException();
+ }
+ for (int i = 0; i < length; i++)
+ {
+ destination[i] = Get();
+ }
+ return this;
+ }
+
///
/// Returns the byte at the specified index and does not change the position.
- ///
///
/// The index, must not be negative and less than limit.
/// The byte at the specified index.
@@ -617,6 +651,8 @@ public virtual ByteBuffer Get(byte[] destination, int offset, int length) // J2N
/// position, limit, capacity and mark don't affect the hash code.
///
/// The hash code calculated from the remaining bytes.
+ /// Note to inheritors: This implementation reads bytes one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public override int GetHashCode()
{
int myPosition = position;
@@ -696,7 +732,7 @@ public ByteBuffer SetOrder(ByteOrder byteOrder)
///
/// The source byte array.
/// This buffer.
- /// If is less than src.Length.
+ /// If is less than source.Length.
/// If no changes may be made to the contents of this buffer.
/// If is null.
public ByteBuffer Put(byte[] source)
@@ -721,6 +757,8 @@ public ByteBuffer Put(byte[] source)
/// greater than source.Length - offset.
///
/// This buffer.
+ /// Note to inheritors: This implementation writes bytes one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
/// If is less than .
///
/// plus indicates a position not within this instance.
@@ -751,6 +789,32 @@ public virtual ByteBuffer Put(byte[] source, int offset, int length) // J2N TODO
return this;
}
+ ///
+ /// Writes bytes in the given span to the current position and increases the
+ /// position by the number of bytes written.
+ ///
+ /// Calling this method has a similar effect as
+ /// Put(source, 0, source.Length).
+ ///
+ /// The source span.
+ /// This buffer.
+ /// Note to inheritors: This implementation writes bytes one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
+ /// If is less than source.Length.
+ /// If no changes may be made to the contents of this buffer.
+ public virtual ByteBuffer Put(ReadOnlySpan source) // J2N specific
+ {
+ int length = source.Length;
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ for (int i = 0; i < length; i++)
+ {
+ Put(source[i]);
+ }
+ return this;
+ }
+
///
/// Writes all the remaining bytes of the byte buffer to this
/// buffer's current position, and increases both buffers' position by the
@@ -773,10 +837,21 @@ public virtual ByteBuffer Put(ByteBuffer source)
if (IsReadOnly)
throw new ReadOnlyBufferException(); // J2N: Harmony has a bug - it shouldn't read the source and change its position unless this buffer is writable
- byte[] contents = new byte[source.Remaining];
- source.Get(contents);
- Put(contents);
- return this;
+ int length = source.Remaining;
+ byte[]? arrayToReturnToPool = null;
+ Span contents = length > ByteStackBufferSize
+ ? (arrayToReturnToPool = ArrayPool.Shared.Rent(length)).AsSpan(0, length)
+ : stackalloc byte[length];
+ try
+ {
+ source.Get(contents);
+ Put(contents);
+ return this;
+ }
+ finally
+ {
+ ArrayPool.Shared.ReturnIfNotNull(arrayToReturnToPool);
+ }
}
///
@@ -989,5 +1064,4 @@ public override string ToString()
return buf.ToString();
}
}
-
}
diff --git a/src/J2N/IO/CharArrayBuffer.cs b/src/J2N/IO/CharArrayBuffer.cs
index 49567f2e..144171ab 100644
--- a/src/J2N/IO/CharArrayBuffer.cs
+++ b/src/J2N/IO/CharArrayBuffer.cs
@@ -88,6 +88,17 @@ public override sealed CharBuffer Get(char[] destination, int offset, int length
return this;
}
+ public override CharBuffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ throw new BufferUnderflowException();
+
+ backingArray.AsSpan(offset + position, length).CopyTo(destination);
+ position += length;
+ return this;
+ }
+
//public override sealed bool IsDirect => false;
public override sealed ByteOrder Order => ByteOrder.NativeOrder;
diff --git a/src/J2N/IO/CharBuffer.cs b/src/J2N/IO/CharBuffer.cs
index 2a685f39..37547b87 100644
--- a/src/J2N/IO/CharBuffer.cs
+++ b/src/J2N/IO/CharBuffer.cs
@@ -16,8 +16,10 @@
*/
#endregion
+using J2N.Buffers;
using J2N.Text;
using System;
+using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Text;
@@ -121,7 +123,7 @@ public static CharBuffer Wrap(string characterSequence)
{
if (characterSequence is null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.characterSequence);
- return new CharSequenceAdapter(characterSequence.AsCharSequence()); // J2N TODO: Create StringAdapter?
+ return new CharReadOnlyMemoryAdapter(characterSequence.AsMemory());
}
///
@@ -159,7 +161,7 @@ public static CharBuffer Wrap(string characterSequence, int startIndex, int leng
if (startIndex > characterSequence.Length - length) // Checks for int overflow
ThrowHelper.ThrowArgumentOutOfRange_IndexLengthString(startIndex, length);
- return new CharSequenceAdapter(characterSequence.AsCharSequence()) // J2N TODO: Create StringAdapter?
+ return new CharReadOnlyMemoryAdapter(characterSequence.AsMemory())
{
position = startIndex,
limit = startIndex + length
@@ -174,12 +176,19 @@ public static CharBuffer Wrap(string characterSequence, int startIndex, int leng
///
/// The which the new buffer will be based on.
/// The created char buffer.
+ /// 's property is known to perform
+ /// poorly and some operations on a raw will suffer as a result. It is generally
+ /// preferable to use to allocate a temporary array and then use the
+ /// method to transfer the chars to the temporary array,
+ /// then use the array to call the overload for better performance.
+ /// Be sure to call to return the array to the pool when you
+ /// are finished with the instance.
/// If is null.
public static CharBuffer Wrap(StringBuilder characterSequence)
{
if (characterSequence is null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.characterSequence);
- return new CharSequenceAdapter(characterSequence.AsCharSequence()); // J2N TODO: Create StringBuilderAdapter?
+ return new StringBuilderAdapter(characterSequence);
}
///
@@ -198,6 +207,13 @@ public static CharBuffer Wrap(StringBuilder characterSequence)
/// The end index, must be no less than and no
/// greater than characterSequence.Length.
/// The created char buffer.
+ /// 's property is known to perform
+ /// poorly and some operations on a raw will suffer as a result. It is generally
+ /// preferable to use to allocate a temporary array and then use the
+ /// method to transfer the chars to the temporary array,
+ /// then use the array to call the overload for better performance.
+ /// Be sure to call to return the array to the pool when you
+ /// are finished with the instance.
///
/// plus indicates a position not within this instance.
///
@@ -217,7 +233,7 @@ public static CharBuffer Wrap(StringBuilder characterSequence, int startIndex, i
if (startIndex > characterSequence.Length - length) // Checks for int overflow
ThrowHelper.ThrowArgumentOutOfRange_IndexLengthString(startIndex, length);
- return new CharSequenceAdapter(characterSequence.AsCharSequence()) // J2N TODO: Create StringAdapter?
+ return new StringBuilderAdapter(characterSequence)
{
position = startIndex,
limit = startIndex + length
@@ -237,8 +253,16 @@ public static CharBuffer Wrap(StringBuilder characterSequence, int startIndex, i
/// If is null.
public static CharBuffer Wrap(ICharSequence characterSequence)
{
- if (characterSequence is null)
+ if (characterSequence is null || !characterSequence.HasValue)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.characterSequence);
+
+ if (characterSequence is StringCharSequence str)
+ return new CharReadOnlyMemoryAdapter(str.Value!.AsMemory());
+ if (characterSequence is CharArrayCharSequence ca)
+ return new ReadOnlyCharArrayBuffer(ca.Length, ca.Value!, arrayOffset: 0);
+ if (characterSequence is StringBuilderCharSequence sb)
+ return new StringBuilderAdapter(sb.Value!);
+
return new CharSequenceAdapter(characterSequence);
}
@@ -268,7 +292,7 @@ public static CharBuffer Wrap(ICharSequence characterSequence)
/// If is null.
public static CharBuffer Wrap(ICharSequence characterSequence, int startIndex, int length)
{
- if (characterSequence is null)
+ if (characterSequence is null || !characterSequence.HasValue)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.characterSequence);
if (startIndex < 0)
ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(startIndex, ExceptionArgument.startIndex);
@@ -277,6 +301,31 @@ public static CharBuffer Wrap(ICharSequence characterSequence, int startIndex, i
if (startIndex > characterSequence.Length - length) // Checks for int overflow
ThrowHelper.ThrowArgumentOutOfRange_IndexLengthString(startIndex, length);
+ if (characterSequence is StringCharSequence str)
+ {
+ return new CharReadOnlyMemoryAdapter(str.Value!.AsMemory())
+ {
+ position = startIndex,
+ limit = startIndex + length
+ };
+ }
+ if (characterSequence is CharArrayCharSequence ca)
+ {
+ return new ReadOnlyCharArrayBuffer(ca.Length, ca.Value!, arrayOffset: 0)
+ {
+ position = startIndex,
+ limit = startIndex + length
+ };
+ }
+ if (characterSequence is StringBuilderCharSequence sb)
+ {
+ return new StringBuilderAdapter(sb.Value!)
+ {
+ position = startIndex,
+ limit = startIndex + length
+ };
+ }
+
return new CharSequenceAdapter(characterSequence)
{
position = startIndex,
@@ -364,6 +413,8 @@ public char this[int index]
/// A negative value if this is less than ; 0 if
/// this equals to ; a positive valie if this is
/// greater than .
+ /// Note to inheritors: This implementation reads chars one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public virtual int CompareTo(CharBuffer? other)
{
if (other is null) return 1; // Using 1 if other is null as specified here: https://stackoverflow.com/a/4852537
@@ -414,6 +465,8 @@ public virtual int CompareTo(CharBuffer? other)
///
/// The object to compare with this char buffer.
/// true if this char buffer is equal to , false otherwise.
+ /// Note to inheritors: This implementation reads chars one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public override bool Equals(object? other)
{
if (other is null || !(other is CharBuffer otherBuffer))
@@ -472,6 +525,8 @@ public virtual CharBuffer Get(char[] destination)
/// The number of chars to read, must be no less than zero and no
/// greater than destination.Length - offset.
/// This buffer.
+ /// Note to inheritors: This implementation reads chars one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
///
/// plus indicates a position not within this instance.
///
@@ -503,6 +558,33 @@ public virtual CharBuffer Get(char[] destination, int offset, int length) // J2N
return this;
}
+ ///
+ /// Reads chars from the current position into the specified span,
+ /// and increases the position by the number of chars read.
+ ///
+ /// The property is used to determine
+ /// how many chars to read.
+ ///
+ /// The target span, sliced to the proper position, if necessary.
+ /// This buffer.
+ /// Note to inheritors: This implementation reads chars one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
+ /// If is greater than
+ /// .
+ public virtual CharBuffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ {
+ throw new BufferUnderflowException();
+ }
+ for (int i = 0; i < length; i++)
+ {
+ destination[i] = Get();
+ }
+ return this;
+ }
+
///
/// Returns a char at the specified ; the position is not changed.
///
@@ -530,6 +612,8 @@ public virtual CharBuffer Get(char[] destination, int offset, int length) // J2N
/// position, limit, capacity and mark don't affect the hash code.
///
/// The hash code calculated from the remaining chars.
+ /// Note to inheritors: This implementation reads chars one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public override int GetHashCode()
{
int myPosition = position;
@@ -624,6 +708,8 @@ public CharBuffer Put(char[] source)
/// The number of chars to write, must be no less than zero and no
/// greater than source.Length - offset.
/// This buffer.
+ /// Note to inheritors: This implementation writes chars one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
/// If is less than .
///
/// plus indicates a position not within this instance.
@@ -656,6 +742,32 @@ public virtual CharBuffer Put(char[] source, int offset, int length) // J2N TODO
return this;
}
+ ///
+ /// Writes chars in the given span to the current position and increases the
+ /// position by the number of chars written.
+ ///
+ /// Calling this method has a similar effect as
+ /// Put(source, 0, source.Length).
+ ///
+ /// The source span.
+ /// This buffer.
+ /// Note to inheritors: This implementation writes chars one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
+ /// If is less than source.Length.
+ /// If no changes may be made to the contents of this buffer.
+ public virtual CharBuffer Put(ReadOnlySpan source) // J2N specific
+ {
+ int length = source.Length;
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ for (int i = 0; i < length; i++)
+ {
+ Put(source[i]);
+ }
+ return this;
+ }
+
///
/// Writes all the remaining chars of the char buffer to this
/// buffer's current position, and increases both buffers' position by the
@@ -678,10 +790,21 @@ public virtual CharBuffer Put(CharBuffer source)
if (IsReadOnly)
throw new ReadOnlyBufferException(); // J2N: Harmony has a bug - it shouldn't read the source and change its position unless this buffer is writable
- char[] contents = new char[source.Remaining];
- source.Get(contents);
- Put(contents);
- return this;
+ int length = source.Remaining;
+ char[]? arrayToReturnToPool = null;
+ Span contents = length * sizeof(char) > ByteStackBufferSize
+ ? (arrayToReturnToPool = ArrayPool.Shared.Rent(length)).AsSpan(0, length)
+ : stackalloc char[length];
+ try
+ {
+ source.Get(contents);
+ Put(contents);
+ return this;
+ }
+ finally
+ {
+ ArrayPool.Shared.ReturnIfNotNull(arrayToReturnToPool);
+ }
}
///
diff --git a/src/J2N/IO/CharReadOnlyMemoryAdapter.cs b/src/J2N/IO/CharReadOnlyMemoryAdapter.cs
new file mode 100644
index 00000000..a9691d13
--- /dev/null
+++ b/src/J2N/IO/CharReadOnlyMemoryAdapter.cs
@@ -0,0 +1,193 @@
+#region Copyright 2010 by Apache Harmony, Licensed under the Apache License, Version 2.0
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#endregion
+
+using System;
+
+namespace J2N.IO
+{
+ ///
+ /// This class wraps a char sequence to be a buffer.
+ ///
+ /// Implementation notice:
+ ///
+ /// - based buffer is always readonly.
+ ///
+ ///
+ // J2N: Note that this does the same job as ReadOnlyCharArrayBuffer and could effectively replace it,
+ // but also supports string without any allocations. We are only keeping ReadOnlyCharArrayBuffer around
+ // because it is paired and we cannot simply replace ReadWriteCharArrayBuffer's char[] backing field
+ // with Memory because the char[] is exposed through the Array/ProtectedArray properties in those cases.
+ internal sealed class CharReadOnlyMemoryAdapter : CharBuffer
+ {
+ internal static CharReadOnlyMemoryAdapter Copy(CharReadOnlyMemoryAdapter other)
+ {
+ return new CharReadOnlyMemoryAdapter(other.sequence)
+ {
+ limit = other.limit,
+ position = other.position,
+ mark = other.mark
+ };
+ }
+
+ internal readonly object? backingInstance; // Keeps the memory behind sequence in scope
+ internal readonly ReadOnlyMemory sequence;
+
+ internal CharReadOnlyMemoryAdapter(ReadOnlyMemory chseq)
+ : base(chseq.Length)
+ {
+ sequence = chseq;
+ sequence.TryGetReference(ref backingInstance);
+ }
+
+ public override CharBuffer AsReadOnlyBuffer() => Duplicate();
+
+ public override CharBuffer Compact()
+ {
+ throw new ReadOnlyBufferException();
+ }
+
+ public override CharBuffer Duplicate() => Copy(this);
+
+ public override char Get()
+ {
+ if (position == limit)
+ {
+ throw new BufferUnderflowException();
+ }
+ return sequence.Span[position++];
+ }
+
+ public override char Get(int index)
+ {
+ if ((uint)index >= (uint)limit)
+ {
+ throw new ArgumentOutOfRangeException(nameof(index));
+ }
+ return sequence.Span[index];
+ }
+
+ public override sealed CharBuffer Get(char[] destination, int offset, int length) // J2N TODO: API - rename startIndex instead of offset
+ {
+ if (destination is null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.destination);
+ if (offset < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(offset, ExceptionArgument.offset);
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(length, ExceptionArgument.length);
+ if (offset > destination.Length - length) // Checks for int overflow
+ ThrowHelper.ThrowArgumentOutOfRange_IndexLengthString(offset, length);
+ if (length > Remaining)
+ throw new BufferUnderflowException();
+
+ int newPosition = position + length;
+ sequence.Slice(position, length).CopyTo(destination.AsMemory(offset, length));
+ position = newPosition;
+ return this;
+ }
+
+ public override CharBuffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ throw new BufferUnderflowException();
+
+ int newPosition = position + length;
+ sequence.Span.Slice(position, length).CopyTo(destination);
+ position = newPosition;
+ return this;
+ }
+
+ //public override bool IsDirect => false;
+
+ public override bool IsReadOnly => true;
+
+ public override ByteOrder Order => ByteOrder.NativeOrder;
+
+ protected override char[] ProtectedArray
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ protected override int ProtectedArrayOffset
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ protected override bool ProtectedHasArray => false;
+
+ public override CharBuffer Put(char value)
+ {
+ throw new ReadOnlyBufferException();
+ }
+
+ public override CharBuffer Put(int index, char value)
+ {
+ throw new ReadOnlyBufferException();
+ }
+
+ public override sealed CharBuffer Put(char[] source, int offset, int length) // J2N TODO: API - rename startIndex instead of offset
+ {
+ if (source is null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
+ if (offset < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(offset, ExceptionArgument.offset);
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(length, ExceptionArgument.length);
+ if (offset > source.Length - length) // Checks for int overflow
+ ThrowHelper.ThrowArgumentOutOfRange_IndexLengthString(offset, length);
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ throw new ReadOnlyBufferException();
+ }
+
+ public override CharBuffer Put(string source, int startIndex, int length)
+ {
+ if (source is null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
+ if (startIndex < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(startIndex, ExceptionArgument.startIndex);
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(length, ExceptionArgument.length);
+ if (startIndex > source.Length - length) // Checks for int overflow
+ ThrowHelper.ThrowArgumentOutOfRange_IndexLengthString(startIndex, length);
+
+ throw new ReadOnlyBufferException();
+ }
+
+ public override CharBuffer Slice()
+ {
+ return new CharReadOnlyMemoryAdapter(sequence.Slice(position, limit - position)); // J2N: Corrected 2nd parameter
+ }
+
+ public override CharBuffer Subsequence(int startIndex, int length)
+ {
+ if (startIndex < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(startIndex, ExceptionArgument.startIndex);
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(length, ExceptionArgument.length);
+ if (startIndex > Remaining - length) // Checks for int overflow
+ ThrowHelper.ThrowArgumentOutOfRange_IndexLengthString(startIndex, length);
+
+ CharReadOnlyMemoryAdapter result = Copy(this);
+ result.position = position + startIndex;
+ result.limit = position + startIndex + length;
+ return result;
+ }
+ }
+}
diff --git a/src/J2N/IO/CharSequenceAdapter.cs b/src/J2N/IO/CharSequenceAdapter.cs
index 6fd62654..4c68f373 100644
--- a/src/J2N/IO/CharSequenceAdapter.cs
+++ b/src/J2N/IO/CharSequenceAdapter.cs
@@ -18,7 +18,6 @@
using J2N.Text;
using System;
-using System.Diagnostics.CodeAnalysis;
namespace J2N.IO
@@ -92,7 +91,19 @@ public override sealed CharBuffer Get(char[] destination, int offset, int length
throw new BufferUnderflowException();
int newPosition = position + length;
- sequence.ToString().CopyTo(position, destination, offset, length);
+ sequence.ToString().CopyTo(position, destination, offset, length); // J2N TODO: Create specialized adapter for StringBuilder as a separate class and then loop through the indexer here
+ position = newPosition;
+ return this;
+ }
+
+ public override CharBuffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ throw new BufferUnderflowException();
+
+ int newPosition = position + length;
+ sequence.ToString().AsSpan(position, length).CopyTo(destination); // J2N TODO: Create specialized adapter for StringBuilder as a separate class and then loop through the indexer here
position = newPosition;
return this;
}
diff --git a/src/J2N/IO/CharToByteBufferAdapter.cs b/src/J2N/IO/CharToByteBufferAdapter.cs
index 8b08a816..71ed7a3e 100644
--- a/src/J2N/IO/CharToByteBufferAdapter.cs
+++ b/src/J2N/IO/CharToByteBufferAdapter.cs
@@ -161,6 +161,8 @@ public override char Get(int index)
return byteBuffer.GetChar(index << 1);
}
+ // J2N TODO: Need a way to convert the bytes (in the specified endianness) to chars and override Get(Span)
+
//public override bool IsDirect => byteBuffer.IsDirect;
public override bool IsReadOnly => byteBuffer.IsReadOnly;
@@ -199,6 +201,8 @@ public override CharBuffer Put(int index, char value)
return this;
}
+ // J2N TODO: Need a way to convert the bytes (in the specified endianness) from chars and override Put(ReadOnlySpan)
+
public override CharBuffer Slice()
{
byteBuffer.Limit = limit << 1;
diff --git a/src/J2N/IO/DoubleArrayBuffer.cs b/src/J2N/IO/DoubleArrayBuffer.cs
index a59c27da..6da4a8b9 100644
--- a/src/J2N/IO/DoubleArrayBuffer.cs
+++ b/src/J2N/IO/DoubleArrayBuffer.cs
@@ -87,6 +87,16 @@ public override sealed DoubleBuffer Get(double[] destination, int offset, int le
return this;
}
+ public override DoubleBuffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ throw new BufferUnderflowException();
+
+ backingArray.AsSpan(offset + position, length).CopyTo(destination);
+ position += length;
+ return this;
+ }
//public override sealed bool IsDirect => false;
diff --git a/src/J2N/IO/DoubleBuffer.cs b/src/J2N/IO/DoubleBuffer.cs
index 7d0fabe0..ea7d82bb 100644
--- a/src/J2N/IO/DoubleBuffer.cs
+++ b/src/J2N/IO/DoubleBuffer.cs
@@ -16,7 +16,9 @@
*/
#endregion
+using J2N.Buffers;
using System;
+using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Text;
@@ -164,6 +166,8 @@ internal DoubleBuffer(int capacity)
/// A negative value if this is less than ; 0 if this
/// equals to ; a positive value if this is greater
/// than .
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public virtual int CompareTo(DoubleBuffer? other)
{
if (other is null) return 1; // Using 1 if other is null as specified here: https://stackoverflow.com/a/4852537
@@ -206,6 +210,8 @@ public virtual int CompareTo(DoubleBuffer? other)
/// The object to compare with this .
/// true if this is equal to ,
/// false otherwise.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public override bool Equals(object? other)
{
if (other is null || !(other is DoubleBuffer otherBuffer))
@@ -268,6 +274,8 @@ public virtual DoubleBuffer Get(double[] destination)
/// The number of s to read, must be no less than zero and not
/// greater than destination.Length - offset.
/// This buffer.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
///
/// plus indicates a position not within this instance.
///
@@ -297,6 +305,33 @@ public virtual DoubleBuffer Get(double[] destination, int offset, int length) //
return this;
}
+ ///
+ /// Reads s from the current position into the specified span,
+ /// and increases the position by the number of s read.
+ ///
+ /// The property is used to determine
+ /// how many s to read.
+ ///
+ /// The target span, sliced to the proper position, if necessary.
+ /// This buffer.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
+ /// If is greater than
+ /// .
+ public virtual DoubleBuffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ {
+ throw new BufferUnderflowException();
+ }
+ for (int i = 0; i < length; i++)
+ {
+ destination[i] = Get();
+ }
+ return this;
+ }
+
///
/// Returns an at the specified ; the position is not changed.
///
@@ -318,6 +353,8 @@ public virtual DoubleBuffer Get(double[] destination, int offset, int length) //
/// position, limit, capacity and mark don't affect the hash code.
///
/// The hash code calculated from the remaining s.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public override int GetHashCode()
{
int myPosition = position;
@@ -410,6 +447,8 @@ public DoubleBuffer Put(double[] source)
/// The number of s to write, must be no less than zero and not
/// greater than source.Length - offset.
/// This buffer.
+ /// Note to inheritors: This implementation writes s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
/// If is less than .
///
/// plus indicates a position not within this instance.
@@ -440,6 +479,32 @@ public virtual DoubleBuffer Put(double[] source, int offset, int length) // J2N
return this;
}
+ ///
+ /// Writes s in the given span to the current position and increases the
+ /// position by the number of s written.
+ ///
+ /// Calling this method has a similar effect as
+ /// Put(source, 0, source.Length).
+ ///
+ /// The source span.
+ /// This buffer.
+ /// Note to inheritors: This implementation writes s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
+ /// If is less than source.Length.
+ /// If no changes may be made to the contents of this buffer.
+ public virtual DoubleBuffer Put(ReadOnlySpan source) // J2N specific
+ {
+ int length = source.Length;
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ for (int i = 0; i < length; i++)
+ {
+ Put(source[i]);
+ }
+ return this;
+ }
+
///
/// Writes all the remaining s of the to this
/// buffer's current position, and increases both buffers' position by the
@@ -462,10 +527,21 @@ public virtual DoubleBuffer Put(DoubleBuffer source)
if (IsReadOnly)
throw new ReadOnlyBufferException(); // J2N: Harmony has a bug - it shouldn't read the source and change its position unless this buffer is writable
- double[] contents = new double[source.Remaining];
- source.Get(contents);
- Put(contents);
- return this;
+ int length = source.Remaining;
+ double[]? arrayToReturnToPool = null;
+ Span contents = length * sizeof(double) > ByteStackBufferSize
+ ? (arrayToReturnToPool = ArrayPool.Shared.Rent(length)).AsSpan(0, length)
+ : stackalloc double[length];
+ try
+ {
+ source.Get(contents);
+ Put(contents);
+ return this;
+ }
+ finally
+ {
+ ArrayPool.Shared.ReturnIfNotNull(arrayToReturnToPool);
+ }
}
///
diff --git a/src/J2N/IO/DoubleToByteBufferAdapter.cs b/src/J2N/IO/DoubleToByteBufferAdapter.cs
index 6c7cc296..b65cd5cf 100644
--- a/src/J2N/IO/DoubleToByteBufferAdapter.cs
+++ b/src/J2N/IO/DoubleToByteBufferAdapter.cs
@@ -153,6 +153,8 @@ public override double Get(int index)
return byteBuffer.GetDouble(index << 3);
}
+ // J2N TODO: Need a way to convert the bytes (in the specified endianness) to doubles and override Get(Span)
+
//public override bool IsDirect => byteBuffer.IsDirect;
public override bool IsReadOnly => byteBuffer.IsReadOnly;
@@ -191,6 +193,8 @@ public override DoubleBuffer Put(int index, double value)
return this;
}
+ // J2N TODO: Need a way to convert the bytes (in the specified endianness) from doubles and override Put(ReadOnlySpan)
+
public override DoubleBuffer Slice()
{
byteBuffer.SetLimit(limit << 3);
diff --git a/src/J2N/IO/HeapByteBuffer.cs b/src/J2N/IO/HeapByteBuffer.cs
index d399efa2..da12ebac 100644
--- a/src/J2N/IO/HeapByteBuffer.cs
+++ b/src/J2N/IO/HeapByteBuffer.cs
@@ -83,6 +83,17 @@ public override sealed ByteBuffer Get(byte[] destination, int offset, int length
return this;
}
+ public override sealed ByteBuffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ throw new BufferUnderflowException();
+
+ backingArray.AsSpan(offset + position, length).CopyTo(destination);
+ position += length;
+ return this;
+ }
+
public override sealed byte Get()
{
if (position == limit)
diff --git a/src/J2N/IO/Int16ArrayBuffer.cs b/src/J2N/IO/Int16ArrayBuffer.cs
index 5a4a988a..ef333417 100644
--- a/src/J2N/IO/Int16ArrayBuffer.cs
+++ b/src/J2N/IO/Int16ArrayBuffer.cs
@@ -86,6 +86,17 @@ public override sealed Int16Buffer Get(short[] destination, int offset, int leng
return this;
}
+ public override sealed Int16Buffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ throw new BufferUnderflowException();
+
+ backingArray.AsSpan(offset + position, length).CopyTo(destination);
+ position += length;
+ return this;
+ }
+
//public override sealed bool IsDirect => false;
public override sealed ByteOrder Order => ByteOrder.NativeOrder;
diff --git a/src/J2N/IO/Int16Buffer.cs b/src/J2N/IO/Int16Buffer.cs
index 33c94a17..03f8a720 100644
--- a/src/J2N/IO/Int16Buffer.cs
+++ b/src/J2N/IO/Int16Buffer.cs
@@ -16,7 +16,9 @@
*/
#endregion
+using J2N.Buffers;
using System;
+using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Text;
@@ -162,6 +164,8 @@ internal Int16Buffer(int capacity)
/// A negative value if this is less than ; 0 if
/// this equals to ; a positive value if this is
/// greater than .
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public virtual int CompareTo(Int16Buffer? other)
{
if (other is null) return 1; // Using 1 if other is null as specified here: https://stackoverflow.com/a/4852537
@@ -212,6 +216,8 @@ public virtual int CompareTo(Int16Buffer? other)
///
/// The object to compare with this .
/// true if this is equal to , false otherwise.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public override bool Equals(object? other)
{
if (other is null || !(other is Int16Buffer otherBuffer))
@@ -272,6 +278,8 @@ public virtual Int16Buffer Get(short[] destination)
/// The number of s to read, must be no less than zero and
/// not greater than destination.Length - offset.
/// This buffer.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
///
/// plus indicates a position not within this instance.
///
@@ -301,6 +309,33 @@ public virtual Int16Buffer Get(short[] destination, int offset, int length) // J
return this;
}
+ ///
+ /// Reads s from the current position into the specified span,
+ /// and increases the position by the number of s read.
+ ///
+ /// The property is used to determine
+ /// how many s to read.
+ ///
+ /// The target span, sliced to the proper position, if necessary.
+ /// This buffer.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
+ /// If is greater than
+ /// .
+ public virtual Int16Buffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ {
+ throw new BufferUnderflowException();
+ }
+ for (int i = 0; i < length; i++)
+ {
+ destination[i] = Get();
+ }
+ return this;
+ }
+
///
/// Returns the at the specified ; the position is not changed.
///
@@ -323,6 +358,8 @@ public virtual Int16Buffer Get(short[] destination, int offset, int length) // J
/// position, limit, capacity and mark don't affect the hash code.
///
/// The hash code calculated from the remaining s.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public override int GetHashCode()
{
int myPosition = position;
@@ -414,6 +451,8 @@ public Int16Buffer Put(short[] source)
/// The number of s to write, must be no less than zero and
/// not greater than source.Length - offset.
/// This buffer.
+ /// Note to inheritors: This implementation writes s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
/// If is less than .
///
/// plus indicates a position not within this instance.
@@ -444,6 +483,32 @@ public virtual Int16Buffer Put(short[] source, int offset, int length) // J2N TO
return this;
}
+ ///
+ /// Writes s in the given span to the current position and increases the
+ /// position by the number of s written.
+ ///
+ /// Calling this method has a similar effect as
+ /// Put(source, 0, source.Length).
+ ///
+ /// The source span.
+ /// This buffer.
+ /// Note to inheritors: This implementation writes s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
+ /// If is less than source.Length.
+ /// If no changes may be made to the contents of this buffer.
+ public virtual Int16Buffer Put(ReadOnlySpan source) // J2N specific
+ {
+ int length = source.Length;
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ for (int i = 0; i < length; i++)
+ {
+ Put(source[i]);
+ }
+ return this;
+ }
+
///
/// Writes all the remaining s of the to this
/// buffer's current position, and increases both buffers' position by the
@@ -466,10 +531,21 @@ public virtual Int16Buffer Put(Int16Buffer source)
if (IsReadOnly)
throw new ReadOnlyBufferException(); // J2N: Harmony has a bug - it shouldn't read the source and change its position unless this buffer is writable
- short[] contents = new short[source.Remaining];
- source.Get(contents);
- Put(contents);
- return this;
+ int length = source.Remaining;
+ short[]? arrayToReturnToPool = null;
+ Span contents = length * sizeof(short) > ByteStackBufferSize
+ ? (arrayToReturnToPool = ArrayPool.Shared.Rent(length)).AsSpan(0, length)
+ : stackalloc short[length];
+ try
+ {
+ source.Get(contents);
+ Put(contents);
+ return this;
+ }
+ finally
+ {
+ ArrayPool.Shared.ReturnIfNotNull(arrayToReturnToPool);
+ }
}
///
diff --git a/src/J2N/IO/Int16ToByteBufferAdapter.cs b/src/J2N/IO/Int16ToByteBufferAdapter.cs
index 9a412bd5..bb7bc71b 100644
--- a/src/J2N/IO/Int16ToByteBufferAdapter.cs
+++ b/src/J2N/IO/Int16ToByteBufferAdapter.cs
@@ -156,6 +156,8 @@ public override short Get(int index)
return byteBuffer.GetInt16(index << 1);
}
+ // J2N TODO: Need a way to convert the bytes (in the specified endianness) to shorts and override Get(Span)
+
//public override bool IsDirect => byteBuffer.IsDirect;
public override bool IsReadOnly => byteBuffer.IsReadOnly;
@@ -197,6 +199,8 @@ public override Int16Buffer Put(int index, short value)
return this;
}
+ // J2N TODO: Need a way to convert the bytes (in the specified endianness) from shorts and override Put(ReadOnlySpan)
+
public override Int16Buffer Slice()
{
byteBuffer.Limit = (limit << 1);
diff --git a/src/J2N/IO/Int32ArrayBuffer.cs b/src/J2N/IO/Int32ArrayBuffer.cs
index 3e08aefb..2b31d4ba 100644
--- a/src/J2N/IO/Int32ArrayBuffer.cs
+++ b/src/J2N/IO/Int32ArrayBuffer.cs
@@ -86,6 +86,17 @@ public override sealed Int32Buffer Get(int[] destination, int offset, int length
return this;
}
+ public override sealed Int32Buffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ throw new BufferUnderflowException();
+
+ backingArray.AsSpan(offset + position, length).CopyTo(destination);
+ position += length;
+ return this;
+ }
+
//public override sealed bool IsDirect => false;
public override sealed ByteOrder Order => ByteOrder.NativeOrder;
diff --git a/src/J2N/IO/Int32Buffer.cs b/src/J2N/IO/Int32Buffer.cs
index a35e5689..90625349 100644
--- a/src/J2N/IO/Int32Buffer.cs
+++ b/src/J2N/IO/Int32Buffer.cs
@@ -16,7 +16,9 @@
*/
#endregion
+using J2N.Buffers;
using System;
+using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Text;
@@ -161,6 +163,8 @@ internal Int32Buffer(int capacity)
/// a negative value if this is less than ; 0 if this
/// equals to ; a positive value if this is greater
/// than .
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public virtual int CompareTo(Int32Buffer? other)
{
if (other is null) return 1; // Using 1 if other is null as specified here: https://stackoverflow.com/a/4852537
@@ -212,6 +216,8 @@ public virtual int CompareTo(Int32Buffer? other)
/// The object to compare with this .
/// true if this is equal to ,
/// false otherwise.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public override bool Equals(object? other)
{
if (other is null || !(other is Int32Buffer otherBuffer))
@@ -271,6 +277,8 @@ public virtual Int32Buffer Get(int[] destination)
/// The number of s to read, must be no less than zero and not
/// greater than destination.Length - offset.
/// This buffer.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
///
/// plus indicates a position not within this instance.
///
@@ -300,6 +308,33 @@ public virtual Int32Buffer Get(int[] destination, int offset, int length) // J2N
return this;
}
+ ///
+ /// Reads s from the current position into the specified span,
+ /// and increases the position by the number of s read.
+ ///
+ /// The property is used to determine
+ /// how many s to read.
+ ///
+ /// The target span, sliced to the proper position, if necessary.
+ /// This buffer.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
+ /// If is greater than
+ /// .
+ public virtual Int32Buffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ {
+ throw new BufferUnderflowException();
+ }
+ for (int i = 0; i < length; i++)
+ {
+ destination[i] = Get();
+ }
+ return this;
+ }
+
///
/// Returns an at the specified ; the position is not changed.
///
@@ -321,6 +356,8 @@ public virtual Int32Buffer Get(int[] destination, int offset, int length) // J2N
/// position, limit, capacity and mark don't affect the hash code.
///
/// The hash code calculated from the remaining s.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public override int GetHashCode()
{
int myPosition = position;
@@ -411,6 +448,8 @@ public Int32Buffer Put(int[] source)
/// The number of s to write, must be no less than zero and not
/// greater than source.Length - offset.
/// This buffer.
+ /// Note to inheritors: This implementation writes s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
/// If is less than .
///
/// plus indicates a position not within this instance.
@@ -441,6 +480,32 @@ public virtual Int32Buffer Put(int[] source, int offset, int length) // J2N TODO
return this;
}
+ ///
+ /// Writes s in the given span to the current position and increases the
+ /// position by the number of s written.
+ ///
+ /// Calling this method has a similar effect as
+ /// Put(source, 0, source.Length).
+ ///
+ /// The source span.
+ /// This buffer.
+ /// Note to inheritors: This implementation writes s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
+ /// If is less than source.Length.
+ /// If no changes may be made to the contents of this buffer.
+ public virtual Int32Buffer Put(ReadOnlySpan source) // J2N specific
+ {
+ int length = source.Length;
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ for (int i = 0; i < length; i++)
+ {
+ Put(source[i]);
+ }
+ return this;
+ }
+
///
/// Writes all the remaining s of the to this
/// buffer's current position, and increases both buffers' position by the
@@ -463,10 +528,21 @@ public virtual Int32Buffer Put(Int32Buffer source)
if (IsReadOnly)
throw new ReadOnlyBufferException(); // J2N: Harmony has a bug - it shouldn't read the source and change its position unless this buffer is writable
- int[] contents = new int[source.Remaining];
- source.Get(contents);
- Put(contents);
- return this;
+ int length = source.Remaining;
+ int[]? arrayToReturnToPool = null;
+ Span contents = length * sizeof(int) > ByteStackBufferSize
+ ? (arrayToReturnToPool = ArrayPool.Shared.Rent(length)).AsSpan(0, length)
+ : stackalloc int[length];
+ try
+ {
+ source.Get(contents);
+ Put(contents);
+ return this;
+ }
+ finally
+ {
+ ArrayPool.Shared.ReturnIfNotNull(arrayToReturnToPool);
+ }
}
///
diff --git a/src/J2N/IO/Int32ToByteBufferAdapter.cs b/src/J2N/IO/Int32ToByteBufferAdapter.cs
index d024bc6d..85392164 100644
--- a/src/J2N/IO/Int32ToByteBufferAdapter.cs
+++ b/src/J2N/IO/Int32ToByteBufferAdapter.cs
@@ -163,6 +163,8 @@ public override int Get(int index)
return byteBuffer.GetInt32(index << 2);
}
+ // J2N TODO: Need a way to convert the bytes (in the specified endianness) to ints and override Get(Span)
+
//public override bool IsDirect => byteBuffer.IsDirect;
public override bool IsReadOnly => byteBuffer.IsReadOnly;
@@ -201,6 +203,8 @@ public override Int32Buffer Put(int index, int value)
return this;
}
+ // J2N TODO: Need a way to convert the bytes (in the specified endianness) from ints and override Put(ReadOnlySpan)
+
public override Int32Buffer Slice()
{
byteBuffer.Limit = limit << 2;
diff --git a/src/J2N/IO/Int64ArrayBuffer.cs b/src/J2N/IO/Int64ArrayBuffer.cs
index 283fb620..8b58ec02 100644
--- a/src/J2N/IO/Int64ArrayBuffer.cs
+++ b/src/J2N/IO/Int64ArrayBuffer.cs
@@ -88,6 +88,17 @@ public override sealed Int64Buffer Get(long[] destination, int offset, int lengt
return this;
}
+ public override sealed Int64Buffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ throw new BufferUnderflowException();
+
+ backingArray.AsSpan(offset + position, length).CopyTo(destination);
+ position += length;
+ return this;
+ }
+
//public override sealed bool IsDirect => false;
public override sealed ByteOrder Order => ByteOrder.NativeOrder;
diff --git a/src/J2N/IO/Int64Buffer.cs b/src/J2N/IO/Int64Buffer.cs
index 516487f3..7e194796 100644
--- a/src/J2N/IO/Int64Buffer.cs
+++ b/src/J2N/IO/Int64Buffer.cs
@@ -16,7 +16,9 @@
*/
#endregion
+using J2N.Buffers;
using System;
+using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Text;
@@ -172,6 +174,8 @@ public int ArrayOffset
/// A negative value if this is less than ; 0 if this
/// equals to ; a positive value if this is greater
/// than .
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public int CompareTo(Int64Buffer? other)
{
if (other is null) return 1; // Using 1 if other is null as specified here: https://stackoverflow.com/a/4852537
@@ -223,6 +227,8 @@ public int CompareTo(Int64Buffer? other)
/// The object to compare with this .
/// true if this is equal to ,
/// false otherwise.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public override bool Equals(object? other)
{
if (other is null || !(other is Int64Buffer otherBuffer))
@@ -282,6 +288,8 @@ public virtual Int64Buffer Get(long[] destination)
/// The number of s to read, must be no less than zero and not
/// greater than destination.Length - offset.
/// This buffer.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
///
/// plus indicates a position not within this instance.
///
@@ -313,6 +321,33 @@ public virtual Int64Buffer Get(long[] destination, int offset, int length) // J2
return this;
}
+ ///
+ /// Reads s from the current position into the specified span,
+ /// and increases the position by the number of s read.
+ ///
+ /// The property is used to determine
+ /// how many s to read.
+ ///
+ /// The target span, sliced to the proper position, if necessary.
+ /// This buffer.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
+ /// If is greater than
+ /// .
+ public virtual Int64Buffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ {
+ throw new BufferUnderflowException();
+ }
+ for (int i = 0; i < length; i++)
+ {
+ destination[i] = Get();
+ }
+ return this;
+ }
+
///
/// Returns an at the specified ; the position is not changed.
///
@@ -337,6 +372,8 @@ public bool HasArray
/// position, limit, capacity and mark don't affect the hash code.
///
/// The hash code calculated from the remaining s.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public override int GetHashCode()
{
int myPosition = position;
@@ -429,6 +466,8 @@ public Int64Buffer Put(long[] source)
/// The number of s to write, must be no less than zero and not
/// greater than source.Length - offset.
/// This buffer.
+ /// Note to inheritors: This implementation writes s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
/// If is less than .
///
/// plus indicates a position not within this instance.
@@ -459,6 +498,32 @@ public virtual Int64Buffer Put(long[] source, int offset, int length) // J2N TOD
return this;
}
+ ///
+ /// Writes s in the given span to the current position and increases the
+ /// position by the number of s written.
+ ///
+ /// Calling this method has a similar effect as
+ /// Put(source, 0, source.Length).
+ ///
+ /// The source span.
+ /// This buffer.
+ /// Note to inheritors: This implementation writes s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
+ /// If is less than source.Length.
+ /// If no changes may be made to the contents of this buffer.
+ public virtual Int64Buffer Put(ReadOnlySpan source) // J2N specific
+ {
+ int length = source.Length;
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ for (int i = 0; i < length; i++)
+ {
+ Put(source[i]);
+ }
+ return this;
+ }
+
///
/// Writes all the remaining s of the to this
/// buffer's current position, and increases both buffers' position by the
@@ -481,10 +546,21 @@ public virtual Int64Buffer Put(Int64Buffer source)
if (IsReadOnly)
throw new ReadOnlyBufferException(); // J2N: Harmony has a bug - it shouldn't read the source and change its position unless this buffer is writable
- long[] contents = new long[source.Remaining];
- source.Get(contents);
- Put(contents);
- return this;
+ int length = source.Remaining;
+ long[]? arrayToReturnToPool = null;
+ Span contents = length * sizeof(long) > ByteStackBufferSize
+ ? (arrayToReturnToPool = ArrayPool.Shared.Rent(length)).AsSpan(0, length)
+ : stackalloc long[length];
+ try
+ {
+ source.Get(contents);
+ Put(contents);
+ return this;
+ }
+ finally
+ {
+ ArrayPool.Shared.ReturnIfNotNull(arrayToReturnToPool);
+ }
}
///
diff --git a/src/J2N/IO/Int64ToByteBufferAdapter.cs b/src/J2N/IO/Int64ToByteBufferAdapter.cs
index 9dde15d9..7820c906 100644
--- a/src/J2N/IO/Int64ToByteBufferAdapter.cs
+++ b/src/J2N/IO/Int64ToByteBufferAdapter.cs
@@ -155,6 +155,8 @@ public override long Get(int index)
return byteBuffer.GetInt64(index << 3);
}
+ // J2N TODO: Need a way to convert the bytes (in the specified endianness) to longs and override Get(Span)
+
//public override bool IsDirect => byteBuffer.IsDirect;
public override bool IsReadOnly => byteBuffer.IsReadOnly;
@@ -192,6 +194,9 @@ public override Int64Buffer Put(int index, long value)
byteBuffer.PutInt64(index << 3, value);
return this;
}
+
+ // J2N TODO: Need a way to convert the bytes (in the specified endianness) from longs and override Put(ReadOnlySpan)
+
public override Int64Buffer Slice()
{
byteBuffer.SetLimit(limit << 3);
diff --git a/src/J2N/IO/ReadOnlyCharArrayBuffer.cs b/src/J2N/IO/ReadOnlyCharArrayBuffer.cs
index 6560b152..14cfa250 100644
--- a/src/J2N/IO/ReadOnlyCharArrayBuffer.cs
+++ b/src/J2N/IO/ReadOnlyCharArrayBuffer.cs
@@ -79,12 +79,17 @@ public override CharBuffer Put(int index, char value)
throw new ReadOnlyBufferException();
}
- public override sealed CharBuffer Put(char[] source, int offset, int length)
+ public override CharBuffer Put(char[] source, int offset, int length)
{
throw new ReadOnlyBufferException();
}
- public override sealed CharBuffer Put(CharBuffer src)
+ public override CharBuffer Put(ReadOnlySpan source) // J2N specific
+ {
+ throw new ReadOnlyBufferException();
+ }
+
+ public override CharBuffer Put(CharBuffer src)
{
throw new ReadOnlyBufferException();
}
diff --git a/src/J2N/IO/ReadOnlyDoubleArrayBuffer.cs b/src/J2N/IO/ReadOnlyDoubleArrayBuffer.cs
index a040fa0e..4e46b0a5 100644
--- a/src/J2N/IO/ReadOnlyDoubleArrayBuffer.cs
+++ b/src/J2N/IO/ReadOnlyDoubleArrayBuffer.cs
@@ -16,6 +16,8 @@
*/
#endregion
+using System;
+
namespace J2N.IO
{
///
@@ -82,7 +84,12 @@ public override DoubleBuffer Put(DoubleBuffer buffer)
throw new ReadOnlyBufferException();
}
- public override sealed DoubleBuffer Put(double[] source, int offset, int length)
+ public override DoubleBuffer Put(double[] source, int offset, int length)
+ {
+ throw new ReadOnlyBufferException();
+ }
+
+ public override DoubleBuffer Put(ReadOnlySpan source) // J2N specific
{
throw new ReadOnlyBufferException();
}
diff --git a/src/J2N/IO/ReadOnlyHeapByteBuffer.cs b/src/J2N/IO/ReadOnlyHeapByteBuffer.cs
index 7fcb8f11..d6f5f894 100644
--- a/src/J2N/IO/ReadOnlyHeapByteBuffer.cs
+++ b/src/J2N/IO/ReadOnlyHeapByteBuffer.cs
@@ -16,6 +16,8 @@
*/
#endregion
+using System;
+
namespace J2N.IO
{
///
@@ -80,6 +82,11 @@ public override ByteBuffer Put(byte[] source, int offset, int length)
throw new ReadOnlyBufferException();
}
+ public override ByteBuffer Put(ReadOnlySpan source) // J2N specific
+ {
+ throw new ReadOnlyBufferException();
+ }
+
public override ByteBuffer PutDouble(double value)
{
throw new ReadOnlyBufferException();
diff --git a/src/J2N/IO/ReadOnlyInt16ArrayBuffer.cs b/src/J2N/IO/ReadOnlyInt16ArrayBuffer.cs
index 9ed2ba98..fb49c651 100644
--- a/src/J2N/IO/ReadOnlyInt16ArrayBuffer.cs
+++ b/src/J2N/IO/ReadOnlyInt16ArrayBuffer.cs
@@ -16,6 +16,8 @@
*/
#endregion
+using System;
+
namespace J2N.IO
{
///
@@ -81,7 +83,12 @@ public override Int16Buffer Put(int index, short value)
throw new ReadOnlyBufferException();
}
- public override sealed Int16Buffer Put(short[] source, int offset, int length)
+ public override Int16Buffer Put(short[] source, int offset, int length)
+ {
+ throw new ReadOnlyBufferException();
+ }
+
+ public override Int16Buffer Put(ReadOnlySpan source) // J2N specific
{
throw new ReadOnlyBufferException();
}
diff --git a/src/J2N/IO/ReadOnlyInt32ArrayBuffer.cs b/src/J2N/IO/ReadOnlyInt32ArrayBuffer.cs
index ab3ac3a1..93caa46a 100644
--- a/src/J2N/IO/ReadOnlyInt32ArrayBuffer.cs
+++ b/src/J2N/IO/ReadOnlyInt32ArrayBuffer.cs
@@ -16,7 +16,7 @@
*/
#endregion
-using System.Diagnostics.CodeAnalysis;
+using System;
namespace J2N.IO
@@ -84,7 +84,12 @@ public override Int32Buffer Put(Int32Buffer buffer)
throw new ReadOnlyBufferException();
}
- public override sealed Int32Buffer Put(int[] source, int offset, int length)
+ public override Int32Buffer Put(int[] source, int offset, int length)
+ {
+ throw new ReadOnlyBufferException();
+ }
+
+ public override Int32Buffer Put(ReadOnlySpan source) // J2N specific
{
throw new ReadOnlyBufferException();
}
diff --git a/src/J2N/IO/ReadOnlyInt64ArrayBuffer.cs b/src/J2N/IO/ReadOnlyInt64ArrayBuffer.cs
index 45104f2d..6f4f00d2 100644
--- a/src/J2N/IO/ReadOnlyInt64ArrayBuffer.cs
+++ b/src/J2N/IO/ReadOnlyInt64ArrayBuffer.cs
@@ -16,6 +16,8 @@
*/
#endregion
+using System;
+
namespace J2N.IO
{
///
@@ -81,7 +83,12 @@ public override Int64Buffer Put(Int64Buffer buffer)
throw new ReadOnlyBufferException();
}
- public override sealed Int64Buffer Put(long[] source, int offset, int length)
+ public override Int64Buffer Put(long[] source, int offset, int length)
+ {
+ throw new ReadOnlyBufferException();
+ }
+
+ public override Int64Buffer Put(ReadOnlySpan source) // J2N specific
{
throw new ReadOnlyBufferException();
}
diff --git a/src/J2N/IO/ReadOnlySingleArrayBuffer.cs b/src/J2N/IO/ReadOnlySingleArrayBuffer.cs
index 8d9bd05d..cf9e733d 100644
--- a/src/J2N/IO/ReadOnlySingleArrayBuffer.cs
+++ b/src/J2N/IO/ReadOnlySingleArrayBuffer.cs
@@ -16,6 +16,8 @@
*/
#endregion
+using System;
+
namespace J2N.IO
{
///
@@ -86,6 +88,11 @@ public override sealed SingleBuffer Put(float[] source, int offset, int length)
throw new ReadOnlyBufferException();
}
+ public override SingleBuffer Put(ReadOnlySpan source) // J2N specific
+ {
+ throw new ReadOnlyBufferException();
+ }
+
public override SingleBuffer Slice()
{
return new ReadOnlySingleArrayBuffer(Remaining, backingArray, offset + position);
diff --git a/src/J2N/IO/ReadWriteCharArrayBuffer.cs b/src/J2N/IO/ReadWriteCharArrayBuffer.cs
index c690276e..13194d99 100644
--- a/src/J2N/IO/ReadWriteCharArrayBuffer.cs
+++ b/src/J2N/IO/ReadWriteCharArrayBuffer.cs
@@ -113,6 +113,17 @@ public override CharBuffer Put(char[] source, int offset, int length) // J2N TOD
return this;
}
+ public override CharBuffer Put(ReadOnlySpan source) // J2N specific
+ {
+ int length = source.Length;
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ source.CopyTo(backingArray.AsSpan(offset + position, length));
+ position += length;
+ return this;
+ }
+
public override CharBuffer Slice()
{
return new ReadWriteCharArrayBuffer(Remaining, backingArray, offset + position);
diff --git a/src/J2N/IO/ReadWriteDoubleArrayBuffer.cs b/src/J2N/IO/ReadWriteDoubleArrayBuffer.cs
index ddb2d94f..46996abe 100644
--- a/src/J2N/IO/ReadWriteDoubleArrayBuffer.cs
+++ b/src/J2N/IO/ReadWriteDoubleArrayBuffer.cs
@@ -113,6 +113,17 @@ public override DoubleBuffer Put(double[] source, int offset, int length) // J2N
return this;
}
+ public override DoubleBuffer Put(ReadOnlySpan source) // J2N specific
+ {
+ int length = source.Length;
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ source.CopyTo(backingArray.AsSpan(offset + position, length));
+ position += length;
+ return this;
+ }
+
public override DoubleBuffer Slice()
{
return new ReadWriteDoubleArrayBuffer(Remaining, backingArray, offset + position);
diff --git a/src/J2N/IO/ReadWriteHeapByteBuffer.cs b/src/J2N/IO/ReadWriteHeapByteBuffer.cs
index 414971b0..1d91ead7 100644
--- a/src/J2N/IO/ReadWriteHeapByteBuffer.cs
+++ b/src/J2N/IO/ReadWriteHeapByteBuffer.cs
@@ -119,14 +119,23 @@ public override ByteBuffer Put(byte[] source, int offset, int length) // J2N TOD
ThrowHelper.ThrowArgumentOutOfRange_IndexLengthArray(offset, ExceptionArgument.offset, length);
if (length > Remaining)
throw new BufferOverflowException();
- if (IsReadOnly)
- throw new ReadOnlyBufferException();
System.Array.Copy(source, offset, backingArray, base.offset + position, length);
position += length;
return this;
}
+ public override ByteBuffer Put(ReadOnlySpan source) // J2N specific
+ {
+ int length = source.Length;
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ source.CopyTo(backingArray.AsSpan(offset + position, length));
+ position += length;
+ return this;
+ }
+
public override ByteBuffer PutDouble(double value)
{
return PutInt64(BitConversion.DoubleToRawInt64Bits(value));
diff --git a/src/J2N/IO/ReadWriteInt16ArrayBuffer.cs b/src/J2N/IO/ReadWriteInt16ArrayBuffer.cs
index 379c9c6b..1caef670 100644
--- a/src/J2N/IO/ReadWriteInt16ArrayBuffer.cs
+++ b/src/J2N/IO/ReadWriteInt16ArrayBuffer.cs
@@ -116,6 +116,17 @@ public override Int16Buffer Put(short[] source, int offset, int length) // J2N T
return this;
}
+ public override Int16Buffer Put(ReadOnlySpan source) // J2N specific
+ {
+ int length = source.Length;
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ source.CopyTo(backingArray.AsSpan(offset + position, length));
+ position += length;
+ return this;
+ }
+
public override Int16Buffer Slice()
{
return new ReadWriteInt16ArrayBuffer(Remaining, backingArray, offset + position);
diff --git a/src/J2N/IO/ReadWriteInt32ArrayBuffer.cs b/src/J2N/IO/ReadWriteInt32ArrayBuffer.cs
index e55de91f..d6e1fff1 100644
--- a/src/J2N/IO/ReadWriteInt32ArrayBuffer.cs
+++ b/src/J2N/IO/ReadWriteInt32ArrayBuffer.cs
@@ -115,6 +115,17 @@ public override Int32Buffer Put(int[] source, int offset, int length) // J2N TOD
return this;
}
+ public override Int32Buffer Put(ReadOnlySpan source) // J2N specific
+ {
+ int length = source.Length;
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ source.CopyTo(backingArray.AsSpan(offset + position, length));
+ position += length;
+ return this;
+ }
+
public override Int32Buffer Slice()
{
return new ReadWriteInt32ArrayBuffer(Remaining, backingArray, offset + position);
diff --git a/src/J2N/IO/ReadWriteInt64ArrayBuffer.cs b/src/J2N/IO/ReadWriteInt64ArrayBuffer.cs
index ab6c3c66..748bad82 100644
--- a/src/J2N/IO/ReadWriteInt64ArrayBuffer.cs
+++ b/src/J2N/IO/ReadWriteInt64ArrayBuffer.cs
@@ -113,6 +113,17 @@ public override Int64Buffer Put(long[] source, int offset, int length) // J2N TO
return this;
}
+ public override Int64Buffer Put(ReadOnlySpan source) // J2N specific
+ {
+ int length = source.Length;
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ source.CopyTo(backingArray.AsSpan(offset + position, length));
+ position += length;
+ return this;
+ }
+
public override Int64Buffer Slice()
{
return new ReadWriteInt64ArrayBuffer(Remaining, backingArray, offset + position);
diff --git a/src/J2N/IO/ReadWriteSingleArrayBuffer.cs b/src/J2N/IO/ReadWriteSingleArrayBuffer.cs
index 7fd83660..916f1605 100644
--- a/src/J2N/IO/ReadWriteSingleArrayBuffer.cs
+++ b/src/J2N/IO/ReadWriteSingleArrayBuffer.cs
@@ -113,6 +113,17 @@ public override SingleBuffer Put(float[] source, int offset, int length) // J2N
return this;
}
+ public override SingleBuffer Put(ReadOnlySpan source) // J2N specific
+ {
+ int length = source.Length;
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ source.CopyTo(backingArray.AsSpan(offset + position, length));
+ position += length;
+ return this;
+ }
+
public override SingleBuffer Slice()
{
return new ReadWriteSingleArrayBuffer(Remaining, backingArray, offset + position);
diff --git a/src/J2N/IO/SingleArrayBuffer.cs b/src/J2N/IO/SingleArrayBuffer.cs
index 7cd4b7e7..369a7289 100644
--- a/src/J2N/IO/SingleArrayBuffer.cs
+++ b/src/J2N/IO/SingleArrayBuffer.cs
@@ -86,6 +86,17 @@ public override sealed SingleBuffer Get(float[] destination, int offset, int len
return this;
}
+ public override SingleBuffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ throw new BufferUnderflowException();
+
+ backingArray.AsSpan(offset + position, length).CopyTo(destination);
+ position += length;
+ return this;
+ }
+
//public override sealed bool IsDirect => false;
public override sealed ByteOrder Order => ByteOrder.NativeOrder;
diff --git a/src/J2N/IO/SingleBuffer.cs b/src/J2N/IO/SingleBuffer.cs
index e73fa906..39ed0ad7 100644
--- a/src/J2N/IO/SingleBuffer.cs
+++ b/src/J2N/IO/SingleBuffer.cs
@@ -16,7 +16,9 @@
*/
#endregion
+using J2N.Buffers;
using System;
+using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Text;
@@ -163,6 +165,8 @@ internal SingleBuffer(int capacity)
/// a negative value if this is less than ; 0 if this
/// equals to ; a positive value if this is greater
/// than .
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public virtual int CompareTo(SingleBuffer? other)
{
if (other is null) return 1; // Using 1 if other is null as specified here: https://stackoverflow.com/a/4852537
@@ -205,6 +209,8 @@ public virtual int CompareTo(SingleBuffer? other)
/// The object to compare with this .
/// true if this is equal to ,
/// false otherwise.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public override bool Equals(object? other)
{
if (other is null || !(other is SingleBuffer otherBuffer))
@@ -267,6 +273,8 @@ public virtual SingleBuffer Get(float[] destination)
/// The number of s to read, must be no less than zero and not
/// greater than destination.Length - offset.
/// This buffer.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
///
/// plus indicates a position not within this instance.
///
@@ -296,6 +304,33 @@ public virtual SingleBuffer Get(float[] destination, int offset, int length) //
return this;
}
+ ///
+ /// Reads s from the current position into the specified span,
+ /// and increases the position by the number of s read.
+ ///
+ /// The property is used to determine
+ /// how many s to read.
+ ///
+ /// The target span, sliced to the proper position, if necessary.
+ /// This buffer.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
+ /// If is greater than
+ /// .
+ public virtual SingleBuffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ {
+ throw new BufferUnderflowException();
+ }
+ for (int i = 0; i < length; i++)
+ {
+ destination[i] = Get();
+ }
+ return this;
+ }
+
///
/// Returns an at the specified ; the position is not changed.
///
@@ -317,6 +352,8 @@ public virtual SingleBuffer Get(float[] destination, int offset, int length) //
/// position, limit, capacity and mark don't affect the hash code.
///
/// The hash code calculated from the remaining s.
+ /// Note to inheritors: This implementation reads s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
public override int GetHashCode()
{
int myPosition = position;
@@ -407,6 +444,8 @@ public SingleBuffer Put(float[] source)
/// The number of s to write, must be no less than zero and not
/// greater than source.Length - offset.
/// This buffer.
+ /// Note to inheritors: This implementation writes s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
/// If is less than .
///
/// plus indicates a position not within this instance.
@@ -437,6 +476,32 @@ public virtual SingleBuffer Put(float[] source, int offset, int length) // J2N T
return this;
}
+ ///
+ /// Writes s in the given span to the current position and increases the
+ /// position by the number of s written.
+ ///
+ /// Calling this method has a similar effect as
+ /// Put(source, 0, source.Length).
+ ///
+ /// The source span.
+ /// This buffer.
+ /// Note to inheritors: This implementation writes s one at a time and it is highly
+ /// recommended to override to provide a more optimized implementation.
+ /// If is less than source.Length.
+ /// If no changes may be made to the contents of this buffer.
+ public virtual SingleBuffer Put(ReadOnlySpan source) // J2N specific
+ {
+ int length = source.Length;
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ for (int i = 0; i < length; i++)
+ {
+ Put(source[i]);
+ }
+ return this;
+ }
+
///
/// Writes all the remaining s of the to this
/// buffer's current position, and increases both buffers' position by the
@@ -459,10 +524,21 @@ public virtual SingleBuffer Put(SingleBuffer source)
if (IsReadOnly)
throw new ReadOnlyBufferException(); // J2N: Harmony has a bug - it shouldn't read the source and change its position unless this buffer is writable
- float[] contents = new float[source.Remaining];
- source.Get(contents);
- Put(contents);
- return this;
+ int length = source.Remaining;
+ float[]? arrayToReturnToPool = null;
+ Span contents = length * sizeof(float) > ByteStackBufferSize
+ ? (arrayToReturnToPool = ArrayPool.Shared.Rent(length)).AsSpan(0, length)
+ : stackalloc float[length];
+ try
+ {
+ source.Get(contents);
+ Put(contents);
+ return this;
+ }
+ finally
+ {
+ ArrayPool.Shared.ReturnIfNotNull(arrayToReturnToPool);
+ }
}
///
diff --git a/src/J2N/IO/SingleToByteBufferAdapter.cs b/src/J2N/IO/SingleToByteBufferAdapter.cs
index 012c4fee..f803cfeb 100644
--- a/src/J2N/IO/SingleToByteBufferAdapter.cs
+++ b/src/J2N/IO/SingleToByteBufferAdapter.cs
@@ -156,6 +156,7 @@ public override float Get(int index)
return byteBuffer.GetSingle(index << 2);
}
+ // J2N TODO: Need a way to convert the bytes (in the specified endianness) to floats and override Get(Span)
//public override bool IsDirect => byteBuffer.IsDirect;
@@ -196,6 +197,8 @@ public override SingleBuffer Put(int index, float value)
return this;
}
+ // J2N TODO: Need a way to convert the bytes (in the specified endianness) from floats and override Put(ReadOnlySpan)
+
public override SingleBuffer Slice()
{
byteBuffer.SetLimit(limit << 2);
diff --git a/src/J2N/IO/StringBuilderAdapter.cs b/src/J2N/IO/StringBuilderAdapter.cs
new file mode 100644
index 00000000..d351ca10
--- /dev/null
+++ b/src/J2N/IO/StringBuilderAdapter.cs
@@ -0,0 +1,195 @@
+#region Copyright 2010 by Apache Harmony, Licensed under the Apache License, Version 2.0
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#endregion
+
+using J2N.Text;
+using System;
+using System.Text;
+
+namespace J2N.IO
+{
+ ///
+ /// This class wraps a char sequence to be a buffer.
+ ///
+ /// Implementation notice:
+ ///
+ /// - Char sequence based buffer is always readonly.
+ ///
+ ///
+ internal sealed class StringBuilderAdapter : CharBuffer
+ {
+ internal static StringBuilderAdapter Copy(StringBuilderAdapter other)
+ {
+ return new StringBuilderAdapter(other.sequence)
+ {
+ limit = other.limit,
+ position = other.position,
+ mark = other.mark
+ };
+ }
+
+ internal readonly StringBuilder sequence;
+
+ internal StringBuilderAdapter(StringBuilder chseq)
+ : base(chseq.Length)
+ {
+ sequence = chseq;
+ }
+
+ public override CharBuffer AsReadOnlyBuffer() => Duplicate();
+
+ public override CharBuffer Compact()
+ {
+ throw new ReadOnlyBufferException();
+ }
+
+ public override CharBuffer Duplicate() => Copy(this);
+
+ public override char Get()
+ {
+ if (position == limit)
+ {
+ throw new BufferUnderflowException();
+ }
+ return sequence[position++];
+ }
+
+ public override char Get(int index)
+ {
+ if ((uint)index >= (uint)limit)
+ {
+ throw new ArgumentOutOfRangeException(nameof(index));
+ }
+ return sequence[index];
+ }
+
+ public override sealed CharBuffer Get(char[] destination, int offset, int length) // J2N TODO: API - rename startIndex instead of offset
+ {
+ if (destination is null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.destination);
+ if (offset < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(offset, ExceptionArgument.offset);
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(length, ExceptionArgument.length);
+ if (offset > destination.Length - length) // Checks for int overflow
+ ThrowHelper.ThrowArgumentOutOfRange_IndexLengthString(offset, length);
+ if (length > Remaining)
+ throw new BufferUnderflowException();
+
+
+ int newPosition = position + length;
+ sequence.CopyTo(position, destination, offset, length);
+ position = newPosition;
+ return this;
+ }
+
+ public override CharBuffer Get(Span destination) // J2N specific
+ {
+ int length = destination.Length;
+ if (length > Remaining)
+ throw new BufferUnderflowException();
+
+ int newPosition = position + length;
+ sequence.CopyTo(position, destination, length);
+ position = newPosition;
+ return this;
+ }
+
+ //public override bool IsDirect => false;
+
+ public override bool IsReadOnly => true;
+
+ public override ByteOrder Order => ByteOrder.NativeOrder;
+
+ protected override char[] ProtectedArray
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ protected override int ProtectedArrayOffset
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ protected override bool ProtectedHasArray => false;
+
+ public override CharBuffer Put(char value)
+ {
+ throw new ReadOnlyBufferException();
+ }
+
+ public override CharBuffer Put(int index, char value)
+ {
+ throw new ReadOnlyBufferException();
+ }
+
+ public override sealed CharBuffer Put(char[] source, int offset, int length) // J2N TODO: API - rename startIndex instead of offset
+ {
+ if (source is null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
+ if (offset < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(offset, ExceptionArgument.offset);
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(length, ExceptionArgument.length);
+ if (offset > source.Length - length) // Checks for int overflow
+ ThrowHelper.ThrowArgumentOutOfRange_IndexLengthString(offset, length);
+ if (length > Remaining)
+ throw new BufferOverflowException();
+
+ throw new ReadOnlyBufferException();
+ }
+
+ public override CharBuffer Put(string source, int startIndex, int length)
+ {
+ if (source is null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
+ if (startIndex < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(startIndex, ExceptionArgument.startIndex);
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(length, ExceptionArgument.length);
+ if (startIndex > source.Length - length) // Checks for int overflow
+ ThrowHelper.ThrowArgumentOutOfRange_IndexLengthString(startIndex, length);
+
+ throw new ReadOnlyBufferException();
+ }
+
+ public override CharBuffer Slice()
+ {
+ int length = Remaining;
+ // J2N NOTE: If the caller slices again, this will be more efficient than using CharSequenceAdapter around a string
+ // and will also index faster if the StringBuilder has more than one chunk.
+ char[] chars = new char[length];
+ sequence.CopyTo(position, chars, 0, length);
+ return new ReadOnlyCharArrayBuffer(length, chars, arrayOffset: 0);
+ }
+
+ public override CharBuffer Subsequence(int startIndex, int length)
+ {
+ if (startIndex < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(startIndex, ExceptionArgument.startIndex);
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRange_MustBeNonNegative(length, ExceptionArgument.length);
+ if (startIndex > Remaining - length) // Checks for int overflow
+ ThrowHelper.ThrowArgumentOutOfRange_IndexLengthString(startIndex, length);
+
+ StringBuilderAdapter result = Copy(this);
+ result.position = position + startIndex;
+ result.limit = position + startIndex + length;
+ return result;
+ }
+ }
+}
diff --git a/src/J2N/MemoryExtensions.cs b/src/J2N/MemoryExtensions.cs
index 79264001..0a397946 100644
--- a/src/J2N/MemoryExtensions.cs
+++ b/src/J2N/MemoryExtensions.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -428,5 +429,35 @@ internal unsafe static void ReverseText(char* text, int count)
}
#endregion ReverseText
+
+ #region TryGetReference
+
+ ///
+ /// Sets the supplied to the underlying or
+ /// of this . This allows use of as a field
+ /// of a struct or class without having the underlying or go out of scope.
+ ///
+ /// This .
+ /// When this method returns successfully, the refernce will be set by ref to the
+ /// underlying or of .
+ /// true if the underlying reference could be retrieved; otherwise, false.
+ /// Note that if the underlying memory is not a or ,
+ /// this method will always return false.
+ internal static bool TryGetReference(this ReadOnlyMemory text, [MaybeNullWhen(false)] ref object? reference)
+ {
+ if (MemoryMarshal.TryGetString(text, out string? stringValue, out _, out _) && stringValue is not null)
+ {
+ reference = stringValue;
+ return true;
+ }
+ else if (MemoryMarshal.TryGetArray(text, out ArraySegment arraySegment) && arraySegment.Array is not null)
+ {
+ reference = arraySegment.Array;
+ return true;
+ }
+ return false;
+ }
+
+ #endregion
}
}
diff --git a/tests/NUnit/J2N.Tests/IO/TestByteBuffer.cs b/tests/NUnit/J2N.Tests/IO/TestByteBuffer.cs
index 6135834d..af7a66da 100644
--- a/tests/NUnit/J2N.Tests/IO/TestByteBuffer.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestByteBuffer.cs
@@ -377,6 +377,42 @@ public virtual void TestGet()
}
}
+ /*
+ * Class under test for ByteBuffer Get(Span)
+ */
+ [Test]
+ public virtual void TestGetbyteSpan() // J2N specific
+ {
+ Span array = new byte[1];
+ buf.Clear();
+ for (int i = 0; i < buf.Capacity; i++)
+ {
+ assertEquals(buf.Position, i);
+ ByteBuffer ret = buf.Get(array);
+ assertEquals(array[0], buf.Get(i));
+ assertSame(ret, buf);
+ }
+ try
+ {
+ buf.Get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (BufferUnderflowException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Get((byte[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
/*
* Class under test for java.nio.ByteBuffer get(byte[])
*/
@@ -669,6 +705,57 @@ public virtual void TestPutbyte()
}
}
+ /*
+ * Class under test for ByteBuffer Put(ReadOnlySpan)
+ */
+ [Test]
+ public virtual void TestPutbyteSpan() // J2N specific
+ {
+ Span array = new byte[1];
+ if (buf.IsReadOnly)
+ {
+ try
+ {
+ buf.Put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ReadOnlyBufferException e)
+ {
+ // expected
+ }
+ return;
+ }
+
+ buf.Clear();
+ for (int i = 0; i < buf.Capacity; i++)
+ {
+ assertEquals(buf.Position, i);
+ array[0] = (byte)i;
+ ByteBuffer ret = buf.Put(array);
+ assertEquals(buf.Get(i), (byte)i);
+ assertSame(ret, buf);
+ }
+ try
+ {
+ buf.Put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (BufferOverflowException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Put((byte[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
/*
* Class under test for java.nio.ByteBuffer put(byte[])
*/
diff --git a/tests/NUnit/J2N.Tests/IO/TestByteBuffer2.cs b/tests/NUnit/J2N.Tests/IO/TestByteBuffer2.cs
index 28c21b08..60723d97 100644
--- a/tests/NUnit/J2N.Tests/IO/TestByteBuffer2.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestByteBuffer2.cs
@@ -51,6 +51,15 @@ private static void bulkGet(ByteBuffer b)
ck(b, (long)a[i + 7], (long)((byte)Ic(i)));
}
+ private static void bulkGetSpan(ByteBuffer b) // J2N specific
+ {
+ int n = b.Capacity;
+ Span a = new byte[n + 7];
+ b.Get(a.Slice(7, n));
+ for (int i = 0; i < n; i++)
+ ck(b, (long)a[i + 7], (long)((byte)Ic(i)));
+ }
+
private static void relPut(ByteBuffer b)
{
int n = b.Capacity;
@@ -81,6 +90,17 @@ private static void bulkPutArray(ByteBuffer b)
b.Flip();
}
+ private static void bulkPutSpan(ByteBuffer b) // J2N specific
+ {
+ int n = b.Capacity;
+ b.Clear();
+ Span a = new byte[n + 7];
+ for (int i = 0; i < n; i++)
+ a[i + 7] = (byte)Ic(i);
+ b.Put(a.Slice(7, n));
+ b.Flip();
+ }
+
private static void bulkPutBuffer(ByteBuffer b)
{
int n = b.Capacity;
@@ -312,9 +332,22 @@ public static void test(int level, ByteBuffer b, bool direct)
absGet(b);
bulkGet(b);
+ relPut(b); // J2N specific
+ relGet(b);
+ absGet(b);
+ bulkGetSpan(b);
+
+ absPut(b); // J2N specific
+ relGet(b);
+ absGet(b);
+ bulkGetSpan(b);
+
bulkPutArray(b);
relGet(b);
+ bulkPutSpan(b); // J2N specific
+ relGet(b);
+
bulkPutBuffer(b);
relGet(b);
@@ -538,6 +571,11 @@ public static void test(int level, ByteBuffer b, bool direct)
bulkPutArray(rb);
});
+ tryCatch(b, typeof(ReadOnlyBufferException), () =>
+ {
+ bulkPutSpan(rb); // J2N specific
+ });
+
tryCatch(b, typeof(ReadOnlyBufferException), () =>
{
bulkPutBuffer(rb);
diff --git a/tests/NUnit/J2N.Tests/IO/TestCharBuffer.cs b/tests/NUnit/J2N.Tests/IO/TestCharBuffer.cs
index bebf2707..e1631931 100644
--- a/tests/NUnit/J2N.Tests/IO/TestCharBuffer.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestCharBuffer.cs
@@ -42,7 +42,10 @@ public virtual void TestWrap()
string s = "A test string to test with.";
char[] ca = s.ToCharArray();
StringBuilder sb = new StringBuilder(s);
- ICharSequence cs = s.AsCharSequence();
+ ICharSequence scs = s.AsCharSequence();
+ ICharSequence sbcs = sb.AsCharSequence();
+ ICharSequence cacs = ca.AsCharSequence();
+ ICharSequence customcs = new MockCharSequence(s.AsMemory());
// Control - char[] was part of the original Java implementation
// and used length rather than end index. So we will check that our conversion
@@ -57,9 +60,52 @@ public virtual void TestWrap()
Assert.AreEqual(CharBuffer.Wrap(ca).Limit, CharBuffer.Wrap(sb).Limit);
Assert.AreEqual(CharBuffer.Wrap(ca, 6, 10).Limit, CharBuffer.Wrap(sb, 6, 10).Limit);
- // ICharSequence
- Assert.AreEqual(CharBuffer.Wrap(ca).Limit, CharBuffer.Wrap(cs).Limit);
- Assert.AreEqual(CharBuffer.Wrap(ca, 6, 10).Limit, CharBuffer.Wrap(cs, 6, 10).Limit);
+ // ICharSequence (string)
+ Assert.AreEqual(CharBuffer.Wrap(ca).Limit, CharBuffer.Wrap(scs).Limit);
+ Assert.AreEqual(CharBuffer.Wrap(ca, 6, 10).Limit, CharBuffer.Wrap(scs, 6, 10).Limit);
+
+ // ICharSequence (StringBuilder)
+ Assert.AreEqual(CharBuffer.Wrap(ca).Limit, CharBuffer.Wrap(sbcs).Limit);
+ Assert.AreEqual(CharBuffer.Wrap(ca, 6, 10).Limit, CharBuffer.Wrap(sbcs, 6, 10).Limit);
+
+ // ICharSequence (char[])
+ Assert.AreEqual(CharBuffer.Wrap(ca).Limit, CharBuffer.Wrap(cacs).Limit);
+ Assert.AreEqual(CharBuffer.Wrap(ca, 6, 10).Limit, CharBuffer.Wrap(cacs, 6, 10).Limit);
+
+ // ICharSequence (custom)
+ Assert.AreEqual(CharBuffer.Wrap(ca).Limit, CharBuffer.Wrap(customcs).Limit);
+ Assert.AreEqual(CharBuffer.Wrap(ca, 6, 10).Limit, CharBuffer.Wrap(customcs, 6, 10).Limit);
+ }
+
+ ///
+ /// A custom implementation used for testing unknown
+ /// implementations, since we generally optimize by using the underlying value of
+ /// , or
+ /// rather than the interface itself.
+ ///
+ private sealed class MockCharSequence : ICharSequence
+ {
+ private readonly ReadOnlyMemory value;
+ public MockCharSequence(ReadOnlyMemory value)
+ {
+ this.value = value;
+ }
+
+ public char this[int index] => value.Span[index];
+
+ public bool HasValue => true;
+
+ public int Length => value.Length;
+
+ public ICharSequence Subsequence(int startIndex, int length)
+ {
+ return new MockCharSequence(value.Slice(startIndex, length));
+ }
+
+ public override string ToString()
+ {
+ return value.ToString();
+ }
}
@@ -361,6 +407,32 @@ public virtual void TestGet()
}
}
+ /*
+ * Class under test for CharBuffer Get(Span)
+ */
+ [Test]
+ public virtual void TestGetcharSpan() // J2N specific
+ {
+ Span array = new char[1];
+ buf.Clear();
+ for (int i = 0; i < buf.Capacity; i++)
+ {
+ assertEquals(buf.Position, i);
+ CharBuffer ret = buf.Get(array);
+ assertEquals(array[0], buf.Get(i));
+ assertSame(ret, buf);
+ }
+ try
+ {
+ buf.Get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (BufferUnderflowException e)
+ {
+ // expected
+ }
+ }
+
/*
* Class under test for java.nio.CharBuffer get(char[])
*/
@@ -385,6 +457,15 @@ public virtual void TestGetcharArray()
{
// expected
}
+ try // J2N: Added check for guard clause
+ {
+ buf.Get((char[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ArgumentNullException e)
+ {
+ // expected
+ }
}
/*
@@ -550,6 +631,44 @@ public virtual void TestPutchar()
}
}
+ /*
+ * Class under test for CharBuffer Put(ReadOnlySpan)
+ */
+ [Test]
+ public virtual void TestPutcharSpan() // J2N specific
+ {
+ Span array = new char[1];
+
+ buf.Clear();
+ for (int i = 0; i < buf.Capacity; i++)
+ {
+ assertEquals(buf.Position, i);
+ array[0] = (char)i;
+ CharBuffer ret = buf.Put(array);
+ assertEquals(buf.Get(i), (char)i);
+ assertSame(ret, buf);
+ }
+ try
+ {
+ buf.Put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (BufferOverflowException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Put((char[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
/*
* Class under test for java.nio.CharBuffer put(char[])
*/
diff --git a/tests/NUnit/J2N.Tests/IO/TestCharBuffer2.cs b/tests/NUnit/J2N.Tests/IO/TestCharBuffer2.cs
index ab78a043..8e55ad0c 100644
--- a/tests/NUnit/J2N.Tests/IO/TestCharBuffer2.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestCharBuffer2.cs
@@ -54,6 +54,15 @@ private static void bulkGet(CharBuffer b)
ck(b, (long)a[i + 7], (long)((char)Ic(i)));
}
+ private static void bulkGetSpan(CharBuffer b) // J2N specific
+ {
+ int n = b.Capacity;
+ Span a = new char[n + 7];
+ b.Get(a.Slice(7, n));
+ for (int i = 0; i < n; i++)
+ ck(b, (long)a[i + 7], (long)((char)Ic(i)));
+ }
+
private static void relPut(CharBuffer b)
{
int n = b.Capacity;
@@ -84,6 +93,17 @@ private static void bulkPutArray(CharBuffer b)
b.Flip();
}
+ private static void bulkPutSpan(CharBuffer b) // J2N specific
+ {
+ int n = b.Capacity;
+ b.Clear();
+ Span a = new char[n + 7];
+ for (int i = 0; i < n; i++)
+ a[i + 7] = (char)Ic(i);
+ b.Put(a.Slice(7, n));
+ b.Flip();
+ }
+
private static void bulkPutBuffer(CharBuffer b)
{
int n = b.Capacity;
@@ -210,9 +230,22 @@ public static void test(int level, CharBuffer b, bool direct)
absGet(b);
bulkGet(b);
+ relPut(b); // J2N specific
+ relGet(b);
+ absGet(b);
+ bulkGetSpan(b);
+
+ absPut(b); // J2N specific
+ relGet(b);
+ absGet(b);
+ bulkGetSpan(b);
+
bulkPutArray(b);
relGet(b);
+ bulkPutSpan(b); // J2N specific
+ relGet(b);
+
bulkPutBuffer(b);
relGet(b);
@@ -433,6 +466,11 @@ public static void test(int level, CharBuffer b, bool direct)
bulkPutArray(rb);
});
+ tryCatch(b, typeof(ReadOnlyBufferException), () =>
+ {
+ bulkPutSpan(rb); // J2N specific
+ });
+
tryCatch(b, typeof(ReadOnlyBufferException), () =>
{
bulkPutBuffer(rb);
diff --git a/tests/NUnit/J2N.Tests/IO/TestDoubleBuffer.cs b/tests/NUnit/J2N.Tests/IO/TestDoubleBuffer.cs
index 0e5229b5..b96b0d43 100644
--- a/tests/NUnit/J2N.Tests/IO/TestDoubleBuffer.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestDoubleBuffer.cs
@@ -303,6 +303,32 @@ public virtual void TestGet()
}
}
+ /*
+ * Class under test for DoubleBuffer Get(Span)
+ */
+ [Test]
+ public virtual void TestGetdoubleSpan() // J2N specific
+ {
+ Span array = new double[1];
+ buf.Clear();
+ for (int i = 0; i < buf.Capacity; i++)
+ {
+ assertEquals(buf.Position, i);
+ DoubleBuffer ret = buf.Get(array);
+ assertEquals(array[0], buf.Get(i), 0.01);
+ assertSame(ret, buf);
+ }
+ try
+ {
+ buf.Get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (BufferUnderflowException e)
+ {
+ // expected
+ }
+ }
+
/*
* Class under test for java.nio.DoubleBuffer get(double[])
*/
@@ -327,6 +353,15 @@ public virtual void TestGetdoubleArray()
{
// expected
}
+ try // J2N: Added check for guard clause
+ {
+ buf.Get((double[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ArgumentNullException e)
+ {
+ // expected
+ }
}
/*
@@ -511,6 +546,44 @@ public virtual void TestPutdouble()
}
}
+ /*
+ * Class under test for DoubleBuffer Put(ReadOnlySpan)
+ */
+ [Test]
+ public virtual void TestPutdoubleSpan() // J2N specific
+ {
+ Span array = new double[1];
+
+ buf.Clear();
+ for (int i = 0; i < buf.Capacity; i++)
+ {
+ assertEquals(buf.Position, i);
+ array[0] = (double)i;
+ DoubleBuffer ret = buf.Put(array);
+ assertEquals(buf.Get(i), (double)i, 0.0);
+ assertSame(ret, buf);
+ }
+ try
+ {
+ buf.Put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (BufferOverflowException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Put((double[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
/*
* Class under test for java.nio.DoubleBuffer put(double[])
*/
@@ -537,6 +610,15 @@ public virtual void TestPutdoubleArray()
{
// expected
}
+ try
+ {
+ buf.Put((double[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ArgumentNullException e)
+ {
+ // expected
+ }
}
/*
diff --git a/tests/NUnit/J2N.Tests/IO/TestDoubleBuffer2.cs b/tests/NUnit/J2N.Tests/IO/TestDoubleBuffer2.cs
index 9770e629..6dde204c 100644
--- a/tests/NUnit/J2N.Tests/IO/TestDoubleBuffer2.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestDoubleBuffer2.cs
@@ -57,6 +57,15 @@ private static void bulkGet(DoubleBuffer b)
ck(b, (long)a[i + 7], (long)((double)Ic(i)));
}
+ private static void bulkGetSpan(DoubleBuffer b) // J2N specific
+ {
+ int n = b.Capacity;
+ Span a = new double[n + 7];
+ b.Get(a.Slice(7, n));
+ for (int i = 0; i < n; i++)
+ ck(b, (long)a[i + 7], (long)((double)Ic(i)));
+ }
+
private static void relPut(DoubleBuffer b)
{
int n = b.Capacity;
@@ -87,6 +96,17 @@ private static void bulkPutArray(DoubleBuffer b)
b.Flip();
}
+ private static void bulkPutSpan(DoubleBuffer b) // J2N specific
+ {
+ int n = b.Capacity;
+ b.Clear();
+ Span a = new double[n + 7];
+ for (int i = 0; i < n; i++)
+ a[i + 7] = (double)Ic(i);
+ b.Put(a.Slice(7, n));
+ b.Flip();
+ }
+
private static void bulkPutBuffer(DoubleBuffer b)
{
int n = b.Capacity;
@@ -201,9 +221,22 @@ public static void test(int level, DoubleBuffer b, bool direct)
absGet(b);
bulkGet(b);
+ relPut(b); // J2N specific
+ relGet(b);
+ absGet(b);
+ bulkGetSpan(b);
+
+ absPut(b); // J2N specific
+ relGet(b);
+ absGet(b);
+ bulkGetSpan(b);
+
bulkPutArray(b);
relGet(b);
+ bulkPutSpan(b); // J2N specific
+ relGet(b);
+
bulkPutBuffer(b);
relGet(b);
@@ -415,6 +448,11 @@ public static void test(int level, DoubleBuffer b, bool direct)
bulkPutArray(rb);
});
+ tryCatch(b, typeof(ReadOnlyBufferException), () =>
+ {
+ bulkPutSpan(rb); // J2N specific
+ });
+
tryCatch(b, typeof(ReadOnlyBufferException), () =>
{
bulkPutBuffer(rb);
diff --git a/tests/NUnit/J2N.Tests/IO/TestInt16Buffer.cs b/tests/NUnit/J2N.Tests/IO/TestInt16Buffer.cs
index cc752e44..1b74d714 100644
--- a/tests/NUnit/J2N.Tests/IO/TestInt16Buffer.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestInt16Buffer.cs
@@ -269,6 +269,41 @@ public virtual void TestGet()
}
}
+ /*
+ * Class under test for Int16Buffer Get(Span)
+ */
+ public virtual void TestGetshortSpan() // J2N specific
+ {
+ Span array = new short[1];
+ buf.Clear();
+ for (int i = 0; i < buf.Capacity; i++)
+ {
+ assertEquals(buf.Position, i);
+ Int16Buffer ret = buf.Get(array);
+ assertEquals(array[0], buf.Get(i));
+ assertSame(ret, buf);
+ }
+ try
+ {
+ buf.Get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (BufferUnderflowException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Get((short[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
/*
* Class under test for java.nio.Int16Buffer get(short[])
*/
@@ -292,6 +327,15 @@ public virtual void TestGetshortArray()
{
// expected
}
+ try // J2N: Added check for guard clause
+ {
+ buf.Get((short[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ArgumentNullException e)
+ {
+ // expected
+ }
}
/*
@@ -467,6 +511,44 @@ public virtual void TestPutshort()
}
}
+ /*
+ * Class under test for Int16Buffer Put(ReadOnlySpan)
+ */
+ [Test]
+ public virtual void TestPutshortSpan() // J2N specific
+ {
+ Span array = new short[1];
+ buf.Clear();
+ for (int i = 0; i < buf.Capacity; i++)
+ {
+ assertEquals(buf.Position, i);
+ array[0] = (short)i;
+ Int16Buffer ret = buf.Put(array);
+ assertEquals(buf.Get(i), (short)i);
+ assertSame(ret, buf);
+ }
+ try
+ {
+ buf.Put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (BufferOverflowException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Position = (buf.Limit);
+ // buf.Put((short[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
/*
* Class under test for java.nio.Int16Buffer put(short[])
*/
diff --git a/tests/NUnit/J2N.Tests/IO/TestInt16Buffer2.cs b/tests/NUnit/J2N.Tests/IO/TestInt16Buffer2.cs
index afa9b1d2..c05473ee 100644
--- a/tests/NUnit/J2N.Tests/IO/TestInt16Buffer2.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestInt16Buffer2.cs
@@ -53,6 +53,15 @@ private static void bulkGet(Int16Buffer b)
ck(b, (long)a[i + 7], (long)((short)Ic(i)));
}
+ private static void bulkGetSpan(Int16Buffer b) // J2N specific
+ {
+ int n = b.Capacity;
+ Span a = new short[n + 7];
+ b.Get(a.Slice(7, n));
+ for (int i = 0; i < n; i++)
+ ck(b, (long)a[i + 7], (long)((short)Ic(i)));
+ }
+
private static void relPut(Int16Buffer b)
{
int n = b.Capacity;
@@ -83,6 +92,17 @@ private static void bulkPutArray(Int16Buffer b)
b.Flip();
}
+ private static void bulkPutSpan(Int16Buffer b) // J2N specific
+ {
+ int n = b.Capacity;
+ b.Clear();
+ Span a = new short[n + 7];
+ for (int i = 0; i < n; i++)
+ a[i + 7] = (short)Ic(i);
+ b.Put(a.Slice(7, n));
+ b.Flip();
+ }
+
private static void bulkPutBuffer(Int16Buffer b)
{
int n = b.Capacity;
@@ -196,9 +216,22 @@ public static void test(int level, Int16Buffer b, bool direct)
absGet(b);
bulkGet(b);
+ relPut(b); // J2N specific
+ relGet(b);
+ absGet(b);
+ bulkGetSpan(b);
+
+ absPut(b); // J2N specific
+ relGet(b);
+ absGet(b);
+ bulkGetSpan(b);
+
bulkPutArray(b);
relGet(b);
+ bulkPutSpan(b); // J2N specific
+ relGet(b);
+
bulkPutBuffer(b);
relGet(b);
@@ -391,6 +424,11 @@ public static void test(int level, Int16Buffer b, bool direct)
bulkPutArray(rb);
});
+ tryCatch(b, typeof(ReadOnlyBufferException), () =>
+ {
+ bulkPutSpan(rb); // J2N specific
+ });
+
tryCatch(b, typeof(ReadOnlyBufferException), () =>
{
bulkPutBuffer(rb);
diff --git a/tests/NUnit/J2N.Tests/IO/TestInt32Buffer.cs b/tests/NUnit/J2N.Tests/IO/TestInt32Buffer.cs
index d32f4945..4bfc9a32 100644
--- a/tests/NUnit/J2N.Tests/IO/TestInt32Buffer.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestInt32Buffer.cs
@@ -267,6 +267,42 @@ public virtual void TestGet()
}
}
+ /*
+ * Class under test for Int32Buffer Get(Span)
+ */
+ [Test]
+ public virtual void TestGetintSpan() // J2N specific
+ {
+ Span array = new int[1];
+ buf.Clear();
+ for (int i = 0; i < buf.Capacity; i++)
+ {
+ assertEquals(buf.Position, i);
+ Int32Buffer ret = buf.Get(array);
+ assertEquals(array[0], buf.Get(i));
+ assertSame(ret, buf);
+ }
+ try
+ {
+ buf.Get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (BufferUnderflowException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Get((int[])null);
+ // fail("Should throw NPE"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
/*
* Class under test for java.nio.Int32Buffer get(int[])
*/
@@ -484,6 +520,44 @@ public virtual void TestPutint()
}
}
+ /*
+ * Class under test for Int32Buffer Put(ReadOnlySpan)
+ */
+ [Test]
+ public virtual void TestPutintSpan() // J2N specific
+ {
+ Span array = new int[1];
+ buf.Clear();
+ for (int i = 0; i < buf.Capacity; i++)
+ {
+ assertEquals(buf.Position, i);
+ array[0] = (int)i;
+ Int32Buffer ret = buf.Put(array);
+ assertEquals(buf.Get(i), (int)i);
+ assertSame(ret, buf);
+ }
+ try
+ {
+ buf.Put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (BufferOverflowException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Position = (buf.Limit);
+ // buf.Put((int[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
/*
* Class under test for java.nio.Int32Buffer put(int[])
*/
diff --git a/tests/NUnit/J2N.Tests/IO/TestInt32Buffer2.cs b/tests/NUnit/J2N.Tests/IO/TestInt32Buffer2.cs
index e4cbdc4c..560733f0 100644
--- a/tests/NUnit/J2N.Tests/IO/TestInt32Buffer2.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestInt32Buffer2.cs
@@ -54,6 +54,15 @@ private static void bulkGet(Int32Buffer b)
ck(b, (long)a[i + 7], (long)((int)Ic(i)));
}
+ private static void bulkGetSpan(Int32Buffer b) // J2N specific
+ {
+ int n = b.Capacity;
+ Span a = new int[n + 7];
+ b.Get(a.Slice(7, n));
+ for (int i = 0; i < n; i++)
+ ck(b, (long)a[i + 7], (long)((int)Ic(i)));
+ }
+
private static void relPut(Int32Buffer b)
{
int n = b.Capacity;
@@ -84,6 +93,17 @@ private static void bulkPutArray(Int32Buffer b)
b.Flip();
}
+ private static void bulkPutSpan(Int32Buffer b) // J2N specific
+ {
+ int n = b.Capacity;
+ b.Clear();
+ Span a = new int[n + 7];
+ for (int i = 0; i < n; i++)
+ a[i + 7] = (int)Ic(i);
+ b.Put(a.Slice(7, n));
+ b.Flip();
+ }
+
private static void bulkPutBuffer(Int32Buffer b)
{
int n = b.Capacity;
@@ -200,9 +220,22 @@ public static void test(int level, Int32Buffer b, bool direct)
absGet(b);
bulkGet(b);
+ relPut(b); // J2N specific
+ relGet(b);
+ absGet(b);
+ bulkGetSpan(b);
+
+ absPut(b); // J2N specific
+ relGet(b);
+ absGet(b);
+ bulkGetSpan(b);
+
bulkPutArray(b);
relGet(b);
+ bulkPutSpan(b); // J2N specific
+ relGet(b);
+
bulkPutBuffer(b);
relGet(b);
@@ -396,6 +429,11 @@ public static void test(int level, Int32Buffer b, bool direct)
bulkPutArray(rb);
});
+ tryCatch(b, typeof(ReadOnlyBufferException), () =>
+ {
+ bulkPutSpan(rb); // J2N specific
+ });
+
tryCatch(b, typeof(ReadOnlyBufferException), () =>
{
bulkPutBuffer(rb);
diff --git a/tests/NUnit/J2N.Tests/IO/TestInt64Buffer.cs b/tests/NUnit/J2N.Tests/IO/TestInt64Buffer.cs
index b38dc9f2..bba272f1 100644
--- a/tests/NUnit/J2N.Tests/IO/TestInt64Buffer.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestInt64Buffer.cs
@@ -269,6 +269,43 @@ public virtual void TestGet()
}
}
+ /*
+ * Class under test for Int64Buffer Get(Span)
+ */
+ [Test]
+ public virtual void TestGetlongSpan() // J2N specific
+ {
+ Span array = new long[1];
+ buf.Clear();
+ for (int i = 0; i < buf.Capacity; i++)
+ {
+ assertEquals(buf.Position, i);
+ Int64Buffer ret = buf.Get(array);
+ assertEquals(array[0], buf.Get(i));
+ assertSame(ret, buf);
+ }
+ try
+ {
+ buf.Get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (BufferUnderflowException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Position = (buf.Limit);
+ // buf.Get((long[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
/*
* Class under test for java.nio.Int64Buffer get(long[])
*/
@@ -487,6 +524,44 @@ public virtual void TestPutlong()
}
}
+ /*
+ * Class under test for Int64Buffer Put(ReadOnlySpan)
+ */
+ [Test]
+ public virtual void TestPutlongSpan() // J2N specific
+ {
+ Span array = new long[1];
+ buf.Clear();
+ for (int i = 0; i < buf.Capacity; i++)
+ {
+ assertEquals(buf.Position, i);
+ array[0] = (long)i;
+ Int64Buffer ret = buf.Put(array);
+ assertEquals(buf.Get(i), (long)i);
+ assertSame(ret, buf);
+ }
+ try
+ {
+ buf.Put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (BufferOverflowException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Position = (buf.Limit);
+ // buf.Put((long[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
/*
* Class under test for java.nio.Int64Buffer put(long[])
*/
diff --git a/tests/NUnit/J2N.Tests/IO/TestInt64Buffer2.cs b/tests/NUnit/J2N.Tests/IO/TestInt64Buffer2.cs
index 9c226afc..253644ec 100644
--- a/tests/NUnit/J2N.Tests/IO/TestInt64Buffer2.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestInt64Buffer2.cs
@@ -53,6 +53,15 @@ private static void bulkGet(Int64Buffer b)
ck(b, (long)a[i + 7], (long)((long)Ic(i)));
}
+ private static void bulkGetSpan(Int64Buffer b) // J2N specific
+ {
+ int n = b.Capacity;
+ Span a = new long[n + 7];
+ b.Get(a.Slice(7, n));
+ for (int i = 0; i < n; i++)
+ ck(b, (long)a[i + 7], (long)((long)Ic(i)));
+ }
+
private static void relPut(Int64Buffer b)
{
int n = b.Capacity;
@@ -83,6 +92,17 @@ private static void bulkPutArray(Int64Buffer b)
b.Flip();
}
+ private static void bulkPutSpan(Int64Buffer b) // J2N specific
+ {
+ int n = b.Capacity;
+ b.Clear();
+ Span a = new long[n + 7];
+ for (int i = 0; i < n; i++)
+ a[i + 7] = (long)Ic(i);
+ b.Put(a.Slice(7, n));
+ b.Flip();
+ }
+
private static void bulkPutBuffer(Int64Buffer b)
{
int n = b.Capacity;
@@ -199,9 +219,22 @@ public static void test(int level, Int64Buffer b, bool direct)
absGet(b);
bulkGet(b);
+ relPut(b); // J2N specific
+ relGet(b);
+ absGet(b);
+ bulkGetSpan(b);
+
+ absPut(b); // J2N specific
+ relGet(b);
+ absGet(b);
+ bulkGetSpan(b);
+
bulkPutArray(b);
relGet(b);
+ bulkPutSpan(b); // J2N specific
+ relGet(b);
+
bulkPutBuffer(b);
relGet(b);
@@ -398,6 +431,11 @@ public static void test(int level, Int64Buffer b, bool direct)
bulkPutArray(rb);
});
+ tryCatch(b, typeof(ReadOnlyBufferException), () =>
+ {
+ bulkPutSpan(rb); // J2N specific
+ });
+
tryCatch(b, typeof(ReadOnlyBufferException), () =>
{
bulkPutBuffer(rb);
diff --git a/tests/NUnit/J2N.Tests/IO/TestReadOnlyCharBuffer.cs b/tests/NUnit/J2N.Tests/IO/TestReadOnlyCharBuffer.cs
index 24de0b6b..19dc2719 100644
--- a/tests/NUnit/J2N.Tests/IO/TestReadOnlyCharBuffer.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestReadOnlyCharBuffer.cs
@@ -93,6 +93,31 @@ public override void TestPutchar()
}
}
+ [Test]
+ public override void TestPutcharSpan() // J2N specific
+ {
+ Span array = new char[1];
+ try
+ {
+ buf.Put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ReadOnlyBufferException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Put((char[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
[Test]
public override void TestPutcharArray()
{
diff --git a/tests/NUnit/J2N.Tests/IO/TestReadOnlyDoubleBuffer.cs b/tests/NUnit/J2N.Tests/IO/TestReadOnlyDoubleBuffer.cs
index 8f1e527f..95bb6754 100644
--- a/tests/NUnit/J2N.Tests/IO/TestReadOnlyDoubleBuffer.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestReadOnlyDoubleBuffer.cs
@@ -90,6 +90,31 @@ public override void TestPutdouble()
}
}
+ [Test]
+ public override void TestPutdoubleSpan() // J2N specific
+ {
+ Span array = new double[1];
+ try
+ {
+ buf.Put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ReadOnlyBufferException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Put((double[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
[Test]
public override void TestPutdoubleArray()
{
diff --git a/tests/NUnit/J2N.Tests/IO/TestReadOnlyInt16Buffer.cs b/tests/NUnit/J2N.Tests/IO/TestReadOnlyInt16Buffer.cs
index 5de6090f..0c449880 100644
--- a/tests/NUnit/J2N.Tests/IO/TestReadOnlyInt16Buffer.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestReadOnlyInt16Buffer.cs
@@ -92,6 +92,31 @@ public override void TestPutshort()
}
}
+ [Test]
+ public override void TestPutshortSpan() // J2N specific
+ {
+ Span array = new short[1];
+ try
+ {
+ buf.Put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ReadOnlyBufferException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Put((short[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
[Test]
public override void TestPutshortArray()
{
diff --git a/tests/NUnit/J2N.Tests/IO/TestReadOnlyInt32Buffer.cs b/tests/NUnit/J2N.Tests/IO/TestReadOnlyInt32Buffer.cs
index da7ee1c9..86c53034 100644
--- a/tests/NUnit/J2N.Tests/IO/TestReadOnlyInt32Buffer.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestReadOnlyInt32Buffer.cs
@@ -92,6 +92,31 @@ public override void TestPutint()
}
}
+ [Test]
+ public override void TestPutintSpan() // J2N specific
+ {
+ Span array = new int[1];
+ try
+ {
+ buf.Put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ReadOnlyBufferException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Put((int[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
[Test]
public override void TestPutintArray()
{
diff --git a/tests/NUnit/J2N.Tests/IO/TestReadOnlyInt64Buffer.cs b/tests/NUnit/J2N.Tests/IO/TestReadOnlyInt64Buffer.cs
index 6a81e9d9..95ab9757 100644
--- a/tests/NUnit/J2N.Tests/IO/TestReadOnlyInt64Buffer.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestReadOnlyInt64Buffer.cs
@@ -92,6 +92,31 @@ public override void TestPutlong()
}
}
+ [Test]
+ public override void TestPutlongSpan() // J2N specific
+ {
+ Span array = new long[1];
+ try
+ {
+ buf.Put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ReadOnlyBufferException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Put((long[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
[Test]
public override void TestPutlongArray()
{
diff --git a/tests/NUnit/J2N.Tests/IO/TestReadOnlySingleBuffer.cs b/tests/NUnit/J2N.Tests/IO/TestReadOnlySingleBuffer.cs
index aa7fea94..0fe85486 100644
--- a/tests/NUnit/J2N.Tests/IO/TestReadOnlySingleBuffer.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestReadOnlySingleBuffer.cs
@@ -92,6 +92,31 @@ public override void TestPutfloat()
}
}
+ [Test]
+ public override void TestPutfloatSpan() // J2N specific
+ {
+ Span array = new float[1];
+ try
+ {
+ buf.Put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ReadOnlyBufferException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Put((float[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
[Test]
public override void TestPutfloatArray()
{
diff --git a/tests/NUnit/J2N.Tests/IO/TestSingleBuffer.cs b/tests/NUnit/J2N.Tests/IO/TestSingleBuffer.cs
index ab33bff7..d876defa 100644
--- a/tests/NUnit/J2N.Tests/IO/TestSingleBuffer.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestSingleBuffer.cs
@@ -292,6 +292,44 @@ public virtual void TestGet()
}
}
+ /*
+ * Class under test for SingleBuffer Get(Span)
+ */
+ [Test]
+ public virtual void TestGetfloatSpan() // J2N specific
+ {
+ Span array = new float[1];
+ buf.Clear();
+ for (int i = 0; i < buf.Capacity; i++)
+ {
+ assertEquals(buf.Position, i);
+ SingleBuffer ret = buf.Get(array);
+ assertEquals(array[0], buf.Get(i), 0.01);
+ assertSame(ret, buf);
+ }
+ try
+ {
+ buf.Get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (BufferUnderflowException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Position = (buf.Limit);
+ // buf.Get((float[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ buf.Get(new float[0].AsSpan());
+ }
+
/*
* Class under test for java.nio.SingleBuffer get(float[])
*/
@@ -514,6 +552,44 @@ public virtual void TestPutfloat()
}
}
+ /*
+ * Class under test for SingleBuffer Put(ReadOnlySpan)
+ */
+ [Test]
+ public virtual void TestPutfloatSpan() // J2N specific
+ {
+ Span array = new float[1];
+ buf.Clear();
+ for (int i = 0; i < buf.Capacity; i++)
+ {
+ assertEquals(buf.Position, i);
+ array[0] = (float)i;
+ SingleBuffer ret = buf.Put(array);
+ assertEquals(buf.Get(i), (float)i, 0.0);
+ assertSame(ret, buf);
+ }
+ try
+ {
+ buf.Put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (BufferOverflowException e)
+ {
+ // expected
+ }
+ // J2N: Null converts to empty span, should not throw
+ //try
+ //{
+ // buf.Position = (buf.Limit);
+ // buf.Put((float[])null);
+ // fail("Should throw Exception"); //$NON-NLS-1$
+ //}
+ //catch (ArgumentNullException e)
+ //{
+ // // expected
+ //}
+ }
+
/*
* Class under test for java.nio.SingleBuffer put(float[])
*/
diff --git a/tests/NUnit/J2N.Tests/IO/TestSingleBuffer2.cs b/tests/NUnit/J2N.Tests/IO/TestSingleBuffer2.cs
index 756dfc23..ea2f1604 100644
--- a/tests/NUnit/J2N.Tests/IO/TestSingleBuffer2.cs
+++ b/tests/NUnit/J2N.Tests/IO/TestSingleBuffer2.cs
@@ -58,6 +58,15 @@ private static void bulkGet(SingleBuffer b)
ck(b, (long)a[i + 7], (long)((float)Ic(i)));
}
+ private static void bulkGetSpan(SingleBuffer b) // J2N specific
+ {
+ int n = b.Capacity;
+ Span a = new float[n + 7];
+ b.Get(a.Slice(7, n));
+ for (int i = 0; i < n; i++)
+ ck(b, (long)a[i + 7], (long)((float)Ic(i)));
+ }
+
private static void relPut(SingleBuffer b)
{
int n = b.Capacity;
@@ -88,6 +97,17 @@ private static void bulkPutArray(SingleBuffer b)
b.Flip();
}
+ private static void bulkPutSpan(SingleBuffer b) // J2N specific
+ {
+ int n = b.Capacity;
+ b.Clear();
+ Span a = new float[n + 7];
+ for (int i = 0; i < n; i++)
+ a[i + 7] = (float)Ic(i);
+ b.Put(a.Slice(7, n));
+ b.Flip();
+ }
+
private static void bulkPutBuffer(SingleBuffer b)
{
int n = b.Capacity;
@@ -203,9 +223,22 @@ public static void test(int level, SingleBuffer b, bool direct)
absGet(b);
bulkGet(b);
+ relPut(b); // J2N specific
+ relGet(b);
+ absGet(b);
+ bulkGetSpan(b);
+
+ absPut(b); // J2N specific
+ relGet(b);
+ absGet(b);
+ bulkGetSpan(b);
+
bulkPutArray(b);
relGet(b);
+ bulkPutSpan(b); // J2N specific
+ relGet(b);
+
bulkPutBuffer(b);
relGet(b);
@@ -421,6 +454,11 @@ public static void test(int level, SingleBuffer b, bool direct)
bulkPutArray(rb);
});
+ tryCatch(b, typeof(ReadOnlyBufferException), () =>
+ {
+ bulkPutSpan(rb); // J2N specific
+ });
+
tryCatch(b, typeof(ReadOnlyBufferException), () =>
{
bulkPutBuffer(rb);
diff --git a/tests/NUnit/J2N.Tests/IO/TestWrappedCharBuffer3.cs b/tests/NUnit/J2N.Tests/IO/TestWrappedCharBuffer3.cs
new file mode 100644
index 00000000..301c0953
--- /dev/null
+++ b/tests/NUnit/J2N.Tests/IO/TestWrappedCharBuffer3.cs
@@ -0,0 +1,165 @@
+using NUnit.Framework;
+using System;
+using System.Text;
+
+namespace J2N.IO
+{
+ internal class TestWrappedCharBuffer3 : TestReadOnlyCharBuffer
+ {
+ protected static readonly StringBuilder TEST_STRINGBUILDER = new StringBuilder("123456789abcdef12345");
+
+ public override void SetUp()
+ {
+ base.SetUp();
+ buf = CharBuffer.Wrap(TEST_STRINGBUILDER);
+ baseBuf = buf;
+ }
+
+ public override void TearDown()
+ {
+ base.TearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ [Test]
+ public void TestWrappedCharSequence_IllegalArg()
+ {
+ StringBuilder str = TEST_STRINGBUILDER;
+ try
+ {
+ CharBuffer.Wrap(str, -1, 0 - -1); // J2N: Corrected 3rd parameter
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ArgumentOutOfRangeException e)
+ {
+ // expected
+ }
+ try
+ {
+ CharBuffer.Wrap(str, 21, 21 - 21); // J2N: Corrected 3rd parameter
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ArgumentOutOfRangeException e)
+ {
+ // expected
+ }
+ try
+ {
+ CharBuffer.Wrap(str, 2, 1 - 2); // J2N: Corrected 3rd parameter
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ArgumentOutOfRangeException e)
+ {
+ // expected
+ }
+ try
+ {
+ CharBuffer.Wrap(str, 0, 21 - 0); // J2N: Corrected 3rd parameter
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ArgumentOutOfRangeException e)
+ {
+ // expected
+ }
+ try
+ {
+ CharBuffer.Wrap((String)null, -1, 21 - -1); // J2N: Corrected 3rd parameter
+ fail("Should throw Exception"); //$NON-NLS-1$
+ }
+ catch (ArgumentNullException e)
+ {
+ // expected
+ }
+ }
+
+ [Test]
+ public override void TestArray()
+ {
+ try
+ {
+ var _ = buf.Array;
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ }
+ catch (NotSupportedException e)
+ {
+ }
+ }
+
+ [Test]
+ public override void TestPutcharArrayintint()
+ {
+ char[] array = new char[1];
+ try
+ {
+ buf.Put(array, 0, array.Length - 0); // J2N: Corrected 3rd parameter
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ }
+ catch (ReadOnlyBufferException e)
+ {
+ // expected
+ }
+ try
+ {
+ buf.Put((char[])null, 0, 1 - 0); // J2N: Corrected 3rd parameter
+ fail("Should throw NullPointerException"); //$NON-NLS-1$
+ }
+ catch (ArgumentNullException e)
+ {
+ // expected
+ }
+ try
+ {
+ buf.Put(new char[buf.Capacity + 1], 0, (buf.Capacity + 1) - 0); // J2N: Corrected 3rd parameter
+ fail("Should throw BufferOverflowException"); //$NON-NLS-1$
+ }
+ catch (BufferOverflowException e)
+ {
+ // expected
+ }
+ try
+ {
+ buf.Put(array, -1, array.Length - -1); // J2N: Corrected 3rd parameter
+ fail("Should throw IndexOutOfBoundsException"); //$NON-NLS-1$
+ }
+ catch (ArgumentOutOfRangeException e)
+ {
+ // expected
+ }
+ }
+
+ [Test]
+ public override void TestPutCharBuffer()
+ {
+ CharBuffer other = CharBuffer.Allocate(1);
+ try
+ {
+ buf.Put(other);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ }
+ catch (ReadOnlyBufferException e)
+ {
+ // expected
+ }
+ try
+ {
+ buf.Put((CharBuffer)null);
+ fail("Should throw NullPointerException"); //$NON-NLS-1$
+ }
+ catch (ArgumentNullException e)
+ {
+ // expected
+ }
+ try
+ {
+ buf.Put(buf);
+ fail("Should throw IllegalArgumentException"); //$NON-NLS-1$
+ }
+ catch (ArgumentException e)
+ {
+ // expected
+ }
+ }
+
+ }
+}