Skip to content

Commit

Permalink
Fix issues with uint64 enums
Browse files Browse the repository at this point in the history
- hide the implementation of enums from code generators
- fix uint64 the issue in the cpp-generator
- fix #5108
- fix issues in cpp code-generator
- new tests
- add monster_enum.fbs for checking of the cpp code generator
  • Loading branch information
vglavnyy committed Apr 9, 2019
1 parent 23bb574 commit 42df4d4
Show file tree
Hide file tree
Showing 27 changed files with 2,320 additions and 256 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ endfunction()

if(FLATBUFFERS_BUILD_TESTS)
compile_flatbuffers_schema_to_cpp(tests/monster_test.fbs)
compile_flatbuffers_schema_to_cpp(tests/monster_enum.fbs)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/tests)
add_executable(flattests ${FlatBuffers_Tests_SRCS})
set_property(TARGET flattests
Expand Down
5 changes: 5 additions & 0 deletions include/flatbuffers/code_generators.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ class CodeWriter {
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
Expand Down
77 changes: 69 additions & 8 deletions include/flatbuffers/idl.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,13 @@ inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE &&
t <= BASE_TYPE_UCHAR; }

inline bool IsUnsigned(BaseType t) {
return (t == BASE_TYPE_UTYPE) || (t == BASE_TYPE_UCHAR) ||
(t == BASE_TYPE_USHORT) || (t == BASE_TYPE_UINT) ||
(t == BASE_TYPE_ULONG);
}

// clang-format on

extern const char *const kTypeNames[];
Expand Down Expand Up @@ -327,30 +334,44 @@ inline size_t InlineAlignment(const Type &type) {
return IsStruct(type) ? type.struct_def->minalign : SizeOf(type.base_type);
}

struct EnumVal {
EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
EnumVal() : value(0) {}
struct EnumDef;
struct EnumValBuilder;

struct EnumVal {
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;

bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
bool IsZero() const { return 0 == value; }
bool IsNonZero() const { return !IsZero(); }

uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
int64_t GetAsInt64() const { return value; }
bool IsZero() const { return 0 == value; }
bool IsNonZero() const { return !IsZero(); }

std::string name;
std::vector<std::string> doc_comment;
int64_t value;
Type union_type;

private:
friend EnumDef;
friend EnumValBuilder;
friend bool operator==(const EnumVal &lhs, const EnumVal &rhs);

EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
EnumVal() : value(0) {}

int64_t value;
};

struct EnumDef : public Definition {
EnumDef() : is_union(false), uses_multiple_type_instances(false) {}

EnumVal *ReverseLookup(int64_t enum_idx, bool skip_union_default = true) {
for (auto it = Vals().begin() +
for (auto it = Vals().begin() +
static_cast<int>(is_union && skip_union_default);
it != Vals().end(); ++it) {
if ((*it)->value == enum_idx) { return *it; }
if ((*it)->GetAsInt64() == enum_idx) { return *it; }
}
return nullptr;
}
Expand All @@ -359,20 +380,60 @@ struct EnumDef : public Definition {

bool Deserialize(Parser &parser, const reflection::Enum *values);

template<typename T>
void ChangeEnumValue(EnumVal* ev, T new_val);
void SortByValue();
void RemoveDuplicates();

std::string AllFlags() const;
const EnumVal *MinValue() const;
const EnumVal *MaxValue() const;
// Returns the number of integer steps from v1 to v2.
uint64_t Distance(const EnumVal *v1, const EnumVal *v2) const;
// Returns the number of integer steps from Min to Max.
uint64_t Distance() const { return Distance(MinValue(), MaxValue()); }

// In fact, this is uint64/int64 safe ReverseLookup without skip_union_default.
EnumVal *FindByValue(const std::string &constant) const;

bool IsUInt64() const {
return (BASE_TYPE_ULONG == underlying_type.base_type);
}

std::string ToString(const EnumVal &ev) const {
return IsUInt64() ? NumToString(ev.GetAsUInt64())
: NumToString(ev.GetAsInt64());
}

size_t size() const { return vals.vec.size(); }

const std::vector<EnumVal *> &Vals() const {
FLATBUFFERS_ASSERT(false == vals.vec.empty());
return vals.vec;
}

SymbolTable<EnumVal> vals;
const EnumVal *Lookup(const std::string &enum_name) const {
return vals.Lookup(enum_name);
}

bool is_union;
// Type is a union which uses type aliases where at least one type is
// available under two different names.
bool uses_multiple_type_instances;
Type underlying_type;

private:
friend EnumValBuilder;
SymbolTable<EnumVal> vals;
};

inline bool operator==(const EnumVal& lhs, const EnumVal& rhs) {
return lhs.value == rhs.value;
}
inline bool operator!=(const EnumVal & lhs, const EnumVal & rhs) {
return !(lhs == rhs);
}

inline bool EqualByName(const Type &a, const Type &b) {
return a.base_type == b.base_type && a.element == b.element &&
(a.struct_def == b.struct_def ||
Expand Down Expand Up @@ -705,7 +766,7 @@ class Parser : public ParserState {

FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);

private:
private:
void Message(const std::string &msg);
void Warning(const std::string &msg);
FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
Expand Down
2 changes: 1 addition & 1 deletion include/flatbuffers/reflection_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ inline const BaseType (&EnumValuesBaseType())[17] {
}

inline const char * const *EnumNamesBaseType() {
static const char * const names[] = {
static const char * const names[18] = {
"None",
"UType",
"Bool",
Expand Down
2 changes: 2 additions & 0 deletions include/flatbuffers/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,11 +380,13 @@ template<> inline bool StringToNumber(const char *s, double *val) {
return StringToFloatImpl(val, s);
}

// FLATBUFFERS_ATTRIBUTE(deprecated("use StringToNumber() instead"))
inline int64_t StringToInt(const char *s, int base = 10) {
int64_t val;
return StringToIntegerImpl(&val, s, base) ? val : 0;
}

// FLATBUFFERS_ATTRIBUTE(deprecated("use StringToNumber() instead"))
inline uint64_t StringToUInt(const char *s, int base = 10) {
uint64_t val;
return StringToIntegerImpl(&val, s, base) ? val : 0;
Expand Down
4 changes: 2 additions & 2 deletions samples/monster_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ inline const Color (&EnumValuesColor())[3] {
}

inline const char * const *EnumNamesColor() {
static const char * const names[] = {
static const char * const names[4] = {
"Red",
"Green",
"Blue",
Expand Down Expand Up @@ -79,7 +79,7 @@ inline const Equipment (&EnumValuesEquipment())[2] {
}

inline const char * const *EnumNamesEquipment() {
static const char * const names[] = {
static const char * const names[3] = {
"NONE",
"Weapon",
nullptr
Expand Down
Loading

0 comments on commit 42df4d4

Please sign in to comment.