Add Get Bytes Method Generator for C#
I updated idl_gen_general.cpp to add support for generating a Get Bytes method for a vector to the generated C# source code. Given a byte vector field named Foo, a method named GetFooBytes() will be generated in the C# source code that will return an ArraySegment<byte> value referencing the vector data in the underlying ByteBuffer. I added a method to Table.cs named __vector_as_arraysegment that is used by the code generated by the change to the C# generator. __vector_as_arraysegment will take the offset of the vector and will return the ArraySegment<byte> value corresponding to the bytes that store the vector data. I updated FlatBuffersExampleTests.cs to add tests to validate my implementation of Table.__vector_as_arraysegment. I added tests to demonstrate that the bytes for the monster's name can be extracted from the underlying byte array. I also added tests to show that Table.__vector_as_arraysegment returns a null value if the vector is not present in the FlatBuffer. I used the updated flatc.exe program to regenerate the C# source files for the MyGame example. The new Monster class includes the GetXXXBytes methods to return the byte arrays containing data for vectors.
This commit is contained in:
parent
fe2f8d32aa
commit
e083e466b8
|
@ -67,6 +67,21 @@ namespace FlatBuffers
|
||||||
return offset + bb.GetInt(offset) + sizeof(int); // data starts after the length
|
return offset + bb.GetInt(offset) + sizeof(int); // data starts after the length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the data of a vector whoses offset is stored at "offset" in this object as an
|
||||||
|
// ArraySegment<byte>. If the vector is not present in the ByteBuffer,
|
||||||
|
// then a null value will be returned.
|
||||||
|
protected 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 new ArraySegment<byte>(this.bb.Data, pos, len);
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize any Table-derived type to point to the union at the given offset.
|
// Initialize any Table-derived type to point to the union at the given offset.
|
||||||
protected TTable __union<TTable>(TTable t, int offset) where TTable : Table
|
protected TTable __union<TTable>(TTable t, int offset) where TTable : Table
|
||||||
{
|
{
|
||||||
|
|
|
@ -145,7 +145,7 @@ LanguageParameters language_parameters[] = {
|
||||||
"",
|
"",
|
||||||
"Position",
|
"Position",
|
||||||
"Offset",
|
"Offset",
|
||||||
"using FlatBuffers;\n\n",
|
"using System;\nusing FlatBuffers;\n\n",
|
||||||
{
|
{
|
||||||
nullptr,
|
nullptr,
|
||||||
"///",
|
"///",
|
||||||
|
@ -823,17 +823,29 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
|
||||||
code += "}\n";
|
code += "}\n";
|
||||||
}
|
}
|
||||||
// Generate a ByteBuffer accessor for strings & vectors of scalars.
|
// Generate a ByteBuffer accessor for strings & vectors of scalars.
|
||||||
if (((field.value.type.base_type == BASE_TYPE_VECTOR &&
|
if ((field.value.type.base_type == BASE_TYPE_VECTOR &&
|
||||||
IsScalar(field.value.type.VectorType().base_type)) ||
|
IsScalar(field.value.type.VectorType().base_type)) ||
|
||||||
field.value.type.base_type == BASE_TYPE_STRING) &&
|
field.value.type.base_type == BASE_TYPE_STRING) {
|
||||||
lang.language == IDLOptions::kJava) {
|
switch (lang.language) {
|
||||||
code += " public ByteBuffer ";
|
case IDLOptions::kJava:
|
||||||
code += MakeCamel(field.name, lang.first_camel_upper);
|
code += " public ByteBuffer ";
|
||||||
code += "AsByteBuffer() { return __vector_as_bytebuffer(";
|
code += MakeCamel(field.name, lang.first_camel_upper);
|
||||||
code += NumToString(field.value.offset) + ", ";
|
code += "AsByteBuffer() { return __vector_as_bytebuffer(";
|
||||||
code += NumToString(field.value.type.base_type == BASE_TYPE_STRING ? 1 :
|
code += NumToString(field.value.offset) + ", ";
|
||||||
InlineSize(field.value.type.VectorType()));
|
code += NumToString(field.value.type.base_type == BASE_TYPE_STRING ? 1 :
|
||||||
code += "); }\n";
|
InlineSize(field.value.type.VectorType()));
|
||||||
|
code += "); }\n";
|
||||||
|
break;
|
||||||
|
case IDLOptions::kCSharp:
|
||||||
|
code += " public ArraySegment<byte>? Get";
|
||||||
|
code += MakeCamel(field.name, lang.first_camel_upper);
|
||||||
|
code += "Bytes() { return __vector_as_arraysegment(";
|
||||||
|
code += NumToString(field.value.offset);
|
||||||
|
code += "); }\n";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate mutators for scalar fields or vectors of scalars
|
// generate mutators for scalar fields or vectors of scalars
|
||||||
|
|
|
@ -107,6 +107,14 @@ namespace FlatBuffers.Test
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void IsFalse(bool value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
throw new AssertFailedException(false, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void Throws<T>(Action action) where T : Exception
|
public static void Throws<T>(Action action) where T : Exception
|
||||||
{
|
{
|
||||||
var caught = false;
|
var caught = false;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
using MyGame.Example;
|
using MyGame.Example;
|
||||||
|
|
||||||
namespace FlatBuffers.Test
|
namespace FlatBuffers.Test
|
||||||
|
@ -184,6 +185,18 @@ namespace FlatBuffers.Test
|
||||||
Assert.AreEqual("test2", monster.GetTestarrayofstring(1));
|
Assert.AreEqual("test2", monster.GetTestarrayofstring(1));
|
||||||
|
|
||||||
Assert.AreEqual(false, monster.Testbool);
|
Assert.AreEqual(false, monster.Testbool);
|
||||||
|
|
||||||
|
var nameBytes = monster.GetNameBytes().Value;
|
||||||
|
Assert.AreEqual("MyMonster", Encoding.UTF8.GetString(nameBytes.Array, nameBytes.Offset, nameBytes.Count));
|
||||||
|
|
||||||
|
if (0 == monster.TestarrayofboolsLength)
|
||||||
|
{
|
||||||
|
Assert.IsFalse(monster.GetTestarrayofboolsBytes().HasValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.IsTrue(monster.GetTestarrayofboolsBytes().HasValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[FlatBuffersTestMethod]
|
[FlatBuffersTestMethod]
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace MyGame.Example
|
namespace MyGame.Example
|
||||||
{
|
{
|
||||||
|
|
||||||
|
using System;
|
||||||
using FlatBuffers;
|
using FlatBuffers;
|
||||||
|
|
||||||
/// an example documentation comment: monster object
|
/// an example documentation comment: monster object
|
||||||
|
@ -19,8 +20,10 @@ public sealed class Monster : Table {
|
||||||
public short Hp { get { int o = __offset(8); return o != 0 ? bb.GetShort(o + bb_pos) : (short)100; } }
|
public short Hp { get { int o = __offset(8); return o != 0 ? bb.GetShort(o + bb_pos) : (short)100; } }
|
||||||
public bool MutateHp(short hp) { int o = __offset(8); if (o != 0) { bb.PutShort(o + bb_pos, hp); return true; } else { return false; } }
|
public bool MutateHp(short hp) { int o = __offset(8); if (o != 0) { bb.PutShort(o + bb_pos, hp); return true; } else { return false; } }
|
||||||
public string Name { get { int o = __offset(10); return o != 0 ? __string(o + bb_pos) : null; } }
|
public string Name { get { int o = __offset(10); return o != 0 ? __string(o + bb_pos) : null; } }
|
||||||
|
public ArraySegment<byte>? GetNameBytes() { return __vector_as_arraysegment(10); }
|
||||||
public byte GetInventory(int j) { int o = __offset(14); return o != 0 ? bb.Get(__vector(o) + j * 1) : (byte)0; }
|
public byte GetInventory(int j) { int o = __offset(14); return o != 0 ? bb.Get(__vector(o) + j * 1) : (byte)0; }
|
||||||
public int InventoryLength { get { int o = __offset(14); return o != 0 ? __vector_len(o) : 0; } }
|
public int InventoryLength { get { int o = __offset(14); return o != 0 ? __vector_len(o) : 0; } }
|
||||||
|
public ArraySegment<byte>? GetInventoryBytes() { return __vector_as_arraysegment(14); }
|
||||||
public bool MutateInventory(int j, byte inventory) { int o = __offset(14); if (o != 0) { bb.Put(__vector(o) + j * 1, inventory); return true; } else { return false; } }
|
public bool MutateInventory(int j, byte inventory) { int o = __offset(14); if (o != 0) { bb.Put(__vector(o) + j * 1, inventory); return true; } else { return false; } }
|
||||||
public Color Color { get { int o = __offset(16); return o != 0 ? (Color)bb.GetSbyte(o + bb_pos) : Color.Blue; } }
|
public Color Color { get { int o = __offset(16); return o != 0 ? (Color)bb.GetSbyte(o + bb_pos) : Color.Blue; } }
|
||||||
public bool MutateColor(Color color) { int o = __offset(16); if (o != 0) { bb.PutSbyte(o + bb_pos, (sbyte)color); return true; } else { return false; } }
|
public bool MutateColor(Color color) { int o = __offset(16); if (o != 0) { bb.PutSbyte(o + bb_pos, (sbyte)color); return true; } else { return false; } }
|
||||||
|
@ -41,6 +44,7 @@ public sealed class Monster : Table {
|
||||||
public Monster GetEnemy(Monster obj) { int o = __offset(28); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
|
public Monster GetEnemy(Monster obj) { int o = __offset(28); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
|
||||||
public byte GetTestnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.Get(__vector(o) + j * 1) : (byte)0; }
|
public byte GetTestnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.Get(__vector(o) + j * 1) : (byte)0; }
|
||||||
public int TestnestedflatbufferLength { get { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; } }
|
public int TestnestedflatbufferLength { get { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; } }
|
||||||
|
public ArraySegment<byte>? GetTestnestedflatbufferBytes() { return __vector_as_arraysegment(30); }
|
||||||
public bool MutateTestnestedflatbuffer(int j, byte testnestedflatbuffer) { int o = __offset(30); if (o != 0) { bb.Put(__vector(o) + j * 1, testnestedflatbuffer); return true; } else { return false; } }
|
public bool MutateTestnestedflatbuffer(int j, byte testnestedflatbuffer) { int o = __offset(30); if (o != 0) { bb.Put(__vector(o) + j * 1, testnestedflatbuffer); return true; } else { return false; } }
|
||||||
public Stat Testempty { get { return GetTestempty(new Stat()); } }
|
public Stat Testempty { get { return GetTestempty(new Stat()); } }
|
||||||
public Stat GetTestempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
|
public Stat GetTestempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
|
||||||
|
@ -64,6 +68,7 @@ public sealed class Monster : Table {
|
||||||
public bool MutateTesthashu64Fnv1a(ulong testhashu64_fnv1a) { int o = __offset(50); if (o != 0) { bb.PutUlong(o + bb_pos, testhashu64_fnv1a); return true; } else { return false; } }
|
public bool MutateTesthashu64Fnv1a(ulong testhashu64_fnv1a) { int o = __offset(50); if (o != 0) { bb.PutUlong(o + bb_pos, testhashu64_fnv1a); return true; } else { return false; } }
|
||||||
public bool GetTestarrayofbools(int j) { int o = __offset(52); return o != 0 ? 0!=bb.Get(__vector(o) + j * 1) : false; }
|
public bool GetTestarrayofbools(int j) { int o = __offset(52); return o != 0 ? 0!=bb.Get(__vector(o) + j * 1) : false; }
|
||||||
public int TestarrayofboolsLength { get { int o = __offset(52); return o != 0 ? __vector_len(o) : 0; } }
|
public int TestarrayofboolsLength { get { int o = __offset(52); return o != 0 ? __vector_len(o) : 0; } }
|
||||||
|
public ArraySegment<byte>? GetTestarrayofboolsBytes() { return __vector_as_arraysegment(52); }
|
||||||
public bool MutateTestarrayofbools(int j, bool testarrayofbools) { int o = __offset(52); if (o != 0) { bb.Put(__vector(o) + j * 1, (byte)(testarrayofbools ? 1 : 0)); return true; } else { return false; } }
|
public bool MutateTestarrayofbools(int j, bool testarrayofbools) { int o = __offset(52); if (o != 0) { bb.Put(__vector(o) + j * 1, (byte)(testarrayofbools ? 1 : 0)); return true; } else { return false; } }
|
||||||
|
|
||||||
public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(25); }
|
public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(25); }
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace MyGame.Example
|
namespace MyGame.Example
|
||||||
{
|
{
|
||||||
|
|
||||||
|
using System;
|
||||||
using FlatBuffers;
|
using FlatBuffers;
|
||||||
|
|
||||||
public sealed class Stat : Table {
|
public sealed class Stat : Table {
|
||||||
|
@ -11,6 +12,7 @@ public sealed class Stat : Table {
|
||||||
public Stat __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
|
public Stat __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
|
||||||
|
|
||||||
public string Id { get { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } }
|
public string Id { get { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } }
|
||||||
|
public ArraySegment<byte>? GetIdBytes() { return __vector_as_arraysegment(4); }
|
||||||
public long Val { get { int o = __offset(6); return o != 0 ? bb.GetLong(o + bb_pos) : (long)0; } }
|
public long Val { get { int o = __offset(6); return o != 0 ? bb.GetLong(o + bb_pos) : (long)0; } }
|
||||||
public bool MutateVal(long val) { int o = __offset(6); if (o != 0) { bb.PutLong(o + bb_pos, val); return true; } else { return false; } }
|
public bool MutateVal(long val) { int o = __offset(6); if (o != 0) { bb.PutLong(o + bb_pos, val); return true; } else { return false; } }
|
||||||
public ushort Count { get { int o = __offset(8); return o != 0 ? bb.GetUshort(o + bb_pos) : (ushort)0; } }
|
public ushort Count { get { int o = __offset(8); return o != 0 ? bb.GetUshort(o + bb_pos) : (ushort)0; } }
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace MyGame.Example
|
namespace MyGame.Example
|
||||||
{
|
{
|
||||||
|
|
||||||
|
using System;
|
||||||
using FlatBuffers;
|
using FlatBuffers;
|
||||||
|
|
||||||
public sealed class Test : Struct {
|
public sealed class Test : Struct {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace MyGame.Example
|
namespace MyGame.Example
|
||||||
{
|
{
|
||||||
|
|
||||||
|
using System;
|
||||||
using FlatBuffers;
|
using FlatBuffers;
|
||||||
|
|
||||||
public sealed class TestSimpleTableWithEnum : Table {
|
public sealed class TestSimpleTableWithEnum : Table {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace MyGame.Example
|
namespace MyGame.Example
|
||||||
{
|
{
|
||||||
|
|
||||||
|
using System;
|
||||||
using FlatBuffers;
|
using FlatBuffers;
|
||||||
|
|
||||||
public sealed class Vec3 : Struct {
|
public sealed class Vec3 : Struct {
|
||||||
|
|
Loading…
Reference in New Issue