1 /**
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_VERIFIER_UTIL_RANGE_HPP_
17 #define PANDA_VERIFIER_UTIL_RANGE_HPP_
18 
19 #include <limits>
20 #include <string>
21 #include <algorithm>
22 #include <iterator>
23 
24 namespace ark::verifier {
25 
26 template <typename... T>
27 class Range;
28 
29 template <typename Int>
30 // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
31 class Range<Int> {
32 public:
33     class Iterator {
34     public:
35         using value_type = Int;                               // NOLINT(readability-identifier-naming)
36         using pointer = Int *;                                // NOLINT(readability-identifier-naming)
37         using reference = Int &;                              // NOLINT(readability-identifier-naming)
38         using difference_type = std::make_signed_t<Int>;      // NOLINT(readability-identifier-naming)
39         using iterator_category = std::forward_iterator_tag;  // NOLINT(readability-identifier-naming)
40 
41         // NOLINTNEXTLINE(google-explicit-constructor)
Iterator(const Int val)42         Iterator(const Int val) : val_ {val} {}
43         Iterator() = default;
44         Iterator(const Iterator &) = default;
45         Iterator(Iterator &&) = default;
46         Iterator &operator=(const Iterator &) = default;
47         Iterator &operator=(Iterator &&) = default;
48         ~Iterator() = default;
49 
50         // NOLINTNEXTLINE(cert-dcl21-cpp)
operator ++(int)51         Iterator operator++(int)
52         {
53             Iterator old {*this};
54             ++val_;
55             return old;
56         }
operator ++()57         Iterator &operator++()
58         {
59             ++val_;
60             return *this;
61         }
62         // NOLINTNEXTLINE(cert-dcl21-cpp)
operator --(int)63         Iterator operator--(int)
64         {
65             Iterator old {*this};
66             --val_;
67             return old;
68         }
operator --()69         Iterator &operator--()
70         {
71             --val_;
72             return *this;
73         }
operator ==(const Iterator &rhs)74         bool operator==(const Iterator &rhs)
75         {
76             return val_ == rhs.val_;
77         }
operator !=(const Iterator &rhs)78         bool operator!=(const Iterator &rhs)
79         {
80             return val_ != rhs.val_;
81         }
operator *()82         Int operator*()
83         {
84             return val_;
85         }
86 
87     private:
88         Int val_ = std::numeric_limits<Int>::min();
89     };
90     template <typename Container>
91     // NOLINTNEXTLINE(google-explicit-constructor)
Range(const Container &cont)92     Range(const Container &cont) : from_ {0}, to_ {cont.size() - 1}
93     {
94     }
Range(const Int from, const Int to)95     Range(const Int from, const Int to) : from_ {std::min(from, to)}, to_ {std::max(from, to)} {}
96     Range() = default;
97     ~Range() = default;
98 
begin() const99     Iterator begin() const  // NOLINT(readability-identifier-naming)
100     {
101         return {from_};
102     }
cbegin() const103     Iterator cbegin() const  // NOLINT(readability-identifier-naming)
104     {
105         return {from_};
106     }
end() const107     Iterator end() const  // NOLINT(readability-identifier-naming)
108     {
109         return {to_ + 1};
110     }
cend() const111     Iterator cend() const  // NOLINT(readability-identifier-naming)
112     {
113         return {to_ + 1};
114     }
BasedAt(Int point) const115     Range BasedAt(Int point) const
116     {
117         return Range {point, point + to_ - from_};
118     }
Contains(Int point) const119     bool Contains(Int point) const
120     {
121         return point >= from_ && point <= to_;
122     }
PutInBounds(Int point) const123     Int PutInBounds(Int point) const
124     {
125         if (point < from_) {
126             return from_;
127         }
128         if (point > to_) {
129             return to_;
130         }
131         return point;
132     }
Length() const133     size_t Length() const
134     {
135         return to_ - from_ + 1;
136     }
OffsetOf(Int val) const137     Int OffsetOf(Int val) const
138     {
139         return val - from_;
140     }
IndexOf(Int offset) const141     Int IndexOf(Int offset) const
142     {
143         return offset + from_;
144     }
Start() const145     Int Start() const
146     {
147         return from_;
148     }
Finish() const149     Int Finish() const
150     {
151         return to_;
152     }
operator ==(const Range &rhs) const153     bool operator==(const Range &rhs) const
154     {
155         return from_ == rhs.from_ && to_ == rhs.to_;
156     }
157 
158 private:
159     Int from_;
160     Int to_;
161 };
162 
163 template <typename Int>
164 Range(Int, Int, typename std::enable_if<std::is_integral<Int>::value, bool>::type b = true) -> Range<Int>;
165 }  // namespace ark::verifier
166 
167 namespace std {  // NOLINT(cert-dcl58-cpp)
168 template <typename Int>
to_string(const ark::verifier::Range<Int> &range)169 string to_string(const ark::verifier::Range<Int> &range)  // NOLINT(readability-identifier-naming)
170 {
171     return string {"[ "} + to_string(range.Start()) + " .. " + to_string(range.Finish()) + " ]";
172 }
173 }  // namespace std
174 
175 #endif  // !PANDA_VERIFIER_UTIL_RANGE_HPP_
176