Skip to content

Commit

Permalink
[C#]Change to ENABLE_SPAN_T that doesn't require UNSAFE_BYTEBUFFER. (#…
Browse files Browse the repository at this point in the history
…6073)

* ENABLE_SPAN_T doesn't require UNSAFE_BYTEBUFFER.

Change to ENABLE_SPAN_T that doesn't require UNSAFE_BYTEBUFFER.

* Selectable framework.

Changed target framework to allow selection of 2.0 or 2.1 (or higher)

* Added target framework version check.

* Add core test project.

* Added run on .Net Core.
  • Loading branch information
harujoh authored Sep 23, 2020
1 parent ab139d6 commit e0bbaa6
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 43 deletions.
111 changes: 69 additions & 42 deletions net/FlatBuffers/ByteBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,15 @@
using System.Runtime.InteropServices;
using System.Text;

#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
using System.Buffers.Binary;
#endif

#if ENABLE_SPAN_T && !UNSAFE_BYTEBUFFER
#error ENABLE_SPAN_T requires UNSAFE_BYTEBUFFER to also be defined
#endif

namespace FlatBuffers
{
public abstract class ByteBufferAllocator
{
#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
public abstract Span<byte> Span { get; }
public abstract ReadOnlySpan<byte> ReadOnlySpan { get; }
public abstract Memory<byte> Memory { get; }
Expand Down Expand Up @@ -102,7 +98,7 @@ public override void GrowFront(int newSize)
InitBuffer();
}

#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
public override Span<byte> Span => _buffer;
public override ReadOnlySpan<byte> ReadOnlySpan => _buffer;
public override Memory<byte> Memory => _buffer;
Expand All @@ -112,7 +108,7 @@ public override void GrowFront(int newSize)
private void InitBuffer()
{
Length = _buffer.Length;
#if !ENABLE_SPAN_T
#if !ENABLE_SPAN_T || !NETSTANDARD2_1
Buffer = _buffer;
#endif
}
Expand Down Expand Up @@ -224,7 +220,7 @@ public static int ArraySize<T>(T[] x)
return SizeOf<T>() * x.Length;
}

#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
public static int ArraySize<T>(Span<T> x)
{
return SizeOf<T>() * x.Length;
Expand All @@ -233,7 +229,7 @@ public static int ArraySize<T>(Span<T> x)

// Get a portion of the buffer casted into an array of type T, given
// the buffer position and length.
#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
public T[] ToArray<T>(int pos, int len)
where T : struct
{
Expand Down Expand Up @@ -261,7 +257,7 @@ public byte[] ToFullArray()
return ToArray<byte>(0, Length);
}

#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
public ReadOnlyMemory<byte> ToReadOnlyMemory(int pos, int len)
{
return _buffer.ReadOnlyMemory.Slice(pos, len);
Expand Down Expand Up @@ -324,7 +320,7 @@ static public ulong ReverseBytes(ulong input)
((input & 0xFF00000000000000UL) >> 56));
}

#if !UNSAFE_BYTEBUFFER
#if !UNSAFE_BYTEBUFFER && !ENABLE_SPAN_T
// Helper functions for the safe (but slower) version.
protected void WriteLittleEndian(int offset, int count, ulong data)
{
Expand Down Expand Up @@ -364,7 +360,46 @@ protected ulong ReadLittleEndian(int offset, int count)
}
return r;
}
#endif // !UNSAFE_BYTEBUFFER
#elif ENABLE_SPAN_T && NETSTANDARD2_1
protected void WriteLittleEndian(int offset, int count, ulong data)
{
if (BitConverter.IsLittleEndian)
{
for (int i = 0; i < count; i++)
{
_buffer.Span[offset + i] = (byte)(data >> i * 8);
}
}
else
{
for (int i = 0; i < count; i++)
{
_buffer.Span[offset + count - 1 - i] = (byte)(data >> i * 8);
}
}
}

protected ulong ReadLittleEndian(int offset, int count)
{
AssertOffsetAndLength(offset, count);
ulong r = 0;
if (BitConverter.IsLittleEndian)
{
for (int i = 0; i < count; i++)
{
r |= (ulong)_buffer.Span[offset + i] << i * 8;
}
}
else
{
for (int i = 0; i < count; i++)
{
r |= (ulong)_buffer.Span[offset + count - 1 - i] << i * 8;
}
}
return r;
}
#endif // !UNSAFE_BYTEBUFFER && !ENABLE_SPAN_T

private void AssertOffsetAndLength(int offset, int length)
{
Expand All @@ -375,7 +410,7 @@ private void AssertOffsetAndLength(int offset, int length)
#endif
}

#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1

public void PutSbyte(int offset, sbyte value)
{
Expand Down Expand Up @@ -423,17 +458,12 @@ public void Put(int offset, byte value)
PutByte(offset, value);
}

