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 "packet/packet_view.h" 18 19 #include <algorithm> 20 21 #include "os/log.h" 22 23 namespace bluetooth { 24 namespace packet { 25 26 template <bool little_endian> 27 PacketView<little_endian>::PacketView(const std::forward_list<class View> fragments) 28 : fragments_(fragments), length_(0) { 29 for (auto fragment : fragments_) { 30 length_ += fragment.size(); 31 } 32 } 33 34 template <bool little_endian> 35 PacketView<little_endian>::PacketView(std::shared_ptr<std::vector<uint8_t>> packet) 36 : fragments_({View(packet, 0, packet->size())}), length_(packet->size()) {} 37 38 template <bool little_endian> 39 Iterator<little_endian> PacketView<little_endian>::begin() const { 40 return Iterator<little_endian>(this->fragments_, 0); 41 } 42 43 template <bool little_endian> 44 Iterator<little_endian> PacketView<little_endian>::end() const { 45 return Iterator<little_endian>(this->fragments_, size()); 46 } 47 48 template <bool little_endian> 49 uint8_t PacketView<little_endian>::operator[](size_t index) const { 50 return at(index); 51 } 52 53 template <bool little_endian> 54 uint8_t PacketView<little_endian>::at(size_t index) const { 55 ASSERT_LOG(index < length_, "Index %zu out of bounds", index); 56 for (const auto& fragment : fragments_) { 57 if (index < fragment.size()) { 58 return fragment[index]; 59 } 60 index -= fragment.size(); 61 } 62 ASSERT_LOG(false, "Out of fragments searching for index %zu", index); 63 return 0; 64 } 65 66 template <bool little_endian> 67 size_t PacketView<little_endian>::size() const { 68 return length_; 69 } 70 71 template <bool little_endian> 72 std::forward_list<View> PacketView<little_endian>::GetSubviewList(size_t begin, size_t end) const { 73 ASSERT(begin <= end); 74 ASSERT(end <= length_); 75 76 std::forward_list<View> view_list; 77 std::forward_list<View>::iterator it = view_list.before_begin(); 78 size_t length = end - begin; 79 for (const auto& fragment : fragments_) { 80 if (begin >= fragment.size()) { 81 begin -= fragment.size(); 82 } else { 83 View view(fragment, begin, begin + std::min(length, fragment.size() - begin)); 84 length -= view.size(); 85 it = view_list.insert_after(it, view); 86 begin = 0; 87 } 88 } 89 return view_list; 90 } 91 92 template <bool little_endian> 93 PacketView<true> PacketView<little_endian>::GetLittleEndianSubview(size_t begin, size_t end) const { 94 return PacketView<true>(GetSubviewList(begin, end)); 95 } 96 97 template <bool little_endian> 98 PacketView<false> PacketView<little_endian>::GetBigEndianSubview(size_t begin, size_t end) const { 99 return PacketView<false>(GetSubviewList(begin, end)); 100 } 101 102 template <bool little_endian> 103 void PacketView<little_endian>::Append(PacketView to_add) { 104 auto insertion_point = fragments_.begin(); 105 size_t remaining_length = length_; 106 while (remaining_length > 0) { 107 remaining_length -= insertion_point->size(); 108 if (remaining_length > 0) { 109 insertion_point++; 110 } 111 } 112 ASSERT(insertion_point != fragments_.end()); 113 for (const auto& fragment : to_add.fragments_) { 114 fragments_.insert_after(insertion_point, fragment); 115 insertion_point++; 116 } 117 length_ += to_add.length_; 118 } 119 120 // Explicit instantiations for both types of PacketViews. 121 template class PacketView<true>; 122 template class PacketView<false>; 123 } // namespace packet 124 } // namespace bluetooth 125