summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorDerek Bailey <derek.bailey@thermofisher.com>2018-08-20 16:31:44 -0700
committerWouter van Oortmerssen <aardappel@gmail.com>2018-08-20 16:31:44 -0700
commitd8f49e18d70613dec608987ef897c94b95942d75 (patch)
treeb69512cd35c1e2a7be97254f1f822f49b8b0bd96 /net
parent1f5eae5d6a135ff6811724f6c57f911d1f46bb15 (diff)
downloadflatbuffers-d8f49e18d70613dec608987ef897c94b95942d75.tar.gz
flatbuffers-d8f49e18d70613dec608987ef897c94b95942d75.tar.bz2
flatbuffers-d8f49e18d70613dec608987ef897c94b95942d75.zip
Mono Fix for Unsafe Mode (#4887)
* Added preprocessor define for C++ if Template Aliases are supported by the compiler * Revert "Revert "Performance Increase of Vector of Structures using .NET BlockCopy (#4830)"" This reverts commit 1f5eae5d6a135ff6811724f6c57f911d1f46bb15. * Put<T> method was inside #if UNSAFE_BYTEBUFFER which caused compilation failure when building in unsafe mode * Revert "Added preprocessor define for C++ if Template Aliases are supported by the compiler" This reverts commit a75af7352127c261baf0b6cca5cb823e13e78f11.
Diffstat (limited to 'net')
-rw-r--r--net/FlatBuffers/ByteBuffer.cs120
-rw-r--r--net/FlatBuffers/FlatBufferBuilder.cs43
-rw-r--r--net/FlatBuffers/Table.cs23
3 files changed, 182 insertions, 4 deletions
diff --git a/net/FlatBuffers/ByteBuffer.cs b/net/FlatBuffers/ByteBuffer.cs
index 878e740b..7b170c17 100644
--- a/net/FlatBuffers/ByteBuffer.cs
+++ b/net/FlatBuffers/ByteBuffer.cs
@@ -30,6 +30,7 @@
//
using System;
+using System.Collections.Generic;
using System.IO;
using System.Text;
@@ -91,19 +92,78 @@ namespace FlatBuffers
public byte[] ToArray(int pos, int len)
{
- byte[] arr = new byte[len];
- Buffer.BlockCopy(_buffer, pos, arr, 0, len);
+ return ToArray<byte>(pos, len);
+ }
+
+ /// <summary>
+ /// A lookup of type sizes. Used instead of Marshal.SizeOf() which has additional
+ /// overhead, but also is compatible with generic functions for simplified code.
+ /// </summary>
+ private static Dictionary<Type, int> genericSizes = new Dictionary<Type, int>()
+ {
+ { typeof(bool), sizeof(bool) },
+ { typeof(float), sizeof(float) },
+ { typeof(double), sizeof(double) },
+ { typeof(sbyte), sizeof(sbyte) },
+ { typeof(byte), sizeof(byte) },
+ { typeof(short), sizeof(short) },
+ { typeof(ushort), sizeof(ushort) },
+ { typeof(int), sizeof(int) },
+ { typeof(uint), sizeof(uint) },
+ { typeof(ulong), sizeof(ulong) },
+ { typeof(long), sizeof(long) },
+ };
+
+ /// <summary>
+ /// Get the wire-size (in bytes) of a type supported by flatbuffers.
+ /// </summary>
+ /// <param name="t">The type to get the wire size of</param>
+ /// <returns></returns>
+ public static int SizeOf<T>()
+ {
+ return genericSizes[typeof(T)];
+ }
+
+ /// <summary>
+ /// Checks if the Type provided is supported as scalar value
+ /// </summary>
+ /// <typeparam name="T">The Type to check</typeparam>
+ /// <returns>True if the type is a scalar type that is supported, falsed otherwise</returns>
+ public static bool IsSupportedType<T>()
+ {
+ return genericSizes.ContainsKey(typeof(T));
+ }
+
+ /// <summary>
+ /// Get the wire-size (in bytes) of an typed array
+ /// </summary>
+ /// <typeparam name="T">The type of the array</typeparam>
+ /// <param name="x">The array to get the size of</param>
+ /// <returns>The number of bytes the array takes on wire</returns>
+ public static int ArraySize<T>(T[] x)
+ {
+ return SizeOf<T>() * x.Length;
+ }
+
+ // Get a portion of the buffer casted into an array of type T, given
+ // the buffer position and length.
+ public T[] ToArray<T>(int pos, int len)
+ where T: struct
+ {
+ AssertOffsetAndLength(pos, len);
+ T[] arr = new T[len];
+ Buffer.BlockCopy(_buffer, pos, arr, 0, ArraySize(arr));
return arr;
}
public byte[] ToSizedArray()
{
- return ToArray(Position, Length - Position);
+ return ToArray<byte>(Position, Length - Position);
}
public byte[] ToFullArray()
{
- return ToArray(0, Length);
+ return ToArray<byte>(0, Length);
}
public ArraySegment<byte> ToArraySegment(int pos, int len)
@@ -370,6 +430,58 @@ namespace FlatBuffers
#endif // UNSAFE_BYTEBUFFER
+ /// <summary>
+ /// Copies an array of type T into this buffer, ending at the given
+ /// offset into this buffer. The starting offset is calculated based on the length
+ /// of the array and is the value returned.
+ /// </summary>
+ /// <typeparam name="T">The type of the input data (must be a struct)</typeparam>
+ /// <param name="offset">The offset into this buffer where the copy will end</param>
+ /// <param name="x">The array to copy data from</param>
+ /// <returns>The 'start' location of this buffer now, after the copy completed</returns>
+ public int Put<T>(int offset, T[] x)
+ where T : struct
+ {
+ if(x == null)
+ {
+ throw new ArgumentNullException("Cannot put a null array");
+ }
+
+ if(x.Length == 0)
+ {
+ throw new ArgumentException("Cannot put an empty array");
+ }
+
+ if(!IsSupportedType<T>())
+ {
+ throw new ArgumentException("Cannot put an array of type "
+ + typeof(T) + " into this buffer");
+ }
+
+ if (BitConverter.IsLittleEndian)
+ {
+ int numBytes = ByteBuffer.ArraySize(x);
+ offset -= numBytes;
+ AssertOffsetAndLength(offset, numBytes);
+ // if we are LE, just do a block copy
+ Buffer.BlockCopy(x, 0, _buffer, offset, numBytes);
+ }
+ else
+ {
+ throw new NotImplementedException("Big Endian Support not implemented yet " +
+ "for putting typed arrays");
+ // if we are BE, we have to swap each element by itself
+ //for(int i = x.Length - 1; i >= 0; i--)
+ //{
+ // todo: low priority, but need to genericize the Put<T>() functions
+ //}
+ }
+ return offset;
+ }
+
+
+
+
public sbyte GetSbyte(int index)
{
AssertOffsetAndLength(index, sizeof(sbyte));
diff --git a/net/FlatBuffers/FlatBufferBuilder.cs b/net/FlatBuffers/FlatBufferBuilder.cs
index a2224498..33bba969 100644
--- a/net/FlatBuffers/FlatBufferBuilder.cs
+++ b/net/FlatBuffers/FlatBufferBuilder.cs
@@ -179,6 +179,18 @@ namespace FlatBuffers
_bb.PutFloat(_space -= sizeof(float), x);
}
+ /// <summary>
+ /// Puts an array of type T into this builder at the
+ /// current offset
+ /// </summary>
+ /// <typeparam name="T">The type of the input data </typeparam>
+ /// <param name="x">The array to copy data from</param>
+ public void Put<T>(T[] x)
+ where T : struct
+ {
+ _space = _bb.Put(_space, x);
+ }
+
public void PutDouble(double x)
{
_bb.PutDouble(_space -= sizeof(double), x);
@@ -246,6 +258,37 @@ namespace FlatBuffers
public void AddFloat(float x) { Prep(sizeof(float), 0); PutFloat(x); }
/// <summary>
+ /// Add an array of type T to the buffer (aligns the data and grows if necessary).
+ /// </summary>
+ /// <typeparam name="T">The type of the input data</typeparam>
+ /// <param name="x">The array to copy data from</param>
+ public void Add<T>(T[] x)
+ where T : struct
+ {
+ if (x == null)
+ {
+ throw new ArgumentNullException("Cannot add a null array");
+ }
+
+ if( x.Length == 0)
+ {
+ // don't do anything if the array is empty
+ return;
+ }
+
+ if(!ByteBuffer.IsSupportedType<T>())
+ {
+ throw new ArgumentException("Cannot add this Type array to the builder");
+ }
+
+ int size = ByteBuffer.SizeOf<T>();
+ // Need to prep on size (for data alignment) and then we pass the
+ // rest of the length (minus 1) as additional bytes
+ Prep(size, size * (x.Length - 1));
+ Put(x);
+ }
+
+ /// <summary>
/// Add a `double` to the buffer (aligns the data and grows if necessary).
/// </summary>
/// <param name="x">The `double` to add to the buffer.</param>
diff --git a/net/FlatBuffers/Table.cs b/net/FlatBuffers/Table.cs
index 4a188ff8..07db5f42 100644
--- a/net/FlatBuffers/Table.cs
+++ b/net/FlatBuffers/Table.cs
@@ -94,6 +94,29 @@ namespace FlatBuffers
return bb.ToArraySegment(pos, len);
}
+ // Get the data of a vector whoses offset is stored at "offset" in this object as an
+ // T[]. If the vector is not present in the ByteBuffer, then a null value will be
+ // returned.
+ public T[] __vector_as_array<T>(int offset)
+ where T : struct
+ {
+ if(!BitConverter.IsLittleEndian)
+ {
+ throw new NotSupportedException("Getting typed arrays on a Big Endian " +
+ "system is not support");
+ }
+
+ var o = this.__offset(offset);
+ if (0 == o)
+ {
+ return null;
+ }
+
+ var pos = this.__vector(o);
+ var len = this.__vector_len(o);
+ return bb.ToArray<T>(pos, len);
+ }
+
// Initialize any Table-derived type to point to the union at the given offset.
public T __union<T>(int offset) where T : struct, IFlatbufferObject
{