Use google flatbuffers for some waterbox core communication

Nyma cores have to move some big complex structs on init and it's annoying and error prone.  This solution is not fast, but these are one time transfers anyway, and it does keep code size and saved size down.  Architecture yay.
This commit is contained in:
nattthebear 2020-05-28 20:24:03 -04:00
parent 5a0992c2b7
commit de25b53fe2
58 changed files with 16468 additions and 554 deletions

View File

@ -0,0 +1,891 @@
/*
* 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.
*/
// There are 3 #defines that have an impact on performance / features of this ByteBuffer implementation
//
// 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..
//
// ENABLE_SPAN_T
// This will enable reading and writing blocks of memory with a Span<T> instead if 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
//
// Using UNSAFE_BYTEBUFFER and BYTEBUFFER_NO_BOUNDS_CHECK together can yield a
// performance gain of ~15% for some operations, however doing so is potentially
// dangerous. Do so at your own risk!
//
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
#if ENABLE_SPAN_T
using System.Buffers.Binary;
#endif
#if ENABLE_SPAN_T && !UNSAFE_BYTEBUFFER
#error ENABLE_SPAN_T requires UNSAFE_BYTEBUFFER to also be defined
#endif
namespace FlatBuffers
{
public abstract class ByteBufferAllocator
{
#if ENABLE_SPAN_T
public abstract Span<byte> Span { get; }
public abstract ReadOnlySpan<byte> ReadOnlySpan { get; }
public abstract Memory<byte> Memory { get; }
public abstract ReadOnlyMemory<byte> ReadOnlyMemory { get; }
#else
public byte[] Buffer
{
get;
protected set;
}
#endif
public int Length
{
get;
protected set;
}
public abstract void GrowFront(int newSize);
}
public sealed class ByteArrayAllocator : ByteBufferAllocator
{
private byte[] _buffer;
public ByteArrayAllocator(byte[] buffer)
{
_buffer = buffer;
InitBuffer();
}
public override void GrowFront(int newSize)
{
if ((Length & 0xC0000000) != 0)
throw new Exception(
"ByteBuffer: cannot grow buffer beyond 2 gigabytes.");
if (newSize < Length)
throw new Exception("ByteBuffer: cannot truncate buffer.");
byte[] newBuffer = new byte[newSize];
System.Buffer.BlockCopy(_buffer, 0, newBuffer, newSize - Length, Length);
_buffer = newBuffer;
InitBuffer();
}
#if ENABLE_SPAN_T
public override Span<byte> Span => _buffer;
public override ReadOnlySpan<byte> ReadOnlySpan => _buffer;
public override Memory<byte> Memory => _buffer;
public override ReadOnlyMemory<byte> ReadOnlyMemory => _buffer;
#endif
private void InitBuffer()
{
Length = _buffer.Length;
#if !ENABLE_SPAN_T
Buffer = _buffer;
#endif
}
}
/// <summary>
/// Class to mimic Java's ByteBuffer which is used heavily in Flatbuffers.
/// </summary>
public class ByteBuffer
{
private ByteBufferAllocator _buffer;
private int _pos; // Must track start of the buffer.
public ByteBuffer(ByteBufferAllocator allocator, int position)
{
_buffer = allocator;
_pos = position;
}
public ByteBuffer(int size) : this(new byte[size]) { }
public ByteBuffer(byte[] buffer) : this(buffer, 0) { }
public ByteBuffer(byte[] buffer, int pos)
{
_buffer = new ByteArrayAllocator(buffer);
_pos = pos;
}
public int Position
{
get { return _pos; }
set { _pos = value; }
}
public int Length { get { return _buffer.Length; } }
public void Reset()
{
_pos = 0;
}
// Create a new ByteBuffer on the same underlying data.
// The new ByteBuffer's position will be same as this buffer's.
public ByteBuffer Duplicate()
{
return new ByteBuffer(_buffer, Position);
}
// Increases the size of the ByteBuffer, and copies the old data towards
// the end of the new buffer.
public void GrowFront(int newSize)
{
_buffer.GrowFront(newSize);
}
public byte[] ToArray(int pos, int 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;
}
#if ENABLE_SPAN_T
public static int ArraySize<T>(Span<T> x)
{
return SizeOf<T>() * x.Length;
}
#endif
// Get a portion of the buffer casted into an array of type T, given
// the buffer position and length.
#if ENABLE_SPAN_T
public T[] ToArray<T>(int pos, int len)
where T : struct
{
AssertOffsetAndLength(pos, len);
return MemoryMarshal.Cast<byte, T>(_buffer.ReadOnlySpan.Slice(pos)).Slice(0, len).ToArray();
}
#else
public T[] ToArray<T>(int pos, int len)
where T : struct
{
AssertOffsetAndLength(pos, len);
T[] arr = new T[len];
Buffer.BlockCopy(_buffer.Buffer, pos, arr, 0, ArraySize(arr));
return arr;
}
#endif
public byte[] ToSizedArray()
{
return ToArray<byte>(Position, Length - Position);
}
public byte[] ToFullArray()
{
return ToArray<byte>(0, Length);
}
#if ENABLE_SPAN_T
public ReadOnlyMemory<byte> ToReadOnlyMemory(int pos, int len)
{
return _buffer.ReadOnlyMemory.Slice(pos, len);
}
public Memory<byte> ToMemory(int pos, int len)
{
return _buffer.Memory.Slice(pos, len);
}
public Span<byte> ToSpan(int pos, int len)
{
return _buffer.Span.Slice(pos, len);
}
#else
public ArraySegment<byte> ToArraySegment(int pos, int len)
{
return new ArraySegment<byte>(_buffer.Buffer, pos, len);
}
public MemoryStream ToMemoryStream(int pos, int len)
{
return new MemoryStream(_buffer.Buffer, pos, len);
}
#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 };
#endif // !UNSAFE_BYTEBUFFER
// Helper functions for the unsafe version.
static public ushort ReverseBytes(ushort input)
{
return (ushort)(((input & 0x00FFU) << 8) |
((input & 0xFF00U) >> 8));
}
static public uint ReverseBytes(uint input)
{
return ((input & 0x000000FFU) << 24) |
((input & 0x0000FF00U) << 8) |
((input & 0x00FF0000U) >> 8) |
((input & 0xFF000000U) >> 24);
}
static public ulong ReverseBytes(ulong input)
{
return (((input & 0x00000000000000FFUL) << 56) |
((input & 0x000000000000FF00UL) << 40) |
((input & 0x0000000000FF0000UL) << 24) |
((input & 0x00000000FF000000UL) << 8) |
((input & 0x000000FF00000000UL) >> 8) |
((input & 0x0000FF0000000000UL) >> 24) |
((input & 0x00FF000000000000UL) >> 40) |
((input & 0xFF00000000000000UL) >> 56));
}
#if !UNSAFE_BYTEBUFFER
// Helper functions for the safe (but slower) version.
protected void WriteLittleEndian(int offset, int count, ulong data)
{
if (BitConverter.IsLittleEndian)
{
for (int i = 0; i < count; i++)
{
_buffer.Buffer[offset + i] = (byte)(data >> i * 8);
}
}
else
{
for (int i = 0; i < count; i++)
{
_buffer.Buffer[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.Buffer[offset + i] << i * 8;
}
}
else
{
for (int i = 0; i < count; i++)
{
r |= (ulong)_buffer.Buffer[offset + count - 1 - i] << i * 8;
}
}
return r;
}
#endif // !UNSAFE_BYTEBUFFER
private void AssertOffsetAndLength(int offset, int length)
{
#if !BYTEBUFFER_NO_BOUNDS_CHECK
if (offset < 0 ||
offset > _buffer.Length - length)
throw new ArgumentOutOfRangeException();
#endif
}
#if ENABLE_SPAN_T
public void PutSbyte(int offset, sbyte value)
{
AssertOffsetAndLength(offset, sizeof(sbyte));
_buffer.Span[offset] = (byte)value;
}
public void PutByte(int offset, byte value)
{
AssertOffsetAndLength(offset, sizeof(byte));
_buffer.Span[offset] = value;
}
public void PutByte(int offset, byte value, int count)
{
AssertOffsetAndLength(offset, sizeof(byte) * count);
Span<byte> span = _buffer.Span.Slice(offset, count);
for (var i = 0; i < span.Length; ++i)
span[i] = value;
}
#else
public void PutSbyte(int offset, sbyte value)
{
AssertOffsetAndLength(offset, sizeof(sbyte));
_buffer.Buffer[offset] = (byte)value;
}
public void PutByte(int offset, byte value)
{
AssertOffsetAndLength(offset, sizeof(byte));
_buffer.Buffer[offset] = value;
}
public void PutByte(int offset, byte value, int count)
{
AssertOffsetAndLength(offset, sizeof(byte) * count);
for (var i = 0; i < count; ++i)
_buffer.Buffer[offset + i] = value;
}
#endif
// this method exists in order to conform with Java ByteBuffer standards
public void Put(int offset, byte value)
{
PutByte(offset, value);
}
#if ENABLE_SPAN_T
public unsafe void PutStringUTF8(int offset, string value)
{
AssertOffsetAndLength(offset, value.Length);
fixed (char* s = value)
{
fixed (byte* buffer = &MemoryMarshal.GetReference(_buffer.Span))
{
Encoding.UTF8.GetBytes(s, value.Length, buffer + offset, Length - offset);
}
}
}
#else
public void PutStringUTF8(int offset, string value)
{
AssertOffsetAndLength(offset, value.Length);
Encoding.UTF8.GetBytes(value, 0, value.Length,
_buffer.Buffer, offset);
}
#endif
#if UNSAFE_BYTEBUFFER
// Unsafe but more efficient versions of Put*.
public void PutShort(int offset, short value)
{
PutUshort(offset, (ushort)value);
}
public unsafe void PutUshort(int offset, ushort value)
{
AssertOffsetAndLength(offset, sizeof(ushort));
#if ENABLE_SPAN_T
Span<byte> span = _buffer.Span.Slice(offset);
BinaryPrimitives.WriteUInt16LittleEndian(span, value);
#else
fixed (byte* ptr = _buffer.Buffer)
{
*(ushort*)(ptr + offset) = BitConverter.IsLittleEndian
? value
: ReverseBytes(value);
}
#endif
}
public void PutInt(int offset, int value)
{
PutUint(offset, (uint)value);
}
public unsafe void PutUint(int offset, uint value)
{
AssertOffsetAndLength(offset, sizeof(uint));
#if ENABLE_SPAN_T
Span<byte> span = _buffer.Span.Slice(offset);
BinaryPrimitives.WriteUInt32LittleEndian(span, value);
#else
fixed (byte* ptr = _buffer.Buffer)
{
*(uint*)(ptr + offset) = BitConverter.IsLittleEndian
? value
: ReverseBytes(value);
}
#endif
}
public unsafe void PutLong(int offset, long value)
{
PutUlong(offset, (ulong)value);
}
public unsafe void PutUlong(int offset, ulong value)
{
AssertOffsetAndLength(offset, sizeof(ulong));
#if ENABLE_SPAN_T
Span<byte> span = _buffer.Span.Slice(offset);
BinaryPrimitives.WriteUInt64LittleEndian(span, value);
#else
fixed (byte* ptr = _buffer.Buffer)
{
*(ulong*)(ptr + offset) = BitConverter.IsLittleEndian
? value
: ReverseBytes(value);
}
#endif
}
public unsafe void PutFloat(int offset, float value)
{
AssertOffsetAndLength(offset, sizeof(float));
#if ENABLE_SPAN_T
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.Span))
#else
fixed (byte* ptr = _buffer.Buffer)
#endif
{
if (BitConverter.IsLittleEndian)
{
*(float*)(ptr + offset) = value;
}
else
{
*(uint*)(ptr + offset) = ReverseBytes(*(uint*)(&value));
}
}
}
public unsafe void PutDouble(int offset, double value)
{
AssertOffsetAndLength(offset, sizeof(double));
#if ENABLE_SPAN_T
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.Span))
#else
fixed (byte* ptr = _buffer.Buffer)
#endif
{
if (BitConverter.IsLittleEndian)
{
*(double*)(ptr + offset) = value;
}
else
{
*(ulong*)(ptr + offset) = ReverseBytes(*(ulong*)(&value));
}
}
}
#else // !UNSAFE_BYTEBUFFER
// Slower versions of Put* for when unsafe code is not allowed.
public void PutShort(int offset, short value)
{
AssertOffsetAndLength(offset, sizeof(short));
WriteLittleEndian(offset, sizeof(short), (ulong)value);
}
public void PutUshort(int offset, ushort value)
{
AssertOffsetAndLength(offset, sizeof(ushort));
WriteLittleEndian(offset, sizeof(ushort), (ulong)value);
}
public void PutInt(int offset, int value)
{
AssertOffsetAndLength(offset, sizeof(int));
WriteLittleEndian(offset, sizeof(int), (ulong)value);
}
public void PutUint(int offset, uint value)
{
AssertOffsetAndLength(offset, sizeof(uint));
WriteLittleEndian(offset, sizeof(uint), (ulong)value);
}
public void PutLong(int offset, long value)
{
AssertOffsetAndLength(offset, sizeof(long));
WriteLittleEndian(offset, sizeof(long), (ulong)value);
}
public void PutUlong(int offset, ulong value)
{
AssertOffsetAndLength(offset, sizeof(ulong));
WriteLittleEndian(offset, sizeof(ulong), value);
}
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]);
}
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]);
}
#endif // UNSAFE_BYTEBUFFER
#if ENABLE_SPAN_T
public sbyte GetSbyte(int index)
{
AssertOffsetAndLength(index, sizeof(sbyte));
return (sbyte)_buffer.ReadOnlySpan[index];
}
public byte Get(int index)
{
AssertOffsetAndLength(index, sizeof(byte));
return _buffer.ReadOnlySpan[index];
}
#else
public sbyte GetSbyte(int index)
{
AssertOffsetAndLength(index, sizeof(sbyte));
return (sbyte)_buffer.Buffer[index];
}
public byte Get(int index)
{
AssertOffsetAndLength(index, sizeof(byte));
return _buffer.Buffer[index];
}
#endif
#if ENABLE_SPAN_T
public unsafe string GetStringUTF8(int startPos, int len)
{
fixed (byte* buffer = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan.Slice(startPos)))
{
return Encoding.UTF8.GetString(buffer, len);
}
}
#else
public string GetStringUTF8(int startPos, int len)
{
return Encoding.UTF8.GetString(_buffer.Buffer, startPos, len);
}
#endif
#if UNSAFE_BYTEBUFFER
// Unsafe but more efficient versions of Get*.
public short GetShort(int offset)
{
return (short)GetUshort(offset);
}
public unsafe ushort GetUshort(int offset)
{
AssertOffsetAndLength(offset, sizeof(ushort));
#if ENABLE_SPAN_T
ReadOnlySpan<byte> span = _buffer.ReadOnlySpan.Slice(offset);
return BinaryPrimitives.ReadUInt16LittleEndian(span);
#else
fixed (byte* ptr = _buffer.Buffer)
{
return BitConverter.IsLittleEndian
? *(ushort*)(ptr + offset)
: ReverseBytes(*(ushort*)(ptr + offset));
}
#endif
}
public int GetInt(int offset)
{
return (int)GetUint(offset);
}
public unsafe uint GetUint(int offset)
{
AssertOffsetAndLength(offset, sizeof(uint));
#if ENABLE_SPAN_T
ReadOnlySpan<byte> span = _buffer.ReadOnlySpan.Slice(offset);
return BinaryPrimitives.ReadUInt32LittleEndian(span);
#else
fixed (byte* ptr = _buffer.Buffer)
{
return BitConverter.IsLittleEndian
? *(uint*)(ptr + offset)
: ReverseBytes(*(uint*)(ptr + offset));
}
#endif
}
public long GetLong(int offset)
{
return (long)GetUlong(offset);
}
public unsafe ulong GetUlong(int offset)
{
AssertOffsetAndLength(offset, sizeof(ulong));
#if ENABLE_SPAN_T
ReadOnlySpan<byte> span = _buffer.ReadOnlySpan.Slice(offset);
return BinaryPrimitives.ReadUInt64LittleEndian(span);
#else
fixed (byte* ptr = _buffer.Buffer)
{
return BitConverter.IsLittleEndian
? *(ulong*)(ptr + offset)
: ReverseBytes(*(ulong*)(ptr + offset));
}
#endif
}
public unsafe float GetFloat(int offset)
{
AssertOffsetAndLength(offset, sizeof(float));
#if ENABLE_SPAN_T
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan))
#else
fixed (byte* ptr = _buffer.Buffer)
#endif
{
if (BitConverter.IsLittleEndian)
{
return *(float*)(ptr + offset);
}
else
{
uint uvalue = ReverseBytes(*(uint*)(ptr + offset));
return *(float*)(&uvalue);
}
}
}
public unsafe double GetDouble(int offset)
{
AssertOffsetAndLength(offset, sizeof(double));
#if ENABLE_SPAN_T
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan))
#else
fixed (byte* ptr = _buffer.Buffer)
#endif
{
if (BitConverter.IsLittleEndian)
{
return *(double*)(ptr + offset);
}
else
{
ulong uvalue = ReverseBytes(*(ulong*)(ptr + offset));
return *(double*)(&uvalue);
}
}
}
#else // !UNSAFE_BYTEBUFFER
// Slower versions of Get* for when unsafe code is not allowed.
public short GetShort(int index)
{
return (short)ReadLittleEndian(index, sizeof(short));
}
public ushort GetUshort(int index)
{
return (ushort)ReadLittleEndian(index, sizeof(ushort));
}
public int GetInt(int index)
{
return (int)ReadLittleEndian(index, sizeof(int));
}
public uint GetUint(int index)
{
return (uint)ReadLittleEndian(index, sizeof(uint));
}
public long GetLong(int index)
{
return (long)ReadLittleEndian(index, sizeof(long));
}
public ulong GetUlong(int index)
{
return ReadLittleEndian(index, sizeof(ulong));
}
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];
}
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];
}
#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
#if ENABLE_SPAN_T
MemoryMarshal.Cast<T, byte>(x).CopyTo(_buffer.Span.Slice(offset, numBytes));
#else
Buffer.BlockCopy(x, 0, _buffer.Buffer, offset, numBytes);
#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
public int Put<T>(int offset, Span<T> x)
where T : struct
{
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
MemoryMarshal.Cast<T, byte>(x).CopyTo(_buffer.Span.Slice(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;
}
#endif
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright 2017 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;
namespace FlatBuffers
{
/// <summary>
/// Class that collects utility functions around `ByteBuffer`.
/// </summary>
public class ByteBufferUtil
{
// Extract the size prefix from a `ByteBuffer`.
public static int GetSizePrefix(ByteBuffer bb) {
return bb.GetInt(bb.Position);
}
// Create a duplicate of a size-prefixed `ByteBuffer` that has its position
// advanced just past the size prefix.
public static ByteBuffer RemoveSizePrefix(ByteBuffer bb) {
ByteBuffer s = bb.Duplicate();
s.Position += FlatBufferConstants.SizePrefixLength;
return s;
}
}
}

View File

@ -0,0 +1,842 @@
/*
* 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.Collections.Generic;
using System.Text;
/// @file
/// @addtogroup flatbuffers_csharp_api
/// @{
namespace FlatBuffers
{
/// <summary>
/// Responsible for building up and accessing a FlatBuffer formatted byte
/// array (via ByteBuffer).
/// </summary>
public class FlatBufferBuilder
{
private int _space;
private ByteBuffer _bb;
private int _minAlign = 1;
// The vtable for the current table (if _vtableSize >= 0)
private int[] _vtable = new int[16];
// The size of the vtable. -1 indicates no vtable
private int _vtableSize = -1;
// Starting offset of the current struct/table.
private int _objectStart;
// List of offsets of all vtables.
private int[] _vtables = new int[16];
// Number of entries in `vtables` in use.
private int _numVtables = 0;
// For the current vector being built.
private int _vectorNumElems = 0;
// For CreateSharedString
private Dictionary<string, StringOffset> _sharedStringMap = null;
/// <summary>
/// Create a FlatBufferBuilder with a given initial size.
/// </summary>
/// <param name="initialSize">
/// The initial size to use for the internal buffer.
/// </param>
public FlatBufferBuilder(int initialSize)
{
if (initialSize <= 0)
throw new ArgumentOutOfRangeException("initialSize",
initialSize, "Must be greater than zero");
_space = initialSize;
_bb = new ByteBuffer(initialSize);
}
/// <summary>
/// Create a FlatBufferBuilder backed by the pased in ByteBuffer
/// </summary>
/// <param name="buffer">The ByteBuffer to write to</param>
public FlatBufferBuilder(ByteBuffer buffer)
{
_bb = buffer;
_space = buffer.Length;
buffer.Reset();
}
/// <summary>
/// Reset the FlatBufferBuilder by purging all data that it holds.
/// </summary>
public void Clear()
{
_space = _bb.Length;
_bb.Reset();
_minAlign = 1;
while (_vtableSize > 0) _vtable[--_vtableSize] = 0;
_vtableSize = -1;
_objectStart = 0;
_numVtables = 0;
_vectorNumElems = 0;
}
/// <summary>
/// Gets and sets a Boolean to disable the optimization when serializing
/// default values to a Table.
///
/// In order to save space, fields that are set to their default value
/// don't get serialized into the buffer.
/// </summary>
public bool ForceDefaults { get; set; }
/// @cond FLATBUFFERS_INTERNAL
public int Offset { get { return _bb.Length - _space; } }
public void Pad(int size)
{
_bb.PutByte(_space -= size, 0, size);
}
// Doubles the size of the ByteBuffer, and copies the old data towards
// the end of the new buffer (since we build the buffer backwards).
void GrowBuffer()
{
_bb.GrowFront(_bb.Length << 1);
}
// Prepare to write an element of `size` after `additional_bytes`
// have been written, e.g. if you write a string, you need to align
// such the int length field is aligned to SIZEOF_INT, and the string
// data follows it directly.
// If all you need to do is align, `additional_bytes` will be 0.
public void Prep(int size, int additionalBytes)
{
// Track the biggest thing we've ever aligned to.
if (size > _minAlign)
_minAlign = size;
// Find the amount of alignment needed such that `size` is properly
// aligned after `additional_bytes`
var alignSize =
((~((int)_bb.Length - _space + additionalBytes)) + 1) &
(size - 1);
// Reallocate the buffer if needed.
while (_space < alignSize + size + additionalBytes)
{
var oldBufSize = (int)_bb.Length;
GrowBuffer();
_space += (int)_bb.Length - oldBufSize;
}
if (alignSize > 0)
Pad(alignSize);
}
public void PutBool(bool x)
{
_bb.PutByte(_space -= sizeof(byte), (byte)(x ? 1 : 0));
}
public void PutSbyte(sbyte x)
{
_bb.PutSbyte(_space -= sizeof(sbyte), x);
}
public void PutByte(byte x)
{
_bb.PutByte(_space -= sizeof(byte), x);
}
public void PutShort(short x)
{
_bb.PutShort(_space -= sizeof(short), x);
}
public void PutUshort(ushort x)
{
_bb.PutUshort(_space -= sizeof(ushort), x);
}
public void PutInt(int x)
{
_bb.PutInt(_space -= sizeof(int), x);
}
public void PutUint(uint x)
{
_bb.PutUint(_space -= sizeof(uint), x);
}
public void PutLong(long x)
{
_bb.PutLong(_space -= sizeof(long), x);
}
public void PutUlong(ulong x)
{
_bb.PutUlong(_space -= sizeof(ulong), x);
}
public void PutFloat(float x)
{
_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);
}
#if ENABLE_SPAN_T
/// <summary>
/// Puts a span 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 span to copy data from</param>
public void Put<T>(Span<T> x)
where T : struct
{
_space = _bb.Put(_space, x);
}
#endif
public void PutDouble(double x)
{
_bb.PutDouble(_space -= sizeof(double), x);
}
/// @endcond
/// <summary>
/// Add a `bool` to the buffer (aligns the data and grows if necessary).
/// </summary>
/// <param name="x">The `bool` to add to the buffer.</param>
public void AddBool(bool x) { Prep(sizeof(byte), 0); PutBool(x); }
/// <summary>
/// Add a `sbyte` to the buffer (aligns the data and grows if necessary).
/// </summary>
/// <param name="x">The `sbyte` to add to the buffer.</param>
public void AddSbyte(sbyte x) { Prep(sizeof(sbyte), 0); PutSbyte(x); }
/// <summary>
/// Add a `byte` to the buffer (aligns the data and grows if necessary).
/// </summary>
/// <param name="x">The `byte` to add to the buffer.</param>
public void AddByte(byte x) { Prep(sizeof(byte), 0); PutByte(x); }
/// <summary>
/// Add a `short` to the buffer (aligns the data and grows if necessary).
/// </summary>
/// <param name="x">The `short` to add to the buffer.</param>
public void AddShort(short x) { Prep(sizeof(short), 0); PutShort(x); }
/// <summary>
/// Add an `ushort` to the buffer (aligns the data and grows if necessary).
/// </summary>
/// <param name="x">The `ushort` to add to the buffer.</param>
public void AddUshort(ushort x) { Prep(sizeof(ushort), 0); PutUshort(x); }
/// <summary>
/// Add an `int` to the buffer (aligns the data and grows if necessary).
/// </summary>
/// <param name="x">The `int` to add to the buffer.</param>
public void AddInt(int x) { Prep(sizeof(int), 0); PutInt(x); }
/// <summary>
/// Add an `uint` to the buffer (aligns the data and grows if necessary).
/// </summary>
/// <param name="x">The `uint` to add to the buffer.</param>
public void AddUint(uint x) { Prep(sizeof(uint), 0); PutUint(x); }
/// <summary>
/// Add a `long` to the buffer (aligns the data and grows if necessary).
/// </summary>
/// <param name="x">The `long` to add to the buffer.</param>
public void AddLong(long x) { Prep(sizeof(long), 0); PutLong(x); }
/// <summary>
/// Add an `ulong` to the buffer (aligns the data and grows if necessary).
/// </summary>
/// <param name="x">The `ulong` to add to the buffer.</param>
public void AddUlong(ulong x) { Prep(sizeof(ulong), 0); PutUlong(x); }
/// <summary>
/// Add a `float` to the buffer (aligns the data and grows if necessary).
/// </summary>
/// <param name="x">The `float` to add to the buffer.</param>
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);
}
#if ENABLE_SPAN_T
/// <summary>
/// Add a span 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 span to copy data from</param>
public void Add<T>(Span<T> x)
where T : struct
{
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);
}
#endif
/// <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>
public void AddDouble(double x) { Prep(sizeof(double), 0);
PutDouble(x); }
/// <summary>
/// Adds an offset, relative to where it will be written.
/// </summary>
/// <param name="off">The offset to add to the buffer.</param>
public void AddOffset(int off)
{
Prep(sizeof(int), 0); // Ensure alignment is already done.
if (off > Offset)
throw new ArgumentException();
off = Offset - off + sizeof(int);
PutInt(off);
}
/// @cond FLATBUFFERS_INTERNAL
public void StartVector(int elemSize, int count, int alignment)
{
NotNested();
_vectorNumElems = count;
Prep(sizeof(int), elemSize * count);
Prep(alignment, elemSize * count); // Just in case alignment > int.
}
/// @endcond
/// <summary>
/// Writes data necessary to finish a vector construction.
/// </summary>
public VectorOffset EndVector()
{
PutInt(_vectorNumElems);
return new VectorOffset(Offset);
}
/// <summary>
/// Creates a vector of tables.
/// </summary>
/// <param name="offsets">Offsets of the tables.</param>
public VectorOffset CreateVectorOfTables<T>(Offset<T>[] offsets) where T : struct
{
NotNested();
StartVector(sizeof(int), offsets.Length, sizeof(int));
for (int i = offsets.Length - 1; i >= 0; i--) AddOffset(offsets[i].Value);
return EndVector();
}
/// @cond FLATBUFFERS_INTENRAL
public void Nested(int obj)
{
// Structs are always stored inline, so need to be created right
// where they are used. You'll get this assert if you created it
// elsewhere.
if (obj != Offset)
throw new Exception(
"FlatBuffers: struct must be serialized inline.");
}
public void NotNested()
{
// You should not be creating any other objects or strings/vectors
// while an object is being constructed
if (_vtableSize >= 0)
throw new Exception(
"FlatBuffers: object serialization must not be nested.");
}
public void StartTable(int numfields)
{
if (numfields < 0)
throw new ArgumentOutOfRangeException("Flatbuffers: invalid numfields");
NotNested();
if (_vtable.Length < numfields)
_vtable = new int[numfields];
_vtableSize = numfields;
_objectStart = Offset;
}
// Set the current vtable at `voffset` to the current location in the
// buffer.
public void Slot(int voffset)
{
if (voffset >= _vtableSize)
throw new IndexOutOfRangeException("Flatbuffers: invalid voffset");
_vtable[voffset] = Offset;
}
/// <summary>
/// Adds a Boolean to the Table at index `o` in its vtable using the value `x` and default `d`
/// </summary>
/// <param name="o">The index into the vtable</param>
/// <param name="x">The value to put into the buffer. If the value is equal to the default
/// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
/// <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 SByte to the Table at index `o` in its vtable using the value `x` and default `d`
/// </summary>
/// <param name="o">The index into the vtable</param>
/// <param name="x">The value to put into the buffer. If the value is equal to the default
/// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
/// <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 Byte to the Table at index `o` in its vtable using the value `x` and default `d`
/// </summary>
/// <param name="o">The index into the vtable</param>
/// <param name="x">The value to put into the buffer. If the value is equal to the default
/// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
/// <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 Int16 to the Table at index `o` in its vtable using the value `x` and default `d`
/// </summary>
/// <param name="o">The index into the vtable</param>
/// <param name="x">The value to put into the buffer. If the value is equal to the default
/// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
/// <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 UInt16 to the Table at index `o` in its vtable using the value `x` and default `d`
/// </summary>
/// <param name="o">The index into the vtable</param>
/// <param name="x">The value to put into the buffer. If the value is equal to the default
/// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
/// <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 an Int32 to the Table at index `o` in its vtable using the value `x` and default `d`
/// </summary>
/// <param name="o">The index into the vtable</param>
/// <param name="x">The value to put into the buffer. If the value is equal to the default
/// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
/// <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 UInt32 to the Table at index `o` in its vtable using the value `x` and default `d`
/// </summary>
/// <param name="o">The index into the vtable</param>
/// <param name="x">The value to put into the buffer. If the value is equal to the default
/// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
/// <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 an Int64 to the Table at index `o` in its vtable using the value `x` and default `d`
/// </summary>
/// <param name="o">The index into the vtable</param>
/// <param name="x">The value to put into the buffer. If the value is equal to the default
/// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
/// <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 UInt64 to the Table at index `o` in its vtable using the value `x` and default `d`
/// </summary>
/// <param name="o">The index into the vtable</param>
/// <param name="x">The value to put into the buffer. If the value is equal to the default
/// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
/// <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 Single to the Table at index `o` in its vtable using the value `x` and default `d`
/// </summary>
/// <param name="o">The index into the vtable</param>
/// <param name="x">The value to put into the buffer. If the value is equal to the default
/// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
/// <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 Double to the Table at index `o` in its vtable using the value `x` and default `d`
/// </summary>
/// <param name="o">The index into the vtable</param>
/// <param name="x">The value to put into the buffer. If the value is equal to the default
/// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
/// <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 buffer offset to the Table at index `o` in its vtable using the value `x` and default `d`
/// </summary>
/// <param name="o">The index into the vtable</param>
/// <param name="x">The value to put into the buffer. If the value is equal to the default
/// the value will be skipped.</param>
/// <param name="d">The default value to compare the value against</param>
public void AddOffset(int o, int x, int d) { if (x != d) { AddOffset(x); Slot(o); } }
/// @endcond
/// <summary>
/// Encode the string `s` in the buffer using UTF-8.
/// </summary>
/// <param name="s">The string to encode.</param>
/// <returns>
/// The offset in the buffer where the encoded string starts.
/// </returns>
public StringOffset CreateString(string s)
{
NotNested();
AddByte(0);
var utf8StringLen = Encoding.UTF8.GetByteCount(s);
StartVector(1, utf8StringLen, 1);
_bb.PutStringUTF8(_space -= utf8StringLen, s);
return new StringOffset(EndVector().Value);
}
#if ENABLE_SPAN_T
/// <summary>
/// Creates a string in the buffer from a Span containing
/// a UTF8 string.
/// </summary>
/// <param name="chars">the UTF8 string to add to the buffer</param>
/// <returns>
/// The offset in the buffer where the encoded string starts.
/// </returns>
public StringOffset CreateUTF8String(Span<byte> chars)
{
NotNested();
AddByte(0);
var utf8StringLen = chars.Length;
StartVector(1, utf8StringLen, 1);
_space = _bb.Put(_space, chars);
return new StringOffset(EndVector().Value);
}
#endif
/// <summary>
/// Store a string in the buffer, which can contain any binary data.
/// If a string with this exact contents has already been serialized before,
/// instead simply returns the offset of the existing string.
/// </summary>
/// <param name="s">The string to encode.</param>
/// <returns>
/// The offset in the buffer where the encoded string starts.
/// </returns>
public StringOffset CreateSharedString(string s)
{
if (_sharedStringMap == null)
{
_sharedStringMap = new Dictionary<string, StringOffset>();
}
if (_sharedStringMap.ContainsKey(s))
{
return _sharedStringMap[s];
}
var stringOffset = CreateString(s);
_sharedStringMap.Add(s, stringOffset);
return stringOffset;
}
/// @cond FLATBUFFERS_INTERNAL
// Structs are stored inline, so nothing additional is being added.
// `d` is always 0.
public void AddStruct(int voffset, int x, int d)
{
if (x != d)
{
Nested(x);
Slot(voffset);
}
}
public int EndTable()
{
if (_vtableSize < 0)
throw new InvalidOperationException(
"Flatbuffers: calling EndTable without a StartTable");
AddInt((int)0);
var vtableloc = Offset;
// Write out the current vtable.
int i = _vtableSize - 1;
// Trim trailing zeroes.
for (; i >= 0 && _vtable[i] == 0; i--) {}
int trimmedSize = i + 1;
for (; i >= 0 ; i--) {
// Offset relative to the start of the table.
short off = (short)(_vtable[i] != 0
? vtableloc - _vtable[i]
: 0);
AddShort(off);
// clear out written entry
_vtable[i] = 0;
}
const int standardFields = 2; // The fields below:
AddShort((short)(vtableloc - _objectStart));
AddShort((short)((trimmedSize + standardFields) *
sizeof(short)));
// Search for an existing vtable that matches the current one.
int existingVtable = 0;
for (i = 0; i < _numVtables; i++) {
int vt1 = _bb.Length - _vtables[i];
int vt2 = _space;
short len = _bb.GetShort(vt1);
if (len == _bb.GetShort(vt2)) {
for (int j = sizeof(short); j < len; j += sizeof(short)) {
if (_bb.GetShort(vt1 + j) != _bb.GetShort(vt2 + j)) {
goto endLoop;
}
}
existingVtable = _vtables[i];
break;
}
endLoop: { }
}
if (existingVtable != 0) {
// Found a match:
// Remove the current vtable.
_space = _bb.Length - vtableloc;
// Point table to existing vtable.
_bb.PutInt(_space, existingVtable - vtableloc);
} else {
// No match:
// Add the location of the current vtable to the list of
// vtables.
if (_numVtables == _vtables.Length)
{
// Arrays.CopyOf(vtables num_vtables * 2);
var newvtables = new int[ _numVtables * 2];
Array.Copy(_vtables, newvtables, _vtables.Length);
_vtables = newvtables;
};
_vtables[_numVtables++] = Offset;
// Point table to current vtable.
_bb.PutInt(_bb.Length - vtableloc, Offset - vtableloc);
}
_vtableSize = -1;
return vtableloc;
}
// This checks a required field has been set in a given table that has
// just been constructed.
public void Required(int table, int field)
{
int table_start = _bb.Length - table;
int vtable_start = table_start - _bb.GetInt(table_start);
bool ok = _bb.GetShort(vtable_start + field) != 0;
// If this fails, the caller will show what field needs to be set.
if (!ok)
throw new InvalidOperationException("FlatBuffers: field " + field +
" must be set");
}
/// @endcond
/// <summary>
/// Finalize a buffer, pointing to the given `root_table`.
/// </summary>
/// <param name="rootTable">
/// An offset to be added to the buffer.
/// </param>
/// <param name="sizePrefix">
/// Whether to prefix the size to the buffer.
/// </param>
protected void Finish(int rootTable, bool sizePrefix)
{
Prep(_minAlign, sizeof(int) + (sizePrefix ? sizeof(int) : 0));
AddOffset(rootTable);
if (sizePrefix) {
AddInt(_bb.Length - _space);
}
_bb.Position = _space;
}
/// <summary>
/// Finalize a buffer, pointing to the given `root_table`.
/// </summary>
/// <param name="rootTable">
/// An offset to be added to the buffer.
/// </param>
public void Finish(int rootTable)
{
Finish(rootTable, false);
}
/// <summary>
/// Finalize a buffer, pointing to the given `root_table`, with the size prefixed.
/// </summary>
/// <param name="rootTable">
/// An offset to be added to the buffer.
/// </param>
public void FinishSizePrefixed(int rootTable)
{
Finish(rootTable, true);
}
/// <summary>
/// Get the ByteBuffer representing the FlatBuffer.
/// </summary>
/// <remarks>
/// This is typically only called after you call `Finish()`.
/// The actual data starts at the ByteBuffer's current position,
/// not necessarily at `0`.
/// </remarks>
/// <returns>
/// Returns the ByteBuffer for this FlatBuffer.
/// </returns>
public ByteBuffer DataBuffer { get { return _bb; } }
/// <summary>
/// A utility function to copy and return the ByteBuffer data as a
/// `byte[]`.
/// </summary>
/// <returns>
/// A full copy of the FlatBuffer data.
/// </returns>
public byte[] SizedByteArray()
{
return _bb.ToSizedArray();
}
/// <summary>
/// Finalize a buffer, pointing to the given `rootTable`.
/// </summary>
/// <param name="rootTable">
/// An offset to be added to the buffer.
/// </param>
/// <param name="fileIdentifier">
/// A FlatBuffer file identifier to be added to the buffer before
/// `root_table`.
/// </param>
/// <param name="sizePrefix">
/// Whether to prefix the size to the buffer.
/// </param>
protected void Finish(int rootTable, string fileIdentifier, bool sizePrefix)
{
Prep(_minAlign, sizeof(int) + (sizePrefix ? sizeof(int) : 0) +
FlatBufferConstants.FileIdentifierLength);
if (fileIdentifier.Length !=
FlatBufferConstants.FileIdentifierLength)
throw new ArgumentException(
"FlatBuffers: file identifier must be length " +
FlatBufferConstants.FileIdentifierLength,
"fileIdentifier");
for (int i = FlatBufferConstants.FileIdentifierLength - 1; i >= 0;
i--)
{
AddByte((byte)fileIdentifier[i]);
}
Finish(rootTable, sizePrefix);
}
/// <summary>
/// Finalize a buffer, pointing to the given `rootTable`.
/// </summary>
/// <param name="rootTable">
/// An offset to be added to the buffer.
/// </param>
/// <param name="fileIdentifier">
/// A FlatBuffer file identifier to be added to the buffer before
/// `root_table`.
/// </param>
public void Finish(int rootTable, string fileIdentifier)
{
Finish(rootTable, fileIdentifier, false);
}
/// <summary>
/// Finalize a buffer, pointing to the given `rootTable`, with the size prefixed.
/// </summary>
/// <param name="rootTable">
/// An offset to be added to the buffer.
/// </param>
/// <param name="fileIdentifier">
/// A FlatBuffer file identifier to be added to the buffer before
/// `root_table`.
/// </param>
public void FinishSizePrefixed(int rootTable, string fileIdentifier)
{
Finish(rootTable, fileIdentifier, true);
}
}
}
/// @}

View File

@ -0,0 +1,37 @@
/*
* 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.Collections.Generic;
using System.Linq;
using System.Text;
namespace FlatBuffers
{
public static class FlatBufferConstants
{
public const int FileIdentifierLength = 4;
public const int SizePrefixLength = 4;
/** A version identifier to force a compile error if someone
accidentally tries to build generated code with a runtime of
two mismatched version. Versions need to always match, as
the runtime and generated code are modified in sync.
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_12_0() {}
}
}

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../src/MainSlnCommon.props" />
<ItemGroup>
<Compile Remove="Properties\**" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Remove="Properties\**" />
</ItemGroup>
<ItemGroup>
<None Remove="Properties\**" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,28 @@
/*
* 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.
*/
namespace FlatBuffers
{
/// <summary>
/// This is the base for both structs and tables.
/// </summary>
public interface IFlatbufferObject
{
void __init(int _i, ByteBuffer _bb);
ByteBuffer ByteBuffer { get; }
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.
*/
namespace FlatBuffers
{
/// <summary>
/// Offset class for typesafe assignments.
/// </summary>
public struct Offset<T> where T : struct
{
public int Value;
public Offset(int value)
{
Value = value;
}
}
public struct StringOffset
{
public int Value;
public StringOffset(int value)
{
Value = value;
}
}
public struct VectorOffset
{
public int Value;
public VectorOffset(int value)
{
Value = value;
}
}
}

View File

@ -0,0 +1,52 @@
/*
* 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")]

View File

@ -0,0 +1,34 @@
/*
* 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.
*/
namespace FlatBuffers
{
/// <summary>
/// All structs in the generated code derive from this class, and add their own accessors.
/// </summary>
public struct Struct
{
public int bb_pos { get; private set; }
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) : this()
{
bb = _bb;
bb_pos = _i;
}
}
}

View File

@ -0,0 +1,208 @@
/*
* 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.Text;
using System.Runtime.InteropServices;
namespace FlatBuffers
{
/// <summary>
/// All tables in the generated code derive from this struct, and add their own accessors.
/// </summary>
public struct Table
{
public int bb_pos { get; private set; }
public ByteBuffer bb { get; private set; }
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) : this()
{
bb = _bb;
bb_pos = _i;
}
// Look up a field in the vtable, return an offset into the object, or 0 if the field is not
// present.
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;
}
// Retrieve the relative offset stored at "offset"
public int __indirect(int offset)
{
return offset + bb.GetInt(offset);
}
public static int __indirect(int offset, ByteBuffer bb)
{
return offset + bb.GetInt(offset);
}
// Create a .NET String from UTF-8 data stored inside the flatbuffer.
public string __string(int offset)
{
offset += bb.GetInt(offset);
var len = bb.GetInt(offset);
var startPos = offset + sizeof(int);
return bb.GetStringUTF8(startPos, len);
}
// Get the length of a vector whose offset is stored at "offset" in this object.
public int __vector_len(int offset)
{
offset += bb_pos;
offset += bb.GetInt(offset);
return bb.GetInt(offset);
}
// Get the start of data of a vector whose offset is stored at "offset" in this object.
public int __vector(int offset)
{
offset += bb_pos;
return offset + bb.GetInt(offset) + sizeof(int); // data starts after the length
}
#if ENABLE_SPAN_T
// Get the data of a vector whoses offset is stored at "offset" in this object as an
// Spant&lt;byte&gt;. If the vector is not present in the ByteBuffer,
// then an empty span will be returned.
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
// Get the data of a vector whoses offset is stored at "offset" in this object as an
// ArraySegment&lt;byte&gt;. If the vector is not present in the ByteBuffer,
// then a null value will be returned.
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
// 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
{
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;
}
// Compare strings in the ByteBuffer.
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;
}
// Compare string from the ByteBuffer with the string object
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;
}
}
}

Binary file not shown.

Binary file not shown.

View File

@ -63,4 +63,7 @@
<Compile Update="Consoles/Sony/PSX/Octoshock.*.cs" DependentUpon="Octoshock.cs" />
<Compile Update="Consoles/WonderSwan/WonderSwan.*.cs" DependentUpon="WonderSwan.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\ExternalProjects\FlatBuffers\FlatBuffers.Core.csproj" />
</ItemGroup>
</Project>

View File

@ -107,158 +107,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
[BizImport(CC)]
public abstract void SetLayers(ulong layers);
public enum InputType : byte
{
PADDING = 0, // n-bit, zero
BUTTON, // 1-bit
BUTTON_CAN_RAPID, // 1-bit
SWITCH, // ceil(log2(n))-bit
// Current switch position(default 0).
// Persistent, and bidirectional communication(can be modified driver side, and Mednafen core and emulation module side)
STATUS, // ceil(log2(n))-bit
// emulation module->driver communication
AXIS, // 16-bits; 0 through 65535; 32768 is centered position
POINTER_X, // mouse pointer, 16-bits, signed - in-screen/window range before scaling/offseting normalized coordinates: [0.0, 1.0)
POINTER_Y, // see: mouse_scale_x, mouse_scale_y, mouse_offs_x, mouse_offs_y
AXIS_REL, // mouse relative motion, 16-bits, signed
BYTE_SPECIAL,
RESET_BUTTON, // 1-bit
BUTTON_ANALOG, // 16-bits, 0 - 65535
RUMBLE, // 16-bits, lower 8 bits are weak rumble(0-255), next 8 bits are strong rumble(0-255), 0=no rumble, 255=max rumble. Somewhat subjective, too...
}
[Flags]
public enum AxisFlags: byte
{
NONE = 0,
// Denotes analog data that may need to be scaled to ensure a more squareish logical range(for emulated analog sticks)
SQLR = 0x01,
// Invert config order of the two components(neg,pos) of the axis
INVERT_CO = 0x02,
SETTINGS_UNDOC = 0x80,
}
[Flags]
public enum DeviceFlags: uint
{
NONE = 0,
KEYBOARD = 1
}
[StructLayout(LayoutKind.Sequential)]
public struct NPortInfo
{
public IntPtr _shortName;
public IntPtr _fullName;
public IntPtr _defaultDeviceShortName;
public uint NumDevices;
public string ShortName => Mershul.PtrToStringUtf8(_shortName);
public string FullName => Mershul.PtrToStringUtf8(_fullName);
public string DefaultDeviceShortName => Mershul.PtrToStringUtf8(_defaultDeviceShortName);
}
[StructLayout(LayoutKind.Sequential)]
public struct NDeviceInfo
{
public IntPtr _shortName;
public IntPtr _fullName;
public IntPtr _description;
public DeviceFlags Flags;
public uint ByteLength;
public uint NumInputs;
public string ShortName => Mershul.PtrToStringUtf8(_shortName);
public string FullName => Mershul.PtrToStringUtf8(_fullName);
public string Description => Mershul.PtrToStringUtf8(_description);
}
[StructLayout(LayoutKind.Sequential)]
public struct NInputInfo
{
public IntPtr _settingName;
public IntPtr _name;
public short ConfigOrder;
public ushort BitOffset;
public InputType Type;
public AxisFlags Flags;
public byte BitSize;
public string SettingName => Mershul.PtrToStringUtf8(_settingName);
public string Name => Mershul.PtrToStringUtf8(_name);
}
[StructLayout(LayoutKind.Sequential)]
public struct NButtonInfo
{
public IntPtr _excludeName;
public string ExcludeName => Mershul.PtrToStringUtf8(_excludeName);
}
[StructLayout(LayoutKind.Sequential)]
public struct NAxisInfo
{
public IntPtr _settingsNameNeg;
public IntPtr _settingsNamePos;
public IntPtr _nameNeg;
public IntPtr _namePos;
public string SettingsNameNeg => Mershul.PtrToStringUtf8(_settingsNameNeg);
public string SettingsNamePos => Mershul.PtrToStringUtf8(_settingsNamePos);
public string NameNeg => Mershul.PtrToStringUtf8(_nameNeg);
public string NamePos => Mershul.PtrToStringUtf8(_namePos);
}
[StructLayout(LayoutKind.Sequential)]
public struct NSwitchInfo
{
public uint NumPositions;
public uint DefaultPosition;
[StructLayout(LayoutKind.Sequential)]
public struct Position
{
public IntPtr _settingName;
public IntPtr _name;
public IntPtr _description;
public string SettingName => Mershul.PtrToStringUtf8(_settingName);
public string Name => Mershul.PtrToStringUtf8(_name);
public string Description => Mershul.PtrToStringUtf8(_description);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct NStatusInfo
{
public uint NumStates;
[StructLayout(LayoutKind.Sequential)]
public struct State
{
public IntPtr _shortName;
public IntPtr _name;
public int Color; // (msb)0RGB(lsb), -1 for unused.
public int _Padding;
public string ShortName => Mershul.PtrToStringUtf8(_shortName);
public string Name => Mershul.PtrToStringUtf8(_name);
}
}
[BizImport(CC, Compatibility = true)]
public abstract uint GetNumPorts();
[BizImport(CC, Compatibility = true)]
public abstract NPortInfo* GetPort(uint port);
[BizImport(CC, Compatibility = true)]
public abstract NDeviceInfo* GetDevice(uint port, uint dev);
[BizImport(CC, Compatibility = true)]
public abstract NInputInfo* GetInput(uint port, uint dev, uint input);
[BizImport(CC, Compatibility = true)]
public abstract NButtonInfo* GetButton(uint port, uint dev, uint input);
[BizImport(CC, Compatibility = true)]
public abstract NSwitchInfo* GetSwitch(uint port, uint dev, uint input);
[BizImport(CC, Compatibility = true)]
public abstract NSwitchInfo.Position* GetSwitchPosition(uint port, uint dev, uint input, int i);
[BizImport(CC, Compatibility = true)]
public abstract NStatusInfo* GetStatus(uint port, uint dev, uint input);
[BizImport(CC, Compatibility = true)]
public abstract NStatusInfo.State* GetStatusState(uint port, uint dev, uint input, int i);
[BizImport(CC, Compatibility = true)]
public abstract NAxisInfo* GetAxis(uint port, uint dev, uint input);
[BizImport(CC)]
public abstract void DumpInputs();
/// <summary>
/// Set what input devices we're going to use
@ -290,11 +140,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
[BizImport(CC, Compatibility = true)]
public abstract SystemInfo* GetSystemInfo();
[BizImport(CC, Compatibility = true)]
public abstract void IterateSettings(int index, [In, Out]NymaCore.NymaSettingsInfo.MednaSettingS s);
[BizImport(CC, Compatibility = true)]
public abstract void IterateSettingEnums(int index, int enumIndex,[In, Out]NymaCore.NymaSettingsInfo.MednaSettingS.EnumValueS e);
[BizImport(CC)]
public abstract void DumpSettings();
public delegate void FrontendSettingQuery(string setting, IntPtr dest);
[BizImport(CC)]

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using BizHawk.Emulation.Common;
using NymaTypes;
namespace BizHawk.Emulation.Cores.Waterbox
{
@ -11,9 +12,9 @@ namespace BizHawk.Emulation.Cores.Waterbox
private readonly byte[] _inputPortData = new byte[16 * 16];
private readonly string _controllerDeckName;
private void InitControls()
private void InitControls(List<NPortInfoT> allPorts)
{
_controllerAdapter = new ControllerAdapter(_nyma, _syncSettingsActual.PortDevices, ButtonNameOverrides);
_controllerAdapter = new ControllerAdapter(allPorts, _syncSettingsActual.PortDevices, ButtonNameOverrides);
_nyma.SetInputDevices(_controllerAdapter.Devices);
ControllerDefinition = _controllerAdapter.Definition;
}
@ -35,7 +36,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
/// </summary>
public string[] Devices { get; }
public ControllerDefinition Definition { get; }
public ControllerAdapter(LibNymaCore core, IDictionary<int, string> config, IDictionary<string, string> overrides)
public ControllerAdapter(List<NPortInfoT> allPorts, IDictionary<int, string> config, IDictionary<string, string> overrides)
{
var ret = new ControllerDefinition
{
@ -49,40 +50,36 @@ namespace BizHawk.Emulation.Cores.Waterbox
var finalDevices = new List<string>();
var numPorts = core.GetNumPorts();
if (numPorts > MAX_PORTS)
if (allPorts.Count > MAX_PORTS)
throw new InvalidOperationException($"Too many input ports");
for (uint port = 0, devByteStart = 0; port < numPorts; port++, devByteStart += MAX_PORT_DATA)
for (int port = 0, devByteStart = 0; port < allPorts.Count; port++, devByteStart += MAX_PORT_DATA)
{
var portInfo = *core.GetPort(port);
var deviceName = config.ContainsKey((int)port) ? config[(int)port] : portInfo.DefaultDeviceShortName;
var portInfo = allPorts[port];
var deviceName = config.ContainsKey(port) ? config[port] : portInfo.DefaultDeviceShortName;
finalDevices.Add(deviceName);
var devices = Enumerable.Range(0, (int)portInfo.NumDevices)
.Select(i => new { Index = (uint)i, Device = *core.GetDevice(port, (uint)i) })
.ToList();
var devices = portInfo.Devices;
var device = devices.FirstOrDefault(a => a.Device.ShortName == deviceName);
var device = devices.FirstOrDefault(a => a.ShortName == deviceName);
if (device == null)
{
Console.WriteLine($"Warn: unknown controller device {deviceName}");
device = devices.FirstOrDefault(a => a.Device.ShortName == portInfo.DefaultDeviceShortName);
device = devices.FirstOrDefault(a => a.ShortName == portInfo.DefaultDeviceShortName);
if (device == null)
throw new InvalidOperationException($"Fail: unknown controller device {portInfo.DefaultDeviceShortName}");
}
var deviceInfo = device.Device;
var deviceInfo = device;
if (deviceInfo.ByteLength > MAX_PORT_DATA)
throw new InvalidOperationException($"Input device {deviceInfo.ShortName} uses more than {MAX_PORT_DATA} bytes");
var category = portInfo.FullName + " - " + deviceInfo.FullName;
var inputs = Enumerable.Range(0, (int)deviceInfo.NumInputs)
.Select(i => new { Index = i, Data = *core.GetInput(port, device.Index, (uint)i) })
.OrderBy(a => a.Data.ConfigOrder);
var inputs = deviceInfo.Inputs
.OrderBy(a => a.ConfigOrder);
foreach (var input in inputs)
{
var inputInfo = input.Data;
var inputInfo = input;
var bitSize = (int)inputInfo.BitSize;
var bitOffset = (int)inputInfo.BitOffset;
var byteStart = devByteStart + bitOffset / 8;
@ -93,14 +90,14 @@ namespace BizHawk.Emulation.Cores.Waterbox
var name = $"P{port + 1} {baseName}";
switch (inputInfo.Type)
{
case LibNymaCore.InputType.PADDING:
case InputType.Padding:
{
break;
}
case LibNymaCore.InputType.BUTTON:
case LibNymaCore.InputType.BUTTON_CAN_RAPID:
case InputType.Button:
case InputType.ButtonCanRapid:
{
// var data = *core.GetButton(port, device.Index, (uint)input.Index);
// var data = inputInfo.Extra.AsButton();
// TODO: Wire up data.ExcludeName
ret.BoolButtons.Add(name);
_thunks.Add((c, b) =>
@ -110,14 +107,15 @@ namespace BizHawk.Emulation.Cores.Waterbox
});
break;
}
case LibNymaCore.InputType.SWITCH:
case InputType.Switch:
{
var data = *core.GetSwitch(port, device.Index, (uint)input.Index);
var data = inputInfo.Extra.AsSwitch();
var zzhacky = (int)data.DefaultPosition;
// TODO: Possibly bulebutton for 2 states?
// TODO: Motorcycle shift if we can't get sticky correct?
ret.AxisControls.Add(name);
ret.AxisRanges.Add(new ControllerDefinition.AxisRange(
0, (int)data.DefaultPosition, (int)data.NumPositions - 1));
0, (int)data.DefaultPosition, (int)data.Positions.Count - 1));
_thunks.Add((c, b) =>
{
// HACK: Silently discard this until bizhawk fixes its shit
@ -127,12 +125,12 @@ namespace BizHawk.Emulation.Cores.Waterbox
});
break;
}
case LibNymaCore.InputType.AXIS:
case InputType.Axis:
{
// var data = core.GetAxis(port, device.Index, (uint)input.Index);
// var data = inputInfo.Extra.AsAxis();
ret.AxisControls.Add(name);
ret.AxisRanges.Add(new ControllerDefinition.AxisRange(
0, 0x8000, 0xffff, (inputInfo.Flags & LibNymaCore.AxisFlags.INVERT_CO) != 0
0, 0x8000, 0xffff, (inputInfo.Flags & AxisFlags.InvertCo) != 0
));
_thunks.Add((c, b) =>
{
@ -142,12 +140,12 @@ namespace BizHawk.Emulation.Cores.Waterbox
});
break;
}
case LibNymaCore.InputType.AXIS_REL:
case InputType.AxisRel:
{
// var data = core.GetAxis(port, device.Index, (uint)input.Index);
// var data = inputInfo.Extra.AsAxis();
ret.AxisControls.Add(name);
ret.AxisRanges.Add(new ControllerDefinition.AxisRange(
-0x8000, 0, 0x7fff, (inputInfo.Flags & LibNymaCore.AxisFlags.INVERT_CO) != 0
-0x8000, 0, 0x7fff, (inputInfo.Flags & AxisFlags.InvertCo) != 0
));
_thunks.Add((c, b) =>
{
@ -157,7 +155,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
});
break;
}
case LibNymaCore.InputType.POINTER_X:
case InputType.PointerX:
{
throw new NotImplementedException("TODO: Support Pointer");
// I think the core expects to be sent some sort of 16 bit integer, but haven't investigated much
@ -165,7 +163,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
// ret.AxisRanges.Add(new ControllerDefinition.AxisRange(0, ????, ????));
// break;
}
case LibNymaCore.InputType.POINTER_Y:
case InputType.PointerY:
{
throw new Exception("TODO: Support Pointer");
// I think the core expects to be sent some sort of 16 bit integer, but haven't investigated much
@ -175,7 +173,9 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
// TODO: wire up statuses to something (not controller, of course)
default:
{
throw new NotImplementedException($"Unimplemented button type {inputInfo.Type}");
}
}
ret.CategoryLabels[name] = category;
}

View File

@ -3,9 +3,9 @@ using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using NymaTypes;
using static BizHawk.Emulation.Cores.Waterbox.NymaCore;
using static BizHawk.Emulation.Cores.Waterbox.NymaCore.NymaSettingsInfo;
using static BizHawk.Emulation.Cores.Waterbox.NymaCore.NymaSettingsInfo.MednaSetting;
namespace BizHawk.Emulation.Cores.Waterbox
{
@ -75,8 +75,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
public abstract class MednaPropertyDescriptor : PropertyDescriptor
{
public MednaSetting Setting { get; private set; }
public MednaPropertyDescriptor(MednaSetting setting)
public SettingT Setting { get; private set; }
public MednaPropertyDescriptor(SettingT setting)
: base(setting.SettingsKey, new Attribute[0])
{
Setting = setting;
@ -125,21 +125,21 @@ namespace BizHawk.Emulation.Cores.Waterbox
return ((NymaSyncSettings)component).MednafenValues.ContainsKey(Setting.SettingsKey);
}
public static MednaPropertyDescriptor Create(MednaSetting s)
public static MednaPropertyDescriptor Create(SettingT s)
{
switch (s.Type)
{
case SettingType.INT:
case SettingType.Int:
return new MednaLongDescriptor(s);
case SettingType.UINT:
case SettingType.Uint:
return new MednaUlongDescriptor(s);
case SettingType.BOOL:
case SettingType.Bool:
return new MednaBoolDescriptor(s);
case SettingType.FLOAT:
case SettingType.Float:
return new MednaDoubleDescriptor(s);
case SettingType.STRING:
case SettingType.String:
return new MednaStringDescriptor(s);
case SettingType.ENUM:
case SettingType.Enum:
return new MednaEnumDescriptor(s);
default:
throw new NotImplementedException($"Unexpected SettingType {s.Type}");
@ -149,7 +149,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
public class MednaEnumDescriptor : MednaPropertyDescriptor
{
public MednaEnumDescriptor(MednaSetting s) : base(s) {}
public MednaEnumDescriptor(SettingT s) : base(s) {}
public override Type PropertyType => typeof(string);
protected override object ConvertFromString(string s)
{
@ -163,7 +163,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
private class MyTypeConverter : TypeConverter
{
public MednaSetting Setting { get; set; }
public SettingT Setting { get; set; }
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) => sourceType == typeof(string);
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) => destinationType == typeof(string);
@ -196,7 +196,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
public class MednaStringDescriptor : MednaPropertyDescriptor
{
public MednaStringDescriptor(MednaSetting s) : base(s) {}
public MednaStringDescriptor(SettingT s) : base(s) {}
public override Type PropertyType => typeof(string);
protected override object ConvertFromString(string s)
{
@ -209,7 +209,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
public class MednaBoolDescriptor : MednaPropertyDescriptor
{
public MednaBoolDescriptor(MednaSetting s) : base(s) {}
public MednaBoolDescriptor(SettingT s) : base(s) {}
public override Type PropertyType => typeof(bool);
protected override object ConvertFromString(string s)
{
@ -222,7 +222,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
public class MednaLongDescriptor : MednaPropertyDescriptor
{
public MednaLongDescriptor(MednaSetting s) : base(s) {}
public MednaLongDescriptor(SettingT s) : base(s) {}
public override Type PropertyType => typeof(long);
protected override object ConvertFromString(string s)
{
@ -238,7 +238,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
public class MednaUlongDescriptor : MednaPropertyDescriptor
{
public MednaUlongDescriptor(MednaSetting s) : base(s) {}
public MednaUlongDescriptor(SettingT s) : base(s) {}
public override Type PropertyType => typeof(ulong);
protected override object ConvertFromString(string s)
{
@ -254,7 +254,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
public class MednaDoubleDescriptor : MednaPropertyDescriptor
{
public MednaDoubleDescriptor(MednaSetting s) : base(s) {}
public MednaDoubleDescriptor(SettingT s) : base(s) {}
public override Type PropertyType => typeof(double);
protected override object ConvertFromString(string s)
{

View File

@ -7,7 +7,9 @@ using System.Text;
using BizHawk.BizInvoke;
using BizHawk.Common;
using BizHawk.Emulation.Common;
using FlatBuffers;
using Newtonsoft.Json;
using NymaTypes;
namespace BizHawk.Emulation.Cores.Waterbox
{
@ -159,174 +161,34 @@ namespace BizHawk.Emulation.Cores.Waterbox
/// What devices can be plugged into each port
/// </summary>
public List<Port> Ports { get; set; } = new List<Port>();
public class MednaSetting
{
public string Name;
public string Description;
public string SettingsKey;
public string DefaultValue;
public string Min;
public string Max;
[Flags]
public enum SettingFlags : uint
{
NOFLAGS = 0U, // Always 0, makes setting definitions prettier...maybe.
// TODO(cats)
CAT_INPUT = (1U << 8),
CAT_SOUND = (1U << 9),
CAT_VIDEO = (1U << 10),
CAT_INPUT_MAPPING = (1U << 11), // User-configurable physical->virtual button/axes and hotkey mappings(driver-side code category mainly).
// Setting is used as a path or filename(mostly intended for automatic charset conversion of 0.9.x settings on MS Windows).
CAT_PATH = (1U << 12),
EMU_STATE = (1U << 17), // If the setting affects emulation from the point of view of the emulated program
UNTRUSTED_SAFE = (1U << 18), // If it's safe for an untrusted source to modify it, probably only used in conjunction with
// MDFNST_EX_EMU_STATE and network play
SUPPRESS_DOC = (1U << 19), // Suppress documentation generation for this setting.
COMMON_TEMPLATE = (1U << 20), // Auto-generated common template setting(like nes.xscale, pce.xscale, vb.xscale, nes.enable, pce.enable, vb.enable)
NONPERSISTENT = (1U << 21), // Don't save setting in settings file.
// TODO:
// WILL_BREAK_GAMES (1U << ) // If changing the value of the setting from the default value will break games/programs that would otherwise work.
// TODO(in progress):
REQUIRES_RELOAD = (1U << 24), // If a game reload is required for the setting to take effect.
REQUIRES_RESTART = (1U << 25), // If Mednafen restart is required for the setting to take effect.
}
public SettingFlags Flags;
public enum SettingType : int
{
INT = 0, // (signed), int8, int16, int32, int64(saved as)
UINT, // uint8, uint16, uint32, uint64(saved as)
/// <summary>
/// 0 or 1
/// </summary>
BOOL,
/// <summary>
/// float64
/// </summary>
FLOAT,
STRING,
/// <summary>
/// string value from a list of potential strings
/// </summary>
ENUM,
/// <summary>
/// TODO: How do these work
/// </summary>
MULTI_ENUM,
/// <summary>
/// Shouldn't see any of these
/// </summary>
ALIAS
}
public SettingType Type;
public class EnumValue
{
public string Name;
public string Description;
public string Value;
public EnumValue(MednaSettingS.EnumValueS s)
{
Name = Mershul.PtrToStringUtf8(s.Name);
Description = Mershul.PtrToStringUtf8(s.Description);
Value = Mershul.PtrToStringUtf8(s.Value);
}
}
public MednaSetting()
{}
public MednaSetting(MednaSettingS s)
{
Name = Mershul.PtrToStringUtf8(s.Name);
Description = Mershul.PtrToStringUtf8(s.Description);
SettingsKey = Mershul.PtrToStringUtf8(s.SettingsKey);
DefaultValue = Mershul.PtrToStringUtf8(s.DefaultValue);
Min = Mershul.PtrToStringUtf8(s.Min);
Max = Mershul.PtrToStringUtf8(s.Max);
Flags = (SettingFlags)s.Flags;
Type = (SettingType)s.Type;
}
public List<MednaSetting.EnumValue> SettingEnums { get; set; } = new List<MednaSetting.EnumValue>();
}
[StructLayout(LayoutKind.Sequential)]
public class MednaSettingS
{
public IntPtr Name;
public IntPtr Description;
public IntPtr SettingsKey;
public IntPtr DefaultValue;
public IntPtr Min;
public IntPtr Max;
public uint Flags;
public int Type;
[StructLayout(LayoutKind.Sequential)]
public class EnumValueS
{
public IntPtr Name;
public IntPtr Description;
public IntPtr Value;
}
}
public List<MednaSetting> Settings { get; set; } = new List<MednaSetting>();
public Dictionary<string, MednaSetting> SettingsByKey { get; set; } = new Dictionary<string, MednaSetting>();
public List<SettingT> Settings { get; set; } = new List<SettingT>();
public Dictionary<string, SettingT> SettingsByKey { get; set; } = new Dictionary<string, SettingT>();
public HashSet<string> HiddenSettings { get; set; } = new HashSet<string>();
}
private void InitSyncSettingsInfo()
private void InitSyncSettingsInfo(List<NPortInfoT> allPorts)
{
// TODO: Some shared logic in ControllerAdapter. Avoidable?
var s = new NymaSettingsInfo();
var numPorts = _nyma.GetNumPorts();
for (uint port = 0; port < numPorts; port++)
foreach (var portInfo in allPorts)
{
var portInfo = *_nyma.GetPort(port);
s.Ports.Add(new NymaSettingsInfo.Port
{
Name = portInfo.FullName,
DefaultSettingsValue = portInfo.DefaultDeviceShortName,
AllowedDevices = Enumerable.Range(0, (int)portInfo.NumDevices)
.Select(i =>
{
var dev = *_nyma.GetDevice(port, (uint)i);
return new NymaSettingsInfo.Device
{
Name = dev.FullName,
Description = dev.Description,
SettingValue = dev.ShortName
};
})
.ToList()
AllowedDevices = portInfo.Devices.Select(dev => new NymaSettingsInfo.Device
{
Name = dev.FullName,
Description = dev.Description,
SettingValue = dev.ShortName
}).ToList()
});
}
for (var i = 0;; i++)
foreach (var setting in GetSettingsData())
{
var tt = new NymaSettingsInfo.MednaSettingS();
_nyma.IterateSettings(i, tt);
if (tt.SettingsKey == IntPtr.Zero)
break;
var ss = new NymaSettingsInfo.MednaSetting(tt);
s.Settings.Add(ss);
s.SettingsByKey.Add(ss.SettingsKey, ss);
if (ss.Type == NymaSettingsInfo.MednaSetting.SettingType.ENUM)
{
var l = ss.SettingEnums;
for (var j = 0;; j++)
{
var ff = new NymaSettingsInfo.MednaSettingS.EnumValueS();
_nyma.IterateSettingEnums(i, j, ff);
if (ff.Value == IntPtr.Zero)
break;
var ee = new NymaSettingsInfo.MednaSetting.EnumValue(ff);
l.Add(ee);
}
}
s.Settings.Add(setting);
s.SettingsByKey.Add(setting.SettingsKey, setting);
}
s.HiddenSettings = new HashSet<string>(SettingsOverrides.Keys);
foreach (var ss in ExtraSettings)
{
@ -336,25 +198,25 @@ namespace BizHawk.Emulation.Cores.Waterbox
SettingsInfo = s;
}
private static IReadOnlyCollection<NymaSettingsInfo.MednaSetting> ExtraSettings = new List<NymaSettingsInfo.MednaSetting>
private static IReadOnlyCollection<SettingT> ExtraSettings = new List<SettingT>
{
new NymaSettingsInfo.MednaSetting
new SettingT
{
Name = "Initial Time",
Description = "Initial time of emulation. Only relevant when UseRealTime is false.\nEnter as IS0-8601.",
SettingsKey = "nyma.rtcinitialtime",
DefaultValue = "2010-01-01",
Flags = NymaSettingsInfo.MednaSetting.SettingFlags.EMU_STATE,
Type = NymaSettingsInfo.MednaSetting.SettingType.STRING
Flags = SettingsFlags.EmuState,
Type = SettingType.String
},
new NymaSettingsInfo.MednaSetting
new SettingT
{
Name = "Use RealTime",
Description = "If true, RTC clock will be based off of real time instead of emulated time. Ignored (set to false) when recording a movie.",
SettingsKey = "nyma.rtcrealtime",
DefaultValue = "0",
Flags = NymaSettingsInfo.MednaSetting.SettingFlags.EMU_STATE,
Type = NymaSettingsInfo.MednaSetting.SettingType.BOOL
Flags = SettingsFlags.EmuState,
Type = SettingType.Bool
},
};
}

View File

@ -6,6 +6,8 @@ using System.Runtime.InteropServices;
using BizHawk.Common;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.DiscSystem;
using FlatBuffers;
using NymaTypes;
namespace BizHawk.Emulation.Cores.Waterbox
{
@ -45,7 +47,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
using (_exe.EnterExit())
{
_nyma.PreInit();
InitSyncSettingsInfo();
var portData = GetInputPortsData();
InitSyncSettingsInfo(portData);
_nyma.SetFrontendSettingQuery(_settingsQueryDelegate);
if (firmwares != null)
{
@ -113,7 +116,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
VsyncDenominator = 1 << 24;
_soundBuffer = new short[22050 * 2];
InitControls();
InitControls(portData);
_nyma.SetFrontendSettingQuery(null);
if (_disks != null)
_nyma.SetCDCallbacks(null, null);
@ -199,5 +202,21 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
return ret;
}
private List<SettingT> GetSettingsData()
{
_exe.AddTransientFile(new byte[0], "settings");
_nyma.DumpSettings();
var settingsBuff = _exe.RemoveTransientFile("settings");
return NymaTypes.Settings.GetRootAsSettings(new ByteBuffer(settingsBuff)).UnPack().Values;
}
private List<NPortInfoT> GetInputPortsData()
{
_exe.AddTransientFile(new byte[0], "inputs");
_nyma.DumpInputs();
var settingsBuff = _exe.RemoveTransientFile("inputs");
return NymaTypes.NPorts.GetRootAsNPorts(new ByteBuffer(settingsBuff)).UnPack().Values;
}
}
}

View File

@ -0,0 +1,17 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
[System.FlagsAttribute]
public enum AxisFlags : byte
{
Sqlr = 1,
InvertCo = 2,
SettingsUndoc = 128,
};
}

View File

@ -0,0 +1,15 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
[System.FlagsAttribute]
public enum DeviceFlags : byte
{
Keyboard = 1,
};
}

View File

@ -0,0 +1,100 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
using global::System;
using global::System.Collections.Generic;
using global::FlatBuffers;
public struct EnumValue : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); }
public static EnumValue GetRootAsEnumValue(ByteBuffer _bb) { return GetRootAsEnumValue(_bb, new EnumValue()); }
public static EnumValue GetRootAsEnumValue(ByteBuffer _bb, EnumValue obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public EnumValue __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetNameBytes() { return __p.__vector_as_span<byte>(4, 1); }
#else
public ArraySegment<byte>? GetNameBytes() { return __p.__vector_as_arraysegment(4); }
#endif
public byte[] GetNameArray() { return __p.__vector_as_array<byte>(4); }
public string Description { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetDescriptionBytes() { return __p.__vector_as_span<byte>(6, 1); }
#else
public ArraySegment<byte>? GetDescriptionBytes() { return __p.__vector_as_arraysegment(6); }
#endif
public byte[] GetDescriptionArray() { return __p.__vector_as_array<byte>(6); }
public string Value { get { int o = __p.__offset(8); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetValueBytes() { return __p.__vector_as_span<byte>(8, 1); }
#else
public ArraySegment<byte>? GetValueBytes() { return __p.__vector_as_arraysegment(8); }
#endif
public byte[] GetValueArray() { return __p.__vector_as_array<byte>(8); }
public static Offset<NymaTypes.EnumValue> CreateEnumValue(FlatBufferBuilder builder,
StringOffset NameOffset = default(StringOffset),
StringOffset DescriptionOffset = default(StringOffset),
StringOffset ValueOffset = default(StringOffset)) {
builder.StartTable(3);
EnumValue.AddValue(builder, ValueOffset);
EnumValue.AddDescription(builder, DescriptionOffset);
EnumValue.AddName(builder, NameOffset);
return EnumValue.EndEnumValue(builder);
}
public static void StartEnumValue(FlatBufferBuilder builder) { builder.StartTable(3); }
public static void AddName(FlatBufferBuilder builder, StringOffset NameOffset) { builder.AddOffset(0, NameOffset.Value, 0); }
public static void AddDescription(FlatBufferBuilder builder, StringOffset DescriptionOffset) { builder.AddOffset(1, DescriptionOffset.Value, 0); }
public static void AddValue(FlatBufferBuilder builder, StringOffset ValueOffset) { builder.AddOffset(2, ValueOffset.Value, 0); }
public static Offset<NymaTypes.EnumValue> EndEnumValue(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<NymaTypes.EnumValue>(o);
}
public EnumValueT UnPack() {
var _o = new EnumValueT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(EnumValueT _o) {
_o.Name = this.Name;
_o.Description = this.Description;
_o.Value = this.Value;
}
public static Offset<NymaTypes.EnumValue> Pack(FlatBufferBuilder builder, EnumValueT _o) {
if (_o == null) return default(Offset<NymaTypes.EnumValue>);
var _Name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name);
var _Description = _o.Description == null ? default(StringOffset) : builder.CreateString(_o.Description);
var _Value = _o.Value == null ? default(StringOffset) : builder.CreateString(_o.Value);
return CreateEnumValue(
builder,
_Name,
_Description,
_Value);
}
};
public class EnumValueT
{
public string Name { get; set; }
public string Description { get; set; }
public string Value { get; set; }
public EnumValueT() {
this.Name = null;
this.Description = null;
this.Value = null;
}
}
}

View File

@ -0,0 +1,26 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
public enum InputType : byte
{
Padding = 0,
Button = 1,
ButtonCanRapid = 2,
Switch = 3,
Status = 4,
Axis = 5,
PointerX = 6,
PointerY = 7,
AxisRel = 8,
ByteSpecial = 9,
ResetButton = 10,
ButtonAnalog = 11,
Rumble = 12,
};
}

View File

@ -0,0 +1,115 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
using global::System;
using global::System.Collections.Generic;
using global::FlatBuffers;
public struct NAxisInfo : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); }
public static NAxisInfo GetRootAsNAxisInfo(ByteBuffer _bb) { return GetRootAsNAxisInfo(_bb, new NAxisInfo()); }
public static NAxisInfo GetRootAsNAxisInfo(ByteBuffer _bb, NAxisInfo obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public NAxisInfo __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public string SettingsNameNeg { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetSettingsNameNegBytes() { return __p.__vector_as_span<byte>(4, 1); }
#else
public ArraySegment<byte>? GetSettingsNameNegBytes() { return __p.__vector_as_arraysegment(4); }
#endif
public byte[] GetSettingsNameNegArray() { return __p.__vector_as_array<byte>(4); }
public string SettingsNamePos { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetSettingsNamePosBytes() { return __p.__vector_as_span<byte>(6, 1); }
#else
public ArraySegment<byte>? GetSettingsNamePosBytes() { return __p.__vector_as_arraysegment(6); }
#endif
public byte[] GetSettingsNamePosArray() { return __p.__vector_as_array<byte>(6); }
public string NameNeg { get { int o = __p.__offset(8); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetNameNegBytes() { return __p.__vector_as_span<byte>(8, 1); }
#else
public ArraySegment<byte>? GetNameNegBytes() { return __p.__vector_as_arraysegment(8); }
#endif
public byte[] GetNameNegArray() { return __p.__vector_as_array<byte>(8); }
public string NamePos { get { int o = __p.__offset(10); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetNamePosBytes() { return __p.__vector_as_span<byte>(10, 1); }
#else
public ArraySegment<byte>? GetNamePosBytes() { return __p.__vector_as_arraysegment(10); }
#endif
public byte[] GetNamePosArray() { return __p.__vector_as_array<byte>(10); }
public static Offset<NymaTypes.NAxisInfo> CreateNAxisInfo(FlatBufferBuilder builder,
StringOffset SettingsNameNegOffset = default(StringOffset),
StringOffset SettingsNamePosOffset = default(StringOffset),
StringOffset NameNegOffset = default(StringOffset),
StringOffset NamePosOffset = default(StringOffset)) {
builder.StartTable(4);
NAxisInfo.AddNamePos(builder, NamePosOffset);
NAxisInfo.AddNameNeg(builder, NameNegOffset);
NAxisInfo.AddSettingsNamePos(builder, SettingsNamePosOffset);
NAxisInfo.AddSettingsNameNeg(builder, SettingsNameNegOffset);
return NAxisInfo.EndNAxisInfo(builder);
}
public static void StartNAxisInfo(FlatBufferBuilder builder) { builder.StartTable(4); }
public static void AddSettingsNameNeg(FlatBufferBuilder builder, StringOffset SettingsNameNegOffset) { builder.AddOffset(0, SettingsNameNegOffset.Value, 0); }
public static void AddSettingsNamePos(FlatBufferBuilder builder, StringOffset SettingsNamePosOffset) { builder.AddOffset(1, SettingsNamePosOffset.Value, 0); }
public static void AddNameNeg(FlatBufferBuilder builder, StringOffset NameNegOffset) { builder.AddOffset(2, NameNegOffset.Value, 0); }
public static void AddNamePos(FlatBufferBuilder builder, StringOffset NamePosOffset) { builder.AddOffset(3, NamePosOffset.Value, 0); }
public static Offset<NymaTypes.NAxisInfo> EndNAxisInfo(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<NymaTypes.NAxisInfo>(o);
}
public NAxisInfoT UnPack() {
var _o = new NAxisInfoT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(NAxisInfoT _o) {
_o.SettingsNameNeg = this.SettingsNameNeg;
_o.SettingsNamePos = this.SettingsNamePos;
_o.NameNeg = this.NameNeg;
_o.NamePos = this.NamePos;
}
public static Offset<NymaTypes.NAxisInfo> Pack(FlatBufferBuilder builder, NAxisInfoT _o) {
if (_o == null) return default(Offset<NymaTypes.NAxisInfo>);
var _SettingsNameNeg = _o.SettingsNameNeg == null ? default(StringOffset) : builder.CreateString(_o.SettingsNameNeg);
var _SettingsNamePos = _o.SettingsNamePos == null ? default(StringOffset) : builder.CreateString(_o.SettingsNamePos);
var _NameNeg = _o.NameNeg == null ? default(StringOffset) : builder.CreateString(_o.NameNeg);
var _NamePos = _o.NamePos == null ? default(StringOffset) : builder.CreateString(_o.NamePos);
return CreateNAxisInfo(
builder,
_SettingsNameNeg,
_SettingsNamePos,
_NameNeg,
_NamePos);
}
};
public class NAxisInfoT
{
public string SettingsNameNeg { get; set; }
public string SettingsNamePos { get; set; }
public string NameNeg { get; set; }
public string NamePos { get; set; }
public NAxisInfoT() {
this.SettingsNameNeg = null;
this.SettingsNamePos = null;
this.NameNeg = null;
this.NamePos = null;
}
}
}

View File

@ -0,0 +1,70 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
using global::System;
using global::System.Collections.Generic;
using global::FlatBuffers;
public struct NButtonInfo : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); }
public static NButtonInfo GetRootAsNButtonInfo(ByteBuffer _bb) { return GetRootAsNButtonInfo(_bb, new NButtonInfo()); }
public static NButtonInfo GetRootAsNButtonInfo(ByteBuffer _bb, NButtonInfo obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public NButtonInfo __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public string ExcludeName { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetExcludeNameBytes() { return __p.__vector_as_span<byte>(4, 1); }
#else
public ArraySegment<byte>? GetExcludeNameBytes() { return __p.__vector_as_arraysegment(4); }
#endif
public byte[] GetExcludeNameArray() { return __p.__vector_as_array<byte>(4); }
public static Offset<NymaTypes.NButtonInfo> CreateNButtonInfo(FlatBufferBuilder builder,
StringOffset ExcludeNameOffset = default(StringOffset)) {
builder.StartTable(1);
NButtonInfo.AddExcludeName(builder, ExcludeNameOffset);
return NButtonInfo.EndNButtonInfo(builder);
}
public static void StartNButtonInfo(FlatBufferBuilder builder) { builder.StartTable(1); }
public static void AddExcludeName(FlatBufferBuilder builder, StringOffset ExcludeNameOffset) { builder.AddOffset(0, ExcludeNameOffset.Value, 0); }
public static Offset<NymaTypes.NButtonInfo> EndNButtonInfo(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<NymaTypes.NButtonInfo>(o);
}
public NButtonInfoT UnPack() {
var _o = new NButtonInfoT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(NButtonInfoT _o) {
_o.ExcludeName = this.ExcludeName;
}
public static Offset<NymaTypes.NButtonInfo> Pack(FlatBufferBuilder builder, NButtonInfoT _o) {
if (_o == null) return default(Offset<NymaTypes.NButtonInfo>);
var _ExcludeName = _o.ExcludeName == null ? default(StringOffset) : builder.CreateString(_o.ExcludeName);
return CreateNButtonInfo(
builder,
_ExcludeName);
}
};
public class NButtonInfoT
{
public string ExcludeName { get; set; }
public NButtonInfoT() {
this.ExcludeName = null;
}
}
}

View File

@ -0,0 +1,135 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
using global::System;
using global::System.Collections.Generic;
using global::FlatBuffers;
public struct NDeviceInfo : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); }
public static NDeviceInfo GetRootAsNDeviceInfo(ByteBuffer _bb) { return GetRootAsNDeviceInfo(_bb, new NDeviceInfo()); }
public static NDeviceInfo GetRootAsNDeviceInfo(ByteBuffer _bb, NDeviceInfo obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public NDeviceInfo __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public string ShortName { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetShortNameBytes() { return __p.__vector_as_span<byte>(4, 1); }
#else
public ArraySegment<byte>? GetShortNameBytes() { return __p.__vector_as_arraysegment(4); }
#endif
public byte[] GetShortNameArray() { return __p.__vector_as_array<byte>(4); }
public string FullName { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetFullNameBytes() { return __p.__vector_as_span<byte>(6, 1); }
#else
public ArraySegment<byte>? GetFullNameBytes() { return __p.__vector_as_arraysegment(6); }
#endif
public byte[] GetFullNameArray() { return __p.__vector_as_array<byte>(6); }
public string Description { get { int o = __p.__offset(8); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetDescriptionBytes() { return __p.__vector_as_span<byte>(8, 1); }
#else
public ArraySegment<byte>? GetDescriptionBytes() { return __p.__vector_as_arraysegment(8); }
#endif
public byte[] GetDescriptionArray() { return __p.__vector_as_array<byte>(8); }
public NymaTypes.DeviceFlags Flags { get { int o = __p.__offset(10); return o != 0 ? (NymaTypes.DeviceFlags)__p.bb.Get(o + __p.bb_pos) : 0; } }
public uint ByteLength { get { int o = __p.__offset(12); return o != 0 ? __p.bb.GetUint(o + __p.bb_pos) : (uint)0; } }
public NymaTypes.NInputInfo? Inputs(int j) { int o = __p.__offset(14); return o != 0 ? (NymaTypes.NInputInfo?)(new NymaTypes.NInputInfo()).__assign(__p.__indirect(__p.__vector(o) + j * 4), __p.bb) : null; }
public int InputsLength { get { int o = __p.__offset(14); return o != 0 ? __p.__vector_len(o) : 0; } }
public static Offset<NymaTypes.NDeviceInfo> CreateNDeviceInfo(FlatBufferBuilder builder,
StringOffset ShortNameOffset = default(StringOffset),
StringOffset FullNameOffset = default(StringOffset),
StringOffset DescriptionOffset = default(StringOffset),
NymaTypes.DeviceFlags Flags = 0,
uint ByteLength = 0,
VectorOffset InputsOffset = default(VectorOffset)) {
builder.StartTable(6);
NDeviceInfo.AddInputs(builder, InputsOffset);
NDeviceInfo.AddByteLength(builder, ByteLength);
NDeviceInfo.AddDescription(builder, DescriptionOffset);
NDeviceInfo.AddFullName(builder, FullNameOffset);
NDeviceInfo.AddShortName(builder, ShortNameOffset);
NDeviceInfo.AddFlags(builder, Flags);
return NDeviceInfo.EndNDeviceInfo(builder);
}
public static void StartNDeviceInfo(FlatBufferBuilder builder) { builder.StartTable(6); }
public static void AddShortName(FlatBufferBuilder builder, StringOffset ShortNameOffset) { builder.AddOffset(0, ShortNameOffset.Value, 0); }
public static void AddFullName(FlatBufferBuilder builder, StringOffset FullNameOffset) { builder.AddOffset(1, FullNameOffset.Value, 0); }
public static void AddDescription(FlatBufferBuilder builder, StringOffset DescriptionOffset) { builder.AddOffset(2, DescriptionOffset.Value, 0); }
public static void AddFlags(FlatBufferBuilder builder, NymaTypes.DeviceFlags Flags) { builder.AddByte(3, (byte)Flags, 0); }
public static void AddByteLength(FlatBufferBuilder builder, uint ByteLength) { builder.AddUint(4, ByteLength, 0); }
public static void AddInputs(FlatBufferBuilder builder, VectorOffset InputsOffset) { builder.AddOffset(5, InputsOffset.Value, 0); }
public static VectorOffset CreateInputsVector(FlatBufferBuilder builder, Offset<NymaTypes.NInputInfo>[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); }
public static VectorOffset CreateInputsVectorBlock(FlatBufferBuilder builder, Offset<NymaTypes.NInputInfo>[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); }
public static void StartInputsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
public static Offset<NymaTypes.NDeviceInfo> EndNDeviceInfo(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<NymaTypes.NDeviceInfo>(o);
}
public NDeviceInfoT UnPack() {
var _o = new NDeviceInfoT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(NDeviceInfoT _o) {
_o.ShortName = this.ShortName;
_o.FullName = this.FullName;
_o.Description = this.Description;
_o.Flags = this.Flags;
_o.ByteLength = this.ByteLength;
_o.Inputs = new List<NymaTypes.NInputInfoT>();
for (var _j = 0; _j < this.InputsLength; ++_j) {_o.Inputs.Add(this.Inputs(_j).HasValue ? this.Inputs(_j).Value.UnPack() : null);}
}
public static Offset<NymaTypes.NDeviceInfo> Pack(FlatBufferBuilder builder, NDeviceInfoT _o) {
if (_o == null) return default(Offset<NymaTypes.NDeviceInfo>);
var _ShortName = _o.ShortName == null ? default(StringOffset) : builder.CreateString(_o.ShortName);
var _FullName = _o.FullName == null ? default(StringOffset) : builder.CreateString(_o.FullName);
var _Description = _o.Description == null ? default(StringOffset) : builder.CreateString(_o.Description);
var _Inputs = default(VectorOffset);
if (_o.Inputs != null) {
var __Inputs = new Offset<NymaTypes.NInputInfo>[_o.Inputs.Count];
for (var _j = 0; _j < __Inputs.Length; ++_j) { __Inputs[_j] = NymaTypes.NInputInfo.Pack(builder, _o.Inputs[_j]); }
_Inputs = CreateInputsVector(builder, __Inputs);
}
return CreateNDeviceInfo(
builder,
_ShortName,
_FullName,
_Description,
_o.Flags,
_o.ByteLength,
_Inputs);
}
};
public class NDeviceInfoT
{
public string ShortName { get; set; }
public string FullName { get; set; }
public string Description { get; set; }
public NymaTypes.DeviceFlags Flags { get; set; }
public uint ByteLength { get; set; }
public List<NymaTypes.NInputInfoT> Inputs { get; set; }
public NDeviceInfoT() {
this.ShortName = null;
this.FullName = null;
this.Description = null;
this.Flags = 0;
this.ByteLength = 0;
this.Inputs = null;
}
}
}

View File

@ -0,0 +1,44 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
public enum NInputExtra : byte
{
NONE = 0,
Button = 1,
Axis = 2,
Switch = 3,
Status = 4,
};
public class NInputExtraUnion {
public NInputExtra Type { get; set; }
public object Value { get; set; }
public NInputExtraUnion() {
this.Type = NInputExtra.NONE;
this.Value = null;
}
public T As<T>() where T : class { return this.Value as T; }
public NymaTypes.NButtonInfoT AsButton() { return this.As<NymaTypes.NButtonInfoT>(); }
public NymaTypes.NAxisInfoT AsAxis() { return this.As<NymaTypes.NAxisInfoT>(); }
public NymaTypes.NSwitchInfoT AsSwitch() { return this.As<NymaTypes.NSwitchInfoT>(); }
public NymaTypes.NStatusInfoT AsStatus() { return this.As<NymaTypes.NStatusInfoT>(); }
public static int Pack(FlatBuffers.FlatBufferBuilder builder, NInputExtraUnion _o) {
switch (_o.Type) {
default: return 0;
case NInputExtra.Button: return NymaTypes.NButtonInfo.Pack(builder, _o.AsButton()).Value;
case NInputExtra.Axis: return NymaTypes.NAxisInfo.Pack(builder, _o.AsAxis()).Value;
case NInputExtra.Switch: return NymaTypes.NSwitchInfo.Pack(builder, _o.AsSwitch()).Value;
case NInputExtra.Status: return NymaTypes.NStatusInfo.Pack(builder, _o.AsStatus()).Value;
}
}
}
}

View File

@ -0,0 +1,156 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
using global::System;
using global::System.Collections.Generic;
using global::FlatBuffers;
public struct NInputInfo : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); }
public static NInputInfo GetRootAsNInputInfo(ByteBuffer _bb) { return GetRootAsNInputInfo(_bb, new NInputInfo()); }
public static NInputInfo GetRootAsNInputInfo(ByteBuffer _bb, NInputInfo obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public NInputInfo __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public string SettingName { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetSettingNameBytes() { return __p.__vector_as_span<byte>(4, 1); }
#else
public ArraySegment<byte>? GetSettingNameBytes() { return __p.__vector_as_arraysegment(4); }
#endif
public byte[] GetSettingNameArray() { return __p.__vector_as_array<byte>(4); }
public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetNameBytes() { return __p.__vector_as_span<byte>(6, 1); }
#else
public ArraySegment<byte>? GetNameBytes() { return __p.__vector_as_arraysegment(6); }
#endif
public byte[] GetNameArray() { return __p.__vector_as_array<byte>(6); }
public short ConfigOrder { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetShort(o + __p.bb_pos) : (short)0; } }
public ushort BitOffset { get { int o = __p.__offset(10); return o != 0 ? __p.bb.GetUshort(o + __p.bb_pos) : (ushort)0; } }
public NymaTypes.InputType Type { get { int o = __p.__offset(12); return o != 0 ? (NymaTypes.InputType)__p.bb.Get(o + __p.bb_pos) : NymaTypes.InputType.Padding; } }
public NymaTypes.AxisFlags Flags { get { int o = __p.__offset(14); return o != 0 ? (NymaTypes.AxisFlags)__p.bb.Get(o + __p.bb_pos) : 0; } }
public byte BitSize { get { int o = __p.__offset(16); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte)0; } }
public NymaTypes.NInputExtra ExtraType { get { int o = __p.__offset(18); return o != 0 ? (NymaTypes.NInputExtra)__p.bb.Get(o + __p.bb_pos) : NymaTypes.NInputExtra.NONE; } }
public TTable? Extra<TTable>() where TTable : struct, IFlatbufferObject { int o = __p.__offset(20); return o != 0 ? (TTable?)__p.__union<TTable>(o + __p.bb_pos) : null; }
public static Offset<NymaTypes.NInputInfo> CreateNInputInfo(FlatBufferBuilder builder,
StringOffset SettingNameOffset = default(StringOffset),
StringOffset NameOffset = default(StringOffset),
short ConfigOrder = 0,
ushort BitOffset = 0,
NymaTypes.InputType Type = NymaTypes.InputType.Padding,
NymaTypes.AxisFlags Flags = 0,
byte BitSize = 0,
NymaTypes.NInputExtra Extra_type = NymaTypes.NInputExtra.NONE,
int ExtraOffset = 0) {
builder.StartTable(9);
NInputInfo.AddExtra(builder, ExtraOffset);
NInputInfo.AddName(builder, NameOffset);
NInputInfo.AddSettingName(builder, SettingNameOffset);
NInputInfo.AddBitOffset(builder, BitOffset);
NInputInfo.AddConfigOrder(builder, ConfigOrder);
NInputInfo.AddExtraType(builder, Extra_type);
NInputInfo.AddBitSize(builder, BitSize);
NInputInfo.AddFlags(builder, Flags);
NInputInfo.AddType(builder, Type);
return NInputInfo.EndNInputInfo(builder);
}
public static void StartNInputInfo(FlatBufferBuilder builder) { builder.StartTable(9); }
public static void AddSettingName(FlatBufferBuilder builder, StringOffset SettingNameOffset) { builder.AddOffset(0, SettingNameOffset.Value, 0); }
public static void AddName(FlatBufferBuilder builder, StringOffset NameOffset) { builder.AddOffset(1, NameOffset.Value, 0); }
public static void AddConfigOrder(FlatBufferBuilder builder, short ConfigOrder) { builder.AddShort(2, ConfigOrder, 0); }
public static void AddBitOffset(FlatBufferBuilder builder, ushort BitOffset) { builder.AddUshort(3, BitOffset, 0); }
public static void AddType(FlatBufferBuilder builder, NymaTypes.InputType Type) { builder.AddByte(4, (byte)Type, 0); }
public static void AddFlags(FlatBufferBuilder builder, NymaTypes.AxisFlags Flags) { builder.AddByte(5, (byte)Flags, 0); }
public static void AddBitSize(FlatBufferBuilder builder, byte BitSize) { builder.AddByte(6, BitSize, 0); }
public static void AddExtraType(FlatBufferBuilder builder, NymaTypes.NInputExtra ExtraType) { builder.AddByte(7, (byte)ExtraType, 0); }
public static void AddExtra(FlatBufferBuilder builder, int ExtraOffset) { builder.AddOffset(8, ExtraOffset, 0); }
public static Offset<NymaTypes.NInputInfo> EndNInputInfo(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<NymaTypes.NInputInfo>(o);
}
public NInputInfoT UnPack() {
var _o = new NInputInfoT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(NInputInfoT _o) {
_o.SettingName = this.SettingName;
_o.Name = this.Name;
_o.ConfigOrder = this.ConfigOrder;
_o.BitOffset = this.BitOffset;
_o.Type = this.Type;
_o.Flags = this.Flags;
_o.BitSize = this.BitSize;
_o.Extra = new NymaTypes.NInputExtraUnion();
_o.Extra.Type = this.ExtraType;
switch (this.ExtraType) {
default: break;
case NymaTypes.NInputExtra.Button:
_o.Extra.Value = this.Extra<NymaTypes.NButtonInfo>().HasValue ? this.Extra<NymaTypes.NButtonInfo>().Value.UnPack() : null;
break;
case NymaTypes.NInputExtra.Axis:
_o.Extra.Value = this.Extra<NymaTypes.NAxisInfo>().HasValue ? this.Extra<NymaTypes.NAxisInfo>().Value.UnPack() : null;
break;
case NymaTypes.NInputExtra.Switch:
_o.Extra.Value = this.Extra<NymaTypes.NSwitchInfo>().HasValue ? this.Extra<NymaTypes.NSwitchInfo>().Value.UnPack() : null;
break;
case NymaTypes.NInputExtra.Status:
_o.Extra.Value = this.Extra<NymaTypes.NStatusInfo>().HasValue ? this.Extra<NymaTypes.NStatusInfo>().Value.UnPack() : null;
break;
}
}
public static Offset<NymaTypes.NInputInfo> Pack(FlatBufferBuilder builder, NInputInfoT _o) {
if (_o == null) return default(Offset<NymaTypes.NInputInfo>);
var _SettingName = _o.SettingName == null ? default(StringOffset) : builder.CreateString(_o.SettingName);
var _Name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name);
var _Extra_type = _o.Extra == null ? NymaTypes.NInputExtra.NONE : _o.Extra.Type;
var _Extra = _o.Extra == null ? 0 : NymaTypes.NInputExtraUnion.Pack(builder, _o.Extra);
return CreateNInputInfo(
builder,
_SettingName,
_Name,
_o.ConfigOrder,
_o.BitOffset,
_o.Type,
_o.Flags,
_o.BitSize,
_Extra_type,
_Extra);
}
};
public class NInputInfoT
{
public string SettingName { get; set; }
public string Name { get; set; }
public short ConfigOrder { get; set; }
public ushort BitOffset { get; set; }
public NymaTypes.InputType Type { get; set; }
public NymaTypes.AxisFlags Flags { get; set; }
public byte BitSize { get; set; }
public NymaTypes.NInputExtraUnion Extra { get; set; }
public NInputInfoT() {
this.SettingName = null;
this.Name = null;
this.ConfigOrder = 0;
this.BitOffset = 0;
this.Type = NymaTypes.InputType.Padding;
this.Flags = 0;
this.BitSize = 0;
this.Extra = null;
}
}
}

View File

@ -0,0 +1,119 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
using global::System;
using global::System.Collections.Generic;
using global::FlatBuffers;
public struct NPortInfo : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); }
public static NPortInfo GetRootAsNPortInfo(ByteBuffer _bb) { return GetRootAsNPortInfo(_bb, new NPortInfo()); }
public static NPortInfo GetRootAsNPortInfo(ByteBuffer _bb, NPortInfo obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public NPortInfo __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public string ShortName { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetShortNameBytes() { return __p.__vector_as_span<byte>(4, 1); }
#else
public ArraySegment<byte>? GetShortNameBytes() { return __p.__vector_as_arraysegment(4); }
#endif
public byte[] GetShortNameArray() { return __p.__vector_as_array<byte>(4); }
public string FullName { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetFullNameBytes() { return __p.__vector_as_span<byte>(6, 1); }
#else
public ArraySegment<byte>? GetFullNameBytes() { return __p.__vector_as_arraysegment(6); }
#endif
public byte[] GetFullNameArray() { return __p.__vector_as_array<byte>(6); }
public string DefaultDeviceShortName { get { int o = __p.__offset(8); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetDefaultDeviceShortNameBytes() { return __p.__vector_as_span<byte>(8, 1); }
#else
public ArraySegment<byte>? GetDefaultDeviceShortNameBytes() { return __p.__vector_as_arraysegment(8); }
#endif
public byte[] GetDefaultDeviceShortNameArray() { return __p.__vector_as_array<byte>(8); }
public NymaTypes.NDeviceInfo? Devices(int j) { int o = __p.__offset(10); return o != 0 ? (NymaTypes.NDeviceInfo?)(new NymaTypes.NDeviceInfo()).__assign(__p.__indirect(__p.__vector(o) + j * 4), __p.bb) : null; }
public int DevicesLength { get { int o = __p.__offset(10); return o != 0 ? __p.__vector_len(o) : 0; } }
public static Offset<NymaTypes.NPortInfo> CreateNPortInfo(FlatBufferBuilder builder,
StringOffset ShortNameOffset = default(StringOffset),
StringOffset FullNameOffset = default(StringOffset),
StringOffset DefaultDeviceShortNameOffset = default(StringOffset),
VectorOffset DevicesOffset = default(VectorOffset)) {
builder.StartTable(4);
NPortInfo.AddDevices(builder, DevicesOffset);
NPortInfo.AddDefaultDeviceShortName(builder, DefaultDeviceShortNameOffset);
NPortInfo.AddFullName(builder, FullNameOffset);
NPortInfo.AddShortName(builder, ShortNameOffset);
return NPortInfo.EndNPortInfo(builder);
}
public static void StartNPortInfo(FlatBufferBuilder builder) { builder.StartTable(4); }
public static void AddShortName(FlatBufferBuilder builder, StringOffset ShortNameOffset) { builder.AddOffset(0, ShortNameOffset.Value, 0); }
public static void AddFullName(FlatBufferBuilder builder, StringOffset FullNameOffset) { builder.AddOffset(1, FullNameOffset.Value, 0); }
public static void AddDefaultDeviceShortName(FlatBufferBuilder builder, StringOffset DefaultDeviceShortNameOffset) { builder.AddOffset(2, DefaultDeviceShortNameOffset.Value, 0); }
public static void AddDevices(FlatBufferBuilder builder, VectorOffset DevicesOffset) { builder.AddOffset(3, DevicesOffset.Value, 0); }
public static VectorOffset CreateDevicesVector(FlatBufferBuilder builder, Offset<NymaTypes.NDeviceInfo>[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); }
public static VectorOffset CreateDevicesVectorBlock(FlatBufferBuilder builder, Offset<NymaTypes.NDeviceInfo>[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); }
public static void StartDevicesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
public static Offset<NymaTypes.NPortInfo> EndNPortInfo(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<NymaTypes.NPortInfo>(o);
}
public NPortInfoT UnPack() {
var _o = new NPortInfoT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(NPortInfoT _o) {
_o.ShortName = this.ShortName;
_o.FullName = this.FullName;
_o.DefaultDeviceShortName = this.DefaultDeviceShortName;
_o.Devices = new List<NymaTypes.NDeviceInfoT>();
for (var _j = 0; _j < this.DevicesLength; ++_j) {_o.Devices.Add(this.Devices(_j).HasValue ? this.Devices(_j).Value.UnPack() : null);}
}
public static Offset<NymaTypes.NPortInfo> Pack(FlatBufferBuilder builder, NPortInfoT _o) {
if (_o == null) return default(Offset<NymaTypes.NPortInfo>);
var _ShortName = _o.ShortName == null ? default(StringOffset) : builder.CreateString(_o.ShortName);
var _FullName = _o.FullName == null ? default(StringOffset) : builder.CreateString(_o.FullName);
var _DefaultDeviceShortName = _o.DefaultDeviceShortName == null ? default(StringOffset) : builder.CreateString(_o.DefaultDeviceShortName);
var _Devices = default(VectorOffset);
if (_o.Devices != null) {
var __Devices = new Offset<NymaTypes.NDeviceInfo>[_o.Devices.Count];
for (var _j = 0; _j < __Devices.Length; ++_j) { __Devices[_j] = NymaTypes.NDeviceInfo.Pack(builder, _o.Devices[_j]); }
_Devices = CreateDevicesVector(builder, __Devices);
}
return CreateNPortInfo(
builder,
_ShortName,
_FullName,
_DefaultDeviceShortName,
_Devices);
}
};
public class NPortInfoT
{
public string ShortName { get; set; }
public string FullName { get; set; }
public string DefaultDeviceShortName { get; set; }
public List<NymaTypes.NDeviceInfoT> Devices { get; set; }
public NPortInfoT() {
this.ShortName = null;
this.FullName = null;
this.DefaultDeviceShortName = null;
this.Devices = null;
}
}
}

View File

@ -0,0 +1,74 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
using global::System;
using global::System.Collections.Generic;
using global::FlatBuffers;
public struct NPorts : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); }
public static NPorts GetRootAsNPorts(ByteBuffer _bb) { return GetRootAsNPorts(_bb, new NPorts()); }
public static NPorts GetRootAsNPorts(ByteBuffer _bb, NPorts obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public NPorts __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public NymaTypes.NPortInfo? Values(int j) { int o = __p.__offset(4); return o != 0 ? (NymaTypes.NPortInfo?)(new NymaTypes.NPortInfo()).__assign(__p.__indirect(__p.__vector(o) + j * 4), __p.bb) : null; }
public int ValuesLength { get { int o = __p.__offset(4); return o != 0 ? __p.__vector_len(o) : 0; } }
public static Offset<NymaTypes.NPorts> CreateNPorts(FlatBufferBuilder builder,
VectorOffset ValuesOffset = default(VectorOffset)) {
builder.StartTable(1);
NPorts.AddValues(builder, ValuesOffset);
return NPorts.EndNPorts(builder);
}
public static void StartNPorts(FlatBufferBuilder builder) { builder.StartTable(1); }
public static void AddValues(FlatBufferBuilder builder, VectorOffset ValuesOffset) { builder.AddOffset(0, ValuesOffset.Value, 0); }
public static VectorOffset CreateValuesVector(FlatBufferBuilder builder, Offset<NymaTypes.NPortInfo>[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); }
public static VectorOffset CreateValuesVectorBlock(FlatBufferBuilder builder, Offset<NymaTypes.NPortInfo>[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); }
public static void StartValuesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
public static Offset<NymaTypes.NPorts> EndNPorts(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<NymaTypes.NPorts>(o);
}
public NPortsT UnPack() {
var _o = new NPortsT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(NPortsT _o) {
_o.Values = new List<NymaTypes.NPortInfoT>();
for (var _j = 0; _j < this.ValuesLength; ++_j) {_o.Values.Add(this.Values(_j).HasValue ? this.Values(_j).Value.UnPack() : null);}
}
public static Offset<NymaTypes.NPorts> Pack(FlatBufferBuilder builder, NPortsT _o) {
if (_o == null) return default(Offset<NymaTypes.NPorts>);
var _Values = default(VectorOffset);
if (_o.Values != null) {
var __Values = new Offset<NymaTypes.NPortInfo>[_o.Values.Count];
for (var _j = 0; _j < __Values.Length; ++_j) { __Values[_j] = NymaTypes.NPortInfo.Pack(builder, _o.Values[_j]); }
_Values = CreateValuesVector(builder, __Values);
}
return CreateNPorts(
builder,
_Values);
}
};
public class NPortsT
{
public List<NymaTypes.NPortInfoT> Values { get; set; }
public NPortsT() {
this.Values = null;
}
}
}

View File

@ -0,0 +1,74 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
using global::System;
using global::System.Collections.Generic;
using global::FlatBuffers;
public struct NStatusInfo : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); }
public static NStatusInfo GetRootAsNStatusInfo(ByteBuffer _bb) { return GetRootAsNStatusInfo(_bb, new NStatusInfo()); }
public static NStatusInfo GetRootAsNStatusInfo(ByteBuffer _bb, NStatusInfo obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public NStatusInfo __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public NymaTypes.NStatusState? States(int j) { int o = __p.__offset(4); return o != 0 ? (NymaTypes.NStatusState?)(new NymaTypes.NStatusState()).__assign(__p.__indirect(__p.__vector(o) + j * 4), __p.bb) : null; }
public int StatesLength { get { int o = __p.__offset(4); return o != 0 ? __p.__vector_len(o) : 0; } }
public static Offset<NymaTypes.NStatusInfo> CreateNStatusInfo(FlatBufferBuilder builder,
VectorOffset StatesOffset = default(VectorOffset)) {
builder.StartTable(1);
NStatusInfo.AddStates(builder, StatesOffset);
return NStatusInfo.EndNStatusInfo(builder);
}
public static void StartNStatusInfo(FlatBufferBuilder builder) { builder.StartTable(1); }
public static void AddStates(FlatBufferBuilder builder, VectorOffset StatesOffset) { builder.AddOffset(0, StatesOffset.Value, 0); }
public static VectorOffset CreateStatesVector(FlatBufferBuilder builder, Offset<NymaTypes.NStatusState>[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); }
public static VectorOffset CreateStatesVectorBlock(FlatBufferBuilder builder, Offset<NymaTypes.NStatusState>[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); }
public static void StartStatesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
public static Offset<NymaTypes.NStatusInfo> EndNStatusInfo(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<NymaTypes.NStatusInfo>(o);
}
public NStatusInfoT UnPack() {
var _o = new NStatusInfoT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(NStatusInfoT _o) {
_o.States = new List<NymaTypes.NStatusStateT>();
for (var _j = 0; _j < this.StatesLength; ++_j) {_o.States.Add(this.States(_j).HasValue ? this.States(_j).Value.UnPack() : null);}
}
public static Offset<NymaTypes.NStatusInfo> Pack(FlatBufferBuilder builder, NStatusInfoT _o) {
if (_o == null) return default(Offset<NymaTypes.NStatusInfo>);
var _States = default(VectorOffset);
if (_o.States != null) {
var __States = new Offset<NymaTypes.NStatusState>[_o.States.Count];
for (var _j = 0; _j < __States.Length; ++_j) { __States[_j] = NymaTypes.NStatusState.Pack(builder, _o.States[_j]); }
_States = CreateStatesVector(builder, __States);
}
return CreateNStatusInfo(
builder,
_States);
}
};
public class NStatusInfoT
{
public List<NymaTypes.NStatusStateT> States { get; set; }
public NStatusInfoT() {
this.States = null;
}
}
}

View File

@ -0,0 +1,93 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
using global::System;
using global::System.Collections.Generic;
using global::FlatBuffers;
public struct NStatusState : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); }
public static NStatusState GetRootAsNStatusState(ByteBuffer _bb) { return GetRootAsNStatusState(_bb, new NStatusState()); }
public static NStatusState GetRootAsNStatusState(ByteBuffer _bb, NStatusState obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public NStatusState __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public string ShortName { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetShortNameBytes() { return __p.__vector_as_span<byte>(4, 1); }
#else
public ArraySegment<byte>? GetShortNameBytes() { return __p.__vector_as_arraysegment(4); }
#endif
public byte[] GetShortNameArray() { return __p.__vector_as_array<byte>(4); }
public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetNameBytes() { return __p.__vector_as_span<byte>(6, 1); }
#else
public ArraySegment<byte>? GetNameBytes() { return __p.__vector_as_arraysegment(6); }
#endif
public byte[] GetNameArray() { return __p.__vector_as_array<byte>(6); }
public int Color { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
public static Offset<NymaTypes.NStatusState> CreateNStatusState(FlatBufferBuilder builder,
StringOffset ShortNameOffset = default(StringOffset),
StringOffset NameOffset = default(StringOffset),
int Color = 0) {
builder.StartTable(3);
NStatusState.AddColor(builder, Color);
NStatusState.AddName(builder, NameOffset);
NStatusState.AddShortName(builder, ShortNameOffset);
return NStatusState.EndNStatusState(builder);
}
public static void StartNStatusState(FlatBufferBuilder builder) { builder.StartTable(3); }
public static void AddShortName(FlatBufferBuilder builder, StringOffset ShortNameOffset) { builder.AddOffset(0, ShortNameOffset.Value, 0); }
public static void AddName(FlatBufferBuilder builder, StringOffset NameOffset) { builder.AddOffset(1, NameOffset.Value, 0); }
public static void AddColor(FlatBufferBuilder builder, int Color) { builder.AddInt(2, Color, 0); }
public static Offset<NymaTypes.NStatusState> EndNStatusState(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<NymaTypes.NStatusState>(o);
}
public NStatusStateT UnPack() {
var _o = new NStatusStateT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(NStatusStateT _o) {
_o.ShortName = this.ShortName;
_o.Name = this.Name;
_o.Color = this.Color;
}
public static Offset<NymaTypes.NStatusState> Pack(FlatBufferBuilder builder, NStatusStateT _o) {
if (_o == null) return default(Offset<NymaTypes.NStatusState>);
var _ShortName = _o.ShortName == null ? default(StringOffset) : builder.CreateString(_o.ShortName);
var _Name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name);
return CreateNStatusState(
builder,
_ShortName,
_Name,
_o.Color);
}
};
public class NStatusStateT
{
public string ShortName { get; set; }
public string Name { get; set; }
public int Color { get; set; }
public NStatusStateT() {
this.ShortName = null;
this.Name = null;
this.Color = 0;
}
}
}

View File

@ -0,0 +1,82 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
using global::System;
using global::System.Collections.Generic;
using global::FlatBuffers;
public struct NSwitchInfo : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); }
public static NSwitchInfo GetRootAsNSwitchInfo(ByteBuffer _bb) { return GetRootAsNSwitchInfo(_bb, new NSwitchInfo()); }
public static NSwitchInfo GetRootAsNSwitchInfo(ByteBuffer _bb, NSwitchInfo obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public NSwitchInfo __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public uint DefaultPosition { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetUint(o + __p.bb_pos) : (uint)0; } }
public NymaTypes.NSwitchPosition? Positions(int j) { int o = __p.__offset(6); return o != 0 ? (NymaTypes.NSwitchPosition?)(new NymaTypes.NSwitchPosition()).__assign(__p.__indirect(__p.__vector(o) + j * 4), __p.bb) : null; }
public int PositionsLength { get { int o = __p.__offset(6); return o != 0 ? __p.__vector_len(o) : 0; } }
public static Offset<NymaTypes.NSwitchInfo> CreateNSwitchInfo(FlatBufferBuilder builder,
uint DefaultPosition = 0,
VectorOffset PositionsOffset = default(VectorOffset)) {
builder.StartTable(2);
NSwitchInfo.AddPositions(builder, PositionsOffset);
NSwitchInfo.AddDefaultPosition(builder, DefaultPosition);
return NSwitchInfo.EndNSwitchInfo(builder);
}
public static void StartNSwitchInfo(FlatBufferBuilder builder) { builder.StartTable(2); }
public static void AddDefaultPosition(FlatBufferBuilder builder, uint DefaultPosition) { builder.AddUint(0, DefaultPosition, 0); }
public static void AddPositions(FlatBufferBuilder builder, VectorOffset PositionsOffset) { builder.AddOffset(1, PositionsOffset.Value, 0); }
public static VectorOffset CreatePositionsVector(FlatBufferBuilder builder, Offset<NymaTypes.NSwitchPosition>[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); }
public static VectorOffset CreatePositionsVectorBlock(FlatBufferBuilder builder, Offset<NymaTypes.NSwitchPosition>[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); }
public static void StartPositionsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
public static Offset<NymaTypes.NSwitchInfo> EndNSwitchInfo(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<NymaTypes.NSwitchInfo>(o);
}
public NSwitchInfoT UnPack() {
var _o = new NSwitchInfoT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(NSwitchInfoT _o) {
_o.DefaultPosition = this.DefaultPosition;
_o.Positions = new List<NymaTypes.NSwitchPositionT>();
for (var _j = 0; _j < this.PositionsLength; ++_j) {_o.Positions.Add(this.Positions(_j).HasValue ? this.Positions(_j).Value.UnPack() : null);}
}
public static Offset<NymaTypes.NSwitchInfo> Pack(FlatBufferBuilder builder, NSwitchInfoT _o) {
if (_o == null) return default(Offset<NymaTypes.NSwitchInfo>);
var _Positions = default(VectorOffset);
if (_o.Positions != null) {
var __Positions = new Offset<NymaTypes.NSwitchPosition>[_o.Positions.Count];
for (var _j = 0; _j < __Positions.Length; ++_j) { __Positions[_j] = NymaTypes.NSwitchPosition.Pack(builder, _o.Positions[_j]); }
_Positions = CreatePositionsVector(builder, __Positions);
}
return CreateNSwitchInfo(
builder,
_o.DefaultPosition,
_Positions);
}
};
public class NSwitchInfoT
{
public uint DefaultPosition { get; set; }
public List<NymaTypes.NSwitchPositionT> Positions { get; set; }
public NSwitchInfoT() {
this.DefaultPosition = 0;
this.Positions = null;
}
}
}

View File

@ -0,0 +1,100 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
using global::System;
using global::System.Collections.Generic;
using global::FlatBuffers;
public struct NSwitchPosition : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); }
public static NSwitchPosition GetRootAsNSwitchPosition(ByteBuffer _bb) { return GetRootAsNSwitchPosition(_bb, new NSwitchPosition()); }
public static NSwitchPosition GetRootAsNSwitchPosition(ByteBuffer _bb, NSwitchPosition obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public NSwitchPosition __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public string SettingName { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetSettingNameBytes() { return __p.__vector_as_span<byte>(4, 1); }
#else
public ArraySegment<byte>? GetSettingNameBytes() { return __p.__vector_as_arraysegment(4); }
#endif
public byte[] GetSettingNameArray() { return __p.__vector_as_array<byte>(4); }
public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetNameBytes() { return __p.__vector_as_span<byte>(6, 1); }
#else
public ArraySegment<byte>? GetNameBytes() { return __p.__vector_as_arraysegment(6); }
#endif
public byte[] GetNameArray() { return __p.__vector_as_array<byte>(6); }
public string Description { get { int o = __p.__offset(8); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetDescriptionBytes() { return __p.__vector_as_span<byte>(8, 1); }
#else
public ArraySegment<byte>? GetDescriptionBytes() { return __p.__vector_as_arraysegment(8); }
#endif
public byte[] GetDescriptionArray() { return __p.__vector_as_array<byte>(8); }
public static Offset<NymaTypes.NSwitchPosition> CreateNSwitchPosition(FlatBufferBuilder builder,
StringOffset SettingNameOffset = default(StringOffset),
StringOffset NameOffset = default(StringOffset),
StringOffset DescriptionOffset = default(StringOffset)) {
builder.StartTable(3);
NSwitchPosition.AddDescription(builder, DescriptionOffset);
NSwitchPosition.AddName(builder, NameOffset);
NSwitchPosition.AddSettingName(builder, SettingNameOffset);
return NSwitchPosition.EndNSwitchPosition(builder);
}
public static void StartNSwitchPosition(FlatBufferBuilder builder) { builder.StartTable(3); }
public static void AddSettingName(FlatBufferBuilder builder, StringOffset SettingNameOffset) { builder.AddOffset(0, SettingNameOffset.Value, 0); }
public static void AddName(FlatBufferBuilder builder, StringOffset NameOffset) { builder.AddOffset(1, NameOffset.Value, 0); }
public static void AddDescription(FlatBufferBuilder builder, StringOffset DescriptionOffset) { builder.AddOffset(2, DescriptionOffset.Value, 0); }
public static Offset<NymaTypes.NSwitchPosition> EndNSwitchPosition(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<NymaTypes.NSwitchPosition>(o);
}
public NSwitchPositionT UnPack() {
var _o = new NSwitchPositionT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(NSwitchPositionT _o) {
_o.SettingName = this.SettingName;
_o.Name = this.Name;
_o.Description = this.Description;
}
public static Offset<NymaTypes.NSwitchPosition> Pack(FlatBufferBuilder builder, NSwitchPositionT _o) {
if (_o == null) return default(Offset<NymaTypes.NSwitchPosition>);
var _SettingName = _o.SettingName == null ? default(StringOffset) : builder.CreateString(_o.SettingName);
var _Name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name);
var _Description = _o.Description == null ? default(StringOffset) : builder.CreateString(_o.Description);
return CreateNSwitchPosition(
builder,
_SettingName,
_Name,
_Description);
}
};
public class NSwitchPositionT
{
public string SettingName { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public NSwitchPositionT() {
this.SettingName = null;
this.Name = null;
this.Description = null;
}
}
}

View File

@ -0,0 +1,180 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
using global::System;
using global::System.Collections.Generic;
using global::FlatBuffers;
public struct Setting : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); }
public static Setting GetRootAsSetting(ByteBuffer _bb) { return GetRootAsSetting(_bb, new Setting()); }
public static Setting GetRootAsSetting(ByteBuffer _bb, Setting obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public Setting __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public string Name { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetNameBytes() { return __p.__vector_as_span<byte>(4, 1); }
#else
public ArraySegment<byte>? GetNameBytes() { return __p.__vector_as_arraysegment(4); }
#endif
public byte[] GetNameArray() { return __p.__vector_as_array<byte>(4); }
public string Description { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetDescriptionBytes() { return __p.__vector_as_span<byte>(6, 1); }
#else
public ArraySegment<byte>? GetDescriptionBytes() { return __p.__vector_as_arraysegment(6); }
#endif
public byte[] GetDescriptionArray() { return __p.__vector_as_array<byte>(6); }
public string SettingsKey { get { int o = __p.__offset(8); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetSettingsKeyBytes() { return __p.__vector_as_span<byte>(8, 1); }
#else
public ArraySegment<byte>? GetSettingsKeyBytes() { return __p.__vector_as_arraysegment(8); }
#endif
public byte[] GetSettingsKeyArray() { return __p.__vector_as_array<byte>(8); }
public string DefaultValue { get { int o = __p.__offset(10); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetDefaultValueBytes() { return __p.__vector_as_span<byte>(10, 1); }
#else
public ArraySegment<byte>? GetDefaultValueBytes() { return __p.__vector_as_arraysegment(10); }
#endif
public byte[] GetDefaultValueArray() { return __p.__vector_as_array<byte>(10); }
public string Min { get { int o = __p.__offset(12); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetMinBytes() { return __p.__vector_as_span<byte>(12, 1); }
#else
public ArraySegment<byte>? GetMinBytes() { return __p.__vector_as_arraysegment(12); }
#endif
public byte[] GetMinArray() { return __p.__vector_as_array<byte>(12); }
public string Max { get { int o = __p.__offset(14); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
public Span<byte> GetMaxBytes() { return __p.__vector_as_span<byte>(14, 1); }
#else
public ArraySegment<byte>? GetMaxBytes() { return __p.__vector_as_arraysegment(14); }
#endif
public byte[] GetMaxArray() { return __p.__vector_as_array<byte>(14); }
public NymaTypes.SettingsFlags Flags { get { int o = __p.__offset(16); return o != 0 ? (NymaTypes.SettingsFlags)__p.bb.GetUint(o + __p.bb_pos) : 0; } }
public NymaTypes.SettingType Type { get { int o = __p.__offset(18); return o != 0 ? (NymaTypes.SettingType)__p.bb.GetInt(o + __p.bb_pos) : NymaTypes.SettingType.Int; } }
public NymaTypes.EnumValue? SettingEnums(int j) { int o = __p.__offset(20); return o != 0 ? (NymaTypes.EnumValue?)(new NymaTypes.EnumValue()).__assign(__p.__indirect(__p.__vector(o) + j * 4), __p.bb) : null; }
public int SettingEnumsLength { get { int o = __p.__offset(20); return o != 0 ? __p.__vector_len(o) : 0; } }
public static Offset<NymaTypes.Setting> CreateSetting(FlatBufferBuilder builder,
StringOffset NameOffset = default(StringOffset),
StringOffset DescriptionOffset = default(StringOffset),
StringOffset SettingsKeyOffset = default(StringOffset),
StringOffset DefaultValueOffset = default(StringOffset),
StringOffset MinOffset = default(StringOffset),
StringOffset MaxOffset = default(StringOffset),
NymaTypes.SettingsFlags Flags = 0,
NymaTypes.SettingType Type = NymaTypes.SettingType.Int,
VectorOffset SettingEnumsOffset = default(VectorOffset)) {
builder.StartTable(9);
Setting.AddSettingEnums(builder, SettingEnumsOffset);
Setting.AddType(builder, Type);
Setting.AddFlags(builder, Flags);
Setting.AddMax(builder, MaxOffset);
Setting.AddMin(builder, MinOffset);
Setting.AddDefaultValue(builder, DefaultValueOffset);
Setting.AddSettingsKey(builder, SettingsKeyOffset);
Setting.AddDescription(builder, DescriptionOffset);
Setting.AddName(builder, NameOffset);
return Setting.EndSetting(builder);
}
public static void StartSetting(FlatBufferBuilder builder) { builder.StartTable(9); }
public static void AddName(FlatBufferBuilder builder, StringOffset NameOffset) { builder.AddOffset(0, NameOffset.Value, 0); }
public static void AddDescription(FlatBufferBuilder builder, StringOffset DescriptionOffset) { builder.AddOffset(1, DescriptionOffset.Value, 0); }
public static void AddSettingsKey(FlatBufferBuilder builder, StringOffset SettingsKeyOffset) { builder.AddOffset(2, SettingsKeyOffset.Value, 0); }
public static void AddDefaultValue(FlatBufferBuilder builder, StringOffset DefaultValueOffset) { builder.AddOffset(3, DefaultValueOffset.Value, 0); }
public static void AddMin(FlatBufferBuilder builder, StringOffset MinOffset) { builder.AddOffset(4, MinOffset.Value, 0); }
public static void AddMax(FlatBufferBuilder builder, StringOffset MaxOffset) { builder.AddOffset(5, MaxOffset.Value, 0); }
public static void AddFlags(FlatBufferBuilder builder, NymaTypes.SettingsFlags Flags) { builder.AddUint(6, (uint)Flags, 0); }
public static void AddType(FlatBufferBuilder builder, NymaTypes.SettingType Type) { builder.AddInt(7, (int)Type, 0); }
public static void AddSettingEnums(FlatBufferBuilder builder, VectorOffset SettingEnumsOffset) { builder.AddOffset(8, SettingEnumsOffset.Value, 0); }
public static VectorOffset CreateSettingEnumsVector(FlatBufferBuilder builder, Offset<NymaTypes.EnumValue>[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); }
public static VectorOffset CreateSettingEnumsVectorBlock(FlatBufferBuilder builder, Offset<NymaTypes.EnumValue>[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); }
public static void StartSettingEnumsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
public static Offset<NymaTypes.Setting> EndSetting(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<NymaTypes.Setting>(o);
}
public SettingT UnPack() {
var _o = new SettingT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(SettingT _o) {
_o.Name = this.Name;
_o.Description = this.Description;
_o.SettingsKey = this.SettingsKey;
_o.DefaultValue = this.DefaultValue;
_o.Min = this.Min;
_o.Max = this.Max;
_o.Flags = this.Flags;
_o.Type = this.Type;
_o.SettingEnums = new List<NymaTypes.EnumValueT>();
for (var _j = 0; _j < this.SettingEnumsLength; ++_j) {_o.SettingEnums.Add(this.SettingEnums(_j).HasValue ? this.SettingEnums(_j).Value.UnPack() : null);}
}
public static Offset<NymaTypes.Setting> Pack(FlatBufferBuilder builder, SettingT _o) {
if (_o == null) return default(Offset<NymaTypes.Setting>);
var _Name = _o.Name == null ? default(StringOffset) : builder.CreateString(_o.Name);
var _Description = _o.Description == null ? default(StringOffset) : builder.CreateString(_o.Description);
var _SettingsKey = _o.SettingsKey == null ? default(StringOffset) : builder.CreateString(_o.SettingsKey);
var _DefaultValue = _o.DefaultValue == null ? default(StringOffset) : builder.CreateString(_o.DefaultValue);
var _Min = _o.Min == null ? default(StringOffset) : builder.CreateString(_o.Min);
var _Max = _o.Max == null ? default(StringOffset) : builder.CreateString(_o.Max);
var _SettingEnums = default(VectorOffset);
if (_o.SettingEnums != null) {
var __SettingEnums = new Offset<NymaTypes.EnumValue>[_o.SettingEnums.Count];
for (var _j = 0; _j < __SettingEnums.Length; ++_j) { __SettingEnums[_j] = NymaTypes.EnumValue.Pack(builder, _o.SettingEnums[_j]); }
_SettingEnums = CreateSettingEnumsVector(builder, __SettingEnums);
}
return CreateSetting(
builder,
_Name,
_Description,
_SettingsKey,
_DefaultValue,
_Min,
_Max,
_o.Flags,
_o.Type,
_SettingEnums);
}
};
public class SettingT
{
public string Name { get; set; }
public string Description { get; set; }
public string SettingsKey { get; set; }
public string DefaultValue { get; set; }
public string Min { get; set; }
public string Max { get; set; }
public NymaTypes.SettingsFlags Flags { get; set; }
public NymaTypes.SettingType Type { get; set; }
public List<NymaTypes.EnumValueT> SettingEnums { get; set; }
public SettingT() {
this.Name = null;
this.Description = null;
this.SettingsKey = null;
this.DefaultValue = null;
this.Min = null;
this.Max = null;
this.Flags = 0;
this.Type = NymaTypes.SettingType.Int;
this.SettingEnums = null;
}
}
}

View File

@ -0,0 +1,28 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
public enum SettingType : int
{
/// (signed), int8, int16, int32, int64(saved as)
Int = 0,
/// uint8, uint16, uint32, uint64(saved as)
Uint = 1,
/// 0 or 1
Bool = 2,
/// float64
Float = 3,
String = 4,
/// string value from a list of potential strings
Enum = 5,
/// TODO: How do these work
MultiEnum = 6,
/// Shouldn't see any of these
Alias = 7,
};
}

View File

@ -0,0 +1,74 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
using global::System;
using global::System.Collections.Generic;
using global::FlatBuffers;
public struct Settings : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_1_12_0(); }
public static Settings GetRootAsSettings(ByteBuffer _bb) { return GetRootAsSettings(_bb, new Settings()); }
public static Settings GetRootAsSettings(ByteBuffer _bb, Settings obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
public Settings __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public NymaTypes.Setting? Values(int j) { int o = __p.__offset(4); return o != 0 ? (NymaTypes.Setting?)(new NymaTypes.Setting()).__assign(__p.__indirect(__p.__vector(o) + j * 4), __p.bb) : null; }
public int ValuesLength { get { int o = __p.__offset(4); return o != 0 ? __p.__vector_len(o) : 0; } }
public static Offset<NymaTypes.Settings> CreateSettings(FlatBufferBuilder builder,
VectorOffset ValuesOffset = default(VectorOffset)) {
builder.StartTable(1);
Settings.AddValues(builder, ValuesOffset);
return Settings.EndSettings(builder);
}
public static void StartSettings(FlatBufferBuilder builder) { builder.StartTable(1); }
public static void AddValues(FlatBufferBuilder builder, VectorOffset ValuesOffset) { builder.AddOffset(0, ValuesOffset.Value, 0); }
public static VectorOffset CreateValuesVector(FlatBufferBuilder builder, Offset<NymaTypes.Setting>[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); }
public static VectorOffset CreateValuesVectorBlock(FlatBufferBuilder builder, Offset<NymaTypes.Setting>[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); }
public static void StartValuesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
public static Offset<NymaTypes.Settings> EndSettings(FlatBufferBuilder builder) {
int o = builder.EndTable();
return new Offset<NymaTypes.Settings>(o);
}
public SettingsT UnPack() {
var _o = new SettingsT();
this.UnPackTo(_o);
return _o;
}
public void UnPackTo(SettingsT _o) {
_o.Values = new List<NymaTypes.SettingT>();
for (var _j = 0; _j < this.ValuesLength; ++_j) {_o.Values.Add(this.Values(_j).HasValue ? this.Values(_j).Value.UnPack() : null);}
}
public static Offset<NymaTypes.Settings> Pack(FlatBufferBuilder builder, SettingsT _o) {
if (_o == null) return default(Offset<NymaTypes.Settings>);
var _Values = default(VectorOffset);
if (_o.Values != null) {
var __Values = new Offset<NymaTypes.Setting>[_o.Values.Count];
for (var _j = 0; _j < __Values.Length; ++_j) { __Values[_j] = NymaTypes.Setting.Pack(builder, _o.Values[_j]); }
_Values = CreateValuesVector(builder, __Values);
}
return CreateSettings(
builder,
_Values);
}
};
public class SettingsT
{
public List<NymaTypes.SettingT> Values { get; set; }
public SettingsT() {
this.Values = null;
}
}
}

View File

@ -0,0 +1,34 @@
// <auto-generated>
// automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>
namespace NymaTypes
{
[System.FlagsAttribute]
public enum SettingsFlags : uint
{
/// TODO(cats)
Input = 256,
Sound = 512,
Video = 1024,
/// User-configurable physical->virtual button/axes and hotkey mappings(driver-side code category mainly).
InputMapping = 2048,
Path = 4096,
/// If the setting affects emulation from the point of view of the emulated program
EmuState = 131072,
/// If it's safe for an untrusted source to modify it, probably only used in conjunction with MDFNST_EX_EMU_STATE and network play
UntrustedSafe = 262144,
/// Suppress documentation generation for this setting.
SuppressDoc = 524288,
/// Auto-generated common template setting(like nes.xscale, pce.xscale, vb.xscale, nes.enable, pce.enable, vb.enable)
CommonTemplate = 1048576,
/// Don't save setting in settings file.
NonPersistent = 2097152,
/// TODO(in progress)
RequiresReload = 16777216,
RequiresRestart = 33554432,
};
}

View File

@ -365,6 +365,19 @@ namespace BizHawk.Emulation.Cores.Waterbox
return -EINVAL;
}
}
[BizExport(CallingConvention.Cdecl, EntryPoint = "__wsyscalltab[77]")]
public long FTruncate(int fd, long length)
{
var s = StreamForFd(fd);
if (s == null)
return -EBADF;
if (!s.CanWrite)
return -ESPIPE;
if (!s.CanSeek)
return -ESPIPE;
s.SetLength(length);
return 0;
}
// TODO: Remove this entirely once everything is compiled against the new libc
[BizExport(CallingConvention.Cdecl, EntryPoint = "__wsyscalltab[205]")]

View File

@ -48,6 +48,28 @@
"type_traits": "cpp",
"unordered_map": "cpp",
"utility": "cpp",
"vector": "cpp"
"vector": "cpp",
"__errc": "cpp",
"__locale": "cpp",
"__mutex_base": "cpp",
"__threading_support": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cstdarg": "cpp",
"ctime": "cpp",
"fstream": "cpp",
"iomanip": "cpp",
"ios": "cpp",
"iostream": "cpp",
"istream": "cpp",
"locale": "cpp",
"mutex": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"set": "cpp",
"sstream": "cpp",
"stack": "cpp",
"streambuf": "cpp",
"system_error": "cpp"
}
}

View File

@ -5,6 +5,7 @@
#include <stdint.h>
#include "mednafen/src/FileStream.h"
#include "nyma.h"
#include "NymaTypes_generated.h"
using namespace Mednafen;
@ -204,156 +205,6 @@ ECL_EXPORT void SetInputCallback(void (*cb)())
InputCallback = cb;
}
// same information as PortInfo, but easier to marshal
struct NPortInfo
{
const char* ShortName;
const char* FullName;
const char* DefaultDeviceShortName;
uint32_t NumDevices;
};
struct NDeviceInfo
{
const char* ShortName;
const char* FullName;
const char* Description;
uint32_t Flags;
uint32_t ByteLength;
uint32_t NumInputs;
};
struct NInputInfo
{
const char* SettingName;
const char* Name;
int16_t ConfigOrder;
uint16_t BitOffset;
InputDeviceInputType Type; // uint8_t
uint8_t Flags;
uint8_t BitSize;
};
struct NButtonInfo
{
const char* ExcludeName;
};
struct NAxisInfo
{
// negative, then positive
const char* SettingName[2];
const char* Name[2];
};
struct NSwitchInfo
{
uint32_t NumPositions;
uint32_t DefaultPosition;
struct Position
{
const char* SettingName;
const char* Name;
const char* Description;
};
};
struct NStatusInfo
{
uint32_t NumStates;
struct State
{
const char* ShortName;
const char* Name;
int32_t Color; // (msb)0RGB(lsb), -1 for unused.
int32_t _Padding;
};
};
ECL_EXPORT uint32_t GetNumPorts()
{
return Game->PortInfo.size();
}
ECL_EXPORT NPortInfo& GetPort(uint32_t port)
{
auto& a = *(NPortInfo*)InputPortData;
auto& x = Game->PortInfo[port];
a.ShortName = x.ShortName;
a.FullName = x.FullName;
a.DefaultDeviceShortName = x.DefaultDevice;
a.NumDevices = x.DeviceInfo.size();
return a;
}
ECL_EXPORT NDeviceInfo& GetDevice(uint32_t port, uint32_t dev)
{
auto& b = *(NDeviceInfo*)InputPortData;
auto& y = Game->PortInfo[port].DeviceInfo[dev];
b.ShortName = y.ShortName;
b.FullName = y.FullName;
b.Description = y.Description;
b.Flags = y.Flags;
b.ByteLength = y.IDII.InputByteSize;
b.NumInputs = y.IDII.size();
return b;
}
ECL_EXPORT NInputInfo& GetInput(uint32_t port, uint32_t dev, uint32_t input)
{
auto& c = *(NInputInfo*)InputPortData;
auto& z = Game->PortInfo[port].DeviceInfo[dev].IDII[input];
c.SettingName = z.SettingName;
c.Name = z.Name;
c.ConfigOrder = z.ConfigOrder;
c.BitOffset = z.BitOffset;
c.Type = z.Type;
c.Flags = z.Flags;
c.BitSize = z.BitSize;
return c;
}
ECL_EXPORT NButtonInfo& GetButton(uint32_t port, uint32_t dev, uint32_t input)
{
auto& c = *(NButtonInfo*)InputPortData;
auto& z = Game->PortInfo[port].DeviceInfo[dev].IDII[input].Button;
c.ExcludeName = z.ExcludeName;
return c;
}
ECL_EXPORT NSwitchInfo& GetSwitch(uint32_t port, uint32_t dev, uint32_t input)
{
auto& c = *(NSwitchInfo*)InputPortData;
auto& z = Game->PortInfo[port].DeviceInfo[dev].IDII[input].Switch;
c.NumPositions = z.NumPos;
c.DefaultPosition = z.DefPos;
return c;
}
ECL_EXPORT NSwitchInfo::Position& GetSwitchPosition(uint32_t port, uint32_t dev, uint32_t input, int i)
{
auto& c = *(NSwitchInfo::Position*)InputPortData;
auto& z = Game->PortInfo[port].DeviceInfo[dev].IDII[input].Switch;
c.SettingName = z.Pos[i].SettingName;
c.Name = z.Pos[i].Name;
c.Description = z.Pos[i].Description;
return c;
}
ECL_EXPORT NStatusInfo& GetStatus(uint32_t port, uint32_t dev, uint32_t input)
{
auto& c = *(NStatusInfo*)InputPortData;
auto& z = Game->PortInfo[port].DeviceInfo[dev].IDII[input].Status;
c.NumStates = z.NumStates;
return c;
}
ECL_EXPORT NStatusInfo::State& GetStatusState(uint32_t port, uint32_t dev, uint32_t input, int i)
{
auto& c = *(NStatusInfo::State*)InputPortData;
auto& z = Game->PortInfo[port].DeviceInfo[dev].IDII[input].Status;
c.ShortName = z.States[i].ShortName;
c.Name = z.States[i].Name;
c.Color = z.States[i].Color;
return c;
}
ECL_EXPORT NAxisInfo& GetAxis(uint32_t port, uint32_t dev, uint32_t input)
{
auto& c = *(NAxisInfo*)InputPortData;
auto& z = Game->PortInfo[port].DeviceInfo[dev].IDII[input].Axis;
c.SettingName[0] = z.sname_dir[0];
c.SettingName[1] = z.sname_dir[1];
c.Name[0] = z.name_dir[0];
c.Name[1] = z.name_dir[1];
return c;
}
ECL_EXPORT void SetInputDevices(const char** devices)
{
for (unsigned port = 0; port < MAX_PORTS && devices[port]; port++)
@ -363,47 +214,141 @@ ECL_EXPORT void SetInputDevices(const char** devices)
}
}
struct NSetting
namespace NymaTypes
{
const char* Name;
const char* Description;
const char* SettingsKey;
const char* DefaultValue;
const char* Min;
const char* Max;
uint32_t Flags;
uint32_t Type;
};
struct NEnumValue
#define MAYBENULL(y,x) if(x) y = x
ECL_EXPORT void DumpInputs()
{
const char* Name;
const char* Description;
const char* Value;
};
ECL_EXPORT void IterateSettings(int index, NSetting& s)
{
auto& a = Game->Settings[index];
if (a.name)
NPortsT ports;
for (auto& x: Game->PortInfo)
{
s.Name = a.description;
s.Description = a.description_extra;
s.SettingsKey = a.name;
s.DefaultValue = a.default_value;
s.Min = a.minimum;
s.Max = a.maximum;
s.Flags = a.flags;
s.Type = a.type;
std::unique_ptr<NPortInfoT> a(new NPortInfoT());
MAYBENULL(a->ShortName, x.ShortName);
MAYBENULL(a->FullName, x.FullName);
MAYBENULL(a->DefaultDeviceShortName, x.DefaultDevice);
for (auto& y: x.DeviceInfo)
{
std::unique_ptr<NDeviceInfoT> b(new NDeviceInfoT());
MAYBENULL(b->ShortName, y.ShortName);
MAYBENULL(b->FullName, y.FullName);
MAYBENULL(b->Description, y.Description);
b->Flags = (DeviceFlags)y.Flags;
b->ByteLength = y.IDII.InputByteSize;
for (auto& z: y.IDII)
{
std::unique_ptr<NInputInfoT> c(new NInputInfoT());
MAYBENULL(c->SettingName, z.SettingName);
MAYBENULL(c->Name, z.Name);
c->ConfigOrder = z.ConfigOrder;
c->BitOffset = z.BitOffset;
c->Type = (InputType)z.Type;
c->Flags = (AxisFlags)z.Flags;
c->BitSize = z.BitSize;
switch(z.Type)
{
case IDIT_BUTTON:
case IDIT_BUTTON_CAN_RAPID:
{
auto p(new NButtonInfoT());
MAYBENULL(p->ExcludeName, z.Button.ExcludeName);
c->Extra.type = NInputExtra_Button;
c->Extra.value = p;
break;
}
case IDIT_SWITCH:
{
auto p(new NSwitchInfoT());
p->DefaultPosition = z.Switch.DefPos;
for (uint32_t i = 0; i < z.Switch.NumPos; i++)
{
auto& q = z.Switch.Pos[i];
std::unique_ptr<NSwitchPositionT> d(new NSwitchPositionT());
MAYBENULL(d->SettingName, q.SettingName);
MAYBENULL(d->Name, q.Name);
MAYBENULL(d->Description, q.Description);
p->Positions.push_back(std::move(d));
}
c->Extra.type = NInputExtra_Switch;
c->Extra.value = p;
break;
}
case IDIT_STATUS:
{
auto p(new NStatusInfoT());
for (uint32_t i = 0; i < z.Status.NumStates; i++)
{
auto& q = z.Status.States[i];
std::unique_ptr<NStatusStateT> d(new NStatusStateT());
MAYBENULL(d->ShortName, q.ShortName);
MAYBENULL(d->Name, q.Name);
d->Color = q.Color;
p->States.push_back(std::move(d));
}
c->Extra.type = NInputExtra_Status;
c->Extra.value = p;
break;
}
case IDIT_AXIS:
case IDIT_AXIS_REL:
{
auto p(new NAxisInfoT());
MAYBENULL(p->SettingsNameNeg, z.Axis.sname_dir[0]);
MAYBENULL(p->SettingsNamePos, z.Axis.sname_dir[1]);
MAYBENULL(p->NameNeg, z.Axis.name_dir[0]);
MAYBENULL(p->NamePos, z.Axis.name_dir[1]);
c->Extra.type = NInputExtra_Axis;
c->Extra.value = p;
break;
}
default:
// no extra data on these
break;
}
b->Inputs.push_back(std::move(c));
}
a->Devices.push_back(std::move(b));
}
ports.Values.push_back(std::move(a));
}
flatbuffers::FlatBufferBuilder fbb;
fbb.Finish(NPorts::Pack(fbb, &ports));
FileStream f("inputs", FileStream::MODE_WRITE);
f.write(fbb.GetBufferPointer(), fbb.GetSize());
}
ECL_EXPORT void IterateSettingEnums(int index, int enumIndex, NEnumValue& e)
ECL_EXPORT void DumpSettings()
{
auto& a = Game->Settings[index].enum_list[enumIndex];
if (a.string)
SettingsT settings;
for (auto a = Game->Settings; a->name; a++)
{
e.Name = a.description;
e.Description = a.description_extra;
e.Value = a.string;
std::unique_ptr<SettingT> s(new SettingT());
MAYBENULL(s->Name, a->description);
MAYBENULL(s->Description, a->description_extra);
MAYBENULL(s->SettingsKey, a->name);
MAYBENULL(s->DefaultValue, a->default_value);
MAYBENULL(s->Min, a->minimum);
MAYBENULL(s->Max, a->maximum);
s->Flags = (SettingsFlags)a->flags;
s->Type = (SettingType)a->type;
if (a->enum_list)
{
for (auto b = a->enum_list; b->string; b++)
{
std::unique_ptr<EnumValueT> e(new EnumValueT());
MAYBENULL(e->Name, b->description);
MAYBENULL(e->Description, b->description_extra);
MAYBENULL(e->Value, b->string);
s->SettingEnums.push_back(std::move(e));
}
}
settings.Values.push_back(std::move(s));
}
flatbuffers::FlatBufferBuilder fbb;
fbb.Finish(Settings::Pack(fbb, &settings));
FileStream f("settings", FileStream::MODE_WRITE);
f.write(fbb.GetBufferPointer(), fbb.GetSize());
}
}

151
waterbox/nyma/NymaTypes.fbs Normal file
View File

@ -0,0 +1,151 @@
namespace NymaTypes;
enum SettingType: int32 {
/// (signed), int8, int16, int32, int64(saved as)
Int,
/// uint8, uint16, uint32, uint64(saved as)
Uint,
/// 0 or 1
Bool,
/// float64
Float,
String,
/// string value from a list of potential strings
Enum,
/// TODO: How do these work
MultiEnum,
/// Shouldn't see any of these
Alias,
}
enum SettingsFlags: uint32 (bit_flags) {
/// TODO(cats)
Input = 8,
Sound = 9,
Video = 10,
/// User-configurable physical->virtual button/axes and hotkey mappings(driver-side code category mainly).
InputMapping = 11,
Path = 12,
/// If the setting affects emulation from the point of view of the emulated program
EmuState = 17,
/// If it's safe for an untrusted source to modify it, probably only used in conjunction with MDFNST_EX_EMU_STATE and network play
UntrustedSafe = 18,
/// Suppress documentation generation for this setting.
SuppressDoc = 19,
/// Auto-generated common template setting(like nes.xscale, pce.xscale, vb.xscale, nes.enable, pce.enable, vb.enable)
CommonTemplate = 20,
/// Don't save setting in settings file.
NonPersistent = 21,
/// TODO(in progress)
RequiresReload = 24,
RequiresRestart = 25,
}
table EnumValue {
Name: string;
Description: string;
Value: string;
}
table Setting {
Name: string;
Description: string;
SettingsKey: string;
DefaultValue: string;
Min: string;
Max: string;
Flags: SettingsFlags;
Type: SettingType;
SettingEnums: [EnumValue];
}
table Settings {
Values: [Setting];
}
enum InputType: uint8 {
Padding = 0, // n-bit, zero
Button, // 1-bit
ButtonCanRapid, // 1-bit
Switch, // ceil(log2(n))-bit
// Current switch position(default 0).
// Persistent, and bidirectional communication(can be modified driver side, and Mednafen core and emulation module side)
Status, // ceil(log2(n))-bit
// emulation module->driver communication
Axis, // 16-bits; 0 through 65535; 32768 is centered position
PointerX, // mouse pointer, 16-bits, signed - in-screen/window range before scaling/offseting normalized coordinates: [0.0, 1.0)
PointerY, // see: mouse_scale_x, mouse_scale_y, mouse_offs_x, mouse_offs_y
AxisRel, // mouse relative motion, 16-bits, signed
ByteSpecial,
ResetButton, // 1-bit
ButtonAnalog, // 16-bits, 0 - 65535
Rumble, // 16-bits, lower 8 bits are weak rumble(0-255), next 8 bits are strong rumble(0-255), 0=no rumble, 255=max rumble. Somewhat subjective, too...
}
enum AxisFlags: uint8 (bit_flags) {
// Denotes analog data that may need to be scaled to ensure a more squareish logical range(for emulated analog sticks)
Sqlr = 0,
// Invert config order of the two components(neg,pos) of the axis
InvertCo = 1,
SettingsUndoc = 7,
}
enum DeviceFlags: uint8 (bit_flags) {
Keyboard = 0,
}
table NButtonInfo {
ExcludeName: string;
}
table NAxisInfo {
// negative, then positive
SettingsNameNeg: string;
SettingsNamePos: string;
NameNeg: string;
NamePos: string;
}
table NSwitchInfo {
DefaultPosition: uint32;
Positions: [NSwitchPosition];
}
table NSwitchPosition {
SettingName: string;
Name: string;
Description: string;
}
table NStatusInfo {
States: [NStatusState];
}
table NStatusState {
ShortName: string;
Name: string;
Color: int32; // (msb)0RGB(lsb), -1 for unused.
}
union NInputExtra {
Button: NButtonInfo,
Axis: NAxisInfo,
Switch: NSwitchInfo,
Status: NStatusInfo,
}
table NInputInfo {
SettingName: string;
Name: string;
ConfigOrder: int16;
BitOffset: uint16;
Type: InputType;
Flags: AxisFlags;
BitSize: uint8;
Extra: NInputExtra;
}
table NDeviceInfo {
ShortName: string;
FullName: string;
Description: string;
Flags: DeviceFlags;
ByteLength: uint32;
Inputs: [NInputInfo];
}
table NPortInfo {
ShortName: string;
FullName: string;
DefaultDeviceShortName: string;
Devices: [NDeviceInfo];
}
table NPorts {
Values: [NPortInfo];
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,398 @@
#ifndef FLATBUFFERS_BASE_H_
#define FLATBUFFERS_BASE_H_
// clang-format off
// If activate should be declared and included first.
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
defined(_MSC_VER) && defined(_DEBUG)
// The _CRTDBG_MAP_ALLOC inside <crtdbg.h> will replace
// calloc/free (etc) to its debug version using #define directives.
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
// Replace operator new by trace-enabled version.
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#endif
#if !defined(FLATBUFFERS_ASSERT)
#include <assert.h>
#define FLATBUFFERS_ASSERT assert
#elif defined(FLATBUFFERS_ASSERT_INCLUDE)
// Include file with forward declaration
#include FLATBUFFERS_ASSERT_INCLUDE
#endif
#ifndef ARDUINO
#include <cstdint>
#endif
#include <cstddef>
#include <cstdlib>
#include <cstring>
#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H)
#include <utility.h>
#else
#include <utility>
#endif
#include <string>
#include <type_traits>
#include <vector>
#include <set>
#include <algorithm>
#include <iterator>
#include <memory>
#ifdef _STLPORT_VERSION
#define FLATBUFFERS_CPP98_STL
#endif
#ifndef FLATBUFFERS_CPP98_STL
#include <functional>
#endif
#include "flatbuffers/stl_emulation.h"
#if defined(__ICCARM__)
#include <intrinsics.h>
#endif
// Note the __clang__ check is needed, because clang presents itself
// as an older GNUC compiler (4.2).
// Clang 3.3 and later implement all of the ISO C++ 2011 standard.
// Clang 3.4 and later implement all of the ISO C++ 2014 standard.
// http://clang.llvm.org/cxx_status.html
// Note the MSVC value '__cplusplus' may be incorrect:
// The '__cplusplus' predefined macro in the MSVC stuck at the value 199711L,
// indicating (erroneously!) that the compiler conformed to the C++98 Standard.
// This value should be correct starting from MSVC2017-15.7-Preview-3.
// The '__cplusplus' will be valid only if MSVC2017-15.7-P3 and the `/Zc:__cplusplus` switch is set.
// Workaround (for details see MSDN):
// Use the _MSC_VER and _MSVC_LANG definition instead of the __cplusplus for compatibility.
// The _MSVC_LANG macro reports the Standard version regardless of the '/Zc:__cplusplus' switch.
#if defined(__GNUC__) && !defined(__clang__)
#define FLATBUFFERS_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#else
#define FLATBUFFERS_GCC 0
#endif
#if defined(__clang__)
#define FLATBUFFERS_CLANG (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
#else
#define FLATBUFFERS_CLANG 0
#endif
/// @cond FLATBUFFERS_INTERNAL
#if __cplusplus <= 199711L && \
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
(!defined(__GNUC__) || \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400))
#error A C++11 compatible compiler with support for the auto typing is \
required for FlatBuffers.
#error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__
#endif
#if !defined(__clang__) && \
defined(__GNUC__) && \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600)
// Backwards compatibility for g++ 4.4, and 4.5 which don't have the nullptr
// and constexpr keywords. Note the __clang__ check is needed, because clang
// presents itself as an older GNUC compiler.
#ifndef nullptr_t
const class nullptr_t {
public:
template<class T> inline operator T*() const { return 0; }
private:
void operator&() const;
} nullptr = {};
#endif
#ifndef constexpr
#define constexpr const
#endif
#endif
// The wire format uses a little endian encoding (since that's efficient for
// the common platforms).
#if defined(__s390x__)
#define FLATBUFFERS_LITTLEENDIAN 0
#endif // __s390x__
#if !defined(FLATBUFFERS_LITTLEENDIAN)
#if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
#if (defined(__BIG_ENDIAN__) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
#define FLATBUFFERS_LITTLEENDIAN 0
#else
#define FLATBUFFERS_LITTLEENDIAN 1
#endif // __BIG_ENDIAN__
#elif defined(_MSC_VER)
#if defined(_M_PPC)
#define FLATBUFFERS_LITTLEENDIAN 0
#else
#define FLATBUFFERS_LITTLEENDIAN 1
#endif
#else
#error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN.
#endif
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
#define FLATBUFFERS_VERSION_MAJOR 1
#define FLATBUFFERS_VERSION_MINOR 12
#define FLATBUFFERS_VERSION_REVISION 0
#define FLATBUFFERS_STRING_EXPAND(X) #X
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
namespace flatbuffers {
// Returns version as string "MAJOR.MINOR.REVISION".
const char* FLATBUFFERS_VERSION();
}
#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)) || \
defined(__clang__)
#define FLATBUFFERS_FINAL_CLASS final
#define FLATBUFFERS_OVERRIDE override
#define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t
#else
#define FLATBUFFERS_FINAL_CLASS
#define FLATBUFFERS_OVERRIDE
#define FLATBUFFERS_VTABLE_UNDERLYING_TYPE
#endif
#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
(defined(__cpp_constexpr) && __cpp_constexpr >= 200704)
#define FLATBUFFERS_CONSTEXPR constexpr
#else
#define FLATBUFFERS_CONSTEXPR const
#endif
#if (defined(__cplusplus) && __cplusplus >= 201402L) || \
(defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
#define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR
#else
#define FLATBUFFERS_CONSTEXPR_CPP14
#endif
#if (defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
(defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023026)) || \
defined(__clang__)
#define FLATBUFFERS_NOEXCEPT noexcept
#else
#define FLATBUFFERS_NOEXCEPT
#endif
// NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to
// private, so be sure to put it at the end or reset access mode explicitly.
#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \
defined(__clang__)
#define FLATBUFFERS_DELETE_FUNC(func) func = delete;
#else
#define FLATBUFFERS_DELETE_FUNC(func) private: func;
#endif
#ifndef FLATBUFFERS_HAS_STRING_VIEW
// Only provide flatbuffers::string_view if __has_include can be used
// to detect a header that provides an implementation
#if defined(__has_include)
// Check for std::string_view (in c++17)
#if __has_include(<string_view>) && (__cplusplus >= 201606 || (defined(_HAS_CXX17) && _HAS_CXX17))
#include <string_view>
namespace flatbuffers {
typedef std::string_view string_view;
}
#define FLATBUFFERS_HAS_STRING_VIEW 1
// Check for std::experimental::string_view (in c++14, compiler-dependent)
#elif __has_include(<experimental/string_view>) && (__cplusplus >= 201411)
#include <experimental/string_view>
namespace flatbuffers {
typedef std::experimental::string_view string_view;
}
#define FLATBUFFERS_HAS_STRING_VIEW 1
// Check for absl::string_view
#elif __has_include("absl/strings/string_view.h")
#include "absl/strings/string_view.h"
namespace flatbuffers {
typedef absl::string_view string_view;
}
#define FLATBUFFERS_HAS_STRING_VIEW 1
#endif
#endif // __has_include
#endif // !FLATBUFFERS_HAS_STRING_VIEW
#ifndef FLATBUFFERS_HAS_NEW_STRTOD
// Modern (C++11) strtod and strtof functions are available for use.
// 1) nan/inf strings as argument of strtod;
// 2) hex-float as argument of strtod/strtof.
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || \
(defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \
(defined(__clang__))
#define FLATBUFFERS_HAS_NEW_STRTOD 1
#endif
#endif // !FLATBUFFERS_HAS_NEW_STRTOD
#ifndef FLATBUFFERS_LOCALE_INDEPENDENT
// Enable locale independent functions {strtof_l, strtod_l,strtoll_l, strtoull_l}.
// They are part of the POSIX-2008 but not part of the C/C++ standard.
// GCC/Clang have definition (_XOPEN_SOURCE>=700) if POSIX-2008.
#if ((defined(_MSC_VER) && _MSC_VER >= 1800) || \
(defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE>=700)))
#define FLATBUFFERS_LOCALE_INDEPENDENT 1
#else
#define FLATBUFFERS_LOCALE_INDEPENDENT 0
#endif
#endif // !FLATBUFFERS_LOCALE_INDEPENDENT
// Suppress Undefined Behavior Sanitizer (recoverable only). Usage:
// - __supress_ubsan__("undefined")
// - __supress_ubsan__("signed-integer-overflow")
#if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7))
#define __supress_ubsan__(type) __attribute__((no_sanitize(type)))
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
#define __supress_ubsan__(type) __attribute__((no_sanitize_undefined))
#else
#define __supress_ubsan__(type)
#endif
// This is constexpr function used for checking compile-time constants.
// Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`.
template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) {
return !!t;
}
// Enable C++ attribute [[]] if std:c++17 or higher.
#if ((__cplusplus >= 201703L) \
|| (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
// All attributes unknown to an implementation are ignored without causing an error.
#define FLATBUFFERS_ATTRIBUTE(attr) [[attr]]
#define FLATBUFFERS_FALLTHROUGH() [[fallthrough]]
#else
#define FLATBUFFERS_ATTRIBUTE(attr)
#if FLATBUFFERS_CLANG >= 30800
#define FLATBUFFERS_FALLTHROUGH() [[clang::fallthrough]]
#elif FLATBUFFERS_GCC >= 70300
#define FLATBUFFERS_FALLTHROUGH() [[gnu::fallthrough]]
#else
#define FLATBUFFERS_FALLTHROUGH()
#endif
#endif
/// @endcond
/// @file
namespace flatbuffers {
/// @cond FLATBUFFERS_INTERNAL
// Our default offset / size type, 32bit on purpose on 64bit systems.
// Also, using a consistent offset type maintains compatibility of serialized
// offset values between 32bit and 64bit systems.
typedef uint32_t uoffset_t;
// Signed offsets for references that can go in both directions.
typedef int32_t soffset_t;
// Offset/index used in v-tables, can be changed to uint8_t in
// format forks to save a bit of space if desired.
typedef uint16_t voffset_t;
typedef uintmax_t largest_scalar_t;
// In 32bits, this evaluates to 2GB - 1
#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(::flatbuffers::soffset_t) * 8 - 1)) - 1)
// We support aligning the contents of buffers up to this size.
#define FLATBUFFERS_MAX_ALIGNMENT 16
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4127) // C4127: conditional expression is constant
#endif
template<typename T> T EndianSwap(T t) {
#if defined(_MSC_VER)
#define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
#define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
#define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
#elif defined(__ICCARM__)
#define FLATBUFFERS_BYTESWAP16 __REV16
#define FLATBUFFERS_BYTESWAP32 __REV
#define FLATBUFFERS_BYTESWAP64(x) \
((__REV(static_cast<uint32_t>(x >> 32U))) | (static_cast<uint64_t>(__REV(static_cast<uint32_t>(x)))) << 32U)
#else
#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__)
// __builtin_bswap16 was missing prior to GCC 4.8.
#define FLATBUFFERS_BYTESWAP16(x) \
static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
#else
#define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
#endif
#define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
#define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
#endif
if (sizeof(T) == 1) { // Compile-time if-then's.
return t;
} else if (sizeof(T) == 2) {
union { T t; uint16_t i; } u = { t };
u.i = FLATBUFFERS_BYTESWAP16(u.i);
return u.t;
} else if (sizeof(T) == 4) {
union { T t; uint32_t i; } u = { t };
u.i = FLATBUFFERS_BYTESWAP32(u.i);
return u.t;
} else if (sizeof(T) == 8) {
union { T t; uint64_t i; } u = { t };
u.i = FLATBUFFERS_BYTESWAP64(u.i);
return u.t;
} else {
FLATBUFFERS_ASSERT(0);
return t;
}
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
template<typename T> T EndianScalar(T t) {
#if FLATBUFFERS_LITTLEENDIAN
return t;
#else
return EndianSwap(t);
#endif
}
template<typename T>
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
__supress_ubsan__("alignment")
T ReadScalar(const void *p) {
return EndianScalar(*reinterpret_cast<const T *>(p));
}
template<typename T>
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
__supress_ubsan__("alignment")
void WriteScalar(void *p, T t) {
*reinterpret_cast<T *>(p) = EndianScalar(t);
}
template<typename T> struct Offset;
template<typename T> __supress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) {
*reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o);
}
// Computes how many bytes you'd have to pad to be able to write an
// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
// memory).
__supress_ubsan__("unsigned-integer-overflow")
inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
return ((~buf_size) + 1) & (scalar_size - 1);
}
} // namespace flatbuffers
#endif // FLATBUFFERS_BASE_H_

View File

@ -0,0 +1,229 @@
/*
* 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.
*/
#ifndef FLATBUFFERS_CODE_GENERATORS_H_
#define FLATBUFFERS_CODE_GENERATORS_H_
#include <map>
#include <sstream>
#include "flatbuffers/idl.h"
namespace flatbuffers {
// Utility class to assist in generating code through use of text templates.
//
// Example code:
// CodeWriter code("\t");
// code.SetValue("NAME", "Foo");
// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
// code.SetValue("NAME", "Bar");
// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
// std::cout << code.ToString() << std::endl;
//
// Output:
// void Foo() { printf("%s", "Foo"); }
// void Bar() { printf("%s", "Bar"); }
class CodeWriter {
public:
CodeWriter(std::string pad = std::string())
: pad_(pad), cur_ident_lvl_(0), ignore_ident_(false) {}
// Clears the current "written" code.
void Clear() {
stream_.str("");
stream_.clear();
}
// Associates a key with a value. All subsequent calls to operator+=, where
// the specified key is contained in {{ and }} delimiters will be replaced by
// the given value.
void SetValue(const std::string &key, const std::string &value) {
value_map_[key] = value;
}
std::string GetValue(const std::string &key) const {
const auto it = value_map_.find(key);
return it == value_map_.end() ? "" : it->second;
}
// Appends the given text to the generated code as well as a newline
// character. Any text within {{ and }} delimeters is replaced by values
// previously stored in the CodeWriter by calling SetValue above. The newline
// will be suppressed if the text ends with the \\ character.
void operator+=(std::string text);
// Returns the current contents of the CodeWriter as a std::string.
std::string ToString() const { return stream_.str(); }
// Increase ident level for writing code
void IncrementIdentLevel() { cur_ident_lvl_++; }
// Decrease ident level for writing code
void DecrementIdentLevel() {
if (cur_ident_lvl_) cur_ident_lvl_--;
}
private:
std::map<std::string, std::string> value_map_;
std::stringstream stream_;
std::string pad_;
int cur_ident_lvl_;
bool ignore_ident_;
// Add ident padding (tab or space) based on ident level
void AppendIdent(std::stringstream &stream);
};
class BaseGenerator {
public:
virtual bool generate() = 0;
static std::string NamespaceDir(const Parser &parser, const std::string &path,
const Namespace &ns);
std::string GeneratedFileName(const std::string &path,
const std::string &file_name,
const IDLOptions &options) const;
protected:
BaseGenerator(const Parser &parser, const std::string &path,
const std::string &file_name, std::string qualifying_start,
std::string qualifying_separator, std::string default_extension)
: parser_(parser),
path_(path),
file_name_(file_name),
qualifying_start_(qualifying_start),
qualifying_separator_(qualifying_separator),
default_extension_(default_extension) {}
virtual ~BaseGenerator() {}
// No copy/assign.
BaseGenerator &operator=(const BaseGenerator &);
BaseGenerator(const BaseGenerator &);
std::string NamespaceDir(const Namespace &ns) const;
static const char *FlatBuffersGeneratedWarning();
static std::string FullNamespace(const char *separator, const Namespace &ns);
static std::string LastNamespacePart(const Namespace &ns);
// tracks the current namespace for early exit in WrapInNameSpace
// c++, java and csharp returns a different namespace from
// the following default (no early exit, always fully qualify),
// which works for js and php
virtual const Namespace *CurrentNameSpace() const { return nullptr; }
// Ensure that a type is prefixed with its namespace even within
// its own namespace to avoid conflict between generated method
// names and similarly named classes or structs
std::string WrapInNameSpace(const Namespace *ns,
const std::string &name) const;
std::string WrapInNameSpace(const Definition &def) const;
std::string GetNameSpace(const Definition &def) const;
const Parser &parser_;
const std::string &path_;
const std::string &file_name_;
const std::string qualifying_start_;
const std::string qualifying_separator_;
const std::string default_extension_;
};
struct CommentConfig {
const char *first_line;
const char *content_line_prefix;
const char *last_line;
};
extern void GenComment(const std::vector<std::string> &dc,
std::string *code_ptr, const CommentConfig *config,
const char *prefix = "");
class FloatConstantGenerator {
public:
virtual ~FloatConstantGenerator() {}
std::string GenFloatConstant(const FieldDef &field) const;
private:
virtual std::string Value(double v, const std::string &src) const = 0;
virtual std::string Inf(double v) const = 0;
virtual std::string NaN(double v) const = 0;
virtual std::string Value(float v, const std::string &src) const = 0;
virtual std::string Inf(float v) const = 0;
virtual std::string NaN(float v) const = 0;
template<typename T>
std::string GenFloatConstantImpl(const FieldDef &field) const;
};
class SimpleFloatConstantGenerator : public FloatConstantGenerator {
public:
SimpleFloatConstantGenerator(const char *nan_number,
const char *pos_inf_number,
const char *neg_inf_number);
private:
std::string Value(double v,
const std::string &src) const FLATBUFFERS_OVERRIDE;
std::string Inf(double v) const FLATBUFFERS_OVERRIDE;
std::string NaN(double v) const FLATBUFFERS_OVERRIDE;
std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE;
std::string Inf(float v) const FLATBUFFERS_OVERRIDE;
std::string NaN(float v) const FLATBUFFERS_OVERRIDE;
const std::string nan_number_;
const std::string pos_inf_number_;
const std::string neg_inf_number_;
};
// C++, C#, Java like generator.
class TypedFloatConstantGenerator : public FloatConstantGenerator {
public:
TypedFloatConstantGenerator(const char *double_prefix,
const char *single_prefix, const char *nan_number,
const char *pos_inf_number,
const char *neg_inf_number = "");
private:
std::string Value(double v,
const std::string &src) const FLATBUFFERS_OVERRIDE;
std::string Inf(double v) const FLATBUFFERS_OVERRIDE;
std::string NaN(double v) const FLATBUFFERS_OVERRIDE;
std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE;
std::string Inf(float v) const FLATBUFFERS_OVERRIDE;
std::string NaN(float v) const FLATBUFFERS_OVERRIDE;
std::string MakeNaN(const std::string &prefix) const;
std::string MakeInf(bool neg, const std::string &prefix) const;
const std::string double_prefix_;
const std::string single_prefix_;
const std::string nan_number_;
const std::string pos_inf_number_;
const std::string neg_inf_number_;
};
} // namespace flatbuffers
#endif // FLATBUFFERS_CODE_GENERATORS_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,100 @@
/*
* Copyright 2017 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.
*/
#ifndef FLATBUFFERS_FLATC_H_
#define FLATBUFFERS_FLATC_H_
#include <functional>
#include <limits>
#include <string>
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
namespace flatbuffers {
extern void LogCompilerWarn(const std::string &warn);
extern void LogCompilerError(const std::string &err);
class FlatCompiler {
public:
// Output generator for the various programming languages and formats we
// support.
struct Generator {
typedef bool (*GenerateFn)(const flatbuffers::Parser &parser,
const std::string &path,
const std::string &file_name);
typedef std::string (*MakeRuleFn)(const flatbuffers::Parser &parser,
const std::string &path,
const std::string &file_name);
GenerateFn generate;
const char *generator_opt_short;
const char *generator_opt_long;
const char *lang_name;
bool schema_only;
GenerateFn generateGRPC;
flatbuffers::IDLOptions::Language lang;
const char *generator_help;
MakeRuleFn make_rule;
};
typedef void (*WarnFn)(const FlatCompiler *flatc, const std::string &warn,
bool show_exe_name);
typedef void (*ErrorFn)(const FlatCompiler *flatc, const std::string &err,
bool usage, bool show_exe_name);
// Parameters required to initialize the FlatCompiler.
struct InitParams {
InitParams()
: generators(nullptr),
num_generators(0),
warn_fn(nullptr),
error_fn(nullptr) {}
const Generator *generators;
size_t num_generators;
WarnFn warn_fn;
ErrorFn error_fn;
};
explicit FlatCompiler(const InitParams &params) : params_(params) {}
int Compile(int argc, const char **argv);
std::string GetUsageString(const char *program_name) const;
private:
void ParseFile(flatbuffers::Parser &parser, const std::string &filename,
const std::string &contents,
std::vector<const char *> &include_directories) const;
void LoadBinarySchema(Parser &parser, const std::string &filename,
const std::string &contents);
void Warn(const std::string &warn, bool show_exe_name = true) const;
void Error(const std::string &err, bool usage = true,
bool show_exe_name = true) const;
InitParams params_;
};
} // namespace flatbuffers
#endif // FLATBUFFERS_FLATC_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,330 @@
/*
* 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.
*/
#ifndef FLATBUFFERS_GRPC_H_
#define FLATBUFFERS_GRPC_H_
// Helper functionality to glue FlatBuffers and GRPC.
#include "flatbuffers/flatbuffers.h"
#include "grpc++/support/byte_buffer.h"
#include "grpc/byte_buffer_reader.h"
namespace flatbuffers {
namespace grpc {
// Message is a typed wrapper around a buffer that manages the underlying
// `grpc_slice` and also provides flatbuffers-specific helpers such as `Verify`
// and `GetRoot`. Since it is backed by a `grpc_slice`, the underlying buffer
// is refcounted and ownership is be managed automatically.
template<class T> class Message {
public:
Message() : slice_(grpc_empty_slice()) {}
Message(grpc_slice slice, bool add_ref)
: slice_(add_ref ? grpc_slice_ref(slice) : slice) {}
Message &operator=(const Message &other) = delete;
Message(Message &&other) : slice_(other.slice_) {
other.slice_ = grpc_empty_slice();
}
Message(const Message &other) = delete;
Message &operator=(Message &&other) {
grpc_slice_unref(slice_);
slice_ = other.slice_;
other.slice_ = grpc_empty_slice();
return *this;
}
~Message() { grpc_slice_unref(slice_); }
const uint8_t *mutable_data() const { return GRPC_SLICE_START_PTR(slice_); }
const uint8_t *data() const { return GRPC_SLICE_START_PTR(slice_); }
size_t size() const { return GRPC_SLICE_LENGTH(slice_); }
bool Verify() const {
Verifier verifier(data(), size());
return verifier.VerifyBuffer<T>(nullptr);
}
T *GetMutableRoot() { return flatbuffers::GetMutableRoot<T>(mutable_data()); }
const T *GetRoot() const { return flatbuffers::GetRoot<T>(data()); }
// This is only intended for serializer use, or if you know what you're doing
const grpc_slice &BorrowSlice() const { return slice_; }
private:
grpc_slice slice_;
};
class MessageBuilder;
// SliceAllocator is a gRPC-specific allocator that uses the `grpc_slice`
// refcounted slices to manage memory ownership. This makes it easy and
// efficient to transfer buffers to gRPC.
class SliceAllocator : public Allocator {
public:
SliceAllocator() : slice_(grpc_empty_slice()) {}
SliceAllocator(const SliceAllocator &other) = delete;
SliceAllocator &operator=(const SliceAllocator &other) = delete;
SliceAllocator(SliceAllocator &&other) : slice_(grpc_empty_slice()) {
// default-construct and swap idiom
swap(other);
}
SliceAllocator &operator=(SliceAllocator &&other) {
// move-construct and swap idiom
SliceAllocator temp(std::move(other));
swap(temp);
return *this;
}
void swap(SliceAllocator &other) {
using std::swap;
swap(slice_, other.slice_);
}
virtual ~SliceAllocator() { grpc_slice_unref(slice_); }
virtual uint8_t *allocate(size_t size) override {
FLATBUFFERS_ASSERT(GRPC_SLICE_IS_EMPTY(slice_));
slice_ = grpc_slice_malloc(size);
return GRPC_SLICE_START_PTR(slice_);
}
virtual void deallocate(uint8_t *p, size_t size) override {
FLATBUFFERS_ASSERT(p == GRPC_SLICE_START_PTR(slice_));
FLATBUFFERS_ASSERT(size == GRPC_SLICE_LENGTH(slice_));
grpc_slice_unref(slice_);
slice_ = grpc_empty_slice();
}
virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
size_t new_size, size_t in_use_back,
size_t in_use_front) override {
FLATBUFFERS_ASSERT(old_p == GRPC_SLICE_START_PTR(slice_));
FLATBUFFERS_ASSERT(old_size == GRPC_SLICE_LENGTH(slice_));
FLATBUFFERS_ASSERT(new_size > old_size);
grpc_slice old_slice = slice_;
grpc_slice new_slice = grpc_slice_malloc(new_size);
uint8_t *new_p = GRPC_SLICE_START_PTR(new_slice);
memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
in_use_front);
slice_ = new_slice;
grpc_slice_unref(old_slice);
return new_p;
}
private:
grpc_slice &get_slice(uint8_t *p, size_t size) {
FLATBUFFERS_ASSERT(p == GRPC_SLICE_START_PTR(slice_));
FLATBUFFERS_ASSERT(size == GRPC_SLICE_LENGTH(slice_));
return slice_;
}
grpc_slice slice_;
friend class MessageBuilder;
};
// SliceAllocatorMember is a hack to ensure that the MessageBuilder's
// slice_allocator_ member is constructed before the FlatBufferBuilder, since
// the allocator is used in the FlatBufferBuilder ctor.
namespace detail {
struct SliceAllocatorMember {
SliceAllocator slice_allocator_;
};
} // namespace detail
// MessageBuilder is a gRPC-specific FlatBufferBuilder that uses SliceAllocator
// to allocate gRPC buffers.
class MessageBuilder : private detail::SliceAllocatorMember,
public FlatBufferBuilder {
public:
explicit MessageBuilder(uoffset_t initial_size = 1024)
: FlatBufferBuilder(initial_size, &slice_allocator_, false) {}
MessageBuilder(const MessageBuilder &other) = delete;
MessageBuilder &operator=(const MessageBuilder &other) = delete;
MessageBuilder(MessageBuilder &&other)
: FlatBufferBuilder(1024, &slice_allocator_, false) {
// Default construct and swap idiom.
Swap(other);
}
/// Create a MessageBuilder from a FlatBufferBuilder.
explicit MessageBuilder(FlatBufferBuilder &&src,
void (*dealloc)(void *,
size_t) = &DefaultAllocator::dealloc)
: FlatBufferBuilder(1024, &slice_allocator_, false) {
src.Swap(*this);
src.SwapBufAllocator(*this);
if (buf_.capacity()) {
uint8_t *buf = buf_.scratch_data(); // pointer to memory
size_t capacity = buf_.capacity(); // size of memory
slice_allocator_.slice_ = grpc_slice_new_with_len(buf, capacity, dealloc);
} else {
slice_allocator_.slice_ = grpc_empty_slice();
}
}
/// Move-assign a FlatBufferBuilder to a MessageBuilder.
/// Only FlatBufferBuilder with default allocator (basically, nullptr) is
/// supported.
MessageBuilder &operator=(FlatBufferBuilder &&src) {
// Move construct a temporary and swap
MessageBuilder temp(std::move(src));
Swap(temp);
return *this;
}
MessageBuilder &operator=(MessageBuilder &&other) {
// Move construct a temporary and swap
MessageBuilder temp(std::move(other));
Swap(temp);
return *this;
}
void Swap(MessageBuilder &other) {
slice_allocator_.swap(other.slice_allocator_);
FlatBufferBuilder::Swap(other);
// After swapping the FlatBufferBuilder, we swap back the allocator, which
// restores the original allocator back in place. This is necessary because
// MessageBuilder's allocator is its own member (SliceAllocatorMember). The
// allocator passed to FlatBufferBuilder::vector_downward must point to this
// member.
buf_.swap_allocator(other.buf_);
}
// Releases the ownership of the buffer pointer.
// Returns the size, offset, and the original grpc_slice that
// allocated the buffer. Also see grpc_slice_unref().
uint8_t *ReleaseRaw(size_t &size, size_t &offset, grpc_slice &slice) {
uint8_t *buf = FlatBufferBuilder::ReleaseRaw(size, offset);
slice = slice_allocator_.slice_;
slice_allocator_.slice_ = grpc_empty_slice();
return buf;
}
~MessageBuilder() {}
// GetMessage extracts the subslice of the buffer corresponding to the
// flatbuffers-encoded region and wraps it in a `Message<T>` to handle buffer
// ownership.
template<class T> Message<T> GetMessage() {
auto buf_data = buf_.scratch_data(); // pointer to memory
auto buf_size = buf_.capacity(); // size of memory
auto msg_data = buf_.data(); // pointer to msg
auto msg_size = buf_.size(); // size of msg
// Do some sanity checks on data/size
FLATBUFFERS_ASSERT(msg_data);
FLATBUFFERS_ASSERT(msg_size);
FLATBUFFERS_ASSERT(msg_data >= buf_data);
FLATBUFFERS_ASSERT(msg_data + msg_size <= buf_data + buf_size);
// Calculate offsets from the buffer start
auto begin = msg_data - buf_data;
auto end = begin + msg_size;
// Get the slice we are working with (no refcount change)
grpc_slice slice = slice_allocator_.get_slice(buf_data, buf_size);
// Extract a subslice of the existing slice (increment refcount)
grpc_slice subslice = grpc_slice_sub(slice, begin, end);
// Wrap the subslice in a `Message<T>`, but don't increment refcount
Message<T> msg(subslice, false);
return msg;
}
template<class T> Message<T> ReleaseMessage() {
Message<T> msg = GetMessage<T>();
Reset();
return msg;
}
private:
// SliceAllocator slice_allocator_; // part of SliceAllocatorMember
};
} // namespace grpc
} // namespace flatbuffers
namespace grpc {
template<class T> class SerializationTraits<flatbuffers::grpc::Message<T>> {
public:
static grpc::Status Serialize(const flatbuffers::grpc::Message<T> &msg,
grpc_byte_buffer **buffer, bool *own_buffer) {
// We are passed in a `Message<T>`, which is a wrapper around a
// `grpc_slice`. We extract it here using `BorrowSlice()`. The const cast
// is necessary because the `grpc_raw_byte_buffer_create` func expects
// non-const slices in order to increment their refcounts.
grpc_slice *slice = const_cast<grpc_slice *>(&msg.BorrowSlice());
// Now use `grpc_raw_byte_buffer_create` to package the single slice into a
// `grpc_byte_buffer`, incrementing the refcount in the process.
*buffer = grpc_raw_byte_buffer_create(slice, 1);
*own_buffer = true;
return grpc::Status::OK;
}
// Deserialize by pulling the
static grpc::Status Deserialize(grpc_byte_buffer *buffer,
flatbuffers::grpc::Message<T> *msg) {
if (!buffer) {
return ::grpc::Status(::grpc::StatusCode::INTERNAL, "No payload");
}
// Check if this is a single uncompressed slice.
if ((buffer->type == GRPC_BB_RAW) &&
(buffer->data.raw.compression == GRPC_COMPRESS_NONE) &&
(buffer->data.raw.slice_buffer.count == 1)) {
// If it is, then we can reference the `grpc_slice` directly.
grpc_slice slice = buffer->data.raw.slice_buffer.slices[0];
// We wrap a `Message<T>` around the slice, incrementing the refcount.
*msg = flatbuffers::grpc::Message<T>(slice, true);
} else {
// Otherwise, we need to use `grpc_byte_buffer_reader_readall` to read
// `buffer` into a single contiguous `grpc_slice`. The gRPC reader gives
// us back a new slice with the refcount already incremented.
grpc_byte_buffer_reader reader;
grpc_byte_buffer_reader_init(&reader, buffer);
grpc_slice slice = grpc_byte_buffer_reader_readall(&reader);
grpc_byte_buffer_reader_destroy(&reader);
// We wrap a `Message<T>` around the slice, but don't increment refcount
*msg = flatbuffers::grpc::Message<T>(slice, false);
}
grpc_byte_buffer_destroy(buffer);
#if FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
return ::grpc::Status::OK;
#else
if (msg->Verify()) {
return ::grpc::Status::OK;
} else {
return ::grpc::Status(::grpc::StatusCode::INTERNAL,
"Message verification failed");
}
#endif
}
};
} // namespace grpc
#endif // FLATBUFFERS_GRPC_H_

View File

@ -0,0 +1,127 @@
/*
* Copyright 2015 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.
*/
#ifndef FLATBUFFERS_HASH_H_
#define FLATBUFFERS_HASH_H_
#include <cstdint>
#include <cstring>
#include "flatbuffers/flatbuffers.h"
namespace flatbuffers {
template<typename T> struct FnvTraits {
static const T kFnvPrime;
static const T kOffsetBasis;
};
template<> struct FnvTraits<uint32_t> {
static const uint32_t kFnvPrime = 0x01000193;
static const uint32_t kOffsetBasis = 0x811C9DC5;
};
template<> struct FnvTraits<uint64_t> {
static const uint64_t kFnvPrime = 0x00000100000001b3ULL;
static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
};
template<typename T> T HashFnv1(const char *input) {
T hash = FnvTraits<T>::kOffsetBasis;
for (const char *c = input; *c; ++c) {
hash *= FnvTraits<T>::kFnvPrime;
hash ^= static_cast<unsigned char>(*c);
}
return hash;
}
template<typename T> T HashFnv1a(const char *input) {
T hash = FnvTraits<T>::kOffsetBasis;
for (const char *c = input; *c; ++c) {
hash ^= static_cast<unsigned char>(*c);
hash *= FnvTraits<T>::kFnvPrime;
}
return hash;
}
template<> inline uint16_t HashFnv1<uint16_t>(const char *input) {
uint32_t hash = HashFnv1<uint32_t>(input);
return (hash >> 16) ^ (hash & 0xffff);
}
template<> inline uint16_t HashFnv1a<uint16_t>(const char *input) {
uint32_t hash = HashFnv1a<uint32_t>(input);
return (hash >> 16) ^ (hash & 0xffff);
}
template<typename T> struct NamedHashFunction {
const char *name;
typedef T (*HashFunction)(const char *);
HashFunction function;
};
const NamedHashFunction<uint16_t> kHashFunctions16[] = {
{ "fnv1_16", HashFnv1<uint16_t> },
{ "fnv1a_16", HashFnv1a<uint16_t> },
};
const NamedHashFunction<uint32_t> kHashFunctions32[] = {
{ "fnv1_32", HashFnv1<uint32_t> },
{ "fnv1a_32", HashFnv1a<uint32_t> },
};
const NamedHashFunction<uint64_t> kHashFunctions64[] = {
{ "fnv1_64", HashFnv1<uint64_t> },
{ "fnv1a_64", HashFnv1a<uint64_t> },
};
inline NamedHashFunction<uint16_t>::HashFunction FindHashFunction16(
const char *name) {
std::size_t size = sizeof(kHashFunctions16) / sizeof(kHashFunctions16[0]);
for (std::size_t i = 0; i < size; ++i) {
if (std::strcmp(name, kHashFunctions16[i].name) == 0) {
return kHashFunctions16[i].function;
}
}
return nullptr;
}
inline NamedHashFunction<uint32_t>::HashFunction FindHashFunction32(
const char *name) {
std::size_t size = sizeof(kHashFunctions32) / sizeof(kHashFunctions32[0]);
for (std::size_t i = 0; i < size; ++i) {
if (std::strcmp(name, kHashFunctions32[i].name) == 0) {
return kHashFunctions32[i].function;
}
}
return nullptr;
}
inline NamedHashFunction<uint64_t>::HashFunction FindHashFunction64(
const char *name) {
std::size_t size = sizeof(kHashFunctions64) / sizeof(kHashFunctions64[0]);
for (std::size_t i = 0; i < size; ++i) {
if (std::strcmp(name, kHashFunctions64[i].name) == 0) {
return kHashFunctions64[i].function;
}
}
return nullptr;
}
} // namespace flatbuffers
#endif // FLATBUFFERS_HASH_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,408 @@
/*
* Copyright 2017 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.
*/
#ifndef FLATBUFFERS_MINIREFLECT_H_
#define FLATBUFFERS_MINIREFLECT_H_
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/util.h"
namespace flatbuffers {
// Utilities that can be used with the "mini reflection" tables present
// in generated code with --reflect-types (only types) or --reflect-names
// (also names).
// This allows basic reflection functionality such as pretty-printing
// that does not require the use of the schema parser or loading of binary
// schema files at runtime (reflection.h).
// For any of the functions below that take `const TypeTable *`, you pass
// `FooTypeTable()` if the type of the root is `Foo`.
// First, a generic iterator that can be used by multiple algorithms.
struct IterationVisitor {
// These mark the scope of a table or struct.
virtual void StartSequence() {}
virtual void EndSequence() {}
// Called for each field regardless of wether it is present or not.
// If not present, val == nullptr. set_idx is the index of all set fields.
virtual void Field(size_t /*field_idx*/, size_t /*set_idx*/,
ElementaryType /*type*/, bool /*is_vector*/,
const TypeTable * /*type_table*/, const char * /*name*/,
const uint8_t * /*val*/) {}
// Called for a value that is actually present, after a field, or as part
// of a vector.
virtual void UType(uint8_t, const char *) {}
virtual void Bool(bool) {}
virtual void Char(int8_t, const char *) {}
virtual void UChar(uint8_t, const char *) {}
virtual void Short(int16_t, const char *) {}
virtual void UShort(uint16_t, const char *) {}
virtual void Int(int32_t, const char *) {}
virtual void UInt(uint32_t, const char *) {}
virtual void Long(int64_t) {}
virtual void ULong(uint64_t) {}
virtual void Float(float) {}
virtual void Double(double) {}
virtual void String(const String *) {}
virtual void Unknown(const uint8_t *) {} // From a future version.
// These mark the scope of a vector.
virtual void StartVector() {}
virtual void EndVector() {}
virtual void Element(size_t /*i*/, ElementaryType /*type*/,
const TypeTable * /*type_table*/,
const uint8_t * /*val*/) {}
virtual ~IterationVisitor() {}
};
inline size_t InlineSize(ElementaryType type, const TypeTable *type_table) {
switch (type) {
case ET_UTYPE:
case ET_BOOL:
case ET_CHAR:
case ET_UCHAR: return 1;
case ET_SHORT:
case ET_USHORT: return 2;
case ET_INT:
case ET_UINT:
case ET_FLOAT:
case ET_STRING: return 4;
case ET_LONG:
case ET_ULONG:
case ET_DOUBLE: return 8;
case ET_SEQUENCE:
switch (type_table->st) {
case ST_TABLE:
case ST_UNION: return 4;
case ST_STRUCT:
return static_cast<size_t>(type_table->values[type_table->num_elems]);
default: FLATBUFFERS_ASSERT(false); return 1;
}
default: FLATBUFFERS_ASSERT(false); return 1;
}
}
inline int64_t LookupEnum(int64_t enum_val, const int64_t *values,
size_t num_values) {
if (!values) return enum_val;
for (size_t i = 0; i < num_values; i++) {
if (enum_val == values[i]) return static_cast<int64_t>(i);
}
return -1; // Unknown enum value.
}
template<typename T> const char *EnumName(T tval, const TypeTable *type_table) {
if (!type_table || !type_table->names) return nullptr;
auto i = LookupEnum(static_cast<int64_t>(tval), type_table->values,
type_table->num_elems);
if (i >= 0 && i < static_cast<int64_t>(type_table->num_elems)) {
return type_table->names[i];
}
return nullptr;
}
void IterateObject(const uint8_t *obj, const TypeTable *type_table,
IterationVisitor *visitor);
inline void IterateValue(ElementaryType type, const uint8_t *val,
const TypeTable *type_table, const uint8_t *prev_val,
soffset_t vector_index, IterationVisitor *visitor) {
switch (type) {
case ET_UTYPE: {
auto tval = ReadScalar<uint8_t>(val);
visitor->UType(tval, EnumName(tval, type_table));
break;
}
case ET_BOOL: {
visitor->Bool(ReadScalar<uint8_t>(val) != 0);
break;
}
case ET_CHAR: {
auto tval = ReadScalar<int8_t>(val);
visitor->Char(tval, EnumName(tval, type_table));
break;
}
case ET_UCHAR: {
auto tval = ReadScalar<uint8_t>(val);
visitor->UChar(tval, EnumName(tval, type_table));
break;
}
case ET_SHORT: {
auto tval = ReadScalar<int16_t>(val);
visitor->Short(tval, EnumName(tval, type_table));
break;
}
case ET_USHORT: {
auto tval = ReadScalar<uint16_t>(val);
visitor->UShort(tval, EnumName(tval, type_table));
break;
}
case ET_INT: {
auto tval = ReadScalar<int32_t>(val);
visitor->Int(tval, EnumName(tval, type_table));
break;
}
case ET_UINT: {
auto tval = ReadScalar<uint32_t>(val);
visitor->UInt(tval, EnumName(tval, type_table));
break;
}
case ET_LONG: {
visitor->Long(ReadScalar<int64_t>(val));
break;
}
case ET_ULONG: {
visitor->ULong(ReadScalar<uint64_t>(val));
break;
}
case ET_FLOAT: {
visitor->Float(ReadScalar<float>(val));
break;
}
case ET_DOUBLE: {
visitor->Double(ReadScalar<double>(val));
break;
}
case ET_STRING: {
val += ReadScalar<uoffset_t>(val);
visitor->String(reinterpret_cast<const String *>(val));
break;
}
case ET_SEQUENCE: {
switch (type_table->st) {
case ST_TABLE:
val += ReadScalar<uoffset_t>(val);
IterateObject(val, type_table, visitor);
break;
case ST_STRUCT: IterateObject(val, type_table, visitor); break;
case ST_UNION: {
val += ReadScalar<uoffset_t>(val);
FLATBUFFERS_ASSERT(prev_val);
auto union_type = *prev_val; // Always a uint8_t.
if (vector_index >= 0) {
auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(prev_val);
union_type = type_vec->Get(static_cast<uoffset_t>(vector_index));
}
auto type_code_idx =
LookupEnum(union_type, type_table->values, type_table->num_elems);
if (type_code_idx >= 0 &&
type_code_idx < static_cast<int32_t>(type_table->num_elems)) {
auto type_code = type_table->type_codes[type_code_idx];
switch (type_code.base_type) {
case ET_SEQUENCE: {
auto ref = type_table->type_refs[type_code.sequence_ref]();
IterateObject(val, ref, visitor);
break;
}
case ET_STRING:
visitor->String(reinterpret_cast<const String *>(val));
break;
default: visitor->Unknown(val);
}
} else {
visitor->Unknown(val);
}
break;
}
case ST_ENUM: FLATBUFFERS_ASSERT(false); break;
}
break;
}
default: {
visitor->Unknown(val);
break;
}
}
}
inline void IterateObject(const uint8_t *obj, const TypeTable *type_table,
IterationVisitor *visitor) {
visitor->StartSequence();
const uint8_t *prev_val = nullptr;
size_t set_idx = 0;
for (size_t i = 0; i < type_table->num_elems; i++) {
auto type_code = type_table->type_codes[i];
auto type = static_cast<ElementaryType>(type_code.base_type);
auto is_vector = type_code.is_vector != 0;
auto ref_idx = type_code.sequence_ref;
const TypeTable *ref = nullptr;
if (ref_idx >= 0) { ref = type_table->type_refs[ref_idx](); }
auto name = type_table->names ? type_table->names[i] : nullptr;
const uint8_t *val = nullptr;
if (type_table->st == ST_TABLE) {
val = reinterpret_cast<const Table *>(obj)->GetAddressOf(
FieldIndexToOffset(static_cast<voffset_t>(i)));
} else {
val = obj + type_table->values[i];
}
visitor->Field(i, set_idx, type, is_vector, ref, name, val);
if (val) {
set_idx++;
if (is_vector) {
val += ReadScalar<uoffset_t>(val);
auto vec = reinterpret_cast<const Vector<uint8_t> *>(val);
visitor->StartVector();
auto elem_ptr = vec->Data();
for (size_t j = 0; j < vec->size(); j++) {
visitor->Element(j, type, ref, elem_ptr);
IterateValue(type, elem_ptr, ref, prev_val, static_cast<soffset_t>(j),
visitor);
elem_ptr += InlineSize(type, ref);
}
visitor->EndVector();
} else {
IterateValue(type, val, ref, prev_val, -1, visitor);
}
}
prev_val = val;
}
visitor->EndSequence();
}
inline void IterateFlatBuffer(const uint8_t *buffer,
const TypeTable *type_table,
IterationVisitor *callback) {
IterateObject(GetRoot<uint8_t>(buffer), type_table, callback);
}
// Outputting a Flatbuffer to a string. Tries to conform as close to JSON /
// the output generated by idl_gen_text.cpp.
struct ToStringVisitor : public IterationVisitor {
std::string s;
std::string d;
bool q;
std::string in;
size_t indent_level;
bool vector_delimited;
ToStringVisitor(std::string delimiter, bool quotes, std::string indent,
bool vdelimited = true)
: d(delimiter),
q(quotes),
in(indent),
indent_level(0),
vector_delimited(vdelimited) {}
ToStringVisitor(std::string delimiter)
: d(delimiter),
q(false),
in(""),
indent_level(0),
vector_delimited(true) {}
void append_indent() {
for (size_t i = 0; i < indent_level; i++) { s += in; }
}
void StartSequence() {
s += "{";
s += d;
indent_level++;
}
void EndSequence() {
s += d;
indent_level--;
append_indent();
s += "}";
}
void Field(size_t /*field_idx*/, size_t set_idx, ElementaryType /*type*/,
bool /*is_vector*/, const TypeTable * /*type_table*/,
const char *name, const uint8_t *val) {
if (!val) return;
if (set_idx) {
s += ",";
s += d;
}
append_indent();
if (name) {
if (q) s += "\"";
s += name;
if (q) s += "\"";
s += ": ";
}
}
template<typename T> void Named(T x, const char *name) {
if (name) {
if (q) s += "\"";
s += name;
if (q) s += "\"";
} else {
s += NumToString(x);
}
}
void UType(uint8_t x, const char *name) { Named(x, name); }
void Bool(bool x) { s += x ? "true" : "false"; }
void Char(int8_t x, const char *name) { Named(x, name); }
void UChar(uint8_t x, const char *name) { Named(x, name); }
void Short(int16_t x, const char *name) { Named(x, name); }
void UShort(uint16_t x, const char *name) { Named(x, name); }
void Int(int32_t x, const char *name) { Named(x, name); }
void UInt(uint32_t x, const char *name) { Named(x, name); }
void Long(int64_t x) { s += NumToString(x); }
void ULong(uint64_t x) { s += NumToString(x); }
void Float(float x) { s += NumToString(x); }
void Double(double x) { s += NumToString(x); }
void String(const struct String *str) {
EscapeString(str->c_str(), str->size(), &s, true, false);
}
void Unknown(const uint8_t *) { s += "(?)"; }
void StartVector() {
s += "[";
if (vector_delimited) {
s += d;
indent_level++;
append_indent();
} else {
s += " ";
}
}
void EndVector() {
if (vector_delimited) {
s += d;
indent_level--;
append_indent();
} else {
s += " ";
}
s += "]";
}
void Element(size_t i, ElementaryType /*type*/,
const TypeTable * /*type_table*/, const uint8_t * /*val*/) {
if (i) {
s += ",";
if (vector_delimited) {
s += d;
append_indent();
} else {
s += " ";
}
}
}
};
inline std::string FlatBufferToString(const uint8_t *buffer,
const TypeTable *type_table,
bool multi_line = false,
bool vector_delimited = true) {
ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", false, "",
vector_delimited);
IterateFlatBuffer(buffer, type_table, &tostring_visitor);
return tostring_visitor.s;
}
} // namespace flatbuffers
#endif // FLATBUFFERS_MINIREFLECT_H_

