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 #pragma once
18 
19 #include <cstdint>
20 #include <forward_list>
21 #include <memory>
22 #include <type_traits>
23 
24 #include "packet/custom_field_fixed_size_interface.h"
25 #include "packet/view.h"
26 
27 namespace bluetooth {
28 namespace packet {
29 
30 // Templated Iterator for endianness
31 template <bool little_endian>
32 class Iterator : public std::iterator<std::random_access_iterator_tag, uint8_t> {
33  public:
34   Iterator(const std::forward_list<View>& data, size_t offset);
35   Iterator(const Iterator& itr) = default;
36   virtual ~Iterator() = default;
37 
38   // All addition and subtraction operators are unbounded.
39   Iterator operator+(int offset);
40   Iterator& operator+=(int offset);
41   Iterator& operator++();
42 
43   Iterator operator-(int offset);
44   int operator-(Iterator& itr);
45   Iterator& operator-=(int offset);
46   Iterator& operator--();
47 
48   Iterator& operator=(const Iterator& itr);
49 
50   bool operator!=(const Iterator& itr) const;
51   bool operator==(const Iterator& itr) const;
52 
53   bool operator<(const Iterator& itr) const;
54   bool operator>(const Iterator& itr) const;
55 
56   bool operator<=(const Iterator& itr) const;
57   bool operator>=(const Iterator& itr) const;
58 
59   uint8_t operator*() const;
60 
61   size_t NumBytesRemaining() const;
62 
63   Iterator Subrange(size_t index, size_t length) const;
64 
65   // Get the next sizeof(FixedWidthPODType) bytes and return the filled type
66   template <typename FixedWidthPODType, typename std::enable_if<std::is_pod<FixedWidthPODType>::value, int>::type = 0>
extract()67   FixedWidthPODType extract() {
68     static_assert(std::is_pod<FixedWidthPODType>::value, "Iterator::extract requires a fixed-width type.");
69     FixedWidthPODType extracted_value{};
70     uint8_t* value_ptr = (uint8_t*)&extracted_value;
71 
72     for (size_t i = 0; i < sizeof(FixedWidthPODType); i++) {
73       size_t index = (little_endian ? i : sizeof(FixedWidthPODType) - i - 1);
74       value_ptr[index] = this->operator*();
75       this->operator++();
76     }
77     return extracted_value;
78   }
79 
80   template <typename T, typename std::enable_if<std::is_base_of_v<CustomFieldFixedSizeInterface<T>, T>, int>::type = 0>
extract()81   T extract() {
82     T extracted_value{};
83     for (size_t i = 0; i < CustomFieldFixedSizeInterface<T>::length(); i++) {
84       size_t index = (little_endian ? i : CustomFieldFixedSizeInterface<T>::length() - i - 1);
85       extracted_value.data()[index] = this->operator*();
86       this->operator++();
87     }
88     return extracted_value;
89   }
90 
91  private:
92   std::forward_list<View> data_;
93   size_t index_;
94   size_t begin_;
95   size_t end_;
96 };
97 
98 }  // namespace packet
99 }  // namespace bluetooth
100