Fix issues with uint64 enums (#5265)

* Fix issues with uint64 enums

- hide the implementation of enums from code generators
- fix uint64 the issue in the cpp-generator
- fix #5108
- new tests
- enums with bit_flags attribute should be unsigned

* Refine objectives of EnumDef's FindByValue and ReverseLookup methods

- move EnumDef::ReverseLookup implementation to idl_parser.cpp
- fix typos

* Make the IsUInt64 method private
This commit is contained in:
Vladimir Glavnyy
2019-05-03 03:57:58 +07:00
committed by Wouter van Oortmerssen
parent 6cc30b3272
commit b8ef8c1521
16 changed files with 526 additions and 276 deletions

View File

@@ -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

View File

@@ -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[];
@@ -327,52 +334,96 @@ 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);
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() +
static_cast<int>(is_union && skip_union_default);
it != Vals().end(); ++it) {
if ((*it)->value == enum_idx) { return *it; }
}
return nullptr;
}
Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder,
const Parser &parser) const;
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()); }
EnumVal *ReverseLookup(int64_t enum_idx,
bool skip_union_default = false) const;
EnumVal *FindByValue(const std::string &constant) const;
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:
bool IsUInt64() const {
return (BASE_TYPE_ULONG == underlying_type.base_type);
}
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 ||