1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "fields/vector_field.h"
18 
19 #include "fields/count_field.h"
20 #include "fields/custom_field.h"
21 #include "util.h"
22 
23 const std::string VectorField::kFieldType = "VectorField";
24 
VectorField(std::string name,int element_size,std::string size_modifier,ParseLocation loc)25 VectorField::VectorField(std::string name, int element_size, std::string size_modifier,
26                          ParseLocation loc)
27     : PacketField(name, loc),
28       element_field_(new ScalarField("val", element_size, loc)),
29       element_size_(element_size),
30       size_modifier_(size_modifier) {
31   if (element_size > 64 || element_size < 0) {
32     ERROR(this) << __func__ << ": Not implemented for element size = " << element_size;
33   }
34   if (element_size % 8 != 0) {
35     ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size
36                 << ")";
37   }
38 }
39 
VectorField(std::string name,TypeDef * type_def,std::string size_modifier,ParseLocation loc)40 VectorField::VectorField(std::string name, TypeDef* type_def, std::string size_modifier,
41                          ParseLocation loc)
42     : PacketField(name, loc),
43       element_field_(type_def->GetNewField("val", loc)),
44       element_size_(element_field_->GetSize()),
45       size_modifier_(size_modifier) {
46   if (!element_size_.empty() && element_size_.bits() % 8 != 0) {
47     ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size_
48                 << ")";
49   }
50 }
51 
GetFieldType() const52 const std::string& VectorField::GetFieldType() const { return VectorField::kFieldType; }
53 
GetSize() const54 Size VectorField::GetSize() const {
55   // If there is no size field, then it is of unknown size.
56   if (size_field_ == nullptr) {
57     return Size();
58   }
59 
60   // size_field_ is of type SIZE
61   if (size_field_->GetFieldType() == SizeField::kFieldType) {
62     std::string ret = "(static_cast<size_t>(Get" +
63                       util::UnderscoreToCamelCase(size_field_->GetName()) + "()) * 8)";
64     if (!size_modifier_.empty()) {
65       ret += "+ (" + size_modifier_.substr(1) + " * 8)";
66     }
67     return ret;
68   }
69 
70   // size_field_ is of type COUNT and elements have a fixed size
71   if (!element_size_.empty() && !element_size_.has_dynamic()) {
72     return "(static_cast<size_t>(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) +
73            "()) * " + std::to_string(element_size_.bits()) + ")";
74   }
75 
76   return Size();
77 }
78 
GetBuilderSize() const79 Size VectorField::GetBuilderSize() const {
80   if (!element_size_.empty() && !element_size_.has_dynamic()) {
81     std::string ret = "(static_cast<size_t>(" + GetName() + "_.size()) * " +
82                       std::to_string(element_size_.bits()) + ")";
83     return ret;
84   } else if (element_field_->BuilderParameterMustBeMoved()) {
85     std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() +
86                       "_) { length += elem->size() * 8; } return length; }()";
87     return ret;
88   } else {
89     std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() +
90                       "_) { length += elem.size() * 8; } return length; }()";
91     return ret;
92   }
93 }
94 
GetStructSize() const95 Size VectorField::GetStructSize() const {
96   // If there is no size field, then it is of unknown size.
97   if (size_field_ == nullptr) {
98     return Size();
99   }
100 
101   // size_field_ is of type SIZE
102   if (size_field_->GetFieldType() == SizeField::kFieldType) {
103     std::string ret =
104             "(static_cast<size_t>(to_fill->" + size_field_->GetName() + "_extracted_) * 8)";
105     if (!size_modifier_.empty()) {
106       ret += "- (" + size_modifier_.substr(1) + " * 8)";
107     }
108     return ret;
109   }
110 
111   // size_field_ is of type COUNT and elements have a fixed size
112   if (!element_size_.empty() && !element_size_.has_dynamic()) {
113     return "(static_cast<size_t>(to_fill->" + size_field_->GetName() + "_extracted_) * " +
114            std::to_string(element_size_.bits()) + ")";
115   }
116 
117   return Size();
118 }
119 
GetDataType() const120 std::string VectorField::GetDataType() const {
121   return "std::vector<" + element_field_->GetDataType() + ">";
122 }
123 
GenExtractor(std::ostream & s,int num_leading_bits,bool for_struct) const124 void VectorField::GenExtractor(std::ostream& s, int num_leading_bits, bool for_struct) const {
125   s << "auto " << element_field_->GetName() << "_it = " << GetName() << "_it;";
126   if (size_field_ != nullptr && size_field_->GetFieldType() == CountField::kFieldType) {
127     s << "size_t " << element_field_->GetName() << "_count = ";
128     if (for_struct) {
129       s << "to_fill->" << size_field_->GetName() << "_extracted_;";
130     } else {
131       s << "Get" << util::UnderscoreToCamelCase(size_field_->GetName()) << "();";
132     }
133   }
134   s << "while (";
135   if (size_field_ != nullptr && size_field_->GetFieldType() == CountField::kFieldType) {
136     s << "(" << element_field_->GetName() << "_count > 0) && ";
137     s << "(" << element_field_->GetName() << "_count-- > 0) && ";
138   }
139   if (!element_size_.empty()) {
140     s << element_field_->GetName() << "_it.NumBytesRemaining() >= " << element_size_.bytes()
141       << ") {";
142   } else {
143     s << element_field_->GetName() << "_it.NumBytesRemaining() > 0) {";
144   }
145   if (element_field_->BuilderParameterMustBeMoved()) {
146     s << element_field_->GetDataType() << " " << element_field_->GetName() << "_ptr;";
147   } else {
148     s << element_field_->GetDataType() << " " << element_field_->GetName() << "_value;";
149     s << element_field_->GetDataType() << "* " << element_field_->GetName() << "_ptr = &"
150       << element_field_->GetName() << "_value;";
151   }
152   element_field_->GenExtractor(s, num_leading_bits, for_struct);
153   s << "if (" << element_field_->GetName() << "_ptr != nullptr) { ";
154   if (element_field_->BuilderParameterMustBeMoved()) {
155     s << GetName() << "_ptr->push_back(std::move(" << element_field_->GetName() << "_ptr));";
156   } else {
157     s << GetName() << "_ptr->push_back(" << element_field_->GetName() << "_value);";
158   }
159   s << "}";
160   s << "}";
161 }
162 
GetGetterFunctionName() const163 std::string VectorField::GetGetterFunctionName() const {
164   std::stringstream ss;
165   ss << "Get" << util::UnderscoreToCamelCase(GetName());
166   return ss.str();
167 }
168 
GenGetter(std::ostream & s,Size start_offset,Size end_offset) const169 void VectorField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
170   s << GetDataType() << " " << GetGetterFunctionName() << "() const {";
171   s << "ASSERT(was_validated_);";
172   s << "size_t end_index = size();";
173   s << "auto to_bound = begin();";
174 
175   int num_leading_bits = GenBounds(s, start_offset, end_offset, GetSize());
176   s << GetDataType() << " " << GetName() << "_value{};";
177   s << GetDataType() << "* " << GetName() << "_ptr = &" << GetName() << "_value;";
178   GenExtractor(s, num_leading_bits, false);
179 
180   s << "return " << GetName() << "_value;";
181   s << "}\n";
182 }
183 
GetBuilderParameterType() const184 std::string VectorField::GetBuilderParameterType() const {
185   std::stringstream ss;
186   if (element_field_->BuilderParameterMustBeMoved()) {
187     ss << "std::vector<" << element_field_->GetDataType() << ">";
188   } else {
189     ss << "const std::vector<" << element_field_->GetDataType() << ">&";
190   }
191   return ss.str();
192 }
193 
BuilderParameterMustBeMoved() const194 bool VectorField::BuilderParameterMustBeMoved() const {
195   return element_field_->BuilderParameterMustBeMoved();
196 }
197 
GenBuilderMember(std::ostream & s) const198 bool VectorField::GenBuilderMember(std::ostream& s) const {
199   s << "std::vector<" << element_field_->GetDataType() << "> " << GetName();
200   return true;
201 }
202 
HasParameterValidator() const203 bool VectorField::HasParameterValidator() const {
204   // Does not have parameter validator yet.
205   // TODO: See comment in GenParameterValidator
206   return false;
207 }
208 
GenParameterValidator(std::ostream &) const209 void VectorField::GenParameterValidator(std::ostream&) const {
210   // No Parameter validator if its dynamically size.
211   // TODO: Maybe add a validator to ensure that the size isn't larger than what the size field can
212   // hold.
213   return;
214 }
215 
GenInserter(std::ostream & s) const216 void VectorField::GenInserter(std::ostream& s) const {
217   s << "for (const auto& val_ : " << GetName() << "_) {";
218   element_field_->GenInserter(s);
219   s << "}\n";
220 }
221 
GenValidator(std::ostream &) const222 void VectorField::GenValidator(std::ostream&) const {
223   // NOTE: We could check if the element size divides cleanly into the array size, but we decided to
224   // forgo that in favor of just returning as many elements as possible in a best effort style.
225   //
226   // Other than that there is nothing that arrays need to be validated on other than length so
227   // nothing needs to be done here.
228 }
229 
SetSizeField(const SizeField * size_field)230 void VectorField::SetSizeField(const SizeField* size_field) {
231   if (size_field->GetFieldType() == CountField::kFieldType && !size_modifier_.empty()) {
232     ERROR(this, size_field) << "Can not use count field to describe array with a size modifier."
233                             << " Use size instead";
234   }
235 
236   size_field_ = size_field;
237 }
238 
GetSizeModifier() const239 const std::string& VectorField::GetSizeModifier() const { return size_modifier_; }
240 
IsContainerField() const241 bool VectorField::IsContainerField() const { return true; }
242 
GetElementField() const243 const PacketField* VectorField::GetElementField() const { return element_field_; }
244 
GenStringRepresentation(std::ostream & s,std::string accessor) const245 void VectorField::GenStringRepresentation(std::ostream& s, std::string accessor) const {
246   s << "\"VECTOR[\";";
247 
248   std::string arr_idx = "arridx_" + accessor;
249   std::string vec_size = accessor + ".size()";
250   s << "for (size_t index = 0; index < " << vec_size << "; index++) {";
251   std::string element_accessor = "(" + accessor + "[index])";
252   s << "ss << ((index == 0) ? \"\" : \", \") << ";
253 
254   if (element_field_->GetFieldType() == CustomField::kFieldType) {
255     s << element_accessor << ".ToString()";
256   } else {
257     element_field_->GenStringRepresentation(s, element_accessor);
258   }
259 
260   s << ";}";
261   s << "ss << \"]\"";
262 }
263