Split ARRAY into fixed size ARRAY and VECTOR
Test: bluetooth_packet_parser_test
Change-Id: I438d7583fdb99054528b99a3a3a12ec58d115cb3
diff --git a/gd/hci/hci_layer_test.cc b/gd/hci/hci_layer_test.cc
index 5b5d3d7..a5b8f51 100644
--- a/gd/hci/hci_layer_test.cc
+++ b/gd/hci/hci_layer_test.cc
@@ -330,9 +330,9 @@
ASSERT_EQ(0, hal->GetNumSentCommands());
// Send the response event
- std::vector<uint8_t> supported_commands;
+ std::array<uint8_t, 64> supported_commands;
for (uint8_t i = 0; i < 64; i++) {
- supported_commands.push_back(i);
+ supported_commands[i] = i;
}
hal->callbacks->hciEventReceived(
GetPacketBytes(ReadLocalSupportedCommandsCompleteBuilder::Create(num_packets, error_code, supported_commands)));
diff --git a/gd/packet/parser/Android.bp b/gd/packet/parser/Android.bp
index 63aaa7a..4dc4950 100644
--- a/gd/packet/parser/Android.bp
+++ b/gd/packet/parser/Android.bp
@@ -2,6 +2,7 @@
name: "bluetooth_packetgen",
srcs: [
"fields/array_field.cc",
+ "fields/vector_field.cc",
"fields/body_field.cc",
"fields/checksum_field.cc",
"fields/checksum_start_field.cc",
diff --git a/gd/packet/parser/fields/all_fields.h b/gd/packet/parser/fields/all_fields.h
index 5797076..91323ea 100644
--- a/gd/packet/parser/fields/all_fields.h
+++ b/gd/packet/parser/fields/all_fields.h
@@ -31,3 +31,4 @@
#include "fields/reserved_field.h"
#include "fields/scalar_field.h"
#include "fields/size_field.h"
+#include "fields/vector_field.h"
diff --git a/gd/packet/parser/fields/array_field.cc b/gd/packet/parser/fields/array_field.cc
index 612f874..a39236f 100644
--- a/gd/packet/parser/fields/array_field.cc
+++ b/gd/packet/parser/fields/array_field.cc
@@ -19,16 +19,6 @@
const std::string ArrayField::kFieldType = "ArrayField";
-ArrayField::ArrayField(std::string name, int element_size, std::string size_modifier, ParseLocation loc)
- : PacketField(name, loc), element_size_(element_size), size_modifier_(size_modifier) {
- // Make sure the element_size is a multiple of 8.
- if (element_size_ > 64 || element_size_ < 0)
- ERROR(this) << __func__ << ": Not implemented for element size = " << element_size_;
- 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(name, loc), element_size_(element_size), fixed_size_(fixed_size) {
if (element_size_ > 64 || element_size_ < 0)
@@ -39,14 +29,6 @@
}
}
-ArrayField::ArrayField(std::string name, TypeDef* type_def, std::string size_modifier, ParseLocation loc)
- : PacketField(name, loc), element_size_(type_def->size_), type_def_(type_def), size_modifier_(size_modifier) {
- // 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(name, loc), element_size_(type_def->size_), type_def_(type_def), fixed_size_(fixed_size) {
// If the element type is not variable sized, make sure that it is byte aligned.
@@ -60,44 +42,15 @@
}
Size ArrayField::GetSize() const {
- if (IsFixedSize() && element_size_ != -1) {
+ if (element_size_ != -1) {
return Size(fixed_size_ * element_size_);
}
-
- // If there is no size field, then it is of unknown size.
- if (size_field_ == nullptr) {
- return Size();
- }
-
- // size_field_ is of type SIZE
- if (size_field_->GetFieldType() == SizeField::kFieldType) {
- std::string ret = "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * 8)";
- if (!size_modifier_.empty()) ret += size_modifier_;
- return ret;
- }
-
- // size_field_ is of type COUNT and it is a scalar array
- if (type_def_ == nullptr) {
- return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " + std::to_string(element_size_) + ")";
- }
-
- if (IsCustomFieldArray()) {
- if (type_def_->size_ != -1) {
- return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " + std::to_string(type_def_->size_) +
- ")";
- } else {
- return Size();
- }
- }
-
- // size_field_ is of type COUNT and it is an enum array
- return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " + std::to_string(type_def_->size_) +
- ")";
+ return Size();
}
Size ArrayField::GetBuilderSize() const {
if (element_size_ != -1) {
- std::string ret = "(" + GetName() + "_.size() * " + std::to_string(element_size_) + ")";
+ std::string ret = "(" + std::to_string(fixed_size_) + " * " + std::to_string(element_size_) + ")";
return ret;
} else {
std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() +
@@ -108,9 +61,9 @@
std::string ArrayField::GetDataType() const {
if (type_def_ != nullptr) {
- return "std::vector<" + type_def_->name_ + ">";
+ return "std::array<" + type_def_->name_ + "," + std::to_string(fixed_size_) + ">";
}
- return "std::vector<" + util::GetTypeForSize(element_size_) + ">";
+ return "std::array<" + util::GetTypeForSize(element_size_) + "," + std::to_string(fixed_size_) + ">";
}
void ArrayField::GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const {
@@ -120,15 +73,19 @@
s << "auto it = subview.begin();";
// Add the element size so that we will extract as many elements as we can.
- s << GetDataType() << " vec;";
+ s << GetDataType() << " ret;";
if (element_size_ != -1) {
std::string type = (type_def_ != nullptr) ? type_def_->name_ : util::GetTypeForSize(element_size_);
+ s << GetDataType() << "::iterator ret_it = ret.begin();";
s << "while (it + sizeof(" << type << ") <= subview.end()) {";
- s << "vec.push_back(it.extract<" << type << ">());";
+ s << "*ret_it = it.extract<" << type << ">();";
+ s << "ret_it++;";
s << "}";
} else {
+ s << "std::size_t ret_idx = 0;";
s << "while (it < subview.end()) {";
- s << "it = " << type_def_->name_ << "::Parse(vec, it);";
+ s << "it = " << type_def_->name_ << "::ParseArray(ret, &ret_idx, it);";
+ s << "ret_idx++;";
s << "}";
}
}
@@ -136,49 +93,37 @@
void ArrayField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
s << GetDataType();
s << " Get" << util::UnderscoreToCamelCase(GetName()) << "() {";
- s << "ASSERT(was_validated_);";
GenExtractor(s, start_offset, end_offset);
- s << "return vec;";
+ s << "return ret;";
s << "}\n";
}
bool ArrayField::GenBuilderParameter(std::ostream& s) const {
if (type_def_ != nullptr) {
- s << "const std::vector<" << type_def_->GetTypeName() << ">& " << GetName();
+ s << "const std::array<" << type_def_->GetTypeName() << "," << fixed_size_ << ">& " << GetName();
} else {
- s << "const std::vector<" << util::GetTypeForSize(element_size_) << ">& " << GetName();
+ s << "const std::array<" << util::GetTypeForSize(element_size_) << "," << fixed_size_ << ">& " << GetName();
}
return true;
}
bool ArrayField::GenBuilderMember(std::ostream& s) const {
if (type_def_ != nullptr) {
- s << "std::vector<" << type_def_->GetTypeName() << "> " << GetName();
+ s << "std::array<" << type_def_->GetTypeName() << "," << fixed_size_ << "> " << GetName();
} else {
- s << "std::vector<" << util::GetTypeForSize(element_size_) << "> " << GetName();
+ s << "std::array<" << util::GetTypeForSize(element_size_) << "," << fixed_size_ << "> " << GetName();
}
return true;
}
bool ArrayField::HasParameterValidator() const {
- if (fixed_size_ == -1) {
- // Does not have parameter validator yet.
- // TODO: See comment in GenParameterValidator
- return false;
- }
- return true;
+ return false;
}
-void ArrayField::GenParameterValidator(std::ostream& s) const {
- if (fixed_size_ == -1) {
- // No Parameter validator if its dynamically size.
- // TODO: Maybe add a validator to ensure that the size isn't larger than what the size field can hold.
- return;
- }
-
- s << "ASSERT(" << GetName() << "_.size() == " << fixed_size_ << ");";
+void ArrayField::GenParameterValidator(std::ostream&) const {
+ // Array length is validated by the compiler
}
void ArrayField::GenInserter(std::ostream& s) const {
@@ -212,24 +157,3 @@
bool ArrayField::IsCustomFieldArray() const {
return type_def_ != nullptr && type_def_->GetDefinitionType() == TypeDef::Type::CUSTOM;
}
-
-bool ArrayField::IsFixedSize() const {
- return fixed_size_ != -1;
-}
-
-void ArrayField::SetSizeField(const SizeField* size_field) {
- if (size_field->GetFieldType() == CountField::kFieldType && !size_modifier_.empty()) {
- ERROR(this, size_field) << "Can not use count field to describe array with a size modifier."
- << " Use size instead";
- }
-
- if (IsFixedSize()) {
- ERROR(this, size_field) << "Can not use size field with a fixed size array.";
- }
-
- size_field_ = size_field;
-}
-
-const std::string& ArrayField::GetSizeModifier() const {
- return size_modifier_;
-}
diff --git a/gd/packet/parser/fields/array_field.h b/gd/packet/parser/fields/array_field.h
index d650ba7..679823f 100644
--- a/gd/packet/parser/fields/array_field.h
+++ b/gd/packet/parser/fields/array_field.h
@@ -25,12 +25,8 @@
class ArrayField : public PacketField {
public:
- ArrayField(std::string name, int element_size, std::string size_modifier, ParseLocation loc);
-
ArrayField(std::string name, int element_size, int fixed_size, ParseLocation loc);
- ArrayField(std::string name, TypeDef* type_def, std::string size_modifier, ParseLocation loc);
-
ArrayField(std::string name, TypeDef* type_def, int fixed_size, ParseLocation loc);
static const std::string kFieldType;
@@ -63,12 +59,6 @@
bool IsCustomFieldArray() const;
- bool IsFixedSize() const;
-
- void SetSizeField(const SizeField* size_field);
-
- const std::string& GetSizeModifier() const;
-
const std::string name_;
const int element_size_{-1}; // in bits
@@ -76,8 +66,4 @@
// Fixed size array or dynamic size, size is always in bytes, unless it is count.
const int fixed_size_{-1};
- const SizeField* size_field_{nullptr};
-
- // Size modifier is only used when size_field_ is of type SIZE and is not used with COUNT.
- std::string size_modifier_{""};
};
diff --git a/gd/packet/parser/fields/vector_field.cc b/gd/packet/parser/fields/vector_field.cc
new file mode 100644
index 0000000..6fc7f69
--- /dev/null
+++ b/gd/packet/parser/fields/vector_field.cc
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "fields/vector_field.h"
+#include "util.h"
+
+const std::string VectorField::kFieldType = "VectorField";
+
+VectorField::VectorField(std::string name, int element_size, std::string size_modifier, ParseLocation loc)
+ : PacketField(name, loc), element_size_(element_size), size_modifier_(size_modifier) {
+ if (element_size_ > 64 || element_size_ < 0)
+ ERROR(this) << __func__ << ": Not implemented for element size = " << element_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 (" << element_size << ")";
+ }
+}
+
+VectorField::VectorField(std::string name, TypeDef* type_def, std::string size_modifier, ParseLocation loc)
+ : PacketField(name, loc), element_size_(type_def->size_), type_def_(type_def), size_modifier_(size_modifier) {
+ // 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_ << ")";
+ }
+}
+
+const std::string& VectorField::GetFieldType() const {
+ return VectorField::kFieldType;
+}
+
+Size VectorField::GetSize() const {
+ // If there is no size field, then it is of unknown size.
+ if (size_field_ == nullptr) {
+ return Size();
+ }
+
+ // size_field_ is of type SIZE
+ if (size_field_->GetFieldType() == SizeField::kFieldType) {
+ std::string ret = "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * 8)";
+ if (!size_modifier_.empty()) ret += size_modifier_;
+ return ret;
+ }
+
+ // size_field_ is of type COUNT and it is a scalar array
+ if (type_def_ == nullptr) {
+ return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " + std::to_string(element_size_) + ")";
+ }
+
+ if (IsCustomFieldArray()) {
+ if (type_def_->size_ != -1) {
+ return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " + std::to_string(type_def_->size_) +
+ ")";
+ } else {
+ return Size();
+ }
+ }
+
+ // size_field_ is of type COUNT and it is an enum array
+ return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " + std::to_string(type_def_->size_) +
+ ")";
+}
+
+Size VectorField::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 VectorField::GetDataType() const {
+ if (type_def_ != nullptr) {
+ return "std::vector<" + type_def_->name_ + ">";
+ }
+ return "std::vector<" + util::GetTypeForSize(element_size_) + ">";
+}
+
+void VectorField::GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const {
+ GenBounds(s, start_offset, end_offset, GetSize());
+
+ s << " auto subview = GetLittleEndianSubview(field_begin, field_end); ";
+ s << "auto it = subview.begin();";
+
+ // Add the element size so that we will extract as many elements as we can.
+ s << GetDataType() << " ret;";
+ if (element_size_ != -1) {
+ std::string type = (type_def_ != nullptr) ? type_def_->name_ : util::GetTypeForSize(element_size_);
+ s << "while (it + sizeof(" << type << ") <= subview.end()) {";
+ s << "ret.push_back(it.extract<" << type << ">());";
+ s << "}";
+ } else {
+ s << "while (it < subview.end()) {";
+ s << "it = " << type_def_->name_ << "::Parse(ret, it);";
+ s << "}";
+ }
+}
+
+void VectorField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
+ s << GetDataType();
+ s << " Get" << util::UnderscoreToCamelCase(GetName()) << "() {";
+
+ GenExtractor(s, start_offset, end_offset);
+
+ s << "return ret;";
+ s << "}\n";
+}
+
+bool VectorField::GenBuilderParameter(std::ostream& s) const {
+ if (type_def_ != nullptr) {
+ s << "const std::vector<" << type_def_->GetTypeName() << ">& " << GetName();
+ } else {
+ s << "const std::vector<" << util::GetTypeForSize(element_size_) << ">& " << GetName();
+ }
+ return true;
+}
+
+bool VectorField::HasParameterValidator() const {
+ // Does not have parameter validator yet.
+ // TODO: See comment in GenParameterValidator
+ return false;
+}
+
+void VectorField::GenParameterValidator(std::ostream&) const {
+ // No Parameter validator if its dynamically size.
+ // TODO: Maybe add a validator to ensure that the size isn't larger than what the size field can hold.
+ return;
+}
+
+void VectorField::GenInserter(std::ostream& s) const {
+ s << "for (const auto& val : " << GetName() << "_) {";
+ 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 << "val.Serialize(i);";
+ } else {
+ s << "insert(val, i);";
+ }
+ } else {
+ s << "insert(val, i, " << element_size_ << ");";
+ }
+ s << "}\n";
+}
+
+void VectorField::GenValidator(std::ostream&) const {
+ // NOTE: We could check if the element size divides cleanly into the array size, but we decided to forgo that
+ // in favor of just returning as many elements as possible in a best effort style.
+ //
+ // Other than that there is nothing that arrays need to be validated on other than length so nothing needs to
+ // be done here.
+}
+
+bool VectorField::IsEnumArray() const {
+ return type_def_ != nullptr && type_def_->GetDefinitionType() == TypeDef::Type::ENUM;
+}
+
+bool VectorField::IsCustomFieldArray() const {
+ return type_def_ != nullptr && type_def_->GetDefinitionType() == TypeDef::Type::CUSTOM;
+}
+
+void VectorField::SetSizeField(const SizeField* size_field) {
+ if (size_field->GetFieldType() == CountField::kFieldType && !size_modifier_.empty()) {
+ ERROR(this, size_field) << "Can not use count field to describe array with a size modifier."
+ << " Use size instead";
+ }
+
+ size_field_ = size_field;
+}
+
+const std::string& VectorField::GetSizeModifier() const {
+ return size_modifier_;
+}
diff --git a/gd/packet/parser/fields/vector_field.h b/gd/packet/parser/fields/vector_field.h
new file mode 100644
index 0000000..34f4b31
--- /dev/null
+++ b/gd/packet/parser/fields/vector_field.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "custom_field_def.h"
+#include "enum_def.h"
+#include "fields/count_field.h"
+#include "fields/packet_field.h"
+#include "fields/size_field.h"
+#include "parse_location.h"
+
+class VectorField : public PacketField {
+ public:
+ VectorField(std::string name, int element_size, std::string size_modifier, ParseLocation loc);
+
+ VectorField(std::string name, TypeDef* type_def, std::string size_modifier, ParseLocation loc);
+
+ static const std::string kFieldType;
+
+ virtual const std::string& GetFieldType() const override;
+
+ virtual Size GetSize() const override;
+
+ virtual Size GetBuilderSize() const override;
+
+ virtual std::string GetDataType() const override;
+
+ virtual void GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const override;
+
+ virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+
+ virtual bool GenBuilderParameter(std::ostream& s) const override;
+
+ virtual bool HasParameterValidator() const override;
+
+ virtual void GenParameterValidator(std::ostream& s) const override;
+
+ virtual void GenInserter(std::ostream& s) const override;
+
+ virtual void GenValidator(std::ostream&) const override;
+
+ bool IsEnumArray() const;
+
+ bool IsCustomFieldArray() const;
+
+ void SetSizeField(const SizeField* size_field);
+
+ const std::string& GetSizeModifier() const;
+
+ const std::string name_;
+
+ 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.
+ const SizeField* size_field_{nullptr};
+
+ // Size modifier is only used when size_field_ is of type SIZE and is not used with COUNT.
+ std::string size_modifier_{""};
+};
diff --git a/gd/packet/parser/language_y.yy b/gd/packet/parser/language_y.yy
index b1fb6bc..cc9d214 100644
--- a/gd/packet/parser/language_y.yy
+++ b/gd/packet/parser/language_y.yy
@@ -560,15 +560,15 @@
array_field_definition
: IDENTIFIER ':' INTEGER '[' ']'
{
- DEBUG() << "Array field defined name=" << *$1 << " element_size=" << $3;
- $$ = new ArrayField(*$1, $3, "", LOC);
+ DEBUG() << "Vector field defined name=" << *$1 << " element_size=" << $3;
+ $$ = new VectorField(*$1, $3, "", LOC);
delete $1;
}
| IDENTIFIER ':' INTEGER '[' SIZE_MODIFIER ']'
{
- DEBUG() << "Array field defined name=" << *$1 << " element_size=" << $3
+ DEBUG() << "Vector field defined name=" << *$1 << " element_size=" << $3
<< " size_modifier=" << *$5;
- $$ = new ArrayField(*$1, $3, *$5, LOC);
+ $$ = new VectorField(*$1, $3, *$5, LOC);
delete $1;
delete $5;
}
@@ -581,9 +581,9 @@
}
| IDENTIFIER ':' IDENTIFIER '[' ']'
{
- DEBUG() << "Array field defined name=" << *$1 << " type=" << *$3;
+ DEBUG() << "Vector field defined name=" << *$1 << " type=" << *$3;
if (auto type_def = decls->GetTypeDef(*$3)) {
- $$ = new ArrayField(*$1, type_def, "", LOC);
+ $$ = new VectorField(*$1, type_def, "", LOC);
} else {
ERRORLOC(LOC) << "Can't find type used in array field.";
}
@@ -592,10 +592,10 @@
}
| IDENTIFIER ':' IDENTIFIER '[' SIZE_MODIFIER ']'
{
- DEBUG() << "Array field defined name=" << *$1 << " type=" << *$3
+ DEBUG() << "Vector field defined name=" << *$1 << " type=" << *$3
<< " size_modifier=" << *$5;
if (auto type_def = decls->GetTypeDef(*$3)) {
- $$ = new ArrayField(*$1, type_def, *$5, LOC);
+ $$ = new VectorField(*$1, type_def, *$5, LOC);
} else {
ERRORLOC(LOC) << "Can't find type used in array field.";
}
diff --git a/gd/packet/parser/parent_def.cc b/gd/packet/parser/parent_def.cc
index cbbbe04..32121b5 100644
--- a/gd/packet/parser/parent_def.cc
+++ b/gd/packet/parser/parent_def.cc
@@ -90,9 +90,9 @@
continue;
}
- if (var_len_field->GetFieldType() == ArrayField::kFieldType) {
- const auto& array_field = static_cast<ArrayField*>(var_len_field);
- array_field->SetSizeField(size_field);
+ if (var_len_field->GetFieldType() == VectorField::kFieldType) {
+ const auto& vector_field = static_cast<VectorField*>(var_len_field);
+ vector_field->SetSizeField(size_field);
continue;
}
@@ -216,8 +216,8 @@
FieldList params;
std::set<std::string> param_types = {
- ScalarField::kFieldType, EnumField::kFieldType, ArrayField::kFieldType,
- CustomField::kFieldType, PayloadField::kFieldType,
+ ScalarField::kFieldType, EnumField::kFieldType, ArrayField::kFieldType,
+ VectorField::kFieldType, CustomField::kFieldType, PayloadField::kFieldType,
};
if (parent_ != nullptr) {
@@ -335,22 +335,22 @@
s << "ASSERT(payload_bytes < (static_cast<size_t>(1) << " << field->GetSize().bits() << "));";
s << "insert(static_cast<" << field->GetDataType() << ">(payload_bytes), i," << field->GetSize().bits() << ");";
} else {
- if (sized_field->GetFieldType() != ArrayField::kFieldType) {
+ if (sized_field->GetFieldType() != VectorField::kFieldType) {
ERROR(field) << __func__ << ": Unhandled sized field type for " << field_name;
}
- const auto& array_name = field_name + "_";
- const ArrayField* array = (ArrayField*)sized_field;
- s << "size_t " << array_name + "bytes = 0;";
- if (array->element_size_ == -1) {
- s << "for (auto elem : " << array_name << ") {";
- s << array_name + "bytes += elem.size(); }";
+ const auto& vector_name = field_name + "_";
+ const VectorField* vector = (VectorField*)sized_field;
+ s << "size_t " << vector_name + "bytes = 0;";
+ if (vector->element_size_ == -1) {
+ s << "for (auto elem : " << vector_name << ") {";
+ s << vector_name + "bytes += elem.size(); }";
} else {
- s << array_name + "bytes = ";
- s << array_name << ".size() * (" << array->element_size_ << " / 8);";
+ s << vector_name + "bytes = ";
+ s << vector_name << ".size() * (" << vector->element_size_ << " / 8);";
}
- s << "ASSERT(" << array_name + "bytes < (1 << " << field->GetSize().bits() << "));";
- s << "insert(" << array_name << "bytes";
- s << array->GetSizeModifier() << ", i, ";
+ s << "ASSERT(" << vector_name + "bytes < (1 << " << field->GetSize().bits() << "));";
+ s << "insert(" << vector_name << "bytes";
+ s << vector->GetSizeModifier() << ", i, ";
s << field->GetSize().bits() << ");";
}
} else if (field->GetFieldType() == ChecksumStartField::kFieldType) {
@@ -366,8 +366,8 @@
s << "[shared_checksum_ptr](uint8_t byte){ shared_checksum_ptr->AddByte(byte);},";
s << "[shared_checksum_ptr](){ return static_cast<uint64_t>(shared_checksum_ptr->GetChecksum());}));";
} else if (field->GetFieldType() == CountField::kFieldType) {
- const auto& array_name = ((SizeField*)field)->GetSizedFieldName() + "_";
- s << "insert(" << array_name << ".size(), i, " << field->GetSize().bits() << ");";
+ const auto& vector_name = ((SizeField*)field)->GetSizedFieldName() + "_";
+ s << "insert(" << vector_name << ".size(), i, " << field->GetSize().bits() << ");";
} else {
field->GenInserter(s);
}
diff --git a/gd/packet/parser/test/generated_packet_test.cc b/gd/packet/parser/test/generated_packet_test.cc
index 43e74be..2bf1c7e 100644
--- a/gd/packet/parser/test/generated_packet_test.cc
+++ b/gd/packet/parser/test/generated_packet_test.cc
@@ -443,7 +443,7 @@
}
TEST(GeneratedPacketTest, testFixedArrayEnum) {
- std::vector<ForArrays> fixed_array{
+ std::array<ForArrays, 5> fixed_array{
{ForArrays::ONE, ForArrays::TWO, ForArrays::ONE_TWO, ForArrays::TWO_THREE, ForArrays::FFFF}};
auto packet = FixedArrayEnumBuilder::Create(fixed_array);
ASSERT_EQ(fixed_array_enum.size(), packet->size());
@@ -546,12 +546,12 @@
}
TEST(GeneratedPacketTest, testFixedSizeByteArray) {
- constexpr int byte_array_size = 32;
- std::vector<uint8_t> byte_array(byte_array_size);
+ constexpr std::size_t byte_array_size = 32;
+ std::array<uint8_t, byte_array_size> byte_array;
for (uint8_t i = 0; i < byte_array_size; i++) byte_array[i] = i;
constexpr int word_array_size = 8;
- std::vector<uint32_t> word_array(word_array_size);
+ std::array<uint32_t, word_array_size> word_array;
for (uint32_t i = 0; i < word_array_size; i++) word_array[i] = i;
auto packet = PacketWithFixedArraysOfBytesBuilder::Create(byte_array, word_array);
@@ -583,19 +583,6 @@
}
}
-TEST(GeneratedPacketTest, testFixedSizeArrayValidatorDeath) {
- constexpr int byte_array_size = 33;
- std::vector<uint8_t> byte_array(byte_array_size);
- for (uint8_t i = 0; i < byte_array_size; i++) byte_array[i] = i;
-
- constexpr int word_array_size = 8;
- std::vector<uint32_t> word_array(word_array_size);
- for (uint32_t i = 0; i < word_array_size; i++) word_array[i] = i;
-
- std::unique_ptr<PacketWithFixedArraysOfBytesBuilder> packet;
- ASSERT_DEATH(packet = PacketWithFixedArraysOfBytesBuilder::Create(byte_array, word_array), "size");
-}
-
vector<uint8_t> one_variable{
0x03, 'o', 'n', 'e', // "one"
};
@@ -670,12 +657,8 @@
};
TEST(GeneratedPacketTest, testFixedArrayVariableLength) {
- std::vector<Variable> fixed_array;
- fixed_array.emplace_back("one");
- fixed_array.emplace_back("two");
- fixed_array.emplace_back("three");
- fixed_array.emplace_back("four");
- fixed_array.emplace_back("five");
+ std::array<Variable, 5> fixed_array{std::string("one"), std::string("two"), std::string("three"), std::string("four"),
+ std::string("five")};
auto packet = FixedArrayVariableBuilder::Create(fixed_array);
ASSERT_EQ(fixed_array_variable.size(), packet->size());
diff --git a/gd/packet/parser/test/variable.h b/gd/packet/parser/test/variable.h
index 36361e2..056eac6 100644
--- a/gd/packet/parser/test/variable.h
+++ b/gd/packet/parser/test/variable.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <optional>
+#include <sstream>
#include <string>
#include "packet/bit_inserter.h"
@@ -43,8 +44,30 @@
size_t size() const;
static Iterator<true> Parse(std::vector<Variable>& vec, Iterator<true> it);
+ template <std::size_t arr_size>
+ static Iterator<true> ParseArray(std::array<Variable, arr_size>& arr, std::size_t* arr_idx, Iterator<true> it);
};
+template <std::size_t arr_size>
+Iterator<true> Variable::ParseArray(std::array<Variable, arr_size>& arr, std::size_t* arr_idx, Iterator<true> it) {
+ if (it.NumBytesRemaining() < 1) {
+ return it;
+ }
+ size_t data_length = it.extract<uint8_t>();
+ if (data_length > 255) {
+ return it + it.NumBytesRemaining();
+ }
+ if (it.NumBytesRemaining() < data_length) {
+ return it + it.NumBytesRemaining();
+ }
+ std::stringstream ss;
+ for (size_t i = 0; i < data_length; i++) {
+ ss << it.extract<char>();
+ }
+ arr[*arr_idx] = ss.str();
+ return it;
+}
+
} // namespace test
} // namespace parser
} // namespace packet