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