blob: badd6413f6245686f88b389831582f5cc4b336fb [file] [log] [blame]
/*
* 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 <algorithm>
#include "os/log.h"
namespace bluetooth {
namespace packet {
template <bool little_endian>
PacketView<little_endian>::PacketView(const std::forward_list<class View> fragments)
: fragments_(fragments), length_(0) {
for (auto fragment : fragments_) {
length_ += fragment.size();
}
}
template <bool little_endian>
PacketView<little_endian>::PacketView(std::shared_ptr<std::vector<uint8_t>> packet)
: fragments_({View(packet, 0, packet->size())}), length_(packet->size()) {}
template <bool little_endian>
Iterator<little_endian> PacketView<little_endian>::begin() const {
return Iterator<little_endian>(this->fragments_, 0);
}
template <bool little_endian>
Iterator<little_endian> PacketView<little_endian>::end() const {
return Iterator<little_endian>(this->fragments_, size());
}
template <bool little_endian>
uint8_t PacketView<little_endian>::operator[](size_t index) const {
return at(index);
}
template <bool little_endian>
uint8_t PacketView<little_endian>::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 <bool little_endian>
size_t PacketView<little_endian>::size() const {
return length_;
}
template <bool little_endian>
std::forward_list<View> PacketView<little_endian>::GetSubviewList(size_t begin, size_t end) const {
ASSERT(begin <= end);
ASSERT(end <= length_);
std::forward_list<View> view_list;
std::forward_list<View>::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 <bool little_endian>
PacketView<true> PacketView<little_endian>::GetLittleEndianSubview(size_t begin, size_t end) const {
return PacketView<true>(GetSubviewList(begin, end));
}
template <bool little_endian>
PacketView<false> PacketView<little_endian>::GetBigEndianSubview(size_t begin, size_t end) const {
return PacketView<false>(GetSubviewList(begin, end));
}
template <bool little_endian>
void PacketView<little_endian>::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<true>;
template class PacketView<false>;
} // namespace packet
} // namespace bluetooth