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