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_INDEX_HPP_ 17 #define PANDA_VERIFIER_UTIL_INDEX_HPP_ 18 19 #include "libpandabase/macros.h" 20 #include "verification/util/hash.h" 21 22 #include <limits> 23 24 namespace ark::verifier { 25 // similar to std::optional, but much more effective for numeric types 26 // when not all range of values is required and some value may be used 27 // as dedicated invalid value 28 template <typename Int, const Int INVALID = std::numeric_limits<Int>::max()> 29 class Index { 30 public: Index()31 Index() : value_ {INVALID} {} 32 // NOLINTNEXTLINE(google-explicit-constructor) Index(Int val)33 Index(Int val) : value_ {val} 34 { 35 ASSERT(IsValid()); 36 } operator =(Int val)37 Index &operator=(Int val) 38 { 39 value_ = val; 40 ASSERT(IsValid()); 41 return *this; 42 } 43 Index(const Index &) = default; Index(Index &&idx)44 Index(Index &&idx) : value_ {idx.value_} 45 { 46 idx.Invalidate(); 47 } 48 Index &operator=(const Index &) = default; operator =(Index &&idx)49 Index &operator=(Index &&idx) 50 { 51 value_ = idx.value_; 52 idx.Invalidate(); 53 return *this; 54 } 55 ~Index() = default; 56 operator ==(const Index &other) const57 bool operator==(const Index &other) const 58 { 59 return value_ == other.value_; 60 }; operator !=(const Index &other) const61 bool operator!=(const Index &other) const 62 { 63 return !(*this == other); 64 }; 65 Invalidate()66 void Invalidate() 67 { 68 value_ = INVALID; 69 } 70 IsValid() const71 bool IsValid() const 72 { 73 return value_ != INVALID; 74 } 75 76 // for contextual conversion in if/while/etc. operator bool() const77 explicit operator bool() const 78 { 79 return IsValid(); 80 } 81 82 // NOLINTNEXTLINE(google-explicit-constructor) operator Int() const83 operator Int() const 84 { 85 ASSERT(IsValid()); 86 return value_; 87 } 88 operator *() const89 Int operator*() const 90 { 91 ASSERT(IsValid()); 92 return value_; 93 } 94 95 template <typename T> operator T() const96 explicit operator T() const 97 { 98 ASSERT(IsValid()); 99 // NOTE: check that T is capable of holding valid range of value 100 return static_cast<T>(value_); 101 } 102 103 private: 104 Int value_; 105 template <typename T> 106 friend struct std::hash; 107 }; 108 } // namespace ark::verifier 109 110 namespace std { 111 template <typename Int, const Int I> 112 struct hash<ark::verifier::Index<Int, I>> { 113 size_t operator()(const ark::verifier::Index<Int, I> &i) const noexcept 114 { 115 return ark::verifier::StdHash(i.value_); 116 } 117 }; 118 } // namespace std 119 120 #endif // !PANDA_VERIFIER_UTIL_INDEX_HPP_ 121