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 // std::iterator is deprecated in C++17 onwards. Instead, you must declare all
31 // 5 aliases that the iterator needs for the std library.
32 #if __cplusplus >= 201703L
33 struct IteratorTraits {
34   using iterator_category = std::random_access_iterator_tag;
35   using value_type = uint8_t;
36   using difference_type = std::ptrdiff_t;
37   using pointer = uint8_t*;
38   using reference = uint8_t&;
39 };
40 #else
41 struct IteratorTraits : public std::iterator<std::random_access_iterator_tag, uint8_t> {};
42 #endif
43 
44 // Templated Iterator for endianness
45 template <bool little_endian>
46 class Iterator : public IteratorTraits {
47 public:
48   Iterator(const std::forward_list<View>& data, size_t offset);
49   Iterator(std::shared_ptr<std::vector<uint8_t>> data);
50   Iterator(const Iterator& itr) = default;
51   virtual ~Iterator() = default;
52 
53   // All addition and subtraction operators are unbounded.
54   Iterator operator+(int offset) const;
55   Iterator& operator+=(int offset);
56   Iterator& operator++();
57 
58   Iterator operator-(int offset) const;
59   int operator-(const Iterator& itr) const;
60   Iterator& operator-=(int offset);
61   Iterator& operator--();
62 
63   Iterator& operator=(const Iterator& itr);
64 
65   bool operator!=(const Iterator& itr) const;
66   bool operator==(const Iterator& itr) const;
67 
68   bool operator<(const Iterator& itr) const;
69   bool operator>(const Iterator& itr) const;
70 
71   bool operator<=(const Iterator& itr) const;
72   bool operator>=(const Iterator& itr) const;
73 
74   uint8_t operator*() const;
75 
76   size_t NumBytesRemaining() const;
77 
78   Iterator Subrange(size_t index, size_t length) const;
79 
80   // Get the next sizeof(T) bytes and return the filled type
81   template <typename T, typename std::enable_if<std::is_trivial<T>::value, int>::type = 0>
extract()82   T extract() {
83     static_assert(std::is_trivial<T>::value, "Iterator::extract requires a fixed-width type.");
84     T extracted_value{};
85     uint8_t* value_ptr = (uint8_t*)&extracted_value;
86 
87     for (size_t i = 0; i < sizeof(T); i++) {
88       size_t index = (little_endian ? i : sizeof(T) - i - 1);
89       value_ptr[index] = this->operator*();
90       this->operator++();
91     }
92     return extracted_value;
93   }
94 
95   template <typename T,
96             typename std::enable_if<std::is_base_of_v<CustomFieldFixedSizeInterface<T>, T>,
97                                     int>::type = 0>
extract()98   T extract() {
99     T extracted_value{};
100     for (size_t i = 0; i < CustomFieldFixedSizeInterface<T>::length(); i++) {
101       size_t index = (little_endian ? i : CustomFieldFixedSizeInterface<T>::length() - i - 1);
102       extracted_value.data()[index] = this->operator*();
103       this->operator++();
104     }
105     return extracted_value;
106   }
107 
108 private:
109   std::forward_list<View> data_;
110   size_t index_;
111   size_t begin_;
112   size_t end_;
113 };
114 
115 }  // namespace packet
116 }  // namespace bluetooth
117