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 #pragma once 18 19 #include <map> 20 #include <set> 21 #include <vector> 22 23 #include "fields/all_fields.h" 24 #include "fields/packet_field.h" 25 26 using FieldListIterator = std::vector<PacketField*>::const_iterator; 27 using ReverseFieldListIterator = std::vector<PacketField*>::const_reverse_iterator; 28 29 class FieldList { 30 public: 31 FieldList() = default; 32 FieldList(std::vector<PacketField * > fields)33 FieldList(std::vector<PacketField*> fields) { 34 for (PacketField* field : fields) { 35 AppendField(field); 36 } 37 } 38 39 template <class Iterator> FieldList(Iterator begin,Iterator end)40 FieldList(Iterator begin, Iterator end) { 41 while (begin != end) { 42 AppendField(*begin); 43 begin++; 44 } 45 } 46 47 PacketField* operator[](int index) const { 48 return field_list_[index]; 49 } 50 GetField(std::string field_name)51 PacketField* GetField(std::string field_name) const { 52 auto it = field_map_.find(field_name); 53 if (it == field_map_.end()) { 54 return nullptr; 55 } 56 57 return it->second; 58 } 59 AppendField(PacketField * field)60 void AppendField(PacketField* field) { 61 AddField(field); 62 field_list_.push_back(field); 63 } 64 PrependField(PacketField * field)65 void PrependField(PacketField* field) { 66 AddField(field); 67 field_list_.insert(field_list_.begin(), field); 68 } 69 GetFieldsBeforePayloadOrBody()70 FieldList GetFieldsBeforePayloadOrBody() const { 71 FieldList ret; 72 for (auto it = begin(); it != end(); it++) { 73 const auto& field = *it; 74 if (field->GetFieldType() == PayloadField::kFieldType || field->GetFieldType() == BodyField::kFieldType) { 75 break; 76 } 77 ret.AppendField(*it); 78 } 79 80 return ret; 81 } 82 GetFieldsAfterPayloadOrBody()83 FieldList GetFieldsAfterPayloadOrBody() const { 84 FieldListIterator it; 85 for (it = begin(); it != end(); it++) { 86 const auto& field = *it; 87 if (field->GetFieldType() == PayloadField::kFieldType || field->GetFieldType() == BodyField::kFieldType) { 88 // Increment it once to get first field after payload/body. 89 it++; 90 break; 91 } 92 } 93 94 return FieldList(it, end()); 95 } 96 GetFieldsWithTypes(std::set<std::string> field_types)97 FieldList GetFieldsWithTypes(std::set<std::string> field_types) const { 98 FieldList ret; 99 100 for (const auto& field : field_list_) { 101 if (field_types.find(field->GetFieldType()) != field_types.end()) { 102 ret.AppendField(field); 103 } 104 } 105 106 return ret; 107 } 108 GetFieldsWithoutTypes(std::set<std::string> field_types)109 FieldList GetFieldsWithoutTypes(std::set<std::string> field_types) const { 110 FieldList ret; 111 112 for (const auto& field : field_list_) { 113 if (field_types.find(field->GetFieldType()) == field_types.end()) { 114 ret.AppendField(field); 115 } 116 } 117 118 return ret; 119 } 120 121 // Appends header fields of param to header fields of the current and 122 // prepends footer fields of the param to footer fields of the current. 123 // Ex. Assuming field_list_X has the layout: 124 // field_list_X_header 125 // payload/body 126 // field_list_X_footer 127 // The call to field_list_1.Merge(field_list_2) would result in 128 // field_list_1_header 129 // field_list_2_header 130 // payload/body (uses whatever was in field_list_2) 131 // field_list_2_footer 132 // field_list_1_footer Merge(FieldList nested)133 FieldList Merge(FieldList nested) const { 134 FieldList ret; 135 136 for (const auto& field : GetFieldsBeforePayloadOrBody()) { 137 ret.AppendField(field); 138 } 139 140 for (const auto& field : nested) { 141 ret.AppendField(field); 142 } 143 144 for (const auto& field : GetFieldsAfterPayloadOrBody()) { 145 ret.AppendField(field); 146 } 147 148 return ret; 149 } 150 HasPayloadOrBody()151 bool HasPayloadOrBody() const { 152 return has_payload_ || has_body_; 153 } 154 HasPayload()155 bool HasPayload() const { 156 return has_payload_; 157 } 158 HasBody()159 bool HasBody() const { 160 return has_body_; 161 } 162 begin()163 FieldListIterator begin() const { 164 return field_list_.begin(); 165 } 166 end()167 FieldListIterator end() const { 168 return field_list_.end(); 169 } 170 rbegin()171 ReverseFieldListIterator rbegin() const { 172 return field_list_.rbegin(); 173 } 174 rend()175 ReverseFieldListIterator rend() const { 176 return field_list_.rend(); 177 } 178 size()179 size_t size() const { 180 return field_list_.size(); 181 } 182 183 private: AddField(PacketField * field)184 void AddField(PacketField* field) { 185 if (field_map_.find(field->GetName()) != field_map_.end()) { 186 ERROR(field) << "Field with name \"" << field->GetName() << "\" was previously defined.\n"; 187 } 188 189 if (field->GetFieldType() == PayloadField::kFieldType) { 190 if (has_body_) { 191 ERROR(field) << "Packet already has a body."; 192 } 193 has_payload_ = true; 194 } 195 196 if (field->GetFieldType() == BodyField::kFieldType) { 197 if (has_payload_) { 198 ERROR(field) << "Packet already has a payload."; 199 } 200 has_body_ = true; 201 } 202 203 field_map_.insert(std::pair(field->GetName(), field)); 204 } 205 206 std::vector<PacketField*> field_list_; 207 std::map<std::string, PacketField*> field_map_; 208 bool has_payload_ = false; 209 bool has_body_ = false; 210 }; 211