using System;
using System.Text;
using System.Runtime.InteropServices;
namespace Google.FlatBuffers
{
public struct Table
{
public int bb_pos { get; private set; }
public ByteBuffer bb { get; private set; }
public ByteBuffer ByteBuffer { get { return bb; } }
public Table(int _i, ByteBuffer _bb) : this()
{
bb = _bb;
bb_pos = _i;
}
public int __offset(int vtableOffset)
{
int vtable = bb_pos - bb.GetInt(bb_pos);
return vtableOffset < bb.GetShort(vtable) ? (int)bb.GetShort(vtable + vtableOffset) : 0;
}
public static int __offset(int vtableOffset, int offset, ByteBuffer bb)
{
int vtable = bb.Length - offset;
return (int)bb.GetShort(vtable + vtableOffset - bb.GetInt(vtable)) + vtable;
}
public int __indirect(int offset)
{
return offset + bb.GetInt(offset);
}
public static int __indirect(int offset, ByteBuffer bb)
{
return offset + bb.GetInt(offset);
}
public string __string(int 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);
}
public int __vector_len(int offset)
{
offset += bb_pos;
offset += bb.GetInt(offset);
return bb.GetInt(offset);
}
public int __vector(int offset)
{
offset += bb_pos;
return offset + bb.GetInt(offset) + sizeof(int); }
#if ENABLE_SPAN_T && UNSAFE_BYTEBUFFER
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<T>();
}
var pos = this.__vector(o);
var len = this.__vector_len(o);
return MemoryMarshal.Cast<byte, T>(bb.ToSpan(pos, len * elementSize));
}
#else
public ArraySegment<byte>? __vector_as_arraysegment(int offset)
{
var o = this.__offset(offset);
if (0 == o)
{
return null;
}
var pos = this.__vector(o);
var len = this.__vector_len(o);
return bb.ToArraySegment(pos, len);
}
#endif
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);
}
public T __union<T>(int offset) where T : struct, IFlatbufferObject
{
T t = new T();
t.__init(__indirect(offset), bb);
return t;
}
public static bool __has_identifier(ByteBuffer bb, string ident)
{
if (ident.Length != FlatBufferConstants.FileIdentifierLength)
throw new ArgumentException("FlatBuffers: file identifier must be length " + FlatBufferConstants.FileIdentifierLength, "ident");
for (var i = 0; i < FlatBufferConstants.FileIdentifierLength; i++)
{
if (ident[i] != (char)bb.Get(bb.Position + sizeof(int) + i)) return false;
}
return true;
}
public static int CompareStrings(int offset_1, int offset_2, ByteBuffer bb)
{
offset_1 += bb.GetInt(offset_1);
offset_2 += bb.GetInt(offset_2);
var len_1 = bb.GetInt(offset_1);
var len_2 = bb.GetInt(offset_2);
var startPos_1 = offset_1 + sizeof(int);
var startPos_2 = offset_2 + sizeof(int);
var len = Math.Min(len_1, len_2);
for(int i = 0; i < len; i++) {
byte b1 = bb.Get(i + startPos_1);
byte b2 = bb.Get(i + startPos_2);
if (b1 != b2)
return b1 - b2;
}
return len_1 - len_2;
}
public static int CompareStrings(int offset_1, byte[] key, ByteBuffer bb)
{
offset_1 += bb.GetInt(offset_1);
var len_1 = bb.GetInt(offset_1);
var len_2 = key.Length;
var startPos_1 = offset_1 + sizeof(int);
var len = Math.Min(len_1, len_2);
for (int i = 0; i < len; i++) {
byte b = bb.Get(i + startPos_1);
if (b != key[i])
return b - key[i];
}
return len_1 - len_2;
}
}
}