OSDN Git Service

PDL: Move GenBounds to GenGetter
authorMyles Watson <mylesgw@google.com>
Wed, 18 Sep 2019 23:19:06 +0000 (16:19 -0700)
committerMyles Watson <mylesgw@google.com>
Wed, 25 Sep 2019 15:43:59 +0000 (08:43 -0700)
- Use an element_field_ in ArrayField and VectorField
- Use GenExtractor for all extraction

Test: bluetooth_packet_parser_test
Change-Id: I36ed7cfea3f6754737f00d681f6e5fadf90bad87

28 files changed:
gd/packet/parser/fields/array_field.cc
gd/packet/parser/fields/array_field.h
gd/packet/parser/fields/body_field.cc
gd/packet/parser/fields/body_field.h
gd/packet/parser/fields/checksum_field.cc
gd/packet/parser/fields/checksum_field.h
gd/packet/parser/fields/checksum_start_field.cc
gd/packet/parser/fields/checksum_start_field.h
gd/packet/parser/fields/custom_field.cc
gd/packet/parser/fields/custom_field.h
gd/packet/parser/fields/custom_field_fixed_size.cc
gd/packet/parser/fields/custom_field_fixed_size.h
gd/packet/parser/fields/group_field.cc
gd/packet/parser/fields/group_field.h
gd/packet/parser/fields/packet_field.cc
gd/packet/parser/fields/packet_field.h
gd/packet/parser/fields/payload_field.cc
gd/packet/parser/fields/payload_field.h
gd/packet/parser/fields/reserved_field.cc
gd/packet/parser/fields/reserved_field.h
gd/packet/parser/fields/scalar_field.cc
gd/packet/parser/fields/scalar_field.h
gd/packet/parser/fields/struct_field.cc
gd/packet/parser/fields/struct_field.h
gd/packet/parser/fields/vector_field.cc
gd/packet/parser/fields/vector_field.h
gd/packet/parser/parent_def.cc
gd/packet/parser/struct_def.cc

index c4317e6..545e5dd 100644 (file)
  */
 
 #include "fields/array_field.h"
+
 #include "util.h"
 
 const std::string ArrayField::kFieldType = "ArrayField";
 
-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)
-    ERROR(this) << __func__ << ": Not implemented for element size = " << element_size_;
-  // Make sure the element_size is a multiple of 8.
+ArrayField::ArrayField(std::string name, int element_size, int array_size, ParseLocation loc)
+    : PacketField(name, loc), element_field_(new ScalarField("val", element_size, loc)), element_size_(element_size),
+      array_size_(array_size) {
+  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, 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.
-  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 array_size, ParseLocation loc)
+    : PacketField(name, loc), element_field_(type_def->GetNewField("val", loc)),
+      element_size_(element_field_->GetSize()), array_size_(array_size) {
+  if (!element_size_.empty() && element_size_.bits() % 8 != 0) {
+    ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size_ << ")";
   }
 }
 