View File

@ -0,0 +1,477 @@
/*
* Copyright 2015 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.
*/
#ifndef FLATBUFFERS_REFLECTION_H_
#define FLATBUFFERS_REFLECTION_H_
// This is somewhat of a circular dependency because flatc (and thus this
// file) is needed to generate this header in the first place.
// Should normally not be a problem since it can be generated by the
// previous version of flatc whenever this code needs to change.
// See reflection/generate_code.sh
#include "flatbuffers/reflection_generated.h"
// Helper functionality for reflection.
namespace flatbuffers {
// ------------------------- GETTERS -------------------------
inline bool IsScalar(reflection::BaseType t) {
return t >= reflection::UType && t <= reflection::Double;
}
inline bool IsInteger(reflection::BaseType t) {
return t >= reflection::UType && t <= reflection::ULong;
}
inline bool IsFloat(reflection::BaseType t) {
return t == reflection::Float || t == reflection::Double;
}
inline bool IsLong(reflection::BaseType t) {
return t == reflection::Long || t == reflection::ULong;
}
// Size of a basic type, don't use with structs.
inline size_t GetTypeSize(reflection::BaseType base_type) {
// This needs to correspond to the BaseType enum.
static size_t sizes[] = { 0, 1, 1, 1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 4, 4, 4, 4 };
return sizes[base_type];
}
// Same as above, but now correctly returns the size of a struct if
// the field (or vector element) is a struct.
inline size_t GetTypeSizeInline(reflection::BaseType base_type, int type_index,
const reflection::Schema &schema) {
if (base_type == reflection::Obj &&
schema.objects()->Get(type_index)->is_struct()) {
return schema.objects()->Get(type_index)->bytesize();
} else {
return GetTypeSize(base_type);
}
}
// Get the root, regardless of what type it is.
inline Table *GetAnyRoot(uint8_t *flatbuf) {
return GetMutableRoot<Table>(flatbuf);
}
inline const Table *GetAnyRoot(const uint8_t *flatbuf) {
return GetRoot<Table>(flatbuf);
}
// Get a field's default, if you know it's an integer, and its exact type.
template<typename T> T GetFieldDefaultI(const reflection::Field &field) {
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
return static_cast<T>(field.default_integer());
}
// Get a field's default, if you know it's floating point and its exact type.
template<typename T> T GetFieldDefaultF(const reflection::Field &field) {
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
return static_cast<T>(field.default_real());
}
// Get a field, if you know it's an integer, and its exact type.
template<typename T>
T GetFieldI(const Table &table, const reflection::Field &field) {
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
return table.GetField<T>(field.offset(),
static_cast<T>(field.default_integer()));
}
// Get a field, if you know it's floating point and its exact type.
template<typename T>
T GetFieldF(const Table &table, const reflection::Field &field) {
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
return table.GetField<T>(field.offset(),
static_cast<T>(field.default_real()));
}
// Get a field, if you know it's a string.
inline const String *GetFieldS(const Table &table,
const reflection::Field &field) {
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::String);
return table.GetPointer<const String *>(field.offset());
}
// Get a field, if you know it's a vector.
template<typename T>
Vector<T> *GetFieldV(const Table &table, const reflection::Field &field) {
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Vector &&
sizeof(T) == GetTypeSize(field.type()->element()));
return table.GetPointer<Vector<T> *>(field.offset());
}
// Get a field, if you know it's a vector, generically.
// To actually access elements, use the return value together with
// field.type()->element() in any of GetAnyVectorElemI below etc.
inline VectorOfAny *GetFieldAnyV(const Table &table,
const reflection::Field &field) {
return table.GetPointer<VectorOfAny *>(field.offset());
}
// Get a field, if you know it's a table.
inline Table *GetFieldT(const Table &table, const reflection::Field &field) {
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj ||
field.type()->base_type() == reflection::Union);
return table.GetPointer<Table *>(field.offset());
}
// Get a field, if you know it's a struct.
inline const Struct *GetFieldStruct(const Table &table,
const reflection::Field &field) {
// TODO: This does NOT check if the field is a table or struct, but we'd need
// access to the schema to check the is_struct flag.
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj);
return table.GetStruct<const Struct *>(field.offset());
}
// Get a structure's field, if you know it's a struct.
inline const Struct *GetFieldStruct(const Struct &structure,
const reflection::Field &field) {
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj);
return structure.GetStruct<const Struct *>(field.offset());
}
// Raw helper functions used below: get any value in memory as a 64bit int, a
// double or a string.
// All scalars get static_cast to an int64_t, strings use strtoull, every other
// data type returns 0.
int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data);
// All scalars static cast to double, strings use strtod, every other data
// type is 0.0.
double GetAnyValueF(reflection::BaseType type, const uint8_t *data);
// All scalars converted using stringstream, strings as-is, and all other
// data types provide some level of debug-pretty-printing.
std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
const reflection::Schema *schema, int type_index);
// Get any table field as a 64bit int, regardless of what type it is.
inline int64_t GetAnyFieldI(const Table &table,
const reflection::Field &field) {
auto field_ptr = table.GetAddressOf(field.offset());
return field_ptr ? GetAnyValueI(field.type()->base_type(), field_ptr)
: field.default_integer();
}
// Get any table field as a double, regardless of what type it is.
inline double GetAnyFieldF(const Table &table, const reflection::Field &field) {
auto field_ptr = table.GetAddressOf(field.offset());
return field_ptr ? GetAnyValueF(field.type()->base_type(), field_ptr)
: field.default_real();
}
// Get any table field as a string, regardless of what type it is.
// You may pass nullptr for the schema if you don't care to have fields that
// are of table type pretty-printed.
inline std::string GetAnyFieldS(const Table &table,
const reflection::Field &field,
const reflection::Schema *schema) {
auto field_ptr = table.GetAddressOf(field.offset());
return field_ptr ? GetAnyValueS(field.type()->base_type(), field_ptr, schema,
field.type()->index())
: "";
}
// Get any struct field as a 64bit int, regardless of what type it is.
inline int64_t GetAnyFieldI(const Struct &st, const reflection::Field &field) {
return GetAnyValueI(field.type()->base_type(),
st.GetAddressOf(field.offset()));
}
// Get any struct field as a double, regardless of what type it is.
inline double GetAnyFieldF(const Struct &st, const reflection::Field &field) {
return GetAnyValueF(field.type()->base_type(),
st.GetAddressOf(field.offset()));
}
// Get any struct field as a string, regardless of what type it is.
inline std::string GetAnyFieldS(const Struct &st,
const reflection::Field &field) {
return GetAnyValueS(field.type()->base_type(),
st.GetAddressOf(field.offset()), nullptr, -1);
}
// Get any vector element as a 64bit int, regardless of what type it is.
inline int64_t GetAnyVectorElemI(const VectorOfAny *vec,
reflection::BaseType elem_type, size_t i) {
return GetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i);
}
// Get any vector element as a double, regardless of what type it is.
inline double GetAnyVectorElemF(const VectorOfAny *vec,
reflection::BaseType elem_type, size_t i) {
return GetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i);
}
// Get any vector element as a string, regardless of what type it is.
inline std::string GetAnyVectorElemS(const VectorOfAny *vec,
reflection::BaseType elem_type, size_t i) {
return GetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i,
nullptr, -1);
}
// Get a vector element that's a table/string/vector from a generic vector.
// Pass Table/String/VectorOfAny as template parameter.
// Warning: does no typechecking.
template<typename T>
T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i) {
auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i;
return reinterpret_cast<T *>(elem_ptr + ReadScalar<uoffset_t>(elem_ptr));
}
// Get the inline-address of a vector element. Useful for Structs (pass Struct
// as template arg), or being able to address a range of scalars in-line.
// Get elem_size from GetTypeSizeInline().
// Note: little-endian data on all platforms, use EndianScalar() instead of
// raw pointer access with scalars).
template<typename T>
T *GetAnyVectorElemAddressOf(const VectorOfAny *vec, size_t i,
size_t elem_size) {
return reinterpret_cast<T *>(vec->Data() + elem_size * i);
}
// Similarly, for elements of tables.
template<typename T>
T *GetAnyFieldAddressOf(const Table &table, const reflection::Field &field) {
return reinterpret_cast<T *>(table.GetAddressOf(field.offset()));
}
// Similarly, for elements of structs.
template<typename T>
T *GetAnyFieldAddressOf(const Struct &st, const reflection::Field &field) {
return reinterpret_cast<T *>(st.GetAddressOf(field.offset()));
}
// ------------------------- SETTERS -------------------------
// Set any scalar field, if you know its exact type.
template<typename T>
bool SetField(Table *table, const reflection::Field &field, T val) {
reflection::BaseType type = field.type()->base_type();
if (!IsScalar(type)) { return false; }
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(type));
T def;
if (IsInteger(type)) {
def = GetFieldDefaultI<T>(field);
} else {
FLATBUFFERS_ASSERT(IsFloat(type));
def = GetFieldDefaultF<T>(field);
}
return table->SetField(field.offset(), val, def);
}
// Raw helper functions used below: set any value in memory as a 64bit int, a
// double or a string.
// These work for all scalar values, but do nothing for other data types.
// To set a string, see SetString below.
void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val);
void SetAnyValueF(reflection::BaseType type, uint8_t *data, double val);
void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val);
// Set any table field as a 64bit int, regardless of type what it is.
inline bool SetAnyFieldI(Table *table, const reflection::Field &field,
int64_t val) {
auto field_ptr = table->GetAddressOf(field.offset());
if (!field_ptr) return val == GetFieldDefaultI<int64_t>(field);
SetAnyValueI(field.type()->base_type(), field_ptr, val);
return true;
}
// Set any table field as a double, regardless of what type it is.
inline bool SetAnyFieldF(Table *table, const reflection::Field &field,
double val) {
auto field_ptr = table->GetAddressOf(field.offset());
if (!field_ptr) return val == GetFieldDefaultF<double>(field);
SetAnyValueF(field.type()->base_type(), field_ptr, val);
return true;
}
// Set any table field as a string, regardless of what type it is.
inline bool SetAnyFieldS(Table *table, const reflection::Field &field,
const char *val) {
auto field_ptr = table->GetAddressOf(field.offset());
if (!field_ptr) return false;
SetAnyValueS(field.type()->base_type(), field_ptr, val);
return true;
}
// Set any struct field as a 64bit int, regardless of type what it is.
inline void SetAnyFieldI(Struct *st, const reflection::Field &field,
int64_t val) {
SetAnyValueI(field.type()->base_type(), st->GetAddressOf(field.offset()),
val);
}
// Set any struct field as a double, regardless of type what it is.
inline void SetAnyFieldF(Struct *st, const reflection::Field &field,
double val) {
SetAnyValueF(field.type()->base_type(), st->GetAddressOf(field.offset()),
val);
}
// Set any struct field as a string, regardless of type what it is.
inline void SetAnyFieldS(Struct *st, const reflection::Field &field,
const char *val) {
SetAnyValueS(field.type()->base_type(), st->GetAddressOf(field.offset()),
val);
}
// Set any vector element as a 64bit int, regardless of type what it is.
inline void SetAnyVectorElemI(VectorOfAny *vec, reflection::BaseType elem_type,
size_t i, int64_t val) {
SetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
}
// Set any vector element as a double, regardless of type what it is.
inline void SetAnyVectorElemF(VectorOfAny *vec, reflection::BaseType elem_type,
size_t i, double val) {
SetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
}
// Set any vector element as a string, regardless of type what it is.
inline void SetAnyVectorElemS(VectorOfAny *vec, reflection::BaseType elem_type,
size_t i, const char *val) {
SetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
}
// ------------------------- RESIZING SETTERS -------------------------
// "smart" pointer for use with resizing vectors: turns a pointer inside
// a vector into a relative offset, such that it is not affected by resizes.
template<typename T, typename U> class pointer_inside_vector {
public:
pointer_inside_vector(T *ptr, std::vector<U> &vec)
: offset_(reinterpret_cast<uint8_t *>(ptr) -
reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec))),
vec_(vec) {}
T *operator*() const {
return reinterpret_cast<T *>(
reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec_)) + offset_);
}
T *operator->() const { return operator*(); }
void operator=(const pointer_inside_vector &piv);
private:
size_t offset_;
std::vector<U> &vec_;
};
// Helper to create the above easily without specifying template args.
template<typename T, typename U>
pointer_inside_vector<T, U> piv(T *ptr, std::vector<U> &vec) {
return pointer_inside_vector<T, U>(ptr, vec);
}
inline const char *UnionTypeFieldSuffix() { return "_type"; }
// Helper to figure out the actual table type a union refers to.
inline const reflection::Object &GetUnionType(
const reflection::Schema &schema, const reflection::Object &parent,
const reflection::Field &unionfield, const Table &table) {
auto enumdef = schema.enums()->Get(unionfield.type()->index());
// TODO: this is clumsy and slow, but no other way to find it?
auto type_field = parent.fields()->LookupByKey(
(unionfield.name()->str() + UnionTypeFieldSuffix()).c_str());
FLATBUFFERS_ASSERT(type_field);
auto union_type = GetFieldI<uint8_t>(table, *type_field);
auto enumval = enumdef->values()->LookupByKey(union_type);
return *enumval->object();
}
// Changes the contents of a string inside a FlatBuffer. FlatBuffer must
// live inside a std::vector so we can resize the buffer if needed.
// "str" must live inside "flatbuf" and may be invalidated after this call.
// If your FlatBuffer's root table is not the schema's root table, you should
// pass in your root_table type as well.
void SetString(const reflection::Schema &schema, const std::string &val,
const String *str, std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table = nullptr);
// Resizes a flatbuffers::Vector inside a FlatBuffer. FlatBuffer must
// live inside a std::vector so we can resize the buffer if needed.
// "vec" must live inside "flatbuf" and may be invalidated after this call.
// If your FlatBuffer's root table is not the schema's root table, you should
// pass in your root_table type as well.
uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
const VectorOfAny *vec, uoffset_t num_elems,
uoffset_t elem_size, std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table = nullptr);
template<typename T>
void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
const Vector<T> *vec, std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table = nullptr) {
auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size());
auto newelems = ResizeAnyVector(
schema, newsize, reinterpret_cast<const VectorOfAny *>(vec), vec->size(),
static_cast<uoffset_t>(sizeof(T)), flatbuf, root_table);
// Set new elements to "val".
for (int i = 0; i < delta_elem; i++) {
auto loc = newelems + i * sizeof(T);
auto is_scalar = flatbuffers::is_scalar<T>::value;
if (is_scalar) {
WriteScalar(loc, val);
} else { // struct
*reinterpret_cast<T *>(loc) = val;
}
}
}
// Adds any new data (in the form of a new FlatBuffer) to an existing
// FlatBuffer. This can be used when any of the above methods are not
// sufficient, in particular for adding new tables and new fields.
// This is potentially slightly less efficient than a FlatBuffer constructed
// in one piece, since the new FlatBuffer doesn't share any vtables with the
// existing one.
// The return value can now be set using Vector::MutateOffset or SetFieldT
// below.
const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf,
const uint8_t *newbuf, size_t newlen);
inline bool SetFieldT(Table *table, const reflection::Field &field,
const uint8_t *val) {
FLATBUFFERS_ASSERT(sizeof(uoffset_t) ==
GetTypeSize(field.type()->base_type()));
return table->SetPointer(field.offset(), val);
}
// ------------------------- COPYING -------------------------
// Generic copying of tables from a FlatBuffer into a FlatBuffer builder.
// Can be used to do any kind of merging/selecting you may want to do out
// of existing buffers. Also useful to reconstruct a whole buffer if the
// above resizing functionality has introduced garbage in a buffer you want
// to remove.
// Note: this does not deal with DAGs correctly. If the table passed forms a
// DAG, the copy will be a tree instead (with duplicates). Strings can be
// shared however, by passing true for use_string_pooling.
Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
const reflection::Schema &schema,
const reflection::Object &objectdef,
const Table &table,
bool use_string_pooling = false);
// Verifies the provided flatbuffer using reflection.
// root should point to the root type for this flatbuffer.
// buf should point to the start of flatbuffer data.
// length specifies the size of the flatbuffer data.
bool Verify(const reflection::Schema &schema, const reflection::Object &root,
const uint8_t *buf, size_t length);
} // namespace flatbuffers
#endif // FLATBUFFERS_REFLECTION_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,127 @@
/*
* Copyright 2017 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.
*/
#ifndef FLATBUFFERS_REGISTRY_H_
#define FLATBUFFERS_REGISTRY_H_
#include "flatbuffers/idl.h"
namespace flatbuffers {
// Convenience class to easily parse or generate text for arbitrary FlatBuffers.
// Simply pre-populate it with all schema filenames that may be in use, and
// This class will look them up using the file_identifier declared in the
// schema.
class Registry {
public:
// Call this for all schemas that may be in use. The identifier has
// a function in the generated code, e.g. MonsterIdentifier().
void Register(const char *file_identifier, const char *schema_path) {
Schema schema;
schema.path_ = schema_path;
schemas_[file_identifier] = schema;
}
// Generate text from an arbitrary FlatBuffer by looking up its
// file_identifier in the registry.
bool FlatBufferToText(const uint8_t *flatbuf, size_t len, std::string *dest) {
// Get the identifier out of the buffer.
// If the buffer is truncated, exit.
if (len < sizeof(uoffset_t) + FlatBufferBuilder::kFileIdentifierLength) {
lasterror_ = "buffer truncated";
return false;
}
std::string ident(
reinterpret_cast<const char *>(flatbuf) + sizeof(uoffset_t),
FlatBufferBuilder::kFileIdentifierLength);
// Load and parse the schema.
Parser parser;
if (!LoadSchema(ident, &parser)) return false;
// Now we're ready to generate text.
if (!GenerateText(parser, flatbuf, dest)) {
lasterror_ = "unable to generate text for FlatBuffer binary";
return false;
}
return true;
}
// Converts a binary buffer to text using one of the schemas in the registry,
// use the file_identifier to indicate which.
// If DetachedBuffer::data() is null then parsing failed.
DetachedBuffer TextToFlatBuffer(const char *text,
const char *file_identifier) {
// Load and parse the schema.
Parser parser;
if (!LoadSchema(file_identifier, &parser)) return DetachedBuffer();
// Parse the text.
if (!parser.Parse(text)) {
lasterror_ = parser.error_;
return DetachedBuffer();
}
// We have a valid FlatBuffer. Detach it from the builder and return.
return parser.builder_.Release();
}
// Modify any parsing / output options used by the other functions.
void SetOptions(const IDLOptions &opts) { opts_ = opts; }
// If schemas used contain include statements, call this function for every
// directory the parser should search them for.
void AddIncludeDirectory(const char *path) { include_paths_.push_back(path); }
// Returns a human readable error if any of the above functions fail.
const std::string &GetLastError() { return lasterror_; }
private:
bool LoadSchema(const std::string &ident, Parser *parser) {
// Find the schema, if not, exit.
auto it = schemas_.find(ident);
if (it == schemas_.end()) {
// Don't attach the identifier, since it may not be human readable.
lasterror_ = "identifier for this buffer not in the registry";
return false;
}
auto &schema = it->second;
// Load the schema from disk. If not, exit.
std::string schematext;
if (!LoadFile(schema.path_.c_str(), false, &schematext)) {
lasterror_ = "could not load schema: " + schema.path_;
return false;
}
// Parse schema.
parser->opts = opts_;
if (!parser->Parse(schematext.c_str(), vector_data(include_paths_),
schema.path_.c_str())) {
lasterror_ = parser->error_;
return false;
}
return true;
}
struct Schema {
std::string path_;
// TODO(wvo) optionally cache schema file or parsed schema here.
};
std::string lasterror_;
IDLOptions opts_;
std::vector<const char *> include_paths_;
std::map<std::string, Schema> schemas_;
};
} // namespace flatbuffers
#endif // FLATBUFFERS_REGISTRY_H_

