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/scalar_field.h"
18 
19 #include "util.h"
20 
21 const std::string ScalarField::kFieldType = "ScalarField";
22 
ScalarField(std::string name,int size,ParseLocation loc)23 ScalarField::ScalarField(std::string name, int size, ParseLocation loc) : PacketField(name, loc), size_(size) {
24   if (size_ > 64 || size_ < 0) {
25     ERROR(this) << "Not implemented for size_ = " << size_;
26   }
27 }
28 
GetFieldType() const29 const std::string& ScalarField::GetFieldType() const {
30   return ScalarField::kFieldType;
31 }
32 
GetSize() const33 Size ScalarField::GetSize() const {
34   return size_;
35 }
36 
GetDataType() const37 std::string ScalarField::GetDataType() const {
38   return util::GetTypeForSize(size_);
39 }
40 
GetShiftBits(int i)41 int GetShiftBits(int i) {
42   int bits_past_byte_boundary = i % 8;
43   if (bits_past_byte_boundary == 0) {
44     return 0;
45   } else {
46     return 8 - bits_past_byte_boundary;
47   }
48 }
49 
GenBounds(std::ostream & s,Size start_offset,Size end_offset,Size size) const50 int ScalarField::GenBounds(std::ostream& s, Size start_offset, Size end_offset, Size size) const {
51   int num_leading_bits = 0;
52 
53   if (!start_offset.empty()) {
54     // Default to start if available.
55     num_leading_bits = start_offset.bits() % 8;
56     s << "auto " << GetName() << "_it = to_bound + (" << start_offset << ") / 8;";
57   } else if (!end_offset.empty()) {
58     num_leading_bits = GetShiftBits(end_offset.bits() + size.bits());
59     Size byte_offset = Size(num_leading_bits + size.bits()) + end_offset;
60     s << "auto " << GetName() << "_it = to_bound + (to_bound.NumBytesRemaining() - (" << byte_offset << ") / 8);";
61   } else {
62     ERROR(this) << "Ambiguous offset for field.";
63   }
64   return num_leading_bits;
65 }
66 
GenExtractor(std::ostream & s,int num_leading_bits,bool) const67 void ScalarField::GenExtractor(std::ostream& s, int num_leading_bits, bool) const {
68   Size size = GetSize();
69   // Extract the correct number of bytes. The return type could be different
70   // from the extract type if an earlier field causes the beginning of the
71   // current field to start in the middle of a byte.
72   std::string extract_type = util::GetTypeForSize(size.bits() + num_leading_bits);
73   s << "auto extracted_value = " << GetName() << "_it.extract<" << extract_type << ">();";
74 
75   // Right shift the result to remove leading bits.
76   if (num_leading_bits != 0) {
77     s << "extracted_value >>= " << num_leading_bits << ";";
78   }
79   // Mask the result if necessary.
80   if (util::RoundSizeUp(size.bits()) != size.bits()) {
81     uint64_t mask = 0;
82     for (int i = 0; i < size.bits(); i++) {
83       mask <<= 1;
84       mask |= 1;
85     }
86     s << "extracted_value &= 0x" << std::hex << mask << std::dec << ";";
87   }
88   s << "*" << GetName() << "_ptr = static_cast<" << GetDataType() << ">(extracted_value);";
89 }
90 
GetGetterFunctionName() const91 std::string ScalarField::GetGetterFunctionName() const {
92   std::stringstream ss;
93   ss << "Get" << util::UnderscoreToCamelCase(GetName());
94   return ss.str();
95 }
96 
GenGetter(std::ostream & s,Size start_offset,Size end_offset) const97 void ScalarField::GenGetter(std::ostream& s, Size start_offset, Size end_offset) const {
98   s << GetDataType() << " " << GetGetterFunctionName() << "() const {";
99   s << "ASSERT(was_validated_);";
100   s << "auto to_bound = begin();";
101   int num_leading_bits = GenBounds(s, start_offset, end_offset, GetSize());
102   s << GetDataType() << " " << GetName() << "_value{};";
103   s << GetDataType() << "* " << GetName() << "_ptr = &" << GetName() << "_value;";
104   GenExtractor(s, num_leading_bits, false);
105   s << "return " << GetName() << "_value;";
106   s << "}";
107 }
108 
GetBuilderParameterType() const109 std::string ScalarField::GetBuilderParameterType() const {
110   return GetDataType();
111 }
112 
HasParameterValidator() const113 bool ScalarField::HasParameterValidator() const {
114   return util::RoundSizeUp(GetSize().bits()) != GetSize().bits();
115 }
116 
GenParameterValidator(std::ostream & s) const117 void ScalarField::GenParameterValidator(std::ostream& s) const {
118   s << "ASSERT(" << GetName() << " < (static_cast<uint64_t>(1) << " << GetSize().bits() << "));";
119 }
120 
GenInserter(std::ostream & s) const121 void ScalarField::GenInserter(std::ostream& s) const {
122   if (GetSize().bits() == 8) {
123     s << "i.insert_byte(" << GetName() << "_);";
124   } else {
125     s << "insert(" << GetName() << "_, i," << GetSize().bits() << ");";
126   }
127 }
128 
GenValidator(std::ostream &) const129 void ScalarField::GenValidator(std::ostream&) const {
130   // Do nothing
131 }
132 
GenStringRepresentation(std::ostream & s,std::string accessor) const133 void ScalarField::GenStringRepresentation(std::ostream& s, std::string accessor) const {
134   s << "+" << accessor;
135 }
136