@@ -42,16 +43,15 @@ const std::string& ArrayField::GetFieldType() const {
 }
 
 Size ArrayField::GetSize() const {
-  if (element_size_ != -1) {
-    return Size(fixed_size_ * element_size_);
+  if (!element_size_.empty() && !element_size_.has_dynamic()) {
+    return Size(array_size_ * element_size_.bits());
   }
   return Size();
 }
 
 Size ArrayField::GetBuilderSize() const {
-  if (element_size_ != -1) {
-    std::string ret = "(" + std::to_string(fixed_size_) + " * " + std::to_string(element_size_) + ")";
-    return ret;
+  if (!element_size_.empty() && !element_size_.has_dynamic()) {
+    return GetSize();
   } else {
     std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() +
                       "_) { length += elem.size() * 8; } return length; }()";
@@ -60,27 +60,21 @@ Size ArrayField::GetBuilderSize() const {
 }
 
 std::string ArrayField::GetDataType() const {
-  if (type_def_ != nullptr) {
-    return "std::array<" + type_def_->name_ + "," + std::to_string(fixed_size_) + ">";
-  }
-  return "std::array<" + util::GetTypeForSize(element_size_) + "," + std::to_string(fixed_size_) + ">";
+  return "std::array<" + element_field_->GetDataType() + "," + std::to_string(array_size_) + ">";
 }
 
-void ArrayField::GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const {
-  GenBounds(s, start_offset, end_offset, GetSize());
-
-  s << "auto it = begin_it + field_begin;";
-
-  s << GetDataType() << " value;";
-  std::string type = (type_def_ != nullptr) ? type_def_->name_ : util::GetTypeForSize(element_size_);
-  s << GetDataType() << "::iterator ret_it = value.begin();";
-  if (element_size_ != -1) {
-    s << "while (it + sizeof(" << type << ") <= begin_it + field_end && ret_it < value.end()) {";
-    s << "*ret_it = it.extract<" << type << ">();";
+void ArrayField::GenExtractor(std::ostream& s, int num_leading_bits) const {
+  s << GetDataType() << "::iterator ret_it = " << GetName() << "_ptr->begin();";
+  s << "auto " << element_field_->GetName() << "_it = " << GetName() << "_it;";
+  if (!element_size_.empty() && !element_size_.has_dynamic()) {
+    s << "while (" << element_field_->GetName() << "_it.NumBytesRemaining() >= " << element_size_.bytes();
+    s << " && ret_it < " << GetName() << "_ptr->end()) {";
   } else {
-    s << "while (it < begin_it + field_end && ret_it < value.end()) {";
-    s << "it = " << type_def_->name_ << "::Parse(ret_it, it);";
+    s << "while (" << element_field_->GetName() << "_it.NumBytesRemaining() > 0 ";
+    s << " && ret_it < " << GetName() << "_ptr->end()) {";
   }
+  s << element_field_->GetDataType() << "* " << element_field_->GetName() << "_ptr = ret_it;";
+  element_field_->GenExtractor(s, num_leading_bits);
   s << "ret_it++;";
   s << "}";
 }
@@ -90,29 +84,24 @@ void ArrayField::GenGetter(std::ostream& s, Size start_offset, Size end_offset)
   s << " Get" << util::UnderscoreToCamelCase(GetName()) << "() {";
   s << "ASSERT(was_validated_);";
   s << "size_t end_index = size();";
-  s << "auto begin_it = begin();";
+  s << "auto to_bound = begin();";
 
-  GenExtractor(s, start_offset, end_offset);
+  int num_leading_bits = GenBounds(s, start_offset, end_offset);
+  s << GetDataType() << " " << GetName() << "_value;";
+  s << GetDataType() << "* " << GetName() << "_ptr = &" << GetName() << "_value;";
+  GenExtractor(s, num_leading_bits);
 
-  s << "return value;";
+  s << "return " << GetName() << "_value;";
   s << "}\n";
 }
 
 bool ArrayField::GenBuilderParameter(std::ostream& s) const {
-  if (type_def_ != nullptr) {
-    s << "const std::array<" << type_def_->GetTypeName() << "," << fixed_size_ << ">& " << GetName();
-  } else {
-    s << "const std::array<" << util::GetTypeForSize(element_size_) << "," << fixed_size_ << ">& " << GetName();
-  }
+  s << "const std::array<" << element_field_->GetDataType() << "," << array_size_ << ">& " << GetName();
   return true;
 }
 
 bool ArrayField::GenBuilderMember(std::ostream& s) const {
-  if (type_def_ != nullptr) {
-    s << "std::array<" << type_def_->GetTypeName() << "," << fixed_size_ << "> " << GetName();
-  } else {
-    s << "std::array<" << util::GetTypeForSize(element_size_) << "," << fixed_size_ << "> " << GetName();
-  }
+  s << "std::array<" << element_field_->GetDataType() << "," << array_size_ << "> " << GetName();
   return true;
 }
 
@@ -125,20 +114,8 @@ void ArrayField::GenParameterValidator(std::ostream&) const {
 }
 
 void ArrayField::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 if (IsStructArray()) {
-    s << "val.Serialize(i);";
-  } else {
-    s << "insert(val, i, " << element_size_ << ");";
-  }
+  s << "for (const auto& val_ : " << GetName() << "_) {";
+  element_field_->GenInserter(s);
   s << "}\n";
 }
 
@@ -149,15 +126,3 @@ void ArrayField::GenValidator(std::ostream&) const {
   // Other than that there is nothing that arrays need to be validated on other than length so nothing needs to
   // be done here.
 }
-
-bool ArrayField::IsEnumArray() const {
-  return type_def_ != nullptr && type_def_->GetDefinitionType() == TypeDef::Type::ENUM;
-}
-
-bool ArrayField::IsCustomFieldArray() const {
-  return type_def_ != nullptr && type_def_->GetDefinitionType() == TypeDef::Type::CUSTOM;
-}
-
-bool ArrayField::IsStructArray() const {
-  return type_def_ != nullptr && type_def_->GetDefinitionType() == TypeDef::Type::STRUCT;
-}
index 1892f57..362edce 100644 (file)
 
 #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 "fields/all_fields.h"
 #include "parse_location.h"
+#include "type_def.h"
 
 class ArrayField : public PacketField {
  public:
@@ -39,7 +36,7 @@ class ArrayField : public PacketField {
 
   virtual std::string GetDataType() const override;
 
-  virtual void GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const override;
+  virtual void GenExtractor(std::ostream& s, int num_leading_bits) const override;
 
   virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
 
@@ -55,17 +52,11 @@ class ArrayField : public PacketField {
 
   virtual void GenValidator(std::ostream&) const override;
 
-  bool IsEnumArray() const;
-
-  bool IsCustomFieldArray() const;
-
-  bool IsStructArray() const;
-
   const std::string name_;
 
-  const int element_size_{-1};  // in bits
-  const TypeDef* type_def_{nullptr};
+  const PacketField* element_field_{nullptr};
+
+  const Size element_size_{};
 
-  // Fixed size array or dynamic size, size is always in bytes, unless it is count.
-  const int fixed_size_{-1};
+  const int array_size_{-1};
 };
index 564831b..ffcb22c 100644 (file)
@@ -33,7 +33,7 @@ std::string BodyField::GetDataType() const {
   return "BodyType";
 }
 
-void BodyField::GenExtractor(std::ostream&, Size, Size) const {}
+void BodyField::GenExtractor(std::ostream&, int) const {}
 
 void BodyField::GenGetter(std::ostream&, Size, Size) const {}
 
index 3881f99..fabb04c 100644 (file)
@@ -32,7 +32,7 @@ class BodyField : public PacketField {
 
   virtual std::string GetDataType() const override;
 
-  virtual void GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const override;
+  virtual void GenExtractor(std::ostream& s, int num_leading_bits) const override;
 
   virtual void GenGetter(std::ostream&, Size, Size) const override;
 
index a5cea67..8a476a4 100644 (file)
@@ -30,7 +30,7 @@ std::string ChecksumField::GetDataType() const {
   return type_name_;
 }
 
-void ChecksumField::GenExtractor(std::ostream&, Size, Size) const {}
+void ChecksumField::GenExtractor(std::ostream&, int) const {}
 
 void ChecksumField::GenGetter(std::ostream&, Size, Size) const {}
 
index d4c0ad0..9063f63 100644 (file)
@@ -30,7 +30,7 @@ class ChecksumField : public ScalarField {
 
   virtual std::string GetDataType() const override;
 
-  virtual void GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const override;
+  virtual void GenExtractor(std::ostream& s, int) const override;
 
   virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
 
index b90f073..fc21f49 100644 (file)
@@ -34,7 +34,7 @@ std::string ChecksumStartField::GetDataType() const {
   return "There's no type for Checksum Start fields";
 }
 
-void ChecksumStartField::GenExtractor(std::ostream&, Size, Size) const {}
+void ChecksumStartField::GenExtractor(std::ostream&, int) const {}
 
 void ChecksumStartField::GenGetter(std::ostream&, Size, Size) const {}
 
index ef58356..9119f85 100644 (file)
@@ -33,7 +33,7 @@ class ChecksumStartField : public PacketField {
 
   virtual std::string GetDataType() const override;
 
-  virtual void GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const override;
+  virtual void GenExtractor(std::ostream& s, int num_leading_bits) const override;
 
   virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
 
index 962b460..ad13cb9 100644 (file)
@@ -39,21 +39,23 @@ std::string CustomField::GetDataType() const {
   return type_name_;
 }
 
-void CustomField::GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const {
-  GenBounds(s, start_offset, end_offset, Size());
-  s << "auto it = begin_it.Subrange(field_begin, field_end - field_begin);";
-  s << "std::unique_ptr<" << GetDataType() << "> ptr = std::make_unique<" << GetDataType() << ">();";
-  s << GetDataType() << "::Parse(ptr.get(), it);";
+void CustomField::GenExtractor(std::ostream& s, int) const {
+  s << GetName() << "_it = ";
+  s << GetDataType() << "::Parse( " << GetName() << "_ptr, " << GetName() << "_it);";
 }
 
 void CustomField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
   s << "std::unique_ptr<" << GetDataType() << "> Get" << util::UnderscoreToCamelCase(GetName()) << "() const {";
   s << "ASSERT(was_validated_);";
   s << "size_t end_index = size();";
-  s << "auto begin_it = begin();";
+  s << "auto to_bound = begin();";
 
-  GenExtractor(s, start_offset, end_offset);
-  s << "return ptr;";
+  int num_leading_bits = GenBounds(s, start_offset, end_offset);
+  s << "std::unique_ptr<" << GetDataType() << "> " << GetName() << "_value";
+  s << " = std::make_unique<" << GetDataType() << ">();";
+  s << GetDataType() << "* " << GetName() << "_ptr = " << GetName() << "_value.get();";
+  GenExtractor(s, num_leading_bits);
+  s << "return " << GetName() << "_value;";
   s << "}\n";
 }
 
index 86fefd2..04791a1 100644 (file)
@@ -33,7 +33,7 @@ class CustomField : public PacketField {
 
   virtual std::string GetDataType() const override;
 
-  virtual void GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const override;
+  virtual void GenExtractor(std::ostream& s, int num_leading_bits) const override;
 
   virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
 
index 08d3a0e..33d0a1a 100644 (file)
@@ -30,20 +30,21 @@ std::string CustomFieldFixedSize::GetDataType() const {
   return type_name_;
 }
 
-void CustomFieldFixedSize::GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const {
-  int field_size = GetSize().bits();
-
+int CustomFieldFixedSize::GenBounds(std::ostream& s, Size start_offset, Size end_offset) const {
   if (!start_offset.empty()) {
     // Default to start if available.
-    s << "auto it = begin_it + (" << start_offset << ") / 8;";
+    s << "auto " << GetName() << "_it = to_bound + (" << start_offset << ") / 8;";
   } else if (!end_offset.empty()) {
-    Size byte_offset = Size(field_size) + end_offset;
-    s << "auto it = end_it - (" << byte_offset << ") / 8;";
+    Size byte_offset = GetSize() + end_offset;
+    s << "auto " << GetName() << "_it = to_bound (+ to_bound.NumBytesRemaining() - (" << byte_offset << ") / 8);";
   } else {
     ERROR(this) << "Ambiguous offset for field.";
   }
+  return 0;  // num_leading_bits
+}
 
-  s << GetDataType() << " value = it.extract<" << GetDataType() << ">();";
+void CustomFieldFixedSize::GenExtractor(std::ostream& s, int) const {
+  s << "*" << GetName() << "_ptr = " << GetName() << "_it.extract<" << GetDataType() << ">();";
 }
 
 bool CustomFieldFixedSize::HasParameterValidator() const {
index 5a11c0d..92399b2 100644 (file)
@@ -29,7 +29,9 @@ class CustomFieldFixedSize : public ScalarField {
 
   virtual std::string GetDataType() const override;
 
-  virtual void GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const override;
+  virtual int GenBounds(std::ostream& s, Size start_offset, Size end_offset) const override;
+
+  virtual void GenExtractor(std::ostream& s, int num_leading_bits) const override;
 
   virtual bool HasParameterValidator() const override;
 
index 7b0dfa6..2461b8a 100644 (file)
@@ -44,7 +44,7 @@ std::string GroupField::GetDataType() const {
   return "";
 }
 
-void GroupField::GenExtractor(std::ostream&, Size, Size) const {
+void GroupField::GenExtractor(std::ostream&, int) const {
   ERROR(this) << "GenExtractor should never be called.";
 }
 
index 407a37b..6c14695 100644 (file)
@@ -37,7 +37,7 @@ class GroupField : public PacketField {
 
   virtual std::string GetDataType() const override;
 
-  virtual void GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const override;
+  virtual void GenExtractor(std::ostream& s, int num_leading_bits) const override;
 
   virtual void GenGetter(std::ostream&, Size, Size) const override;
 
index 668166f..bb097d1 100644 (file)
@@ -36,11 +36,11 @@ Size PacketField::GetBuilderSize() const {
   return GetSize();
 }
 
-void PacketField::GenBounds(std::ostream& s, Size start_offset, Size end_offset, Size field_size) const {
+int PacketField::GenBounds(std::ostream& s, Size start_offset, Size end_offset) const {
   // In order to find field_begin and field_end, we must have two of the three Sizes.
-  if ((start_offset.empty() && field_size.empty()) || (start_offset.empty() && end_offset.empty()) ||
-      (end_offset.empty() && field_size.empty())) {
-    ERROR(this) << "GenBounds called without enough information. " << start_offset << end_offset << field_size;
+  if ((start_offset.empty() && GetSize().empty()) || (start_offset.empty() && end_offset.empty()) ||
+      (end_offset.empty() && GetSize().empty())) {
+    ERROR(this) << "GenBounds called without enough information. " << start_offset << end_offset << GetSize();
   }
 
   if (start_offset.bits() % 8 != 0 || end_offset.bits() % 8 != 0) {
@@ -50,20 +50,22 @@ void PacketField::GenBounds(std::ostream& s, Size start_offset, Size end_offset,
   if (!start_offset.empty()) {
     s << "size_t field_begin = (" << start_offset << ") / 8;";
   } else {
-    s << "size_t field_begin = end_index - (" << end_offset << " + " << field_size << ") / 8;";
+    s << "size_t field_begin = end_index - (" << end_offset << " + " << GetSize() << ") / 8;";
   }
 
   if (!end_offset.empty()) {
     s << "size_t field_end = end_index - (" << end_offset << ") / 8;";
     // If the field has a known size, use the minimum for the end
-    if (!field_size.empty()) {
-      s << "size_t field_sized_end = field_begin + (" << field_size << ") / 8;";
+    if (!GetSize().empty()) {
+      s << "size_t field_sized_end = field_begin + (" << GetSize() << ") / 8;";
       s << "if (field_sized_end < field_end) { field_end = field_sized_end; }";
     }
   } else {
-    s << "size_t field_end = field_begin + (" << field_size << ") / 8;";
+    s << "size_t field_end = field_begin + (" << GetSize() << ") / 8;";
     s << "if (field_end > end_index) { field_end = end_index; }";
   }
+  s << "auto " << name_ << "_it = to_bound.Subrange(field_begin, field_end - field_begin); ";
+  return 0;  // num_leading_bits
 }
 
 bool PacketField::GenBuilderMember(std::ostream& s) const {
index 3565dfb..8adb7f5 100644 (file)
@@ -44,11 +44,11 @@ class PacketField : public Loggable {
   // variables.
   virtual std::string GetDataType() const = 0;
 
-  // Given an iterator it, extract the type.
-  virtual void GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const = 0;
+  // Given an iterator {name}_it, extract the type.
+  virtual void GenExtractor(std::ostream& s, int num_leading_bits) const = 0;
 
-  // Calculate field_begin and field_end using the given offsets and size.
-  virtual void GenBounds(std::ostream& s, Size start_offset, Size end_offset, Size field_size) const;
+  // Calculate field_begin and field_end using the given offsets and size, return the number of leading bits
+  virtual int GenBounds(std::ostream& s, Size start_offset, Size end_offset) const;
 
   // Get parser getter definition. Start_offset points to the first bit of the
   // field. end_offset is the first bit after the field. If an offset is empty
index 4f81bd6..2ca3958 100644 (file)
@@ -54,7 +54,7 @@ std::string PayloadField::GetDataType() const {
   return "PacketView";
 }
 
-void PayloadField::GenExtractor(std::ostream&, Size, Size) const {
+void PayloadField::GenExtractor(std::ostream&, int) const {
   ERROR(this) << __func__ << " should never be called. ";
 }
 
@@ -62,14 +62,16 @@ void PayloadField::GenGetter(std::ostream& s, Size start_offset, Size end_offset
   s << "PacketView<kLittleEndian> GetPayload() const {";
   s << "ASSERT(was_validated_);";
   s << "size_t end_index = size();";
-  GenBounds(s, start_offset, end_offset, GetSize());
+  s << "auto to_bound = begin();";
+  GenBounds(s, start_offset, end_offset);
   s << "return GetLittleEndianSubview(field_begin, field_end);";
   s << "}\n\n";
 
   s << "PacketView<!kLittleEndian> GetPayloadBigEndian() const {";
   s << "ASSERT(was_validated_);";
   s << "size_t end_index = size();";
-  GenBounds(s, start_offset, end_offset, GetSize());
+  s << "auto to_bound = begin();";
+  GenBounds(s, start_offset, end_offset);
   s << "return GetBigEndianSubview(field_begin, field_end);";
   s << "}\n";
 }
index db65e89..408fb46 100644 (file)
@@ -34,7 +34,7 @@ class PayloadField : public PacketField {
 
   virtual std::string GetDataType() const override;
 
-  virtual void GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const override;
+  virtual void GenExtractor(std::ostream& s, int num_leading_bits) const override;
 
   virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
 
index 51f9d84..7d3a974 100644 (file)
@@ -36,7 +36,7 @@ std::string ReservedField::GetDataType() const {
   return util::GetTypeForSize(size_);
 }
 
-void ReservedField::GenExtractor(std::ostream&, Size, Size) const {}
+void ReservedField::GenExtractor(std::ostream&, int) const {}
 
 void ReservedField::GenGetter(std::ostream&, Size, Size) const {
   // There is no Getter for a reserved field
index 6c5e160..177b9d1 100644 (file)
@@ -31,7 +31,7 @@ class ReservedField : public PacketField {
 
   virtual std::string GetDataType() const override;
 
-  virtual void GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const override;
+  virtual void GenExtractor(std::ostream& s, int num_leading_bits) const override;
 
   virtual void GenGetter(std::ostream&, Size, Size) const override;
 
index bd9ee1b..347a073 100644 (file)
@@ -47,58 +47,56 @@ int GetShiftBits(int i) {
   }
 }
 
-void ScalarField::GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const {
+int ScalarField::GenBounds(std::ostream& s, Size start_offset, Size end_offset) const {
   int num_leading_bits = 0;
-  int field_size = GetSize().bits();
 
   if (!start_offset.empty()) {
     // Default to start if available.
     num_leading_bits = start_offset.bits() % 8;
-    s << "auto it = begin_it + (" << start_offset << ") / 8;";
+    s << "auto " << GetName() << "_it = to_bound + (" << start_offset << ") / 8;";
   } else if (!end_offset.empty()) {
-    num_leading_bits = GetShiftBits(end_offset.bits() + field_size);
-    Size byte_offset = Size(num_leading_bits + field_size) + end_offset;
-    s << "auto it = end_it - (" << byte_offset << ") / 8;";
+    num_leading_bits = GetShiftBits(end_offset.bits() + GetSize().bits());
+    Size byte_offset = Size(num_leading_bits + GetSize().bits()) + end_offset;
+    s << "auto " << GetName() << "_it = to_bound + (to_bound.NumBytesRemaining() - (" << byte_offset << ") / 8);";
   } else {
     ERROR(this) << "Ambiguous offset for field.";
   }
+  return num_leading_bits;
+}
 
+void ScalarField::GenExtractor(std::ostream& s, int num_leading_bits) const {
   // Extract the correct number of bytes. The return type could be different
   // from the extract type if an earlier field causes the beginning of the
   // current field to start in the middle of a byte.
-  std::string extract_type = util::GetTypeForSize(field_size + num_leading_bits);
-  s << "auto extracted_value = it.extract<" << extract_type << ">();";
+  std::string extract_type = util::GetTypeForSize(GetSize().bits() + num_leading_bits);
+  s << "auto extracted_value = " << GetName() << "_it.extract<" << extract_type << ">();";
 
   // Right shift the result to remove leading bits.
   if (num_leading_bits != 0) {
     s << "extracted_value >>= " << num_leading_bits << ";";
   }
-
   // Mask the result if necessary.
-  if (util::RoundSizeUp(field_size) != field_size) {
+  if (util::RoundSizeUp(GetSize().bits()) != GetSize().bits()) {
     uint64_t mask = 0;
-    for (int i = 0; i < field_size; i++) {
+    for (int i = 0; i < GetSize().bits(); i++) {
       mask <<= 1;
       mask |= 1;
     }
     s << "extracted_value &= 0x" << std::hex << mask << std::dec << ";";
   }
-  s << GetDataType() << " value = static_cast<" << GetDataType() << ">(extracted_value);";
+  s << "*" << GetName() << "_ptr = static_cast<" << GetDataType() << ">(extracted_value);";
 }
 
 void ScalarField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
   s << GetDataType();
   s << " Get" << util::UnderscoreToCamelCase(GetName()) << "() const {";
   s << "ASSERT(was_validated_);";
-
-  if (!start_offset.empty()) {
-    s << "auto begin_it = begin();";
-  } else {
-    s << "auto end_it = end();";
-  }
-  GenExtractor(s, start_offset, end_offset);
-  s << "\n";
-  s << "return value;";
+  s << "auto to_bound = begin();";
+  int num_leading_bits = GenBounds(s, start_offset, end_offset);
+  s << GetDataType() << " " << GetName() << "_value;";
+  s << GetDataType() << "* " << GetName() << "_ptr = &" << GetName() << "_value;";
+  GenExtractor(s, num_leading_bits);
+  s << "return " << GetName() << "_value;";
   s << "}";
 }
 
index b51c43c..290ad3f 100644 (file)
@@ -31,7 +31,9 @@ class ScalarField : public PacketField {
 
   virtual std::string GetDataType() const override;
 
-  virtual void GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const override;
+  virtual int GenBounds(std::ostream& s, Size start_offset, Size end_offset) const override;
+
+  virtual void GenExtractor(std::ostream& s, int num_leading_bits) const override;
 
   virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
 
@@ -46,5 +48,5 @@ class ScalarField : public PacketField {
   virtual void GenValidator(std::ostream&) const override;
 
  private:
-  int size_;
+  const int size_;
 };
index 107cb3b..b7ec66f 100644 (file)
@@ -30,46 +30,26 @@ Size StructField::GetSize() const {
   return size_;
 }
 
-Size StructField::GetBuilderSize() const {
-  if (size_ != -1) {
-    return size_;
-  } else {
-    std::string ret = "(" + GetName() + "_.size() * 8) ";
-    return ret;
-  }
-}
-
 std::string StructField::GetDataType() const {
   return type_name_;
 }
 
-void StructField::GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const {
-  if (size_ != -1) {
-    GenBounds(s, start_offset, end_offset, Size(size_));
-  } else {
-    GenBounds(s, start_offset, end_offset, Size());
-  }
-  s << "auto it = begin_it.Subrange(field_begin, field_end - field_begin); ";
-  s << "std::unique_ptr<" << GetDataType() << "> one = std::make_unique<" << GetDataType() << ">();";
-  s << GetDataType() << "::Parse(one.get(), it);";
+void StructField::GenExtractor(std::ostream& s, int) const {
+  s << GetName() << "_it = ";
+  s << GetDataType() << "::Parse(" << GetName() << "_ptr, " << GetName() << "_it);";
 }
 
 void StructField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
-  if (size_ != -1) {
-    s << GetDataType() << " Get" << util::UnderscoreToCamelCase(GetName()) << "() const {";
-  } else {
-    s << "std::unique_ptr<" << GetDataType() << "> Get" << util::UnderscoreToCamelCase(GetName()) << "() const {";
-  }
+  s << GetDataType() << " Get" << util::UnderscoreToCamelCase(GetName()) << "() const {";
   s << "ASSERT(was_validated_);";
   s << "size_t end_index = size();";
-  s << "auto begin_it = begin();";
-  GenExtractor(s, start_offset, end_offset);
+  s << "auto to_bound = begin();";
+  int num_leading_bits = GenBounds(s, start_offset, end_offset);
+  s << GetDataType() << " " << GetName() << "_value;";
+  s << GetDataType() << "* " << GetName() << "_ptr = &" << GetName() << "_value;";
+  GenExtractor(s, num_leading_bits);
 
-  if (size_ != -1) {
-    s << "return *one;";
-  } else {
-    s << "return one;";
-  }
+  s << "return " << GetName() << "_value;";
   s << "}\n";
 }
 
index 3577b1d..62719bd 100644 (file)
@@ -29,11 +29,9 @@ class StructField : public PacketField {
 
   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 GenExtractor(std::ostream& s, int num_leading_bits) const override;
 
   virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
 
@@ -51,5 +49,5 @@ class StructField : public PacketField {
   std::string type_name_;
 
  public:
-  const int size_{-1};
+  const Size size_{};
 };
index 8e12757..b58d406 100644 (file)
  */
 
 #include "fields/vector_field.h"
+
+#include "fields/count_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.
+    : PacketField(name, loc), element_field_(new ScalarField("val", element_size, 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;
   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_ << ")";
+    : PacketField(name, loc), element_field_(type_def->GetNewField("val", loc)),
+      element_size_(element_field_->GetSize()), size_modifier_(size_modifier) {
+  if (!element_size_.empty() && element_size_.bits() % 8 != 0) {
+    ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size_ << ")";
   }
 }
 
@@ -54,28 +56,18 @@ Size VectorField::GetSize() const {
     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() || IsStructArray()) {
-    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 elements have a fixed size
+  if (!element_size_.empty() && !element_size_.has_dynamic()) {
+    return "(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "() * " +
+           std::to_string(element_size_.bits()) + ")";
   }
 
-  // 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 VectorField::GetBuilderSize() const {
-  if (element_size_ != -1) {
-    std::string ret = "(" + GetName() + "_.size() * " + std::to_string(element_size_) + ")";
+  if (!element_size_.empty() && !element_size_.has_dynamic()) {
+    std::string ret = "(" + GetName() + "_.size() * " + std::to_string(element_size_.bits()) + ")";
     return ret;
   } else {
     std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() +
@@ -85,30 +77,22 @@ Size VectorField::GetBuilderSize() const {
 }
 
 std::string VectorField::GetDataType() const {
-  if (type_def_ != nullptr) {
-    return "std::vector<" + type_def_->name_ + ">";
-  }
-  return "std::vector<" + util::GetTypeForSize(element_size_) + ">";
+  return "std::vector<" + element_field_->GetDataType() + ">";
 }
 
-void VectorField::GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const {
-  GenBounds(s, start_offset, end_offset, GetSize());
-
-  s << "auto it = begin_it.Subrange(field_begin, field_end - field_begin);";
-
-  s << GetDataType() << " ret;";
-  if (element_size_ != -1) {
-    std::string type = (type_def_ != nullptr) ? type_def_->name_ : util::GetTypeForSize(element_size_);
-    s << "while (it.NumBytesRemaining() >= sizeof(" << type << ")) {";
-    s << "ret.push_back(it.extract<" << type << ">());";
-    s << "}";
+void VectorField::GenExtractor(std::ostream& s, int num_leading_bits) const {
+  s << "auto " << element_field_->GetName() << "_it = " << GetName() << "_it;";
+  if (!element_size_.empty() && !element_size_.has_dynamic()) {
+    s << "while (" << element_field_->GetName() << "_it.NumBytesRemaining() >= " << element_size_.bytes() << ") {";
   } else {
-    s << "while (it.NumBytesRemaining() > 0) {";
-    s << type_def_->name_ << " instance;";
-    s << "it = " << type_def_->name_ << "::Parse(&instance, it);";
-    s << "ret.push_back(instance);";
-    s << "}";
+    s << "while (" << element_field_->GetName() << "_it.NumBytesRemaining() > 0) {";
   }
+  s << element_field_->GetDataType() << " " << element_field_->GetName() << "_value;";
+  s << element_field_->GetDataType() << "* " << element_field_->GetName() << "_ptr = &" << element_field_->GetName()
+    << "_value;";
+  element_field_->GenExtractor(s, num_leading_bits);
+  s << GetName() << "_ptr->push_back(" << element_field_->GetName() << "_value);";
+  s << "}";
 }
 
 void VectorField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
@@ -116,29 +100,24 @@ void VectorField::GenGetter(std::ostream& s, Size start_offset, Size end_offset)
   s << " Get" << util::UnderscoreToCamelCase(GetName()) << "() {";
   s << "ASSERT(was_validated_);";
   s << "size_t end_index = size();";
-  s << "auto begin_it = begin();";
+  s << "auto to_bound = begin();";
 
-  GenExtractor(s, start_offset, end_offset);
+  int num_leading_bits = GenBounds(s, start_offset, end_offset);
+  s << GetDataType() << " " << GetName() << "_value;";
+  s << GetDataType() << "* " << GetName() << "_ptr = &" << GetName() << "_value;";
+  GenExtractor(s, num_leading_bits);
 
-  s << "return ret;";
+  s << "return " << GetName() << "_value;";
   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();
-  }
+  s << "const std::vector<" << element_field_->GetDataType() << ">& " << GetName();
   return true;
 }
 
 bool VectorField::GenBuilderMember(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();
-  }
+  s << "const std::vector<" << element_field_->GetDataType() << "> " << GetName();
   return true;
 }
 
@@ -155,20 +134,8 @@ void VectorField::GenParameterValidator(std::ostream&) const {
 }
 
 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 if (IsStructArray()) {
-    s << "val.Serialize(i);";
-  } else {
-    s << "insert(val, i, " << element_size_ << ");";
-  }
+  s << "for (const auto& val_ : " << GetName() << "_) {";
+  element_field_->GenInserter(s);
   s << "}\n";
 }
 
@@ -180,18 +147,6 @@ void VectorField::GenValidator(std::ostream&) const {
   // 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;
-}
-
-bool VectorField::IsStructArray() const {
-  return type_def_ != nullptr && type_def_->GetDefinitionType() == TypeDef::Type::STRUCT;
-}
-
 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."
index b7c0dfd..56fbfa9 100644 (file)
 
 #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"
+#include "type_def.h"
 
 class VectorField : public PacketField {
  public:
@@ -39,7 +37,7 @@ class VectorField : public PacketField {
 
   virtual std::string GetDataType() const override;
 
-  virtual void GenExtractor(std::ostream& s, Size start_offset, Size end_offset) const override;
+  virtual void GenExtractor(std::ostream& s, int num_leading_bits) const override;
 
   virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
 
@@ -55,20 +53,15 @@ class VectorField : public PacketField {
 
   virtual void GenValidator(std::ostream&) const override;
 
-  bool IsEnumArray() const;
-
-  bool IsCustomFieldArray() const;
-
-  bool IsStructArray() 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};
+  const PacketField* element_field_{nullptr};
+
+  const Size element_size_{};
 
   // Fixed size array or dynamic size, size is always in bytes, unless it is count.
   const SizeField* size_field_{nullptr};
index ebf40cf..8aa6e5a 100644 (file)
@@ -337,12 +337,12 @@ void ParentDef::GenSerialize(std::ostream& s) const {
         const auto& vector_name = field_name + "_";
         const VectorField* vector = (VectorField*)sized_field;
         s << "size_t " << vector_name + "bytes =  0;";
-        if (vector->element_size_ == -1) {
+        if (vector->element_size_.empty()) {
           s << "for (auto elem : " << vector_name << ") {";
           s << vector_name + "bytes += elem.size(); }";
         } else {
           s << vector_name + "bytes = ";
-          s << vector_name << ".size() * (" << vector->element_size_ << " / 8);";
+          s << vector_name << ".size() * ((" << vector->element_size_ << ") / 8);";
         }
         s << "ASSERT(" << vector_name + "bytes < (1 << " << field->GetSize().bits() << "));";
         s << "insert(" << vector_name << "bytes";
index fbf3481..fc7842a 100644 (file)
@@ -44,7 +44,7 @@ void StructDef::GenParse(std::ostream& s) const {
     iterator = "Iterator<!kLittleEndian>";
   }
   s << "static " << iterator << " Parse(" << name_ << "* to_return, " << iterator << " struct_it) {";
-  s << "auto begin_it = struct_it;";
+  s << "auto to_bound = struct_it;";
   s << "size_t end_index = struct_it.NumBytesRemaining();";
   s << "if (end_index < " << GetSize().bytes() << ") { return struct_it.Subrange(0,0);}";
   Size field_offset = Size(0);
@@ -55,8 +55,9 @@ void StructDef::GenParse(std::ostream& s) const {
         field->GetFieldType() != ChecksumStartField::kFieldType && field->GetFieldType() != ChecksumField::kFieldType &&
         field->GetFieldType() != CountField::kFieldType) {
       s << "{";
-      field->GenExtractor(s, field_offset, next_field_offset);
-      s << "to_return->" << field->GetName() << "_ = value;";
+      int num_leading_bits = field->GenBounds(s, field_offset, next_field_offset);
+      s << "auto " << field->GetName() << "_ptr = &to_return->" << field->GetName() << "_;";
+      field->GenExtractor(s, num_leading_bits);
       s << "}";
     }
     field_offset = next_field_offset;