View File

@ -0,0 +1,307 @@
/*
* Copyright 2017 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.
*/
#ifndef FLATBUFFERS_STL_EMULATION_H_
#define FLATBUFFERS_STL_EMULATION_H_
// clang-format off
#include <string>
#include <type_traits>
#include <vector>
#include <memory>
#include <limits>
#if defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
#define FLATBUFFERS_CPP98_STL
#endif // defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
#if defined(FLATBUFFERS_CPP98_STL)
#include <cctype>
#endif // defined(FLATBUFFERS_CPP98_STL)
// Check if we can use template aliases
// Not possible if Microsoft Compiler before 2012
// Possible is the language feature __cpp_alias_templates is defined well
// Or possible if the C++ std is C+11 or newer
#if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \
|| (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \
|| (defined(__cplusplus) && __cplusplus >= 201103L)
#define FLATBUFFERS_TEMPLATES_ALIASES
#endif
// This header provides backwards compatibility for C++98 STLs like stlport.
namespace flatbuffers {
// Retrieve ::back() from a string in a way that is compatible with pre C++11
// STLs (e.g stlport).
inline char& string_back(std::string &value) {
return value[value.length() - 1];
}
inline char string_back(const std::string &value) {
return value[value.length() - 1];
}
// Helper method that retrieves ::data() from a vector in a way that is
// compatible with pre C++11 STLs (e.g stlport).
template <typename T> inline T *vector_data(std::vector<T> &vector) {
// In some debug environments, operator[] does bounds checking, so &vector[0]
// can't be used.
return vector.empty() ? nullptr : &vector[0];
}
template <typename T> inline const T *vector_data(
const std::vector<T> &vector) {
return vector.empty() ? nullptr : &vector[0];
}
template <typename T, typename V>
inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
#if defined(FLATBUFFERS_CPP98_STL)
vector->push_back(data);
#else
vector->emplace_back(std::forward<V>(data));
#endif // defined(FLATBUFFERS_CPP98_STL)
}
#ifndef FLATBUFFERS_CPP98_STL
#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
template <typename T>
using numeric_limits = std::numeric_limits<T>;
#else
template <typename T> class numeric_limits :
public std::numeric_limits<T> {};
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
#else
template <typename T> class numeric_limits :
public std::numeric_limits<T> {
public:
// Android NDK fix.
static T lowest() {
return std::numeric_limits<T>::min();
}
};
template <> class numeric_limits<float> :
public std::numeric_limits<float> {
public:
static float lowest() { return -FLT_MAX; }
};
template <> class numeric_limits<double> :
public std::numeric_limits<double> {
public:
static double lowest() { return -DBL_MAX; }
};
template <> class numeric_limits<unsigned long long> {
public:
static unsigned long long min() { return 0ULL; }
static unsigned long long max() { return ~0ULL; }
static unsigned long long lowest() {
return numeric_limits<unsigned long long>::min();
}
};
template <> class numeric_limits<long long> {
public:
static long long min() {
return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1));
}
static long long max() {
return static_cast<long long>(
(1ULL << ((sizeof(long long) << 3) - 1)) - 1);
}
static long long lowest() {
return numeric_limits<long long>::min();
}
};
#endif // FLATBUFFERS_CPP98_STL
#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
#ifndef FLATBUFFERS_CPP98_STL
template <typename T> using is_scalar = std::is_scalar<T>;
template <typename T, typename U> using is_same = std::is_same<T,U>;
template <typename T> using is_floating_point = std::is_floating_point<T>;
template <typename T> using is_unsigned = std::is_unsigned<T>;
template <typename T> using is_enum = std::is_enum<T>;
template <typename T> using make_unsigned = std::make_unsigned<T>;
template<bool B, class T, class F>
using conditional = std::conditional<B, T, F>;
template<class T, T v>
using integral_constant = std::integral_constant<T, v>;
#else
// Map C++ TR1 templates defined by stlport.
template <typename T> using is_scalar = std::tr1::is_scalar<T>;
template <typename T, typename U> using is_same = std::tr1::is_same<T,U>;
template <typename T> using is_floating_point =
std::tr1::is_floating_point<T>;
template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
template <typename T> using is_enum = std::tr1::is_enum<T>;
// Android NDK doesn't have std::make_unsigned or std::tr1::make_unsigned.
template<typename T> struct make_unsigned {
static_assert(is_unsigned<T>::value, "Specialization not implemented!");
using type = T;
};
template<> struct make_unsigned<char> { using type = unsigned char; };
template<> struct make_unsigned<short> { using type = unsigned short; };
template<> struct make_unsigned<int> { using type = unsigned int; };
template<> struct make_unsigned<long> { using type = unsigned long; };
template<>
struct make_unsigned<long long> { using type = unsigned long long; };
template<bool B, class T, class F>
using conditional = std::tr1::conditional<B, T, F>;
template<class T, T v>
using integral_constant = std::tr1::integral_constant<T, v>;
#endif // !FLATBUFFERS_CPP98_STL
#else
// MSVC 2010 doesn't support C++11 aliases.
template <typename T> struct is_scalar : public std::is_scalar<T> {};
template <typename T, typename U> struct is_same : public std::is_same<T,U> {};
template <typename T> struct is_floating_point :
public std::is_floating_point<T> {};
template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
template <typename T> struct is_enum : public std::is_enum<T> {};
template <typename T> struct make_unsigned : public std::make_unsigned<T> {};
template<bool B, class T, class F>
struct conditional : public std::conditional<B, T, F> {};
template<class T, T v>
struct integral_constant : public std::integral_constant<T, v> {};
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
#ifndef FLATBUFFERS_CPP98_STL
#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
template <class T> using unique_ptr = std::unique_ptr<T>;
#else
// MSVC 2010 doesn't support C++11 aliases.
// We're manually "aliasing" the class here as we want to bring unique_ptr
// into the flatbuffers namespace. We have unique_ptr in the flatbuffers
// namespace we have a completely independent implemenation (see below)
// for C++98 STL implementations.
template <class T> class unique_ptr : public std::unique_ptr<T> {
public:
unique_ptr() {}
explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {}
unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); }
unique_ptr(unique_ptr&& u) { *this = std::move(u); }
unique_ptr& operator=(std::unique_ptr<T>&& u) {
std::unique_ptr<T>::reset(u.release());
return *this;
}
unique_ptr& operator=(unique_ptr&& u) {
std::unique_ptr<T>::reset(u.release());
return *this;
}
unique_ptr& operator=(T* p) {
return std::unique_ptr<T>::operator=(p);
}
};
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
#else
// Very limited implementation of unique_ptr.
// This is provided simply to allow the C++ code generated from the default
// settings to function in C++98 environments with no modifications.
template <class T> class unique_ptr {
public:
typedef T element_type;
unique_ptr() : ptr_(nullptr) {}
explicit unique_ptr(T* p) : ptr_(p) {}
unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); }
unique_ptr(const unique_ptr& u) : ptr_(nullptr) {
reset(const_cast<unique_ptr*>(&u)->release());
}
~unique_ptr() { reset(); }
unique_ptr& operator=(const unique_ptr& u) {
reset(const_cast<unique_ptr*>(&u)->release());
return *this;
}
unique_ptr& operator=(unique_ptr&& u) {
reset(u.release());
return *this;
}
unique_ptr& operator=(T* p) {
reset(p);
return *this;
}
const T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
T* get() const noexcept { return ptr_; }
explicit operator bool() const { return ptr_ != nullptr; }
// modifiers
T* release() {
T* value = ptr_;
ptr_ = nullptr;
return value;
}
void reset(T* p = nullptr) {
T* value = ptr_;
ptr_ = p;
if (value) delete value;
}
void swap(unique_ptr& u) {
T* temp_ptr = ptr_;
ptr_ = u.ptr_;
u.ptr_ = temp_ptr;
}
private:
T* ptr_;
};
template <class T> bool operator==(const unique_ptr<T>& x,
const unique_ptr<T>& y) {
return x.get() == y.get();
}
template <class T, class D> bool operator==(const unique_ptr<T>& x,
const D* y) {
return static_cast<D*>(x.get()) == y;
}
template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) {
return reinterpret_cast<intptr_t>(x.get()) == y;
}
template <class T> bool operator!=(const unique_ptr<T>& x, decltype(nullptr)) {
return !!x;
}
template <class T> bool operator!=(decltype(nullptr), const unique_ptr<T>& x) {
return !!x;
}
template <class T> bool operator==(const unique_ptr<T>& x, decltype(nullptr)) {
return !x;
}
template <class T> bool operator==(decltype(nullptr), const unique_ptr<T>& x) {
return !x;
}
#endif // !FLATBUFFERS_CPP98_STL
} // namespace flatbuffers
#endif // FLATBUFFERS_STL_EMULATION_H_

