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/iterator.h"
18 
19 #undef NDEBUG
20 #include <cassert>
21 
22 namespace bluetooth {
23 namespace packet {
24 
25 template <bool little_endian>
Iterator(const std::forward_list<View> & data,size_t offset)26 Iterator<little_endian>::Iterator(const std::forward_list<View>& data, size_t offset) {
27   data_ = data;
28   index_ = offset;
29   begin_ = 0;
30   end_ = 0;
31   for (auto& view : data) {
32     end_ += view.size();
33   }
34 }
35 
36 template <bool little_endian>
Iterator(std::shared_ptr<std::vector<uint8_t>> data)37 Iterator<little_endian>::Iterator(std::shared_ptr<std::vector<uint8_t>> data) {
38   data_.emplace_front(data, 0, data->size());
39   index_ = 0;
40   begin_ = 0;
41   end_ = data_.front().size();
42 }
43 
44 template <bool little_endian>
operator +(int offset) const45 Iterator<little_endian> Iterator<little_endian>::operator+(int offset) const {
46   auto itr(*this);
47 
48   return itr += offset;
49 }
50 
51 template <bool little_endian>
operator +=(int offset)52 Iterator<little_endian>& Iterator<little_endian>::operator+=(int offset) {
53   index_ += offset;
54   return *this;
55 }
56 
57 template <bool little_endian>
operator ++()58 Iterator<little_endian>& Iterator<little_endian>::operator++() {
59   index_++;
60   return *this;
61 }
62 
63 template <bool little_endian>
operator -(int offset) const64 Iterator<little_endian> Iterator<little_endian>::operator-(int offset) const {
65   auto itr(*this);
66 
67   return itr -= offset;
68 }
69 
70 template <bool little_endian>
operator -(const Iterator<little_endian> & itr) const71 int Iterator<little_endian>::operator-(const Iterator<little_endian>& itr) const {
72   return index_ - itr.index_;
73 }
74 
75 template <bool little_endian>
operator -=(int offset)76 Iterator<little_endian>& Iterator<little_endian>::operator-=(int offset) {
77   index_ -= offset;
78 
79   return *this;
80 }
81 
82 template <bool little_endian>
operator --()83 Iterator<little_endian>& Iterator<little_endian>::operator--() {
84   if (index_ != 0) {
85     index_--;
86   }
87   return *this;
88 }
89 
90 template <bool little_endian>
operator =(const Iterator<little_endian> & itr)91 Iterator<little_endian>& Iterator<little_endian>::operator=(const Iterator<little_endian>& itr) {
92   if (this == &itr) {
93     return *this;
94   }
95   this->data_ = itr.data_;
96   this->begin_ = itr.begin_;
97   this->end_ = itr.end_;
98   this->index_ = itr.index_;
99   return *this;
100 }
101 
102 template <bool little_endian>
operator ==(const Iterator<little_endian> & itr) const103 bool Iterator<little_endian>::operator==(const Iterator<little_endian>& itr) const {
104   return index_ == itr.index_;
105 }
106 
107 template <bool little_endian>
operator !=(const Iterator<little_endian> & itr) const108 bool Iterator<little_endian>::operator!=(const Iterator<little_endian>& itr) const {
109   return !(*this == itr);
110 }
111 
112 template <bool little_endian>
operator <(const Iterator<little_endian> & itr) const113 bool Iterator<little_endian>::operator<(const Iterator<little_endian>& itr) const {
114   return index_ < itr.index_;
115 }
116 
117 template <bool little_endian>
operator >(const Iterator<little_endian> & itr) const118 bool Iterator<little_endian>::operator>(const Iterator<little_endian>& itr) const {
119   return index_ > itr.index_;
120 }
121 
122 template <bool little_endian>
operator <=(const Iterator<little_endian> & itr) const123 bool Iterator<little_endian>::operator<=(const Iterator<little_endian>& itr) const {
124   return index_ <= itr.index_;
125 }
126 
127 template <bool little_endian>
operator >=(const Iterator<little_endian> & itr) const128 bool Iterator<little_endian>::operator>=(const Iterator<little_endian>& itr) const {
129   return index_ >= itr.index_;
130 }
131 
132 template <bool little_endian>
operator *() const133 uint8_t Iterator<little_endian>::operator*() const {
134   assert(NumBytesRemaining() > 0);
135   size_t index = index_;
136 
137   for (auto view : data_) {
138     if (index < view.size()) {
139       return view[index];
140     }
141     index -= view.size();
142   }
143 
144   // Out of fragments searching for index.
145   std::abort();
146   return 0;
147 }
148 
149 template <bool little_endian>
NumBytesRemaining() const150 size_t Iterator<little_endian>::NumBytesRemaining() const {
151   if (end_ > index_ && index_ >= begin_) {
152     return end_ - index_;
153   }
154   return 0;
155 }
156 
157 template <bool little_endian>
Subrange(size_t index,size_t length) const158 Iterator<little_endian> Iterator<little_endian>::Subrange(size_t index, size_t length) const {
159   Iterator<little_endian> to_return(*this);
160   if (to_return.NumBytesRemaining() > index) {
161     to_return.index_ = to_return.index_ + index;
162     to_return.begin_ = to_return.index_;
163     if (to_return.NumBytesRemaining() >= length) {
164       to_return.end_ = to_return.index_ + length;
165     }
166   } else {
167     to_return.end_ = 0;
168   }
169 
170   return to_return;
171 }
172 
173 // Explicit instantiations for both types of Iterators.
174 template class Iterator<true>;
175 template class Iterator<false>;
176 }  // namespace packet
177 }  // namespace bluetooth
178