Loading system/gd/packet/custom_type_checker.h 0 → 100644 +36 −0 Original line number Diff line number Diff line #include <array> #include "packet/bit_inserter.h" #include "packet/iterator.h" namespace bluetooth { namespace packet { // Checks a custom type has all the necessary static functions with the correct signatures. template <typename T> class CustomTypeChecker { public: template <class C, void (*)(const C&, BitInserter&)> struct SerializeChecker {}; template <class C, size_t (*)(const C&)> struct SizeChecker {}; template <class C, Iterator<true> (*)(std::vector<C>& vec, Iterator<true> it)> struct ParseChecker {}; template <class C, Iterator<false> (*)(std::vector<C>& vec, Iterator<false> it)> struct ParseCheckerBigEndian {}; template <class C> static int Test(SerializeChecker<C, &C::Serialize>*, SizeChecker<C, &C::Size>*, ParseChecker<C, &C::Parse>*); template <class C> static int Test(SerializeChecker<C, &C::Serialize>*, SizeChecker<C, &C::Size>*, ParseCheckerBigEndian<C, &C::Parse>*); template <class C> static char Test(...); static constexpr bool value = (sizeof(Test<T>(0, 0, 0)) == sizeof(int)); }; } // namespace packet } // namespace bluetooth system/gd/packet/parser/custom_field_def.cc +7 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ #include "util.h" CustomFieldDef::CustomFieldDef(std::string name, std::string include) : TypeDef(name), include_(include) {} CustomFieldDef::CustomFieldDef(std::string name, std::string include, int size) : TypeDef(name, size), include_(include) { if (size % 8 != 0) { Loading Loading @@ -50,3 +52,8 @@ void CustomFieldDef::GenUsing(std::ostream& s) const { } s << GetTypeName() << ";"; } void CustomFieldDef::GenCustomFieldCheck(std::ostream& s) const { s << "static_assert(CustomTypeChecker<" << name_ << ">::value, \""; s << name_ << " is not a valid custom field type. Please see README for more details.\");"; } system/gd/packet/parser/custom_field_def.h +4 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ class CustomFieldDef : public TypeDef { public: CustomFieldDef(std::string name, std::string include); CustomFieldDef(std::string name, std::string include, int size); virtual PacketField* GetNewField(const std::string& name, ParseLocation loc) const override; Loading @@ -34,5 +36,7 @@ class CustomFieldDef : public TypeDef { void GenUsing(std::ostream& s) const; void GenCustomFieldCheck(std::ostream& s) const; const std::string include_; }; system/gd/packet/parser/fields/array_field.cc +47 −14 Original line number Diff line number Diff line Loading @@ -20,25 +20,33 @@ ArrayField::ArrayField(std::string name, int element_size, std::string size_modifier, ParseLocation loc) : PacketField(loc, name), element_size_(element_size), size_modifier_(size_modifier) { // Make sure the element_size is a multiple of 8. if (element_size % 8 != 0) ERROR(this) << "Can only have arrays with elements that are byte aligned."; if (element_size % 8 != 0) { ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size << ")"; } } ArrayField::ArrayField(std::string name, int element_size, int fixed_size, ParseLocation loc) : PacketField(loc, name), element_size_(element_size), fixed_size_(fixed_size) { // Make sure the element_size is a multiple of 8. if (element_size % 8 != 0) ERROR(this) << "Can only have arrays with elements that are byte aligned."; if (element_size % 8 != 0) { ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size << ")"; } } ArrayField::ArrayField(std::string name, TypeDef* type_def, std::string size_modifier, ParseLocation loc) : PacketField(loc, name), element_size_(type_def->size_), type_def_(type_def), size_modifier_(size_modifier) { // If it is an enum array, make sure that the enum definition is byte aligned. if (type_def_->size_ % 8 != 0) ERROR(this) << "Can only have arrays with elements that are byte aligned."; // If the element type is not variable sized, make sure that it is byte aligned. if (type_def_->size_ != -1 && type_def_->size_ % 8 != 0) { ERROR(this) << "Can only have arrays with elements that are byte aligned (" << type_def_->size_ << ")"; } } ArrayField::ArrayField(std::string name, TypeDef* type_def, int fixed_size, ParseLocation loc) : PacketField(loc, name), element_size_(type_def->size_), type_def_(type_def), fixed_size_(fixed_size) { // If it is an enum array, make sure that the enum definition is byte aligned. if (type_def_->size_ % 8 != 0) ERROR(this) << "Can only have arrays with elements that are byte aligned."; // If the element type is not variable sized, make sure that it is byte aligned. if (type_def_->size_ != -1 && type_def_->size_ % 8 != 0) { ERROR(this) << "Can only have arrays with elements that are byte aligned (" << type_def_->size_ << ")"; } } PacketField::Type ArrayField::GetFieldType() const { Loading Loading @@ -69,8 +77,12 @@ Size ArrayField::GetSize() const { } if (IsCustomFieldArray()) { if (type_def_->size_ != -1) { return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " + std::to_string(type_def_->size_ / 8) + ")"; } else { return Size(); } } // size_field_ is of type COUNT and it is an enum array Loading @@ -78,6 +90,17 @@ Size ArrayField::GetSize() const { ")"; } Size ArrayField::GetBuilderSize() const { if (element_size_ != -1) { std::string ret = "(" + GetName() + "_.size() * " + std::to_string(element_size_) + ")"; return ret; } else { std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() + "_) { length += elem.size() * 8; } return length; }()"; return ret; } } std::string ArrayField::GetType() const { if (type_def_ != nullptr) { return "std::vector<" + type_def_->name_ + ">"; Loading Loading @@ -113,10 +136,16 @@ void ArrayField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) // Add the element size so that we will extract as many elements as we can. s << GetType() << " ret;"; if (element_size_ != -1) { std::string type = (type_def_ != nullptr) ? type_def_->name_ : util::GetTypeForSize(element_size_); s << "while (it + sizeof(" << type << ") <= array_end) {"; s << "ret.push_back(it.extract<" << type << ">());"; s << "}"; } else { s << "while (it < array_end) {"; s << "it = " << type_def_->name_ << "::Parse(ret, it);"; s << "}"; } s << "return ret;"; s << "}\n"; Loading Loading @@ -152,7 +181,7 @@ void ArrayField::GenParameterValidator(std::ostream& s) const { return; } s << "ASSERT(" << GetName() << ".size() == " << fixed_size_ << ");"; s << "ASSERT(" << GetName() << "_.size() == " << fixed_size_ << ");"; } void ArrayField::GenInserter(std::ostream& s) const { Loading @@ -160,7 +189,11 @@ void ArrayField::GenInserter(std::ostream& s) const { if (IsEnumArray()) { s << "insert(static_cast<" << util::GetTypeForSize(type_def_->size_) << ">(val), i, " << type_def_->size_ << ");"; } else if (IsCustomFieldArray()) { if (type_def_->size_ == -1) { s << type_def_->name_ << "::Serialize(val, i);"; } else { s << "insert(val, i);"; } } else { s << "insert(val, i, " << element_size_ << ");"; } Loading system/gd/packet/parser/fields/array_field.h +3 −1 Original line number Diff line number Diff line Loading @@ -37,6 +37,8 @@ class ArrayField : public PacketField { virtual Size GetSize() const override; virtual Size GetBuilderSize() const override; virtual std::string GetType() const override; virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override; Loading @@ -63,7 +65,7 @@ class ArrayField : public PacketField { const std::string name_; const int element_size_{-1}; // units is bits const int element_size_{-1}; // in bits const TypeDef* type_def_{nullptr}; // Fixed size array or dynamic size, size is always in bytes, unless it is count. Loading Loading
system/gd/packet/custom_type_checker.h 0 → 100644 +36 −0 Original line number Diff line number Diff line #include <array> #include "packet/bit_inserter.h" #include "packet/iterator.h" namespace bluetooth { namespace packet { // Checks a custom type has all the necessary static functions with the correct signatures. template <typename T> class CustomTypeChecker { public: template <class C, void (*)(const C&, BitInserter&)> struct SerializeChecker {}; template <class C, size_t (*)(const C&)> struct SizeChecker {}; template <class C, Iterator<true> (*)(std::vector<C>& vec, Iterator<true> it)> struct ParseChecker {}; template <class C, Iterator<false> (*)(std::vector<C>& vec, Iterator<false> it)> struct ParseCheckerBigEndian {}; template <class C> static int Test(SerializeChecker<C, &C::Serialize>*, SizeChecker<C, &C::Size>*, ParseChecker<C, &C::Parse>*); template <class C> static int Test(SerializeChecker<C, &C::Serialize>*, SizeChecker<C, &C::Size>*, ParseCheckerBigEndian<C, &C::Parse>*); template <class C> static char Test(...); static constexpr bool value = (sizeof(Test<T>(0, 0, 0)) == sizeof(int)); }; } // namespace packet } // namespace bluetooth
system/gd/packet/parser/custom_field_def.cc +7 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ #include "util.h" CustomFieldDef::CustomFieldDef(std::string name, std::string include) : TypeDef(name), include_(include) {} CustomFieldDef::CustomFieldDef(std::string name, std::string include, int size) : TypeDef(name, size), include_(include) { if (size % 8 != 0) { Loading Loading @@ -50,3 +52,8 @@ void CustomFieldDef::GenUsing(std::ostream& s) const { } s << GetTypeName() << ";"; } void CustomFieldDef::GenCustomFieldCheck(std::ostream& s) const { s << "static_assert(CustomTypeChecker<" << name_ << ">::value, \""; s << name_ << " is not a valid custom field type. Please see README for more details.\");"; }
system/gd/packet/parser/custom_field_def.h +4 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ class CustomFieldDef : public TypeDef { public: CustomFieldDef(std::string name, std::string include); CustomFieldDef(std::string name, std::string include, int size); virtual PacketField* GetNewField(const std::string& name, ParseLocation loc) const override; Loading @@ -34,5 +36,7 @@ class CustomFieldDef : public TypeDef { void GenUsing(std::ostream& s) const; void GenCustomFieldCheck(std::ostream& s) const; const std::string include_; };
system/gd/packet/parser/fields/array_field.cc +47 −14 Original line number Diff line number Diff line Loading @@ -20,25 +20,33 @@ ArrayField::ArrayField(std::string name, int element_size, std::string size_modifier, ParseLocation loc) : PacketField(loc, name), element_size_(element_size), size_modifier_(size_modifier) { // Make sure the element_size is a multiple of 8. if (element_size % 8 != 0) ERROR(this) << "Can only have arrays with elements that are byte aligned."; if (element_size % 8 != 0) { ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size << ")"; } } ArrayField::ArrayField(std::string name, int element_size, int fixed_size, ParseLocation loc) : PacketField(loc, name), element_size_(element_size), fixed_size_(fixed_size) { // Make sure the element_size is a multiple of 8. if (element_size % 8 != 0) ERROR(this) << "Can only have arrays with elements that are byte aligned."; if (element_size % 8 != 0) { ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size << ")"; } } ArrayField::ArrayField(std::string name, TypeDef* type_def, std::string size_modifier, ParseLocation loc) : PacketField(loc, name), element_size_(type_def->size_), type_def_(type_def), size_modifier_(size_modifier) { // If it is an enum array, make sure that the enum definition is byte aligned. if (type_def_->size_ % 8 != 0) ERROR(this) << "Can only have arrays with elements that are byte aligned."; // If the element type is not variable sized, make sure that it is byte aligned. if (type_def_->size_ != -1 && type_def_->size_ % 8 != 0) { ERROR(this) << "Can only have arrays with elements that are byte aligned (" << type_def_->size_ << ")"; } } ArrayField::ArrayField(std::string name, TypeDef* type_def, int fixed_size, ParseLocation loc) : PacketField(loc, name), element_size_(type_def->size_), type_def_(type_def), fixed_size_(fixed_size) { // If it is an enum array, make sure that the enum definition is byte aligned. if (type_def_->size_ % 8 != 0) ERROR(this) << "Can only have arrays with elements that are byte aligned."; // If the element type is not variable sized, make sure that it is byte aligned. if (type_def_->size_ != -1 && type_def_->size_ % 8 != 0) { ERROR(this) << "Can only have arrays with elements that are byte aligned (" << type_def_->size_ << ")"; } } PacketField::Type ArrayField::GetFieldType() const { Loading Loading @@ -69,8 +77,12 @@ Size ArrayField::GetSize() const { } if (IsCustomFieldArray()) { if (type_def_->size_ != -1) { return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " + std::to_string(type_def_->size_ / 8) + ")"; } else { return Size(); } } // size_field_ is of type COUNT and it is an enum array Loading @@ -78,6 +90,17 @@ Size ArrayField::GetSize() const { ")"; } Size ArrayField::GetBuilderSize() const { if (element_size_ != -1) { std::string ret = "(" + GetName() + "_.size() * " + std::to_string(element_size_) + ")"; return ret; } else { std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() + "_) { length += elem.size() * 8; } return length; }()"; return ret; } } std::string ArrayField::GetType() const { if (type_def_ != nullptr) { return "std::vector<" + type_def_->name_ + ">"; Loading Loading @@ -113,10 +136,16 @@ void ArrayField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) // Add the element size so that we will extract as many elements as we can. s << GetType() << " ret;"; if (element_size_ != -1) { std::string type = (type_def_ != nullptr) ? type_def_->name_ : util::GetTypeForSize(element_size_); s << "while (it + sizeof(" << type << ") <= array_end) {"; s << "ret.push_back(it.extract<" << type << ">());"; s << "}"; } else { s << "while (it < array_end) {"; s << "it = " << type_def_->name_ << "::Parse(ret, it);"; s << "}"; } s << "return ret;"; s << "}\n"; Loading Loading @@ -152,7 +181,7 @@ void ArrayField::GenParameterValidator(std::ostream& s) const { return; } s << "ASSERT(" << GetName() << ".size() == " << fixed_size_ << ");"; s << "ASSERT(" << GetName() << "_.size() == " << fixed_size_ << ");"; } void ArrayField::GenInserter(std::ostream& s) const { Loading @@ -160,7 +189,11 @@ void ArrayField::GenInserter(std::ostream& s) const { if (IsEnumArray()) { s << "insert(static_cast<" << util::GetTypeForSize(type_def_->size_) << ">(val), i, " << type_def_->size_ << ");"; } else if (IsCustomFieldArray()) { if (type_def_->size_ == -1) { s << type_def_->name_ << "::Serialize(val, i);"; } else { s << "insert(val, i);"; } } else { s << "insert(val, i, " << element_size_ << ");"; } Loading
system/gd/packet/parser/fields/array_field.h +3 −1 Original line number Diff line number Diff line Loading @@ -37,6 +37,8 @@ class ArrayField : public PacketField { virtual Size GetSize() const override; virtual Size GetBuilderSize() const override; virtual std::string GetType() const override; virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override; Loading @@ -63,7 +65,7 @@ class ArrayField : public PacketField { const std::string name_; const int element_size_{-1}; // units is bits const int element_size_{-1}; // in bits const TypeDef* type_def_{nullptr}; // Fixed size array or dynamic size, size is always in bytes, unless it is count. Loading