View File

@ -0,0 +1,683 @@
/*
* 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.
*/
#ifndef FLATBUFFERS_UTIL_H_
#define FLATBUFFERS_UTIL_H_
#include <errno.h>
#include "flatbuffers/base.h"
#ifndef FLATBUFFERS_PREFER_PRINTF
# include <sstream>
#else // FLATBUFFERS_PREFER_PRINTF
# include <float.h>
# include <stdio.h>
#endif // FLATBUFFERS_PREFER_PRINTF
#include <iomanip>
#include <string>
namespace flatbuffers {
// @locale-independent functions for ASCII characters set.
// Fast checking that character lies in closed range: [a <= x <= b]
// using one compare (conditional branch) operator.
inline bool check_ascii_range(char x, char a, char b) {
FLATBUFFERS_ASSERT(a <= b);
// (Hacker's Delight): `a <= x <= b` <=> `(x-a) <={u} (b-a)`.
// The x, a, b will be promoted to int and subtracted without overflow.
return static_cast<unsigned int>(x - a) <= static_cast<unsigned int>(b - a);
}
// Case-insensitive isalpha
inline bool is_alpha(char c) {
// ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
return check_ascii_range(c & 0xDF, 'a' & 0xDF, 'z' & 0xDF);
}
// Check (case-insensitive) that `c` is equal to alpha.
inline bool is_alpha_char(char c, char alpha) {
FLATBUFFERS_ASSERT(is_alpha(alpha));
// ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
return ((c & 0xDF) == (alpha & 0xDF));
}
// https://en.cppreference.com/w/cpp/string/byte/isxdigit
// isdigit and isxdigit are the only standard narrow character classification
// functions that are not affected by the currently installed C locale. although
// some implementations (e.g. Microsoft in 1252 codepage) may classify
// additional single-byte characters as digits.
inline bool is_digit(char c) { return check_ascii_range(c, '0', '9'); }
inline bool is_xdigit(char c) {
// Replace by look-up table.
return is_digit(c) || check_ascii_range(c & 0xDF, 'a' & 0xDF, 'f' & 0xDF);
}
// Case-insensitive isalnum
inline bool is_alnum(char c) { return is_alpha(c) || is_digit(c); }
// @end-locale-independent functions for ASCII character set
#ifdef FLATBUFFERS_PREFER_PRINTF
template<typename T> size_t IntToDigitCount(T t) {
size_t digit_count = 0;
// Count the sign for negative numbers
if (t < 0) digit_count++;
// Count a single 0 left of the dot for fractional numbers
if (-1 < t && t < 1) digit_count++;
// Count digits until fractional part
T eps = std::numeric_limits<float>::epsilon();
while (t <= (-1 + eps) || (1 - eps) <= t) {
t /= 10;
digit_count++;
}
return digit_count;
}
template<typename T> size_t NumToStringWidth(T t, int precision = 0) {
size_t string_width = IntToDigitCount(t);
// Count the dot for floating point numbers
if (precision) string_width += (precision + 1);
return string_width;
}
template<typename T>
std::string NumToStringImplWrapper(T t, const char *fmt, int precision = 0) {
size_t string_width = NumToStringWidth(t, precision);
std::string s(string_width, 0x00);
// Allow snprintf to use std::string trailing null to detect buffer overflow
snprintf(const_cast<char *>(s.data()), (s.size() + 1), fmt, string_width, t);
return s;
}
#endif // FLATBUFFERS_PREFER_PRINTF
// Convert an integer or floating point value to a string.
// In contrast to std::stringstream, "char" values are
// converted to a string of digits, and we don't use scientific notation.
template<typename T> std::string NumToString(T t) {
// clang-format off
#ifndef FLATBUFFERS_PREFER_PRINTF
std::stringstream ss;
ss << t;
return ss.str();
#else // FLATBUFFERS_PREFER_PRINTF
auto v = static_cast<long long>(t);
return NumToStringImplWrapper(v, "%.*lld");
#endif // FLATBUFFERS_PREFER_PRINTF
// clang-format on
}
// Avoid char types used as character data.
template<> inline std::string NumToString<signed char>(signed char t) {
return NumToString(static_cast<int>(t));
}
template<> inline std::string NumToString<unsigned char>(unsigned char t) {
return NumToString(static_cast<int>(t));
}
template<> inline std::string NumToString<char>(char t) {
return NumToString(static_cast<int>(t));
}
#if defined(FLATBUFFERS_CPP98_STL)
template<> inline std::string NumToString<long long>(long long t) {
char buf[21]; // (log((1 << 63) - 1) / log(10)) + 2
snprintf(buf, sizeof(buf), "%lld", t);
return std::string(buf);
}
template<>
inline std::string NumToString<unsigned long long>(unsigned long long t) {
char buf[22]; // (log((1 << 63) - 1) / log(10)) + 1
snprintf(buf, sizeof(buf), "%llu", t);
return std::string(buf);
}
#endif // defined(FLATBUFFERS_CPP98_STL)
// Special versions for floats/doubles.
template<typename T> std::string FloatToString(T t, int precision) {
// clang-format off
#ifndef FLATBUFFERS_PREFER_PRINTF
// to_string() prints different numbers of digits for floats depending on
// platform and isn't available on Android, so we use stringstream
std::stringstream ss;
// Use std::fixed to suppress scientific notation.
ss << std::fixed;
// Default precision is 6, we want that to be higher for doubles.
ss << std::setprecision(precision);
ss << t;
auto s = ss.str();
#else // FLATBUFFERS_PREFER_PRINTF
auto v = static_cast<double>(t);
auto s = NumToStringImplWrapper(v, "%0.*f", precision);
#endif // FLATBUFFERS_PREFER_PRINTF
// clang-format on
// Sadly, std::fixed turns "1" into "1.00000", so here we undo that.
auto p = s.find_last_not_of('0');
if (p != std::string::npos) {
// Strip trailing zeroes. If it is a whole number, keep one zero.
s.resize(p + (s[p] == '.' ? 2 : 1));
}
return s;
}
template<> inline std::string NumToString<double>(double t) {
return FloatToString(t, 12);
}
template<> inline std::string NumToString<float>(float t) {
return FloatToString(t, 6);
}
// Convert an integer value to a hexadecimal string.
// The returned string length is always xdigits long, prefixed by 0 digits.
// For example, IntToStringHex(0x23, 8) returns the string "00000023".
inline std::string IntToStringHex(int i, int xdigits) {
FLATBUFFERS_ASSERT(i >= 0);
// clang-format off
#ifndef FLATBUFFERS_PREFER_PRINTF
std::stringstream ss;
ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase
<< i;
return ss.str();
#else // FLATBUFFERS_PREFER_PRINTF
return NumToStringImplWrapper(i, "%.*X", xdigits);
#endif // FLATBUFFERS_PREFER_PRINTF
// clang-format on
}
// clang-format off
// Use locale independent functions {strtod_l, strtof_l, strtoll_l, strtoull_l}.
#if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && (FLATBUFFERS_LOCALE_INDEPENDENT > 0)
class ClassicLocale {
#ifdef _MSC_VER
typedef _locale_t locale_type;
#else
typedef locale_t locale_type; // POSIX.1-2008 locale_t type
#endif
ClassicLocale();
~ClassicLocale();
locale_type locale_;
static ClassicLocale instance_;
public:
static locale_type Get() { return instance_.locale_; }
};
#ifdef _MSC_VER
#define __strtoull_impl(s, pe, b) _strtoui64_l(s, pe, b, ClassicLocale::Get())
#define __strtoll_impl(s, pe, b) _strtoi64_l(s, pe, b, ClassicLocale::Get())
#define __strtod_impl(s, pe) _strtod_l(s, pe, ClassicLocale::Get())
#define __strtof_impl(s, pe) _strtof_l(s, pe, ClassicLocale::Get())
#else
#define __strtoull_impl(s, pe, b) strtoull_l(s, pe, b, ClassicLocale::Get())
#define __strtoll_impl(s, pe, b) strtoll_l(s, pe, b, ClassicLocale::Get())
#define __strtod_impl(s, pe) strtod_l(s, pe, ClassicLocale::Get())
#define __strtof_impl(s, pe) strtof_l(s, pe, ClassicLocale::Get())
#endif
#else
#define __strtod_impl(s, pe) strtod(s, pe)
#define __strtof_impl(s, pe) static_cast<float>(strtod(s, pe))
#ifdef _MSC_VER
#define __strtoull_impl(s, pe, b) _strtoui64(s, pe, b)
#define __strtoll_impl(s, pe, b) _strtoi64(s, pe, b)
#else
#define __strtoull_impl(s, pe, b) strtoull(s, pe, b)
#define __strtoll_impl(s, pe, b) strtoll(s, pe, b)
#endif
#endif
inline void strtoval_impl(int64_t *val, const char *str, char **endptr,
int base) {
*val = __strtoll_impl(str, endptr, base);
}
inline void strtoval_impl(uint64_t *val, const char *str, char **endptr,
int base) {
*val = __strtoull_impl(str, endptr, base);
}
inline void strtoval_impl(double *val, const char *str, char **endptr) {
*val = __strtod_impl(str, endptr);
}
// UBSAN: double to float is safe if numeric_limits<float>::is_iec559 is true.
__supress_ubsan__("float-cast-overflow")
inline void strtoval_impl(float *val, const char *str, char **endptr) {
*val = __strtof_impl(str, endptr);
}
#undef __strtoull_impl
#undef __strtoll_impl
#undef __strtod_impl
#undef __strtof_impl
// clang-format on
// Adaptor for strtoull()/strtoll().
// Flatbuffers accepts numbers with any count of leading zeros (-009 is -9),
// while strtoll with base=0 interprets first leading zero as octal prefix.
// In future, it is possible to add prefixed 0b0101.
// 1) Checks errno code for overflow condition (out of range).
// 2) If base <= 0, function try to detect base of number by prefix.
//
// Return value (like strtoull and strtoll, but reject partial result):
// - If successful, an integer value corresponding to the str is returned.
// - If full string conversion can't be performed, 0 is returned.
// - If the converted value falls out of range of corresponding return type, a
// range error occurs. In this case value MAX(T)/MIN(T) is returned.
template<typename T>
inline bool StringToIntegerImpl(T *val, const char *const str,
const int base = 0,
const bool check_errno = true) {
// T is int64_t or uint64_T
FLATBUFFERS_ASSERT(str);
if (base <= 0) {
auto s = str;
while (*s && !is_digit(*s)) s++;
if (s[0] == '0' && is_alpha_char(s[1], 'X'))
return StringToIntegerImpl(val, str, 16, check_errno);
// if a prefix not match, try base=10
return StringToIntegerImpl(val, str, 10, check_errno);
} else {
if (check_errno) errno = 0; // clear thread-local errno
auto endptr = str;
strtoval_impl(val, str, const_cast<char **>(&endptr), base);
if ((*endptr != '\0') || (endptr == str)) {
*val = 0; // erase partial result
return false; // invalid string
}
// errno is out-of-range, return MAX/MIN
if (check_errno && errno) return false;
return true;
}
}
template<typename T>
inline bool StringToFloatImpl(T *val, const char *const str) {
// Type T must be either float or double.
FLATBUFFERS_ASSERT(str && val);
auto end = str;
strtoval_impl(val, str, const_cast<char **>(&end));
auto done = (end != str) && (*end == '\0');
if (!done) *val = 0; // erase partial result
return done;
}
// Convert a string to an instance of T.
// Return value (matched with StringToInteger64Impl and strtod):
// - If successful, a numeric value corresponding to the str is returned.
// - If full string conversion can't be performed, 0 is returned.
// - If the converted value falls out of range of corresponding return type, a
// range error occurs. In this case value MAX(T)/MIN(T) is returned.
template<typename T> inline bool StringToNumber(const char *s, T *val) {
FLATBUFFERS_ASSERT(s && val);
int64_t i64;
// The errno check isn't needed, will return MAX/MIN on overflow.
if (StringToIntegerImpl(&i64, s, 0, false)) {
const int64_t max = (flatbuffers::numeric_limits<T>::max)();
const int64_t min = flatbuffers::numeric_limits<T>::lowest();
if (i64 > max) {
*val = static_cast<T>(max);
return false;
}
if (i64 < min) {
// For unsigned types return max to distinguish from
// "no conversion can be performed" when 0 is returned.
*val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min);
return false;
}
*val = static_cast<T>(i64);
return true;
}
*val = 0;
return false;
}
template<> inline bool StringToNumber<int64_t>(const char *str, int64_t *val) {
return StringToIntegerImpl(val, str);
}
template<>
inline bool StringToNumber<uint64_t>(const char *str, uint64_t *val) {
if (!StringToIntegerImpl(val, str)) return false;
// The strtoull accepts negative numbers:
// If the minus sign was part of the input sequence, the numeric value
// calculated from the sequence of digits is negated as if by unary minus
// in the result type, which applies unsigned integer wraparound rules.
// Fix this behaviour (except -0).
if (*val) {
auto s = str;
while (*s && !is_digit(*s)) s++;
s = (s > str) ? (s - 1) : s; // step back to one symbol
if (*s == '-') {
// For unsigned types return the max to distinguish from
// "no conversion can be performed".
*val = (flatbuffers::numeric_limits<uint64_t>::max)();
return false;
}
}
return true;
}
template<> inline bool StringToNumber(const char *s, float *val) {
return StringToFloatImpl(val, s);
}
template<> inline bool StringToNumber(const char *s, double *val) {
return StringToFloatImpl(val, s);
}
inline int64_t StringToInt(const char *s, int base = 10) {
int64_t val;
return StringToIntegerImpl(&val, s, base) ? val : 0;
}
inline uint64_t StringToUInt(const char *s, int base = 10) {
uint64_t val;
return StringToIntegerImpl(&val, s, base) ? val : 0;
}
typedef bool (*LoadFileFunction)(const char *filename, bool binary,
std::string *dest);
typedef bool (*FileExistsFunction)(const char *filename);
LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function);
FileExistsFunction SetFileExistsFunction(
FileExistsFunction file_exists_function);
// Check if file "name" exists.
bool FileExists(const char *name);
// Check if "name" exists and it is also a directory.
bool DirExists(const char *name);
// Load file "name" into "buf" returning true if successful
// false otherwise. If "binary" is false data is read
// using ifstream's text mode, otherwise data is read with
// no transcoding.
bool LoadFile(const char *name, bool binary, std::string *buf);
// Save data "buf" of length "len" bytes into a file
// "name" returning true if successful, false otherwise.
// If "binary" is false data is written using ifstream's
// text mode, otherwise data is written with no
// transcoding.
bool SaveFile(const char *name, const char *buf, size_t len, bool binary);
// Save data "buf" into file "name" returning true if
// successful, false otherwise. If "binary" is false
// data is written using ifstream's text mode, otherwise
// data is written with no transcoding.
inline bool SaveFile(const char *name, const std::string &buf, bool binary) {
return SaveFile(name, buf.c_str(), buf.size(), binary);
}
// Functionality for minimalistic portable path handling.
// The functions below behave correctly regardless of whether posix ('/') or
// Windows ('/' or '\\') separators are used.
// Any new separators inserted are always posix.
FLATBUFFERS_CONSTEXPR char kPathSeparator = '/';
// Returns the path with the extension, if any, removed.
std::string StripExtension(const std::string &filepath);
// Returns the extension, if any.
std::string GetExtension(const std::string &filepath);
// Return the last component of the path, after the last separator.
std::string StripPath(const std::string &filepath);
// Strip the last component of the path + separator.
std::string StripFileName(const std::string &filepath);
// Concatenates a path with a filename, regardless of wether the path
// ends in a separator or not.
std::string ConCatPathFileName(const std::string &path,
const std::string &filename);
// Replaces any '\\' separators with '/'
std::string PosixPath(const char *path);
// This function ensure a directory exists, by recursively
// creating dirs for any parts of the path that don't exist yet.
void EnsureDirExists(const std::string &filepath);
// Obtains the absolute path from any other path.
// Returns the input path if the absolute path couldn't be resolved.
std::string AbsolutePath(const std::string &filepath);
// To and from UTF-8 unicode conversion functions
// Convert a unicode code point into a UTF-8 representation by appending it
// to a string. Returns the number of bytes generated.
inline int ToUTF8(uint32_t ucc, std::string *out) {
FLATBUFFERS_ASSERT(!(ucc & 0x80000000)); // Top bit can't be set.
// 6 possible encodings: http://en.wikipedia.org/wiki/UTF-8
for (int i = 0; i < 6; i++) {
// Max bits this encoding can represent.
uint32_t max_bits = 6 + i * 5 + static_cast<int>(!i);
if (ucc < (1u << max_bits)) { // does it fit?
// Remaining bits not encoded in the first byte, store 6 bits each
uint32_t remain_bits = i * 6;
// Store first byte:
(*out) += static_cast<char>((0xFE << (max_bits - remain_bits)) |
(ucc >> remain_bits));
// Store remaining bytes:
for (int j = i - 1; j >= 0; j--) {
(*out) += static_cast<char>(((ucc >> (j * 6)) & 0x3F) | 0x80);
}
return i + 1; // Return the number of bytes added.
}
}
FLATBUFFERS_ASSERT(0); // Impossible to arrive here.
return -1;
}
// Converts whatever prefix of the incoming string corresponds to a valid
// UTF-8 sequence into a unicode code. The incoming pointer will have been
// advanced past all bytes parsed.
// returns -1 upon corrupt UTF-8 encoding (ignore the incoming pointer in
// this case).
inline int FromUTF8(const char **in) {
int len = 0;
// Count leading 1 bits.
for (int mask = 0x80; mask >= 0x04; mask >>= 1) {
if (**in & mask) {
len++;
} else {
break;
}
}
if ((static_cast<unsigned char>(**in) << len) & 0x80)
return -1; // Bit after leading 1's must be 0.
if (!len) return *(*in)++;
// UTF-8 encoded values with a length are between 2 and 4 bytes.
if (len < 2 || len > 4) { return -1; }
// Grab initial bits of the code.
int ucc = *(*in)++ & ((1 << (7 - len)) - 1);
for (int i = 0; i < len - 1; i++) {
if ((**in & 0xC0) != 0x80) return -1; // Upper bits must 1 0.
ucc <<= 6;
ucc |= *(*in)++ & 0x3F; // Grab 6 more bits of the code.
}
// UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for
// UTF-16 surrogate pairs).
if (ucc >= 0xD800 && ucc <= 0xDFFF) { return -1; }
// UTF-8 must represent code points in their shortest possible encoding.
switch (len) {
case 2:
// Two bytes of UTF-8 can represent code points from U+0080 to U+07FF.
if (ucc < 0x0080 || ucc > 0x07FF) { return -1; }
break;
case 3:
// Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF.
if (ucc < 0x0800 || ucc > 0xFFFF) { return -1; }
break;
case 4:
// Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF.
if (ucc < 0x10000 || ucc > 0x10FFFF) { return -1; }
break;
}
return ucc;
}
#ifndef FLATBUFFERS_PREFER_PRINTF
// Wraps a string to a maximum length, inserting new lines where necessary. Any
// existing whitespace will be collapsed down to a single space. A prefix or
// suffix can be provided, which will be inserted before or after a wrapped
// line, respectively.
inline std::string WordWrap(const std::string in, size_t max_length,
const std::string wrapped_line_prefix,
const std::string wrapped_line_suffix) {
std::istringstream in_stream(in);
std::string wrapped, line, word;
in_stream >> word;
line = word;
while (in_stream >> word) {
if ((line.length() + 1 + word.length() + wrapped_line_suffix.length()) <
max_length) {
line += " " + word;
} else {
wrapped += line + wrapped_line_suffix + "\n";
line = wrapped_line_prefix + word;
}
}
wrapped += line;
return wrapped;
}
#endif // !FLATBUFFERS_PREFER_PRINTF
inline bool EscapeString(const char *s, size_t length, std::string *_text,
bool allow_non_utf8, bool natural_utf8) {
std::string &text = *_text;
text += "\"";
for (uoffset_t i = 0; i < length; i++) {
char c = s[i];
switch (c) {
case '\n': text += "\\n"; break;
case '\t': text += "\\t"; break;
case '\r': text += "\\r"; break;
case '\b': text += "\\b"; break;
case '\f': text += "\\f"; break;
case '\"': text += "\\\""; break;
case '\\': text += "\\\\"; break;
default:
if (c >= ' ' && c <= '~') {
text += c;
} else {
// Not printable ASCII data. Let's see if it's valid UTF-8 first:
const char *utf8 = s + i;
int ucc = FromUTF8(&utf8);
if (ucc < 0) {
if (allow_non_utf8) {
text += "\\x";
text += IntToStringHex(static_cast<uint8_t>(c), 2);
} else {
// There are two cases here:
//
// 1) We reached here by parsing an IDL file. In that case,
// we previously checked for non-UTF-8, so we shouldn't reach
// here.
//
// 2) We reached here by someone calling GenerateText()
// on a previously-serialized flatbuffer. The data might have
// non-UTF-8 Strings, or might be corrupt.
//
// In both cases, we have to give up and inform the caller
// they have no JSON.
return false;
}
} else {
if (natural_utf8) {
// utf8 points to past all utf-8 bytes parsed
text.append(s + i, static_cast<size_t>(utf8 - s - i));
} else if (ucc <= 0xFFFF) {
// Parses as Unicode within JSON's \uXXXX range, so use that.
text += "\\u";
text += IntToStringHex(ucc, 4);
} else if (ucc <= 0x10FFFF) {
// Encode Unicode SMP values to a surrogate pair using two \u
// escapes.
uint32_t base = ucc - 0x10000;
auto high_surrogate = (base >> 10) + 0xD800;
auto low_surrogate = (base & 0x03FF) + 0xDC00;
text += "\\u";
text += IntToStringHex(high_surrogate, 4);
text += "\\u";
text += IntToStringHex(low_surrogate, 4);
}
// Skip past characters recognized.
i = static_cast<uoffset_t>(utf8 - s - 1);
}
}
break;
}
}
text += "\"";
return true;
}
inline std::string BufferToHexText(const void *buffer, size_t buffer_size,
size_t max_length,
const std::string &wrapped_line_prefix,
const std::string &wrapped_line_suffix) {
std::string text = wrapped_line_prefix;
size_t start_offset = 0;
const char *s = reinterpret_cast<const char *>(buffer);
for (size_t i = 0; s && i < buffer_size; i++) {
// Last iteration or do we have more?
bool have_more = i + 1 < buffer_size;
text += "0x";
text += IntToStringHex(static_cast<uint8_t>(s[i]), 2);
if (have_more) { text += ','; }
// If we have more to process and we reached max_length
if (have_more &&
text.size() + wrapped_line_suffix.size() >= start_offset + max_length) {
text += wrapped_line_suffix;
text += '\n';
start_offset = text.size();
text += wrapped_line_prefix;
}
}
text += wrapped_line_suffix;
return text;
}
// Remove paired quotes in a string: "text"|'text' -> text.
std::string RemoveStringQuotes(const std::string &s);
// Change th global C-locale to locale with name <locale_name>.
// Returns an actual locale name in <_value>, useful if locale_name is "" or
// null.
bool SetGlobalTestLocale(const char *locale_name,
std::string *_value = nullptr);
// Read (or test) a value of environment variable.
bool ReadEnvironmentVariable(const char *var_name,
std::string *_value = nullptr);
// MSVC specific: Send all assert reports to STDOUT to prevent CI hangs.
void SetupDefaultCRTReportMode();
} // namespace flatbuffers
#endif // FLATBUFFERS_UTIL_H_

BIN
waterbox/nyma/flatc.exe Normal file

Binary file not shown.

View File

@ -0,0 +1,3 @@
#!/bin/sh
./flatc --cpp --gen-object-api NymaTypes.fbs
./flatc --csharp --gen-object-api -o ../../src/Bizhawk.Emulation.Cores/Waterbox NymaTypes.fbs