/* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "packet/packet_view.h" #include #include "os/log.h" namespace bluetooth { namespace packet { template PacketView::PacketView(const std::forward_list fragments) : fragments_(fragments), length_(0) { for (auto fragment : fragments_) { length_ += fragment.size(); } } template PacketView::PacketView(std::shared_ptr> packet) : fragments_({View(packet, 0, packet->size())}), length_(packet->size()) {} template Iterator PacketView::begin() const { return Iterator(this->fragments_, 0); } template Iterator PacketView::end() const { return Iterator(this->fragments_, size()); } template uint8_t PacketView::operator[](size_t index) const { return at(index); } template uint8_t PacketView::at(size_t index) const { ASSERT_LOG(index < length_, "Index %zu out of bounds", index); for (const auto& fragment : fragments_) { if (index < fragment.size()) { return fragment[index]; } index -= fragment.size(); } ASSERT_LOG(false, "Out of fragments searching for index %zu", index); return 0; } template size_t PacketView::size() const { return length_; } template std::forward_list PacketView::GetSubviewList(size_t begin, size_t end) const { ASSERT(begin <= end); ASSERT(end <= length_); std::forward_list view_list; std::forward_list::iterator it = view_list.before_begin(); size_t length = end - begin; for (const auto& fragment : fragments_) { if (begin >= fragment.size()) { begin -= fragment.size(); } else { View view(fragment, begin, begin + std::min(length, fragment.size() - begin)); length -= view.size(); it = view_list.insert_after(it, view); begin = 0; } } return view_list; } template PacketView PacketView::GetLittleEndianSubview(size_t begin, size_t end) const { return PacketView(GetSubviewList(begin, end)); } template PacketView PacketView::GetBigEndianSubview(size_t begin, size_t end) const { return PacketView(GetSubviewList(begin, end)); } template void PacketView::Append(PacketView to_add) { auto insertion_point = fragments_.begin(); size_t remaining_length = length_; while (remaining_length > 0) { remaining_length -= insertion_point->size(); if (remaining_length > 0) { insertion_point++; } } ASSERT(insertion_point != fragments_.end()); for (const auto& fragment : to_add.fragments_) { fragments_.insert_after(insertion_point, fragment); insertion_point++; } length_ += to_add.length_; } // Explicit instantiations for both types of PacketViews. template class PacketView; template class PacketView; } // namespace packet } // namespace bluetooth