Bump flatbuffers to v24.3.25 version (#6968)
This commit is contained in:
committed by
GitHub
parent
7436835244
commit
825132eec7
+205
-55
@@ -14,24 +14,25 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// There are 3 #defines that have an impact on performance / features of this ByteBuffer implementation
|
||||
// There are three conditional compilation symbols that have an impact on performance/features of this ByteBuffer implementation.
|
||||
//
|
||||
// UNSAFE_BYTEBUFFER
|
||||
// UNSAFE_BYTEBUFFER
|
||||
// This will use unsafe code to manipulate the underlying byte array. This
|
||||
// can yield a reasonable performance increase.
|
||||
//
|
||||
// BYTEBUFFER_NO_BOUNDS_CHECK
|
||||
// This will disable the bounds check asserts to the byte array. This can
|
||||
// yield a small performance gain in normal code..
|
||||
// yield a small performance gain in normal code.
|
||||
//
|
||||
// ENABLE_SPAN_T
|
||||
// This will enable reading and writing blocks of memory with a Span<T> instead if just
|
||||
// This will enable reading and writing blocks of memory with a Span<T> instead of just
|
||||
// T[]. You can also enable writing directly to shared memory or other types of memory
|
||||
// by providing a custom implementation of ByteBufferAllocator.
|
||||
// ENABLE_SPAN_T also requires UNSAFE_BYTEBUFFER to be defined
|
||||
// ENABLE_SPAN_T also requires UNSAFE_BYTEBUFFER to be defined, or .NET
|
||||
// Standard 2.1.
|
||||
//
|
||||
// Using UNSAFE_BYTEBUFFER and BYTEBUFFER_NO_BOUNDS_CHECK together can yield a
|
||||
// performance gain of ~15% for some operations, however doing so is potentially
|
||||
// performance gain of ~15% for some operations, however doing so is potentially
|
||||
// dangerous. Do so at your own risk!
|
||||
//
|
||||
|
||||
@@ -42,19 +43,19 @@ using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
using System.Buffers.Binary;
|
||||
#endif
|
||||
|
||||
#if ENABLE_SPAN_T && !UNSAFE_BYTEBUFFER
|
||||
#error ENABLE_SPAN_T requires UNSAFE_BYTEBUFFER to also be defined
|
||||
#warning ENABLE_SPAN_T requires UNSAFE_BYTEBUFFER to also be defined
|
||||
#endif
|
||||
|
||||
namespace FlatBuffers
|
||||
namespace Google.FlatBuffers
|
||||
{
|
||||
public abstract class ByteBufferAllocator
|
||||
{
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
public abstract Span<byte> Span { get; }
|
||||
public abstract ReadOnlySpan<byte> ReadOnlySpan { get; }
|
||||
public abstract Memory<byte> Memory { get; }
|
||||
@@ -102,7 +103,7 @@ namespace FlatBuffers
|
||||
InitBuffer();
|
||||
}
|
||||
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
public override Span<byte> Span => _buffer;
|
||||
public override ReadOnlySpan<byte> ReadOnlySpan => _buffer;
|
||||
public override Memory<byte> Memory => _buffer;
|
||||
@@ -224,7 +225,19 @@ namespace FlatBuffers
|
||||
return SizeOf<T>() * x.Length;
|
||||
}
|
||||
|
||||
#if ENABLE_SPAN_T
|
||||
/// <summary>
|
||||
/// Get the wire-size (in bytes) of an typed array segment, taking only the
|
||||
/// range specified by <paramref name="x"/> into account.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the array</typeparam>
|
||||
/// <param name="x">The array segment to get the size of</param>
|
||||
/// <returns>The number of bytes the array segment takes on wire</returns>
|
||||
public static int ArraySize<T>(ArraySegment<T> x)
|
||||
{
|
||||
return SizeOf<T>() * x.Count;
|
||||
}
|
||||
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
public static int ArraySize<T>(Span<T> x)
|
||||
{
|
||||
return SizeOf<T>() * x.Length;
|
||||
@@ -233,7 +246,7 @@ namespace FlatBuffers
|
||||
|
||||
// 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 && UNSAFE_BYTEBUFFER
|
||||
public T[] ToArray<T>(int pos, int len)
|
||||
where T : struct
|
||||
{
|
||||
@@ -261,7 +274,7 @@ namespace FlatBuffers
|
||||
return ToArray<byte>(0, Length);
|
||||
}
|
||||
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
public ReadOnlyMemory<byte> ToReadOnlyMemory(int pos, int len)
|
||||
{
|
||||
return _buffer.ReadOnlyMemory.Slice(pos, len);
|
||||
@@ -289,11 +302,14 @@ namespace FlatBuffers
|
||||
#endif
|
||||
|
||||
#if !UNSAFE_BYTEBUFFER
|
||||
// Pre-allocated helper arrays for convertion.
|
||||
private float[] floathelper = new[] { 0.0f };
|
||||
private int[] inthelper = new[] { 0 };
|
||||
private double[] doublehelper = new[] { 0.0 };
|
||||
private ulong[] ulonghelper = new[] { 0UL };
|
||||
// A conversion union where all the members are overlapping. This allows to reinterpret the bytes of one type
|
||||
// as another, without additional copies.
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
struct ConversionUnion
|
||||
{
|
||||
[FieldOffset(0)] public int intValue;
|
||||
[FieldOffset(0)] public float floatValue;
|
||||
}
|
||||
#endif // !UNSAFE_BYTEBUFFER
|
||||
|
||||
// Helper functions for the unsafe version.
|
||||
@@ -321,7 +337,7 @@ namespace FlatBuffers
|
||||
((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)
|
||||
{
|
||||
@@ -361,7 +377,46 @@ namespace FlatBuffers
|
||||
}
|
||||
return r;
|
||||
}
|
||||
#endif // !UNSAFE_BYTEBUFFER
|
||||
#elif ENABLE_SPAN_T
|
||||
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
|
||||
|
||||
private void AssertOffsetAndLength(int offset, int length)
|
||||
{
|
||||
@@ -372,7 +427,7 @@ namespace FlatBuffers
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
|
||||
public void PutSbyte(int offset, sbyte value)
|
||||
{
|
||||
@@ -420,7 +475,7 @@ namespace FlatBuffers
|
||||
PutByte(offset, value);
|
||||
}
|
||||
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
public unsafe void PutStringUTF8(int offset, string value)
|
||||
{
|
||||
AssertOffsetAndLength(offset, value.Length);
|
||||
@@ -432,6 +487,13 @@ namespace FlatBuffers
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif ENABLE_SPAN_T
|
||||
public void PutStringUTF8(int offset, string value)
|
||||
{
|
||||
AssertOffsetAndLength(offset, value.Length);
|
||||
Encoding.UTF8.GetBytes(value.AsSpan().Slice(0, value.Length),
|
||||
_buffer.Span.Slice(offset));
|
||||
}
|
||||
#else
|
||||
public void PutStringUTF8(int offset, string value)
|
||||
{
|
||||
@@ -451,7 +513,7 @@ namespace FlatBuffers
|
||||
public unsafe void PutUshort(int offset, ushort value)
|
||||
{
|
||||
AssertOffsetAndLength(offset, sizeof(ushort));
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T // && UNSAFE_BYTEBUFFER
|
||||
Span<byte> span = _buffer.Span.Slice(offset);
|
||||
BinaryPrimitives.WriteUInt16LittleEndian(span, value);
|
||||
#else
|
||||
@@ -472,7 +534,7 @@ namespace FlatBuffers
|
||||
public unsafe void PutUint(int offset, uint value)
|
||||
{
|
||||
AssertOffsetAndLength(offset, sizeof(uint));
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T // && UNSAFE_BYTEBUFFER
|
||||
Span<byte> span = _buffer.Span.Slice(offset);
|
||||
BinaryPrimitives.WriteUInt32LittleEndian(span, value);
|
||||
#else
|
||||
@@ -493,7 +555,7 @@ namespace FlatBuffers
|
||||
public unsafe void PutUlong(int offset, ulong value)
|
||||
{
|
||||
AssertOffsetAndLength(offset, sizeof(ulong));
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T // && UNSAFE_BYTEBUFFER
|
||||
Span<byte> span = _buffer.Span.Slice(offset);
|
||||
BinaryPrimitives.WriteUInt64LittleEndian(span, value);
|
||||
#else
|
||||
@@ -509,7 +571,7 @@ namespace FlatBuffers
|
||||
public unsafe void PutFloat(int offset, float value)
|
||||
{
|
||||
AssertOffsetAndLength(offset, sizeof(float));
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T // && UNSAFE_BYTEBUFFER
|
||||
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.Span))
|
||||
#else
|
||||
fixed (byte* ptr = _buffer.Buffer)
|
||||
@@ -529,7 +591,7 @@ namespace FlatBuffers
|
||||
public unsafe void PutDouble(int offset, double value)
|
||||
{
|
||||
AssertOffsetAndLength(offset, sizeof(double));
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T // && UNSAFE_BYTEBUFFER
|
||||
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.Span))
|
||||
#else
|
||||
fixed (byte* ptr = _buffer.Buffer)
|
||||
@@ -586,22 +648,23 @@ namespace FlatBuffers
|
||||
public void PutFloat(int offset, float value)
|
||||
{
|
||||
AssertOffsetAndLength(offset, sizeof(float));
|
||||
floathelper[0] = value;
|
||||
Buffer.BlockCopy(floathelper, 0, inthelper, 0, sizeof(float));
|
||||
WriteLittleEndian(offset, sizeof(float), (ulong)inthelper[0]);
|
||||
// TODO(derekbailey): use BitConvert.SingleToInt32Bits() whenever flatbuffers upgrades to a .NET version
|
||||
// that contains it.
|
||||
ConversionUnion union;
|
||||
union.intValue = 0;
|
||||
union.floatValue = value;
|
||||
WriteLittleEndian(offset, sizeof(float), (ulong)union.intValue);
|
||||
}
|
||||
|
||||
public void PutDouble(int offset, double value)
|
||||
{
|
||||
AssertOffsetAndLength(offset, sizeof(double));
|
||||
doublehelper[0] = value;
|
||||
Buffer.BlockCopy(doublehelper, 0, ulonghelper, 0, sizeof(double));
|
||||
WriteLittleEndian(offset, sizeof(double), ulonghelper[0]);
|
||||
WriteLittleEndian(offset, sizeof(double), (ulong)BitConverter.DoubleToInt64Bits(value));
|
||||
}
|
||||
|
||||
#endif // UNSAFE_BYTEBUFFER
|
||||
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
public sbyte GetSbyte(int index)
|
||||
{
|
||||
AssertOffsetAndLength(index, sizeof(sbyte));
|
||||
@@ -627,7 +690,7 @@ namespace FlatBuffers
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
public unsafe string GetStringUTF8(int startPos, int len)
|
||||
{
|
||||
fixed (byte* buffer = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan.Slice(startPos)))
|
||||
@@ -635,6 +698,11 @@ namespace FlatBuffers
|
||||
return Encoding.UTF8.GetString(buffer, len);
|
||||
}
|
||||
}
|
||||
#elif ENABLE_SPAN_T
|
||||
public string GetStringUTF8(int startPos, int len)
|
||||
{
|
||||
return Encoding.UTF8.GetString(_buffer.Span.Slice(startPos, len));
|
||||
}
|
||||
#else
|
||||
public string GetStringUTF8(int startPos, int len)
|
||||
{
|
||||
@@ -652,7 +720,7 @@ namespace FlatBuffers
|
||||
public unsafe ushort GetUshort(int offset)
|
||||
{
|
||||
AssertOffsetAndLength(offset, sizeof(ushort));
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T // && UNSAFE_BYTEBUFFER
|
||||
ReadOnlySpan<byte> span = _buffer.ReadOnlySpan.Slice(offset);
|
||||
return BinaryPrimitives.ReadUInt16LittleEndian(span);
|
||||
#else
|
||||
@@ -673,7 +741,7 @@ namespace FlatBuffers
|
||||
public unsafe uint GetUint(int offset)
|
||||
{
|
||||
AssertOffsetAndLength(offset, sizeof(uint));
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T // && UNSAFE_BYTEBUFFER
|
||||
ReadOnlySpan<byte> span = _buffer.ReadOnlySpan.Slice(offset);
|
||||
return BinaryPrimitives.ReadUInt32LittleEndian(span);
|
||||
#else
|
||||
@@ -694,10 +762,10 @@ namespace FlatBuffers
|
||||
public unsafe ulong GetUlong(int offset)
|
||||
{
|
||||
AssertOffsetAndLength(offset, sizeof(ulong));
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T // && UNSAFE_BYTEBUFFER
|
||||
ReadOnlySpan<byte> span = _buffer.ReadOnlySpan.Slice(offset);
|
||||
return BinaryPrimitives.ReadUInt64LittleEndian(span);
|
||||
#else
|
||||
#else
|
||||
fixed (byte* ptr = _buffer.Buffer)
|
||||
{
|
||||
return BitConverter.IsLittleEndian
|
||||
@@ -710,7 +778,7 @@ namespace FlatBuffers
|
||||
public unsafe float GetFloat(int offset)
|
||||
{
|
||||
AssertOffsetAndLength(offset, sizeof(float));
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T // && UNSAFE_BYTEBUFFER
|
||||
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan))
|
||||
#else
|
||||
fixed (byte* ptr = _buffer.Buffer)
|
||||
@@ -731,7 +799,7 @@ namespace FlatBuffers
|
||||
public unsafe double GetDouble(int offset)
|
||||
{
|
||||
AssertOffsetAndLength(offset, sizeof(double));
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T // && UNSAFE_BYTEBUFFER
|
||||
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan))
|
||||
#else
|
||||
fixed (byte* ptr = _buffer.Buffer)
|
||||
@@ -782,19 +850,17 @@ namespace FlatBuffers
|
||||
|
||||
public float GetFloat(int index)
|
||||
{
|
||||
int i = (int)ReadLittleEndian(index, sizeof(float));
|
||||
inthelper[0] = i;
|
||||
Buffer.BlockCopy(inthelper, 0, floathelper, 0, sizeof(float));
|
||||
return floathelper[0];
|
||||
// TODO(derekbailey): use BitConvert.Int32BitsToSingle() whenever flatbuffers upgrades to a .NET version
|
||||
// that contains it.
|
||||
ConversionUnion union;
|
||||
union.floatValue = 0;
|
||||
union.intValue = (int)ReadLittleEndian(index, sizeof(float));
|
||||
return union.floatValue;
|
||||
}
|
||||
|
||||
public double GetDouble(int index)
|
||||
{
|
||||
ulong i = ReadLittleEndian(index, sizeof(double));
|
||||
// There's Int64BitsToDouble but it uses unsafe code internally.
|
||||
ulonghelper[0] = i;
|
||||
Buffer.BlockCopy(ulonghelper, 0, doublehelper, 0, sizeof(double));
|
||||
return doublehelper[0];
|
||||
return BitConverter.Int64BitsToDouble((long)ReadLittleEndian(index, sizeof(double)));
|
||||
}
|
||||
#endif // UNSAFE_BYTEBUFFER
|
||||
|
||||
@@ -815,7 +881,30 @@ namespace FlatBuffers
|
||||
throw new ArgumentNullException("Cannot put a null array");
|
||||
}
|
||||
|
||||
if (x.Length == 0)
|
||||
return Put(offset, new ArraySegment<T>(x));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies an array segment of type T into this buffer, ending at the
|
||||
/// given offset into this buffer. The starting offset is calculated
|
||||
/// based on the count of the array segment 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 segment to copy data from</param>
|
||||
/// <returns>The 'start' location of this buffer now, after the copy
|
||||
/// completed</returns>
|
||||
public int Put<T>(int offset, ArraySegment<T> x)
|
||||
where T : struct
|
||||
{
|
||||
if (x.Equals(default(ArraySegment<T>)))
|
||||
{
|
||||
throw new ArgumentNullException("Cannot put a uninitialized array segment");
|
||||
}
|
||||
|
||||
if (x.Count == 0)
|
||||
{
|
||||
throw new ArgumentException("Cannot put an empty array");
|
||||
}
|
||||
@@ -832,10 +921,11 @@ namespace FlatBuffers
|
||||
offset -= numBytes;
|
||||
AssertOffsetAndLength(offset, numBytes);
|
||||
// if we are LE, just do a block copy
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
MemoryMarshal.Cast<T, byte>(x).CopyTo(_buffer.Span.Slice(offset, numBytes));
|
||||
#else
|
||||
Buffer.BlockCopy(x, 0, _buffer.Buffer, offset, numBytes);
|
||||
var srcOffset = ByteBuffer.SizeOf<T>() * x.Offset;
|
||||
Buffer.BlockCopy(x.Array, srcOffset, _buffer.Buffer, offset, numBytes);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@@ -851,7 +941,67 @@ namespace FlatBuffers
|
||||
return offset;
|
||||
}
|
||||
|
||||
#if ENABLE_SPAN_T
|
||||
/// <summary>
|
||||
/// Copies an array segment of type T into this buffer, ending at the
|
||||
/// given offset into this buffer. The starting offset is calculated
|
||||
/// based on the count of the array segment 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="ptr">The pointer to copy data from</param>
|
||||
/// <param name="sizeInBytes">The number of bytes to copy</param>
|
||||
/// <returns>The 'start' location of this buffer now, after the copy
|
||||
/// completed</returns>
|
||||
public int Put<T>(int offset, IntPtr ptr, int sizeInBytes)
|
||||
where T : struct
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
{
|
||||
throw new ArgumentNullException("Cannot add a null pointer");
|
||||
}
|
||||
|
||||
if(sizeInBytes <= 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)
|
||||
{
|
||||
offset -= sizeInBytes;
|
||||
AssertOffsetAndLength(offset, sizeInBytes);
|
||||
// if we are LE, just do a block copy
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
unsafe
|
||||
{
|
||||
var span = new Span<byte>(ptr.ToPointer(), sizeInBytes);
|
||||
span.CopyTo(_buffer.Span.Slice(offset, sizeInBytes));
|
||||
}
|
||||
#else
|
||||
Marshal.Copy(ptr, _buffer.Buffer, offset, sizeInBytes);
|
||||
#endif
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
public int Put<T>(int offset, Span<T> x)
|
||||
where T : struct
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
using System;
|
||||
|
||||
namespace FlatBuffers
|
||||
namespace Google.FlatBuffers
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that collects utility functions around `ByteBuffer`.
|
||||
|
||||
+189
-8
@@ -23,7 +23,7 @@ using System.Text;
|
||||
/// @addtogroup flatbuffers_csharp_api
|
||||
/// @{
|
||||
|
||||
namespace FlatBuffers
|
||||
namespace Google.FlatBuffers
|
||||
{
|
||||
/// <summary>
|
||||
/// Responsible for building up and accessing a FlatBuffer formatted byte
|
||||
@@ -67,7 +67,7 @@ namespace FlatBuffers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a FlatBufferBuilder backed by the pased in ByteBuffer
|
||||
/// Create a FlatBufferBuilder backed by the passed in ByteBuffer
|
||||
/// </summary>
|
||||
/// <param name="buffer">The ByteBuffer to write to</param>
|
||||
public FlatBufferBuilder(ByteBuffer buffer)
|
||||
@@ -90,6 +90,10 @@ namespace FlatBuffers
|
||||
_objectStart = 0;
|
||||
_numVtables = 0;
|
||||
_vectorNumElems = 0;
|
||||
if (_sharedStringMap != null)
|
||||
{
|
||||
_sharedStringMap.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -206,7 +210,32 @@ namespace FlatBuffers
|
||||
_space = _bb.Put(_space, x);
|
||||
}
|
||||
|
||||
#if ENABLE_SPAN_T
|
||||
/// <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 segment to copy data from</param>
|
||||
public void Put<T>(ArraySegment<T> x)
|
||||
where T : struct
|
||||
{
|
||||
_space = _bb.Put(_space, x);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Puts data of type T into this builder at the
|
||||
/// current offset
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the input data </typeparam>
|
||||
/// <param name="ptr">The pointer to copy data from</param>
|
||||
/// <param name="sizeInBytes">The length of the data in bytes</param>
|
||||
public void Put<T>(IntPtr ptr, int sizeInBytes)
|
||||
where T : struct
|
||||
{
|
||||
_space = _bb.Put<T>(_space, ptr, sizeInBytes);
|
||||
}
|
||||
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
/// <summary>
|
||||
/// Puts a span of type T into this builder at the
|
||||
/// current offset
|
||||
@@ -293,13 +322,24 @@ namespace FlatBuffers
|
||||
/// <param name="x">The array to copy data from</param>
|
||||
public void Add<T>(T[] x)
|
||||
where T : struct
|
||||
{
|
||||
Add(new ArraySegment<T>(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 segment to copy data from</param>
|
||||
public void Add<T>(ArraySegment<T> x)
|
||||
where T : struct
|
||||
{
|
||||
if (x == null)
|
||||
{
|
||||
throw new ArgumentNullException("Cannot add a null array");
|
||||
}
|
||||
|
||||
if( x.Length == 0)
|
||||
if( x.Count == 0)
|
||||
{
|
||||
// don't do anything if the array is empty
|
||||
return;
|
||||
@@ -313,11 +353,53 @@ namespace FlatBuffers
|
||||
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));
|
||||
Prep(size, size * (x.Count - 1));
|
||||
Put(x);
|
||||
}
|
||||
|
||||
#if ENABLE_SPAN_T
|
||||
/// <summary>
|
||||
/// Adds the data of type T pointed to by the given pointer to the buffer (aligns the data and grows if necessary).
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the input data</typeparam>
|
||||
/// <param name="ptr">The pointer to copy data from</param>
|
||||
/// <param name="sizeInBytes">The data size in bytes</param>
|
||||
public void Add<T>(IntPtr ptr, int sizeInBytes)
|
||||
where T : struct
|
||||
{
|
||||
if(sizeInBytes == 0)
|
||||
{
|
||||
// don't do anything if the array is empty
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr == IntPtr.Zero)
|
||||
{
|
||||
throw new ArgumentNullException("Cannot add a null pointer");
|
||||
}
|
||||
|
||||
if(sizeInBytes < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("sizeInBytes", "sizeInBytes cannot be negative");
|
||||
}
|
||||
|
||||
if(!ByteBuffer.IsSupportedType<T>())
|
||||
{
|
||||
throw new ArgumentException("Cannot add this Type array to the builder");
|
||||
}
|
||||
|
||||
int size = ByteBuffer.SizeOf<T>();
|
||||
if((sizeInBytes % size) != 0)
|
||||
{
|
||||
throw new ArgumentException("The given size in bytes " + sizeInBytes + " doesn't match the element size of T ( " + size + ")", "sizeInBytes");
|
||||
}
|
||||
|
||||
// Need to prep on size (for data alignment) and then we pass the
|
||||
// rest of the length (minus 1) as additional bytes
|
||||
Prep(size, sizeInBytes - size);
|
||||
Put<T>(ptr, sizeInBytes);
|
||||
}
|
||||
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
/// <summary>
|
||||
/// Add a span of type T to the buffer (aligns the data and grows if necessary).
|
||||
/// </summary>
|
||||
@@ -356,7 +438,8 @@ namespace FlatBuffers
|
||||
if (off > Offset)
|
||||
throw new ArgumentException();
|
||||
|
||||
off = Offset - off + sizeof(int);
|
||||
if (off != 0)
|
||||
off = Offset - off + sizeof(int);
|
||||
PutInt(off);
|
||||
}
|
||||
|
||||
@@ -445,6 +528,15 @@ namespace FlatBuffers
|
||||
/// <param name="d">The default value to compare the value against</param>
|
||||
public void AddBool(int o, bool x, bool d) { if (ForceDefaults || x != d) { AddBool(x); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Boolean to the Table at index `o` in its vtable using the nullable value `x`
|
||||
/// </summary>
|
||||
/// <param name="o">The index into the vtable</param>
|
||||
/// <param name="x">The nullable boolean value to put into the buffer. If it doesn't have a value
|
||||
/// it will skip writing to the buffer.</param>
|
||||
public void AddBool(int o, bool? x) { if (x.HasValue) { AddBool(x.Value); Slot(o); } }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a SByte to the Table at index `o` in its vtable using the value `x` and default `d`
|
||||
/// </summary>
|
||||
@@ -454,6 +546,14 @@ namespace FlatBuffers
|
||||
/// <param name="d">The default value to compare the value against</param>
|
||||
public void AddSbyte(int o, sbyte x, sbyte d) { if (ForceDefaults || x != d) { AddSbyte(x); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a SByte to the Table at index `o` in its vtable using the nullable value `x`
|
||||
/// </summary>
|
||||
/// <param name="o">The index into the vtable</param>
|
||||
/// <param name="x">The nullable sbyte value to put into the buffer. If it doesn't have a value
|
||||
/// it will skip writing to the buffer.</param>
|
||||
public void AddSbyte(int o, sbyte? x) { if (x.HasValue) { AddSbyte(x.Value); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Byte to the Table at index `o` in its vtable using the value `x` and default `d`
|
||||
/// </summary>
|
||||
@@ -463,6 +563,14 @@ namespace FlatBuffers
|
||||
/// <param name="d">The default value to compare the value against</param>
|
||||
public void AddByte(int o, byte x, byte d) { if (ForceDefaults || x != d) { AddByte(x); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Byte to the Table at index `o` in its vtable using the nullable value `x`
|
||||
/// </summary>
|
||||
/// <param name="o">The index into the vtable</param>
|
||||
/// <param name="x">The nullable byte value to put into the buffer. If it doesn't have a value
|
||||
/// it will skip writing to the buffer.</param>
|
||||
public void AddByte(int o, byte? x) { if (x.HasValue) { AddByte(x.Value); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Int16 to the Table at index `o` in its vtable using the value `x` and default `d`
|
||||
/// </summary>
|
||||
@@ -472,6 +580,14 @@ namespace FlatBuffers
|
||||
/// <param name="d">The default value to compare the value against</param>
|
||||
public void AddShort(int o, short x, int d) { if (ForceDefaults || x != d) { AddShort(x); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Int16 to the Table at index `o` in its vtable using the nullable value `x`
|
||||
/// </summary>
|
||||
/// <param name="o">The index into the vtable</param>
|
||||
/// <param name="x">The nullable int16 value to put into the buffer. If it doesn't have a value
|
||||
/// it will skip writing to the buffer.</param>
|
||||
public void AddShort(int o, short? x) { if (x.HasValue) { AddShort(x.Value); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a UInt16 to the Table at index `o` in its vtable using the value `x` and default `d`
|
||||
/// </summary>
|
||||
@@ -481,6 +597,14 @@ namespace FlatBuffers
|
||||
/// <param name="d">The default value to compare the value against</param>
|
||||
public void AddUshort(int o, ushort x, ushort d) { if (ForceDefaults || x != d) { AddUshort(x); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Uint16 to the Table at index `o` in its vtable using the nullable value `x`
|
||||
/// </summary>
|
||||
/// <param name="o">The index into the vtable</param>
|
||||
/// <param name="x">The nullable uint16 value to put into the buffer. If it doesn't have a value
|
||||
/// it will skip writing to the buffer.</param>
|
||||
public void AddUshort(int o, ushort? x) { if (x.HasValue) { AddUshort(x.Value); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds an Int32 to the Table at index `o` in its vtable using the value `x` and default `d`
|
||||
/// </summary>
|
||||
@@ -490,6 +614,14 @@ namespace FlatBuffers
|
||||
/// <param name="d">The default value to compare the value against</param>
|
||||
public void AddInt(int o, int x, int d) { if (ForceDefaults || x != d) { AddInt(x); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Int32 to the Table at index `o` in its vtable using the nullable value `x`
|
||||
/// </summary>
|
||||
/// <param name="o">The index into the vtable</param>
|
||||
/// <param name="x">The nullable int32 value to put into the buffer. If it doesn't have a value
|
||||
/// it will skip writing to the buffer.</param>
|
||||
public void AddInt(int o, int? x) { if (x.HasValue) { AddInt(x.Value); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a UInt32 to the Table at index `o` in its vtable using the value `x` and default `d`
|
||||
/// </summary>
|
||||
@@ -499,6 +631,14 @@ namespace FlatBuffers
|
||||
/// <param name="d">The default value to compare the value against</param>
|
||||
public void AddUint(int o, uint x, uint d) { if (ForceDefaults || x != d) { AddUint(x); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a UInt32 to the Table at index `o` in its vtable using the nullable value `x`
|
||||
/// </summary>
|
||||
/// <param name="o">The index into the vtable</param>
|
||||
/// <param name="x">The nullable uint32 value to put into the buffer. If it doesn't have a value
|
||||
/// it will skip writing to the buffer.</param>
|
||||
public void AddUint(int o, uint? x) { if (x.HasValue) { AddUint(x.Value); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds an Int64 to the Table at index `o` in its vtable using the value `x` and default `d`
|
||||
/// </summary>
|
||||
@@ -508,6 +648,14 @@ namespace FlatBuffers
|
||||
/// <param name="d">The default value to compare the value against</param>
|
||||
public void AddLong(int o, long x, long d) { if (ForceDefaults || x != d) { AddLong(x); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Int64 to the Table at index `o` in its vtable using the nullable value `x`
|
||||
/// </summary>
|
||||
/// <param name="o">The index into the vtable</param>
|
||||
/// <param name="x">The nullable int64 value to put into the buffer. If it doesn't have a value
|
||||
/// it will skip writing to the buffer.</param>
|
||||
public void AddLong(int o, long? x) { if (x.HasValue) { AddLong(x.Value); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a UInt64 to the Table at index `o` in its vtable using the value `x` and default `d`
|
||||
/// </summary>
|
||||
@@ -517,6 +665,14 @@ namespace FlatBuffers
|
||||
/// <param name="d">The default value to compare the value against</param>
|
||||
public void AddUlong(int o, ulong x, ulong d) { if (ForceDefaults || x != d) { AddUlong(x); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a UInt64 to the Table at index `o` in its vtable using the nullable value `x`
|
||||
/// </summary>
|
||||
/// <param name="o">The index into the vtable</param>
|
||||
/// <param name="x">The nullable int64 value to put into the buffer. If it doesn't have a value
|
||||
/// it will skip writing to the buffer.</param>
|
||||
public void AddUlong(int o, ulong? x) { if (x.HasValue) { AddUlong(x.Value); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Single to the Table at index `o` in its vtable using the value `x` and default `d`
|
||||
/// </summary>
|
||||
@@ -526,6 +682,14 @@ namespace FlatBuffers
|
||||
/// <param name="d">The default value to compare the value against</param>
|
||||
public void AddFloat(int o, float x, double d) { if (ForceDefaults || x != d) { AddFloat(x); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Single to the Table at index `o` in its vtable using the nullable value `x`
|
||||
/// </summary>
|
||||
/// <param name="o">The index into the vtable</param>
|
||||
/// <param name="x">The nullable single value to put into the buffer. If it doesn't have a value
|
||||
/// it will skip writing to the buffer.</param>
|
||||
public void AddFloat(int o, float? x) { if (x.HasValue) { AddFloat(x.Value); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Double to the Table at index `o` in its vtable using the value `x` and default `d`
|
||||
/// </summary>
|
||||
@@ -535,6 +699,14 @@ namespace FlatBuffers
|
||||
/// <param name="d">The default value to compare the value against</param>
|
||||
public void AddDouble(int o, double x, double d) { if (ForceDefaults || x != d) { AddDouble(x); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a Double to the Table at index `o` in its vtable using the nullable value `x`
|
||||
/// </summary>
|
||||
/// <param name="o">The index into the vtable</param>
|
||||
/// <param name="x">The nullable double value to put into the buffer. If it doesn't have a value
|
||||
/// it will skip writing to the buffer.</param>
|
||||
public void AddDouble(int o, double? x) { if (x.HasValue) { AddDouble(x.Value); Slot(o); } }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a buffer offset to the Table at index `o` in its vtable using the value `x` and default `d`
|
||||
/// </summary>
|
||||
@@ -554,6 +726,10 @@ namespace FlatBuffers
|
||||
/// </returns>
|
||||
public StringOffset CreateString(string s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
return new StringOffset(0);
|
||||
}
|
||||
NotNested();
|
||||
AddByte(0);
|
||||
var utf8StringLen = Encoding.UTF8.GetByteCount(s);
|
||||
@@ -563,7 +739,7 @@ namespace FlatBuffers
|
||||
}
|
||||
|
||||
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
/// <summary>
|
||||
/// Creates a string in the buffer from a Span containing
|
||||
/// a UTF8 string.
|
||||
@@ -594,6 +770,11 @@ namespace FlatBuffers
|
||||
/// </returns>
|
||||
public StringOffset CreateSharedString(string s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
return new StringOffset(0);
|
||||
}
|
||||
|
||||
if (_sharedStringMap == null)
|
||||
{
|
||||
_sharedStringMap = new Dictionary<string, StringOffset>();
|
||||
|
||||
@@ -19,7 +19,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace FlatBuffers
|
||||
namespace Google.FlatBuffers
|
||||
{
|
||||
public static class FlatBufferConstants
|
||||
{
|
||||
@@ -32,6 +32,6 @@ namespace FlatBuffers
|
||||
Changes to the C# implementation need to be sure to change
|
||||
the version here and in the code generator on every possible
|
||||
incompatible change */
|
||||
public static void FLATBUFFERS_1_11_1() {}
|
||||
public static void FLATBUFFERS_24_3_25() {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,822 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
using System;
|
||||
using System.Reflection;using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Google.FlatBuffers
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The Class of the Verifier Options
|
||||
/// </summary>
|
||||
public class Options
|
||||
{
|
||||
public const int DEFAULT_MAX_DEPTH = 64;
|
||||
public const int DEFAULT_MAX_TABLES = 1000000;
|
||||
|
||||
private int max_depth = 0;
|
||||
private int max_tables = 0;
|
||||
private bool string_end_check = false;
|
||||
private bool alignment_check = false;
|
||||
|
||||
public Options()
|
||||
{
|
||||
max_depth = DEFAULT_MAX_DEPTH;
|
||||
max_tables = DEFAULT_MAX_TABLES;
|
||||
string_end_check = true;
|
||||
alignment_check = true;
|
||||
}
|
||||
|
||||
public Options(int maxDepth, int maxTables, bool stringEndCheck, bool alignmentCheck)
|
||||
{
|
||||
max_depth = maxDepth;
|
||||
max_tables = maxTables;
|
||||
string_end_check = stringEndCheck;
|
||||
alignment_check = alignmentCheck;
|
||||
}
|
||||
/// <summary> Maximum depth of nested tables allowed in a valid flatbuffer. </summary>
|
||||
public int maxDepth
|
||||
{
|
||||
get { return max_depth; }
|
||||
set { max_depth = value; }
|
||||
}
|
||||
/// <summary> Maximum number of tables allowed in a valid flatbuffer. </summary>
|
||||
public int maxTables
|
||||
{
|
||||
get { return max_tables; }
|
||||
set { max_tables = value; }
|
||||
}
|
||||
/// <summary> Check that string contains its null terminator </summary>
|
||||
public bool stringEndCheck
|
||||
{
|
||||
get { return string_end_check; }
|
||||
set { string_end_check = value; }
|
||||
}
|
||||
/// <summary> Check alignment of elements </summary>
|
||||
public bool alignmentCheck
|
||||
{
|
||||
get { return alignment_check; }
|
||||
set { alignment_check = value; }
|
||||
}
|
||||
}
|
||||
|
||||
public struct checkElementStruct
|
||||
{
|
||||
public bool elementValid;
|
||||
public uint elementOffset;
|
||||
}
|
||||
|
||||
public delegate bool VerifyTableAction(Verifier verifier, uint tablePos);
|
||||
public delegate bool VerifyUnionAction(Verifier verifier, byte typeId, uint tablePos);
|
||||
|
||||
/// <summary>
|
||||
/// The Main Class of the FlatBuffer Verifier
|
||||
/// </summary>
|
||||
public class Verifier
|
||||
{
|
||||
private ByteBuffer verifier_buffer = null;
|
||||
private Options verifier_options = null;
|
||||
private int depth_cnt = 0;
|
||||
private int num_tables_cnt = 0;
|
||||
|
||||
public const int SIZE_BYTE = 1;
|
||||
public const int SIZE_INT = 4;
|
||||
public const int SIZE_U_OFFSET = 4;
|
||||
public const int SIZE_S_OFFSET = 4;
|
||||
public const int SIZE_V_OFFSET = 2;
|
||||
public const int SIZE_PREFIX_LENGTH = FlatBufferConstants.SizePrefixLength; // default size = 4
|
||||
public const int FLATBUFFERS_MAX_BUFFER_SIZE = System.Int32.MaxValue; // default size = 2147483647
|
||||
public const int FILE_IDENTIFIER_LENGTH = FlatBufferConstants.FileIdentifierLength; // default size = 4
|
||||
|
||||
/// <summary> The Base Constructor of the Verifier object </summary>
|
||||
public Verifier()
|
||||
{
|
||||
// Verifier buffer
|
||||
verifier_buffer = null;
|
||||
// Verifier settings
|
||||
verifier_options = null;
|
||||
// Depth counter
|
||||
depth_cnt = 0;
|
||||
// Tables counter
|
||||
num_tables_cnt = 0;
|
||||
}
|
||||
|
||||
/// <summary> The Constructor of the Verifier object with input parameters: ByteBuffer and/or Options </summary>
|
||||
/// <param name="buf"> Input flat byte buffer defined as ByteBuffer type</param>
|
||||
/// <param name="options"> Options object with settings for the coniguration the Verifier </param>
|
||||
public Verifier(ByteBuffer buf, Options options = null)
|
||||
{
|
||||
verifier_buffer = buf;
|
||||
verifier_options = options ?? new Options();
|
||||
depth_cnt = 0;
|
||||
num_tables_cnt = 0;
|
||||
}
|
||||
|
||||
/// <summary> Bytes Buffer for Verify</summary>
|
||||
public ByteBuffer Buf
|
||||
{
|
||||
get { return verifier_buffer; }
|
||||
set { verifier_buffer = value; }
|
||||
}
|
||||
/// <summary> Options of the Verifier </summary>
|
||||
public Options options
|
||||
{
|
||||
get { return verifier_options; }
|
||||
set { verifier_options = value; }
|
||||
}
|
||||
/// <summary> Counter of tables depth in a tested flatbuffer </summary>
|
||||
public int depth
|
||||
{
|
||||
get { return depth_cnt; }
|
||||
set { depth_cnt = value; }
|
||||
}
|
||||
/// <summary> Counter of tables in a tested flatbuffer </summary>
|
||||
public int numTables
|
||||
{
|
||||
get { return num_tables_cnt; }
|
||||
set { num_tables_cnt = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Method set maximum tables depth of valid structure</summary>
|
||||
/// <param name="value"> Specify Value of the maximum depth of the structure</param>
|
||||
public Verifier SetMaxDepth(int value)
|
||||
{
|
||||
verifier_options.maxDepth = value;
|
||||
return this;
|
||||
}
|
||||
/// <summary> Specify maximum number of tables in structure </summary>
|
||||
/// <param name="value"> Specify Value of the maximum number of the tables in the structure</param>
|
||||
public Verifier SetMaxTables(int value)
|
||||
{
|
||||
verifier_options.maxTables = value;
|
||||
return this;
|
||||
}
|
||||
/// <summary> Enable/disable buffer content alignment check </summary>
|
||||
/// <param name="value"> Value of the State for buffer content alignment check (Enable = true) </param>
|
||||
public Verifier SetAlignmentCheck(bool value)
|
||||
{
|
||||
verifier_options.alignmentCheck = value;
|
||||
return this;
|
||||
}
|
||||
/// <summary> Enable/disable checking of string termination '0' character </summary>
|
||||
/// <param name="value"> Value of the option for string termination '0' character check (Enable = true)</param>
|
||||
public Verifier SetStringCheck(bool value)
|
||||
{
|
||||
verifier_options.stringEndCheck = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary> Check if there is identifier in buffer </summary>
|
||||
/// <param name="buf"> Input flat byte buffer defined as ByteBuffer type </param>
|
||||
/// <param name="startPos">Start position of data in the Byte Buffer</param>
|
||||
/// <param name="identifier"> Identifier for the Byte Buffer</param>
|
||||
/// <returns> Return True when the Byte Buffer Identifier is present</returns>
|
||||
private bool BufferHasIdentifier(ByteBuffer buf, uint startPos, string identifier)
|
||||
{
|
||||
if (identifier.Length != FILE_IDENTIFIER_LENGTH)
|
||||
{
|
||||
throw new ArgumentException("FlatBuffers: file identifier must be length" + Convert.ToString(FILE_IDENTIFIER_LENGTH));
|
||||
}
|
||||
for (int i = 0; i < FILE_IDENTIFIER_LENGTH; i++)
|
||||
{
|
||||
if ((sbyte)identifier[i] != verifier_buffer.GetSbyte(Convert.ToInt32(SIZE_S_OFFSET + i + startPos)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary> Get UOffsetT from buffer at given position - it must be verified before read </summary>
|
||||
/// <param name="buf"> Input flat byte buffer defined as ByteBuffer type </param>
|
||||
/// <param name="pos"> Position of data in the Byte Buffer</param>
|
||||
/// <returns> Return the UOffset Value (Unsigned Integer type - 4 bytes) in pos </returns>
|
||||
private uint ReadUOffsetT(ByteBuffer buf, uint pos)
|
||||
{
|
||||
return buf.GetUint(Convert.ToInt32(pos));
|
||||
}
|
||||
/// <summary> Get SOffsetT from buffer at given position - it must be verified before read </summary>
|
||||
/// <param name="buf"> Input flat byte buffer defined as ByteBuffer type </param>
|
||||
/// <param name="pos"> Position of data in the Byte Buffer</param>
|
||||
/// <returns> Return the SOffset Value (Signed Integer type - 4 bytes) in pos </returns>
|
||||
private int ReadSOffsetT(ByteBuffer buf, int pos)
|
||||
{
|
||||
return buf.GetInt(pos);
|
||||
}
|
||||
/// <summary> Get VOffsetT from buffer at given position - it must be verified before read </summary>
|
||||
/// <param name="buf"> Input flat byte buffer defined as ByteBuffer type </param>
|
||||
/// <param name="pos"> Position of data in the Byte Buffer</param>
|
||||
/// <returns> Return the VOffset Value (Short type - 2 bytes) in pos </returns>
|
||||
private short ReadVOffsetT(ByteBuffer buf, int pos)
|
||||
{
|
||||
return buf.GetShort(pos);
|
||||
}
|
||||
|
||||
/// <summary> Get table data area relative offset from vtable. Result is relative to table start
|
||||
/// Fields which are deprecated are ignored by checking against the vtable's length. </summary>
|
||||
/// <param name="pos"> Position of data in the Byte Buffer </param>
|
||||
/// <param name="vtableOffset"> offset of value in the Table</param>
|
||||
/// <returns> Return the relative VOffset Value (Short type - 2 bytes) in calculated offset </returns>
|
||||
private short GetVRelOffset(int pos, short vtableOffset)
|
||||
{
|
||||
short VOffset = 0;
|
||||
// Used try/catch because pos typa as int 32bit
|
||||
try
|
||||
{
|
||||
// First, get vtable offset
|
||||
short vtable = Convert.ToInt16(pos - ReadSOffsetT(verifier_buffer, pos));
|
||||
// Check that offset points to vtable area (is smaller than vtable size)
|
||||
if (vtableOffset < ReadVOffsetT(verifier_buffer, vtable))
|
||||
{
|
||||
// Now, we can read offset value - TODO check this value against size of table data
|
||||
VOffset = ReadVOffsetT(verifier_buffer, vtable + vtableOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
VOffset = 0;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Exception: {0}", e);
|
||||
return VOffset;
|
||||
}
|
||||
return VOffset;
|
||||
|
||||
}
|
||||
/// <summary> Get table data area absolute offset from vtable. Result is the absolute buffer offset.
|
||||
/// The result value offset cannot be '0' (pointing to itself) so after validation this method returnes '0'
|
||||
/// value as a marker for missing optional entry </summary>
|
||||
/// <param name="tablePos"> Table Position value in the Byte Buffer </param>
|
||||
/// <param name="vtableOffset"> offset value in the Table</param>
|
||||
/// <returns> Return the absolute UOffset Value </returns>
|
||||
private uint GetVOffset(uint tablePos, short vtableOffset)
|
||||
{
|
||||
uint UOffset = 0;
|
||||
// First, get vtable relative offset
|
||||
short relPos = GetVRelOffset(Convert.ToInt32(tablePos), vtableOffset);
|
||||
if (relPos != 0)
|
||||
{
|
||||
// Calculate offset based on table postion
|
||||
UOffset = Convert.ToUInt32(tablePos + relPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
UOffset = 0;
|
||||
}
|
||||
return UOffset;
|
||||
}
|
||||
|
||||
/// <summary> Check flatbuffer complexity (tables depth, elements counter and so on) </summary>
|
||||
/// <returns> If complexity is too high function returns false as verification error </returns>
|
||||
private bool CheckComplexity()
|
||||
{
|
||||
return ((depth <= options.maxDepth) && (numTables <= options.maxTables));
|
||||
}
|
||||
|
||||
/// <summary> Check alignment of element. </summary>
|
||||
/// <returns> Return True when alignment of the element is correct</returns>
|
||||
private bool CheckAlignment(uint element, ulong align)
|
||||
{
|
||||
return (((element & (align - 1)) == 0) || (!options.alignmentCheck));
|
||||
}
|
||||
|
||||
/// <summary> Check if element is valid in buffer area. </summary>
|
||||
/// <param name="pos"> Value defines the offset/position to element</param>
|
||||
/// <param name="elementSize"> Size of element</param>
|
||||
/// <returns> Return True when Element is correct </returns>
|
||||
private bool CheckElement(uint pos, ulong elementSize)
|
||||
{
|
||||
return ((elementSize < Convert.ToUInt64(verifier_buffer.Length)) && (pos <= (Convert.ToUInt32(verifier_buffer.Length) - elementSize)));
|
||||
}
|
||||
/// <summary> Check if element is a valid scalar. </summary>
|
||||
/// <param name="pos"> Value defines the offset to scalar</param>
|
||||
/// <param name="elementSize"> Size of element</param>
|
||||
/// <returns> Return True when Scalar Element is correct </returns>
|
||||
private bool CheckScalar(uint pos, ulong elementSize)
|
||||
{
|
||||
return ((CheckAlignment(pos, elementSize)) && (CheckElement(pos, elementSize)));
|
||||
}
|
||||
/// <summary> Check offset. It is a scalar with size of UOffsetT. </summary>
|
||||
private bool CheckOffset(uint offset)
|
||||
{
|
||||
return (CheckScalar(offset, SIZE_U_OFFSET));
|
||||
}
|
||||
|
||||
private checkElementStruct CheckVectorOrString(uint pos, ulong elementSize)
|
||||
{
|
||||
var result = new checkElementStruct
|
||||
{
|
||||
elementValid = false,
|
||||
elementOffset = 0
|
||||
};
|
||||
|
||||
uint vectorPos = pos;
|
||||
// Check we can read the vector/string size field (it is of uoffset size)
|
||||
if (!CheckScalar(vectorPos, SIZE_U_OFFSET))
|
||||
{
|
||||
// result.elementValid = false; result.elementOffset = 0;
|
||||
return result;
|
||||
}
|
||||
// Check the whole array. If this is a string, the byte past the array
|
||||
// must be 0.
|
||||
uint size = ReadUOffsetT(verifier_buffer, vectorPos);
|
||||
ulong max_elements = (FLATBUFFERS_MAX_BUFFER_SIZE / elementSize);
|
||||
if (size >= max_elements)
|
||||
{
|
||||
// Protect against byte_size overflowing.
|
||||
// result.elementValid = false; result.elementOffset = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint bytes_size = SIZE_U_OFFSET + (Convert.ToUInt32(elementSize) * size);
|
||||
uint buffer_end_pos = vectorPos + bytes_size;
|
||||
result.elementValid = CheckElement(vectorPos, bytes_size);
|
||||
result.elementOffset = buffer_end_pos;
|
||||
return (result);
|
||||
}
|
||||
|
||||
/// <summary>Verify a string at given position.</summary>
|
||||
private bool CheckString(uint pos)
|
||||
{
|
||||
var result = CheckVectorOrString(pos, SIZE_BYTE);
|
||||
if (options.stringEndCheck)
|
||||
{
|
||||
result.elementValid = result.elementValid && CheckScalar(result.elementOffset, 1); // Must have terminator
|
||||
result.elementValid = result.elementValid && (verifier_buffer.GetSbyte(Convert.ToInt32(result.elementOffset)) == 0); // Terminating byte must be 0.
|
||||
}
|
||||
return result.elementValid;
|
||||
}
|
||||
|
||||
/// <summary> Verify the vector of elements of given size </summary>
|
||||
private bool CheckVector(uint pos, ulong elementSize)
|
||||
{
|
||||
var result = CheckVectorOrString(pos, elementSize);
|
||||
return result.elementValid;
|
||||
}
|
||||
/// <summary> Verify table content using structure dependent generated function </summary>
|
||||
private bool CheckTable(uint tablePos, VerifyTableAction verifyAction)
|
||||
{
|
||||
return verifyAction(this, tablePos);
|
||||
}
|
||||
|
||||
/// <summary> String check wrapper function to be used in vector of strings check </summary>
|
||||
private bool CheckStringFunc(Verifier verifier, uint pos)
|
||||
{
|
||||
return verifier.CheckString(pos);
|
||||
}
|
||||
|
||||
/// <summary> Check vector of objects. Use generated object verification function </summary>
|
||||
private bool CheckVectorOfObjects(uint pos, VerifyTableAction verifyAction)
|
||||
{
|
||||
if (!CheckVector(pos, SIZE_U_OFFSET))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uint size = ReadUOffsetT(verifier_buffer, pos);
|
||||
// Vector data starts just after vector size/length
|
||||
uint vecStart = pos + SIZE_U_OFFSET;
|
||||
uint vecOff = 0;
|
||||
// Iterate offsets and verify referenced objects
|
||||
for (uint i = 0; i < size; i++)
|
||||
{
|
||||
vecOff = vecStart + (i * SIZE_U_OFFSET);
|
||||
if (!CheckIndirectOffset(vecOff))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uint objOffset = GetIndirectOffset(vecOff);
|
||||
if (!verifyAction(this, objOffset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary> Check if the offset referenced by offsetPos is the valid offset pointing to buffer</summary>
|
||||
// offsetPos - offset to offset data
|
||||
private bool CheckIndirectOffset(uint pos)
|
||||
{
|
||||
// Check the input offset is valid
|
||||
if(!CheckScalar(pos, SIZE_U_OFFSET))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Get indirect offset
|
||||
uint offset = ReadUOffsetT(verifier_buffer, pos);
|
||||
// May not point to itself neither wrap around (buffers are max 2GB)
|
||||
if ((offset == 0) || (offset >= FLATBUFFERS_MAX_BUFFER_SIZE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Must be inside the buffer
|
||||
return CheckElement(pos + offset, 1);
|
||||
}
|
||||
|
||||
/// <summary> Check flatbuffer content using generated object verification function </summary>
|
||||
private bool CheckBufferFromStart(string identifier, uint startPos, VerifyTableAction verifyAction)
|
||||
{
|
||||
if ((identifier != null) &&
|
||||
(identifier.Length == 0) &&
|
||||
((verifier_buffer.Length < (SIZE_U_OFFSET + FILE_IDENTIFIER_LENGTH)) || (!BufferHasIdentifier(verifier_buffer, startPos, identifier))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(!CheckIndirectOffset(startPos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uint offset = GetIndirectOffset(startPos);
|
||||
return CheckTable(offset, verifyAction); // && GetComputedSize()
|
||||
}
|
||||
|
||||
/// <summary> Get indirect offset. It is an offset referenced by offset Pos </summary>
|
||||
private uint GetIndirectOffset(uint pos)
|
||||
{
|
||||
// Get indirect offset referenced by offsetPos
|
||||
uint offset = pos + ReadUOffsetT(verifier_buffer, pos);
|
||||
return offset;
|
||||
}
|
||||
|
||||
/// <summary> Verify beginning of table </summary>
|
||||
/// <param name="tablePos"> Position in the Table </param>
|
||||
/// <returns> Return True when the verification of the beginning of the table is passed</returns>
|
||||
// (this method is used internally by generated verification functions)
|
||||
public bool VerifyTableStart(uint tablePos)
|
||||
{
|
||||
// Starting new table verification increases complexity of structure
|
||||
depth_cnt++;
|
||||
num_tables_cnt++;
|
||||
|
||||
if (!CheckScalar(tablePos, SIZE_S_OFFSET))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uint vtable = (uint)(tablePos - ReadSOffsetT(verifier_buffer, Convert.ToInt32(tablePos)));
|
||||
return ((CheckComplexity()) && (CheckScalar(vtable, SIZE_V_OFFSET)) && (CheckAlignment(Convert.ToUInt32(ReadVOffsetT(verifier_buffer, Convert.ToInt32(vtable))), SIZE_V_OFFSET)) && (CheckElement(vtable, Convert.ToUInt64(ReadVOffsetT(verifier_buffer, Convert.ToInt32(vtable))))));
|
||||
}
|
||||
|
||||
/// <summary> Verify end of table. In practice, this function does not check buffer but handles
|
||||
/// verification statistics update </summary>
|
||||
// (this method is used internally by generated verification functions)
|
||||
public bool VerifyTableEnd(uint tablePos)
|
||||
{
|
||||
depth--;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary> Verifiy static/inlined data area field </summary>
|
||||
/// <param name="tablePos"> Position in the Table</param>
|
||||
/// <param name="offsetId"> Offset to the static/inlined data element </param>
|
||||
/// <param name="elementSize"> Size of the element </param>
|
||||
/// <param name="align"> Alignment bool value </param>
|
||||
/// <param name="required"> Required Value when the offset == 0 </param>
|
||||
/// <returns>Return True when the verification of the static/inlined data element is passed</returns>
|
||||
// (this method is used internally by generated verification functions)
|
||||
public bool VerifyField(uint tablePos, short offsetId, ulong elementSize, ulong align, bool required)
|
||||
{
|
||||
uint offset = GetVOffset(tablePos, offsetId);
|
||||
if (offset != 0)
|
||||
{
|
||||
return ((CheckAlignment(offset, align)) && (CheckElement(offset, elementSize)));
|
||||
}
|
||||
return !required; // it is OK if field is not required
|
||||
}
|
||||
|
||||
/// <summary> Verify string </summary>
|
||||
/// <param name="tablePos"> Position in the Table</param>
|
||||
/// <param name="vOffset"> Offset to the String element </param>
|
||||
/// <param name="required"> Required Value when the offset == 0 </param>
|
||||
/// <returns>Return True when the verification of the String is passed</returns>
|
||||
// (this method is used internally by generated verification functions)
|
||||
public bool VerifyString(uint tablePos, short vOffset, bool required)
|
||||
{
|
||||
var offset = GetVOffset(tablePos, vOffset);
|
||||
if (offset == 0)
|
||||
{
|
||||
return !required;
|
||||
}
|
||||
if (!CheckIndirectOffset(offset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var strOffset = GetIndirectOffset(offset);
|
||||
return CheckString(strOffset);
|
||||
}
|
||||
|
||||
/// <summary> Verify vector of fixed size structures and scalars </summary>
|
||||
/// <param name="tablePos"> Position in the Table</param>
|
||||
/// <param name="vOffset"> Offset to the Vector of Data </param>
|
||||
/// <param name="elementSize"> Size of the element</param>
|
||||
/// <param name="required"> Required Value when the offset == 0 </param>
|
||||
/// <returns>Return True when the verification of the Vector of Data passed</returns>
|
||||
// (this method is used internally by generated verification functions)
|
||||
public bool VerifyVectorOfData(uint tablePos, short vOffset, ulong elementSize, bool required)
|
||||
{
|
||||
var offset = GetVOffset(tablePos, vOffset);
|
||||
if (offset == 0)
|
||||
{
|
||||
return !required;
|
||||
}
|
||||
if (!CheckIndirectOffset(offset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var vecOffset = GetIndirectOffset(offset);
|
||||
return CheckVector(vecOffset, elementSize);
|
||||
}
|
||||
|
||||
/// <summary> Verify array of strings </summary>
|
||||
/// <param name="tablePos"> Position in the Table</param>
|
||||
/// <param name="offsetId"> Offset to the Vector of String </param>
|
||||
/// <param name="required"> Required Value when the offset == 0 </param>
|
||||
/// <returns>Return True when the verification of the Vector of String passed</returns>
|
||||
// (this method is used internally by generated verification functions)
|
||||
public bool VerifyVectorOfStrings(uint tablePos, short offsetId, bool required)
|
||||
{
|
||||
var offset = GetVOffset(tablePos, offsetId);
|
||||
if (offset == 0)
|
||||
{
|
||||
return !required;
|
||||
}
|
||||
if (!CheckIndirectOffset(offset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var vecOffset = GetIndirectOffset(offset);
|
||||
return CheckVectorOfObjects(vecOffset, CheckStringFunc);
|
||||
}
|
||||
|
||||
/// <summary> Verify vector of tables (objects). Tables are verified using generated verifyObjFunc </summary>
|
||||
/// <param name="tablePos"> Position in the Table</param>
|
||||
/// <param name="offsetId"> Offset to the Vector of Table </param>
|
||||
/// <param name="verifyAction"> Method used to the verification Table </param>
|
||||
/// <param name="required"> Required Value when the offset == 0 </param>
|
||||
/// <returns>Return True when the verification of the Vector of Table passed</returns>
|
||||
// (this method is used internally by generated verification functions)
|
||||
public bool VerifyVectorOfTables(uint tablePos, short offsetId, VerifyTableAction verifyAction, bool required)
|
||||
{
|
||||
var offset = GetVOffset(tablePos, offsetId);
|
||||
if (offset == 0)
|
||||
{
|
||||
return !required;
|
||||
}
|
||||
if (!CheckIndirectOffset(offset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var vecOffset = GetIndirectOffset(offset);
|
||||
return CheckVectorOfObjects(vecOffset, verifyAction);
|
||||
}
|
||||
|
||||
/// <summary> Verify table object using generated verification function. </summary>
|
||||
/// <param name="tablePos"> Position in the Table</param>
|
||||
/// <param name="offsetId"> Offset to the Table </param>
|
||||
/// <param name="verifyAction"> Method used to the verification Table </param>
|
||||
/// <param name="required"> Required Value when the offset == 0 </param>
|
||||
/// <returns>Return True when the verification of the Table passed</returns>
|
||||
// (this method is used internally by generated verification functions)
|
||||
public bool VerifyTable(uint tablePos, short offsetId, VerifyTableAction verifyAction, bool required)
|
||||
{
|
||||
var offset = GetVOffset(tablePos, offsetId);
|
||||
if (offset == 0)
|
||||
{
|
||||
return !required;
|
||||
}
|
||||
if (!CheckIndirectOffset(offset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var tabOffset = GetIndirectOffset(offset);
|
||||
return CheckTable(tabOffset, verifyAction);
|
||||
}
|
||||
|
||||
/// <summary> Verify nested buffer object. When verifyObjFunc is provided, it is used to verify object structure. </summary>
|
||||
/// <param name="tablePos"> Position in the Table </param>
|
||||
/// <param name="offsetId"> Offset to the Table </param>
|
||||
/// <param name="verifyAction"> Method used to the verification Table </param>
|
||||
/// <param name="required"> Required Value when the offset == 0 </param>
|
||||
// (this method is used internally by generated verification functions)
|
||||
public bool VerifyNestedBuffer(uint tablePos, short offsetId, VerifyTableAction verifyAction, bool required)
|
||||
{
|
||||
var offset = GetVOffset(tablePos, offsetId);
|
||||
if (offset == 0)
|
||||
{
|
||||
return !required;
|
||||
}
|
||||
uint vecOffset = GetIndirectOffset(offset);
|
||||
if (!CheckVector(vecOffset, SIZE_BYTE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (verifyAction != null)
|
||||
{
|
||||
var vecLength = ReadUOffsetT(verifier_buffer, vecOffset);
|
||||
// Buffer begins after vector length
|
||||
var vecStart = vecOffset + SIZE_U_OFFSET;
|
||||
// Create and Copy nested buffer bytes from part of Verify Buffer
|
||||
var nestedByteBuffer = new ByteBuffer(verifier_buffer.ToArray(Convert.ToInt32(vecStart), Convert.ToInt32(vecLength)));
|
||||
var nestedVerifyier = new Verifier(nestedByteBuffer, options);
|
||||
// There is no internal identifier - use empty one
|
||||
if (!nestedVerifyier.CheckBufferFromStart("", 0, verifyAction))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary> Verifiy static/inlined data area at absolute offset </summary>
|
||||
/// <param name="pos"> Position of static/inlined data area in the Byte Buffer</param>
|
||||
/// <param name="elementSize"> Size of the union data</param>
|
||||
/// <param name="align"> Alignment bool value </param>
|
||||
/// <returns>Return True when the verification of the Union Data is passed</returns>
|
||||
// (this method is used internally by generated verification functions)
|
||||
public bool VerifyUnionData(uint pos, ulong elementSize, ulong align)
|
||||
{
|
||||
bool result = ((CheckAlignment(pos, align)) && (CheckElement(pos, elementSize)));
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary> Verify string referenced by absolute offset value </summary>
|
||||
/// <param name="pos"> Position of Union String in the Byte Buffer</param>
|
||||
/// <returns>Return True when the verification of the Union String is passed</returns>
|
||||
// (this method is used internally by generated verification functions)
|
||||
public bool VerifyUnionString(uint pos)
|
||||
{
|
||||
bool result = CheckString(pos);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary> Method verifies union object using generated verification function </summary>
|
||||
/// <param name="tablePos"> Position in the Table</param>
|
||||
/// <param name="typeIdVOffset"> Offset in the Table</param>
|
||||
/// <param name="valueVOffset"> Offset to Element</param>
|
||||
/// <param name="verifyAction"> Verification Method used for Union</param>
|
||||
/// <param name="required"> Required Value when the offset == 0 </param>
|
||||
// (this method is used internally by generated verification functions)
|
||||
public bool VerifyUnion(uint tablePos, short typeIdVOffset, short valueVOffset, VerifyUnionAction verifyAction, bool required)
|
||||
{
|
||||
// Check the union type index
|
||||
var offset = GetVOffset(tablePos, typeIdVOffset);
|
||||
if (offset == 0)
|
||||
{
|
||||
return !required;
|
||||
}
|
||||
if (!((CheckAlignment(offset, SIZE_BYTE)) && (CheckElement(offset, SIZE_BYTE))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Check union data
|
||||
offset = GetVOffset(tablePos, valueVOffset);
|
||||
// Take type id
|
||||
var typeId = verifier_buffer.Get(Convert.ToInt32(offset));
|
||||
if (offset == 0)
|
||||
{
|
||||
// When value data is not present, allow union verification function to deal with illegal offset
|
||||
return verifyAction(this, typeId, Convert.ToUInt32(verifier_buffer.Length));
|
||||
}
|
||||
if (!CheckIndirectOffset(offset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Take value offset and validate union structure
|
||||
uint unionOffset = GetIndirectOffset(offset);
|
||||
return verifyAction(this, typeId, unionOffset);
|
||||
}
|
||||
|
||||
/// <summary> Verify vector of unions (objects). Unions are verified using generated verifyObjFunc </summary>
|
||||
/// <param name="tablePos"> Position of the Table</param>
|
||||
/// <param name="typeOffsetId"> Offset in the Table (Union type id)</param>
|
||||
/// <param name="offsetId"> Offset to vector of Data Stucture offset</param>
|
||||
/// <param name="verifyAction"> Verification Method used for Union</param>
|
||||
/// <param name="required"> Required Value when the offset == 0 </param>
|
||||
/// <returns>Return True when the verification of the Vector of Unions passed</returns>
|
||||
// (this method is used internally by generated verification functions)
|
||||
public bool VerifyVectorOfUnion(uint tablePos, short typeOffsetId, short offsetId, VerifyUnionAction verifyAction, bool required)
|
||||
{
|
||||
// type id offset must be valid
|
||||
var offset = GetVOffset(tablePos, typeOffsetId);
|
||||
if (offset == 0)
|
||||
{
|
||||
return !required;
|
||||
}
|
||||
if (!CheckIndirectOffset(offset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Get type id table absolute offset
|
||||
var typeIdVectorOffset = GetIndirectOffset(offset);
|
||||
// values offset must be valid
|
||||
offset = GetVOffset(tablePos, offsetId);
|
||||
if (!CheckIndirectOffset(offset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var valueVectorOffset = GetIndirectOffset(offset);
|
||||
// validate referenced vectors
|
||||
if(!CheckVector(typeIdVectorOffset, SIZE_BYTE) ||
|
||||
!CheckVector(valueVectorOffset, SIZE_U_OFFSET))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Both vectors should have the same length
|
||||
var typeIdVectorLength = ReadUOffsetT(verifier_buffer, typeIdVectorOffset);
|
||||
var valueVectorLength = ReadUOffsetT(verifier_buffer, valueVectorOffset);
|
||||
if (typeIdVectorLength != valueVectorLength)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Verify each union from vectors
|
||||
var typeIdStart = typeIdVectorOffset + SIZE_U_OFFSET;
|
||||
var valueStart = valueVectorOffset + SIZE_U_OFFSET;
|
||||
for (uint i = 0; i < typeIdVectorLength; i++)
|
||||
{
|
||||
// Get type id
|
||||
byte typeId = verifier_buffer.Get(Convert.ToInt32(typeIdStart + i * SIZE_U_OFFSET));
|
||||
// get offset to vector item
|
||||
uint off = valueStart + i * SIZE_U_OFFSET;
|
||||
// Check the vector item has a proper offset
|
||||
if (!CheckIndirectOffset(off))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uint valueOffset = GetIndirectOffset(off);
|
||||
// Verify object
|
||||
if (!verifyAction(this, typeId, valueOffset))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Method verifies flatbuffer data using generated Table verification function.
|
||||
// The data buffer is already provided when creating [Verifier] object (see [NewVerifier])
|
||||
//
|
||||
// - identifier - the expected identifier of buffer data.
|
||||
// When empty identifier is provided the identifier validation is skipped.
|
||||
// - sizePrefixed - this flag should be true when buffer is prefixed with content size
|
||||
// - verifyObjFunc - function to be used for verification. This function is generated by compiler and included in each table definition file with name "<Tablename>Verify"
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// /* Verify Monster table. Ignore buffer name and assume buffer does not contain data length prefix */
|
||||
// isValid = verifier.verifyBuffer(bb, false, MonsterVerify)
|
||||
//
|
||||
// /* Verify Monster table. Buffer name is 'MONS' and contains data length prefix */
|
||||
// isValid = verifier.verifyBuffer("MONS", true, MonsterVerify)
|
||||
/// <summary> Method verifies flatbuffer data using generated Table verification function </summary>
|
||||
///
|
||||
/// <param name="identifier"> The expected identifier of buffer data</param>
|
||||
/// <param name="sizePrefixed"> Flag should be true when buffer is prefixed with content size</param>
|
||||
/// <param name="verifyAction"> Function to be used for verification. This function is generated by compiler and included in each table definition file</param>
|
||||
/// <returns> Return True when verification of FlatBuffer passed</returns>
|
||||
/// <example>
|
||||
/// Example 1. Verify Monster table. Ignore buffer name and assume buffer does not contain data length prefix
|
||||
/// <code> isValid = verifier.VerifyBuffer(bb, false, MonsterVerify)</code>
|
||||
/// Example 2. Verify Monster table. Buffer name is 'MONS' and contains data length prefix
|
||||
/// <code> isValid = verifier.VerifyBuffer("MONS", true, MonsterVerify)</code>
|
||||
/// </example>
|
||||
public bool VerifyBuffer(string identifier, bool sizePrefixed, VerifyTableAction verifyAction)
|
||||
{
|
||||
// Reset counters - starting verification from beginning
|
||||
depth = 0;
|
||||
numTables = 0;
|
||||
|
||||
var start = (uint)(verifier_buffer.Position);
|
||||
if (sizePrefixed)
|
||||
{
|
||||
start = (uint)(verifier_buffer.Position) + SIZE_PREFIX_LENGTH;
|
||||
if(!CheckScalar((uint)(verifier_buffer.Position), SIZE_PREFIX_LENGTH))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uint size = ReadUOffsetT(verifier_buffer, (uint)(verifier_buffer.Position));
|
||||
if (size != ((uint)(verifier_buffer.Length) - start))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return CheckBufferFromStart(identifier, start, verifyAction);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Properties\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Remove="Properties\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Properties\**" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,54 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{28C00774-1E73-4A75-AD8F-844CD21A064D}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>FlatBuffers</RootNamespace>
|
||||
<AssemblyName>FlatBuffers</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ByteBuffer.cs" />
|
||||
<Compile Include="FlatBufferBuilder.cs" />
|
||||
<Compile Include="FlatBufferConstants.cs" />
|
||||
<Compile Include="IFlatbufferObject.cs" />
|
||||
<Compile Include="Offset.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Struct.cs" />
|
||||
<Compile Include="Table.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,42 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.1;net6.0;net8.0</TargetFrameworks>
|
||||
<Description>A cross-platform memory efficient serialization library</Description>
|
||||
<PackageVersion>24.3.25</PackageVersion>
|
||||
<Authors>Google LLC</Authors>
|
||||
<PackageProjectUrl>https://github.com/google/flatbuffers</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/google/flatbuffers</RepositoryUrl>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageIcon>flatbuffers.png</PackageIcon>
|
||||
<PackageTags>Google;FlatBuffers;Serialization;Buffer;Binary;zero copy</PackageTags>
|
||||
<Copyright>Copyright 2022 Google LLC</Copyright>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>flatbuffers.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(UNSAFE_BYTEBUFFER)' == 'true'">
|
||||
<DefineConstants>$(DefineConstants);UNSAFE_BYTEBUFFER</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(BYTEBUFFER_NO_BOUNDS_CHECK)' == 'true'">
|
||||
<DefineConstants>$(DefineConstants);BYTEBUFFER_NO_BOUNDS_CHECK</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(ENABLE_SPAN_T)' == 'true'">
|
||||
<DefineConstants>$(DefineConstants);ENABLE_SPAN_T</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\..\LICENSE" Pack="true" PackagePath="" />
|
||||
<None Include="flatbuffers.png" Pack="true" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace FlatBuffers
|
||||
namespace Google.FlatBuffers
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the base for both structs and tables.
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace FlatBuffers
|
||||
namespace Google.FlatBuffers
|
||||
{
|
||||
/// <summary>
|
||||
/// Offset class for typesafe assignments.
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("FlatBuffers")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("FlatBuffers")]
|
||||
[assembly: AssemblyCopyright("Copyright (c) 2015 Google Inc")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("91c32e64-ef20-47df-9c9f-cec9207bc6df")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
+2
-2
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace FlatBuffers
|
||||
namespace Google.FlatBuffers
|
||||
{
|
||||
/// <summary>
|
||||
/// All structs in the generated code derive from this class, and add their own accessors.
|
||||
@@ -25,7 +25,7 @@ namespace FlatBuffers
|
||||
public ByteBuffer bb { get; private set; }
|
||||
|
||||
// Re-init the internal state with an external buffer {@code ByteBuffer} and an offset within.
|
||||
public Struct(int _i, ByteBuffer _bb)
|
||||
public Struct(int _i, ByteBuffer _bb) : this()
|
||||
{
|
||||
bb = _bb;
|
||||
bb_pos = _i;
|
||||
|
||||
+19
-9
@@ -16,8 +16,9 @@
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace FlatBuffers
|
||||
namespace Google.FlatBuffers
|
||||
{
|
||||
/// <summary>
|
||||
/// All tables in the generated code derive from this struct, and add their own accessors.
|
||||
@@ -30,7 +31,7 @@ namespace FlatBuffers
|
||||
public ByteBuffer ByteBuffer { get { return bb; } }
|
||||
|
||||
// Re-init the internal state with an external buffer {@code ByteBuffer} and an offset within.
|
||||
public Table(int _i, ByteBuffer _bb)
|
||||
public Table(int _i, ByteBuffer _bb) : this()
|
||||
{
|
||||
bb = _bb;
|
||||
bb_pos = _i;
|
||||
@@ -64,7 +65,11 @@ namespace FlatBuffers
|
||||
// Create a .NET String from UTF-8 data stored inside the flatbuffer.
|
||||
public string __string(int offset)
|
||||
{
|
||||
offset += bb.GetInt(offset);
|
||||
int stringOffset = bb.GetInt(offset);
|
||||
if (stringOffset == 0)
|
||||
return null;
|
||||
|
||||
offset += stringOffset;
|
||||
var len = bb.GetInt(offset);
|
||||
var startPos = offset + sizeof(int);
|
||||
return bb.GetStringUTF8(startPos, len);
|
||||
@@ -85,21 +90,27 @@ namespace FlatBuffers
|
||||
return offset + bb.GetInt(offset) + sizeof(int); // data starts after the length
|
||||
}
|
||||
|
||||
#if ENABLE_SPAN_T
|
||||
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
|
||||
// Get the data of a vector whoses offset is stored at "offset" in this object as an
|
||||
// Spant<byte>. If the vector is not present in the ByteBuffer,
|
||||
// then an empty span will be returned.
|
||||
public Span<byte> __vector_as_span(int offset)
|
||||
public Span<T> __vector_as_span<T>(int offset, int elementSize) where T : struct
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
throw new NotSupportedException("Getting typed span on a Big Endian " +
|
||||
"system is not support");
|
||||
}
|
||||
|
||||
var o = this.__offset(offset);
|
||||
if (0 == o)
|
||||
{
|
||||
return new Span<byte>();
|
||||
return new Span<T>();
|
||||
}
|
||||
|
||||
var pos = this.__vector(o);
|
||||
var len = this.__vector_len(o);
|
||||
return bb.ToSpan(pos, len);
|
||||
return MemoryMarshal.Cast<byte, T>(bb.ToSpan(pos, len * elementSize));
|
||||
}
|
||||
#else
|
||||
// Get the data of a vector whoses offset is stored at "offset" in this object as an
|
||||
@@ -145,9 +156,8 @@ namespace FlatBuffers
|
||||
// Initialize any Table-derived type to point to the union at the given offset.
|
||||
public T __union<T>(int offset) where T : struct, IFlatbufferObject
|
||||
{
|
||||
offset += bb_pos;
|
||||
T t = new T();
|
||||
t.__init(offset + bb.GetInt(offset), bb);
|
||||
t.__init(__indirect(offset), bb);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
Binary file not shown.
Reference in New Issue
Block a user