Unsigned types in Java now return bigger size signed types.

(Java doesn't support unsigned types).

ubyte/ushort return as int
uint returns as long
(all with correct masking)

ulong still returns as long, as before.

Tested: on Linux & Windows.
Bug 17521464

Change-Id: Id6bc8f38fc8c1a2f4e6733c6980dc6b6e322b452
This commit is contained in:
Wouter van Oortmerssen 2015-03-18 17:52:39 -07:00
parent f7818d83d7
commit ca5c9e7496
7 changed files with 122 additions and 26 deletions

View File

@ -167,6 +167,51 @@ static std::string GenTypeGet(const LanguageParameters &lang,
: GenTypePointer(lang, type);
}
// Find the destination type the user wants to receive the value in (e.g.
// one size higher signed types for unsigned serialized values in Java).
static Type DestinationType(const LanguageParameters &lang, const Type &type,
bool vectorelem) {
if (lang.language != GeneratorOptions::kJava) return type;
switch (type.base_type) {
case BASE_TYPE_UCHAR: return Type(BASE_TYPE_INT);
case BASE_TYPE_USHORT: return Type(BASE_TYPE_INT);
case BASE_TYPE_UINT: return Type(BASE_TYPE_LONG);
case BASE_TYPE_VECTOR:
if (vectorelem)
return DestinationType(lang, type.VectorType(), vectorelem);
// else fall thru:
default: return type;
}
}
// Mask to turn serialized value into destination type value.
static std::string DestinationMask(const LanguageParameters &lang,
const Type &type, bool vectorelem) {
if (lang.language != GeneratorOptions::kJava) return "";
switch (type.base_type) {
case BASE_TYPE_UCHAR: return " & 0xFF";
case BASE_TYPE_USHORT: return " & 0xFFFF";
case BASE_TYPE_UINT: return " & 0xFFFFFFFFL";
case BASE_TYPE_VECTOR:
if (vectorelem)
return DestinationMask(lang, type.VectorType(), vectorelem);
// else fall thru:
default: return "";
}
}
// Cast necessary to correctly read serialized unsigned values.
static std::string DestinationCast(const LanguageParameters &lang,
const Type &type) {
if (lang.language == GeneratorOptions::kJava &&
(type.base_type == BASE_TYPE_UINT ||
(type.base_type == BASE_TYPE_VECTOR &&
type.element == BASE_TYPE_UINT))) return "(long)";
return "";
}
static std::string GenDefaultValue(const Value &value) {
return value.type.base_type == BASE_TYPE_BOOL
? (value.constant == "0" ? "false" : "true")
@ -276,7 +321,11 @@ static void GenStructArgs(const LanguageParameters &lang,
GenStructArgs(lang, *field.value.type.struct_def, code_ptr,
(field.value.type.struct_def->name + "_").c_str());
} else {
code += ", " + GenTypeBasic(lang, field.value.type) + " " + nameprefix;
code += ", ";
code += GenTypeBasic(lang,
DestinationType(lang, field.value.type, false));
code += " ";
code += nameprefix;
code += MakeCamel(field.name, lang.first_camel_upper);
}
}
@ -304,8 +353,16 @@ static void GenStructBody(const LanguageParameters &lang,
(field.value.type.struct_def->name + "_").c_str());
} else {
code += " builder." + FunctionStart(lang, 'P') + "ut";
code += GenMethod(lang, field.value.type) + "(" += nameprefix;
code += MakeCamel(field.name, lang.first_camel_upper) + ");\n";
code += GenMethod(lang, field.value.type) + "(";
auto argname = nameprefix + MakeCamel(field.name, lang.first_camel_upper);
std::string type_mask = DestinationMask(lang, field.value.type, false);
if (type_mask.length()) {
code += "(" + GenTypeBasic(lang, field.value.type) + ")";
code += "(" + argname + type_mask + ")";
} else {
code += argname;
}
code += ");\n";
}
}
}
@ -363,7 +420,11 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
if (field.deprecated) continue;
GenComment(field.doc_comment, code_ptr, " ");
std::string type_name = GenTypeGet(lang, field.value.type);
std::string method_start = " public " + type_name + " " +
std::string type_name_dest =
GenTypeGet(lang, DestinationType(lang, field.value.type, true));
std::string dest_mask = DestinationMask(lang, field.value.type, true);
std::string dest_cast = DestinationCast(lang, field.value.type);
std::string method_start = " public " + type_name_dest + " " +
MakeCamel(field.name, lang.first_camel_upper);
// Generate the accessors that don't do object reuse.
if (field.value.type.base_type == BASE_TYPE_STRUCT) {
@ -381,7 +442,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
code += "(new ";
code += type_name + "(), j); }\n";
}
std::string getter = GenGetter(lang, field.value.type);
std::string getter = dest_cast + GenGetter(lang, field.value.type);
code += method_start + "(";
// Most field accessors need to retrieve and test the field offset first,
// this is the prefix code for that:
@ -390,14 +451,15 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
"); return o != 0 ? ";
std::string default_cast = "";
if (lang.language == GeneratorOptions::kCSharp)
default_cast = "(" + type_name + ")";
default_cast = "(" + type_name_dest + ")";
if (IsScalar(field.value.type.base_type)) {
if (struct_def.fixed) {
code += ") { return " + getter;
code += "(bb_pos + " + NumToString(field.value.offset) + ")";
code += dest_mask;
} else {
code += offset_prefix + getter;
code += "(o + bb_pos) : " + default_cast;
code += "(o + bb_pos)" + dest_mask + " : " + default_cast;
code += GenDefaultValue(field.value);
}
} else {
@ -436,7 +498,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
} else {
code += index;
}
code += ") : ";
code += ")" + dest_mask + " : ";
code += IsScalar(field.value.type.element)
? default_cast + "0"
: "null";
@ -506,7 +568,10 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
code += ",\n " + GenTypeBasic(lang, field.value.type) + " ";
code += ",\n ";
code += GenTypeBasic(lang,
DestinationType(lang, field.value.type, false));
code += " ";
code += field.name;
// Java doesn't have defaults, which means this method must always
// supply all arguments, and thus won't compile when fields are added.
@ -553,13 +618,21 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
code += " public static void " + FunctionStart(lang, 'A') + "dd";
code += MakeCamel(field.name);
code += "(FlatBufferBuilder builder, ";
code += GenTypeBasic(lang, field.value.type);
code += GenTypeBasic(lang,
DestinationType(lang, field.value.type, false));
auto argname = MakeCamel(field.name, false);
if (!IsScalar(field.value.type.base_type)) argname += "Offset";
code += " " + argname + ") { builder." + FunctionStart(lang, 'A') + "dd";
code += GenMethod(lang, field.value.type) + "(";
code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
code += argname + ", " + GenDefaultValue(field.value);
std::string type_mask = DestinationMask(lang, field.value.type, false);
if (type_mask.length()) {
code += "(" + GenTypeBasic(lang, field.value.type) + ")";
code += "(" + argname + type_mask + ")";
} else {
code += argname;
}
code += ", " + GenDefaultValue(field.value);
code += "); }\n";
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
auto vector_type = field.value.type.VectorType();

