1 #ifndef _TCUEITHER_HPP 2 #define _TCUEITHER_HPP 3 /*------------------------------------------------------------------------- 4 * drawElements Quality Program Tester Core 5 * ---------------------------------------- 6 * 7 * Copyright 2015 The Android Open Source Project 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 *//*! 22 * \file 23 * \brief Template class that is either type of First or Second. 24 *//*--------------------------------------------------------------------*/ 25 26 #include "tcuDefs.hpp" 27 28 namespace tcu 29 { 30 31 /*--------------------------------------------------------------------*//*! 32 * \brief Object containing Either First or Second type of object 33 * 34 * \note Type First and Second are always aligned to same alignment as 35 * deUint64. 36 * \note This type always uses at least sizeof(bool) + max(sizeof(First*), 37 * sizeof(Second*)) + sizeof(deUint64) of memory. 38 *//*--------------------------------------------------------------------*/ 39 template<typename First, typename Second> 40 class Either 41 { 42 public: 43 Either (const First& first); 44 Either (const Second& second); 45 ~Either (void); 46 47 Either (const Either<First, Second>& other); 48 Either& operator= (const Either<First, Second>& other); 49 50 Either& operator= (const First& first); 51 Either& operator= (const Second& second); 52 53 bool isFirst (void) const; 54 bool isSecond (void) const; 55 56 const First& getFirst (void) const; 57 const Second& getSecond (void) const; 58 59 template<typename Type> 60 const Type& get (void) const; 61 62 template<typename Type> 63 bool is (void) const; 64 65 private: 66 void release (void); 67 68 bool m_isFirst; 69 70 union 71 { 72 First* m_first; 73 Second* m_second; 74 }; 75 76 union 77 { 78 deUint8 m_data[sizeof(First) > sizeof(Second) ? sizeof(First) : sizeof(Second)]; 79 deUint64 m_align; 80 }; 81 } DE_WARN_UNUSED_TYPE; 82 83 namespace EitherDetail 84 { 85 86 template<typename Type, typename First, typename Second> 87 struct Get; 88 89 template<typename First, typename Second> 90 struct Get<First, First, Second> 91 { 92 static const First& get (const Either<First, Second>& either) 93 { 94 return either.getFirst(); 95 } 96 }; 97 98 template<typename First, typename Second> 99 struct Get<Second, First, Second> 100 { 101 static const Second& get (const Either<First, Second>& either) 102 { 103 return either.getSecond(); 104 } 105 }; 106 107 template<typename Type, typename First, typename Second> 108 const Type& get (const Either<First, Second>& either) 109 { 110 return Get<Type, First, Second>::get(either); 111 } 112 113 template<typename Type, typename First, typename Second> 114 struct Is; 115 116 template<typename First, typename Second> 117 struct Is<First, First, Second> 118 { 119 static bool is (const Either<First, Second>& either) 120 { 121 return either.isFirst(); 122 } 123 }; 124 125 template<typename First, typename Second> 126 struct Is<Second, First, Second> 127 { 128 static bool is (const Either<First, Second>& either) 129 { 130 return either.isSecond(); 131 } 132 }; 133 134 template<typename Type, typename First, typename Second> 135 bool is (const Either<First, Second>& either) 136 { 137 return Is<Type, First, Second>::is(either); 138 } 139 140 } // EitherDetail 141 142 template<typename First, typename Second> 143 void Either<First, Second>::release (void) 144 { 145 if (m_isFirst) 146 m_first->~First(); 147 else 148 m_second->~Second(); 149 150 m_isFirst = true; 151 m_first = DE_NULL; 152 } 153 154 template<typename First, typename Second> 155 Either<First, Second>::Either (const First& first) 156 : m_isFirst (true) 157 { 158 m_first = new(m_data)First(first); 159 } 160 161 template<typename First, typename Second> 162 Either<First, Second>::Either (const Second& second) 163 : m_isFirst (false) 164 { 165 m_second = new(m_data)Second(second); 166 } 167 168 template<typename First, typename Second> 169 Either<First, Second>::~Either (void) 170 { 171 release(); 172 } 173 174 template<typename First, typename Second> 175 Either<First, Second>::Either (const Either<First, Second>& other) 176 : m_isFirst (other.m_isFirst) 177 { 178 if (m_isFirst) 179 m_first = new(m_data)First(*other.m_first); 180 else 181 m_second = new(m_data)Second(*other.m_second); 182 } 183 184 template<typename First, typename Second> 185 Either<First, Second>& Either<First, Second>::operator= (const Either<First, Second>& other) 186 { 187 if (this == &other) 188 return *this; 189 190 release(); 191 192 m_isFirst = other.m_isFirst; 193 194 if (m_isFirst) 195 m_first = new(m_data)First(*other.m_first); 196 else 197 m_second = new(m_data)Second(*other.m_second); 198 199 return *this; 200 } 201 202 template<typename First, typename Second> 203 Either<First, Second>& Either<First, Second>::operator= (const First& first) 204 { 205 release(); 206 207 m_isFirst = true; 208 m_first = new(m_data)First(first); 209 210 return *this; 211 } 212 213 template<typename First, typename Second> 214 Either<First, Second>& Either<First, Second>::operator= (const Second& second) 215 { 216 release(); 217 218 m_isFirst = false; 219 m_second = new(m_data)Second(second); 220 221 return *this; 222 } 223 224 template<typename First, typename Second> 225 bool Either<First, Second>::isFirst (void) const 226 { 227 return m_isFirst; 228 } 229 230 template<typename First, typename Second> 231 bool Either<First, Second>::isSecond (void) const 232 { 233 return !m_isFirst; 234 } 235 236 template<typename First, typename Second> 237 const First& Either<First, Second>::getFirst (void) const 238 { 239 DE_ASSERT(isFirst()); 240 return *m_first; 241 } 242 243 template<typename First, typename Second> 244 const Second& Either<First, Second>::getSecond (void) const 245 { 246 DE_ASSERT(isSecond()); 247 return *m_second; 248 } 249 250 template<typename First, typename Second> 251 template<typename Type> 252 const Type& Either<First, Second>::get (void) const 253 { 254 return EitherDetail::get<Type, First, Second>(*this); 255 } 256 257 template<typename First, typename Second> 258 template<typename Type> 259 bool Either<First, Second>::is (void) const 260 { 261 return EitherDetail::is<Type, First, Second>(*this); 262 } 263 264 void Either_selfTest (void); 265 266 } // tcu 267 268 #endif // _TCUEITHER_HPP 269