blob: 37dea1683221dfbb669882e921b19cab986ab97e [file] [log] [blame]
Myles Watson41aecb92019-02-06 14:02:36 -08001/*
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/array_field.h"
Myles Watson5e693132019-09-18 16:19:06 -070018
Myles Watson945f4c32019-09-25 15:33:39 -070019#include "fields/custom_field.h"
20#include "fields/scalar_field.h"
Myles Watson41aecb92019-02-06 14:02:36 -080021#include "util.h"
22
Myles Watson6f55d382019-07-15 15:02:48 -070023const std::string ArrayField::kFieldType = "ArrayField";
24
Myles Watson5e693132019-09-18 16:19:06 -070025ArrayField::ArrayField(std::string name, int element_size, int array_size, ParseLocation loc)
26 : PacketField(name, loc), element_field_(new ScalarField("val", element_size, loc)), element_size_(element_size),
27 array_size_(array_size) {
28 if (element_size > 64 || element_size < 0)
29 ERROR(this) << __func__ << ": Not implemented for element size = " << element_size;
Myles Watsonde15b642019-07-02 12:02:47 -070030 if (element_size % 8 != 0) {
31 ERROR(this) << "Can only have arrays with elements that are byte aligned (" << element_size << ")";
32 }
Myles Watson41aecb92019-02-06 14:02:36 -080033}
34
Myles Watson5e693132019-09-18 16:19:06 -070035ArrayField::ArrayField(std::string name, TypeDef* type_def, int array_size, ParseLocation loc)
36 : PacketField(name, loc), element_field_(type_def->GetNewField("val", loc)),
37 element_size_(element_field_->GetSize()), array_size_(array_size) {
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_ << ")";
Myles Watsonde15b642019-07-02 12:02:47 -070040 }
Myles Watson41aecb92019-02-06 14:02:36 -080041}
42
Myles Watson6f55d382019-07-15 15:02:48 -070043const std::string& ArrayField::GetFieldType() const {
44 return ArrayField::kFieldType;
Myles Watson41aecb92019-02-06 14:02:36 -080045}
46
47Size ArrayField::GetSize() const {
Myles Watson5e693132019-09-18 16:19:06 -070048 if (!element_size_.empty() && !element_size_.has_dynamic()) {
49 return Size(array_size_ * element_size_.bits());
Myles Watson41aecb92019-02-06 14:02:36 -080050 }
Jakub Pawlowskide83e2c2019-07-19 14:51:50 +020051 return Size();
Myles Watson41aecb92019-02-06 14:02:36 -080052}
53
Myles Watsonde15b642019-07-02 12:02:47 -070054Size ArrayField::GetBuilderSize() const {
Myles Watson5e693132019-09-18 16:19:06 -070055 if (!element_size_.empty() && !element_size_.has_dynamic()) {
56 return GetSize();
Myles Watson945f4c32019-09-25 15:33:39 -070057 } else if (element_field_->BuilderParameterMustBeMoved()) {
58 std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() +
59 "_) { length += elem->size() * 8; } return length; }()";
60 return ret;
Myles Watsonde15b642019-07-02 12:02:47 -070061 } else {
62 std::string ret = "[this](){ size_t length = 0; for (const auto& elem : " + GetName() +
63 "_) { length += elem.size() * 8; } return length; }()";
64 return ret;
65 }
66}
67
Myles Watson4b8c0ed2019-10-03 09:08:34 -070068Size ArrayField::GetStructSize() const {
69 if (!element_size_.empty() && !element_size_.has_dynamic()) {
70 return GetSize();
71 } else if (element_field_->BuilderParameterMustBeMoved()) {
72 std::string ret = "[this](){ size_t length = 0; for (const auto& elem : to_fill->" + GetName() +
73 "_) { length += elem->size() * 8; } return length; }()";
74 return ret;
75 } else {
76 std::string ret = "[this](){ size_t length = 0; for (const auto& elem : to_fill->" + GetName() +
77 "_) { length += elem.size() * 8; } return length; }()";
78 return ret;
79 }
80}
81
Myles Watson6f55d382019-07-15 15:02:48 -070082std::string ArrayField::GetDataType() const {
Myles Watson5e693132019-09-18 16:19:06 -070083 return "std::array<" + element_field_->GetDataType() + "," + std::to_string(array_size_) + ">";
Myles Watson41aecb92019-02-06 14:02:36 -080084}
85
Myles Watson5e43ed72019-10-02 15:01:15 -070086void ArrayField::GenExtractor(std::ostream& s, int num_leading_bits, bool for_struct) const {
Myles Watson5e693132019-09-18 16:19:06 -070087 s << GetDataType() << "::iterator ret_it = " << GetName() << "_ptr->begin();";
88 s << "auto " << element_field_->GetName() << "_it = " << GetName() << "_it;";
Myles Watsond66ec502019-10-04 16:02:38 -070089 if (!element_size_.empty()) {
Myles Watson5e693132019-09-18 16:19:06 -070090 s << "while (" << element_field_->GetName() << "_it.NumBytesRemaining() >= " << element_size_.bytes();
91 s << " && ret_it < " << GetName() << "_ptr->end()) {";
Myles Watsoncbfe6cf2019-07-16 09:50:23 -070092 } else {
Myles Watson5e693132019-09-18 16:19:06 -070093 s << "while (" << element_field_->GetName() << "_it.NumBytesRemaining() > 0 ";
94 s << " && ret_it < " << GetName() << "_ptr->end()) {";
Myles Watsoncbfe6cf2019-07-16 09:50:23 -070095 }
Myles Watson945f4c32019-09-25 15:33:39 -070096 if (element_field_->BuilderParameterMustBeMoved()) {
97 s << element_field_->GetDataType() << " " << element_field_->GetName() << "_ptr;";
98 } else {
99 s << element_field_->GetDataType() << "* " << element_field_->GetName() << "_ptr = ret_it;";
100 }
Myles Watson5e43ed72019-10-02 15:01:15 -0700101 element_field_->GenExtractor(s, num_leading_bits, for_struct);
Myles Watson945f4c32019-09-25 15:33:39 -0700102 if (element_field_->BuilderParameterMustBeMoved()) {
103 s << "*ret_it = std::move(" << element_field_->GetName() << "_ptr);";
104 }
Myles Watson4b10f632019-08-22 14:11:00 -0700105 s << "ret_it++;";
106 s << "}";
Myles Watsoncbfe6cf2019-07-16 09:50:23 -0700107}
108
Jack Hec61124e2019-11-18 15:35:04 -0800109std::string ArrayField::GetGetterFunctionName() const {
110 std::stringstream ss;
111 ss << "Get" << util::UnderscoreToCamelCase(GetName());
112 return ss.str();
113}
114
Myles Watson41aecb92019-02-06 14:02:36 -0800115void ArrayField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
Jack Hec61124e2019-11-18 15:35:04 -0800116 s << GetDataType() << " " << GetGetterFunctionName() << "() {";
Myles Watson8def62f2019-07-24 15:52:33 -0700117 s << "ASSERT(was_validated_);";
Myles Watson6de86912019-08-06 23:07:52 -0700118 s << "size_t end_index = size();";
Myles Watson5e693132019-09-18 16:19:06 -0700119 s << "auto to_bound = begin();";
Myles Watson41aecb92019-02-06 14:02:36 -0800120
Myles Watsonb6ec5e12019-10-02 15:07:05 -0700121 int num_leading_bits = GenBounds(s, start_offset, end_offset, GetSize());
Myles Watson5e693132019-09-18 16:19:06 -0700122 s << GetDataType() << " " << GetName() << "_value;";
123 s << GetDataType() << "* " << GetName() << "_ptr = &" << GetName() << "_value;";
Myles Watson5e43ed72019-10-02 15:01:15 -0700124 GenExtractor(s, num_leading_bits, false);
Myles Watson41aecb92019-02-06 14:02:36 -0800125
Myles Watson5e693132019-09-18 16:19:06 -0700126 s << "return " << GetName() << "_value;";
Myles Watson41aecb92019-02-06 14:02:36 -0800127 s << "}\n";
128}
129
Jack Hec61124e2019-11-18 15:35:04 -0800130std::string ArrayField::GetBuilderParameterType() const {
131 std::stringstream ss;
Myles Watson945f4c32019-09-25 15:33:39 -0700132 if (element_field_->BuilderParameterMustBeMoved()) {
Jack Hec61124e2019-11-18 15:35:04 -0800133 ss << "std::array<" << element_field_->GetDataType() << "," << array_size_ << ">";
Myles Watson945f4c32019-09-25 15:33:39 -0700134 } else {
Jack Hec61124e2019-11-18 15:35:04 -0800135 ss << "const std::array<" << element_field_->GetDataType() << "," << array_size_ << ">&";
Myles Watson945f4c32019-09-25 15:33:39 -0700136 }
Jack Hec61124e2019-11-18 15:35:04 -0800137 return ss.str();
Myles Watson835bf7b2019-07-17 13:17:24 -0700138}
Myles Watson41aecb92019-02-06 14:02:36 -0800139
Myles Watson945f4c32019-09-25 15:33:39 -0700140bool ArrayField::BuilderParameterMustBeMoved() const {
141 return element_field_->BuilderParameterMustBeMoved();
142}
143
Myles Watson835bf7b2019-07-17 13:17:24 -0700144bool ArrayField::GenBuilderMember(std::ostream& s) const {
Myles Watson5e693132019-09-18 16:19:06 -0700145 s << "std::array<" << element_field_->GetDataType() << "," << array_size_ << "> " << GetName();
Myles Watson41aecb92019-02-06 14:02:36 -0800146 return true;
147}
148
149bool ArrayField::HasParameterValidator() const {
Jakub Pawlowskide83e2c2019-07-19 14:51:50 +0200150 return false;
Myles Watson41aecb92019-02-06 14:02:36 -0800151}
152
Jakub Pawlowskide83e2c2019-07-19 14:51:50 +0200153void ArrayField::GenParameterValidator(std::ostream&) const {
154 // Array length is validated by the compiler
Myles Watson41aecb92019-02-06 14:02:36 -0800155}
156
157void ArrayField::GenInserter(std::ostream& s) const {
Myles Watson5e693132019-09-18 16:19:06 -0700158 s << "for (const auto& val_ : " << GetName() << "_) {";
159 element_field_->GenInserter(s);
Myles Watson41aecb92019-02-06 14:02:36 -0800160 s << "}\n";
161}
162
163void ArrayField::GenValidator(std::ostream&) const {
164 // NOTE: We could check if the element size divides cleanly into the array size, but we decided to forgo that
165 // in favor of just returning as many elements as possible in a best effort style.
166 //
167 // Other than that there is nothing that arrays need to be validated on other than length so nothing needs to
168 // be done here.
169}
Jack Hec61124e2019-11-18 15:35:04 -0800170
171bool ArrayField::IsContainerField() const {
172 return true;
173}
174
175const PacketField* ArrayField::GetElementField() const {
176 return element_field_;
177}