View File

@ -19,7 +19,7 @@ public class Monster extends Table {
public short hp() { int o = __offset(8); return o != 0 ? bb.getShort(o + bb_pos) : 100; }
public String name() { int o = __offset(10); return o != 0 ? __string(o + bb_pos) : null; }
public ByteBuffer nameAsByteBuffer() { return __vector_as_bytebuffer(10, 1); }
public byte inventory(int j) { int o = __offset(14); return o != 0 ? bb.get(__vector(o) + j * 1) : 0; }
public int inventory(int j) { int o = __offset(14); return o != 0 ? bb.get(__vector(o) + j * 1) & 0xFF : 0; }
public int inventoryLength() { int o = __offset(14); return o != 0 ? __vector_len(o) : 0; }
public ByteBuffer inventoryAsByteBuffer() { return __vector_as_bytebuffer(14, 1); }
public byte color() { int o = __offset(16); return o != 0 ? bb.get(o + bb_pos) : 8; }
@ -37,18 +37,18 @@ public class Monster extends Table {
public int testarrayoftablesLength() { int o = __offset(26); return o != 0 ? __vector_len(o) : 0; }
public Monster enemy() { return enemy(new Monster()); }
public Monster enemy(Monster obj) { int o = __offset(28); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
public byte testnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.get(__vector(o) + j * 1) : 0; }
public int testnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.get(__vector(o) + j * 1) & 0xFF : 0; }
public int testnestedflatbufferLength() { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; }
public ByteBuffer testnestedflatbufferAsByteBuffer() { return __vector_as_bytebuffer(30, 1); }
public Stat testempty() { return testempty(new Stat()); }
public Stat testempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
public boolean testbool() { int o = __offset(34); return o != 0 ? 0!=bb.get(o + bb_pos) : false; }
public int testhashs32Fnv1() { int o = __offset(36); return o != 0 ? bb.getInt(o + bb_pos) : 0; }
public int testhashu32Fnv1() { int o = __offset(38); return o != 0 ? bb.getInt(o + bb_pos) : 0; }
public long testhashu32Fnv1() { int o = __offset(38); return o != 0 ? (long)bb.getInt(o + bb_pos) & 0xFFFFFFFFL : 0; }
public long testhashs64Fnv1() { int o = __offset(40); return o != 0 ? bb.getLong(o + bb_pos) : 0; }
public long testhashu64Fnv1() { int o = __offset(42); return o != 0 ? bb.getLong(o + bb_pos) : 0; }
public int testhashs32Fnv1a() { int o = __offset(44); return o != 0 ? bb.getInt(o + bb_pos) : 0; }
public int testhashu32Fnv1a() { int o = __offset(46); return o != 0 ? bb.getInt(o + bb_pos) : 0; }
public long testhashu32Fnv1a() { int o = __offset(46); return o != 0 ? (long)bb.getInt(o + bb_pos) & 0xFFFFFFFFL : 0; }
public long testhashs64Fnv1a() { int o = __offset(48); return o != 0 ? bb.getLong(o + bb_pos) : 0; }
public long testhashu64Fnv1a() { int o = __offset(50); return o != 0 ? bb.getLong(o + bb_pos) : 0; }
@ -78,11 +78,11 @@ public class Monster extends Table {
public static void addTestempty(FlatBufferBuilder builder, int testemptyOffset) { builder.addOffset(14, testemptyOffset, 0); }
public static void addTestbool(FlatBufferBuilder builder, boolean testbool) { builder.addBoolean(15, testbool, false); }
public static void addTesthashs32Fnv1(FlatBufferBuilder builder, int testhashs32Fnv1) { builder.addInt(16, testhashs32Fnv1, 0); }
public static void addTesthashu32Fnv1(FlatBufferBuilder builder, int testhashu32Fnv1) { builder.addInt(17, testhashu32Fnv1, 0); }
public static void addTesthashu32Fnv1(FlatBufferBuilder builder, long testhashu32Fnv1) { builder.addInt(17, (int)(testhashu32Fnv1 & 0xFFFFFFFFL), 0); }
public static void addTesthashs64Fnv1(FlatBufferBuilder builder, long testhashs64Fnv1) { builder.addLong(18, testhashs64Fnv1, 0); }
public static void addTesthashu64Fnv1(FlatBufferBuilder builder, long testhashu64Fnv1) { builder.addLong(19, testhashu64Fnv1, 0); }
public static void addTesthashs32Fnv1a(FlatBufferBuilder builder, int testhashs32Fnv1a) { builder.addInt(20, testhashs32Fnv1a, 0); }
public static void addTesthashu32Fnv1a(FlatBufferBuilder builder, int testhashu32Fnv1a) { builder.addInt(21, testhashu32Fnv1a, 0); }
public static void addTesthashu32Fnv1a(FlatBufferBuilder builder, long testhashu32Fnv1a) { builder.addInt(21, (int)(testhashu32Fnv1a & 0xFFFFFFFFL), 0); }
public static void addTesthashs64Fnv1a(FlatBufferBuilder builder, long testhashs64Fnv1a) { builder.addLong(22, testhashs64Fnv1a, 0); }
public static void addTesthashu64Fnv1a(FlatBufferBuilder builder, long testhashu64Fnv1a) { builder.addLong(23, testhashu64Fnv1a, 0); }
public static int endMonster(FlatBufferBuilder builder) {

View File

@ -12,19 +12,23 @@ public class Stat : Table {
public string Id() { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; }
public long Val() { int o = __offset(6); return o != 0 ? bb.GetLong(o + bb_pos) : (long)0; }
public ushort Count() { int o = __offset(8); return o != 0 ? bb.GetUshort(o + bb_pos) : (ushort)0; }
public static int CreateStat(FlatBufferBuilder builder,
int id = 0,
long val = 0) {
builder.StartObject(2);
long val = 0,
ushort count = 0) {
builder.StartObject(3);
Stat.AddVal(builder, val);
Stat.AddId(builder, id);
Stat.AddCount(builder, count);
return Stat.EndStat(builder);
}
public static void StartStat(FlatBufferBuilder builder) { builder.StartObject(2); }
public static void StartStat(FlatBufferBuilder builder) { builder.StartObject(3); }
public static void AddId(FlatBufferBuilder builder, int idOffset) { builder.AddOffset(0, idOffset, 0); }
public static void AddVal(FlatBufferBuilder builder, long val) { builder.AddLong(1, val, 0); }
public static void AddCount(FlatBufferBuilder builder, ushort count) { builder.AddUshort(2, count, 0); }
public static int EndStat(FlatBufferBuilder builder) {
int o = builder.EndObject();
return o;

View File

@ -30,7 +30,16 @@ func (rcv *Stat) Val() int64 {
return 0
}
func StatStart(builder *flatbuffers.Builder) { builder.StartObject(2) }
func (rcv *Stat) Count() uint16 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.GetUint16(o + rcv._tab.Pos)
}
return 0
}
func StatStart(builder *flatbuffers.Builder) { builder.StartObject(3) }
func StatAddId(builder *flatbuffers.Builder, id flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(id), 0) }
func StatAddVal(builder *flatbuffers.Builder, val int64) { builder.PrependInt64Slot(1, val, 0) }
func StatAddCount(builder *flatbuffers.Builder, count uint16) { builder.PrependUint16Slot(2, count, 0) }
func StatEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { return builder.EndObject() }

View File

@ -15,19 +15,23 @@ public class Stat extends Table {
public String id() { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; }
public ByteBuffer idAsByteBuffer() { return __vector_as_bytebuffer(4, 1); }
public long val() { int o = __offset(6); return o != 0 ? bb.getLong(o + bb_pos) : 0; }
public int count() { int o = __offset(8); return o != 0 ? bb.getShort(o + bb_pos) & 0xFFFF : 0; }
public static int createStat(FlatBufferBuilder builder,
int id,
long val) {
builder.startObject(2);
long val,
int count) {
builder.startObject(3);
Stat.addVal(builder, val);
Stat.addId(builder, id);
Stat.addCount(builder, count);
return Stat.endStat(builder);
}
public static void startStat(FlatBufferBuilder builder) { builder.startObject(2); }
public static void startStat(FlatBufferBuilder builder) { builder.startObject(3); }
public static void addId(FlatBufferBuilder builder, int idOffset) { builder.addOffset(0, idOffset, 0); }
public static void addVal(FlatBufferBuilder builder, long val) { builder.addLong(1, val, 0); }
public static void addCount(FlatBufferBuilder builder, int count) { builder.addShort(2, (short)(count & 0xFFFF), 0); }
public static int endStat(FlatBufferBuilder builder) {
int o = builder.endObject();
return o;

View File

@ -24,6 +24,7 @@ struct Vec3 (force_align: 16) {
table Stat {
id:string;
val:long;
count:ushort;
}
table Monster {

View File

@ -89,11 +89,13 @@ STRUCT_END(Vec3, 32);
struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::String *id() const { return GetPointer<const flatbuffers::String *>(4); }
int64_t val() const { return GetField<int64_t>(6, 0); }
uint16_t count() const { return GetField<uint16_t>(8, 0); }
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* id */) &&
verifier.Verify(id()) &&
VerifyField<int64_t>(verifier, 6 /* val */) &&
VerifyField<uint16_t>(verifier, 8 /* count */) &&
verifier.EndTable();
}
};
@ -103,20 +105,23 @@ struct StatBuilder {
flatbuffers::uoffset_t start_;
void add_id(flatbuffers::Offset<flatbuffers::String> id) { fbb_.AddOffset(4, id); }
void add_val(int64_t val) { fbb_.AddElement<int64_t>(6, val, 0); }
void add_count(uint16_t count) { fbb_.AddElement<uint16_t>(8, count, 0); }
StatBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
StatBuilder &operator=(const StatBuilder &);
flatbuffers::Offset<Stat> Finish() {
auto o = flatbuffers::Offset<Stat>(fbb_.EndTable(start_, 2));
auto o = flatbuffers::Offset<Stat>(fbb_.EndTable(start_, 3));
return o;
}
};
inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> id = 0,
int64_t val = 0) {
int64_t val = 0,
uint16_t count = 0) {
StatBuilder builder_(_fbb);
builder_.add_val(val);
builder_.add_id(id);
builder_.add_count(count);
return builder_.Finish();
}