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, ParseLocation loc)
26 : PacketField(name, loc), element_field_(new ScalarField("val", element_size, loc)), element_size_(element_size),
27 size_modifier_(size_modifier) {
28 if (element_size > 64 || element_size < 0)
29 ERROR(this) << __func__ << ": Not implemented for element size = " << element_size;
30 if (element_size % 8 != 0) {
31 ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size << ")";
32 }
33 }
34
VectorField(std::string name,TypeDef * type_def,std::string size_modifier,ParseLocation loc)35 VectorField::VectorField(std::string name, TypeDef* type_def, std::string size_modifier, ParseLocation loc)
36 : PacketField(name, loc), element_field_(type_def->GetNewField("val", loc)),
37 element_size_(element_field_->GetSize()), size_modifier_(size_modifier) {
38 if (!element_size_.empty() && element_size_.bits() % 8 != 0) {
39 ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size_ << ")";
40 }
41 }
42
GetFieldType() const43 const std::string& VectorField::GetFieldType() const {
44 return VectorField::kFieldType;
45 }
46
GetSize() const47 Size VectorField::GetSize() const {
48 // If there is no size field, then it is of unknown size.
49 if (size_field_ == nullptr) {
50 return Size();
51 }
52
53 // size_field_ is of type SIZE
54 if (size_field_->GetFieldType() == SizeField::kFieldType) {
55 std::string ret = "(static_cast<size_t>(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "()) * 8)";
56 if (!size_modifier_.empty()) ret += "+ (" + size_modifier_.substr(1) + " * 8)";
57 return ret;
58 }
59
60 // size_field_ is of type COUNT and elements have a fixed size
61 if (!element_size_.empty() && !element_size_.has_dynamic()) {
62 return "(static_cast<size_t>(Get" + util::UnderscoreToCamelCase(size_field_->GetName()) + "()) * " +
63 std::to_string(element_size_.bits()) + ")";
64 }
65
66 return Size();
67 }
68
GetBuilderSize() const69 Size VectorField::GetBuilderSize() const {
70 if (!element_size_.empty() && !element_size_.has_dynamic()) {
71 std::string ret = "(static_cast<size_t>(" + GetName() + "_.size()) * " + std::to_string(element_size_.bits()) + ")";
72 return ret;
73 } else if (element_field_->BuilderParameterMustBeMoved()) {
74 std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() +
75 "_) { length += elem->size() * 8; } return length; }()";
76 return ret;
77 } else {
78 std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() +
79 "_) { length += elem.size() * 8; } return length; }()";
80 return ret;
81 }
82 }
83
GetStructSize() const84 Size VectorField::GetStructSize() const {
85 // If there is no size field, then it is of unknown size.
86 if (size_field_ == nullptr) {
87 return Size();
88 }
89
90 // size_field_ is of type SIZE
91 if (size_field_->GetFieldType() == SizeField::kFieldType) {
92 std::string ret = "(static_cast<size_t>(to_fill->" + size_field_->GetName() + "_extracted_) * 8)";
93 if (!size_modifier_.empty()) ret += "- (" + size_modifier_.substr(1) + " * 8)";
94 return ret;
95 }
96
97 // size_field_ is of type COUNT and elements have a fixed size
98 if (!element_size_.empty() && !element_size_.has_dynamic()) {
99 return "(static_cast<size_t>(to_fill->" + size_field_->GetName() + "_extracted_) * " +
100 std::to_string(element_size_.bits()) + ")";
101 }
102
103 return Size();
104 }
105
GetDataType() const106 std::string VectorField::GetDataType() const {
107 return "std::vector<" + element_field_->GetDataType() + ">";
108 }
109
GenExtractor(std::ostream & s,int num_leading_bits,bool for_struct) const110 void VectorField::GenExtractor(std::ostream& s, int num_leading_bits, bool for_struct) const {
111 s << "auto " << element_field_->GetName() << "_it = " << GetName() << "_it;";
112 if (size_field_ != nullptr && size_field_->GetFieldType() == CountField::kFieldType) {
113 s << "size_t " << element_field_->GetName() << "_count = ";
114 if (for_struct) {
115 s << "to_fill->" << size_field_->GetName() << "_extracted_;";
116 } else {
117 s << "Get" << util::UnderscoreToCamelCase(size_field_->GetName()) << "();";
118 }
119 }
120 s << "while (";
121 if (size_field_ != nullptr && size_field_->GetFieldType() == CountField::kFieldType) {
122 s << "(" << element_field_->GetName() << "_count > 0) && ";
123 s << "(" << element_field_->GetName() << "_count-- > 0) && ";
124 }
125 if (!element_size_.empty()) {
126 s << element_field_->GetName() << "_it.NumBytesRemaining() >= " << element_size_.bytes() << ") {";
127 } else {
128 s << element_field_->GetName() << "_it.NumBytesRemaining() > 0) {";
129 }
130 if (element_field_->BuilderParameterMustBeMoved()) {
131 s << element_field_->GetDataType() << " " << element_field_->GetName() << "_ptr;";
132 } else {
133 s << element_field_->GetDataType() << " " << element_field_->GetName() << "_value;";
134 s << element_field_->GetDataType() << "* " << element_field_->GetName() << "_ptr = &" << element_field_->GetName()
135 << "_value;";
136 }
137 element_field_->GenExtractor(s, num_leading_bits, for_struct);
138 s << "if (" << element_field_->GetName() << "_ptr != nullptr) { ";
139 if (element_field_->BuilderParameterMustBeMoved()) {
140 s << GetName() << "_ptr->push_back(std::move(" << element_field_->GetName() << "_ptr));";
141 } else {
142 s << GetName() << "_ptr->push_back(" << element_field_->GetName() << "_value);";
143 }
144 s << "}";
145 s << "}";
146 }
147
GetGetterFunctionName() const148 std::string VectorField::GetGetterFunctionName() const {
149 std::stringstream ss;
150 ss << "Get" << util::UnderscoreToCamelCase(GetName());
151 return ss.str();
152 }
153
GenGetter(std::ostream & s,Size start_offset,Size end_offset) const154 void VectorField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
155 s << GetDataType() << " " << GetGetterFunctionName() << "() const {";
156 s << "ASSERT(was_validated_);";
157 s << "size_t end_index = size();";
158 s << "auto to_bound = begin();";
159
160 int num_leading_bits = GenBounds(s, start_offset, end_offset, GetSize());
161 s << GetDataType() << " " << GetName() << "_value{};";
162 s << GetDataType() << "* " << GetName() << "_ptr = &" << GetName() << "_value;";
163 GenExtractor(s, num_leading_bits, false);
164
165 s << "return " << GetName() << "_value;";
166 s << "}\n";
167 }
168
GetBuilderParameterType() const169 std::string VectorField::GetBuilderParameterType() const {
170 std::stringstream ss;
171 if (element_field_->BuilderParameterMustBeMoved()) {
172 ss << "std::vector<" << element_field_->GetDataType() << ">";
173 } else {
174 ss << "const std::vector<" << element_field_->GetDataType() << ">&";
175 }
176 return ss.str();
177 }
178
BuilderParameterMustBeMoved() const179 bool VectorField::BuilderParameterMustBeMoved() const {
180 return element_field_->BuilderParameterMustBeMoved();
181 }
182
GenBuilderMember(std::ostream & s) const183 bool VectorField::GenBuilderMember(std::ostream& s) const {
184 s << "std::vector<" << element_field_->GetDataType() << "> " << GetName();
185 return true;
186 }
187
HasParameterValidator() const188 bool VectorField::HasParameterValidator() const {
189 // Does not have parameter validator yet.
190 // TODO: See comment in GenParameterValidator
191 return false;
192 }
193
GenParameterValidator(std::ostream &) const194 void VectorField::GenParameterValidator(std::ostream&) const {
195 // No Parameter validator if its dynamically size.
196 // TODO: Maybe add a validator to ensure that the size isn't larger than what the size field can hold.
197 return;
198 }
199
GenInserter(std::ostream & s) const200 void VectorField::GenInserter(std::ostream& s) const {
201 s << "for (const auto& val_ : " << GetName() << "_) {";
202 element_field_->GenInserter(s);
203 s << "}\n";
204 }
205
GenValidator(std::ostream &) const206 void VectorField::GenValidator(std::ostream&) const {
207 // NOTE: We could check if the element size divides cleanly into the array size, but we decided to forgo that
208 // in favor of just returning as many elements as possible in a best effort style.
209 //
210 // Other than that there is nothing that arrays need to be validated on other than length so nothing needs to
211 // be done here.
212 }
213
SetSizeField(const SizeField * size_field)214 void VectorField::SetSizeField(const SizeField* size_field) {
215 if (size_field->GetFieldType() == CountField::kFieldType && !size_modifier_.empty()) {
216 ERROR(this, size_field) << "Can not use count field to describe array with a size modifier."
217 << " Use size instead";
218 }
219
220 size_field_ = size_field;
221 }
222
GetSizeModifier() const223 const std::string& VectorField::GetSizeModifier() const {
224 return size_modifier_;
225 }
226
IsContainerField() const227 bool VectorField::IsContainerField() const {
228 return true;
229 }
230
GetElementField() const231 const PacketField* VectorField::GetElementField() const {
232 return element_field_;
233 }
234
GenStringRepresentation(std::ostream & s,std::string accessor) const235 void VectorField::GenStringRepresentation(std::ostream& s, std::string accessor) const {
236 s << "\"VECTOR[\";";
237
238 std::string arr_idx = "arridx_" + accessor;
239 std::string vec_size = accessor + ".size()";
240 s << "for (size_t index = 0; index < " << vec_size << "; index++) {";
241 std::string element_accessor = "(" + accessor + "[index])";
242 s << "ss << ((index == 0) ? \"\" : \", \") << ";
243
244 if (element_field_->GetFieldType() == CustomField::kFieldType) {
245 s << element_accessor << ".ToString()";
246 } else {
247 element_field_->GenStringRepresentation(s, element_accessor);
248 }
249
250 s << ";}";
251 s << "ss << \"]\"";
252 }
253