#if ENABLE_SPAN_T
public unsafe void PutStringUTF8(int offset, string value)
#if ENABLE_SPAN_T && NETSTANDARD2_1
public void PutStringUTF8(int offset, string value)
{
AssertOffsetAndLength(offset, value.Length);
fixed (char* s = value)
{
fixed (byte* buffer = &MemoryMarshal.GetReference(_buffer.Span))
{
Encoding.UTF8.GetBytes(s, value.Length, buffer + offset, Length - offset);
}
}
Encoding.UTF8.GetBytes(value.AsSpan().Slice(0, value.Length),
_buffer.Span.Slice(offset));
}
#else
public void PutStringUTF8(int offset, string value)
Expand All @@ -454,7 +484,7 @@ public void PutShort(int offset, short value)
public unsafe void PutUshort(int offset, ushort value)
{
AssertOffsetAndLength(offset, sizeof(ushort));
#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
Span<byte> span = _buffer.Span.Slice(offset);
BinaryPrimitives.WriteUInt16LittleEndian(span, value);
#else
Expand All @@ -475,7 +505,7 @@ public void PutInt(int offset, int value)
public unsafe void PutUint(int offset, uint value)
{
AssertOffsetAndLength(offset, sizeof(uint));
#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
Span<byte> span = _buffer.Span.Slice(offset);
BinaryPrimitives.WriteUInt32LittleEndian(span, value);
#else
Expand All @@ -496,7 +526,7 @@ public unsafe void PutLong(int offset, long value)
public unsafe void PutUlong(int offset, ulong value)
{
AssertOffsetAndLength(offset, sizeof(ulong));
#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
Span<byte> span = _buffer.Span.Slice(offset);
BinaryPrimitives.WriteUInt64LittleEndian(span, value);
#else
Expand All @@ -512,7 +542,7 @@ public unsafe void PutUlong(int offset, ulong value)
public unsafe void PutFloat(int offset, float value)
{
AssertOffsetAndLength(offset, sizeof(float));
#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.Span))
#else
fixed (byte* ptr = _buffer.Buffer)
Expand All @@ -532,7 +562,7 @@ public unsafe void PutFloat(int offset, float value)
public unsafe void PutDouble(int offset, double value)
{
AssertOffsetAndLength(offset, sizeof(double));
#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.Span))
#else
fixed (byte* ptr = _buffer.Buffer)
Expand Down Expand Up @@ -605,7 +635,7 @@ public void PutDouble(int offset, double value)

#endif // UNSAFE_BYTEBUFFER

#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
public sbyte GetSbyte(int index)
{
AssertOffsetAndLength(index, sizeof(sbyte));
Expand All @@ -631,13 +661,10 @@ public byte Get(int index)
}
#endif

#if ENABLE_SPAN_T
public unsafe string GetStringUTF8(int startPos, int len)
#if ENABLE_SPAN_T && NETSTANDARD2_1
public string GetStringUTF8(int startPos, int len)
{
fixed (byte* buffer = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan.Slice(startPos)))
{
return Encoding.UTF8.GetString(buffer, len);
}
return Encoding.UTF8.GetString(_buffer.Span.Slice(startPos, len));
}
#else
public string GetStringUTF8(int startPos, int len)
Expand All @@ -656,7 +683,7 @@ public short GetShort(int offset)
public unsafe ushort GetUshort(int offset)
{
AssertOffsetAndLength(offset, sizeof(ushort));
#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
ReadOnlySpan<byte> span = _buffer.ReadOnlySpan.Slice(offset);
return BinaryPrimitives.ReadUInt16LittleEndian(span);
#else
Expand All @@ -677,7 +704,7 @@ public int GetInt(int offset)
public unsafe uint GetUint(int offset)
{
AssertOffsetAndLength(offset, sizeof(uint));
#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
ReadOnlySpan<byte> span = _buffer.ReadOnlySpan.Slice(offset);
return BinaryPrimitives.ReadUInt32LittleEndian(span);
#else
Expand All @@ -698,7 +725,7 @@ public long GetLong(int offset)
public unsafe ulong GetUlong(int offset)
{
AssertOffsetAndLength(offset, sizeof(ulong));
#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
ReadOnlySpan<byte> span = _buffer.ReadOnlySpan.Slice(offset);
return BinaryPrimitives.ReadUInt64LittleEndian(span);
#else
Expand All @@ -714,7 +741,7 @@ public unsafe ulong GetUlong(int offset)
public unsafe float GetFloat(int offset)
{
AssertOffsetAndLength(offset, sizeof(float));
#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan))
#else
fixed (byte* ptr = _buffer.Buffer)
Expand All @@ -735,7 +762,7 @@ public unsafe float GetFloat(int offset)
public unsafe double GetDouble(int offset)
{
AssertOffsetAndLength(offset, sizeof(double));
#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan))
#else
fixed (byte* ptr = _buffer.Buffer)
Expand Down Expand Up @@ -834,7 +861,7 @@ public int Put<T>(int offset, T[] x)
offset -= numBytes;
AssertOffsetAndLength(offset, numBytes);
// if we are LE, just do a block copy
#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
MemoryMarshal.Cast<T, byte>(x).CopyTo(_buffer.Span.Slice(offset, numBytes));
#else
Buffer.BlockCopy(x, 0, _buffer.Buffer, offset, numBytes);
Expand All @@ -853,7 +880,7 @@ public int Put<T>(int offset, T[] x)
return offset;
}

#if ENABLE_SPAN_T
#if ENABLE_SPAN_T && NETSTANDARD2_1
public int Put<T>(int offset, Span<T> x)
where T : struct
{
Expand Down
2 changes: 1 addition & 1 deletion net/FlatBuffers/FlatBuffers.Core.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit e0bbaa6

Please sign in to comment.